Skip to content

Commit 84fc2b4

Browse files
committed
build: fix cli build / modernize
<!-- ps-id: d669b3d0-e0e6-4462-8e45-666751095542 -->
1 parent 3956d25 commit 84fc2b4

File tree

9 files changed

+730
-680
lines changed

9 files changed

+730
-680
lines changed

package-lock.json

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

package.json

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,23 @@
77
"email": "[email protected]",
88
"url": "https://jmespath.site"
99
},
10-
"main": "dist/jmespath.umd.js",
10+
"type": "module",
1111
"bin": {
12-
"jp": "dist/lib/bin/jp.js"
12+
"jp": "./dist/cli.mjs"
1313
},
14-
"module": "dist/jmespath.esm.js",
15-
"typings": "dist/types/index.d.ts",
16-
"types": "dist/types/index.d.ts",
14+
"main": "./dist/index.cjs",
15+
"module": "./dist/index.mjs",
16+
"types": "./dist/index.d.ts",
1717
"exports": {
1818
".": {
19-
"types": "./dist/types/index.d.ts",
20-
"import": "./dist/jmespath.esm.js",
21-
"require": "./dist/jmespath.umd.js"
19+
"types": "./dist/index.d.ts",
20+
"import": "./dist/index.mjs",
21+
"require": "./dist/index.cjs"
22+
},
23+
"./cli": {
24+
"types": "./dist/cli.d.ts",
25+
"import": "./dist/cli.mjs",
26+
"require": "./dist/cli.cjs"
2227
}
2328
},
2429
"files": [
@@ -51,9 +56,10 @@
5156
"lint:fix": "biome check --write",
5257
"lint:ci": "biome check --diagnostic-level=error",
5358
"prebuild": "npx rimraf dist",
54-
"build": "npx tsc --outDir dist/lib -d --module commonjs && npx tsc --project tsconfig.bin.json && npx rollup -c rollup.config.ts",
59+
"build": "tsup",
60+
"dev": "ts-node src/cli.ts",
5561
"perf": "node --expose-gc scripts/perf.js",
56-
"start": "npx rollup -c rollup.config.ts -w",
62+
"start": "tsup --watch",
5763
"test": "vitest --run",
5864
"test:watch": "vitest",
5965
"test:prod": "npm run lint && npm run test && npm test -- test/build-artifacts.spec.ts",
@@ -66,21 +72,16 @@
6672
},
6773
"devDependencies": {
6874
"@biomejs/biome": "2.0.6",
69-
"@rollup/plugin-json": "^4.1.0",
70-
"@rollup/plugin-node-resolve": "^13.0.0",
71-
"@rollup/plugin-terser": "^0.4.0",
72-
"@rollup/plugin-typescript": "^8.2.1",
7375
"@vitest/coverage-v8": "^3.2.4",
7476
"clean-publish": "^3.4.5",
7577
"coveralls-next": "^4.2.0",
7678
"husky": "^6.0.0",
7779
"lint-staged": "^11.0.0",
7880
"rimraf": "^3.0.2",
79-
"rollup": "^2.50.5",
80-
"rollup-plugin-typescript2": "^0.36.0",
8181
"shelljs": "^0.8.4",
8282
"tinybench": "^2.5.1",
8383
"ts-node": "^10.9.2",
84+
"tsup": "^8.5.0",
8485
"typescript": "^5.8.3",
8586
"vitest": "^3.2.4"
8687
}

rollup.config.ts

Lines changed: 0 additions & 49 deletions
This file was deleted.

bin/jp.ts renamed to src/cli.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
#! /usr/bin/env node
2-
31
'use strict';
42

53
import { ParseArgsConfig, parseArgs } from 'node:util';
64
import * as fs from 'fs';
75
import pkg from '../package.json';
8-
import jmespath, { JSONValue } from '../src';
6+
import jmespath, { JSONValue } from './index';
97

108
const args = getArgs();
119

src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,6 @@ export const jmespath = {
124124
TYPE_STRING,
125125
};
126126

127-
export default jmespath;
127+
// Export as default for backward compatibility
128+
// Supports both: import jmespath from '...' and import { jmespath } from '...'
129+
export { jmespath as default };

test/build-artifacts.spec.ts

Lines changed: 79 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,114 @@
1-
import { existsSync, readFileSync, statSync } from 'fs';
1+
import { execSync } from 'child_process';
2+
import { existsSync, readFileSync } from 'fs';
23
import { join } from 'path';
34
import { describe, expect, it } from 'vitest';
45

56
const DIST_DIR = join(process.cwd(), 'dist');
6-
const TYPES_DIR = join(DIST_DIR, 'types');
7-
const LIB_DIR = join(DIST_DIR, 'lib');
87

