veryfront 0.1.216 → 0.1.217

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 (160) hide show
  1. package/esm/cli/commands/generate/integration-generator-helpers.d.ts +35 -0
  2. package/esm/cli/commands/generate/integration-generator-helpers.d.ts.map +1 -0
  3. package/esm/cli/commands/generate/integration-generator-helpers.js +123 -0
  4. package/esm/cli/commands/generate/integration-generator.d.ts +1 -2
  5. package/esm/cli/commands/generate/integration-generator.d.ts.map +1 -1
  6. package/esm/cli/commands/generate/integration-generator.js +1 -123
  7. package/esm/cli/commands/knowledge/command-helpers.d.ts +48 -0
  8. package/esm/cli/commands/knowledge/command-helpers.d.ts.map +1 -0
  9. package/esm/cli/commands/knowledge/command-helpers.js +216 -0
  10. package/esm/cli/commands/knowledge/command.d.ts +11 -16
  11. package/esm/cli/commands/knowledge/command.d.ts.map +1 -1
  12. package/esm/cli/commands/knowledge/command.js +25 -212
  13. package/esm/cli/mcp/remote-file-tool-helpers.d.ts +5 -0
  14. package/esm/cli/mcp/remote-file-tool-helpers.d.ts.map +1 -0
  15. package/esm/cli/mcp/remote-file-tool-helpers.js +22 -0
  16. package/esm/cli/mcp/remote-file-tools.d.ts.map +1 -1
  17. package/esm/cli/mcp/remote-file-tools.js +1 -22
  18. package/esm/cli/templates/integration-loader-helpers.d.ts +8 -0
  19. package/esm/cli/templates/integration-loader-helpers.d.ts.map +1 -0
  20. package/esm/cli/templates/integration-loader-helpers.js +29 -0
  21. package/esm/cli/templates/integration-loader.d.ts.map +1 -1
  22. package/esm/cli/templates/integration-loader.js +5 -21
  23. package/esm/cli/templates/manifest.d.ts +1 -0
  24. package/esm/cli/templates/manifest.js +2 -1
  25. package/esm/deno.js +2 -2
  26. package/esm/src/agent/runtime/index.d.ts.map +1 -1
  27. package/esm/src/agent/runtime/index.js +48 -90
  28. package/esm/src/chat/ag-ui-helpers.d.ts +17 -0
  29. package/esm/src/chat/ag-ui-helpers.d.ts.map +1 -0
  30. package/esm/src/chat/ag-ui-helpers.js +111 -0
  31. package/esm/src/chat/ag-ui.d.ts.map +1 -1
  32. package/esm/src/chat/ag-ui.js +1 -111
  33. package/esm/src/config/schemas/config.schema.d.ts +1 -0
  34. package/esm/src/config/schemas/config.schema.d.ts.map +1 -1
  35. package/esm/src/config/schemas/config.schema.js +11 -0
  36. package/esm/src/config/schemas/index.d.ts +11 -1
  37. package/esm/src/config/schemas/index.d.ts.map +1 -1
  38. package/esm/src/errors/error-registry-helpers.d.ts +6 -0
  39. package/esm/src/errors/error-registry-helpers.d.ts.map +1 -0
  40. package/esm/src/errors/error-registry-helpers.js +9 -0
  41. package/esm/src/errors/error-registry.d.ts.map +1 -1
  42. package/esm/src/errors/error-registry.js +4 -3
  43. package/esm/src/extensions/factory-loader.d.ts +29 -0
  44. package/esm/src/extensions/factory-loader.d.ts.map +1 -0
  45. package/esm/src/extensions/factory-loader.js +63 -0
  46. package/esm/src/extensions/index.d.ts +16 -0
  47. package/esm/src/extensions/index.d.ts.map +1 -1
  48. package/esm/src/extensions/index.js +16 -0
  49. package/esm/src/extensions/orchestrate.d.ts +54 -0
  50. package/esm/src/extensions/orchestrate.d.ts.map +1 -0
  51. package/esm/src/extensions/orchestrate.js +116 -0
  52. package/esm/src/html/styles-builder/plugin-loader.d.ts.map +1 -1
  53. package/esm/src/html/styles-builder/plugin-loader.js +23 -0
  54. package/esm/src/html/styles-builder/tailwind-plugin-allowlist.d.ts +29 -0
  55. package/esm/src/html/styles-builder/tailwind-plugin-allowlist.d.ts.map +1 -0
  56. package/esm/src/html/styles-builder/tailwind-plugin-allowlist.js +48 -0
  57. package/esm/src/modules/react-loader/ssr-module-loader/loader-helpers.d.ts +15 -0
  58. package/esm/src/modules/react-loader/ssr-module-loader/loader-helpers.d.ts.map +1 -0
  59. package/esm/src/modules/react-loader/ssr-module-loader/loader-helpers.js +22 -0
  60. package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts +0 -2
  61. package/esm/src/modules/react-loader/ssr-module-loader/loader.d.ts.map +1 -1
  62. package/esm/src/modules/react-loader/ssr-module-loader/loader.js +4 -24
  63. package/esm/src/platform/adapters/fs/veryfront/adapter-helpers.d.ts +19 -0
  64. package/esm/src/platform/adapters/fs/veryfront/adapter-helpers.d.ts.map +1 -0
  65. package/esm/src/platform/adapters/fs/veryfront/adapter-helpers.js +26 -0
  66. package/esm/src/platform/adapters/fs/veryfront/adapter.d.ts.map +1 -1
  67. package/esm/src/platform/adapters/fs/veryfront/adapter.js +4 -20
  68. package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts +1 -0
  69. package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.d.ts.map +1 -1
  70. package/esm/src/platform/adapters/fs/veryfront/read-operations-helpers.js +3 -0
  71. package/esm/src/platform/adapters/fs/veryfront/read-operations.d.ts.map +1 -1
  72. package/esm/src/platform/adapters/fs/veryfront/read-operations.js +4 -7
  73. package/esm/src/platform/adapters/fs/veryfront/websocket-manager-helpers.d.ts +28 -0
  74. package/esm/src/platform/adapters/fs/veryfront/websocket-manager-helpers.d.ts.map +1 -0
  75. package/esm/src/platform/adapters/fs/veryfront/websocket-manager-helpers.js +41 -0
  76. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts +1 -4
  77. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.d.ts.map +1 -1
  78. package/esm/src/platform/adapters/fs/veryfront/websocket-manager.js +7 -40
  79. package/esm/src/provider/runtime-loader/tool-input-status.d.ts +17 -0
  80. package/esm/src/provider/runtime-loader/tool-input-status.d.ts.map +1 -0
  81. package/esm/src/provider/runtime-loader/tool-input-status.js +155 -0
  82. package/esm/src/provider/runtime-loader.d.ts +2 -3
  83. package/esm/src/provider/runtime-loader.d.ts.map +1 -1
  84. package/esm/src/provider/runtime-loader.js +2 -155
  85. package/esm/src/rendering/orchestrator/pipeline-helpers.d.ts +8 -0
  86. package/esm/src/rendering/orchestrator/pipeline-helpers.d.ts.map +1 -0
  87. package/esm/src/rendering/orchestrator/pipeline-helpers.js +20 -0
  88. package/esm/src/rendering/orchestrator/pipeline.d.ts +0 -3
  89. package/esm/src/rendering/orchestrator/pipeline.d.ts.map +1 -1
  90. package/esm/src/rendering/orchestrator/pipeline.js +4 -22
  91. package/esm/src/routing/api/module-loader/loader-helpers.d.ts +10 -0
  92. package/esm/src/routing/api/module-loader/loader-helpers.d.ts.map +1 -0
  93. package/esm/src/routing/api/module-loader/loader-helpers.js +62 -0
  94. package/esm/src/routing/api/module-loader/loader.d.ts +1 -1
  95. package/esm/src/routing/api/module-loader/loader.d.ts.map +1 -1
  96. package/esm/src/routing/api/module-loader/loader.js +2 -60
  97. package/esm/src/server/bootstrap.d.ts +22 -2
  98. package/esm/src/server/bootstrap.d.ts.map +1 -1
  99. package/esm/src/server/bootstrap.js +67 -5
  100. package/esm/src/server/dev-ui/manifest.d.ts +2 -0
  101. package/esm/src/server/dev-ui/manifest.js +3 -1
  102. package/esm/src/server/handlers/request/api/project-discovery.d.ts.map +1 -1
  103. package/esm/src/server/handlers/request/api/project-discovery.js +14 -8
  104. package/esm/src/server/production-server.js +1 -1
  105. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.d.ts.map +1 -1
  106. package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.js +2 -2
  107. package/esm/src/studio/bridge/bridge-bundle.generated.d.ts.map +1 -1
  108. package/esm/src/studio/bridge/bridge-bundle.generated.js +1 -1
  109. package/esm/src/tool/index.d.ts +1 -1
  110. package/esm/src/tool/index.d.ts.map +1 -1
  111. package/esm/src/tool/types.d.ts +20 -0
  112. package/esm/src/tool/types.d.ts.map +1 -1
  113. package/esm/src/utils/version-constant.d.ts +1 -1
  114. package/esm/src/utils/version-constant.js +1 -1
  115. package/package.json +1 -1
  116. package/src/cli/commands/generate/integration-generator-helpers.ts +185 -0
  117. package/src/cli/commands/generate/integration-generator.ts +12 -168
  118. package/src/cli/commands/knowledge/command-helpers.ts +295 -0
  119. package/src/cli/commands/knowledge/command.ts +33 -259
  120. package/src/cli/mcp/remote-file-tool-helpers.ts +27 -0
  121. package/src/cli/mcp/remote-file-tools.ts +6 -28
  122. package/src/cli/templates/integration-loader-helpers.ts +49 -0
  123. package/src/cli/templates/integration-loader.ts +10 -28
  124. package/src/cli/templates/manifest.js +2 -1
  125. package/src/deno.js +2 -2
  126. package/src/src/agent/runtime/index.ts +77 -94
  127. package/src/src/chat/ag-ui-helpers.ts +139 -0
  128. package/src/src/chat/ag-ui.ts +11 -139
  129. package/src/src/config/schemas/config.schema.ts +11 -0
  130. package/src/src/config/schemas/index.ts +15 -1
  131. package/src/src/errors/error-registry-helpers.ts +23 -0
  132. package/src/src/errors/error-registry.ts +8 -3
  133. package/src/src/extensions/factory-loader.ts +76 -0
  134. package/src/src/extensions/index.ts +20 -0
  135. package/src/src/extensions/orchestrate.ts +184 -0
  136. package/src/src/html/styles-builder/plugin-loader.ts +32 -0
  137. package/src/src/html/styles-builder/tailwind-plugin-allowlist.ts +51 -0
  138. package/src/src/modules/react-loader/ssr-module-loader/loader-helpers.ts +37 -0
  139. package/src/src/modules/react-loader/ssr-module-loader/loader.ts +8 -39
  140. package/src/src/platform/adapters/fs/veryfront/adapter-helpers.ts +43 -0
  141. package/src/src/platform/adapters/fs/veryfront/adapter.ts +8 -22
  142. package/src/src/platform/adapters/fs/veryfront/read-operations-helpers.ts +4 -0
  143. package/src/src/platform/adapters/fs/veryfront/read-operations.ts +4 -7
  144. package/src/src/platform/adapters/fs/veryfront/websocket-manager-helpers.ts +73 -0
  145. package/src/src/platform/adapters/fs/veryfront/websocket-manager.ts +29 -44
  146. package/src/src/provider/runtime-loader/tool-input-status.ts +210 -0
  147. package/src/src/provider/runtime-loader.ts +6 -203
  148. package/src/src/rendering/orchestrator/pipeline-helpers.ts +35 -0
  149. package/src/src/rendering/orchestrator/pipeline.ts +8 -35
  150. package/src/src/routing/api/module-loader/loader-helpers.ts +68 -0
  151. package/src/src/routing/api/module-loader/loader.ts +8 -65
  152. package/src/src/server/bootstrap.ts +88 -7
  153. package/src/src/server/dev-ui/manifest.js +3 -1
  154. package/src/src/server/handlers/request/api/project-discovery.ts +19 -8
  155. package/src/src/server/production-server.ts +1 -1
  156. package/src/src/server/services/rsc/endpoints/rsc-bundles.generated.ts +2 -2
  157. package/src/src/studio/bridge/bridge-bundle.generated.ts +1 -1
  158. package/src/src/tool/index.ts +1 -0
  159. package/src/src/tool/types.ts +21 -0
  160. package/src/src/utils/version-constant.ts +1 -1
