@zappdev/vite 0.5.0-alpha.0 → 0.5.0-alpha.2

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 +200 -0
  2. package/package.json +8 -3
  3. package/src/index.ts +36 -12
package/dist/index.js ADDED
@@ -0,0 +1,200 @@
1
+ import { createRequire } from "node:module";
2
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+
4
+ // src/index.ts
5
+ import path from "node:path";
6
+ import { existsSync } from "node:fs";
7
+ import { mkdir, readdir, readFile } from "node:fs/promises";
8
+ var WORKER_PATTERN = /new\s+(?:SharedWorker|Worker)\s*\(\s*(?:new\s+URL\(\s*["'`](.+?)["'`]\s*,\s*import\.meta\.url\s*\)|["'`](.+?)["'`])/g;
9
+ async function scanDir(dir) {
10
+ const results = [];
11
+ try {
12
+ const entries = await readdir(dir, { withFileTypes: true });
13
+ for (const entry of entries) {
14
+ if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "zapp")
15
+ continue;
16
+ const full = path.join(dir, entry.name);
17
+ if (entry.isDirectory()) {
18
+ results.push(...await scanDir(full));
19
+ } else if (/\.(ts|tsx|js|jsx|mjs)$/.test(entry.name)) {
20
+ results.push(full);
21
+ }
22
+ }
23
+ } catch {}
24
+ return results;
25
+ }
26
+ async function discoverWorkers(srcDir) {
27
+ const files = await scanDir(srcDir);
28
+ const found = new Map;
29
+ for (const file of files) {
30
+ const content = await readFile(file, "utf-8");
31
+ let match;
32
+ WORKER_PATTERN.lastIndex = 0;
33
+ while ((match = WORKER_PATTERN.exec(content)) !== null) {
34
+ const spec = match[1] || match[2];
35
+ if (!spec || found.has(spec))
36
+ continue;
37
+ const sourcePath = path.resolve(path.dirname(file), spec);
38
+ const baseName = path.basename(spec).replace(/\.[^.]+$/, "");
39
+ found.set(spec, {
40
+ specifier: spec,
41
+ sourcePath,
42
+ outputName: `${baseName}.mjs`,
43
+ outputUrl: `/_workers/${baseName}.mjs`
44
+ });
45
+ }
46
+ }
47
+ return [...found.values()];
48
+ }
49
+ async function bundleWorker(entry, outDir, aliases) {
50
+ try {
51
+ const vite = await import("vite");
52
+ await vite.build({
53
+ configFile: false,
54
+ logLevel: "silent",
55
+ build: {
56
+ outDir,
57
+ emptyOutDir: false,
58
+ minify: true,
59
+ rollupOptions: {
60
+ input: entry.sourcePath,
61
+ output: {
62
+ format: "es",
63
+ entryFileNames: entry.outputName,
64
+ dir: outDir
65
+ }
66
+ }
67
+ },
68
+ resolve: { alias: aliases }
69
+ });
70
+ return true;
71
+ } catch (e) {
72
+ console.error(`[zapp] worker bundle failed: ${entry.specifier}`, e);
73
+ return false;
74
+ }
75
+ }
76
+ function zappWorkers(options) {
77
+ let root = "";
78
+ let srcDir = "";
79
+ let workers = [];
80
+ let backendEntry = null;
81
+ let aliases = {};
82
+ let isDev = false;
83
+ let outDir = "";
84
+ let backendFromConfig = options?.backend;
85
+ return {
86
+ name: "zapp-workers",
87
+ enforce: "pre",
88
+ async configResolved(config) {
89
+ root = config.root;
90
+ srcDir = path.join(root, "src");
91
+ outDir = path.join(root, "dist", "_workers");
92
+ isDev = config.command === "serve";
93
+ const resolvedAlias = config.resolve?.alias;
94
+ if (resolvedAlias && typeof resolvedAlias === "object" && !Array.isArray(resolvedAlias)) {
95
+ aliases = resolvedAlias;
96
+ }
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
+ },
108
+ async buildStart() {
109
+ 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
+ }
119
+ if (workers.length > 0) {
120
+ console.log(`[zapp] discovered ${workers.length} worker(s)`);
121
+ }
122
+ if (backendEntry) {
123
+ console.log(`[zapp] backend worker: ${path.relative(root, backendSrc)}`);
124
+ }
125
+ },
126
+ transform(code, id) {
127
+ if (!id.endsWith(".ts") && !id.endsWith(".tsx") && !id.endsWith(".js") && !id.endsWith(".jsx"))
128
+ return null;
129
+ if (id.includes("node_modules"))
130
+ return null;
131
+ let modified = false;
132
+ let result = code;
133
+ for (const entry of workers) {
134
+ const escaped = entry.specifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
135
+ const regex = new RegExp(`(new\\s+(?:SharedWorker|Worker)\\s*\\(\\s*["'\`])${escaped}(["'\`])`, "g");
136
+ const replaced = result.replace(regex, `$1${entry.outputUrl}$2`);
137
+ if (replaced !== result) {
138
+ result = replaced;
139
+ modified = true;
140
+ }
141
+ }
142
+ return modified ? { code: result, map: null } : null;
143
+ },
144
+ async configureServer(server) {
145
+ const devOutDir = path.join(root, ".zapp", "workers");
146
+ await mkdir(devOutDir, { recursive: true });
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);
160
+ for (const entry of allEntries) {
161
+ const ok = await bundleWorker(entry, devOutDir, aliases);
162
+ if (ok)
163
+ console.log(`[zapp] dev-bundled worker: ${entry.outputName}`);
164
+ }
165
+ server.middlewares.use(async (req, res, next) => {
166
+ if (!req.url?.startsWith("/_workers/"))
167
+ return next();
168
+ const fileName = req.url.slice("/_workers/".length);
169
+ const filePath = path.join(devOutDir, fileName);
170
+ if (existsSync(filePath)) {
171
+ const content = await readFile(filePath, "utf-8");
172
+ res.setHeader("Content-Type", "application/javascript");
173
+ res.end(content);
174
+ } else {
175
+ res.statusCode = 404;
176
+ res.end("Worker not found");
177
+ }
178
+ });
179
+ },
180
+ async generateBundle() {
181
+ if (isDev)
182
+ return;
183
+ await mkdir(outDir, { recursive: true });
184
+ const allEntries = [...workers];
185
+ if (backendEntry)
186
+ allEntries.push(backendEntry);
187
+ for (const entry of allEntries) {
188
+ const ok = await bundleWorker(entry, outDir, aliases);
189
+ if (ok) {
190
+ console.log(`[zapp] bundled worker: ${entry.outputName}`);
191
+ }
192
+ }
193
+ }
194
+ };
195
+ }
196
+ var src_default = zappWorkers;
197
+ export {
198
+ zappWorkers,
199
+ src_default as default
200
+ };
package/package.json CHANGED
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "name": "@zappdev/vite",
3
- "version": "0.5.0-alpha.0",
3
+ "version": "0.5.0-alpha.2",
4
4
  "type": "module",
