@_linked/server 2.14.0 → 2.14.1

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 (33) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/lib/esm/backend.js.map +1 -1
  3. package/lib/esm/index.js.map +1 -1
  4. package/lib/esm/ontologies/lincd-server.js.map +1 -1
  5. package/lib/esm/ontologies/lincd-server.register.js.map +1 -1
  6. package/lib/esm/package.js.map +1 -1
  7. package/lib/esm/shapes/LincdAPI.js +4 -1
  8. package/lib/esm/shapes/LincdAPI.js.map +1 -1
  9. package/lib/esm/shapes/LincdWebApp.js +4 -1
  10. package/lib/esm/shapes/LincdWebApp.js.map +1 -1
  11. package/lib/esm/shapes/LinkedServer.d.ts +6 -1
  12. package/lib/esm/shapes/LinkedServer.js +71 -47
  13. package/lib/esm/shapes/LinkedServer.js.map +1 -1
  14. package/lib/esm/shapes/filestores/LocalFileStore.js.map +1 -1
  15. package/lib/esm/shapes/quadstores/BackendAPIStore.js.map +1 -1
  16. package/lib/esm/types/RouteConfig.js.map +1 -1
  17. package/lib/esm/types.js.map +1 -1
  18. package/lib/esm/utils/NodeQuadStore.js.map +1 -1
  19. package/lib/esm/utils/Shapes.js.map +1 -1
  20. package/lib/esm/utils/accessUrl.js.map +1 -1
  21. package/lib/esm/utils/bootstrapEntry.d.ts +30 -2
  22. package/lib/esm/utils/bootstrapEntry.js +32 -2
  23. package/lib/esm/utils/bootstrapEntry.js.map +1 -1
  24. package/lib/esm/utils/releaseManifest.js.map +1 -1
  25. package/lib/esm/utils/resizeSource.js.map +1 -1
  26. package/lib/esm/utils/resizedImagesPurpose.js.map +1 -1
  27. package/lib/esm/utils/routeAssets.js.map +1 -1
  28. package/lib/esm/utils/spaFallback.js.map +1 -1
  29. package/lib/esm/utils/ssrCss.d.ts +3 -0
  30. package/lib/esm/utils/ssrCss.js +48 -0
  31. package/lib/esm/utils/ssrCss.js.map +1 -0
  32. package/lib/esm/utils/syncShapes.js.map +1 -1
  33. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"accessUrl.js","sourceRoot":"","sources":["../../../src/utils/accessUrl.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,EAAE;IAC7C,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;AAC/B,CAAC,CAAC"}
