export-runtime 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.
Files changed (2) hide show
  1. package/handler.js +88 -0
  2. package/package.json +1 -1
package/handler.js CHANGED
@@ -19,6 +19,78 @@ const isReadableStream = (value) =>
19
19
  const isClass = (fn) =>
20
20
  typeof fn === "function" && /^class\s/.test(Function.prototype.toString.call(fn));
21
21
 
22
+ // Generate TypeScript type definitions from exports
23
+ const generateTypeDefinitions = (exports, exportKeys) => {
24
+ const lines = [
25
+ "// Auto-generated type definitions",
26
+ "// All functions are async over the network",
27
+ "",
28
+ ];
29
+
30
+ const generateType = (value, name, indent = "") => {
31
+ if (isClass(value)) {
32
+ // Extract class method names
33
+ const proto = value.prototype;
34
+ const methodNames = Object.getOwnPropertyNames(proto).filter(
35
+ (n) => n !== "constructor" && typeof proto[n] === "function"
36
+ );
37
+
38
+ lines.push(`${indent}export declare class ${name} {`);
39
+ lines.push(`${indent} constructor(...args: any[]);`);
40
+ for (const method of methodNames) {
41
+ lines.push(`${indent} ${method}(...args: any[]): Promise<any>;`);
42
+ }
43
+ lines.push(`${indent} [Symbol.dispose](): Promise<void>;`);
44
+ lines.push(`${indent} "[release]"(): Promise<void>;`);
45
+ lines.push(`${indent}}`);
46
+ } else if (typeof value === "function") {
47
+ // Check if it's an async generator
48
+ const fnStr = Function.prototype.toString.call(value);
49
+ if (fnStr.startsWith("async function*") || fnStr.includes("async *")) {
50
+ lines.push(
51
+ `${indent}export declare function ${name}(...args: any[]): Promise<AsyncIterable<any>>;`
52
+ );
53
+ } else if (fnStr.includes("ReadableStream")) {
54
+ lines.push(
55
+ `${indent}export declare function ${name}(...args: any[]): Promise<ReadableStream<any>>;`
56
+ );
57
+ } else {
58
+ lines.push(
59
+ `${indent}export declare function ${name}(...args: any[]): Promise<any>;`
60
+ );
61
+ }
62
+ } else if (typeof value === "object" && value !== null) {
63
+ // Nested object with methods
64
+ const keys = Object.keys(value);
65
+ lines.push(`${indent}export declare const ${name}: {`);
66
+ for (const key of keys) {
67
+ const v = value[key];
68
+ if (typeof v === "function") {
69
+ lines.push(`${indent} ${key}(...args: any[]): Promise<any>;`);
70
+ } else {
71
+ lines.push(`${indent} ${key}: any;`);
72
+ }
73
+ }
74
+ lines.push(`${indent}};`);
75
+ } else {
76
+ lines.push(`${indent}export declare const ${name}: any;`);
77
+ }
78
+ };
79
+
80
+ for (const key of exportKeys) {
81
+ generateType(exports[key], key);
82
+ lines.push("");
83
+ }
84
+
85
+ // Add createUploadStream helper type
86
+ lines.push("export declare function createUploadStream(): Promise<{");
87
+ lines.push(" stream: WritableStream<any>;");
88
+ lines.push(" writableId: number;");
89
+ lines.push("}>;");
90
+
91
+ return lines.join("\n");
92
+ };
93
+
22
94
  export const createHandler = (exports) => {
23
95
  const exportKeys = Object.keys(exports);
24
96
  const iteratorStore = new Map();
@@ -280,6 +352,18 @@ export const createHandler = (exports) => {
280
352
  const wsProtocol = url.protocol === "https:" ? "wss:" : "ws:";
281
353
  const wsUrl = `${wsProtocol}//${url.host}${url.pathname}`;
282
354
 
355
+ // Serve TypeScript type definitions
356
+ if (url.searchParams.has("types") || url.pathname.endsWith(".d.ts")) {
357
+ const typeDefinitions = generateTypeDefinitions(exports, exportKeys);
358
+ return new Response(typeDefinitions, {
359
+ headers: {
360
+ "Content-Type": "application/typescript; charset=utf-8",
361
+ "Access-Control-Allow-Origin": "*",
362
+ "Cache-Control": "no-cache",
363
+ },
364
+ });
365
+ }
366
+
283
367
  // Generate named exports
284
368
  const namedExports = exportKeys
285
369
  .map((key) => `export const ${key} = createProxy([${JSON.stringify(key)}]);`)
@@ -291,11 +375,15 @@ export const createHandler = (exports) => {
291
375
  .replace("__DEVALUE_PARSE__", DEVALUE_PARSE)
292
376
  .replace("__NAMED_EXPORTS__", namedExports);
293
377
 
378
+ // Build types URL for X-TypeScript-Types header
379
+ const typesUrl = `${url.protocol}//${url.host}${url.pathname}?types`;
380
+
294
381
  return new Response(clientCode, {
295
382
  headers: {
296
383
  "Content-Type": "application/javascript; charset=utf-8",
297
384
  "Access-Control-Allow-Origin": "*",
298
385
  "Cache-Control": "no-cache",
386
+ "X-TypeScript-Types": typesUrl,
299
387
  },
300
388
  });
301
389
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "export-runtime",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Cloudflare Workers ESM Export Framework Runtime",
5
5
  "keywords": [
6
6
  "cloudflare",