98
describe('Build Artifacts', () => {
109
describe('TypeScript Declarations', () => {
1110
it('should generate main index.d.ts file', () => {
12-
const indexDtsPath = join(TYPES_DIR, 'index.d.ts');
11+
const indexDtsPath = join(DIST_DIR, 'index.d.ts');
1312
expect(existsSync(indexDtsPath), `Expected ${indexDtsPath} to exist`).toBe(true);
1413

1514
const content = readFileSync(indexDtsPath, 'utf-8');
16-
expect(content).toContain('export declare function search');
17-
expect(content).toContain('export declare function compile');
18-
expect(content).toContain('export declare const registerFunction');
15+
expect(content).toContain('declare function search');
16+
expect(content).toContain('declare function compile');
17+
expect(content).toContain('declare const registerFunction');
1918
});
2019

21-
it('should generate all required type declaration files', () => {
22-
const requiredFiles = [
23-
'AST.type.d.ts',
24-
'JSON.type.d.ts',
25-
'Lexer.d.ts',
26-
'Lexer.type.d.ts',
27-
'Parser.d.ts',
28-
'Parser.type.d.ts',
29-
'Runtime.d.ts',
30-
'Scope.d.ts',
31-
'TreeInterpreter.d.ts',
32-
'utils/index.d.ts',
33-
'utils/strings.d.ts',
34-
'utils/text.d.ts',
35-
];
36-
37-
for (const file of requiredFiles) {
38-
const filePath = join(TYPES_DIR, file);
39-
expect(existsSync(filePath), `Expected ${filePath} to exist`).toBe(true);
40-
}
20+
it('should generate CLI type declarations', () => {
21+
const cliDtsPath = join(DIST_DIR, 'cli.d.ts');
22+
expect(existsSync(cliDtsPath), `Expected ${cliDtsPath} to exist`).toBe(true);
4123
});
4224

4325
it('should export all main types and functions', () => {
44-
const indexDtsPath = join(TYPES_DIR, 'index.d.ts');
26+
const indexDtsPath = join(DIST_DIR, 'index.d.ts');
4527
const content = readFileSync(indexDtsPath, 'utf-8');
4628

4729
// Check for main function exports
48-
expect(content).toContain('export declare function search');
49-
expect(content).toContain('export declare function compile');
50-
expect(content).toContain('export declare function tokenize');
30+
expect(content).toContain('declare function search');
31+
expect(content).toContain('declare function compile');
32+
expect(content).toContain('declare function tokenize');
5133

5234
// Check for type exports
53-
expect(content).toContain('export type { JSONArray, JSONObject, JSONPrimitive, JSONValue }');
54-
expect(content).toContain('export type { Options }');
55-
expect(content).toContain('export type { BuiltInFunctionNames');
35+
expect(content).toContain('type JSONArray');
36+
expect(content).toContain('type JSONObject');
37+
expect(content).toContain('type JSONPrimitive');
38+
expect(content).toContain('type JSONValue');
5639

5740
// Check for constant exports
58-
expect(content).toContain('export declare const TYPE_ANY');
59-
expect(content).toContain('export declare const TYPE_STRING');
60-
expect(content).toContain('export declare const TYPE_NUMBER');
41+
expect(content).toContain('declare const TYPE_ANY');
42+
expect(content).toContain('declare const TYPE_STRING');
43+
expect(content).toContain('declare const TYPE_NUMBER');
6144
});
6245
});
6346

64-
describe('UMD and ESM Bundles', () => {
65-
it('should generate UMD bundle', () => {
66-
const umdPath = join(DIST_DIR, 'jmespath.umd.js');
67-
expect(existsSync(umdPath), `Expected ${umdPath} to exist`).toBe(true);
47+
describe('Modern Dual Format Bundles', () => {
48+
it('should generate CommonJS bundle', () => {
49+
const cjsPath = join(DIST_DIR, 'index.cjs');
50+
expect(existsSync(cjsPath), `Expected ${cjsPath} to exist`).toBe(true);
6851

69-
const content = readFileSync(umdPath, 'utf-8');
70-
expect(content).toContain('(function (global, factory)');
71-
});
72-
73-
it('should generate minified UMD bundle', () => {
74-
const umdMinPath = join(DIST_DIR, 'jmespath.umd.min.js');
75-
expect(existsSync(umdMinPath), `Expected ${umdMinPath} to exist`).toBe(true);
76-
77-
const stat = statSync(umdMinPath);
78-
expect(stat.size).toBeGreaterThan(0);
52+
const content = readFileSync(cjsPath, 'utf-8');
53+
expect(content).toContain('exports');
7954
});
8055

8156
it('should generate ESM bundle', () => {
82-
const esmPath = join(DIST_DIR, 'jmespath.esm.js');
57+
const esmPath = join(DIST_DIR, 'index.mjs');
8358
expect(existsSync(esmPath), `Expected ${esmPath} to exist`).toBe(true);
8459

8560
const content = readFileSync(esmPath, 'utf-8');
86-
expect(content).toContain('export {');
61+
expect(content).toContain('export');
8762
});
8863

89-
it('should generate minified ESM bundle', () => {
90-
const esmMinPath = join(DIST_DIR, 'jmespath.esm.min.js');
91-
expect(existsSync(esmMinPath), `Expected ${esmMinPath} to exist`).toBe(true);
64+
it('should generate source maps', () => {
65+
const cjsMapPath = join(DIST_DIR, 'index.cjs.map');
66+
const esmMapPath = join(DIST_DIR, 'index.mjs.map');
9267

93-
const stat = statSync(esmMinPath);
94-
expect(stat.size).toBeGreaterThan(0);
68+
expect(existsSync(cjsMapPath), `Expected ${cjsMapPath} to exist`).toBe(true);
69+
expect(existsSync(esmMapPath), `Expected ${esmMapPath} to exist`).toBe(true);
9570
});
9671
});
9772

9873
describe('CLI Binary', () => {
99-
it('should generate CLI binary', () => {
100-
const binPath = join(LIB_DIR, 'bin', 'jp.js');
74+
it('should generate CLI binary (ESM only)', () => {
75+
const binPath = join(DIST_DIR, 'cli.mjs');
10176
expect(existsSync(binPath), `Expected ${binPath} to exist`).toBe(true);
10277

10378
const content = readFileSync(binPath, 'utf-8');
104-
expect(content).toContain('#! /usr/bin/env node');
79+
expect(content).toContain('#!/usr/bin/env node');
10580
});
10681

10782
it('should generate source maps for CLI binary', () => {
108-
const mapPath = join(LIB_DIR, 'bin', 'jp.js.map');
109-
expect(existsSync(mapPath), `Expected ${mapPath} to exist`).toBe(true);
83+
const mjsMapPath = join(DIST_DIR, 'cli.mjs.map');
84+
expect(existsSync(mjsMapPath), `Expected ${mjsMapPath} to exist`).toBe(true);
85+
});
86+
87+
it('should have functional CLI that can execute JMESPath queries', () => {
88+
const binPath = join(DIST_DIR, 'cli.mjs');
89+
const testData = '{"foo": {"bar": "baz"}}';
90+
const query = 'foo.bar';
91+
92+
// Test basic functionality
93+
const result = execSync(`echo '${testData}' | node ${binPath} '${query}'`, {
94+
encoding: 'utf-8',
95+
cwd: process.cwd(),
96+
});
97+
98+
expect(result.trim()).toBe('"baz"');
99+
});
100+
101+
it('should show help when --help flag is used', () => {
102+
const binPath = join(DIST_DIR, 'cli.mjs');
103+
104+
const result = execSync(`node ${binPath} --help`, {
105+
encoding: 'utf-8',
106+
cwd: process.cwd(),
107+
});
108+
109+
expect(result).toContain('NAME:');
110+
expect(result).toContain('jp - jp [<options>] <expression>');
111+
expect(result).toContain('OPTIONS:');
110112
});
111113
});
112114

@@ -115,17 +117,17 @@ describe('Build Artifacts', () => {
115117
const pkgPath = join(process.cwd(), 'package.json');
116118
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
117119

118-
expect(pkg.main).toBe('dist/jmespath.umd.js');
119-
expect(pkg.module).toBe('dist/jmespath.esm.js');
120-
expect(pkg.types).toBe('dist/types/index.d.ts');
121-
expect(pkg.typings).toBe('dist/types/index.d.ts');
120+
expect(pkg.main).toBe('./dist/index.cjs');
121+
expect(pkg.module).toBe('./dist/index.mjs');
122+
expect(pkg.types).toBe('./dist/index.d.ts');
123+
expect(pkg.type).toBe('module');
122124
});
123125

124126
it('should have correct bin configuration', () => {
125127
const pkgPath = join(process.cwd(), 'package.json');
126128
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
127129

128-
expect(pkg.bin).toEqual({ jp: 'dist/lib/bin/jp.js' });
130+
expect(pkg.bin).toEqual({ jp: './dist/cli.mjs' });
129131
});
130132

131133
it('should include dist directory in files', () => {
@@ -141,9 +143,15 @@ describe('Build Artifacts', () => {
141143

142144
expect(pkg.exports).toBeDefined();
143145
expect(pkg.exports['.']).toBeDefined();
144-
expect(pkg.exports['.'].types).toBe('./dist/types/index.d.ts');
145-
expect(pkg.exports['.'].import).toBe('./dist/jmespath.esm.js');
146-
expect(pkg.exports['.'].require).toBe('./dist/jmespath.umd.js');
146+
expect(pkg.exports['.'].types).toBe('./dist/index.d.ts');
147+
expect(pkg.exports['.'].import).toBe('./dist/index.mjs');
148+
expect(pkg.exports['.'].require).toBe('./dist/index.cjs');
149+
150+
// Check CLI export
151+
expect(pkg.exports['./cli']).toBeDefined();
152+
expect(pkg.exports['./cli'].types).toBe('./dist/cli.d.ts');
153+
expect(pkg.exports['./cli'].import).toBe('./dist/cli.mjs');
154+
expect(pkg.exports['./cli'].require).toBe('./dist/cli.cjs');
147155
});
148156
});
149157
});

tsconfig.bin.json

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)