diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..d70c927b --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,47 @@ +{ + "permissions": { + "allow": [ + "Bash(git add:*)", + "Bash(git commit:*)", + "Bash(git worktree:*)" + ] + }, + "hooks": { + "PostToolUse": [ + { + "matcher": "Edit", + "hooks": [ + { + "type": "command", + "command": "bun run typecheck 2>&1 | head -30" + }, + { + "type": "command", + "command": "bun run lint:fix 2>&1 | head -30" + }, + { + "type": "command", + "command": "bun run knip:fix 2>&1 | head -50" + } + ] + }, + { + "matcher": "Write", + "hooks": [ + { + "type": "command", + "command": "bun run typecheck 2>&1 | head -30" + }, + { + "type": "command", + "command": "bun run lint:fix 2>&1 | head -30" + }, + { + "type": "command", + "command": "bun run knip:fix 2>&1 | head -50" + } + ] + } + ] + } +} diff --git a/.github/workflows/knip.yml b/.github/workflows/knip.yml new file mode 100644 index 00000000..fe38eb06 --- /dev/null +++ b/.github/workflows/knip.yml @@ -0,0 +1,26 @@ +name: Knip + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + knip: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Run Knip + run: bun run knip diff --git a/.gitignore b/.gitignore index 82e41184..fdc480a7 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,4 @@ coverage/ *.seed *.pid.lock +.worktrees diff --git a/bun.lock b/bun.lock index 2cb0a852..3ef1e5d2 100644 --- a/bun.lock +++ b/bun.lock @@ -1,6 +1,5 @@ { "lockfileVersion": 1, - "configVersion": 1, "workspaces": { "": { "name": "base44", @@ -15,7 +14,6 @@ "@types/json-schema": "^7.0.15", "@types/lodash.kebabcase": "^4.1.9", "@types/node": "^22.10.5", - "@types/tar": "^6.1.13", "@vercel/detect-agent": "^1.1.0", "chalk": "^5.6.2", "commander": "^12.1.0", @@ -30,9 +28,10 @@ "http-proxy-middleware": "^3.0.5", "json-schema-to-typescript": "^15.0.4", "json5": "^2.2.3", + "knip": "^5.83.1", "ky": "^1.14.2", "lodash.kebabcase": "^4.1.1", - "msw": "^2.12.7", + "msw": "^2.12.10", "nanoid": "^5.1.6", "open": "^11.0.0", "p-wait-for": "^6.0.0", @@ -71,6 +70,12 @@ "@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="], + "@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], @@ -141,6 +146,8 @@ "@mswjs/interceptors": ["@mswjs/interceptors@0.41.2", "", { "dependencies": { "@open-draft/deferred-promise": "^2.2.0", "@open-draft/logger": "^0.3.0", "@open-draft/until": "^2.0.0", "is-node-process": "^1.2.0", "outvariant": "^1.4.3", "strict-event-emitter": "^0.5.1" } }, "sha512-7G0Uf0yK3f2bjElBLGHIQzgRgMESczOMyYVasq1XK8P5HaXtlW4eQhz9MBL+TQILZLaruq+ClGId+hH0w4jvWw=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], @@ -153,6 +160,46 @@ "@open-draft/until": ["@open-draft/until@2.1.0", "", {}, "sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg=="], + "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.17.1", "", { "os": "android", "cpu": "arm" }, "sha512-+VuZyMYYaap5uDAU1xDU3Kul0FekLqpBS8kI5JozlWfYQKnc/HsZg2gHPkQrj0SC9lt74WMNCfOzZZJlYXSdEQ=="], + + "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.17.1", "", { "os": "android", "cpu": "arm64" }, "sha512-YlDDTjvOEKhom/cRSVsXsMVeXVIAM9PJ/x2mfe08rfuS0iIEfJd8PngKbEIhG72WPxleUa+vkEZj9ncmC14z3Q=="], + + "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.17.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-HOYYLSY4JDk14YkXaz/ApgJYhgDP4KsG8EZpgpOxdszGW9HmIMMY/vXqVKYW74dSH+GQkIXYxBrEh3nv+XODVg=="], + + "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.17.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-JHPJbsa5HvPq2/RIdtGlqfaG9zV2WmgvHrKTYmlW0L5esqtKCBuetFudXTBzkNcyD69kSZLzH92AzTr6vFHMFg=="], + + "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.17.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-UD1FRC8j8xZstFXYsXwQkNmmg7vUbee006IqxokwDUUA+xEgKZDpLhBEiVKM08Urb+bn7Q0gn6M1pyNR0ng5mg=="], + + "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.17.1", "", { "os": "linux", "cpu": "arm" }, "sha512-wFWC1wyf2ROFWTxK5x0Enm++DSof3EBQ/ypyAesMDLiYxOOASDoMOZG1ylWUnlKaCt5W7eNOWOzABpdfFf/ssA=="], + + "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.17.1", "", { "os": "linux", "cpu": "arm" }, "sha512-k/hUif0GEBk/csSqCfTPXb8AAVs1NNWCa/skBghvNbTtORcWfOVqJ3mM+2pE189+enRm4UnryLREu5ysI0kXEQ=="], + + "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.17.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Cwm6A071ww60QouJ9LoHAwBgEoZzHQ0Qaqk2E7WLfBdiQN9mLXIDhnrpn04hlRElRPhLiu/dtg+o5PPLvaINXQ=="], + + "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.17.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-+hwlE2v3m0r3sk93SchJL1uyaKcPjf+NGO/TD2DZUDo+chXx7FfaEj0nUMewigSt7oZ2sQN9Z4NJOtUa75HE5Q=="], + + "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.17.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-bO+rsaE5Ox8cFyeL5Ct5tzot1TnQpFa/Wmu5k+hqBYSH2dNVDGoi0NizBN5QV8kOIC6O5MZr81UG4yW/2FyDTA=="], + + "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.17.1", "", { "os": "linux", "cpu": "none" }, "sha512-B/P+hxKQ1oX4YstI9Lyh4PGzqB87Ddqj/A4iyRBbPdXTcxa+WW3oRLx1CsJKLmHPdDk461Hmbghq1Bm3pl+8Aw=="], + + "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.17.1", "", { "os": "linux", "cpu": "none" }, "sha512-ulp2H3bFXzd/th2maH+QNKj5qgOhJ3v9Yspdf1svTw3CDOuuTl6sRKsWQ7MUw0vnkSNvQndtflBwVXgzZvURsQ=="], + + "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.17.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-LAXYVe3rKk09Zo9YKF2ZLBcH8sz8Oj+JIyiUxiHtq0hiYLMsN6dOpCf2hzQEjPAmsSEA/hdC1PVKeXo+oma8mQ=="], + + "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.17.1", "", { "os": "linux", "cpu": "x64" }, "sha512-3RAhxipMKE8RCSPn7O//sj440i+cYTgYbapLeOoDvQEt6R1QcJjTsFgI4iz99FhVj3YbPxlZmcLB5VW+ipyRTA=="], + + "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.17.1", "", { "os": "linux", "cpu": "x64" }, "sha512-wpjMEubGU8r9VjZTLdZR3aPHaBqTl8Jl8F4DBbgNoZ+yhkhQD1/MGvY70v2TLnAI6kAHSvcqgfvaqKDa2iWsPQ=="], + + "@oxc-resolver/binding-openharmony-arm64": ["@oxc-resolver/binding-openharmony-arm64@11.17.1", "", { "os": "none", "cpu": "arm64" }, "sha512-XIE4w17RYAVIgx+9Gs3deTREq5tsmalbatYOOBGNdH7n0DfTE600c7wYXsp7ANc3BPDXsInnOzXDEPCvO1F6cg=="], + + "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.17.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-Lqi5BlHX3zS4bpSOkIbOKVf7DIk6Gvmdifr2OuOI58eUUyP944M8/OyaB09cNpPy9Vukj7nmmhOzj8pwLgAkIg=="], + + "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.17.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-l6lTcLBQVj1HNquFpXSsrkCIM8X5Hlng5YNQJrg00z/KyovvDV5l3OFhoRyZ+aLBQ74zUnMRaJZC7xcBnHyeNg=="], + + "@oxc-resolver/binding-win32-ia32-msvc": ["@oxc-resolver/binding-win32-ia32-msvc@11.17.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-VTzVtfnCCsU/6GgvursWoyZrhe3Gj/RyXzDWmh4/U1Y3IW0u1FZbp+hCIlBL16pRPbDc5YvXVtCOnA41QOrOoQ=="], + + "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.17.1", "", { "os": "win32", "cpu": "x64" }, "sha512-jRPVU+6/12baj87q2+UGRh30FBVBzqKdJ7rP/mSqiL1kpNQB9yZ1j0+m3sru1m+C8hiFK7lBFwjUtYUBI7+UpQ=="], + "@posthog/core": ["@posthog/core@1.10.0", "", { "dependencies": { "cross-spawn": "^7.0.6" } }, "sha512-Xk3JQ+cdychsvftrV3G9ZrN9W329lbyFW0pGJXFGKFQf8qr4upw2SgNg9BVorjSrfhoXZRnJGt/uNF4nGFBL5A=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.57.1", "", { "os": "android", "cpu": "arm" }, "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg=="], @@ -211,6 +258,8 @@ "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + "@types/body-parser": ["@types/body-parser@1.19.6", "", { "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g=="], "@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="], @@ -255,8 +304,6 @@ "@types/statuses": ["@types/statuses@2.0.6", "", {}, "sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA=="], - "@types/tar": ["@types/tar@6.1.13", "", { "dependencies": { "@types/node": "*", "minipass": "^4.0.0" } }, "sha512-IznnlmU5f4WcGTh2ltRu/Ijpmk8wiWXfF0VA4s+HPjHZgvFggk1YaIkbo5krX/zUCzWF8N/l4+W/LNxnvAJ8nw=="], - "@vercel/detect-agent": ["@vercel/detect-agent@1.1.0", "", {}, "sha512-Zfq6FbIcYl9gaAmVu6ROsqUiCNwpEj3Ljz/tMX5fl12Z95OFOxzf7vlO03WE5JBU/ri1tBDFHnW41dihMINOPQ=="], "@vitest/expect": ["@vitest/expect@4.0.18", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" } }, "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ=="], @@ -385,6 +432,8 @@ "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="], @@ -397,6 +446,8 @@ "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], + "formatly": ["formatly@0.3.0", "", { "dependencies": { "fd-package-json": "^2.0.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w=="], + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], @@ -481,12 +532,16 @@ "jake": ["jake@10.9.4", "", { "dependencies": { "async": "^3.2.6", "filelist": "^1.0.4", "picocolors": "^1.1.1" }, "bin": { "jake": "bin/cli.js" } }, "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA=="], + "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + "js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], "json-schema-to-typescript": ["json-schema-to-typescript@15.0.4", "", { "dependencies": { "@apidevtools/json-schema-ref-parser": "^11.5.5", "@types/json-schema": "^7.0.15", "@types/lodash": "^4.17.7", "is-glob": "^4.0.3", "js-yaml": "^4.1.0", "lodash": "^4.17.21", "minimist": "^1.2.8", "prettier": "^3.2.5", "tinyglobby": "^0.2.9" }, "bin": { "json2ts": "dist/src/cli.js" } }, "sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ=="], "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + "knip": ["knip@5.83.1", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "jiti": "^2.6.0", "js-yaml": "^4.1.1", "minimist": "^1.2.8", "oxc-resolver": "^11.15.0", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.5.2", "strip-json-comments": "5.0.3", "zod": "^4.1.11" }, "peerDependencies": { "@types/node": ">=18", "typescript": ">=5.0.4 <7" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-av3ZG/Nui6S/BNL8Tmj12yGxYfTnwWnslouW97m40him7o8MwiMjZBY9TPvlEWUci45aVId0/HbgTwSKIDGpMw=="], + "ky": ["ky@1.14.3", "", {}, "sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw=="], "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], @@ -513,7 +568,7 @@ "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - "minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="], + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="], @@ -543,6 +598,8 @@ "outvariant": ["outvariant@1.4.3", "", {}, "sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA=="], + "oxc-resolver": ["oxc-resolver@11.17.1", "", { "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.17.1", "@oxc-resolver/binding-android-arm64": "11.17.1", "@oxc-resolver/binding-darwin-arm64": "11.17.1", "@oxc-resolver/binding-darwin-x64": "11.17.1", "@oxc-resolver/binding-freebsd-x64": "11.17.1", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.17.1", "@oxc-resolver/binding-linux-arm-musleabihf": "11.17.1", "@oxc-resolver/binding-linux-arm64-gnu": "11.17.1", "@oxc-resolver/binding-linux-arm64-musl": "11.17.1", "@oxc-resolver/binding-linux-ppc64-gnu": "11.17.1", "@oxc-resolver/binding-linux-riscv64-gnu": "11.17.1", "@oxc-resolver/binding-linux-riscv64-musl": "11.17.1", "@oxc-resolver/binding-linux-s390x-gnu": "11.17.1", "@oxc-resolver/binding-linux-x64-gnu": "11.17.1", "@oxc-resolver/binding-linux-x64-musl": "11.17.1", "@oxc-resolver/binding-openharmony-arm64": "11.17.1", "@oxc-resolver/binding-wasm32-wasi": "11.17.1", "@oxc-resolver/binding-win32-arm64-msvc": "11.17.1", "@oxc-resolver/binding-win32-ia32-msvc": "11.17.1", "@oxc-resolver/binding-win32-x64-msvc": "11.17.1" } }, "sha512-pyRXK9kH81zKlirHufkFhOFBZRks8iAMLwPH8gU7lvKFiuzUH9L8MxDEllazwOb8fjXMcWjY1PMDfMJ2/yh5cw=="], + "p-wait-for": ["p-wait-for@6.0.0", "", {}, "sha512-2kKzMtjS8TVcpCOU/gr3vZ4K/WIyS1AsEFXFWapM/0lERCdyTbB6ZeuCIp+cL1aeLZfQoMdZFCBTHiK4I9UtOw=="], "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], @@ -623,6 +680,8 @@ "slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="], + "smol-toml": ["smol-toml@1.6.0", "", {}, "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw=="], + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], @@ -641,6 +700,8 @@ "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], + "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="], + "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="], "tar": ["tar@7.5.7", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ=="], @@ -667,6 +728,8 @@ "tough-cookie": ["tough-cookie@6.0.0", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "type-fest": ["type-fest@5.4.4", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw=="], "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], @@ -687,6 +750,8 @@ "vitest": ["vitest@4.0.18", "", { "dependencies": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", "@vitest/pretty-format": "4.0.18", "@vitest/runner": "4.0.18", "@vitest/snapshot": "4.0.18", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.18", "@vitest/browser-preview": "4.0.18", "@vitest/browser-webdriverio": "4.0.18", "@vitest/ui": "4.0.18", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ=="], + "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="], + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], @@ -713,17 +778,15 @@ "@apidevtools/json-schema-ref-parser/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - "@isaacs/fs-minipass/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], - "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "json-schema-to-typescript/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "knip/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - "minizlib/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "msw/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], @@ -737,8 +800,6 @@ "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "tar/minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], - "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "@apidevtools/json-schema-ref-parser/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], @@ -747,6 +808,8 @@ "json-schema-to-typescript/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "knip/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], diff --git a/knip.json b/knip.json new file mode 100644 index 00000000..e0e4fa5b --- /dev/null +++ b/knip.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://unpkg.com/knip@5/schema.json", + "entry": ["src/cli/index.ts", "tests/**/testkit/index.ts"], + "project": ["src/**/*.ts", "tests/**/*.ts"], + "ignore": ["dist/**", "tests/fixtures/**"] +} diff --git a/package.json b/package.json index d06f60fe..88e72508 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,9 @@ "lint": "biome check src tests", "lint:fix": "biome check --write src tests", "test": "vitest run", - "test:watch": "vitest" + "test:watch": "vitest", + "knip": "knip", + "knip:fix": "knip --fix" }, "keywords": [ "base44", @@ -44,7 +46,6 @@ "@types/json-schema": "^7.0.15", "@types/lodash.kebabcase": "^4.1.9", "@types/node": "^22.10.5", - "@types/tar": "^6.1.13", "@vercel/detect-agent": "^1.1.0", "chalk": "^5.6.2", "commander": "^12.1.0", @@ -59,9 +60,10 @@ "http-proxy-middleware": "^3.0.5", "json-schema-to-typescript": "^15.0.4", "json5": "^2.2.3", + "knip": "^5.83.1", "ky": "^1.14.2", "lodash.kebabcase": "^4.1.1", - "msw": "^2.12.7", + "msw": "^2.12.10", "nanoid": "^5.1.6", "open": "^11.0.0", "p-wait-for": "^6.0.0", diff --git a/src/cli/telemetry/consts.ts b/src/cli/telemetry/consts.ts index 4f4d21ec..51264626 100644 --- a/src/cli/telemetry/consts.ts +++ b/src/cli/telemetry/consts.ts @@ -2,4 +2,3 @@ export const POSTHOG_API_KEY = "phc_VsHW5HxTzpORanESQh9A08tmZLQkKbtIBTYoQvRpPOp"; export const TELEMETRY_DISABLED_ENV_VAR = "BASE44_DISABLE_TELEMETRY"; export const POSTHOG_REQUEST_TIMEOUT_MS = 1000; -export const POSTHOG_SHUTDOWN_TIMEOUT_MS = 1000; diff --git a/src/cli/telemetry/index.ts b/src/cli/telemetry/index.ts index b518bd11..2200c7f9 100644 --- a/src/cli/telemetry/index.ts +++ b/src/cli/telemetry/index.ts @@ -1,8 +1 @@ export { addCommandInfoToErrorReporter } from "./commander-hooks.js"; -export type { ErrorContext } from "./error-reporter.js"; -export { ErrorReporter } from "./error-reporter.js"; -export { - getPostHogClient, - isTelemetryEnabled, - shutdownPostHog, -} from "./posthog.js"; diff --git a/src/cli/telemetry/posthog.ts b/src/cli/telemetry/posthog.ts index ecd46c11..196da031 100644 --- a/src/cli/telemetry/posthog.ts +++ b/src/cli/telemetry/posthog.ts @@ -2,7 +2,6 @@ import { PostHog } from "posthog-node"; import { POSTHOG_API_KEY, POSTHOG_REQUEST_TIMEOUT_MS, - POSTHOG_SHUTDOWN_TIMEOUT_MS, TELEMETRY_DISABLED_ENV_VAR, } from "./consts.js"; @@ -43,18 +42,3 @@ export function getPostHogClient(): PostHog | null { return client; } - -export async function shutdownPostHog(): Promise { - if (!client) { - return; - } - - const clientToShutdown = client; - client = null; // Prevent further use - - try { - await clientToShutdown.shutdown(POSTHOG_SHUTDOWN_TIMEOUT_MS); - } catch { - // Silent - don't let shutdown errors block CLI exit - } -} diff --git a/src/cli/utils/runCommand.ts b/src/cli/utils/runCommand.ts index d5184db7..613d4226 100644 --- a/src/cli/utils/runCommand.ts +++ b/src/cli/utils/runCommand.ts @@ -8,7 +8,7 @@ import { isLoggedIn, readAuth } from "@/core/auth/index.js"; import { isCLIError } from "@/core/errors.js"; import { initAppConfig } from "@/core/project/index.js"; -export interface RunCommandOptions { +interface RunCommandOptions { /** * Use the full ASCII art banner instead of the simple intro tag. * Useful for commands like `create` that want more visual impact. diff --git a/src/core/auth/config.ts b/src/core/auth/config.ts index c4068900..fa1e3b6f 100644 --- a/src/core/auth/config.ts +++ b/src/core/auth/config.ts @@ -2,11 +2,7 @@ import { renewAccessToken } from "@/core/auth/api.js"; import type { AuthData } from "@/core/auth/schema.js"; import { AuthDataSchema } from "@/core/auth/schema.js"; import { getAuthFilePath } from "@/core/config.js"; -import { - AuthRequiredError, - FileReadError, - SchemaValidationError, -} from "@/core/errors.js"; +import { FileReadError, SchemaValidationError } from "@/core/errors.js"; import { deleteFile, readJsonFile, writeJsonFile } from "@/core/utils/fs.js"; // Buffer time before expiration to trigger proactive refresh (60 seconds) @@ -143,20 +139,3 @@ export async function isLoggedIn(): Promise { return false; } } - -/** - * Ensures the user is logged in before proceeding. - * - * @throws {AuthRequiredError} If the user is not logged in. - * - * @example - * await requireAuth(); - * // Code here will only run if user is authenticated - */ -export async function requireAuth(): Promise { - if (!(await isLoggedIn())) { - throw new AuthRequiredError( - "Not logged in. Please run 'base44 login' first.", - ); - } -} diff --git a/src/core/auth/schema.ts b/src/core/auth/schema.ts index 70a613fc..93597665 100644 --- a/src/core/auth/schema.ts +++ b/src/core/auth/schema.ts @@ -60,8 +60,6 @@ export const OAuthErrorSchema = z.object({ error_description: z.string().optional(), }); -export type OAuthError = z.infer; - export const UserInfoSchema = z.object({ email: z.email(), name: z.string(), diff --git a/src/core/config.ts b/src/core/config.ts index 30f307a4..426252e2 100644 --- a/src/core/config.ts +++ b/src/core/config.ts @@ -15,7 +15,7 @@ import { // Templates are copied to dist/templates/ const __dirname = dirname(fileURLToPath(import.meta.url)); -export function getBase44GlobalDir(): string { +function getBase44GlobalDir(): string { return join(homedir(), ".base44"); } diff --git a/src/core/errors.ts b/src/core/errors.ts index d5a15830..11b449c5 100644 --- a/src/core/errors.ts +++ b/src/core/errors.ts @@ -59,7 +59,7 @@ export interface ErrorHint { command?: string; // Optional command to run } -export interface CLIErrorOptions { +interface CLIErrorOptions { hints?: ErrorHint[]; cause?: Error; } @@ -72,7 +72,7 @@ export interface CLIErrorOptions { * Base class for all CLI errors. * Provides structured error data with code, hints, and cause tracking. */ -export abstract class CLIError extends Error { +abstract class CLIError extends Error { abstract readonly code: string; readonly hints: ErrorHint[]; override readonly cause?: Error; @@ -92,13 +92,13 @@ export abstract class CLIError extends Error { * User errors - the user did something wrong that they can fix. * Examples: not logged in, invalid config, missing project */ -export abstract class UserError extends CLIError {} +abstract class UserError extends CLIError {} /** * System errors - something broke that needs investigation. * Examples: API failures, network issues, file system errors */ -export abstract class SystemError extends CLIError {} +abstract class SystemError extends CLIError {} // ============================================================================ // User Errors @@ -248,7 +248,7 @@ export class InvalidInputError extends UserError { // System Errors // ============================================================================ -export interface ApiErrorOptions extends CLIErrorOptions { +interface ApiErrorOptions extends CLIErrorOptions { statusCode?: number; requestUrl?: string; requestMethod?: string; diff --git a/src/core/project/app-config.ts b/src/core/project/app-config.ts index 9a9e8006..ead6ef61 100644 --- a/src/core/project/app-config.ts +++ b/src/core/project/app-config.ts @@ -11,7 +11,7 @@ import type { AppConfig } from "@/core/project/schema.js"; import { AppConfigSchema } from "@/core/project/schema.js"; import { readJsonFile, writeFile } from "@/core/utils/fs.js"; -export interface CachedAppConfig { +interface CachedAppConfig { id: string; projectRoot: string; } @@ -89,7 +89,7 @@ export function setAppConfig(config: CachedAppConfig): void { cache = config; } -export function generateAppConfigContent(id: string): string { +function generateAppConfigContent(id: string): string { return `// Base44 App Configuration // This file links your local project to your Base44 app. // Do not commit this file to version control. @@ -109,9 +109,7 @@ export async function writeAppConfig( return configPath; } -export async function findAppConfigPath( - projectRoot: string, -): Promise { +async function findAppConfigPath(projectRoot: string): Promise { const files = await globby(APP_CONFIG_PATTERN, { cwd: projectRoot, absolute: true, diff --git a/src/core/project/create.ts b/src/core/project/create.ts index 59928a40..07acba05 100644 --- a/src/core/project/create.ts +++ b/src/core/project/create.ts @@ -5,14 +5,14 @@ import { createProject, downloadProject } from "@/core/project/api.js"; import type { Template } from "@/core/project/schema.js"; import { renderTemplate } from "@/core/project/template.js"; -export interface CreateProjectOptions { +interface CreateProjectOptions { name: string; description?: string; path: string; template: Template; } -export interface CreateProjectResult { +interface CreateProjectResult { projectId: string; projectDir: string; } diff --git a/src/core/project/deploy.ts b/src/core/project/deploy.ts index 71b5a499..2c925de4 100644 --- a/src/core/project/deploy.ts +++ b/src/core/project/deploy.ts @@ -24,7 +24,7 @@ export function hasResourcesToDeploy(projectData: ProjectData): boolean { /** * Result of deploying all project resources. */ -export interface DeployAllResult { +interface DeployAllResult { /** * The app URL if a site was deployed, undefined otherwise. */ diff --git a/src/core/project/schema.ts b/src/core/project/schema.ts index 4e8d6fe1..78ff677c 100644 --- a/src/core/project/schema.ts +++ b/src/core/project/schema.ts @@ -12,8 +12,6 @@ export const TemplatesConfigSchema = z.object({ }); export type Template = z.infer; -export type TemplatesConfig = z.infer; - const SiteConfigSchema = z.object({ buildCommand: z.string().optional(), serveCommand: z.string().optional(), @@ -34,7 +32,6 @@ export const ProjectConfigSchema = z.object({ agentsDir: z.string().optional().default("agents"), }); -export type SiteConfig = z.infer; export type ProjectConfig = z.infer; export const AppConfigSchema = z.object({ @@ -47,8 +44,6 @@ export const CreateProjectResponseSchema = z.looseObject({ id: z.string(), }); -export type CreateProjectResponse = z.infer; - export const ProjectSchema = z .object({ id: z.string(), diff --git a/src/core/project/template.ts b/src/core/project/template.ts index 668b4a6a..198d53fe 100644 --- a/src/core/project/template.ts +++ b/src/core/project/template.ts @@ -8,7 +8,7 @@ import type { Template } from "@/core/project/schema.js"; import { TemplatesConfigSchema } from "@/core/project/schema.js"; import { copyFile, readJsonFile, writeFile } from "@/core/utils/fs.js"; -export interface TemplateData { +interface TemplateData { name: string; description?: string; projectId: string; diff --git a/src/core/resources/agent/config.ts b/src/core/resources/agent/config.ts index ddc8889c..a6bd9c46 100644 --- a/src/core/resources/agent/config.ts +++ b/src/core/resources/agent/config.ts @@ -14,25 +14,6 @@ import { import type { AgentConfig, AgentConfigApiResponse } from "./schema.js"; import { AgentConfigSchema } from "./schema.js"; -export function generateAgentConfigContent(name: string): string { - return `// Base44 Agent Configuration -// Agent name must be lowercase alphanumeric with underscores only -{ - "name": "${name}", - // Brief description of what this agent does - "description": "", - // Detailed instructions for the agent's behavior - "instructions": "", - // Tool configurations - entity tools and backend function tools - // Entity tool example: { "entity_name": "tasks", "allowed_operations": ["read", "create"] } - // Function tool example: { "function_name": "send_email", "description": "Send an email" } - "tool_configs": [], - // Optional WhatsApp greeting message - "whatsapp_greeting": null -} -`; -} - async function readAgentFile(agentPath: string): Promise { const parsed = await readJsonFile(agentPath); const result = AgentConfigSchema.safeParse(parsed); diff --git a/src/core/resources/function/config.ts b/src/core/resources/function/config.ts index a2ca7390..87277eed 100644 --- a/src/core/resources/function/config.ts +++ b/src/core/resources/function/config.ts @@ -9,9 +9,7 @@ import type { import { FunctionConfigSchema } from "@/core/resources/function/schema.js"; import { pathExists, readJsonFile } from "@/core/utils/fs.js"; -export async function readFunctionConfig( - configPath: string, -): Promise { +async function readFunctionConfig(configPath: string): Promise { const parsed = await readJsonFile(configPath); const result = FunctionConfigSchema.safeParse(parsed); @@ -26,9 +24,7 @@ export async function readFunctionConfig( return result.data; } -export async function readFunction( - configPath: string, -): Promise { +async function readFunction(configPath: string): Promise { const config = await readFunctionConfig(configPath); const functionDir = dirname(configPath); const entryPath = join(functionDir, config.entry); diff --git a/src/core/resources/index.ts b/src/core/resources/index.ts index 191bbdb9..d33c4d30 100644 --- a/src/core/resources/index.ts +++ b/src/core/resources/index.ts @@ -1,4 +1,3 @@ export * from "./agent/index.js"; export * from "./entity/index.js"; export * from "./function/index.js"; -export type { Resource } from "./types.js"; diff --git a/src/core/types/generator.ts b/src/core/types/generator.ts index 280ba1d2..3ab2dce1 100644 --- a/src/core/types/generator.ts +++ b/src/core/types/generator.ts @@ -9,7 +9,7 @@ import type { Entity } from "@/core/resources/entity/index.js"; import type { BackendFunction } from "@/core/resources/function/index.js"; import { writeFile } from "@/core/utils/fs.js"; -export interface GenerateTypesInput { +interface GenerateTypesInput { entities: Entity[]; functions: BackendFunction[]; agents: AgentConfig[]; diff --git a/src/core/types/index.ts b/src/core/types/index.ts index bb5182be..0dc05825 100644 --- a/src/core/types/index.ts +++ b/src/core/types/index.ts @@ -1,2 +1,2 @@ -export { type GenerateTypesInput, generateTypesFile } from "./generator.js"; +export { generateTypesFile } from "./generator.js"; export { updateProjectConfig } from "./update-project.js"; diff --git a/tests/cli/testkit/Base44APIMock.ts b/tests/cli/testkit/Base44APIMock.ts index 86b0b123..cea6ba21 100644 --- a/tests/cli/testkit/Base44APIMock.ts +++ b/tests/cli/testkit/Base44APIMock.ts @@ -6,7 +6,7 @@ const BASE_URL = "https://app.base44.com"; // ─── RESPONSE TYPES ────────────────────────────────────────── -export interface DeviceCodeResponse { +interface DeviceCodeResponse { device_code: string; user_code: string; verification_uri: string; @@ -14,62 +14,62 @@ export interface DeviceCodeResponse { interval: number; } -export interface TokenResponse { +interface TokenResponse { access_token: string; refresh_token: string; expires_in: number; token_type: string; } -export interface UserInfoResponse { +interface UserInfoResponse { email: string; name?: string; } -export interface EntitiesPushResponse { +interface EntitiesPushResponse { created: string[]; updated: string[]; deleted: string[]; } -export interface FunctionsPushResponse { +interface FunctionsPushResponse { deployed: string[]; deleted: string[]; errors: Array<{ name: string; message: string }> | null; } -export interface SiteDeployResponse { +interface SiteDeployResponse { app_url: string; } -export interface SiteUrlResponse { +interface SiteUrlResponse { url: string; } -export interface AgentsPushResponse { +interface AgentsPushResponse { created: string[]; updated: string[]; deleted: string[]; } -export interface AgentsFetchResponse { +interface AgentsFetchResponse { items: Array<{ name: string; [key: string]: unknown }>; total: number; } -export interface CreateAppResponse { +interface CreateAppResponse { id: string; name: string; } -export interface ListProjectsResponse { +interface ListProjectsResponse { id: string; name: string; user_description?: string | null; is_managed_source_code?: boolean; } -export interface ErrorResponse { +interface ErrorResponse { status: number; body?: unknown; }