@funstack/static 0.0.1-alpha.0 → 0.0.2-alpha.0

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 (99) hide show
  1. package/LICENSE +21 -0
  2. package/dist/build/buildApp.mjs +34 -0
  3. package/dist/build/buildApp.mjs.map +1 -0
  4. package/dist/build/contentHash.mjs +14 -0
  5. package/dist/build/contentHash.mjs.map +1 -0
  6. package/dist/build/dependencyGraph.mjs +46 -0
  7. package/dist/build/dependencyGraph.mjs.map +1 -0
  8. package/dist/build/rscPath.mjs +17 -0
  9. package/dist/build/rscPath.mjs.map +1 -0
  10. package/dist/build/rscProcessor.mjs +66 -0
  11. package/dist/build/rscProcessor.mjs.map +1 -0
  12. package/dist/client/entry.mjs +53 -0
  13. package/dist/client/entry.mjs.map +1 -0
  14. package/dist/client/error-boundary.mjs +48 -0
  15. package/dist/client/error-boundary.mjs.map +1 -0
  16. package/dist/client/globals.mjs +10 -0
  17. package/dist/client/globals.mjs.map +1 -0
  18. package/dist/entries/client.d.mts +1 -0
  19. package/dist/entries/client.mjs +3 -0
  20. package/dist/entries/rsc-client.d.mts +3 -0
  21. package/dist/entries/rsc-client.mjs +6 -0
  22. package/dist/entries/rsc.d.mts +3 -0
  23. package/dist/entries/rsc.mjs +4 -0
  24. package/dist/entries/server.d.mts +2 -0
  25. package/dist/entries/server.mjs +3 -0
  26. package/dist/entries/ssr.d.mts +2 -0
  27. package/dist/entries/ssr.mjs +3 -0
  28. package/dist/index.d.mts +2 -30
  29. package/dist/index.mjs +2 -6082
  30. package/dist/plugin/getRSCEntryPoint.mjs +16 -0
  31. package/dist/plugin/getRSCEntryPoint.mjs.map +1 -0
  32. package/dist/plugin/index.d.mts +30 -0
  33. package/dist/plugin/index.d.mts.map +1 -0
  34. package/dist/plugin/index.mjs +61 -0
  35. package/dist/plugin/index.mjs.map +1 -0
  36. package/dist/plugin/server.mjs +64 -0
  37. package/dist/plugin/server.mjs.map +1 -0
  38. package/dist/rsc/defer.d.mts +50 -0
  39. package/dist/rsc/defer.d.mts.map +1 -0
  40. package/dist/rsc/defer.mjs +124 -0
  41. package/dist/rsc/defer.mjs.map +1 -0
  42. package/dist/rsc/entry.d.mts +30 -0
  43. package/dist/rsc/entry.d.mts.map +1 -0
  44. package/dist/rsc/entry.mjs +94 -0
  45. package/dist/rsc/entry.mjs.map +1 -0
  46. package/dist/rsc/marker.mjs +15 -0
  47. package/dist/rsc/marker.mjs.map +1 -0
  48. package/dist/rsc/request.mjs +9 -0
  49. package/dist/rsc/request.mjs.map +1 -0
  50. package/dist/rsc/rscModule.mjs +25 -0
  51. package/dist/rsc/rscModule.mjs.map +1 -0
  52. package/dist/rsc-client/clientWrapper.d.mts +12 -0
  53. package/dist/rsc-client/clientWrapper.d.mts.map +1 -0
  54. package/dist/rsc-client/clientWrapper.mjs +44 -0
  55. package/dist/rsc-client/clientWrapper.mjs.map +1 -0
  56. package/dist/rsc-client/entry.d.mts +1 -0
  57. package/dist/rsc-client/entry.mjs +5 -0
  58. package/dist/ssr/entry.d.mts +15 -0
  59. package/dist/ssr/entry.d.mts.map +1 -0
  60. package/dist/ssr/entry.mjs +53 -0
  61. package/dist/ssr/entry.mjs.map +1 -0
  62. package/dist/util/basePath.mjs +28 -0
  63. package/dist/util/basePath.mjs.map +1 -0
  64. package/dist/util/drainStream.mjs +12 -0
  65. package/dist/util/drainStream.mjs.map +1 -0
  66. package/package.json +22 -7
  67. package/dist/build-BhjMQ5b5.mjs +0 -5
  68. package/dist/build2-BFobw-wK.mjs +0 -5269
  69. package/dist/build2-BFobw-wK.mjs.map +0 -1
  70. package/dist/chunk-CVYhg9ik.mjs +0 -45
  71. package/dist/chunk-ezxmLbPQ-BTJgBwYB.mjs +0 -29
  72. package/dist/chunk-ezxmLbPQ-BTJgBwYB.mjs.map +0 -1
  73. package/dist/chunk-yG6w5hYl.mjs +0 -41
  74. package/dist/chunk-yG6w5hYl.mjs.map +0 -1
  75. package/dist/config-ChWWLT6T.mjs +0 -41331
  76. package/dist/config-ChWWLT6T.mjs.map +0 -1
  77. package/dist/dist-CijqjcI1.mjs +0 -6699
  78. package/dist/dist-CijqjcI1.mjs.map +0 -1
  79. package/dist/false-CW0Ab7Sy.mjs +0 -6
  80. package/dist/false-CW0Ab7Sy.mjs.map +0 -1
  81. package/dist/false-CoaQMKhH.mjs +0 -3
  82. package/dist/index.d.mts.map +0 -1
  83. package/dist/index.mjs.map +0 -1
  84. package/dist/lib-BY2rcZzh.mjs +0 -366
  85. package/dist/lib-BY2rcZzh.mjs.map +0 -1
  86. package/dist/node-entry-Elsz8XBx.mjs +0 -18443
  87. package/dist/node-entry-Elsz8XBx.mjs.map +0 -1
  88. package/dist/parseAst-C9pD5vU6.mjs +0 -2109
  89. package/dist/parseAst-C9pD5vU6.mjs.map +0 -1
  90. package/dist/picocolors-BxaHL81J-CyL9Yrra.mjs +0 -74
  91. package/dist/picocolors-BxaHL81J-CyL9Yrra.mjs.map +0 -1
  92. package/dist/postcss-CQ0jlpM-.mjs +0 -5439
  93. package/dist/postcss-CQ0jlpM-.mjs.map +0 -1
  94. package/dist/postcss-import-D8PxJXZF.mjs +0 -452
  95. package/dist/postcss-import-D8PxJXZF.mjs.map +0 -1
  96. package/dist/rollup-Cs2z7Zqk.mjs +0 -9
  97. package/dist/rollup-Cs2z7Zqk.mjs.map +0 -1
  98. package/dist/watch-70G_ECVN.mjs +0 -7044
  99. package/dist/watch-70G_ECVN.mjs.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 uhyo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,34 @@
