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