@vesk/adapter 0.2.91 → 0.2.93
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/client-bundle.d.ts +4 -0
- package/dist/client-bundle.d.ts.map +1 -1
- package/dist/client-bundle.js +222 -97
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +29 -2
- package/dist/esbuild-fallback.d.ts.map +1 -1
- package/dist/esbuild-fallback.js +9 -6
- package/dist/platform-handler.d.ts.map +1 -1
- package/dist/platform-handler.js +43 -7
- package/package.json +4 -4
package/dist/client-bundle.d.ts
CHANGED
|
@@ -132,6 +132,10 @@ export declare function buildRuntimeCode(runtimeDir: string): string;
|
|
|
132
132
|
/**
|
|
133
133
|
* Names the client runtime actually exports, so the tree-shaken bundle only
|
|
134
134
|
* emits the modules reachable from the used set.
|
|
135
|
+
*
|
|
136
|
+
* Parses index-client.js with the AST parser instead of regex so that direct
|
|
137
|
+
* declarations (export function locals() {}, export const x = 1, export class
|
|
138
|
+
* Foo {}) are captured alongside re-exports (export { X } from '...').
|
|
135
139
|
*/
|
|
136
140
|
export declare function runtimeExportNames(runtimeDir: string): Set<string>;
|
|
137
141
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-bundle.d.ts","sourceRoot":"","sources":["../src/client-bundle.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,kBAAkB,EAAmF,MAAM,yBAAyB,CAAC;AAuEnL;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA4BhE;AAED;;;;;GAKG;AACH,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC7B,EAAE,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvB,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,IAAI,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE;gBAAE,IAAI,CAAC,EAAE,MAAM,CAAC;gBAAC,IAAI,CAAC,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;IACtH,WAAW,CAAC,EAAE;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC1C,YAAY,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,CAAC,EAAE;gBAAE,IAAI,CAAC,EAAE,MAAM,CAAC;gBAAC,MAAM,CAAC,EAAE;oBAAE,IAAI,CAAC,EAAE,MAAM,CAAC;oBAAC,IAAI,CAAC,EAAE,MAAM,CAAA;iBAAE,CAAA;aAAE,CAAA;SAAE,CAAC,CAAC;KAC/F,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;
|
|
1
|
+
{"version":3,"file":"client-bundle.d.ts","sourceRoot":"","sources":["../src/client-bundle.ts"],"names":[],"mappings":"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"}
|
package/dist/client-bundle.js
CHANGED
|
@@ -137,32 +137,41 @@ function isAnyImport(node) {
|
|
|
137
137
|
}
|
|
138
138
|
/**
|
|
139
139
|
* Generated client-preamble nodes the bundle must not re-emit: the local
|
|
140
|
-
* `const __components = {}`
|
|
141
|
-
* the chunk IIFEs already define their own
|
|
142
|
-
* declaration in the same scope would
|
|
140
|
+
* `const __components = {}` / `const __hydrators = {}` registries plus the
|
|
141
|
+
* `__cleanup` / `__place` helpers — the chunk IIFEs already define their own
|
|
142
|
+
* registries, so a second declaration in the same scope would shadow the live
|
|
143
|
+
* map (registrations would land on a detached object).
|
|
143
144
|
*/
|
|
144
145
|
function isRuntimePreamble(node) {
|
|
145
146
|
if (node.type === 'FunctionDeclaration' && (node.id?.name === '__cleanup' || node.id?.name === '__place')) {
|
|
146
147
|
return true;
|
|
147
148
|
}
|
|
148
149
|
if (node.type === 'VariableDeclaration') {
|
|
149
|
-
|
|
150
|
+
const name = node.declarations?.[0]?.id?.name;
|
|
151
|
+
return name === '__components' || name === '__hydrators';
|
|
150
152
|
}
|
|
151
153
|
return false;
|
|
152
154
|
}
|
|
153
155
|
/**
|
|
154
156
|
* `export default __components[<name>];` / `export const <name> = __components[<name>];`
|
|
155
|
-
* aliases emitted by codegen.
|
|
156
|
-
*
|
|
157
|
+
* aliases emitted by codegen. Hydrate-mode codegen emits the same alias against
|
|
158
|
+
* `__hydrators`. The bundle registers components on those maps directly, so
|
|
159
|
+
* these module-level re-exports must go — two surviving `export default`s in
|
|
160
|
+
* one chunk are a `SyntaxError: Identifier '.default' has already been
|
|
161
|
+
* declared` that kills every page script.
|
|
157
162
|
*/
|
|
158
163
|
function isComponentExport(node) {
|
|
164
|
+
const isRegistry = (ref) => {
|
|
165
|
+
const n = ref;
|
|
166
|
+
return !!n && n.type === 'MemberExpression' && n.object?.type === 'Identifier'
|
|
167
|
+
&& (n.object.name === '__components' || n.object.name === '__hydrators');
|
|
168
|
+
};
|
|
159
169
|
if (node.type === 'ExportDefaultDeclaration') {
|
|
160
|
-
|
|
161
|
-
return !!d && d.type === 'MemberExpression' && d.object?.type === 'Identifier' && d.object.name === '__components';
|
|
170
|
+
return isRegistry(node.declaration);
|
|
162
171
|
}
|
|
163
172
|
if (node.type === 'ExportNamedDeclaration') {
|
|
164
173
|
const init = node.declaration?.type === 'VariableDeclaration' ? node.declaration.declarations?.[0]?.init : undefined;
|
|
165
|
-
return
|
|
174
|
+
return isRegistry(init);
|
|
166
175
|
}
|
|
167
176
|
return false;
|
|
168
177
|
}
|
|
@@ -582,7 +591,7 @@ function removeRanges(code, ranges) {
|
|
|
582
591
|
*/
|
|
583
592
|
function fallbackReplay(cached, filePath, imports) {
|
|
584
593
|
const comp = cached.compCode ? imports.add(cached.compCode, filePath).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
585
|
-
const hyd = cached.hydCode ? imports.add(cached.hydCode, filePath).replace(
|
|
594
|
+
const hyd = cached.hydCode ? imports.add(cached.hydCode, filePath).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
586
595
|
return [comp, hyd].filter(Boolean).join('\n');
|
|
587
596
|
}
|
|
588
597
|
/**
|
|
@@ -929,7 +938,7 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
929
938
|
const compSpecs = [];
|
|
930
939
|
const hydSpecs = [];
|
|
931
940
|
const compCode = compWithImports ? imports.add(compWithImports, filePath, compSpecs).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
932
|
-
const hydCode = hydWithImports ? imports.add(hydWithImports, filePath, hydSpecs).replace(
|
|
941
|
+
const hydCode = hydWithImports ? imports.add(hydWithImports, filePath, hydSpecs).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
933
942
|
if (rawComp)
|
|
934
943
|
collectRuntimeImports(rawComp);
|
|
935
944
|
if (rawHyd)
|
|
@@ -1236,7 +1245,7 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
1236
1245
|
const shim = join(tmpBase, `shim-${i}.js`);
|
|
1237
1246
|
const shimLines = [`const m = globalThis.__veskShared[${JSON.stringify(file)}];`];
|
|
1238
1247
|
if (hasDefault)
|
|
1239
|
-
shimLines.push(`export default m;`);
|
|
1248
|
+
shimLines.push(`export default m["default"];`);
|
|
1240
1249
|
for (const name of [...named].sort()) {
|
|
1241
1250
|
shimLines.push(`export const ${name} = m[${JSON.stringify(name)}];`);
|
|
1242
1251
|
}
|
|
@@ -1304,30 +1313,53 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
1304
1313
|
// Pass the app tsconfig so esbuild resolves tsconfig `paths` aliases
|
|
1305
1314
|
// (`@/x`, `@app/x`) inside transitively bundled modules too.
|
|
1306
1315
|
const appTsconfig = findTsconfigPath(appDir);
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1316
|
+
// Build an alias map so esbuild can resolve bare specifiers
|
|
1317
|
+
// (e.g. "vesk-qr") from the app's node_modules. The entry code lives
|
|
1318
|
+
// in a temp directory, so esbuild's default resolver (walking up from
|
|
1319
|
+
// the entry file) can't find app-level node_modules. resolveDir
|
|
1320
|
+
// doesn't exist in this esbuild version, so we alias each bare
|
|
1321
|
+
// specifier to its resolved absolute path.
|
|
1322
|
+
const alias = {};
|
|
1323
|
+
for (const source of entry.importsTable.sources()) {
|
|
1324
|
+
if (source.startsWith('/') || source.startsWith('./') || source.startsWith('../'))
|
|
1325
|
+
continue;
|
|
1326
|
+
let resolved = resolveSsrModule(source, appDir);
|
|
1327
|
+
if (!resolved)
|
|
1328
|
+
resolved = resolveImportPath(source, appDir);
|
|
1329
|
+
if (resolved && !resolved.startsWith('\0builtin:')) {
|
|
1330
|
+
alias[source] = resolved;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
const result = await Promise.race([
|
|
1334
|
+
build({
|
|
1335
|
+
entryPoints: [tmpFile],
|
|
1336
|
+
bundle: true,
|
|
1337
|
+
format: 'iife',
|
|
1338
|
+
platform: 'browser',
|
|
1339
|
+
write: false,
|
|
1340
|
+
logLevel: 'silent',
|
|
1341
|
+
loader: { '.js': 'tsx' },
|
|
1342
|
+
// Bundled dependencies (lucide-vesk above all) carry a license
|
|
1343
|
+
// banner per module, and a barrel import pulls in hundreds of
|
|
1344
|
+
// them. Those banners were ~339 KB of a 350 KB chunk, which is
|
|
1345
|
+
// what kept a barrel import from being usable at all. Attribution
|
|
1346
|
+
// for a dependency stays in its own package; shipping every
|
|
1347
|
+
// module's header inside our own chunk adds nothing.
|
|
1348
|
+
legalComments: 'none',
|
|
1349
|
+
// Shared app modules are NOT inlined here: the resolver below
|
|
1350
|
+
// redirects them to a generated shim reading
|
|
1351
|
+
// `globalThis.__veskShared`, so the single copy in
|
|
1352
|
+
// shared-modules.js serves every route chunk. (esbuild's `alias`
|
|
1353
|
+
// option only accepts bare package names, so this is a resolver
|
|
1354
|
+
// rather than a map.)
|
|
1355
|
+
...(sharedRedirectPlugin ? { plugins: [sharedRedirectPlugin, serverOnlyGuard] } : { plugins: [serverOnlyGuard] }),
|
|
1356
|
+
...(appTsconfig ? { tsconfig: appTsconfig } : {}),
|
|
1357
|
+
// Alias bare specifiers to their resolved absolute paths so
|
|
1358
|
+
// esbuild can find them from the temp chunk dir.
|
|
1359
|
+
...(Object.keys(alias).length ? { alias } : {}),
|
|
1360
|
+
}),
|
|
1361
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('chunk esbuild timeout')), 60000)),
|
|
1362
|
+
]);
|
|
1331
1363
|
finalCode = result.outputFiles[0].text;
|
|
1332
1364
|
}
|
|
1333
1365
|
catch (e) {
|
|
@@ -1337,22 +1369,22 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
1337
1369
|
return x.text + at;
|
|
1338
1370
|
}).join(' | ') || err?.message || String(e);
|
|
1339
1371
|
console.error('[vesk] chunk bundle failed', entry.name, detail);
|
|
1340
|
-
//
|
|
1341
|
-
//
|
|
1342
|
-
//
|
|
1343
|
-
//
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1372
|
+
// A module-scope server-only use is diagnosed here rather than after
|
|
1373
|
+
// the try: the bundler itself throws when the transitive TCP driver
|
|
1374
|
+
// (pg → node:net) can't be browser-bundled, which would otherwise
|
|
1375
|
+
// shadow the real, actionable problem.
|
|
1376
|
+
if (eagerHits.length > 0) {
|
|
1377
|
+
const eagerDetail = eagerHits
|
|
1378
|
+
.map(h => `${h.importer} uses ${h.bindings.map(b => `"${b}"`).join(', ')} from "${h.specifier}" at module scope`)
|
|
1379
|
+
.join('; ');
|
|
1380
|
+
console.error('[vesk] server-only package used at module scope in client code', entry.name + ':', eagerDetail);
|
|
1381
|
+
throw new Error(`[vesk] ${entry.name}: ${eagerDetail}.\n` +
|
|
1382
|
+
'A module-scope statement runs the moment the browser evaluates the chunk, so a ' +
|
|
1383
|
+
'server-only package cannot be substituted there. Move that work into an API route ' +
|
|
1384
|
+
'(app/api/**/route.ts) or a server action — if the binding is only used from inside ' +
|
|
1385
|
+
'a function, this build already handles it.');
|
|
1348
1386
|
}
|
|
1349
|
-
|
|
1350
|
-
// classic script at least parses. Bindings imported from native-only
|
|
1351
|
-
// `@vesk/*` libraries get throwing stubs (a readable degradation
|
|
1352
|
-
// instead of a baffling `X is not defined`); every other stripped
|
|
1353
|
-
// name stays dangling, which is the pre-existing failure mode.
|
|
1354
|
-
const stripped = demoteExports(removeCompiledNodes(entry.code, isAnyImport));
|
|
1355
|
-
finalCode = chunkIIFE(nativeLibraryImportStubs(entry.code) + stripped);
|
|
1387
|
+
throw new Error(`[vesk] chunk bundle failed: ${entry.name} — ${detail}`);
|
|
1356
1388
|
}
|
|
1357
1389
|
finally {
|
|
1358
1390
|
try {
|
|
@@ -1360,25 +1392,6 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
1360
1392
|
}
|
|
1361
1393
|
catch { }
|
|
1362
1394
|
}
|
|
1363
|
-
// Checked OUTSIDE the try above, deliberately. A TCP driver cannot be
|
|
1364
|
-
// stubbed into a browser bundle — a page that looked fine and failed on
|
|
1365
|
-
// its first query would be worse than a build error — and the catch
|
|
1366
|
-
// block degrades every failure into "strip the imports and carry on",
|
|
1367
|
-
// which is exactly the wrong outcome for this one.
|
|
1368
|
-
if (eagerHits.length > 0) {
|
|
1369
|
-
// A stub would throw while the chunk is still evaluating, so the page
|
|
1370
|
-
// would die before a component existed. That is the worst place to
|
|
1371
|
-
// learn about it: refuse the build instead.
|
|
1372
|
-
const detail = eagerHits
|
|
1373
|
-
.map(h => `${h.importer} uses ${h.bindings.map(b => `"${b}"`).join(', ')} from "${h.specifier}" at module scope`)
|
|
1374
|
-
.join('; ');
|
|
1375
|
-
console.error('[vesk] server-only package used at module scope in client code', entry.name + ':', detail);
|
|
1376
|
-
throw new Error(`[vesk] ${entry.name}: ${detail}.\n` +
|
|
1377
|
-
'A module-scope statement runs the moment the browser evaluates the chunk, so a ' +
|
|
1378
|
-
'server-only package cannot be substituted there. Move that work into an API route ' +
|
|
1379
|
-
'(app/api/**/route.ts) or a server action — if the binding is only used from inside ' +
|
|
1380
|
-
'a function, this build already handles it.');
|
|
1381
|
-
}
|
|
1382
1395
|
if (driverHits.length > 0) {
|
|
1383
1396
|
const detail = [...new Set(driverHits.map(h => `${h.specifier} (from ${h.importer})`))].join(', ');
|
|
1384
1397
|
console.error('[vesk] chunk bundle contains a TCP-only driver', entry.name + ':', detail);
|
|
@@ -1494,6 +1507,13 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
1494
1507
|
let hydratorLines = [];
|
|
1495
1508
|
let aliasLines = [];
|
|
1496
1509
|
let hydratorAliasLines = [];
|
|
1510
|
+
// Mono builds bundle every file into one module scope. External-package
|
|
1511
|
+
// imports (e.g. vesk-qr) are not stripped by stripVskImports/stripRuntimeImport,
|
|
1512
|
+
// so multiple files importing the same package would emit duplicate
|
|
1513
|
+
// `import { X } from "pkg"` declarations — a SyntaxError. Fold them into
|
|
1514
|
+
// one deduped import block instead (mirrors what ChunkImports does for
|
|
1515
|
+
// code-split chunks).
|
|
1516
|
+
const monoImports = new ChunkImports();
|
|
1497
1517
|
function compileFileMono(filePath, resolvedName) {
|
|
1498
1518
|
if (seen.has(filePath))
|
|
1499
1519
|
return;
|
|
@@ -1512,8 +1532,15 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
1512
1532
|
if (hydCode)
|
|
1513
1533
|
collectRuntimeImports(hydCode);
|
|
1514
1534
|
// Comp and hyd share the file's top-level bindings — scope together.
|
|
1515
|
-
|
|
1516
|
-
|
|
1535
|
+
let strippedComp = compCode ? stripExports(stripVskImports(stripRuntimeImport(compCode))).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
1536
|
+
let strippedHyd = hydCode ? stripExports(stripVskImports(stripRuntimeImport(hydCode))).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
1537
|
+
// Fold remaining external-package imports into the shared dedup set and
|
|
1538
|
+
// strip them from each file's contribution, so the same package imported
|
|
1539
|
+
// by multiple files only emits one `import` statement.
|
|
1540
|
+
if (monoImports.ok) {
|
|
1541
|
+
strippedComp = strippedComp ? monoImports.add(strippedComp, filePath).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
1542
|
+
strippedHyd = strippedHyd ? monoImports.add(strippedHyd, filePath).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
1543
|
+
}
|
|
1517
1544
|
const fileCode = [strippedComp, strippedHyd].filter(Boolean).join('\n');
|
|
1518
1545
|
if (fileCode.trim())
|
|
1519
1546
|
componentLines.push(scopeFileContribution(fileCode));
|
|
@@ -1554,9 +1581,73 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
1554
1581
|
for (const [compName, compPath] of compMap) {
|
|
1555
1582
|
compileFileMono(compPath, compName);
|
|
1556
1583
|
}
|
|
1557
|
-
|
|
1584
|
+
// Emit the deduplicated external-package import block at the top of the
|
|
1585
|
+
// bundle so every file can reference those bindings without duplicate
|
|
1586
|
+
// declarations. If the import merge aborted (conflicting bindings), log a
|
|
1587
|
+
// warning and leave imports in place (best-effort, matches historical behaviour).
|
|
1588
|
+
if (monoImports.ok) {
|
|
1589
|
+
const head = monoImports.render();
|
|
1590
|
+
if (head)
|
|
1591
|
+
componentLines.unshift(head);
|
|
1592
|
+
}
|
|
1593
|
+
else {
|
|
1594
|
+
console.error('[vesk] mono import merge aborted:', monoImports.reason);
|
|
1595
|
+
}
|
|
1596
|
+
let main = await buildMainBundle(routeTree, runtimeDir, false, {
|
|
1558
1597
|
componentLines, hydratorLines, aliasLines, hydratorAliasLines,
|
|
1559
1598
|
}, !!options?.hmr, !!options?.importRuntime, runtimeImportNames, options?.routeDataCache);
|
|
1599
|
+
// Bundle the monolithic output through esbuild so bare external-package
|
|
1600
|
+
// imports (e.g. vesk-qr) are inlined instead of shipped as filesystem
|
|
1601
|
+
// paths the browser cannot load. Without this, client.js contains
|
|
1602
|
+
// `import ... from "/absolute/path/to/node_modules/…"` — the dev server
|
|
1603
|
+
// answers that with its SPA fallback (text/html), the module script dies,
|
|
1604
|
+
// the router never starts and hydration never completes.
|
|
1605
|
+
const appTsconfig = findTsconfigPath(appDir);
|
|
1606
|
+
const tmpBase = mkdtempSync(join(resolve(appDir, '..'), 'tmp-vesk-mono-'));
|
|
1607
|
+
try {
|
|
1608
|
+
const tmpFile = join(tmpBase, 'entry.js');
|
|
1609
|
+
writeFileSync(tmpFile, main, 'utf-8');
|
|
1610
|
+
const result = await build({
|
|
1611
|
+
entryPoints: [tmpFile],
|
|
1612
|
+
bundle: true,
|
|
1613
|
+
format: 'iife',
|
|
1614
|
+
platform: 'browser',
|
|
1615
|
+
write: false,
|
|
1616
|
+
logLevel: 'silent',
|
|
1617
|
+
loader: { '.js': 'tsx' },
|
|
1618
|
+
legalComments: 'none',
|
|
1619
|
+
...(appTsconfig ? { tsconfig: appTsconfig } : {}),
|
|
1620
|
+
// Stub optional CJS deps (qrcode-generator via vesk-qr, canvas,
|
|
1621
|
+
// @zxing/*) so esbuild never bundles their CJS source into the client
|
|
1622
|
+
// bundle — that would emit a `__require` shim that throws in the
|
|
1623
|
+
// browser. vesk-qr now lazy-loads them via dynamic import; stubbing
|
|
1624
|
+
// keeps the bundle valid ESM without shipping dead code.
|
|
1625
|
+
plugins: [
|
|
1626
|
+
{
|
|
1627
|
+
name: 'stub-browser-packages',
|
|
1628
|
+
setup(b) {
|
|
1629
|
+
b.onResolve({ filter: /^(qrcode-generator|canvas|@zxing\/(browser|node))(\/|$)/ }, (args) => ({ path: args.path, namespace: 'browser-stub' }));
|
|
1630
|
+
b.onLoad({ filter: /.*/, namespace: 'browser-stub' }, () => ({
|
|
1631
|
+
contents: 'export {}\n',
|
|
1632
|
+
loader: 'js',
|
|
1633
|
+
}));
|
|
1634
|
+
},
|
|
1635
|
+
},
|
|
1636
|
+
],
|
|
1637
|
+
});
|
|
1638
|
+
main = result.outputFiles[0].text;
|
|
1639
|
+
}
|
|
1640
|
+
catch (e) {
|
|
1641
|
+
const detail = e?.errors?.map((x) => x.text).join(' | ') || e.message || String(e);
|
|
1642
|
+
console.error('[vesk] client bundle failed', detail);
|
|
1643
|
+
throw new Error(`[vesk] client bundle failed — ${detail}`);
|
|
1644
|
+
}
|
|
1645
|
+
finally {
|
|
1646
|
+
try {
|
|
1647
|
+
rmSync(tmpBase, { recursive: true, force: true });
|
|
1648
|
+
}
|
|
1649
|
+
catch { }
|
|
1650
|
+
}
|
|
1560
1651
|
// Mono (non-codeSplit) builds are the production path — no incremental cache.
|
|
1561
1652
|
componentOwners.report('client bundle');
|
|
1562
1653
|
return { main: await applyTransformPlugins(main, 'client.js'), chunks: [] };
|
|
@@ -1600,15 +1691,46 @@ export function buildRuntimeCode(runtimeDir) {
|
|
|
1600
1691
|
/**
|
|
1601
1692
|
* Names the client runtime actually exports, so the tree-shaken bundle only
|
|
1602
1693
|
* emits the modules reachable from the used set.
|
|
1694
|
+
*
|
|
1695
|
+
* Parses index-client.js with the AST parser instead of regex so that direct
|
|
1696
|
+
* declarations (export function locals() {}, export const x = 1, export class
|
|
1697
|
+
* Foo {}) are captured alongside re-exports (export { X } from '...').
|
|
1603
1698
|
*/
|
|
1604
1699
|
export function runtimeExportNames(runtimeDir) {
|
|
1605
1700
|
const indexSrc = readFileSync(join(runtimeDir, 'index-client.js'), 'utf-8');
|
|
1606
1701
|
const names = new Set();
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1702
|
+
const ast = parse(indexSrc, { filename: join(runtimeDir, 'index-client.js') });
|
|
1703
|
+
for (const node of ast.body) {
|
|
1704
|
+
const n = node;
|
|
1705
|
+
if (n.type === 'ExportNamedDeclaration') {
|
|
1706
|
+
if (n.declaration) {
|
|
1707
|
+
// Direct declaration: export function foo() {}, export const x = 1,
|
|
1708
|
+
// export class Bar {}
|
|
1709
|
+
const decl = n.declaration;
|
|
1710
|
+
if (decl.type === 'FunctionDeclaration' && decl.id) {
|
|
1711
|
+
names.add(String(decl.id.name));
|
|
1712
|
+
}
|
|
1713
|
+
else if (decl.type === 'ClassDeclaration' && decl.id) {
|
|
1714
|
+
names.add(String(decl.id.name));
|
|
1715
|
+
}
|
|
1716
|
+
else if (decl.type === 'VariableDeclaration') {
|
|
1717
|
+
for (const d of decl.declarations) {
|
|
1718
|
+
if (d.id.type === 'Identifier') {
|
|
1719
|
+
names.add(String(d.id.name));
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
else if (n.source) {
|
|
1725
|
+
// Re-export: export { X } from '...' or export { X as Y } from '...'
|
|
1726
|
+
for (const spec of n.specifiers) {
|
|
1727
|
+
if (spec.type === 'ExportSpecifier') {
|
|
1728
|
+
const exported = spec.exported.name;
|
|
1729
|
+
if (exported)
|
|
1730
|
+
names.add(String(exported));
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1612
1734
|
}
|
|
1613
1735
|
}
|
|
1614
1736
|
return names;
|
|
@@ -1700,25 +1822,28 @@ async function bundleRuntimeNames(runtimeDir, names, strict = false) {
|
|
|
1700
1822
|
}
|
|
1701
1823
|
catch { /* not present yet */ }
|
|
1702
1824
|
writeFileSync(entry, `export { ${unique.join(', ')} } from ${JSON.stringify(indexClient)};\n`);
|
|
1703
|
-
const result = await
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1825
|
+
const result = await Promise.race([
|
|
1826
|
+
build({
|
|
1827
|
+
entryPoints: [esbuildPath(entry)],
|
|
1828
|
+
bundle: true,
|
|
1829
|
+
format: 'iife',
|
|
1830
|
+
globalName: '__veskRuntime',
|
|
1831
|
+
platform: 'browser',
|
|
1832
|
+
target: ['es2022'],
|
|
1833
|
+
treeShaking: true,
|
|
1834
|
+
// Do not let esbuild rename identifiers here. This bundle is one large
|
|
1835
|
+
// IIFE built from many runtime modules, and the renaming pass of some
|
|
1836
|
+
// esbuild versions (observed on 0.25.12) emits a free reference to an
|
|
1837
|
+
// undefined minified name (ReferenceError: m is not defined) that kills
|
|
1838
|
+
// client hydration for the whole app. Whitespace-only output keeps the
|
|
1839
|
+
// runtime deterministic at a modest size cost; tree-shaking still prunes
|
|
1840
|
+
// unreachable modules, so names coming out of the IIFE are untouched.
|
|
1841
|
+
minify: false,
|
|
1842
|
+
write: false,
|
|
1843
|
+
logLevel: 'silent',
|
|
1844
|
+
}),
|
|
1845
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('runtime esbuild timeout')), 60000)),
|
|
1846
|
+
]);
|
|
1722
1847
|
const bundle = result.outputFiles[0].text;
|
|
1723
1848
|
return `${bundle}\nconst { ${unique.join(', ')} } = __veskRuntime;\nexport { ${unique.join(', ')} };\n`;
|
|
1724
1849
|
}
|
package/dist/dev-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,MAAM,EAA6C,MAAM,WAAW,CAAC;AASjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAO7C,OAAO,KAAK,EAAa,gBAAgB,EAAwB,MAAM,yBAAyB,CAAC;AAgBjG;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB;+EAC2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAwDD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mHAAmH;IACnH,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B;;8BAE0B;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,WAAW,CAAC;IAChC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACvE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAChH,CAUA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,MAAM,EAA6C,MAAM,WAAW,CAAC;AASjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAO7C,OAAO,KAAK,EAAa,gBAAgB,EAAwB,MAAM,yBAAyB,CAAC;AAgBjG;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB;+EAC2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAwDD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mHAAmH;IACnH,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B;;8BAE0B;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,WAAW,CAAC;IAChC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACvE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAChH,CAUA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQrD;AAUD,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4sBvG"}
|
package/dist/dev-server.js
CHANGED
|
@@ -150,7 +150,10 @@ export function devBootstrapScript() {
|
|
|
150
150
|
export function injectDevScripts(html) {
|
|
151
151
|
if (!html.includes('</body>'))
|
|
152
152
|
return html;
|
|
153
|
-
const scripts = '\t<script type="module" src="/_vesk/
|
|
153
|
+
const scripts = '\t<script type="module" src="/_vesk/client.js"></script>\n' +
|
|
154
|
+
'\t<script type="module" src="/_vesk/hmr.js"></script>\n' +
|
|
155
|
+
devBootstrapScript() +
|
|
156
|
+
'\n';
|
|
154
157
|
return html.replace('</body>', scripts + '</body>');
|
|
155
158
|
}
|
|
156
159
|
const MIME = {
|
|
@@ -404,7 +407,12 @@ export async function startDevServer(appDir, options) {
|
|
|
404
407
|
}
|
|
405
408
|
}
|
|
406
409
|
}
|
|
407
|
-
await doBuild()
|
|
410
|
+
await doBuild();
|
|
411
|
+
if (pendingInitialError) {
|
|
412
|
+
console.error(`vesk dev: initial build failed — ${pendingInitialError.message}`);
|
|
413
|
+
console.error(`vesk dev: cannot start server with a broken build. Fix the errors above and restart.`);
|
|
414
|
+
process.exit(1);
|
|
415
|
+
}
|
|
408
416
|
const server = createServer(async (req, res) => {
|
|
409
417
|
const url = new URL(req.url || '/', `http://localhost:${port}`);
|
|
410
418
|
// SSR fetches may run while concurrent sub-requests (e.g. the page's own
|
|
@@ -507,6 +515,25 @@ export async function startDevServer(appDir, options) {
|
|
|
507
515
|
res.end(runtimeBundle);
|
|
508
516
|
return;
|
|
509
517
|
}
|
|
518
|
+
// Serve the dev client bundle at /_vesk/client.js. The file is written to
|
|
519
|
+
// devDir/static/client.js by the build step. The SSR-injected script tag
|
|
520
|
+
// references this exact URL.
|
|
521
|
+
if (url.pathname === '/_vesk/client.js') {
|
|
522
|
+
const clientPath = resolve(devDir, 'static', 'client.js');
|
|
523
|
+
try {
|
|
524
|
+
if (existsSync(clientPath)) {
|
|
525
|
+
res.writeHead(200, { 'Content-Type': 'application/javascript' });
|
|
526
|
+
res.end(readFileSync(clientPath, 'utf-8'));
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
catch {
|
|
531
|
+
/* fall through to 404 below */
|
|
532
|
+
}
|
|
533
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
534
|
+
res.end('client.js not built yet');
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
510
537
|
// External data scripts (/ssr-data.js?t=...) are emitted by
|
|
511
538
|
// storeDataScriptGlobal once a render serializes SSR data. Without this
|
|
512
539
|
// route the dev SPA fallback served the HTML document as the script's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"esbuild-fallback.d.ts","sourceRoot":"","sources":["../src/esbuild-fallback.ts"],"names":[],"mappings":"AAkCA,wBAAsB,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"esbuild-fallback.d.ts","sourceRoot":"","sources":["../src/esbuild-fallback.ts"],"names":[],"mappings":"AAkCA,wBAAsB,KAAK,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAoBtD"}
|
package/dist/esbuild-fallback.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// the compiler's dependency-free `stripCodeTypes` (acorn-based), so no
|
|
5
5
|
// transformSync path exists anymore.
|
|
6
6
|
let _nativeBuild = null;
|
|
7
|
-
let _nativeDead =
|
|
7
|
+
let _nativeDead = process.env.VESK_NO_NATIVE_ESBUILD === 'true';
|
|
8
8
|
let _wasm = null;
|
|
9
9
|
let _wasmReady = null;
|
|
10
10
|
async function loadNative() {
|
|
@@ -25,22 +25,25 @@ async function getWasm() {
|
|
|
25
25
|
_wasmReady = import('esbuild-wasm').then(m => {
|
|
26
26
|
_wasm = m;
|
|
27
27
|
return m;
|
|
28
|
-
}).catch(() => {
|
|
28
|
+
}).catch((e) => {
|
|
29
29
|
_wasmReady = null;
|
|
30
|
-
throw new Error(
|
|
30
|
+
throw new Error(`esbuild-wasm not available — install it with: npm install esbuild-wasm (underlying: ${e instanceof Error ? e.message : String(e)})`);
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
return _wasmReady;
|
|
34
34
|
}
|
|
35
35
|
export async function build(options) {
|
|
36
36
|
await loadNative();
|
|
37
|
-
if (_nativeBuild) {
|
|
37
|
+
if (_nativeBuild && !_nativeDead) {
|
|
38
38
|
try {
|
|
39
|
-
return await
|
|
39
|
+
return await Promise.race([
|
|
40
|
+
_nativeBuild(options),
|
|
41
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('esbuild native timeout')), 120000)),
|
|
42
|
+
]);
|
|
40
43
|
}
|
|
41
44
|
catch (e) {
|
|
42
45
|
const msg = e instanceof Error ? e.message : String(e);
|
|
43
|
-
if (msg.includes('SIGILL') || msg.includes('illegal hardware instruction') || msg.includes('cannot execute binary file')) {
|
|
46
|
+
if (msg.includes('SIGILL') || msg.includes('illegal hardware instruction') || msg.includes('cannot execute binary file') || msg.includes('esbuild native timeout')) {
|
|
44
47
|
console.warn('vesk: native esbuild failed, falling back to esbuild-wasm:', msg);
|
|
45
48
|
_nativeDead = true;
|
|
46
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-handler.d.ts","sourceRoot":"","sources":["../src/platform-handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AASvE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAMpD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtC;AAgBD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CA4PjF;AAED,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"platform-handler.d.ts","sourceRoot":"","sources":["../src/platform-handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AASvE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iFAAiF;IACjF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAMpD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtC;AAgBD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,oBAAoB,GAAG,MAAM,CA4PjF;AAED,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmJzF;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB"}
|
package/dist/platform-handler.js
CHANGED
|
@@ -337,17 +337,42 @@ export const sep = '/';
|
|
|
337
337
|
export const delimiter = ':';
|
|
338
338
|
export const spawnSync = () => ({ status: 0 });
|
|
339
339
|
export const execSync = () => '';
|
|
340
|
-
export const randomBytes = () => ({});
|
|
341
|
-
export const createHash = () => ({ update: () => {}, digest: () => '' });
|
|
342
340
|
`;
|
|
343
|
-
return {
|
|
344
|
-
contents,
|
|
345
|
-
loader: 'js',
|
|
346
|
-
};
|
|
341
|
+
return { contents, loader: 'js' };
|
|
347
342
|
});
|
|
348
343
|
},
|
|
349
344
|
});
|
|
350
345
|
}
|
|
346
|
+
// Edge/neutral targets bundle everything into ESM. CJS dependencies (e.g.
|
|
347
|
+
// qrcode-generator via vesk-qr) can't be bundled as ESM — esbuild rewrites
|
|
348
|
+
// their require() calls into `__require` shims that throw in ESM output.
|
|
349
|
+
// esbuild 0.28's string `external` option does not externalize resolvable
|
|
350
|
+
// bare specifiers (it emits `__require` shims instead), so resolve these
|
|
351
|
+
// packages to empty stub modules. Nothing from them is bundled, so no
|
|
352
|
+
// `__require` definition or call leaks into the edge bundle. vesk-qr and its
|
|
353
|
+
// optional CJS deps (qrcode-generator, canvas, @zxing/*) are optional at
|
|
354
|
+
// runtime on edge (they fail gracefully), so stubbing them at build time is
|
|
355
|
+
// safe and keeps the bundle valid ESM.
|
|
356
|
+
plugins.push({
|
|
357
|
+
name: 'stub-edge-packages',
|
|
358
|
+
setup(build) {
|
|
359
|
+
build.onResolve({ filter: /^(vesk-qr|qrcode-generator|canvas|@zxing\/(browser|node))(\/|$)/ }, (args) => ({ path: args.path, namespace: 'vesk-edge-stub' }));
|
|
360
|
+
build.onLoad({ filter: /.*/, namespace: 'vesk-edge-stub' }, () => ({
|
|
361
|
+
contents: [
|
|
362
|
+
'export const CofoundrMatrix = undefined;\n',
|
|
363
|
+
'export const generate = undefined;\n',
|
|
364
|
+
'export const Qr = undefined;\n',
|
|
365
|
+
'export const RawHtml = undefined;\n',
|
|
366
|
+
'export const CanvasUnavailableError = undefined;\n',
|
|
367
|
+
'export const InvalidConfigError = undefined;\n',
|
|
368
|
+
'export const QREncodingError = undefined;\n',
|
|
369
|
+
'export const ScanReliabilityError = undefined;\n',
|
|
370
|
+
'export const QRError = undefined;\n',
|
|
371
|
+
].join(''),
|
|
372
|
+
loader: 'js',
|
|
373
|
+
}));
|
|
374
|
+
},
|
|
375
|
+
});
|
|
351
376
|
const result = await build({
|
|
352
377
|
entryPoints: [entry],
|
|
353
378
|
bundle: true,
|
|
@@ -377,7 +402,18 @@ export const createHash = () => ({ update: () => {}, digest: () => '' });
|
|
|
377
402
|
'const require = createRequire(import.meta.url);\n',
|
|
378
403
|
},
|
|
379
404
|
}
|
|
380
|
-
: {
|
|
405
|
+
: {
|
|
406
|
+
// Edge/neutral targets bundle everything into ESM. CJS dependencies
|
|
407
|
+
// (e.g. qrcode-generator via vesk-qr) can't be bundled as ESM —
|
|
408
|
+
// esbuild adds `__require` shims that throw in ESM output. Mark them
|
|
409
|
+
// external so they're left as bare imports instead of `__require`
|
|
410
|
+
// shims. vesk-qr is ESM but internally requires() its CJS deps,
|
|
411
|
+
// which would generate __require shims — externalize it too so its
|
|
412
|
+
// code never enters the bundle. On edge hosts without node_modules
|
|
413
|
+
// these external imports fail at runtime (expected — CJS packages
|
|
414
|
+
// don't run on edge), but the bundle itself is valid ESM.
|
|
415
|
+
external: ['vesk-qr', 'qrcode-generator', 'canvas', '@zxing/browser', '@zxing/node'],
|
|
416
|
+
}),
|
|
381
417
|
logOverride: { 'direct-eval': 'silent' },
|
|
382
418
|
plugins,
|
|
383
419
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vesk/adapter",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.93",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vesk adapter — builds deployable .vesk/ output for Deno and Node serverless",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"sharp": "^0.35.3"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@vesk/compiler": "^0.2.
|
|
27
|
-
"@vesk/runtime": "^0.2.
|
|
28
|
-
"@vesk/types": "^0.2.
|
|
26
|
+
"@vesk/compiler": "^0.2.93",
|
|
27
|
+
"@vesk/runtime": "^0.2.93",
|
|
28
|
+
"@vesk/types": "^0.2.93"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/ws": "^8.18.1",
|