exportc 0.0.2 → 0.0.3

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/README.md CHANGED
@@ -13,6 +13,9 @@ cd export && npm install && cd ..
13
13
 
14
14
  # Start development (Wrangler starts automatically!)
15
15
  npm run dev
16
+
17
+ # Deploy to Cloudflare Workers Sites
18
+ npm run export
16
19
  ```
17
20
 
18
21
  ## Usage
@@ -57,22 +60,22 @@ import { exportPlugin } from "exportc/vite";
57
60
 
58
61
  export default defineConfig({
59
62
  plugins: [
60
- exportPlugin({
61
- // Production Worker URL (required for production builds)
62
- production: "https://my-api.workers.dev",
63
-
64
- // Optional: customize dev server
65
- // port: 8787,
66
- // autoStart: true, // Auto-start Wrangler (default: true)
67
- }),
63
+ exportPlugin(),
64
+ // Production URL is auto-detected from export/package.json name
65
+ // Override with: exportPlugin({ production: "https://custom.workers.dev" })
68
66
  ],
69
67
  });
70
68
  ```
71
69
 
72
- When you run `npm run dev`, the plugin:
70
+ **Development** (`npm run dev`):
73
71
  1. Automatically starts Wrangler dev server
74
72
  2. Waits for it to be ready
75
- 3. Transforms `export:/` imports to point to the local server
73
+ 3. Transforms `export:/` imports to `http://localhost:8787`
74
+
75
+ **Production** (`npm run export`):
76
+ 1. Builds Vite app
77
+ 2. Deploys to Workers Sites (static assets + server exports)
78
+ 3. `export:/` imports resolve to `https://{worker-name}.workers.dev`
76
79
 
77
80
  ## Project Structure
78
81
 
