Skip to content

Commit ca18aa6

Browse files
Merge pull request #176 from contentstack/staging
fix/esm-js-extension-issue
2 parents beb6cd0 + 95f925b commit ca18aa6

9 files changed

Lines changed: 253 additions & 29 deletions

File tree

.talismanrc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ fileignoreconfig:
33
ignore_detectors:
44
- filecontent
55
- filename: package-lock.json
6-
checksum: af3bffd9f46b71daf5b8dd0b3eace75dfd367e359b11503259dc00a8c7105bf0
6+
checksum: 59653dc17458f6bddffb6178bfb8f8191ad4715f41a788082a11d3b08e966b4c
77
- filename: .husky/pre-commit
88
checksum: 5baabd7d2c391648163f9371f0e5e9484f8fb90fa2284cfc378732ec3192c193
99
- filename: test/request.spec.ts
@@ -14,4 +14,6 @@ fileignoreconfig:
1414
checksum: 08ccd6342b3adbeb7b85309a034b4df4b2ad905a0cc2a3778ab483b61ba41b9e
1515
- filename: test/retryPolicy/delivery-sdk-handlers.spec.ts
1616
checksum: 6d22d7482aa6dccba5554ae497e5b0c3572357a5cead6f4822ee4428edc12207
17+
- filename: test/contentstack-core.spec.ts
18+
checksum: 2d1e0f63ad8ea37890de2aa6c7e394c83488888f4a40ad7a71eeba2290b95924
1719
version: ""

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
## Change log
22

3+
### Version: 1.3.8
4+
#### Date: Jan-12-2026
5+
- Fix: Add .js extensions to relative imports in ESM build for proper module resolution
6+
- Fix: Change lodash import from named import to default import for ESM compatibility with CommonJS modules
7+
8+
### Version: 1.3.7
9+
#### Date: Jan-12-2026
10+
- Fix: Improve error messages
11+
12+
13+
### Version: 1.3.8
14+
#### Date: Jan-15-2026
15+
- Fix: Add .js extensions to relative imports in ESM build for proper module resolution
16+
- Fix: Change lodash import from named import to default import for ESM compatibility with CommonJS modules
17+
318
### Version: 1.3.7
419
#### Date: Jan-12-2026
520
- Fix: Improve error messages

README.md