@@ -1,160 +1,7 @@
1
- import * as dntShim from "../../_dnt.shims.js";
2
1
  import { getAnthropicMessagesUrl, getGoogleEmbeddingUrl, getGoogleGenerateContentUrl, getGoogleStreamGenerateContentUrl, getOpenAIChatCompletionsUrl, getOpenAIEmbeddingUrl, getOpenAIResponsesUrl, } from "./runtime-loader/provider-endpoints.js";
3
2
  import { createAnthropicRequestInit, createGoogleRequestInit, createOpenAIRequestInit, } from "./runtime-loader/provider-request-init.js";
4
- export const TOOL_INPUT_PENDING_THRESHOLD_MS = 5_000;
5
- function getToolCallIdFromStreamPart(part) {
6
- if (!part || typeof part !== "object") {
7
- return null;
8
- }
9
- const record = part;
10
- if (typeof record.toolCallId === "string" && record.toolCallId.length > 0) {
11
- return record.toolCallId;
12
- }
13
- if (typeof record.id === "string" && record.id.length > 0) {
14
- return record.id;
15
- }
16
- return null;
17
- }
18
- function collectDueToolStatuses(toolStates, now, thresholdMs) {
19
- const events = [];
20
- for (const [toolCallId, state] of toolStates.entries()) {
21
- if (state.dueAt === null || state.dueAt > now) {
22
- continue;
23
- }
24
- state.dueAt = now + thresholdMs;
25
- state.lastStatus = "pending_input";
26
- events.push({
27
- type: "data-tool-call-status",
28
- data: {
29
- toolCallId,
30
- status: "pending_input",
31
- },
32
- });
33
- }
34
- return events;
35
- }
36
- export async function* withToolInputStatusTransitions(stream, thresholdMs = TOOL_INPUT_PENDING_THRESHOLD_MS) {
37
- const iterator = stream[Symbol.asyncIterator]();
38
- const toolStates = new Map();
39
- const buffered = [];
40
- let nextPartPromise = null;
41
- const closeTool = (toolCallId) => {
42
- if (!toolCallId) {
43
- return;
44
- }
45
- toolStates.delete(toolCallId);
46
- };
47
- const schedulePending = (toolCallId) => {
48
- if (!toolCallId) {
49
- return;
50
- }
51
- const state = toolStates.get(toolCallId) ?? {
52
- dueAt: null,
53
- lastStatus: null,
54
- };
55
- state.dueAt = Date.now() + thresholdMs;
56
- toolStates.set(toolCallId, state);
57
- };
58
- const markStreaming = (toolCallId) => {
59
- if (!toolCallId) {
60
- return;
61
- }
62
- const state = toolStates.get(toolCallId) ?? {
63
- dueAt: null,
64
- lastStatus: null,
65
- };
66
- if (state.lastStatus !== "streaming_input") {
67
- buffered.push({
68
- type: "data-tool-call-status",
69
- data: {
70
- toolCallId,
71
- status: "streaming_input",
72
- },
73
- });
74
- }
75
- state.lastStatus = "streaming_input";
76
- state.dueAt = Date.now() + thresholdMs;
77
- toolStates.set(toolCallId, state);
78
- };
79
- const processPart = (part) => {
80
- if (!part || typeof part !== "object") {
81
- buffered.push(part);
82
- return;
83
- }
84
- const record = part;
85
- const partType = typeof record.type === "string" ? record.type : null;
86
- const toolCallId = getToolCallIdFromStreamPart(part);
87
- switch (partType) {
88
- case "tool-input-start":
89
- schedulePending(toolCallId);
90
- buffered.push(part);
91
- return;
92
- case "tool-input-delta":
93
- markStreaming(toolCallId);
94
- buffered.push(part);
95
- return;
96
- case "tool-call":
97
- case "tool-result":
98
- case "tool-error":
99
- closeTool(toolCallId);
100
- buffered.push(part);
101
- return;
102
- case "finish":
103
- case "error":
104
- toolStates.clear();
105
- buffered.push(part);
106
- return;
107
- default:
108
- buffered.push(part);
109
- return;
110
- }
111
- };
112
- while (true) {
113
- if (buffered.length > 0) {
114
- yield buffered.shift();
115
- continue;
116
- }
117
- if (!nextPartPromise) {
118
- nextPartPromise = iterator.next();
119
- }
120
- const nextDueAt = [...toolStates.values()]
121
- .map((state) => state.dueAt)
122
- .filter((value) => value !== null)
123
- .sort((left, right) => left - right)[0] ?? null;
124
- if (nextDueAt !== null) {
125
- let timeoutId = null;
126
- const timeoutResult = await Promise.race([
127
- nextPartPromise.then((result) => ({ kind: "part", result })),
128
- new Promise((resolve) => {
129
- timeoutId = dntShim.setTimeout(() => resolve({ kind: "timeout" }), Math.max(0, nextDueAt - Date.now()));
130
- }),
131
- ]);
132
- if (timeoutId !== null) {
133
- clearTimeout(timeoutId);
134
- }
135
- if (timeoutResult.kind === "timeout") {
136
- buffered.push(...collectDueToolStatuses(toolStates, Date.now(), thresholdMs));
137
- continue;
138
- }
139
- nextPartPromise = null;
140
- if (timeoutResult.result.done) {
141
- buffered.push(...collectDueToolStatuses(toolStates, Date.now(), thresholdMs));
142
- while (buffered.length > 0) {
143
- yield buffered.shift();
144
- }
145
- return;
146
- }
147
- processPart(timeoutResult.result.value);
148
- continue;
149
- }
150
- const result = await nextPartPromise;
151
- nextPartPromise = null;
152
- if (result.done) {
153
- return;
154
- }
155
- processPart(result.value);
156
- }
157
- }
3
+ import { TOOL_INPUT_PENDING_THRESHOLD_MS, withToolInputStatusTransitions, } from "./runtime-loader/tool-input-status.js";
4
+ export { TOOL_INPUT_PENDING_THRESHOLD_MS, withToolInputStatusTransitions };
158
5
  function isNumberArray(value) {
159
6
  return Array.isArray(value) && value.every((entry) => typeof entry === "number");
160
7
  }
