Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
620 changes: 314 additions & 306 deletions package-lock.json

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions src/lib/asset-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,28 @@ export class AssetQuery extends BaseQuery {

return this;
}

/**
* @method assetFields
* @memberof AssetQuery
* @description Include specific asset fields in the response (CDA getAssets).
* Use with asset_fields[]: user_defined_fields, embedded, ai_suggested, visual_markups.
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.asset().assetFields("user_defined_fields", "embedded").find();
*
* @param {...string} fields - Asset field names to include (e.g. user_defined_fields, embedded, ai_suggested, visual_markups)
* @returns {AssetQuery} - Returns the AssetQuery instance for chaining.
*/
assetFields(...fields: string[]): this {
if (fields.length > 0) {
this._queryParams['asset_fields[]'] = fields;
}
return this;
}

/**
* @method query
* @memberof AssetQuery
Expand Down
23 changes: 22 additions & 1 deletion src/lib/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AxiosInstance, getData } from '@contentstack/core';
export class Asset {
private _client: AxiosInstance;
private _urlPath: string;
_queryParams: { [key: string]: string | number } = {};
_queryParams: { [key: string]: string | number | string[] } = {};

constructor(client: AxiosInstance, assetUid: string) {
this._client = client;
Expand Down Expand Up @@ -129,6 +129,27 @@ export class Asset {
return this;
}

/**
* @method assetFields
* @memberof Asset
* @description Include specific asset fields in the response (CDA getAssets - single asset).
* Use with asset_fields[]: user_defined_fields, embedded, ai_suggested, visual_markups.
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.asset("assetUid").assetFields("user_defined_fields", "embedded").fetch();
*
* @param {...string} fields - Asset field names to include (e.g. user_defined_fields, embedded, ai_suggested, visual_markups)
* @returns {Asset} - Returns the Asset instance for chaining.
*/
assetFields(...fields: string[]): this {
if (fields.length > 0) {
this._queryParams['asset_fields[]'] = fields;
}
return this;
}

/**
* @method fetch
* @memberof Asset
Expand Down
21 changes: 21 additions & 0 deletions src/lib/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,27 @@ export class Entries extends BaseQuery {
return this;
}

/**
* @method assetFields
* @memberof Entries
* @description Include specific asset fields in the response (CDA getEntry/entries).
* Use with asset_fields[]: user_defined_fields, embedded, ai_suggested, visual_markups.
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.contentType("contentTypeUid").entry().assetFields("user_defined_fields", "embedded").find();
*
* @param {...string} fields - Asset field names to include (e.g. user_defined_fields, embedded, ai_suggested, visual_markups)
* @returns {Entries} - Returns the Entries instance for chaining.
*/
assetFields(...fields: string[]): this {
if (fields.length > 0) {
this._queryParams['asset_fields[]'] = fields;
}
return this;
}

/**
* Override find method to include content type UID directly for better caching
*/
Expand Down
21 changes: 21 additions & 0 deletions src/lib/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,4 +273,25 @@ export class Entry {
}
return this;
}

