diff --git a/Games/claudecraft/package.json b/Games/claudecraft/package.json index c21f54312..2a91f3ccb 100644 --- a/Games/claudecraft/package.json +++ b/Games/claudecraft/package.json @@ -18,14 +18,14 @@ "three": "^0.182.0" }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/Games/duet-keys/package.json b/Games/duet-keys/package.json index d65efe021..e3b548fab 100644 --- a/Games/duet-keys/package.json +++ b/Games/duet-keys/package.json @@ -19,15 +19,15 @@ "three": "^0.182.0" }, "devDependencies": { - "@react-three/drei": "^10.7.7", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@react-three/drei": "catalog:", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/Games/loopline/package.json b/Games/loopline/package.json index aa7303a16..4d04aa4fe 100644 --- a/Games/loopline/package.json +++ b/Games/loopline/package.json @@ -19,15 +19,15 @@ "three": "^0.182.0" }, "devDependencies": { - "@react-three/drei": "^10.7.7", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@react-three/drei": "catalog:", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/Games/spire-cards/package.json b/Games/spire-cards/package.json index 40412d22a..b1db7b780 100644 --- a/Games/spire-cards/package.json +++ b/Games/spire-cards/package.json @@ -18,14 +18,14 @@ "three": "^0.182.0" }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/Games/starhome/package.json b/Games/starhome/package.json index 016ac19aa..15c4d9b15 100644 --- a/Games/starhome/package.json +++ b/Games/starhome/package.json @@ -19,15 +19,15 @@ "three": "^0.182.0" }, "devDependencies": { - "@react-three/drei": "^10.7.7", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@react-three/drei": "catalog:", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/Games/studio-showcase/package.json b/Games/studio-showcase/package.json index c8df3e4be..29a4d6e20 100644 --- a/Games/studio-showcase/package.json +++ b/Games/studio-showcase/package.json @@ -20,15 +20,15 @@ "three": "^0.182.0" }, "devDependencies": { - "@react-three/drei": "^10.7.7", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@react-three/drei": "catalog:", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/Games/the-robots/package.json b/Games/the-robots/package.json index 7df91b529..269a5dc1e 100644 --- a/Games/the-robots/package.json +++ b/Games/the-robots/package.json @@ -18,14 +18,14 @@ "three": "^0.182.0" }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/Games/tower-guard/package.json b/Games/tower-guard/package.json index 6f8be1b41..9921b013f 100644 --- a/Games/tower-guard/package.json +++ b/Games/tower-guard/package.json @@ -19,14 +19,14 @@ "three": "^0.182.0" }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/Games/vice-isle/package.json b/Games/vice-isle/package.json index fdb7bef62..c4e72164e 100644 --- a/Games/vice-isle/package.json +++ b/Games/vice-isle/package.json @@ -20,14 +20,14 @@ "three": "^0.182.0" }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/Games/wreckway/package.json b/Games/wreckway/package.json index c317000b2..30dee71a7 100644 --- a/Games/wreckway/package.json +++ b/Games/wreckway/package.json @@ -20,14 +20,14 @@ "three": "^0.182.0" }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" }, "exports": { ".": "./src/index.tsx", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 77f11bd18..d8a598678 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -16,13 +16,13 @@ "react-dom": "19.2.3" }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", + "@tailwindcss/vite": "catalog:", "@tauri-apps/cli": "^2", - "@types/react": "^19", - "@types/react-dom": "^19", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" } } diff --git a/apps/dev/package.json b/apps/dev/package.json index 5dee81c41..da42fe75c 100644 --- a/apps/dev/package.json +++ b/apps/dev/package.json @@ -23,13 +23,13 @@ }, "devDependencies": { "@jgengine/editor": "workspace:*", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2" + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:" } } diff --git a/bun.lock b/bun.lock index 1f807fe92..b05f1c8e8 100644 --- a/bun.lock +++ b/bun.lock @@ -24,14 +24,14 @@ "three": "^0.182.0", }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "Games/duet-keys": { @@ -48,15 +48,15 @@ "three": "^0.182.0", }, "devDependencies": { - "@react-three/drei": "^10.7.7", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@react-three/drei": "catalog:", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "Games/loopline": { @@ -73,15 +73,15 @@ "three": "^0.182.0", }, "devDependencies": { - "@react-three/drei": "^10.7.7", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@react-three/drei": "catalog:", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "Games/spire-cards": { @@ -97,14 +97,14 @@ "three": "^0.182.0", }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "Games/starhome": { @@ -121,15 +121,15 @@ "three": "^0.182.0", }, "devDependencies": { - "@react-three/drei": "^10.7.7", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@react-three/drei": "catalog:", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "Games/studio-showcase": { @@ -147,15 +147,15 @@ "three": "^0.182.0", }, "devDependencies": { - "@react-three/drei": "^10.7.7", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@react-three/drei": "catalog:", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "Games/the-robots": { @@ -171,14 +171,14 @@ "three": "^0.182.0", }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "Games/tower-guard": { @@ -195,14 +195,14 @@ "three": "^0.182.0", }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "Games/vice-isle": { @@ -220,14 +220,14 @@ "three": "^0.182.0", }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "Games/wreckway": { @@ -245,14 +245,14 @@ "three": "^0.182.0", }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "apps/desktop": { @@ -265,14 +265,14 @@ "react-dom": "19.2.3", }, "devDependencies": { - "@tailwindcss/vite": "^4.0.15", + "@tailwindcss/vite": "catalog:", "@tauri-apps/cli": "^2", - "@types/react": "^19", - "@types/react-dom": "^19", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "apps/dev": { @@ -291,14 +291,14 @@ }, "devDependencies": { "@jgengine/editor": "workspace:*", - "@tailwindcss/vite": "^4.0.15", - "@types/react": "^19", - "@types/react-dom": "^19", - "@types/three": "^0.182.0", - "@vitejs/plugin-react": "^4.3.4", - "tailwindcss": "^4.0.15", - "typescript": "^5", - "vite": "^6.2.2", + "@tailwindcss/vite": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@types/three": "catalog:", + "@vitejs/plugin-react": "catalog:", + "tailwindcss": "catalog:", + "typescript": "catalog:", + "vite": "catalog:", }, }, "apps/web": { @@ -588,6 +588,17 @@ }, }, }, + "catalog": { + "@react-three/drei": "^10.7.7", + "@tailwindcss/vite": "^4.0.15", + "@types/react": "^19", + "@types/react-dom": "^19", + "@types/three": "^0.182.0", + "@vitejs/plugin-react": "^4.3.4", + "tailwindcss": "^4.0.15", + "typescript": "^5", + "vite": "^6.2.2", + }, "packages": { "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], diff --git a/package.json b/package.json index e4c2f13c8..8d8872772 100644 --- a/package.json +++ b/package.json @@ -2,13 +2,20 @@ "name": "jgengine-monorepo", "private": true, "type": "module", - "workspaces": [ - "packages/*", - "Games/*", - "apps/*", - "examples/*", - "registry" - ], + "workspaces": { + "packages": ["packages/*", "Games/*", "apps/*", "examples/*", "registry"], + "catalog": { + "@react-three/drei": "^10.7.7", + "@tailwindcss/vite": "^4.0.15", + "@types/react": "^19", + "@types/react-dom": "^19", + "@types/three": "^0.182.0", + "@vitejs/plugin-react": "^4.3.4", + "tailwindcss": "^4.0.15", + "typescript": "^5", + "vite": "^6.2.2" + } + }, "scripts": { "agent:preflight": "bun scripts/agent-preflight.ts", "ship:preflight": "bun scripts/agent-preflight.ts --ship", diff --git a/packages/jgengine/src/pkg.ts b/packages/jgengine/src/pkg.ts index 2245551bb..7e2d75d10 100644 --- a/packages/jgengine/src/pkg.ts +++ b/packages/jgengine/src/pkg.ts @@ -7,7 +7,7 @@ interface PackageJson { name?: string; version?: string; type?: string; - workspaces?: string[]; + workspaces?: string[] | { packages: string[]; catalog?: Record; catalogs?: Record> }; scripts?: Record; dependencies?: Record; devDependencies?: Record; @@ -63,7 +63,8 @@ export function findUp(startDir: string, predicate: (dir: string) => boolean): s export function findWorkspaceRoot(startDir: string): string | null { return findUp(startDir, (dir) => { const pkg = readPackageJson(join(dir, "package.json")); - return Array.isArray(pkg?.workspaces); + const workspaces = pkg?.workspaces; + return Array.isArray(workspaces) ? true : Array.isArray(workspaces?.packages); }); } diff --git a/scripts/agent-preflight.ts b/scripts/agent-preflight.ts index a6304f766..575ea420b 100644 --- a/scripts/agent-preflight.ts +++ b/scripts/agent-preflight.ts @@ -36,9 +36,16 @@ requirePath("node_modules", "run bun install before generators or gates"); requirePath("node_modules/ts-morph", "dependencies are incomplete; finish bun install before continuing"); requirePath("node_modules/@typescript/native-preview", "dependencies are incomplete; finish bun install before continuing"); +function workspacePatterns(): string[] { + const workspaces = JSON.parse(readFileSync(join(root, "package.json"), "utf8")).workspaces as + | string[] + | { packages: string[] }; + return Array.isArray(workspaces) ? workspaces : workspaces.packages; +} + function workspaceManifests(): string[] { const manifests = ["package.json"]; - const patterns = JSON.parse(readFileSync(join(root, "package.json"), "utf8")).workspaces as string[]; + const patterns = workspacePatterns(); for (const pattern of patterns) { if (pattern.endsWith("/*")) { const base = pattern.slice(0, -2); diff --git a/scripts/ensure-ready.ts b/scripts/ensure-ready.ts index 8f1cbab97..77d04d4ef 100644 --- a/scripts/ensure-ready.ts +++ b/scripts/ensure-ready.ts @@ -22,8 +22,15 @@ if (!existsSync(join(process.cwd(), "node_modules", ".bin", "tsgo"))) { run("node_modules incomplete (tsgo missing) — running bun install", ["bun", "install"], 300_000); } +function workspacePatterns(): string[] { + const workspaces = JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf8")).workspaces as + | string[] + | { packages: string[] }; + return Array.isArray(workspaces) ? workspaces : workspaces.packages; +} + function workspacePackages(): Map { - const patterns = JSON.parse(readFileSync(join(process.cwd(), "package.json"), "utf8")).workspaces as string[]; + const patterns = workspacePatterns(); const dirs: string[] = []; for (const pattern of patterns) { if (pattern.endsWith("/*")) {