@@ -0,0 +1,8 @@
1
+ import type { LayoutItem } from "../../types/index.js";
2
+ export declare function extractRenderedCssHash(html: string): string | undefined;
3
+ export declare function serializeLayouts(nestedLayouts: LayoutItem[], projectDir: string): Array<{
4
+ kind: LayoutItem["kind"];
5
+ path: string;
6
+ }>;
7
+ export declare function serializeLayoutProps(layoutProps: Map<string, Record<string, unknown>>): Record<string, Record<string, unknown>>;
8
+ //# sourceMappingURL=pipeline-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-helpers.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/pipeline-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAKvD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEvE;AAED,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,UAAU,EAAE,EAC3B,UAAU,EAAE,MAAM,GACjB,KAAK,CAAC;IAAE,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAUnD;AAED,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAChD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAQzC"}
@@ -0,0 +1,20 @@
1
+ import { extractRelativePath as extractRelativePathShared } from "../../utils/route-path-utils.js";
2
+ const RENDERED_CSS_HASH_RE = /href="\/_vf\/css\/([a-z0-9-]{1,16})\.css"/i;
3
+ export function extractRenderedCssHash(html) {
4
+ return html.match(RENDERED_CSS_HASH_RE)?.[1];
5
+ }
6
+ export function serializeLayouts(nestedLayouts, projectDir) {
7
+ return nestedLayouts
8
+ .filter((layout) => layout.componentPath || layout.path)
9
+ .map((layout) => ({
10
+ kind: layout.kind,
11
+ path: extractRelativePathShared(layout.componentPath || layout.path || "", projectDir),
12
+ }));
13
+ }
14
+ export function serializeLayoutProps(layoutProps) {
15
+ const serialized = {};
16
+ for (const [layoutId, props] of layoutProps.entries()) {
17
+ serialized[layoutId] = props;
18
+ }
19
+ return serialized;
20
+ }
@@ -53,7 +53,6 @@ export declare class RenderPipeline {
53
53
  */
54
54
  clearModuleCache(): void;
55
55
  private loadModule;
56
- private extractRenderedCssHash;
57
56
  private resolveCssFromRenderedHtml;
58
57
  /**
59
58
  * Load modules in parallel and return only successfully loaded ones.
@@ -76,8 +75,6 @@ export declare class RenderPipeline {
76
75
  /** Resolve page data for SPA client-side navigation without rendering HTML. */
77
76
  resolvePageData(slug: string, options?: RenderOptions): Promise<PageDataResponse>;
78
77
  private extractMdxMetadata;
79
- private serializeLayouts;
80
- private serializeLayoutProps;
81
78
  private resolveAppPath;
82
79
  private resolveProjectUpdatedAt;
83
80
  private resolvePageDataCss;
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAgBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA6ChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACxE,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,gBAAgB,EAAE,wBAAwB,CAAC;IAC3C,YAAY,EAAE,YAAY,CAAC;IAC3B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,OAAO,qBAAqB,EAAE,sBAAsB,CAAC;CAC1E;AAyBD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,kBAAkB,CAAqB;gBAEnC,MAAM,EAAE,oBAAoB;IAaxC;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAKxB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,sBAAsB;YAIhB,0BAA0B;IAaxC;;;;;;;;;OASG;YACW,qBAAqB;IAyDnC;;;OAGG;YACW,mBAAmB;IAiGjC,OAAO,CAAC,uBAAuB;IAkCzB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA+P9E,+EAA+E;IACzE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;YA+EzE,kBAAkB;IA2ChC,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,oBAAoB;YAYd,cAAc;IAW5B,OAAO,CAAC,uBAAuB;YAYjB,kBAAkB;YAmElB,uBAAuB;IAmBrC;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;CAetB"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../../src/src/rendering/orchestrator/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAqBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AA2ChF,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACxE,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,YAAY,CAAC;IAC3B,gBAAgB,EAAE,wBAAwB,CAAC;IAC3C,YAAY,EAAE,YAAY,CAAC;IAC3B,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,OAAO,qBAAqB,EAAE,sBAAsB,CAAC;CAC1E;AAyBD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,kBAAkB,CAAqB;gBAEnC,MAAM,EAAE,oBAAoB;IAaxC;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAKxB,OAAO,CAAC,UAAU;YAIJ,0BAA0B;IAaxC;;;;;;;;;OASG;YACW,qBAAqB;IAyDnC;;;OAGG;YACW,mBAAmB;IAiGjC,OAAO,CAAC,uBAAuB;IAkCzB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA+P9E,+EAA+E;IACzE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;YA+EzE,kBAAkB;YA2ClB,cAAc;IAW5B,OAAO,CAAC,uBAAuB;YAYjB,kBAAkB;YAmElB,uBAAuB;IAmBrC;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;CAetB"}
@@ -22,6 +22,7 @@ import { VeryfrontError } from "../../errors/index.js";
22
22
  import { FILE_NOT_FOUND, RENDER_ERROR } from "../../errors/error-registry.js";
