@firtoz/worker-helper 1.5.1 → 1.6.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @firtoz/worker-helper
2
2
 
3
+ ## 1.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`80a7aa6`](https://github.com/firtoz/fullstack-toolkit/commit/80a7aa6abbca3b7ef621e6dd92f51954bee84b43) Thanks [@firtoz](https://github.com/firtoz)! - `prepareEnvFiles` no longer passes `.env` / `.env.local` to `wrangler types` when a matching `.env.example` / `.env.local.example` exists, so generated `worker-configuration.d.ts` headers match CI and local dev.
8
+
9
+ ## 1.6.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [`c3a3cc7`](https://github.com/firtoz/fullstack-toolkit/commit/c3a3cc778ba9ce4b5efe1bcdd8d541f46dec3bfd) Thanks [@firtoz](https://github.com/firtoz)! - Publish compiled ESM and TypeScript declarations from `dist/` for each package (`tsup`, `prepack` build). `exports`, `main`, and `types` resolve to `dist/`; CLI bins point at built JS with a Node shebang where applicable. Shared `scripts/tsup-lib.ts` discovers `src` entries and externals; workspace test apps map `@firtoz/*` to package sources in `tsconfig` for accurate generics during typecheck. `@firtoz/socka` is published under the scoped name with the same `dist/` layout.
14
+
15
+ ### Patch Changes
16
+
17
+ - [`f78c988`](https://github.com/firtoz/fullstack-toolkit/commit/f78c988d37a9cc48490ee3372dccc14a42810bfe) Thanks [@firtoz](https://github.com/firtoz)! - Improve READMEs: npm shields, contextual stack badges, clearer taglines, and new docs for `@firtoz/idb-collections` and `@firtoz/collection-sync`. Align `@firtoz/db-helpers` copy with published `dist/` builds.
18
+
3
19
  ## 1.5.1
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # @firtoz/worker-helper
2
2
 
3
- Type-safe Web Worker helper with Zod validation for input and output messages. This package provides a simple way to create type-safe Web Workers with automatic validation of messages sent between the main thread and worker threads.
3
+ [![npm version](https://img.shields.io/npm/v/%40firtoz%2Fworker-helper.svg)](https://www.npmjs.com/package/@firtoz/worker-helper)
4
+ [![npm downloads](https://img.shields.io/npm/dm/%40firtoz%2Fworker-helper.svg)](https://www.npmjs.com/package/@firtoz/worker-helper)
5
+ [![license](https://img.shields.io/npm/l/%40firtoz%2Fworker-helper.svg)](https://github.com/firtoz/fullstack-toolkit/blob/main/LICENSE)
6
+
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
8
+ [![Zod](https://img.shields.io/badge/Zod-3B82F6?logo=zod&logoColor=white)](https://zod.dev)
9
+ [![Web Workers](https://img.shields.io/badge/Web_Workers-646464)](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)
10
+
11
+ **Typed messages between the main thread and workers** — Zod validates every postMessage in both directions, with helpers for Cloudflare `wrangler types` / `.env` when you deploy Workers too.
4
12
 
5
13
  > **⚠️ Early WIP Notice:** This package is in very early development and is **not production-ready**. It is TypeScript-only and may have breaking changes. While I (the maintainer) have limited time, I'm open to PRs for features, bug fixes, or additional support (like JS builds). Please feel free to try it out and contribute! See [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
6
14
 
@@ -0,0 +1,51 @@
1
+ import { ZodType } from 'zod/v4';
2
+
3
+ interface WorkerClientOptions<TClientMessage, TServerMessage> {
4
+ /**
5
+ * Worker instance to wrap
6
+ */
7
+ worker: Worker;
8
+ /**
9
+ * Schema for validating messages sent to the worker
10
+ */
11
+ clientSchema: ZodType<TClientMessage>;
12
+ /**
13
+ * Schema for validating messages received from the worker
14
+ */
15
+ serverSchema: ZodType<TServerMessage>;
16
+ /**
17
+ * Callback for validated messages from the worker
18
+ */
19
+ onMessage?: (message: TServerMessage) => void;
20
+ /**
21
+ * Callback for when validation fails on incoming messages
22
+ */
23
+ onValidationError?: (error: Error, rawMessage: unknown) => void;
24
+ /**
25
+ * Callback for worker errors
26
+ */
27
+ onError?: (event: ErrorEvent) => void;
28
+ }
29
+ declare class WorkerClient<TClientMessage, TServerMessage> {
30
+ private worker;
31
+ private readonly clientSchema;
32
+ private readonly serverSchema;
33
+ private readonly onMessageCallback?;
34
+ private readonly onValidationErrorCallback?;
35
+ constructor(options: WorkerClientOptions<TClientMessage, TServerMessage>);
36
+ private handleMessage;
37
+ /**
38
+ * Send a message to the worker with validation
39
+ */
40
+ send(message: TClientMessage): void;
41
+ /**
42
+ * Terminate the worker
43
+ */
44
+ terminate(): void;
45
+ /**
46
+ * Get the underlying Worker instance
47
+ */
48
+ getWorker(): Worker;
49
+ }
50
+
51
+ export { WorkerClient, type WorkerClientOptions };
@@ -0,0 +1,3 @@
1
+ export { WorkerClient } from './chunk-TYKZZZOR.js';
2
+ //# sourceMappingURL=WorkerClient.js.map
3
+ //# sourceMappingURL=WorkerClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"WorkerClient.js"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Find workspace root by walking up from startPath until we find a package.json
3
+ * with a "workspaces" field (npm/bun convention).
4
+ */
5
+ declare function findWorkspaceRoot(startPath: string): string | null;
6
+ /**
7
+ * Expand workspace glob patterns (e.g. "packages/*", "tests/*") to absolute paths.
8
+ * Only supports single-level globs; each pattern must be exactly "dirname/*".
9
+ */
10
+ declare function expandWorkspacePatterns(root: string, patterns: string[]): string[];
11
+ /**
12
+ * Get workspace package paths from root package.json (workspaces field).
13
+ * Returns absolute paths to each workspace member directory.
14
+ */
15
+ declare function getWorkspacePaths(root: string): string[];
16
+ /**
17
+ * Find all wrangler config files under the given workspace member paths.
18
+ * Does not rely on git; includes untracked configs (e.g. new durable objects).
19
+ */
20
+ declare function findWranglerConfigsInPaths(workspacePaths: string[]): string[];
21
+ /**
22
+ * Discover all wrangler config paths for the workspace containing cwd.
23
+ * Returns empty array if not in a workspace or if root has no workspaces field.
24
+ */
25
+ declare function discoverWranglerConfigs(cwd: string): string[];
26
+
27
+ export { discoverWranglerConfigs, expandWorkspacePatterns, findWorkspaceRoot, findWranglerConfigsInPaths, getWorkspacePaths };
@@ -0,0 +1,3 @@
1
+ export { discoverWranglerConfigs, expandWorkspacePatterns, findWorkspaceRoot, findWranglerConfigsInPaths, getWorkspacePaths } from './chunk-QEZL4IJI.js';
2
+ //# sourceMappingURL=cf-typegen-discovery.js.map
3
+ //# sourceMappingURL=cf-typegen-discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"cf-typegen-discovery.js"}
@@ -0,0 +1 @@
1
+ #!/usr/bin/env bun
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env bun
2
+ import { findWorkspaceRoot, discoverWranglerConfigs } from './chunk-QEZL4IJI.js';
3
+ import { prepareEnvFiles } from './chunk-A4S7WGGQ.js';
4
+ import { spawnSync } from 'child_process';
5
+ import * as fs from 'fs';
6
+ import path from 'path';
7
+ import process from 'process';
8
+
9
+ var cwd = process.argv[2];
10
+ var extraWranglerArgs = process.argv.slice(3);
11
+ if (!cwd || !fs.existsSync(cwd)) {
12
+ console.error(
13
+ "Please specify a directory as the first parameter. Usually $(pwd)."
14
+ );
15
+ process.exit(1);
16
+ }
17
+ console.log(`Running CF typegen for: ${cwd}`);
18
+ function runWranglerTypes() {
19
+ const envFiles = prepareEnvFiles(cwd);
20
+ console.log("Running wrangler types...");
21
+ const workspaceRoot = findWorkspaceRoot(cwd);
22
+ let allConfigs;
23
+ if (workspaceRoot) {
24
+ allConfigs = discoverWranglerConfigs(cwd);
25
+ } else {
26
+ console.warn("\u26A0 No workspace root found, using current directory only");
27
+ allConfigs = [];
28
+ }
29
+ if (allConfigs.length > 0) {
30
+ console.log(` Found ${allConfigs.length} wrangler config(s) in workspace`);
31
+ }
32
+ const args = ["types", "-c", "wrangler.jsonc"];
33
+ const currentWranglerJsonc = path.join(cwd, "wrangler.jsonc");
34
+ const currentWranglerJson = path.join(cwd, "wrangler.json");
35
+ for (const configPath of allConfigs) {
36
+ const resolvedPath = path.resolve(configPath);
37
+ if (resolvedPath === currentWranglerJsonc || resolvedPath === currentWranglerJson) {
38
+ continue;
39
+ }
40
+ const relativePath = path.relative(cwd, configPath);
41
+ args.push("-c", relativePath);
42
+ }
43
+ for (const envFile of envFiles) {
44
+ args.push("--env-file", envFile);
45
+ }
46
+ args.push(...extraWranglerArgs);
47
+ const command = `wrangler ${args.join(" ")}`;
48
+ console.log(` Command: ${command}`);
49
+ const result = spawnSync("wrangler", args, {
50
+ cwd,
51
+ stdio: "inherit"
52
+ });
53
+ if (result.status !== 0) {
54
+ console.error("Failed to run wrangler types");
55
+ process.exit(1);
56
+ }
57
+ console.log("\u2713 Wrangler types generated with all workspace bindings");
58
+ }
59
+ try {
60
+ runWranglerTypes();
61
+ console.log("\n\u2713 CF typegen completed successfully");
62
+ } catch (error) {
63
+ console.error("\n\u2717 CF typegen failed:", error);
64
+ process.exit(1);
65
+ }
66
+ //# sourceMappingURL=cf-typegen.js.map
67
+ //# sourceMappingURL=cf-typegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cf-typegen.ts"],"names":[],"mappings":"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","file":"cf-typegen.js","sourcesContent":["#!/usr/bin/env bun\nimport { spawnSync } from \"node:child_process\";\nimport * as fs from \"node:fs\";\nimport path from \"node:path\";\nimport process from \"node:process\";\nimport {\n\tdiscoverWranglerConfigs,\n\tfindWorkspaceRoot,\n} from \"./cf-typegen-discovery\";\nimport { prepareEnvFiles } from \"./utils/prepare-env\";\n\n// First arg: directory (cwd). Remaining args: passed through to `wrangler types`.\nconst cwd = process.argv[2];\nconst extraWranglerArgs = process.argv.slice(3);\n\nif (!cwd || !fs.existsSync(cwd)) {\n\tconsole.error(\n\t\t\"Please specify a directory as the first parameter. Usually $(pwd).\",\n\t);\n\tprocess.exit(1);\n}\n\nconsole.log(`Running CF typegen for: ${cwd}`);\n\nfunction runWranglerTypes() {\n\tconst envFiles = prepareEnvFiles(cwd);\n\n\tconsole.log(\"Running wrangler types...\");\n\n\t// Discover wrangler configs from npm/bun workspace definition (includes untracked packages)\n\tconst workspaceRoot = findWorkspaceRoot(cwd);\n\tlet allConfigs: string[];\n\tif (workspaceRoot) {\n\t\tallConfigs = discoverWranglerConfigs(cwd);\n\t} else {\n\t\tconsole.warn(\"⚠ No workspace root found, using current directory only\");\n\t\tallConfigs = [];\n\t}\n\n\tif (allConfigs.length > 0) {\n\t\tconsole.log(` Found ${allConfigs.length} wrangler config(s) in workspace`);\n\t}\n\n\t// Build args for wrangler types: multiple -c flags, --env-file, then any extra args\n\t// The first config should be the current directory's wrangler.jsonc\n\tconst args: string[] = [\"types\", \"-c\", \"wrangler.jsonc\"];\n\n\t// Add other configs (relative to cwd for better readability)\n\tconst currentWranglerJsonc = path.join(cwd, \"wrangler.jsonc\");\n\tconst currentWranglerJson = path.join(cwd, \"wrangler.json\");\n\n\tfor (const configPath of allConfigs) {\n\t\tconst resolvedPath = path.resolve(configPath);\n\t\t// Skip if it's the current directory's config\n\t\tif (\n\t\t\tresolvedPath === currentWranglerJsonc ||\n\t\t\tresolvedPath === currentWranglerJson\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\t\t// Make path relative to cwd\n\t\tconst relativePath = path.relative(cwd, configPath);\n\t\targs.push(\"-c\", relativePath);\n\t}\n\n\tfor (const envFile of envFiles) {\n\t\targs.push(\"--env-file\", envFile);\n\t}\n\n\targs.push(...extraWranglerArgs);\n\n\tconst command = `wrangler ${args.join(\" \")}`;\n\tconsole.log(` Command: ${command}`);\n\n\tconst result = spawnSync(\"wrangler\", args, {\n\t\tcwd,\n\t\tstdio: \"inherit\",\n\t});\n\tif (result.status !== 0) {\n\t\tconsole.error(\"Failed to run wrangler types\");\n\t\tprocess.exit(1);\n\t}\n\tconsole.log(\"✓ Wrangler types generated with all workspace bindings\");\n}\n\n// Run all steps\ntry {\n\trunWranglerTypes();\n\tconsole.log(\"\\n✓ CF typegen completed successfully\");\n} catch (error: unknown) {\n\tconsole.error(\"\\n✗ CF typegen failed:\", error);\n\tprocess.exit(1);\n}\n"]}
@@ -0,0 +1,51 @@
1
+ import * as fs from 'fs';
2
+ import path from 'path';
3
+ import process from 'process';
4
+
5
+ // src/utils/prepare-env.ts
6
+ function isCiEnvironment() {
7
+ return Boolean(process.env.CI) || process.env.GITHUB_ACTIONS === "true";
8
+ }
9
+ function prepareEnvFiles(targetDir) {
10
+ const exampleEnvPath = path.join(targetDir, ".env.example");
11
+ const exampleEnvLocalPath = path.join(targetDir, ".env.local.example");
12
+ const exampleEnvExists = fs.existsSync(exampleEnvPath);
13
+ const exampleLocalEnvExists = fs.existsSync(exampleEnvLocalPath);
14
+ const envPath = path.join(targetDir, ".env");
15
+ const envLocalPath = path.join(targetDir, ".env.local");
16
+ let envExists = fs.existsSync(envPath);
17
+ let envLocalExists = fs.existsSync(envLocalPath);
18
+ const allowCopies = !isCiEnvironment();
19
+ if (allowCopies && exampleEnvExists) {
20
+ if (!envExists) {
21
+ fs.cpSync(exampleEnvPath, envPath);
22
+ console.log("\u2713 Created .env from .env.example");
23
+ envExists = true;
24
+ }
25
+ }
26
+ if (allowCopies && exampleLocalEnvExists) {
27
+ if (!envLocalExists) {
28
+ fs.cpSync(exampleEnvLocalPath, envLocalPath);
29
+ console.log("\u2713 Created .env.local from .env.local.example");
30
+ envLocalExists = true;
31
+ }
32
+ }
33
+ const result = [];
34
+ if (exampleEnvExists) {
35
+ result.push(".env.example");
36
+ }
37
+ if (exampleLocalEnvExists) {
38
+ result.push(".env.local.example");
39
+ }
40
+ if (!exampleEnvExists && envExists) {
41
+ result.push(".env");
42
+ }
43
+ if (!exampleLocalEnvExists && envLocalExists) {
44
+ result.push(".env.local");
45
+ }
46
+ return result;
47
+ }
48
+
49
+ export { prepareEnvFiles };
50
+ //# sourceMappingURL=chunk-A4S7WGGQ.js.map
51
+ //# sourceMappingURL=chunk-A4S7WGGQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/prepare-env.ts"],"names":[],"mappings":";;;;;AAIA,SAAS,eAAA,GAA2B;AACnC,EAAA,OAAO,QAAQ,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,IAAK,OAAA,CAAQ,IAAI,cAAA,KAAmB,MAAA;AAClE;AAWO,SAAS,gBAAgB,SAAA,EAA6B;AAC5D,EAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,cAAc,CAAA;AAC1D,EAAA,MAAM,mBAAA,GAAsB,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,oBAAoB,CAAA;AAErE,EAAA,MAAM,gBAAA,GAAsB,cAAW,cAAc,CAAA;AACrD,EAAA,MAAM,qBAAA,GAA2B,cAAW,mBAAmB,CAAA;AAE/D,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,MAAM,CAAA;AAC3C,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,IAAA,CAAK,SAAA,EAAW,YAAY,CAAA;AAEtD,EAAA,IAAI,SAAA,GAAe,cAAW,OAAO,CAAA;AACrC,EAAA,IAAI,cAAA,GAAoB,cAAW,YAAY,CAAA;AAE/C,EAAA,MAAM,WAAA,GAAc,CAAC,eAAA,EAAgB;AAErC,EAAA,IAAI,eAAe,gBAAA,EAAkB;AACpC,IAAA,IAAI,CAAC,SAAA,EAAW;AACf,MAAG,EAAA,CAAA,MAAA,CAAO,gBAAgB,OAAO,CAAA;AAEjC,MAAA,OAAA,CAAQ,IAAI,uCAAkC,CAAA;AAC9C,MAAA,SAAA,GAAY,IAAA;AAAA,IACb;AAAA,EACD;AAEA,EAAA,IAAI,eAAe,qBAAA,EAAuB;AACzC,IAAA,IAAI,CAAC,cAAA,EAAgB;AACpB,MAAG,EAAA,CAAA,MAAA,CAAO,qBAAqB,YAAY,CAAA;AAE3C,MAAA,OAAA,CAAQ,IAAI,mDAA8C,CAAA;AAC1D,MAAA,cAAA,GAAiB,IAAA;AAAA,IAClB;AAAA,EACD;AAEA,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,IAAI,gBAAA,EAAkB;AACrB,IAAA,MAAA,CAAO,KAAK,cAAc,CAAA;AAAA,EAC3B;AACA,EAAA,IAAI,qBAAA,EAAuB;AAC1B,IAAA,MAAA,CAAO,KAAK,oBAAoB,CAAA;AAAA,EACjC;AAIA,EAAA,IAAI,CAAC,oBAAoB,SAAA,EAAW;AACnC,IAAA,MAAA,CAAO,KAAK,MAAM,CAAA;AAAA,EACnB;AACA,EAAA,IAAI,CAAC,yBAAyB,cAAA,EAAgB;AAC7C,IAAA,MAAA,CAAO,KAAK,YAAY,CAAA;AAAA,EACzB;AAEA,EAAA,OAAO,MAAA;AACR","file":"chunk-A4S7WGGQ.js","sourcesContent":["import * as fs from \"node:fs\";\nimport path from \"node:path\";\nimport process from \"node:process\";\n\nfunction isCiEnvironment(): boolean {\n\treturn Boolean(process.env.CI) || process.env.GITHUB_ACTIONS === \"true\";\n}\n\n/**\n * Ensures a .env and .env.local file exists in the target directory.\n * If it doesn't exist, copies from .env.example and .env.local.example.\n *\n * In CI, does not create those files — typegen uses `.env.example` / `.env.local.example` only when real files are absent.\n *\n * @param targetDir - The directory where the .env and .env.local files should exist\n * @returns An array of the files that were created or already existed\n */\nexport function prepareEnvFiles(targetDir: string): string[] {\n\tconst exampleEnvPath = path.join(targetDir, \".env.example\");\n\tconst exampleEnvLocalPath = path.join(targetDir, \".env.local.example\");\n\n\tconst exampleEnvExists = fs.existsSync(exampleEnvPath);\n\tconst exampleLocalEnvExists = fs.existsSync(exampleEnvLocalPath);\n\n\tconst envPath = path.join(targetDir, \".env\");\n\tconst envLocalPath = path.join(targetDir, \".env.local\");\n\n\tlet envExists = fs.existsSync(envPath);\n\tlet envLocalExists = fs.existsSync(envLocalPath);\n\n\tconst allowCopies = !isCiEnvironment();\n\n\tif (allowCopies && exampleEnvExists) {\n\t\tif (!envExists) {\n\t\t\tfs.cpSync(exampleEnvPath, envPath);\n\n\t\t\tconsole.log(\"✓ Created .env from .env.example\");\n\t\t\tenvExists = true;\n\t\t}\n\t}\n\n\tif (allowCopies && exampleLocalEnvExists) {\n\t\tif (!envLocalExists) {\n\t\t\tfs.cpSync(exampleEnvLocalPath, envLocalPath);\n\n\t\t\tconsole.log(\"✓ Created .env.local from .env.local.example\");\n\t\t\tenvLocalExists = true;\n\t\t}\n\t}\n\n\tconst result: string[] = [];\n\t// The order matters, because latter files' values will override former files' values\n\tif (exampleEnvExists) {\n\t\tresult.push(\".env.example\");\n\t}\n\tif (exampleLocalEnvExists) {\n\t\tresult.push(\".env.local.example\");\n\t}\n\t// Only pass real .env / .env.local when there is no corresponding example file.\n\t// Otherwise `wrangler types` embeds different `--env-file` lists locally (with\n\t// .env.local) vs CI (no .env.local), causing noisy diffs in committed worker-configuration.d.ts.\n\tif (!exampleEnvExists && envExists) {\n\t\tresult.push(\".env\");\n\t}\n\tif (!exampleLocalEnvExists && envLocalExists) {\n\t\tresult.push(\".env.local\");\n\t}\n\n\treturn result;\n}\n"]}
@@ -0,0 +1,77 @@
1
+ import * as fs from 'fs';
2
+ import path from 'path';
3
+
4
+ // src/cf-typegen-discovery.ts
5
+ function findWorkspaceRoot(startPath) {
6
+ let dir = path.resolve(startPath);
7
+ for (; ; ) {
8
+ const pkgPath = path.join(dir, "package.json");
9
+ if (fs.existsSync(pkgPath)) {
10
+ try {
11
+ const content = fs.readFileSync(pkgPath, "utf8");
12
+ const pkg = JSON.parse(content);
13
+ if (pkg.workspaces != null && (Array.isArray(pkg.workspaces) || typeof pkg.workspaces === "object" && "packages" in pkg.workspaces)) {
14
+ return dir;
15
+ }
16
+ } catch {
17
+ }
18
+ }
19
+ const parent = path.dirname(dir);
20
+ if (parent === dir) break;
21
+ dir = parent;
22
+ }
23
+ return null;
24
+ }
25
+ function expandWorkspacePatterns(root, patterns) {
26
+ const dirs = [];
27
+ for (const pattern of patterns) {
28
+ if (!pattern.endsWith("/*")) continue;
29
+ const base = pattern.slice(0, -2);
30
+ const basePath = path.join(root, base);
31
+ try {
32
+ const entries = fs.readdirSync(basePath, { withFileTypes: true });
33
+ for (const e of entries) {
34
+ if (e.isDirectory()) {
35
+ dirs.push(path.join(basePath, e.name));
36
+ }
37
+ }
38
+ } catch {
39
+ }
40
+ }
41
+ return dirs;
42
+ }
43
+ function getWorkspacePaths(root) {
44
+ const pkgPath = path.join(root, "package.json");
45
+ try {
46
+ const content = fs.readFileSync(pkgPath, "utf8");
47
+ const pkg = JSON.parse(content);
48
+ const raw = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages;
49
+ if (!Array.isArray(raw)) return [];
50
+ return expandWorkspacePatterns(root, raw);
51
+ } catch {
52
+ return [];
53
+ }
54
+ }
55
+ function findWranglerConfigsInPaths(workspacePaths) {
56
+ const results = [];
57
+ for (const dir of workspacePaths) {
58
+ for (const name of ["wrangler.json", "wrangler.jsonc"]) {
59
+ const fullPath = path.join(dir, name);
60
+ if (fs.existsSync(fullPath)) {
61
+ results.push(fullPath);
62
+ break;
63
+ }
64
+ }
65
+ }
66
+ return results.sort((a, b) => a < b ? -1 : 1);
67
+ }
68
+ function discoverWranglerConfigs(cwd) {
69
+ const workspaceRoot = findWorkspaceRoot(cwd);
70
+ if (!workspaceRoot) return [];
71
+ const workspacePaths = getWorkspacePaths(workspaceRoot);
72
+ return findWranglerConfigsInPaths(workspacePaths);
73
+ }
74
+
75
+ export { discoverWranglerConfigs, expandWorkspacePatterns, findWorkspaceRoot, findWranglerConfigsInPaths, getWorkspacePaths };
76
+ //# sourceMappingURL=chunk-QEZL4IJI.js.map
77
+ //# sourceMappingURL=chunk-QEZL4IJI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cf-typegen-discovery.ts"],"names":[],"mappings":"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","file":"chunk-QEZL4IJI.js","sourcesContent":["import * as fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Find workspace root by walking up from startPath until we find a package.json\n * with a \"workspaces\" field (npm/bun convention).\n */\nexport function findWorkspaceRoot(startPath: string): string | null {\n\tlet dir = path.resolve(startPath);\n\tfor (;;) {\n\t\tconst pkgPath = path.join(dir, \"package.json\");\n\t\tif (fs.existsSync(pkgPath)) {\n\t\t\ttry {\n\t\t\t\tconst content = fs.readFileSync(pkgPath, \"utf8\");\n\t\t\t\tconst pkg = JSON.parse(content) as { workspaces?: unknown };\n\t\t\t\tif (\n\t\t\t\t\tpkg.workspaces != null &&\n\t\t\t\t\t(Array.isArray(pkg.workspaces) ||\n\t\t\t\t\t\t(typeof pkg.workspaces === \"object\" &&\n\t\t\t\t\t\t\t\"packages\" in pkg.workspaces))\n\t\t\t\t) {\n\t\t\t\t\treturn dir;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// ignore parse errors\n\t\t\t}\n\t\t}\n\t\tconst parent = path.dirname(dir);\n\t\tif (parent === dir) break;\n\t\tdir = parent;\n\t}\n\treturn null;\n}\n\n/**\n * Expand workspace glob patterns (e.g. \"packages/*\", \"tests/*\") to absolute paths.\n * Only supports single-level globs; each pattern must be exactly \"dirname/*\".\n */\nexport function expandWorkspacePatterns(\n\troot: string,\n\tpatterns: string[],\n): string[] {\n\tconst dirs: string[] = [];\n\tfor (const pattern of patterns) {\n\t\tif (!pattern.endsWith(\"/*\")) continue;\n\t\tconst base = pattern.slice(0, -2);\n\t\tconst basePath = path.join(root, base);\n\t\ttry {\n\t\t\tconst entries = fs.readdirSync(basePath, { withFileTypes: true });\n\t\t\tfor (const e of entries) {\n\t\t\t\tif (e.isDirectory()) {\n\t\t\t\t\tdirs.push(path.join(basePath, e.name));\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// base path may not exist\n\t\t}\n\t}\n\treturn dirs;\n}\n\n/**\n * Get workspace package paths from root package.json (workspaces field).\n * Returns absolute paths to each workspace member directory.\n */\nexport function getWorkspacePaths(root: string): string[] {\n\tconst pkgPath = path.join(root, \"package.json\");\n\ttry {\n\t\tconst content = fs.readFileSync(pkgPath, \"utf8\");\n\t\tconst pkg = JSON.parse(content) as {\n\t\t\tworkspaces?: string[] | { packages?: string[] };\n\t\t};\n\t\tconst raw = Array.isArray(pkg.workspaces)\n\t\t\t? pkg.workspaces\n\t\t\t: pkg.workspaces?.packages;\n\t\tif (!Array.isArray(raw)) return [];\n\t\treturn expandWorkspacePatterns(root, raw);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Find all wrangler config files under the given workspace member paths.\n * Does not rely on git; includes untracked configs (e.g. new durable objects).\n */\nexport function findWranglerConfigsInPaths(workspacePaths: string[]): string[] {\n\tconst results: string[] = [];\n\tfor (const dir of workspacePaths) {\n\t\tfor (const name of [\"wrangler.json\", \"wrangler.jsonc\"]) {\n\t\t\tconst fullPath = path.join(dir, name);\n\t\t\tif (fs.existsSync(fullPath)) {\n\t\t\t\tresults.push(fullPath);\n\t\t\t\tbreak; // at most one per dir\n\t\t\t}\n\t\t}\n\t}\n\treturn results.sort((a, b) => (a < b ? -1 : 1));\n}\n\n/**\n * Discover all wrangler config paths for the workspace containing cwd.\n * Returns empty array if not in a workspace or if root has no workspaces field.\n */\nexport function discoverWranglerConfigs(cwd: string): string[] {\n\tconst workspaceRoot = findWorkspaceRoot(cwd);\n\tif (!workspaceRoot) return [];\n\tconst workspacePaths = getWorkspacePaths(workspaceRoot);\n\treturn findWranglerConfigsInPaths(workspacePaths);\n}\n"]}
@@ -0,0 +1,48 @@
1
+ // src/WorkerClient.ts
2
+ var WorkerClient = class {
3
+ constructor(options) {
4
+ this.clientSchema = options.clientSchema;
5
+ this.serverSchema = options.serverSchema;
6
+ this.onMessageCallback = options.onMessage;
7
+ this.onValidationErrorCallback = options.onValidationError;
8
+ this.worker = options.worker;
9
+ this.worker.addEventListener("message", (event) => {
10
+ this.handleMessage(event);
11
+ });
12
+ if (options.onError) {
13
+ this.worker.addEventListener("error", options.onError);
14
+ }
15
+ }
16
+ handleMessage(event) {
17
+ try {
18
+ const validatedMessage = this.serverSchema.parse(event.data);
19
+ this.onMessageCallback?.(validatedMessage);
20
+ } catch (error) {
21
+ const validationError = error instanceof Error ? error : new Error(String(error));
22
+ this.onValidationErrorCallback?.(validationError, event.data);
23
+ }
24
+ }
25
+ /**
26
+ * Send a message to the worker with validation
27
+ */
28
+ send(message) {
29
+ const validatedMessage = this.clientSchema.parse(message);
30
+ this.worker.postMessage(validatedMessage);
31
+ }
32
+ /**
33
+ * Terminate the worker
34
+ */
35
+ terminate() {
36
+ this.worker.terminate();
37
+ }
38
+ /**
39
+ * Get the underlying Worker instance
40
+ */
41
+ getWorker() {
42
+ return this.worker;
43
+ }
44
+ };
45
+
46
+ export { WorkerClient };
47
+ //# sourceMappingURL=chunk-TYKZZZOR.js.map
48
+ //# sourceMappingURL=chunk-TYKZZZOR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/WorkerClient.ts"],"names":[],"mappings":";AA6BO,IAAM,eAAN,MAAmD;AAAA,EAUzD,YAAY,OAAA,EAA8D;AACzE,IAAA,IAAA,CAAK,eAAe,OAAA,CAAQ,YAAA;AAC5B,IAAA,IAAA,CAAK,eAAe,OAAA,CAAQ,YAAA;AAC5B,IAAA,IAAA,CAAK,oBAAoB,OAAA,CAAQ,SAAA;AACjC,IAAA,IAAA,CAAK,4BAA4B,OAAA,CAAQ,iBAAA;AACzC,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AAGtB,IAAA,IAAA,CAAK,MAAA,CAAO,gBAAA,CAAiB,SAAA,EAAW,CAAC,KAAA,KAAwB;AAChE,MAAA,IAAA,CAAK,cAAc,KAAK,CAAA;AAAA,IACzB,CAAC,CAAA;AAED,IAAA,IAAI,QAAQ,OAAA,EAAS;AACpB,MAAA,IAAA,CAAK,MAAA,CAAO,gBAAA,CAAiB,OAAA,EAAS,OAAA,CAAQ,OAAO,CAAA;AAAA,IACtD;AAAA,EACD;AAAA,EAEQ,cAAc,KAAA,EAA2B;AAChD,IAAA,IAAI;AAEH,MAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,YAAA,CAAa,KAAA,CAAM,MAAM,IAAI,CAAA;AAC3D,MAAA,IAAA,CAAK,oBAAoB,gBAAgB,CAAA;AAAA,IAC1C,SAAS,KAAA,EAAO;AAEf,MAAA,MAAM,eAAA,GACL,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACzD,MAAA,IAAA,CAAK,yBAAA,GAA4B,eAAA,EAAiB,KAAA,CAAM,IAAI,CAAA;AAAA,IAC7D;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKO,KAAK,OAAA,EAA+B;AAE1C,IAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,YAAA,CAAa,KAAA,CAAM,OAAO,CAAA;AACxD,IAAA,IAAA,CAAK,MAAA,CAAO,YAAY,gBAAgB,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKO,SAAA,GAAkB;AACxB,IAAA,IAAA,CAAK,OAAO,SAAA,EAAU;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKO,SAAA,GAAoB;AAC1B,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACb;AACD","file":"chunk-TYKZZZOR.js","sourcesContent":["import type { ZodType } from \"zod/v4\";\n\nexport interface WorkerClientOptions<TClientMessage, TServerMessage> {\n\t/**\n\t * Worker instance to wrap\n\t */\n\tworker: Worker;\n\t/**\n\t * Schema for validating messages sent to the worker\n\t */\n\tclientSchema: ZodType<TClientMessage>;\n\t/**\n\t * Schema for validating messages received from the worker\n\t */\n\tserverSchema: ZodType<TServerMessage>;\n\t/**\n\t * Callback for validated messages from the worker\n\t */\n\tonMessage?: (message: TServerMessage) => void;\n\t/**\n\t * Callback for when validation fails on incoming messages\n\t */\n\tonValidationError?: (error: Error, rawMessage: unknown) => void;\n\t/**\n\t * Callback for worker errors\n\t */\n\tonError?: (event: ErrorEvent) => void;\n}\n\nexport class WorkerClient<TClientMessage, TServerMessage> {\n\tprivate worker: Worker;\n\tprivate readonly clientSchema: ZodType<TClientMessage>;\n\tprivate readonly serverSchema: ZodType<TServerMessage>;\n\tprivate readonly onMessageCallback?: (message: TServerMessage) => void;\n\tprivate readonly onValidationErrorCallback?: (\n\t\terror: Error,\n\t\trawMessage: unknown,\n\t) => void;\n\n\tconstructor(options: WorkerClientOptions<TClientMessage, TServerMessage>) {\n\t\tthis.clientSchema = options.clientSchema;\n\t\tthis.serverSchema = options.serverSchema;\n\t\tthis.onMessageCallback = options.onMessage;\n\t\tthis.onValidationErrorCallback = options.onValidationError;\n\t\tthis.worker = options.worker;\n\n\t\t// Setup event handlers\n\t\tthis.worker.addEventListener(\"message\", (event: MessageEvent) => {\n\t\t\tthis.handleMessage(event);\n\t\t});\n\n\t\tif (options.onError) {\n\t\t\tthis.worker.addEventListener(\"error\", options.onError);\n\t\t}\n\t}\n\n\tprivate handleMessage(event: MessageEvent): void {\n\t\ttry {\n\t\t\t// Validate the incoming message\n\t\t\tconst validatedMessage = this.serverSchema.parse(event.data);\n\t\t\tthis.onMessageCallback?.(validatedMessage);\n\t\t} catch (error) {\n\t\t\t// Validation failed\n\t\t\tconst validationError =\n\t\t\t\terror instanceof Error ? error : new Error(String(error));\n\t\t\tthis.onValidationErrorCallback?.(validationError, event.data);\n\t\t}\n\t}\n\n\t/**\n\t * Send a message to the worker with validation\n\t */\n\tpublic send(message: TClientMessage): void {\n\t\t// Validate the outgoing message\n\t\tconst validatedMessage = this.clientSchema.parse(message);\n\t\tthis.worker.postMessage(validatedMessage);\n\t}\n\n\t/**\n\t * Terminate the worker\n\t */\n\tpublic terminate(): void {\n\t\tthis.worker.terminate();\n\t}\n\n\t/**\n\t * Get the underlying Worker instance\n\t */\n\tpublic getWorker(): Worker {\n\t\treturn this.worker;\n\t}\n}\n"]}
@@ -0,0 +1,45 @@
1
+ // src/worker-helper.ts
2
+ var WorkerHelper = class {
3
+ constructor(self, inputSchema, outputSchema, handlers) {
4
+ this.self = self;
5
+ this.inputSchema = inputSchema;
6
+ this.outputSchema = outputSchema;
7
+ this.handlers = handlers;
8
+ this.send = (response) => {
9
+ const outputValidation = this.outputSchema.safeParse(response);
10
+ if (!outputValidation.success) {
11
+ this.handlers.handleOutputValidationError(
12
+ outputValidation.error,
13
+ response
14
+ );
15
+ return;
16
+ }
17
+ this.self.postMessage(response);
18
+ };
19
+ this.setupMessageListener();
20
+ }
21
+ setupMessageListener() {
22
+ this.self.addEventListener("message", (event) => {
23
+ this.handleMessage(event);
24
+ });
25
+ }
26
+ async handleMessage(event) {
27
+ const validationResult = this.inputSchema.safeParse(event.data);
28
+ if (!validationResult.success) {
29
+ await this.handlers.handleInputValidationError(
30
+ validationResult.error,
31
+ event.data
32
+ );
33
+ return;
34
+ }
35
+ try {
36
+ await this.handlers.handleMessage(validationResult.data);
37
+ } catch (error) {
38
+ await this.handlers.handleProcessingError(error, validationResult.data);
39
+ }
40
+ }
41
+ };
42
+
43
+ export { WorkerHelper };
44
+ //# sourceMappingURL=chunk-UNYDCGUS.js.map
45
+ //# sourceMappingURL=chunk-UNYDCGUS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/worker-helper.ts"],"names":[],"mappings":";AAoBO,IAAe,eAAf,MAA6C;AAAA,EACnD,WAAA,CACS,IAAA,EACA,WAAA,EACA,YAAA,EACA,QAAA,EACP;AAJO,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AACA,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAKT,IAAA,IAAA,CAAU,IAAA,GAAO,CAAC,QAAA,KAAsB;AAEvC,MAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,YAAA,CAAa,SAAA,CAAU,QAAQ,CAAA;AAC7D,MAAA,IAAI,CAAC,iBAAiB,OAAA,EAAS;AAC9B,QAAA,IAAA,CAAK,QAAA,CAAS,2BAAA;AAAA,UACb,gBAAA,CAAiB,KAAA;AAAA,UACjB;AAAA,SACD;AACA,QAAA;AAAA,MACD;AAGA,MAAA,IAAA,CAAK,IAAA,CAAK,YAAY,QAAQ,CAAA;AAAA,IAC/B,CAAA;AAhBC,IAAA,IAAA,CAAK,oBAAA,EAAqB;AAAA,EAC3B;AAAA,EAiBQ,oBAAA,GAA6B;AACpC,IAAA,IAAA,CAAK,IAAA,CAAK,gBAAA,CAAiB,SAAA,EAAW,CAAC,KAAA,KAAwB;AAC9D,MAAA,IAAA,CAAK,cAAc,KAAK,CAAA;AAAA,IACzB,CAAC,CAAA;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,KAAA,EAAoC;AAE/D,IAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,WAAA,CAAY,SAAA,CAAU,MAAM,IAAI,CAAA;AAE9D,IAAA,IAAI,CAAC,iBAAiB,OAAA,EAAS;AAC9B,MAAA,MAAM,KAAK,QAAA,CAAS,0BAAA;AAAA,QACnB,gBAAA,CAAiB,KAAA;AAAA,QACjB,KAAA,CAAM;AAAA,OACP;AACA,MAAA;AAAA,IACD;AAGA,IAAA,IAAI;AACH,MAAA,MAAM,IAAA,CAAK,QAAA,CAAS,aAAA,CAAc,gBAAA,CAAiB,IAAI,CAAA;AAAA,IACxD,SAAS,KAAA,EAAO;AACf,MAAA,MAAM,IAAA,CAAK,QAAA,CAAS,qBAAA,CAAsB,KAAA,EAAO,iBAAiB,IAAI,CAAA;AAAA,IACvE;AAAA,EACD;AACD","file":"chunk-UNYDCGUS.js","sourcesContent":["import type { ZodError, ZodType } from \"zod/v4\";\n\ntype MessageTarget = DedicatedWorkerGlobalScope;\n\nexport type WorkerHelperHandlers<TInput, TOutput> = {\n\thandleMessage: (data: TInput) => void | Promise<void>;\n\thandleInputValidationError: (\n\t\terror: ZodError<TInput>,\n\t\toriginalData: unknown,\n\t) => void | Promise<void>;\n\thandleOutputValidationError: (\n\t\terror: ZodError<TOutput>,\n\t\toriginalData: TOutput,\n\t) => void | Promise<void>;\n\thandleProcessingError: (\n\t\terror: unknown,\n\t\tvalidatedData: TInput,\n\t) => void | Promise<void>;\n};\n\nexport abstract class WorkerHelper<TInput, TOutput> {\n\tconstructor(\n\t\tprivate self: MessageTarget,\n\t\tprivate inputSchema: ZodType<TInput>,\n\t\tprivate outputSchema: ZodType<TOutput>,\n\t\tprivate handlers: WorkerHelperHandlers<TInput, TOutput>,\n\t) {\n\t\tthis.setupMessageListener();\n\t}\n\n\tprotected send = (response: TOutput) => {\n\t\t// Validate output before sending\n\t\tconst outputValidation = this.outputSchema.safeParse(response);\n\t\tif (!outputValidation.success) {\n\t\t\tthis.handlers.handleOutputValidationError(\n\t\t\t\toutputValidation.error,\n\t\t\t\tresponse,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Send as success response\n\t\tthis.self.postMessage(response);\n\t};\n\n\tprivate setupMessageListener(): void {\n\t\tthis.self.addEventListener(\"message\", (event: MessageEvent) => {\n\t\t\tthis.handleMessage(event);\n\t\t});\n\t}\n\n\tprivate async handleMessage(event: MessageEvent): Promise<void> {\n\t\t// Validate input using safeParse\n\t\tconst validationResult = this.inputSchema.safeParse(event.data);\n\n\t\tif (!validationResult.success) {\n\t\t\tawait this.handlers.handleInputValidationError(\n\t\t\t\tvalidationResult.error,\n\t\t\t\tevent.data,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle the validated message\n\t\ttry {\n\t\t\tawait this.handlers.handleMessage(validationResult.data);\n\t\t} catch (error) {\n\t\t\tawait this.handlers.handleProcessingError(error, validationResult.data);\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export { WorkerClient, WorkerClientOptions } from './WorkerClient.js';
2
+ export { WorkerHelper, WorkerHelperHandlers } from './worker-helper.js';
3
+ import 'zod/v4';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { WorkerClient } from './chunk-TYKZZZOR.js';
2
+ export { WorkerHelper } from './chunk-UNYDCGUS.js';
3
+ //# sourceMappingURL=index.js.map
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Ensures a .env and .env.local file exists in the target directory.
3
+ * If it doesn't exist, copies from .env.example and .env.local.example.
4
+ *
5
+ * In CI, does not create those files — typegen uses `.env.example` / `.env.local.example` only when real files are absent.
6
+ *
7
+ * @param targetDir - The directory where the .env and .env.local files should exist
8
+ * @returns An array of the files that were created or already existed
9
+ */
10
+ declare function prepareEnvFiles(targetDir: string): string[];
11
+
12
+ export { prepareEnvFiles };
@@ -0,0 +1,3 @@
1
+ export { prepareEnvFiles } from '../chunk-A4S7WGGQ.js';
2
+ //# sourceMappingURL=prepare-env.js.map
3
+ //# sourceMappingURL=prepare-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"prepare-env.js"}
@@ -0,0 +1,21 @@
1
+ import { ZodType, ZodError } from 'zod/v4';
2
+
3
+ type MessageTarget = DedicatedWorkerGlobalScope;
4
+ type WorkerHelperHandlers<TInput, TOutput> = {
5
+ handleMessage: (data: TInput) => void | Promise<void>;
6
+ handleInputValidationError: (error: ZodError<TInput>, originalData: unknown) => void | Promise<void>;
7
+ handleOutputValidationError: (error: ZodError<TOutput>, originalData: TOutput) => void | Promise<void>;
8
+ handleProcessingError: (error: unknown, validatedData: TInput) => void | Promise<void>;
9
+ };
10
+ declare abstract class WorkerHelper<TInput, TOutput> {
11
+ private self;
12
+ private inputSchema;
13
+ private outputSchema;
14
+ private handlers;
15
+ constructor(self: MessageTarget, inputSchema: ZodType<TInput>, outputSchema: ZodType<TOutput>, handlers: WorkerHelperHandlers<TInput, TOutput>);
16
+ protected send: (response: TOutput) => void;
17
+ private setupMessageListener;
18
+ private handleMessage;
19
+ }
20
+
21
+ export { WorkerHelper, type WorkerHelperHandlers };
@@ -0,0 +1,3 @@
1
+ export { WorkerHelper } from './chunk-UNYDCGUS.js';
2
+ //# sourceMappingURL=worker-helper.js.map
3
+ //# sourceMappingURL=worker-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"worker-helper.js"}
package/package.json CHANGED
@@ -1,32 +1,36 @@
1
1
  {
2
2
  "name": "@firtoz/worker-helper",
3
- "version": "1.5.1",
3
+ "version": "1.6.1",
4
4
  "description": "Type-safe Web Worker helper with Zod validation and Cloudflare Workers utilities (cf-typegen)",
5
- "main": "./src/index.ts",
6
- "module": "./src/index.ts",
7
- "types": "./src/index.ts",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
10
- "types": "./src/index.ts",
11
- "import": "./src/index.ts",
12
- "require": "./src/index.ts"
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
13
  },
14
14
  "./*": {
15
- "types": "./src/*.ts",
16
- "import": "./src/*.ts",
17
- "require": "./src/*.ts"
15
+ "types": "./dist/*.d.ts",
16
+ "import": "./dist/*.js"
18
17
  }
19
18
  },
20
19
  "bin": {
21
- "cf-typegen": "./src/cf-typegen.ts"
20
+ "cf-typegen": "./dist/cf-typegen.js"
22
21
  },
23
22
  "files": [
23
+ "dist/**/*.js",
24
+ "dist/**/*.js.map",
25
+ "dist/**/*.d.ts",
24
26
  "src/**/*.ts",
25
27
  "README.md",
26
28
  "CHANGELOG.md"
27
29
  ],
28
30
  "scripts": {
29
- "typecheck": "tsc --noEmit -p ./tsconfig.json",
31
+ "build": "tsup && bun ../../scripts/add-node-shebang.ts dist/cf-typegen.js",
32
+ "prepack": "bun run build",
33
+ "typecheck": "tsgo --noEmit -p ./tsconfig.json",
30
34
  "lint": "biome check --write src",
31
35
  "lint:ci": "biome ci src",
32
36
  "format": "biome format src --write",
@@ -67,8 +71,8 @@
67
71
  "zod": "^4.3.6"
68
72
  },
69
73
  "devDependencies": {
70
- "@types/node": "^25.5.0",
71
- "@firtoz/maybe-error": "^1.5.2",
72
- "bun-types": "^1.3.11"
74
+ "@types/node": "^25.6.0",
75
+ "@firtoz/maybe-error": "^1.6.1",
76
+ "bun-types": "^1.3.12"
73
77
  }
74
78
  }
@@ -56,10 +56,13 @@ export function prepareEnvFiles(targetDir: string): string[] {
56
56
  if (exampleLocalEnvExists) {
57
57
  result.push(".env.local.example");
58
58
  }
59
- if (envExists) {
59
+ // Only pass real .env / .env.local when there is no corresponding example file.
60
+ // Otherwise `wrangler types` embeds different `--env-file` lists locally (with
61
+ // .env.local) vs CI (no .env.local), causing noisy diffs in committed worker-configuration.d.ts.
62
+ if (!exampleEnvExists && envExists) {
60
63
  result.push(".env");
61
64
  }
62
- if (envLocalExists) {
65
+ if (!exampleLocalEnvExists && envLocalExists) {
63
66
  result.push(".env.local");
64
67
  }
65
68