veryfront 0.1.367 → 0.1.369

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 (155) hide show
  1. package/esm/cli/commands/init/config-generator.d.ts.map +1 -1
  2. package/esm/cli/commands/init/config-generator.js +1 -0
  3. package/esm/cli/main.js +15 -0
  4. package/esm/deno.d.ts +3 -3
  5. package/esm/deno.js +5 -5
  6. package/esm/extensions/ext-esbuild/src/binary.d.ts +7 -0
  7. package/esm/extensions/ext-esbuild/src/binary.d.ts.map +1 -0
  8. package/esm/extensions/ext-esbuild/src/binary.js +143 -0
  9. package/esm/extensions/ext-esbuild/src/es-module-lexer.d.ts +17 -0
  10. package/esm/extensions/ext-esbuild/src/es-module-lexer.d.ts.map +1 -0
  11. package/esm/extensions/ext-esbuild/src/es-module-lexer.js +29 -0
  12. package/esm/extensions/ext-esbuild/src/esbuild-bundler.d.ts +20 -0
  13. package/esm/extensions/ext-esbuild/src/esbuild-bundler.d.ts.map +1 -0
  14. package/esm/extensions/ext-esbuild/src/esbuild-bundler.js +98 -0
  15. package/esm/extensions/ext-esbuild/src/index.d.ts +19 -0
  16. package/esm/extensions/ext-esbuild/src/index.d.ts.map +1 -0
  17. package/esm/extensions/ext-esbuild/src/index.js +40 -0
  18. package/esm/extensions/ext-esbuild/src/plugin-adapter.d.ts +14 -0
  19. package/esm/extensions/ext-esbuild/src/plugin-adapter.d.ts.map +1 -0
  20. package/esm/extensions/ext-esbuild/src/plugin-adapter.js +55 -0
  21. package/esm/extensions/ext-esbuild/src/runtime.d.ts +4 -0
  22. package/esm/extensions/ext-esbuild/src/runtime.d.ts.map +1 -0
  23. package/esm/extensions/ext-esbuild/src/runtime.js +43 -0
  24. package/esm/src/agent/conversation-bootstrap.d.ts +1 -1
  25. package/esm/src/agent/conversation-bootstrap.d.ts.map +1 -1
  26. package/esm/src/agent/conversation-bootstrap.js +1 -1
  27. package/esm/src/agent/conversation-root-run-context.d.ts +3 -3
  28. package/esm/src/agent/conversation-root-run-context.d.ts.map +1 -1
  29. package/esm/src/agent/conversation-root-run-context.js +3 -3
  30. package/esm/src/agent/durable.d.ts +1 -1
  31. package/esm/src/agent/durable.d.ts.map +1 -1
  32. package/esm/src/agent/durable.js +2 -2
  33. package/esm/src/agent/fork-runtime-stream.d.ts +11 -1
  34. package/esm/src/agent/fork-runtime-stream.d.ts.map +1 -1
  35. package/esm/src/agent/fork-runtime-stream.js +36 -0
  36. package/esm/src/agent/hosted-child-bootstrap.d.ts +1 -1
  37. package/esm/src/agent/hosted-child-bootstrap.d.ts.map +1 -1
  38. package/esm/src/agent/hosted-child-bootstrap.js +1 -1
  39. package/esm/src/agent/index.d.ts +1 -1
  40. package/esm/src/agent/index.d.ts.map +1 -1
  41. package/esm/src/agent/index.js +1 -1
  42. package/esm/src/build/bundler/code-splitter/build-context.d.ts +1 -1
  43. package/esm/src/build/bundler/code-splitter/build-context.d.ts.map +1 -1
  44. package/esm/src/build/bundler/code-splitter/build-context.js +1 -1
  45. package/esm/src/build/bundler/code-splitter/esbuild-plugin.d.ts +1 -1
  46. package/esm/src/build/bundler/code-splitter/esbuild-plugin.d.ts.map +1 -1
  47. package/esm/src/build/bundler/code-splitter/manifest-builder.d.ts +1 -1
  48. package/esm/src/build/bundler/code-splitter/manifest-builder.d.ts.map +1 -1
  49. package/esm/src/build/bundler/code-splitter/types.d.ts +1 -1
  50. package/esm/src/build/bundler/code-splitter/types.d.ts.map +1 -1
  51. package/esm/src/build/compiler/mdx-compiler/transpiler.js +1 -1
  52. package/esm/src/build/compiler/mdx-to-js.js +1 -1
  53. package/esm/src/build/embedded/preset.js +1 -1
  54. package/esm/src/build/production-build/client-runtime.js +1 -1
  55. package/esm/src/discovery/transpiler.js +1 -1
  56. package/esm/src/extensions/bundler.d.ts +28 -0
  57. package/esm/src/extensions/bundler.d.ts.map +1 -0
  58. package/esm/src/extensions/bundler.js +42 -0
  59. package/esm/src/extensions/interfaces/bundler.d.ts +162 -27
  60. package/esm/src/extensions/interfaces/bundler.d.ts.map +1 -1
  61. package/esm/src/extensions/interfaces/index.d.ts +2 -1
  62. package/esm/src/extensions/interfaces/index.d.ts.map +1 -1
  63. package/esm/src/extensions/interfaces/module-lexer.d.ts +45 -0
  64. package/esm/src/extensions/interfaces/module-lexer.d.ts.map +1 -0
  65. package/esm/src/extensions/interfaces/module-lexer.js +13 -0
  66. package/esm/src/extensions/loader.d.ts.map +1 -1
  67. package/esm/src/extensions/loader.js +7 -1
  68. package/esm/src/extensions/recommendations.d.ts.map +1 -1
  69. package/esm/src/extensions/recommendations.js +3 -0
  70. package/esm/src/platform/compat/esbuild.d.ts +20 -6
  71. package/esm/src/platform/compat/esbuild.d.ts.map +1 -1
  72. package/esm/src/platform/compat/esbuild.js +20 -137
  73. package/esm/src/rendering/script-page-handling.js +1 -1
  74. package/esm/src/routing/api/module-loader/esbuild-plugin.d.ts +1 -1
  75. package/esm/src/routing/api/module-loader/esbuild-plugin.d.ts.map +1 -1
  76. package/esm/src/routing/api/module-loader/loader.js +1 -1
  77. package/esm/src/server/bootstrap.d.ts.map +1 -1
  78. package/esm/src/server/bootstrap.js +22 -0
  79. package/esm/src/server/dev-server/middleware.js +1 -1
  80. package/esm/src/server/handlers/dev/files/esbuild-plugins.d.ts +1 -1
  81. package/esm/src/server/handlers/dev/files/esbuild-plugins.d.ts.map +1 -1
  82. package/esm/src/server/handlers/studio/bridge-modules.handler.js +1 -1
  83. package/esm/src/server/services/rsc/endpoints/script-handlers.js +1 -1
  84. package/esm/src/server/services/rsc/orchestrators/hydrator-handler.js +1 -1
  85. package/esm/src/server/shared/browser-module-bundler.js +1 -1
  86. package/esm/src/testing/bdd.d.ts +1 -0
  87. package/esm/src/testing/bdd.d.ts.map +1 -1
  88. package/esm/src/testing/bdd.js +1 -0
  89. package/esm/src/testing/init.js +7 -0
  90. package/esm/src/transforms/esm/http-bundler.d.ts +1 -1
  91. package/esm/src/transforms/esm/http-bundler.d.ts.map +1 -1
  92. package/esm/src/transforms/esm/lexer.d.ts +2 -9
  93. package/esm/src/transforms/esm/lexer.d.ts.map +1 -1
  94. package/esm/src/transforms/esm/lexer.js +9 -10
  95. package/esm/src/transforms/esm/transform-utils.d.ts +1 -1
  96. package/esm/src/transforms/esm/transform-utils.d.ts.map +1 -1
  97. package/esm/src/transforms/import-rewriter/parse-cache.d.ts +1 -1
  98. package/esm/src/transforms/import-rewriter/parse-cache.d.ts.map +1 -1
  99. package/esm/src/transforms/import-rewriter/parse-cache.js +8 -7
  100. package/esm/src/transforms/mdx/esm-module-loader/import-transformer.js +1 -1
  101. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.js +2 -2
  102. package/esm/src/utils/version-constant.d.ts +1 -1
  103. package/esm/src/utils/version-constant.js +1 -1
  104. package/package.json +1 -1
  105. package/src/cli/commands/init/config-generator.ts +1 -0
  106. package/src/cli/main.ts +14 -0
  107. package/src/deno.js +5 -5
  108. package/src/extensions/ext-esbuild/src/binary.ts +154 -0
  109. package/src/extensions/ext-esbuild/src/es-module-lexer.ts +34 -0
  110. package/src/extensions/ext-esbuild/src/esbuild-bundler.ts +122 -0
  111. package/src/extensions/ext-esbuild/src/index.ts +46 -0
  112. package/src/extensions/ext-esbuild/src/plugin-adapter.ts +66 -0
  113. package/src/extensions/ext-esbuild/src/runtime.ts +54 -0
  114. package/src/src/agent/conversation-bootstrap.ts +2 -2
  115. package/src/src/agent/conversation-root-run-context.ts +6 -6
  116. package/src/src/agent/durable.ts +3 -3
  117. package/src/src/agent/fork-runtime-stream.ts +61 -1
  118. package/src/src/agent/hosted-child-bootstrap.ts +2 -2
  119. package/src/src/agent/index.ts +2 -0
  120. package/src/src/build/bundler/code-splitter/build-context.ts +1 -1
  121. package/src/src/build/bundler/code-splitter/esbuild-plugin.ts +1 -1
  122. package/src/src/build/bundler/code-splitter/manifest-builder.ts +1 -1
  123. package/src/src/build/bundler/code-splitter/splitter.ts +1 -1
  124. package/src/src/build/bundler/code-splitter/types.ts +1 -1
  125. package/src/src/build/compiler/mdx-compiler/transpiler.ts +1 -1
  126. package/src/src/build/compiler/mdx-to-js.ts +1 -1
  127. package/src/src/build/embedded/preset.ts +1 -1
  128. package/src/src/build/production-build/client-runtime.ts +2 -2
  129. package/src/src/discovery/transpiler.ts +2 -2
  130. package/src/src/extensions/bundler.ts +85 -0
  131. package/src/src/extensions/interfaces/bundler.ts +189 -16
  132. package/src/src/extensions/interfaces/index.ts +16 -0
  133. package/src/src/extensions/interfaces/module-lexer.ts +46 -0
  134. package/src/src/extensions/loader.ts +6 -1
  135. package/src/src/extensions/recommendations.ts +3 -0
  136. package/src/src/platform/compat/esbuild.ts +48 -160
  137. package/src/src/rendering/script-page-handling.ts +1 -1
  138. package/src/src/routing/api/module-loader/esbuild-plugin.ts +1 -1
  139. package/src/src/routing/api/module-loader/loader.ts +2 -2
  140. package/src/src/server/bootstrap.ts +29 -0
  141. package/src/src/server/dev-server/middleware.ts +1 -1
  142. package/src/src/server/handlers/dev/files/esbuild-plugins.ts +1 -1
  143. package/src/src/server/handlers/studio/bridge-modules.handler.ts +1 -1
  144. package/src/src/server/services/rsc/endpoints/script-handlers.ts +4 -4
  145. package/src/src/server/services/rsc/orchestrators/hydrator-handler.ts +1 -1
  146. package/src/src/server/shared/browser-module-bundler.ts +1 -1
  147. package/src/src/testing/bdd.ts +1 -0
  148. package/src/src/testing/init.ts +9 -0
  149. package/src/src/transforms/esm/http-bundler.ts +1 -1
  150. package/src/src/transforms/esm/lexer.ts +13 -21
  151. package/src/src/transforms/esm/transform-utils.ts +1 -1
  152. package/src/src/transforms/import-rewriter/parse-cache.ts +10 -7
  153. package/src/src/transforms/mdx/esm-module-loader/import-transformer.ts +1 -1
  154. package/src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts +2 -2
  155. package/src/src/utils/version-constant.ts +1 -1
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Bundler contract resolution helper.
3
+ *
4
+ * Core code uses this thin wrapper instead of importing `esbuild` directly,
5
+ * so the bundler implementation lives in `@veryfront/ext-esbuild` (or any
6
+ * other extension that satisfies the contract).
7
+ *
8
+ * @module extensions/bundler
9
+ */
10
+
11
+ import { resolve as resolveContract } from "./contracts.js";
12
+ import type {
13
+ BuildContext,
14
+ BundleOptions,
15
+ Bundler,
16
+ BundleResult,
17
+ TransformOptions,
18
+ TransformResult,
19
+ } from "./interfaces/bundler.js";
20
+
21
+ /** Resolve the registered `Bundler` contract. Throws if no extension provides it. */
22
+ export function getBundler(): Bundler {
23
+ return resolveContract<Bundler>("Bundler");
24
+ }
25
+
26
+ /** Convenience wrapper: `bundler.bundle(opts)`. */
27
+ export function build(options: BundleOptions): Promise<BundleResult> {
28
+ return getBundler().bundle(options);
29
+ }
30
+
31
+ /**
32
+ * Convenience wrapper that mirrors esbuild's `transform(code, options)`
33
+ * positional signature so call-sites migrating off esbuild keep their shape.
34
+ */
35
+ export function transform(
36
+ code: string,
37
+ options: Omit<TransformOptions, "code"> = {},
38
+ ): Promise<TransformResult> {
39
+ return getBundler().transform({ code, ...options });
40
+ }
41
+
42
+ /**
43
+ * Stop the bundler. Optional — extension teardown will also call this. Provided
44
+ * so tests that previously called `esbuild.stop()` keep working.
45
+ */
46
+ export async function stop(): Promise<void> {
47
+ const b = getBundler();
48
+ if (b.stop) await b.stop();
49
+ }
50
+
51
+ /** Create an incremental build context (watch/rebuild mode). */
52
+ export function context(options: BundleOptions): Promise<BuildContext> {
53
+ const b = getBundler();
54
+ if (!b.context) {
55
+ throw new Error("Registered Bundler extension does not support context() (incremental builds)");
56
+ }
57
+ return b.context(options);
58
+ }
59
+
60
+ export type {
61
+ BuildContext,
62
+ BuildFailure,
63
+ BundleOptions,
64
+ BundleOptions as BuildOptions,
65
+ BundleOutput,
66
+ Bundler,
67
+ BundleResult,
68
+ BundleResult as BuildResult,
69
+ BundlerMessage,
70
+ BundlerMessage as Message,
71
+ BundlerPlugin,
72
+ BundlerPlugin as Plugin,
73
+ BundlerPluginBuild,
74
+ BundlerPluginBuild as PluginBuild,
75
+ Loader,
76
+ Metafile,
77
+ OnLoadArgs,
78
+ OnLoadResult,
79
+ OnResolveArgs,
80
+ OnResolveResult,
81
+ OnResolveResult as ResolveResult,
82
+ StdinOptions,
83
+ TransformOptions,
84
+ TransformResult,
85
+ } from "./interfaces/bundler.js";
@@ -6,12 +6,61 @@
6
6
  * @module extensions/interfaces/bundler
