@vesk/adapter 0.2.15 → 0.2.17
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.map +1 -1
- package/dist/client-bundle.js +243 -35
- package/dist/css.d.ts +6 -11
- package/dist/css.d.ts.map +1 -1
- package/dist/css.js +19 -38
- package/dist/dev-config.d.ts.map +1 -1
- package/dist/dev-config.js +139 -3
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +90 -1
- package/dist/events.d.ts +9 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +109 -0
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +33 -43
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -34
- package/dist/manifest.d.ts +1 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +2 -1
- package/dist/platform-deploy.d.ts.map +1 -1
- package/dist/platform-deploy.js +1 -0
- package/dist/platform-handler.d.ts +2 -0
- package/dist/platform-handler.d.ts.map +1 -1
- package/dist/platform-handler.js +14 -2
- package/dist/prod-server.d.ts.map +1 -1
- package/dist/prod-server.js +62 -15
- package/dist/runtime-bundle.d.ts.map +1 -1
- package/dist/runtime-bundle.js +10 -0
- package/dist/ssr-function.d.ts.map +1 -1
- package/dist/ssr-function.js +43 -32
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-bundle.d.ts","sourceRoot":"","sources":["../src/client-bundle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client-bundle.d.ts","sourceRoot":"","sources":["../src/client-bundle.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,kBAAkB,EAAqC,MAAM,yBAAyB,CAAC;AAoCrI;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA8BhE;AAmUD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkBxD;AAmCD,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,SAAS,EAAE,EACtB,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,kBAAkB,CAAC,CAuX7B;AAMD,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CA+B3D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAUlE;AAYD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAuCrG"}
|
package/dist/client-bundle.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync, existsSync, writeFileSync, unlinkSync, statSync, rmSync } from 'node:fs';
|
|
1
|
+
import { readFileSync, existsSync, writeFileSync, unlinkSync, statSync, rmSync, mkdtempSync } from 'node:fs';
|
|
2
2
|
import { resolve, join, dirname, relative, sep } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { build } from './esbuild-fallback.js';
|
|
@@ -197,18 +197,160 @@ function demoteExports(code) {
|
|
|
197
197
|
code = code.slice(0, e.start) + e.text + code.slice(e.end);
|
|
198
198
|
return code;
|
|
199
199
|
}
|
|
200
|
+
function hasChunkImports(code) {
|
|
201
|
+
try {
|
|
202
|
+
const ast = parse(code);
|
|
203
|
+
return (ast.body ?? []).some((n) => n.type === 'ImportDeclaration');
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
200
209
|
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
* Rewrites a compiled file's source specifier so esbuild can resolve it from
|
|
211
|
+
* the temp bundle entry. Bare package specifiers (e.g. `lucide-vesk`) stay
|
|
212
|
+
* as-is; relative specifiers are resolved to absolute filesystem paths with a
|
|
213
|
+
* `.ts` extension appended so esbuild loads the module as TypeScript and
|
|
214
|
+
* inlines its exported values. Offset-based on the parser AST — never a text
|
|
215
|
+
* scan.
|
|
216
|
+
*/
|
|
217
|
+
function resolveImportSource(src, filePath) {
|
|
218
|
+
if (src.startsWith('./') || src.startsWith('../')) {
|
|
219
|
+
return resolve(dirname(filePath), src) + '.ts';
|
|
220
|
+
}
|
|
221
|
+
return src;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Accumulates every import a code-split chunk needs and rebuilds it as a
|
|
225
|
+
* single deduped import block.
|
|
226
|
+
*
|
|
227
|
+
* A chunk is the concatenation of several independently compiled files, and
|
|
228
|
+
* each file's component AND hydrator both keep their imports verbatim. So the
|
|
229
|
+
* same named binding frequently appears multiple times in one chunk — once per
|
|
230
|
+
* (file, comp|hyd) pair, plus once per extra file. acorn's `parse()` rejects
|
|
231
|
+
* that with `Identifier has already been declared`, so `hasChunkImports` used
|
|
232
|
+
* to silently return false and esbuild — which rejects the same duplicates —
|
|
233
|
+
* never ran; the chunk shipped with raw `import` statements inside its
|
|
234
|
+
* classic-script IIFE and hydration died with `SyntaxError: Cannot use import
|
|
235
|
+
* statement outside a module`.
|
|
236
|
+
*
|
|
237
|
+
* Processing each file's contribution in isolation avoids the duplicate
|
|
238
|
+
* bindings entirely (a single compiled file parses cleanly), folds the imports
|
|
239
|
+
* into a per-source map keyed by local binding, strips them from the file
|
|
240
|
+
* body, and later emits one merged import block at the top of the chunk.
|
|
209
241
|
*/
|
|
210
|
-
|
|
211
|
-
|
|
242
|
+
class ChunkImports {
|
|
243
|
+
bySource = new Map();
|
|
244
|
+
aborted = false;
|
|
245
|
+
abortReason = null;
|
|
246
|
+
fail(reason, code) {
|
|
247
|
+
if (!this.aborted) {
|
|
248
|
+
this.aborted = true;
|
|
249
|
+
this.abortReason = reason;
|
|
250
|
+
}
|
|
251
|
+
return code;
|
|
252
|
+
}
|
|
253
|
+
/** Folds one file's imports into the merged set and returns the code with its imports stripped. */
|
|
254
|
+
add(code, filePath) {
|
|
255
|
+
if (!code || this.aborted)
|
|
256
|
+
return code;
|
|
257
|
+
let ast;
|
|
258
|
+
try {
|
|
259
|
+
ast = parse(code);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// A single compiled file is always valid ESM; if it somehow is not,
|
|
263
|
+
// stop merging so the assembler falls back to the historical path.
|
|
264
|
+
return this.fail(`unparseable contribution from ${filePath}`, code);
|
|
265
|
+
}
|
|
266
|
+
const body = ast.body ?? [];
|
|
267
|
+
const ranges = [];
|
|
268
|
+
for (const raw of body) {
|
|
269
|
+
const node = raw;
|
|
270
|
+
if (node.type !== 'ImportDeclaration' || typeof node.start !== 'number' || typeof node.end !== 'number')
|
|
271
|
+
continue;
|
|
272
|
+
const src = node.source?.value;
|
|
273
|
+
if (typeof src !== 'string')
|
|
274
|
+
continue;
|
|
275
|
+
const resolved = resolveImportSource(src, filePath);
|
|
276
|
+
let group = this.bySource.get(resolved);
|
|
277
|
+
if (!group) {
|
|
278
|
+
group = { named: new Map() };
|
|
279
|
+
this.bySource.set(resolved, group);
|
|
280
|
+
}
|
|
281
|
+
for (const spec of node.specifiers ?? []) {
|
|
282
|
+
const s = spec;
|
|
283
|
+
const local = s.local?.name;
|
|
284
|
+
if (typeof local !== 'string')
|
|
285
|
+
return this.fail(`nameless specifier from '${resolved}' in ${filePath}`, code);
|
|
286
|
+
if (s.type === 'ImportDefaultSpecifier') {
|
|
287
|
+
if (group.default && group.default.local !== local)
|
|
288
|
+
return this.fail(`conflicting default imports from '${resolved}' in ${filePath}`, code);
|
|
289
|
+
group.default = { kind: 'default', local };
|
|
290
|
+
}
|
|
291
|
+
else if (s.type === 'ImportNamespaceSpecifier') {
|
|
292
|
+
if (group.namespace && group.namespace.local !== local)
|
|
293
|
+
return this.fail(`conflicting namespace imports from '${resolved}' in ${filePath}`, code);
|
|
294
|
+
group.namespace = { kind: 'namespace', local };
|
|
295
|
+
}
|
|
296
|
+
else if (s.type === 'ImportSpecifier') {
|
|
297
|
+
const imported = s.imported?.name;
|
|
298
|
+
if (typeof imported !== 'string')
|
|
299
|
+
return this.fail(`nameless named-import from '${resolved}' in ${filePath}`, code);
|
|
300
|
+
const existing = group.named.get(imported);
|
|
301
|
+
if (existing && existing.local !== local)
|
|
302
|
+
return this.fail(`'${imported}' from '${resolved}' bound to both '${existing.local}' and '${local}' in ${filePath}`, code);
|
|
303
|
+
group.named.set(imported, { kind: 'named', local, imported });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
let cut = node.end;
|
|
307
|
+
if (code[cut] === ';')
|
|
308
|
+
cut++;
|
|
309
|
+
ranges.push([node.start, cut]);
|
|
310
|
+
}
|
|
311
|
+
if (ranges.length === 0)
|
|
312
|
+
return code;
|
|
313
|
+
return removeRanges(code, ranges);
|
|
314
|
+
}
|
|
315
|
+
/** True when every file parsed and merged cleanly (no conflict, no parse abort). */
|
|
316
|
+
get ok() {
|
|
317
|
+
return !this.aborted;
|
|
318
|
+
}
|
|
319
|
+
/** Why the merge aborted (null when `ok`). Surfaced by the assembler. */
|
|
320
|
+
get reason() {
|
|
321
|
+
return this.abortReason;
|
|
322
|
+
}
|
|
323
|
+
/** Renders the deduped import block (empty string when there are no imports). */
|
|
324
|
+
render() {
|
|
325
|
+
if (this.aborted || this.bySource.size === 0)
|
|
326
|
+
return '';
|
|
327
|
+
const lines = [];
|
|
328
|
+
const sources = [...this.bySource.keys()].sort();
|
|
329
|
+
for (const src of sources) {
|
|
330
|
+
const g = this.bySource.get(src);
|
|
331
|
+
const parts = [];
|
|
332
|
+
if (g.default)
|
|
333
|
+
parts.push(`import ${g.default.local} from ${JSON.stringify(src)}`);
|
|
334
|
+
if (g.namespace)
|
|
335
|
+
parts.push(`import * as ${g.namespace.local} from ${JSON.stringify(src)}`);
|
|
336
|
+
const named = [...g.named.values()].sort((a, b) => (a.imported < b.imported ? -1 : 1));
|
|
337
|
+
if (named.length > 0) {
|
|
338
|
+
const specs = named.map((sp) => (sp.imported === sp.local ? sp.local : `${sp.imported} as ${sp.local}`)).join(', ');
|
|
339
|
+
parts.push(`import { ${specs} } from ${JSON.stringify(src)}`);
|
|
340
|
+
}
|
|
341
|
+
lines.push(parts.join('\n'));
|
|
342
|
+
}
|
|
343
|
+
return lines.join('\n');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/** Removes a set of offset ranges from a source string, high-to-low. */
|
|
347
|
+
function removeRanges(code, ranges) {
|
|
348
|
+
const sorted = [...ranges].sort((a, b) => b[0] - a[0]);
|
|
349
|
+
let out = code;
|
|
350
|
+
for (const [start, end] of sorted) {
|
|
351
|
+
out = out.slice(0, start) + out.slice(end);
|
|
352
|
+
}
|
|
353
|
+
return out.trim();
|
|
212
354
|
}
|
|
213
355
|
/**
|
|
214
356
|
* Scopes one file's contribution to the shared chunk: module-level
|
|
@@ -365,7 +507,7 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
365
507
|
function stripExports(code) {
|
|
366
508
|
return removeCompiledNodes(code, isComponentExport);
|
|
367
509
|
}
|
|
368
|
-
function compileFile(filePath, resolvedName, output) {
|
|
510
|
+
function compileFile(filePath, resolvedName, output, imports) {
|
|
369
511
|
if (seen.has(filePath))
|
|
370
512
|
return;
|
|
371
513
|
seen.add(filePath);
|
|
@@ -390,11 +532,17 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
390
532
|
if (cached && cacheUsable) {
|
|
391
533
|
cachedFileHits++;
|
|
392
534
|
for (const dep of cached.imports)
|
|
393
|
-
compileFile(dep, cache?.files.get(dep)?.actualName ?? '', output);
|
|
535
|
+
compileFile(dep, cache?.files.get(dep)?.actualName ?? '', output, imports);
|
|
394
536
|
// Comp and hyd contributions of one file share its top-level bindings
|
|
395
537
|
// (e.g. `const links` used by both the component and its hydrator),
|
|
396
|
-
// so they must be scoped together in a single block.
|
|
397
|
-
|
|
538
|
+
// so they must be scoped together in a single block. Cached codes keep
|
|
539
|
+
// their imports; each side is folded separately because comp+hyd of one
|
|
540
|
+
// file carry the same import twice (joint parse would abort the merge).
|
|
541
|
+
// Mirror the fresh path exactly: strip, rename the hydrator registry,
|
|
542
|
+
// trim — otherwise warm output drifts from cold output.
|
|
543
|
+
const cachedComp = cached.compCode ? imports.add(cached.compCode, filePath).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
544
|
+
const cachedHyd = cached.hydCode ? imports.add(cached.hydCode, filePath).replace(/__components/g, '__hydrators').replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
545
|
+
const cachedFileCode = [cachedComp, cachedHyd].filter(Boolean).join('\n');
|
|
398
546
|
if (cachedFileCode.trim())
|
|
399
547
|
output.push(scopeFileContribution(cachedFileCode));
|
|
400
548
|
for (const n of cached.runtimeNames)
|
|
@@ -411,13 +559,17 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
411
559
|
src = inlineMdContentAttrs(src, dirname(filePath), guessProjectRoots(appDir));
|
|
412
560
|
}
|
|
413
561
|
const namesBefore = cache ? new Set(runtimeImportNames) : null;
|
|
414
|
-
const importedPaths = resolveVskImports(filePath, (p, n) => compileFile(p, n
|
|
562
|
+
const importedPaths = resolveVskImports(filePath, (p, n) => compileFile(p, n, output, imports));
|
|
415
563
|
// One parse/IR pass feeds both client modes AND the component-name
|
|
416
564
|
// lookup — the dev hot path pays the acorn+TS parse once per edit
|
|
417
565
|
// instead of three times.
|
|
418
566
|
const { comp: rawComp, hyd: rawHyd, name: actualName } = compileClientBoth(src, null, filePath);
|
|
419
|
-
|
|
420
|
-
|
|
567
|
+
// Cache keeps the import-carrying codes so a warm build can re-fold them
|
|
568
|
+
// into its own fresh accumulator; the emitted codes are import-stripped.
|
|
569
|
+
const compWithImports = rawComp ? stripExports(stripVskImports(stripRuntimeImport(rawComp))) : '';
|
|
570
|
+
const hydWithImports = rawHyd ? stripExports(stripVskImports(stripRuntimeImport(rawHyd))) : '';
|
|
571
|
+
const compCode = compWithImports ? imports.add(compWithImports, filePath).replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
572
|
+
const hydCode = hydWithImports ? imports.add(hydWithImports, filePath).replace(/__components/g, '__hydrators').replace(/^\n+/, '').replace(/\n+$/, '') : '';
|
|
421
573
|
if (rawComp)
|
|
422
574
|
collectRuntimeImports(rawComp);
|
|
423
575
|
if (rawHyd)
|
|
@@ -444,8 +596,8 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
444
596
|
cache.files.set(filePath, {
|
|
445
597
|
mtimeMs: st.mtimeMs,
|
|
446
598
|
size: st.size,
|
|
447
|
-
compCode,
|
|
448
|
-
hydCode,
|
|
599
|
+
compCode: compWithImports,
|
|
600
|
+
hydCode: hydWithImports,
|
|
449
601
|
actualName,
|
|
450
602
|
runtimeNames: [...runtimeImportNames].filter((n) => !namesBefore.has(n)),
|
|
451
603
|
imports: importedPaths,
|
|
@@ -479,57 +631,113 @@ export async function generateClientBundle(routeTree, appDir, componentMap, opti
|
|
|
479
631
|
function walkSplit(nodes, _chain) {
|
|
480
632
|
for (const node of nodes) {
|
|
481
633
|
const chunkCode = [];
|
|
634
|
+
const chunkImports = new ChunkImports();
|
|
482
635
|
const pagePath = resolve(appDir, node.sourceDir, 'page.vsk');
|
|
483
636
|
if (node.page && existsSync(pagePath)) {
|
|
484
|
-
compileFile(pagePath, node.page, chunkCode);
|
|
637
|
+
compileFile(pagePath, node.page, chunkCode, chunkImports);
|
|
485
638
|
}
|
|
486
639
|
const layoutPath = resolve(appDir, node.sourceDir, 'layout.vsk');
|
|
487
640
|
if (node.layout && existsSync(layoutPath)) {
|
|
488
|
-
compileFile(layoutPath, node.layout, chunkCode);
|
|
641
|
+
compileFile(layoutPath, node.layout, chunkCode, chunkImports);
|
|
489
642
|
}
|
|
490
643
|
const errorPath = resolve(appDir, node.sourceDir, 'error.vsk');
|
|
491
644
|
if (node.error && existsSync(errorPath)) {
|
|
492
|
-
compileFile(errorPath, node.error, chunkCode);
|
|
645
|
+
compileFile(errorPath, node.error, chunkCode, chunkImports);
|
|
493
646
|
}
|
|
494
647
|
const notFoundPath = resolve(appDir, node.sourceDir, 'not-found.vsk');
|
|
495
648
|
if (node.notFound && existsSync(notFoundPath)) {
|
|
496
|
-
compileFile(notFoundPath, node.notFound, chunkCode);
|
|
649
|
+
compileFile(notFoundPath, node.notFound, chunkCode, chunkImports);
|
|
497
650
|
}
|
|
498
651
|
const offlinePath = resolve(appDir, node.sourceDir, 'offline.vsk');
|
|
499
652
|
if (node.offline && existsSync(offlinePath)) {
|
|
500
|
-
compileFile(offlinePath, node.offline, chunkCode);
|
|
653
|
+
compileFile(offlinePath, node.offline, chunkCode, chunkImports);
|
|
501
654
|
}
|
|
502
655
|
const networkPath = resolve(appDir, node.sourceDir, 'network.vsk');
|
|
503
656
|
if (node.network && existsSync(networkPath)) {
|
|
504
|
-
compileFile(networkPath, node.network, chunkCode);
|
|
657
|
+
compileFile(networkPath, node.network, chunkCode, chunkImports);
|
|
505
658
|
}
|
|
506
659
|
const loadingPath = resolve(appDir, node.sourceDir, 'loading.vsk');
|
|
507
660
|
if (node.loading && existsSync(loadingPath)) {
|
|
508
|
-
compileFile(loadingPath, node.loading, chunkCode);
|
|
661
|
+
compileFile(loadingPath, node.loading, chunkCode, chunkImports);
|
|
509
662
|
}
|
|
510
663
|
if (chunkCode.length > 0) {
|
|
511
664
|
const chunkName = `page-${buildChunkName(node)}.js`;
|
|
512
|
-
|
|
665
|
+
// Prepend this chunk's deduped imports (one statement per source, no
|
|
666
|
+
// duplicate bindings) so the classic script exposes the bare
|
|
667
|
+
// identifiers its file bodies reference, and esbuild can parse and
|
|
668
|
+
// inline them.
|
|
669
|
+
if (!chunkImports.ok)
|
|
670
|
+
console.error('[vesk] chunk import merge aborted for', chunkName + ':', chunkImports.reason);
|
|
671
|
+
const head = chunkImports.render();
|
|
672
|
+
const code = (head ? head + '\n\n' : '') + chunkCode.join('\n\n');
|
|
673
|
+
chunkEntries.push({ name: chunkName, code, node });
|
|
513
674
|
}
|
|
514
675
|
walkSplit(node.children || [], [..._chain, node]);
|
|
515
676
|
}
|
|
516
677
|
}
|
|
517
678
|
walkSplit(routeTree, []);
|
|
518
679
|
const sharedCode = [];
|
|
680
|
+
const sharedImports = new ChunkImports();
|
|
519
681
|
const compMap = componentMap || new Map();
|
|
520
682
|
for (const [compName, compPath] of compMap) {
|
|
521
|
-
compileFile(compPath, compName, sharedCode);
|
|
683
|
+
compileFile(compPath, compName, sharedCode, sharedImports);
|
|
522
684
|
}
|
|
523
685
|
if (sharedCode.length > 0) {
|
|
524
|
-
|
|
686
|
+
if (!sharedImports.ok)
|
|
687
|
+
console.error('[vesk] chunk import merge aborted for shared.js:', sharedImports.reason);
|
|
688
|
+
const head = sharedImports.render();
|
|
689
|
+
const code = (head ? head + '\n\n' : '') + sharedCode.join('\n\n');
|
|
690
|
+
chunkEntries.push({ name: 'shared.js', code, node: null });
|
|
525
691
|
}
|
|
692
|
+
const chunkIIFE = (body) => `(()=>{\nconst __components = globalThis.__components || (globalThis.__components = {});\nconst __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});\n${body}\n})();\n`;
|
|
526
693
|
for (const entry of chunkEntries) {
|
|
527
|
-
if (entry.code.trim())
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
694
|
+
if (!entry.code.trim())
|
|
695
|
+
continue;
|
|
696
|
+
let finalCode;
|
|
697
|
+
if (hasChunkImports(entry.code)) {
|
|
698
|
+
// Bundle the chunk through esbuild so every remaining import (npm
|
|
699
|
+
// packages like lucide-vesk and rewritten relative `.ts` value
|
|
700
|
+
// modules) is inlined into the IIFE — a classic script cannot carry
|
|
701
|
+
// a live `import`, and a stripped binding referenced by a component
|
|
702
|
+
// would otherwise throw `X is not defined` at hydration. Imports were
|
|
703
|
+
// already deduped per file by `ChunkImports`, so esbuild can parse the
|
|
704
|
+
// bundle entry.
|
|
705
|
+
const tmpBase = mkdtempSync(join(resolve(appDir, '..'), 'tmp-vesk-chunk-'));
|
|
706
|
+
const tmpFile = join(tmpBase, 'entry.js');
|
|
707
|
+
const toBundle = `const __components = globalThis.__components || (globalThis.__components = {});\nconst __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});\n${entry.code}\n`;
|
|
708
|
+
writeFileSync(tmpFile, toBundle);
|
|
709
|
+
try {
|
|
710
|
+
const result = await build({
|
|
711
|
+
entryPoints: [tmpFile],
|
|
712
|
+
bundle: true,
|
|
713
|
+
format: 'iife',
|
|
714
|
+
platform: 'browser',
|
|
715
|
+
write: false,
|
|
716
|
+
logLevel: 'silent',
|
|
717
|
+
loader: { '.js': 'tsx' },
|
|
718
|
+
});
|
|
719
|
+
finalCode = result.outputFiles[0].text;
|
|
720
|
+
}
|
|
721
|
+
catch (e) {
|
|
722
|
+
const err = e;
|
|
723
|
+
console.error('[vesk] chunk bundle failed', entry.name, err?.errors?.map((x) => x.text).join(' | ') || err?.message || String(e));
|
|
724
|
+
// Fall back to the historical behavior: strip every import so the
|
|
725
|
+
// classic script at least parses (referenced values will surface as
|
|
726
|
+
// ReferenceErrors at runtime — the pre-existing failure mode).
|
|
727
|
+
const stripped = demoteExports(removeCompiledNodes(entry.code, isAnyImport));
|
|
728
|
+
finalCode = chunkIIFE(stripped);
|
|
729
|
+
}
|
|
730
|
+
finally {
|
|
731
|
+
try {
|
|
732
|
+
rmSync(tmpBase, { recursive: true, force: true });
|
|
733
|
+
}
|
|
734
|
+
catch { }
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
finalCode = chunkIIFE(entry.code);
|
|
532
739
|
}
|
|
740
|
+
chunks.push({ name: entry.name, code: finalCode });
|
|
533
741
|
}
|
|
534
742
|
function annotate(nodes) {
|
|
535
743
|
for (const node of nodes) {
|
package/dist/css.d.ts
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-
export declare const TAILWIND_CSS_URL = "/_vesk/static/_tailwind.css";
|
|
2
1
|
export declare const GLOBAL_CSS_URL = "/_vesk/static/global.css";
|
|
3
2
|
/** Resolve the project's user stylesheet source (`src/global.css`, then `src/app.css`). */
|
|
4
3
|
export declare function resolveUserCssPath(appDir: string): string | null;
|
|
5
4
|
/** True when the project has a user stylesheet source (`src/global.css` or `src/app.css`). */
|
|
6
5
|
export declare function hasUserCss(appDir: string): boolean;
|
|
7
|
-
/** True when a non-empty `
|
|
8
|
-
export declare function
|
|
6
|
+
/** True when a non-empty `global.css` was produced for the build (prod disk output). */
|
|
7
|
+
export declare function hasBuiltGlobalCss(outDir: string): boolean;
|
|
9
8
|
/** True when the active plugin pipeline includes the tailwind plugin. */
|
|
10
9
|
export declare function isTailwindPlugin(plugins: Array<{
|
|
11
10
|
name?: string;
|
|
12
11
|
}> | undefined | null): boolean;
|
|
13
12
|
/**
|
|
14
13
|
* Single source of truth for the `/_vesk/static/*.css` link list. Callers
|
|
15
|
-
* supply environment facts — `
|
|
16
|
-
* (built-file present + non-empty in prod,
|
|
17
|
-
*
|
|
18
|
-
* paths share one ordering.
|
|
14
|
+
* supply environment facts — `enabled`: a global stylesheet output is
|
|
15
|
+
* available (built-file present + non-empty in prod, user stylesheet present
|
|
16
|
+
* in dev) — so build, request, dev, and prod paths share one ordering.
|
|
19
17
|
*/
|
|
20
18
|
export declare function resolveCssUrls(opts: {
|
|
21
|
-
|
|
22
|
-
userCss?: boolean;
|
|
19
|
+
enabled?: boolean;
|
|
23
20
|
}): string[];
|
|
24
|
-
/** Drop tailwind framework directives from user CSS, keeping hand-written rules. */
|
|
25
|
-
export declare function stripTailwindDirectives(css: string): string;
|
|
26
21
|
//# sourceMappingURL=css.d.ts.map
|
package/dist/css.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"css.d.ts","sourceRoot":"","sources":["../src/css.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,cAAc,6BAA6B,CAAC;AAEzD,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMhE;AAED,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wFAAwF;AACxF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGzD;AAED,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAE9F;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,EAAE,CAGpE"}
|
package/dist/css.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared stylesheet resolution for the adapter build, prod server, generated
|
|
3
3
|
* SSR functions, dev server, and action handler. Each environment feeds its
|
|
4
|
-
* facts (`
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* facts (`enabled`: a built global stylesheet exists) into `resolveCssUrls`,
|
|
5
|
+
* so the `/_vesk/static/global.css` link list comes from one place instead of
|
|
6
|
+
* several ad-hoc copies.
|
|
7
|
+
*
|
|
8
|
+
* Vesk follows the single-file CSS convention used by other frameworks
|
|
9
|
+
* (Next.js/Remix/SvelteKit): a single `src/global.css` is the stylesheet
|
|
10
|
+
* source. When the Tailwind plugin is active the whole file is compiled into
|
|
11
|
+
* one `/_vesk/static/global.css`; otherwise the user CSS is served as-is from
|
|
12
|
+
* the same URL. There is no separate `_tailwind.css` anymore — user rules and
|
|
13
|
+
* the compiled Tailwind output live in the same file, in one `<link>`.
|
|
7
14
|
*/
|
|
8
15
|
import { readFileSync, existsSync } from 'node:fs';
|
|
9
16
|
import { resolve } from 'node:path';
|
|
10
|
-
import { cssBlockEnd } from '@vesk/compiler/src/scan';
|
|
11
|
-
export const TAILWIND_CSS_URL = '/_vesk/static/_tailwind.css';
|
|
12
17
|
export const GLOBAL_CSS_URL = '/_vesk/static/global.css';
|
|
13
18
|
/** Resolve the project's user stylesheet source (`src/global.css`, then `src/app.css`). */
|
|
14
19
|
export function resolveUserCssPath(appDir) {
|
|
@@ -24,9 +29,9 @@ export function resolveUserCssPath(appDir) {
|
|
|
24
29
|
export function hasUserCss(appDir) {
|
|
25
30
|
return resolveUserCssPath(appDir) !== null;
|
|
26
31
|
}
|
|
27
|
-
/** True when a non-empty `
|
|
28
|
-
export function
|
|
29
|
-
const p = resolve(outDir, 'static', '
|
|
32
|
+
/** True when a non-empty `global.css` was produced for the build (prod disk output). */
|
|
33
|
+
export function hasBuiltGlobalCss(outDir) {
|
|
34
|
+
const p = resolve(outDir, 'static', 'global.css');
|
|
30
35
|
return existsSync(p) && readFileSync(p, 'utf-8').trim().length > 0;
|
|
31
36
|
}
|
|
32
37
|
/** True when the active plugin pipeline includes the tailwind plugin. */
|
|
@@ -35,36 +40,12 @@ export function isTailwindPlugin(plugins) {
|
|
|
35
40
|
}
|
|
36
41
|
/**
|
|
37
42
|
* Single source of truth for the `/_vesk/static/*.css` link list. Callers
|
|
38
|
-
* supply environment facts — `
|
|
39
|
-
* (built-file present + non-empty in prod,
|
|
40
|
-
*
|
|
41
|
-
* paths share one ordering.
|
|
43
|
+
* supply environment facts — `enabled`: a global stylesheet output is
|
|
44
|
+
* available (built-file present + non-empty in prod, user stylesheet present
|
|
45
|
+
* in dev) — so build, request, dev, and prod paths share one ordering.
|
|
42
46
|
*/
|
|
43
47
|
export function resolveCssUrls(opts) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (opts.userCss)
|
|
48
|
-
urls.push(GLOBAL_CSS_URL);
|
|
49
|
-
return urls;
|
|
50
|
-
}
|
|
51
|
-
/** Drop tailwind framework directives from user CSS, keeping hand-written rules. */
|
|
52
|
-
export function stripTailwindDirectives(css) {
|
|
53
|
-
const blockStart = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+[\w-]+\s*\{)/;
|
|
54
|
-
let result = css.replace(/^\s*@import\s+['"]tailwindcss['"]\s*;?\s*$/gm, '');
|
|
55
|
-
result = result.replace(/^\s*@source\s+['"][^'"]+['"]\s*;?\s*$/gm, '');
|
|
56
|
-
const output = [];
|
|
57
|
-
let pos = 0;
|
|
58
|
-
while (pos < result.length) {
|
|
59
|
-
const lineEnd = result.indexOf('\n', pos) === -1 ? result.length : result.indexOf('\n', pos) + 1;
|
|
60
|
-
const line = result.slice(pos, lineEnd);
|
|
61
|
-
if (blockStart.test(line.trim())) {
|
|
62
|
-
const end = cssBlockEnd(result, pos);
|
|
63
|
-
pos = end;
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
output.push(line);
|
|
67
|
-
pos = lineEnd;
|
|
68
|
-
}
|
|
69
|
-
return output.join('').trim();
|
|
48
|
+
if (opts.enabled)
|
|
49
|
+
return [GLOBAL_CSS_URL];
|
|
50
|
+
return [];
|
|
70
51
|
}
|
package/dist/dev-config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-config.d.ts","sourceRoot":"","sources":["../src/dev-config.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAMjE;AAQD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmC/G;AAED,oEAAoE;AACpE,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAM9E;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAQrG;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAc5F;
|
|
1
|
+
{"version":3,"file":"dev-config.d.ts","sourceRoot":"","sources":["../src/dev-config.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAMjE;AAQD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmC/G;AAED,oEAAoE;AACpE,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAM9E;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAQrG;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAc5F;AAgOD,wJAAwJ;AACxJ,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAcxD;AAyYD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2EtF;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAqC9F"}
|