From dc33874db47617abe016790c439f28df82391a03 Mon Sep 17 00:00:00 2001 From: Torbjorn van Heeswijck Date: Sat, 30 Aug 2025 17:49:29 +0930 Subject: [PATCH 1/5] Use yarn version 4.9.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b3e483..ff6c5f0 100644 --- a/package.json +++ b/package.json @@ -66,5 +66,5 @@ "node-fetch": "^3.3.2", "query-string": "^9.2.2" }, - "packageManager": "yarn@4.9.2" + "packageManager": "yarn@4.9.4" } From 04cfcc667cc639bae65f38d63c868244b9f99056 Mon Sep 17 00:00:00 2001 From: Torbjorn van Heeswijck Date: Sun, 31 Aug 2025 19:53:14 +0930 Subject: [PATCH 2/5] MI-255: Upgrade dependencies --- package.json | 9 +- yarn.lock | 379 +++++++++++++++++++++++++++------------------------ 2 files changed, 207 insertions(+), 181 deletions(-) diff --git a/package.json b/package.json index ff6c5f0..e765b00 100644 --- a/package.json +++ b/package.json @@ -50,15 +50,16 @@ "@aligent/ts-code-standards": "^4.0.2", "@types/node": "^22.16.5", "diff": "^8.0.2", - "eslint": "^9.31.0", - "openapi-typescript": "^7.8.0", + "eslint": "^9.34.0", + "openapi-typescript": "^7.9.1", "prettier": "^3.6.2", "rimraf": "^6.0.1", "simple-git": "^3.28.0", "ts-morph": "^26.0.0", - "tsd": "^0.32.0", + "tsd": "^0.33.0", "tshy": "^3.0.2", - "typescript": "^5.8.3", + "typescript": "^5.9.2", + "typescript-eslint": "^8.41.0", "uuid": "^11.1.0" }, "dependencies": { diff --git a/yarn.lock b/yarn.lock index 740bead..c5bccfe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,18 +12,19 @@ __metadata: "@aligent/ts-code-standards": "npm:^4.0.2" "@types/node": "npm:^22.16.5" diff: "npm:^8.0.2" - eslint: "npm:^9.31.0" + eslint: "npm:^9.34.0" form-data: "npm:^4.0.4" node-fetch: "npm:^3.3.2" - openapi-typescript: "npm:^7.8.0" + openapi-typescript: "npm:^7.9.1" prettier: "npm:^3.6.2" query-string: "npm:^9.2.2" rimraf: "npm:^6.0.1" simple-git: "npm:^3.28.0" ts-morph: "npm:^26.0.0" - tsd: "npm:^0.32.0" + tsd: "npm:^0.33.0" tshy: "npm:^3.0.2" - typescript: "npm:^5.8.3" + typescript: "npm:^5.9.2" + typescript-eslint: "npm:^8.41.0" uuid: "npm:^11.1.0" languageName: unknown linkType: soft @@ -94,14 +95,14 @@ __metadata: linkType: hard "@eslint/compat@npm:^1.3.1": - version: 1.3.1 - resolution: "@eslint/compat@npm:1.3.1" + version: 1.3.2 + resolution: "@eslint/compat@npm:1.3.2" peerDependencies: eslint: ^8.40 || 9 peerDependenciesMeta: eslint: optional: true - checksum: 10c0/8dfcea5ecb854111f9c0acc23a469e0a25cdaddceb5fb40c47988c247d6e32ec199bcd00f1b8ba9ed779228526552703c4b74948169e78b78b5fd814e04b042b + checksum: 10c0/9b95b49ee74c50adf8f0e45066b471bc76842c43d4721727ff93d186745bdd1679d18420c992a05eab3bb41762672cd3faa5c56c99325dbb97200f7533cbd2bf languageName: node linkType: hard @@ -116,19 +117,19 @@ __metadata: languageName: node linkType: hard -"@eslint/config-helpers@npm:^0.3.0": - version: 0.3.0 - resolution: "@eslint/config-helpers@npm:0.3.0" - checksum: 10c0/013ae7b189eeae8b30cc2ee87bc5c9c091a9cd615579003290eb28bebad5d78806a478e74ba10b3fe08ed66975b52af7d2cd4b4b43990376412b14e5664878c8 +"@eslint/config-helpers@npm:^0.3.1": + version: 0.3.1 + resolution: "@eslint/config-helpers@npm:0.3.1" + checksum: 10c0/f6c5b3a0b76a0d7d84cc93e310c259e6c3e0792ddd0a62c5fc0027796ffae44183432cb74b2c2b1162801ee1b1b34a6beb5d90a151632b4df7349f994146a856 languageName: node linkType: hard -"@eslint/core@npm:^0.15.0, @eslint/core@npm:^0.15.1": - version: 0.15.1 - resolution: "@eslint/core@npm:0.15.1" +"@eslint/core@npm:^0.15.2": + version: 0.15.2 + resolution: "@eslint/core@npm:0.15.2" dependencies: "@types/json-schema": "npm:^7.0.15" - checksum: 10c0/abaf641940776638b8c15a38d99ce0dac551a8939310ec81b9acd15836a574cf362588eaab03ab11919bc2a0f9648b19ea8dee33bf12675eb5b6fd38bda6f25e + checksum: 10c0/c17a6dc4f5a6006ecb60165cc38bcd21fefb4a10c7a2578a0cfe5813bbd442531a87ed741da5adab5eb678e8e693fda2e2b14555b035355537e32bcec367ea17 languageName: node linkType: hard @@ -149,17 +150,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.32.0": - version: 9.32.0 - resolution: "@eslint/js@npm:9.32.0" - checksum: 10c0/f71e8f9146638d11fb15238279feff98801120a4d4130f1c587c4f09b024ff5ec01af1ba88e97ba6b7013488868898a668f77091300cc3d4394c7a8ed32d2667 - languageName: node - linkType: hard - -"@eslint/js@npm:^9.30.0": - version: 9.31.0 - resolution: "@eslint/js@npm:9.31.0" - checksum: 10c0/f9d4c73d0fafe70679a418cbb25ab7ebcc8f1dba6c32456d6f8ba5a137d583ecff233cfe10f61f41d7d4d2220e94cff1f39fc7ed1fa3819d1888dee1cad678ea +"@eslint/js@npm:9.34.0, @eslint/js@npm:^9.30.0": + version: 9.34.0 + resolution: "@eslint/js@npm:9.34.0" + checksum: 10c0/53f1bfd2a374683d9382a6850354555f6e89a88416c34a5d34e9fbbaf717e97c2b06300e8f93e5eddba8bda8951ccab7f93a680e56ded1a3d21d526019e69bab languageName: node linkType: hard @@ -170,13 +164,13 @@ __metadata: languageName: node linkType: hard -"@eslint/plugin-kit@npm:^0.3.4": - version: 0.3.4 - resolution: "@eslint/plugin-kit@npm:0.3.4" +"@eslint/plugin-kit@npm:^0.3.5": + version: 0.3.5 + resolution: "@eslint/plugin-kit@npm:0.3.5" dependencies: - "@eslint/core": "npm:^0.15.1" + "@eslint/core": "npm:^0.15.2" levn: "npm:^0.4.1" - checksum: 10c0/64331ca100f62a0115d10419a28059d0f377e390192163b867b9019517433d5073d10b4ec21f754fa01faf832aceb34178745924baab2957486f8bf95fd628d2 + checksum: 10c0/c178c1b58c574200c0fd125af3e4bc775daba7ce434ba6d1eeaf9bcb64b2e9fea75efabffb3ed3ab28858e55a016a5efa95f509994ee4341b341199ca630b89e languageName: node linkType: hard @@ -348,9 +342,9 @@ __metadata: languageName: node linkType: hard -"@redocly/openapi-core@npm:^1.34.3": - version: 1.34.3 - resolution: "@redocly/openapi-core@npm:1.34.3" +"@redocly/openapi-core@npm:^1.34.5": + version: 1.34.5 + resolution: "@redocly/openapi-core@npm:1.34.5" dependencies: "@redocly/ajv": "npm:^8.11.2" "@redocly/config": "npm:^0.22.0" @@ -361,7 +355,7 @@ __metadata: minimatch: "npm:^5.0.1" pluralize: "npm:^8.0.0" yaml-ast-parser: "npm:0.0.43" - checksum: 10c0/09a089c206419f716dd66009ac9cf90f1de8b44537828e8e23be7846f28c64190a6733d53974d8cbe17d455309b12dbff3b136ec64d7932f9183c01c9e6a777b + checksum: 10c0/e75ca28d9a7ad3dcb4879e958f2f064aa6d00dc8a52377fbed5a4fec48fa7892056c33dae7996ced9c613b347b400a4610c1c50d4910eb951e40222dbb154085 languageName: node linkType: hard @@ -383,10 +377,10 @@ __metadata: languageName: node linkType: hard -"@tsd/typescript@npm:~5.8.3": - version: 5.8.3 - resolution: "@tsd/typescript@npm:5.8.3" - checksum: 10c0/d136086026f66286fb4f5b02f88109c4bcfe965956620c8eec2ee9aebe9e2d03caba208df0c0612209954de2df4ef2f9ff1c845b8d500b7db6e819585d3ade71 +"@tsd/typescript@npm:^5.9.2": + version: 5.9.2 + resolution: "@tsd/typescript@npm:5.9.2" + checksum: 10c0/4ac4c6e7f3fdf308f4b4dfe14c5a72a518f12efdaa49001a08a64fe687bdc14399abf0bceaf768be04549f4c8a46502cec4a5574555589b33d35fb28a2fd7001 languageName: node linkType: hard @@ -437,106 +431,106 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.38.0" +"@typescript-eslint/eslint-plugin@npm:8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.41.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.38.0" - "@typescript-eslint/type-utils": "npm:8.38.0" - "@typescript-eslint/utils": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" + "@typescript-eslint/scope-manager": "npm:8.41.0" + "@typescript-eslint/type-utils": "npm:8.41.0" + "@typescript-eslint/utils": "npm:8.41.0" + "@typescript-eslint/visitor-keys": "npm:8.41.0" graphemer: "npm:^1.4.0" ignore: "npm:^7.0.0" natural-compare: "npm:^1.4.0" ts-api-utils: "npm:^2.1.0" peerDependencies: - "@typescript-eslint/parser": ^8.38.0 + "@typescript-eslint/parser": ^8.41.0 eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/199b82e9f0136baecf515df7c31bfed926a7c6d4e6298f64ee1a77c8bdd7a8cb92a2ea55a5a345c9f2948a02f7be6d72530efbe803afa1892b593fbd529d0c27 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/29812ee5deeae65e67db29faa8d96bc70255c45788f342b11838850ea29a96e4331622cad3e703ffacaa895372845d44fd6b04786117c78f1a027595adff2e62 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/parser@npm:8.38.0" +"@typescript-eslint/parser@npm:8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/parser@npm:8.41.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.38.0" - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" + "@typescript-eslint/scope-manager": "npm:8.41.0" + "@typescript-eslint/types": "npm:8.41.0" + "@typescript-eslint/typescript-estree": "npm:8.41.0" + "@typescript-eslint/visitor-keys": "npm:8.41.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/5580c2a328f0c15f85e4a0961a07584013cc0aca85fe868486187f7c92e9e3f6602c6e3dab917b092b94cd492ed40827c6f5fea42730bef88eb17592c947adf4 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/ca13ff505e9253aee761741f96714cd65a296bbfcac961efbbf7a909ff3d180b2142a23db0a2a5e50b928fa56586528b7e47ba6301089dd850945018dbf2ef50 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/project-service@npm:8.38.0" +"@typescript-eslint/project-service@npm:8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/project-service@npm:8.41.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.38.0" - "@typescript-eslint/types": "npm:^8.38.0" + "@typescript-eslint/tsconfig-utils": "npm:^8.41.0" + "@typescript-eslint/types": "npm:^8.41.0" debug: "npm:^4.3.4" peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/87d2f55521e289bbcdc666b1f4587ee2d43039cee927310b05abaa534b528dfb1b5565c1545bb4996d7fbdf9d5a3b0aa0e6c93a8f1289e3fcfd60d246364a884 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/907ba880fcaf0805fc97012b431536b5b06db6ae4a0095708f9d9a4406feddabd964f09ea4ca99d8fa7bd141dbcc9496f1a9eb6683361a6bb01fb714a361126c languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/scope-manager@npm:8.38.0" +"@typescript-eslint/scope-manager@npm:8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/scope-manager@npm:8.41.0" dependencies: - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" - checksum: 10c0/ceaf489ea1f005afb187932a7ee363dfe1e0f7cc3db921283991e20e4c756411a5e25afbec72edd2095d6a4384f73591f4c750cf65b5eaa650c90f64ef9fe809 + "@typescript-eslint/types": "npm:8.41.0" + "@typescript-eslint/visitor-keys": "npm:8.41.0" + checksum: 10c0/6b339ac1fc37a1e05dc6de421db9f9b138c357497ec87af2471ad30e48c78b4979d3da40943a1c81fc85d1537326a4f938843434db63d29eff414b9364daf8e8 languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.38.0, @typescript-eslint/tsconfig-utils@npm:^8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.38.0" +"@typescript-eslint/tsconfig-utils@npm:8.41.0, @typescript-eslint/tsconfig-utils@npm:^8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.41.0" peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/1a90da16bf1f7cfbd0303640a8ead64a0080f2b1d5969994bdac3b80abfa1177f0c6fbf61250bae082e72cf5014308f2f5cc98edd6510202f13420a7ffd07a84 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/98618a536b9cb071eacba2970ce2ca1b9243de78f4604c2e350823a5275b9d7d15238dbe6acd197c30c0b6cbbf37782c247d14984e1015a109431e4180d76af6 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/type-utils@npm:8.38.0" +"@typescript-eslint/type-utils@npm:8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/type-utils@npm:8.41.0" dependencies: - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" - "@typescript-eslint/utils": "npm:8.38.0" + "@typescript-eslint/types": "npm:8.41.0" + "@typescript-eslint/typescript-estree": "npm:8.41.0" + "@typescript-eslint/utils": "npm:8.41.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^2.1.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/27795c4bd0be395dda3424e57d746639c579b7522af1c17731b915298a6378fd78869e8e141526064b6047db2c86ba06444469ace19c98cda5779d06f4abd37c + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/d4f9ae07a30f1cf331c3e3a67f8749b38f199ba5000f7a600492c27f6bec774f15c3553f293c520fb999fb88108665f2785d5261daec1445b17af14a7bb0bfac languageName: node linkType: hard -"@typescript-eslint/types@npm:8.38.0, @typescript-eslint/types@npm:^8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/types@npm:8.38.0" - checksum: 10c0/f0ac0060c98c0f3d1871f107177b6ae25a0f1846ca8bd8cfc7e1f1dd0ddce293cd8ac4a5764d6a767de3503d5d01defcd68c758cb7ba6de52f82b209a918d0d2 +"@typescript-eslint/types@npm:8.41.0, @typescript-eslint/types@npm:^8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/types@npm:8.41.0" + checksum: 10c0/4945a7ed7789e0527833ee378b962416d6d0d61eb6c891fe49cb6c8dc8a9adbfc58676080ca767a1f034f74f9a981caf5f4d4706cba5025c0520a801fb45d7e1 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.38.0" +"@typescript-eslint/typescript-estree@npm:8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.41.0" dependencies: - "@typescript-eslint/project-service": "npm:8.38.0" - "@typescript-eslint/tsconfig-utils": "npm:8.38.0" - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" + "@typescript-eslint/project-service": "npm:8.41.0" + "@typescript-eslint/tsconfig-utils": "npm:8.41.0" + "@typescript-eslint/types": "npm:8.41.0" + "@typescript-eslint/visitor-keys": "npm:8.41.0" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" @@ -544,33 +538,33 @@ __metadata: semver: "npm:^7.6.0" ts-api-utils: "npm:^2.1.0" peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/00a00f6549877f4ae5c2847fa5ac52bf42cbd59a87533856c359e2746e448ed150b27a6137c92fd50c06e6a4b39e386d6b738fac97d80d05596e81ce55933230 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/e86233d895403ec4986ced25f56898b2704a84545bb7dfe933f5c64f2ab969dcb7ada7e21ea7e015c875cc94a0767e70573442724960c631b7b3fc556a984c9c languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/utils@npm:8.38.0" +"@typescript-eslint/utils@npm:8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/utils@npm:8.41.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.7.0" - "@typescript-eslint/scope-manager": "npm:8.38.0" - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" + "@typescript-eslint/scope-manager": "npm:8.41.0" + "@typescript-eslint/types": "npm:8.41.0" + "@typescript-eslint/typescript-estree": "npm:8.41.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/e97a45bf44f315f9ed8c2988429e18c88e3369c9ee3227ee86446d2d49f7325abebbbc9ce801e178f676baa986d3e1fd4b5391f1640c6eb8944c123423ae43bb + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/3a2ed9b5f801afeccde44dbacdeae0b9c82cc3e1af5e92926929ad86384dc0fb0027152e68c5edfabe904647c2160c0c45ec9c848a8d67c3efb86b78a1343acb languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.38.0" +"@typescript-eslint/visitor-keys@npm:8.41.0": + version: 8.41.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.41.0" dependencies: - "@typescript-eslint/types": "npm:8.38.0" + "@typescript-eslint/types": "npm:8.41.0" eslint-visitor-keys: "npm:^4.2.1" - checksum: 10c0/071a756e383f41a6c9e51d78c8c64bd41cd5af68b0faef5fbaec4fa5dbd65ec9e4cd610c2e2cdbe9e2facc362995f202850622b78e821609a277b5b601a1d4ec + checksum: 10c0/cfe52e77b9e07c23a4d9f4adf9e6bf27822e58694c9a34fefa4b9fc96d553e9df561971c4da5fc78392522e34696fc1149a76f6a02c328136771c5efe0fd1029 languageName: node linkType: hard @@ -715,16 +709,18 @@ __metadata: linkType: hard "array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": - version: 3.1.8 - resolution: "array-includes@npm:3.1.8" + version: 3.1.9 + resolution: "array-includes@npm:3.1.9" dependencies: - call-bind: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" - es-object-atoms: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.4" - is-string: "npm:^1.0.7" - checksum: 10c0/5b1004d203e85873b96ddc493f090c9672fd6c80d7a60b798da8a14bff8a670ff95db5aafc9abc14a211943f05220dacf8ea17638ae0af1a6a47b8c0b48ce370 + es-abstract: "npm:^1.24.0" + es-object-atoms: "npm:^1.1.1" + get-intrinsic: "npm:^1.3.0" + is-string: "npm:^1.1.1" + math-intrinsics: "npm:^1.1.0" + checksum: 10c0/0235fa69078abeac05ac4250699c44996bc6f774a9cbe45db48674ce6bd142f09b327d31482ff75cf03344db4ea03eae23edb862d59378b484b47ed842574856 languageName: node linkType: hard @@ -1305,26 +1301,26 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9": - version: 1.23.9 - resolution: "es-abstract@npm:1.23.9" +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9, es-abstract@npm:^1.24.0": + version: 1.24.0 + resolution: "es-abstract@npm:1.24.0" dependencies: array-buffer-byte-length: "npm:^1.0.2" arraybuffer.prototype.slice: "npm:^1.0.4" available-typed-arrays: "npm:^1.0.7" call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" + call-bound: "npm:^1.0.4" data-view-buffer: "npm:^1.0.2" data-view-byte-length: "npm:^1.0.2" data-view-byte-offset: "npm:^1.0.1" es-define-property: "npm:^1.0.1" es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" + es-object-atoms: "npm:^1.1.1" es-set-tostringtag: "npm:^2.1.0" es-to-primitive: "npm:^1.3.0" function.prototype.name: "npm:^1.1.8" - get-intrinsic: "npm:^1.2.7" - get-proto: "npm:^1.0.0" + get-intrinsic: "npm:^1.3.0" + get-proto: "npm:^1.0.1" get-symbol-description: "npm:^1.1.0" globalthis: "npm:^1.0.4" gopd: "npm:^1.2.0" @@ -1336,21 +1332,24 @@ __metadata: is-array-buffer: "npm:^3.0.5" is-callable: "npm:^1.2.7" is-data-view: "npm:^1.0.2" + is-negative-zero: "npm:^2.0.3" is-regex: "npm:^1.2.1" + is-set: "npm:^2.0.3" is-shared-array-buffer: "npm:^1.0.4" is-string: "npm:^1.1.1" is-typed-array: "npm:^1.1.15" - is-weakref: "npm:^1.1.0" + is-weakref: "npm:^1.1.1" math-intrinsics: "npm:^1.1.0" - object-inspect: "npm:^1.13.3" + object-inspect: "npm:^1.13.4" object-keys: "npm:^1.1.1" object.assign: "npm:^4.1.7" own-keys: "npm:^1.0.1" - regexp.prototype.flags: "npm:^1.5.3" + regexp.prototype.flags: "npm:^1.5.4" safe-array-concat: "npm:^1.1.3" safe-push-apply: "npm:^1.0.0" safe-regex-test: "npm:^1.1.0" set-proto: "npm:^1.0.0" + stop-iteration-iterator: "npm:^1.1.0" string.prototype.trim: "npm:^1.2.10" string.prototype.trimend: "npm:^1.0.9" string.prototype.trimstart: "npm:^1.0.8" @@ -1359,8 +1358,8 @@ __metadata: typed-array-byte-offset: "npm:^1.0.4" typed-array-length: "npm:^1.0.7" unbox-primitive: "npm:^1.1.0" - which-typed-array: "npm:^1.1.18" - checksum: 10c0/1de229c9e08fe13c17fe5abaec8221545dfcd57e51f64909599a6ae896df84b8fd2f7d16c60cb00d7bf495b9298ca3581aded19939d4b7276854a4b066f8422b + which-typed-array: "npm:^1.1.19" + checksum: 10c0/b256e897be32df5d382786ce8cce29a1dd8c97efbab77a26609bd70f2ed29fbcfc7a31758cb07488d532e7ccccdfca76c1118f2afe5a424cdc05ca007867c318 languageName: node linkType: hard @@ -1503,8 +1502,8 @@ __metadata: linkType: hard "eslint-plugin-prettier@npm:^5.5.3": - version: 5.5.3 - resolution: "eslint-plugin-prettier@npm:5.5.3" + version: 5.5.4 + resolution: "eslint-plugin-prettier@npm:5.5.4" dependencies: prettier-linter-helpers: "npm:^1.0.0" synckit: "npm:^0.11.7" @@ -1518,7 +1517,7 @@ __metadata: optional: true eslint-config-prettier: optional: true - checksum: 10c0/7524e381b400fec67dd2bd1a71779c220a5410f0063cd220d144431f291ec800bee1985709ef0dd38d666d01e0e53bec93824063912784d4021db8473fafe73e + checksum: 10c0/5cc780e0ab002f838ad8057409e86de4ff8281aa2704a50fa8511abff87028060c2e45741bc9cbcbd498712e8d189de8026e70aed9e20e50fe5ba534ee5a8442 languageName: node linkType: hard @@ -1597,18 +1596,18 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^9.31.0": - version: 9.32.0 - resolution: "eslint@npm:9.32.0" +"eslint@npm:^9.34.0": + version: 9.34.0 + resolution: "eslint@npm:9.34.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.12.1" "@eslint/config-array": "npm:^0.21.0" - "@eslint/config-helpers": "npm:^0.3.0" - "@eslint/core": "npm:^0.15.0" + "@eslint/config-helpers": "npm:^0.3.1" + "@eslint/core": "npm:^0.15.2" "@eslint/eslintrc": "npm:^3.3.1" - "@eslint/js": "npm:9.32.0" - "@eslint/plugin-kit": "npm:^0.3.4" + "@eslint/js": "npm:9.34.0" + "@eslint/plugin-kit": "npm:^0.3.5" "@humanfs/node": "npm:^0.16.6" "@humanwhocodes/module-importer": "npm:^1.0.1" "@humanwhocodes/retry": "npm:^0.4.2" @@ -1643,7 +1642,7 @@ __metadata: optional: true bin: eslint: bin/eslint.js - checksum: 10c0/e8a23924ec5f8b62e95483002ca25db74e25c23bd9c6d98a9f656ee32f820169bee3bfdf548ec728b16694f198b3db857d85a49210ee4a035242711d08fdc602 + checksum: 10c0/ba3e54fa0c8ed23d062f91519afaae77fed922a6c4d76130b6cd32154bcb406aaea4b3c5ed88e0be40828c1d5b6921592f3947dbdc5e2043de6bd7aa341fe5ea languageName: node linkType: hard @@ -2416,6 +2415,13 @@ __metadata: languageName: node linkType: hard +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: 10c0/bcdcf6b8b9714063ffcfa9929c575ac69bfdabb8f4574ff557dfc086df2836cf07e3906f5bbc4f2a5c12f8f3ba56af640c843cdfc74da8caed86c7c7d66fd08e + languageName: node + linkType: hard + "is-number-object@npm:^1.1.1": version: 1.1.1 resolution: "is-number-object@npm:1.1.1" @@ -2468,7 +2474,7 @@ __metadata: languageName: node linkType: hard -"is-string@npm:^1.0.7, is-string@npm:^1.1.1": +"is-string@npm:^1.1.1": version: 1.1.1 resolution: "is-string@npm:1.1.1" dependencies: @@ -2512,7 +2518,7 @@ __metadata: languageName: node linkType: hard -"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.0": +"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.1": version: 1.1.1 resolution: "is-weakref@npm:1.1.1" dependencies: @@ -3144,7 +3150,7 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.3": +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": version: 1.13.4 resolution: "object-inspect@npm:1.13.4" checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 @@ -3208,21 +3214,21 @@ __metadata: languageName: node linkType: hard -"openapi-typescript@npm:^7.8.0": - version: 7.8.0 - resolution: "openapi-typescript@npm:7.8.0" +"openapi-typescript@npm:^7.9.1": + version: 7.9.1 + resolution: "openapi-typescript@npm:7.9.1" dependencies: - "@redocly/openapi-core": "npm:^1.34.3" + "@redocly/openapi-core": "npm:^1.34.5" ansi-colors: "npm:^4.1.3" change-case: "npm:^5.4.4" parse-json: "npm:^8.3.0" - supports-color: "npm:^10.0.0" + supports-color: "npm:^10.1.0" yargs-parser: "npm:^21.1.1" peerDependencies: typescript: ^5.x bin: openapi-typescript: bin/cli.js - checksum: 10c0/5c73e769b83d01c8a9d409b9f07e5c3ab4805392445acf47f17b931fecb8bd4ca1f271a31acc32a2ec8ebd25ce9f71ededa13ddec9285d694034035e2bc0db7a + checksum: 10c0/52db65d211f872e0a34018cca409f388d70d55fa7cd6e07eacbb8ffc873ed78ffa29f95758766e2bd51ef87145aea8b66350638355cac5887f407aba9080d408 languageName: node linkType: hard @@ -3463,16 +3469,16 @@ __metadata: linkType: hard "prettier-plugin-organize-imports@npm:^4.1.0": - version: 4.1.0 - resolution: "prettier-plugin-organize-imports@npm:4.1.0" + version: 4.2.0 + resolution: "prettier-plugin-organize-imports@npm:4.2.0" peerDependencies: prettier: ">=2.0" typescript: ">=2.9" - vue-tsc: ^2.1.0 + vue-tsc: ^2.1.0 || 3 peerDependenciesMeta: vue-tsc: optional: true - checksum: 10c0/fb2d6d415bac96b65a77ea7de9f708e8613436aeb9d82bbe63edeb312fd1362c0d3c57319bd4cc4adfc8b9964fb6c205cbbf8efd9546931b0f9874c0ae624a6a + checksum: 10c0/3b20652d7ff71786c088bdb4189b315bca086faee70db1c10aca21dc41efadbcba45ef37b0842fb91f14f31927b6bed63433b2725346dc79b3833b6694b33eed languageName: node linkType: hard @@ -3692,7 +3698,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.3": +"regexp.prototype.flags@npm:^1.5.3, regexp.prototype.flags@npm:^1.5.4": version: 1.5.4 resolution: "regexp.prototype.flags@npm:1.5.4" dependencies: @@ -3876,7 +3882,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.6.0": +"semver@npm:^7.3.4, semver@npm:^7.3.5": version: 7.7.1 resolution: "semver@npm:7.7.1" bin: @@ -3885,6 +3891,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.6.0": + version: 7.7.2 + resolution: "semver@npm:7.7.2" + bin: + semver: bin/semver.js + checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea + languageName: node + linkType: hard + "set-function-length@npm:^1.2.2": version: 1.2.2 resolution: "set-function-length@npm:1.2.2" @@ -4096,6 +4111,16 @@ __metadata: languageName: node linkType: hard +"stop-iteration-iterator@npm:^1.1.0": + version: 1.1.0 + resolution: "stop-iteration-iterator@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + internal-slot: "npm:^1.1.0" + checksum: 10c0/de4e45706bb4c0354a4b1122a2b8cc45a639e86206807ce0baf390ee9218d3ef181923fa4d2b67443367c491aa255c5fbaa64bb74648e3c5b48299928af86c09 + languageName: node + linkType: hard + "string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0": version: 4.2.3 resolution: "string-width@npm:4.2.3" @@ -4232,10 +4257,10 @@ __metadata: languageName: node linkType: hard -"supports-color@npm:^10.0.0": - version: 10.0.0 - resolution: "supports-color@npm:10.0.0" - checksum: 10c0/0e7884dfd02a07b3c6e0b235346f58c19f0201f1e44f7807583581761b354688c8577378785b5a4e3b03110809786c4c808e0e086cd91911f7b8bc59132703a8 +"supports-color@npm:^10.1.0": + version: 10.2.0 + resolution: "supports-color@npm:10.2.0" + checksum: 10c0/a240dbbc52dbdfc9b727a74e30c9a661cb7dd610ee662ae15de332f4993f172f284e57237e03a44abf48587ee142695aa7b25daee73c93a9c356f89dfba7d492 languageName: node linkType: hard @@ -4348,11 +4373,11 @@ __metadata: languageName: node linkType: hard -"tsd@npm:^0.32.0": - version: 0.32.0 - resolution: "tsd@npm:0.32.0" +"tsd@npm:^0.33.0": + version: 0.33.0 + resolution: "tsd@npm:0.33.0" dependencies: - "@tsd/typescript": "npm:~5.8.3" + "@tsd/typescript": "npm:^5.9.2" eslint-formatter-pretty: "npm:^4.1.0" globby: "npm:^11.0.1" jest-diff: "npm:^29.0.3" @@ -4361,7 +4386,7 @@ __metadata: read-pkg-up: "npm:^7.0.0" bin: tsd: dist/cli.js - checksum: 10c0/371e8269052f9665b7290e2049ddcc36c67320028715632b0e3e4666e6dfa8a935c801fbdcaa94393ffb7e439c4cdcb6142859560d21d2a938f5c240e7f10833 + checksum: 10c0/24cd7a07abcd339fc80152a3dae910cd276bc70c081357b0165b6ece845b1dbf321767fcb9627794c10385161368a671a0c80b5ad18547ad9668b46071288d4b languageName: node linkType: hard @@ -4483,22 +4508,22 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^8.35.1": - version: 8.38.0 - resolution: "typescript-eslint@npm:8.38.0" +"typescript-eslint@npm:^8.35.1, typescript-eslint@npm:^8.41.0": + version: 8.41.0 + resolution: "typescript-eslint@npm:8.41.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.38.0" - "@typescript-eslint/parser": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" - "@typescript-eslint/utils": "npm:8.38.0" + "@typescript-eslint/eslint-plugin": "npm:8.41.0" + "@typescript-eslint/parser": "npm:8.41.0" + "@typescript-eslint/typescript-estree": "npm:8.41.0" + "@typescript-eslint/utils": "npm:8.41.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/486b9862ee08f7827d808a2264ce03b58087b11c4c646c0da3533c192a67ae3fcb4e68d7a1e69d0f35a1edc274371a903a50ecfe74012d5eaa896cb9d5a81e0b + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/e141ffaf0332053483526a31e68755fe1438f6367571f39e67e32c0e15d509e8678adab2020597720b0307360493724d8dcf60d0620611d7e1e209d7f952cfe9 languageName: node linkType: hard -"typescript@npm:^5.5.3, typescript@npm:^5.8.3": +"typescript@npm:^5.5.3, typescript@npm:^5.9.2": version: 5.9.2 resolution: "typescript@npm:5.9.2" bin: @@ -4508,7 +4533,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.5.3#optional!builtin, typescript@patch:typescript@npm%3A^5.8.3#optional!builtin": +"typescript@patch:typescript@npm%3A^5.5.3#optional!builtin, typescript@patch:typescript@npm%3A^5.9.2#optional!builtin": version: 5.9.2 resolution: "typescript@patch:typescript@npm%3A5.9.2#optional!builtin::version=5.9.2&hash=5786d5" bin: @@ -4650,7 +4675,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.18": +"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.19": version: 1.1.19 resolution: "which-typed-array@npm:1.1.19" dependencies: From 9f3be2982ed844fd1c70e7e88c3637cd0359624c Mon Sep 17 00:00:00 2001 From: Torbjorn van Heeswijck Date: Sun, 31 Aug 2025 19:58:24 +0930 Subject: [PATCH 3/5] MI-255: Fix type inference for optional requestBody - Add a test for a post request with optional requestBody - Modify requestBody inference to pass - Minor cleanup of types --- src/internal/reference/operation-inference.ts | 89 ++++++++++++------- src/internal/type-utils.ts | 64 ++++++++++++- src/management/v2/index.ts | 13 +-- src/management/v3/index.ts | 15 ++-- test-d/v3/catalog/product-metafields-post.ts | 47 ++++++++++ 5 files changed, 183 insertions(+), 45 deletions(-) create mode 100644 test-d/v3/catalog/product-metafields-post.ts diff --git a/src/internal/reference/operation-inference.ts b/src/internal/reference/operation-inference.ts index 2aaad6b..3c036e6 100644 --- a/src/internal/reference/operation-inference.ts +++ b/src/internal/reference/operation-inference.ts @@ -1,7 +1,5 @@ -// TECH DEBT: Work out if these eslint rules are reasonable in this context -/* eslint-disable @typescript-eslint/no-empty-object-type */ -/* eslint-disable @typescript-eslint/no-explicit-any */ import type { RequestMethod } from '../operation.js'; +import type { Flatten, IsOptional } from '../type-utils.js'; // Takes an OpenAPI paths specification and converts it into our internal operation index format, // removing any undefined endpoints and flattening the paths into a single type @@ -9,41 +7,48 @@ export type InferOperationIndex = Flatten<{ [PathStr in keyof PathsSpec & string]: PathOperationIndex; }>; -// Takes a record of types and flattens them into a single intersection type -// This combines all the operations from different paths into one type -type Flatten> = UnionToIntersection; -type UnionToIntersection = (T extends any ? (x: T) => any : never) extends (x: infer R) => any - ? R - : never; - -// Converts an OpenAPI 3.0 path specification into our operation index format -// Currently this only extracts type details for application/json request bodies +/** + * @description Formats the OpenAPI parameters, responses, and responseBody specs at a given path + * in preparation for flattening the paths in to a single index type + * + * @see InferOperationIndex for more information + */ type PathOperationIndex = { - [K in keyof PathSpec as K extends RequestMethodLc - ? `${Uppercase} ${Path}` - : never]: PathSpec[K] extends { parameters?: infer Params; responses?: infer Responses } - ? PathSpec[K] extends { - requestBody: { content: { 'application/json': infer RequestBody } }; + [K in keyof PathSpec as PathKey]: PathSpec[K] extends { + parameters?: infer Params; + responses?: infer Responses; } ? { - readonly parameters: (unknown extends Params ? {} : Params) & { - body: RequestBody; - }; - readonly response: Response; - } - : { - readonly parameters: unknown extends Params ? {} : Params; - readonly response: Response; + parameters: Params & ParamsRequestBody; + response: ResponseUnion; } : never; }; -// Lowercase version of our RequestMethod type -// Used for matching HTTP methods in OpenAPI specs which are typically lowercase -type RequestMethodLc = Lowercase; +/** + * @description Combines the REST operation method with the endpoint path to form a unique key + * @example + * ```ts + * type A = PathKey<'get', '/path/a'> + * // A is 'GET /path/a' + */ +type PathKey = + K extends Lowercase ? `${Uppercase} ${Path}` : never; -// Converts OpenAPI response specifications into our internal response format -type Response = { +/** + * @description Converts OpenAPI response specifications into a union of possible responses + * Only responses with a 'application/json' content type are included + * + * @example + * ```ts + * type A = Response<{ + * 200: { content: { 'application/json': { a: string } } }; + * 204: { content: { 'application/json': {} } }; + * }>; + * // A is { status: 200, body: { a: string } } | { status: 204, body: {} } + * ``` + */ +type ResponseUnion = { [Status in keyof ResponsesSpec]: { status: Status; body: ResponsesSpec[Status] extends { content: { 'application/json': infer ResponseBody } } @@ -51,3 +56,27 @@ type Response = { : never; }; }[keyof ResponsesSpec]; + +/** + * @description Extracts the request body from an OpenAPI specification + * - Keeps the optional or required nature of the request body from the original spec + * - Only includes 'application/json' content type request bodies + * - Returns a type with no body property if the original spec has no request body property (e.g. GET requests) + * + * @example + * ```ts + * type A = ParamsRequestBody<{ + * requestBody: { content: { 'application/json': { a: string } } }; + * }>; + * // A is { body: { a: string } } + * ``` + */ +type ParamsRequestBody = PathSpec extends { + requestBody?: { content: { 'application/json': infer RequestBody } }; +} + ? unknown extends RequestBody + ? unknown + : IsOptional extends true + ? Partial<{ body: RequestBody }> + : { body: RequestBody } + : never; diff --git a/src/internal/type-utils.ts b/src/internal/type-utils.ts index 6be5f6f..b7a7961 100644 --- a/src/internal/type-utils.ts +++ b/src/internal/type-utils.ts @@ -1,10 +1,14 @@ export type Const = (A extends Narrowable ? A : never) | { [K in keyof A]: Const }; -// TECH DEBT: Work out if these eslint rules are reasonable in this context -// eslint-disable-next-line @typescript-eslint/no-explicit-any -type Narrowable = string | number | bigint | boolean | readonly any[]; -export type RemoveStart< +/** + * @description Removes a string from the start of another string + * @example + * ```ts + * type A = RemoveStart<'a', 'abc'> + * // A is 'bc' + */ +export type RemovePrefix< Start extends string, Subject extends string, > = Subject extends `${Start}${infer End}` ? End : never; @@ -14,3 +18,55 @@ export type SimplifyDeep = Type extends object [TypeKey in keyof Type]: SimplifyDeep; } : Type; + +// Takes a record of types and flattens them into a single intersection type +// This combines all the operations from different paths into one type +/** + * @description Flattens a record of types into a single intersection type + * @example + * ```ts + * type A = { + * 'path/a': { get: { params: { a: string } } }, + * 'path/b': { post: { params: { b: number } } }, + * 'path/c': { get: { params: { c: string } } } + * } + * type B = Flatten + * // B is { + * get: { params: { a: string } } & + * post: { params: { b: number } } & + * get: { params: { c: string } } + * } + * ``` + */ +export type Flatten> = UnionToIntersection; + +/** + * @description Converts a union type into an intersection type + * @example + * ```ts + * type A = { a: string } | { b: number } + * type B = UnionToIntersection + * // B is { a: string } & { b: number } + * ``` + */ +type UnionToIntersection = (T extends unknown ? (x: T) => unknown : never) extends ( + x: infer R +) => unknown + ? R + : never; + +/** + * @description Checks if a property of an object is optional + * @example + * ```ts + * type A = IsOptional<{ a: string }, 'a'> + * // A is false + * type B = IsOptional<{ a?: string }, 'a'> + * // B is true + * ``` + */ +export type IsOptional = K extends keyof T + ? T extends Record + ? false + : true + : false; diff --git a/src/management/v2/index.ts b/src/management/v2/index.ts index c036ed5..364cca3 100644 --- a/src/management/v2/index.ts +++ b/src/management/v2/index.ts @@ -10,7 +10,7 @@ import { Transport, } from '../../internal/operation.js'; import type { V2 as reference } from '../../internal/reference/index.js'; -import type { Const, RemoveStart, SimplifyDeep } from '../../internal/type-utils.js'; +import type { Const, RemovePrefix, SimplifyDeep } from '../../internal/type-utils.js'; export type Operations = reference.Operation; @@ -78,7 +78,7 @@ export class Client { ): Promise | null>; delete( - path: RemoveStart<'DELETE ', CustomEndpoints>, + path: RemovePrefix<'DELETE ', CustomEndpoints>, params?: Parameters ): Promise; @@ -100,7 +100,7 @@ export class Client { params: Const ): Promise | null>; - get(path: RemoveStart<'GET ', CustomEndpoints>, params?: Parameters): Promise; + get(path: RemovePrefix<'GET ', CustomEndpoints>, params?: Parameters): Promise; async get(path: string, params?: Parameters): Promise { const res = await this.send(`GET ${path}`, params); @@ -120,7 +120,10 @@ export class Client { params: Const ): Promise>; - post(path: RemoveStart<'POST ', CustomEndpoints>, params?: Parameters): Promise; + post( + path: RemovePrefix<'POST ', CustomEndpoints>, + params?: Parameters + ): Promise; async post(path: string, params?: Parameters): Promise { const res = await this.send(`POST ${path}`, params); @@ -137,7 +140,7 @@ export class Client { params: Const ): Promise>; - put(path: RemoveStart<'PUT ', CustomEndpoints>, params?: Parameters): Promise; + put(path: RemovePrefix<'PUT ', CustomEndpoints>, params?: Parameters): Promise; async put(path: string, params?: Parameters): Promise { const res = await this.send(`PUT ${path}`, params); diff --git a/src/management/v3/index.ts b/src/management/v3/index.ts index 5af43b5..98db76d 100644 --- a/src/management/v3/index.ts +++ b/src/management/v3/index.ts @@ -12,7 +12,7 @@ import { Transport, } from '../../internal/operation.js'; import type { V3 as reference } from '../../internal/reference/index.js'; -import type { Const, RemoveStart, SimplifyDeep } from '../../internal/type-utils.js'; +import type { Const, RemovePrefix, SimplifyDeep } from '../../internal/type-utils.js'; import type { NarrowResponse } from './response-narrowing.js'; export type Operations = reference.Operation; @@ -84,7 +84,7 @@ export class Client { params: Const ): Promise | null>; - get(path: RemoveStart<'GET ', CustomEndpoints>, params?: Parameters): Promise; + get(path: RemovePrefix<'GET ', CustomEndpoints>, params?: Parameters): Promise; async get(path: string, params?: Parameters): Promise { const res = await this.send(`GET ${path}`, params); @@ -103,7 +103,7 @@ export class Client { ): AsyncIterable>; list( - path: RemoveStart<'GET ', CustomEndpoints>, + path: RemovePrefix<'GET ', CustomEndpoints>, params?: Parameters ): AsyncIterable; @@ -132,7 +132,10 @@ export class Client { params: Const ): Promise>; - post(path: RemoveStart<'POST ', CustomEndpoints>, params?: Parameters): Promise; + post( + path: RemovePrefix<'POST ', CustomEndpoints>, + params?: Parameters + ): Promise; async post(path: string, params?: Parameters): Promise { const res = await this.send(`POST ${path}`, params); @@ -149,7 +152,7 @@ export class Client { params: Const ): Promise>; - put(path: RemoveStart<'PUT ', CustomEndpoints>, params?: Parameters): Promise; + put(path: RemovePrefix<'PUT ', CustomEndpoints>, params?: Parameters): Promise; async put(path: string, params?: Parameters): Promise { const res = await this.send(`PUT ${path}`, params); @@ -170,7 +173,7 @@ export class Client { ): Promise | null>; delete( - path: RemoveStart<'DELETE ', CustomEndpoints>, + path: RemovePrefix<'DELETE ', CustomEndpoints>, params?: Parameters ): Promise; diff --git a/test-d/v3/catalog/product-metafields-post.ts b/test-d/v3/catalog/product-metafields-post.ts new file mode 100644 index 0000000..ea0a3d5 --- /dev/null +++ b/test-d/v3/catalog/product-metafields-post.ts @@ -0,0 +1,47 @@ +import { Client, expectType } from '../../index.test-d.js'; + +export default (client: Client) => { + client.v3 + .post('/catalog/products/metafields', { + body: [ + { + permission_set: 'app_only', + namespace: 'Sales Department', + key: 'Staff Name', + value: 'Ronaldo', + resource_id: 42, + }, + ], + }) + .then(response => { + expectType(response); + }); +}; + +type Expected = ReadonlyArray<{ + readonly value: string; + readonly key: string; + readonly description: string; + readonly id: number; + readonly date_created: string; + readonly date_modified: string; + readonly resource_id: number; + readonly namespace: string; + readonly permission_set: + | 'app_only' + | 'read' + | 'write' + | 'read_and_sf_access' + | 'write_and_sf_access'; + readonly resource_type: + | 'brand' + | 'product' + | 'variant' + | 'category' + | 'cart' + | 'channel' + | 'location' + | 'order' + | 'customer'; + readonly owner_client_id: string; +}>; From b9a81131ec05c996c2e9af1229b0b2e3bae35123 Mon Sep 17 00:00:00 2001 From: Torbjorn van Heeswijck Date: Sun, 31 Aug 2025 19:58:48 +0930 Subject: [PATCH 4/5] MI-255: Remove unnecessary type exports, add lots of JSDocs --- src/internal/operation.ts | 120 +++++++++++++----- src/internal/reference/operation-inference.ts | 34 ++++- src/internal/type-utils.ts | 18 ++- src/management/v2/index.ts | 23 ++-- src/management/v3/index.ts | 50 ++++++-- src/management/v3/response-narrowing.ts | 3 + src/management/v3/spec-sniffer.ts | 4 +- 7 files changed, 194 insertions(+), 58 deletions(-) diff --git a/src/internal/operation.ts b/src/internal/operation.ts index b032c31..3d691a8 100644 --- a/src/internal/operation.ts +++ b/src/internal/operation.ts @@ -8,10 +8,14 @@ import { Agent as HttpsAgent } from 'https'; import fetch, { Response as FetchResponse } from 'node-fetch'; import qs from 'query-string'; -// Represents HTTP methods supported by the API +/** + * @description HTTP methods supported by the API + */ export type RequestMethod = 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT'; -// Represents a complete API request with its endpoint and parameters +/** + * @description Represents a complete API request with its endpoint and parameters + */ export type Request< ReqLine extends RequestLine = RequestLine, Params extends Parameters = Parameters, @@ -20,23 +24,37 @@ export type Request< readonly parameters: Params; }; -// Represents an API endpoint in the format "METHOD /path" -// e.g., "GET /products" or "POST /orders" +/** + * @description Represents an API endpoint in the format "METHOD /path" + * e.g., "GET /products" or "POST /orders" + */ export type RequestLine = `${RequestMethod} ${string}`; -// Represents all possible parameter types that can be sent with a request: -// - path: URL path parameters (e.g., /products/{id}) -// - query: URL query parameters -// - body: Request body data -// - header: Custom HTTP headers +/** + * @description Represents all possible parameter types that can be sent with a request: + */ export type Parameters = { + /** + * @description URL path parameters (e.g., /products/{id}) + */ readonly path?: Record; + /** + * @description URL query parameters + */ readonly query?: any; + /** + * @description Request body data + */ readonly body?: any; + /** + * @description Custom HTTP headers + */ readonly header?: Record; }; -// Represents an API response with status code and optional body +/** + * @description Represents an API response with status code and optional body + */ export type Response = { readonly status: number | string; readonly body?: any; @@ -45,6 +63,10 @@ export type Response = { // Namespace for response-related type utilities export namespace Response { type SuccessStatus = 200 | 201 | 204; + + /** + * @description Extracts and formats the possible success responses for an operation + */ export type Success = T extends Operation ? Success : T extends { status: SuccessStatus } @@ -52,7 +74,9 @@ export namespace Response { : never; } -// Represents a complete API operation with its parameters and expected response +/** + * @description Represents a complete API operation with its parameters and expected response + */ export type Operation = { readonly parameters: Request['parameters']; readonly response: Response; @@ -61,43 +85,59 @@ export type Operation = { // Namespace for operation-related type utilities // TODO: MI-199 - determine if this is still required export namespace Operation { - // Extracts the minimal required input parameters for an operation + /** + * @description Extracts the minimal required input parameters for an operation + */ export type MinimalInput = InputParameters; - // Transforms API parameters based on their type: - // - query parameters are made optional (Partial) - // - header parameters have Accept and Content-Type removed since they're handled by the client - // - all other parameters (path, body) are kept as-is - // TODO: MI-199 should we be making params partial? - type TransformParam< + /** + * @description Makes properties optional if they're on the 'query' object + */ + type MakeQueryParamsOptional< OpParams extends Operation['parameters'], K extends keyof OpParams, > = K extends 'query' ? Partial : OpParams[K]; - // Transforms operation parameters to make certain fields optional + /** + * @description Makes properties optional if they can be empty objects + */ + type MakeEmptyObjectOptional = { + readonly [K in keyof T as {} extends T[K] ? K : never]?: T[K]; + } & { + readonly [K in keyof T as {} extends T[K] ? never : K]: T[K]; + }; + + /** + * @description Prepares request parameters by making query params and any possibly empty params optional + */ type InputParameters = MakeEmptyObjectOptional<{ - [K in keyof OpParams]: TransformParam; + [K in keyof OpParams]: MakeQueryParamsOptional; }>; } -// Maps request lines to their corresponding operations +/** + * @description Maps request lines to their corresponding operations + */ export type OperationIndex = Record; // Namespace for operation index utilities export namespace OperationIndex { - // Filters operations to only include those with optional parameters + /** + * @description Filters operations to only include those with optional parameters + */ export type FilterOptionalParams = { [K in keyof Ops as {} extends Ops[K]['parameters'] ? K : never]: Ops[K]; }; } -// Utility type that makes properties optional if they can be empty objects -type MakeEmptyObjectOptional = { - readonly [K in keyof T as {} extends T[K] ? K : never]?: T[K]; -} & { - readonly [K in keyof T as {} extends T[K] ? never : K]: T[K]; -}; - +/** + * @description Resolves the path for a request + * @example + * ```ts + * resolvePath('/products/{id}', { id: 123 }) + * // returns '/products/123' + * ``` + */ export function resolvePath(parameterizedPath: string, pathParams: Record): string { return parameterizedPath .split('/') @@ -116,10 +156,14 @@ export function resolvePath(parameterizedPath: string, pathParams: Record Promise; -// Configuration options for the fetch-based transport +/** + * @description Configuration options for the fetch-based transport + */ export type FetchTransportOptions = { readonly baseUrl: string; readonly headers: Record; @@ -165,6 +209,20 @@ const defaultRetryConfig: Exclude; + * // A is { + * // 'PUT /path/a': RequiredRequestBody<{ + * // a: string; + * // }, + * // unknown, + * // { + * // b: string; + * // }> + * // } + */ export type InferOperationIndex = Flatten<{ [PathStr in keyof PathsSpec & string]: PathOperationIndex; }>; @@ -17,11 +45,11 @@ type PathOperationIndex = { [K in keyof PathSpec as PathKey]: PathSpec[K] extends { parameters?: infer Params; responses?: infer Responses; - } - ? { + } + ? { parameters: Params & ParamsRequestBody; response: ResponseUnion; - } + } : never; }; diff --git a/src/internal/type-utils.ts b/src/internal/type-utils.ts index b7a7961..927754a 100644 --- a/src/internal/type-utils.ts +++ b/src/internal/type-utils.ts @@ -1,5 +1,11 @@ -export type Const = (A extends Narrowable ? A : never) | { [K in keyof A]: Const }; +/** + * @description Recursively Constrains a type to only include primitives + * + * // TECH DEBT: Work out if this and SimplifyDeep are both required + */ +export type Const = (A extends Primitive ? A : never) | { [K in keyof A]: Const }; +type Primitive = string | number | bigint | boolean; /** * @description Removes a string from the start of another string @@ -13,6 +19,16 @@ export type RemovePrefix< Subject extends string, > = Subject extends `${Start}${infer End}` ? End : never; +/** + * @description Simplifies a deeply nested object type. + * The resulting type signatures use primitives rather than generics and are easier to read. + * @example + * ```ts + * type A = { a: { b: Partial<{ c: string }> } } + * type B = SimplifyDeep + * // B is { a: { b: { c?: string } } } + * ``` + */ export type SimplifyDeep = Type extends object ? { [TypeKey in keyof Type]: SimplifyDeep; diff --git a/src/management/v2/index.ts b/src/management/v2/index.ts index 364cca3..198da8d 100644 --- a/src/management/v2/index.ts +++ b/src/management/v2/index.ts @@ -12,26 +12,33 @@ import { import type { V2 as reference } from '../../internal/reference/index.js'; import type { Const, RemovePrefix, SimplifyDeep } from '../../internal/type-utils.js'; -export type Operations = reference.Operation; +type Operations = reference.Operation; -export type RequestLine = keyof Operations; +type RequestLine = keyof Operations; -export type NoParamsRequestLine = keyof OperationIndex.FilterOptionalParams; +type NoParamsRequestLine = keyof OperationIndex.FilterOptionalParams; -export type InferResponse = SimplifyDeep< - Operations[ReqLine]['response'] ->; +type InferResponse = SimplifyDeep; -export type ResponseData = +type ResponseData = Response.Success extends { readonly body: infer Data } ? SimplifyDeep : never; -export type Config = Omit & { +type Config = Omit & { readonly storeHash: string; readonly accessToken: string; }; +/** + * @description Client for interacting with the BigCommerce V2 Management API + * @template CustomEndpoints - A string literal type representing custom API paths + * that are not part of the official BigCommerce API specification. This allows + * type-safe access to non-standard endpoints. + * @example + * ```ts + * const client = new Client({ storeHash: '1234567890', accessToken: '1234567890' }); + */ export class Client { constructor(config: Config); diff --git a/src/management/v3/index.ts b/src/management/v3/index.ts index 98db76d..b48dc4b 100644 --- a/src/management/v3/index.ts +++ b/src/management/v3/index.ts @@ -15,33 +15,59 @@ import type { V3 as reference } from '../../internal/reference/index.js'; import type { Const, RemovePrefix, SimplifyDeep } from '../../internal/type-utils.js'; import type { NarrowResponse } from './response-narrowing.js'; +/** + * @description Represents all possible API Operations in the v3 API + * e.g. "GET /catalog/products", "POST /orders", etc. and their matching request specifications + */ export type Operations = reference.Operation; -// RequestLine represents all possible API endpoints in the Operations type -// e.g. "GET /catalog/products", "POST /orders", etc. -export type RequestLine = keyof Operations; - -// NoParamsRequestLine represents only the API endpoints that have no required parameters -// This filters Operations to only include endpoints where all parameters are optional -// e.g. "GET /catalog/products" would be included, but "GET /catalog/products/{id}" would not -export type NoParamsRequestLine = keyof OperationIndex.FilterOptionalParams; - -export type InferResponse = SimplifyDeep< +/** + * @description Represents all possible API Request paths in the v3 API + * e.g. "GET /catalog/products", "POST /orders", etc. + */ +type RequestLine = keyof Operations; + +/** + * @description Represents API paths that have no required parameters in the v3 API + * e.g. "GET /catalog/products" would be included, but "GET /catalog/products/{id}" would not + */ +type NoParamsRequestLine = keyof OperationIndex.FilterOptionalParams; + +/** + * @description Infer and simplify the response type for a given request line and parameters + */ +type InferResponse = SimplifyDeep< NarrowResponse, Operations[ReqLine]['response']> >; -export type ResponseData = +/** + * @description Infer and simplify the response data type for a given request line and parameters + * Returns `never` for invalid requests + */ +type ResponseData = Response.Success> extends { readonly body: { readonly data?: infer Data }; } ? SimplifyDeep : never; -export type Config = Omit & { +/** + * @description Configuration options for the V3 client + */ +type Config = Omit & { readonly storeHash: string; readonly accessToken: string; }; +/** + * @description Client for interacting with the BigCommerce V3 Management API + * @template CustomEndpoints - A string literal type representing custom API paths + * that are not part of the official BigCommerce API specification. This allows + * type-safe access to non-standard endpoints. + * @example + * ```ts + * const client = new Client({ storeHash: '1234567890', accessToken: '1234567890' }); + */ export class Client { constructor(config: Config); diff --git a/src/management/v3/response-narrowing.ts b/src/management/v3/response-narrowing.ts index 65c0daa..c7f853f 100644 --- a/src/management/v3/response-narrowing.ts +++ b/src/management/v3/response-narrowing.ts @@ -19,6 +19,9 @@ import type { * Currently, this module supports `include`, `include_fields` and `exclude_fields`. */ +/** + * @description Modifies the response type to reflect optional include, include_fields, and exclude_fields parameters + */ export type NarrowResponse< Ops extends OperationIndex, Req extends Request, diff --git a/src/management/v3/spec-sniffer.ts b/src/management/v3/spec-sniffer.ts index a32a630..84daaa7 100644 --- a/src/management/v3/spec-sniffer.ts +++ b/src/management/v3/spec-sniffer.ts @@ -10,9 +10,7 @@ import type { Operations as Ops } from './index.js'; */ export type NoDataElementInResponse = { [K in keyof Ops]: Ops[K]['response'] extends { status: 200 | 201 } - ? // TECH DEBT: Work out if these eslint rules are reasonable in this context - // eslint-disable-next-line @typescript-eslint/no-explicit-any - Ops[K]['response']['body'] extends { data?: any } + ? Ops[K]['response']['body'] extends { data?: unknown } ? never : K : never; From dd3b211e04f582f0285da788addc892cda3d4499 Mon Sep 17 00:00:00 2001 From: Torbjorn van Heeswijck Date: Sun, 31 Aug 2025 20:02:00 +0930 Subject: [PATCH 5/5] Chore: bump patch version to 1.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8b3e483..bcca222 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@aligent/bigcommerce-api", - "version": "1.1.0", + "version": "1.1.1", "type": "module", "scripts": { "test": "tsd",