7
7
  */
8
8
 
9
+ /** Location of an error or warning in source. */
10
+ export interface BundlerMessageLocation {
11
+ file: string;
12
+ line: number;
13
+ column: number;
14
+ length?: number;
15
+ lineText?: string;
16
+ }
17
+
18
+ /** A diagnostic message (error or warning) from a bundler. */
19
+ export interface BundlerMessage {
20
+ text: string;
21
+ location?: BundlerMessageLocation | null;
22
+ notes?: { text: string; location?: BundlerMessageLocation | null }[];
23
+ pluginName?: string;
24
+ detail?: unknown;
25
+ }
26
+
27
+ /** Input file entry in a {@link Metafile}. */
28
+ export interface MetafileInput {
29
+ bytes: number;
30
+ imports: { path: string; kind?: string; external?: boolean; original?: string }[];
31
+ format?: "cjs" | "esm";
32
+ }
33
+
34
+ /** Output file entry in a {@link Metafile}. */
35
+ export interface MetafileOutput {
36
+ bytes: number;
37
+ inputs: Record<string, { bytesInOutput: number }>;
38
+ imports: { path: string; kind?: string; external?: boolean }[];
39
+ exports: string[];
40
+ entryPoint?: string;
41
+ cssBundle?: string;
42
+ }
43
+
44
+ /** Dependency-graph metadata produced by a bundler when `metafile: true`. */
45
+ export interface Metafile {
46
+ inputs: Record<string, MetafileInput>;
47
+ outputs: Record<string, MetafileOutput>;
48
+ }
49
+
50
+ /** In-memory source input for {@link BundleOptions.stdin}. */
51
+ export interface StdinOptions {
52
+ contents: string;
53
+ resolveDir?: string;
54
+ sourcefile?: string;
55
+ loader?: Loader | string;
56
+ }
57
+
9
58
  /** Options passed to {@link Bundler.bundle}. */