@@ -23,27 +23,54 @@ export async function deploy(argv) {
23
23
 
24
24
  p.intro(pc.bgCyan(pc.black(" exportc deploy ")));
25
25
 
26
- const s = p.spinner();
27
- s.start("Deploying to Cloudflare Workers...");
26
+ // Step 1: Build Vite
27
+ const s1 = p.spinner();
28
+ s1.start("Building with Vite...");
28
29
 
29
- // Run deploy
30
- const deployProcess = spawn("npm", ["run", "deploy"], {
30
+ const viteBuild = spawn("npm", ["run", "build"], {
31
+ cwd,
32
+ stdio: ["ignore", "pipe", "pipe"],
33
+ shell: true,
34
+ });
35
+
36
+ let viteBuildOutput = "";
37
+ viteBuild.stdout.on("data", (data) => { viteBuildOutput += data.toString(); });
38
+ viteBuild.stderr.on("data", (data) => { viteBuildOutput += data.toString(); });
39
+
40
+ const viteExitCode = await new Promise((resolve) => {
41
+ viteBuild.on("close", resolve);
42
+ viteBuild.on("error", () => resolve(1));
43
+ });
44
+
45
+ if (viteExitCode !== 0) {
46
+ s1.stop("Vite build failed");
47
+ console.error(viteBuildOutput);
48
+ process.exit(1);
49
+ }
50
+
51
+ s1.stop("Vite build complete");
52
+
53
+ // Step 2: Deploy to Cloudflare Workers
54
+ const s2 = p.spinner();
55
+ s2.start("Deploying to Cloudflare Workers...");
56
+
57
+ const wranglerDeploy = spawn("npm", ["run", "deploy"], {
31
58
  cwd: exportDir,
32
59
  stdio: "inherit",
33
60
  shell: true,
34
61
  });
35
62
 
36
- const exitCode = await new Promise((resolve) => {
37
- deployProcess.on("close", resolve);
38
- deployProcess.on("error", () => resolve(1));
63
+ const wranglerExitCode = await new Promise((resolve) => {
64
+ wranglerDeploy.on("close", resolve);
65
+ wranglerDeploy.on("error", () => resolve(1));
39
66
  });
40
67
 
41
- if (exitCode !== 0) {
42
- s.stop("Deployment failed");
68
+ if (wranglerExitCode !== 0) {
69
+ s2.stop("Deployment failed");
43
70
  process.exit(1);
44
71
  }
45
72
 
46
- s.stop("Deployed successfully!");
73
+ s2.stop("Deployed successfully!");
47
74
 
48
75
  // Read worker name from export/package.json
49
76
  const exportPkgPath = path.join(exportDir, "package.json");
@@ -51,13 +78,16 @@ export async function deploy(argv) {
51
78
  const workerName = exportPkg.name;
52
79
 
53
80
  p.note(
54
- `Your exports are now live at:
81
+ `Your app is now live at:
55
82
  ${pc.cyan(`https://${workerName}.workers.dev/`)}
56
83
 
57
- ${pc.bold("Update your Vite config for production:")}
58
- ${pc.dim("// vite.config.ts")}
59
- ${pc.cyan(`exportPlugin({ production: "https://${workerName}.workers.dev" })`)}`,
60
- "Deployed"
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"
61
91
  );
62
92
 
63
93
  p.outro("Done!");
package/commands/init.js CHANGED
@@ -132,6 +132,15 @@ export class Counter {
132
132
  fs.writeFileSync(indexPath, template);
133
133
  }
134
134
 
135
+ // Detect Vite build output directory from vite.config
136
+ let viteBuildOutDir = "dist"; // default
137
+ const viteConfigPath = path.join(cwd, viteConfig);
138
+ let viteConfigContent = fs.readFileSync(viteConfigPath, "utf8");
139
+ const outDirMatch = viteConfigContent.match(/outDir:\s*['"]([^'"]+)['"]/);
140
+ if (outDirMatch) {
141
+ viteBuildOutDir = outDirMatch[1];
142
+ }
143
+
135
144
  // Create export/package.json
136
145
  const exportPkgPath = path.join(exportDir, "package.json");
137
146
  const exportPkg = {
@@ -139,6 +148,7 @@ export class Counter {
139
148
  private: true,
140
149
  type: "module",
141
150
  exports: "./",
151
+ main: `../${viteBuildOutDir}`, // Static assets from Vite build
142
152
  scripts: {
143
153
  dev: "generate-export-types && wrangler dev",
144
154
  deploy: "generate-export-types && wrangler deploy",
@@ -160,25 +170,20 @@ export class Counter {
160
170
  // Update main package.json
161
171
  pkg.scripts = pkg.scripts || {};
162
172
 
163
- // Add deploy script for export
164
- if (!pkg.scripts["deploy"]) {
165
- pkg.scripts["deploy"] = "cd export && npm run deploy";
166
- } else if (!pkg.scripts["deploy"].includes("export")) {
167
- // Add export deploy to existing deploy script
168
- pkg.scripts["deploy:export"] = "cd export && npm run deploy";
173
+ // Add export script: build + deploy as Workers Sites
174
+ if (!pkg.scripts["export"]) {
175
+ pkg.scripts["export"] = "vite build && cd export && npm run deploy";
169
176
  }
170
177
 
171
178
  // Add exportc to devDependencies
172
179
  pkg.devDependencies = pkg.devDependencies || {};
173
180
  if (!pkg.devDependencies.exportc) {
174
- pkg.devDependencies.exportc = "^0.0.1";
181
+ pkg.devDependencies.exportc = "^0.0.2";
175
182
  }
176
183
 
177
184
  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
178
185
 
179
186
  // Update vite.config
180
- const viteConfigPath = path.join(cwd, viteConfig);
181
- let viteConfigContent = fs.readFileSync(viteConfigPath, "utf8");
182
187
 
183
188
  // Check if export plugin is already added
184
189
  if (!viteConfigContent.includes("exportc/vite")) {
@@ -305,8 +310,9 @@ ${pc.bold("Next steps:")}
305
310
  ${pc.cyan(`import { hello } from "export:/";`)}
306
311
  ${pc.cyan(`const message = await hello("World");`)}
307
312
 
308
- 4. Deploy to Cloudflare:
309
- ${pc.cyan("npm run deploy")}`,
313
+ 4. Deploy to Cloudflare Workers Sites:
314
+ ${pc.cyan("npm run export")}
315
+ ${pc.dim("# Builds Vite + deploys everything to Workers")}`,
310
316
  "Created"
311
317
  );
312
318
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exportc",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "CLI to add export to existing projects",
5
5
  "scripts": {
6
6
  "test": "node --test test/*.test.mjs"
package/vite-plugin.js CHANGED
@@ -14,7 +14,7 @@
14
14
  */
15
15
 
16
16
  import { spawn } from "node:child_process";
17
- import { existsSync } from "node:fs";
17
+ import { existsSync, readFileSync } from "node:fs";
18
18
  import { resolve } from "node:path";
19
19
 
20
20
  const EXPORT_PREFIX = "export:";
@@ -23,7 +23,7 @@ const DEFAULT_DEV_PORT = 8787;
23
23
  /**
24
24
  * @param {Object} options
25
25
  * @param {string} [options.dev] - Development server URL (default: http://localhost:8787)
26
- * @param {string} [options.production] - Production Worker URL (required for production builds)
26
+ * @param {string} [options.production] - Production Worker URL (auto-detected from export/package.json name if not specified)
27
27
  * @param {string} [options.exportDir] - Export directory (default: ./export)
28
28
  * @param {boolean} [options.autoStart] - Auto-start Wrangler in dev mode (default: true)
29
29
  * @returns {import('vite').Plugin}
@@ -31,7 +31,7 @@ const DEFAULT_DEV_PORT = 8787;
31
31
  export function exportPlugin(options = {}) {
32
32
  const devPort = options.port || DEFAULT_DEV_PORT;
33
33
  const devUrl = options.dev || `http://localhost:${devPort}`;
34
- const prodUrl = options.production;
34
+ let prodUrl = options.production;
35
35
  const exportDir = options.exportDir || "./export";
36
36
  const autoStart = options.autoStart !== false;
37
37
 
@@ -40,6 +40,21 @@ export function exportPlugin(options = {}) {
40
40
  let wranglerReady = false;
41
41
  let wranglerReadyPromise = null;
42
42
 
43
+ // Auto-detect production URL from export/package.json
44
+ const detectProductionUrl = (root) => {
45
+ if (prodUrl) return prodUrl;
46
+ try {
47
+ const exportPkgPath = resolve(root, exportDir, "package.json");
48
+ if (existsSync(exportPkgPath)) {
49
+ const exportPkg = JSON.parse(readFileSync(exportPkgPath, "utf8"));
50
+ if (exportPkg.name) {
51
+ return `https://${exportPkg.name}.workers.dev`;
52
+ }
53
+ }
54
+ } catch {}
55
+ return null;
56
+ };
57
+
43
58
  const startWrangler = (root) => {
44
59
  const exportPath = resolve(root, exportDir);
45
60
 
@@ -136,6 +151,11 @@ export function exportPlugin(options = {}) {
136
151
 
137
152
  config(config, { command }) {
138
153
  isDev = command === "serve";
154
+ // Auto-detect production URL if not specified
155
+ if (!isDev && !prodUrl) {
156
+ const root = config.root || process.cwd();
157
+ prodUrl = detectProductionUrl(root);
158
+ }
139
159
  return {};
140
160
  },
141
161