Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f5eac13
fix: modified filter.dart
abhinav-from-contentstack Sep 13, 2024
faf3537
fix: updated query_test.dart and type issue in client.dart
abhinav-from-contentstack Sep 14, 2024
69377a5
fix: updated assets_test.dart to use JS SDK test stack
abhinav-from-contentstack Sep 14, 2024
2f9d430
fix: removed superEnum from fit,format,orientation,publishtype
abhinav-from-contentstack Sep 14, 2024
0795b46
fix: updated tests
abhinav-from-contentstack Sep 14, 2024
d1a0eed
fix: removed superenum dependency from include.dart enum
abhinav-from-contentstack Sep 15, 2024
8cfdd0d
WIP: removing superEnum dep from operations.dart
abhinav-from-contentstack Sep 15, 2024
3dc5cd8
fix: removed superEnum dependency from operations.dart
abhinav-from-contentstack Sep 15, 2024
5b38930
fix: removed superEnum dep from operator.dart and reference.dart
abhinav-from-contentstack Sep 15, 2024
05c452f
fix: removed superenum generated files
abhinav-from-contentstack Sep 15, 2024
8206c52
changes for v3 migration
reeshika-h Dec 3, 2024
2dbb196
chore: Test cases modification
reeshika-h Dec 9, 2024
a29e89a
version bump
reeshika-h Dec 9, 2024
e225400
Merge pull request #24 from contentstack/fix
reeshika-h Feb 7, 2025
9b43dbe
version bump
reeshika-h Feb 10, 2025
ee91b8a
Merge pull request #26 from contentstack/fix
reeshika-h Feb 10, 2025
4defbbc
Merge pull request #25 from contentstack/development
reeshika-h Feb 10, 2025
d801459
Merge pull request #28 from contentstack/master
reeshika-h Feb 11, 2025
275cdcc
workflow update
reeshika-h Feb 12, 2025
80ab941
Merge pull request #29 from contentstack/fix
harshithad0703 Feb 12, 2025
18ad5ef
Merge pull request #30 from contentstack/development
harshithad0703 Feb 12, 2025
f07ca25
Added security file
reeshika-h Feb 17, 2025
dccfa0b
Merge pull request #31 from contentstack/fix
harshithad0703 Feb 17, 2025
e105e4a
Merge pull request #32 from contentstack/development
reeshika-h Feb 17, 2025
30fd6e4
semgrep issue fixed
reeshika-h Feb 17, 2025
36ab6fe
Merge pull request #33 from contentstack/fix
reeshika-h Feb 17, 2025
826743a
Merge pull request #34 from contentstack/development
reeshika-h Feb 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/check-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Comment PR
if: github.base_ref == 'master' && github.head_ref != 'next'
if: github.base_ref == 'master' && github.head_ref != 'staging'
uses: thollander/actions-comment-pull-request@v2
with:
message: |
We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the next branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch.
- name: Check branch
if: github.base_ref == 'master' && github.head_ref != 'next'
if: github.base_ref == 'master' && github.head_ref != 'staging'
run: |
echo "ERROR: We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the next branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch."
exit 1
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# CHANGELOG

### **FEB-17-2025**

#### v1.0.0 - v3 migration null support added
#### Removed super_enum lib

## v0.5.1 - Added support for gcp_na region
#### Added support for gcp_na region

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# MIT License

Copyright (c) 2012 - 2024 Contentstack. All rights reserved.
Copyright (c) 2012 - 2025 Contentstack. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ final response = imageTransformation..canvas(imageParams)..getUrl();

MIT License

