diff --git a/README.md b/README.md index c12b1b6..e2d62e4 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,10 @@ Here's an example of it being used along with VSCode's eslint plugin, with auto- - [Usage with eslint-plugin-markdown](#usage-with-eslint-plugin-markdown) - [Presets](#presets) - [custom](#custom) + - [copy](#copy) + - [excludeLines](#excludelines) + - [onlyIfExists](#onlyifexists) + - [comparison](#comparison) - [barrel](#barrel) - [markdownFromJsdoc](#markdownfromjsdoc) - [monorepoTOC](#monorepotoc) @@ -139,7 +143,7 @@ module.exports = { ### Presets -#### [custom](./src/presets/custom.ts#L61) +#### [custom](./src/presets/custom.ts#L62) Define your own codegen function, which will receive all options specified. Import the `Preset` type from this library to define a strongly-typed preset function: @@ -284,6 +288,52 @@ module.exports.myGenerator = ({dependencies}) => { ##### Demo ![](./gifs/custom.gif) + + +#### [copy](./src/presets/copy.ts#L53) + +Copies a whole other file. Useful for "borrowing" an implementation of a simple utility from another project, without needing to publish it. Obviously this creates duplicated code, so use judiciously! + +##### basic usage +```js +// codegen:start {preset: copy, source: ../../another-project/src/some-file.ts} import {z} from 'zod' export const MyObject = z.object({ foo: z.string() }) +// codegen:end +``` + +#### excludeLines + +```ts +import {z} from 'zod/v4' // in this project we use zod v4, but we're copying from a project that uses zod v3 +// codegen:start {preset: copy, source: ../../another-project/src/some-file.ts, excludeLines: ['^import']} +export const MyObject = z.object({foo: z.string()}) +// codegen:end +``` + +#### onlyIfExists +```js +// copy a file from a sibling project, but only if the sibling project actually exists +// in this case this will effectively skip the copying step on machines that don't have the sibling project installed +// e.g. on CI runners. +// codegen:start {preset: copy, source: ../../another-project/src/some-file.ts, onlyIfExists: ../../another-project/package.json} +import {z} from 'zod' + +export const MyObject = z.object({foo: z.string()}) +// codegen:end +``` + +#### comparison +```js +// by default, the content will perform a "simplified" comparison with existing content, so differences from tools like prettier +// are ignored. if you care about whitespace and similar differences, you can set the comparison option to `strict`. +// codegen:start {preset: copy, source: ../../another-project/src/some-file.ts, comparison: strict} +import {z} from 'zod' + +export const MyObject = z.object({foo: z.string()}) +// codegen:end +``` + + + #### [barrel](./src/presets/barrel.ts#L38) @@ -315,7 +365,7 @@ export * from './some/path/module-c' ![](./gifs/barrel.gif) -#### [markdownFromJsdoc](./src/presets/markdown-from-jsdoc.ts#L20) +#### [markdownFromJsdoc](./src/presets/markdown-from-jsdoc.ts#L21) Convert jsdoc for an es export from a javascript/typescript file to markdown. diff --git a/package.json b/package.json index caf2282..ec6574e 100644 --- a/package.json +++ b/package.json @@ -35,17 +35,21 @@ "e2e": "playwright test" }, "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "~7.12.0", - "@babel/parser": "^7.11.5", - "@babel/traverse": "^7.11.5", + "@babel/core": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1", "@pnpm/deps.graph-sequencer": "^1.0.0", + "@types/babel__core": "^7.20.5", + "@types/babel__generator": "^7.27.0", "@types/dedent": "0.7.0", "@types/eslint": "^8.44.7", "@types/glob": "7.1.3", "@types/js-yaml": "3.12.5", "@types/lodash": "^4.14.202", "@types/node": "^20.0.0", + "arktype": "^2.1.20", "cheerio": "^1.0.0", "dedent": "^1.5.1", "eslint-plugin-markdown": "^4.0.1", @@ -59,13 +63,12 @@ "ms": "^2.1.3", "read-pkg-up": "^7.0.1", "safe-stringify": "^1.1.0", - "strip-ansi": "6.0.1" + "strip-ansi": "6.0.1", + "zod": "^3.25.48" }, "devDependencies": { - "@babel/types": "7.12.11", "@eslint/config-inspector": "^0.4.11", "@playwright/test": "^1.40.0", - "@types/babel__generator": "7.6.2", "@types/babel__traverse": "7.11.0", "@types/dedent": "0.7.0", "@types/glob": "7.1.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index adc874f..a75ca4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,20 +9,29 @@ importers: .: dependencies: '@babel/core': - specifier: ^7.11.6 - version: 7.19.6 + specifier: ^7.27.1 + version: 7.27.1 '@babel/generator': - specifier: ~7.12.0 - version: 7.12.17 + specifier: ^7.27.1 + version: 7.27.1 '@babel/parser': - specifier: ^7.11.5 - version: 7.19.6 + specifier: ^7.27.1 + version: 7.27.1 '@babel/traverse': - specifier: ^7.11.5 - version: 7.19.6 + specifier: ^7.27.1 + version: 7.27.1 + '@babel/types': + specifier: ^7.27.1 + version: 7.27.1 '@pnpm/deps.graph-sequencer': specifier: ^1.0.0 version: 1.0.0 + '@types/babel__core': + specifier: ^7.20.5 + version: 7.20.5 + '@types/babel__generator': + specifier: ^7.27.0 + version: 7.27.0 '@types/dedent': specifier: 0.7.0 version: 0.7.0 @@ -41,6 +50,9 @@ importers: '@types/node': specifier: ^20.0.0 version: 20.9.4 + arktype: + specifier: ^2.1.20 + version: 2.1.20 cheerio: specifier: ^1.0.0 version: 1.0.0 @@ -83,19 +95,16 @@ importers: strip-ansi: specifier: 6.0.1 version: 6.0.1 + zod: + specifier: ^3.25.48 + version: 3.25.48 devDependencies: - '@babel/types': - specifier: 7.12.11 - version: 7.12.11 '@eslint/config-inspector': specifier: ^0.4.11 version: 0.4.11(eslint@8.57.1) '@playwright/test': specifier: ^1.40.0 version: 1.40.0 - '@types/babel__generator': - specifier: 7.6.2 - version: 7.6.2 '@types/babel__traverse': specifier: 7.11.0 version: 7.11.0 @@ -152,6 +161,12 @@ packages: resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} engines: {node: '>=6.0.0'} + '@ark/schema@0.46.0': + resolution: {integrity: sha512-c2UQdKgP2eqqDArfBqQIJppxJHvNNXuQPeuSPlDML4rjw+f1cu0qAlzOG4b8ujgm9ctIDWwhpyw6gjG5ledIVQ==} + + '@ark/util@0.46.0': + resolution: {integrity: sha512-JPy/NGWn/lvf1WmGCPw2VGpBg5utZraE84I7wli18EDF3p3zc/e9WolT35tINeZO3l7C77SjqRJeAUoT0CvMRg==} + '@babel/code-frame@7.18.6': resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} engines: {node: '>=6.9.0'} @@ -160,77 +175,61 @@ packages: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.19.4': - resolution: {integrity: sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/core@7.19.6': - resolution: {integrity: sha512-D2Ue4KHpc6Ys2+AxpIx1BZ8+UegLLLE2p3KJEuJRKmokHOtl49jQ5ny1773KsGLZs8MQvBidAF6yWUJxRqtKtg==} + '@babel/compat-data@7.27.1': + resolution: {integrity: sha512-Q+E+rd/yBzNQhXkG+zQnF58e4zoZfBedaxwzPmicKsiK3nt8iJYrSrDbjwFFDGC4f+rPafqRaPH6TsDoSvMf7A==} engines: {node: '>=6.9.0'} - '@babel/generator@7.12.17': - resolution: {integrity: sha512-DSA7ruZrY4WI8VxuS1jWSRezFnghEoYEFrZcw9BizQRmOZiUsiHl59+qEARGPqPikwA/GPTyRCi7isuCK/oyqg==} - - '@babel/generator@7.19.6': - resolution: {integrity: sha512-oHGRUQeoX1QrKeJIKVe0hwjGqNnVYsM5Nep5zo0uE0m42sLH+Fsd2pStJ5sRM1bNyTUUoz0pe2lTeMJrb/taTA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.19.3': - resolution: {integrity: sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==} + '@babel/core@7.27.1': + resolution: {integrity: sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==} engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-environment-visitor@7.18.9': - resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-function-name@7.19.0': - resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} - engines: {node: '>=6.9.0'} - - '@babel/helper-hoist-variables@7.18.6': - resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} - engines: {node: '>=6.9.0'} + '@babel/generator@7.12.17': + resolution: {integrity: sha512-DSA7ruZrY4WI8VxuS1jWSRezFnghEoYEFrZcw9BizQRmOZiUsiHl59+qEARGPqPikwA/GPTyRCi7isuCK/oyqg==} - '@babel/helper-module-imports@7.18.6': - resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} + '@babel/generator@7.27.1': + resolution: {integrity: sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.19.6': - resolution: {integrity: sha512-fCmcfQo/KYr/VXXDIyd3CBGZ6AFhPFy1TfSEJ+PilGVlQT6jcbqtHAM4C1EciRqMza7/TpOUZliuSH+U6HAhJw==} + '@babel/helper-compilation-targets@7.27.1': + resolution: {integrity: sha512-2YaDd/Rd9E598B5+WIc8wJPmWETiiJXFYVE60oX8FDohv7rAUU3CQj+A1MgeEmcsk2+dQuEjIe/GDvig0SqL4g==} engines: {node: '>=6.9.0'} - '@babel/helper-simple-access@7.19.4': - resolution: {integrity: sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==} + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} - '@babel/helper-split-export-declaration@7.18.6': - resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} + '@babel/helper-module-transforms@7.27.1': + resolution: {integrity: sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 - '@babel/helper-string-parser@7.19.4': - resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} '@babel/helper-validator-identifier@7.19.1': resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.22.20': - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.7': resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.18.6': - resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==} + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.19.4': - resolution: {integrity: sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==} + '@babel/helpers@7.27.1': + resolution: {integrity: sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==} engines: {node: '>=6.9.0'} '@babel/highlight@7.18.6': @@ -241,24 +240,21 @@ packages: resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} engines: {node: '>=6.9.0'} - '@babel/parser@7.19.6': - resolution: {integrity: sha512-h1IUp81s2JYJ3mRkdxJgs4UvmSsRvDrx5ICSJbPvtWYv5i1nTBGcBpnog+89rAFMwvvru6E5NUHdBe01UeSzYA==} + '@babel/parser@7.27.1': + resolution: {integrity: sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/template@7.18.10': - resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} + '@babel/template@7.27.1': + resolution: {integrity: sha512-Fyo3ghWMqkHHpHQCoBs2VnYjR4iWFFjguTDEqA5WgZDOrFesVjMhMM2FSqTKSoUSDO1VQtavj8NFpdRBEvJTtg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.19.6': - resolution: {integrity: sha512-6l5HrUCzFM04mfbG09AagtYyR2P0B71B1wN7PfSPiksDPz2k5H9CBC1tcZpz2M8OxbKTPccByoOJ22rUKbpmQQ==} + '@babel/traverse@7.27.1': + resolution: {integrity: sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==} engines: {node: '>=6.9.0'} - '@babel/types@7.12.11': - resolution: {integrity: sha512-ukA9SQtKThINm++CX1CwmliMrE54J6nIYB5XTwL5f/CLFW9owfls+YSU8tVW15RQ2w+a3fSbPjC6HdQNtWZkiA==} - - '@babel/types@7.19.4': - resolution: {integrity: sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==} + '@babel/types@7.27.1': + resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} engines: {node: '>=6.9.0'} '@esbuild/aix-ppc64@0.19.12': @@ -598,8 +594,8 @@ packages: resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} engines: {node: '>=6.0.0'} - '@jridgewell/gen-mapping@0.3.2': - resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} '@jridgewell/resolve-uri@3.1.0': @@ -610,6 +606,10 @@ packages: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + '@jridgewell/sourcemap-codec@1.4.14': resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} @@ -619,6 +619,9 @@ packages: '@jridgewell/trace-mapping@0.3.17': resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jsdevtools/ez-spawn@3.0.4': resolution: {integrity: sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==} engines: {node: '>=10'} @@ -861,8 +864,14 @@ packages: '@ts-morph/common@0.17.0': resolution: {integrity: sha512-RMSSvSfs9kb0VzkvQ2NWobwnj7TxCA9vI/IjR9bDHqgAyVbu2T0DN4wiKVqomyDWqO7dPr/tErSfq7urQ1Q37g==} - '@types/babel__generator@7.6.2': - resolution: {integrity: sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ==} + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} '@types/babel__traverse@7.11.0': resolution: {integrity: sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg==} @@ -1247,6 +1256,9 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} + arktype@2.1.20: + resolution: {integrity: sha512-IZCEEXaJ8g+Ijd59WtSYwtjnqXiwM8sWQ5EjGamcto7+HVN9eK0C4p0zDlCuAwWhpqr6fIBkxPuYDl4/Mcj/+Q==} + array-buffer-byte-length@1.0.2: resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} @@ -1337,8 +1349,8 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} - browserslist@4.21.4: - resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} + browserslist@4.24.5: + resolution: {integrity: sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1392,8 +1404,8 @@ packages: resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} engines: {node: '>=16'} - caniuse-lite@1.0.30001423: - resolution: {integrity: sha512-09iwWGOlifvE1XuHokFMP7eR38a0JnajoyL3/i87c8ZjRWRrdKo1fqjNfugfBD0UDBIOz0U+jtNhJ0EPm1VleQ==} + caniuse-lite@1.0.30001716: + resolution: {integrity: sha512-49/c1+x3Kwz7ZIWt+4DvK3aMJy9oYXXG6/97JKsnjdCk/6n9vVyWL8NAwVt95Lwt9eigI10Hl782kDfZUUlRXw==} chai@4.4.1: resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} @@ -1535,8 +1547,8 @@ packages: resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} engines: {node: ^14.18.0 || >=16.10.0} - convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} cookie-es@1.1.0: resolution: {integrity: sha512-L2rLOcK0wzWSfSDA33YR+PUHDG10a8px7rUHKWbGLP4YfbsMed2KFUw5fczvDPbT98DDe3LEzviswl810apTEw==} @@ -1721,8 +1733,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.4.284: - resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} + electron-to-chromium@1.5.149: + resolution: {integrity: sha512-UyiO82eb9dVOx8YO3ajDf9jz2kKyt98DEITRdeLPstOEuTlLzDA4Gyq5K9he71TQziU5jUVu2OAu5N48HmQiyQ==} elegant-spinner@1.0.1: resolution: {integrity: sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==} @@ -1789,8 +1801,8 @@ packages: engines: {node: '>=12'} hasBin: true - escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} escape-goat@4.0.0: @@ -2714,8 +2726,8 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - json5@2.2.1: - resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true @@ -2839,6 +2851,9 @@ packages: resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==} engines: {node: 14 || >=16.14} + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -2978,8 +2993,8 @@ packages: node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} - node-releases@2.0.6: - resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -3223,6 +3238,9 @@ packages: picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -3488,10 +3506,6 @@ packages: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true - semver@6.3.0: - resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} - hasBin: true - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -3775,10 +3789,6 @@ packages: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3936,8 +3946,8 @@ packages: universal-user-agent@6.0.1: resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} - update-browserslist-db@1.0.10: - resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -4108,6 +4118,9 @@ packages: resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} engines: {node: '>=12'} + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -4131,8 +4144,8 @@ packages: resolution: {integrity: sha512-Mb6GzuRyUEl8X+6V6xzHbd4XV0au/4gOYrYP+CAfHL32uPmGswES+v2YqonZiW1NZWVA3jkssCKSU2knonm/aQ==} engines: {node: '>=20'} - zod@3.23.8: - resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + zod@3.25.48: + resolution: {integrity: sha512-0X1mz8FtgEIvaxGjdIImYpZEaZMrund9pGXm3M6vM7Reba0e2eI71KPjSCGXBfwKDPwPoywf6waUKc3/tFvX2Q==} snapshots: @@ -4143,6 +4156,12 @@ snapshots: '@jridgewell/gen-mapping': 0.1.1 '@jridgewell/trace-mapping': 0.3.17 + '@ark/schema@0.46.0': + dependencies: + '@ark/util': 0.46.0 + + '@ark/util@0.46.0': {} + '@babel/code-frame@7.18.6': dependencies: '@babel/highlight': 7.18.6 @@ -4152,101 +4171,86 @@ snapshots: '@babel/highlight': 7.23.4 chalk: 2.4.2 - '@babel/compat-data@7.19.4': {} + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.27.1': {} - '@babel/core@7.19.6': + '@babel/core@7.27.1': dependencies: '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.19.6 - '@babel/helper-compilation-targets': 7.19.3(@babel/core@7.19.6) - '@babel/helper-module-transforms': 7.19.6 - '@babel/helpers': 7.19.4 - '@babel/parser': 7.19.6 - '@babel/template': 7.18.10 - '@babel/traverse': 7.19.6 - '@babel/types': 7.19.4 - convert-source-map: 1.9.0 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.1 + '@babel/helper-compilation-targets': 7.27.1 + '@babel/helper-module-transforms': 7.27.1(@babel/core@7.27.1) + '@babel/helpers': 7.27.1 + '@babel/parser': 7.27.1 + '@babel/template': 7.27.1 + '@babel/traverse': 7.27.1 + '@babel/types': 7.27.1 + convert-source-map: 2.0.0 debug: 4.3.4 gensync: 1.0.0-beta.2 - json5: 2.2.1 - semver: 6.3.0 + json5: 2.2.3 + semver: 6.3.1 transitivePeerDependencies: - supports-color '@babel/generator@7.12.17': dependencies: - '@babel/types': 7.19.4 + '@babel/types': 7.27.1 jsesc: 2.5.2 source-map: 0.5.7 - '@babel/generator@7.19.6': + '@babel/generator@7.27.1': dependencies: - '@babel/types': 7.19.4 - '@jridgewell/gen-mapping': 0.3.2 - jsesc: 2.5.2 - - '@babel/helper-compilation-targets@7.19.3(@babel/core@7.19.6)': - dependencies: - '@babel/compat-data': 7.19.4 - '@babel/core': 7.19.6 - '@babel/helper-validator-option': 7.18.6 - browserslist: 4.21.4 - semver: 6.3.0 - - '@babel/helper-environment-visitor@7.18.9': {} - - '@babel/helper-function-name@7.19.0': - dependencies: - '@babel/template': 7.18.10 - '@babel/types': 7.19.4 - - '@babel/helper-hoist-variables@7.18.6': - dependencies: - '@babel/types': 7.19.4 + '@babel/parser': 7.27.1 + '@babel/types': 7.27.1 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 - '@babel/helper-module-imports@7.18.6': + '@babel/helper-compilation-targets@7.27.1': dependencies: - '@babel/types': 7.19.4 + '@babel/compat-data': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.24.5 + lru-cache: 5.1.1 + semver: 6.3.1 - '@babel/helper-module-transforms@7.19.6': + '@babel/helper-module-imports@7.27.1': dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.18.6 - '@babel/helper-simple-access': 7.19.4 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.18.10 - '@babel/traverse': 7.19.6 - '@babel/types': 7.19.4 + '@babel/traverse': 7.27.1 + '@babel/types': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/helper-simple-access@7.19.4': - dependencies: - '@babel/types': 7.19.4 - - '@babel/helper-split-export-declaration@7.18.6': + '@babel/helper-module-transforms@7.27.1(@babel/core@7.27.1)': dependencies: - '@babel/types': 7.19.4 + '@babel/core': 7.27.1 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.27.1 + transitivePeerDependencies: + - supports-color - '@babel/helper-string-parser@7.19.4': {} + '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.19.1': {} - '@babel/helper-validator-identifier@7.22.20': {} - '@babel/helper-validator-identifier@7.24.7': {} - '@babel/helper-validator-option@7.18.6': {} + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} - '@babel/helpers@7.19.4': + '@babel/helpers@7.27.1': dependencies: - '@babel/template': 7.18.10 - '@babel/traverse': 7.19.6 - '@babel/types': 7.19.4 - transitivePeerDependencies: - - supports-color + '@babel/template': 7.27.1 + '@babel/types': 7.27.1 '@babel/highlight@7.18.6': dependencies: @@ -4256,46 +4260,36 @@ snapshots: '@babel/highlight@7.23.4': dependencies: - '@babel/helper-validator-identifier': 7.22.20 + '@babel/helper-validator-identifier': 7.24.7 chalk: 2.4.2 js-tokens: 4.0.0 - '@babel/parser@7.19.6': + '@babel/parser@7.27.1': dependencies: - '@babel/types': 7.19.4 + '@babel/types': 7.27.1 - '@babel/template@7.18.10': + '@babel/template@7.27.1': dependencies: - '@babel/code-frame': 7.18.6 - '@babel/parser': 7.19.6 - '@babel/types': 7.19.4 + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.27.1 + '@babel/types': 7.27.1 - '@babel/traverse@7.19.6': + '@babel/traverse@7.27.1': dependencies: - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.19.6 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.19.6 - '@babel/types': 7.19.4 + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.27.1 + '@babel/parser': 7.27.1 + '@babel/template': 7.27.1 + '@babel/types': 7.27.1 debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.12.11': - dependencies: - '@babel/helper-validator-identifier': 7.19.1 - lodash: 4.17.21 - to-fast-properties: 2.0.0 - - '@babel/types@7.19.4': + '@babel/types@7.27.1': dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 '@esbuild/aix-ppc64@0.19.12': optional: true @@ -4523,18 +4517,20 @@ snapshots: '@jridgewell/gen-mapping@0.1.1': dependencies: '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/gen-mapping@0.3.2': + '@jridgewell/gen-mapping@0.3.8': dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/resolve-uri@3.1.0': {} '@jridgewell/set-array@1.1.2': {} + '@jridgewell/set-array@1.2.1': {} + '@jridgewell/sourcemap-codec@1.4.14': {} '@jridgewell/sourcemap-codec@1.4.15': {} @@ -4544,6 +4540,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jsdevtools/ez-spawn@3.0.4': dependencies: call-me-maybe: 1.0.2 @@ -4807,13 +4808,26 @@ snapshots: mkdirp: 1.0.4 path-browserify: 1.0.1 - '@types/babel__generator@7.6.2': + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.27.1 + '@babel/types': 7.27.1 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.11.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.27.1 + + '@types/babel__template@7.4.4': dependencies: - '@babel/types': 7.19.4 + '@babel/parser': 7.27.1 + '@babel/types': 7.27.1 '@types/babel__traverse@7.11.0': dependencies: - '@babel/types': 7.19.4 + '@babel/types': 7.27.1 '@types/dedent@0.7.0': {} @@ -5269,6 +5283,11 @@ snapshots: aria-query@5.3.2: {} + arktype@2.1.20: + dependencies: + '@ark/schema': 0.46.0 + '@ark/util': 0.46.0 + array-buffer-byte-length@1.0.2: dependencies: call-bound: 1.0.4 @@ -5385,12 +5404,12 @@ snapshots: dependencies: fill-range: 7.0.1 - browserslist@4.21.4: + browserslist@4.24.5: dependencies: - caniuse-lite: 1.0.30001423 - electron-to-chromium: 1.4.284 - node-releases: 2.0.6 - update-browserslist-db: 1.0.10(browserslist@4.21.4) + caniuse-lite: 1.0.30001716 + electron-to-chromium: 1.5.149 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.5) buffer-from@1.1.2: {} @@ -5439,7 +5458,7 @@ snapshots: camelcase@8.0.0: {} - caniuse-lite@1.0.30001423: {} + caniuse-lite@1.0.30001716: {} chai@4.4.1: dependencies: @@ -5596,7 +5615,7 @@ snapshots: consola@3.2.3: {} - convert-source-map@1.9.0: {} + convert-source-map@2.0.0: {} cookie-es@1.1.0: {} @@ -5767,7 +5786,7 @@ snapshots: eastasianwidth@0.2.0: {} - electron-to-chromium@1.4.284: {} + electron-to-chromium@1.5.149: {} elegant-spinner@1.0.1: {} @@ -5938,7 +5957,7 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - escalade@3.1.1: {} + escalade@3.2.0: {} escape-goat@4.0.0: {} @@ -5982,10 +6001,10 @@ snapshots: eslint-plugin-codegen@0.29.0(eslint@8.57.1): dependencies: - '@babel/core': 7.19.6 + '@babel/core': 7.27.1 '@babel/generator': 7.12.17 - '@babel/parser': 7.19.6 - '@babel/traverse': 7.19.6 + '@babel/parser': 7.27.1 + '@babel/traverse': 7.27.1 '@pnpm/deps.graph-sequencer': 1.0.0 '@types/dedent': 0.7.0 '@types/eslint': 8.44.7 @@ -7048,7 +7067,7 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} - json5@2.2.1: {} + json5@2.2.3: {} jsonc-parser@3.2.1: {} @@ -7193,6 +7212,10 @@ snapshots: lru-cache@10.0.1: {} + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + lru-cache@6.0.0: dependencies: yallist: 4.0.0 @@ -7313,7 +7336,7 @@ snapshots: node-fetch-native@1.6.4: {} - node-releases@2.0.6: {} + node-releases@2.0.19: {} normalize-package-data@2.5.0: dependencies: @@ -7623,6 +7646,8 @@ snapshots: picocolors@1.0.1: {} + picocolors@1.1.1: {} + picomatch@2.3.1: {} pkg-dir@4.2.0: @@ -7710,7 +7735,7 @@ snapshots: quick-lru: 7.0.0 url-join: 5.0.0 validate-npm-package-name: 5.0.1 - zod: 3.23.8 + zod: 3.25.48 zod-package-json: 1.0.3 query-string@9.0.0: @@ -7931,8 +7956,6 @@ snapshots: semver@5.7.1: {} - semver@6.3.0: {} - semver@6.3.1: {} semver@7.5.4: @@ -8226,8 +8249,6 @@ snapshots: dependencies: os-tmpdir: 1.0.2 - to-fast-properties@2.0.0: {} - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -8380,11 +8401,11 @@ snapshots: universal-user-agent@6.0.1: {} - update-browserslist-db@1.0.10(browserslist@4.21.4): + update-browserslist-db@1.1.3(browserslist@4.24.5): dependencies: - browserslist: 4.21.4 - escalade: 3.1.1 - picocolors: 1.0.0 + browserslist: 4.24.5 + escalade: 3.2.0 + picocolors: 1.1.1 update-notifier@7.3.1: dependencies: @@ -8577,6 +8598,8 @@ snapshots: xdg-basedir@5.1.0: {} + yallist@3.1.1: {} + yallist@4.0.0: {} yn@3.1.1: {} @@ -8589,6 +8612,6 @@ snapshots: zod-package-json@1.0.3: dependencies: - zod: 3.23.8 + zod: 3.25.48 - zod@3.23.8: {} + zod@3.25.48: {} diff --git a/src/dependencies.ts b/src/dependencies.ts index 9dd87df..251bd14 100644 --- a/src/dependencies.ts +++ b/src/dependencies.ts @@ -1,3 +1,7 @@ +import * as babelGenerator from '@babel/generator' +import * as babelParser from '@babel/parser' +import * as babelTraverse from '@babel/traverse' +import * as babelTypes from '@babel/types' import * as cheerio from 'cheerio' import * as child_process from 'child_process' import dedent from 'dedent' @@ -11,6 +15,7 @@ import * as readPkgUp from 'read-pkg-up' import {fetchSync} from './fetch-sync' import {makeSynchronous} from './make-synchronous' import * as presetsModule from './presets' +import * as simplify from './simplify' export const dependencies: presetsModule.PresetDependencies = { dedent: Object.assign(dedent, {default: dedent}), // backcompat: accidentally used `import * as dedent from 'dedent'` previously @@ -23,5 +28,10 @@ export const dependencies: presetsModule.PresetDependencies = { child_process, makeSynchronous, fetchSync, + simplify, cheerio, + babelParser, + babelTraverse, + babelGenerator: babelGenerator as never, + babelTypes, } diff --git a/src/index.ts b/src/index.ts index 2b4c5a5..d0f1d55 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,7 @@ import {codegen} from './rule' // idea: codegen/fs rule. type fs.anything and it generates an import for fs. same for path and os. export type {Preset} from './presets' +export type {DefinePreset} from './presets/util/standard-schema-preset' const processor = createProcessor() diff --git a/src/presets/copy.ts b/src/presets/copy.ts new file mode 100644 index 0000000..aeb363b --- /dev/null +++ b/src/presets/copy.ts @@ -0,0 +1,94 @@ +import {definePreset} from './util/standard-schema-preset' + +/** + * Copies a whole other file. Useful for "borrowing" an implementation of a simple utility from another project, without needing to publish it. + * Obviously this creates duplicated code, so use judiciously! + * + * ##### basic usage + * ```js + * // codegen:start {preset: copy, source: ../../another-project/src/some-file.ts} + * import {z} from 'zod' + * export const MyObject = z.object({ foo: z.string() }) + * // codegen:end + * ``` + * + * #### excludeLines + * + * ```ts + * ; + * import {z} from 'zod/v4' // in this project we use zod v4, but we're copying from a project that uses zod v3 + * // codegen:start {preset: copy, source: ../../another-project/src/some-file.ts, excludeLines: ['^import']} + * ; + * export const MyObject = z.object({ foo: z.string() }) + * // codegen:end + * ``` + * + * #### onlyIfExists + * ```js + * // copy a file from a sibling project, but only if the sibling project actually exists + * // in this case this will effectively skip the copying step on machines that don't have the sibling project installed + * // e.g. on CI runners. + * // codegen:start {preset: copy, source: ../../another-project/src/some-file.ts, onlyIfExists: ../../another-project/package.json} + * ; + * import {z} from 'zod' + * ; + * export const MyObject = z.object({ foo: z.string() }); + * ; + * // codegen:end + * ``` + * + * #### comparison + * ```js + * // by default, the content will perform a "simplified" comparison with existing content, so differences from tools like prettier + * // are ignored. if you care about whitespace and similar differences, you can set the comparison option to `strict`. + * // codegen:start {preset: copy, source: ../../another-project/src/some-file.ts, comparison: strict} + * ; + * import {z} from "zod" + * ; + * export const MyObject = z.object({ foo: z.string() }) + * ; + * // codegen:end + * ``` + */ +export const copy = definePreset( + { + /** path to the file to copy. can be absolute or relative to the file being linted */ + source: 'string', + /** if provided, only runs if this file exists - if it's missing, the existing content is returned (defaulting to empty string) */ + onlyIfExists: 'string | undefined', + /** if provided, these lines will be removed from the copied content. e.g. `excludeLines: ['^import', '// codegen:']` */ + excludeLines: 'string[] | undefined', + /** + * if set to `strict` the content will update if it's not a perfect match. by default (`simplified`) it will only update + * if the "simplified" version of the content is different. + */ + comparison: '"simplified" | "strict" | undefined', + }, + ({options, meta, context, dependencies: {fs, path, simplify}}) => { + // todo: add an option to allow syncing the other way - that is, if the content on the file being linted is newer, + // don't autofix - offer two suggestions: 1) write to the source file, 2) write to the file being linted. + const getAbsolutePath = (filepath: string) => path.resolve(path.dirname(context.physicalFilename), filepath) + const shouldRun = options.onlyIfExists ? fs.existsSync(getAbsolutePath(options.onlyIfExists)) : true + if (!shouldRun) return meta.existingContent || '' + + let content = fs.readFileSync(getAbsolutePath(options.source), 'utf8') + if (options.excludeLines) { + const regexes = options.excludeLines.map(line => new RegExp(line)) + const lines = content.split('\n') + content = lines.filter(line => !regexes.some(regex => regex.test(line))).join('\n') + } + + let isUpToDate: boolean + // eslint-disable-next-line unicorn/prefer-ternary + if (!options.comparison || options.comparison === 'simplified') { + // we only want to declare it outdated if the simplified versions are different + isUpToDate = simplify.equivalentSimplified(content, meta.existingContent) + } else { + isUpToDate = content === meta.existingContent + } + + if (isUpToDate) return meta.existingContent || '' + + return content + }, +) diff --git a/src/presets/custom.ts b/src/presets/custom.ts index 2f0639b..4125241 100644 --- a/src/presets/custom.ts +++ b/src/presets/custom.ts @@ -1,5 +1,6 @@ import type {Preset} from '.' import * as path from 'path' +import {definePreset} from './util/standard-schema-preset' const tsxAvailable = () => { try { @@ -94,7 +95,10 @@ export const custom: Preset> = ({c // eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment const sourceModule = require(sourcePath) // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any - const func: Preset = options.export ? sourceModule[options.export] : sourceModule + let func: Preset = options.export ? sourceModule[options.export] : sourceModule + if (Array.isArray(func)) { + func = definePreset(func[0], func[1] as never) + } if (typeof func !== 'function') { throw new TypeError(`Couldn't find export ${options.export || 'function'} from ${sourcePath} - got ${typeof func}`) } diff --git a/src/presets/index.ts b/src/presets/index.ts index 28b0e12..6b9c902 100644 --- a/src/presets/index.ts +++ b/src/presets/index.ts @@ -26,6 +26,11 @@ export interface PresetDependencies { cheerio: typeof import('cheerio') makeSynchronous: typeof import('../make-synchronous').makeSynchronous fetchSync: typeof import('../fetch-sync').fetchSync + simplify: typeof import('../simplify') + babelParser: typeof import('@babel/parser') + babelTraverse: typeof import('@babel/traverse') + babelGenerator: typeof import('../types/babel-generator') + babelTypes: typeof import('@babel/types') } export interface CacheOptions { @@ -57,6 +62,7 @@ export type Preset = (params: PresetParams) => // codegen:start {preset: barrel} export * from './barrel' +export * from './copy' export * from './custom' export * from './empty' export * from './labeler' diff --git a/src/presets/markdown-from-jsdoc.ts b/src/presets/markdown-from-jsdoc.ts index 5a2bd18..aae10c8 100644 --- a/src/presets/markdown-from-jsdoc.ts +++ b/src/presets/markdown-from-jsdoc.ts @@ -5,6 +5,7 @@ import {Node} from '@babel/types' import * as lodash from 'lodash' import * as os from 'os' import * as path from 'path' +import {equivalentSimplified} from '../simplify' /** * Convert jsdoc for an es export from a javascript/typescript file to markdown. @@ -30,11 +31,11 @@ export const markdownFromJsdoc: Preset<{source: string; export?: string; headerL ExportNamedDeclaration({node: decl}) { switch (decl.declaration?.type) { case 'ClassDeclaration': { - idable[decl.declaration.id.name] = decl as Node + idable[decl.declaration.id!.name] = decl as Node for (const node of decl.declaration.body.body) { if (node.type === 'ClassPrivateMethod' || node.type === 'ClassPrivateProperty') continue if ('key' in node && 'name' in node.key) { - idable[`${decl.declaration.id.name}: ${node.key.name}`] = node as Node + idable[`${decl.declaration.id!.name}: ${node.key.name}`] = node as Node } } break @@ -147,5 +148,7 @@ export const markdownFromJsdoc: Preset<{source: string; export?: string; headerL throw new Error(`Couldn't find export in ${targetFile} with jsdoc called ${exportName}`) } - return blocks.join('\n\n') + const expected = blocks.join('\n\n') + if (equivalentSimplified(expected, meta.existingContent)) return meta.existingContent + return expected } diff --git a/src/presets/util/standard-schema-preset.ts b/src/presets/util/standard-schema-preset.ts new file mode 100644 index 0000000..189aaa3 --- /dev/null +++ b/src/presets/util/standard-schema-preset.ts @@ -0,0 +1,65 @@ +import * as arktype from 'arktype' +import {Preset} from '../..' +import {StandardSchemaV1, looksLikeStandardSchemaFailure, prettifyStandardSchemaError} from '../../standard-schema' + +type $ = {} +/** define a preset using an arktype schema definition. note that you don't have to import arktype */ +export function definePreset>( + def: arktype.type.validate, + fn: arktype.type.infer extends Record + ? Preset> + : 'Options must be an object', +): Exclude +/** define a perset using any standard-schema definition (zod, arktype, effect, etc.) */ +export function definePreset( + schema: StandardSchemaV1, + fn: Preset, +): Preset + +export function definePreset(schema: unknown, fn: Preset<{}> | string): typeof fn { + if (typeof fn === 'string') { + throw new Error(`Invalid options/implementation: ${fn}`) + } + if (schema && '~standard' in (schema as StandardSchemaV1)) { + return definePresetFromStandardSchema(schema as StandardSchemaV1<{}, {}>, fn) + } + return definePresetFromStandardSchema(arktype.type(schema as never) as never, fn) +} + +const definePresetFromStandardSchema = ( + schema: StandardSchemaV1, + fn: Preset, +): Preset => { + return params => { + const result = schema['~standard'].validate(params.options) + if (result instanceof Promise) { + throw new Error('Standard Schema validation is async') + } + if (looksLikeStandardSchemaFailure(result)) { + throw new Error(`Invalid options: ${prettifyStandardSchemaError(result.issues)}`) + } + return fn({...params, options: result.value as never}) + } +} + +/** + * Use this to define a preset, with runtime and compile-time type checking, without importing any values from this library. + * All you need to do is implement an identity function, then at lint time the plugin will do the rest. + * + * @example + * ```ts + * const definePreset: import('eslint-plugin-codegen').DefinePreset = (...args) => args + * + * export const myPreset = definePreset({ foo: 'string' }, ({options}) => { + * return options.foo.slice() + * }) + * ``` + * + * (you can use jsdoc to define the type in plain js too) + * */ +export type DefinePreset = >( + def: arktype.type.validate, + fn: arktype.type.infer extends Record + ? Preset> + : 'Options must be an object', +) => [typeof def, typeof fn] diff --git a/src/simplify.ts b/src/simplify.ts new file mode 100644 index 0000000..d67fd23 --- /dev/null +++ b/src/simplify.ts @@ -0,0 +1,15 @@ +/** removes all non-alphanumeric characters and converts to lowercase */ +export const simplifyContent = (content: string) => { + return content.replaceAll(/\W+/g, '').toLowerCase() +} + +/** + * returns true if the simplified versions of the two strings are the same + * can be useful if you want to know if two large blocks of code are equivalent - note that + * in theory this could return false positives for totally different inputs, since it ignores + * all formatting, punctuation, etc. V unlikely that you'll have two different inputs with the + * exact same letters in the same order, but different meanings. + */ +export const equivalentSimplified = (left: string, right: string) => { + return simplifyContent(left) === simplifyContent(right) +} diff --git a/src/standard-schema.ts b/src/standard-schema.ts new file mode 100644 index 0000000..82639a9 --- /dev/null +++ b/src/standard-schema.ts @@ -0,0 +1,118 @@ +/** The Standard Schema interface. */ +export interface StandardSchemaV1 { + /** The Standard Schema properties. */ + readonly '~standard': StandardSchemaV1.Props +} + +export declare namespace StandardSchemaV1 { + /** The Standard Schema properties interface. */ + export interface Props { + /** The version number of the standard. */ + readonly version: 1 + /** The vendor name of the schema library. */ + readonly vendor: string + /** Validates unknown input values. */ + readonly validate: (value: unknown) => Result | Promise> + /** Inferred types associated with the schema. */ + readonly types?: Types | undefined + } + + /** The result interface of the validate function. */ + export type Result = SuccessResult | FailureResult + + /** The result interface if validation succeeds. */ + export interface SuccessResult { + /** The typed output value. */ + readonly value: Output + /** The non-existent issues. */ + readonly issues?: undefined + } + + /** The result interface if validation fails. */ + export interface FailureResult { + /** The issues of failed validation. */ + readonly issues: ReadonlyArray + } + + /** The issue interface of the failure output. */ + export interface Issue { + /** The error message of the issue. */ + readonly message: string + /** The path of the issue, if any. */ + readonly path?: ReadonlyArray | undefined + } + + /** The path segment interface of the issue. */ + export interface PathSegment { + /** The key representing a path segment. */ + readonly key: PropertyKey + } + + /** The Standard Schema types interface. */ + export interface Types { + /** The input type of the schema. */ + readonly input: Input + /** The output type of the schema. */ + readonly output: Output + } + + /** Infers the input type of a Standard Schema. */ + export type InferInput = NonNullable['input'] + + /** Infers the output type of a Standard Schema. */ + export type InferOutput = NonNullable['output'] +} + +export const looksLikeStandardSchemaFailure = (error: unknown): error is StandardSchemaV1.FailureResult => { + return !!error && typeof error === 'object' && 'issues' in error && Array.isArray(error.issues) +} + +export const looksLikeStandardSchema = (thing: unknown): thing is StandardSchemaV1 => { + return !!thing && typeof thing === 'object' && '~standard' in thing && typeof thing['~standard'] === 'object' +} + +export const prettifyStandardSchemaError = (error: unknown): string | null => { + if (!looksLikeStandardSchemaFailure(error)) return null + + const issues = [...error.issues] + .map(issue => { + const path = issue.path || [] + const primitivePathSegments = path.map(segment => { + if (typeof segment === 'string' || typeof segment === 'number' || typeof segment === 'symbol') return segment + return segment.key + }) + const dotPath = toDotPath(primitivePathSegments) + return { + issue, + path, + primitivePathSegments, + dotPath, + } + }) + .sort((a, b) => a.path.length - b.path.length) + + const lines: string[] = [] + + for (const {issue, dotPath} of issues) { + let message = `✖ ${issue.message}` + if (dotPath) message += ` → at ${dotPath}` + lines.push(message) + } + + return lines.join('\n') +} + +export function toDotPath(path: (string | number | symbol)[]): string { + const segs: string[] = [] + for (const seg of path) { + if (typeof seg === 'number') segs.push(`[${seg}]`) + else if (typeof seg === 'symbol') segs.push(`[${JSON.stringify(String(seg))}]`) + else if (/[^\w$]/.test(seg)) segs.push(`[${JSON.stringify(seg)}]`) + else { + if (segs.length) segs.push('.') + segs.push(seg) + } + } + + return segs.join('') +} diff --git a/src/types/babel-generator.ts b/src/types/babel-generator.ts new file mode 100644 index 0000000..a0bf691 --- /dev/null +++ b/src/types/babel-generator.ts @@ -0,0 +1,213 @@ +// todo: make a "copy" preset? +import * as t from '@babel/types' + +export interface GeneratorOptions { + /** + * Optional string to add as a block comment at the start of the output file. + */ + auxiliaryCommentBefore?: string | undefined + + /** + * Optional string to add as a block comment at the end of the output file. + */ + auxiliaryCommentAfter?: string | undefined + + /** + * Function that takes a comment (as a string) and returns true if the comment should be included in the output. + * By default, comments are included if `opts.comments` is `true` or if `opts.minifed` is `false` and the comment + * contains `@preserve` or `@license`. + */ + shouldPrintComment?(comment: string): boolean + + /** + * Attempt to use the same line numbers in the output code as in the source code (helps preserve stack traces). + * Defaults to `false`. + */ + retainLines?: boolean | undefined + + /** + * Retain parens around function expressions (could be used to change engine parsing behavior) + * Defaults to `false`. + */ + retainFunctionParens?: boolean | undefined + + /** + * Should comments be included in output? Defaults to `true`. + */ + comments?: boolean | undefined + + /** + * Set to true to avoid adding whitespace for formatting. Defaults to the value of `opts.minified`. + */ + compact?: boolean | 'auto' | undefined + + /** + * Should the output be minified. Defaults to `false`. + */ + minified?: boolean | undefined + + /** + * Set to true to reduce whitespace (but not as much as opts.compact). Defaults to `false`. + */ + concise?: boolean | undefined + + /** + * Used in warning messages + */ + filename?: string | undefined + + /** + * Enable generating source maps. Defaults to `false`. + */ + sourceMaps?: boolean | undefined + + /** + * A root for all relative URLs in the source map. + */ + sourceRoot?: string | undefined + + /** + * The filename for the source code (i.e. the code in the `code` argument). + * This will only be used if `code` is a string. + */ + sourceFileName?: string | undefined + + /** + * Set to true to run jsesc with "json": true to print "\u00A9" vs. "©"; + */ + jsonCompatibleStrings?: boolean | undefined + + /** + * Set to true to enable support for experimental decorators syntax before module exports. + * Defaults to `false`. + */ + decoratorsBeforeExport?: boolean | undefined + + /** + * The import attributes/assertions syntax to use. + * When not specified, @babel/generator will try to match the style in the input code based on the AST shape. + */ + importAttributesKeyword?: 'with' | 'assert' | 'with-legacy' + + /** + * Options for outputting jsesc representation. + */ + jsescOption?: + | { + /** + * The default value for the quotes option is 'single'. This means that any occurrences of ' in the input + * string are escaped as \', so that the output can be used in a string literal wrapped in single quotes. + */ + quotes?: 'single' | 'double' | 'backtick' | undefined + + /** + * The default value for the numbers option is 'decimal'. This means that any numeric values are represented + * using decimal integer literals. Other valid options are binary, octal, and hexadecimal, which result in + * binary integer literals, octal integer literals, and hexadecimal integer literals, respectively. + */ + numbers?: 'binary' | 'octal' | 'decimal' | 'hexadecimal' | undefined + + /** + * The wrap option takes a boolean value (true or false), and defaults to false (disabled). When enabled, the + * output is a valid JavaScript string literal wrapped in quotes. The type of quotes can be specified through + * the quotes setting. + */ + wrap?: boolean | undefined + + /** + * The es6 option takes a boolean value (true or false), and defaults to false (disabled). When enabled, any + * astral Unicode symbols in the input are escaped using ECMAScript 6 Unicode code point escape sequences + * instead of using separate escape sequences for each surrogate half. If backwards compatibility with ES5 + * environments is a concern, don’t enable this setting. If the json setting is enabled, the value for the es6 + * setting is ignored (as if it was false). + */ + es6?: boolean | undefined + + /** + * The escapeEverything option takes a boolean value (true or false), and defaults to false (disabled). When + * enabled, all the symbols in the output are escaped — even printable ASCII symbols. + */ + escapeEverything?: boolean | undefined + + /** + * The minimal option takes a boolean value (true or false), and defaults to false (disabled). When enabled, + * only a limited set of symbols in the output are escaped: \0, \b, \t, \n, \f, \r, \\, \u2028, \u2029. + */ + minimal?: boolean | undefined + + /** + * The isScriptContext option takes a boolean value (true or false), and defaults to false (disabled). When + * enabled, occurrences of or