1
+ {"version":3,"file":"accessUrl.js","sourceRoot":"","sources":["../../../src/utils/accessUrl.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,EAAE;IAC7C,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;AAC/B,CAAC,CAAC","sourcesContent":["/**\n * get access url for frontend to set FileStorage\n *\n * @returns frontend access url\n */\nexport const getAccessUrlLocalFileStore = () => {\n return process.env.SITE_ROOT;\n};\n"]}
@@ -30,8 +30,8 @@ export declare const resolveViteMainEntry: (manifest: BundleManifest) => ViteMan
30
30
  *
31
31
  * The build manifest is what actually separates the two. Once a manifest has
32
32
  * been loaded the built assets are on disk and must be used, `server.vite`
33
- * notwithstanding. Keep both call sites on this one function so they cannot
34
- * drift apart again.
33
+ * notwithstanding. Call it only through `resolveViteServingMode`, once per
34
+ * start, so the call sites cannot drift apart again.
35
35
  */
36
36
  export declare const isViteDevServer: ({ viteConfig, buildOutput, }: {
37
37
  /** `config.server.vite` — present whenever the app is a Vite app at all. */
@@ -43,6 +43,34 @@ export declare const isViteDevServer: ({ viteConfig, buildOutput, }: {
43
43
  */
44
44
  buildOutput: unknown;
45
45
  }) => boolean;
46
+ /**
47
+ * Decide, once per server start, whether pages are served by the live Vite
48
+ * dev server or from a `vite build` on disk — and read the build manifest
49
+ * only when it will actually be used.
50
+ *
51
+ * `linked start` attaches a live Vite dev server in every mode, so its
52
+ * presence alone cannot tell dev from a production start. A manifest on disk
53
+ * cannot either: `public/bundles/.vite/manifest.json` survives from any
54
+ * earlier `vite build`, and treating it as "not dev" made a development
55
+ * server link the stale built CSS while Vite injected the live styles. So in
56
+ * development with Vite attached the manifest is not read at all; everywhere
57
+ * else the answer is `isViteDevServer` over the manifest's entry, exactly as
58
+ * before.
59
+ *
60
+ * The result is stored and reused by the render path, so the `__viteDev`
61
+ * marker, the entry bootstrap and the route preloads cannot disagree.
62
+ */
63
+ export declare const resolveViteServingMode: ({ viteConfig, nodeEnv, readManifest, }: {
64
+ /** `config.server.vite` — the attached Vite dev server, if any. */
65
+ viteConfig: unknown;
66
+ /** `process.env.NODE_ENV` at start. */
67
+ nodeEnv: string | undefined;
68
+ /** Reads the build manifest; returns null when there is none. */
69
+ readManifest: () => BundleManifest | null;
70
+ }) => {
71
+ viteDevServer: boolean;
72
+ manifest: BundleManifest | null;
73
+ };
46
74
  /** The subset of `renderToPipeableStream` options that boots the client. */
47
75
  export interface BootstrapEntryOptions {
48
76
  bootstrapScriptContent?: string;
@@ -23,10 +23,40 @@ export const resolveViteMainEntry = (manifest) => {
23
23
  *
24
24
  * The build manifest is what actually separates the two. Once a manifest has
25
25
  * been loaded the built assets are on disk and must be used, `server.vite`
26
- * notwithstanding. Keep both call sites on this one function so they cannot
27
- * drift apart again.
26
+ * notwithstanding. Call it only through `resolveViteServingMode`, once per
27
+ * start, so the call sites cannot drift apart again.
28
28
  */
29
29
  export const isViteDevServer = ({ viteConfig, buildOutput, }) => !!viteConfig && !buildOutput;
30
+ /**
31
+ * Decide, once per server start, whether pages are served by the live Vite
32
+ * dev server or from a `vite build` on disk — and read the build manifest
33
+ * only when it will actually be used.
34
+ *
35
+ * `linked start` attaches a live Vite dev server in every mode, so its
36
+ * presence alone cannot tell dev from a production start. A manifest on disk
37
+ * cannot either: `public/bundles/.vite/manifest.json` survives from any
38
+ * earlier `vite build`, and treating it as "not dev" made a development
39
+ * server link the stale built CSS while Vite injected the live styles. So in
40
+ * development with Vite attached the manifest is not read at all; everywhere
41
+ * else the answer is `isViteDevServer` over the manifest's entry, exactly as
42
+ * before.
43
+ *
44
+ * The result is stored and reused by the render path, so the `__viteDev`
45
+ * marker, the entry bootstrap and the route preloads cannot disagree.
46
+ */
47
+ export const resolveViteServingMode = ({ viteConfig, nodeEnv, readManifest, }) => {
48
+ if (viteConfig && nodeEnv === 'development') {
49
+ return { viteDevServer: true, manifest: null };
50
+ }
51
+ const manifest = readManifest();
52
+ return {
53
+ viteDevServer: isViteDevServer({
54
+ viteConfig,
55
+ buildOutput: manifest ? resolveViteMainEntry(manifest) : null,
56
+ }),
57
+ manifest,
58
+ };
59
+ };
30
60
  /**
31
61
  * Vite dev-mode preamble. Vite middleware intercepts `/src/index.tsx` and
32
62
  * transforms+serves it; `/@vite/client` provides the HMR client.
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrapEntry.js","sourceRoot":"","sources":["../../../src/utils/bootstrapEntry.ts"],"names":[],"mappings":"AAaA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,QAAwB,EACE,EAAE;IAC5B,MAAM,KAAK,GACT,QAAQ,CAAC,eAAe,CAAC;QACzB,QAAQ,CAAC,cAAc,CAAC;QACxB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,OAAO,CAAC,CAAC;IACvD,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAE,KAA2B,CAAC,CAAC,CAAC,IAAI,CAAC;AAClF,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAC9B,UAAU,EACV,WAAW,GAUZ,EAAW,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,WAAW,CAAC;AAS5C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;;;;;;;;;eAS3B,CAAC;AAEhB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EACpC,aAAa,EACb,iBAAiB,EACjB,SAAS,GAQV,EAAyB,EAAE;IAC1B,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,CAAC;IAChE,CAAC;IACD,OAAO,iBAAiB;QACtB,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,SAAS,CAAC,EAAE;QACnC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;AACxC,CAAC,CAAC"}
1
+ {"version":3,"file":"bootstrapEntry.js","sourceRoot":"","sources":["../../../src/utils/bootstrapEntry.ts"],"names":[],"mappings":"AAaA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,QAAwB,EACE,EAAE;IAC5B,MAAM,KAAK,GACT,QAAQ,CAAC,eAAe,CAAC;QACzB,QAAQ,CAAC,cAAc,CAAC;QACxB,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,aAAD,CAAC,uBAAD,CAAC,CAAE,OAAO,CAAC,CAAC;IACvD,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAE,KAA2B,CAAC,CAAC,CAAC,IAAI,CAAC;AAClF,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAC9B,UAAU,EACV,WAAW,GAUZ,EAAW,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,WAAW,CAAC;AAE5C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,EACrC,UAAU,EACV,OAAO,EACP,YAAY,GAQb,EAA+D,EAAE;IAChE,IAAI,UAAU,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;QAC5C,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjD,CAAC;IACD,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;IAChC,OAAO;QACL,aAAa,EAAE,eAAe,CAAC;YAC7B,UAAU;YACV,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI;SAC9D,CAAC;QACF,QAAQ;KACT,CAAC;AACJ,CAAC,CAAC;AASF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;;;;;;;;;eAS3B,CAAC;AAEhB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EACpC,aAAa,EACb,iBAAiB,EACjB,SAAS,GAQV,EAAyB,EAAE;IAC1B,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,CAAC;IAChE,CAAC;IACD,OAAO,iBAAiB;QACtB,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,SAAS,CAAC,EAAE;QACnC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;AACxC,CAAC,CAAC","sourcesContent":["/**\n * Decide how the client entry is handed to `renderToPipeableStream`.\n *\n * React renders `bootstrapScripts` as a plain `<script src async>`. Vite always\n * emits the client entry as an ES module, so a production Vite build served\n * that way died on its first line with \"Cannot use import statement outside a\n * module\" and the app never hydrated. An entry that came out of a Vite\n * manifest therefore goes through `bootstrapModules` — the same tag with\n * `type=\"module\"` — while a legacy webpack bundle is a classic script and has\n * to keep `bootstrapScripts`.\n */\nimport type { BundleManifest, ViteManifestEntry } from './routeAssets.js';\n\n/**\n * The Vite manifest's client entry, or null when the manifest has none.\n *\n * Vite keys the entry by its source path; `isEntry` is the fallback for an app\n * whose entry does not sit at `src/index.*`.\n */\nexport const resolveViteMainEntry = (\n manifest: BundleManifest,\n): ViteManifestEntry | null => {\n const entry =\n manifest['src/index.tsx'] ||\n manifest['src/index.ts'] ||\n Object.values(manifest).find((e: any) => e?.isEntry);\n return entry && typeof entry === 'object' ? (entry as ViteManifestEntry) : null;\n};\n\n/**\n * Is a live Vite dev server serving this request?\n *\n * Two decisions hang off this answer — how the client entry is bootstrapped\n * (dev preamble vs. the built entry) and whether route preload tags are\n * emitted — and they have to agree. Asking `config.server.vite` alone is not\n * enough: a *production* Vite build can be run from a config that still\n * carries `server.vite`, and answering \"dev\" there hands the browser an\n * inline preamble importing `/@vite/client`, which does not exist in\n * production, so nothing hydrates.\n *\n * The build manifest is what actually separates the two. Once a manifest has\n * been loaded the built assets are on disk and must be used, `server.vite`\n * notwithstanding. Call it only through `resolveViteServingMode`, once per\n * start, so the call sites cannot drift apart again.\n */\nexport const isViteDevServer = ({\n viteConfig,\n buildOutput,\n}: {\n /** `config.server.vite` — present whenever the app is a Vite app at all. */\n viteConfig: unknown;\n /**\n * Evidence that `vite build` has run: the latest build manifest, or the\n * entry resolved out of it. Falsy means there is nothing built to serve,\n * which is the one thing only dev mode is true of.\n */\n buildOutput: unknown;\n}): boolean => !!viteConfig && !buildOutput;\n\n/**\n * Decide, once per server start, whether pages are served by the live Vite\n * dev server or from a `vite build` on disk — and read the build manifest\n * only when it will actually be used.\n *\n * `linked start` attaches a live Vite dev server in every mode, so its\n * presence alone cannot tell dev from a production start. A manifest on disk\n * cannot either: `public/bundles/.vite/manifest.json` survives from any\n * earlier `vite build`, and treating it as \"not dev\" made a development\n * server link the stale built CSS while Vite injected the live styles. So in\n * development with Vite attached the manifest is not read at all; everywhere\n * else the answer is `isViteDevServer` over the manifest's entry, exactly as\n * before.\n *\n * The result is stored and reused by the render path, so the `__viteDev`\n * marker, the entry bootstrap and the route preloads cannot disagree.\n */\nexport const resolveViteServingMode = ({\n viteConfig,\n nodeEnv,\n readManifest,\n}: {\n /** `config.server.vite` — the attached Vite dev server, if any. */\n viteConfig: unknown;\n /** `process.env.NODE_ENV` at start. */\n nodeEnv: string | undefined;\n /** Reads the build manifest; returns null when there is none. */\n readManifest: () => BundleManifest | null;\n}): { viteDevServer: boolean; manifest: BundleManifest | null } => {\n if (viteConfig && nodeEnv === 'development') {\n return { viteDevServer: true, manifest: null };\n }\n const manifest = readManifest();\n return {\n viteDevServer: isViteDevServer({\n viteConfig,\n buildOutput: manifest ? resolveViteMainEntry(manifest) : null,\n }),\n manifest,\n };\n};\n\n/** The subset of `renderToPipeableStream` options that boots the client. */\nexport interface BootstrapEntryOptions {\n bootstrapScriptContent?: string;\n bootstrapModules?: string[];\n bootstrapScripts?: string[];\n}\n\n/**\n * Vite dev-mode preamble. Vite middleware intercepts `/src/index.tsx` and\n * transforms+serves it; `/@vite/client` provides the HMR client.\n * `@vitejs/plugin-react` requires this preamble to define\n * `$RefreshReg$`/`$RefreshSig$` — without it the first React module throws\n * \"can't detect preamble\" and hydration blows up.\n */\nexport const VITE_DEV_BOOTSTRAP_CONTENT = `\n import(\"/@vite/client\");\n import(\"/@react-refresh\").then(RefreshRuntime => {\n RefreshRuntime.injectIntoGlobalHook(window);\n window.$RefreshReg$ = () => {};\n window.$RefreshSig$ = () => (type) => type;\n window.__vite_plugin_react_preamble_installed__ = true;\n return import(\"/src/index.tsx\");\n });\n `;\n\nexport const resolveBootstrapEntry = ({\n viteDevServer,\n mainEntryIsModule,\n mainEntry,\n}: {\n /** The Vite dev server is running, so it serves and transforms the entry. */\n viteDevServer: boolean;\n /** `mainEntry` was resolved from a Vite manifest, so it is an ES module. */\n mainEntryIsModule: boolean;\n /** URL of the built client entry. */\n mainEntry: string;\n}): BootstrapEntryOptions => {\n if (viteDevServer) {\n return { bootstrapScriptContent: VITE_DEV_BOOTSTRAP_CONTENT };\n }\n return mainEntryIsModule\n ? { bootstrapModules: [mainEntry] }\n : { bootstrapScripts: [mainEntry] };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"releaseManifest.js","sourceRoot":"","sources":["../../../src/utils/releaseManifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"releaseManifest.js","sourceRoot":"","sources":["../../../src/utils/releaseManifest.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Read the release manifest `@_linked/cli` writes next to the client bundle,\n * and work out which base URL the server should render its asset tags with.\n *\n * `linked build-app` (CLI >= 1.19) publishes every release under a versioned\n * key prefix (`releases/<version>-<revision>/…`) and records where it was built\n * for in `public/bundles/linked-release.json`. Before that manifest existed the\n * only way to point a running server at a published release was to set\n * `STATIC_ACCESS_URL` to `<accessURL>/<releasePrefix>` by hand — a value that\n * has to be edited on every release and that silently serves the wrong (or a\n * deleted) release when it drifts from what was actually published.\n *\n * Reading the manifest removes that step. Nothing here changes what a server\n * without a manifest does: every existing app keeps the exact behaviour it has.\n */\nimport * as fsNative from 'fs';\nimport path from 'path';\n\n/** Path of the manifest, relative to the app root. Set by `@_linked/cli`. */\nexport const RELEASE_MANIFEST_PATH = 'public/bundles/linked-release.json';\n\n/**\n * Manifest schema versions this server understands. An unknown version is\n * ignored rather than guessed at: a later schema may well move or redefine\n * `destination`, and serving assets from a misread URL breaks the whole app,\n * whereas ignoring it only costs the automatic base (the old manual\n * `STATIC_ACCESS_URL` still works).\n */\nexport const SUPPORTED_MANIFEST_SCHEMA_VERSIONS = [1];\n\n/** Directory `vite build` writes the client bundle to, as a URL suffix. */\nconst BUNDLE_URL_SUFFIX = '/public/bundles';\n\n/** Only the fields this server reads; the CLI owns the full type. */\nexport interface ReleaseManifestDestination {\n accessURL?: string;\n releasePrefix?: string;\n baseURL?: string;\n}\n\nexport interface ReleaseManifest {\n schemaVersion?: number;\n appName?: string;\n appVersion?: string;\n releaseId?: string;\n target?: string;\n publishable?: boolean;\n destination?: ReleaseManifestDestination;\n}\n\nconst trimTrailingSlashes = (value: string): string =>\n value.replace(/\\/+$/, '');\n\n/** A base URL is only usable if it is absolute — assets live on another host. */\nconst isAbsoluteURL = (value: string): boolean =>\n /^[a-z][a-z0-9+.-]*:\\/\\//i.test(value);\n\n/**\n * Read and validate the release manifest of the app rooted at `appRoot`.\n *\n * Returns `null` — never throws — when there is no manifest, when it cannot be\n * parsed, or when it is not a release this server can read. A broken manifest\n * must not stop a server from booting: falling back to the previous behaviour\n * is always safe, crashing never is.\n */\nexport const readReleaseManifest = (\n appRoot: string = process.cwd(),\n warn: (message: string) => void = console.warn,\n): ReleaseManifest | null => {\n const manifestPath = path.resolve(appRoot, RELEASE_MANIFEST_PATH);\n if (!fsNative.existsSync(manifestPath)) return null;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(fsNative.readFileSync(manifestPath, 'utf-8'));\n } catch (err) {\n warn(\n `[LinkedServer] ignoring unreadable release manifest at ${manifestPath}: ${\n (err as Error).message\n }`,\n );\n return null;\n }\n\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n warn(\n `[LinkedServer] ignoring release manifest at ${manifestPath}: expected a JSON object`,\n );\n return null;\n }\n\n const manifest = parsed as ReleaseManifest;\n if (!SUPPORTED_MANIFEST_SCHEMA_VERSIONS.includes(manifest.schemaVersion as number)) {\n warn(\n `[LinkedServer] ignoring release manifest at ${manifestPath}: unsupported schemaVersion ` +\n `${JSON.stringify(manifest.schemaVersion)} (this server reads ` +\n `${SUPPORTED_MANIFEST_SCHEMA_VERSIONS.join(', ')}). Set STATIC_ACCESS_URL to pick a release.`,\n );\n return null;\n }\n\n return manifest;\n};\n\n/**\n * The static access URL a manifest implies: the release's root on the store,\n * i.e. everything the server prefixes `/public/<asset>` with. `''` when the\n * manifest describes no published location.\n *\n * `destination.baseURL` is preferred because it is the literal value the client\n * bundle was built with as Vite's `base`, so deriving the server's tags from it\n * guarantees the entry tags and the bundle's own chunk URLs agree. It points at\n * the bundle directory, so the `/public/bundles` tail comes off again here.\n * `accessURL` + `releasePrefix` is the fallback for a manifest whose `baseURL`\n * is missing, empty (a Capacitor build writes `\"\"`) or shaped unexpectedly.\n */\nexport const releaseStaticAccessURL = (\n manifest: ReleaseManifest | null,\n): string => {\n const destination = manifest?.destination;\n if (!destination || typeof destination !== 'object') return '';\n\n const baseURL = trimTrailingSlashes(String(destination.baseURL || '').trim());\n if (baseURL && isAbsoluteURL(baseURL) && baseURL.endsWith(BUNDLE_URL_SUFFIX)) {\n return baseURL.slice(0, -BUNDLE_URL_SUFFIX.length);\n }\n\n const accessURL = trimTrailingSlashes(\n String(destination.accessURL || '').trim(),\n );\n const releasePrefix = String(destination.releasePrefix || '')\n .trim()\n .replace(/^\\/+|\\/+$/g, '');\n if (accessURL && isAbsoluteURL(accessURL) && releasePrefix) {\n return `${accessURL}/${releasePrefix}`;\n }\n\n // A Capacitor build ships its assets inside the native app: it records an\n // empty destination on purpose and must not influence the server's URLs.\n return '';\n};\n\nexport interface ResolveStaticAccessURLOptions {\n /** `true` in development, where Vite serves assets from the app's origin. */\n isDevAssets?: boolean;\n env?: NodeJS.ProcessEnv;\n /** The app root to look for the release manifest in. */\n appRoot?: string;\n /** Pre-read manifest; read from `appRoot` when omitted. */\n manifest?: ReleaseManifest | null;\n /** `LinkedFileStorage.accessURL` — today's last resort. */\n fileStoreAccessURL?: string;\n warn?: (message: string) => void;\n}\n\n/**\n * Resolve the base URL the server renders asset tags with, in this order:\n *\n * 1. development — always a relative path, so bundle URLs work on whatever port\n * the dev server bound to and Vite keeps serving the assets itself;\n * 2. `STATIC_ACCESS_URL` — an explicit deployment decision, and every existing\n * deployment that pins a release already sets it, so it has to keep winning;\n * 3. the release manifest's destination — the release this build was actually\n * published as;\n * 4. `LinkedFileStorage.accessURL`, then `''` — exactly what happened before.\n *\n * The returned value never has a trailing slash, so callers can append\n * `/public/<path>` to it.\n */\nexport const resolveStaticAccessURL = ({\n isDevAssets = false,\n env = process.env,\n appRoot = process.cwd(),\n manifest,\n fileStoreAccessURL,\n warn = console.warn,\n}: ResolveStaticAccessURLOptions = {}): string => {\n if (isDevAssets) return '';\n\n const explicit = String(env.STATIC_ACCESS_URL || '').trim();\n if (explicit) return trimTrailingSlashes(explicit);\n\n const resolvedManifest =\n manifest === undefined ? readReleaseManifest(appRoot, warn) : manifest;\n const fromRelease = releaseStaticAccessURL(resolvedManifest);\n if (fromRelease) return fromRelease;\n\n return trimTrailingSlashes(String(fileStoreAccessURL || '').trim());\n};\n\n/**\n * Build the URL of one asset under `public/`, the way the HTML entry tags do.\n * `assetPath` is app-relative and starts with a slash, e.g. `/bundles/main.js`.\n */\nexport const staticAssetURL = (\n staticAccessURL: string,\n assetPath: string,\n): string => `${trimTrailingSlashes(staticAccessURL)}/public${assetPath}`;\n\n/**\n * Build the URL of one file inside the client bundle directory.\n *\n * Vite manifest paths (`assets/Page-abc123.js`, and the entries of `css`) are\n * relative to the bundle directory — the same directory `vite build` writes to\n * and `linked build-app` hands Vite as its `base`. Everything the build emitted\n * therefore has to be addressed as `<base>/public/bundles/<path>`, exactly the\n * way the entry tags are, so a page never mixes the release host with the app's\n * own origin.\n */\nexport const bundleAssetURL = (\n staticAccessURL: string,\n bundlePath: string,\n): string =>\n staticAssetURL(staticAccessURL, `/bundles/${bundlePath.replace(/^\\/+/, '')}`);\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"resizeSource.js","sourceRoot":"","sources":["../../../src/utils/resizeSource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resizeSource.js","sourceRoot":"","sources":["../../../src/utils/resizeSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { publicUploadPath } from '@_linked/server-utils/utils/ServerPaths';\n\n/**\n * Deciding whether `/resized/*` is allowed to fetch a given `src`.\n *\n * The route used to hand `req.query.src` straight to `fetch`, which made every\n * deployment an open proxy into its own network: cloud metadata endpoints,\n * anything on localhost, anything on a private range. The fetched bytes were\n * then written into the *public* file store and the caller redirected to them,\n * so a reachable internal resource was not merely leaked but persisted.\n *\n * The rule now is the one the route always intended, and which the TODO in\n * `resizeImage` described: a `src` may only name an image this app already\n * stores. Everything else is refused before any request is made.\n */\n\n/** Why a `src` was refused. Kept separate from the message so callers can map it to a status. */\nexport type ResizeSourceRejection =\n | 'unparsable'\n | 'wrong-origin'\n | 'outside-store'\n | 'not-stored';\n\nexport interface ResizeSourceAllowed {\n allowed: true;\n /**\n * The key candidates to try against the store, in order.\n *\n * There is more than one because `IFileStore` has no URL-to-key inverse and\n * the two implementations do not agree on the shape. `S3FileStore` serves a\n * key directly under its `accessURL`, so the path *is* the key.\n * `LocalFileStore` serves `accessURL + '/uploads' + '/' + key`, so the same\n * derivation yields `uploads/photo.jpg` for a file stored as `photo.jpg`.\n *\n * Trying both costs one extra `fileExists` in the local case and keeps the\n * check fail-closed: a path that matches neither shape is refused.\n */\n keys: string[];\n /**\n * The URL to fetch: rebuilt from the validated origin and pathname, never the\n * caller's string. A validated string can still carry credentials, a query, a\n * fragment, or percent-encoding that resolves elsewhere, so reusing it would\n * hand back the control the check just took away.\n *\n * Built from the pathname rather than from a key, so it does not depend on\n * which key shape the store uses.\n */\n url: string;\n}\n\nexport interface ResizeSourceRefused {\n allowed: false;\n reason: ResizeSourceRejection;\n}\n\nexport type ResizeSourceDecision = ResizeSourceAllowed | ResizeSourceRefused;\n\n/**\n * The first candidate key the store actually holds, or null.\n *\n * Kept here rather than in the route so the two-shape detail stays in one\n * place with the comment that explains it.\n */\nexport async function findStoredKey(\n keys: string[],\n fileExists: (key: string) => Promise<boolean>\n): Promise<string | null> {\n for (const key of keys) {\n if (await fileExists(key)) {\n return key;\n }\n }\n return null;\n}\n\n/**\n * Work out the key a `src` refers to inside the store, or why it does not.\n *\n * Origin is compared on parsed URLs, never with `startsWith`: with a string\n * prefix, `https://cdn.example.com.evil.com/x.png` passes a check for\n * `https://cdn.example.com`. `URL.origin` folds in scheme, host and port, and\n * normalises the host, so it cannot be walked past that way.\n *\n * `accessURL` may carry a path (a bucket sub-path, or a CDN mounted under a\n * prefix). The key is what remains of the source's pathname after that prefix,\n * so a source outside the prefix is refused rather than silently resolving to a\n * key that climbs out of it.\n */\nexport function resolveResizeSource(\n src: string,\n accessURL: string | undefined\n): ResizeSourceDecision {\n if (!accessURL) {\n // No store configured means nothing can be proven to belong to it.\n return { allowed: false, reason: 'outside-store' };\n }\n\n let source: URL;\n let base: URL;\n try {\n source = new URL(src);\n base = new URL(accessURL);\n } catch {\n return { allowed: false, reason: 'unparsable' };\n }\n\n // Scheme is part of origin, so http:// is refused when the store is https://.\n // That is deliberate: a downgrade is a redirect target waiting to happen.\n if (source.origin !== base.origin || source.origin === 'null') {\n return { allowed: false, reason: 'wrong-origin' };\n }\n\n // Credentials never belong in a store URL, and `URL.origin` ignores them.\n if (source.username || source.password) {\n return { allowed: false, reason: 'wrong-origin' };\n }\n\n const basePath = trimTrailingSlash(base.pathname);\n const sourcePath = source.pathname;\n\n if (basePath && basePath !== '/') {\n if (\n sourcePath !== basePath &&\n !sourcePath.startsWith(basePath + '/')\n ) {\n return { allowed: false, reason: 'outside-store' };\n }\n }\n\n const relativePath = decodeURIComponent(\n sourcePath.slice(basePath === '/' ? 0 : basePath.length)\n ).replace(/^\\/+/, '');\n\n if (!relativePath || relativePath.includes('\\0')) {\n return { allowed: false, reason: 'outside-store' };\n }\n\n // `..` cannot escape the store through a URL pathname, because the URL parser\n // resolves it before we see it — but a key is also used to build a filesystem\n // path downstream, so refuse it rather than rely on that.\n if (relativePath.split('/').some((segment) => segment === '..')) {\n return { allowed: false, reason: 'outside-store' };\n }\n\n const keys = [relativePath];\n // LocalFileStore's public URL carries the upload mount that its keys do not.\n const localPrefix = publicUploadPath.replace(/^\\/+/, '') + '/';\n if (relativePath.startsWith(localPrefix)) {\n keys.push(relativePath.slice(localPrefix.length));\n }\n\n return {\n allowed: true,\n keys,\n url: `${trimTrailingSlash(base.origin + basePath)}/${relativePath\n .split('/')\n .map(encodeURIComponent)\n .join('/')}`,\n };\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.endsWith('/') ? value.slice(0, -1) : value;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"resizedImagesPurpose.js","sourceRoot":"","sources":["../../../src/utils/resizedImagesPurpose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAEpD;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB;IACnC,iBAAiB,CAAC,eAAe,CAAC,oBAAoB,EAAE;QACtD,WAAW,EACT,+GAA+G;KAClH,CAAC,CAAC;IACH,OAAO,iBAAiB,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAC1D,CAAC"}
1
+ {"version":3,"file":"resizedImagesPurpose.js","sourceRoot":"","sources":["../../../src/utils/resizedImagesPurpose.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC;AAEpD;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB;IACnC,iBAAiB,CAAC,eAAe,CAAC,oBAAoB,EAAE;QACtD,WAAW,EACT,+GAA+G;KAClH,CAAC,CAAC;IACH,OAAO,iBAAiB,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["import { LinkedFileStorage } from '@_linked/core/utils/LinkedFileStorage';\n\n/**\n * Where `/resized/*` keeps the derivatives it generates.\n *\n * A resize cache is not the same thing as user uploads, even though it has\n * always shared a folder with them. Uploads are the originals and must be kept;\n * derivatives are reproducible from those originals and can be dropped, rebuilt\n * or served from somewhere cheaper. Naming it separately lets an app make that\n * call rather than inheriting whatever the uploads store happens to be:\n *\n * ```ts\n * // keep originals in S3, but cache derivatives on the local disk\n * LinkedFileStorage.setStore(resizedImagesPurpose, new LocalFileStore('cache'));\n * ```\n *\n * Left alone it resolves to the default store, which is what the route did\n * before purposes existed — so nobody has to care unless they want to.\n *\n * The constant lives here rather than in core's `FileStorePurposes` because\n * core never writes a resized image; the package that owns the concept owns the\n * name.\n */\nexport const resizedImagesPurpose = 'resizedImages';\n\n/**\n * The store for resized derivatives.\n *\n * The purpose is registered here, at the point of use, rather than as a side\n * effect of importing this module. The registry is process-global and can be\n * cleared while the process lives — `LinkedFileStorage.resetForTests()` does\n * exactly that — and an unregistered purpose makes `getStore` throw, which in a\n * request handler surfaces as a hung request rather than an error. Registering\n * on the way past is idempotent and removes the ordering rule entirely.\n */\nexport function getResizedImagesStore() {\n LinkedFileStorage.registerPurpose(resizedImagesPurpose, {\n description:\n 'Resized image derivatives generated by GET /resized/*. Reproducible from the uploads store, so safe to clear.',\n });\n return LinkedFileStorage.getStore(resizedImagesPurpose);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"routeAssets.js","sourceRoot":"","sources":["../../../src/utils/routeAssets.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"routeAssets.js","sourceRoot":"","sources":["../../../src/utils/routeAssets.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Resolve the JS/CSS a matched route wants preloaded into URLs, on the same\n * base the entry tags (`main.js` / `main.css`) already use.\n *\n * Route chunks used to be emitted origin-relative (`/bundles/<file>`) while the\n * entry tags went through `staticAssetURL`. A release served from a file store\n * or CDN then produced a page that asked one host for its entry bundle and the\n * app server for its route chunks — the latter 404ing, since the server mounts\n * the bundle directory at `/public`. Both now compose through\n * `bundleAssetURL`, so every URL on the page points at the build that actually\n * produced the file.\n */\nimport { bundleAssetURL } from './releaseManifest.js';\n\n/** The fields this server reads from a Vite manifest entry. */\nexport interface ViteManifestEntry {\n file?: string;\n src?: string;\n css?: string[];\n isEntry?: boolean;\n}\n\n/**\n * A bundle manifest. Vite keys entries by source path and maps them to objects;\n * the legacy webpack manifest mapped output names to bare URL strings.\n */\nexport type BundleManifest = Record<string, string | ViteManifestEntry | unknown>;\n\nconst isAbsoluteURL = (value: string): boolean =>\n /^[a-z][a-z0-9+.-]*:\\/\\//i.test(value);\n\n/**\n * Last-resort match for a chunk name whose casing does not line up with the\n * manifest.\n *\n * Webpack named its chunks after the route (`home`, `signin`); Vite keys its\n * manifest by source path (`src/pages/Home.tsx`). An app carrying the old\n * lowercase `preloadChunks` therefore matched nothing at all. This compares the\n * file's basename case-insensitively, anchored on the path separator so\n * `Home` cannot be answered by `MyHome.tsx`.\n */\nconst caseInsensitiveEntryFor = (\n manifest: BundleManifest,\n chunkName: string,\n): ViteManifestEntry | null => {\n const lower = chunkName.toLowerCase();\n const entry = Object.values(manifest).find((e: any) => {\n const src = typeof e?.src === 'string' ? e.src.toLowerCase() : null;\n if (!src) return false;\n return ['tsx', 'ts'].some((ext) => {\n const name = `${lower}.${ext}`;\n return src === name || src.endsWith(`/${name}`);\n });\n });\n return entry && typeof entry === 'object' ? (entry as ViteManifestEntry) : null;\n};\n\n/**\n * Find the Vite manifest entry for a route chunk, by source path, by tail, or\n * — only once both of those miss — by a case-insensitive basename.\n */\nconst viteEntryFor = (\n manifest: BundleManifest,\n chunkName: string,\n): ViteManifestEntry | null => {\n const direct =\n manifest[`src/pages/${chunkName}.tsx`] || manifest[`src/pages/${chunkName}.ts`];\n const entry =\n direct ||\n Object.values(manifest).find(\n (e: any) =>\n e?.src?.endsWith(`${chunkName}.tsx`) || e?.src?.endsWith(`${chunkName}.ts`),\n );\n if (entry && typeof entry === 'object') return entry as ViteManifestEntry;\n return caseInsensitiveEntryFor(manifest, chunkName);\n};\n\n/**\n * Put a value taken from a webpack-shaped manifest on the asset base.\n *\n * Those values are already URL-ish (`/bundles/page.bundle.js`), so the bundle\n * directory prefix comes off again before `bundleAssetURL` puts the real one\n * back on. An entry that is already absolute names its own host and is left\n * alone.\n */\nconst webpackAssetURL = (value: string, staticAccessURL: string): string => {\n if (isAbsoluteURL(value)) return value;\n const bundleRelative = value.replace(/^\\/+/, '').replace(/^bundles\\//, '');\n return bundleAssetURL(staticAccessURL, bundleRelative);\n};\n\n/** Resolve a route chunk's script URL, or null when the manifest has none. */\nexport const resolveRouteScript = (\n manifest: BundleManifest,\n chunkName: string,\n staticAccessURL: string,\n): string | null => {\n const viteEntry = viteEntryFor(manifest, chunkName);\n if (viteEntry?.file) {\n return bundleAssetURL(staticAccessURL, viteEntry.file);\n }\n // Webpack shape: keyed by output name.\n const webpackEntry =\n manifest[`${chunkName}.js`] ||\n manifest[`${chunkName}.bundle.js`] ||\n manifest[`${chunkName}.mjs`];\n return typeof webpackEntry === 'string'\n ? webpackAssetURL(webpackEntry, staticAccessURL)\n : null;\n};\n\n/** Resolve a route chunk's stylesheet URLs. */\nexport const resolveRouteStyles = (\n manifest: BundleManifest,\n chunkName: string,\n staticAccessURL: string,\n): string[] => {\n const viteEntry = viteEntryFor(manifest, chunkName);\n if (viteEntry && Array.isArray(viteEntry.css)) {\n return viteEntry.css.map((css) => bundleAssetURL(staticAccessURL, css));\n }\n const webpackCss = manifest[`${chunkName}.css`];\n return typeof webpackCss === 'string'\n ? [webpackAssetURL(webpackCss, staticAccessURL)]\n : [];\n};\n\n/**\n * Chunk names already reported as unresolved.\n *\n * A route's `preloadChunks` are resolved on every render of that route, so a\n * name the manifest does not know would otherwise warn on every request. One\n * line per name is enough: the fix is in the app's source, not in this run.\n */\nconst warnedUnresolvedChunks = new Set<string>();\n\n/** Forget which chunk names have been warned about. For tests. */\nexport const resetUnresolvedChunkWarnings = (): void => {\n warnedUnresolvedChunks.clear();\n};\n\n/**\n * Say so when a declared preload chunk resolves to nothing.\n *\n * Silence here is what let an app ship webpack-era lowercase `preloadChunks`\n * against a Vite manifest and emit no preload tags at all, with nothing\n * visibly broken.\n */\nconst warnUnresolvedChunk = (chunkName: string): void => {\n if (warnedUnresolvedChunks.has(chunkName)) return;\n warnedUnresolvedChunks.add(chunkName);\n console.warn(\n `[routeAssets] preloadChunk \"${chunkName}\" matched nothing in the bundle manifest — ` +\n 'no preload tags will be emitted for it. Check that the name matches the ' +\n 'page source file (Vite manifest keys look like \"src/pages/Home.tsx\").',\n );\n};\n\n/** The preload URLs for every chunk a matched route asked for. */\nexport const resolveRouteAssets = (\n manifest: BundleManifest,\n chunkNames: string[],\n staticAccessURL: string,\n): { scripts: string[]; styles: string[] } => {\n const scripts: string[] = [];\n const styles: string[] = [];\n for (const chunkName of chunkNames) {\n const script = resolveRouteScript(manifest, chunkName, staticAccessURL);\n const chunkStyles = resolveRouteStyles(manifest, chunkName, staticAccessURL);\n if (script) scripts.push(script);\n styles.push(...chunkStyles);\n if (!script && chunkStyles.length === 0) warnUnresolvedChunk(chunkName);\n }\n return { scripts, styles };\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"spaFallback.js","sourceRoot":"","sources":["../../../src/utils/spaFallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AAE3D,SAAS,SAAS,CAAC,GAAQ;;IACzB,+EAA+E;IAC/E,OAAO,GAAG,IAAI,CAAC,MAAA,GAAG,CAAC,OAAO,mCAAI,GAAG,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAU;IACtC,OAAO,OAAO,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,CAAA,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,SAAS,QAAQ,CAAC,KAAY;IAC5B,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACrB,OAAO,CAAC,GAAG,CAAC,IAAI,oBAAoB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,CAAC,EAAE,CAAC;IACxD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAQ;;IACvC,MAAM,KAAK,GAAG,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAG,QAAQ,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,MAAM,KAAK,GAAG,MAAA,SAAS,CAAC,GAAG,CAAC,0CAAE,KAAK,CAAC;IACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO;IAElC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK;QAAE,OAAO,CAAC,sBAAsB;IAE/D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,CAAC,CAAC;QAAE,OAAO;IAExB,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACtB,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAQ,EAAE,GAAG,QAAe;;IAC7D,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC;IAE1B,MAAM,KAAK,GAAG,MAAA,SAAS,CAAC,GAAG,CAAC,0CAAE,KAAK,CAAC;IACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO;IACnD,GAAG,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAExC,kEAAkE;IAClE,gBAAgB,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC"}
1
+ {"version":3,"file":"spaFallback.js","sourceRoot":"","sources":["../../../src/utils/spaFallback.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;AAE3D,SAAS,SAAS,CAAC,GAAQ;;IACzB,+EAA+E;IAC/E,OAAO,GAAG,IAAI,CAAC,MAAA,GAAG,CAAC,OAAO,mCAAI,GAAG,CAAC,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAU;IACtC,OAAO,OAAO,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,CAAA,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,SAAS,QAAQ,CAAC,KAAY;IAC5B,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACrB,OAAO,CAAC,GAAG,CAAC,IAAI,oBAAoB,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAAE,CAAC,EAAE,CAAC;IACxD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAQ;;IACvC,MAAM,KAAK,GAAG,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAG,QAAQ,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,MAAM,KAAK,GAAG,MAAA,SAAS,CAAC,GAAG,CAAC,0CAAE,KAAK,CAAC;IACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO;IAElC,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK;QAAE,OAAO,CAAC,sBAAsB;IAE/D,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,CAAC,CAAC;QAAE,OAAO;IAExB,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACtB,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAQ,EAAE,GAAG,QAAe;;IAC7D,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,CAAC;IAE1B,MAAM,KAAK,GAAG,MAAA,SAAS,CAAC,GAAG,CAAC,0CAAE,KAAK,CAAC;IACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO;IACnD,GAAG,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAExC,kEAAkE;IAClE,gBAAgB,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC","sourcesContent":["/**\n * SPA-fallback ordering.\n *\n * `LinkedServer` serves the client shell from a catch-all `GET *` route. In\n * express a catch-all is only a \"fallback\" by accident of ORDER: it is the last\n * layer on the router stack, so everything registered earlier wins. Nothing\n * enforces that afterwards, and two supported code paths register routes after\n * the catch-all would otherwise exist:\n *\n * - `setupAfterControllers()` — a documented provider lifecycle hook which, by\n * definition, runs after the controllers are in place.\n * - HMR reloads — on a workspace source change the CLI's watcher calls\n * `LinkedServer.onSourceChange()`, which disposes the package's providers and\n * re-runs `setupBeforeControllers()`. `BackendProvider.disposeRoutes()`\n * SPLICES the provider's layers out of `router.stack`; `registerRoute()` can\n * only APPEND them back, so they land behind the catch-all.\n *\n * Only GET is affected (the catch-all is `GET *`) and the shadowed route still\n * answers `200`, just with an HTML body — which is why this reads as an\n * auth/config problem rather than a routing one. The response size is the tell.\n *\n * Ordering is enforced at REGISTRATION time, from the two places that create\n * the situation: `LinkedServer` installs the fallback after\n * `setupAfterControllers`, and re-pins it at the end of `onSourceChange`.\n * `repinSpaFallback` is therefore explicit rather than automatic — anything\n * that registers GET routes at some other moment must call it too.\n *\n * Re-pinning is safe to do here because it never runs while a registration is\n * in flight. `BackendProvider.registerRoute()` reads back `router.stack[i]` for\n * the indices its own `app[method](...)` call just appended, so moving layers\n * *inside* that window would make a provider capture the fallback's layer as\n * its own — and its next `disposeRoutes()` would delete the fallback outright.\n * Both call sites run after such a batch completes, never during one. (Note\n * also that `disposeRoutes` matches layers by object identity, not index, so\n * changing a layer's position never confuses disposal.)\n *\n * Trailing error-handling middleware (arity-4 handlers) is deliberately kept\n * BEHIND the fallback: express only reaches an error handler that comes after\n * the layer that failed, so pinning the fallback dead last would stop errors\n * thrown while rendering the shell from reaching the app's error handler.\n */\n\nconst FALLBACK = Symbol.for('@_linked/server.spaFallback');\n\nfunction getRouter(app: any): any {\n // express 4 exposes `_router` (lazily created); express 5 renames it `router`.\n return app && (app._router ?? app.router);\n}\n\nfunction isErrorHandlingLayer(layer: any): boolean {\n return typeof layer?.handle === 'function' && layer.handle.length === 4;\n}\n\n/**\n * Index the fallback should sit at: after every ordinary layer, but before the\n * contiguous run of error-handling middleware at the very end of the stack.\n */\nfunction pinIndex(stack: any[]): number {\n let i = stack.length;\n while (i > 0 && isErrorHandlingLayer(stack[i - 1])) i--;\n return i;\n}\n\n/**\n * Move the tracked SPA fallback back to the tail of the router stack (ahead of\n * any trailing error handlers). Call after registering routes late — notably\n * after an HMR dispose/re-register cycle.\n *\n * A no-op when no fallback is installed, when the fallback layer is no longer\n * on the stack (it was removed on purpose — don't resurrect it), or when it is\n * already in position.\n */\nexport function repinSpaFallback(app: any): void {\n const layer = app?.[FALLBACK];\n if (!layer) return;\n const stack = getRouter(app)?.stack;\n if (!Array.isArray(stack)) return;\n\n const target = pinIndex(stack);\n if (stack[target - 1] === layer) return; // already in position\n\n const from = stack.indexOf(layer);\n if (from === -1) return;\n\n stack.splice(from, 1);\n stack.splice(pinIndex(stack), 0, layer);\n}\n\n/**\n * Register the SPA catch-all and remember its layer so it can be re-pinned\n * later. Drop-in replacement for `app.get('*', handler)`.\n */\nexport function installSpaFallback(app: any, ...handlers: any[]): void {\n app.get('*', ...handlers);\n\n const stack = getRouter(app)?.stack;\n if (!Array.isArray(stack) || !stack.length) return;\n app[FALLBACK] = stack[stack.length - 1];\n\n // Ordinary layers may already sit behind trailing error handlers.\n repinSpaFallback(app);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export declare const ssrCssInlineUrls: (ids: Iterable<string>, { publicDir }?: {
2
+ publicDir?: string | false;
3
+ }) => string[];
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Which Vite module-graph ids the dev SSR inlines as CSS.
3
+ *
4
+ * In Vite dev, CSS reaches the browser through JS after hydration, so the
5
+ * server inlines what the graph already holds into `<style id="ssr-css">` to
6
+ * avoid an unstyled first paint. Each stylesheet is loaded as `<file>?inline`,
7
+ * which makes Vite return the processed CSS as a string default export.
8
+ *
9
+ * Not every `.css` id in the graph can be loaded that way:
10
+ *
11
+ * - `?direct` ids are added by Vite's transform middleware when a browser
12
+ * requests a stylesheet with `Accept: text/css` (a `<link>`). Loading one
13
+ * returns raw CSS, which the SSR transform then parses as JavaScript —
14
+ * "Parse failure: Expected ';', '}' or <eof>".
15
+ * - Files under Vite's `publicDir` are served verbatim and are not part of
16
+ * the app's styles; a stale production bundle under `public/bundles/` is
17
+ * the usual one.
18
+ * - `?inline` (our own loads), `?raw` and `?url` ids are not stylesheets.
19
+ *
20
+ * The same file also appears under several ids (with and without a query,
21
+ * or once per graph), so ids are reduced to their file and each file is
22
+ * loaded once, in first-seen order to keep the cascade order.
23
+ */
24
+ const NON_STYLESHEET_QUERY = ['inline', 'direct', 'raw', 'url'];
25
+ export const ssrCssInlineUrls = (ids, { publicDir } = {}) => {
26
+ const publicPrefix = publicDir ? publicDir.replace(/\/+$/, '') + '/' : null;
27
+ const seen = new Set();
28
+ const urls = [];
29
+ for (const id of ids) {
30
+ const queryAt = id.indexOf('?');
31
+ const file = queryAt === -1 ? id : id.slice(0, queryAt);
32
+ if (!file.endsWith('.css'))
33
+ continue;
34
+ if (queryAt !== -1) {
35
+ const params = new URLSearchParams(id.slice(queryAt + 1));
36
+ if (NON_STYLESHEET_QUERY.some((key) => params.has(key)))
37
+ continue;
38
+ }
39
+ if (publicPrefix && file.startsWith(publicPrefix))
40
+ continue;
41
+ if (seen.has(file))
42
+ continue;
43
+ seen.add(file);
44
+ urls.push(file + '?inline');
45
+ }
46
+ return urls;
47
+ };
48
+ //# sourceMappingURL=ssrCss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrCss.js","sourceRoot":"","sources":["../../../src/utils/ssrCss.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAEhE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,GAAqB,EACrB,EAAE,SAAS,KAAqC,EAAE,EACxC,EAAE;IACZ,MAAM,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5E,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,SAAS;QACrC,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;YAC1D,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAAE,SAAS;QACpE,CAAC;QACD,IAAI,YAAY,IAAI,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;YAAE,SAAS;QAC5D,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC","sourcesContent":["/**\n * Which Vite module-graph ids the dev SSR inlines as CSS.\n *\n * In Vite dev, CSS reaches the browser through JS after hydration, so the\n * server inlines what the graph already holds into `<style id=\"ssr-css\">` to\n * avoid an unstyled first paint. Each stylesheet is loaded as `<file>?inline`,\n * which makes Vite return the processed CSS as a string default export.\n *\n * Not every `.css` id in the graph can be loaded that way:\n *\n * - `?direct` ids are added by Vite's transform middleware when a browser\n * requests a stylesheet with `Accept: text/css` (a `<link>`). Loading one\n * returns raw CSS, which the SSR transform then parses as JavaScript —\n * \"Parse failure: Expected ';', '}' or <eof>\".\n * - Files under Vite's `publicDir` are served verbatim and are not part of\n * the app's styles; a stale production bundle under `public/bundles/` is\n * the usual one.\n * - `?inline` (our own loads), `?raw` and `?url` ids are not stylesheets.\n *\n * The same file also appears under several ids (with and without a query,\n * or once per graph), so ids are reduced to their file and each file is\n * loaded once, in first-seen order to keep the cascade order.\n */\nconst NON_STYLESHEET_QUERY = ['inline', 'direct', 'raw', 'url'];\n\nexport const ssrCssInlineUrls = (\n ids: Iterable<string>,\n { publicDir }: { publicDir?: string | false } = {},\n): string[] => {\n const publicPrefix = publicDir ? publicDir.replace(/\\/+$/, '') + '/' : null;\n const seen = new Set<string>();\n const urls: string[] = [];\n for (const id of ids) {\n const queryAt = id.indexOf('?');\n const file = queryAt === -1 ? id : id.slice(0, queryAt);\n if (!file.endsWith('.css')) continue;\n if (queryAt !== -1) {\n const params = new URLSearchParams(id.slice(queryAt + 1));\n if (NON_STYLESHEET_QUERY.some((key) => params.has(key))) continue;\n }\n if (publicPrefix && file.startsWith(publicPrefix)) continue;\n if (seen.has(file)) continue;\n seen.add(file);\n urls.push(file + '?inline');\n }\n return urls;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"syncShapes.js","sourceRoot":"","sources":["../../../src/utils/syncShapes.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"syncShapes.js","sourceRoot":"","sources":["../../../src/utils/syncShapes.ts"],"names":[],"mappings":"","sourcesContent":[""]}
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "type": "git",
11
11
  "url": "git+https://github.com/linked-fw/server.git"
12
12
  },
13
- "version": "2.14.0",
13
+ "version": "2.14.1",
14
14
  "packageManager": "npm@11.19.1",
15
15
  "linkedPackage": true,
16
16
  "type": "module",