exportc 0.0.3 → 0.0.4
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 +16 -10
- package/commands/dev.js +1 -1
- package/commands/init.js +7 -7
- package/package.json +1 -1
- package/vite-plugin.d.ts +3 -3
- package/vite-plugin.js +65 -8
package/README.md
CHANGED
|
@@ -20,11 +20,11 @@ npm run export
|
|
|
20
20
|
|
|
21
21
|
## Usage
|
|
22
22
|
|
|
23
|
-
After initialization, import your server exports using the `export
|
|
23
|
+
After initialization, import your server exports using the `export/` prefix:
|
|
24
24
|
|
|
25
25
|
```typescript
|
|
26
26
|
// In your Vite app
|
|
27
|
-
import { hello, Counter } from "export
|
|
27
|
+
import { hello, Counter } from "export/";
|
|
28
28
|
|
|
29
29
|
const message = await hello("World"); // "Hello, World!"
|
|
30
30
|
|
|
@@ -51,7 +51,7 @@ Deploy your exports to Cloudflare Workers.
|
|
|
51
51
|
|
|
52
52
|
## Vite Plugin
|
|
53
53
|
|
|
54
|
-
The `exportPlugin` automatically starts Wrangler and transforms `export
|
|
54
|
+
The `exportPlugin` automatically starts Wrangler and transforms `export/` imports:
|
|
55
55
|
|
|
56
56
|
```typescript
|
|
57
57
|
// vite.config.ts
|
|
@@ -70,12 +70,12 @@ export default defineConfig({
|
|
|
70
70
|
**Development** (`npm run dev`):
|
|
71
71
|
1. Automatically starts Wrangler dev server
|
|
72
72
|
2. Waits for it to be ready
|
|
73
|
-
3. Transforms `export
|
|
73
|
+
3. Transforms `export/` imports to `http://localhost:8787`
|
|
74
74
|
|
|
75
75
|
**Production** (`npm run export`):
|
|
76
76
|
1. Builds Vite app
|
|
77
77
|
2. Deploys to Workers Sites (static assets + server exports)
|
|
78
|
-
3. `export
|
|
78
|
+
3. `export/` imports resolve to `https://{worker-name}.workers.dev`
|
|
79
79
|
|
|
80
80
|
## Project Structure
|
|
81
81
|
|
|
@@ -93,20 +93,26 @@ my-vite-app/
|
|
|
93
93
|
|
|
94
94
|
## TypeScript Support
|
|
95
95
|
|
|
96
|
-
The `export-env.d.ts` file
|
|
96
|
+
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
97
|
|
|
98
98
|
```typescript
|
|
99
|
-
// export-env.d.ts
|
|
100
|
-
declare module "export
|
|
99
|
+
// export-env.d.ts (auto-generated)
|
|
100
|
+
declare module "export/" {
|
|
101
101
|
export function hello(name: string): Promise<string>;
|
|
102
|
-
export
|
|
102
|
+
export class Counter {
|
|
103
|
+
constructor(initial?: number);
|
|
104
|
+
increment(): Promise<number>;
|
|
105
|
+
[Symbol.dispose](): Promise<void>;
|
|
106
|
+
}
|
|
103
107
|
}
|
|
104
108
|
|
|
105
|
-
declare module "export
|
|
109
|
+
declare module "export/utils" {
|
|
106
110
|
export function formatDate(date: Date): Promise<string>;
|
|
107
111
|
}
|
|
108
112
|
```
|
|
109
113
|
|
|
114
|
+
Types are inferred from your actual export code, so you get accurate type information with zero manual maintenance.
|
|
115
|
+
|
|
110
116
|
## License
|
|
111
117
|
|
|
112
118
|
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
|
@@ -76,7 +76,7 @@ export async function init(argv) {
|
|
|
76
76
|
if (!fs.existsSync(indexPath)) {
|
|
77
77
|
const template = isTypeScript
|
|
78
78
|
? `// Server-side exports - these will be available to your client code
|
|
79
|
-
// Import from "export
|
|
79
|
+
// Import from "export/" in your client code
|
|
80
80
|
|
|
81
81
|
export async function hello(name: string): Promise<string> {
|
|
82
82
|
return \`Hello, \${name}!\`;
|
|
@@ -103,7 +103,7 @@ export class Counter {
|
|
|
103
103
|
}
|
|
104
104
|
`
|
|
105
105
|
: `// Server-side exports - these will be available to your client code
|
|
106
|
-
// Import from "export
|
|
106
|
+
// Import from "export/" in your client code
|
|
107
107
|
|
|
108
108
|
export async function hello(name) {
|
|
109
109
|
return \`Hello, \${name}!\`;
|
|
@@ -237,13 +237,13 @@ wrangler.toml
|
|
|
237
237
|
if (isTypeScript) {
|
|
238
238
|
const envDtsPath = path.join(cwd, "export-env.d.ts");
|
|
239
239
|
if (!fs.existsSync(envDtsPath)) {
|
|
240
|
-
const envDtsContent = `// Type declarations for export
|
|
240
|
+
const envDtsContent = `// Type declarations for export/ imports
|
|
241
241
|
// This file is auto-generated by exportc. You can modify it to add custom types.
|
|
242
242
|
|
|
243
243
|
// Re-export types from your export directory
|
|
244
244
|
// Update this when you add new exports
|
|
245
245
|
|
|
246
|
-
declare module "export
|
|
246
|
+
declare module "export/" {
|
|
247
247
|
export function hello(name: string): Promise<string>;
|
|
248
248
|
export function add(a: number, b: number): Promise<number>;
|
|
249
249
|
export class Counter {
|
|
@@ -255,7 +255,7 @@ declare module "export:/" {
|
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
// Add more module declarations for subpaths:
|
|
258
|
-
// declare module "export
|
|
258
|
+
// declare module "export/utils" {
|
|
259
259
|
// export function myUtil(): Promise<void>;
|
|
260
260
|
// }
|
|
261
261
|
`;
|
|
@@ -289,7 +289,7 @@ declare module "export:/" {
|
|
|
289
289
|
├── package.json ${pc.dim("# Worker configuration")}
|
|
290
290
|
└── .gitignore
|
|
291
291
|
|
|
292
|
-
${pc.cyan("export-env.d.ts")} ${pc.dim("# Type declarations for export
|
|
292
|
+
${pc.cyan("export-env.d.ts")} ${pc.dim("# Type declarations for export/ imports")}`
|
|
293
293
|
: `${pc.cyan("export/")}
|
|
294
294
|
├── index.${ext} ${pc.dim("# Your server exports")}
|
|
295
295
|
├── package.json ${pc.dim("# Worker configuration")}
|
|
@@ -307,7 +307,7 @@ ${pc.bold("Next steps:")}
|
|
|
307
307
|
${pc.cyan("npm run dev")}
|
|
308
308
|
|
|
309
309
|
3. Import in your client code:
|
|
310
|
-
${pc.cyan(`import { hello } from "export
|
|
310
|
+
${pc.cyan(`import { hello } from "export/";`)}
|
|
311
311
|
${pc.cyan(`const message = await hello("World");`)}
|
|
312
312
|
|
|
313
313
|
4. Deploy to Cloudflare Workers Sites:
|
package/package.json
CHANGED
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})`;
|