@fairfox/polly 0.1.4 → 0.2.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.
package/dist/cli/polly.js CHANGED
@@ -1,22 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
3
  import { createRequire } from "node:module";
4
- var __create = Object.create;
5
- var __getProtoOf = Object.getPrototypeOf;
6
4
  var __defProp = Object.defineProperty;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __toESM = (mod, isNodeMode, target) => {
10
- target = mod != null ? __create(__getProtoOf(mod)) : {};
11
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
12
- for (let key of __getOwnPropNames(mod))
13
- if (!__hasOwnProp.call(to, key))
14
- __defProp(to, key, {
15
- get: () => mod[key],
16
- enumerable: true
17
- });
18
- return to;
19
- };
20
5
  var __export = (target, all) => {
21
6
  for (var name in all)
22
7
  __defProp(target, name, {
@@ -29,6 +14,65 @@ var __export = (target, all) => {
29
14
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
30
15
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
31
16
 
17
+ // cli/polly.ts
18
+ import { existsSync as existsSync2 } from "fs";
19
+
20
+ // cli/template-utils.ts
21
+ import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
22
+ import { join } from "node:path";
23
+ function processTemplate(content, projectName) {
24
+ return content.replace(/\{\{PROJECT_NAME\}\}/g, projectName).replace(/\{\{PROJECT_NAME_UPPER\}\}/g, projectName.toUpperCase()).replace(/\{\{PROJECT_NAME_CAMEL\}\}/g, toCamelCase(projectName));
25
+ }
26
+ function toCamelCase(str) {
27
+ return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/^(.)/, (char) => char.toLowerCase());
28
+ }
29
+ async function scaffoldFromTemplate(options) {
30
+ const { projectName, projectPath, templateDir } = options;
31
+ mkdirSync(projectPath, { recursive: true });
32
+ copyTemplateFiles(templateDir, projectPath, projectName);
33
+ }
34
+ function copyTemplateFiles(sourceDir, targetDir, projectName, relativePath = "") {
35
+ if (!existsSync(sourceDir)) {
36
+ throw new Error(`Template directory not found: ${sourceDir}`);
37
+ }
38
+ const entries = readdirSync(sourceDir, { withFileTypes: true });
39
+ for (const entry of entries) {
40
+ const sourcePath = join(sourceDir, entry.name);
41
+ const targetPath = join(targetDir, relativePath, entry.name.replace(".template", ""));
42
+ if (entry.isDirectory()) {
43
+ mkdirSync(targetPath, { recursive: true });
44
+ copyTemplateFiles(sourceDir, targetDir, projectName, join(relativePath, entry.name));
45
+ } else if (entry.name.endsWith(".template")) {
46
+ const content = readFileSync(sourcePath, "utf-8");
47
+ const processed = processTemplate(content, projectName);
48
+ writeFileSync(targetPath, processed, "utf-8");
49
+ } else {
50
+ cpSync(sourcePath, targetPath);
51
+ }
52
+ }
53
+ }
54
+ function getTemplateDir(projectType, baseDir) {
55
+ return join(baseDir, "..", "templates", projectType);
56
+ }
57
+ function validateProjectName(name) {
58
+ if (!name || name.trim().length === 0) {
59
+ return { valid: false, error: "Project name cannot be empty" };
60
+ }
61
+ if (!/^[a-z0-9-_]+$/i.test(name)) {
62
+ return {
63
+ valid: false,
64
+ error: "Project name can only contain letters, numbers, hyphens, and underscores"
65
+ };
66
+ }
67
+ if (name.startsWith("-") || name.startsWith("_")) {
68
+ return {
69
+ valid: false,
70
+ error: "Project name cannot start with a hyphen or underscore"
71
+ };
72
+ }
73
+ return { valid: true };
74
+ }
75
+
32
76
  // cli/polly.ts
33
77
  var __dirname2 = import.meta.dir;
34
78
  var command = process.argv[2];
@@ -195,218 +239,29 @@ async function check() {
195
239
  }
196
240
  }
197
241
  async function init() {
198
- const projectName = commandArgs[0] || "my-extension";
242
+ const projectName = commandArgs[0] || "my-project";
243
+ const typeArg = commandArgs.find((arg) => arg.startsWith("--type="))?.split("=")[1] || "extension";
244
+ const projectType = typeArg;
245
+ const validation = validateProjectName(projectName);
246
+ if (!validation.valid) {
247
+ console.error(`\x1B[31m\u2717 ${validation.error}\x1B[0m
248
+ `);
249
+ process.exit(1);
250
+ }
199
251
  const projectPath = `${cwd}/${projectName}`;
200
- const { existsSync, mkdirSync, writeFileSync } = await import("fs");
201
- if (existsSync(projectPath)) {
252
+ if (existsSync2(projectPath)) {
202
253
  console.error(`\x1B[31m\u2717 Directory '${projectName}' already exists\x1B[0m
203
254
  `);
204
255
  process.exit(1);
205
256
  }
206
- const dirs = [
257
+ const templateDir = getTemplateDir(projectType, __dirname2);
258
+ await scaffoldFromTemplate({
259
+ projectName,
207
260
  projectPath,
208
- `${projectPath}/src`,
209
- `${projectPath}/src/background`,
210
- `${projectPath}/src/popup`
211
- ];
212
- for (const dir of dirs) {
213
- mkdirSync(dir, { recursive: true });
214
- }
215
- const packageJson = {
216
- name: projectName,
217
- version: "0.1.0",
218
- type: "module",
219
- scripts: {
220
- check: "web-ext check",
221
- build: "web-ext build",
222
- "build:prod": "web-ext build --prod",
223
- typecheck: "web-ext typecheck",
224
- lint: "web-ext lint",
225
- "lint:fix": "web-ext lint --fix",
226
- format: "web-ext format",
227
- test: "web-ext test",
228
- verify: "web-ext verify",
229
- "verify:setup": "web-ext verify --setup",
230
- visualize: "web-ext visualize",
231
- "visualize:export": "web-ext visualize --export",
232
- "visualize:serve": "web-ext visualize --serve"
233
- },
234
- dependencies: {
235
- "@fairfox/web-ext": "*"
236
- }
237
- };
238
- writeFileSync(`${projectPath}/package.json`, JSON.stringify(packageJson, null, 2));
239
- const manifest = {
240
- manifest_version: 3,
241
- name: projectName,
242
- version: "0.1.0",
243
- description: "A Chrome extension built with @fairfox/web-ext",
244
- background: {
245
- service_worker: "background/index.js",
246
- type: "module"
247
- },
248
- action: {
249
- default_popup: "popup/popup.html"
250
- },
251
- permissions: ["storage"]
252
- };
253
- writeFileSync(`${projectPath}/manifest.json`, JSON.stringify(manifest, null, 2));
254
- const backgroundScript = `/**
255
- * Background Service Worker
256
- */
257
-
258
- import { getMessageBus } from "@fairfox/web-ext/message-bus";
259
- import { MessageRouter } from "@fairfox/web-ext/message-router";
260
-
261
- const bus = getMessageBus("background");
262
- new MessageRouter(bus);
263
-
264
- // Add your message handlers here
265
- bus.on("PING", async () => {
266
- return { success: true, message: "pong" };
267
- });
268
-
269
- console.log("Background service worker initialized");
270
- `;
271
- writeFileSync(`${projectPath}/src/background/index.ts`, backgroundScript);
272
- const popupHtml = `<!DOCTYPE html>
273
- <html>
274
- <head>
275
- <meta charset="utf-8" />
276
- <title>${projectName}</title>
277
- </head>
278
- <body>
279
- <div id="root"></div>
280
- <script type="module" src="./index.js"></script>
281
- </body>
282
- </html>
283
- `;
284
- writeFileSync(`${projectPath}/src/popup/popup.html`, popupHtml);
285
- const popupScript = `/**
286
- * Popup UI
287
- */
288
-
289
- import { getMessageBus } from "@fairfox/web-ext/message-bus";
290
-
291
- const bus = getMessageBus("popup");
292
-
293
- // Simple example without UI framework
294
- const root = document.getElementById("root");
295
-
296
- if (root) {
297
- root.innerHTML = \`
298
- <div style="padding: 16px; min-width: 200px;">
299
- <h1 style="margin: 0 0 8px 0; font-size: 18px;">${projectName}</h1>
300
- <button id="ping-btn" style="padding: 8px 16px;">Ping Background</button>
301
- <p id="response" style="margin-top: 8px; font-size: 14px;"></p>
302
- </div>
303
- \`;
304
-
305
- const btn = document.getElementById("ping-btn");
306
- const response = document.getElementById("response");
307
-
308
- btn?.addEventListener("click", async () => {
309
- const result = await bus.send({ type: "PING" });
310
- if (response) {
311
- response.textContent = JSON.stringify(result);
312
- }
261
+ projectType,
262
+ templateDir
313
263
  });
314
264
  }
315
- `;
316
- writeFileSync(`${projectPath}/src/popup/index.ts`, popupScript);
317
- const tsconfig = {
318
- compilerOptions: {
319
- target: "ES2022",
320
- module: "ESNext",
321
- lib: ["ES2022", "DOM"],
322
- moduleResolution: "bundler",
323
- strict: true,
324
- esModuleInterop: true,
325
- skipLibCheck: true,
326
- forceConsistentCasingInFileNames: true,
327
- resolveJsonModule: true,
328
- allowSyntheticDefaultImports: true,
329
- jsx: "react-jsx",
330
- jsxImportSource: "preact"
331
- },
332
- include: ["src/**/*"]
333
- };
334
- writeFileSync(`${projectPath}/tsconfig.json`, JSON.stringify(tsconfig, null, 2));
335
- const biomeConfig = {
336
- files: {
337
- includes: ["src/**/*.ts", "src/**/*.tsx"],
338
- ignoreUnknown: true
339
- },
340
- linter: {
341
- enabled: true,
342
- rules: {
343
- recommended: true
344
- }
345
- },
346
- formatter: {
347
- enabled: true,
348
- indentStyle: "space",
349
- indentWidth: 2
350
- }
351
- };
352
- writeFileSync(`${projectPath}/biome.json`, JSON.stringify(biomeConfig, null, 2));
353
- const readme = `# ${projectName}
354
-
355
- A Chrome extension built with [@fairfox/web-ext](https://github.com/fairfox/web-ext).
356
-
357
- ## Getting Started
358
-
359
- 1. Install dependencies:
360
- \`\`\`bash
361
- bun install
362
- \`\`\`
363
-
364
- 2. Build the extension:
365
- \`\`\`bash
366
- bun run build
367
- \`\`\`
368
-
369
- 3. Load the extension in Chrome:
370
- - Open \`chrome://extensions\`
371
- - Enable "Developer mode"
372
- - Click "Load unpacked"
373
- - Select the \`dist/\` folder
374
-
375
- ## Development
376
-
377
- - \`bun run build\` - Build the extension
378
- - \`bun run check\` - Run all checks (typecheck, lint, test, build)
379
- - \`bun run typecheck\` - Type check your code
380
- - \`bun run lint\` - Lint your code
381
- - \`bun run format\` - Format your code
382
- - \`bun run verify\` - Run formal verification
383
- - \`bun run visualize\` - Generate architecture diagrams
384
-
385
- ## Project Structure
386
-
387
- \`\`\`
388
- ${projectName}/
389
- \u251C\u2500\u2500 src/
390
- \u2502 \u251C\u2500\u2500 background/
391
- \u2502 \u2502 \u2514\u2500\u2500 index.ts # Background service worker
392
- \u2502 \u2514\u2500\u2500 popup/
393
- \u2502 \u251C\u2500\u2500 popup.html # Popup HTML
394
- \u2502 \u2514\u2500\u2500 index.ts # Popup script
395
- \u251C\u2500\u2500 manifest.json # Extension manifest
396
- \u251C\u2500\u2500 dist/ # Build output (load this in Chrome)
397
- \u251C\u2500\u2500 package.json
398
- \u251C\u2500\u2500 tsconfig.json
399
- \u2514\u2500\u2500 biome.json
400
- \`\`\`
401
- `;
402
- writeFileSync(`${projectPath}/README.md`, readme);
403
- const gitignore = `node_modules
404
- dist
405
- docs
406
- .DS_Store
407
- `;
408
- writeFileSync(`${projectPath}/.gitignore`, gitignore);
409
- }
410
265
  function help() {}
411
266
  async function main() {
412
267
  try {
@@ -461,4 +316,4 @@ async function main() {
461
316
  }
462
317
  main();
463
318
 
464
- //# debugId=BB7E0889114F14F064756E2164756E21
319
+ //# debugId=498624C7345252DB64756E2164756E21
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../cli/polly.ts"],
3
+ "sources": ["../cli/polly.ts", "../cli/template-utils.ts"],
4
4
  "sourcesContent": [
5
- "#!/usr/bin/env bun\n/**\n * Polly CLI\n *\n * Command-line tool for building multi-execution-context applications\n * with reactive state and cross-context messaging.\n *\n * Supports: Chrome extensions, PWAs, Node/Bun/Deno apps with workers\n *\n * Usage:\n * polly init [name] Create a new project\n * polly check Run all checks (typecheck, lint, test, build)\n * polly build [options] Build the project\n * polly dev Build with watch mode\n * polly typecheck Type check your code\n * polly lint [--fix] Lint your code\n * polly format Format your code\n * polly test [args] Run tests (requires bun test)\n * polly verify [args] Run formal verification\n * polly visualize [args] Generate architecture diagrams\n * polly help Show help\n *\n * Options:\n * --prod Build for production (minified)\n * --config <path> Path to config file (default: polly.config.ts)\n * --fix Auto-fix lint/format issues\n */\n\n// Use Bun built-ins instead of Node.js APIs\nconst __dirname = import.meta.dir;\n\nconst command = process.argv[2];\nconst commandArgs = process.argv.slice(3);\nconst cwd = process.cwd();\n\n// Parse arguments\nconst args = {\n prod: process.argv.includes(\"--prod\"),\n config: process.argv.includes(\"--config\")\n ? process.argv[process.argv.indexOf(\"--config\") + 1]\n : undefined,\n};\n\n/**\n * Load user's configuration\n */\nasync function loadConfig() {\n const configPaths = [\n args.config,\n `${cwd}/polly.config.ts`,\n `${cwd}/polly.config.js`,\n `${cwd}/polly.config.mjs`,\n ].filter(Boolean) as string[];\n\n for (const configPath of configPaths) {\n // Use Bun.file().exists() instead of existsSync\n if (await Bun.file(configPath).exists()) {\n try {\n const config = await import(configPath);\n return config.default || config;\n } catch (error) {\n console.error(`❌ Failed to load config: ${configPath}`);\n throw error;\n }\n }\n }\n return {\n srcDir: \"src\",\n distDir: \"dist\",\n manifest: \"manifest.json\",\n };\n}\n\n/**\n * Build command - build the extension\n */\nasync function build() {\n const config = await loadConfig();\n\n // Check if bundled (published) or in monorepo\n const bundledScript = `${__dirname}/../scripts/build-extension.js`;\n const monorepoScript = `${__dirname}/../scripts/build-extension.ts`;\n const buildScriptPath = (await Bun.file(bundledScript).exists()) ? bundledScript : monorepoScript;\n\n // Pass config via environment\n process.env[\"WEB_EXT_SRC\"] = `${cwd}/${config.srcDir || \"src\"}`;\n process.env[\"WEB_EXT_DIST\"] = `${cwd}/${config.distDir || \"dist\"}`;\n process.env[\"WEB_EXT_MANIFEST\"] = `${cwd}/${config.manifest || \"manifest.json\"}`;\n process.env[\"WEB_EXT_CWD\"] = cwd;\n process.env[\"WEB_EXT_PROD\"] = args.prod ? \"true\" : \"false\";\n\n // Run build\n const proc = Bun.spawn([\"bun\", buildScriptPath], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n process.exit(exitCode);\n }\n}\n\n/**\n * Dev command - build with watch mode\n */\nasync function dev() {\n await build();\n}\n\n/**\n * Verify command - delegate to @fairfox/web-ext-verify\n */\nasync function verify() {\n // Check if bundled (published) or in monorepo\n const bundledCli = `${__dirname}/../vendor/verify/src/cli.js`;\n const monorepoCli = `${__dirname}/../../verify/src/cli.ts`;\n const verifyCli = (await Bun.file(bundledCli).exists()) ? bundledCli : monorepoCli;\n\n const proc = Bun.spawn([\"bun\", verifyCli, ...commandArgs], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n stdin: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Verification failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Visualize command - delegate to @fairfox/polly-visualize\n */\nasync function visualize() {\n // Check if bundled (published) or in monorepo\n const bundledCli = `${__dirname}/../vendor/visualize/src/cli.js`;\n const monorepoCli = `${__dirname}/../../visualize/src/cli.ts`;\n const visualizeCli = (await Bun.file(bundledCli).exists()) ? bundledCli : monorepoCli;\n\n const proc = Bun.spawn([\"bun\", visualizeCli, ...commandArgs], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n stdin: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Visualization failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Typecheck command - run TypeScript type checking\n */\nasync function typecheck() {\n const proc = Bun.spawn([\"bunx\", \"tsc\", \"--noEmit\"], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Type checking failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Lint command - run Biome linter\n */\nasync function lint() {\n const fix = commandArgs.includes(\"--fix\");\n const lintArgs = fix ? [\"check\", \"--write\", \".\"] : [\"check\", \".\"];\n\n const proc = Bun.spawn([\"bunx\", \"@biomejs/biome\", ...lintArgs], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Linting failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Format command - run Biome formatter\n */\nasync function format() {\n const proc = Bun.spawn([\"bunx\", \"@biomejs/biome\", \"format\", \"--write\", \".\"], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Formatting failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Test command - run Bun tests\n */\nasync function test() {\n const proc = Bun.spawn([\"bun\", \"test\", ...commandArgs], {\n cwd,\n stdout: \"pipe\",\n stderr: \"pipe\",\n stdin: \"inherit\",\n });\n\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\n\n // Output the results\n if (stdout) process.stdout.write(stdout);\n if (stderr) process.stderr.write(stderr);\n\n const exitCode = await proc.exited;\n\n // Check if no tests were found (not a failure)\n if (stderr.includes(\"0 test files matching\")) {\n return;\n }\n\n if (exitCode !== 0) {\n throw new Error(`Tests failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Check command - run all quality checks in sequence\n */\nasync function check() {\n const checks = [\n { name: \"Type checking\", fn: typecheck },\n { name: \"Linting\", fn: lint },\n { name: \"Testing\", fn: test },\n { name: \"Building\", fn: build },\n { name: \"Verification\", fn: verify, optional: true },\n { name: \"Visualization\", fn: visualize, optional: true },\n ];\n\n for (const { name, fn, optional } of checks) {\n try {\n await fn();\n } catch (_error) {\n if (optional) {\n continue;\n }\n console.error(`\\n\\x1b[31m✗ ${name} failed\\x1b[0m\\n`);\n process.exit(1);\n }\n }\n}\n\n/**\n * Init command - scaffold a new extension\n */\nasync function init() {\n const projectName = commandArgs[0] || \"my-extension\";\n const projectPath = `${cwd}/${projectName}`;\n\n // Check if directory already exists\n const { existsSync, mkdirSync, writeFileSync } = await import(\"node:fs\");\n\n if (existsSync(projectPath)) {\n console.error(`\\x1b[31m✗ Directory '${projectName}' already exists\\x1b[0m\\n`);\n process.exit(1);\n }\n\n // Create project structure\n const dirs = [\n projectPath,\n `${projectPath}/src`,\n `${projectPath}/src/background`,\n `${projectPath}/src/popup`,\n ];\n\n for (const dir of dirs) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Create package.json\n const packageJson = {\n name: projectName,\n version: \"0.1.0\",\n type: \"module\",\n scripts: {\n check: \"web-ext check\",\n build: \"web-ext build\",\n \"build:prod\": \"web-ext build --prod\",\n typecheck: \"web-ext typecheck\",\n lint: \"web-ext lint\",\n \"lint:fix\": \"web-ext lint --fix\",\n format: \"web-ext format\",\n test: \"web-ext test\",\n verify: \"web-ext verify\",\n \"verify:setup\": \"web-ext verify --setup\",\n visualize: \"web-ext visualize\",\n \"visualize:export\": \"web-ext visualize --export\",\n \"visualize:serve\": \"web-ext visualize --serve\",\n },\n dependencies: {\n \"@fairfox/web-ext\": \"*\",\n },\n };\n\n writeFileSync(`${projectPath}/package.json`, JSON.stringify(packageJson, null, 2));\n\n // Create manifest.json at root\n const manifest = {\n manifest_version: 3,\n name: projectName,\n version: \"0.1.0\",\n description: \"A Chrome extension built with @fairfox/web-ext\",\n background: {\n service_worker: \"background/index.js\",\n type: \"module\",\n },\n action: {\n default_popup: \"popup/popup.html\",\n },\n permissions: [\"storage\"],\n };\n\n writeFileSync(`${projectPath}/manifest.json`, JSON.stringify(manifest, null, 2));\n\n // Create background script\n const backgroundScript = `/**\n * Background Service Worker\n */\n\nimport { getMessageBus } from \"@fairfox/web-ext/message-bus\";\nimport { MessageRouter } from \"@fairfox/web-ext/message-router\";\n\nconst bus = getMessageBus(\"background\");\nnew MessageRouter(bus);\n\n// Add your message handlers here\nbus.on(\"PING\", async () => {\n return { success: true, message: \"pong\" };\n});\n\nconsole.log(\"Background service worker initialized\");\n`;\n\n writeFileSync(`${projectPath}/src/background/index.ts`, backgroundScript);\n\n // Create popup HTML in src/popup\n const popupHtml = `<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <title>${projectName}</title>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"./index.js\"></script>\n </body>\n</html>\n`;\n\n writeFileSync(`${projectPath}/src/popup/popup.html`, popupHtml);\n\n // Create popup script\n const popupScript = `/**\n * Popup UI\n */\n\nimport { getMessageBus } from \"@fairfox/web-ext/message-bus\";\n\nconst bus = getMessageBus(\"popup\");\n\n// Simple example without UI framework\nconst root = document.getElementById(\"root\");\n\nif (root) {\n root.innerHTML = \\`\n <div style=\"padding: 16px; min-width: 200px;\">\n <h1 style=\"margin: 0 0 8px 0; font-size: 18px;\">${projectName}</h1>\n <button id=\"ping-btn\" style=\"padding: 8px 16px;\">Ping Background</button>\n <p id=\"response\" style=\"margin-top: 8px; font-size: 14px;\"></p>\n </div>\n \\`;\n\n const btn = document.getElementById(\"ping-btn\");\n const response = document.getElementById(\"response\");\n\n btn?.addEventListener(\"click\", async () => {\n const result = await bus.send({ type: \"PING\" });\n if (response) {\n response.textContent = JSON.stringify(result);\n }\n });\n}\n`;\n\n writeFileSync(`${projectPath}/src/popup/index.ts`, popupScript);\n\n // Create tsconfig.json\n const tsconfig = {\n compilerOptions: {\n target: \"ES2022\",\n module: \"ESNext\",\n lib: [\"ES2022\", \"DOM\"],\n moduleResolution: \"bundler\",\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n forceConsistentCasingInFileNames: true,\n resolveJsonModule: true,\n allowSyntheticDefaultImports: true,\n jsx: \"react-jsx\",\n jsxImportSource: \"preact\",\n },\n include: [\"src/**/*\"],\n };\n\n writeFileSync(`${projectPath}/tsconfig.json`, JSON.stringify(tsconfig, null, 2));\n\n // Create biome.json\n const biomeConfig = {\n files: {\n includes: [\"src/**/*.ts\", \"src/**/*.tsx\"],\n ignoreUnknown: true,\n },\n linter: {\n enabled: true,\n rules: {\n recommended: true,\n },\n },\n formatter: {\n enabled: true,\n indentStyle: \"space\",\n indentWidth: 2,\n },\n };\n\n writeFileSync(`${projectPath}/biome.json`, JSON.stringify(biomeConfig, null, 2));\n\n // Create README\n const readme = `# ${projectName}\n\nA Chrome extension built with [@fairfox/web-ext](https://github.com/fairfox/web-ext).\n\n## Getting Started\n\n1. Install dependencies:\n \\`\\`\\`bash\n bun install\n \\`\\`\\`\n\n2. Build the extension:\n \\`\\`\\`bash\n bun run build\n \\`\\`\\`\n\n3. Load the extension in Chrome:\n - Open \\`chrome://extensions\\`\n - Enable \"Developer mode\"\n - Click \"Load unpacked\"\n - Select the \\`dist/\\` folder\n\n## Development\n\n- \\`bun run build\\` - Build the extension\n- \\`bun run check\\` - Run all checks (typecheck, lint, test, build)\n- \\`bun run typecheck\\` - Type check your code\n- \\`bun run lint\\` - Lint your code\n- \\`bun run format\\` - Format your code\n- \\`bun run verify\\` - Run formal verification\n- \\`bun run visualize\\` - Generate architecture diagrams\n\n## Project Structure\n\n\\`\\`\\`\n${projectName}/\n├── src/\n│ ├── background/\n│ │ └── index.ts # Background service worker\n│ └── popup/\n│ ├── popup.html # Popup HTML\n│ └── index.ts # Popup script\n├── manifest.json # Extension manifest\n├── dist/ # Build output (load this in Chrome)\n├── package.json\n├── tsconfig.json\n└── biome.json\n\\`\\`\\`\n`;\n\n writeFileSync(`${projectPath}/README.md`, readme);\n\n // Create .gitignore\n const gitignore = `node_modules\ndist\ndocs\n.DS_Store\n`;\n\n writeFileSync(`${projectPath}/.gitignore`, gitignore);\n}\n\n/**\n * Help command\n */\nfunction help() {\n // Help is shown automatically via commander\n}\n\n/**\n * Main entry point\n */\nasync function main() {\n try {\n switch (command) {\n case \"init\":\n await init();\n break;\n case \"check\":\n await check();\n break;\n case \"build\":\n await build();\n break;\n case \"dev\":\n await dev();\n break;\n case \"typecheck\":\n await typecheck();\n break;\n case \"lint\":\n await lint();\n break;\n case \"format\":\n await format();\n break;\n case \"test\":\n await test();\n break;\n case \"verify\":\n await verify();\n break;\n case \"visualize\":\n await visualize();\n break;\n case \"help\":\n case \"--help\":\n case \"-h\":\n case undefined:\n help();\n break;\n default:\n console.error(`❌ Unknown command: ${command}\\n`);\n help();\n process.exit(1);\n }\n } catch (error) {\n console.error(\"\\n❌ Command failed:\", error);\n process.exit(1);\n }\n}\n\nmain();\n"
5
+ "#!/usr/bin/env bun\n/**\n * Polly CLI\n *\n * Command-line tool for building multi-execution-context applications\n * with reactive state and cross-context messaging.\n *\n * Supports: Chrome extensions, PWAs, Node/Bun/Deno apps with workers\n *\n * Usage:\n * polly init [name] [--type=TYPE] Create a new project\n * polly check Run all checks (typecheck, lint, test, build)\n * polly build [options] Build the project\n * polly dev Build with watch mode\n * polly typecheck Type check your code\n * polly lint [--fix] Lint your code\n * polly format Format your code\n * polly test [args] Run tests (requires bun test)\n * polly verify [args] Run formal verification\n * polly visualize [args] Generate architecture diagrams\n * polly help Show help\n *\n * Project Types (init --type):\n * extension Chrome/Firefox extension (default)\n * pwa Progressive Web App with workers\n * websocket WebSocket server application\n * generic Generic TypeScript project\n *\n * Options:\n * --prod Build for production (minified)\n * --config <path> Path to config file (default: polly.config.ts)\n * --fix Auto-fix lint/format issues\n * --type=TYPE Project type for init command\n */\n\nimport { existsSync } from \"node:fs\";\nimport {\n type ProjectType,\n getTemplateDir,\n scaffoldFromTemplate,\n validateProjectName,\n} from \"./template-utils\";\n\n// Use Bun built-ins instead of Node.js APIs\nconst __dirname = import.meta.dir;\n\nconst command = process.argv[2];\nconst commandArgs = process.argv.slice(3);\nconst cwd = process.cwd();\n\n// Parse arguments\nconst args = {\n prod: process.argv.includes(\"--prod\"),\n config: process.argv.includes(\"--config\")\n ? process.argv[process.argv.indexOf(\"--config\") + 1]\n : undefined,\n};\n\n/**\n * Load user's configuration\n */\nasync function loadConfig() {\n const configPaths = [\n args.config,\n `${cwd}/polly.config.ts`,\n `${cwd}/polly.config.js`,\n `${cwd}/polly.config.mjs`,\n ].filter(Boolean) as string[];\n\n for (const configPath of configPaths) {\n // Use Bun.file().exists() instead of existsSync\n if (await Bun.file(configPath).exists()) {\n try {\n const config = await import(configPath);\n return config.default || config;\n } catch (error) {\n console.error(`❌ Failed to load config: ${configPath}`);\n throw error;\n }\n }\n }\n return {\n srcDir: \"src\",\n distDir: \"dist\",\n manifest: \"manifest.json\",\n };\n}\n\n/**\n * Build command - build the extension\n */\nasync function build() {\n const config = await loadConfig();\n\n // Check if bundled (published) or in monorepo\n const bundledScript = `${__dirname}/../scripts/build-extension.js`;\n const monorepoScript = `${__dirname}/../scripts/build-extension.ts`;\n const buildScriptPath = (await Bun.file(bundledScript).exists()) ? bundledScript : monorepoScript;\n\n // Pass config via environment\n process.env[\"WEB_EXT_SRC\"] = `${cwd}/${config.srcDir || \"src\"}`;\n process.env[\"WEB_EXT_DIST\"] = `${cwd}/${config.distDir || \"dist\"}`;\n process.env[\"WEB_EXT_MANIFEST\"] = `${cwd}/${config.manifest || \"manifest.json\"}`;\n process.env[\"WEB_EXT_CWD\"] = cwd;\n process.env[\"WEB_EXT_PROD\"] = args.prod ? \"true\" : \"false\";\n\n // Run build\n const proc = Bun.spawn([\"bun\", buildScriptPath], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n process.exit(exitCode);\n }\n}\n\n/**\n * Dev command - build with watch mode\n */\nasync function dev() {\n await build();\n}\n\n/**\n * Verify command - delegate to @fairfox/web-ext-verify\n */\nasync function verify() {\n // Check if bundled (published) or in monorepo\n const bundledCli = `${__dirname}/../vendor/verify/src/cli.js`;\n const monorepoCli = `${__dirname}/../../verify/src/cli.ts`;\n const verifyCli = (await Bun.file(bundledCli).exists()) ? bundledCli : monorepoCli;\n\n const proc = Bun.spawn([\"bun\", verifyCli, ...commandArgs], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n stdin: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Verification failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Visualize command - delegate to @fairfox/polly-visualize\n */\nasync function visualize() {\n // Check if bundled (published) or in monorepo\n const bundledCli = `${__dirname}/../vendor/visualize/src/cli.js`;\n const monorepoCli = `${__dirname}/../../visualize/src/cli.ts`;\n const visualizeCli = (await Bun.file(bundledCli).exists()) ? bundledCli : monorepoCli;\n\n const proc = Bun.spawn([\"bun\", visualizeCli, ...commandArgs], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n stdin: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Visualization failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Typecheck command - run TypeScript type checking\n */\nasync function typecheck() {\n const proc = Bun.spawn([\"bunx\", \"tsc\", \"--noEmit\"], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Type checking failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Lint command - run Biome linter\n */\nasync function lint() {\n const fix = commandArgs.includes(\"--fix\");\n const lintArgs = fix ? [\"check\", \"--write\", \".\"] : [\"check\", \".\"];\n\n const proc = Bun.spawn([\"bunx\", \"@biomejs/biome\", ...lintArgs], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Linting failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Format command - run Biome formatter\n */\nasync function format() {\n const proc = Bun.spawn([\"bunx\", \"@biomejs/biome\", \"format\", \"--write\", \".\"], {\n cwd,\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n if (exitCode !== 0) {\n throw new Error(`Formatting failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Test command - run Bun tests\n */\nasync function test() {\n const proc = Bun.spawn([\"bun\", \"test\", ...commandArgs], {\n cwd,\n stdout: \"pipe\",\n stderr: \"pipe\",\n stdin: \"inherit\",\n });\n\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\n\n // Output the results\n if (stdout) process.stdout.write(stdout);\n if (stderr) process.stderr.write(stderr);\n\n const exitCode = await proc.exited;\n\n // Check if no tests were found (not a failure)\n if (stderr.includes(\"0 test files matching\")) {\n return;\n }\n\n if (exitCode !== 0) {\n throw new Error(`Tests failed with exit code ${exitCode}`);\n }\n}\n\n/**\n * Check command - run all quality checks in sequence\n */\nasync function check() {\n const checks = [\n { name: \"Type checking\", fn: typecheck },\n { name: \"Linting\", fn: lint },\n { name: \"Testing\", fn: test },\n { name: \"Building\", fn: build },\n { name: \"Verification\", fn: verify, optional: true },\n { name: \"Visualization\", fn: visualize, optional: true },\n ];\n\n for (const { name, fn, optional } of checks) {\n try {\n await fn();\n } catch (_error) {\n if (optional) {\n continue;\n }\n console.error(`\\n\\x1b[31m✗ ${name} failed\\x1b[0m\\n`);\n process.exit(1);\n }\n }\n}\n\n/**\n * Init command - scaffold a new project\n */\nasync function init() {\n // Parse arguments\n const projectName = commandArgs[0] || \"my-project\";\n const typeArg =\n commandArgs.find((arg) => arg.startsWith(\"--type=\"))?.split(\"=\")[1] || \"extension\";\n const projectType = typeArg as ProjectType;\n\n // Validate project name\n const validation = validateProjectName(projectName);\n if (!validation.valid) {\n console.error(`\\x1b[31m✗ ${validation.error}\\x1b[0m\\n`);\n process.exit(1);\n }\n\n const projectPath = `${cwd}/${projectName}`;\n\n // Check if directory already exists\n if (existsSync(projectPath)) {\n console.error(`\\x1b[31m✗ Directory '${projectName}' already exists\\x1b[0m\\n`);\n process.exit(1);\n }\n\n // Get template directory\n const templateDir = getTemplateDir(projectType, __dirname);\n\n // Scaffold project\n await scaffoldFromTemplate({\n projectName,\n projectPath,\n projectType,\n templateDir,\n });\n}\n\n/**\n * Help command\n */\nfunction help() {\n // Help is shown automatically via commander\n}\n\n/**\n * Main entry point\n */\nasync function main() {\n try {\n switch (command) {\n case \"init\":\n await init();\n break;\n case \"check\":\n await check();\n break;\n case \"build\":\n await build();\n break;\n case \"dev\":\n await dev();\n break;\n case \"typecheck\":\n await typecheck();\n break;\n case \"lint\":\n await lint();\n break;\n case \"format\":\n await format();\n break;\n case \"test\":\n await test();\n break;\n case \"verify\":\n await verify();\n break;\n case \"visualize\":\n await visualize();\n break;\n case \"help\":\n case \"--help\":\n case \"-h\":\n case undefined:\n help();\n break;\n default:\n console.error(`❌ Unknown command: ${command}\\n`);\n help();\n process.exit(1);\n }\n } catch (error) {\n console.error(\"\\n❌ Command failed:\", error);\n process.exit(1);\n }\n}\n\nmain();\n",
6
+ "/**\n * Template utilities for project initialization\n */\n\nimport { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type ProjectType = \"extension\" | \"pwa\" | \"websocket\" | \"generic\";\n\nexport interface TemplateOptions {\n projectName: string;\n projectPath: string;\n projectType: ProjectType;\n templateDir: string;\n}\n\n/**\n * Process template file and replace placeholders\n */\nexport function processTemplate(content: string, projectName: string): string {\n return content\n .replace(/\\{\\{PROJECT_NAME\\}\\}/g, projectName)\n .replace(/\\{\\{PROJECT_NAME_UPPER\\}\\}/g, projectName.toUpperCase())\n .replace(/\\{\\{PROJECT_NAME_CAMEL\\}\\}/g, toCamelCase(projectName));\n}\n\n/**\n * Convert string to camelCase\n */\nfunction toCamelCase(str: string): string {\n return str\n .replace(/[-_](.)/g, (_, char) => char.toUpperCase())\n .replace(/^(.)/, (char) => char.toLowerCase());\n}\n\n/**\n * Copy template directory to project\n */\nexport async function scaffoldFromTemplate(options: TemplateOptions): Promise<void> {\n const { projectName, projectPath, templateDir } = options;\n\n // Create project directory\n mkdirSync(projectPath, { recursive: true });\n\n // Copy all template files\n copyTemplateFiles(templateDir, projectPath, projectName);\n}\n\n/**\n * Recursively copy template files and process them\n */\nfunction copyTemplateFiles(\n sourceDir: string,\n targetDir: string,\n projectName: string,\n relativePath = \"\"\n): void {\n if (!existsSync(sourceDir)) {\n throw new Error(`Template directory not found: ${sourceDir}`);\n }\n\n const entries = readdirSync(sourceDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const sourcePath = join(sourceDir, entry.name);\n const targetPath = join(targetDir, relativePath, entry.name.replace(\".template\", \"\"));\n\n if (entry.isDirectory()) {\n // Create directory and recurse\n mkdirSync(targetPath, { recursive: true });\n copyTemplateFiles(sourceDir, targetDir, projectName, join(relativePath, entry.name));\n } else if (entry.name.endsWith(\".template\")) {\n // Process template file\n const content = readFileSync(sourcePath, \"utf-8\");\n const processed = processTemplate(content, projectName);\n writeFileSync(targetPath, processed, \"utf-8\");\n } else {\n // Copy binary files as-is\n cpSync(sourcePath, targetPath);\n }\n }\n}\n\n/**\n * Get available project types\n */\nexport function getAvailableTypes(): ProjectType[] {\n return [\"extension\", \"pwa\", \"websocket\", \"generic\"];\n}\n\n/**\n * Get template directory for project type\n */\nexport function getTemplateDir(projectType: ProjectType, baseDir: string): string {\n return join(baseDir, \"..\", \"templates\", projectType);\n}\n\n/**\n * Validate project name\n */\nexport function validateProjectName(name: string): {\n valid: boolean;\n error?: string;\n} {\n if (!name || name.trim().length === 0) {\n return { valid: false, error: \"Project name cannot be empty\" };\n }\n\n if (!/^[a-z0-9-_]+$/i.test(name)) {\n return {\n valid: false,\n error: \"Project name can only contain letters, numbers, hyphens, and underscores\",\n };\n }\n\n if (name.startsWith(\"-\") || name.startsWith(\"_\")) {\n return {\n valid: false,\n error: \"Project name cannot start with a hyphen or underscore\",\n };\n }\n\n return { valid: true };\n}\n"
6
7
  ],
7
- "mappings": "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",
8
- "debugId": "BB7E0889114F14F064756E2164756E21",
8
+ "mappings": ";;;;;;;;;;;;;;;;;AAmCA,uBAAS;;;AC/BT;AACA;AAcO,SAAS,eAAe,CAAC,SAAiB,aAA6B;AAAA,EAC5E,OAAO,QACJ,QAAQ,yBAAyB,WAAW,EAC5C,QAAQ,+BAA+B,YAAY,YAAY,CAAC,EAChE,QAAQ,+BAA+B,YAAY,WAAW,CAAC;AAAA;AAMpE,SAAS,WAAW,CAAC,KAAqB;AAAA,EACxC,OAAO,IACJ,QAAQ,YAAY,CAAC,GAAG,SAAS,KAAK,YAAY,CAAC,EACnD,QAAQ,QAAQ,CAAC,SAAS,KAAK,YAAY,CAAC;AAAA;AAMjD,eAAsB,oBAAoB,CAAC,SAAyC;AAAA,EAClF,QAAQ,aAAa,aAAa,gBAAgB;AAAA,EAGlD,UAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAAA,EAG1C,kBAAkB,aAAa,aAAa,WAAW;AAAA;AAMzD,SAAS,iBAAiB,CACxB,WACA,WACA,aACA,eAAe,IACT;AAAA,EACN,IAAI,CAAC,WAAW,SAAS,GAAG;AAAA,IAC1B,MAAM,IAAI,MAAM,iCAAiC,WAAW;AAAA,EAC9D;AAAA,EAEA,MAAM,UAAU,YAAY,WAAW,EAAE,eAAe,KAAK,CAAC;AAAA,EAE9D,WAAW,SAAS,SAAS;AAAA,IAC3B,MAAM,aAAa,KAAK,WAAW,MAAM,IAAI;AAAA,IAC7C,MAAM,aAAa,KAAK,WAAW,cAAc,MAAM,KAAK,QAAQ,aAAa,EAAE,CAAC;AAAA,IAEpF,IAAI,MAAM,YAAY,GAAG;AAAA,MAEvB,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,MACzC,kBAAkB,WAAW,WAAW,aAAa,KAAK,cAAc,MAAM,IAAI,CAAC;AAAA,IACrF,EAAO,SAAI,MAAM,KAAK,SAAS,WAAW,GAAG;AAAA,MAE3C,MAAM,UAAU,aAAa,YAAY,OAAO;AAAA,MAChD,MAAM,YAAY,gBAAgB,SAAS,WAAW;AAAA,MACtD,cAAc,YAAY,WAAW,OAAO;AAAA,IAC9C,EAAO;AAAA,MAEL,OAAO,YAAY,UAAU;AAAA;AAAA,EAEjC;AAAA;AAaK,SAAS,cAAc,CAAC,aAA0B,SAAyB;AAAA,EAChF,OAAO,KAAK,SAAS,MAAM,aAAa,WAAW;AAAA;AAM9C,SAAS,mBAAmB,CAAC,MAGlC;AAAA,EACA,IAAI,CAAC,QAAQ,KAAK,KAAK,EAAE,WAAW,GAAG;AAAA,IACrC,OAAO,EAAE,OAAO,OAAO,OAAO,+BAA+B;AAAA,EAC/D;AAAA,EAEA,IAAI,CAAC,iBAAiB,KAAK,IAAI,GAAG;AAAA,IAChC,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,IAAI,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,GAAG;AAAA,IAChD,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,OAAO,EAAE,OAAO,KAAK;AAAA;;;AD9EvB,IAAM,aAAY,YAAY;AAE9B,IAAM,UAAU,QAAQ,KAAK;AAC7B,IAAM,cAAc,QAAQ,KAAK,MAAM,CAAC;AACxC,IAAM,MAAM,QAAQ,IAAI;AAGxB,IAAM,OAAO;AAAA,EACX,MAAM,QAAQ,KAAK,SAAS,QAAQ;AAAA,EACpC,QAAQ,QAAQ,KAAK,SAAS,UAAU,IACpC,QAAQ,KAAK,QAAQ,KAAK,QAAQ,UAAU,IAAI,KAChD;AACN;AAKA,eAAe,UAAU,GAAG;AAAA,EAC1B,MAAM,cAAc;AAAA,IAClB,KAAK;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL,EAAE,OAAO,OAAO;AAAA,EAEhB,WAAW,cAAc,aAAa;AAAA,IAEpC,IAAI,MAAM,IAAI,KAAK,UAAU,EAAE,OAAO,GAAG;AAAA,MACvC,IAAI;AAAA,QACF,MAAM,SAAS,MAAa;AAAA,QAC5B,OAAO,OAAO,WAAW;AAAA,QACzB,OAAO,OAAO;AAAA,QACd,QAAQ,MAAM,iCAA2B,YAAY;AAAA,QACrD,MAAM;AAAA;AAAA,IAEV;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAMF,eAAe,KAAK,GAAG;AAAA,EACrB,MAAM,SAAS,MAAM,WAAW;AAAA,EAGhC,MAAM,gBAAgB,GAAG;AAAA,EACzB,MAAM,iBAAiB,GAAG;AAAA,EAC1B,MAAM,kBAAmB,MAAM,IAAI,KAAK,aAAa,EAAE,OAAO,IAAK,gBAAgB;AAAA,EAGnF,QAAQ,IAAI,iBAAiB,GAAG,OAAO,OAAO,UAAU;AAAA,EACxD,QAAQ,IAAI,kBAAkB,GAAG,OAAO,OAAO,WAAW;AAAA,EAC1D,QAAQ,IAAI,sBAAsB,GAAG,OAAO,OAAO,YAAY;AAAA,EAC/D,QAAQ,IAAI,iBAAiB;AAAA,EAC7B,QAAQ,IAAI,kBAAkB,KAAK,OAAO,SAAS;AAAA,EAGnD,MAAM,OAAO,IAAI,MAAM,CAAC,OAAO,eAAe,GAAG;AAAA,IAC/C;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAAA,EAED,MAAM,WAAW,MAAM,KAAK;AAAA,EAC5B,IAAI,aAAa,GAAG;AAAA,IAClB,QAAQ,KAAK,QAAQ;AAAA,EACvB;AAAA;AAMF,eAAe,GAAG,GAAG;AAAA,EACnB,MAAM,MAAM;AAAA;AAMd,eAAe,MAAM,GAAG;AAAA,EAEtB,MAAM,aAAa,GAAG;AAAA,EACtB,MAAM,cAAc,GAAG;AAAA,EACvB,MAAM,YAAa,MAAM,IAAI,KAAK,UAAU,EAAE,OAAO,IAAK,aAAa;AAAA,EAEvE,MAAM,OAAO,IAAI,MAAM,CAAC,OAAO,WAAW,GAAG,WAAW,GAAG;AAAA,IACzD;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,EACT,CAAC;AAAA,EAED,MAAM,WAAW,MAAM,KAAK;AAAA,EAC5B,IAAI,aAAa,GAAG;AAAA,IAClB,MAAM,IAAI,MAAM,sCAAsC,UAAU;AAAA,EAClE;AAAA;AAMF,eAAe,SAAS,GAAG;AAAA,EAEzB,MAAM,aAAa,GAAG;AAAA,EACtB,MAAM,cAAc,GAAG;AAAA,EACvB,MAAM,eAAgB,MAAM,IAAI,KAAK,UAAU,EAAE,OAAO,IAAK,aAAa;AAAA,EAE1E,MAAM,OAAO,IAAI,MAAM,CAAC,OAAO,cAAc,GAAG,WAAW,GAAG;AAAA,IAC5D;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,EACT,CAAC;AAAA,EAED,MAAM,WAAW,MAAM,KAAK;AAAA,EAC5B,IAAI,aAAa,GAAG;AAAA,IAClB,MAAM,IAAI,MAAM,uCAAuC,UAAU;AAAA,EACnE;AAAA;AAMF,eAAe,SAAS,GAAG;AAAA,EACzB,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,OAAO,UAAU,GAAG;AAAA,IAClD;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAAA,EAED,MAAM,WAAW,MAAM,KAAK;AAAA,EAC5B,IAAI,aAAa,GAAG;AAAA,IAClB,MAAM,IAAI,MAAM,uCAAuC,UAAU;AAAA,EACnE;AAAA;AAMF,eAAe,IAAI,GAAG;AAAA,EACpB,MAAM,MAAM,YAAY,SAAS,OAAO;AAAA,EACxC,MAAM,WAAW,MAAM,CAAC,SAAS,WAAW,GAAG,IAAI,CAAC,SAAS,GAAG;AAAA,EAEhE,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,kBAAkB,GAAG,QAAQ,GAAG;AAAA,IAC9D;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAAA,EAED,MAAM,WAAW,MAAM,KAAK;AAAA,EAC5B,IAAI,aAAa,GAAG;AAAA,IAClB,MAAM,IAAI,MAAM,iCAAiC,UAAU;AAAA,EAC7D;AAAA;AAMF,eAAe,MAAM,GAAG;AAAA,EACtB,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,kBAAkB,UAAU,WAAW,GAAG,GAAG;AAAA,IAC3E;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAAA,EAED,MAAM,WAAW,MAAM,KAAK;AAAA,EAC5B,IAAI,aAAa,GAAG;AAAA,IAClB,MAAM,IAAI,MAAM,oCAAoC,UAAU;AAAA,EAChE;AAAA;AAMF,eAAe,IAAI,GAAG;AAAA,EACpB,MAAM,OAAO,IAAI,MAAM,CAAC,OAAO,QAAQ,GAAG,WAAW,GAAG;AAAA,IACtD;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,EACT,CAAC;AAAA,EAED,MAAM,SAAS,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,EACpD,MAAM,SAAS,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,EAGpD,IAAI;AAAA,IAAQ,QAAQ,OAAO,MAAM,MAAM;AAAA,EACvC,IAAI;AAAA,IAAQ,QAAQ,OAAO,MAAM,MAAM;AAAA,EAEvC,MAAM,WAAW,MAAM,KAAK;AAAA,EAG5B,IAAI,OAAO,SAAS,uBAAuB,GAAG;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,IAAI,aAAa,GAAG;AAAA,IAClB,MAAM,IAAI,MAAM,+BAA+B,UAAU;AAAA,EAC3D;AAAA;AAMF,eAAe,KAAK,GAAG;AAAA,EACrB,MAAM,SAAS;AAAA,IACb,EAAE,MAAM,iBAAiB,IAAI,UAAU;AAAA,IACvC,EAAE,MAAM,WAAW,IAAI,KAAK;AAAA,IAC5B,EAAE,MAAM,WAAW,IAAI,KAAK;AAAA,IAC5B,EAAE,MAAM,YAAY,IAAI,MAAM;AAAA,IAC9B,EAAE,MAAM,gBAAgB,IAAI,QAAQ,UAAU,KAAK;AAAA,IACnD,EAAE,MAAM,iBAAiB,IAAI,WAAW,UAAU,KAAK;AAAA,EACzD;AAAA,EAEA,aAAa,MAAM,IAAI,cAAc,QAAQ;AAAA,IAC3C,IAAI;AAAA,MACF,MAAM,GAAG;AAAA,MACT,OAAO,QAAQ;AAAA,MACf,IAAI,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAQ,MAAM;AAAA,iBAAc;AAAA,CAAsB;AAAA,MAClD,QAAQ,KAAK,CAAC;AAAA;AAAA,EAElB;AAAA;AAMF,eAAe,IAAI,GAAG;AAAA,EAEpB,MAAM,cAAc,YAAY,MAAM;AAAA,EACtC,MAAM,UACJ,YAAY,KAAK,CAAC,QAAQ,IAAI,WAAW,SAAS,CAAC,GAAG,MAAM,GAAG,EAAE,MAAM;AAAA,EACzE,MAAM,cAAc;AAAA,EAGpB,MAAM,aAAa,oBAAoB,WAAW;AAAA,EAClD,IAAI,CAAC,WAAW,OAAO;AAAA,IACrB,QAAQ,MAAM,kBAAY,WAAW;AAAA,CAAgB;AAAA,IACrD,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EAEA,MAAM,cAAc,GAAG,OAAO;AAAA,EAG9B,IAAI,YAAW,WAAW,GAAG;AAAA,IAC3B,QAAQ,MAAM,6BAAuB;AAAA,CAAsC;AAAA,IAC3E,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EAGA,MAAM,cAAc,eAAe,aAAa,UAAS;AAAA,EAGzD,MAAM,qBAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAAA;AAMH,SAAS,IAAI,GAAG;AAOhB,eAAe,IAAI,GAAG;AAAA,EACpB,IAAI;AAAA,IACF,QAAQ;AAAA,WACD;AAAA,QACH,MAAM,KAAK;AAAA,QACX;AAAA,WACG;AAAA,QACH,MAAM,MAAM;AAAA,QACZ;AAAA,WACG;AAAA,QACH,MAAM,MAAM;AAAA,QACZ;AAAA,WACG;AAAA,QACH,MAAM,IAAI;AAAA,QACV;AAAA,WACG;AAAA,QACH,MAAM,UAAU;AAAA,QAChB;AAAA,WACG;AAAA,QACH,MAAM,KAAK;AAAA,QACX;AAAA,WACG;AAAA,QACH,MAAM,OAAO;AAAA,QACb;AAAA,WACG;AAAA,QACH,MAAM,KAAK;AAAA,QACX;AAAA,WACG;AAAA,QACH,MAAM,OAAO;AAAA,QACb;AAAA,WACG;AAAA,QACH,MAAM,UAAU;AAAA,QAChB;AAAA,WACG;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,QACH,KAAK;AAAA,QACL;AAAA;AAAA,QAEA,QAAQ,MAAM,2BAAqB;AAAA,CAAW;AAAA,QAC9C,KAAK;AAAA,QACL,QAAQ,KAAK,CAAC;AAAA;AAAA,IAElB,OAAO,OAAO;AAAA,IACd,QAAQ,MAAM;AAAA,yBAAsB,KAAK;AAAA,IACzC,QAAQ,KAAK,CAAC;AAAA;AAAA;AAIlB,KAAK;",
9
+ "debugId": "498624C7345252DB64756E2164756E21",
9
10
  "names": []
10
11
  }
@@ -0,0 +1,81 @@
1
+ import { createRequire } from "node:module";
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true,
8
+ configurable: true,
9
+ set: (newValue) => all[name] = () => newValue
10
+ });
11
+ };
12
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
13
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
14
+
15
+ // cli/template-utils.ts
16
+ import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
17
+ import { join } from "node:path";
18
+ function processTemplate(content, projectName) {
19
+ return content.replace(/\{\{PROJECT_NAME\}\}/g, projectName).replace(/\{\{PROJECT_NAME_UPPER\}\}/g, projectName.toUpperCase()).replace(/\{\{PROJECT_NAME_CAMEL\}\}/g, toCamelCase(projectName));
20
+ }
21
+ function toCamelCase(str) {
22
+ return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase()).replace(/^(.)/, (char) => char.toLowerCase());
23
+ }
24
+ async function scaffoldFromTemplate(options) {
25
+ const { projectName, projectPath, templateDir } = options;
26
+ mkdirSync(projectPath, { recursive: true });
27
+ copyTemplateFiles(templateDir, projectPath, projectName);
28
+ }
29
+ function copyTemplateFiles(sourceDir, targetDir, projectName, relativePath = "") {
30
+ if (!existsSync(sourceDir)) {
31
+ throw new Error(`Template directory not found: ${sourceDir}`);
32
+ }
33
+ const entries = readdirSync(sourceDir, { withFileTypes: true });
34
+ for (const entry of entries) {
35
+ const sourcePath = join(sourceDir, entry.name);
36
+ const targetPath = join(targetDir, relativePath, entry.name.replace(".template", ""));
37
+ if (entry.isDirectory()) {
38
+ mkdirSync(targetPath, { recursive: true });
39
+ copyTemplateFiles(sourceDir, targetDir, projectName, join(relativePath, entry.name));
40
+ } else if (entry.name.endsWith(".template")) {
41
+ const content = readFileSync(sourcePath, "utf-8");
42
+ const processed = processTemplate(content, projectName);
43
+ writeFileSync(targetPath, processed, "utf-8");
44
+ } else {
45
+ cpSync(sourcePath, targetPath);
46
+ }
47
+ }
48
+ }
49
+ function getAvailableTypes() {
50
+ return ["extension", "pwa", "websocket", "generic"];
51
+ }
52
+ function getTemplateDir(projectType, baseDir) {
53
+ return join(baseDir, "..", "templates", projectType);
54
+ }
55
+ function validateProjectName(name) {
56
+ if (!name || name.trim().length === 0) {
57
+ return { valid: false, error: "Project name cannot be empty" };
58
+ }
59
+ if (!/^[a-z0-9-_]+$/i.test(name)) {
60
+ return {
61
+ valid: false,
62
+ error: "Project name can only contain letters, numbers, hyphens, and underscores"
63
+ };
64
+ }
65
+ if (name.startsWith("-") || name.startsWith("_")) {
66
+ return {
67
+ valid: false,
68
+ error: "Project name cannot start with a hyphen or underscore"
69
+ };
70
+ }
71
+ return { valid: true };
72
+ }
73
+ export {
74
+ validateProjectName,
75
+ scaffoldFromTemplate,
76
+ processTemplate,
77
+ getTemplateDir,
78
+ getAvailableTypes
79
+ };
80
+
81
+ //# debugId=88205CACB51C961664756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../cli/template-utils.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Template utilities for project initialization\n */\n\nimport { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type ProjectType = \"extension\" | \"pwa\" | \"websocket\" | \"generic\";\n\nexport interface TemplateOptions {\n projectName: string;\n projectPath: string;\n projectType: ProjectType;\n templateDir: string;\n}\n\n/**\n * Process template file and replace placeholders\n */\nexport function processTemplate(content: string, projectName: string): string {\n return content\n .replace(/\\{\\{PROJECT_NAME\\}\\}/g, projectName)\n .replace(/\\{\\{PROJECT_NAME_UPPER\\}\\}/g, projectName.toUpperCase())\n .replace(/\\{\\{PROJECT_NAME_CAMEL\\}\\}/g, toCamelCase(projectName));\n}\n\n/**\n * Convert string to camelCase\n */\nfunction toCamelCase(str: string): string {\n return str\n .replace(/[-_](.)/g, (_, char) => char.toUpperCase())\n .replace(/^(.)/, (char) => char.toLowerCase());\n}\n\n/**\n * Copy template directory to project\n */\nexport async function scaffoldFromTemplate(options: TemplateOptions): Promise<void> {\n const { projectName, projectPath, templateDir } = options;\n\n // Create project directory\n mkdirSync(projectPath, { recursive: true });\n\n // Copy all template files\n copyTemplateFiles(templateDir, projectPath, projectName);\n}\n\n/**\n * Recursively copy template files and process them\n */\nfunction copyTemplateFiles(\n sourceDir: string,\n targetDir: string,\n projectName: string,\n relativePath = \"\"\n): void {\n if (!existsSync(sourceDir)) {\n throw new Error(`Template directory not found: ${sourceDir}`);\n }\n\n const entries = readdirSync(sourceDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const sourcePath = join(sourceDir, entry.name);\n const targetPath = join(targetDir, relativePath, entry.name.replace(\".template\", \"\"));\n\n if (entry.isDirectory()) {\n // Create directory and recurse\n mkdirSync(targetPath, { recursive: true });\n copyTemplateFiles(sourceDir, targetDir, projectName, join(relativePath, entry.name));\n } else if (entry.name.endsWith(\".template\")) {\n // Process template file\n const content = readFileSync(sourcePath, \"utf-8\");\n const processed = processTemplate(content, projectName);\n writeFileSync(targetPath, processed, \"utf-8\");\n } else {\n // Copy binary files as-is\n cpSync(sourcePath, targetPath);\n }\n }\n}\n\n/**\n * Get available project types\n */\nexport function getAvailableTypes(): ProjectType[] {\n return [\"extension\", \"pwa\", \"websocket\", \"generic\"];\n}\n\n/**\n * Get template directory for project type\n */\nexport function getTemplateDir(projectType: ProjectType, baseDir: string): string {\n return join(baseDir, \"..\", \"templates\", projectType);\n}\n\n/**\n * Validate project name\n */\nexport function validateProjectName(name: string): {\n valid: boolean;\n error?: string;\n} {\n if (!name || name.trim().length === 0) {\n return { valid: false, error: \"Project name cannot be empty\" };\n }\n\n if (!/^[a-z0-9-_]+$/i.test(name)) {\n return {\n valid: false,\n error: \"Project name can only contain letters, numbers, hyphens, and underscores\",\n };\n }\n\n if (name.startsWith(\"-\") || name.startsWith(\"_\")) {\n return {\n valid: false,\n error: \"Project name cannot start with a hyphen or underscore\",\n };\n }\n\n return { valid: true };\n}\n"
6
+ ],
7
+ "mappings": ";;;;;;;;;;;;;;;AAIA;AACA;AAcO,SAAS,eAAe,CAAC,SAAiB,aAA6B;AAAA,EAC5E,OAAO,QACJ,QAAQ,yBAAyB,WAAW,EAC5C,QAAQ,+BAA+B,YAAY,YAAY,CAAC,EAChE,QAAQ,+BAA+B,YAAY,WAAW,CAAC;AAAA;AAMpE,SAAS,WAAW,CAAC,KAAqB;AAAA,EACxC,OAAO,IACJ,QAAQ,YAAY,CAAC,GAAG,SAAS,KAAK,YAAY,CAAC,EACnD,QAAQ,QAAQ,CAAC,SAAS,KAAK,YAAY,CAAC;AAAA;AAMjD,eAAsB,oBAAoB,CAAC,SAAyC;AAAA,EAClF,QAAQ,aAAa,aAAa,gBAAgB;AAAA,EAGlD,UAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAAA,EAG1C,kBAAkB,aAAa,aAAa,WAAW;AAAA;AAMzD,SAAS,iBAAiB,CACxB,WACA,WACA,aACA,eAAe,IACT;AAAA,EACN,IAAI,CAAC,WAAW,SAAS,GAAG;AAAA,IAC1B,MAAM,IAAI,MAAM,iCAAiC,WAAW;AAAA,EAC9D;AAAA,EAEA,MAAM,UAAU,YAAY,WAAW,EAAE,eAAe,KAAK,CAAC;AAAA,EAE9D,WAAW,SAAS,SAAS;AAAA,IAC3B,MAAM,aAAa,KAAK,WAAW,MAAM,IAAI;AAAA,IAC7C,MAAM,aAAa,KAAK,WAAW,cAAc,MAAM,KAAK,QAAQ,aAAa,EAAE,CAAC;AAAA,IAEpF,IAAI,MAAM,YAAY,GAAG;AAAA,MAEvB,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,MACzC,kBAAkB,WAAW,WAAW,aAAa,KAAK,cAAc,MAAM,IAAI,CAAC;AAAA,IACrF,EAAO,SAAI,MAAM,KAAK,SAAS,WAAW,GAAG;AAAA,MAE3C,MAAM,UAAU,aAAa,YAAY,OAAO;AAAA,MAChD,MAAM,YAAY,gBAAgB,SAAS,WAAW;AAAA,MACtD,cAAc,YAAY,WAAW,OAAO;AAAA,IAC9C,EAAO;AAAA,MAEL,OAAO,YAAY,UAAU;AAAA;AAAA,EAEjC;AAAA;AAMK,SAAS,iBAAiB,GAAkB;AAAA,EACjD,OAAO,CAAC,aAAa,OAAO,aAAa,SAAS;AAAA;AAM7C,SAAS,cAAc,CAAC,aAA0B,SAAyB;AAAA,EAChF,OAAO,KAAK,SAAS,MAAM,aAAa,WAAW;AAAA;AAM9C,SAAS,mBAAmB,CAAC,MAGlC;AAAA,EACA,IAAI,CAAC,QAAQ,KAAK,KAAK,EAAE,WAAW,GAAG;AAAA,IACrC,OAAO,EAAE,OAAO,OAAO,OAAO,+BAA+B;AAAA,EAC/D;AAAA,EAEA,IAAI,CAAC,iBAAiB,KAAK,IAAI,GAAG;AAAA,IAChC,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,IAAI,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,GAAG;AAAA,IAChD,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,OAAO,EAAE,OAAO,KAAK;AAAA;",
8
+ "debugId": "88205CACB51C961664756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,21 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  import { createRequire } from "node:module";
3
- var __create = Object.create;
4
- var __getProtoOf = Object.getPrototypeOf;
5
3
  var __defProp = Object.defineProperty;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __toESM = (mod, isNodeMode, target) => {
9
- target = mod != null ? __create(__getProtoOf(mod)) : {};
10
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
- for (let key of __getOwnPropNames(mod))
12
- if (!__hasOwnProp.call(to, key))
13
- __defProp(to, key, {
14
- get: () => mod[key],
15
- enumerable: true
16
- });
17
- return to;
18
- };
19
4
  var __export = (target, all) => {
20
5
  for (var name in all)
21
6
  __defProp(target, name, {
@@ -2086,4 +2071,4 @@ Stack trace:`, COLORS.gray));
2086
2071
  process.exit(1);
2087
2072
  });
2088
2073
 
2089
- //# debugId=10F00303D4610C9D64756E2164756E21
2074
+ //# debugId=1B244FC1308B4F2264756E2164756E21