@dainprotocol/cli 1.2.26 → 1.2.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,289 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ var path_1 = __importDefault(require("path"));
7
+ /**
8
+ * Build command tests - focusing on WASM detection, esbuild config, and static files
9
+ */
10
+ describe('build.ts', function () {
11
+ describe('findWasmFiles logic', function () {
12
+ // Test the WASM file filtering logic
13
+ function shouldIncludeWasmFile(fullPath) {
14
+ // Only include WASM files in dist/nodejs directories (Node.js bindings)
15
+ return fullPath.includes('/dist/') || fullPath.includes('/build/');
16
+ }
17
+ test('includes WASM files in /dist/ directories', function () {
18
+ expect(shouldIncludeWasmFile('/node_modules/package/dist/module.wasm')).toBe(true);
19
+ expect(shouldIncludeWasmFile('/node_modules/@scope/pkg/dist/nodejs/binding.wasm')).toBe(true);
20
+ });
21
+ test('includes WASM files in /build/ directories', function () {
22
+ expect(shouldIncludeWasmFile('/node_modules/package/build/Release/native.wasm')).toBe(true);
23
+ });
24
+ test('excludes WASM files in root of package', function () {
25
+ expect(shouldIncludeWasmFile('/node_modules/package/module.wasm')).toBe(false);
26
+ });
27
+ test('excludes WASM files in src directories', function () {
28
+ expect(shouldIncludeWasmFile('/node_modules/package/src/module.wasm')).toBe(false);
29
+ });
30
+ test('excludes WASM files in test directories', function () {
31
+ expect(shouldIncludeWasmFile('/node_modules/package/test/fixture.wasm')).toBe(false);
32
+ });
33
+ });
34
+ describe('directory scanning exclusions', function () {
35
+ // Test the directories that should be skipped
36
+ function shouldSkipDirectory(name) {
37
+ return name === '.bin' || name === '.cache';
38
+ }
39
+ test('skips .bin directory', function () {
40
+ expect(shouldSkipDirectory('.bin')).toBe(true);
41
+ });
42
+ test('skips .cache directory', function () {
43
+ expect(shouldSkipDirectory('.cache')).toBe(true);
44
+ });
45
+ test('does not skip regular directories', function () {
46
+ expect(shouldSkipDirectory('dist')).toBe(false);
47
+ expect(shouldSkipDirectory('src')).toBe(false);
48
+ expect(shouldSkipDirectory('@scope')).toBe(false);
49
+ });
50
+ test('does not skip .pnpm store (scanned for packages)', function () {
51
+ expect(shouldSkipDirectory('.pnpm')).toBe(false);
52
+ });
53
+ });
54
+ describe('copyWasmDependencies logic', function () {
55
+ // Test the bundle scanning for WASM references
56
+ function isWasmReferencedInBundle(wasmName, bundleContent) {
57
+ return bundleContent.includes(wasmName);
58
+ }
59
+ test('detects WASM file references in bundle', function () {
60
+ var bundle = "\n const wasmPath = require.resolve(\"zstd-codec/zstddec.wasm\");\n const decoder = new Decoder(wasmPath);\n ";
61
+ expect(isWasmReferencedInBundle('zstddec.wasm', bundle)).toBe(true);
62
+ });
63
+ test('does not match partial WASM names', function () {
64
+ var bundle = 'const zstddec_module = require("module");';
65
+ expect(isWasmReferencedInBundle('zstddec.wasm', bundle)).toBe(false);
66
+ });
67
+ test('handles multiple WASM references', function () {
68
+ var bundle = "\n require(\"libzstd.wasm\");\n require(\"wasm_exec.wasm\");\n ";
69
+ expect(isWasmReferencedInBundle('libzstd.wasm', bundle)).toBe(true);
70
+ expect(isWasmReferencedInBundle('wasm_exec.wasm', bundle)).toBe(true);
71
+ expect(isWasmReferencedInBundle('other.wasm', bundle)).toBe(false);
72
+ });
73
+ });
74
+ describe('runtime configuration', function () {
75
+ function getNodeBuildOptions(watch) {
76
+ return {
77
+ platform: 'node',
78
+ target: 'es2020',
79
+ minify: !watch,
80
+ };
81
+ }
82
+ function getWorkersBuildOptions() {
83
+ return {
84
+ format: 'esm',
85
+ target: 'esnext',
86
+ conditions: ['worker', 'workerd', 'browser'],
87
+ outExtension: { '.js': '.mjs' },
88
+ };
89
+ }
90
+ test('node runtime: platform is node', function () {
91
+ var options = getNodeBuildOptions(false);
92
+ expect(options.platform).toBe('node');
93
+ });
94
+ test('node runtime: minify when not watching', function () {
95
+ expect(getNodeBuildOptions(false).minify).toBe(true);
96
+ expect(getNodeBuildOptions(true).minify).toBe(false);
97
+ });
98
+ test('node runtime: targets ES2020', function () {
99
+ expect(getNodeBuildOptions(false).target).toBe('es2020');
100
+ });
101
+ test('workers runtime: uses ESM format', function () {
102
+ var options = getWorkersBuildOptions();
103
+ expect(options.format).toBe('esm');
104
+ });
105
+ test('workers runtime: targets esnext', function () {
106
+ var options = getWorkersBuildOptions();
107
+ expect(options.target).toBe('esnext');
108
+ });
109
+ test('workers runtime: has worker conditions', function () {
110
+ var options = getWorkersBuildOptions();
111
+ expect(options.conditions).toContain('worker');
112
+ expect(options.conditions).toContain('workerd');
113
+ expect(options.conditions).toContain('browser');
114
+ });
115
+ test('workers runtime: outputs .mjs files', function () {
116
+ var _a;
117
+ var options = getWorkersBuildOptions();
118
+ expect((_a = options.outExtension) === null || _a === void 0 ? void 0 : _a['.js']).toBe('.mjs');
119
+ });
120
+ test('runtime selection falls back to config then node', function () {
121
+ function resolveRuntime(optionsRuntime, configRuntime) {
122
+ return optionsRuntime || configRuntime || 'node';
123
+ }
124
+ expect(resolveRuntime('workers', 'node')).toBe('workers');
125
+ expect(resolveRuntime(undefined, 'workers')).toBe('workers');
126
+ expect(resolveRuntime(undefined, undefined)).toBe('node');
127
+ });
128
+ });
129
+ describe('output directory handling', function () {
130
+ test('resolves out-dir from config', function () {
131
+ var cwd = '/project';
132
+ var config = { 'out-dir': 'dist' };
133
+ var outDir = path_1.default.join(cwd, config['out-dir']);
134
+ expect(outDir).toBe('/project/dist');
135
+ });
136
+ test('defaults to "build" when not specified', function () {
137
+ var cwd = '/project';
138
+ var config = {};
139
+ var outDir = path_1.default.join(cwd, config['out-dir'] || 'build');
140
+ expect(outDir).toBe('/project/build');
141
+ });
142
+ test('watch mode uses .dain directory', function () {
143
+ var cwd = '/project';
144
+ var dainDir = path_1.default.join(cwd, '.dain');
145
+ var outDir = path_1.default.join(cwd, 'build');
146
+ function getTargetDir(isWatch) {
147
+ return isWatch ? dainDir : outDir;
148
+ }
149
+ expect(getTargetDir(true)).toBe('/project/.dain');
150
+ expect(getTargetDir(false)).toBe('/project/build');
151
+ });
152
+ });
153
+ describe('static files handling', function () {
154
+ test('resolves static-dir from config', function () {
155
+ var cwd = '/project';
156
+ var config = { 'static-dir': 'assets' };
157
+ var staticDir = path_1.default.join(cwd, config['static-dir']);
158
+ expect(staticDir).toBe('/project/assets');
159
+ });
160
+ test('defaults to "static" when not specified', function () {
161
+ var cwd = '/project';
162
+ var config = {};
163
+ var staticDir = config['static-dir']
164
+ ? path_1.default.join(cwd, config['static-dir'])
165
+ : path_1.default.join(cwd, 'static');
166
+ expect(staticDir).toBe('/project/static');
167
+ });
168
+ test('static output goes to targetDir/static', function () {
169
+ var targetDir = '/project/build';
170
+ var staticOutDir = path_1.default.join(targetDir, 'static');
171
+ expect(staticOutDir).toBe('/project/build/static');
172
+ });
173
+ });
174
+ describe('entry point handling', function () {
175
+ test('uses main-file from config', function () {
176
+ var config = { 'main-file': 'src/index.ts' };
177
+ expect(config['main-file']).toBe('src/index.ts');
178
+ });
179
+ test('entry point is always an array', function () {
180
+ var config = { 'main-file': 'src/server.ts' };
181
+ var entryPoints = [config['main-file']];
182
+ expect(Array.isArray(entryPoints)).toBe(true);
183
+ expect(entryPoints).toEqual(['src/server.ts']);
184
+ });
185
+ });
186
+ describe('WASM file extension detection', function () {
187
+ test('identifies .wasm files', function () {
188
+ var isWasm = function (filename) { return filename.endsWith('.wasm'); };
189
+ expect(isWasm('module.wasm')).toBe(true);
190
+ expect(isWasm('binding.wasm')).toBe(true);
191
+ expect(isWasm('decoder.WASM')).toBe(false); // Case sensitive
192
+ expect(isWasm('module.js')).toBe(false);
193
+ expect(isWasm('wasm.js')).toBe(false); // "wasm" in name, not extension
194
+ });
195
+ });
196
+ describe('path operations', function () {
197
+ test('basename extracts filename from path', function () {
198
+ expect(path_1.default.basename('/node_modules/pkg/dist/module.wasm')).toBe('module.wasm');
199
+ expect(path_1.default.basename('/long/nested/path/file.wasm')).toBe('file.wasm');
200
+ });
201
+ test('join constructs destination path', function () {
202
+ var outDir = '/project/build';
203
+ var wasmName = 'decoder.wasm';
204
+ var destPath = path_1.default.join(outDir, wasmName);
205
+ expect(destPath).toBe('/project/build/decoder.wasm');
206
+ });
207
+ });
208
+ describe('bundle path calculation', function () {
209
+ test('calculates bundle path for standard build', function () {
210
+ var targetDir = '/project/build';
211
+ var bundlePath = path_1.default.join(targetDir, 'index.js');
212
+ expect(bundlePath).toBe('/project/build/index.js');
213
+ });
214
+ test('calculates bundle path for watch mode', function () {
215
+ var dainDir = '/project/.dain';
216
+ var bundlePath = path_1.default.join(dainDir, 'index.js');
217
+ expect(bundlePath).toBe('/project/.dain/index.js');
218
+ });
219
+ });
220
+ describe('error handling', function () {
221
+ test('unsupported runtime throws error', function () {
222
+ function validateRuntime(runtime) {
223
+ if (runtime !== 'node' && runtime !== 'workers') {
224
+ throw new Error("Unsupported runtime: ".concat(runtime));
225
+ }
226
+ }
227
+ expect(function () { return validateRuntime('node'); }).not.toThrow();
228
+ expect(function () { return validateRuntime('workers'); }).not.toThrow();
229
+ expect(function () { return validateRuntime('deno'); }).toThrow('Unsupported runtime: deno');
230
+ expect(function () { return validateRuntime('bun'); }).toThrow('Unsupported runtime: bun');
231
+ });
232
+ });
233
+ describe('sourcemap generation', function () {
234
+ test('sourcemap is always enabled', function () {
235
+ var buildOptions = { sourcemap: true };
236
+ expect(buildOptions.sourcemap).toBe(true);
237
+ });
238
+ });
239
+ describe('bundle configuration', function () {
240
+ test('bundle option is always true', function () {
241
+ var buildOptions = { bundle: true };
242
+ expect(buildOptions.bundle).toBe(true);
243
+ });
244
+ });
245
+ });
246
+ describe('WASM detection patterns', function () {
247
+ // Common WASM packages that should be detected
248
+ var commonWasmPackages = [
249
+ '@noble/ed25519',
250
+ '@solana/buffer-layout',
251
+ 'zstd-codec',
252
+ 'zstddec',
253
+ 'wasm-pack',
254
+ ];
255
+ describe('common package paths', function () {
256
+ test.each(commonWasmPackages)('detects %s dist WASM files', function (pkg) {
257
+ var distPath = "/node_modules/".concat(pkg, "/dist/module.wasm");
258
+ expect(distPath.includes('/dist/')).toBe(true);
259
+ });
260
+ });
261
+ describe('pnpm store paths', function () {
262
+ test('handles .pnpm versioned paths', function () {
263
+ var pnpmPath = '/node_modules/.pnpm/zstd-codec@0.1.5/node_modules/zstd-codec/dist/zstddec.wasm';
264
+ expect(pnpmPath.includes('/dist/')).toBe(true);
265
+ expect(pnpmPath.endsWith('.wasm')).toBe(true);
266
+ });
267
+ test('handles scoped packages in pnpm', function () {
268
+ var pnpmPath = '/node_modules/.pnpm/@solana+web3.js@1.95.0/node_modules/@solana/web3.js/dist/binding.wasm';
269
+ expect(pnpmPath.includes('/dist/')).toBe(true);
270
+ });
271
+ });
272
+ });
273
+ describe('build process exit behavior', function () {
274
+ test('non-watch, non-deploy mode exits with 0', function () {
275
+ var options = { watch: false, deploy: false };
276
+ var shouldExit = !options.watch && !options.deploy;
277
+ expect(shouldExit).toBe(true);
278
+ });
279
+ test('watch mode does not exit', function () {
280
+ var options = { watch: true, deploy: false };
281
+ var shouldExit = !options.watch && !options.deploy;
282
+ expect(shouldExit).toBe(false);
283
+ });
284
+ test('deploy mode does not exit', function () {
285
+ var options = { watch: false, deploy: true };
286
+ var shouldExit = !options.watch && !options.deploy;
287
+ expect(shouldExit).toBe(false);
288
+ });
289
+ });
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var utils_1 = require("../utils");
4
+ // Mock fs-extra before importing
5
+ jest.mock('fs-extra', function () { return ({
6
+ readFile: jest.fn(),
7
+ readdir: jest.fn(),
8
+ existsSync: jest.fn(),
9
+ readFileSync: jest.fn(),
10
+ }); });
11
+ // Test the env parsing logic directly
12
+ describe('loadEnvVariables', function () {
13
+ // Extract the parsing logic for testing
14
+ test('parses simple key=value pairs', function () {
15
+ var content = "FOO=bar\nBAZ=qux";
16
+ var result = (0, utils_1.parseEnvContent)(content);
17
+ expect(result).toEqual([
18
+ { name: 'FOO', value: 'bar' },
19
+ { name: 'BAZ', value: 'qux' },
20
+ ]);
21
+ });
22
+ test('handles values with = signs (like base64)', function () {
23
+ var content = "API_KEY=sk_test_abc123==\nSECRET=a=b=c=d";
24
+ var result = (0, utils_1.parseEnvContent)(content);
25
+ expect(result).toEqual([
26
+ { name: 'API_KEY', value: 'sk_test_abc123==' },
27
+ { name: 'SECRET', value: 'a=b=c=d' },
28
+ ]);
29
+ });
30
+ test('ignores comment lines', function () {
31
+ var content = "# This is a comment\nFOO=bar\n# Another comment\nBAZ=qux";
32
+ var result = (0, utils_1.parseEnvContent)(content);
33
+ expect(result).toEqual([
34
+ { name: 'FOO', value: 'bar' },
35
+ { name: 'BAZ', value: 'qux' },
36
+ ]);
37
+ });
38
+ test('ignores empty lines', function () {
39
+ var content = "FOO=bar\n\nBAZ=qux\n\n";
40
+ var result = (0, utils_1.parseEnvContent)(content);
41
+ expect(result).toEqual([
42
+ { name: 'FOO', value: 'bar' },
43
+ { name: 'BAZ', value: 'qux' },
44
+ ]);
45
+ });
46
+ test('removes surrounding quotes from values', function () {
47
+ var content = "FOO=\"bar\"\nBAZ='qux'\nSINGLE=\"quoted value\"";
48
+ var result = (0, utils_1.parseEnvContent)(content);
49
+ expect(result).toEqual([
50
+ { name: 'FOO', value: 'bar' },
51
+ { name: 'BAZ', value: 'qux' },
52
+ { name: 'SINGLE', value: 'quoted value' },
53
+ ]);
54
+ });
55
+ test('handles whitespace around = sign', function () {
56
+ var content = " FOO = bar\n BAZ=qux";
57
+ var result = (0, utils_1.parseEnvContent)(content);
58
+ expect(result).toEqual([
59
+ { name: 'FOO', value: 'bar' },
60
+ { name: 'BAZ', value: 'qux' },
61
+ ]);
62
+ });
63
+ test('skips lines without = sign', function () {
64
+ var content = "FOO=bar\nINVALID LINE\nBAZ=qux";
65
+ var result = (0, utils_1.parseEnvContent)(content);
66
+ expect(result).toEqual([
67
+ { name: 'FOO', value: 'bar' },
68
+ { name: 'BAZ', value: 'qux' },
69
+ ]);
70
+ });
71
+ test('skips lines with empty name or value', function () {
72
+ var content = "=bar\nFOO=\nVALID=value";
73
+ var result = (0, utils_1.parseEnvContent)(content);
74
+ expect(result).toEqual([
75
+ { name: 'VALID', value: 'value' },
76
+ ]);
77
+ });
78
+ test('handles complex production-like env file', function () {
79
+ var content = "# Production environment\nDATABASE_URL=postgresql://user:pass@host:5432/db?schema=public\nJWT_SECRET=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ\nREDIS_URL=\"redis://localhost:6379\"\nAPI_KEY='sk_live_abc123=='\n\n# Comment in the middle\nEMPTY_LINE_AFTER=true";
80
+ var result = (0, utils_1.parseEnvContent)(content);
81
+ expect(result).toHaveLength(5);
82
+ expect(result[0].name).toBe('DATABASE_URL');
83
+ expect(result[0].value).toContain('postgresql://');
84
+ expect(result[1].name).toBe('JWT_SECRET');
85
+ expect(result[1].value).toContain('eyJ');
86
+ expect(result[2].value).toBe('redis://localhost:6379');
87
+ expect(result[3].value).toBe('sk_live_abc123==');
88
+ });
89
+ });
90
+ describe('fetchWithTimeout', function () {
91
+ test('AbortController pattern is correct', function () {
92
+ // Test that our timeout pattern is implemented correctly
93
+ var controller = new AbortController();
94
+ // Signal starts as not aborted
95
+ expect(controller.signal.aborted).toBe(false);
96
+ // Abort changes the signal
97
+ controller.abort();
98
+ expect(controller.signal.aborted).toBe(true);
99
+ });
100
+ test('setTimeout + AbortController integration', function () {
101
+ jest.useFakeTimers();
102
+ var controller = new AbortController();
103
+ var timeoutMs = 100;
104
+ // Set up timeout to abort
105
+ var timeoutId = setTimeout(function () { return controller.abort(); }, timeoutMs);
106
+ expect(controller.signal.aborted).toBe(false);
107
+ // Advance time past timeout
108
+ jest.advanceTimersByTime(150);
109
+ expect(controller.signal.aborted).toBe(true);
110
+ clearTimeout(timeoutId);
111
+ jest.useRealTimers();
112
+ });
113
+ test('clearTimeout prevents abort', function () {
114
+ jest.useFakeTimers();
115
+ var controller = new AbortController();
116
+ var timeoutMs = 100;
117
+ var timeoutId = setTimeout(function () { return controller.abort(); }, timeoutMs);
118
+ // Clear before timeout
119
+ clearTimeout(timeoutId);
120
+ // Advance time past what would have been the timeout
121
+ jest.advanceTimersByTime(200);
122
+ // Should NOT be aborted since we cleared the timeout
123
+ expect(controller.signal.aborted).toBe(false);
124
+ jest.useRealTimers();
125
+ });
126
+ });