10
59
  export interface BundleOptions {
11
- /** Entry point file paths. */
12
- entryPoints: string[];
60
+ /** Entry point file paths, or a `{ outputName: inputPath }` map. */
61
+ entryPoints?: string[] | Record<string, string>;
13
62
  /** Output directory. */
14
- outdir: string;
63
+ outdir?: string;
15
64
  /** Bundle format (`esm`, `cjs`, `iife`). */
16
65
  format?: "esm" | "cjs" | "iife";
17
66
  /** Target environment(s). */
@@ -19,11 +68,37 @@ export interface BundleOptions {
19
68
  /** Enable minification. */
20
69
  minify?: boolean;
21
70
  /** Enable source maps. */
22
- sourcemap?: boolean | "inline" | "external";
71
+ sourcemap?: boolean | "inline" | "external" | "linked" | "both";
23
72
  /** Enable code splitting. */
24
73
  splitting?: boolean;
25
74
  /** Additional plugins. */
26
75
  plugins?: BundlerPlugin[];
76
+
77
+ /** Whether to bundle dependencies into the output (vs. leaving imports as-is). */
78
+ bundle?: boolean;
79
+ /** Write output to disk; when false, returns bytes in-memory only. */
80
+ write?: boolean;
81
+ /** Target platform influencing default externals and resolution. */
82
+ platform?: "browser" | "node" | "neutral";
83
+ /** Packages/paths to exclude from the bundle. */
84
+ external?: string[];
85
+ /** Bundle an in-memory source string instead of reading from disk. */
86
+ stdin?: StdinOptions;
87
+ /** Compile-time constant replacements, e.g. `{ "process.env.NODE_ENV": '"production"' }`. */
88
+ define?: Record<string, string>;
89
+ /** JSX transform mode. */
90
+ jsx?: "transform" | "preserve" | "automatic";
91
+ /** Module specifier used for the automatic JSX runtime import. */
92
+ jsxImportSource?: string;
93
+ /** File extensions to try during import resolution. */
94
+ resolveExtensions?: string[];
95
+ /** Drop unused exports and dead code. */
96
+ treeShaking?: boolean;
97
+ /** Verbosity of diagnostic output. */
98
+ logLevel?: "silent" | "error" | "warning" | "info" | "debug" | "verbose";
99
+ /** Emit a dependency-graph {@link Metafile} in the result. */
100
+ metafile?: boolean;
101
+
27
102
  /** Extra implementation-specific options. */
28
103
  [key: string]: unknown;
29
104
  }
@@ -34,24 +109,47 @@ export interface BundleOutput {
34
109
  path: string;
35
110
  /** Raw byte content. */
36
111
  contents: Uint8Array;
112
+ /** Lazy-decoded UTF-8 string view of `contents`. */
113
+ text: string;
114
+ /** Optional content hash. */
115
+ hash?: string;
37
116
  }
38
117
 
39
118
  /** Result returned from {@link Bundler.bundle}. */
40
119
  export interface BundleResult {
41
120
  /** Output files produced by the bundle. */
42
- outputs: BundleOutput[];
121
+ outputFiles: BundleOutput[];
43
122
  /** Warnings emitted during bundling. */
44
- warnings: string[];
123
+ warnings: BundlerMessage[];
45
124
  /** Errors encountered during bundling. */
46
- errors: string[];
125
+ errors: BundlerMessage[];
126
+ /** Dependency-graph metadata, populated when `metafile: true`. */
127
+ metafile?: Metafile;
47
128
  }
48
129
 
130
+ /** Loader hint for source files. Mirrors esbuild's `Loader` type. */
131
+ export type Loader =
132
+ | "js"
133
+ | "jsx"
134
+ | "ts"
135
+ | "tsx"
136
+ | "css"
137
+ | "json"
138
+ | "text"
139
+ | "base64"
140
+ | "file"
141
+ | "dataurl"
142
+ | "binary"
143
+ | "default"
144
+ | "empty"
145
+ | "copy";
146
+
49
147
  /** Options passed to {@link Bundler.transform}. */
50
148
  export interface TransformOptions {
51
149
  /** Source code to transform. */
52
150
  code: string;
53
151
  /** Loader hint (`ts`, `tsx`, `jsx`, `css`, etc.). */
54
- loader?: string;
152
+ loader?: Loader;
55
153
  /** Output format. */
56
154
  format?: "esm" | "cjs" | "iife";
57
155
  /** Target environment(s). */
@@ -60,6 +158,14 @@ export interface TransformOptions {
60
158
  minify?: boolean;
61
159
  /** Enable source maps. */
62
160
  sourcemap?: boolean | "inline" | "external";
161
+ /** JSX transform mode. */
162
+ jsx?: "transform" | "preserve" | "automatic";
163
+ /** Module specifier used for the automatic JSX runtime import. */
164
+ jsxImportSource?: string;
165
+ /** Drop unused exports and dead code. */
166
+ treeShaking?: boolean;
167
+ /** Preserve original identifier names through minification. */
168
+ keepNames?: boolean;
63
169
  /** Extra implementation-specific options. */
64
170
  [key: string]: unknown;
65
171
  }
@@ -74,30 +180,95 @@ export interface TransformResult {
74
180
  warnings: string[];
75
181
  }
76
182
 
183
+ /** Arguments passed to an `onResolve` callback. */
184
+ export interface OnResolveArgs {
185
+ path: string;
186
+ importer: string;
187
+ namespace: string;
188
+ resolveDir: string;
189
+ /** e.g. "import-statement", "dynamic-import", "require-call", "entry-point". */
190
+ kind: string;
191
+ pluginData?: unknown;
192
+ }
193
+
194
+ /** Result returned from an `onResolve` callback. */
195
+ export interface OnResolveResult {
196
+ path?: string;
197
+ namespace?: string;
198
+ external?: boolean;
199
+ errors?: BundlerMessage[];
200
+ warnings?: BundlerMessage[];
201
+ pluginData?: unknown;
202
+ sideEffects?: boolean;
203
+ watchFiles?: string[];
204
+ }
205
+
206
+ /** Arguments passed to an `onLoad` callback. */
207
+ export interface OnLoadArgs {
208
+ path: string;
209
+ namespace: string;
210
+ suffix?: string;
211
+ pluginData?: unknown;
212
+ }
213
+
214
+ /** Result returned from an `onLoad` callback. */
215
+ export interface OnLoadResult {
216
+ contents?: string | Uint8Array;
217
+ loader?: string;
218
+ resolveDir?: string;
219
+ errors?: BundlerMessage[];
220
+ warnings?: BundlerMessage[];
221
+ pluginData?: unknown;
222
+ watchFiles?: string[];
223
+ }
224
+
77
225
  /** Build context exposed to bundler plugins. */
78
226
  export interface BundlerPluginBuild {
79
- /** Register a resolver callback for the given filter. */
80
227
  onResolve(
81
228
  options: { filter: RegExp; namespace?: string },
82
229
  callback: (
83
- args: { path: string; namespace: string },
84
- ) => { path?: string; namespace?: string; external?: boolean } | undefined,
230
+ args: OnResolveArgs,
231
+ ) =>
232
+ | OnResolveResult
233
+ | null
234
+ | undefined
235
+ | void
236
+ | Promise<OnResolveResult | null | undefined | void>,
85
237
  ): void;
86
- /** Register a loader callback for the given filter. */
87
238
  onLoad(
88
239
  options: { filter: RegExp; namespace?: string },
89
240
  callback: (
90
- args: { path: string; namespace: string },
91
- ) => { contents?: string; loader?: string } | undefined,
241
+ args: OnLoadArgs,
242
+ ) =>
243
+ | OnLoadResult
244
+ | null
245
+ | undefined
246
+ | void
247
+ | Promise<OnLoadResult | null | undefined | void>,
92
248
  ): void;
249
+ onDispose(callback: () => void): void;
93
250
  }