/**
* @method assetFields
* @memberof Entry
* @description Include specific asset fields in the response (CDA getEntry).
* Use with asset_fields[]: user_defined_fields, embedded, ai_suggested, visual_markups.
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.contentType("contentTypeUid").entry("entryUid").assetFields("user_defined_fields", "embedded").fetch();
*
* @param {...string} fields - Asset field names to include (e.g. user_defined_fields, embedded, ai_suggested, visual_markups)
* @returns {Entry} - Returns the Entry instance for chaining.
*/
assetFields(...fields: string[]): this {
if (fields.length > 0) {
this._queryParams['asset_fields[]'] = fields;
}
return this;
}
}
14 changes: 14 additions & 0 deletions test/api/asset-query.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,20 @@ describe("AssetQuery API tests", () => {
console.log('No assets found in stack - test data dependent');
}
});
it("should query assets with asset_fields[] CDA param (user_defined_fields, embedded, ai_suggested, visual_markups)", async () => {
const result = await makeAssetQuery()
.assetFields("user_defined_fields", "embedded", "ai_suggested", "visual_markups")
.limit(2)
.find<TAsset>();
if (result.assets) {
expect(result.assets).toBeDefined();
if (result.assets.length > 0) {
expect(result.assets[0].uid).toBeDefined();
expect(result.assets[0]._version).toBeDefined();
expect(result.assets[0].content_type).toBeDefined();
}
}
});
});
function makeAssetQuery(): AssetQuery {
const asset = stack.asset();
Expand Down
11 changes: 11 additions & 0 deletions test/api/asset.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,17 @@ describe('Asset API tests', () => {
expect(result.created_by).toBeDefined();
expect(result.updated_by).toBeDefined();
});

it('should fetch asset with asset_fields[] CDA param (user_defined_fields, embedded, ai_suggested, visual_markups)', async () => {
const result = await makeAsset(assetUid)
.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups')
.fetch<BaseAsset>();
expect(result).toBeDefined();
expect(result.uid).toBeDefined();
expect(result._version).toBeDefined();
expect(result.url).toBeDefined();
expect(result.filename).toBeDefined();
});
});
function makeAsset(uid = ''): Asset {
const asset = stack.asset(uid);
Expand Down
13 changes: 13 additions & 0 deletions test/api/entries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,19 @@ describe("Entries API test cases", () => {
if (data.entries) expect(data.entries.length).toBeGreaterThan(0);
});

it("should query entries with asset_fields[] CDA param (user_defined_fields, embedded, ai_suggested, visual_markups)", async () => {
const result = await makeEntries(BLOG_POST_CT)
.assetFields("user_defined_fields", "embedded", "ai_suggested", "visual_markups")
.find<TEntry>();
if (result.entries) {
expect(result.entries).toBeDefined();
if (result.entries.length > 0) {
expect(result.entries[0].uid).toBeDefined();
expect(result.entries[0]._version).toBeDefined();
}
}
});

it("CT Taxonomies Query: Get Entries With Taxonomy Terms Parent and Excluding the term itself ($above, level)", async () => {
// ABOVE operation finds entries tagged with PARENT terms of the given term
// Requires a child term (e.g., term_one_child) to find its parents
Expand Down
10 changes: 10 additions & 0 deletions test/api/entry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ describe('Entry API tests', () => {
expect(result._version).toBeDefined();
expect(result.publish_details).toBeDefined();
});

it('should fetch entry with asset_fields[] CDA param (user_defined_fields, embedded, ai_suggested, visual_markups)', async () => {
const result = await makeEntry(entryUid)
.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups')
.fetch<TEntry>();
expect(result).toBeDefined();
expect(result.uid).toBeDefined();
expect(result._version).toBeDefined();
expect(result.locale).toBeDefined();
});
});
function makeEntry(uid = ''): Entry {
const entry = stack.contentType(BLOG_POST_CT).entry(uid);
Expand Down
22 changes: 22 additions & 0 deletions test/unit/asset-query.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ describe('AssetQuery class', () => {
expect(assetQuery._queryParams.locale).toBe('en-us');
});

it('should add "asset_fields[]" in _queryParams when assetFields method is called', () => {
const returnedValue = assetQuery.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups');
expect(returnedValue).toBeInstanceOf(AssetQuery);
expect(assetQuery._queryParams['asset_fields[]']).toEqual(['user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups']);
});

it('should not set asset_fields[] when assetFields is called with no arguments', () => {
assetQuery.assetFields();
expect(assetQuery._queryParams['asset_fields[]']).toBeUndefined();
});

it('should return response data when successful', async () => {
mockClient.onGet('/assets').reply(200, assetQueryFindResponseDataMock);
const response = await assetQuery.find();
Expand All @@ -72,4 +83,15 @@ describe('AssetQuery class', () => {
expect(returnedValue._parameters).toEqual({ fieldUid: 'value' });
}
});

it('should call find with asset_fields[] query params when assetFields is set', async () => {
mockClient.onGet('/assets').reply((config) => {
expect(config.params).toBeDefined();
expect(config.params['asset_fields[]']).toEqual(['user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups']);
return [200, assetQueryFindResponseDataMock];
});
assetQuery.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups');
const result = await assetQuery.find();
expect(result).toEqual(assetQueryFindResponseDataMock);
});
});
22 changes: 22 additions & 0 deletions test/unit/asset.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ describe('Asset class', () => {
expect(asset._queryParams.version).toBe('1');
});

it('should add "asset_fields[]" in _queryParams when assetFields method is called', () => {
const returnedValue = asset.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups');
expect(returnedValue).toBeInstanceOf(Asset);
expect(asset._queryParams['asset_fields[]']).toEqual(['user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups']);
});

it('should not set asset_fields[] when assetFields is called with no arguments', () => {
asset.assetFields();
expect(asset._queryParams['asset_fields[]']).toBeUndefined();
});

it('should add "fetch" in _queryParams when fetch method is called', async () => {
mockClient.onGet(`/assets/assetUid`).reply(200, assetFetchDataMock);
const returnedValue = await asset.fetch();
Expand All @@ -74,4 +85,15 @@ describe('Asset class', () => {

expect(result).toEqual(responseWithoutAsset);
});

it('should call fetch with asset_fields[] query params when assetFields is set', async () => {
mockClient.onGet(`/assets/assetUid`).reply((config) => {
expect(config.params).toBeDefined();
expect(config.params['asset_fields[]']).toEqual(['user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups']);
return [200, assetFetchDataMock];
});
asset.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups');
const result = await asset.fetch();
expect(result).toEqual(assetFetchDataMock.asset);
});
});
22 changes: 22 additions & 0 deletions test/unit/entries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ describe('Entries class', () => {
expect(entry._queryParams.include_content_type).toBe('true');
});

it('should add "asset_fields[]" in _queryParams when assetFields method is called', () => {
const returnedValue = entry.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups');
expect(returnedValue).toBeInstanceOf(Entries);
expect(entry._queryParams['asset_fields[]']).toEqual(['user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups']);
});

it('should not set asset_fields[] when assetFields is called with no arguments', () => {
entry.assetFields();
expect(entry._queryParams['asset_fields[]']).toBeUndefined();
});

it('should add "include_reference_content_type_uid" in _queryParams when includeReferenceContentTypeUID method is called', () => {
const returnedValue = entry.includeReferenceContentTypeUID();
expect(returnedValue).toBeInstanceOf(Entries);
Expand Down Expand Up @@ -149,6 +160,17 @@ describe('Entries class', () => {
expect(returnedValue).toEqual(entryFindMock);
});

it('should call find with asset_fields[] query params when assetFields is set', async () => {
mockClient.onGet(`/content_types/contentTypeUid/entries`).reply((config) => {
expect(config.params).toBeDefined();
expect(config.params['asset_fields[]']).toEqual(['user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups']);
return [200, entryFindMock];
});
entry.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups');
const result = await entry.find();
expect(result).toEqual(entryFindMock);
});

it('CT Taxonomy Query: Get entries with one term', () => {
const query = entry.query().where("taxonomies.taxonomy_uid", QueryOperation.EQUALS, "term_uid");
expect(query._parameters).toEqual({"taxonomies.taxonomy_uid": "term_uid"});
Expand Down
24 changes: 24 additions & 0 deletions test/unit/entry.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,17 @@ describe('Entry class', () => {
expect(entry._queryParams.key3).toEqual(['value3']);
});

it('should add "asset_fields[]" in _queryParams when assetFields method is called', () => {
const returnedValue = entry.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups');
expect(returnedValue).toBeInstanceOf(Entry);
expect(entry._queryParams['asset_fields[]']).toEqual(['user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups']);
});

it('should not set asset_fields[] when assetFields is called with no arguments', () => {
entry.assetFields();
expect(entry._queryParams['asset_fields[]']).toBeUndefined();
});

it('should get the API response when fetch method is called', async () => {
mockClient.onGet(`/content_types/contentTypeUid/entries/entryUid`).reply(200, entryFetchMock);
const returnedValue = await entry.fetch();
Expand Down Expand Up @@ -237,4 +248,17 @@ describe('Fetch with variants', () => {

expect(result).toEqual(responseWithoutEntry);
});

it('should call fetch with asset_fields[] query params when assetFields is set', async () => {
mockClient.onGet('/content_types/contentTypeUid/entries/entryUid').reply((config) => {
expect(config.params).toBeDefined();
expect(config.params['asset_fields[]']).toEqual(['user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups']);
return [200, entryFetchMock];
});

entry.assetFields('user_defined_fields', 'embedded', 'ai_suggested', 'visual_markups');
const result = await entry.fetch();

expect(result).toEqual(entryFetchMock.entry);
});
})