exportc 0.0.6 → 0.0.7

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.
@@ -1,4 +1,3 @@
1
- import * as p from "@clack/prompts";
2
1
  import pc from "picocolors";
3
2
  import fs from "node:fs";
4
3
  import path from "node:path";
@@ -10,49 +9,44 @@ export async function deploy(argv) {
10
9
 
11
10
  // Check if export directory exists
12
11
  if (!fs.existsSync(exportDir)) {
13
- p.cancel(`No export/ directory found. Run ${pc.cyan("exportc init")} first.`);
12
+ console.error(pc.red("✗") + ` No export/ directory found. Run ${pc.cyan("exportc init")} first.`);
14
13
  process.exit(1);
15
14
  }
16
15
 
17
16
  // Check if dependencies are installed
18
17
  const nodeModules = path.join(exportDir, "node_modules");
19
18
  if (!fs.existsSync(nodeModules)) {
20
- p.cancel(`Dependencies not installed. Run ${pc.cyan("cd export && npm install")} first.`);
19
+ console.error(pc.red("✗") + ` Dependencies not installed. Run ${pc.cyan("cd export && npm install")} first.`);
21
20
  process.exit(1);
22
21
  }
23
22
 
24
- p.intro(pc.bgCyan(pc.black(" exportc deploy ")));
23
+ console.log(pc.cyan("exportc deploy"));
24
+ console.log();
25
25
 
26
26
  // Step 1: Build Vite
27
- const s1 = p.spinner();
28
- s1.start("Building with Vite...");
27
+ console.log("Building with Vite...");
29
28
 
30
29
  const viteBuild = spawn("npm", ["run", "build"], {
31
30
  cwd,
32
- stdio: ["ignore", "pipe", "pipe"],
31
+ stdio: "inherit",
33
32
  shell: true,
34
33
  });
35
34
 
36
- let viteBuildOutput = "";
37
- viteBuild.stdout.on("data", (data) => { viteBuildOutput += data.toString(); });
38
- viteBuild.stderr.on("data", (data) => { viteBuildOutput += data.toString(); });
39
-
40
35
  const viteExitCode = await new Promise((resolve) => {
41
36
  viteBuild.on("close", resolve);
42
37
  viteBuild.on("error", () => resolve(1));
43
38
  });
44
39
 
45
40
  if (viteExitCode !== 0) {
46
- s1.stop("Vite build failed");
47
- console.error(viteBuildOutput);
41
+ console.error(pc.red("✗") + " Vite build failed");
48
42
  process.exit(1);
49
43
  }
50
44
 
51
- s1.stop("Vite build complete");
45
+ console.log(pc.green("✓") + " Vite build complete");
46
+ console.log();
52
47
 
53
48
  // Step 2: Deploy to Cloudflare Workers
54
- const s2 = p.spinner();
55
- s2.start("Deploying to Cloudflare Workers...");
49
+ console.log("Deploying to Cloudflare Workers...");
56
50
 
57
51
  const wranglerDeploy = spawn("npm", ["run", "deploy"], {
58
52
  cwd: exportDir,
@@ -66,29 +60,15 @@ export async function deploy(argv) {
66
60
  });
67
61
 
68
62
  if (wranglerExitCode !== 0) {
69
- s2.stop("Deployment failed");
63
+ console.error(pc.red("✗") + " Deployment failed");
70
64
  process.exit(1);
71
65
  }
72
66
 
73
- s2.stop("Deployed successfully!");
74
-
75
67
  // Read worker name from export/package.json
76
68
  const exportPkgPath = path.join(exportDir, "package.json");
77
69
  const exportPkg = JSON.parse(fs.readFileSync(exportPkgPath, "utf8"));
78
70
  const workerName = exportPkg.name;
79
71
 
80
- p.note(
81
- `Your app is now live at:
82
- ${pc.cyan(`https://${workerName}.workers.dev/`)}
83
-
84
- ${pc.bold("What was deployed:")}
85
- - Static assets (Vite build output)
86
- - Server exports (export/ directory)
87
-
88
- ${pc.bold("Client imports will resolve to:")}
89
- ${pc.cyan(`https://${workerName}.workers.dev/`)}`,
90
- "Workers Sites"
91
- );
92
-
93
- p.outro("Done!");
72
+ console.log();
73
+ console.log(pc.green("✓") + " Deployed to " + pc.cyan(`https://${workerName}.workers.dev/`));
94
74
  }
package/commands/dev.js CHANGED
@@ -1,4 +1,3 @@
1
- import * as p from "@clack/prompts";
2
1
  import pc from "picocolors";
3
2
  import fs from "node:fs";
4
3
  import path from "node:path";
@@ -10,48 +9,33 @@ export async function dev(argv) {
10
9
 
11
10
  // Check if export directory exists
12
11
  if (!fs.existsSync(exportDir)) {
13
- p.cancel(`No export/ directory found. Run ${pc.cyan("exportc init")} first.`);
12
+ console.error(pc.red("✗") + ` No export/ directory found. Run ${pc.cyan("exportc init")} first.`);
14
13
  process.exit(1);
15
14
  }
16
15
 
17
16
  // Check if dependencies are installed
18
17
  const nodeModules = path.join(exportDir, "node_modules");
19
18
  if (!fs.existsSync(nodeModules)) {
20
- p.cancel(`Dependencies not installed. Run ${pc.cyan("cd export && npm install")} first.`);
19
+ console.error(pc.red("✗") + ` Dependencies not installed. Run ${pc.cyan("cd export && npm install")} first.`);
21
20
  process.exit(1);
22
21
  }
23
22
 
24
- p.intro(pc.bgCyan(pc.black(" exportc dev ")));
23
+ console.log(pc.cyan("exportc dev"));
24
+ console.log();
25
+ console.log("Starting Wrangler dev server...");
25
26
 
26
- const s = p.spinner();
27
- s.start("Starting export dev server...");
28
-
29
- // Generate types first
30
- const generateTypes = spawn("npm", ["run", "dev"], {
27
+ const wrangler = spawn("npm", ["run", "dev"], {
31
28
  cwd: exportDir,
32
29
  stdio: "inherit",
33
30
  shell: true,
34
31
  });
35
32
 
36
- generateTypes.on("error", (err) => {
37
- s.stop("Failed to start dev server");
38
- console.error(pc.red(err.message));
33
+ wrangler.on("error", (err) => {
34
+ console.error(pc.red("✗") + " Failed to start dev server");
35
+ console.error(err.message);
39
36
  process.exit(1);
40
37
  });
41
38
 
42
- s.stop("Export dev server started!");
43
-
44
- p.note(
45
- `Wrangler dev server is running at ${pc.cyan("http://localhost:8787")}
46
-
47
- ${pc.bold("In your Vite app:")}
48
- ${pc.cyan(`import { hello } from "export/";`)}
49
- ${pc.cyan(`const message = await hello("World");`)}
50
-
51
- ${pc.dim("Press Ctrl+C to stop")}`,
52
- "Running"
53
- );
54
-
55
39
  // Keep the process running
56
40
  await new Promise(() => {});
57
41
  }
package/commands/init.js CHANGED
@@ -1,106 +1,53 @@
1
- import * as p from "@clack/prompts";
2
1
  import pc from "picocolors";
3
2
  import fs from "node:fs";
4
3
  import path from "node:path";
5
- import { fileURLToPath } from "node:url";
6
4
  import { execSync } from "node:child_process";
7
5
 
8
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
-
10
6
  export async function init(argv) {
11
7
  const cwd = process.cwd();
12
- const isNonInteractive = argv.yes || argv.y || process.env.CI === "true";
13
8
 
14
- if (!isNonInteractive) {
15
- p.intro(pc.bgCyan(pc.black(" exportc init ")));
16
- }
9
+ console.log(pc.cyan("exportc init"));
10
+ console.log();
17
11
 
18
12
  // Check for Vite project
19
13
  const viteConfigFiles = ["vite.config.ts", "vite.config.js", "vite.config.mts", "vite.config.mjs"];
20
14
  const viteConfig = viteConfigFiles.find((f) => fs.existsSync(path.join(cwd, f)));
21
15
 
22
16
  if (!viteConfig) {
23
- if (isNonInteractive) {
24
- console.error("Error: No Vite config found. exportc currently only supports Vite projects.");
25
- process.exit(1);
26
- }
27
- p.cancel("No Vite config found. exportc currently only supports Vite projects.");
17
+ console.error(pc.red("✗") + " No Vite config found. exportc only supports Vite projects.");
28
18
  process.exit(1);
29
19
  }
30
20
 
31
21
  // Check for package.json
32
22
  const pkgPath = path.join(cwd, "package.json");
33
23
  if (!fs.existsSync(pkgPath)) {
34
- if (isNonInteractive) {
35
- console.error("Error: No package.json found.");
36
- process.exit(1);
37
- }
38
- p.cancel("No package.json found.");
24
+ console.error(pc.red("✗") + " No package.json found.");
39
25
  process.exit(1);
40
26
  }
41
27
 
42
28
  const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
43
29
 
44
- // Check if already initialized
45
- const exportDir = path.join(cwd, "export");
46
- if (fs.existsSync(exportDir) && !isNonInteractive) {
47
- const overwrite = await p.confirm({
48
- message: "export/ directory already exists. Continue and overwrite?",
49
- initialValue: false,
50
- });
51
- if (p.isCancel(overwrite) || !overwrite) {
52
- p.cancel("Operation cancelled.");
53
- process.exit(0);
54
- }
55
- }
56
-
57
- // Get worker name (use default in non-interactive mode)
58
- const defaultWorkerName = pkg.name ? `${pkg.name}-api` : "my-api";
59
- let workerName;
60
-
61
- if (isNonInteractive) {
62
- workerName = argv.name || defaultWorkerName;
63
- } else {
64
- workerName = await p.text({
65
- message: "Worker name:",
66
- placeholder: defaultWorkerName,
67
- defaultValue: defaultWorkerName,
68
- validate: (v) => {
69
- if (!v) return "Worker name is required";
70
- if (!/^[a-z0-9-]+$/.test(v)) return "Use lowercase letters, numbers, and hyphens only";
71
- },
72
- });
73
-
74
- if (p.isCancel(workerName)) {
75
- p.cancel("Operation cancelled.");
76
- process.exit(0);
77
- }
78
- }
30
+ // Auto-generate worker name from package name
31
+ const workerName = argv.name || (pkg.name ? `${pkg.name}-api` : "my-api");
79
32
 
80
33
  // Check for TypeScript
81
34
  const isTypeScript = viteConfig.endsWith(".ts") || viteConfig.endsWith(".mts") ||
82
35
  fs.existsSync(path.join(cwd, "tsconfig.json"));
83
36
 
84
- let s;
85
- if (!isNonInteractive) {
86
- s = p.spinner();
87
- s.start("Initializing export...");
88
- } else {
89
- console.log("Initializing export...");
90
- }
37
+ const exportDir = path.join(cwd, "export");
38
+ const ext = isTypeScript ? "ts" : "js";
91
39
 
92
40
  // Create export directory
41
+ console.log(pc.gray("Creating export directory..."));
93
42
  if (!fs.existsSync(exportDir)) {
94
43
  fs.mkdirSync(exportDir, { recursive: true });
95
44
  }
96
45
 
97
46
  // Create export/index.ts or index.js
98
- const ext = isTypeScript ? "ts" : "js";
99
47
  const indexPath = path.join(exportDir, `index.${ext}`);
100
48
  if (!fs.existsSync(indexPath)) {
101
49
  const template = isTypeScript
102
- ? `// Server-side exports - these will be available to your client code
103
- // Import from "export/" in your client code
50
+ ? `// Server-side exports - import from "export/" in your client code
104
51
 
105
52
  export async function hello(name: string): Promise<string> {
106
53
  return \`Hello, \${name}!\`;
@@ -126,8 +73,7 @@ export class Counter {
126
73
  }
127
74
  }
128
75
  `
129
- : `// Server-side exports - these will be available to your client code
130
- // Import from "export/" in your client code
76
+ : `// Server-side exports - import from "export/" in your client code
131
77
 
132
78
  export async function hello(name) {
133
79
  return \`Hello, \${name}!\`;
@@ -156,8 +102,8 @@ export class Counter {
156
102
  fs.writeFileSync(indexPath, template);
157
103
  }
158
104
 
159
- // Detect Vite build output directory from vite.config
160
- let viteBuildOutDir = "dist"; // default
105
+ // Detect Vite build output directory
106
+ let viteBuildOutDir = "dist";
161
107
  const viteConfigPath = path.join(cwd, viteConfig);
162
108
  let viteConfigContent = fs.readFileSync(viteConfigPath, "utf8");
163
109
  const outDirMatch = viteConfigContent.match(/outDir:\s*['"]([^'"]+)['"]/);
@@ -172,7 +118,7 @@ export class Counter {
172
118
  private: true,
173
119
  type: "module",
174
120
  exports: "./",
175
- main: `../${viteBuildOutDir}`, // Static assets from Vite build
121
+ main: `../${viteBuildOutDir}`,
176
122
  scripts: {
177
123
  dev: "generate-export-types && wrangler dev",
178
124
  deploy: "generate-export-types && wrangler deploy",
@@ -193,28 +139,21 @@ export class Counter {
193
139
 
194
140
  // Update main package.json
195
141
  pkg.scripts = pkg.scripts || {};
196
-
197
- // Add export script: build + deploy as Workers Sites
198
142
  if (!pkg.scripts["export"]) {
199
143
  pkg.scripts["export"] = "vite build && cd export && npm run deploy";
200
144
  }
201
145
 
202
- // Add exportc to devDependencies
203
146
  pkg.devDependencies = pkg.devDependencies || {};
204
147
  if (!pkg.devDependencies.exportc) {
205
- pkg.devDependencies.exportc = "^0.0.2";
148
+ pkg.devDependencies.exportc = "^0.0.6";
206
149
  }
207
150
 
208
151
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
209
152
 
210
153
  // Update vite.config
211
-
212
- // Check if export plugin is already added
213
154
  if (!viteConfigContent.includes("exportc/vite")) {
214
- // Add import at the top
215
155
  const importStatement = `import { exportPlugin } from "exportc/vite";\n`;
216
156
 
217
- // Find the first import or the start of the file
218
157
  const importMatch = viteConfigContent.match(/^(import\s+.+\s+from\s+['"].+['"];?\s*\n?)+/m);
219
158
  if (importMatch) {
220
159
  const insertPos = importMatch.index + importMatch[0].length;
@@ -226,16 +165,12 @@ export class Counter {
226
165
  viteConfigContent = importStatement + viteConfigContent;
227
166
  }
228
167
 
229
- // Add plugin to defineConfig
230
- // Look for plugins array
231
168
  if (viteConfigContent.includes("plugins:")) {
232
- // Add to existing plugins array
233
169
  viteConfigContent = viteConfigContent.replace(
234
170
  /plugins:\s*\[/,
235
171
  "plugins: [exportPlugin(), "
236
172
  );
237
173
  } else {
238
- // Add plugins array to defineConfig
239
174
  viteConfigContent = viteConfigContent.replace(
240
175
  /defineConfig\(\s*\{/,
241
176
  "defineConfig({\n plugins: [exportPlugin()],"
@@ -245,7 +180,7 @@ export class Counter {
245
180
  fs.writeFileSync(viteConfigPath, viteConfigContent);
246
181
  }
247
182
 
248
- // Create .gitignore entries for export directory
183
+ // Create .gitignore
249
184
  const exportGitignorePath = path.join(exportDir, ".gitignore");
250
185
  const gitignoreContent = `# Generated files
251
186
  .export-*.js
@@ -257,15 +192,11 @@ wrangler.toml
257
192
  `;
258
193
  fs.writeFileSync(exportGitignorePath, gitignoreContent);
259
194
 
260
- // Create export-env.d.ts in main project for TypeScript support
195
+ // Create export-env.d.ts for TypeScript
261
196
  if (isTypeScript) {
262
197
  const envDtsPath = path.join(cwd, "export-env.d.ts");
263
198
  if (!fs.existsSync(envDtsPath)) {
264
- const envDtsContent = `// Type declarations for export/ imports
265
- // This file is auto-generated by exportc. You can modify it to add custom types.
266
-
267
- // Re-export types from your export directory
268
- // Update this when you add new exports
199
+ const envDtsContent = `// Auto-generated by exportc - types are updated when you run npm run dev
269
200
 
270
201
  declare module "export/" {
271
202
  export function hello(name: string): Promise<string>;
@@ -277,17 +208,11 @@ declare module "export/" {
277
208
  [Symbol.dispose](): Promise<void>;
278
209
  }
279
210
  }
280
-
281
- // Add more module declarations for subpaths:
282
- // declare module "export/utils" {
283
- // export function myUtil(): Promise<void>;
284
- // }
285
211
  `;
286
212
  fs.writeFileSync(envDtsPath, envDtsContent);
287
213
  }
288
214
 
289
- // Update tsconfig to include the type declarations
290
- // Modern Vite uses tsconfig.app.json for app code, older uses tsconfig.json directly
215
+ // Update tsconfig
291
216
  const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
292
217
  const tsconfigPath = path.join(cwd, "tsconfig.json");
293
218
  const targetTsconfig = fs.existsSync(tsconfigAppPath) ? tsconfigAppPath : tsconfigPath;
@@ -296,78 +221,32 @@ declare module "export/" {
296
221
  try {
297
222
  const tsconfigContent = fs.readFileSync(targetTsconfig, "utf8");
298
223
  const tsconfig = JSON.parse(tsconfigContent);
299
-
300
- // Add export-env.d.ts to include if not already present
301
224
  tsconfig.include = tsconfig.include || [];
302
225
  if (!tsconfig.include.includes("export-env.d.ts")) {
303
226
  tsconfig.include.push("export-env.d.ts");
304
227
  fs.writeFileSync(targetTsconfig, JSON.stringify(tsconfig, null, 2) + "\n");
305
228
  }
306
229
  } catch {
307
- // Ignore JSON parse errors (might have comments)
230
+ // Ignore JSON parse errors
308
231
  }
309
232
  }
310
233
  }
311
234
 
312
- // Install dependencies in export directory
313
- if (!isNonInteractive) {
314
- s.stop("Files created!");
315
- s.start("Installing dependencies...");
316
- } else {
317
- console.log("Installing dependencies...");
318
- }
235
+ console.log(pc.green("✓") + " Created export/");
319
236
 
237
+ // Install dependencies
238
+ console.log(pc.gray("Installing dependencies..."));
320
239
  try {
321
- execSync("npm install", {
322
- cwd: exportDir,
323
- stdio: isNonInteractive ? "inherit" : "pipe",
324
- });
325
- } catch (err) {
326
- if (!isNonInteractive) {
327
- s.stop("Failed to install dependencies");
328
- p.log.error(`Run ${pc.cyan("cd export && npm install")} manually.`);
329
- } else {
330
- console.error("Failed to install dependencies. Run 'cd export && npm install' manually.");
331
- }
332
- }
333
-
334
- if (!isNonInteractive) {
335
- s.stop("Export initialized!");
336
-
337
- const filesCreated = isTypeScript
338
- ? `${pc.cyan("export/")}
339
- ├── index.${ext} ${pc.dim("# Your server exports")}
340
- ├── package.json ${pc.dim("# Worker configuration")}
341
- └── .gitignore
342
-
343
- ${pc.cyan("export-env.d.ts")} ${pc.dim("# Type declarations for export/ imports")}`
344
- : `${pc.cyan("export/")}
345
- ├── index.${ext} ${pc.dim("# Your server exports")}
346
- ├── package.json ${pc.dim("# Worker configuration")}
347
- └── .gitignore`;
348
-
349
- p.note(
350
- `${filesCreated}
351
-
352
- ${pc.bold("Next steps:")}
353
-
354
- 1. Start development (Vite + Wrangler auto-start):
355
- ${pc.cyan("npm run dev")}
356
-
357
- 2. Import in your client code:
358
- ${pc.cyan(`import { hello } from "export/";`)}
359
- ${pc.cyan(`const message = await hello("World");`)}
360
-
361
- 3. Deploy to Cloudflare Workers Sites:
362
- ${pc.cyan("npm run export")}
363
- ${pc.dim("# Builds Vite + deploys everything to Workers")}`,
364
- "Ready"
365
- );
366
-
367
- p.outro(`Run ${pc.cyan("npm run dev")} to start!`);
368
- } else {
369
- console.log("Export initialized successfully!");
370
- console.log("\nNext steps:");
371
- console.log(" npm run dev");
372
- }
240
+ execSync("npm install", { cwd: exportDir, stdio: "pipe" });
241
+ console.log(pc.green("✓") + " Installed dependencies");
242
+ } catch {
243
+ console.log(pc.yellow("!") + " Failed to install. Run: cd export && npm install");
244
+ }
245
+
246
+ // Done
247
+ console.log();
248
+ console.log(pc.green("Done!") + " Run " + pc.cyan("npm run dev") + " to start.");
249
+ console.log();
250
+ console.log(pc.gray(" import { hello } from \"export/\";"));
251
+ console.log(pc.gray(" await hello(\"World\");"));
373
252
  }
package/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import mri from "mri";
4
- import * as p from "@clack/prompts";
5
4
  import pc from "picocolors";
6
5
  import { init } from "./commands/init.js";
7
6
  import { dev } from "./commands/dev.js";
@@ -11,36 +10,32 @@ const argv = mri(process.argv.slice(2), {
11
10
  alias: {
12
11
  h: "help",
13
12
  v: "version",
13
+ y: "yes",
14
14
  },
15
- boolean: ["help", "version"],
15
+ boolean: ["help", "version", "yes"],
16
16
  });
17
17
 
18
18
  const command = argv._[0];
19
19
 
20
20
  const HELP = `
21
- ${pc.bold("exportc")} - Add export to existing projects
21
+ ${pc.bold("exportc")} - Add export to existing Vite projects
22
22
 
23
23
  ${pc.bold("Usage:")}
24
24
  exportc <command> [options]
25
25
 
26
26
  ${pc.bold("Commands:")}
27
- init Initialize export in an existing Vite project
28
- dev Start development server (Vite + Wrangler)
27
+ init Initialize export in a Vite project
28
+ dev Start Wrangler dev server
29
29
  deploy Deploy to Cloudflare Workers
30
30
 
31
31
  ${pc.bold("Options:")}
32
32
  -h, --help Show this help message
33
33
  -v, --version Show version number
34
34
 
35
- ${pc.bold("Examples:")}
35
+ ${pc.bold("Example:")}
36
36
  ${pc.dim("# Add export to your Vite project")}
37
37
  npx exportc init
38
-
39
- ${pc.dim("# Start development")}
40
- npx exportc dev
41
-
42
- ${pc.dim("# Deploy to Cloudflare")}
43
- npx exportc deploy
38
+ npm run dev
44
39
  `;
45
40
 
46
41
  if (argv.help || !command) {
@@ -70,6 +65,6 @@ if (!handler) {
70
65
  try {
71
66
  await handler(argv);
72
67
  } catch (err) {
73
- p.cancel(err.message);
68
+ console.error(pc.red("Error:"), err.message);
74
69
  process.exit(1);
75
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exportc",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "CLI to add export to existing projects",
5
5
  "scripts": {
6
6
  "test": "node --test test/init.test.mjs",
@@ -39,7 +39,6 @@
39
39
  "commands"
40
40
  ],
41
41
  "dependencies": {
42
- "@clack/prompts": "^0.8.2",
43
42
  "mri": "^1.2.0",
44
43
  "picocolors": "^1.1.1"
45
44
  },