94
251
 
95
252
  /** A bundler plugin that hooks into the build pipeline. */
96
253
  export interface BundlerPlugin {
97
254
  /** Unique plugin name. */
98
255
  name: string;
99
- /** Called once when the plugin is registered. */
100
- setup(build: BundlerPluginBuild): void;
256
+ /** Called once when the plugin is registered. May be async. */
257
+ setup(build: BundlerPluginBuild): void | Promise<void>;
258
+ }
259
+
260
+ /** Incremental/rebuild context produced by {@link Bundler.context}. */
261
+ export interface BuildContext {
262
+ /** Re-run the build with cached state. */
263
+ rebuild(): Promise<BundleResult>;
264
+ /** Release context resources. */
265
+ dispose(): Promise<void>;
266
+ }
267
+
268
+ /** Failure thrown by {@link Bundler.bundle} or {@link Bundler.transform}. */
269
+ export interface BuildFailure extends Error {
270
+ errors: BundlerMessage[];
271
+ warnings: BundlerMessage[];
101
272
  }
102
273
 
103
274
  /**
@@ -111,6 +282,8 @@ export interface Bundler {
111
282
  bundle(options: BundleOptions): Promise<BundleResult>;
112
283
  /** Transform a single source string without writing to disk. */
113
284
  transform(options: TransformOptions): Promise<TransformResult>;