23
23
  import { buildQueryAwareCacheKey } from "../../cache/keys.js";
24
24
  import { extractRelativePath as extractRelativePathShared, extractRouteParams as extractRouteParamsShared, } from "../../utils/route-path-utils.js";
25
+ import { extractRenderedCssHash, serializeLayoutProps, serializeLayouts, } from "./pipeline-helpers.js";
25
26
  import { join } from "../../platform/compat/path/index.js";
26
27
  import { isExtendedFSAdapter } from "../../platform/adapters/fs/wrapper.js";
27
28
  import { DataFetcher } from "../../data/index.js";
@@ -40,7 +41,6 @@ import { collectModulesToLoad, DATA_FETCH_TIMEOUT_MS, hasDataFetchingFunction, M
40
41
  const renderPageLog = logger.component("render-page");
41
42
  const renderPipelineLog = logger.component("render-pipeline");
42
43
  const resolvePageDataLog = logger.component("resolve-page-data");
43
- const RENDERED_CSS_HASH_RE = /href="\/_vf\/css\/([a-z0-9-]{1,16})\.css"/i;
44
44
  // Re-export test helper for backward compatibility
45
45
  export { __injectCssCacheForTests } from "./css-cache.js";
46
46
  export class RenderPipeline {
@@ -70,11 +70,8 @@ export class RenderPipeline {
70
70
  loadModule(filePath) {
71
71
  return loadModule(filePath, this.moduleLoaderConfig);
72
72
  }
73
- extractRenderedCssHash(html) {
74
- return html.match(RENDERED_CSS_HASH_RE)?.[1];
75
- }
76
73
  async resolveCssFromRenderedHtml(html, projectSlug) {
77
- const cssHash = this.extractRenderedCssHash(html);
74
+ const cssHash = extractRenderedCssHash(html);
78
75
  if (!cssHash)
79
76
  return undefined;
80
77
  const cachedCss = await getCSSByHashAsync(cssHash);
@@ -407,9 +404,9 @@ export class RenderPipeline {
407
404
  const dataResolution = await this.resolveDataFetching(slug, pageInfo.entity.path, layoutResult.nestedLayouts, options);
408
405
  const pageProps = dataResolution.pageProps;
409
406
  const params = dataResolution.params;
410
- const layoutProps = this.serializeLayoutProps(dataResolution.layoutProps);
407
+ const layoutProps = serializeLayoutProps(dataResolution.layoutProps);
411
408
  const { frontmatter, headings } = await this.extractMdxMetadata(pageType, pageInfo, slug, options, params);
412
- const layouts = this.serializeLayouts(layoutResult.nestedLayouts);
409
+ const layouts = serializeLayouts(layoutResult.nestedLayouts, this.config.projectDir);
413
410
  const providers = [];
414
411
  const projectUpdatedAt = this.resolveProjectUpdatedAt();
415
412
  const appPath = await this.resolveAppPath();
@@ -469,21 +466,6 @@ export class RenderPipeline {
469
466
  return { frontmatter: {}, headings: [] };
470
467
  }
471
468
  }
472
- serializeLayouts(nestedLayouts) {
473
- return nestedLayouts
474
- .filter((layout) => layout.componentPath || layout.path)
475
- .map((layout) => ({
476
- kind: layout.kind,
477
- path: extractRelativePathShared(layout.componentPath || layout.path || "", this.config.projectDir),
478
- }));
479
- }
480
- serializeLayoutProps(layoutProps) {
481
- const serialized = {};
482
- for (const [layoutId, props] of layoutProps.entries()) {
483
- serialized[layoutId] = props;
484
- }
485
- return serialized;
486
- }
487
469
  async resolveAppPath() {
488
470
  for (const ext of LAYOUT_EXTENSIONS) {
489
471
  const candidatePath = join(this.config.projectDir, `components/app.${ext}`);
@@ -0,0 +1,10 @@
1
+ export declare const FILE_EXTENSIONS: string[];
2
+ /**
3
+ * Validates that a module path is contained within the project directory.
4
+ * Prevents path traversal attacks that could load arbitrary files from the host.
5
+ */
6
+ export declare function validateModulePath(modulePath: string, projectDir: string): void;
7
+ export declare function resolveExportEntry(entry: unknown): string | undefined;
8
+ export declare function toCjsDestructureBindings(bindings: string): string;
9
+ export declare function getLoaderForFile(filePath: string): "tsx" | "jsx" | "ts" | "js" | "json";
10
+ //# sourceMappingURL=loader-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader-helpers.d.ts","sourceRoot":"","sources":["../../../../../src/src/routing/api/module-loader/loader-helpers.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,eAAe,EAAE,MAAM,EAA+C,CAAC;AAEpF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAY/E;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAcrE;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAejE;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAGvF"}
@@ -0,0 +1,62 @@
1
+ import * as pathHelper from "../../../platform/compat/path/index.js";
2
+ import { createError, toError } from "../../../errors/veryfront-error.js";
3
+ import { isWithinDirectory } from "../../../security/path-validation.js";
4
+ const EXT_TO_LOADER = {
5
+ tsx: "tsx",
6
+ jsx: "jsx",
7
+ ts: "ts",
8
+ json: "json",
9
+ };
10
+ export const FILE_EXTENSIONS = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs"];
11
+ /**
12
+ * Validates that a module path is contained within the project directory.
13
+ * Prevents path traversal attacks that could load arbitrary files from the host.
14
+ */
15
+ export function validateModulePath(modulePath, projectDir) {
16
+ const resolved = pathHelper.resolve(modulePath);
17
+ const resolvedProject = pathHelper.resolve(projectDir);
18
+ if (!isWithinDirectory(resolvedProject, resolved)) {
19
+ throw toError(createError({
20
+ type: "api",
21
+ message: `[API] module path escapes project directory: ${modulePath}`,
22
+ }));
23
+ }
24
+ }
25
+ export function resolveExportEntry(entry) {
26
+ if (typeof entry === "string")
27
+ return entry;
28
+ if (entry && typeof entry === "object") {
29
+ const obj = entry;
30
+ for (const key of ["import", "default"]) {
31
+ const value = obj[key];
32
+ if (typeof value === "string")
33
+ return value;
34
+ if (value && typeof value === "object") {
35
+ const nested = value;
36
+ if (typeof nested.default === "string")
37
+ return nested.default;
38
+ }
39
+ }
40
+ }
41
+ return undefined;
42
+ }
43
+ export function toCjsDestructureBindings(bindings) {
44
+ const inner = bindings.trim().replace(/^\{\s*/, "").replace(/\s*\}$/, "");
45
+ if (!inner)
46
+ return "{}";
47
+ const converted = inner
48
+ .split(",")
49
+ .map((part) => part.trim())
50
+ .filter(Boolean)
51
+ .map((part) => {
52
+ const aliasMatch = part.match(/^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)$/);
53
+ if (aliasMatch)
54
+ return `${aliasMatch[1]}: ${aliasMatch[2]}`;
55
+ return part;
56
+ });
57
+ return `{ ${converted.join(", ")} }`;
58
+ }
59
+ export function getLoaderForFile(filePath) {
60
+ const ext = filePath.split(".").pop() ?? "";
61
+ return EXT_TO_LOADER[ext] ?? "js";
62
+ }
@@ -1,6 +1,6 @@
1
1
  import type { APIRoute, LoadModuleOptions } from "./types.js";
2
2
  import type { FileSystem } from "../../../platform/compat/fs.js";
3
- export declare function toCjsDestructureBindings(bindings: string): string;
3
+ export { toCjsDestructureBindings } from "./loader-helpers.js";
4
4
  export declare function loadHandlerModule(options: LoadModuleOptions): Promise<APIRoute | null>;
5
5
  export declare function getNodeExternalPackagesToResolve(userDeps: Map<string, string>): string[];
6
6
  export declare function resolveNodePackageToFileUrl(projectDir: string, packageName: string, fs: FileSystem, pathToFileURL: typeof import("node:url").pathToFileURL): Promise<string | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../../src/src/routing/api/module-loader/loader.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAI9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AA4KjE,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAejE;AAgBD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAyBtF;AAuaD,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAUxF;AAED,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,cAAc,UAAU,EAAE,aAAa,GACrD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoBxB;AAED,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,GACb,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAW9C;AAED,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CA6EjB;AAED,wBAAgB,qCAAqC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqB1E;AAED,wBAAgB,0CAA0C,CACxD,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,MAAM,CAoDR;AAED,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CA0BjB;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBlE"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../../src/src/routing/api/module-loader/loader.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAI9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAkBjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAgI/D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAyBtF;AAuaD,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAUxF;AAED,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,UAAU,EACd,aAAa,EAAE,cAAc,UAAU,EAAE,aAAa,GACrD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoBxB;AAED,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,GACb,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAW9C;AAED,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CA6EjB;AAED,wBAAgB,qCAAqC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAqB1E;AAED,wBAAgB,0CAA0C,CACxD,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,MAAM,CAoDR;AAED,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CA0BjB;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBlE"}
@@ -7,6 +7,7 @@ import { createError, toError } from "../../../errors/veryfront-error.js";
7
7
  import { getEsbuildLoader } from "../../../utils/path-utils.js";
8
8
  import { createFileSystem } from "../../../platform/compat/fs.js";
9
9
  import * as pathHelper from "../../../platform/compat/path/index.js";
10
+ import { FILE_EXTENSIONS, getLoaderForFile, resolveExportEntry, toCjsDestructureBindings, validateModulePath, } from "./loader-helpers.js";
10
11
  import { isDeno, isNode } from "../../../platform/compat/runtime.js";
11
12
  import { withSpan } from "../../../observability/tracing/otlp-setup.js";
12
13
  import { isCompiledBinary } from "../../../utils/index.js";
@@ -14,20 +15,7 @@ import { wrapWithCurrentContext } from "../../../platform/adapters/fs/veryfront/
14
15
  import { isWithinDirectory } from "../../../security/path-validation.js";
15
16
  import { rewriteNpmImports } from "../../../transforms/npm-import-rewrites.js";
16
17
  const logger = serverLogger.component("api");
17
- /**
18
- * Validates that a module path is contained within the project directory.
19
- * Prevents path traversal attacks that could load arbitrary files from the host.
20
- */
21
- function validateModulePath(modulePath, projectDir) {
22
- const resolved = pathHelper.resolve(modulePath);
23
- const resolvedProject = pathHelper.resolve(projectDir);
24
- if (!isWithinDirectory(resolvedProject, resolved)) {
25
- throw toError(createError({
26
- type: "api",
27
- message: `[API] module path escapes project directory: ${modulePath}`,
28
- }));
29
- }
30
- }
18
+ export { toCjsDestructureBindings } from "./loader-helpers.js";
31
19
  /** Node.js built-in module names — shared across the CJS shim, esbuild externals, and Deno rewrites. */
32
20
  const NODE_BUILTINS = [
33
21
  "assert",
@@ -148,52 +136,6 @@ require.resolve = function(id) { return __vf_builtinRequire.resolve(id); };
148
136
  require.ensure = function(mods, cb) { cb(); };
149
137
  `.trim();
150
138
  }
151
- function resolveExportEntry(entry) {
152
- if (typeof entry === "string")
153
- return entry;
154
- if (entry && typeof entry === "object") {
155
- const obj = entry;
156
- // Prefer import > default > first string value
157
- for (const key of ["import", "default"]) {
158
- const val = obj[key];
159
- if (typeof val === "string")
160
- return val;
161
- if (val && typeof val === "object") {
162
- const nested = val;
163
- if (typeof nested.default === "string")
164
- return nested.default;
165
- }
166
- }
167
- }
168
- return undefined;
169
- }
170
- export function toCjsDestructureBindings(bindings) {
171
- const inner = bindings.trim().replace(/^\{\s*/, "").replace(/\s*\}$/, "");
172
- if (!inner)
173
- return "{}";
174
- const converted = inner
175
- .split(",")
176
- .map((part) => part.trim())
177
- .filter(Boolean)
178
- .map((part) => {
179
- const aliasMatch = part.match(/^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)$/);
180
- if (aliasMatch)
181
- return `${aliasMatch[1]}: ${aliasMatch[2]}`;
182
- return part;
183
- });
184
- return `{ ${converted.join(", ")} }`;
185
- }
186
- const FILE_EXTENSIONS = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs"];
187
- const EXT_TO_LOADER = {
188
- tsx: "tsx",
189
- jsx: "jsx",
190
- ts: "ts",
191
- json: "json",
192
- };
193
- function getLoaderForFile(filePath) {
194
- const ext = filePath.split(".").pop() ?? "";
195
- return EXT_TO_LOADER[ext] ?? "js";
196
- }
197
139
  export function loadHandlerModule(options) {
198
140
  return withSpan("api.loadHandlerModule", async () => {
199
141
  const { projectDir, modulePath, adapter, config } = options;
@@ -1,5 +1,6 @@
1
1
  import type { RuntimeAdapter } from "../platform/adapters/base.js";
2
2
  import type { VeryfrontConfig } from "../config/index.js";
3
+ import { type ExtensionLoader } from "../extensions/index.js";
3
4
  export interface BootstrapResult {
4
5
  /** Enhanced runtime adapter (with FSAdapter if configured) */
5
6
  adapter: RuntimeAdapter;
@@ -9,9 +10,28 @@ export interface BootstrapResult {
9
10
  usingFSAdapter: boolean;
10
11
  /** FSAdapter type (if used) */
11
12
  fsAdapterType?: string;
12
- /** Dispose FSAdapter resources (WebSocket connections, caches) */
13
- dispose?: () => void;
13
+ /**
14
+ * Extension loader that ran setup for all discovered extensions.
15
+ * Even when no extensions exist, a loader instance is present so callers
16
+ * can safely invoke `teardownAll()` unconditionally.
17
+ */
18
+ extensionLoader: ExtensionLoader;
19
+ /**
20
+ * Dispose bootstrap resources: tears down extensions (reverse order),
21
+ * then releases any FSAdapter resources (WebSocket connections, caches).
22
+ */
23
+ dispose?: () => void | Promise<void>;
14
24
  }
25
+ /**
26
+ * Run extension orchestration, disposing the FS adapter if orchestration fails.
27
+ *
28
+ * Exported for unit testing. In the FS-adapter path the caller has already
29
+ * allocated FS resources (WebSocket connections, caches) that must be
30
+ * released before the bootstrap error propagates.
31
+ *
32
+ * @internal
33
+ */
34
+ export declare function orchestrateOrDisposeFS(orchestrate: () => Promise<ExtensionLoader>, fsDispose: (() => void) | undefined): Promise<ExtensionLoader>;
15
35
  export declare function bootstrap(projectDir: string, adapter: RuntimeAdapter): Promise<BootstrapResult>;
16
36
  export declare function bootstrapDev(projectDir: string, adapter: RuntimeAdapter): Promise<BootstrapResult>;
17
37
  export declare function bootstrapProd(projectDir: string, adapter: RuntimeAdapter): Promise<BootstrapResult>;
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../src/src/server/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AA6B1D,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,OAAO,EAAE,cAAc,CAAC;IAExB,2BAA2B;IAC3B,MAAM,EAAE,eAAe,CAAC;IAExB,wCAAwC;IACxC,cAAc,EAAE,OAAO,CAAC;IAExB,+BAA+B;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAkDD,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,eAAe,CAAC,CAqG1B;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,eAAe,CAAC,CAa1B;AAED,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,eAAe,CAAC,CAyB1B"}
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../src/src/server/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG1D,OAAO,EAAE,KAAK,eAAe,EAAyB,MAAM,wBAAwB,CAAC;AA2BrF,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,OAAO,EAAE,cAAc,CAAC;IAExB,2BAA2B;IAC3B,MAAM,EAAE,eAAe,CAAC;IAExB,wCAAwC;IACxC,cAAc,EAAE,OAAO,CAAC;IAExB,+BAA+B;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,eAAe,EAAE,eAAe,CAAC;IAEjC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAeD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,EAC3C,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAClC,OAAO,CAAC,eAAe,CAAC,CAO1B;AAkDD,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,eAAe,CAAC,CAyI1B;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,eAAe,CAAC,CAa1B;AAED,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,eAAe,CAAC,CAyB1B"}
@@ -1,4 +1,5 @@
1
1
  import { clearConfigCache, getConfig } from "../config/index.js";
2
+ import { orchestrateExtensions } from "../extensions/index.js";
2
3
  import { getEnvironmentConfig, refreshEnvironmentConfig, } from "../config/environment-config.js";
3
4
  import { getErrorMessage } from "../errors/veryfront-error.js";
4
5
  import { INVALID_ARGUMENT } from "../errors/index.js";
@@ -14,6 +15,36 @@ import { clearDomainCache } from "./utils/domain-lookup.js";
14
15
  const bootstrapLog = logger.component("bootstrap");
15
16
  const bootstrapDevLog = logger.component("bootstrap-dev");
16
17
  const bootstrapProdLog = logger.component("bootstrap-prod");
18
+ function combineDispose(extensionLoader, fsDispose) {
19
+ return async () => {
20
+ try {
21
+ await extensionLoader.teardownAll();
22
+ }
23
+ finally {
24
+ if (fsDispose)
25
+ fsDispose();
26
+ }
27
+ };
28
+ }
29
+ /**
30
+ * Run extension orchestration, disposing the FS adapter if orchestration fails.
31
+ *
32
+ * Exported for unit testing. In the FS-adapter path the caller has already
33
+ * allocated FS resources (WebSocket connections, caches) that must be
34
+ * released before the bootstrap error propagates.
35
+ *
36
+ * @internal
37
+ */
38
+ export async function orchestrateOrDisposeFS(orchestrate, fsDispose) {
39
+ try {
40
+ return await orchestrate();
41
+ }
42
+ catch (err) {
43
+ if (fsDispose)
44
+ fsDispose();
45
+ throw err;
46
+ }
47
+ }
17
48
  let envLogged = false;
18
49
  async function ensureEnvLoaded(projectDir, adapter) {
19
50
  if (hasEnvLoaded()) {
@@ -72,7 +103,18 @@ export async function bootstrap(projectDir, adapter) {
72
103
  const needsFSAdapter = fsType != null && fsType !== "local";
73
104
  if (!needsFSAdapter) {
74
105
  bootstrapLog.debug("Using local filesystem (no FSAdapter needed)");
75
- return { adapter, config, usingFSAdapter: false };
106
+ const extensionLoader = await orchestrateExtensions({
107
+ projectDir,
108
+ config,
109
+ logger: bootstrapLog,
110
+ });
111
+ return {
112
+ adapter,
113
+ config,
114
+ usingFSAdapter: false,
115
+ extensionLoader,
116
+ dispose: combineDispose(extensionLoader),
117
+ };
76
118
  }
77
119
  bootstrapLog.debug("Initializing FSAdapter", { type: fsType });
78
120
  // Inject server-layer callbacks into FS config so the platform layer
@@ -91,7 +133,18 @@ export async function bootstrap(projectDir, adapter) {
91
133
  runtime: adapter.id,
92
134
  fsAdapter: "local",
93
135
  });
94
- return { adapter, config, usingFSAdapter: false };
136
+ const extensionLoader = await orchestrateExtensions({
137
+ projectDir,
138
+ config,
139
+ logger: bootstrapLog,
140
+ });
141
+ return {
142
+ adapter,
143
+ config,
144
+ usingFSAdapter: false,
145
+ extensionLoader,
146
+ dispose: combineDispose(extensionLoader),
147
+ };
95
148
  }
96
149
  const isProxyMode = config.fs?.veryfront?.proxyMode === true;
97
150
  const isProductionMode = config.fs?.veryfront?.productionMode === true;
@@ -122,20 +175,29 @@ export async function bootstrap(projectDir, adapter) {
122
175
  runtime: adapter.id,
123
176
  fsAdapter: fsType,
124
177
  });
125
- let dispose;
178
+ let fsDispose;
126
179
  if (isExtendedFSAdapter(enhancedAdapter.fs)) {
127
180
  const underlying = enhancedAdapter.fs.getUnderlyingAdapter();
128
181
  if ("dispose" in underlying &&
129
182
  typeof underlying.dispose === "function") {
130
- dispose = () => underlying.dispose();
183
+ fsDispose = () => underlying.dispose();
131
184
  }
132
185
  }
186
+ // If extension orchestration fails after the FS adapter has been wired up,
187
+ // release the FS resources (WebSocket connections, caches) before
188
+ // propagating the error — otherwise the adapter would leak.
189
+ const extensionLoader = await orchestrateOrDisposeFS(() => orchestrateExtensions({
190
+ projectDir,
191
+ config,
192
+ logger: bootstrapLog,
193
+ }), fsDispose);
133
194
  return {
134
195
  adapter: enhancedAdapter,
135
196
  config,
136
197
  usingFSAdapter: true,
137
198
  fsAdapterType: fsType,
138
- dispose,
199
+ extensionLoader,
200
+ dispose: combineDispose(extensionLoader, fsDispose),
139
201
  };
140
202
  }
141
203
  export async function bootstrapDev(projectDir, adapter) {
@@ -11,6 +11,7 @@ declare namespace _default {
11
11
  "dashboard/App.tsx": string;
12
12
  "dashboard/components/AgentsTab.tsx": string;
13
13
  "dashboard/components/Sidebar.tsx": string;
14
+ "dashboard/components/WorkflowsTab.helpers.ts": string;
14
15
  "dashboard/components/WorkflowsTab.tsx": string;
15
16
  "dashboard/components/shared.tsx": string;
16
17
  "dashboard/components/Card.tsx": string;
@@ -23,6 +24,7 @@ declare namespace _default {
23
24
  "dashboard/components/FilesTab.tsx": string;
24
25
  "dashboard/components/APITab.tsx": string;
25
26
  "dashboard/components/AgentTab.tsx": string;
27
+ "dashboard/components/WorkflowsTab.helpers.test.ts": string;
26
28
  "dashboard/components/Header.tsx": string;
27
29
  "dashboard/index.tsx": string;
28
30
  };