5
- "main": "src/index.ts",
5
+ "main": "dist/index.js",
6
6
  "types": "src/index.ts",
7
7
  "exports": {
8
- ".": "./src/index.ts"
8
+ ".": "./dist/index.js"
9
9
  },
10
10
  "files": [
11
+ "dist/",
11
12
  "src/"
12
13
  ],
14
+ "scripts": {
15
+ "build": "bun build src/index.ts --outdir dist --format esm --target node",
16
+ "prepack": "bun run build"
17
+ },
13
18
  "peerDependencies": {
14
19
  "vite": ">=5.0.0"
15
20
  }
package/src/index.ts CHANGED
@@ -104,7 +104,12 @@ async function bundleWorker(entry: WorkerEntry, outDir: string, aliases: Record<
104
104
  }
105
105
  }
106
106
 
107
- export function zappWorkers(): Plugin {
107
+ interface ZappWorkersOptions {
108
+ /** Path to backend worker source, relative to project root. Overrides zapp.config.ts. */
109
+ backend?: string;
110
+ }
111
+
112
+ export function zappWorkers(options?: ZappWorkersOptions): Plugin {
108
113
  let root = "";
109
114
  let srcDir = "";
110
115
  let workers: WorkerEntry[] = [];
@@ -112,12 +117,13 @@ export function zappWorkers(): Plugin {
112
117
  let aliases: Record<string, string> = {};
113
118
  let isDev = false;
114
119
  let outDir = "";
120
+ let backendFromConfig = options?.backend;
115
121
 
116
122
  return {
117
123
  name: "zapp-workers",
118
124
  enforce: "pre",
119
125
 
120
- configResolved(config) {
126
+ async configResolved(config) {
121
127
  root = config.root;
122
128
  srcDir = path.join(root, "src");
123
129
  outDir = path.join(root, "dist", "_workers");
@@ -128,18 +134,34 @@ export function zappWorkers(): Plugin {
128
134
  if (resolvedAlias && typeof resolvedAlias === "object" && !Array.isArray(resolvedAlias)) {
129
135
  aliases = resolvedAlias as Record<string, string>;
130
136
  }
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
+ }
131
151
  },
132
152
 
133
153
  async buildStart() {
134
154
  // Discover workers from source
135
155
  workers = await discoverWorkers(srcDir);
136
156
 
137
- // Check for backend worker (convention: src/backend.ts)
138
- const backendPath = path.join(srcDir, "backend.ts");
139
- if (existsSync(backendPath)) {
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)) {
140
162
  backendEntry = {
141
- specifier: "./backend.ts",
142
- sourcePath: backendPath,
163
+ specifier: path.relative(srcDir, backendSrc),
164
+ sourcePath: backendSrc,
143
165
  outputName: "backend.mjs",
144
166
  outputUrl: "/_workers/backend.mjs",
145
167
  };
@@ -149,7 +171,7 @@ export function zappWorkers(): Plugin {
149
171
  console.log(`[zapp] discovered ${workers.length} worker(s)`);
150
172
  }
151
173
  if (backendEntry) {
152
- console.log("[zapp] backend worker: src/backend.ts");
174
+ console.log(`[zapp] backend worker: ${path.relative(root, backendSrc)}`);
153
175
  }
154
176
  },
155
177
 
@@ -187,11 +209,13 @@ export function zappWorkers(): Plugin {
187
209
  await mkdir(devOutDir, { recursive: true });
188
210
 
189
211
  workers = await discoverWorkers(srcDir);
190
- const backendPath = path.join(srcDir, "backend.ts");
191
- if (existsSync(backendPath)) {
212
+ const backendSrc = backendFromConfig
213
+ ? path.resolve(root, backendFromConfig)
214
+ : path.join(srcDir, "backend.ts");
215
+ if (existsSync(backendSrc)) {
192
216
  backendEntry = {
193
- specifier: "./backend.ts",
194
- sourcePath: backendPath,
217
+ specifier: path.relative(srcDir, backendSrc),
218
+ sourcePath: backendSrc,
195
219
  outputName: "backend.mjs",
196
220
  outputUrl: "/_workers/backend.mjs",
197
221
  };