Line data Source code
1 : import 'dart:async';
2 : import 'dart:io';
3 :
4 : import 'package:contentstack/client.dart';
5 : import 'package:contentstack/contentstack.dart';
6 : import 'package:contentstack/src/asset.dart';
7 : import 'package:contentstack/src/asset_query.dart';
8 : import 'package:contentstack/src/image_transform.dart';
9 : import 'package:contentstack/src/sync/publishtype.dart';
10 : import 'package:http/http.dart';
11 :
12 : /// Choosing a Region
13 : /// A Contentstack region refers to the location of the data centers
14 : /// where your organization's data resides
15 : /// * Default [Region](https://www.contentstack.com/docs/developers/contentstack-regions/about-regions/) is: US
16 : enum Region { us, eu }
17 :
18 : /// A stack is like a container that holds the content of your app.
19 : /// Learn more about [Stacks](https://www.contentstack.com/docs/developers/set-up-stack/about-stack/).
20 : class Stack {
21 : Map<String, String> stackHeader = <String, String>{};
22 : final String _apiKey;
23 : final String _deliveryToken;
24 : final String _environment;
25 : final String _host;
26 : final Region region;
27 : final String branch;
28 : final String apiVersion;
29 : HttpClient _client;
30 :
31 : ///
32 : /// Create a new Stack instance with stack's apikey, token,
33 : /// environment name and Optional parameters like.
34 : /// Throws an [ArgumentError] if [apiKey], [deliveryToken]
35 : /// and [environment] is not passed.
36 : /// import 'package:contentstack/contentstack.dart' as contentstack;
37 6 : /// var stack = contentstack.Stack('api_key', 'delivery_token', environment)
38 : ///
39 : /// Example:
40 : ///
41 : /// ```dart
42 6 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
43 : /// ```
44 1 : ///
45 : Stack(this._apiKey, this._deliveryToken, this._environment,
46 1 : {this.branch = '',
47 : this.apiVersion = 'v3',
48 24 : this.region = Region.us,
49 1 : String host = 'cdn.contentstack.io',
50 : BaseClient client})
51 : : _host = (region == Region.us)
52 24 : ? host
53 1 : : (host == 'cdn.contentstack.io'
54 : ? 'eu-cdn.contentstack.com'
55 : : 'eu-$host') {
56 24 : // final blank = s == null || s.trim() == '';
57 1 : if (_apiKey.replaceAll(RegExp('\\W'), '').isEmpty ?? true) {
58 : throw ArgumentError.notNull('APIkey');
59 : }
60 12 :
61 6 : if (_deliveryToken.replaceAll(RegExp('\\W'), '').isEmpty ?? true) {
62 6 : throw ArgumentError.notNull('deliveryToken');
63 6 : }
64 :
65 : if (_environment.replaceAll(RegExp('\\W'), '').isEmpty ?? true) {
66 18 : throw ArgumentError.notNull('environment');
67 : }
68 :
69 : stackHeader = {
70 : 'api_key': _apiKey,
71 : 'access_token': _deliveryToken,
72 : 'environment': _environment,
73 : };
74 : if (branch != null && branch.isNotEmpty) {
75 : stackHeader['branch'] = branch;
76 : }
77 :
78 : _client = HttpClient(stackHeader, client: client, stack: this);
79 : }
80 :
81 : /// It returns apiKey of the Stack
82 4 : ///
83 8 : /// Example
84 : /// ```dart
85 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
86 : /// var apiKey = stack.apiKey;
87 : /// ```
88 : String get apiKey => _apiKey;
89 :
90 : /// It returns delivery token of the Stack
91 : ///
92 : /// Example
93 : ///
94 : /// ```dart
95 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
96 : /// var deliveryToken = stack.deliveryToken;
97 : /// ```
98 : String get deliveryToken => _deliveryToken;
99 :
100 1 : /// It returns endpoint of the Stack
101 2 : ///
102 : /// Example
103 : ///
104 : /// ```dart
105 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
106 : /// var environment = stack.environment;
107 : /// ```
108 : String get endpoint => host;
109 :
110 : /// It returns delivery token of the Environment
111 : ///
112 : /// Example
113 : ///
114 : /// ```dart
115 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
116 : /// var environment = stack.environment;
117 : /// ```
118 1 : String get environment => _environment;
119 2 :
120 : /// It returns host of the Stack
121 : ///
122 : /// Example
123 : ///
124 : /// ```dart
125 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
126 : /// var environment = stack.environment;
127 : /// ```
128 : String get host => _host;
129 :
130 : ///
131 : /// This call fetches the latest version of a specific
132 1 : /// asset of a particular stack.
133 : /// API Reference :
134 2 : /// https://www.contentstack.com/docs/developers/apis/content-delivery-api/#single-asset
135 2 : /// [uid] assetUid
136 : ///
137 : /// Example:
138 : ///
139 : /// ```dart
140 : /// var stack = contentstack.Stack(apiKey, deliveryToken, environment);
141 : /// var asset = stack.asset('uid');
142 : /// ```
143 : ///
144 : Asset asset(String uid) {
145 : return Asset(uid, _client);
146 : }
147 :
148 1 : ///
149 2 : /// This call fetches the list of all the assets of a particular stack.
150 2 : /// It also returns the content of each asset in JSON format.
151 : /// You can also specify the environment of which you wish to get the assets.
152 : /// API Reference :
153 : /// https://www.contentstack.com/docs/developers/apis/content-delivery-api/#all-assets
154 : ///
155 : /// Example:
156 : ///
157 : /// ```dart
158 : /// var stack = contentstack.Stack(apiKey, deliveryToken, environment);
159 : /// var asset = stack.assetQuery();
160 : /// ```
161 2 : ///
162 : AssetQuery assetQuery() {
163 : return AssetQuery(_client);
164 : }
165 :
166 : ///
167 : /// ContentType accepts contentTypeId in as the parameter
168 : /// Returns instance of [ContentType].
169 : /// contentType takes [contentTypeId] as optional parameter
170 : /// If you want get one contentType by their content_type_uid
171 2 : ///
172 : /// Example:
173 : ///
174 : /// ```dart
175 : /// var stack = contentstack.Stack(apiKey, deliveryToken, environment);
176 : /// var contentType = stack.contentType('content_type_id');
177 : /// ```
178 : ///
179 : ContentType contentType([String contentTypeId]) {
180 : return ContentType(contentTypeId, _client);
181 2 : }
182 :
183 : ///
184 : /// Fetches all Content Types from the Stack.
185 : /// This call returns comprehensive information
186 : /// of all the content types available in a particular stack in your account.
187 : /// API Reference: https://www.contentstack.com/docs/apis/content-delivery-api/#content-types
188 : /// [queryParameters] is query parameters for the content_types of type [Map]
189 : /// returns list of content_types
190 : ///
191 10 : /// Example:
192 : ///
193 : /// ```dart
194 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
195 : /// response = stack.getContentTypes(queryParameters);
196 : /// ```
197 : ///
198 : Future<T> getContentTypes<T, K>(Map queryParameters) {
199 : final Uri uri = Uri.https(endpoint, '$apiVersion/content_types');
200 : return _client.sendRequest<T, K>(uri);
201 10 : }
202 :
203 : ///
204 : /// The Image Delivery API is used to retrieve, manipulate and/or convert image
205 : /// files of your Contentstack account and deliver it to your
206 : /// web or mobile properties.
207 : /// {Supported input formats}: JPEG, PNG, WEBP, GIF
208 : /// {Supported output formats}: JPEG (baseline & progressive),
209 : /// PNG, WEBP (lossy & lossless), GIF
210 : /// Read documentation for more details:
211 : /// https://www.contentstack.com/docs/developers/apis/image-delivery-api/#limitations-with-optimizing-image
212 : ///
213 : /// [imageUrl] is the required parameter
214 : ///
215 : /// Example:
216 : ///
217 : /// ```dart
218 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
219 : /// imageTransformation = stack.imageTransform(imageUrl);
220 : /// ```
221 : ///
222 1 : ImageTransformation imageTransform(String imageUrl) {
223 2 : return ImageTransformation(imageUrl, _client);
224 : }
225 :
226 : ///
227 : /// If the result of the initial sync (or subsequent sync)
228 : /// contains more than 100 records, the response would be
229 : /// paginated. It provides pagination token in the response.
230 : /// However, you do not have to use the pagination token
231 : /// manually to get the next batch, the SDK does that
232 : /// automatically until the sync is complete. Pagination token
233 : /// can be used in case you want to fetch only selected batches.
234 : /// It is especially useful if the sync process is
235 : /// interrupted midway (due to network issues, etc.). In such cases,
236 : /// this token can be used to restart the sync
237 : /// process from where it was interrupted.
238 : ///
239 : Future<T> paginationToken<T, K>(String paginationToken) {
240 : final parameters = <String, String>{};
241 1 : if (paginationToken != null && paginationToken.isNotEmpty) {
242 4 : parameters['pagination_token'] = paginationToken;
243 2 : }
244 : return _syncRequest<T, K>(parameters);
245 : }
246 :
247 : ///
248 : /// removeHeader function is to Remove header by [headerKey]
249 : /// It requires header key to delete the header
250 : /// returns [Stack] Instance
251 : ///
252 : /// Example:
253 : /// ```dart
254 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
255 : /// stack = stack..removeHeader('headerKey');
256 : /// ```
257 : void removeHeader(String headerKey) {
258 : if (headerKey != null) {
259 : if (stackHeader.containsKey(headerKey)) {
260 : stackHeader.remove(headerKey);
261 : }
262 : }
263 : }
264 :
265 : /// Adds headers for the request
266 : ///
267 : /// Example:
268 : ///
269 : /// ```dart
270 : /// final stack = contentstack.Stack(apiKey, deliveryToken, environment);
271 : /// stack = stack..setHeader('headerKey', 'headervalue');
272 : /// ```
273 1 : void setHeader(String key, String value) {
274 : if (key.isNotEmpty && value.isNotEmpty) {
275 : stackHeader[key] = value;
276 : }
277 : }
278 1 :
279 1 : /////////////////////////////////////////////////
280 1 : // ---------[Synchronization]---------- //
281 1 : /////////////////////////////////////////////////
282 :
283 1 : /// * [contentTypeUid] -- You can also initialize sync with entries of
284 1 : /// only specific content_type. To do this, use syncContentType and specify
285 : /// the content type uid as its value. However, if you do this,
286 1 : /// the subsequent syncs will only include the entries of the
287 1 : /// specified content_type.
288 : ///
289 : /// * [fromDate] -- You can also initialize sync with entries published
290 2 : /// after a specific date. To do this, use from_date
291 1 : /// and specify the start date as its value.
292 1 : ///
293 1 : /// * [locale] -- You can also initialize sync with entries of
294 1 : /// only specific locales.
295 1 : /// To do this, use syncLocale and specify the locale code as its value.
296 1 : /// However, if you do this, the subsequent syncs will only include
297 1 : /// the entries of the specified locales.
298 1 : ///
299 1 : /// * [publishType] -- Use the type parameter
300 1 : /// to get a specific type of content.
301 1 : /// If you do not specify any value,
302 1 : /// it will bring all published entries and published assets.
303 1 : ///
304 : /// Returns: List Of [SyncResult]
305 : ///
306 : Future<T> sync<T, K>(
307 1 : {String contentTypeUid,
308 : String fromDate,
309 : String locale,
310 1 : PublishType publishType}) async {
311 4 : final parameter = <String, String>{};
312 4 : parameter['init'] = 'true';
313 2 : if (contentTypeUid != null && contentTypeUid.isNotEmpty) {
314 : parameter['content_type_uid'] = contentTypeUid;
315 : }
316 : if (fromDate != null && fromDate.isNotEmpty) {
317 : parameter['from_date'] = fromDate;
318 : }
319 : if (locale != null && locale.isNotEmpty) {
320 : parameter['locale'] = locale;
321 : }
322 : if (publishType != null) {
323 : publishType.when(assetPublished: (result) {
324 : parameter['publish_type'] = 'asset_published';
325 : }, entryPublished: (result) {
326 : parameter['publish_type'] = 'entry_published';
327 : }, assetUnpublished: (result) {
328 : parameter['publish_type'] = 'asset_unpublished';
329 1 : }, assetDeleted: (result) {
330 1 : parameter['publish_type'] = 'asset_deleted';
331 1 : }, entryUnpublished: (result) {
332 1 : parameter['publish_type'] = 'entry_unpublished';
333 : }, entryDeleted: (result) {
334 1 : parameter['publish_type'] = 'entry_deleted';
335 : }, contentTypeDeleted: (result) {
336 : parameter['publish_type'] = 'content_type_deleted';
337 : });
338 : }
339 :
340 : return _syncRequest<T, K>(parameter);
341 : }
342 :
343 : ///
344 1 : /// You can use the sync token (that you receive after initial sync)
345 1 : /// to get the updated content next time.
346 1 : /// sync token fetches only the content that was added after your last sync,
347 1 : /// and the details of the content that was deleted or updated.
348 : ///
349 : ///
350 4 : Future<T> syncToken<T, K>(String syncToken) {
351 4 : final parameters = <String, String>{};
352 2 : if (syncToken != null && syncToken.isNotEmpty) {
353 : parameters['sync_token'] = syncToken;
354 : }
355 :
356 : parameters['environment'] = _client.stackHeaders['environment'];
357 : final Uri uri = Uri.https(endpoint, '$apiVersion/stacks/sync', parameters);
358 : return _client.sendRequest<T, K>(uri);
359 : }
360 :
361 18 : Future<T> _syncRequest<T, K>(parameters) async {
362 : parameters['environment'] = _client.stackHeaders['environment'];
363 : final Uri uri = Uri.https(endpoint, '$apiVersion/stacks/sync', parameters);
364 : return _client.sendRequest<T, K>(uri);
365 : }
366 : }
|