285
+ /** Create an incremental build context (watch/rebuild mode). */
286
+ context?(options: BundleOptions): Promise<BuildContext>;
114
287
  /** Release bundler resources (child processes, watchers, etc.). */
115
288
  stop?(): Promise<void>;
116
289
  }
@@ -10,16 +10,32 @@
10
10
  import "../../../_dnt.polyfills.js";
11
11
 
12
12
  export type {
13
+ BuildContext,
14
+ BuildFailure,
13
15
  BundleOptions,
14
16
  BundleOutput,
15
17
  Bundler,
16
18
  BundleResult,
19
+ BundlerMessage,
20
+ BundlerMessageLocation,
17
21
  BundlerPlugin,
18
22
  BundlerPluginBuild,
23
+ Loader,
24
+ Metafile,
25
+ MetafileInput,
26
+ MetafileOutput,
27
+ OnLoadArgs,
28
+ OnLoadResult,
29
+ OnResolveArgs,
30
+ OnResolveResult,
31
+ StdinOptions,
19
32
  TransformOptions,
20
33
  TransformResult,
21
34
  } from "./bundler.js";
22
35
 
36
+ // Module lexer
37
+ export type { ImportSpecifier, ModuleLexer } from "./module-lexer.js";
38
+
23
39
  // Cache store
