@firtoz/worker-helper 1.3.4 → 1.4.0
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 +6 -0
- package/package.json +3 -3
- package/src/cf-typegen-discovery.ts +110 -0
- package/src/cf-typegen.ts +12 -52
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @firtoz/worker-helper
|
|
2
2
|
|
|
3
|
+
## 1.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`6e96ebb`](https://github.com/firtoz/fullstack-toolkit/commit/6e96ebb05a992cc33ea339e5466b608774be62c3) Thanks [@firtoz](https://github.com/firtoz)! - cf-typegen now discovers wrangler configs from the npm/bun workspace definition (root package.json `workspaces` field) instead of using `git ls-files`. Untracked workspace packages (e.g. new durable objects like fal-user-do) are included in type generation without needing to be committed first.
|
|
8
|
+
|
|
3
9
|
## 1.3.4
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@firtoz/worker-helper",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Type-safe Web Worker helper with Zod validation and Cloudflare Workers utilities (cf-typegen)",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"module": "./src/index.ts",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"zod": "^4.3.6"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
|
-
"@types/node": "^25.2.
|
|
70
|
+
"@types/node": "^25.2.3",
|
|
71
71
|
"@firtoz/maybe-error": "^1.5.2",
|
|
72
|
-
"bun-types": "^1.3.
|
|
72
|
+
"bun-types": "^1.3.9"
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Find workspace root by walking up from startPath until we find a package.json
|
|
6
|
+
* with a "workspaces" field (npm/bun convention).
|
|
7
|
+
*/
|
|
8
|
+
export function findWorkspaceRoot(startPath: string): string | null {
|
|
9
|
+
let dir = path.resolve(startPath);
|
|
10
|
+
for (;;) {
|
|
11
|
+
const pkgPath = path.join(dir, "package.json");
|
|
12
|
+
if (fs.existsSync(pkgPath)) {
|
|
13
|
+
try {
|
|
14
|
+
const content = fs.readFileSync(pkgPath, "utf8");
|
|
15
|
+
const pkg = JSON.parse(content) as { workspaces?: unknown };
|
|
16
|
+
if (
|
|
17
|
+
pkg.workspaces != null &&
|
|
18
|
+
(Array.isArray(pkg.workspaces) ||
|
|
19
|
+
(typeof pkg.workspaces === "object" &&
|
|
20
|
+
"packages" in pkg.workspaces))
|
|
21
|
+
) {
|
|
22
|
+
return dir;
|
|
23
|
+
}
|
|
24
|
+
} catch {
|
|
25
|
+
// ignore parse errors
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const parent = path.dirname(dir);
|
|
29
|
+
if (parent === dir) break;
|
|
30
|
+
dir = parent;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Expand workspace glob patterns (e.g. "packages/*", "tests/*") to absolute paths.
|
|
37
|
+
* Only supports single-level globs; each pattern must be exactly "dirname/*".
|
|
38
|
+
*/
|
|
39
|
+
export function expandWorkspacePatterns(
|
|
40
|
+
root: string,
|
|
41
|
+
patterns: string[],
|
|
42
|
+
): string[] {
|
|
43
|
+
const dirs: string[] = [];
|
|
44
|
+
for (const pattern of patterns) {
|
|
45
|
+
if (!pattern.endsWith("/*")) continue;
|
|
46
|
+
const base = pattern.slice(0, -2);
|
|
47
|
+
const basePath = path.join(root, base);
|
|
48
|
+
try {
|
|
49
|
+
const entries = fs.readdirSync(basePath, { withFileTypes: true });
|
|
50
|
+
for (const e of entries) {
|
|
51
|
+
if (e.isDirectory()) {
|
|
52
|
+
dirs.push(path.join(basePath, e.name));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
} catch {
|
|
56
|
+
// base path may not exist
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return dirs;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get workspace package paths from root package.json (workspaces field).
|
|
64
|
+
* Returns absolute paths to each workspace member directory.
|
|
65
|
+
*/
|
|
66
|
+
export function getWorkspacePaths(root: string): string[] {
|
|
67
|
+
const pkgPath = path.join(root, "package.json");
|
|
68
|
+
try {
|
|
69
|
+
const content = fs.readFileSync(pkgPath, "utf8");
|
|
70
|
+
const pkg = JSON.parse(content) as {
|
|
71
|
+
workspaces?: string[] | { packages?: string[] };
|
|
72
|
+
};
|
|
73
|
+
const raw = Array.isArray(pkg.workspaces)
|
|
74
|
+
? pkg.workspaces
|
|
75
|
+
: pkg.workspaces?.packages;
|
|
76
|
+
if (!Array.isArray(raw)) return [];
|
|
77
|
+
return expandWorkspacePatterns(root, raw);
|
|
78
|
+
} catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Find all wrangler config files under the given workspace member paths.
|
|
85
|
+
* Does not rely on git; includes untracked configs (e.g. new durable objects).
|
|
86
|
+
*/
|
|
87
|
+
export function findWranglerConfigsInPaths(workspacePaths: string[]): string[] {
|
|
88
|
+
const results: string[] = [];
|
|
89
|
+
for (const dir of workspacePaths) {
|
|
90
|
+
for (const name of ["wrangler.json", "wrangler.jsonc"]) {
|
|
91
|
+
const fullPath = path.join(dir, name);
|
|
92
|
+
if (fs.existsSync(fullPath)) {
|
|
93
|
+
results.push(fullPath);
|
|
94
|
+
break; // at most one per dir
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return results.sort((a, b) => (a < b ? -1 : 1));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Discover all wrangler config paths for the workspace containing cwd.
|
|
103
|
+
* Returns empty array if not in a workspace or if root has no workspaces field.
|
|
104
|
+
*/
|
|
105
|
+
export function discoverWranglerConfigs(cwd: string): string[] {
|
|
106
|
+
const workspaceRoot = findWorkspaceRoot(cwd);
|
|
107
|
+
if (!workspaceRoot) return [];
|
|
108
|
+
const workspacePaths = getWorkspacePaths(workspaceRoot);
|
|
109
|
+
return findWranglerConfigsInPaths(workspacePaths);
|
|
110
|
+
}
|
package/src/cf-typegen.ts
CHANGED
|
@@ -3,6 +3,10 @@ import { execSync } from "node:child_process";
|
|
|
3
3
|
import * as fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
6
|
+
import {
|
|
7
|
+
discoverWranglerConfigs,
|
|
8
|
+
findWorkspaceRoot,
|
|
9
|
+
} from "./cf-typegen-discovery";
|
|
6
10
|
import { prepareEnvFiles } from "./utils/prepare-env";
|
|
7
11
|
|
|
8
12
|
// Use the current working directory
|
|
@@ -16,65 +20,21 @@ if (!cwd || !fs.existsSync(cwd)) {
|
|
|
16
20
|
|
|
17
21
|
console.log(`Running CF typegen for: ${cwd}`);
|
|
18
22
|
|
|
19
|
-
/**
|
|
20
|
-
* Find the git root directory using git command
|
|
21
|
-
*/
|
|
22
|
-
function findGitRoot(startPath: string): string | null {
|
|
23
|
-
try {
|
|
24
|
-
const output = execSync("git rev-parse --show-toplevel", {
|
|
25
|
-
cwd: startPath,
|
|
26
|
-
encoding: "utf8",
|
|
27
|
-
});
|
|
28
|
-
return output.trim();
|
|
29
|
-
} catch {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Find all wrangler config files using git ls-files
|
|
36
|
-
* This is more efficient and respects .gitignore
|
|
37
|
-
*/
|
|
38
|
-
function findAllWranglerConfigs(gitRoot: string): string[] {
|
|
39
|
-
try {
|
|
40
|
-
// Use git ls-files to find all tracked wrangler configs
|
|
41
|
-
const output = execSync(
|
|
42
|
-
'git ls-files "**/wrangler.json" "**/wrangler.jsonc"',
|
|
43
|
-
{
|
|
44
|
-
cwd: gitRoot,
|
|
45
|
-
encoding: "utf8",
|
|
46
|
-
},
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
return output
|
|
50
|
-
.trim()
|
|
51
|
-
.split("\n")
|
|
52
|
-
.filter((line) => line.length > 0)
|
|
53
|
-
.map((relativePath) => path.join(gitRoot, relativePath))
|
|
54
|
-
.sort((a, b) => (a < b ? -1 : 1));
|
|
55
|
-
} catch (err) {
|
|
56
|
-
console.warn("⚠ Failed to run git ls-files:", err);
|
|
57
|
-
return [];
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
23
|
function runWranglerTypes() {
|
|
62
24
|
const envFiles = prepareEnvFiles(cwd);
|
|
63
25
|
|
|
64
26
|
console.log("Running wrangler types...");
|
|
65
27
|
|
|
66
|
-
//
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
console.
|
|
28
|
+
// Discover wrangler configs from npm/bun workspace definition (includes untracked packages)
|
|
29
|
+
const workspaceRoot = findWorkspaceRoot(cwd);
|
|
30
|
+
let allConfigs: string[];
|
|
31
|
+
if (workspaceRoot) {
|
|
32
|
+
allConfigs = discoverWranglerConfigs(cwd);
|
|
33
|
+
} else {
|
|
34
|
+
console.warn("⚠ No workspace root found, using current directory only");
|
|
35
|
+
allConfigs = [];
|
|
73
36
|
}
|
|
74
37
|
|
|
75
|
-
// Find all wrangler configs in the workspace
|
|
76
|
-
const allConfigs = gitRoot ? findAllWranglerConfigs(gitRoot) : [];
|
|
77
|
-
|
|
78
38
|
if (allConfigs.length > 0) {
|
|
79
39
|
console.log(` Found ${allConfigs.length} wrangler config(s) in workspace`);
|
|
80
40
|
}
|