1
+ import { getModulePathFor } from "../rsc/rscModule.mjs";
2
+ import { getRscPayloadPath, rscPayloadPlaceholder } from "./rscPath.mjs";
3
+ import { drainStream } from "../util/drainStream.mjs";
4
+ import { computeContentHash } from "./contentHash.mjs";
5
+ import { processRscComponents } from "./rscProcessor.mjs";
6
+ import path from "node:path";
7
+ import { mkdir, writeFile } from "node:fs/promises";
8
+ import { pathToFileURL } from "node:url";
9
+
10
+ //#region src/build/buildApp.ts
11
+ async function buildApp(builder, context) {
12
+ const { config } = builder;
13
+ const entry = await import(pathToFileURL(path.join(config.environments.rsc.build.outDir, "index.js")).href);
14
+ const baseDir = config.environments.client.build.outDir;
15
+ const { html, appRsc, deferRegistry } = await entry.build();
16
+ const htmlContent = await drainStream(html);
17
+ const { components, appRscContent } = await processRscComponents(deferRegistry.loadAll(), appRsc, context);
18
+ const mainPayloadHash = await computeContentHash(appRscContent);
19
+ const base = config.base.endsWith("/") ? config.base.slice(0, -1) : config.base;
20
+ const mainPayloadPath = base === "/" ? getRscPayloadPath(mainPayloadHash) : base + getRscPayloadPath(mainPayloadHash);
21
+ const finalHtmlContent = htmlContent.replaceAll(rscPayloadPlaceholder, mainPayloadPath);
22
+ await writeFileNormal(path.join(baseDir, "index.html"), finalHtmlContent, context);
23
+ await writeFileNormal(path.join(baseDir, getRscPayloadPath(mainPayloadHash).replace(/^\//, "")), appRscContent, context);
24
+ for (const { finalId, finalContent } of components) await writeFileNormal(path.join(baseDir, getModulePathFor(finalId).replace(/^\//, "")), finalContent, context);
25
+ }
26
+ async function writeFileNormal(filePath, data, context) {
27
+ await mkdir(path.dirname(filePath), { recursive: true });
28
+ context.info(`[funstack] Writing ${filePath}`);
29
+ await writeFile(filePath, data);
30
+ }
31
+
32
+ //#endregion
33
+ export { buildApp };
34
+ //# sourceMappingURL=buildApp.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildApp.mjs","names":[],"sources":["../../src/build/buildApp.ts"],"sourcesContent":["import { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { ViteBuilder, MinimalPluginContextWithoutEnvironment } from \"vite\";\nimport { rscPayloadPlaceholder, getRscPayloadPath } from \"./rscPath\";\nimport { getModulePathFor } from \"../rsc/rscModule\";\nimport { processRscComponents } from \"./rscProcessor\";\nimport { computeContentHash } from \"./contentHash\";\nimport { drainStream } from \"../util/drainStream\";\n\nexport async function buildApp(\n builder: ViteBuilder,\n context: MinimalPluginContextWithoutEnvironment,\n) {\n const { config } = builder;\n // import server entry\n const entryPath = path.join(config.environments.rsc.build.outDir, \"index.js\");\n const entry: typeof import(\"../rsc/entry\") = await import(\n pathToFileURL(entryPath).href\n );\n\n // render rsc and html\n const baseDir = config.environments.client.build.outDir;\n const { html, appRsc, deferRegistry } = await entry.build();\n\n // Drain HTML stream to string (needed for placeholder replacement later)\n const htmlContent = await drainStream(html);\n\n // Process RSC components with content-based hashes for deterministic file names\n const { components, appRscContent } = await processRscComponents(\n deferRegistry.loadAll(),\n appRsc,\n context,\n );\n\n // Compute hash for main RSC payload and apply base path\n const mainPayloadHash = await computeContentHash(appRscContent);\n const base = config.base.endsWith(\"/\")\n ? config.base.slice(0, -1)\n : config.base;\n const mainPayloadPath =\n base === \"/\"\n ? getRscPayloadPath(mainPayloadHash)\n : base + getRscPayloadPath(mainPayloadHash);\n\n // Replace placeholder with final hashed path (including base path)\n const finalHtmlContent = htmlContent.replaceAll(\n rscPayloadPlaceholder,\n mainPayloadPath,\n );\n\n // Write HTML with replaced path\n await writeFileNormal(\n path.join(baseDir, \"index.html\"),\n finalHtmlContent,\n context,\n );\n\n // Write main RSC payload with hashed filename\n await writeFileNormal(\n path.join(baseDir, getRscPayloadPath(mainPayloadHash).replace(/^\\//, \"\")),\n appRscContent,\n context,\n );\n\n // Write processed components with hash-based IDs\n for (const { finalId, finalContent } of components) {\n const filePath = path.join(\n baseDir,\n getModulePathFor(finalId).replace(/^\\//, \"\"),\n );\n await writeFileNormal(filePath, finalContent, context);\n }\n}\n\nasync function writeFileNormal(\n filePath: string,\n data: string,\n context: MinimalPluginContextWithoutEnvironment,\n) {\n await mkdir(path.dirname(filePath), { recursive: true });\n context.info(`[funstack] Writing ${filePath}`);\n await writeFile(filePath, data);\n}\n"],"mappings":";;;;;;;;;;AAUA,eAAsB,SACpB,SACA,SACA;CACA,MAAM,EAAE,WAAW;CAGnB,MAAM,QAAuC,MAAM,OACjD,cAFgB,KAAK,KAAK,OAAO,aAAa,IAAI,MAAM,QAAQ,WAAW,CAEnD,CAAC;CAI3B,MAAM,UAAU,OAAO,aAAa,OAAO,MAAM;CACjD,MAAM,EAAE,MAAM,QAAQ,kBAAkB,MAAM,MAAM,OAAO;CAG3D,MAAM,cAAc,MAAM,YAAY,KAAK;CAG3C,MAAM,EAAE,YAAY,kBAAkB,MAAM,qBAC1C,cAAc,SAAS,EACvB,QACA,QACD;CAGD,MAAM,kBAAkB,MAAM,mBAAmB,cAAc;CAC/D,MAAM,OAAO,OAAO,KAAK,SAAS,IAAI,GAClC,OAAO,KAAK,MAAM,GAAG,GAAG,GACxB,OAAO;CACX,MAAM,kBACJ,SAAS,MACL,kBAAkB,gBAAgB,GAClC,OAAO,kBAAkB,gBAAgB;CAG/C,MAAM,mBAAmB,YAAY,WACnC,uBACA,gBACD;AAGD,OAAM,gBACJ,KAAK,KAAK,SAAS,aAAa,EAChC,kBACA,QACD;AAGD,OAAM,gBACJ,KAAK,KAAK,SAAS,kBAAkB,gBAAgB,CAAC,QAAQ,OAAO,GAAG,CAAC,EACzE,eACA,QACD;AAGD,MAAK,MAAM,EAAE,SAAS,kBAAkB,WAKtC,OAAM,gBAJW,KAAK,KACpB,SACA,iBAAiB,QAAQ,CAAC,QAAQ,OAAO,GAAG,CAC7C,EAC+B,cAAc,QAAQ;;AAI1D,eAAe,gBACb,UACA,MACA,SACA;AACA,OAAM,MAAM,KAAK,QAAQ,SAAS,EAAE,EAAE,WAAW,MAAM,CAAC;AACxD,SAAQ,KAAK,sBAAsB,WAAW;AAC9C,OAAM,UAAU,UAAU,KAAK"}
@@ -0,0 +1,14 @@
1
+ //#region src/build/contentHash.ts
2
+ /**
3
+ * Computes a SHA-256 hash of the given content and returns the first 16 hex characters.
4
+ * 16 hex chars = 64 bits, which provides sufficient uniqueness for our use case.
5
+ */
6
+ async function computeContentHash(content) {
7
+ const data = new TextEncoder().encode(content);
8
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
9
+ return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 16);
10
+ }
11
+
12
+ //#endregion
13
+ export { computeContentHash };
14
+ //# sourceMappingURL=contentHash.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contentHash.mjs","names":[],"sources":["../../src/build/contentHash.ts"],"sourcesContent":["/**\n * Computes a SHA-256 hash of the given content and returns the first 16 hex characters.\n * 16 hex chars = 64 bits, which provides sufficient uniqueness for our use case.\n */\nexport async function computeContentHash(content: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(content);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n const hashHex = hashArray\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n return hashHex.slice(0, 16);\n}\n"],"mappings":";;;;;AAIA,eAAsB,mBAAmB,SAAkC;CAEzE,MAAM,OADU,IAAI,aAAa,CACZ,OAAO,QAAQ;CACpC,MAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,KAAK;AAK9D,QAJkB,MAAM,KAAK,IAAI,WAAW,WAAW,CAAC,CAErD,KAAK,MAAM,EAAE,SAAS,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,CAC3C,KAAK,GAAG,CACI,MAAM,GAAG,GAAG"}
@@ -0,0 +1,46 @@
1
+ //#region src/build/dependencyGraph.ts
2
+ /**
3
+ * Finds which IDs from the known set are referenced in the given content.
4
+ */
5
+ function findReferencedIds(content, allKnownIds) {
6
+ const referenced = /* @__PURE__ */ new Set();
7
+ for (const id of allKnownIds) if (content.includes(id)) referenced.add(id);
8
+ return referenced;
9
+ }
10
+ /**
11
+ * Performs topological sort using Kahn's algorithm.
12
+ * Returns both the sorted nodes and any nodes that are part of cycles.
13
+ *
14
+ * @param dependencies - Map of node ID to the set of IDs it depends on (references)
15
+ */
16
+ function topologicalSort(dependencies) {
17
+ const allNodes = new Set(dependencies.keys());
18
+ const inDegree = /* @__PURE__ */ new Map();
19
+ for (const node of allNodes) inDegree.set(node, 0);
20
+ for (const [_node, deps] of dependencies) for (const dep of deps) if (allNodes.has(dep)) inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);
21
+ const queue = [];
22
+ for (const [node, degree] of inDegree) if (degree === 0) queue.push(node);
23
+ const sorted = [];
24
+ while (queue.length > 0) {
25
+ const node = queue.shift();
26
+ sorted.push(node);
27
+ const deps = dependencies.get(node);
28
+ if (deps) {
29
+ for (const dep of deps) if (allNodes.has(dep)) {
30
+ const newDegree = (inDegree.get(dep) ?? 1) - 1;
31
+ inDegree.set(dep, newDegree);
32
+ if (newDegree === 0) queue.push(dep);
33
+ }
34
+ }
35
+ }
36
+ const inCycle = [];
37
+ for (const node of allNodes) if (!sorted.includes(node)) inCycle.push(node);
38
+ return {
39
+ sorted,
40
+ inCycle
41
+ };
42
+ }
43
+
44
+ //#endregion
45
+ export { findReferencedIds, topologicalSort };
46
+ //# sourceMappingURL=dependencyGraph.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencyGraph.mjs","names":[],"sources":["../../src/build/dependencyGraph.ts"],"sourcesContent":["/**\n * Result of topological sort.\n */\nexport interface SortResult {\n /** Components that can be processed in dependency order */\n sorted: string[];\n /** Components stuck in cycles (cannot determine stable order) */\n inCycle: string[];\n}\n\n/**\n * Finds which IDs from the known set are referenced in the given content.\n */\nexport function findReferencedIds(\n content: string,\n allKnownIds: Set<string>,\n): Set<string> {\n const referenced = new Set<string>();\n for (const id of allKnownIds) {\n if (content.includes(id)) {\n referenced.add(id);\n }\n }\n return referenced;\n}\n\n/**\n * Performs topological sort using Kahn's algorithm.\n * Returns both the sorted nodes and any nodes that are part of cycles.\n *\n * @param dependencies - Map of node ID to the set of IDs it depends on (references)\n */\nexport function topologicalSort(\n dependencies: Map<string, Set<string>>,\n): SortResult {\n const allNodes = new Set(dependencies.keys());\n\n // Calculate in-degree for each node (how many other nodes reference it)\n const inDegree = new Map<string, number>();\n for (const node of allNodes) {\n inDegree.set(node, 0);\n }\n\n for (const [_node, deps] of dependencies) {\n for (const dep of deps) {\n if (allNodes.has(dep)) {\n inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);\n }\n }\n }\n\n // Start with nodes that have in-degree 0 (no one references them)\n const queue: string[] = [];\n for (const [node, degree] of inDegree) {\n if (degree === 0) {\n queue.push(node);\n }\n }\n\n const sorted: string[] = [];\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n sorted.push(node);\n\n // Decrement in-degree of nodes this node depends on\n const deps = dependencies.get(node);\n if (deps) {\n for (const dep of deps) {\n if (allNodes.has(dep)) {\n const newDegree = (inDegree.get(dep) ?? 1) - 1;\n inDegree.set(dep, newDegree);\n if (newDegree === 0) {\n queue.push(dep);\n }\n }\n }\n }\n }\n\n // Nodes not in sorted result are part of cycles\n const inCycle: string[] = [];\n for (const node of allNodes) {\n if (!sorted.includes(node)) {\n inCycle.push(node);\n }\n }\n\n return { sorted, inCycle };\n}\n"],"mappings":";;;;AAaA,SAAgB,kBACd,SACA,aACa;CACb,MAAM,6BAAa,IAAI,KAAa;AACpC,MAAK,MAAM,MAAM,YACf,KAAI,QAAQ,SAAS,GAAG,CACtB,YAAW,IAAI,GAAG;AAGtB,QAAO;;;;;;;;AAST,SAAgB,gBACd,cACY;CACZ,MAAM,WAAW,IAAI,IAAI,aAAa,MAAM,CAAC;CAG7C,MAAM,2BAAW,IAAI,KAAqB;AAC1C,MAAK,MAAM,QAAQ,SACjB,UAAS,IAAI,MAAM,EAAE;AAGvB,MAAK,MAAM,CAAC,OAAO,SAAS,aAC1B,MAAK,MAAM,OAAO,KAChB,KAAI,SAAS,IAAI,IAAI,CACnB,UAAS,IAAI,MAAM,SAAS,IAAI,IAAI,IAAI,KAAK,EAAE;CAMrD,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,CAAC,MAAM,WAAW,SAC3B,KAAI,WAAW,EACb,OAAM,KAAK,KAAK;CAIpB,MAAM,SAAmB,EAAE;AAE3B,QAAO,MAAM,SAAS,GAAG;EACvB,MAAM,OAAO,MAAM,OAAO;AAC1B,SAAO,KAAK,KAAK;EAGjB,MAAM,OAAO,aAAa,IAAI,KAAK;AACnC,MAAI,MACF;QAAK,MAAM,OAAO,KAChB,KAAI,SAAS,IAAI,IAAI,EAAE;IACrB,MAAM,aAAa,SAAS,IAAI,IAAI,IAAI,KAAK;AAC7C,aAAS,IAAI,KAAK,UAAU;AAC5B,QAAI,cAAc,EAChB,OAAM,KAAK,IAAI;;;;CAQzB,MAAM,UAAoB,EAAE;AAC5B,MAAK,MAAM,QAAQ,SACjB,KAAI,CAAC,OAAO,SAAS,KAAK,CACxB,SAAQ,KAAK,KAAK;AAItB,QAAO;EAAE;EAAQ;EAAS"}
@@ -0,0 +1,17 @@
1
+ import { getModulePathFor, getPayloadIDFor } from "../rsc/rscModule.mjs";
2
+
3
+ //#region src/build/rscPath.ts
4
+ /**
5
+ * Placeholder used during SSR (will be replaced after hash is computed)
6
+ */
7
+ const rscPayloadPlaceholder = "__FUNSTACK_RSC_PAYLOAD_PATH__";
8
+ /**
9
+ * Generate final path from content hash (reuses same folder as deferred payloads)
10
+ */
11
+ function getRscPayloadPath(contentHash) {
12
+ return getModulePathFor(getPayloadIDFor(contentHash));
13
+ }
14
+
15
+ //#endregion
16
+ export { getRscPayloadPath, rscPayloadPlaceholder };
17
+ //# sourceMappingURL=rscPath.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rscPath.mjs","names":[],"sources":["../../src/build/rscPath.ts"],"sourcesContent":["import { getModulePathFor, getPayloadIDFor } from \"../rsc/rscModule\";\n\n/**\n * Placeholder used during SSR (will be replaced after hash is computed)\n */\nexport const rscPayloadPlaceholder = \"__FUNSTACK_RSC_PAYLOAD_PATH__\";\n\n/**\n * Generate final path from content hash (reuses same folder as deferred payloads)\n */\nexport function getRscPayloadPath(contentHash: string): string {\n return getModulePathFor(getPayloadIDFor(contentHash));\n}\n"],"mappings":";;;;;;AAKA,MAAa,wBAAwB;;;;AAKrC,SAAgB,kBAAkB,aAA6B;AAC7D,QAAO,iBAAiB,gBAAgB,YAAY,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { getPayloadIDFor } from "../rsc/rscModule.mjs";
2
+ import { drainStream } from "../util/drainStream.mjs";
3
+ import { computeContentHash } from "./contentHash.mjs";
4
+ import { findReferencedIds, topologicalSort } from "./dependencyGraph.mjs";
5
+
6
+ //#region src/build/rscProcessor.ts
7
+ /**
8
+ * Processes RSC components by replacing temporary UUIDs with content-based hashes.
9
+ *
10
+ * @param deferRegistryIterator - Iterator yielding components with { id, data }
11
+ * @param appRscStream - The main RSC stream
12
+ * @param context - Optional context for logging warnings
13
+ */
14
+ async function processRscComponents(deferRegistryIterator, appRscStream, context) {
15
+ const components = /* @__PURE__ */ new Map();
16
+ for await (const { id, data } of deferRegistryIterator) components.set(id, data);
17
+ let appRscContent = await drainStream(appRscStream);
18
+ if (components.size === 0) return {
19
+ components: [],
20
+ appRscContent,
21
+ idMapping: /* @__PURE__ */ new Map()
22
+ };
23
+ const allIds = new Set(components.keys());
24
+ const dependencies = /* @__PURE__ */ new Map();
25
+ for (const [id, content] of components) {
26
+ const otherIds = new Set(allIds);
27
+ otherIds.delete(id);
28
+ const refs = findReferencedIds(content, otherIds);
29
+ dependencies.set(id, refs);
30
+ }
31
+ const { sorted, inCycle } = topologicalSort(dependencies);
32
+ const idMapping = /* @__PURE__ */ new Map();
33
+ if (inCycle.length > 0) {
34
+ context?.warn(`[funstack] Warning: ${inCycle.length} RSC component(s) are in dependency cycles and will keep unstable IDs: ${inCycle.join(", ")}`);
35
+ for (const id of inCycle) idMapping.set(id, id);
36
+ }
37
+ const processedComponents = [];
38
+ for (const tempId of sorted) {
39
+ let content = components.get(tempId);
40
+ for (const [oldId, newId] of idMapping) if (oldId !== newId) content = content.replaceAll(oldId, newId);
41
+ const finalId = getPayloadIDFor(await computeContentHash(content));
42
+ idMapping.set(tempId, finalId);
43
+ processedComponents.push({
44
+ finalId,
45
+ finalContent: content
46
+ });
47
+ }
48
+ for (const tempId of inCycle) {
49
+ let content = components.get(tempId);
50
+ for (const [oldId, newId] of idMapping) if (oldId !== newId) content = content.replaceAll(oldId, newId);
51
+ processedComponents.push({
52
+ finalId: tempId,
53
+ finalContent: content
54
+ });
55
+ }
56
+ for (const [oldId, newId] of idMapping) if (oldId !== newId) appRscContent = appRscContent.replaceAll(oldId, newId);
57
+ return {
58
+ components: processedComponents,
59
+ appRscContent,
60
+ idMapping
61
+ };
62
+ }
63
+
64
+ //#endregion
65
+ export { processRscComponents };
66
+ //# sourceMappingURL=rscProcessor.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rscProcessor.mjs","names":[],"sources":["../../src/build/rscProcessor.ts"],"sourcesContent":["import { drainStream } from \"../util/drainStream\";\nimport { getPayloadIDFor } from \"../rsc/rscModule\";\nimport { computeContentHash } from \"./contentHash\";\nimport { findReferencedIds, topologicalSort } from \"./dependencyGraph\";\n\nexport interface ProcessedComponent {\n finalId: string;\n finalContent: string;\n}\n\nexport interface ProcessResult {\n components: ProcessedComponent[];\n appRscContent: string;\n idMapping: Map<string, string>;\n}\n\ninterface RawComponent {\n id: string;\n data: string;\n}\n\n/**\n * Processes RSC components by replacing temporary UUIDs with content-based hashes.\n *\n * @param deferRegistryIterator - Iterator yielding components with { id, data }\n * @param appRscStream - The main RSC stream\n * @param context - Optional context for logging warnings\n */\nexport async function processRscComponents(\n deferRegistryIterator: AsyncIterable<RawComponent>,\n appRscStream: ReadableStream,\n context?: { warn: (message: string) => void },\n): Promise<ProcessResult> {\n // Step 1: Collect all components from deferRegistry\n const components = new Map<string, string>();\n for await (const { id, data } of deferRegistryIterator) {\n components.set(id, data);\n }\n\n // Step 2: Drain appRsc stream to string\n let appRscContent = await drainStream(appRscStream);\n\n // If no components, return early\n if (components.size === 0) {\n return {\n components: [],\n appRscContent,\n idMapping: new Map(),\n };\n }\n\n const allIds = new Set(components.keys());\n\n // Step 3: Build dependency graph\n // For each component, find which other component IDs appear in its content\n const dependencies = new Map<string, Set<string>>();\n for (const [id, content] of components) {\n const otherIds = new Set(allIds);\n otherIds.delete(id); // Don't include self-references\n const refs = findReferencedIds(content, otherIds);\n dependencies.set(id, refs);\n }\n\n // Step 4: Topologically sort components\n const { sorted, inCycle } = topologicalSort(dependencies);\n\n // Step 5: Handle cycles - warn and keep original temp IDs\n const idMapping = new Map<string, string>();\n\n if (inCycle.length > 0) {\n context?.warn(\n `[funstack] Warning: ${inCycle.length} RSC component(s) are in dependency cycles and will keep unstable IDs: ${inCycle.join(\", \")}`,\n );\n for (const id of inCycle) {\n idMapping.set(id, id); // Map to itself (keep original ID)\n }\n }\n\n // Step 6: Process sorted components in order\n const processedComponents: ProcessedComponent[] = [];\n\n for (const tempId of sorted) {\n let content = components.get(tempId)!;\n\n // Replace all already-finalized temp IDs with their hash-based IDs\n for (const [oldId, newId] of idMapping) {\n if (oldId !== newId) {\n content = content.replaceAll(oldId, newId);\n }\n }\n\n // Compute content hash for this component\n const contentHash = await computeContentHash(content);\n const finalId = getPayloadIDFor(contentHash);\n\n // Create mapping\n idMapping.set(tempId, finalId);\n\n processedComponents.push({\n finalId,\n finalContent: content,\n });\n }\n\n // Add cycle members to processed components (with original IDs)\n for (const tempId of inCycle) {\n let content = components.get(tempId)!;\n\n // Replace finalized IDs in cycle member content\n for (const [oldId, newId] of idMapping) {\n if (oldId !== newId) {\n content = content.replaceAll(oldId, newId);\n }\n }\n\n processedComponents.push({\n finalId: tempId, // Keep original temp ID\n finalContent: content,\n });\n }\n\n // Step 7: Process appRsc - replace all temp IDs with final IDs\n for (const [oldId, newId] of idMapping) {\n if (oldId !== newId) {\n appRscContent = appRscContent.replaceAll(oldId, newId);\n }\n }\n\n return {\n components: processedComponents,\n appRscContent,\n idMapping,\n };\n}\n"],"mappings":";;;;;;;;;;;;;AA4BA,eAAsB,qBACpB,uBACA,cACA,SACwB;CAExB,MAAM,6BAAa,IAAI,KAAqB;AAC5C,YAAW,MAAM,EAAE,IAAI,UAAU,sBAC/B,YAAW,IAAI,IAAI,KAAK;CAI1B,IAAI,gBAAgB,MAAM,YAAY,aAAa;AAGnD,KAAI,WAAW,SAAS,EACtB,QAAO;EACL,YAAY,EAAE;EACd;EACA,2BAAW,IAAI,KAAK;EACrB;CAGH,MAAM,SAAS,IAAI,IAAI,WAAW,MAAM,CAAC;CAIzC,MAAM,+BAAe,IAAI,KAA0B;AACnD,MAAK,MAAM,CAAC,IAAI,YAAY,YAAY;EACtC,MAAM,WAAW,IAAI,IAAI,OAAO;AAChC,WAAS,OAAO,GAAG;EACnB,MAAM,OAAO,kBAAkB,SAAS,SAAS;AACjD,eAAa,IAAI,IAAI,KAAK;;CAI5B,MAAM,EAAE,QAAQ,YAAY,gBAAgB,aAAa;CAGzD,MAAM,4BAAY,IAAI,KAAqB;AAE3C,KAAI,QAAQ,SAAS,GAAG;AACtB,WAAS,KACP,uBAAuB,QAAQ,OAAO,yEAAyE,QAAQ,KAAK,KAAK,GAClI;AACD,OAAK,MAAM,MAAM,QACf,WAAU,IAAI,IAAI,GAAG;;CAKzB,MAAM,sBAA4C,EAAE;AAEpD,MAAK,MAAM,UAAU,QAAQ;EAC3B,IAAI,UAAU,WAAW,IAAI,OAAO;AAGpC,OAAK,MAAM,CAAC,OAAO,UAAU,UAC3B,KAAI,UAAU,MACZ,WAAU,QAAQ,WAAW,OAAO,MAAM;EAM9C,MAAM,UAAU,gBADI,MAAM,mBAAmB,QAAQ,CACT;AAG5C,YAAU,IAAI,QAAQ,QAAQ;AAE9B,sBAAoB,KAAK;GACvB;GACA,cAAc;GACf,CAAC;;AAIJ,MAAK,MAAM,UAAU,SAAS;EAC5B,IAAI,UAAU,WAAW,IAAI,OAAO;AAGpC,OAAK,MAAM,CAAC,OAAO,UAAU,UAC3B,KAAI,UAAU,MACZ,WAAU,QAAQ,WAAW,OAAO,MAAM;AAI9C,sBAAoB,KAAK;GACvB,SAAS;GACT,cAAc;GACf,CAAC;;AAIJ,MAAK,MAAM,CAAC,OAAO,UAAU,UAC3B,KAAI,UAAU,MACZ,iBAAgB,cAAc,WAAW,OAAO,MAAM;AAI1D,QAAO;EACL,YAAY;EACZ;EACA;EACD"}
@@ -0,0 +1,53 @@
1
+ import { GlobalErrorBoundary } from "./error-boundary.mjs";
2
+ import { devMainRscPath } from "../rsc/request.mjs";
3
+ import { appClientManifestVar } from "./globals.mjs";
4
+ import { withBasePath } from "../util/basePath.mjs";
5
+ import { createFromFetch, createFromReadableStream } from "@vitejs/plugin-rsc/browser";
6
+ import React, { startTransition, useEffect, useState } from "react";
7
+ import { createRoot, hydrateRoot } from "react-dom/client";
8
+ import { rscStream } from "rsc-html-stream/client";
9
+ import { jsx } from "react/jsx-runtime";
10
+
11
+ //#region src/client/entry.tsx
12
+ async function devMain() {
13
+ let setPayload;
14
+ const initialPayload = await createFromReadableStream(rscStream);
15
+ function BrowserRoot() {
16
+ const [payload, setPayload_] = useState(initialPayload);
17
+ useEffect(() => {
18
+ setPayload = (v) => startTransition(() => setPayload_(v));
19
+ }, [setPayload_]);
20
+ return payload.root;
21
+ }
22
+ async function fetchRscPayload() {
23
+ const payload = await createFromFetch(fetch(withBasePath(devMainRscPath)));
24
+ setPayload(payload);
25
+ }
26
+ const browserRoot = /* @__PURE__ */ jsx(React.StrictMode, { children: /* @__PURE__ */ jsx(GlobalErrorBoundary, { children: /* @__PURE__ */ jsx(BrowserRoot, {}) }) });
27
+ if (globalThis.__NO_HYDRATE) createRoot(document).render(browserRoot);
28
+ else hydrateRoot(document, browserRoot);
29
+ if (import.meta.hot) import.meta.hot.on("rsc:update", () => {
30
+ fetchRscPayload();
31
+ });
32
+ }
33
+ async function prodMain() {
34
+ const manifest = globalThis[appClientManifestVar];
35
+ const payload = await createFromFetch(fetch(manifest.stream));
36
+ function BrowserRoot() {
37
+ return payload.root;
38
+ }
39
+ const browserRoot = /* @__PURE__ */ jsx(BrowserRoot, {});
40
+ const appRootId = manifest.marker;
41
+ const appMarker = document.getElementById(appRootId);
42
+ if (!appMarker) throw new Error(`Failed to find app root element by id "${appRootId}". This is likely a bug.`);
43
+ const appRoot = appMarker.parentElement;
44
+ if (!appRoot) throw new Error(`App root element has no parent element. This is likely a bug.`);
45
+ appMarker.remove();
46
+ createRoot(appRoot).render(browserRoot);
47
+ }
48
+ if (import.meta.env.DEV) devMain();
49
+ else prodMain();
50
+
51
+ //#endregion
52
+ export { };
53
+ //# sourceMappingURL=entry.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.mjs","names":[],"sources":["../../src/client/entry.tsx"],"sourcesContent":["import {\n createFromReadableStream,\n createFromFetch,\n} from \"@vitejs/plugin-rsc/browser\";\nimport React, { startTransition, useEffect, useState } from \"react\";\nimport { createRoot, hydrateRoot } from \"react-dom/client\";\nimport { rscStream } from \"rsc-html-stream/client\";\nimport { GlobalErrorBoundary } from \"./error-boundary\";\nimport type { RscPayload } from \"../rsc/entry\";\nimport { devMainRscPath } from \"../rsc/request\";\nimport { appClientManifestVar, type AppClientManifest } from \"./globals\";\nimport { withBasePath } from \"../util/basePath\";\n\nasync function devMain() {\n let setPayload: (v: RscPayload) => void;\n\n const initialPayload = await createFromReadableStream<RscPayload>(rscStream);\n\n function BrowserRoot() {\n const [payload, setPayload_] = useState(initialPayload);\n\n useEffect(() => {\n setPayload = (v) => startTransition(() => setPayload_(v));\n }, [setPayload_]);\n\n return payload.root;\n }\n\n // re-fetch RSC and trigger re-rendering\n async function fetchRscPayload() {\n const payload = await createFromFetch<RscPayload>(\n fetch(withBasePath(devMainRscPath)),\n );\n setPayload(payload);\n }\n // hydration\n const browserRoot = (\n <React.StrictMode>\n <GlobalErrorBoundary>\n <BrowserRoot />\n </GlobalErrorBoundary>\n </React.StrictMode>\n );\n\n if (\n // @ts-expect-error\n globalThis.__NO_HYDRATE\n ) {\n // This happens when SSR failed on server\n createRoot(document).render(browserRoot);\n } else {\n hydrateRoot(document, browserRoot);\n }\n\n // implement server HMR by triggering re-fetch/render of RSC upon server code change\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", () => {\n fetchRscPayload();\n });\n }\n}\n\nasync function prodMain() {\n const manifest: AppClientManifest =\n // @ts-expect-error\n globalThis[appClientManifestVar];\n\n const payload = await createFromFetch<RscPayload>(fetch(manifest.stream));\n\n function BrowserRoot() {\n return payload.root;\n }\n const browserRoot = <BrowserRoot />;\n const appRootId: string = manifest.marker;\n\n const appMarker = document.getElementById(appRootId);\n if (!appMarker) {\n throw new Error(\n `Failed to find app root element by id \"${appRootId}\". This is likely a bug.`,\n );\n }\n const appRoot = appMarker.parentElement;\n if (!appRoot) {\n throw new Error(\n `App root element has no parent element. This is likely a bug.`,\n );\n }\n appMarker.remove();\n\n createRoot(appRoot).render(browserRoot);\n}\n\nif (import.meta.env.DEV) {\n devMain();\n} else {\n prodMain();\n}\n"],"mappings":";;;;;;;;;;;AAaA,eAAe,UAAU;CACvB,IAAI;CAEJ,MAAM,iBAAiB,MAAM,yBAAqC,UAAU;CAE5E,SAAS,cAAc;EACrB,MAAM,CAAC,SAAS,eAAe,SAAS,eAAe;AAEvD,kBAAgB;AACd,iBAAc,MAAM,sBAAsB,YAAY,EAAE,CAAC;KACxD,CAAC,YAAY,CAAC;AAEjB,SAAO,QAAQ;;CAIjB,eAAe,kBAAkB;EAC/B,MAAM,UAAU,MAAM,gBACpB,MAAM,aAAa,eAAe,CAAC,CACpC;AACD,aAAW,QAAQ;;CAGrB,MAAM,cACJ,oBAAC,MAAM,wBACL,oBAAC,iCACC,oBAAC,gBAAc,GACK,GACL;AAGrB,KAEE,WAAW,aAGX,YAAW,SAAS,CAAC,OAAO,YAAY;KAExC,aAAY,UAAU,YAAY;AAIpC,KAAI,OAAO,KAAK,IACd,QAAO,KAAK,IAAI,GAAG,oBAAoB;AACrC,mBAAiB;GACjB;;AAIN,eAAe,WAAW;CACxB,MAAM,WAEJ,WAAW;CAEb,MAAM,UAAU,MAAM,gBAA4B,MAAM,SAAS,OAAO,CAAC;CAEzE,SAAS,cAAc;AACrB,SAAO,QAAQ;;CAEjB,MAAM,cAAc,oBAAC,gBAAc;CACnC,MAAM,YAAoB,SAAS;CAEnC,MAAM,YAAY,SAAS,eAAe,UAAU;AACpD,KAAI,CAAC,UACH,OAAM,IAAI,MACR,0CAA0C,UAAU,0BACrD;CAEH,MAAM,UAAU,UAAU;AAC1B,KAAI,CAAC,QACH,OAAM,IAAI,MACR,gEACD;AAEH,WAAU,QAAQ;AAElB,YAAW,QAAQ,CAAC,OAAO,YAAY;;AAGzC,IAAI,OAAO,KAAK,IAAI,IAClB,UAAS;IAET,WAAU"}
@@ -0,0 +1,48 @@
1
+ "use client";
2
+
3
+ import React, { startTransition } from "react";
4
+ import { ErrorBoundary } from "react-error-boundary";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+
7
+ //#region src/client/error-boundary.tsx
8
+ /**
9
+ * Whole-page error boundary for unexpected errors during development
10
+ */
11
+ const GlobalErrorBoundary = (props) => {
12
+ return /* @__PURE__ */ jsx(ErrorBoundary, {
13
+ FallbackComponent: Fallback,
14
+ children: props.children
15
+ });
16
+ };
17
+ const Fallback = ({ error, resetErrorBoundary }) => {
18
+ const errorMessage = error instanceof Error ? error.message : String(error);
19
+ return /* @__PURE__ */ jsxs("html", { children: [/* @__PURE__ */ jsx("head", { children: /* @__PURE__ */ jsx("title", { children: "Unexpected Error" }) }), /* @__PURE__ */ jsxs("body", {
20
+ style: {
21
+ height: "100vh",
22
+ display: "flex",
23
+ flexDirection: "column",
24
+ placeContent: "center",
25
+ placeItems: "center",
26
+ fontSize: "24px",
27
+ fontWeight: 400,
28
+ lineHeight: "1.5em"
29
+ },
30
+ children: [
31
+ /* @__PURE__ */ jsx("h1", { children: "Caught an unexpected error" }),
32
+ /* @__PURE__ */ jsx("p", { children: "See the console for details." }),
33
+ /* @__PURE__ */ jsxs("pre", { children: ["Error: ", errorMessage] }),
34
+ /* @__PURE__ */ jsx("button", {
35
+ onClick: () => {
36
+ startTransition(() => {
37
+ resetErrorBoundary();
38
+ });
39
+ },
40
+ children: "Reset"
41
+ })
42
+ ]
43
+ })] });
44
+ };
45
+
46
+ //#endregion
47
+ export { GlobalErrorBoundary };
48
+ //# sourceMappingURL=error-boundary.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-boundary.mjs","names":[],"sources":["../../src/client/error-boundary.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { startTransition } from \"react\";\nimport { ErrorBoundary, type FallbackProps } from \"react-error-boundary\";\n\n/**\n * Whole-page error boundary for unexpected errors during development\n */\nexport const GlobalErrorBoundary: React.FC<React.PropsWithChildren> = (\n props,\n) => {\n return (\n <ErrorBoundary FallbackComponent={Fallback}>{props.children}</ErrorBoundary>\n );\n};\n\nconst Fallback: React.FC<FallbackProps> = ({ error, resetErrorBoundary }) => {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return (\n <html>\n <head>\n <title>Unexpected Error</title>\n </head>\n <body\n style={{\n height: \"100vh\",\n display: \"flex\",\n flexDirection: \"column\",\n placeContent: \"center\",\n placeItems: \"center\",\n fontSize: \"24px\",\n fontWeight: 400,\n lineHeight: \"1.5em\",\n }}\n >\n <h1>Caught an unexpected error</h1>\n <p>See the console for details.</p>\n <pre>Error: {errorMessage}</pre>\n <button\n onClick={() => {\n startTransition(() => {\n resetErrorBoundary();\n });\n }}\n >\n Reset\n </button>\n </body>\n </html>\n );\n};\n"],"mappings":";;;;;;;;;;AAQA,MAAa,uBACX,UACG;AACH,QACE,oBAAC;EAAc,mBAAmB;YAAW,MAAM;GAAyB;;AAIhF,MAAM,YAAqC,EAAE,OAAO,yBAAyB;CAC3E,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,QACE,qBAAC,qBACC,oBAAC,oBACC,oBAAC,qBAAM,qBAAwB,GAC1B,EACP,qBAAC;EACC,OAAO;GACL,QAAQ;GACR,SAAS;GACT,eAAe;GACf,cAAc;GACd,YAAY;GACZ,UAAU;GACV,YAAY;GACZ,YAAY;GACb;;GAED,oBAAC,kBAAG,+BAA+B;GACnC,oBAAC,iBAAE,iCAAgC;GACnC,qBAAC,oBAAI,WAAQ,gBAAmB;GAChC,oBAAC;IACC,eAAe;AACb,2BAAsB;AACpB,0BAAoB;OACpB;;cAEL;KAEQ;;GACJ,IACF"}
@@ -0,0 +1,10 @@
1
+ //#region src/client/globals.ts
2
+ const globalPrefix = "FUNSTACK_STATIC_";
3
+ /**
4
+ * Variable name for the app client manifest
5
+ */
6
+ const appClientManifestVar = `${globalPrefix}appClientManifest`;
7
+
8
+ //#endregion
9
+ export { appClientManifestVar };
10
+ //# sourceMappingURL=globals.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globals.mjs","names":[],"sources":["../../src/client/globals.ts"],"sourcesContent":["// Prefix for global variables\nconst globalPrefix = \"FUNSTACK_STATIC_\";\n\n/**\n * Variable name for the app client manifest\n */\nexport const appClientManifestVar = `${globalPrefix}appClientManifest`;\n\nexport interface AppClientManifest {\n marker: string;\n stream: string;\n}\n"],"mappings":";AACA,MAAM,eAAe;;;;AAKrB,MAAa,uBAAuB,GAAG,aAAa"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,3 @@
1
+ import "../client/entry.mjs";
2
+
3
+ export { };
@@ -0,0 +1,3 @@
1
+ import { ClientWrapper, RegistryContext } from "../rsc-client/clientWrapper.mjs";
2
+ import "../rsc-client/entry.mjs";
3
+ export { ClientWrapper, RegistryContext };
@@ -0,0 +1,6 @@
1
+ "use client";
2
+
3
+ import { ClientWrapper, RegistryContext } from "../rsc-client/clientWrapper.mjs";
4
+ import "../rsc-client/entry.mjs";
5
+
6
+ export { ClientWrapper, RegistryContext };
@@ -0,0 +1,3 @@
1
+ import { defer } from "../rsc/defer.mjs";
2
+ import { RscPayload, build, isServeRSCError, serveHTML, serveRSC } from "../rsc/entry.mjs";
3
+ export { RscPayload, build, defer, isServeRSCError, serveHTML, serveRSC };
@@ -0,0 +1,4 @@
1
+ import { defer } from "../rsc/defer.mjs";
2
+ import { build, isServeRSCError, serveHTML, serveRSC } from "../rsc/entry.mjs";
3
+
4
+ export { build, defer, isServeRSCError, serveHTML, serveRSC };
@@ -0,0 +1,2 @@
1
+ import { defer } from "../rsc/defer.mjs";
2
+ export { defer };
@@ -0,0 +1,3 @@
1
+ import { defer } from "../rsc/defer.mjs";
2
+
3
+ export { defer };
@@ -0,0 +1,2 @@
1
+ import { renderHTML } from "../ssr/entry.mjs";
2
+ export { renderHTML };
@@ -0,0 +1,3 @@
1
+ import { renderHTML } from "../ssr/entry.mjs";
2
+
3
+ export { renderHTML };
package/dist/index.d.mts CHANGED
@@ -1,30 +1,2 @@
1
- import { Plugin } from "vite";
2
-
3
- //#region src/index.d.ts
4
- interface FunstackStaticOptions {
5
- /**
6
- * Root component of the page.
7
- * The file should `export default` a React component that renders the whole page.
8
- * (`<html>...</html>`).
9
- */
10
- root: string;
11
- /**
12
- * Entry point of your application.
13
- * The file should `export default` a React component that renders the application content.
14
- */
15
- app: string;
16
- /**
17
- * Output directory for build.
18
- *
19
- * @default dist/public
20
- */
21
- publicOutDir?: string;
22
- }
23
- declare function funstackStatic({
24
- root,
25
- app,
26
- publicOutDir
27
- }: FunstackStaticOptions): (Plugin | Plugin[])[];
28
- //#endregion
29
- export { FunstackStaticOptions, funstackStatic as default };
30
- //# sourceMappingURL=index.d.mts.map
1
+ import { FunstackStaticOptions, funstackStatic } from "./plugin/index.mjs";
2
+ export { type FunstackStaticOptions, funstackStatic as default };