24
40
  export type { CacheStore } from "./cache-store.js";
25
41
 
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Contract interface for ES module lexers.
3
+ *
4
+ * Parses ES module import/export specifiers from source code.
5
+ * Kept separate from {@link Bundler} because the surfaces are orthogonal:
6
+ * a lexer only inspects specifier positions, while a bundler compiles and
7
+ * emits output.
8
+ *
9
+ * Default implementation: `@veryfront/ext-esbuild` (backed by `es-module-lexer`).
10
+ *
11
+ * @module extensions/interfaces/module-lexer
12
+ */
13
+
14
+ /**
15
+ * A single import specifier position record, matching the shape produced by
16
+ * `es-module-lexer`.
17
+ */
18
+ export interface ImportSpecifier {
19
+ /** Module specifier (e.g. "react"). Undefined when the specifier cannot be statically resolved (dynamic import with non-literal expression, or import.meta). */
20
+ n: string | undefined;
21
+ /** Start of module specifier. */
22
+ s: number;
23
+ /** End of module specifier. */
24
+ e: number;
25
+ /** Start of import statement. */
26
+ ss: number;
27
+ /** End of import statement. */
28
+ se: number;
29
+ /** Index of the dynamic import token in the source; -1 for static imports, -2 for import.meta. */
30
+ d: number;
31
+ /** Start position of the import attributes (with/assert) block in the source; -1 if none. */
32
+ a: number;
33
+ }
34
+
35
+ /**
36
+ * Module lexer contract interface.
37
+ *
38
+ * Implementations parse ES module import specifiers from source code and
39
+ * return positional records suitable for further rewriting.
40
+ */
41
+ export interface ModuleLexer {
42
+ /** Optional async initialization (e.g., loading WASM). Called lazily by the default impl before first parse. */
43
+ init?(): Promise<void>;
44
+ /** Parse ES module import/export specifiers from source code. */
45
+ parse(code: string): readonly ImportSpecifier[];
46
+ }
@@ -253,7 +253,12 @@ export class ExtensionLoader {
253
253
  }
