plgg-bundle 0.0.5 → 0.0.6
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plgg-bundle",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "In-house minimal library bundler for the plgg monorepo (ESM+CJS dual output, per-file .d.ts tree), zero new dependencies — reuses the project's own TypeScript, no native binding.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -13,6 +13,10 @@ import {
|
|
|
13
13
|
import { tmpdir } from "node:os";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import { collectModules } from "plgg-bundle/domain/usecase/collectModules";
|
|
16
|
+
import {
|
|
17
|
+
emitCjsBundle,
|
|
18
|
+
emitEsmBundle,
|
|
19
|
+
} from "plgg-bundle/domain/usecase/emitBundle";
|
|
16
20
|
|
|
17
21
|
test("collectModules records external specifiers without walking them", () => {
|
|
18
22
|
const root = mkdtempSync(
|
|
@@ -20,7 +24,9 @@ test("collectModules records external specifiers without walking them", () => {
|
|
|
20
24
|
);
|
|
21
25
|
try {
|
|
22
26
|
const entry = join(root, "src", "main.ts");
|
|
23
|
-
mkdirSync(join(root, "src"), {
|
|
27
|
+
mkdirSync(join(root, "src"), {
|
|
28
|
+
recursive: true,
|
|
29
|
+
});
|
|
24
30
|
writeFileSync(
|
|
25
31
|
entry,
|
|
26
32
|
'import { readFileSync } from "node:fs";\nexport const read = readFileSync;\n',
|
|
@@ -40,21 +46,26 @@ test("collectModules records external specifiers without walking them", () => {
|
|
|
40
46
|
),
|
|
41
47
|
]);
|
|
42
48
|
} finally {
|
|
43
|
-
rmSync(root, {
|
|
49
|
+
rmSync(root, {
|
|
50
|
+
recursive: true,
|
|
51
|
+
force: true,
|
|
52
|
+
});
|
|
44
53
|
}
|
|
45
54
|
});
|
|
46
55
|
|
|
47
56
|
test("collectModules throws on an unresolvable non-external specifier", () => {
|
|
48
57
|
const root = mkdtempSync(
|
|
49
|
-
join(
|
|
58
|
+
join(
|
|
59
|
+
tmpdir(),
|
|
60
|
+
"plgg-bundle-collect-missing-",
|
|
61
|
+
),
|
|
50
62
|
);
|
|
51
63
|
try {
|
|
52
64
|
const entry = join(root, "src", "main.ts");
|
|
53
|
-
mkdirSync(join(root, "src"), {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
);
|
|
65
|
+
mkdirSync(join(root, "src"), {
|
|
66
|
+
recursive: true,
|
|
67
|
+
});
|
|
68
|
+
writeFileSync(entry, 'import "missing";\n');
|
|
58
69
|
return check(
|
|
59
70
|
rejects(() =>
|
|
60
71
|
collectModules({
|
|
@@ -68,7 +79,10 @@ test("collectModules throws on an unresolvable non-external specifier", () => {
|
|
|
68
79
|
toBe(true),
|
|
69
80
|
);
|
|
70
81
|
} finally {
|
|
71
|
-
rmSync(root, {
|
|
82
|
+
rmSync(root, {
|
|
83
|
+
recursive: true,
|
|
84
|
+
force: true,
|
|
85
|
+
});
|
|
72
86
|
}
|
|
73
87
|
});
|
|
74
88
|
|
|
@@ -92,13 +106,21 @@ test("collectModules inlines an installed prebundled dist entry without resolvin
|
|
|
92
106
|
"dist",
|
|
93
107
|
"index.es.js",
|
|
94
108
|
);
|
|
95
|
-
mkdirSync(join(root, "src"), {
|
|
96
|
-
mkdirSync(join(root, "node_modules", "dep", "dist"), {
|
|
97
|
-
recursive: true,
|
|
98
|
-
});
|
|
99
|
-
mkdirSync(join(root, "node_modules", "plgg", "dist"), {
|
|
109
|
+
mkdirSync(join(root, "src"), {
|
|
100
110
|
recursive: true,
|
|
101
111
|
});
|
|
112
|
+
mkdirSync(
|
|
113
|
+
join(root, "node_modules", "dep", "dist"),
|
|
114
|
+
{
|
|
115
|
+
recursive: true,
|
|
116
|
+
},
|
|
117
|
+
);
|
|
118
|
+
mkdirSync(
|
|
119
|
+
join(root, "node_modules", "plgg", "dist"),
|
|
120
|
+
{
|
|
121
|
+
recursive: true,
|
|
122
|
+
},
|
|
123
|
+
);
|
|
102
124
|
writeFileSync(
|
|
103
125
|
entry,
|
|
104
126
|
'import dep from "dep";\nexport const value = dep.value;\n',
|
|
@@ -159,7 +181,10 @@ test("collectModules inlines an installed prebundled dist entry without resolvin
|
|
|
159
181
|
),
|
|
160
182
|
]);
|
|
161
183
|
} finally {
|
|
162
|
-
rmSync(root, {
|
|
184
|
+
rmSync(root, {
|
|
185
|
+
recursive: true,
|
|
186
|
+
force: true,
|
|
187
|
+
});
|
|
163
188
|
}
|
|
164
189
|
});
|
|
165
190
|
|
|
@@ -190,11 +215,17 @@ test("collectModules resolves node_modules source files without dist-registry fi
|
|
|
190
215
|
aliasPrefix: "app",
|
|
191
216
|
aliasSrcRoot: join(root, "src"),
|
|
192
217
|
external: /^node:/,
|
|
193
|
-
resolve: importFixtureResolver(
|
|
218
|
+
resolve: importFixtureResolver(
|
|
219
|
+
dep,
|
|
220
|
+
internal,
|
|
221
|
+
),
|
|
194
222
|
});
|
|
195
223
|
return check(graph.modules.length, toBe(3));
|
|
196
224
|
} finally {
|
|
197
|
-
rmSync(root, {
|
|
225
|
+
rmSync(root, {
|
|
226
|
+
recursive: true,
|
|
227
|
+
force: true,
|
|
228
|
+
});
|
|
198
229
|
}
|
|
199
230
|
});
|
|
200
231
|
|
|
@@ -225,11 +256,134 @@ test("collectModules resolves non-js dist source files without dist-registry fil
|
|
|
225
256
|
aliasPrefix: "app",
|
|
226
257
|
aliasSrcRoot: join(root, "src"),
|
|
227
258
|
external: /^node:/,
|
|
228
|
-
resolve: importFixtureResolver(
|
|
259
|
+
resolve: importFixtureResolver(
|
|
260
|
+
dep,
|
|
261
|
+
internal,
|
|
262
|
+
),
|
|
229
263
|
});
|
|
230
264
|
return check(graph.modules.length, toBe(3));
|
|
231
265
|
} finally {
|
|
232
|
-
rmSync(root, {
|
|
266
|
+
rmSync(root, {
|
|
267
|
+
recursive: true,
|
|
268
|
+
force: true,
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test("an app bundling two dists with identical inner module paths keeps each dist's externals resolvable", () => {
|
|
274
|
+
// Regression for the plggmatic blank-page defect:
|
|
275
|
+
// pkg-a and pkg-b are plgg-bundle ESM dists whose
|
|
276
|
+
// inner registries both key "src/index.ts", and
|
|
277
|
+
// pkg-b requires pkg-a through its inner
|
|
278
|
+
// __externals table. The outer rewrite must keep
|
|
279
|
+
// that table's key in step with the rewritten
|
|
280
|
+
// require, or pkg-b's inner lookup falls into the
|
|
281
|
+
// async import fallback and yields a Promise where
|
|
282
|
+
// a namespace is expected.
|
|
283
|
+
const root = mkdtempSync(
|
|
284
|
+
join(tmpdir(), "plgg-bundle-collect-nested-"),
|
|
285
|
+
);
|
|
286
|
+
try {
|
|
287
|
+
const entry = join(root, "src", "main.ts");
|
|
288
|
+
const pkgA = join(
|
|
289
|
+
root,
|
|
290
|
+
"node_modules",
|
|
291
|
+
"pkg-a",
|
|
292
|
+
"dist",
|
|
293
|
+
"index.es.js",
|
|
294
|
+
);
|
|
295
|
+
const pkgB = join(
|
|
296
|
+
root,
|
|
297
|
+
"node_modules",
|
|
298
|
+
"pkg-b",
|
|
299
|
+
"dist",
|
|
300
|
+
"index.es.js",
|
|
301
|
+
);
|
|
302
|
+
mkdirSync(join(root, "src"), {
|
|
303
|
+
recursive: true,
|
|
304
|
+
});
|
|
305
|
+
mkdirSync(join(pkgA, ".."), {
|
|
306
|
+
recursive: true,
|
|
307
|
+
});
|
|
308
|
+
mkdirSync(join(pkgB, ".."), {
|
|
309
|
+
recursive: true,
|
|
310
|
+
});
|
|
311
|
+
writeFileSync(
|
|
312
|
+
entry,
|
|
313
|
+
[
|
|
314
|
+
'import { box } from "pkg-a";',
|
|
315
|
+
'import { useBox } from "pkg-b";',
|
|
316
|
+
"export const direct = box(1);",
|
|
317
|
+
"export const viaB = useBox();",
|
|
318
|
+
].join("\n"),
|
|
319
|
+
);
|
|
320
|
+
// Both dists come from the real emitter, so the
|
|
321
|
+
// fixture cannot drift from the emitted shape.
|
|
322
|
+
writeFileSync(
|
|
323
|
+
pkgA,
|
|
324
|
+
emitEsmBundle(
|
|
325
|
+
{
|
|
326
|
+
entryId: "src/index.ts",
|
|
327
|
+
modules: [
|
|
328
|
+
{
|
|
329
|
+
id: "src/index.ts",
|
|
330
|
+
code: "exports.box = (v) => v * 2;",
|
|
331
|
+
externals: [],
|
|
332
|
+
},
|
|
333
|
+
],
|
|
334
|
+
},
|
|
335
|
+
["box"],
|
|
336
|
+
),
|
|
337
|
+
);
|
|
338
|
+
writeFileSync(
|
|
339
|
+
pkgB,
|
|
340
|
+
emitEsmBundle(
|
|
341
|
+
{
|
|
342
|
+
entryId: "src/index.ts",
|
|
343
|
+
modules: [
|
|
344
|
+
{
|
|
345
|
+
id: "src/index.ts",
|
|
346
|
+
code: 'exports.useBox = () => require("pkg-a").box(21);',
|
|
347
|
+
externals: ["pkg-a"],
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
},
|
|
351
|
+
["useBox"],
|
|
352
|
+
),
|
|
353
|
+
);
|
|
354
|
+
const graph = collectModules({
|
|
355
|
+
entryFile: entry,
|
|
356
|
+
root,
|
|
357
|
+
aliasPrefix: "app",
|
|
358
|
+
aliasSrcRoot: join(root, "src"),
|
|
359
|
+
external: /^node:/,
|
|
360
|
+
resolve: (specifier, _fromFile) =>
|
|
361
|
+
specifier === "pkg-a"
|
|
362
|
+
? pkgA
|
|
363
|
+
: specifier === "pkg-b"
|
|
364
|
+
? pkgB
|
|
365
|
+
: undefined,
|
|
366
|
+
});
|
|
367
|
+
const mod: {
|
|
368
|
+
exports: Record<string, unknown>;
|
|
369
|
+
} = {
|
|
370
|
+
exports: {},
|
|
371
|
+
};
|
|
372
|
+
new Function(
|
|
373
|
+
"module",
|
|
374
|
+
"exports",
|
|
375
|
+
"require",
|
|
376
|
+
emitCjsBundle(graph),
|
|
377
|
+
)(mod, mod.exports, () => ({}));
|
|
378
|
+
return all([
|
|
379
|
+
check(mod.exports.direct, toBe(2)),
|
|
380
|
+
check(mod.exports.viaB, toBe(42)),
|
|
381
|
+
]);
|
|
382
|
+
} finally {
|
|
383
|
+
rmSync(root, {
|
|
384
|
+
recursive: true,
|
|
385
|
+
force: true,
|
|
386
|
+
});
|
|
233
387
|
}
|
|
234
388
|
});
|
|
235
389
|
|
|
@@ -238,9 +392,13 @@ const writeImportFixture = (
|
|
|
238
392
|
dep: string,
|
|
239
393
|
internal: string,
|
|
240
394
|
): void => {
|
|
241
|
-
mkdirSync(join(entry, ".."), {
|
|
395
|
+
mkdirSync(join(entry, ".."), {
|
|
396
|
+
recursive: true,
|
|
397
|
+
});
|
|
242
398
|
mkdirSync(join(dep, ".."), { recursive: true });
|
|
243
|
-
mkdirSync(join(internal, ".."), {
|
|
399
|
+
mkdirSync(join(internal, ".."), {
|
|
400
|
+
recursive: true,
|
|
401
|
+
});
|
|
244
402
|
writeFileSync(
|
|
245
403
|
entry,
|
|
246
404
|
'import { value } from "dep";\nexport const out = value;\n',
|
|
@@ -135,7 +135,10 @@ const linkModule = (
|
|
|
135
135
|
cjs: string,
|
|
136
136
|
acc: Map<string, Module>,
|
|
137
137
|
): ReadonlyArray<string> => {
|
|
138
|
-
const specifiers = inlineRequireSpecifiers(
|
|
138
|
+
const specifiers = inlineRequireSpecifiers(
|
|
139
|
+
file,
|
|
140
|
+
cjs,
|
|
141
|
+
);
|
|
139
142
|
const externals: string[] = [];
|
|
140
143
|
const deps: string[] = [];
|
|
141
144
|
let rewritten = cjs;
|
|
@@ -156,6 +159,13 @@ const linkModule = (
|
|
|
156
159
|
spec,
|
|
157
160
|
idOf(ctx.root, resolved),
|
|
158
161
|
);
|
|
162
|
+
if (isInstalledDist(file)) {
|
|
163
|
+
rewritten = replaceExternalKey(
|
|
164
|
+
rewritten,
|
|
165
|
+
spec,
|
|
166
|
+
idOf(ctx.root, resolved),
|
|
167
|
+
);
|
|
168
|
+
}
|
|
159
169
|
}
|
|
160
170
|
acc.set(id, {
|
|
161
171
|
id,
|
|
@@ -185,14 +195,18 @@ const inlineRequireSpecifiers = (
|
|
|
185
195
|
return specifiers;
|
|
186
196
|
}
|
|
187
197
|
const internal = bundledModuleIds(cjs);
|
|
188
|
-
return specifiers.filter(
|
|
198
|
+
return specifiers.filter(
|
|
199
|
+
(spec) => !internal.has(spec),
|
|
200
|
+
);
|
|
189
201
|
};
|
|
190
202
|
|
|
191
203
|
/**
|
|
192
204
|
* Whether a file is a registry-installed built JS entry.
|
|
193
205
|
* Source packages under the monorepo are never matched.
|
|
194
206
|
*/
|
|
195
|
-
const isInstalledDist = (
|
|
207
|
+
const isInstalledDist = (
|
|
208
|
+
file: string,
|
|
209
|
+
): boolean => {
|
|
196
210
|
const normalized = file.split("\\").join("/");
|
|
197
211
|
return (
|
|
198
212
|
normalized.includes("/node_modules/") &&
|
|
@@ -262,6 +276,29 @@ const requireSpecifiers = (
|
|
|
262
276
|
m[1] === undefined ? [] : [m[1]],
|
|
263
277
|
);
|
|
264
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Rewrite an inlined dist's inner `__externals` table
|
|
281
|
+
* key from the original specifier to the outer module
|
|
282
|
+
* id. A plgg-bundle ESM dist resolves an external
|
|
283
|
+
* required inside its inner module bodies through this
|
|
284
|
+
* table; {@link replaceRequire} rewrites those bodies'
|
|
285
|
+
* `require("<spec>")` calls to the outer id, so the key
|
|
286
|
+
* must follow or the inner lookup misses and falls into
|
|
287
|
+
* the transpiled dynamic-import fallback — a Promise
|
|
288
|
+
* where the consumer expects a namespace ("plgg_1.box
|
|
289
|
+
* is not a function"). Matches the exact
|
|
290
|
+
* `"<spec>": __extN` shape the TS printer emits for the
|
|
291
|
+
* table, so ordinary code never collides with it.
|
|
292
|
+
*/
|
|
293
|
+
const replaceExternalKey = (
|
|
294
|
+
cjs: string,
|
|
295
|
+
spec: string,
|
|
296
|
+
id: string,
|
|
297
|
+
): string =>
|
|
298
|
+
cjs
|
|
299
|
+
.split(`${JSON.stringify(spec)}: __ext`)
|
|
300
|
+
.join(`${JSON.stringify(id)}: __ext`);
|
|
301
|
+
|
|
265
302
|
/**
|
|
266
303
|
* Rewrite every `require("spec")` occurrence to
|
|
267
304
|
* `require("id")`. Operates on the exact specifier
|
|
@@ -126,12 +126,12 @@ test("discoverWorkspace finds installed deps of a sibling source package", () =>
|
|
|
126
126
|
const local = join(root, "packages", "local");
|
|
127
127
|
writePackage(local, "local", true);
|
|
128
128
|
writePackage(
|
|
129
|
-
join(local, "node_modules", "plgg-
|
|
130
|
-
"plgg-
|
|
129
|
+
join(local, "node_modules", "plgg-cms"),
|
|
130
|
+
"plgg-cms",
|
|
131
131
|
false,
|
|
132
132
|
);
|
|
133
133
|
const found = discoverWorkspace(app).find(
|
|
134
|
-
(p) => p.name === "plgg-
|
|
134
|
+
(p) => p.name === "plgg-cms",
|
|
135
135
|
);
|
|
136
136
|
return check(found?.kind, toBe("dist"));
|
|
137
137
|
} finally {
|