@zappdev/vite 0.5.0-alpha.3 → 0.6.0-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 (3) hide show
  1. package/dist/index.js +27 -39
  2. package/package.json +1 -1
  3. package/src/index.ts +39 -53
package/dist/index.js CHANGED
@@ -73,19 +73,37 @@ async function bundleWorker(entry, outDir, aliases) {
73
73
  return false;
74
74
  }
75
75
  }
76
+ function resolveHeadlessEntries(root, headless) {
77
+ if (!headless)
78
+ return [];
79
+ const entries = [];
80
+ for (const [id, srcPath] of Object.entries(headless)) {
81
+ const abs = path.resolve(root, srcPath);
82
+ if (!existsSync(abs)) {
83
+ console.warn(`[zapp] headless worker "${id}" not found at ${srcPath}`);
84
+ continue;
85
+ }
86
+ entries.push({
87
+ specifier: srcPath,
88
+ sourcePath: abs,
89
+ outputName: `_headless_${id}.mjs`,
90
+ outputUrl: `/_workers/_headless_${id}.mjs`
91
+ });
92
+ }
93
+ return entries;
94
+ }
76
95
  function zappWorkers(options) {
77
96
  let root = "";
78
97
  let srcDir = "";
79
98
  let workers = [];
80
- let backendEntry = null;
99
+ let headlessEntries = [];
81
100
  let aliases = {};
82
101
  let isDev = false;
83
102
  let outDir = "";
84
- let backendFromConfig = options?.backend;
85
103
  return {
86
104
  name: "zapp-workers",
87
105
  enforce: "pre",
88
- async configResolved(config) {
106
+ configResolved(config) {
89
107
  root = config.root;
90
108
  srcDir = path.join(root, "src");
91
109
  outDir = path.join(root, "dist", "_workers");
@@ -94,33 +112,15 @@ function zappWorkers(options) {
94
112
  if (resolvedAlias && typeof resolvedAlias === "object" && !Array.isArray(resolvedAlias)) {
95
113
  aliases = resolvedAlias;
96
114
  }
97
- if (!backendFromConfig) {
98
- try {
99
- const configPath = path.join(root, "zapp.config.ts");
100
- const mod = await import(configPath);
101
- const zappConfig = typeof mod.default === "function" ? mod.default() : mod.default;
102
- if (zappConfig?.backend) {
103
- backendFromConfig = zappConfig.backend;
104
- }
105
- } catch {}
106
- }
107
115
  },
108
116
  async buildStart() {
109
117
  workers = await discoverWorkers(srcDir);
110
- const backendSrc = backendFromConfig ? path.resolve(root, backendFromConfig) : path.join(srcDir, "backend.ts");
111
- if (existsSync(backendSrc)) {
112
- backendEntry = {
113
- specifier: path.relative(srcDir, backendSrc),
114
- sourcePath: backendSrc,
115
- outputName: "backend.mjs",
116
- outputUrl: "/_workers/backend.mjs"
117
- };
118
- }
118
+ headlessEntries = resolveHeadlessEntries(root, options?.headless);
119
119
  if (workers.length > 0) {
120
120
  console.log(`[zapp] discovered ${workers.length} worker(s)`);
121
121
  }
122
- if (backendEntry) {
123
- console.log(`[zapp] backend worker: ${path.relative(root, backendSrc)}`);
122
+ for (const entry of headlessEntries) {
123
+ console.log(`[zapp] headless worker: ${path.relative(root, entry.sourcePath)}`);
124
124
  }
125
125
  },
126
126
  transform(code, id) {
@@ -145,18 +145,8 @@ function zappWorkers(options) {
145
145
  const devOutDir = path.join(root, ".zapp", "workers");
146
146
  await mkdir(devOutDir, { recursive: true });
147
147
  workers = await discoverWorkers(srcDir);
148
- const backendSrc = backendFromConfig ? path.resolve(root, backendFromConfig) : path.join(srcDir, "backend.ts");
149
- if (existsSync(backendSrc)) {
150
- backendEntry = {
151
- specifier: path.relative(srcDir, backendSrc),
152
- sourcePath: backendSrc,
153
- outputName: "backend.mjs",
154
- outputUrl: "/_workers/backend.mjs"
155
- };
156
- }
157
- const allEntries = [...workers];
158
- if (backendEntry)
159
- allEntries.push(backendEntry);
148
+ headlessEntries = resolveHeadlessEntries(root, options?.headless);
149
+ const allEntries = [...workers, ...headlessEntries];
160
150
  for (const entry of allEntries) {
161
151
  const ok = await bundleWorker(entry, devOutDir, aliases);
162
152
  if (ok)
@@ -181,9 +171,7 @@ function zappWorkers(options) {
181
171
  if (isDev)
182
172
  return;
183
173
  await mkdir(outDir, { recursive: true });
184
- const allEntries = [...workers];
185
- if (backendEntry)
186
- allEntries.push(backendEntry);
174
+ const allEntries = [...workers, ...headlessEntries];
187
175
  for (const entry of allEntries) {
188
176
  const ok = await bundleWorker(entry, outDir, aliases);
189
177
  if (ok) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zappdev/vite",
3
- "version": "0.5.0-alpha.3",
3
+ "version": "0.6.0-alpha.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
package/src/index.ts CHANGED
@@ -105,25 +105,47 @@ async function bundleWorker(entry: WorkerEntry, outDir: string, aliases: Record<
105
105
  }
106
106
 
107
107
  interface ZappWorkersOptions {
108
- /** Path to backend worker source, relative to project root. Overrides zapp.config.ts. */
109
- backend?: string;
108
+ /**
109
+ * Headless workers to bundle, keyed by ID. Values are source paths relative
110
+ * to project root. Output URL is `/_workers/_headless_<id>.mjs` — the native
111
+ * runtime loads these at app startup via generated Zen-C code.
112
+ */
113
+ headless?: Record<string, string>;
114
+ }
115
+
116
+ function resolveHeadlessEntries(root: string, headless?: Record<string, string>): WorkerEntry[] {
117
+ if (!headless) return [];
118
+ const entries: WorkerEntry[] = [];
119
+ for (const [id, srcPath] of Object.entries(headless)) {
120
+ const abs = path.resolve(root, srcPath);
121
+ if (!existsSync(abs)) {
122
+ console.warn(`[zapp] headless worker "${id}" not found at ${srcPath}`);
123
+ continue;
124
+ }
125
+ entries.push({
126
+ specifier: srcPath,
127
+ sourcePath: abs,
128
+ outputName: `_headless_${id}.mjs`,
129
+ outputUrl: `/_workers/_headless_${id}.mjs`,
130
+ });
131
+ }
132
+ return entries;
110
133
  }
111
134
 
112
135
  export function zappWorkers(options?: ZappWorkersOptions): Plugin {
113
136
  let root = "";
114
137
  let srcDir = "";
115
138
  let workers: WorkerEntry[] = [];
116
- let backendEntry: WorkerEntry | null = null;
139
+ let headlessEntries: WorkerEntry[] = [];
117
140
  let aliases: Record<string, string> = {};
118
141
  let isDev = false;
119
142
  let outDir = "";
120
- let backendFromConfig = options?.backend;
121
143
 
122
144
  return {
123
145
  name: "zapp-workers",
124
146
  enforce: "pre",
125
147
 
126
- async configResolved(config) {
148
+ configResolved(config) {
127
149
  root = config.root;
128
150
  srcDir = path.join(root, "src");
129
151
  outDir = path.join(root, "dist", "_workers");
@@ -134,44 +156,20 @@ export function zappWorkers(options?: ZappWorkersOptions): Plugin {
134
156
  if (resolvedAlias && typeof resolvedAlias === "object" && !Array.isArray(resolvedAlias)) {
135
157
  aliases = resolvedAlias as Record<string, string>;
136
158
  }
137
-
138
- // Auto-read backend path from zapp.config.ts if not passed as option
139
- if (!backendFromConfig) {
140
- try {
141
- const configPath = path.join(root, "zapp.config.ts");
142
- const mod = await import(configPath);
143
- const zappConfig = typeof mod.default === "function" ? mod.default() : mod.default;
144
- if (zappConfig?.backend) {
145
- backendFromConfig = zappConfig.backend;
146
- }
147
- } catch {
148
- // No zapp.config.ts or no backend field — that's fine
149
- }
150
- }
151
159
  },
152
160
 
153
161
  async buildStart() {
154
- // Discover workers from source
162
+ // Webview-spawned workers: discovered by scanning source.
155
163
  workers = await discoverWorkers(srcDir);
156
164
 
157
- // Backend worker path from config, or fall back to src/backend.ts convention
158
- const backendSrc = backendFromConfig
159
- ? path.resolve(root, backendFromConfig)
160
- : path.join(srcDir, "backend.ts");
161
- if (existsSync(backendSrc)) {
162
- backendEntry = {
163
- specifier: path.relative(srcDir, backendSrc),
164
- sourcePath: backendSrc,
165
- outputName: "backend.mjs",
166
- outputUrl: "/_workers/backend.mjs",
167
- };
168
- }
165
+ // Headless workers: declared in zapp.config.ts.
166
+ headlessEntries = resolveHeadlessEntries(root, options?.headless);
169
167
 
170
168
  if (workers.length > 0) {
171
169
  console.log(`[zapp] discovered ${workers.length} worker(s)`);
172
170
  }
173
- if (backendEntry) {
174
- console.log(`[zapp] backend worker: ${path.relative(root, backendSrc)}`);
171
+ for (const entry of headlessEntries) {
172
+ console.log(`[zapp] headless worker: ${path.relative(root, entry.sourcePath)}`);
175
173
  }
176
174
  },
177
175
 
@@ -198,9 +196,10 @@ export function zappWorkers(options?: ZappWorkersOptions): Plugin {
198
196
  },
199
197
 
200
198
  // Dev: bundle workers eagerly so they exist on disk before the native
201
- // binary launches. The backend worker is loaded directly by native code
202
- // and never goes through HTTP, so a lazy-on-request middleware would never
203
- // bundle it. Eager bundling also lets native fall back to filesystem.
199
+ // binary launches. Headless workers are loaded directly by native code
200
+ // via the generated .zapp/zapp_headless_workers.zc, so a lazy-on-request
201
+ // middleware would never bundle them. Eager bundling also lets native
202
+ // fall back to filesystem.
204
203
  //
205
204
  // configureServer runs before buildStart, so we re-discover workers here
206
205
  // (buildStart's results aren't yet available).
@@ -209,21 +208,9 @@ export function zappWorkers(options?: ZappWorkersOptions): Plugin {
209
208
  await mkdir(devOutDir, { recursive: true });
210
209
 
211
210
  workers = await discoverWorkers(srcDir);
212
- const backendSrc = backendFromConfig
213
- ? path.resolve(root, backendFromConfig)
214
- : path.join(srcDir, "backend.ts");
215
- if (existsSync(backendSrc)) {
216
- backendEntry = {
217
- specifier: path.relative(srcDir, backendSrc),
218
- sourcePath: backendSrc,
219
- outputName: "backend.mjs",
220
- outputUrl: "/_workers/backend.mjs",
221
- };
222
- }
223
-
224
- const allEntries = [...workers];
225
- if (backendEntry) allEntries.push(backendEntry);
211
+ headlessEntries = resolveHeadlessEntries(root, options?.headless);
226
212
 
213
+ const allEntries = [...workers, ...headlessEntries];
227
214
  for (const entry of allEntries) {
228
215
  const ok = await bundleWorker(entry, devOutDir, aliases);
229
216
  if (ok) console.log(`[zapp] dev-bundled worker: ${entry.outputName}`);
@@ -254,8 +241,7 @@ export function zappWorkers(options?: ZappWorkersOptions): Plugin {
254
241
 
255
242
  await mkdir(outDir, { recursive: true });
256
243
 
257
- const allEntries = [...workers];
258
- if (backendEntry) allEntries.push(backendEntry);
244
+ const allEntries = [...workers, ...headlessEntries];
259
245
 
260
246
  for (const entry of allEntries) {
261
247
  const ok = await bundleWorker(entry, outDir, aliases);