Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
240d7f5
feat: Implement Taxonomy class and update TaxonomyQuery for enhanced …
harshithad0703 Oct 13, 2025
77caa3b
Merge pull request #240 from contentstack/feat/dx-3628-get-all-taxonomy
harshithad0703 Oct 14, 2025
df96f25
get a single taxonomy
harshithad0703 Oct 17, 2025
056fc6d
Merge pull request #242 from contentstack/feat/dx-3629-single-taxonomy
harshithad0703 Oct 17, 2025
c213dd8
feat: Add Term and TermQuery classes for enhanced taxonomy term manag…
harshithad0703 Oct 23, 2025
b7e629a
refactor: Rename TermQueryFindResponseDataMock to termQueryFindRespon…
harshithad0703 Oct 23, 2025
6ed4fdb
Merge pull request #243 from contentstack/feat/dx-3630-get-terms
harshithad0703 Oct 23, 2025
908f206
feat: Add locales method to Term class and corresponding tests
harshithad0703 Oct 28, 2025
92d633d
refactor: Update locales method in Term class to return data directly…
harshithad0703 Oct 28, 2025
33bca3b
Merge pull request #247 from contentstack/feat/dx-3632-terms-loacales
harshithad0703 Oct 28, 2025
c4695d8
feat: Add ancestors method to Term class and update related tests
harshithad0703 Oct 28, 2025
7a8b8a4
Merge pull request #248 from contentstack/feat/dx-3634-ancestors
harshithad0703 Oct 28, 2025
4e97212
feat: Add descendants method to Term class and update related tests
harshithad0703 Oct 28, 2025
519c7a3
feat: Enhance Taxonomy and TermQuery classes with detailed documentat…
harshithad0703 Oct 28, 2025
62e3994
docs: Update descriptions in Taxonomy and Term classes to clarify pub…
harshithad0703 Oct 28, 2025
6a8122f
feat: type definitions for taxonomy management
harshithad0703 Oct 28, 2025
75c7d9a
Merge pull request #249 from contentstack/feat/dx-3633-descendants
harshithad0703 Oct 29, 2025
19aa8d5
Merge branch 'main' into feat/dx-3797-update-taxonomy-api
harshithad0703 Dec 15, 2025
13fa7d9
refactor: update API endpoints from /taxonomy-manager to /taxonomies
harshithad0703 Dec 15, 2025
251a61c
Merge branch 'main' into feat/taxonomy-publishing
harshithad0703 Dec 15, 2025
d88c4fc
Merge branch 'feat/taxonomy-publishing' into feat/dx-3797-update-taxo…
harshithad0703 Dec 15, 2025
a85d2a2
Merge pull request #284 from contentstack/feat/dx-3797-update-taxonom…
harshithad0703 Dec 15, 2025
63b49fd
Merge branch 'main' into feat/taxonomy-publishing
harshithad0703 Jan 13, 2026
38e9def
Merge branch 'main' into feat/taxonomy-publishing
harshithad0703 Jan 13, 2026
43bc2aa
test: update locales test case to include assertions
harshithad0703 Jan 19, 2026
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
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type { ImageTransform } from './lib/image-transform';
export type { AssetQuery } from './lib/asset-query';
export type { TaxonomyQuery } from './lib/taxonomy-query';
export type { ContentTypeQuery } from './lib/contenttype-query';
export type { Taxonomy } from './lib/taxonomy';
export { ErrorMessages, ErrorCode } from './lib/error-messages';

export default contentstack;
8 changes: 7 additions & 1 deletion src/lib/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import {TaxonomyQuery} from './taxonomy-query';
import { GlobalFieldQuery } from './global-field-query';
import { GlobalField } from './global-field';
import { Taxonomy } from './taxonomy';

