@decocms/tanstack 7.20.2 → 7.20.3

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.
Files changed (2) hide show
  1. package/package.json +4 -4
  2. package/src/vite/plugin.js +74 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decocms/tanstack",
3
- "version": "7.20.2",
3
+ "version": "7.20.3",
4
4
  "type": "module",
5
5
  "description": "Deco framework binding for TanStack Start + Cloudflare Workers",
6
6
  "repository": {
@@ -24,9 +24,9 @@
24
24
  "lint:unused": "knip"
25
25
  },
26
26
  "dependencies": {
27
- "@decocms/blocks": "7.20.2",
28
- "@decocms/blocks-admin": "7.20.2",
29
- "@decocms/blocks-cli": "7.20.2",
27
+ "@decocms/blocks": "7.20.3",
28
+ "@decocms/blocks-admin": "7.20.3",
29
+ "@decocms/blocks-cli": "7.20.3",
30
30
  "@deco-cx/warp-node": "^0.3.16",
31
31
  "fast-json-patch": "^3.1.0",
32
32
  "ws": "^8.18.0"
@@ -376,27 +376,52 @@ export function decoVitePlugin() {
376
376
  server.watcher.on("change", (file) => handleBlocksDirEvent(file, false));
377
377
  server.watcher.on("unlink", (file) => handleBlocksDirEvent(file, true));
378
378
 
379
- // Cold-start bootstrap: always regenerate `blocks.gen.json` from source
380
- // on dev startup. We deliberately do NOT gate this on mtime. A fresh git
381
- // checkout/clone (e.g. Studio's preview sandbox) rewrites every file's
382
- // mtime to the checkout time, so the committed artifact can be CONTENT-
383
- // stale yet mtime-"fresh" the old `source.mtime > artifact.mtime` gate
384
- // then skipped regen and served the stale snapshot (the double-render
385
- // bug in branch previews). Regen is cheap (tens of ms for a typical
386
- // decofile) and fire-and-forget, so it never blocks startup. No POST
387
- // /.decofile here the SSR runtime isn't listening yet, and `setup.ts`
388
- // reads the freshly-written .json via the load() hook on the first
389
- // request (the watch-driven path above handles live edits, with reload).
379
+ // Cold-start bootstrap of `blocks.gen.json`, in two modes:
380
+ //
381
+ // MISSING (fresh clone): blocks.gen.json is gitignored, so a first
382
+ // checkout has no file on disk. The async refresh below is
383
+ // fire-and-forget and races the first request `setup.ts` reads the
384
+ // .json sibling via the blocks.gen.ts load() hook, and a miss falls
385
+ // back to the empty stub, rendering a blank page until regen lands and
386
+ // triggers a reload. So when the snapshot is ABSENT we generate it
387
+ // SYNCHRONOUSLY, blocking startup until the very first request can see
388
+ // real content. This only fires on a fresh clone, never steady-state.
389
+ //
390
+ // PRESENT (steady state): refresh asynchronously and DELIBERATELY NOT
391
+ // gated on mtime. A fresh git checkout rewrites every file's mtime to
392
+ // the checkout time, so a committed artifact could be CONTENT-stale yet
393
+ // mtime-"fresh" — the old `source.mtime > artifact.mtime` gate then
394
+ // served the stale snapshot (the double-render bug in branch previews).
395
+ // Regen is cheap (tens of ms) and fire-and-forget, so it never blocks
396
+ // startup. No POST /.decofile here — the SSR runtime isn't listening
397
+ // yet; `setup.ts` reads the freshly-written .json on the first request
398
+ // (the watch-driven path above handles live edits, with reload).
390
399
  if (existsSync(blocksDir)) {
391
- ensureMerged()
392
- .then(({ result }) => {
393
- if (result && !result.empty) {
394
- console.log(`[deco] bootstrapped ${result.count} blocks from .deco/blocks`);
395
- }
396
- })
397
- .catch((err) => {
398
- console.warn("[deco] blocks bootstrap failed:", err?.message ?? err);
399
- });
400
+ if (!existsSync(jsonFile)) {
401
+ console.log("[deco] blocks.gen.json missing generating on cold start…");
402
+ try {
403
+ const scriptPath = path.resolve(
404
+ cwd,
405
+ "node_modules/@decocms/blocks-cli/scripts/generate-blocks.ts",
406
+ );
407
+ execFileSync("npx", ["tsx", scriptPath], { cwd, stdio: "inherit" });
408
+ } catch (err) {
409
+ console.warn(
410
+ "[deco] blocks.gen.json cold-start generation failed:",
411
+ err?.message ?? err,
412
+ );
413
+ }
414
+ } else {
415
+ ensureMerged()
416
+ .then(({ result }) => {
417
+ if (result && !result.empty) {
418
+ console.log(`[deco] bootstrapped ${result.count} blocks from .deco/blocks`);
419
+ }
420
+ })
421
+ .catch((err) => {
422
+ console.warn("[deco] blocks bootstrap failed:", err?.message ?? err);
423
+ });
424
+ }
400
425
  }
401
426
 
402
427
  // --- meta.gen.json auto-regeneration ---
@@ -456,6 +481,35 @@ export function decoVitePlugin() {
456
481
  }, 500);
457
482
  };
458
483
 
484
+ // Cold-start bootstrap: generate meta.gen.json if it's absent. The
485
+ // artifact is gitignored (committing it causes constant PR conflicts), so
486
+ // a fresh clone has no file on disk — yet setup.ts imports it EAGERLY via
487
+ // createAdminSetup, so the import would reject on the first request.
488
+ //
489
+ // Unlike the blocks bootstrap above, this is (a) gated on absence and
490
+ // (b) SYNCHRONOUS: a full ts-morph schema pass takes seconds, so we only
491
+ // pay it when the file is genuinely missing, and we must finish before the
492
+ // server accepts a request. Once the file exists on disk (any subsequent
493
+ // start), this is skipped and the watch-driven regen below keeps it fresh.
494
+ if (!existsSync(schemaOutFile)) {
495
+ console.log("[deco] meta.gen.json missing — generating on cold start…");
496
+ try {
497
+ const scriptPath = path.resolve(
498
+ cwd,
499
+ "node_modules/@decocms/blocks-cli/scripts/generate-schema.ts",
500
+ );
501
+ execFileSync("npx", ["tsx", scriptPath, "--site", schemaSiteName], {
502
+ cwd,
503
+ stdio: "inherit",
504
+ });
505
+ } catch (err) {
506
+ console.warn(
507
+ "[deco] meta.gen.json cold-start generation failed:",
508
+ err?.message ?? err,
509
+ );
510
+ }
511
+ }
512
+
459
513
  const isSchemaSource = (file) => {
460
514
  const rel = path.relative(cwd, file);
461
515
  return (