Lines changed: 98 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,128 @@
1+
# @contentstack/core
2+
13
[![Contentstack](https://www.contentstack.com/docs/static/images/contentstack.png)](https://www.contentstack.com/)
2-
## TypeScript Core SDK for Contentstack
4+
5+
TypeScript Core SDK for Contentstack - A foundational library providing core modules and utilities for Contentstack TypeScript SDKs.
6+
7+
## About Contentstack
38

49
Contentstack is a headless CMS with an API-first approach. It is a CMS that developers can use to build powerful cross-platform applications in their favorite languages. Build your application frontend, and Contentstack will take care of the rest. [Read More](https://www.contentstack.com/).
510

6-
### Prerequisite
11+
## Description
712

8-
You need Node.js version 4.4.7 or later installed to use the Contentstack TS Core SDK.
13+
This package contains core modules and utilities used by the [Contentstack TypeScript Delivery SDK](https://github.com/contentstack/contentstack-typescript/). It provides essential functionality including HTTP client configuration, error handling, request management, parameter serialization, and retry policies.
914

10-
## Installation
15+
## Features
1116

12-
```
17+
- **HTTP Client**: Configurable Axios-based HTTP client with support for custom adapters
18+
- **Error Handling**: Comprehensive error classes for API and Contentstack-specific errors
19+
- **Request Management**: Request handling with interceptors and custom error callbacks
20+
- **Parameter Serialization**: Custom parameter serialization for API requests
21+
- **Retry Policies**: Built-in retry logic for handling rate limits and transient errors
22+
- **TypeScript Support**: Full TypeScript definitions included
23+
- **Multiple Build Formats**: Supports CommonJS, ESM, UMD, and TypeScript declarations
24+
25+
## Important Note
26+
27+
**This package is an internal dependency** used by Contentstack TypeScript SDKs. End users should **not** install this package directly. Instead, install the appropriate Contentstack SDK (e.g., [Contentstack TypeScript Delivery SDK](https://github.com/contentstack/contentstack-typescript/)), which will automatically include this package as a dependency.
28+
29+
## For SDK Developers
30+
31+
If you are developing or maintaining a Contentstack SDK and need to use this core package directly, you can install it as a dependency:
32+
33+
```bash
1334
npm install @contentstack/core
1435
```
1536

16-
## Use case
37+
Then import the modules:
1738

18-
This package contains some core modules and utilities used by the [Contentstack Typescript Delivery SDK](https://github.com/contentstack/contentstack-javascript/) SDK.
39+
```typescript
40+
import {
41+
httpClient,
42+
// ... other exports
43+
} from '@contentstack/core';
44+
```
1945

2046
## Development
2147

22-
### Create the build:
48+
### Prerequisites
2349

50+
- Node.js version 4.4.7 or later
51+
52+
### Setup
53+
54+
Clone the repository and install dependencies:
55+
56+
```bash
57+
git clone https://github.com/contentstack/contentstack-js-core.git
58+
cd contentstack-js-core
59+
npm install
2460
```
61+
62+
### Build
63+
64+
Build all output formats (CommonJS, ESM, UMD, and TypeScript declarations):
65+
66+
```bash
2567
npm run build
2668
```
2769

28-
### Run Scripts:
29-
30-
Run the unit tests:
70+
Build specific formats:
3171

72+
```bash
73+
npm run build # Build all
74+
npm run build:cjs # CommonJS
75+
npm run build:esm # ES Modules
76+
npm run build:umd # UMD
77+
npm run build:types # TypeScript declarations
3278
```
79+
80+
### Testing
81+
82+
Run unit tests:
83+
84+
```bash
3385
npm run test
3486
```
3587

36-
Run the lint tests:
88+
Run linting:
3789

38-
```
90+
```bash
3991
npm run lint
4092
```
4193

42-
Pack the SDK:
94+
### Packaging
4395

44-
```
96+
Create a package tarball:
97+
98+
```bash
4599
npm run package
46-
```
100+
```
101+
102+
### Clean
103+
104+
Clean build artifacts:
105+
106+
```bash
107+
npm run clean
108+
```
109+
110+
## License
111+
112+
This project is licensed under the MIT License. See the [LICENSE.txt](LICENSE.txt) file for details.
113+
114+
## Repository
115+
116+
- **GitHub**: [contentstack/contentstack-js-core](https://github.com/contentstack/contentstack-js-core)
117+
118+
## Related Projects
119+
120+
- [Contentstack TypeScript Delivery SDK](https://github.com/contentstack/contentstack-javascript/)
121+
122+
## Support
123+
124+
For issues and feature requests, please visit the [GitHub Issues](https://github.com/contentstack/contentstack-js-core/issues) page.
125+
126+
---
127+
128+
Copyright (c) 2016-2025 Contentstack. All rights reserved.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/core",
3-
"version": "1.3.7",
3+
"version": "1.3.8",
44
"type": "commonjs",
55
"main": "./dist/cjs/src/index.js",
66
"types": "./dist/cjs/src/index.d.ts",

src/lib/contentstack-core.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { cloneDeep } from 'lodash';
1+
import _ from 'lodash';
22
import { serialize } from './param-serializer';
33
import axios, { AxiosRequestHeaders, getAdapter } from 'axios';
44
import { AxiosInstance, HttpClientParams } from './types';
@@ -20,6 +20,7 @@ export function httpClient(options: HttpClientParams): AxiosInstance {
2020
const title = [data.name, data.message].filter((a) => a).join(' - ');
2121
console.error(ERROR_MESSAGES.CONSOLE.ERROR_WITH_TITLE(title));
2222
}
23+
2324
return;
2425
}
2526
if (data !== undefined) {
@@ -38,7 +39,7 @@ export function httpClient(options: HttpClientParams): AxiosInstance {
3839

3940
const config: HttpClientParams = {
4041
...defaultConfig,
41-
...cloneDeep(options),
42+
..._.cloneDeep(options),
4243
};
4344

4445
if (config.apiKey && config.headers) {

test/contentstack-core.spec.ts

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ import { AxiosInstance } from '../src';
22
import { httpClient } from '../src/lib/contentstack-core';
33
import MockAdapter from 'axios-mock-adapter';
44
describe('contentstackCore', () => {
5-
it('should return default config when no config is passed', (done) => {
6-
const client = httpClient({});
7-
done();
5+
it('should return default config when no config is passed', () => {
6+
httpClient({});
87
});
98

109
describe('logHandler', () => {
@@ -17,7 +16,9 @@ describe('contentstackCore', () => {
1716
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
1817
httpClient({}).defaults.logHandler('error', error);
1918

20-
expect(consoleErrorSpy).toHaveBeenCalledWith('Error: Error - Something went wrong. Review the error details and try again.');
19+
expect(consoleErrorSpy).toHaveBeenCalledWith(
20+
'Error: Error - Something went wrong. Review the error details and try again.'
21+
);
2122

2223
consoleErrorSpy.mockRestore();
2324
});
@@ -152,7 +153,7 @@ describe('contentstackCore', () => {
152153
it('should call the onError function when an error occurs', async () => {
153154
// Suppress expected console.error from network error
154155
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
155-
156+
156157
const onError = jest.fn();
157158
const options = {
158159
defaultHostname: 'cdn.contentstack.io',
@@ -166,7 +167,7 @@ describe('contentstackCore', () => {
166167
} catch (error: unknown) {
167168
expect(onError).toBeCalledWith(error);
168169
}
169-
170+
170171
consoleErrorSpy.mockRestore();
171172
});
172173

@@ -188,4 +189,74 @@ describe('contentstackCore', () => {
188189
expect(client.httpClientParams.onError).not.toBeCalled();
189190
});
190191
});
192+
193+
describe('config deep cloning', () => {
194+
it('should properly handle nested objects in params using cloneDeep', () => {
195+
const options = {
196+
defaultHostname: 'example.com',
197+
params: {
198+
environment: 'test',
199+
nested: {
200+
level1: {
201+
level2: {
202+
value: 'deep-nested',
203+
},
204+
},
205+
},
206+
},
207+
};
208+
209+
const instance = httpClient(options);
210+
211+
// Verify nested structure is properly accessible
212+
// This test ensures cloneDeep is working correctly (ESM import fix)
213+
expect(instance.httpClientParams.params?.nested?.level1?.level2?.value).toBe('deep-nested');
214+
expect(instance.httpClientParams.params?.environment).toBe('test');
215+
});
216+
217+
it('should handle complex nested structures in params', () => {
218+
const complexOptions = {
219+
defaultHostname: 'example.com',
220+
params: {
221+
environment: 'production',
222+
filters: {
223+
category: {
224+
name: 'tech',
225+
tags: ['javascript', 'typescript'],
226+
},
227+
},
228+
},
229+
};
230+
231+
const instance = httpClient(complexOptions);
232+
233+
// Verify complex nested structure is properly handled
234+
expect(instance.httpClientParams.params?.filters?.category?.name).toBe('tech');
235+
expect(instance.httpClientParams.params?.filters?.category?.tags).toEqual(['javascript', 'typescript']);
236+
});
237+
238+
it('should work correctly with lodash cloneDeep import (ESM compatibility)', () => {
239+
// This test verifies that the lodash import works correctly in ESM
240+
// by ensuring nested object cloning works as expected
241+
const options = {
242+
defaultHostname: 'example.com',
243+
params: {
244+
query: {
245+
type: 'entry',
246+
include: {
247+
count: true,
248+
schema: true,
249+
},
250+
},
251+
},
252+
};
253+
254+
const instance = httpClient(options);
255+
256+
// If cloneDeep wasn't working (due to import issues), this would fail
257+
expect(instance.httpClientParams.params?.query?.type).toBe('entry');
258+
expect(instance.httpClientParams.params?.query?.include?.count).toBe(true);
259+
expect(instance.httpClientParams.params?.query?.include?.schema).toBe(true);
260+
});
261+
});
191262
});

test/esm-exports.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ describe('ESM Exports Tests', () => {
2828

2929
it('should re-export getData from ESM index.js', () => {
3030
const indexContent = fs.readFileSync(esmIndexPath, 'utf-8');
31-
expect(indexContent).toContain("export * from './lib/request'");
31+
expect(indexContent).toContain("export * from './lib/request.js'");
3232
});
3333

3434
it('should verify getData is a named export in ESM build', () => {

0 commit comments

Comments
 (0)