254
254
  }
255
255
  }
256
+ const hadSetupExtensions = this.setupOrder.length > 0;
256
257
  this.setupOrder = [];
257
- reset();
258
+ // Only clear the contract registry when this loader actually registered
259
+ // contracts via setupAll(). Otherwise an idempotent teardown on an empty
260
+ // loader would wipe contracts registered out-of-band (e.g. by the test
261
+ // harness in `tests/_helpers/contract-init.ts`).
262
+ if (hadSetupExtensions) reset();
258
263
  }
259
264
  }
@@ -6,6 +6,9 @@
6
6
 
7
7
  const recommendations = new Map<string, string>([
8
8
  ["Bundler", "@veryfront/ext-esbuild"],
9
+ // ModuleLexer ships in the same package as Bundler (es-module-lexer +
10
+ // esbuild are co-bundled into ext-esbuild).
11
+ ["ModuleLexer", "@veryfront/ext-esbuild"],
9
12
  ["CacheStore", "@veryfront/ext-redis"],
10
13
  ["TokenCacheStore", "@veryfront/ext-redis"],
11
14
  ["CSSProcessor", "@veryfront/ext-tailwind"],
@@ -1,165 +1,53 @@
1
1
  /**
2
- * esbuild compatibility layer with deno compile support.
3
- * Extracts esbuild binary from VFS to temp dir on first use in compiled binaries.
4
- * Sets ESBUILD_BINARY_PATH in both Deno.env and process.env (esbuild reads process.env).
2
+ * Compatibility shim for code that previously imported esbuild via this path.
3
+ *
4
+ * The actual esbuild runtime now lives in the `@veryfront/ext-esbuild`
5
+ * extension; this module forwards to the registered `Bundler` contract so
6
+ * legacy callers keep working without importing `esbuild` directly.
5
7
  */
6
- import * as dntShim from "../../../_dnt.shims.js";
7
8
 
8
-
9
- export type { BuildOptions, BuildResult, TransformOptions, TransformResult } from "esbuild";
10
-
11
- import nodeProcess from "node:process";
12
- import { serverLogger } from "../../utils/logger/logger.js";
13
- import { getEnv, setEnv } from "./process.js";
14
- import { isDenoCompiled } from "./runtime.js";
15
- import { ESBUILD_VERSION, getEsbuildBinaryName, getVFSBasePath } from "./esbuild-shared.js";
16
- import { FILE_NOT_FOUND } from "../../errors/index.js";
17
-
18
- function getTempDir(): string {
19
- return getEnv("TMPDIR") ?? getEnv("TEMP") ?? getEnv("TMP") ?? "/tmp";
20
- }
21
-
22
- function getEsbuildCacheDir(): string {
23
- return `${getTempDir()}/veryfront-esbuild`;
24
- }
25
-
26
- let esbuildModule: typeof import("esbuild") | null = null;
27
- let setupComplete = false;
28
- let setupPromise: Promise<void> | null = null;
29
-
30
- async function isFile(path: string): Promise<boolean> {
31
- try {
32
- const stat = await dntShim.Deno.stat(path);
33
- return stat.isFile;
34
- } catch (_) {
35
- /* expected: file may not exist */
36
- return false;
37
- }
38
- }
39
-
40
- async function findEsbuildInVFS(): Promise<string | null> {
41
- const binaryName = getEsbuildBinaryName();
42
- const vfsBase = getVFSBasePath(new URL(import.meta.url).pathname, getTempDir());
43
-
44
- const possiblePaths = [
45
- `${vfsBase}/node_modules/${binaryName}/bin/esbuild`,
46
- `${vfsBase}/node_modules/.deno/${binaryName}@${ESBUILD_VERSION}/node_modules/${binaryName}/bin/esbuild`,
47
- `${vfsBase}/node_modules/.deno/esbuild@${ESBUILD_VERSION}/node_modules/${binaryName}/bin/esbuild`,
48
- `${vfsBase}/node_modules/esbuild/bin/esbuild`,
49
- `${vfsBase}/node_modules/.package/esbuild@${ESBUILD_VERSION}/bin/esbuild`,
50
- `${vfsBase}/node_modules/.package/${binaryName}@${ESBUILD_VERSION}/bin/esbuild`,
51
- ];
52
-
53
- for (const vfsPath of possiblePaths) {
54
- if (await isFile(vfsPath)) return vfsPath;
55
- }
56
-
57
- try {
58
- const nodeModulesPath = `${vfsBase}/node_modules`;
59
- for await (const entry of dntShim.Deno.readDir(nodeModulesPath)) {
60
- if (entry.name !== binaryName && !entry.name.startsWith("@esbuild")) continue;
61
-
62
- const binPath = `${nodeModulesPath}/${entry.name}/bin/esbuild`;
63
- if (await isFile(binPath)) return binPath;
64
- }
65
- } catch (_) {
66
- /* expected: node_modules directory may not be readable in VFS */
67
- }
68
-
69
- return null;
70
- }
71
-
72
- async function extractEsbuildBinary(): Promise<string> {
73
- const cacheDir = getEsbuildCacheDir();
74
- const targetPath = `${cacheDir}/esbuild-${ESBUILD_VERSION}`;
75
-
76
- try {
77
- const stat = await dntShim.Deno.stat(targetPath);
78
- if (stat.isFile && stat.mode && (stat.mode & 0o111)) return targetPath;
79
- } catch (_) {
80
- /* expected: cached binary does not exist yet, need to extract */
81
- }
82
-
83
- const vfsPath = await findEsbuildInVFS();
84
- if (!vfsPath) {
85
- const vfsBase = getVFSBasePath(new URL(import.meta.url).pathname, getTempDir());
86
- throw FILE_NOT_FOUND.create({
87
- detail: `Could not find esbuild binary in deno compile VFS.\n` +
88
- ` Platform: ${getEsbuildBinaryName()}\n` +
89
- ` VFS base: ${vfsBase}\n` +
90
- ` Tip: Ensure esbuild is in dependencies and deno compile includes node_modules.`,
91
- });
92
- }
93
-
94
- await dntShim.Deno.mkdir(cacheDir, { recursive: true });
95
-
96
- const binary = await dntShim.Deno.readFile(vfsPath);
97
- await dntShim.Deno.writeFile(targetPath, binary, { mode: 0o755 });
98
-
99
- return targetPath;
100
- }
101
-
102
- async function ensureEsbuildBinary(): Promise<void> {
103
- if (setupComplete) return;
104
-
105
- if (setupPromise) {
106
- await setupPromise;
107
- return;
108
- }
109
-
110
- setupPromise = (async () => {
111
- if (getEnv("ESBUILD_BINARY_PATH") || !isDenoCompiled) {
112
- setupComplete = true;
113
- return;
114
- }
115
-
116
- try {
117
- const binaryPath = await extractEsbuildBinary();
118
- setEnv("ESBUILD_BINARY_PATH", binaryPath);
119
- nodeProcess.env.ESBUILD_BINARY_PATH = binaryPath;
120
- } catch (error) {
121
- serverLogger.error("[esbuild] Binary extraction failed", error);
122
- } finally {
123
- setupComplete = true;
124
- }
125
- })();
126
-
127
- try {
128
- await setupPromise;
129
- } finally {
130
- setupPromise = null;
131
- }
132
- }
133
-
134
- export async function getEsbuild(): Promise<typeof import("esbuild")> {
135
- await ensureEsbuildBinary();
136
- if (esbuildModule) return esbuildModule;
137
-
138
- esbuildModule = await import("esbuild");
139
- return esbuildModule;
140
- }
141
-
142
- export async function transform(
143
- code: string,
144
- options?: import("esbuild").TransformOptions,
145
- ): Promise<import("esbuild").TransformResult> {
146
- const esbuild = await getEsbuild();
147
- return esbuild.transform(code, options);
148
- }
149
-
150
- export async function build(
151
- options: import("esbuild").BuildOptions,
152
- ): Promise<import("esbuild").BuildResult> {
153
- const esbuild = await getEsbuild();
154
- return esbuild.build(options);
155
- }
156
-
157
- export async function stop(): Promise<void> {
158
- const esbuild = await getEsbuild();
159
- esbuild.stop();
160
- }
161
-
162
- /** Eager initialization for server startup. */
9
+ import {
10
+ build as bundlerBuild,
11
+ getBundler,
12
+ stop as bundlerStop,
13
+ transform as bundlerTransform,
14
+ } from "../../extensions/bundler.js";
15
+ import type {
16
+ BundleOptions,
17
+ BundleResult,
18
+ TransformOptions,
19
+ TransformResult,
20
+ } from "../../extensions/bundler.js";
21
+
22
+ export type {
23
+ BundleOptions as BuildOptions,
24
+ BundleResult as BuildResult,
25
+ TransformOptions,
26
+ TransformResult,
27
+ } from "../../extensions/bundler.js";
28
+
29
+ /** esbuild-shaped facade backed by the registered `Bundler` contract. */
30
+ export function getEsbuild(): {
31
+ build: (opts: BundleOptions) => Promise<BundleResult>;
32
+ transform: (
33
+ code: string,
34
+ opts?: Omit<TransformOptions, "code">,
35
+ ) => Promise<TransformResult>;
36
+ stop: () => Promise<void>;
37
+ } {
38
+ getBundler();
39
+ return {
40
+ build: bundlerBuild,
41
+ transform: bundlerTransform,
42
+ stop: bundlerStop,
43
+ };
44
+ }
45
+
46
+ export const transform = bundlerTransform;
47
+ export const build = bundlerBuild;
48
+ export const stop = bundlerStop;
49
+
50
+ /** No-op kept for backwards compatibility with legacy bootstrap callers. */
163
51
  export async function initializeEsbuild(): Promise<void> {
164
- await ensureEsbuildBinary();
52
+ getBundler();
165
53
  }