Copyright (c) 2012 - 2021
Copyright (c) 2012 - 2025
[Contentstack](https://www.contentstack.com/). All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down
27 changes: 27 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Security

Contentstack takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations.

If you believe you have found a security vulnerability in any Contentstack-owned repository, please report it to us as described below.

## Reporting Security Issues

**Please do not report security vulnerabilities through public GitHub issues.**

Send email to [[email protected]](mailto:[email protected]).

You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:

- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
- Full paths of source file(s) related to the manifestation of the issue
- The location of the affected source code (tag/branch/commit or direct URL)
- Any special configuration required to reproduce the issue
- Step-by-step instructions to reproduce the issue
- Proof-of-concept or exploit code (if possible)
- Impact of the issue, including how an attacker might exploit the issue

This information will help us triage your report more quickly.

[https://www.contentstack.com/trust/](https://www.contentstack.com/trust/)
50 changes: 25 additions & 25 deletions lib/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import 'package:http/http.dart' as http;

class HttpClient extends http.BaseClient {
final http.Client _client;
final Stack stack;
final Map<String, String> stackHeaders;
final Stack? stack;
final Map<String, String>? stackHeaders;

factory HttpClient(Map<String, String> headers,
{http.Client client, Stack stack}) {
factory HttpClient(Map<String, String>? headers,
{http.Client? client, Stack? stack}) {
final stackClient = client ?? http.Client();
return HttpClient._internal(stackClient, headers, stack);
}
Expand All @@ -26,13 +26,13 @@ class HttpClient extends http.BaseClient {
return _client.send(request);
}

Future<T> sendRequest<T, K>(Uri uri) async {
stackHeaders[CONTENT_TYPE] = CONTENT_TYPE_VALUE;
stackHeaders[X_USER_AGENT] = X_USER_AGENT_VALUE;
Future<T?> sendRequest<T, K>(Uri uri) async {
stackHeaders![CONTENT_TYPE] = CONTENT_TYPE_VALUE;
stackHeaders![X_USER_AGENT] = X_USER_AGENT_VALUE;
final response = await http
.get(uri, headers: stackHeaders)
.get(uri, headers: stackHeaders as Map<String, String>)
.timeout(const Duration(seconds: TIMEOUT));
Object bodyJson;
Object? bodyJson;
try {
bodyJson = jsonDecode(response.body);
} on FormatException {
Expand All @@ -44,42 +44,42 @@ class HttpClient extends http.BaseClient {
rethrow;
}
if (response.statusCode == 200) {
final Map bodyJson = json.decode(utf8.decode(response.bodyBytes));
if (T == EntryModel && bodyJson.containsKey('entry')) {
final Map? bodyJson = json.decode(utf8.decode(response.bodyBytes));
if (T == EntryModel && bodyJson!.containsKey('entry')) {
return fromJson<T, K>(bodyJson['entry']);
} else if (K == EntryModel && bodyJson.containsKey('entries')) {
} else if (K == EntryModel && bodyJson!.containsKey('entries')) {
return fromJson<T, K>(bodyJson['entries']);
} else if (T == AssetModel && bodyJson.containsKey('asset')) {
} else if (T == AssetModel && bodyJson!.containsKey('asset')) {
return fromJson<T, K>(bodyJson['asset']);
} else if (K == AssetModel && bodyJson.containsKey('assets')) {
} else if (K == AssetModel && bodyJson!.containsKey('assets')) {
return fromJson<T, K>(bodyJson['assets']);
} else if (T == SyncResult && bodyJson.containsKey('items')) {
} else if (T == SyncResult && bodyJson!.containsKey('items')) {
return fromJson<T, K>(bodyJson);
} else {
if (bodyJson.containsKey('entries')) {
var previewResponse = stack.livePreview['entries'];
if (bodyJson!.containsKey('entries')) {
var previewResponse = stack!.livePreview?.entries;
if (previewResponse != null) {
return fromJson<T, K>(mergeLivePreview(bodyJson, previewResponse));
return fromJson<T, K>(mergeLivePreview(bodyJson, Map.fromEntries(previewResponse)));
}
}
return fromJson<T, K>(bodyJson);
}
} else {
return bodyJson;
return fromJson<T, K>(bodyJson) as FutureOr<T?>;
}
}

mergeLivePreview(Map bodyJson, Map previewResponse) {}
mergeLivePreview(Map? bodyJson, Map previewResponse) {}

/// Generic objects as well as List of generic objects
/// (from a JSON list response).
/// First, you need to have a function that checks the type of the
/// generic object and returns the result of the corresponding fromJson call
/// code taken from:
/// https://stackoverflow.com/questions/56271651/how-to-pass-a-generic-type-as-a-parameter-to-a-future-in-flutter
static T fromJson<T, K>(dynamic json) {
static T? fromJson<T, K>(dynamic json) {
if (json is Iterable) {
return _fromJsonList<K>(json) as T;
return _fromJsonList<K>(json as List<dynamic>) as T;
} else if (T == AssetModel) {
return AssetModel.fromJson(json) as T;
} else if (T == EntryModel) {
Expand All @@ -91,14 +91,14 @@ class HttpClient extends http.BaseClient {
}
}

static List<K> _fromJsonList<K>(List jsonList) {
static List<K?>? _fromJsonList<K>(List? jsonList) {
if (jsonList == null) {
return null;
}

final output = <K>[];
final output = <K?>[];
// ignore: prefer_final_in_for_each
for (Map<String, dynamic> json in jsonList) {
for (Map<String, dynamic> json in jsonList as Iterable<Map<String, dynamic>>) {
output.add(fromJson(json));
}
return output;
Expand Down
12 changes: 6 additions & 6 deletions lib/constant.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ const X_USER_AGENT_VALUE = '$SDK_NAME-v$SDK_VERSION';
const TIMEOUT = 30;

void ifLivePreviewEnable(HttpClient _client) {
final dictLivePreview = _client.stack.livePreview;
final dictLivePreview = _client.stack!.livePreview;
const String AUTH = 'authorization';
if (dictLivePreview.containsKey('enable')) {
_client.stack.removeHeader('access_token');
_client.stack.removeHeader('environment');
_client.stack.setHeader(AUTH, _client.stack.livePreview[AUTH]);
_client.stack.setHost(dictLivePreview['host']);
if (dictLivePreview!.containsKey('enable')) {
_client.stack!.removeHeader('access_token');
_client.stack!.removeHeader('environment');
_client.stack!.setHeader(AUTH, _client.stack!.livePreview![AUTH]);
_client.stack!.setHost(dictLivePreview['host']);
final String errMessage = '''Invalid content_type_uid! Make sure you have
provided same content_type_uid
livePreviewQuery parameter in stack class''';
Expand Down
20 changes: 10 additions & 10 deletions lib/src/asset.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import 'package:contentstack/client.dart';
/// Learn more about [Assets](https://www.contentstack.com/docs/developers/apis/content-delivery-api/#get-a-single-asset)
///
class Asset {
final HttpClient _client;
final String _uid;
String _urlPath;
final HttpClient? _client;
final String? _uid;
String? _urlPath;

final Map<String, String> assetParameter = <String, String>{};
final Map<String, String?> assetParameter = <String, String?>{};

/// * [_uid] assetUid:
/// Enter the unique ID of the asset of which you wish to retrieve
Expand All @@ -27,8 +27,8 @@ class Asset {
/// });
///
Asset(this._uid, [this._client]) {
assetParameter['environment'] = _client.stackHeaders['environment'];
_urlPath = '/${_client.stack.apiVersion}/assets';
assetParameter['environment'] = _client!.stackHeaders!['environment'];
_urlPath = '/${_client!.stack!.apiVersion}/assets';
}

///
Expand Down Expand Up @@ -57,13 +57,13 @@ class Asset {
/// }).catchError((error) {
/// print(error['error_code']);
/// });
Future<T> fetch<T, K>() {
if (_uid == null || _uid.isEmpty) {
Future<T?> fetch<T, K>() {
if (_uid == null || _uid!.isEmpty) {
throw Exception('Provide asset uid to fetch single entry');
}
final uri =
Uri.https(_client.stack.endpoint, '$_urlPath/$_uid', assetParameter);
return _client.sendRequest<T, K>(uri);
Uri.https(_client!.stack!.endpoint!, '$_urlPath/$_uid', assetParameter);
return _client!.sendRequest<T, K>(uri);
}

///
Expand Down
14 changes: 7 additions & 7 deletions lib/src/asset_query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import 'package:contentstack/src/base_query.dart';
/// You can also specify the environment of which you wish to get the assets.
/// Learn more about [Assets](https://www.contentstack.com/docs/developers/apis/content-delivery-api/#all-assets)
class AssetQuery extends BaseQuery {
final HttpClient _client;
String _urlPath;
final HttpClient? _client;
late String _urlPath;

AssetQuery([this._client]) {
queryParameter['environment'] = _client.stackHeaders['environment'];
_urlPath = '/${_client.stack.apiVersion}/assets';
queryParameter['environment'] = _client!.stackHeaders!['environment'];
_urlPath = '/${_client!.stack!.apiVersion}/assets';
}

///
Expand Down Expand Up @@ -42,9 +42,9 @@ class AssetQuery extends BaseQuery {
/// }).catchError((error) {
/// print(error['error_code']);
/// });
Future<T> find<T, K>() async {
final uri = Uri.https(_client.stack.endpoint, _urlPath, queryParameter);
return _client.sendRequest<T, K>(uri);
Future<T?> find<T, K>() async {
final uri = Uri.https(_client!.stack!.endpoint!, _urlPath, queryParameter);
return _client!.sendRequest<T, K>(uri);
}

///
Expand Down
56 changes: 34 additions & 22 deletions lib/src/base_query.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'package:contentstack/src/enums/operations.dart';
import 'package:contentstack/src/enums/operations_type.dart';

///
/// This is base Query class that contains common
/// functions to query in Entry, Assets and content_type
/// common query for asset & entry
class BaseQuery {
final Map<String, String> queryParameter = <String, String>{};
final Map<String, String?> queryParameter = <String, String?>{};
final Map<String, dynamic> parameter = <String, dynamic>{};

///
Expand Down Expand Up @@ -156,27 +157,38 @@ class BaseQuery {

void where(String fieldUid, QueryOperation queryOperation) {
if (fieldUid != null && fieldUid.isNotEmpty) {
queryOperation.when(equals: (operation) {
parameter[fieldUid] = operation.value;
}, notEquals: (operation) {
parameter[fieldUid] = {'\$ne': operation.value};
}, includes: (operation) {
parameter[fieldUid] = {'\$in': operation.value};
}, excludes: (operation) {
parameter[fieldUid] = {'\$nin': operation.value};
}, isLessThan: (operation) {
parameter[fieldUid] = {'\$lt': operation.value};
}, isLessThanOrEqual: (operation) {
parameter[fieldUid] = {'\$lte': operation.value};
}, isGreaterThan: (operation) {
parameter[fieldUid] = {'\$gt': operation.value};
}, isGreaterThanOrEqual: (operation) {
parameter[fieldUid] = {'\$gte': operation.value};
}, exists: (operation) {
parameter[fieldUid] = {'\$exists': operation.value};
}, matches: (operation) {
parameter[fieldUid] = {'\$regex': operation.regex};
});
switch(queryOperation.operationType) {
case QueryOperationType.Equals:
parameter[fieldUid] = queryOperation.value;
break;
case QueryOperationType.NotEquals:
parameter[fieldUid] = {'\$ne': queryOperation.value};
break;
case QueryOperationType.Includes:
parameter[fieldUid] = {'\$in': queryOperation.value};
break;
case QueryOperationType.Excludes:
parameter[fieldUid] = {'\$nin': queryOperation.value};
break;
case QueryOperationType.IsLessThan:
parameter[fieldUid] = {'\$lt': queryOperation.value};
break;
case QueryOperationType.IsLessThanOrEqual:
parameter[fieldUid] = {'\$lte': queryOperation.value};
break;
case QueryOperationType.IsGreaterThan:
parameter[fieldUid] = {'\$gt': queryOperation.value};
break;
case QueryOperationType.IsGreaterThanOrEqual:
parameter[fieldUid] = {'\$gte': queryOperation.value};
break;
case QueryOperationType.Exists:
parameter[fieldUid] = {'\$exists': queryOperation.value};
break;
case QueryOperationType.Matches:
parameter[fieldUid] = {'\$regex': queryOperation.value};
break;
}
}
}
}
Loading