exportc 0.0.3 → 0.0.5
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 +45 -33
- package/commands/dev.js +1 -1
- package/commands/init.js +72 -38
- package/package.json +3 -2
- package/vite-plugin.d.ts +3 -3
- package/vite-plugin.js +65 -8
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# exportc
|
|
2
2
|
|
|
3
|
-
Add [export](https://github.com/ihasq/export) to existing Vite projects.
|
|
3
|
+
Add [export](https://github.com/ihasq/export) to existing Vite projects. One command sets up server-side functions with full TypeScript support.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -18,13 +18,20 @@ npm run dev
|
|
|
18
18
|
npm run export
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
## What You Get
|
|
22
|
+
|
|
23
|
+
- **Single command dev** -- `npm run dev` starts both Vite and Wrangler
|
|
24
|
+
- **Auto-generated types** -- TypeScript definitions from your actual code
|
|
25
|
+
- **Workers Sites deploy** -- Static assets + server exports in one deployment
|
|
26
|
+
- **Zero config** -- Production URL auto-detected from package name
|
|
27
|
+
|
|
21
28
|
## Usage
|
|
22
29
|
|
|
23
|
-
After initialization, import your server exports using the `export
|
|
30
|
+
After initialization, import your server exports using the `export/` prefix:
|
|
24
31
|
|
|
25
32
|
```typescript
|
|
26
33
|
// In your Vite app
|
|
27
|
-
import { hello, Counter } from "export
|
|
34
|
+
import { hello, Counter } from "export/";
|
|
28
35
|
|
|
29
36
|
const message = await hello("World"); // "Hello, World!"
|
|
30
37
|
|
|
@@ -34,24 +41,17 @@ await counter.increment(); // 1
|
|
|
34
41
|
|
|
35
42
|
## Commands
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
### `exportc dev`
|
|
45
|
-
|
|
46
|
-
Start the Wrangler development server for your exports.
|
|
47
|
-
|
|
48
|
-
### `exportc deploy`
|
|
49
|
-
|
|
50
|
-
Deploy your exports to Cloudflare Workers.
|
|
44
|
+
| Command | Description |
|
|
45
|
+
|---------|-------------|
|
|
46
|
+
| `npm run dev` | Start Vite + Wrangler together, auto-generate types |
|
|
47
|
+
| `npm run export` | Build Vite app and deploy to Workers Sites |
|
|
48
|
+
| `exportc init` | Initialize export in your project |
|
|
49
|
+
| `exportc dev` | Start Wrangler dev server standalone |
|
|
50
|
+
| `exportc deploy` | Deploy exports only |
|
|
51
51
|
|
|
52
52
|
## Vite Plugin
|
|
53
53
|
|
|
54
|
-
The `exportPlugin`
|
|
54
|
+
The `exportPlugin` handles everything automatically:
|
|
55
55
|
|
|
56
56
|
```typescript
|
|
57
57
|
// vite.config.ts
|
|
@@ -67,15 +67,20 @@ export default defineConfig({
|
|
|
67
67
|
});
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
### Development (`npm run dev`)
|
|
71
|
+
|
|
72
|
+
1. Automatically starts Wrangler dev server in the background
|
|
73
|
+
2. Waits for it to be ready before serving your app
|
|
74
|
+
3. Generates `export-env.d.ts` with TypeScript declarations
|
|
75
|
+
4. Watches for changes and regenerates types automatically
|
|
76
|
+
5. Transforms `export/` imports to `http://localhost:8787`
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
### Production (`npm run export`)
|
|
79
|
+
|
|
80
|
+
1. Builds your Vite app
|
|
77
81
|
2. Deploys to Workers Sites (static assets + server exports)
|
|
78
|
-
3. `export
|
|
82
|
+
3. `export/` imports resolve to `https://{worker-name}.workers.dev`
|
|
83
|
+
4. Everything runs on Cloudflare's edge network
|
|
79
84
|
|
|
80
85
|
## Project Structure
|
|
81
86
|
|
|
@@ -83,30 +88,37 @@ After running `exportc init`:
|
|
|
83
88
|
|
|
84
89
|
```
|
|
85
90
|
my-vite-app/
|
|
86
|
-
├── src/ # Your Vite app
|
|
91
|
+
├── src/ # Your Vite app (unchanged)
|
|
87
92
|
├── export/ # Server exports (Cloudflare Worker)
|
|
88
93
|
│ ├── index.ts # Your server code
|
|
89
|
-
│
|
|
90
|
-
|
|
94
|
+
│ ├── package.json # Worker configuration
|
|
95
|
+
│ └── .gitignore # Generated files excluded
|
|
96
|
+
├── export-env.d.ts # TypeScript declarations (auto-generated)
|
|
91
97
|
└── vite.config.ts # Updated with exportPlugin
|
|
92
98
|
```
|
|
93
99
|
|
|
94
100
|
## TypeScript Support
|
|
95
101
|
|
|
96
|
-
The `export-env.d.ts` file
|
|
102
|
+
The `export-env.d.ts` file is **automatically generated** when you run `npm run dev`. The Vite plugin watches for changes to your export files and regenerates type declarations automatically.
|
|
97
103
|
|
|
98
104
|
```typescript
|
|
99
|
-
// export-env.d.ts
|
|
100
|
-
declare module "export
|
|
105
|
+
// export-env.d.ts (auto-generated)
|
|
106
|
+
declare module "export/" {
|
|
101
107
|
export function hello(name: string): Promise<string>;
|
|
102
|
-
export
|
|
108
|
+
export class Counter {
|
|
109
|
+
constructor(initial?: number);
|
|
110
|
+
increment(): Promise<number>;
|
|
111
|
+
[Symbol.dispose](): Promise<void>;
|
|
112
|
+
}
|
|
103
113
|
}
|
|
104
114
|
|
|
105
|
-
declare module "export
|
|
115
|
+
declare module "export/utils" {
|
|
106
116
|
export function formatDate(date: Date): Promise<string>;
|
|
107
117
|
}
|
|
108
118
|
```
|
|
109
119
|
|
|
120
|
+
Types are inferred from your actual export code, so you get accurate type information with zero manual maintenance.
|
|
121
|
+
|
|
110
122
|
## License
|
|
111
123
|
|
|
112
124
|
MIT
|
package/commands/dev.js
CHANGED
|
@@ -45,7 +45,7 @@ export async function dev(argv) {
|
|
|
45
45
|
`Wrangler dev server is running at ${pc.cyan("http://localhost:8787")}
|
|
46
46
|
|
|
47
47
|
${pc.bold("In your Vite app:")}
|
|
48
|
-
${pc.cyan(`import { hello } from "export
|
|
48
|
+
${pc.cyan(`import { hello } from "export/";`)}
|
|
49
49
|
${pc.cyan(`const message = await hello("World");`)}
|
|
50
50
|
|
|
51
51
|
${pc.dim("Press Ctrl+C to stop")}`,
|
package/commands/init.js
CHANGED
|
@@ -8,14 +8,21 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
8
8
|
|
|
9
9
|
export async function init(argv) {
|
|
10
10
|
const cwd = process.cwd();
|
|
11
|
+
const isNonInteractive = argv.yes || argv.y || process.env.CI === "true";
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
if (!isNonInteractive) {
|
|
14
|
+
p.intro(pc.bgCyan(pc.black(" exportc init ")));
|
|
15
|
+
}
|
|
13
16
|
|
|
14
17
|
// Check for Vite project
|
|
15
18
|
const viteConfigFiles = ["vite.config.ts", "vite.config.js", "vite.config.mts", "vite.config.mjs"];
|
|
16
19
|
const viteConfig = viteConfigFiles.find((f) => fs.existsSync(path.join(cwd, f)));
|
|
17
20
|
|
|
18
21
|
if (!viteConfig) {
|
|
22
|
+
if (isNonInteractive) {
|
|
23
|
+
console.error("Error: No Vite config found. exportc currently only supports Vite projects.");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
19
26
|
p.cancel("No Vite config found. exportc currently only supports Vite projects.");
|
|
20
27
|
process.exit(1);
|
|
21
28
|
}
|
|
@@ -23,6 +30,10 @@ export async function init(argv) {
|
|
|
23
30
|
// Check for package.json
|
|
24
31
|
const pkgPath = path.join(cwd, "package.json");
|
|
25
32
|
if (!fs.existsSync(pkgPath)) {
|
|
33
|
+
if (isNonInteractive) {
|
|
34
|
+
console.error("Error: No package.json found.");
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
26
37
|
p.cancel("No package.json found.");
|
|
27
38
|
process.exit(1);
|
|
28
39
|
}
|
|
@@ -31,7 +42,7 @@ export async function init(argv) {
|
|
|
31
42
|
|
|
32
43
|
// Check if already initialized
|
|
33
44
|
const exportDir = path.join(cwd, "export");
|
|
34
|
-
if (fs.existsSync(exportDir)) {
|
|
45
|
+
if (fs.existsSync(exportDir) && !isNonInteractive) {
|
|
35
46
|
const overwrite = await p.confirm({
|
|
36
47
|
message: "export/ directory already exists. Continue and overwrite?",
|
|
37
48
|
initialValue: false,
|
|
@@ -42,28 +53,40 @@ export async function init(argv) {
|
|
|
42
53
|
}
|
|
43
54
|
}
|
|
44
55
|
|
|
45
|
-
// Get worker name
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
// Get worker name (use default in non-interactive mode)
|
|
57
|
+
const defaultWorkerName = pkg.name ? `${pkg.name}-api` : "my-api";
|
|
58
|
+
let workerName;
|
|
59
|
+
|
|
60
|
+
if (isNonInteractive) {
|
|
61
|
+
workerName = argv.name || defaultWorkerName;
|
|
62
|
+
} else {
|
|
63
|
+
workerName = await p.text({
|
|
64
|
+
message: "Worker name:",
|
|
65
|
+
placeholder: defaultWorkerName,
|
|
66
|
+
defaultValue: defaultWorkerName,
|
|
67
|
+
validate: (v) => {
|
|
68
|
+
if (!v) return "Worker name is required";
|
|
69
|
+
if (!/^[a-z0-9-]+$/.test(v)) return "Use lowercase letters, numbers, and hyphens only";
|
|
70
|
+
},
|
|
71
|
+
});
|
|
55
72
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
73
|
+
if (p.isCancel(workerName)) {
|
|
74
|
+
p.cancel("Operation cancelled.");
|
|
75
|
+
process.exit(0);
|
|
76
|
+
}
|
|
59
77
|
}
|
|
60
78
|
|
|
61
79
|
// Check for TypeScript
|
|
62
80
|
const isTypeScript = viteConfig.endsWith(".ts") || viteConfig.endsWith(".mts") ||
|
|
63
81
|
fs.existsSync(path.join(cwd, "tsconfig.json"));
|
|
64
82
|
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
let s;
|
|
84
|
+
if (!isNonInteractive) {
|
|
85
|
+
s = p.spinner();
|
|
86
|
+
s.start("Initializing export...");
|
|
87
|
+
} else {
|
|
88
|
+
console.log("Initializing export...");
|
|
89
|
+
}
|
|
67
90
|
|
|
68
91
|
// Create export directory
|
|
69
92
|
if (!fs.existsSync(exportDir)) {
|
|
@@ -76,7 +99,7 @@ export async function init(argv) {
|
|
|
76
99
|
if (!fs.existsSync(indexPath)) {
|
|
77
100
|
const template = isTypeScript
|
|
78
101
|
? `// Server-side exports - these will be available to your client code
|
|
79
|
-
// Import from "export
|
|
102
|
+
// Import from "export/" in your client code
|
|
80
103
|
|
|
81
104
|
export async function hello(name: string): Promise<string> {
|
|
82
105
|
return \`Hello, \${name}!\`;
|
|
@@ -103,7 +126,7 @@ export class Counter {
|
|
|
103
126
|
}
|
|
104
127
|
`
|
|
105
128
|
: `// Server-side exports - these will be available to your client code
|
|
106
|
-
// Import from "export
|
|
129
|
+
// Import from "export/" in your client code
|
|
107
130
|
|
|
108
131
|
export async function hello(name) {
|
|
109
132
|
return \`Hello, \${name}!\`;
|
|
@@ -237,13 +260,13 @@ wrangler.toml
|
|
|
237
260
|
if (isTypeScript) {
|
|
238
261
|
const envDtsPath = path.join(cwd, "export-env.d.ts");
|
|
239
262
|
if (!fs.existsSync(envDtsPath)) {
|
|
240
|
-
const envDtsContent = `// Type declarations for export
|
|
263
|
+
const envDtsContent = `// Type declarations for export/ imports
|
|
241
264
|
// This file is auto-generated by exportc. You can modify it to add custom types.
|
|
242
265
|
|
|
243
266
|
// Re-export types from your export directory
|
|
244
267
|
// Update this when you add new exports
|
|
245
268
|
|
|
246
|
-
declare module "export
|
|
269
|
+
declare module "export/" {
|
|
247
270
|
export function hello(name: string): Promise<string>;
|
|
248
271
|
export function add(a: number, b: number): Promise<number>;
|
|
249
272
|
export class Counter {
|
|
@@ -255,25 +278,29 @@ declare module "export:/" {
|
|
|
255
278
|
}
|
|
256
279
|
|
|
257
280
|
// Add more module declarations for subpaths:
|
|
258
|
-
// declare module "export
|
|
281
|
+
// declare module "export/utils" {
|
|
259
282
|
// export function myUtil(): Promise<void>;
|
|
260
283
|
// }
|
|
261
284
|
`;
|
|
262
285
|
fs.writeFileSync(envDtsPath, envDtsContent);
|
|
263
286
|
}
|
|
264
287
|
|
|
265
|
-
// Update tsconfig
|
|
288
|
+
// Update tsconfig to include the type declarations
|
|
289
|
+
// Modern Vite uses tsconfig.app.json for app code, older uses tsconfig.json directly
|
|
290
|
+
const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
|
|
266
291
|
const tsconfigPath = path.join(cwd, "tsconfig.json");
|
|
267
|
-
|
|
292
|
+
const targetTsconfig = fs.existsSync(tsconfigAppPath) ? tsconfigAppPath : tsconfigPath;
|
|
293
|
+
|
|
294
|
+
if (fs.existsSync(targetTsconfig)) {
|
|
268
295
|
try {
|
|
269
|
-
const tsconfigContent = fs.readFileSync(
|
|
296
|
+
const tsconfigContent = fs.readFileSync(targetTsconfig, "utf8");
|
|
270
297
|
const tsconfig = JSON.parse(tsconfigContent);
|
|
271
298
|
|
|
272
299
|
// Add export-env.d.ts to include if not already present
|
|
273
300
|
tsconfig.include = tsconfig.include || [];
|
|
274
301
|
if (!tsconfig.include.includes("export-env.d.ts")) {
|
|
275
302
|
tsconfig.include.push("export-env.d.ts");
|
|
276
|
-
fs.writeFileSync(
|
|
303
|
+
fs.writeFileSync(targetTsconfig, JSON.stringify(tsconfig, null, 2) + "\n");
|
|
277
304
|
}
|
|
278
305
|
} catch {
|
|
279
306
|
// Ignore JSON parse errors (might have comments)
|
|
@@ -281,22 +308,23 @@ declare module "export:/" {
|
|
|
281
308
|
}
|
|
282
309
|
}
|
|
283
310
|
|
|
284
|
-
|
|
311
|
+
if (!isNonInteractive) {
|
|
312
|
+
s.stop("Export initialized!");
|
|
285
313
|
|
|
286
|
-
|
|
287
|
-
|
|
314
|
+
const filesCreated = isTypeScript
|
|
315
|
+
? `${pc.cyan("export/")}
|
|
288
316
|
├── index.${ext} ${pc.dim("# Your server exports")}
|
|
289
317
|
├── package.json ${pc.dim("# Worker configuration")}
|
|
290
318
|
└── .gitignore
|
|
291
319
|
|
|
292
|
-
${pc.cyan("export-env.d.ts")} ${pc.dim("# Type declarations for export
|
|
293
|
-
|
|
320
|
+
${pc.cyan("export-env.d.ts")} ${pc.dim("# Type declarations for export/ imports")}`
|
|
321
|
+
: `${pc.cyan("export/")}
|
|
294
322
|
├── index.${ext} ${pc.dim("# Your server exports")}
|
|
295
323
|
├── package.json ${pc.dim("# Worker configuration")}
|
|
296
324
|
└── .gitignore`;
|
|
297
325
|
|
|
298
|
-
|
|
299
|
-
|
|
326
|
+
p.note(
|
|
327
|
+
`${filesCreated}
|
|
300
328
|
|
|
301
329
|
${pc.bold("Next steps:")}
|
|
302
330
|
|
|
@@ -307,14 +335,20 @@ ${pc.bold("Next steps:")}
|
|
|
307
335
|
${pc.cyan("npm run dev")}
|
|
308
336
|
|
|
309
337
|
3. Import in your client code:
|
|
310
|
-
${pc.cyan(`import { hello } from "export
|
|
338
|
+
${pc.cyan(`import { hello } from "export/";`)}
|
|
311
339
|
${pc.cyan(`const message = await hello("World");`)}
|
|
312
340
|
|
|
313
341
|
4. Deploy to Cloudflare Workers Sites:
|
|
314
342
|
${pc.cyan("npm run export")}
|
|
315
343
|
${pc.dim("# Builds Vite + deploys everything to Workers")}`,
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
344
|
+
"Created"
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
p.outro(`Run ${pc.cyan("cd export && npm install")} to get started!`);
|
|
348
|
+
} else {
|
|
349
|
+
console.log("Export initialized successfully!");
|
|
350
|
+
console.log("\nNext steps:");
|
|
351
|
+
console.log(" cd export && npm install && cd ..");
|
|
352
|
+
console.log(" npm run dev");
|
|
353
|
+
}
|
|
320
354
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "exportc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "CLI to add export to existing projects",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"test": "node --test test
|
|
6
|
+
"test": "node --test test/init.test.mjs",
|
|
7
|
+
"test:e2e": "node --test test/e2e.test.mjs"
|
|
7
8
|
},
|
|
8
9
|
"keywords": [
|
|
9
10
|
"cloudflare",
|
package/vite-plugin.d.ts
CHANGED
|
@@ -37,11 +37,11 @@ export interface ExportPluginOptions {
|
|
|
37
37
|
* Vite plugin for export integration
|
|
38
38
|
*
|
|
39
39
|
* Automatically starts Wrangler when you run `npm run dev` and allows
|
|
40
|
-
* importing server exports using the "export
|
|
40
|
+
* importing server exports using the "export/" prefix:
|
|
41
41
|
*
|
|
42
42
|
* ```ts
|
|
43
|
-
* import { hello } from "export
|
|
44
|
-
* import { utils } from "export
|
|
43
|
+
* import { hello } from "export/";
|
|
44
|
+
* import { utils } from "export/utils";
|
|
45
45
|
* ```
|
|
46
46
|
*
|
|
47
47
|
* @example
|
package/vite-plugin.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vite plugin for export integration
|
|
3
3
|
*
|
|
4
|
-
* Allows importing server exports using the "export
|
|
5
|
-
* import { hello } from "export
|
|
6
|
-
* import { utils } from "export
|
|
4
|
+
* Allows importing server exports using the "export/" prefix:
|
|
5
|
+
* import { hello } from "export/";
|
|
6
|
+
* import { utils } from "export/utils";
|
|
7
7
|
*
|
|
8
8
|
* In development:
|
|
9
9
|
* - Automatically starts Wrangler dev server
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { spawn } from "node:child_process";
|
|
17
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
17
|
+
import { existsSync, readFileSync, writeFileSync, watchFile, unwatchFile } from "node:fs";
|
|
18
18
|
import { resolve } from "node:path";
|
|
19
19
|
|
|
20
|
-
const EXPORT_PREFIX = "export
|
|
20
|
+
const EXPORT_PREFIX = "export/";
|
|
21
21
|
const DEFAULT_DEV_PORT = 8787;
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -55,6 +55,44 @@ export function exportPlugin(options = {}) {
|
|
|
55
55
|
return null;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
+
// Generate export-env.d.ts from .export-types.js
|
|
59
|
+
const generateTypeDeclarations = (root) => {
|
|
60
|
+
try {
|
|
61
|
+
const typesFilePath = resolve(root, exportDir, ".export-types.js");
|
|
62
|
+
if (!existsSync(typesFilePath)) return;
|
|
63
|
+
|
|
64
|
+
const typesContent = readFileSync(typesFilePath, "utf8");
|
|
65
|
+
// Extract the first line which contains the default export
|
|
66
|
+
const firstLine = typesContent.split('\n')[0];
|
|
67
|
+
if (!firstLine.startsWith('export default ')) return;
|
|
68
|
+
|
|
69
|
+
// Remove "export default " prefix and trailing ";"
|
|
70
|
+
const jsonStr = firstLine.slice('export default '.length).replace(/;$/, '');
|
|
71
|
+
|
|
72
|
+
// Parse the types map
|
|
73
|
+
const typesMap = JSON.parse(jsonStr);
|
|
74
|
+
|
|
75
|
+
// Generate declare module statements
|
|
76
|
+
const declarations = ['// Auto-generated by exportc. Do not edit manually.', '// Re-run "npm run dev" to regenerate after changing export/ files.', ''];
|
|
77
|
+
|
|
78
|
+
for (const [route, types] of Object.entries(typesMap)) {
|
|
79
|
+
const modulePath = route === "" ? "export/" : `export/${route}`;
|
|
80
|
+
declarations.push(`declare module "${modulePath}" {`);
|
|
81
|
+
// Indent the type declarations
|
|
82
|
+
const indented = types.split('\n').map(line => line ? ` ${line}` : '').join('\n');
|
|
83
|
+
declarations.push(indented);
|
|
84
|
+
declarations.push('}');
|
|
85
|
+
declarations.push('');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const envDtsPath = resolve(root, "export-env.d.ts");
|
|
89
|
+
writeFileSync(envDtsPath, declarations.join('\n'));
|
|
90
|
+
console.log(`[exportc] Generated type declarations: export-env.d.ts`);
|
|
91
|
+
} catch (err) {
|
|
92
|
+
console.warn(`[exportc] Failed to generate type declarations:`, err.message);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
58
96
|
const startWrangler = (root) => {
|
|
59
97
|
const exportPath = resolve(root, exportDir);
|
|
60
98
|
|
|
@@ -164,8 +202,27 @@ export function exportPlugin(options = {}) {
|
|
|
164
202
|
const root = server.config.root || process.cwd();
|
|
165
203
|
wranglerReadyPromise = startWrangler(root);
|
|
166
204
|
|
|
205
|
+
// Generate types after Wrangler is ready
|
|
206
|
+
wranglerReadyPromise.then(() => {
|
|
207
|
+
// Initial generation
|
|
208
|
+
setTimeout(() => generateTypeDeclarations(root), 1000);
|
|
209
|
+
|
|
210
|
+
// Watch for changes to .export-types.js
|
|
211
|
+
const typesFilePath = resolve(root, exportDir, ".export-types.js");
|
|
212
|
+
if (existsSync(typesFilePath)) {
|
|
213
|
+
watchFile(typesFilePath, { interval: 1000 }, () => {
|
|
214
|
+
generateTypeDeclarations(root);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
167
219
|
// Cleanup on server close
|
|
168
|
-
server.httpServer?.on("close",
|
|
220
|
+
server.httpServer?.on("close", () => {
|
|
221
|
+
stopWrangler();
|
|
222
|
+
// Stop watching
|
|
223
|
+
const typesFilePath = resolve(root, exportDir, ".export-types.js");
|
|
224
|
+
unwatchFile(typesFilePath);
|
|
225
|
+
});
|
|
169
226
|
}
|
|
170
227
|
},
|
|
171
228
|
|
|
@@ -233,7 +290,7 @@ export { default } from "${fullUrl}";
|
|
|
233
290
|
return null;
|
|
234
291
|
}
|
|
235
292
|
|
|
236
|
-
if (code.includes('import("export
|
|
293
|
+
if (code.includes('import("export/') || code.includes("import('export/")) {
|
|
237
294
|
const baseUrl = isDev ? devUrl : prodUrl;
|
|
238
295
|
if (!baseUrl && !isDev) {
|
|
239
296
|
this.warn(`[exportc] Production URL not configured for dynamic imports in ${id}`);
|
|
@@ -241,7 +298,7 @@ export { default } from "${fullUrl}";
|
|
|
241
298
|
}
|
|
242
299
|
|
|
243
300
|
const transformed = code.replace(
|
|
244
|
-
/import\((['"])export
|
|
301
|
+
/import\((['"])export\/([^'"]*)\1\)/g,
|
|
245
302
|
(match, quote, path) => {
|
|
246
303
|
const fullUrl = new URL(path || "/", baseUrl).href;
|
|
247
304
|
return `import(${quote}${fullUrl}${quote})`;
|