diff --git a/examples/misc/express/valibot/fetch.ts b/examples/misc/express/valibot/fetch.ts index db4fe7e1..5606ad7c 100644 --- a/examples/misc/express/valibot/fetch.ts +++ b/examples/misc/express/valibot/fetch.ts @@ -1,6 +1,6 @@ import type { PathMap } from "../../spec/valibot"; -import JSONT from "@notainc/typed-api-spec/json"; -import type FetchT from "@notainc/typed-api-spec/fetch"; +import type { JSONT } from "@notainc/typed-api-spec/json"; +import type { FetchT } from "@notainc/typed-api-spec/fetch"; const fetchT = fetch as FetchT; const origin = "http://localhost:3000"; diff --git a/examples/misc/express/zod/fetch.ts b/examples/misc/express/zod/fetch.ts index f15ab9cc..7a5e3355 100644 --- a/examples/misc/express/zod/fetch.ts +++ b/examples/misc/express/zod/fetch.ts @@ -1,6 +1,6 @@ import type { PathMap } from "../../spec/zod"; -import JSONT from "@notainc/typed-api-spec/json"; -import type FetchT from "@notainc/typed-api-spec/fetch"; +import type { JSONT } from "@notainc/typed-api-spec/json"; +import type { FetchT } from "@notainc/typed-api-spec/fetch"; const fetchT = fetch as FetchT; const origin = "http://localhost:3000"; diff --git a/examples/misc/fastify/zod/fetch.ts b/examples/misc/fastify/zod/fetch.ts index d1f1b208..6fd885fa 100644 --- a/examples/misc/fastify/zod/fetch.ts +++ b/examples/misc/fastify/zod/fetch.ts @@ -1,5 +1,5 @@ -import JSONT from "@notainc/typed-api-spec/json"; -import type FetchT from "@notainc/typed-api-spec/fetch"; +import type { JSONT } from "@notainc/typed-api-spec/json"; +import type { FetchT } from "@notainc/typed-api-spec/fetch"; import { PathMap } from "../../spec/zod"; const fetchT = fetch as FetchT; diff --git a/package-lock.json b/package-lock.json index e53c4710..e8aea98d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -540,6 +540,13 @@ "node": ">=6.0.0" } }, + "node_modules/@andrewbranch/untar.js": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@andrewbranch/untar.js/-/untar.js-1.0.4.tgz", + "integrity": "sha512-pVXSwPsLuw8IGLo2Di0EaOfsk+ntVvpkk942J/sHYIkwvtKUakEcPh7HBgZ6tuimgzKSEHgCvO4XgQ05DEbwDw==", + "dev": true, + "license": "MIT" + }, "node_modules/@apidevtools/json-schema-ref-parser": { "version": "11.7.3", "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.3.tgz", @@ -557,6 +564,82 @@ "url": "https://github.com/sponsors/philsturgeon" } }, + "node_modules/@arethetypeswrong/cli": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/@arethetypeswrong/cli/-/cli-0.18.5.tgz", + "integrity": "sha512-gM+8vRsQOD/Uc7EnBedUhkG5OCsDWE4uoak5QvomGpMpaky0Eh41p04nIMgrWb8EOmqZUJGc6zz9hsP6E56R7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@arethetypeswrong/core": "0.18.5", + "chalk": "^4.1.2", + "cli-table3": "^0.6.3", + "commander": "^10.0.1", + "marked": "^9.1.2", + "marked-terminal": "^7.1.0", + "semver": "^7.5.4" + }, + "bin": { + "attw": "dist/index.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@arethetypeswrong/cli/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@arethetypeswrong/core": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/@arethetypeswrong/core/-/core-0.18.5.tgz", + "integrity": "sha512-9ytjzGwxjm9Uz7I9avfbt5vlQt6uk9uRRESzJjqrznl6WKvI6dwYTo+vJ3U02Wrq/mR3iql/PzhvHhKdJIAjDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@andrewbranch/untar.js": "^1.0.3", + "@loaderkit/resolve": "^1.0.2", + "cjs-module-lexer": "^1.2.3", + "fflate": "^0.8.3", + "lru-cache": "^11.0.1", + "semver": "^7.5.4", + "typescript": "5.6.1-rc", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@arethetypeswrong/core/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@arethetypeswrong/core/node_modules/typescript": { + "version": "5.6.1-rc", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.1-rc.tgz", + "integrity": "sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -2297,6 +2380,13 @@ "node": ">=18" } }, + "node_modules/@braidai/lang": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@braidai/lang/-/lang-1.1.2.tgz", + "integrity": "sha512-qBcknbBufNHlui137Hft8xauQMTZDKdophmLFv05r2eNmdIv/MlPuP4TdUknHG68UdWLgVZwgxVe735HzJNIwA==", + "dev": true, + "license": "ISC" + }, "node_modules/@bundled-es-modules/cookie": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz", @@ -5933,6 +6023,16 @@ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "license": "MIT" }, + "node_modules/@loaderkit/resolve": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@loaderkit/resolve/-/resolve-1.0.6.tgz", + "integrity": "sha512-G8FdIoF5CypfwmD9rl8BXod5HDn8JqB0CCNBXDTaRZ+yRYhARrrSToX1zg1zy9jX3zLqigsELwhT4gNtkdQAUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "@braidai/lang": "^1.0.0" + } + }, "node_modules/@mdx-js/mdx": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", @@ -10677,6 +10777,13 @@ "node": ">=8" } }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, "node_modules/classnames": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", @@ -10725,6 +10832,133 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dev": true, + "license": "ISC", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-highlight/node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-highlight/node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/cli-highlight/node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-highlight/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.2.tgz", + "integrity": "sha512-Nt9ZJjXTv5R8MHbqby/wXQ6Gi0Bb3TcYZkR1bzuL4yB2OxWPkXknz513gEF0GoA6tn00UpbPvERW8rzCuWCA6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/cli-table3": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", @@ -12298,6 +12532,19 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -13465,6 +13712,13 @@ "node": ">=0.4.0" } }, + "node_modules/fflate": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "dev": true, + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -16109,6 +16363,83 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/marked": { + "version": "9.1.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz", + "integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/marked-terminal": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.3.0.tgz", + "integrity": "sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "ansi-regex": "^6.1.0", + "chalk": "^5.4.1", + "cli-highlight": "^2.1.11", + "cli-table3": "^0.6.5", + "node-emoji": "^2.2.0", + "supports-hyperlinks": "^3.1.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "marked": ">=1 <16" + } + }, + "node_modules/marked-terminal/node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked-terminal/node_modules/ansi-regex": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.3.0.tgz", + "integrity": "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -24272,6 +24603,23 @@ "node": ">=8" } }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -26079,6 +26427,16 @@ } } }, + "node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/value-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", @@ -27585,6 +27943,7 @@ "path-to-regexp": "^8.4.2" }, "devDependencies": { + "@arethetypeswrong/cli": "^0.18.5", "@eslint/js": "^9.39.5", "@types/path-to-regexp": "^1.7.0", "@types/qs": "^6.9.15", diff --git a/pkgs/typed-api-spec/eslint.config.js b/pkgs/typed-api-spec/eslint.config.js index 2476967b..1df54ed5 100644 --- a/pkgs/typed-api-spec/eslint.config.js +++ b/pkgs/typed-api-spec/eslint.config.js @@ -67,4 +67,13 @@ module.exports = tseslint.config( "@typescript-eslint/no-unused-expressions": "off", }, }, + { + files: ["scripts/**/*.mjs"], + languageOptions: { + globals: { + process: "readonly", + console: "readonly", + }, + }, + }, ); diff --git a/pkgs/typed-api-spec/package.json b/pkgs/typed-api-spec/package.json index 1f65b2d5..daf561d4 100644 --- a/pkgs/typed-api-spec/package.json +++ b/pkgs/typed-api-spec/package.json @@ -7,11 +7,13 @@ "watch:build": "tsup --watch", "format": "oxfmt .", "watch:type-check": "npx tsc --noEmit --watch", - "test": "run-p test:*", - "test:unit": "vitest", + "test": "run-p -c test:*", + "test:unit": "vitest run", "test:lint": "eslint .", "test:format": "oxfmt --check .", - "test:type-check": "tsc --noEmit" + "test:type-check": "tsc --noEmit", + "test:pack-smoke": "node scripts/pack-smoke.mjs", + "test:attw": "attw --pack --profile node16" }, "author": "mpppk", "license": "MIT", @@ -20,11 +22,12 @@ "url": "https://github.com/nota/typed-api-spec" }, "devDependencies": { + "@arethetypeswrong/cli": "^0.18.5", + "@eslint/js": "^9.39.5", "@types/path-to-regexp": "^1.7.0", "@types/qs": "^6.9.15", "@types/supertest": "^7.2.0", "@vitest/coverage-v8": "^4.1.11", - "@eslint/js": "^9.39.5", "dotenv-cli": "^7.2.1", "eslint": "^9.39.5", "eslint-plugin-strict-dependencies": "^1.3.35", @@ -83,39 +86,74 @@ ], "exports": { ".": { - "types": "./dist/index.d.ts", - "require": "./dist/index.js", - "import": "./dist/index.mjs" + "require": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + } }, "./core": { - "types": "./dist/core/index.d.ts", - "require": "./dist/core/index.js", - "import": "./dist/core/index.mjs" + "require": { + "types": "./dist/core/index.d.ts", + "default": "./dist/core/index.js" + }, + "import": { + "types": "./dist/core/index.d.mts", + "default": "./dist/core/index.mjs" + } }, "./express": { - "types": "./dist/express/index.d.ts", - "require": "./dist/express/index.js", - "import": "./dist/express/index.mjs" + "require": { + "types": "./dist/express/index.d.ts", + "default": "./dist/express/index.js" + }, + "import": { + "types": "./dist/express/index.d.mts", + "default": "./dist/express/index.mjs" + } }, "./fastify": { - "types": "./dist/fastify/index.d.ts", - "require": "./dist/fastify/index.js", - "import": "./dist/fastify/index.mjs" + "require": { + "types": "./dist/fastify/index.d.ts", + "default": "./dist/fastify/index.js" + }, + "import": { + "types": "./dist/fastify/index.d.mts", + "default": "./dist/fastify/index.mjs" + } }, "./fetch": { - "types": "./dist/fetch/index.d.ts", - "require": "./dist/fetch/index.js", - "import": "./dist/fetch/index.mjs" + "require": { + "types": "./dist/fetch/index.d.ts", + "default": "./dist/fetch/index.js" + }, + "import": { + "types": "./dist/fetch/index.d.mts", + "default": "./dist/fetch/index.mjs" + } }, "./json": { - "types": "./dist/json/index.d.ts", - "require": "./dist/json/index.js", - "import": "./dist/json/index.mjs" + "require": { + "types": "./dist/json/index.d.ts", + "default": "./dist/json/index.js" + }, + "import": { + "types": "./dist/json/index.d.mts", + "default": "./dist/json/index.mjs" + } }, "./msw": { - "types": "./dist/msw/index.d.ts", - "require": "./dist/msw/index.js", - "import": "./dist/msw/index.mjs" + "require": { + "types": "./dist/msw/index.d.ts", + "default": "./dist/msw/index.js" + }, + "import": { + "types": "./dist/msw/index.d.mts", + "default": "./dist/msw/index.mjs" + } } }, "main": "./dist/index.js", diff --git a/pkgs/typed-api-spec/scripts/pack-smoke.mjs b/pkgs/typed-api-spec/scripts/pack-smoke.mjs new file mode 100644 index 00000000..930dadf6 --- /dev/null +++ b/pkgs/typed-api-spec/scripts/pack-smoke.mjs @@ -0,0 +1,113 @@ +import { execSync } from "node:child_process"; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; + +const REQUIRED_PEERS = { + ".": [], + core: [], + fetch: [], + json: [], + express: ["express"], + fastify: [], + msw: ["msw"], +}; + +const ALL_OPTIONAL_PEERS = [ + "express", + "fastify", + "fastify-type-provider-zod", + "msw", + "valibot", + "zod", + "@valibot/to-json-schema", +]; + +const cacheDir = join(tmpdir(), "tas-pack-smoke-npm-cache"); +mkdirSync(cacheDir, { recursive: true }); +const cleanupDirs = []; + +function run(cmd, cwd) { + return execSync(cmd, { + cwd, + stdio: "pipe", + encoding: "utf8", + env: { ...process.env, npm_config_cache: cacheDir }, + }); +} + +function packTarball() { + const packDir = mkdtempSync(join(tmpdir(), "tas-pack-")); + cleanupDirs.push(packDir); + const json = run( + `npm pack --json --pack-destination "${packDir}"`, + process.cwd(), + ); + return join(packDir, JSON.parse(json)[0].filename); +} + +function makeFixture(tarball, extraPeers, { omitOptional }) { + const dir = mkdtempSync(join(tmpdir(), "tas-fixture-")); + cleanupDirs.push(dir); + run("npm init -y", dir); + const omitFlag = omitOptional ? "--omit=optional" : ""; + const peers = extraPeers.join(" "); + run( + `npm install --no-audit --no-fund ${omitFlag} ${peers} "${tarball}"`.trim(), + dir, + ); + return dir; +} + +function checkSubpath(dir, subpath, failures) { + const spec = + subpath === "." + ? "@notainc/typed-api-spec" + : `@notainc/typed-api-spec/${subpath}`; + writeFileSync(join(dir, "c.cjs"), `require(${JSON.stringify(spec)})`); + writeFileSync(join(dir, "e.mjs"), `await import(${JSON.stringify(spec)})`); + for (const file of ["c.cjs", "e.mjs"]) { + try { + run(`node ${file}`, dir); + } catch (e) { + failures.push(`[${subpath}] ${file} failed:\n${e.stdout}\n${e.stderr}`); + } + } +} + +function groupByPeers(peerMap) { + const groups = new Map(); + for (const [subpath, peers] of Object.entries(peerMap)) { + const key = [...peers].sort().join(","); + if (!groups.has(key)) groups.set(key, { peers, subpaths: [] }); + groups.get(key).subpaths.push(subpath); + } + return [...groups.values()]; +} + +const failures = []; + +try { + const tarball = packTarball(); + + for (const { peers, subpaths } of groupByPeers(REQUIRED_PEERS)) { + const dir = makeFixture(tarball, peers, { omitOptional: true }); + for (const subpath of subpaths) checkSubpath(dir, subpath, failures); + } + + const fullDir = makeFixture(tarball, ALL_OPTIONAL_PEERS, { + omitOptional: false, + }); + for (const subpath of Object.keys(REQUIRED_PEERS)) { + checkSubpath(fullDir, subpath, failures); + } +} finally { + for (const dir of cleanupDirs) rmSync(dir, { recursive: true, force: true }); +} + +if (failures.length > 0) { + console.error(failures.join("\n\n")); + process.exit(1); +} + +console.log("pack smoke: OK"); diff --git a/pkgs/typed-api-spec/src/express/index.ts b/pkgs/typed-api-spec/src/express/index.ts index bc5c4b2a..7f946f93 100644 --- a/pkgs/typed-api-spec/src/express/index.ts +++ b/pkgs/typed-api-spec/src/express/index.ts @@ -5,7 +5,7 @@ import { ApiResBody, ApiSpec, AnyApiEndpoints, -} from "../index"; +} from "../core"; import { NextFunction, ParamsDictionary, diff --git a/pkgs/typed-api-spec/src/fetch/index.t-test.ts b/pkgs/typed-api-spec/src/fetch/index.t-test.ts index e6e94a64..7bd26435 100644 --- a/pkgs/typed-api-spec/src/fetch/index.t-test.ts +++ b/pkgs/typed-api-spec/src/fetch/index.t-test.ts @@ -6,8 +6,8 @@ import { MissingQueryError, ToApiEndpoints, } from "../core"; -import FetchT, { ValidateUrl } from "./index"; -import JSONT, { JsonStringifyResult } from "../json"; +import type { FetchT, ValidateUrl } from "./index"; +import type { JSONT, JsonStringifyResult } from "../json"; import { Equal, Expect } from "../core/type-test"; import { C } from "../compile-error-utils"; import z from "zod"; diff --git a/pkgs/typed-api-spec/src/fetch/index.ts b/pkgs/typed-api-spec/src/fetch/index.ts index 31c3bea5..e2dc1a7b 100644 --- a/pkgs/typed-api-spec/src/fetch/index.ts +++ b/pkgs/typed-api-spec/src/fetch/index.ts @@ -242,7 +242,10 @@ type FetchInputType< * @template E - ApiEndpoints * E is used to infer the type of the acceptable path, response body, and more */ -type FetchT = < +export type FetchT< + UrlPrefix extends UrlPrefixPattern, + E extends ApiEndpoints, +> = < /** * Internal type for FetchT * They are not supposed to be specified by the user @@ -296,7 +299,5 @@ type FetchT = < ] ) => Promise; -export default FetchT; - export * from "./validation"; export * from "./new-fetch"; diff --git a/pkgs/typed-api-spec/src/fetch/new-fetch.ts b/pkgs/typed-api-spec/src/fetch/new-fetch.ts index 4a96cd1f..352596e8 100644 --- a/pkgs/typed-api-spec/src/fetch/new-fetch.ts +++ b/pkgs/typed-api-spec/src/fetch/new-fetch.ts @@ -1,4 +1,4 @@ -import type FetchT from "./index.js"; +import type { FetchT } from "./index.js"; import { ApiEndpointsSchema, ToApiEndpoints } from "../core/schema.js"; import { withValidation } from "./index.js"; diff --git a/pkgs/typed-api-spec/src/index.ts b/pkgs/typed-api-spec/src/index.ts index 3f547132..3f0e19a3 100644 --- a/pkgs/typed-api-spec/src/index.ts +++ b/pkgs/typed-api-spec/src/index.ts @@ -18,28 +18,13 @@ export { toRoutes as toFastifyRoutes, } from "./fastify"; -import FetchT, { RequestInitT } from "./fetch"; -export { FetchT, RequestInitT }; +export type { FetchT, RequestInitT } from "./fetch"; -import JSONT, { - JSON$stringifyT, - TypedString, - JsonStringifyResult, - Jsonify, - JsonifyObject, -} from "./json"; -export { +export type { JSONT, JSON$stringifyT, TypedString, JsonStringifyResult, Jsonify, JsonifyObject, -}; - -export { - newHttp as newMswHttp, - Http as MswHttp, - HttpRequestHandler as MswHttpRequestHandler, - HttpRequestResolverExtras as MswHttpRequestResolverExtras, -} from "./msw"; +} from "./json"; diff --git a/pkgs/typed-api-spec/src/json/index.ts b/pkgs/typed-api-spec/src/json/index.ts index e76aa00e..12d77e50 100644 --- a/pkgs/typed-api-spec/src/json/index.ts +++ b/pkgs/typed-api-spec/src/json/index.ts @@ -7,12 +7,10 @@ export type JSON$stringifyT = ( space?: number | string | undefined, ) => TypedString>; -type JSONT = Omit & { +export type JSONT = Omit & { stringify: JSON$stringifyT; }; -export default JSONT; - // JSONとして有効なプリミティブ型 + Date type JsonPrimitive = string | number | boolean | null | Date; diff --git a/pkgs/typed-api-spec/src/msw/http.test.ts b/pkgs/typed-api-spec/src/msw/http.test.ts index c657e0f8..8382cf1d 100644 --- a/pkgs/typed-api-spec/src/msw/http.test.ts +++ b/pkgs/typed-api-spec/src/msw/http.test.ts @@ -5,7 +5,7 @@ import { newHttp } from "./index"; import { z } from "zod"; import { ApiEndpointsSchema } from "../core"; import { newFetch } from "../fetch"; -import JSONT from "../json"; +import type { JSONT } from "../json"; const JSONT = JSON as JSONT;