monocrate 0.1.0 → 0.3.0
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.
- package/dist/assemble.d.ts +3 -0
- package/dist/assemble.d.ts.map +1 -0
- package/dist/{bundle.js → assemble.js} +2 -2
- package/dist/assemble.js.map +1 -0
- package/dist/build-dependency-graph.d.ts +1 -1
- package/dist/build-dependency-graph.d.ts.map +1 -1
- package/dist/build-dependency-graph.js +6 -7
- package/dist/build-dependency-graph.js.map +1 -1
- package/dist/build-package-map.js +1 -1
- package/dist/build-package-map.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/monocrate-cli.d.ts.map +1 -1
- package/dist/monocrate-cli.js +15 -13
- package/dist/monocrate-cli.js.map +1 -1
- package/dist/monocrate.d.ts +35 -11
- package/dist/monocrate.d.ts.map +1 -1
- package/dist/monocrate.js +79 -17
- package/dist/monocrate.js.map +1 -1
- package/dist/transform-package-json.js +1 -1
- package/dist/transform-package-json.js.map +1 -1
- package/package.json +9 -4
- package/dist/bundle.d.ts +0 -3
- package/dist/bundle.d.ts.map +0 -1
- package/dist/bundle.js.map +0 -1
- package/dist/bundler.d.ts +0 -3
- package/dist/bundler.d.ts.map +0 -1
- package/dist/bundler.js +0 -62
- package/dist/bundler.js.map +0 -1
- package/dist/copy-bundler.d.ts +0 -3
- package/dist/copy-bundler.d.ts.map +0 -1
- package/dist/copy-bundler.js +0 -11
- package/dist/copy-bundler.js.map +0 -1
- package/dist/dependency-graph.d.ts +0 -3
- package/dist/dependency-graph.d.ts.map +0 -1
- package/dist/dependency-graph.js +0 -44
- package/dist/dependency-graph.js.map +0 -1
- package/dist/index.test.d.ts +0 -2
- package/dist/index.test.d.ts.map +0 -1
- package/dist/index.test.js +0 -110
- package/dist/index.test.js.map +0 -1
- package/dist/monocrate.test.d.ts +0 -2
- package/dist/monocrate.test.d.ts.map +0 -1
- package/dist/monocrate.test.js +0 -998
- package/dist/monocrate.test.js.map +0 -1
- package/dist/package-transformer.d.ts +0 -5
- package/dist/package-transformer.d.ts.map +0 -1
- package/dist/package-transformer.js +0 -20
- package/dist/package-transformer.js.map +0 -1
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/dist/monocrate.test.js
DELETED
|
@@ -1,998 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
2
|
-
import * as fs from 'node:fs';
|
|
3
|
-
import * as os from 'node:os';
|
|
4
|
-
import * as path from 'node:path';
|
|
5
|
-
import { describe, it, expect, afterEach } from 'vitest';
|
|
6
|
-
import { monocrate } from './index.js';
|
|
7
|
-
import { findMonorepoRoot } from './monorepo.js';
|
|
8
|
-
const tempDirs = [];
|
|
9
|
-
function createTempDir(prefix) {
|
|
10
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), prefix));
|
|
11
|
-
tempDirs.push(dir);
|
|
12
|
-
return dir;
|
|
13
|
-
}
|
|
14
|
-
function folderify(recipe) {
|
|
15
|
-
const ret = createTempDir('monocrate-test-');
|
|
16
|
-
const keys = Object.keys(recipe).map((p) => path.normalize(p));
|
|
17
|
-
const set = new Set(keys);
|
|
18
|
-
for (const key of keys) {
|
|
19
|
-
if (key === '.') {
|
|
20
|
-
throw new Error(`bad input - the recipe contains a file name which is either empty ('') or a dot ('.')`);
|
|
21
|
-
}
|
|
22
|
-
for (let curr = path.dirname(key); curr !== '.'; curr = path.dirname(curr)) {
|
|
23
|
-
if (set.has(curr)) {
|
|
24
|
-
throw new Error(`bad input - a file (${key}) is nested under another file (${curr})`);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
for (const [relativePath, content] of Object.entries(recipe)) {
|
|
29
|
-
const file = path.join(ret, relativePath);
|
|
30
|
-
const dir = path.dirname(file);
|
|
31
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
32
|
-
if (typeof content === 'string') {
|
|
33
|
-
fs.writeFileSync(file, content);
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
fs.writeFileSync(file, JSON.stringify(content, null, 2));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return ret;
|
|
40
|
-
}
|
|
41
|
-
function unfolderify(dir) {
|
|
42
|
-
const result = {};
|
|
43
|
-
function walk(currentDir, prefix) {
|
|
44
|
-
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
45
|
-
for (const entry of entries) {
|
|
46
|
-
const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
47
|
-
const fullPath = path.join(currentDir, entry.name);
|
|
48
|
-
if (entry.isDirectory()) {
|
|
49
|
-
walk(fullPath, relativePath);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
53
|
-
if (entry.name.endsWith('.json')) {
|
|
54
|
-
result[relativePath] = JSON.parse(content);
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
result[relativePath] = content;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
walk(dir, '');
|
|
63
|
-
return result;
|
|
64
|
-
}
|
|
65
|
-
async function runMonocrate(monorepoRoot, sourcePackage, entryPoint = 'dist/index.js') {
|
|
66
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
67
|
-
const result = await monocrate({
|
|
68
|
-
sourceDir: path.join(monorepoRoot, sourcePackage),
|
|
69
|
-
outputDir,
|
|
70
|
-
monorepoRoot,
|
|
71
|
-
});
|
|
72
|
-
if (!result.success) {
|
|
73
|
-
throw new Error(`monocrate failed: ${result.error}`);
|
|
74
|
-
}
|
|
75
|
-
let stdout = '';
|
|
76
|
-
let stderr = '';
|
|
77
|
-
try {
|
|
78
|
-
stdout = execSync(`node --enable-source-maps ${path.join(outputDir, entryPoint)}`, {
|
|
79
|
-
encoding: 'utf-8',
|
|
80
|
-
stdio: 'pipe',
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
stderr = error.stderr;
|
|
85
|
-
}
|
|
86
|
-
const output = unfolderify(outputDir);
|
|
87
|
-
return { stdout, stderr, output };
|
|
88
|
-
}
|
|
89
|
-
describe('monorepo discovery', () => {
|
|
90
|
-
afterEach(() => {
|
|
91
|
-
for (const dir of tempDirs) {
|
|
92
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
93
|
-
}
|
|
94
|
-
tempDirs.length = 0;
|
|
95
|
-
});
|
|
96
|
-
it('finds monorepo root with npm workspaces', () => {
|
|
97
|
-
const monorepoRoot = folderify({
|
|
98
|
-
'package.json': { name: 'my-monorepo', workspaces: ['packages/*'] },
|
|
99
|
-
'packages/app/package.json': { name: '@test/app' },
|
|
100
|
-
});
|
|
101
|
-
const found = findMonorepoRoot(path.join(monorepoRoot, 'packages/app'));
|
|
102
|
-
expect(found).toBe(monorepoRoot);
|
|
103
|
-
});
|
|
104
|
-
it('finds monorepo root with pnpm workspaces', () => {
|
|
105
|
-
const monorepoRoot = folderify({
|
|
106
|
-
'package.json': { name: 'pnpm-root' },
|
|
107
|
-
'pnpm-workspace.yaml': `packages:
|
|
108
|
-
- 'packages/*'
|
|
109
|
-
`,
|
|
110
|
-
'packages/app/package.json': { name: '@test/app' },
|
|
111
|
-
});
|
|
112
|
-
const found = findMonorepoRoot(path.join(monorepoRoot, 'packages/app'));
|
|
113
|
-
expect(found).toBe(monorepoRoot);
|
|
114
|
-
});
|
|
115
|
-
it('throws when no monorepo root is found', () => {
|
|
116
|
-
const tempDir = createTempDir('no-monorepo-');
|
|
117
|
-
fs.mkdirSync(path.join(tempDir, 'some-package'));
|
|
118
|
-
expect(() => findMonorepoRoot(path.join(tempDir, 'some-package'))).toThrow('Could not find monorepo root');
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
describe('error handling', () => {
|
|
122
|
-
afterEach(() => {
|
|
123
|
-
for (const dir of tempDirs) {
|
|
124
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
125
|
-
}
|
|
126
|
-
tempDirs.length = 0;
|
|
127
|
-
});
|
|
128
|
-
it('returns error when dist directory does not exist', async () => {
|
|
129
|
-
const monorepoRoot = folderify({
|
|
130
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
131
|
-
'packages/app/package.json': {
|
|
132
|
-
name: '@test/app',
|
|
133
|
-
version: '1.0.0',
|
|
134
|
-
main: 'dist/index.js',
|
|
135
|
-
},
|
|
136
|
-
// No dist directory created
|
|
137
|
-
});
|
|
138
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
139
|
-
const result = await monocrate({
|
|
140
|
-
sourceDir: path.join(monorepoRoot, 'packages/app'),
|
|
141
|
-
outputDir,
|
|
142
|
-
monorepoRoot,
|
|
143
|
-
});
|
|
144
|
-
expect(result.success).toBe(false);
|
|
145
|
-
if (!result.success) {
|
|
146
|
-
expect(result.error).toContain('dist directory not found');
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
it('returns error when package.json is invalid JSON syntax', async () => {
|
|
150
|
-
const monorepoRoot = folderify({
|
|
151
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
152
|
-
'packages/app/package.json': 'invalid json {{{',
|
|
153
|
-
});
|
|
154
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
155
|
-
const result = await monocrate({
|
|
156
|
-
sourceDir: path.join(monorepoRoot, 'packages/app'),
|
|
157
|
-
outputDir,
|
|
158
|
-
monorepoRoot,
|
|
159
|
-
});
|
|
160
|
-
expect(result.success).toBe(false);
|
|
161
|
-
});
|
|
162
|
-
it('returns error when package.json fails schema validation', async () => {
|
|
163
|
-
const monorepoRoot = folderify({
|
|
164
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
165
|
-
// Missing required 'name' field
|
|
166
|
-
'packages/app/package.json': { version: '1.0.0', main: 'dist/index.js' },
|
|
167
|
-
});
|
|
168
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
169
|
-
const result = await monocrate({
|
|
170
|
-
sourceDir: path.join(monorepoRoot, 'packages/app'),
|
|
171
|
-
outputDir,
|
|
172
|
-
monorepoRoot,
|
|
173
|
-
});
|
|
174
|
-
expect(result.success).toBe(false);
|
|
175
|
-
if (!result.success) {
|
|
176
|
-
expect(result.error).toContain('Invalid package.json');
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
it('returns error when source package directory has no package.json', async () => {
|
|
180
|
-
const monorepoRoot = folderify({
|
|
181
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
182
|
-
// No packages/app/package.json
|
|
183
|
-
});
|
|
184
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
185
|
-
const result = await monocrate({
|
|
186
|
-
sourceDir: path.join(monorepoRoot, 'packages/app'),
|
|
187
|
-
outputDir,
|
|
188
|
-
monorepoRoot,
|
|
189
|
-
});
|
|
190
|
-
expect(result.success).toBe(false);
|
|
191
|
-
if (!result.success) {
|
|
192
|
-
expect(result.error).toContain(`Could not find a monorepo package at ${monorepoRoot}/packages/app`);
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
it('works with workspace object format (packages field)', async () => {
|
|
196
|
-
const monorepoRoot = folderify({
|
|
197
|
-
'package.json': { workspaces: { packages: ['packages/*'] } },
|
|
198
|
-
'packages/app/package.json': {
|
|
199
|
-
name: '@test/app',
|
|
200
|
-
version: '1.0.0',
|
|
201
|
-
main: 'dist/index.js',
|
|
202
|
-
dependencies: { '@test/lib': 'workspace:*' },
|
|
203
|
-
},
|
|
204
|
-
'packages/app/dist/index.js': `import { greet } from '@test/lib';
|
|
205
|
-
console.log(greet());
|
|
206
|
-
`,
|
|
207
|
-
'packages/lib/package.json': {
|
|
208
|
-
name: '@test/lib',
|
|
209
|
-
version: '1.0.0',
|
|
210
|
-
main: 'dist/index.js',
|
|
211
|
-
},
|
|
212
|
-
'packages/lib/dist/index.js': `export function greet() {
|
|
213
|
-
return 'Hello!';
|
|
214
|
-
}
|
|
215
|
-
`,
|
|
216
|
-
});
|
|
217
|
-
const { stdout, output } = await runMonocrate(monorepoRoot, 'packages/app');
|
|
218
|
-
expect(output['package.json']).toEqual({
|
|
219
|
-
name: '@test/app',
|
|
220
|
-
version: '1.0.0',
|
|
221
|
-
main: 'dist/index.js',
|
|
222
|
-
});
|
|
223
|
-
expect(stdout.trim()).toBe('Hello!');
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
describe('package.json transformation', () => {
|
|
227
|
-
afterEach(() => {
|
|
228
|
-
for (const dir of tempDirs) {
|
|
229
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
230
|
-
}
|
|
231
|
-
tempDirs.length = 0;
|
|
232
|
-
});
|
|
233
|
-
it('preserves exports field in package.json', async () => {
|
|
234
|
-
const monorepoRoot = folderify({
|
|
235
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
236
|
-
'packages/app/package.json': {
|
|
237
|
-
name: '@test/app',
|
|
238
|
-
version: '1.0.0',
|
|
239
|
-
main: 'dist/index.js',
|
|
240
|
-
types: 'dist/index.d.ts',
|
|
241
|
-
exports: {
|
|
242
|
-
'.': {
|
|
243
|
-
types: './dist/index.d.ts',
|
|
244
|
-
import: './dist/index.js',
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
},
|
|
248
|
-
'packages/app/dist/index.js': `export const foo = 'foo';
|
|
249
|
-
`,
|
|
250
|
-
'packages/app/dist/index.d.ts': `export declare const foo: string;
|
|
251
|
-
`,
|
|
252
|
-
});
|
|
253
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
254
|
-
const result = await monocrate({
|
|
255
|
-
sourceDir: path.join(monorepoRoot, 'packages/app'),
|
|
256
|
-
outputDir,
|
|
257
|
-
monorepoRoot,
|
|
258
|
-
});
|
|
259
|
-
expect(result.success).toBe(true);
|
|
260
|
-
const output = unfolderify(outputDir);
|
|
261
|
-
const pkgJson = output['package.json'];
|
|
262
|
-
expect(pkgJson.exports).toEqual({
|
|
263
|
-
'.': {
|
|
264
|
-
types: './dist/index.d.ts',
|
|
265
|
-
import: './dist/index.js',
|
|
266
|
-
},
|
|
267
|
-
});
|
|
268
|
-
});
|
|
269
|
-
it('preserves metadata fields like description and keywords', async () => {
|
|
270
|
-
const monorepoRoot = folderify({
|
|
271
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
272
|
-
'packages/app/package.json': {
|
|
273
|
-
name: '@test/app',
|
|
274
|
-
version: '1.0.0',
|
|
275
|
-
main: 'dist/index.js',
|
|
276
|
-
description: 'Test package',
|
|
277
|
-
keywords: ['test', 'example'],
|
|
278
|
-
author: 'Test Author',
|
|
279
|
-
license: 'MIT',
|
|
280
|
-
},
|
|
281
|
-
'packages/app/dist/index.js': `export const foo = 'foo';
|
|
282
|
-
`,
|
|
283
|
-
});
|
|
284
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
285
|
-
const result = await monocrate({
|
|
286
|
-
sourceDir: path.join(monorepoRoot, 'packages/app'),
|
|
287
|
-
outputDir,
|
|
288
|
-
monorepoRoot,
|
|
289
|
-
});
|
|
290
|
-
expect(result.success).toBe(true);
|
|
291
|
-
const output = unfolderify(outputDir);
|
|
292
|
-
const pkgJson = output['package.json'];
|
|
293
|
-
expect(pkgJson.description).toBe('Test package');
|
|
294
|
-
expect(pkgJson.keywords).toEqual(['test', 'example']);
|
|
295
|
-
expect(pkgJson.author).toBe('Test Author');
|
|
296
|
-
expect(pkgJson.license).toBe('MIT');
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
describe('monocrate e2e', () => {
|
|
300
|
-
afterEach(() => {
|
|
301
|
-
for (const dir of tempDirs) {
|
|
302
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
303
|
-
}
|
|
304
|
-
tempDirs.length = 0;
|
|
305
|
-
});
|
|
306
|
-
it('bundles a simple package with an in-repo dependency', async () => {
|
|
307
|
-
const monorepoRoot = folderify({
|
|
308
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
309
|
-
'packages/app/package.json': {
|
|
310
|
-
name: '@test/app',
|
|
311
|
-
version: '1.0.0',
|
|
312
|
-
main: 'dist/index.js',
|
|
313
|
-
types: 'dist/index.d.ts',
|
|
314
|
-
dependencies: {
|
|
315
|
-
'@test/lib': 'workspace:*',
|
|
316
|
-
chalk: '^5.0.0',
|
|
317
|
-
},
|
|
318
|
-
},
|
|
319
|
-
'packages/app/dist/index.js': `import { greet } from '@test/lib';
|
|
320
|
-
console.log(greet('World'));
|
|
321
|
-
`,
|
|
322
|
-
'packages/app/dist/index.d.ts': `import { greet } from '@test/lib';
|
|
323
|
-
`,
|
|
324
|
-
'packages/lib/package.json': {
|
|
325
|
-
name: '@test/lib',
|
|
326
|
-
version: '1.0.0',
|
|
327
|
-
main: 'dist/index.js',
|
|
328
|
-
types: 'dist/index.d.ts',
|
|
329
|
-
dependencies: {
|
|
330
|
-
lodash: '^4.17.21',
|
|
331
|
-
},
|
|
332
|
-
},
|
|
333
|
-
'packages/lib/dist/index.js': `export function greet(name) {
|
|
334
|
-
return 'Hello, ' + name + '!';
|
|
335
|
-
}
|
|
336
|
-
`,
|
|
337
|
-
'packages/lib/dist/index.d.ts': `export declare function greet(name: string): string;
|
|
338
|
-
`,
|
|
339
|
-
});
|
|
340
|
-
const { stdout, output } = await runMonocrate(monorepoRoot, 'packages/app');
|
|
341
|
-
expect(output['package.json']).toEqual({
|
|
342
|
-
name: '@test/app',
|
|
343
|
-
version: '1.0.0',
|
|
344
|
-
main: 'dist/index.js',
|
|
345
|
-
types: 'dist/index.d.ts',
|
|
346
|
-
dependencies: {
|
|
347
|
-
chalk: '^5.0.0',
|
|
348
|
-
lodash: '^4.17.21',
|
|
349
|
-
},
|
|
350
|
-
});
|
|
351
|
-
expect(stdout.trim()).toBe('Hello, World!');
|
|
352
|
-
});
|
|
353
|
-
it('bundles only the requested package when monorepo has multiple packages', async () => {
|
|
354
|
-
const monorepoRoot = folderify({
|
|
355
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
356
|
-
// First app with its own lib and external dep
|
|
357
|
-
'packages/app-alpha/package.json': {
|
|
358
|
-
name: '@test/app-alpha',
|
|
359
|
-
version: '1.0.0',
|
|
360
|
-
main: 'dist/index.js',
|
|
361
|
-
dependencies: {
|
|
362
|
-
'@test/lib-alpha': 'workspace:*',
|
|
363
|
-
chalk: '^5.0.0',
|
|
364
|
-
},
|
|
365
|
-
},
|
|
366
|
-
'packages/app-alpha/dist/index.js': `import { getAlpha } from '@test/lib-alpha';
|
|
367
|
-
console.log('Alpha: ' + getAlpha());
|
|
368
|
-
`,
|
|
369
|
-
'packages/lib-alpha/package.json': {
|
|
370
|
-
name: '@test/lib-alpha',
|
|
371
|
-
version: '1.0.0',
|
|
372
|
-
main: 'dist/index.js',
|
|
373
|
-
dependencies: {
|
|
374
|
-
lodash: '^4.17.21',
|
|
375
|
-
},
|
|
376
|
-
},
|
|
377
|
-
'packages/lib-alpha/dist/index.js': `export function getAlpha() {
|
|
378
|
-
return 'ALPHA';
|
|
379
|
-
}
|
|
380
|
-
`,
|
|
381
|
-
// Second app with its own lib and different external dep
|
|
382
|
-
'packages/app-beta/package.json': {
|
|
383
|
-
name: '@test/app-beta',
|
|
384
|
-
version: '2.0.0',
|
|
385
|
-
main: 'dist/index.js',
|
|
386
|
-
dependencies: {
|
|
387
|
-
'@test/lib-beta': 'workspace:*',
|
|
388
|
-
zod: '^3.0.0',
|
|
389
|
-
},
|
|
390
|
-
},
|
|
391
|
-
'packages/app-beta/dist/index.js': `import { getBeta } from '@test/lib-beta';
|
|
392
|
-
console.log('Beta: ' + getBeta());
|
|
393
|
-
`,
|
|
394
|
-
'packages/lib-beta/package.json': {
|
|
395
|
-
name: '@test/lib-beta',
|
|
396
|
-
version: '2.0.0',
|
|
397
|
-
main: 'dist/index.js',
|
|
398
|
-
dependencies: {
|
|
399
|
-
uuid: '^9.0.0',
|
|
400
|
-
},
|
|
401
|
-
},
|
|
402
|
-
'packages/lib-beta/dist/index.js': `export function getBeta() {
|
|
403
|
-
return 'BETA';
|
|
404
|
-
}
|
|
405
|
-
`,
|
|
406
|
-
});
|
|
407
|
-
// Bundle only app-alpha
|
|
408
|
-
const alpha = await runMonocrate(monorepoRoot, 'packages/app-alpha');
|
|
409
|
-
expect(alpha.output['package.json']).toEqual({
|
|
410
|
-
name: '@test/app-alpha',
|
|
411
|
-
version: '1.0.0',
|
|
412
|
-
main: 'dist/index.js',
|
|
413
|
-
dependencies: {
|
|
414
|
-
chalk: '^5.0.0',
|
|
415
|
-
lodash: '^4.17.21',
|
|
416
|
-
},
|
|
417
|
-
});
|
|
418
|
-
expect(alpha.stdout.trim()).toBe('Alpha: ALPHA');
|
|
419
|
-
// Bundle only app-beta
|
|
420
|
-
const beta = await runMonocrate(monorepoRoot, 'packages/app-beta');
|
|
421
|
-
expect(beta.output['package.json']).toEqual({
|
|
422
|
-
name: '@test/app-beta',
|
|
423
|
-
version: '2.0.0',
|
|
424
|
-
main: 'dist/index.js',
|
|
425
|
-
dependencies: {
|
|
426
|
-
zod: '^3.0.0',
|
|
427
|
-
uuid: '^9.0.0',
|
|
428
|
-
},
|
|
429
|
-
});
|
|
430
|
-
expect(beta.stdout.trim()).toBe('Beta: BETA');
|
|
431
|
-
});
|
|
432
|
-
it('bundles deep chain of in-repo dependencies', async () => {
|
|
433
|
-
const monorepoRoot = folderify({
|
|
434
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
435
|
-
'packages/app/package.json': {
|
|
436
|
-
name: '@test/app',
|
|
437
|
-
version: '1.0.0',
|
|
438
|
-
main: 'dist/index.js',
|
|
439
|
-
dependencies: {
|
|
440
|
-
'@test/level1': 'workspace:*',
|
|
441
|
-
express: '^4.18.0',
|
|
442
|
-
},
|
|
443
|
-
},
|
|
444
|
-
'packages/app/dist/index.js': `import { fromLevel1 } from '@test/level1';
|
|
445
|
-
console.log(fromLevel1());
|
|
446
|
-
`,
|
|
447
|
-
'packages/level1/package.json': {
|
|
448
|
-
name: '@test/level1',
|
|
449
|
-
version: '1.0.0',
|
|
450
|
-
main: 'dist/index.js',
|
|
451
|
-
dependencies: {
|
|
452
|
-
'@test/level2': 'workspace:*',
|
|
453
|
-
lodash: '^4.17.21',
|
|
454
|
-
},
|
|
455
|
-
},
|
|
456
|
-
'packages/level1/dist/index.js': `import { fromLevel2 } from '@test/level2';
|
|
457
|
-
export function fromLevel1() {
|
|
458
|
-
return 'L1->' + fromLevel2();
|
|
459
|
-
}
|
|
460
|
-
`,
|
|
461
|
-
'packages/level2/package.json': {
|
|
462
|
-
name: '@test/level2',
|
|
463
|
-
version: '1.0.0',
|
|
464
|
-
main: 'dist/index.js',
|
|
465
|
-
dependencies: {
|
|
466
|
-
'@test/level3': 'workspace:*',
|
|
467
|
-
chalk: '^5.0.0',
|
|
468
|
-
},
|
|
469
|
-
},
|
|
470
|
-
'packages/level2/dist/index.js': `import { fromLevel3 } from '@test/level3';
|
|
471
|
-
export function fromLevel2() {
|
|
472
|
-
return 'L2->' + fromLevel3();
|
|
473
|
-
}
|
|
474
|
-
`,
|
|
475
|
-
'packages/level3/package.json': {
|
|
476
|
-
name: '@test/level3',
|
|
477
|
-
version: '1.0.0',
|
|
478
|
-
main: 'dist/index.js',
|
|
479
|
-
dependencies: {
|
|
480
|
-
'@test/level4': 'workspace:*',
|
|
481
|
-
zod: '^3.0.0',
|
|
482
|
-
},
|
|
483
|
-
},
|
|
484
|
-
'packages/level3/dist/index.js': `import { fromLevel4 } from '@test/level4';
|
|
485
|
-
export function fromLevel3() {
|
|
486
|
-
return 'L3->' + fromLevel4();
|
|
487
|
-
}
|
|
488
|
-
`,
|
|
489
|
-
'packages/level4/package.json': {
|
|
490
|
-
name: '@test/level4',
|
|
491
|
-
version: '1.0.0',
|
|
492
|
-
main: 'dist/index.js',
|
|
493
|
-
dependencies: {
|
|
494
|
-
uuid: '^9.0.0',
|
|
495
|
-
},
|
|
496
|
-
},
|
|
497
|
-
'packages/level4/dist/index.js': `export function fromLevel4() {
|
|
498
|
-
return 'L4';
|
|
499
|
-
}
|
|
500
|
-
`,
|
|
501
|
-
});
|
|
502
|
-
const { stdout, output } = await runMonocrate(monorepoRoot, 'packages/app');
|
|
503
|
-
expect(output['package.json']).toEqual({
|
|
504
|
-
name: '@test/app',
|
|
505
|
-
version: '1.0.0',
|
|
506
|
-
main: 'dist/index.js',
|
|
507
|
-
dependencies: {
|
|
508
|
-
express: '^4.18.0',
|
|
509
|
-
lodash: '^4.17.21',
|
|
510
|
-
chalk: '^5.0.0',
|
|
511
|
-
zod: '^3.0.0',
|
|
512
|
-
uuid: '^9.0.0',
|
|
513
|
-
},
|
|
514
|
-
});
|
|
515
|
-
expect(stdout.trim()).toBe('L1->L2->L3->L4');
|
|
516
|
-
});
|
|
517
|
-
it('works with pnpm workspaces', async () => {
|
|
518
|
-
const monorepoRoot = folderify({
|
|
519
|
-
'package.json': { name: 'pnpm-monorepo' },
|
|
520
|
-
'pnpm-workspace.yaml': `packages:
|
|
521
|
-
- 'packages/*'
|
|
522
|
-
`,
|
|
523
|
-
'packages/app/package.json': {
|
|
524
|
-
name: '@test/pnpm-app',
|
|
525
|
-
version: '1.0.0',
|
|
526
|
-
main: 'dist/index.js',
|
|
527
|
-
dependencies: {
|
|
528
|
-
'@test/pnpm-lib': 'workspace:*',
|
|
529
|
-
chalk: '^5.0.0',
|
|
530
|
-
},
|
|
531
|
-
},
|
|
532
|
-
'packages/app/dist/index.js': `import { pnpmGreet } from '@test/pnpm-lib';
|
|
533
|
-
console.log(pnpmGreet());
|
|
534
|
-
`,
|
|
535
|
-
'packages/lib/package.json': {
|
|
536
|
-
name: '@test/pnpm-lib',
|
|
537
|
-
version: '1.0.0',
|
|
538
|
-
main: 'dist/index.js',
|
|
539
|
-
dependencies: {
|
|
540
|
-
lodash: '^4.17.21',
|
|
541
|
-
},
|
|
542
|
-
},
|
|
543
|
-
'packages/lib/dist/index.js': `export function pnpmGreet() {
|
|
544
|
-
return 'pnpm works!';
|
|
545
|
-
}
|
|
546
|
-
`,
|
|
547
|
-
});
|
|
548
|
-
const { stdout, output } = await runMonocrate(monorepoRoot, 'packages/app');
|
|
549
|
-
expect(output['package.json']).toEqual({
|
|
550
|
-
name: '@test/pnpm-app',
|
|
551
|
-
version: '1.0.0',
|
|
552
|
-
main: 'dist/index.js',
|
|
553
|
-
dependencies: {
|
|
554
|
-
chalk: '^5.0.0',
|
|
555
|
-
lodash: '^4.17.21',
|
|
556
|
-
},
|
|
557
|
-
});
|
|
558
|
-
expect(stdout.trim()).toBe('pnpm works!');
|
|
559
|
-
});
|
|
560
|
-
it('excludes devDependencies from the output', async () => {
|
|
561
|
-
const monorepoRoot = folderify({
|
|
562
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
563
|
-
'packages/app/package.json': {
|
|
564
|
-
name: '@test/app',
|
|
565
|
-
version: '1.0.0',
|
|
566
|
-
main: 'dist/index.js',
|
|
567
|
-
dependencies: {
|
|
568
|
-
'@test/lib': 'workspace:*',
|
|
569
|
-
chalk: '^5.0.0',
|
|
570
|
-
},
|
|
571
|
-
devDependencies: {
|
|
572
|
-
vitest: '^1.0.0',
|
|
573
|
-
typescript: '^5.0.0',
|
|
574
|
-
},
|
|
575
|
-
},
|
|
576
|
-
'packages/app/dist/index.js': `import { greet } from '@test/lib';
|
|
577
|
-
console.log(greet('World'));
|
|
578
|
-
`,
|
|
579
|
-
'packages/lib/package.json': {
|
|
580
|
-
name: '@test/lib',
|
|
581
|
-
version: '1.0.0',
|
|
582
|
-
main: 'dist/index.js',
|
|
583
|
-
dependencies: {
|
|
584
|
-
lodash: '^4.17.21',
|
|
585
|
-
},
|
|
586
|
-
devDependencies: {
|
|
587
|
-
'@types/lodash': '^4.14.0',
|
|
588
|
-
},
|
|
589
|
-
},
|
|
590
|
-
'packages/lib/dist/index.js': `export function greet(name) {
|
|
591
|
-
return 'Hello, ' + name + '!';
|
|
592
|
-
}
|
|
593
|
-
`,
|
|
594
|
-
});
|
|
595
|
-
const { stdout, output } = await runMonocrate(monorepoRoot, 'packages/app');
|
|
596
|
-
expect(output['package.json']).toEqual({
|
|
597
|
-
name: '@test/app',
|
|
598
|
-
version: '1.0.0',
|
|
599
|
-
main: 'dist/index.js',
|
|
600
|
-
dependencies: {
|
|
601
|
-
chalk: '^5.0.0',
|
|
602
|
-
lodash: '^4.17.21',
|
|
603
|
-
},
|
|
604
|
-
});
|
|
605
|
-
expect(stdout.trim()).toBe('Hello, World!');
|
|
606
|
-
});
|
|
607
|
-
it('preserves line numbers in stack traces', async () => {
|
|
608
|
-
// Line 1: export function throwError() {
|
|
609
|
-
// Line 2: throw new Error('intentional error');
|
|
610
|
-
// Line 3: }
|
|
611
|
-
const libSource = `export function throwError() {
|
|
612
|
-
throw new Error('intentional error');
|
|
613
|
-
}
|
|
614
|
-
`;
|
|
615
|
-
const monorepoRoot = folderify({
|
|
616
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
617
|
-
'packages/app/package.json': {
|
|
618
|
-
name: '@test/app',
|
|
619
|
-
version: '1.0.0',
|
|
620
|
-
main: 'dist/index.js',
|
|
621
|
-
dependencies: {
|
|
622
|
-
'@test/lib': 'workspace:*',
|
|
623
|
-
},
|
|
624
|
-
},
|
|
625
|
-
'packages/app/dist/index.js': `import { throwError } from '@test/lib';
|
|
626
|
-
throwError();
|
|
627
|
-
`,
|
|
628
|
-
'packages/lib/package.json': {
|
|
629
|
-
name: '@test/lib',
|
|
630
|
-
version: '1.0.0',
|
|
631
|
-
main: 'dist/index.js',
|
|
632
|
-
},
|
|
633
|
-
'packages/lib/dist/index.js': libSource,
|
|
634
|
-
});
|
|
635
|
-
const { stderr } = await runMonocrate(monorepoRoot, 'packages/app');
|
|
636
|
-
// Verify the stack trace contains the error message and the line number in the output
|
|
637
|
-
// The throw statement is on line 2 of the lib dist file
|
|
638
|
-
expect(stderr).toContain('intentional error');
|
|
639
|
-
// The error occurs in the deps directory where the in-repo dep is placed
|
|
640
|
-
expect(stderr).toContain('index.js:2');
|
|
641
|
-
});
|
|
642
|
-
it('rewrites imports in both .js and .d.ts files', async () => {
|
|
643
|
-
const monorepoRoot = folderify({
|
|
644
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
645
|
-
'packages/a/package.json': {
|
|
646
|
-
name: '@myorg/a',
|
|
647
|
-
main: 'dist/index.js',
|
|
648
|
-
types: 'dist/index.d.ts',
|
|
649
|
-
dependencies: { '@myorg/b': '*', lodash: '^4.0.0' },
|
|
650
|
-
},
|
|
651
|
-
'packages/a/dist/index.js': `import { foo } from '@myorg/b';
|
|
652
|
-
export const bar = foo;
|
|
653
|
-
`,
|
|
654
|
-
'packages/a/dist/index.d.ts': `import { foo } from '@myorg/b';
|
|
655
|
-
export declare const bar: typeof foo;
|
|
656
|
-
`,
|
|
657
|
-
'packages/b/package.json': {
|
|
658
|
-
name: '@myorg/b',
|
|
659
|
-
main: 'dist/index.js',
|
|
660
|
-
types: 'dist/index.d.ts',
|
|
661
|
-
dependencies: { lodash: '^4.0.0' },
|
|
662
|
-
},
|
|
663
|
-
'packages/b/dist/index.js': `export const foo = 'foo';
|
|
664
|
-
`,
|
|
665
|
-
'packages/b/dist/index.d.ts': `export declare const foo: string;
|
|
666
|
-
`,
|
|
667
|
-
});
|
|
668
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
669
|
-
const result = await monocrate({
|
|
670
|
-
sourceDir: path.join(monorepoRoot, 'packages/a'),
|
|
671
|
-
outputDir,
|
|
672
|
-
monorepoRoot,
|
|
673
|
-
});
|
|
674
|
-
expect(result.success).toBe(true);
|
|
675
|
-
const output = unfolderify(outputDir);
|
|
676
|
-
console.error(JSON.stringify(output, null, 2));
|
|
677
|
-
// Verify .js file has rewritten import
|
|
678
|
-
expect(output['dist/index.js']).toContain('../deps/packages/b/dist/index.js');
|
|
679
|
-
expect(output['dist/index.js']).not.toContain("'@myorg/b'");
|
|
680
|
-
// Verify .d.ts file has rewritten import
|
|
681
|
-
expect(output['dist/index.d.ts']).toContain('../deps/packages/b/dist/index.js');
|
|
682
|
-
expect(output['dist/index.d.ts']).not.toContain("'@myorg/b'");
|
|
683
|
-
});
|
|
684
|
-
it('rewrites export declarations', async () => {
|
|
685
|
-
const monorepoRoot = folderify({
|
|
686
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
687
|
-
'packages/a/package.json': {
|
|
688
|
-
name: '@myorg/a',
|
|
689
|
-
main: 'dist/index.js',
|
|
690
|
-
dependencies: { '@myorg/b': '*' },
|
|
691
|
-
},
|
|
692
|
-
'packages/a/dist/index.js': `export { foo } from '@myorg/b';
|
|
693
|
-
export * from '@myorg/b';
|
|
694
|
-
`,
|
|
695
|
-
'packages/b/package.json': {
|
|
696
|
-
name: '@myorg/b',
|
|
697
|
-
main: 'dist/index.js',
|
|
698
|
-
},
|
|
699
|
-
'packages/b/dist/index.js': `export const foo = 'foo';
|
|
700
|
-
export const bar = 'bar';
|
|
701
|
-
`,
|
|
702
|
-
});
|
|
703
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
704
|
-
const result = await monocrate({
|
|
705
|
-
sourceDir: path.join(monorepoRoot, 'packages/a'),
|
|
706
|
-
outputDir,
|
|
707
|
-
monorepoRoot,
|
|
708
|
-
});
|
|
709
|
-
expect(result.success).toBe(true);
|
|
710
|
-
const output = unfolderify(outputDir);
|
|
711
|
-
// Verify export declarations have rewritten module specifiers
|
|
712
|
-
const indexJs = output['dist/index.js'];
|
|
713
|
-
expect(indexJs).toContain('../deps/packages/b/dist/index.js');
|
|
714
|
-
expect(indexJs).not.toContain("'@myorg/b'");
|
|
715
|
-
});
|
|
716
|
-
it('leaves third-party imports unchanged', async () => {
|
|
717
|
-
const monorepoRoot = folderify({
|
|
718
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
719
|
-
'packages/a/package.json': {
|
|
720
|
-
name: '@myorg/a',
|
|
721
|
-
main: 'dist/index.js',
|
|
722
|
-
dependencies: { '@myorg/b': '*', lodash: '^4.0.0' },
|
|
723
|
-
},
|
|
724
|
-
'packages/a/dist/index.js': `import { foo } from '@myorg/b';
|
|
725
|
-
import _ from 'lodash';
|
|
726
|
-
import * as path from 'node:path';
|
|
727
|
-
export const bar = foo;
|
|
728
|
-
`,
|
|
729
|
-
'packages/b/package.json': {
|
|
730
|
-
name: '@myorg/b',
|
|
731
|
-
main: 'dist/index.js',
|
|
732
|
-
},
|
|
733
|
-
'packages/b/dist/index.js': `export const foo = 'foo';
|
|
734
|
-
`,
|
|
735
|
-
});
|
|
736
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
737
|
-
const result = await monocrate({
|
|
738
|
-
sourceDir: path.join(monorepoRoot, 'packages/a'),
|
|
739
|
-
outputDir,
|
|
740
|
-
monorepoRoot,
|
|
741
|
-
});
|
|
742
|
-
expect(result.success).toBe(true);
|
|
743
|
-
const output = unfolderify(outputDir);
|
|
744
|
-
const indexJs = output['dist/index.js'];
|
|
745
|
-
// Third-party imports should be unchanged
|
|
746
|
-
expect(indexJs).toContain("from 'lodash'");
|
|
747
|
-
expect(indexJs).toContain("from 'node:path'");
|
|
748
|
-
});
|
|
749
|
-
it('rewrites imports in nested files at different depths', async () => {
|
|
750
|
-
const monorepoRoot = folderify({
|
|
751
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
752
|
-
'packages/a/package.json': {
|
|
753
|
-
name: '@myorg/a',
|
|
754
|
-
main: 'dist/index.js',
|
|
755
|
-
dependencies: { '@myorg/b': '*' },
|
|
756
|
-
},
|
|
757
|
-
'packages/a/dist/index.js': `import { foo } from '@myorg/b';
|
|
758
|
-
export { helper } from './utils/helper.js';
|
|
759
|
-
export const bar = foo;
|
|
760
|
-
`,
|
|
761
|
-
'packages/a/dist/utils/helper.js': `import { foo } from '@myorg/b';
|
|
762
|
-
export const helper = foo + '-helper';
|
|
763
|
-
`,
|
|
764
|
-
'packages/b/package.json': {
|
|
765
|
-
name: '@myorg/b',
|
|
766
|
-
main: 'dist/index.js',
|
|
767
|
-
},
|
|
768
|
-
'packages/b/dist/index.js': `export const foo = 'foo';
|
|
769
|
-
`,
|
|
770
|
-
});
|
|
771
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
772
|
-
const result = await monocrate({
|
|
773
|
-
sourceDir: path.join(monorepoRoot, 'packages/a'),
|
|
774
|
-
outputDir,
|
|
775
|
-
monorepoRoot,
|
|
776
|
-
});
|
|
777
|
-
expect(result.success).toBe(true);
|
|
778
|
-
const output = unfolderify(outputDir);
|
|
779
|
-
// Root level file should have '../deps/...'
|
|
780
|
-
expect(output['dist/index.js']).toContain('../deps/packages/b/dist/index.js');
|
|
781
|
-
// Nested file should have '../../deps/...'
|
|
782
|
-
expect(output['dist/utils/helper.js']).toContain('../../deps/packages/b/dist/index.js');
|
|
783
|
-
});
|
|
784
|
-
it('handles packages in different monorepo directories', async () => {
|
|
785
|
-
const monorepoRoot = folderify({
|
|
786
|
-
'package.json': { name: 'my-monorepo', workspaces: ['packages/*', 'libs/*'] },
|
|
787
|
-
'packages/a/package.json': {
|
|
788
|
-
name: '@myorg/a',
|
|
789
|
-
main: 'dist/index.js',
|
|
790
|
-
dependencies: { '@myorg/b': '*', '@myorg/utils': '*' },
|
|
791
|
-
},
|
|
792
|
-
'packages/a/dist/index.js': `import { foo } from '@myorg/b';
|
|
793
|
-
import { util } from '@myorg/utils';
|
|
794
|
-
export const bar = foo + util;
|
|
795
|
-
`,
|
|
796
|
-
'packages/b/package.json': {
|
|
797
|
-
name: '@myorg/b',
|
|
798
|
-
main: 'dist/index.js',
|
|
799
|
-
},
|
|
800
|
-
'packages/b/dist/index.js': `export const foo = 'foo';
|
|
801
|
-
`,
|
|
802
|
-
'libs/utils/package.json': {
|
|
803
|
-
name: '@myorg/utils',
|
|
804
|
-
main: 'dist/index.js',
|
|
805
|
-
},
|
|
806
|
-
'libs/utils/dist/index.js': `export const util = 'util';
|
|
807
|
-
`,
|
|
808
|
-
});
|
|
809
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
810
|
-
const result = await monocrate({
|
|
811
|
-
sourceDir: path.join(monorepoRoot, 'packages/a'),
|
|
812
|
-
outputDir,
|
|
813
|
-
monorepoRoot,
|
|
814
|
-
});
|
|
815
|
-
expect(result.success).toBe(true);
|
|
816
|
-
const output = unfolderify(outputDir);
|
|
817
|
-
const indexJs = output['dist/index.js'];
|
|
818
|
-
// Both imports should be rewritten with correct paths
|
|
819
|
-
expect(indexJs).toContain('../deps/packages/b/dist/index.js');
|
|
820
|
-
expect(indexJs).toContain('../deps/libs/utils/dist/index.js');
|
|
821
|
-
// Verify the deps directory structure mirrors the monorepo
|
|
822
|
-
expect(output).toHaveProperty('deps/packages/b/dist/index.js');
|
|
823
|
-
expect(output).toHaveProperty('deps/libs/utils/dist/index.js');
|
|
824
|
-
});
|
|
825
|
-
it('verifies output directory structure matches spec', async () => {
|
|
826
|
-
const monorepoRoot = folderify({
|
|
827
|
-
'package.json': { name: 'my-monorepo', workspaces: ['packages/*', 'libs/*'] },
|
|
828
|
-
'packages/a/package.json': {
|
|
829
|
-
name: '@myorg/a',
|
|
830
|
-
main: 'dist/index.js',
|
|
831
|
-
types: 'dist/index.d.ts',
|
|
832
|
-
dependencies: { '@myorg/b': '*' },
|
|
833
|
-
},
|
|
834
|
-
'packages/a/dist/index.js': `import { foo } from '@myorg/b';
|
|
835
|
-
export const bar = foo;
|
|
836
|
-
`,
|
|
837
|
-
'packages/a/dist/index.d.ts': `import { foo } from '@myorg/b';
|
|
838
|
-
export declare const bar: typeof foo;
|
|
839
|
-
`,
|
|
840
|
-
'packages/a/dist/utils/helper.js': `export const x = 1;
|
|
841
|
-
`,
|
|
842
|
-
'packages/a/dist/utils/helper.d.ts': `export declare const x: number;
|
|
843
|
-
`,
|
|
844
|
-
'packages/b/package.json': {
|
|
845
|
-
name: '@myorg/b',
|
|
846
|
-
main: 'dist/index.js',
|
|
847
|
-
types: 'dist/index.d.ts',
|
|
848
|
-
},
|
|
849
|
-
'packages/b/dist/index.js': `export const foo = 'foo';
|
|
850
|
-
`,
|
|
851
|
-
'packages/b/dist/index.d.ts': `export declare const foo: string;
|
|
852
|
-
`,
|
|
853
|
-
});
|
|
854
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
855
|
-
const result = await monocrate({
|
|
856
|
-
sourceDir: path.join(monorepoRoot, 'packages/a'),
|
|
857
|
-
outputDir,
|
|
858
|
-
monorepoRoot,
|
|
859
|
-
});
|
|
860
|
-
expect(result.success).toBe(true);
|
|
861
|
-
const output = unfolderify(outputDir);
|
|
862
|
-
// Verify root structure
|
|
863
|
-
expect(output).toHaveProperty('package.json');
|
|
864
|
-
expect(output).toHaveProperty('dist/index.js');
|
|
865
|
-
expect(output).toHaveProperty('dist/index.d.ts');
|
|
866
|
-
expect(output).toHaveProperty('dist/utils/helper.js');
|
|
867
|
-
expect(output).toHaveProperty('dist/utils/helper.d.ts');
|
|
868
|
-
// Verify deps structure
|
|
869
|
-
expect(output).toHaveProperty('deps/packages/b/dist/index.js');
|
|
870
|
-
expect(output).toHaveProperty('deps/packages/b/dist/index.d.ts');
|
|
871
|
-
});
|
|
872
|
-
it('handles source package importing itself by name', async () => {
|
|
873
|
-
const monorepoRoot = folderify({
|
|
874
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
875
|
-
'packages/a/package.json': {
|
|
876
|
-
name: '@myorg/a',
|
|
877
|
-
main: 'dist/index.js',
|
|
878
|
-
dependencies: {},
|
|
879
|
-
},
|
|
880
|
-
'packages/a/dist/index.js': `import { helper } from '@myorg/a/utils/helper';
|
|
881
|
-
export const result = helper;
|
|
882
|
-
`,
|
|
883
|
-
'packages/a/dist/utils/helper.js': `export const helper = 'helper';
|
|
884
|
-
`,
|
|
885
|
-
});
|
|
886
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
887
|
-
const result = await monocrate({
|
|
888
|
-
sourceDir: path.join(monorepoRoot, 'packages/a'),
|
|
889
|
-
outputDir,
|
|
890
|
-
monorepoRoot,
|
|
891
|
-
});
|
|
892
|
-
expect(result.success).toBe(true);
|
|
893
|
-
const output = unfolderify(outputDir);
|
|
894
|
-
const indexJs = output['dist/index.js'];
|
|
895
|
-
// Self-import should be rewritten to relative path
|
|
896
|
-
expect(indexJs).toContain('./utils/helper');
|
|
897
|
-
expect(indexJs).not.toContain("'@myorg/a/utils/helper'");
|
|
898
|
-
});
|
|
899
|
-
it('handles subpath imports like @myorg/b/submodule', async () => {
|
|
900
|
-
const monorepoRoot = folderify({
|
|
901
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
902
|
-
'packages/a/package.json': {
|
|
903
|
-
name: '@myorg/a',
|
|
904
|
-
main: 'dist/index.js',
|
|
905
|
-
dependencies: { '@myorg/b': '*' },
|
|
906
|
-
},
|
|
907
|
-
'packages/a/dist/index.js': `import { helper } from '@myorg/b/utils/helper';
|
|
908
|
-
export const result = helper;
|
|
909
|
-
`,
|
|
910
|
-
'packages/b/package.json': {
|
|
911
|
-
name: '@myorg/b',
|
|
912
|
-
main: 'dist/index.js',
|
|
913
|
-
},
|
|
914
|
-
'packages/b/dist/index.js': `export const foo = 'foo';
|
|
915
|
-
`,
|
|
916
|
-
'packages/b/dist/utils/helper.js': `export const helper = 'helper';
|
|
917
|
-
`,
|
|
918
|
-
});
|
|
919
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
920
|
-
const result = await monocrate({
|
|
921
|
-
sourceDir: path.join(monorepoRoot, 'packages/a'),
|
|
922
|
-
outputDir,
|
|
923
|
-
monorepoRoot,
|
|
924
|
-
});
|
|
925
|
-
expect(result.success).toBe(true);
|
|
926
|
-
const output = unfolderify(outputDir);
|
|
927
|
-
const indexJs = output['dist/index.js'];
|
|
928
|
-
// Subpath import should be rewritten with preserved subpath
|
|
929
|
-
expect(indexJs).toContain('../deps/packages/b/dist/utils/helper');
|
|
930
|
-
expect(indexJs).not.toContain("'@myorg/b/utils/helper'");
|
|
931
|
-
});
|
|
932
|
-
it('handles dynamic imports', async () => {
|
|
933
|
-
const monorepoRoot = folderify({
|
|
934
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
935
|
-
'packages/a/package.json': {
|
|
936
|
-
name: '@myorg/a',
|
|
937
|
-
main: 'dist/index.js',
|
|
938
|
-
dependencies: { '@myorg/b': '*' },
|
|
939
|
-
},
|
|
940
|
-
'packages/a/dist/index.js': `const b = await import('@myorg/b');
|
|
941
|
-
export const foo = b.foo;
|
|
942
|
-
`,
|
|
943
|
-
'packages/b/package.json': {
|
|
944
|
-
name: '@myorg/b',
|
|
945
|
-
main: 'dist/index.js',
|
|
946
|
-
},
|
|
947
|
-
'packages/b/dist/index.js': `export const foo = 'foo';
|
|
948
|
-
`,
|
|
949
|
-
});
|
|
950
|
-
const outputDir = createTempDir('monocrate-output-');
|
|
951
|
-
const result = await monocrate({
|
|
952
|
-
sourceDir: path.join(monorepoRoot, 'packages/a'),
|
|
953
|
-
outputDir,
|
|
954
|
-
monorepoRoot,
|
|
955
|
-
});
|
|
956
|
-
expect(result.success).toBe(true);
|
|
957
|
-
const output = unfolderify(outputDir);
|
|
958
|
-
const indexJs = output['dist/index.js'];
|
|
959
|
-
// Dynamic import should be rewritten
|
|
960
|
-
expect(indexJs).toContain('../deps/packages/b/dist/index.js');
|
|
961
|
-
expect(indexJs).not.toContain("import('@myorg/b')");
|
|
962
|
-
});
|
|
963
|
-
it('handles cross-dependency imports between in-repo deps', async () => {
|
|
964
|
-
const monorepoRoot = folderify({
|
|
965
|
-
'package.json': { workspaces: ['packages/*'] },
|
|
966
|
-
'packages/app/package.json': {
|
|
967
|
-
name: '@myorg/app',
|
|
968
|
-
main: 'dist/index.js',
|
|
969
|
-
dependencies: { '@myorg/lib-a': '*' },
|
|
970
|
-
},
|
|
971
|
-
'packages/app/dist/index.js': `import { a } from '@myorg/lib-a';
|
|
972
|
-
console.log(a);
|
|
973
|
-
`,
|
|
974
|
-
'packages/lib-a/package.json': {
|
|
975
|
-
name: '@myorg/lib-a',
|
|
976
|
-
main: 'dist/index.js',
|
|
977
|
-
dependencies: { '@myorg/lib-b': '*' },
|
|
978
|
-
},
|
|
979
|
-
'packages/lib-a/dist/index.js': `import { b } from '@myorg/lib-b';
|
|
980
|
-
export const a = 'a-' + b;
|
|
981
|
-
`,
|
|
982
|
-
'packages/lib-b/package.json': {
|
|
983
|
-
name: '@myorg/lib-b',
|
|
984
|
-
main: 'dist/index.js',
|
|
985
|
-
},
|
|
986
|
-
'packages/lib-b/dist/index.js': `export const b = 'b';
|
|
987
|
-
`,
|
|
988
|
-
});
|
|
989
|
-
const { stdout, output } = await runMonocrate(monorepoRoot, 'packages/app');
|
|
990
|
-
// Verify the deps files also have their imports rewritten
|
|
991
|
-
const libAIndex = output['deps/packages/lib-a/dist/index.js'];
|
|
992
|
-
expect(libAIndex).toContain('../lib-b/dist/index.js');
|
|
993
|
-
expect(libAIndex).not.toContain("'@myorg/lib-b'");
|
|
994
|
-
// Verify execution works
|
|
995
|
-
expect(stdout.trim()).toBe('a-b');
|
|
996
|
-
});
|
|
997
|
-
});
|
|
998
|
-
//# sourceMappingURL=monocrate.test.js.map
|