export class Stack {
readonly config: StackConfig;
Expand All @@ -27,6 +28,7 @@
* @returns {Asset}
* @example
* import contentstack from '@contentstack/delivery-sdk'
import { Taxonomy } from './taxonomy';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@harshithad0703 Fix this docstring

*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const asset = stack.asset() // For collection of asset
Expand Down Expand Up @@ -78,7 +80,11 @@

* const taxonomy = stack.taxonomy() // For taxonomy query object
*/
taxonomy(): TaxonomyQuery {
taxonomy(): TaxonomyQuery;
taxonomy(uid: string): Taxonomy;
taxonomy(uid?: string): Taxonomy | TaxonomyQuery {
if (uid) return new Taxonomy(this._client, uid);

Check warning on line 86 in src/lib/stack.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

Check warning on line 86 in src/lib/stack.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

return new TaxonomyQuery(this._client);
}

Expand Down
35 changes: 28 additions & 7 deletions src/lib/taxonomy-query.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
import { Query } from "./query";
import { AxiosInstance } from "@contentstack/core";
import { AxiosInstance, getData } from "@contentstack/core";
import { FindResponse } from "./types";

export class TaxonomyQuery extends Query {
constructor(client: AxiosInstance) {
super(client, {}, {}); // will need make changes to Query class so that CT uid is not mandatory
this._client = client;
this._urlPath = `/taxonomies/entries`;
}
};
constructor(client: AxiosInstance) {
super(client, {}, {}); // will need make changes to Query class so that CT uid is not mandatory
this._client = client;
this._urlPath = `/taxonomies/entries`;
}
/**
* @method find
* @memberof TaxonomyQuery
* @description Fetches a list of all published taxonomies available in the stack.
* @returns {Promise<FindResponse<T>>}
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const taxonomyQuery = stack.taxonomy();
* const result = await taxonomyQuery.find();
*/
override async find<T>(): Promise<FindResponse<T>> {
this._urlPath = "/taxonomies";
const response = await getData(this._client, this._urlPath, {
params: this._queryParams,
});

return response as FindResponse<T>;
}
}
68 changes: 68 additions & 0 deletions src/lib/taxonomy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { AxiosInstance, getData } from '@contentstack/core';
import { TermQuery } from './term-query';
import { Term } from './term';

/**
* @class Taxonomy
* @description Represents a published taxonomy with methods to fetch taxonomy data and manage terms. Requires taxonomy_publish feature flag to be enabled.
*/
export class Taxonomy {
private _client: AxiosInstance;
private _taxonomyUid: string;
private _urlPath: string;

_queryParams: { [key: string]: string | number } = {};

/**
* @constructor
* @param {AxiosInstance} client - The HTTP client instance
* @param {string} taxonomyUid - The taxonomy UID
*/
constructor(client: AxiosInstance, taxonomyUid: string) {
this._client = client;
this._taxonomyUid = taxonomyUid;
this._urlPath = `/taxonomies/${this._taxonomyUid}`;
}

/**
* @method term
* @memberof Taxonomy
* @description Gets a specific term or creates a term query
* @param {string} [uid] - Optional term UID. If provided, returns a Term instance. If not provided, returns a TermQuery instance.
* @returns {Term | TermQuery}
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* // Get a specific term
* const term = stack.taxonomy('taxonomy_uid').term('term_uid');
* // Get all terms
* const termQuery = stack.taxonomy('taxonomy_uid').term();
*/
term(uid: string): Term;
term(): TermQuery;
term(uid?: string): Term | TermQuery {
if (uid) return new Term(this._client, this._taxonomyUid, uid);

return new TermQuery(this._client, this._taxonomyUid);
}

/**
* @method fetch
* @memberof Taxonomy
* @description Fetches the taxonomy data by UID
* @returns {Promise<T>}
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.taxonomy('taxonomy_uid').fetch();
*/
async fetch<T>(): Promise<T> {
const response = await getData(this._client, this._urlPath);

if (response.taxonomy) return response.taxonomy as T;

return response;
}
}
40 changes: 40 additions & 0 deletions src/lib/term-query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { AxiosInstance, getData } from '@contentstack/core';
import { FindResponse } from './types';

/**
* @class TermQuery
* @description Represents a query for fetching multiple published terms from a taxonomy. Requires taxonomy_publish feature flag to be enabled.
*/
export class TermQuery {
private _taxonomyUid: string;
private _client: AxiosInstance;
private _urlPath: string;
_queryParams: { [key: string]: string | number } = {};

/**
* @constructor
* @param {AxiosInstance} client - The HTTP client instance
* @param {string} taxonomyUid - The taxonomy UID
*/
constructor(client: AxiosInstance, taxonomyUid: string) {
this._client = client;
this._taxonomyUid = taxonomyUid;
this._urlPath = `/taxonomies/${this._taxonomyUid}/terms`;
}

/**
* @method find
* @memberof TermQuery
* @description Fetches a list of all published terms within a specific taxonomy.
* @returns {Promise<FindResponse<T>>}
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.taxonomy('taxonomy_uid').term().find();
*/
async find<T>(): Promise<FindResponse<T>> {
const response = await getData(this._client, this._urlPath, { params: this._queryParams });
return response as FindResponse<T>;
}
}
93 changes: 93 additions & 0 deletions src/lib/term.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { AxiosInstance, getData } from "@contentstack/core";

/**
* @class Term
* @description Represents a published taxonomy term with methods to fetch term data, locales, ancestors, and descendants. Requires taxonomy_publish feature flag to be enabled.
*/
export class Term {
protected _client: AxiosInstance;
private _taxonomyUid: string;
private _termUid: string;
private _urlPath: string;

/**
* @constructor
* @param {AxiosInstance} client - The HTTP client instance
* @param {string} taxonomyUid - The taxonomy UID
* @param {string} termUid - The term UID
*/
constructor(client: AxiosInstance, taxonomyUid: string, termUid: string) {
this._client = client;
this._taxonomyUid = taxonomyUid;
this._termUid = termUid;
this._urlPath = `/taxonomies/${this._taxonomyUid}/terms/${this._termUid}`;
}

/**
* @method locales
* @memberof Term
* @description Fetches all published, localized versions of a single term.
* @returns {Promise<T>}
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.taxonomy('taxonomy_uid').term('term_uid').locales();
*/
async locales<T>(): Promise<T> {
const response = await getData(this._client, `${this._urlPath}/locales`);
if (response.locales) return response.locales as T;
return response;
}

/**
* @method ancestors
* @memberof Term
* @description Fetches all ancestors of a single published term, up to the root.
* @returns {Promise<T>}
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.taxonomy('taxonomy_uid').term('term_uid').ancestors();
*/
async ancestors<T>(): Promise<T> {
const response = await getData(this._client, `${this._urlPath}/ancestors`);
if (response.ancestors) return response.ancestors as T;
return response;
}

/**
* @method descendants
* @memberof Term
* @description Fetches all descendants of a single published term.
* @returns {Promise<T>}
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.taxonomy('taxonomy_uid').term('term_uid').descendants();
*/
async descendants<T>(): Promise<T> {
const response = await getData(this._client, `${this._urlPath}/descendants`);
if (response.descendants) return response.descendants as T;
return response;
}

/**
* @method fetch
* @memberof Term
* @description Fetches all descendants of a single published term.
* @returns {Promise<T>}
* @example
* import contentstack from '@contentstack/delivery-sdk'
*
* const stack = contentstack.stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
* const result = await stack.taxonomy('taxonomy_uid').term('term_uid').fetch();
*/
async fetch<T>(): Promise<T> {
const response = await getData(this._client, this._urlPath);
if (response.term) return response.term as T;
return response;
}
}
38 changes: 34 additions & 4 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@ export type queryParams = {

/**
* Interface for creating Contentstack plugins
*
*
* @example
* ```typescript
* import { ContentstackPlugin } from '@contentstack/delivery-sdk';
*
*
* class MyPlugin implements ContentstackPlugin {
* onRequest(config: any): any {
* // Modify request configuration
* console.log('Processing request:', config.url);
* return { ...config, headers: { ...config.headers, 'X-Custom-Header': 'value' } };
* }
*
*
* onResponse(request: any, response: any, data: any): any {
* // Process response data
* console.log('Processing response:', response.status);
* return { ...response, data: { ...data, processed: true } };
* }
* }
*
*
* const stack = contentstack.stack({
* apiKey: 'your-api-key',
* deliveryToken: 'your-delivery-token',
Expand Down Expand Up @@ -317,6 +317,8 @@ export interface FindResponse<T> {
assets?: T[];
global_fields?: T[];
count?: number;
taxonomies?: T[];
terms?: T[];
}

export interface LivePreviewQuery {
Expand All @@ -340,3 +342,31 @@ export type LivePreview = {
management_token?: string;
preview_token?: string;
};

export interface BaseTaxonomy {
uid: string;
name: string;
description?: string;
terms_count?: number;
created_at: string;
updated_at: string;
created_by: string;
updated_by: string;
type: string;
ACL: ACL;
publish_details?: PublishDetails;
}

export interface BaseTerm {
taxonomy_uid: string;
uid: string;
name: string;
created_by: string;
created_at: string;
updated_by: string;
updated_at: string;
children_count?: number;
depth?: number;
ACL: ACL;
publish_details?: PublishDetails;
}
33 changes: 33 additions & 0 deletions test/api/taxonomy.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* eslint-disable no-console */
/* eslint-disable promise/always-return */
import { stackInstance } from '../utils/stack-instance';
import { TTaxonomies, TTaxonomy } from './types';
import dotenv from 'dotenv';
import { TaxonomyQuery } from '../../src/lib/taxonomy-query';
import { Taxonomy } from '../../src/lib/taxonomy';

dotenv.config()

const stack = stackInstance();
describe('ContentType API test cases', () => {
it('should give taxonomies when taxonomies method is called', async () => {
const result = await makeTaxonomies().find<TTaxonomies>();
expect(result).toBeDefined();
});

it('should give a single taxonomy when taxonomy method is called with taxonomyUid', async () => {
const result = await makeTaxonomy('taxonomy_testing').fetch<TTaxonomy>();
expect(result).toBeDefined();
});
});

function makeTaxonomies(): TaxonomyQuery {
const taxonomies = stack.taxonomy();

return taxonomies;
}

function makeTaxonomy(taxonomyUid: string): Taxonomy {
const taxonomy = stack.taxonomy(taxonomyUid);
return taxonomy;
}
Loading