From 88fbfce3fb3ae541801c4906ff099cf0894fd950 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 16:12:49 +0100 Subject: [PATCH 01/56] update deps --- .eslintrc.cjs | 80 - eslint.config.mjs | 139 ++ package.json | 51 +- pnpm-lock.yaml | 3994 +++++++++++++++++------------------- schema.json | 4 +- scripts/gen-schema.ts | 13 +- src/CLI.ts | 8 +- src/Configuration.ts | 107 +- src/Core.ts | 292 ++- src/Markdown.ts | 31 +- src/Parser.ts | 230 +-- test/Configuration.test.ts | 2 +- 12 files changed, 2410 insertions(+), 2541 deletions(-) delete mode 100644 .eslintrc.cjs create mode 100644 eslint.config.mjs diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 28592a3..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,80 +0,0 @@ -/* eslint-disable no-undef */ -module.exports = { - ignorePatterns: ["dist", "*.mjs", "docs", "*.md"], - parser: "@typescript-eslint/parser", - parserOptions: { - ecmaVersion: 2018, - sourceType: "module" - }, - settings: { - "import/parsers": { - "@typescript-eslint/parser": [".ts", ".tsx"] - }, - "import/resolver": { - typescript: { - alwaysTryTypes: true - } - } - }, - extends: [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@effect/recommended" - ], - plugins: ["deprecation", "import", "sort-destructure-keys", "simple-import-sort", "codegen"], - rules: { - "codegen/codegen": "error", - "no-fallthrough": "off", - "no-irregular-whitespace": "off", - "object-shorthand": "error", - "prefer-destructuring": "off", - "sort-imports": "off", - "no-unused-vars": "off", - "prefer-rest-params": "off", - "prefer-spread": "off", - "import/first": "error", - "import/no-cycle": "error", - "import/newline-after-import": "error", - "import/no-duplicates": "error", - "import/no-unresolved": "off", - "import/order": "off", - "simple-import-sort/imports": "off", - "sort-destructure-keys/sort-destructure-keys": "error", - "deprecation/deprecation": "off", - "@typescript-eslint/array-type": ["warn", { "default": "generic", "readonly": "generic" }], - "@typescript-eslint/member-delimiter-style": 0, - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/ban-types": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-empty-interface": "off", - "@typescript-eslint/no-empty-object-type": "off", - "@typescript-eslint/consistent-type-imports": "warn", - "@typescript-eslint/no-unused-vars": ["error", { - "argsIgnorePattern": "^_", - "varsIgnorePattern": "^_" - }], - "@typescript-eslint/ban-ts-comment": "off", - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/no-array-constructor": "off", - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-namespace": "off", - "@effect/dprint": [ - "error", - { - config: { - "indentWidth": 2, - "lineWidth": 100, - "semiColons": "asi", - "quoteStyle": "alwaysDouble", - "trailingCommas": "never", - "operatorPosition": "maintain", - "arrowFunction.useParentheses": "force" - } - } - ] - } -} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..5cb490c --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,139 @@ +import { fixupPluginRules } from "@eslint/compat" +import { FlatCompat } from "@eslint/eslintrc" +import js from "@eslint/js" +import tsParser from "@typescript-eslint/parser" +import codegen from "eslint-plugin-codegen" +import _import from "eslint-plugin-import" +import simpleImportSort from "eslint-plugin-simple-import-sort" +import sortDestructureKeys from "eslint-plugin-sort-destructure-keys" +import path from "node:path" +import { fileURLToPath } from "node:url" + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}) + +export default [ + { + ignores: ["**/dist", "**/build", "**/docs", "**/*.md"] + }, + ...compat.extends( + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@effect/recommended" + ), + { + plugins: { + import: fixupPluginRules(_import), + "sort-destructure-keys": sortDestructureKeys, + "simple-import-sort": simpleImportSort, + codegen + }, + + languageOptions: { + parser: tsParser, + ecmaVersion: 2018, + sourceType: "module" + }, + + settings: { + "import/parsers": { + "@typescript-eslint/parser": [".ts", ".tsx"] + }, + + "import/resolver": { + typescript: { + alwaysTryTypes: true + } + } + }, + + rules: { + "codegen/codegen": "error", + "no-fallthrough": "off", + "no-irregular-whitespace": "off", + "object-shorthand": "error", + "prefer-destructuring": "off", + "sort-imports": "off", + + "no-restricted-syntax": [ + "error", + { + selector: "CallExpression[callee.property.name='push'] > SpreadElement.arguments", + message: "Do not use spread arguments in Array.push" + } + ], + + "no-unused-vars": "off", + "require-yield": "off", + "prefer-rest-params": "off", + "prefer-spread": "off", + "import/first": "error", + "import/newline-after-import": "error", + "import/no-duplicates": "error", + "import/no-unresolved": "off", + "import/order": "off", + "simple-import-sort/imports": "off", + "sort-destructure-keys/sort-destructure-keys": "error", + "deprecation/deprecation": "off", + + "@typescript-eslint/array-type": [ + "warn", + { + default: "generic", + readonly: "generic" + } + ], + + "@typescript-eslint/member-delimiter-style": 0, + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-empty-interface": "off", + "@typescript-eslint/consistent-type-imports": "warn", + + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_" + } + ], + + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/camelcase": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/interface-name-prefix": "off", + "@typescript-eslint/no-array-constructor": "off", + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/no-namespace": "off", + + "@effect/dprint": [ + "error", + { + config: { + indentWidth: 2, + lineWidth: 120, + semiColons: "asi", + quoteStyle: "alwaysDouble", + trailingCommas: "never", + operatorPosition: "maintain", + "arrowFunction.useParentheses": "force" + } + } + ] + } + }, + { + files: ["packages/*/src/**/*", "packages/*/test/**/*"], + rules: { + "no-console": "error" + } + } +] diff --git a/package.json b/package.json index a83283a..a839dd8 100644 --- a/package.json +++ b/package.json @@ -38,41 +38,40 @@ "dependencies": { "@effect/markdown-toc": "^0.1.0", "doctrine": "^3.0.0", - "glob": "^10.3.12", - "prettier": "^3.2.5" + "glob": "^11.0.1", + "prettier": "^3.5.2" }, "devDependencies": { "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.7", - "@effect/cli": "0.42.0", - "@effect/eslint-plugin": "^0.2.0", - "@effect/language-service": "^0.1.0", - "@effect/platform": "0.63.0", - "@effect/platform-node": "0.58.0", - "@effect/schema": "0.72.0", + "@effect/cli": "0.56.2", + "@effect/eslint-plugin": "0.2.x", + "@effect/language-service": "^0.2.0", + "@effect/platform": "0.77.2", + "@effect/platform-node": "0.73.2", + "@eslint/compat": "^1.2.7", "@types/doctrine": "0.0.9", "@types/glob": "^8.1.0", - "@types/node": "^22.5.2", - "@typescript-eslint/eslint-plugin": "^8.3.0", - "@typescript-eslint/parser": "^8.3.0", - "@vitest/coverage-v8": "^2.0.5", - "chalk": "^5.3.0", - "effect": "3.7.0", - "eslint": "^8.56.0", - "eslint-import-resolver-typescript": "^3.6.3", - "eslint-plugin-codegen": "^0.28.0", - "eslint-plugin-deprecation": "^3.0.0", - "eslint-plugin-import": "^2.29.1", + "@types/node": "^22.13.5", + "@typescript-eslint/eslint-plugin": "^8.25.0", + "@typescript-eslint/parser": "^8.25.0", + "@vitest/coverage-v8": "^3.0.7", + "chalk": "^5.4.1", + "effect": "3.13.2", + "eslint": "^9.21.0", + "eslint-import-resolver-typescript": "^3.8.3", + "eslint-plugin-codegen": "^0.29.0", + "eslint-plugin-import": "^2.31.0", "eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-sort-destructure-keys": "^2.0.0", "rimraf": "^6.0.1", - "ts-morph": "^23.0.0", - "tsconfck": "^3.1.3", - "tsup": "^8.2.4", - "tsx": "^4.19.0", - "typescript": "^5.5.4", - "vite": "^5.4.2", - "vitest": "^2.0.5" + "ts-morph": "^25.0.1", + "tsconfck": "^3.1.5", + "tsup": "^8.4.0", + "tsx": "^4.19.3", + "typescript": "^5.7.3", + "vite": "^6.2.0", + "vitest": "^3.0.7" }, "peerDependencies": { "tsx": "^4.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9715be2..84107ab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,11 +15,11 @@ importers: specifier: ^3.0.0 version: 3.0.0 glob: - specifier: ^10.3.12 - version: 10.3.12 + specifier: ^11.0.1 + version: 11.0.1 prettier: - specifier: ^3.2.5 - version: 3.2.5 + specifier: ^3.5.2 + version: 3.5.2 devDependencies: '@changesets/changelog-github': specifier: ^0.5.0 @@ -28,23 +28,23 @@ importers: specifier: ^2.27.7 version: 2.27.7 '@effect/cli': - specifier: 0.42.0 - version: 0.42.0(@effect/platform@0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0))(@effect/printer-ansi@0.35.0(@effect/typeclass@0.26.0(effect@3.7.0))(effect@3.7.0))(@effect/printer@0.35.0(@effect/typeclass@0.26.0(effect@3.7.0))(effect@3.7.0))(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0) + specifier: 0.56.2 + version: 0.56.2(@effect/platform@0.77.2(effect@3.13.2))(@effect/printer-ansi@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2))(@effect/printer@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2))(effect@3.13.2) '@effect/eslint-plugin': - specifier: ^0.2.0 + specifier: 0.2.x version: 0.2.0 '@effect/language-service': - specifier: ^0.1.0 - version: 0.1.0 + specifier: ^0.2.0 + version: 0.2.0 '@effect/platform': - specifier: 0.63.0 - version: 0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0) + specifier: 0.77.2 + version: 0.77.2(effect@3.13.2) '@effect/platform-node': - specifier: 0.58.0 - version: 0.58.0(@effect/platform@0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0))(effect@3.7.0) - '@effect/schema': - specifier: 0.72.0 - version: 0.72.0(effect@3.7.0) + specifier: 0.73.2 + version: 0.73.2(@effect/platform@0.77.2(effect@3.13.2))(effect@3.13.2) + '@eslint/compat': + specifier: ^1.2.7 + version: 1.2.7(eslint@9.21.0) '@types/doctrine': specifier: 0.0.9 version: 0.0.9 @@ -52,139 +52,124 @@ importers: specifier: ^8.1.0 version: 8.1.0 '@types/node': - specifier: ^22.5.2 - version: 22.5.2 + specifier: ^22.13.5 + version: 22.13.5 '@typescript-eslint/eslint-plugin': - specifier: ^8.3.0 - version: 8.3.0(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint@8.56.0)(typescript@5.5.4) + specifier: ^8.25.0 + version: 8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0)(typescript@5.7.3) '@typescript-eslint/parser': - specifier: ^8.3.0 - version: 8.3.0(eslint@8.56.0)(typescript@5.5.4) + specifier: ^8.25.0 + version: 8.25.0(eslint@9.21.0)(typescript@5.7.3) '@vitest/coverage-v8': - specifier: ^2.0.5 - version: 2.0.5(vitest@2.0.5(@types/node@22.5.2)) + specifier: ^3.0.7 + version: 3.0.7(vitest@3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0)) chalk: - specifier: ^5.3.0 - version: 5.3.0 + specifier: ^5.4.1 + version: 5.4.1 effect: - specifier: 3.7.0 - version: 3.7.0 + specifier: 3.13.2 + version: 3.13.2 eslint: - specifier: ^8.56.0 - version: 8.56.0 + specifier: ^9.21.0 + version: 9.21.0 eslint-import-resolver-typescript: - specifier: ^3.6.3 - version: 3.6.3(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.56.0) + specifier: ^3.8.3 + version: 3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0) eslint-plugin-codegen: - specifier: ^0.28.0 - version: 0.28.0(eslint@8.56.0) - eslint-plugin-deprecation: - specifier: ^3.0.0 - version: 3.0.0(eslint@8.56.0)(typescript@5.5.4) + specifier: ^0.29.0 + version: 0.29.0(eslint@9.21.0) eslint-plugin-import: - specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.3)(eslint@8.56.0) + specifier: ^2.31.0 + version: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0) eslint-plugin-simple-import-sort: specifier: ^12.1.1 - version: 12.1.1(eslint@8.56.0) + version: 12.1.1(eslint@9.21.0) eslint-plugin-sort-destructure-keys: specifier: ^2.0.0 - version: 2.0.0(eslint@8.56.0) + version: 2.0.0(eslint@9.21.0) rimraf: specifier: ^6.0.1 version: 6.0.1 ts-morph: - specifier: ^23.0.0 - version: 23.0.0 + specifier: ^25.0.1 + version: 25.0.1 tsconfck: - specifier: ^3.1.3 - version: 3.1.3(typescript@5.5.4) + specifier: ^3.1.5 + version: 3.1.5(typescript@5.7.3) tsup: - specifier: ^8.2.4 - version: 8.2.4(postcss@8.4.44)(tsx@4.19.0)(typescript@5.5.4)(yaml@2.5.0) + specifier: ^8.4.0 + version: 8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@5.7.3)(yaml@2.7.0) tsx: - specifier: ^4.19.0 - version: 4.19.0 + specifier: ^4.19.3 + version: 4.19.3 typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.7.3 + version: 5.7.3 vite: - specifier: ^5.4.2 - version: 5.4.2(@types/node@22.5.2) + specifier: ^6.2.0 + version: 6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) vitest: - specifier: ^2.0.5 - version: 2.0.5(@types/node@22.5.2) + specifier: ^3.0.7 + version: 3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) publishDirectory: dist packages: - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@babel/code-frame@7.24.7': - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.25.4': - resolution: {integrity: sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==} + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} engines: {node: '>=6.9.0'} - '@babel/core@7.25.2': - resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} + '@babel/core@7.26.9': + resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} engines: {node: '>=6.9.0'} '@babel/generator@7.12.17': resolution: {integrity: sha512-DSA7ruZrY4WI8VxuS1jWSRezFnghEoYEFrZcw9BizQRmOZiUsiHl59+qEARGPqPikwA/GPTyRCi7isuCK/oyqg==} - '@babel/generator@7.25.6': - resolution: {integrity: sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==} + '@babel/generator@7.26.9': + resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.25.2': - resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} + '@babel/helper-compilation-targets@7.26.5': + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.24.7': - resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.25.2': - resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-simple-access@7.24.7': - resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.24.8': - resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.24.7': - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.24.8': - resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} + '@babel/helpers@7.26.9': + resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.25.6': - resolution: {integrity: sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==} - engines: {node: '>=6.9.0'} - - '@babel/highlight@7.24.7': - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.25.6': - resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==} + '@babel/parser@7.26.9': + resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} engines: {node: '>=6.0.0'} hasBin: true @@ -192,20 +177,21 @@ packages: resolution: {integrity: sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==} engines: {node: '>=6.9.0'} - '@babel/template@7.25.0': - resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} + '@babel/template@7.26.9': + resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.25.6': - resolution: {integrity: sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==} + '@babel/traverse@7.26.9': + resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} engines: {node: '>=6.9.0'} - '@babel/types@7.25.6': - resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==} + '@babel/types@7.26.9': + resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} engines: {node: '>=6.9.0'} - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} '@changesets/apply-release-plan@7.0.4': resolution: {integrity: sha512-HLFwhKWayKinWAul0Vj+76jVx1Pc2v55MGPVjZ924Y/ROeSsBMFutv9heHmCUj48lJyRfOTJG5+ar+29FUky/A==} @@ -271,383 +257,274 @@ packages: '@dprint/formatter@0.4.1': resolution: {integrity: sha512-IB/GXdlMOvi0UhQQ9mcY15Fxcrc2JPadmo6tqefCNV0bptFq7YBpggzpqYXldBXDa04CbKJ+rDwO2eNRPE2+/g==} - '@dprint/typescript@0.91.7': - resolution: {integrity: sha512-V2Ai2qiXbv0EZnv+hAtlQVAcXx3lTA0Gn2lfMj5fMrlmMFltGv/YNxn9noukc1HkPENEmcsMA6aUBFjeyB9aIw==} + '@dprint/typescript@0.91.8': + resolution: {integrity: sha512-tuKn4leCPItox1O4uunHcQF0QllDCvPWklnNQIh2PiWWVtRAGltJJnM4Cwj5AciplosD1Hiz7vAY3ew3crLb3A==} - '@effect/cli@0.42.0': - resolution: {integrity: sha512-BCHCRVrwXDdBuK1I0Lx7C0idmiTD+GNDAOpdspw2C0YtaZD0Xkrz/YqMs5Gq4vynGE0VcFHsCzZK32x/gIHyVA==} + '@effect/cli@0.56.2': + resolution: {integrity: sha512-hhzH/iCQkT0jNGCSzuJxEASkihKNjWtcYe0cIm/GbQ5O4Mczmhb9cl/U/EPOPwfJBbAgPrO4P6ma3sYY5GuPVw==} peerDependencies: - '@effect/platform': ^0.63.0 - '@effect/printer': ^0.35.0 - '@effect/printer-ansi': ^0.35.0 - '@effect/schema': ^0.72.0 - effect: ^3.7.0 + '@effect/platform': ^0.77.2 + '@effect/printer': ^0.41.2 + '@effect/printer-ansi': ^0.41.2 + effect: ^3.13.2 '@effect/eslint-plugin@0.2.0': resolution: {integrity: sha512-PC/hEDGctYGYIjZyhM6kbD4FyHxLgoYNoQNjGkCXcFEzi71vQc3PJKe2JnCgzcUDvr/Nc2qgTVU4ONYwjHzQGA==} - '@effect/language-service@0.1.0': - resolution: {integrity: sha512-BnlM8LlaqCAYgdRfxlbR7gXGh/FD1scL1fPgNVJEPoOM08od1jtJz+iKhwfaud8TPnnhZR+TED2h5ynjanLeCQ==} + '@effect/language-service@0.2.0': + resolution: {integrity: sha512-DoK41yKGyQv79o0ca8gxEogMlt+IphXkdCXwgenbQjH1BXKD7tJAr0+VsDhblycQcvQ39f1l9NZN9CBqjM9ALA==} '@effect/markdown-toc@0.1.0': resolution: {integrity: sha512-IRfvvwqQLabVTIw9hhIj4scOGIYPfa13QuEFv+dBWE6p47R+RR0J8jQvfDINFf0Vn80XXVjNRtZxkZpkKXLx2A==} engines: {node: '>=0.10.0'} hasBin: true - '@effect/platform-node-shared@0.13.0': - resolution: {integrity: sha512-AQ/kOJmie/0BMMHcCdjWkdC7yHh42my+tHqkOgJse71fwotxl1r2zXi4dADQu++iFH/fhaWQrpuUqlWvGPyz6w==} - peerDependencies: - '@effect/platform': ^0.63.0 - effect: ^3.7.0 - - '@effect/platform-node@0.58.0': - resolution: {integrity: sha512-HW7BmtemCUCaNhrXfC+qIF1T8BxUc7KBHSrvlIE6sTiWlw54h7bIld1lyksAIXeSJMoRKP9vEAroEmLigGJf9A==} + '@effect/platform-node-shared@0.27.2': + resolution: {integrity: sha512-U6eXYCOEFTrQSShnzftzLcG4ybauDMLL8uwU7kKS3s6Wzaz7ivALFSVyxgQnaxO3t2QQBePWdd9b3DVsLgiBFw==} peerDependencies: - '@effect/platform': ^0.63.0 - effect: ^3.7.0 + '@effect/platform': ^0.77.2 + effect: ^3.13.2 - '@effect/platform@0.63.0': - resolution: {integrity: sha512-24AtBGkTNzkYU4XOH3SLo9M4PyeHtW81PFwqovKPSm9+yxTLYR2lAVqFftIfaGfBqgsNVuNrh0SaELDWGdSP6Q==} + '@effect/platform-node@0.73.2': + resolution: {integrity: sha512-lO9SlcN7/Fpzu5VE/EKMxkmXt0n0vQ+rCirfGL1cNFcax9klw0A6uAJj2UvDRnX+o5YRlWNAgg5AN5uiGDUy0g==} peerDependencies: - '@effect/schema': ^0.72.0 - effect: ^3.7.0 + '@effect/platform': ^0.77.2 + effect: ^3.13.2 - '@effect/printer-ansi@0.35.0': - resolution: {integrity: sha512-4VJpGXRWDk2W9HtT1OX2OYTl/Gm4kZ2k0k0U409D/FiHfD/KSsaHuFCI4/cHnuPx+vS6AQHulVTVbKWPRlRw2w==} + '@effect/platform@0.77.2': + resolution: {integrity: sha512-stvroKHJVfjd3XhZJEPUAOgzqu9DH1vnGHIAjfs2ma6Z4qcjVpFXrxa0ZYmwRaWVIFsiADMenkN0I7XrRdAgLw==} peerDependencies: - '@effect/typeclass': ^0.26.0 - effect: ^3.7.0 + effect: ^3.13.2 - '@effect/printer@0.35.0': - resolution: {integrity: sha512-e0FY9RvTfiH20oUPIutvqXr62ycWHCVn4oZaVa63y7QbzrX1PdhqGysf+O1qq4sEZHj/1WCJ6VCCDnnys7RZnQ==} + '@effect/printer-ansi@0.41.2': + resolution: {integrity: sha512-6XQ2VIJ70Pfu9sGYdFt4lon/4IdQSgJr7gr17uRJReARs153gZaNqh+q5pJMSJQ5wvjii1gYioIC/4HH8+o+aQ==} peerDependencies: - '@effect/typeclass': ^0.26.0 - effect: ^3.7.0 + '@effect/typeclass': ^0.32.2 + effect: ^3.13.2 - '@effect/schema@0.72.0': - resolution: {integrity: sha512-I25wIy0Njx+002lmXk8xqcdFGMGkScl6EfxRE0nkoyecQVg+v1mw7DHkSwzR6CcL4s2tITwM3Z40ALJjArPqgA==} + '@effect/printer@0.41.2': + resolution: {integrity: sha512-FpKvt8Iey30kHkbl/pPmnYEmhdltuJiNX+zGfqlkArmBnz+l1EseYQ3t/LjdChcuW8reumNlMln2bQlnGKhHvw==} peerDependencies: - effect: ^3.7.0 + '@effect/typeclass': ^0.32.2 + effect: ^3.13.2 - '@effect/typeclass@0.26.0': - resolution: {integrity: sha512-rAbeESXVIm3quIWOjNSGi6p+KAtbVpzByOfj8fbBrnTHHbjhAQ9G7lG2YBtLsjUtQysW3JVWkDD+bb6i6tftFQ==} + '@effect/typeclass@0.32.2': + resolution: {integrity: sha512-kCk3E4D0vEcRnY1MotaGEA5c/1X3a3dmcUHVBs0hLxN/6ct23Lun7J87tk+U2PJAwAUvUceSS3lQska9/eDkXA==} peerDependencies: - effect: ^3.7.0 + effect: ^3.13.2 - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - - '@esbuild/aix-ppc64@0.23.1': - resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + '@esbuild/aix-ppc64@0.25.0': + resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm64@0.23.1': - resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + '@esbuild/android-arm64@0.25.0': + resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-arm@0.23.1': - resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + '@esbuild/android-arm@0.25.0': + resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/android-x64@0.23.1': - resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + '@esbuild/android-x64@0.25.0': + resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-arm64@0.23.1': - resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + '@esbuild/darwin-arm64@0.25.0': + resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/darwin-x64@0.23.1': - resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + '@esbuild/darwin-x64@0.25.0': + resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-arm64@0.23.1': - resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + '@esbuild/freebsd-arm64@0.25.0': + resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.23.1': - resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + '@esbuild/freebsd-x64@0.25.0': + resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm64@0.23.1': - resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + '@esbuild/linux-arm64@0.25.0': + resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-arm@0.23.1': - resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + '@esbuild/linux-arm@0.25.0': + resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-ia32@0.23.1': - resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + '@esbuild/linux-ia32@0.25.0': + resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-loong64@0.23.1': - resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + '@esbuild/linux-loong64@0.25.0': + resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-mips64el@0.23.1': - resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + '@esbuild/linux-mips64el@0.25.0': + resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-ppc64@0.23.1': - resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + '@esbuild/linux-ppc64@0.25.0': + resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-riscv64@0.23.1': - resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + '@esbuild/linux-riscv64@0.25.0': + resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-s390x@0.23.1': - resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + '@esbuild/linux-s390x@0.25.0': + resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/linux-x64@0.23.1': - resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + '@esbuild/linux-x64@0.25.0': + resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] + '@esbuild/netbsd-arm64@0.25.0': + resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} + engines: {node: '>=18'} + cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.23.1': - resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + '@esbuild/netbsd-x64@0.25.0': + resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.23.1': - resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + '@esbuild/openbsd-arm64@0.25.0': + resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.23.1': - resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + '@esbuild/openbsd-x64@0.25.0': + resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/sunos-x64@0.23.1': - resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + '@esbuild/sunos-x64@0.25.0': + resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-arm64@0.23.1': - resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + '@esbuild/win32-arm64@0.25.0': + resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-ia32@0.23.1': - resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + '@esbuild/win32-ia32@0.25.0': + resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@esbuild/win32-x64@0.23.1': - resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + '@esbuild/win32-x64@0.25.0': + resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.4.0': - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + '@eslint-community/eslint-utils@4.4.1': + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint-community/regexpp@4.11.0': - resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/compat@1.2.7': + resolution: {integrity: sha512-xvv7hJE32yhegJ8xNAnb62ggiAwTYHBpUCWhRxEj/ksvgDJuSXfoDkBcRYaYNFiJ+jH0IE3K16hd+xXzhBgNbg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^9.10.0 + peerDependenciesMeta: + eslint: + optional: true - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/config-array@0.19.2': + resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.56.0': - resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/core@0.12.0': + resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.0': + resolution: {integrity: sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@humanwhocodes/config-array@0.11.13': - resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} - engines: {node: '>=10.10.0'} + '@eslint/js@9.21.0': + resolution: {integrity: sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.7': + resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/object-schema@2.0.1': - resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.2': + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} + engines: {node: '>=18.18'} '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} @@ -669,8 +546,8 @@ packages: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} '@jridgewell/resolve-uri@3.1.2': @@ -709,80 +586,86 @@ packages: resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} engines: {node: '>=12.4.0'} - '@parcel/watcher-android-arm64@2.4.1': - resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==} + '@parcel/watcher-android-arm64@2.5.1': + resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [android] - '@parcel/watcher-darwin-arm64@2.4.1': - resolution: {integrity: sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==} + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [darwin] - '@parcel/watcher-darwin-x64@2.4.1': - resolution: {integrity: sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==} + '@parcel/watcher-darwin-x64@2.5.1': + resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [darwin] - '@parcel/watcher-freebsd-x64@2.4.1': - resolution: {integrity: sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==} + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [freebsd] - '@parcel/watcher-linux-arm-glibc@2.4.1': - resolution: {integrity: sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==} + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - '@parcel/watcher-linux-arm64-glibc@2.4.1': - resolution: {integrity: sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==} + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - '@parcel/watcher-linux-arm64-musl@2.4.1': - resolution: {integrity: sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==} + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - '@parcel/watcher-linux-x64-glibc@2.4.1': - resolution: {integrity: sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==} + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - '@parcel/watcher-linux-x64-musl@2.4.1': - resolution: {integrity: sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==} + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - '@parcel/watcher-win32-arm64@2.4.1': - resolution: {integrity: sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==} + '@parcel/watcher-win32-arm64@2.5.1': + resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [win32] - '@parcel/watcher-win32-ia32@2.4.1': - resolution: {integrity: sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==} + '@parcel/watcher-win32-ia32@2.5.1': + resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} engines: {node: '>= 10.0.0'} cpu: [ia32] os: [win32] - '@parcel/watcher-win32-x64@2.4.1': - resolution: {integrity: sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==} + '@parcel/watcher-win32-x64@2.5.1': + resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [win32] - '@parcel/watcher@2.4.1': - resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} + '@parcel/watcher@2.5.1': + resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} engines: {node: '>= 10.0.0'} '@pkgjs/parseargs@0.11.0': @@ -793,91 +676,112 @@ packages: resolution: {integrity: sha512-vWWVbYYBBN/kweokmURicokyg7crzcDZo9/naziv8B8RSWrLWFpq5Xl0ro6QCQKgRmb6O78Qy9uQT+Fp79RxsA==} engines: {node: '>=16.14'} - '@rollup/rollup-android-arm-eabi@4.21.2': - resolution: {integrity: sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==} + '@rollup/rollup-android-arm-eabi@4.34.8': + resolution: {integrity: sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.21.2': - resolution: {integrity: sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==} + '@rollup/rollup-android-arm64@4.34.8': + resolution: {integrity: sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.21.2': - resolution: {integrity: sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==} + '@rollup/rollup-darwin-arm64@4.34.8': + resolution: {integrity: sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.21.2': - resolution: {integrity: sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==} + '@rollup/rollup-darwin-x64@4.34.8': + resolution: {integrity: sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.21.2': - resolution: {integrity: sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==} + '@rollup/rollup-freebsd-arm64@4.34.8': + resolution: {integrity: sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.34.8': + resolution: {integrity: sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': + resolution: {integrity: sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.21.2': - resolution: {integrity: sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==} + '@rollup/rollup-linux-arm-musleabihf@4.34.8': + resolution: {integrity: sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.21.2': - resolution: {integrity: sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==} + '@rollup/rollup-linux-arm64-gnu@4.34.8': + resolution: {integrity: sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.21.2': - resolution: {integrity: sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==} + '@rollup/rollup-linux-arm64-musl@4.34.8': + resolution: {integrity: sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.21.2': - resolution: {integrity: sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==} + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': + resolution: {integrity: sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': + resolution: {integrity: sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.21.2': - resolution: {integrity: sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==} + '@rollup/rollup-linux-riscv64-gnu@4.34.8': + resolution: {integrity: sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.21.2': - resolution: {integrity: sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==} + '@rollup/rollup-linux-s390x-gnu@4.34.8': + resolution: {integrity: sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.21.2': - resolution: {integrity: sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==} + '@rollup/rollup-linux-x64-gnu@4.34.8': + resolution: {integrity: sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.21.2': - resolution: {integrity: sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==} + '@rollup/rollup-linux-x64-musl@4.34.8': + resolution: {integrity: sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.21.2': - resolution: {integrity: sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==} + '@rollup/rollup-win32-arm64-msvc@4.34.8': + resolution: {integrity: sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.21.2': - resolution: {integrity: sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==} + '@rollup/rollup-win32-ia32-msvc@4.34.8': + resolution: {integrity: sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.21.2': - resolution: {integrity: sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==} + '@rollup/rollup-win32-x64-msvc@4.34.8': + resolution: {integrity: sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==} cpu: [x64] os: [win32] + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - '@ts-morph/common@0.24.0': - resolution: {integrity: sha512-c1xMmNHWpNselmpIqursHeOHHBTIsJLbB+NuovbTTRCNiTLEr/U9dbJ8qy0jd/O2x5pc3seWuOUN5R2IoOTp8A==} + '@standard-schema/spec@1.0.0': + resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + + '@ts-morph/common@0.26.1': + resolution: {integrity: sha512-Sn28TGl/4cFpcM+jwsH1wLncYq3FtN/BIpem+HOygfBWPT5pAeS5dB4VFVzV8FbnOKHpDLZmvAl4AjPEev5idA==} '@types/dedent@0.7.0': resolution: {integrity: sha512-EGlKlgMhnLt/cM4DbUSafFdrkeJoC9Mvnj0PUCU7tFmTjMjNRT957kXCx0wYm3JuEq4o4ZsS5vG+NlkM2DMd2A==} @@ -888,8 +792,8 @@ packages: '@types/eslint@8.56.12': resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} '@types/glob@7.1.3': resolution: {integrity: sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==} @@ -915,8 +819,8 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/lodash@4.17.7': - resolution: {integrity: sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==} + '@types/lodash@4.17.15': + resolution: {integrity: sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw==} '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} @@ -927,11 +831,11 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@20.16.3': - resolution: {integrity: sha512-/wdGiWRkMOm53gAsSyFMXFZHbVg7C6CbkrzHNpaHoYfsUWPg7m6ZRKtvQjgvQ9i8WT540a3ydRlRQbxjY30XxQ==} + '@types/node@20.17.19': + resolution: {integrity: sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==} - '@types/node@22.5.2': - resolution: {integrity: sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==} + '@types/node@22.13.5': + resolution: {integrity: sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -951,123 +855,98 @@ packages: '@types/yargs@17.0.33': resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - '@typescript-eslint/eslint-plugin@8.3.0': - resolution: {integrity: sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==} + '@typescript-eslint/eslint-plugin@8.25.0': + resolution: {integrity: sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/parser@8.3.0': - resolution: {integrity: sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==} + '@typescript-eslint/parser@8.25.0': + resolution: {integrity: sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/scope-manager@7.18.0': - resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} - engines: {node: ^18.18.0 || >=20.0.0} + typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/scope-manager@8.3.0': - resolution: {integrity: sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==} + '@typescript-eslint/scope-manager@8.25.0': + resolution: {integrity: sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.3.0': - resolution: {integrity: sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==} + '@typescript-eslint/type-utils@8.25.0': + resolution: {integrity: sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/types@7.18.0': - resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} - engines: {node: ^18.18.0 || >=20.0.0} + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/types@8.3.0': - resolution: {integrity: sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==} + '@typescript-eslint/types@8.25.0': + resolution: {integrity: sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@7.18.0': - resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/typescript-estree@8.3.0': - resolution: {integrity: sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==} + '@typescript-eslint/typescript-estree@8.25.0': + resolution: {integrity: sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/utils@7.18.0': - resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 + typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/utils@8.3.0': - resolution: {integrity: sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==} + '@typescript-eslint/utils@8.25.0': + resolution: {integrity: sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/visitor-keys@7.18.0': - resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/visitor-keys@8.3.0': - resolution: {integrity: sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==} + '@typescript-eslint/visitor-keys@8.25.0': + resolution: {integrity: sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@ungap/structured-clone@1.2.0': - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - - '@vitest/coverage-v8@2.0.5': - resolution: {integrity: sha512-qeFcySCg5FLO2bHHSa0tAZAOnAUbp4L6/A5JDuj9+bt53JREl8hpLjLHEWF0e/gWc8INVpJaqA7+Ene2rclpZg==} + '@vitest/coverage-v8@3.0.7': + resolution: {integrity: sha512-Av8WgBJLTrfLOer0uy3CxjlVuWK4CzcLBndW1Nm2vI+3hZ2ozHututkfc7Blu1u6waeQ7J8gzPK/AsBRnWA5mQ==} peerDependencies: - vitest: 2.0.5 + '@vitest/browser': 3.0.7 + vitest: 3.0.7 + peerDependenciesMeta: + '@vitest/browser': + optional: true - '@vitest/expect@2.0.5': - resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==} + '@vitest/expect@3.0.7': + resolution: {integrity: sha512-QP25f+YJhzPfHrHfYHtvRn+uvkCFCqFtW9CktfBxmB+25QqWsx7VB2As6f4GmwllHLDhXNHvqedwhvMmSnNmjw==} - '@vitest/pretty-format@2.0.5': - resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==} + '@vitest/mocker@3.0.7': + resolution: {integrity: sha512-qui+3BLz9Eonx4EAuR/i+QlCX6AUZ35taDQgwGkK/Tw6/WgwodSrjN1X2xf69IA/643ZX5zNKIn2svvtZDrs4w==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true - '@vitest/runner@2.0.5': - resolution: {integrity: sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig==} + '@vitest/pretty-format@3.0.7': + resolution: {integrity: sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg==} - '@vitest/snapshot@2.0.5': - resolution: {integrity: sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew==} + '@vitest/runner@3.0.7': + resolution: {integrity: sha512-WeEl38Z0S2ZcuRTeyYqaZtm4e26tq6ZFqh5y8YD9YxfWuu0OFiGFUbnxNynwLjNRHPsXyee2M9tV7YxOTPZl2g==} - '@vitest/spy@2.0.5': - resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==} + '@vitest/snapshot@3.0.7': + resolution: {integrity: sha512-eqTUryJWQN0Rtf5yqCGTQWsCFOQe4eNz5Twsu21xYEcnFJtMU5XvmG0vgebhdLlrHQTSq5p8vWHJIeJQV8ovsA==} - '@vitest/utils@2.0.5': - resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==} + '@vitest/spy@3.0.7': + resolution: {integrity: sha512-4T4WcsibB0B6hrKdAZTM37ekuyFZt2cGbEGd2+L0P8ov15J1/HUsUaqkXEQPNAWr4BtPPe1gI+FYfMHhEKfR8w==} + + '@vitest/utils@3.0.7': + resolution: {integrity: sha512-xePVpCRfooFX3rANQjwoditoXgWb1MaFbzmGuPP59MK6i13mrnDw/yEIyJudLeW6/38mCNcwCiJIGmpDPibAIg==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.11.2: - resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} engines: {node: '>=0.4.0'} hasBin: true @@ -1082,8 +961,8 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} ansi-styles@3.2.1: @@ -1105,52 +984,53 @@ packages: any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - array-buffer-byte-length@1.0.0: - resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} - array-includes@3.1.7: - resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} engines: {node: '>= 0.4'} array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - array.prototype.findlastindex@1.2.3: - resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} + array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} engines: {node: '>= 0.4'} - array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} engines: {node: '>= 0.4'} - array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.2: - resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + autolinker@0.28.1: resolution: {integrity: sha512-zQAFO1Dlsn69eXaO6+7YZc+v84aquQKbwpzCE3L0stj56ERn9hutFxPopViLjo9G+rWwjozRhgS5KJ25Xy19cQ==} - available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} balanced-match@1.0.2: @@ -1160,10 +1040,6 @@ packages: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -1174,16 +1050,16 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.23.3: - resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - bundle-require@5.0.0: - resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} peerDependencies: esbuild: '>=0.18' @@ -1192,18 +1068,27 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - call-bind@1.0.5: - resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.3: + resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} + engines: {node: '>= 0.4'} callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001655: - resolution: {integrity: sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==} + caniuse-lite@1.0.30001701: + resolution: {integrity: sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw==} - chai@5.1.1: - resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} engines: {node: '>=12'} chalk@2.4.2: @@ -1214,8 +1099,8 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} character-entities-legacy@1.1.4: @@ -1234,16 +1119,16 @@ packages: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - code-block-writer@13.0.2: - resolution: {integrity: sha512-XfXzAGiStXSmCIwrkdfvc7FS5Dtj8yelCtyOf2p2skCAfvLd6zu0rGzuS9NSCO3bq1JKpFZ7tbKdKlcd5occQA==} + code-block-writer@13.0.3: + resolution: {integrity: sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==} color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -1272,8 +1157,8 @@ packages: concat-with-sourcemaps@1.1.0: resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} - consola@3.2.3: - resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + consola@3.4.0: + resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} engines: {node: ^14.18.0 || >=16.10.0} convert-source-map@2.0.0: @@ -1289,6 +1174,22 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + dataloader@1.4.0: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} @@ -1300,17 +1201,8 @@ packages: supports-color: optional: true - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - debug@4.3.6: - resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1333,8 +1225,8 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - define-data-property@1.1.1: - resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} define-properties@1.2.1: @@ -1374,14 +1266,18 @@ packages: resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} engines: {node: '>=10'} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - effect@3.7.0: - resolution: {integrity: sha512-TXrb4SHTHrij396NfvGgpOD/5Sh503LtN2AeskkB7YO6Oe1tWSekk8dcrj3AWbMDOJ/fXOvcf6HD+Svus2zIeA==} + effect@3.13.2: + resolution: {integrity: sha512-/w+CPqHDJ33Wq7xC4YKAchrEEPtjvxh563xH9kDTZp99seNYBoBs87vl8DJwartEjj+KLQLP8PzoDne+XmGT2A==} - electron-to-chromium@1.5.13: - resolution: {integrity: sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==} + electron-to-chromium@1.5.107: + resolution: {integrity: sha512-dJr1o6yCntRkXElnhsHh1bAV19bo/hKyFf7tCcWgpXbuFIF0Lakjgqv5LRfSDaNzAII8Fnxg2tqgHkgCvxdbxw==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1389,8 +1285,8 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - enhanced-resolve@5.17.1: - resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} engines: {node: '>=10.13.0'} enquirer@2.4.1: @@ -1400,28 +1296,39 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.22.3: - resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + es-abstract@1.23.9: + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} - es-set-tostringtag@2.0.2: - resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} - es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} - esbuild@0.23.1: - resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + esbuild@0.25.0: + resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==} engines: {node: '>=18'} hasBin: true @@ -1444,8 +1351,8 @@ packages: eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - eslint-import-resolver-typescript@3.6.3: - resolution: {integrity: sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==} + eslint-import-resolver-typescript@3.8.3: + resolution: {integrity: sha512-A0bu4Ks2QqDWNpeEgTQMPTngaMhuDu4yv6xpftBMAf+1ziXnpx+eSR1WRfoPTe2BAiAjHFZ7kSNx1fvr5g5pmQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -1457,8 +1364,8 @@ packages: eslint-plugin-import-x: optional: true - eslint-module-utils@2.8.0: - resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + eslint-module-utils@2.12.0: + resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -1478,43 +1385,16 @@ packages: eslint-import-resolver-webpack: optional: true - eslint-module-utils@2.8.2: - resolution: {integrity: sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - - eslint-plugin-codegen@0.28.0: - resolution: {integrity: sha512-tM8Pj0Ej2QYqN7hpREA8IJ2P36fpvW5TIu8Vx/Y4JlyLy+pAO8PsVYRIdw0+qQ900eCQSyDoSa93O0+NfNjbnQ==} + eslint-plugin-codegen@0.29.0: + resolution: {integrity: sha512-C5NqptnJgf5ngxAaPg125OodjYeDD1o79Q2QbRV4Ga8WGX70KyC9KgB5walRy037fl9/JFC8PKVB9lwLOBbVGw==} engines: {node: '>=18.0.0'} - eslint-plugin-deprecation@3.0.0: - resolution: {integrity: sha512-JuVLdNg/uf0Adjg2tpTyYoYaMbwQNn/c78P1HcccokvhtRphgnRjZDKmhlxbxYptppex03zO76f97DD/yQHv7A==} - peerDependencies: - eslint: ^8.0.0 - typescript: ^4.2.4 || ^5.0.0 - - eslint-plugin-import@2.29.1: - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + eslint-plugin-import@2.31.0: + resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 peerDependenciesMeta: '@typescript-eslint/parser': optional: true @@ -1536,30 +1416,39 @@ packages: peerDependencies: eslint: 5 - 9 - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@8.2.0: + resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint@8.56.0: - resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.21.0: + resolution: {integrity: sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -1577,18 +1466,14 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - expand-range@1.8.2: resolution: {integrity: sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==} engines: {node: '>=0.10.0'} + expect-type@1.1.0: + resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} + engines: {node: '>=12.0.0'} + expect@29.7.0: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1604,8 +1489,8 @@ packages: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} - fast-check@3.22.0: - resolution: {integrity: sha512-8HKz3qXqnHYp/VCNn2qfjHdAdcI8zcSqOyX64GOMukp7SL2bfzfeDKjSd+UyECtejccaZv3LcvZTm9YDD22iCQ==} + fast-check@3.23.2: + resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} engines: {node: '>=8.0.0'} fast-deep-equal@3.1.3: @@ -1618,6 +1503,10 @@ packages: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -1627,9 +1516,17 @@ packages: fastq@1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} fill-range@2.2.4: resolution: {integrity: sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==} @@ -1653,15 +1550,16 @@ packages: find-yarn-workspace-root2@1.2.16: resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} - flatted@3.2.9: - resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} for-in@1.0.2: resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} @@ -1671,8 +1569,8 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} - foreground-child@3.3.0: - resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} fp-ts@2.16.9: @@ -1686,9 +1584,6 @@ packages: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} engines: {node: '>=6 <7 || >=8'} - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1697,8 +1592,8 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} engines: {node: '>= 0.4'} functions-have-names@1.2.3: @@ -1708,26 +1603,20 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - - get-intrinsic@1.2.2: - resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} - get-symbol-description@1.0.0: - resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} - get-tsconfig@4.8.0: - resolution: {integrity: sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==} + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} @@ -1737,42 +1626,34 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.3.12: - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true - glob@11.0.0: - resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} + glob@11.0.1: + resolution: {integrity: sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==} engines: {node: 20 || >=22} hasBin: true - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - globals@13.24.0: - resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} - engines: {node: '>=8'} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} - globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} - gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -1788,8 +1669,9 @@ packages: resolution: {integrity: sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==} deprecated: Removed event-stream from gulp-header - has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} @@ -1799,23 +1681,23 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - has-property-descriptors@1.0.1: - resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} engines: {node: '>= 0.4'} - has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} - has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} hosted-git-info@2.8.9: @@ -1827,37 +1709,22 @@ packages: human-id@1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} - ignore@5.3.0: - resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} - engines: {node: '>= 4'} - ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -1865,15 +1732,15 @@ packages: resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - internal-slot@1.0.6: - resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} io-ts-extra@0.11.6: resolution: {integrity: sha512-rTsvx3W5B2nx7p/eGf+OsEaBTmjSjLzxBDEiweCjwqIL9ZN6CZjG7hFK8zyGJyM0I2uCsRU4uYUhaTgg2SKHkQ==} - io-ts@2.2.21: - resolution: {integrity: sha512-zz2Z69v9ZIC3mMLYWIeoUcwWD6f+O7yP92FMVVaXEOSZH1jnVBmET/urd/uoarD1WGBY4rCj8TAyMPzsGNzMFQ==} + io-ts@2.2.22: + resolution: {integrity: sha512-FHCCztTkHoV9mdBsHpocLpdTAfh956ZQcIkWQxxS0U5HT53vtrcuYdQneEJKH6xILaLNzXVl2Cvwtoy8XNN0AA==} peerDependencies: fp-ts: ^2.5.0 @@ -1883,38 +1750,45 @@ packages: is-alphanumerical@1.0.4: resolution: {integrity: sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==} - is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} - is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} is-buffer@1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - is-bun-module@1.1.0: - resolution: {integrity: sha512-4mTAVPlrXpaN3jtF0lsnPCMGnq4+qZjVIKq0HCpfcqf8OC1SM5oATCIAPM5V5FN05qp2NNnFndphmdZS9CV3hA==} + is-bun-module@1.3.0: + resolution: {integrity: sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==} is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} - is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} is-decimal@1.0.4: @@ -1932,10 +1806,18 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -1943,12 +1825,12 @@ packages: is-hexadecimal@1.0.4: resolution: {integrity: sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==} - is-negative-zero@2.0.2: - resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} - is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} is-number@2.1.0: @@ -1963,47 +1845,49 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - is-plain-object@2.0.4: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} - is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} - is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} - is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} is-subdir@1.2.0: resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} engines: {node: '>=4'} - is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} - is-typed-array@1.1.12: - resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} - is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} is-windows@1.0.2: resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} @@ -2042,15 +1926,11 @@ packages: resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} - jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - jackspeak@4.0.1: - resolution: {integrity: sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==} + jackspeak@4.1.0: + resolution: {integrity: sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==} engines: {node: 20 || >=22} jest-diff@29.7.0: @@ -2093,6 +1973,11 @@ packages: engines: {node: '>=4'} hasBin: true + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -2140,8 +2025,8 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lilconfig@3.1.2: - resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} lines-and-columns@1.2.4: @@ -2188,18 +2073,14 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - loupe@3.1.1: - resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} - - lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.0.0: - resolution: {integrity: sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==} + lru-cache@11.0.2: + resolution: {integrity: sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==} engines: {node: 20 || >=22} lru-cache@4.1.5: @@ -2208,8 +2089,8 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - magic-string@0.30.11: - resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} magicast@0.3.5: resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} @@ -2222,6 +2103,10 @@ packages: resolution: {integrity: sha512-TurLymbyLyo+kAUUAV9ggR9EPcDjP/ctlv9QAFiqUH7c+t6FlsbivPo9OKTU8xdOx9oNd2drW/Fi5RRElQbUqA==} engines: {node: '>=0.10.0'} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + math-random@1.0.4: resolution: {integrity: sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==} @@ -2231,9 +2116,6 @@ packages: mdast-util-to-string@2.0.0: resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -2250,14 +2132,6 @@ packages: engines: {node: '>=10.0.0'} hasBin: true - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - minimatch@10.0.1: resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} engines: {node: 20 || >=22} @@ -2276,10 +2150,6 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -2288,18 +2158,10 @@ packages: resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} engines: {node: '>=0.10.0'} - mkdirp@3.0.1: - resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} - engines: {node: '>=10'} - hasBin: true - mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} - ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -2309,8 +2171,8 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2332,67 +2194,46 @@ packages: encoding: optional: true - node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + 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==} - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - object.fromentries@2.0.7: - resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} engines: {node: '>= 0.4'} - object.groupby@1.0.1: - resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} object.pick@1.3.0: resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} engines: {node: '>=0.10.0'} - object.values@1.1.7: - resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - - optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} os-tmpdir@1.0.2: @@ -2402,6 +2243,10 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} engines: {node: '>=8'} @@ -2433,6 +2278,9 @@ packages: package-json-from-dist@1.0.0: resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -2451,25 +2299,13 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} - path-scurry@1.11.1: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} @@ -2482,20 +2318,24 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} pathval@2.0.0: resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} engines: {node: '>= 14.16'} - 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'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -2508,6 +2348,10 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + postcss-load-config@6.0.1: resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} engines: {node: '>= 18'} @@ -2526,8 +2370,8 @@ packages: yaml: optional: true - postcss@8.4.44: - resolution: {integrity: sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==} + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} preferred-pm@3.1.4: @@ -2547,8 +2391,8 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + prettier@3.5.2: + resolution: {integrity: sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==} engines: {node: '>=14'} hasBin: true @@ -2594,15 +2438,19 @@ packages: readable-stream@2.3.8: resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regexp.prototype.flags@1.5.1: - resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} remarkable@1.7.4: @@ -2629,41 +2477,42 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} hasBin: true reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - rimraf@6.0.1: resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} engines: {node: 20 || >=22} hasBin: true - rollup@4.21.2: - resolution: {integrity: sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==} + rollup@4.34.8: + resolution: {integrity: sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - safe-array-concat@1.0.1: - resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - safe-regex-test@1.0.0: - resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -2681,18 +2530,27 @@ packages: engines: {node: '>=10'} hasBin: true - set-function-length@1.1.1: - resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} - set-function-name@2.0.1: - resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} set-getter@0.1.1: resolution: {integrity: sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==} engines: {node: '>=0.10.0'} + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -2709,8 +2567,21 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -2726,8 +2597,8 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} - source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} source-map@0.5.7: @@ -2754,12 +2625,15 @@ packages: spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - spdx-license-ids@3.0.20: - resolution: {integrity: sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==} + spdx-license-ids@3.0.21: + resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stable-hash@0.0.4: + resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -2767,8 +2641,8 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@3.7.0: - resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + std-env@3.8.0: + resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -2778,15 +2652,17 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string.prototype.trim@1.2.8: - resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} - string.prototype.trimend@1.0.7: - resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} - string.prototype.trimstart@1.0.7: - resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -2811,14 +2687,6 @@ packages: resolution: {integrity: sha512-p9LsUieSjWNNAxVCXLeilaDlmuUOrDS5/dF9znM1nZc7EGX5+zEFC0bEevsNIaldjlks+2jns5Siz6F9iK6jwA==} engines: {node: '>=0.10.0'} - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -2852,9 +2720,6 @@ packages: resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} engines: {node: '>=18'} - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -2868,26 +2733,29 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinypool@1.0.1: - resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==} + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} + + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} engines: {node: ^18.0.0 || >=20.0.0} - tinyrainbow@1.2.0: - resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - tinyspy@3.0.0: - resolution: {integrity: sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA==} + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} tmp@0.0.33: 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-object-path@0.3.0: resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} engines: {node: '>=0.10.0'} @@ -2909,20 +2777,20 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true - ts-api-utils@1.3.0: - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} + ts-api-utils@2.0.1: + resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + engines: {node: '>=18.12'} peerDependencies: - typescript: '>=4.2.0' + typescript: '>=4.8.4' ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - ts-morph@23.0.0: - resolution: {integrity: sha512-FcvFx7a9E8TUe6T3ShihXJLiJOiqyafzFKUO4aqIHDUCIvADdGNShcbc2W5PMr3LerXRv7mafvFZ9lRENxJmug==} + ts-morph@25.0.1: + resolution: {integrity: sha512-QJEiTdnz1YjrB3JFhd626gX4rKHDLSjSVMvGGG4v7ONc3RBwa0Eei98G9AT9uNFDMtV54JyuXsFeC+OH0n6bXQ==} - tsconfck@3.1.3: - resolution: {integrity: sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==} + tsconfck@3.1.5: + resolution: {integrity: sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg==} engines: {node: ^18 || >=20} hasBin: true peerDependencies: @@ -2934,11 +2802,8 @@ packages: tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} - tslib@2.7.0: - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - - tsup@8.2.4: - resolution: {integrity: sha512-akpCPePnBnC/CXgRrcy72ZSntgIEUa1jN0oJbbvpALWKNOz1B7aM+UVDWGRGIO/T/PZugAESWDJUAb5FD48o8Q==} + tsup@8.4.0: + resolution: {integrity: sha512-b+eZbPCjz10fRryaAA7C8xlIHnf8VnsaRqydheLIqwG/Mcpfk8Z5zp3HayX7GaTygkigHl5cBUs+IhcySiIexQ==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -2956,8 +2821,8 @@ packages: typescript: optional: true - tsx@4.19.0: - resolution: {integrity: sha512-bV30kM7bsLZKZIOCHeMNVMJ32/LuJzLVajkQI/qf92J2Qr08ueLQvW00PUZGiuLPP760UINwupgUj8qrSCPUKg==} + tsx@4.19.3: + resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} engines: {node: '>=18.0.0'} hasBin: true @@ -2965,10 +2830,6 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - type-fest@0.6.0: resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} engines: {node: '>=8'} @@ -2977,38 +2838,43 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} - typed-array-buffer@1.0.0: - resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} - typed-array-byte-length@1.0.0: - resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.0: - resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} engines: {node: '>= 0.4'} - typed-array-length@1.0.4: - resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} engines: {node: '>=14.17'} hasBin: true - unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - undici@6.19.8: - resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} - engines: {node: '>=18.17'} + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + undici@7.3.0: + resolution: {integrity: sha512-Qy96NND4Dou5jKoSJ2gm8ax8AJM/Ey9o9mz7KN1bb9GP+G0l20Zw8afxTnY2f4b7hmhn/z8aC2kfArVQlAhFBw==} + engines: {node: '>=20.18.1'} unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} @@ -3017,8 +2883,8 @@ packages: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} - update-browserslist-db@1.1.0: - resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -3032,27 +2898,32 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - vite-node@2.0.5: - resolution: {integrity: sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q==} - engines: {node: ^18.0.0 || >=20.0.0} + vite-node@3.0.7: + resolution: {integrity: sha512-2fX0QwX4GkkkpULXdT1Pf4q0tC1i1lFOyseKoonavXUNlQ77KpW2XqBGGNIm/J4Ows4KxgGJzDguYVPKwG/n5A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - vite@5.4.2: - resolution: {integrity: sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==} - engines: {node: ^18.0.0 || >=20.0.0} + vite@6.2.0: + resolution: {integrity: sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' less: '*' lightningcss: ^1.21.0 sass: '*' sass-embedded: '*' stylus: '*' sugarss: '*' - terser: ^5.4.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 peerDependenciesMeta: '@types/node': optional: true + jiti: + optional: true less: optional: true lightningcss: @@ -3067,21 +2938,28 @@ packages: optional: true terser: optional: true + tsx: + optional: true + yaml: + optional: true - vitest@2.0.5: - resolution: {integrity: sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA==} - engines: {node: ^18.0.0 || >=20.0.0} + vitest@3.0.7: + resolution: {integrity: sha512-IP7gPK3LS3Fvn44x30X1dM9vtawm0aesAa2yBIZ9vQf+qB69NXC5776+Qmcr7ohUXIQuLhk7xQR0aSUIDPqavg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.0.5 - '@vitest/ui': 2.0.5 + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.0.7 + '@vitest/ui': 3.0.7 happy-dom: '*' jsdom: '*' peerDependenciesMeta: '@edge-runtime/vm': optional: true + '@types/debug': + optional: true '@types/node': optional: true '@vitest/browser': @@ -3105,15 +2983,24 @@ packages: whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} which-pm@2.2.0: resolution: {integrity: sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==} engines: {node: '>=8.15'} - which-typed-array@1.1.13: - resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + which-typed-array@1.1.18: + resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} engines: {node: '>= 0.4'} which@1.3.1: @@ -3130,6 +3017,10 @@ packages: engines: {node: '>=8'} hasBin: true + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -3138,11 +3029,8 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + ws@8.18.1: + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -3163,8 +3051,8 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yaml@2.5.0: - resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} + yaml@2.7.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} engines: {node: '>= 14'} hasBin: true @@ -3176,34 +3064,33 @@ publishDirectory: dist snapshots: - '@aashutoshrathi/word-wrap@1.2.6': {} - '@ampproject/remapping@2.3.0': dependencies: - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@babel/code-frame@7.24.7': + '@babel/code-frame@7.26.2': dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.0.1 + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 - '@babel/compat-data@7.25.4': {} + '@babel/compat-data@7.26.8': {} - '@babel/core@7.25.2': + '@babel/core@7.26.9': dependencies: '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.6 - '@babel/helper-compilation-targets': 7.25.2 - '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) - '@babel/helpers': 7.25.6 - '@babel/parser': 7.25.6 - '@babel/template': 7.25.0 - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helpers': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 convert-source-map: 2.0.0 - debug: 4.3.6 + debug: 4.4.0 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -3212,100 +3099,85 @@ snapshots: '@babel/generator@7.12.17': dependencies: - '@babel/types': 7.25.6 + '@babel/types': 7.26.9 jsesc: 2.5.2 source-map: 0.5.7 - '@babel/generator@7.25.6': + '@babel/generator@7.26.9': dependencies: - '@babel/types': 7.25.6 - '@jridgewell/gen-mapping': 0.3.5 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 + jsesc: 3.1.0 - '@babel/helper-compilation-targets@7.25.2': + '@babel/helper-compilation-targets@7.26.5': dependencies: - '@babel/compat-data': 7.25.4 - '@babel/helper-validator-option': 7.24.8 - browserslist: 4.23.3 + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-module-imports@7.24.7': + '@babel/helper-module-imports@7.25.9': dependencies: - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2)': + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': dependencies: - '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.6 + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.9 transitivePeerDependencies: - supports-color - '@babel/helper-simple-access@7.24.7': - dependencies: - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-string-parser@7.24.8': {} + '@babel/helper-string-parser@7.25.9': {} - '@babel/helper-validator-identifier@7.24.7': {} + '@babel/helper-validator-identifier@7.25.9': {} - '@babel/helper-validator-option@7.24.8': {} + '@babel/helper-validator-option@7.25.9': {} - '@babel/helpers@7.25.6': + '@babel/helpers@7.26.9': dependencies: - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 - - '@babel/highlight@7.24.7': - dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.1 + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 - '@babel/parser@7.25.6': + '@babel/parser@7.26.9': dependencies: - '@babel/types': 7.25.6 + '@babel/types': 7.26.9 '@babel/runtime@7.25.6': dependencies: regenerator-runtime: 0.14.1 - '@babel/template@7.25.0': + '@babel/template@7.26.9': dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 - '@babel/traverse@7.25.6': + '@babel/traverse@7.26.9': dependencies: - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.6 - '@babel/parser': 7.25.6 - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 - debug: 4.3.6 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + debug: 4.4.0 globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/types@7.25.6': + '@babel/types@7.26.9': dependencies: - '@babel/helper-string-parser': 7.24.8 - '@babel/helper-validator-identifier': 7.24.7 - to-fast-properties: 2.0.0 + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 - '@bcoe/v8-coverage@0.2.3': {} + '@bcoe/v8-coverage@1.0.2': {} '@changesets/apply-release-plan@7.0.4': dependencies: @@ -3480,26 +3352,25 @@ snapshots: '@dprint/formatter@0.4.1': {} - '@dprint/typescript@0.91.7': {} + '@dprint/typescript@0.91.8': {} - '@effect/cli@0.42.0(@effect/platform@0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0))(@effect/printer-ansi@0.35.0(@effect/typeclass@0.26.0(effect@3.7.0))(effect@3.7.0))(@effect/printer@0.35.0(@effect/typeclass@0.26.0(effect@3.7.0))(effect@3.7.0))(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0)': + '@effect/cli@0.56.2(@effect/platform@0.77.2(effect@3.13.2))(@effect/printer-ansi@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2))(@effect/printer@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2))(effect@3.13.2)': dependencies: - '@effect/platform': 0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0) - '@effect/printer': 0.35.0(@effect/typeclass@0.26.0(effect@3.7.0))(effect@3.7.0) - '@effect/printer-ansi': 0.35.0(@effect/typeclass@0.26.0(effect@3.7.0))(effect@3.7.0) - '@effect/schema': 0.72.0(effect@3.7.0) - effect: 3.7.0 + '@effect/platform': 0.77.2(effect@3.13.2) + '@effect/printer': 0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2) + '@effect/printer-ansi': 0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2) + effect: 3.13.2 ini: 4.1.3 toml: 3.0.0 - yaml: 2.5.0 + yaml: 2.7.0 '@effect/eslint-plugin@0.2.0': dependencies: '@dprint/formatter': 0.4.1 - '@dprint/typescript': 0.91.7 + '@dprint/typescript': 0.91.8 prettier-linter-helpers: 1.0.0 - '@effect/language-service@0.1.0': {} + '@effect/language-service@0.2.0': {} '@effect/markdown-toc@0.1.0': dependencies: @@ -3516,229 +3387,179 @@ snapshots: repeat-string: 1.6.1 strip-color: 0.1.0 - '@effect/platform-node-shared@0.13.0(@effect/platform@0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0))(effect@3.7.0)': + '@effect/platform-node-shared@0.27.2(@effect/platform@0.77.2(effect@3.13.2))(effect@3.13.2)': dependencies: - '@effect/platform': 0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0) - '@parcel/watcher': 2.4.1 - effect: 3.7.0 + '@effect/platform': 0.77.2(effect@3.13.2) + '@parcel/watcher': 2.5.1 + effect: 3.13.2 multipasta: 0.2.5 - '@effect/platform-node@0.58.0(@effect/platform@0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0))(effect@3.7.0)': + '@effect/platform-node@0.73.2(@effect/platform@0.77.2(effect@3.13.2))(effect@3.13.2)': dependencies: - '@effect/platform': 0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0) - '@effect/platform-node-shared': 0.13.0(@effect/platform@0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0))(effect@3.7.0) - effect: 3.7.0 + '@effect/platform': 0.77.2(effect@3.13.2) + '@effect/platform-node-shared': 0.27.2(@effect/platform@0.77.2(effect@3.13.2))(effect@3.13.2) + effect: 3.13.2 mime: 3.0.0 - undici: 6.19.8 - ws: 8.18.0 + undici: 7.3.0 + ws: 8.18.1 transitivePeerDependencies: - bufferutil - utf-8-validate - '@effect/platform@0.63.0(@effect/schema@0.72.0(effect@3.7.0))(effect@3.7.0)': + '@effect/platform@0.77.2(effect@3.13.2)': dependencies: - '@effect/schema': 0.72.0(effect@3.7.0) - effect: 3.7.0 + effect: 3.13.2 find-my-way-ts: 0.1.5 multipasta: 0.2.5 - '@effect/printer-ansi@0.35.0(@effect/typeclass@0.26.0(effect@3.7.0))(effect@3.7.0)': - dependencies: - '@effect/printer': 0.35.0(@effect/typeclass@0.26.0(effect@3.7.0))(effect@3.7.0) - '@effect/typeclass': 0.26.0(effect@3.7.0) - effect: 3.7.0 - - '@effect/printer@0.35.0(@effect/typeclass@0.26.0(effect@3.7.0))(effect@3.7.0)': + '@effect/printer-ansi@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2)': dependencies: - '@effect/typeclass': 0.26.0(effect@3.7.0) - effect: 3.7.0 + '@effect/printer': 0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2) + '@effect/typeclass': 0.32.2(effect@3.13.2) + effect: 3.13.2 - '@effect/schema@0.72.0(effect@3.7.0)': + '@effect/printer@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2)': dependencies: - effect: 3.7.0 - fast-check: 3.22.0 + '@effect/typeclass': 0.32.2(effect@3.13.2) + effect: 3.13.2 - '@effect/typeclass@0.26.0(effect@3.7.0)': + '@effect/typeclass@0.32.2(effect@3.13.2)': dependencies: - effect: 3.7.0 - - '@esbuild/aix-ppc64@0.21.5': - optional: true - - '@esbuild/aix-ppc64@0.23.1': - optional: true - - '@esbuild/android-arm64@0.21.5': - optional: true - - '@esbuild/android-arm64@0.23.1': - optional: true - - '@esbuild/android-arm@0.21.5': - optional: true - - '@esbuild/android-arm@0.23.1': - optional: true + effect: 3.13.2 - '@esbuild/android-x64@0.21.5': + '@esbuild/aix-ppc64@0.25.0': optional: true - '@esbuild/android-x64@0.23.1': + '@esbuild/android-arm64@0.25.0': optional: true - '@esbuild/darwin-arm64@0.21.5': + '@esbuild/android-arm@0.25.0': optional: true - '@esbuild/darwin-arm64@0.23.1': + '@esbuild/android-x64@0.25.0': optional: true - '@esbuild/darwin-x64@0.21.5': + '@esbuild/darwin-arm64@0.25.0': optional: true - '@esbuild/darwin-x64@0.23.1': + '@esbuild/darwin-x64@0.25.0': optional: true - '@esbuild/freebsd-arm64@0.21.5': + '@esbuild/freebsd-arm64@0.25.0': optional: true - '@esbuild/freebsd-arm64@0.23.1': + '@esbuild/freebsd-x64@0.25.0': optional: true - '@esbuild/freebsd-x64@0.21.5': + '@esbuild/linux-arm64@0.25.0': optional: true - '@esbuild/freebsd-x64@0.23.1': + '@esbuild/linux-arm@0.25.0': optional: true - '@esbuild/linux-arm64@0.21.5': + '@esbuild/linux-ia32@0.25.0': optional: true - '@esbuild/linux-arm64@0.23.1': + '@esbuild/linux-loong64@0.25.0': optional: true - '@esbuild/linux-arm@0.21.5': + '@esbuild/linux-mips64el@0.25.0': optional: true - '@esbuild/linux-arm@0.23.1': + '@esbuild/linux-ppc64@0.25.0': optional: true - '@esbuild/linux-ia32@0.21.5': + '@esbuild/linux-riscv64@0.25.0': optional: true - '@esbuild/linux-ia32@0.23.1': + '@esbuild/linux-s390x@0.25.0': optional: true - '@esbuild/linux-loong64@0.21.5': + '@esbuild/linux-x64@0.25.0': optional: true - '@esbuild/linux-loong64@0.23.1': + '@esbuild/netbsd-arm64@0.25.0': optional: true - '@esbuild/linux-mips64el@0.21.5': + '@esbuild/netbsd-x64@0.25.0': optional: true - '@esbuild/linux-mips64el@0.23.1': + '@esbuild/openbsd-arm64@0.25.0': optional: true - '@esbuild/linux-ppc64@0.21.5': + '@esbuild/openbsd-x64@0.25.0': optional: true - '@esbuild/linux-ppc64@0.23.1': + '@esbuild/sunos-x64@0.25.0': optional: true - '@esbuild/linux-riscv64@0.21.5': + '@esbuild/win32-arm64@0.25.0': optional: true - '@esbuild/linux-riscv64@0.23.1': + '@esbuild/win32-ia32@0.25.0': optional: true - '@esbuild/linux-s390x@0.21.5': + '@esbuild/win32-x64@0.25.0': optional: true - '@esbuild/linux-s390x@0.23.1': - optional: true - - '@esbuild/linux-x64@0.21.5': - optional: true - - '@esbuild/linux-x64@0.23.1': - optional: true - - '@esbuild/netbsd-x64@0.21.5': - optional: true - - '@esbuild/netbsd-x64@0.23.1': - optional: true - - '@esbuild/openbsd-arm64@0.23.1': - optional: true - - '@esbuild/openbsd-x64@0.21.5': - optional: true - - '@esbuild/openbsd-x64@0.23.1': - optional: true - - '@esbuild/sunos-x64@0.21.5': - optional: true - - '@esbuild/sunos-x64@0.23.1': - optional: true - - '@esbuild/win32-arm64@0.21.5': - optional: true - - '@esbuild/win32-arm64@0.23.1': - optional: true - - '@esbuild/win32-ia32@0.21.5': - optional: true - - '@esbuild/win32-ia32@0.23.1': - optional: true + '@eslint-community/eslint-utils@4.4.1(eslint@9.21.0)': + dependencies: + eslint: 9.21.0 + eslint-visitor-keys: 3.4.3 - '@esbuild/win32-x64@0.21.5': - optional: true + '@eslint-community/regexpp@4.12.1': {} - '@esbuild/win32-x64@0.23.1': - optional: true + '@eslint/compat@1.2.7(eslint@9.21.0)': + optionalDependencies: + eslint: 9.21.0 - '@eslint-community/eslint-utils@4.4.0(eslint@8.56.0)': + '@eslint/config-array@0.19.2': dependencies: - eslint: 8.56.0 - eslint-visitor-keys: 3.4.3 - - '@eslint-community/regexpp@4.10.0': {} + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color - '@eslint-community/regexpp@4.11.0': {} + '@eslint/core@0.12.0': + dependencies: + '@types/json-schema': 7.0.15 - '@eslint/eslintrc@2.1.4': + '@eslint/eslintrc@3.3.0': dependencies: ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.24.0 - ignore: 5.3.0 - import-fresh: 3.3.0 + debug: 4.4.0 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 js-yaml: 4.1.0 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@8.56.0': {} + '@eslint/js@9.21.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.7': + dependencies: + '@eslint/core': 0.12.0 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} - '@humanwhocodes/config-array@0.11.13': + '@humanfs/node@0.16.6': dependencies: - '@humanwhocodes/object-schema': 2.0.1 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/object-schema@2.0.1': {} + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.2': {} '@isaacs/cliui@8.0.2': dependencies: @@ -3764,11 +3585,11 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.5.2 + '@types/node': 22.13.5 '@types/yargs': 17.0.33 chalk: 4.1.2 - '@jridgewell/gen-mapping@0.3.5': + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.5.0 @@ -3815,122 +3636,138 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} - '@parcel/watcher-android-arm64@2.4.1': + '@parcel/watcher-android-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.1': optional: true - '@parcel/watcher-darwin-arm64@2.4.1': + '@parcel/watcher-darwin-x64@2.5.1': optional: true - '@parcel/watcher-darwin-x64@2.4.1': + '@parcel/watcher-freebsd-x64@2.5.1': optional: true - '@parcel/watcher-freebsd-x64@2.4.1': + '@parcel/watcher-linux-arm-glibc@2.5.1': optional: true - '@parcel/watcher-linux-arm-glibc@2.4.1': + '@parcel/watcher-linux-arm-musl@2.5.1': optional: true - '@parcel/watcher-linux-arm64-glibc@2.4.1': + '@parcel/watcher-linux-arm64-glibc@2.5.1': optional: true - '@parcel/watcher-linux-arm64-musl@2.4.1': + '@parcel/watcher-linux-arm64-musl@2.5.1': optional: true - '@parcel/watcher-linux-x64-glibc@2.4.1': + '@parcel/watcher-linux-x64-glibc@2.5.1': optional: true - '@parcel/watcher-linux-x64-musl@2.4.1': + '@parcel/watcher-linux-x64-musl@2.5.1': optional: true - '@parcel/watcher-win32-arm64@2.4.1': + '@parcel/watcher-win32-arm64@2.5.1': optional: true - '@parcel/watcher-win32-ia32@2.4.1': + '@parcel/watcher-win32-ia32@2.5.1': optional: true - '@parcel/watcher-win32-x64@2.4.1': + '@parcel/watcher-win32-x64@2.5.1': optional: true - '@parcel/watcher@2.4.1': + '@parcel/watcher@2.5.1': dependencies: detect-libc: 1.0.3 is-glob: 4.0.3 micromatch: 4.0.8 node-addon-api: 7.1.1 optionalDependencies: - '@parcel/watcher-android-arm64': 2.4.1 - '@parcel/watcher-darwin-arm64': 2.4.1 - '@parcel/watcher-darwin-x64': 2.4.1 - '@parcel/watcher-freebsd-x64': 2.4.1 - '@parcel/watcher-linux-arm-glibc': 2.4.1 - '@parcel/watcher-linux-arm64-glibc': 2.4.1 - '@parcel/watcher-linux-arm64-musl': 2.4.1 - '@parcel/watcher-linux-x64-glibc': 2.4.1 - '@parcel/watcher-linux-x64-musl': 2.4.1 - '@parcel/watcher-win32-arm64': 2.4.1 - '@parcel/watcher-win32-ia32': 2.4.1 - '@parcel/watcher-win32-x64': 2.4.1 + '@parcel/watcher-android-arm64': 2.5.1 + '@parcel/watcher-darwin-arm64': 2.5.1 + '@parcel/watcher-darwin-x64': 2.5.1 + '@parcel/watcher-freebsd-x64': 2.5.1 + '@parcel/watcher-linux-arm-glibc': 2.5.1 + '@parcel/watcher-linux-arm-musl': 2.5.1 + '@parcel/watcher-linux-arm64-glibc': 2.5.1 + '@parcel/watcher-linux-arm64-musl': 2.5.1 + '@parcel/watcher-linux-x64-glibc': 2.5.1 + '@parcel/watcher-linux-x64-musl': 2.5.1 + '@parcel/watcher-win32-arm64': 2.5.1 + '@parcel/watcher-win32-ia32': 2.5.1 + '@parcel/watcher-win32-x64': 2.5.1 '@pkgjs/parseargs@0.11.0': optional: true '@pnpm/deps.graph-sequencer@1.0.0': {} - '@rollup/rollup-android-arm-eabi@4.21.2': + '@rollup/rollup-android-arm-eabi@4.34.8': + optional: true + + '@rollup/rollup-android-arm64@4.34.8': + optional: true + + '@rollup/rollup-darwin-arm64@4.34.8': + optional: true + + '@rollup/rollup-darwin-x64@4.34.8': optional: true - '@rollup/rollup-android-arm64@4.21.2': + '@rollup/rollup-freebsd-arm64@4.34.8': optional: true - '@rollup/rollup-darwin-arm64@4.21.2': + '@rollup/rollup-freebsd-x64@4.34.8': optional: true - '@rollup/rollup-darwin-x64@4.21.2': + '@rollup/rollup-linux-arm-gnueabihf@4.34.8': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.21.2': + '@rollup/rollup-linux-arm-musleabihf@4.34.8': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.21.2': + '@rollup/rollup-linux-arm64-gnu@4.34.8': optional: true - '@rollup/rollup-linux-arm64-gnu@4.21.2': + '@rollup/rollup-linux-arm64-musl@4.34.8': optional: true - '@rollup/rollup-linux-arm64-musl@4.21.2': + '@rollup/rollup-linux-loongarch64-gnu@4.34.8': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.21.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.34.8': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.21.2': + '@rollup/rollup-linux-riscv64-gnu@4.34.8': optional: true - '@rollup/rollup-linux-s390x-gnu@4.21.2': + '@rollup/rollup-linux-s390x-gnu@4.34.8': optional: true - '@rollup/rollup-linux-x64-gnu@4.21.2': + '@rollup/rollup-linux-x64-gnu@4.34.8': optional: true - '@rollup/rollup-linux-x64-musl@4.21.2': + '@rollup/rollup-linux-x64-musl@4.34.8': optional: true - '@rollup/rollup-win32-arm64-msvc@4.21.2': + '@rollup/rollup-win32-arm64-msvc@4.34.8': optional: true - '@rollup/rollup-win32-ia32-msvc@4.21.2': + '@rollup/rollup-win32-ia32-msvc@4.34.8': optional: true - '@rollup/rollup-win32-x64-msvc@4.21.2': + '@rollup/rollup-win32-x64-msvc@4.34.8': optional: true + '@rtsao/scc@1.1.0': {} + '@sinclair/typebox@0.27.8': {} - '@ts-morph/common@0.24.0': + '@standard-schema/spec@1.0.0': {} + + '@ts-morph/common@0.26.1': dependencies: - fast-glob: 3.3.2 + fast-glob: 3.3.3 minimatch: 9.0.5 - mkdirp: 3.0.1 path-browserify: 1.0.1 '@types/dedent@0.7.0': {} @@ -3939,20 +3776,20 @@ snapshots: '@types/eslint@8.56.12': dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 '@types/json-schema': 7.0.15 - '@types/estree@1.0.5': {} + '@types/estree@1.0.6': {} '@types/glob@7.1.3': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.5.2 + '@types/node': 22.13.5 '@types/glob@8.1.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.5.2 + '@types/node': 22.13.5 '@types/istanbul-lib-coverage@2.0.6': {} @@ -3970,7 +3807,7 @@ snapshots: '@types/json5@0.0.29': {} - '@types/lodash@4.17.7': {} + '@types/lodash@4.17.15': {} '@types/mdast@3.0.15': dependencies: @@ -3980,13 +3817,13 @@ snapshots: '@types/node@12.20.55': {} - '@types/node@20.16.3': + '@types/node@20.17.19': dependencies: undici-types: 6.19.8 - '@types/node@22.5.2': + '@types/node@22.13.5': dependencies: - undici-types: 6.19.8 + undici-types: 6.20.0 '@types/normalize-package-data@2.4.4': {} @@ -4002,183 +3839,146 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.3.0(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint@8.56.0)(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0)(typescript@5.7.3)': dependencies: - '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.3.0(eslint@8.56.0)(typescript@5.5.4) - '@typescript-eslint/scope-manager': 8.3.0 - '@typescript-eslint/type-utils': 8.3.0(eslint@8.56.0)(typescript@5.5.4) - '@typescript-eslint/utils': 8.3.0(eslint@8.56.0)(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 8.3.0 - eslint: 8.56.0 + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.25.0(eslint@9.21.0)(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.25.0 + '@typescript-eslint/type-utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) + '@typescript-eslint/utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.25.0 + eslint: 9.21.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - optionalDependencies: - typescript: 5.5.4 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4)': + '@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3)': dependencies: - '@typescript-eslint/scope-manager': 8.3.0 - '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.5.4) - '@typescript-eslint/visitor-keys': 8.3.0 - debug: 4.3.6 - eslint: 8.56.0 - optionalDependencies: - typescript: 5.5.4 + '@typescript-eslint/scope-manager': 8.25.0 + '@typescript-eslint/types': 8.25.0 + '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.25.0 + debug: 4.4.0 + eslint: 9.21.0 + typescript: 5.7.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.18.0': - dependencies: - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/visitor-keys': 7.18.0 - - '@typescript-eslint/scope-manager@8.3.0': + '@typescript-eslint/scope-manager@8.25.0': dependencies: - '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/visitor-keys': 8.3.0 + '@typescript-eslint/types': 8.25.0 + '@typescript-eslint/visitor-keys': 8.25.0 - '@typescript-eslint/type-utils@8.3.0(eslint@8.56.0)(typescript@5.5.4)': + '@typescript-eslint/type-utils@8.25.0(eslint@9.21.0)(typescript@5.7.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.5.4) - '@typescript-eslint/utils': 8.3.0(eslint@8.56.0)(typescript@5.5.4) - debug: 4.3.6 - ts-api-utils: 1.3.0(typescript@5.5.4) - optionalDependencies: - typescript: 5.5.4 + '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) + '@typescript-eslint/utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) + debug: 4.4.0 + eslint: 9.21.0 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 transitivePeerDependencies: - - eslint - supports-color - '@typescript-eslint/types@7.18.0': {} - - '@typescript-eslint/types@8.3.0': {} - - '@typescript-eslint/typescript-estree@7.18.0(typescript@5.5.4)': - dependencies: - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/visitor-keys': 7.18.0 - debug: 4.3.6 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.4) - optionalDependencies: - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color + '@typescript-eslint/types@8.25.0': {} - '@typescript-eslint/typescript-estree@8.3.0(typescript@5.5.4)': + '@typescript-eslint/typescript-estree@8.25.0(typescript@5.7.3)': dependencies: - '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/visitor-keys': 8.3.0 - debug: 4.3.6 - fast-glob: 3.3.2 + '@typescript-eslint/types': 8.25.0 + '@typescript-eslint/visitor-keys': 8.25.0 + debug: 4.4.0 + fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.4) - optionalDependencies: - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@7.18.0(eslint@8.56.0)(typescript@5.5.4)': - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) - '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) - eslint: 8.56.0 + semver: 7.7.1 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 transitivePeerDependencies: - supports-color - - typescript - '@typescript-eslint/utils@8.3.0(eslint@8.56.0)(typescript@5.5.4)': + '@typescript-eslint/utils@8.25.0(eslint@9.21.0)(typescript@5.7.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) - '@typescript-eslint/scope-manager': 8.3.0 - '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.5.4) - eslint: 8.56.0 + '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0) + '@typescript-eslint/scope-manager': 8.25.0 + '@typescript-eslint/types': 8.25.0 + '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) + eslint: 9.21.0 + typescript: 5.7.3 transitivePeerDependencies: - supports-color - - typescript - '@typescript-eslint/visitor-keys@7.18.0': + '@typescript-eslint/visitor-keys@8.25.0': dependencies: - '@typescript-eslint/types': 7.18.0 - eslint-visitor-keys: 3.4.3 - - '@typescript-eslint/visitor-keys@8.3.0': - dependencies: - '@typescript-eslint/types': 8.3.0 - eslint-visitor-keys: 3.4.3 + '@typescript-eslint/types': 8.25.0 + eslint-visitor-keys: 4.2.0 - '@ungap/structured-clone@1.2.0': {} - - '@vitest/coverage-v8@2.0.5(vitest@2.0.5(@types/node@22.5.2))': + '@vitest/coverage-v8@3.0.7(vitest@3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0))': dependencies: '@ampproject/remapping': 2.3.0 - '@bcoe/v8-coverage': 0.2.3 - debug: 4.3.6 + '@bcoe/v8-coverage': 1.0.2 + debug: 4.4.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.1.7 - magic-string: 0.30.11 + magic-string: 0.30.17 magicast: 0.3.5 - std-env: 3.7.0 + std-env: 3.8.0 test-exclude: 7.0.1 - tinyrainbow: 1.2.0 - vitest: 2.0.5(@types/node@22.5.2) + tinyrainbow: 2.0.0 + vitest: 3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - supports-color - '@vitest/expect@2.0.5': + '@vitest/expect@3.0.7': dependencies: - '@vitest/spy': 2.0.5 - '@vitest/utils': 2.0.5 - chai: 5.1.1 - tinyrainbow: 1.2.0 + '@vitest/spy': 3.0.7 + '@vitest/utils': 3.0.7 + chai: 5.2.0 + tinyrainbow: 2.0.0 - '@vitest/pretty-format@2.0.5': + '@vitest/mocker@3.0.7(vite@6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0))': dependencies: - tinyrainbow: 1.2.0 + '@vitest/spy': 3.0.7 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) - '@vitest/runner@2.0.5': + '@vitest/pretty-format@3.0.7': dependencies: - '@vitest/utils': 2.0.5 - pathe: 1.1.2 + tinyrainbow: 2.0.0 - '@vitest/snapshot@2.0.5': + '@vitest/runner@3.0.7': dependencies: - '@vitest/pretty-format': 2.0.5 - magic-string: 0.30.11 - pathe: 1.1.2 + '@vitest/utils': 3.0.7 + pathe: 2.0.3 - '@vitest/spy@2.0.5': + '@vitest/snapshot@3.0.7': dependencies: - tinyspy: 3.0.0 + '@vitest/pretty-format': 3.0.7 + magic-string: 0.30.17 + pathe: 2.0.3 - '@vitest/utils@2.0.5': + '@vitest/spy@3.0.7': dependencies: - '@vitest/pretty-format': 2.0.5 - estree-walker: 3.0.3 - loupe: 3.1.1 - tinyrainbow: 1.2.0 + tinyspy: 3.0.2 - acorn-jsx@5.3.2(acorn@8.11.2): + '@vitest/utils@3.0.7': dependencies: - acorn: 8.11.2 + '@vitest/pretty-format': 3.0.7 + loupe: 3.1.3 + tinyrainbow: 2.0.0 - acorn@8.11.2: {} + acorn-jsx@5.3.2(acorn@8.14.0): + dependencies: + acorn: 8.14.0 + + acorn@8.14.0: {} ajv@6.12.6: dependencies: @@ -4191,7 +3991,7 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.0.1: {} + ansi-regex@6.1.0: {} ansi-styles@3.2.1: dependencies: @@ -4207,71 +4007,72 @@ snapshots: any-promise@1.3.0: {} - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - argparse@1.0.10: dependencies: sprintf-js: 1.0.3 argparse@2.0.1: {} - array-buffer-byte-length@1.0.0: + array-buffer-byte-length@1.0.2: dependencies: - call-bind: 1.0.5 - is-array-buffer: 3.0.2 + call-bound: 1.0.3 + is-array-buffer: 3.0.5 - array-includes@3.1.7: + array-includes@3.1.8: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - is-string: 1.0.7 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 array-union@2.1.0: {} - array.prototype.findlastindex@1.2.3: + array.prototype.findlastindex@1.2.5: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - get-intrinsic: 1.2.2 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 - array.prototype.flat@1.3.2: + array.prototype.flat@1.3.3: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 - array.prototype.flatmap@1.3.2: + array.prototype.flatmap@1.3.3: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 - arraybuffer.prototype.slice@1.0.2: + arraybuffer.prototype.slice@1.0.4: dependencies: - array-buffer-byte-length: 1.0.0 - call-bind: 1.0.5 + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 - is-array-buffer: 3.0.2 - is-shared-array-buffer: 1.0.2 + es-abstract: 1.23.9 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 assertion-error@2.0.1: {} + async-function@1.0.0: {} + autolinker@0.28.1: dependencies: gulp-header: 1.8.12 - available-typed-arrays@1.0.5: {} + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 balanced-match@1.0.2: {} @@ -4279,8 +4080,6 @@ snapshots: dependencies: is-windows: 1.0.2 - binary-extensions@2.3.0: {} - brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -4294,38 +4093,49 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.23.3: + browserslist@4.24.4: dependencies: - caniuse-lite: 1.0.30001655 - electron-to-chromium: 1.5.13 - node-releases: 2.0.18 - update-browserslist-db: 1.1.0(browserslist@4.23.3) + caniuse-lite: 1.0.30001701 + electron-to-chromium: 1.5.107 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) buffer-from@1.1.2: {} - bundle-require@5.0.0(esbuild@0.23.1): + bundle-require@5.1.0(esbuild@0.25.0): dependencies: - esbuild: 0.23.1 + esbuild: 0.25.0 load-tsconfig: 0.2.5 cac@6.7.14: {} - call-bind@1.0.5: + call-bind-apply-helpers@1.0.2: dependencies: + es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.2 - set-function-length: 1.1.1 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.3: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 callsites@3.1.0: {} - caniuse-lite@1.0.30001655: {} + caniuse-lite@1.0.30001701: {} - chai@5.1.1: + chai@5.2.0: dependencies: assertion-error: 2.0.1 check-error: 2.1.1 deep-eql: 5.0.2 - loupe: 3.1.1 + loupe: 3.1.3 pathval: 2.0.0 chalk@2.4.2: @@ -4339,7 +4149,7 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.3.0: {} + chalk@5.4.1: {} character-entities-legacy@1.1.4: {} @@ -4351,21 +4161,13 @@ snapshots: check-error@2.1.1: {} - chokidar@3.6.0: + chokidar@4.0.3: dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 + readdirp: 4.1.2 ci-info@3.9.0: {} - code-block-writer@13.0.2: {} + code-block-writer@13.0.3: {} color-convert@1.9.3: dependencies: @@ -4394,7 +4196,7 @@ snapshots: dependencies: source-map: 0.6.1 - consola@3.2.3: {} + consola@3.4.0: {} convert-source-map@2.0.0: {} @@ -4412,19 +4214,39 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + is-data-view: 1.0.2 + dataloader@1.4.0: {} debug@3.2.7: dependencies: ms: 2.1.3 - debug@4.3.4: + debug@4.4.0: dependencies: - ms: 2.1.2 - - debug@4.3.6: - dependencies: - ms: 2.1.2 + ms: 2.1.3 dedent@1.5.3: {} @@ -4432,16 +4254,16 @@ snapshots: deep-is@0.1.4: {} - define-data-property@1.1.1: + define-data-property@1.1.4: dependencies: - get-intrinsic: 1.2.2 - gopd: 1.0.1 - has-property-descriptors: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 define-properties@1.2.1: dependencies: - define-data-property: 1.1.1 - has-property-descriptors: 1.0.1 + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 object-keys: 1.1.1 detect-indent@6.1.0: {} @@ -4466,17 +4288,26 @@ snapshots: dotenv@8.6.0: {} + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + eastasianwidth@0.2.0: {} - effect@3.7.0: {} + effect@3.13.2: + dependencies: + '@standard-schema/spec': 1.0.0 + fast-check: 3.23.2 - electron-to-chromium@1.5.13: {} + electron-to-chromium@1.5.107: {} emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} - enhanced-resolve@5.17.1: + enhanced-resolve@5.18.1: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 @@ -4490,116 +4321,114 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-abstract@1.22.3: - dependencies: - array-buffer-byte-length: 1.0.0 - arraybuffer.prototype.slice: 1.0.2 - available-typed-arrays: 1.0.5 - call-bind: 1.0.5 - es-set-tostringtag: 2.0.2 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.2 - get-symbol-description: 1.0.0 - globalthis: 1.0.3 - gopd: 1.0.1 - has-property-descriptors: 1.0.1 - has-proto: 1.0.1 - has-symbols: 1.0.3 - hasown: 2.0.0 - internal-slot: 1.0.6 - is-array-buffer: 3.0.2 + es-abstract@1.23.9: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.3 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 is-callable: 1.2.7 - is-negative-zero: 2.0.2 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - is-string: 1.0.7 - is-typed-array: 1.1.12 - is-weakref: 1.0.2 - object-inspect: 1.13.1 + is-data-view: 1.0.2 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.1 - safe-array-concat: 1.0.1 - safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.8 - string.prototype.trimend: 1.0.7 - string.prototype.trimstart: 1.0.7 - typed-array-buffer: 1.0.0 - typed-array-byte-length: 1.0.0 - typed-array-byte-offset: 1.0.0 - typed-array-length: 1.0.4 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.13 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.18 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} - es-set-tostringtag@2.0.2: + es-module-lexer@1.6.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: dependencies: - get-intrinsic: 1.2.2 - has-tostringtag: 1.0.0 - hasown: 2.0.0 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 - es-shim-unscopables@1.0.2: + es-shim-unscopables@1.1.0: dependencies: - hasown: 2.0.0 + hasown: 2.0.2 - es-to-primitive@1.2.1: + es-to-primitive@1.3.0: dependencies: is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 + is-date-object: 1.1.0 + is-symbol: 1.1.1 - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - - esbuild@0.23.1: + esbuild@0.25.0: optionalDependencies: - '@esbuild/aix-ppc64': 0.23.1 - '@esbuild/android-arm': 0.23.1 - '@esbuild/android-arm64': 0.23.1 - '@esbuild/android-x64': 0.23.1 - '@esbuild/darwin-arm64': 0.23.1 - '@esbuild/darwin-x64': 0.23.1 - '@esbuild/freebsd-arm64': 0.23.1 - '@esbuild/freebsd-x64': 0.23.1 - '@esbuild/linux-arm': 0.23.1 - '@esbuild/linux-arm64': 0.23.1 - '@esbuild/linux-ia32': 0.23.1 - '@esbuild/linux-loong64': 0.23.1 - '@esbuild/linux-mips64el': 0.23.1 - '@esbuild/linux-ppc64': 0.23.1 - '@esbuild/linux-riscv64': 0.23.1 - '@esbuild/linux-s390x': 0.23.1 - '@esbuild/linux-x64': 0.23.1 - '@esbuild/netbsd-x64': 0.23.1 - '@esbuild/openbsd-arm64': 0.23.1 - '@esbuild/openbsd-x64': 0.23.1 - '@esbuild/sunos-x64': 0.23.1 - '@esbuild/win32-arm64': 0.23.1 - '@esbuild/win32-ia32': 0.23.1 - '@esbuild/win32-x64': 0.23.1 + '@esbuild/aix-ppc64': 0.25.0 + '@esbuild/android-arm': 0.25.0 + '@esbuild/android-arm64': 0.25.0 + '@esbuild/android-x64': 0.25.0 + '@esbuild/darwin-arm64': 0.25.0 + '@esbuild/darwin-x64': 0.25.0 + '@esbuild/freebsd-arm64': 0.25.0 + '@esbuild/freebsd-x64': 0.25.0 + '@esbuild/linux-arm': 0.25.0 + '@esbuild/linux-arm64': 0.25.0 + '@esbuild/linux-ia32': 0.25.0 + '@esbuild/linux-loong64': 0.25.0 + '@esbuild/linux-mips64el': 0.25.0 + '@esbuild/linux-ppc64': 0.25.0 + '@esbuild/linux-riscv64': 0.25.0 + '@esbuild/linux-s390x': 0.25.0 + '@esbuild/linux-x64': 0.25.0 + '@esbuild/netbsd-arm64': 0.25.0 + '@esbuild/netbsd-x64': 0.25.0 + '@esbuild/openbsd-arm64': 0.25.0 + '@esbuild/openbsd-x64': 0.25.0 + '@esbuild/sunos-x64': 0.25.0 + '@esbuild/win32-arm64': 0.25.0 + '@esbuild/win32-ia32': 0.25.0 + '@esbuild/win32-x64': 0.25.0 escalade@3.2.0: {} @@ -4612,70 +4441,56 @@ snapshots: eslint-import-resolver-node@0.3.9: dependencies: debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.8 + is-core-module: 2.16.1 + resolve: 1.22.10 transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.56.0): + eslint-import-resolver-typescript@3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0): dependencies: '@nolyfill/is-core-module': 1.0.39 - debug: 4.3.6 - enhanced-resolve: 5.17.1 - eslint: 8.56.0 - eslint-module-utils: 2.8.2(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.56.0))(eslint@8.56.0) - fast-glob: 3.3.2 - get-tsconfig: 4.8.0 - is-bun-module: 1.1.0 - is-glob: 4.0.3 + debug: 4.4.0 + enhanced-resolve: 5.18.1 + eslint: 9.21.0 + get-tsconfig: 4.10.0 + is-bun-module: 1.3.0 + stable-hash: 0.0.4 + tinyglobby: 0.2.12 optionalDependencies: - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.3)(eslint@8.56.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0) transitivePeerDependencies: - - '@typescript-eslint/parser' - - eslint-import-resolver-node - - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.56.0))(eslint@8.56.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0))(eslint@9.21.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.3.0(eslint@8.56.0)(typescript@5.5.4) - eslint: 8.56.0 + '@typescript-eslint/parser': 8.25.0(eslint@9.21.0)(typescript@5.7.3) + eslint: 9.21.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.56.0) - transitivePeerDependencies: - - supports-color - - eslint-module-utils@2.8.2(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.56.0))(eslint@8.56.0): - dependencies: - debug: 3.2.7 - optionalDependencies: - '@typescript-eslint/parser': 8.3.0(eslint@8.56.0)(typescript@5.5.4) - eslint: 8.56.0 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.56.0) + eslint-import-resolver-typescript: 3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0) transitivePeerDependencies: - supports-color - eslint-plugin-codegen@0.28.0(eslint@8.56.0): + eslint-plugin-codegen@0.29.0(eslint@9.21.0): dependencies: - '@babel/core': 7.25.2 + '@babel/core': 7.26.9 '@babel/generator': 7.12.17 - '@babel/parser': 7.25.6 - '@babel/traverse': 7.25.6 + '@babel/parser': 7.26.9 + '@babel/traverse': 7.26.9 '@pnpm/deps.graph-sequencer': 1.0.0 '@types/dedent': 0.7.0 '@types/eslint': 8.56.12 '@types/glob': 7.1.3 '@types/js-yaml': 3.12.5 - '@types/lodash': 4.17.7 - '@types/node': 20.16.3 + '@types/lodash': 4.17.15 + '@types/node': 20.17.19 dedent: 1.5.3 - eslint-plugin-markdown: 4.0.1(eslint@8.56.0) + eslint-plugin-markdown: 4.0.1(eslint@9.21.0) expect: 29.7.0 fp-ts: 2.16.9 - glob: 10.3.12 - io-ts: 2.2.21(fp-ts@2.16.9) + glob: 10.4.5 + io-ts: 2.2.22(fp-ts@2.16.9) io-ts-extra: 0.11.6 js-yaml: 3.14.1 lodash: 4.17.21 @@ -4685,118 +4500,108 @@ snapshots: - eslint - supports-color - eslint-plugin-deprecation@3.0.0(eslint@8.56.0)(typescript@5.5.4): - dependencies: - '@typescript-eslint/utils': 7.18.0(eslint@8.56.0)(typescript@5.5.4) - eslint: 8.56.0 - ts-api-utils: 1.3.0(typescript@5.5.4) - tslib: 2.7.0 - typescript: 5.5.4 - transitivePeerDependencies: - - supports-color - - eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.3)(eslint@8.56.0): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0): dependencies: - array-includes: 3.1.7 - array.prototype.findlastindex: 1.2.3 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.56.0 + eslint: 9.21.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@8.3.0(eslint@8.56.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.56.0))(eslint@8.56.0) - hasown: 2.0.0 - is-core-module: 2.13.1 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0))(eslint@9.21.0) + hasown: 2.0.2 + is-core-module: 2.16.1 is-glob: 4.0.3 minimatch: 3.1.2 - object.fromentries: 2.0.7 - object.groupby: 1.0.1 - object.values: 1.1.7 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 semver: 6.3.1 + string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.3.0(eslint@8.56.0)(typescript@5.5.4) + '@typescript-eslint/parser': 8.25.0(eslint@9.21.0)(typescript@5.7.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-markdown@4.0.1(eslint@8.56.0): + eslint-plugin-markdown@4.0.1(eslint@9.21.0): dependencies: - eslint: 8.56.0 + eslint: 9.21.0 mdast-util-from-markdown: 0.8.5 transitivePeerDependencies: - supports-color - eslint-plugin-simple-import-sort@12.1.1(eslint@8.56.0): + eslint-plugin-simple-import-sort@12.1.1(eslint@9.21.0): dependencies: - eslint: 8.56.0 + eslint: 9.21.0 - eslint-plugin-sort-destructure-keys@2.0.0(eslint@8.56.0): + eslint-plugin-sort-destructure-keys@2.0.0(eslint@9.21.0): dependencies: - eslint: 8.56.0 + eslint: 9.21.0 natural-compare-lite: 1.4.0 - eslint-scope@7.2.2: + eslint-scope@8.2.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 eslint-visitor-keys@3.4.3: {} - eslint@8.56.0: + eslint-visitor-keys@4.2.0: {} + + eslint@9.21.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.56.0 - '@humanwhocodes/config-array': 0.11.13 + '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.2 + '@eslint/core': 0.12.0 + '@eslint/eslintrc': 3.3.0 + '@eslint/js': 9.21.0 + '@eslint/plugin-kit': 0.2.7 + '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 + '@humanwhocodes/retry': 0.4.2 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 + cross-spawn: 7.0.6 + debug: 4.4.0 escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 + eslint-scope: 8.2.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 - ignore: 5.3.0 + ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 + optionator: 0.9.4 transitivePeerDependencies: - supports-color - espree@9.6.1: + espree@10.3.0: dependencies: - acorn: 8.11.2 - acorn-jsx: 5.3.2(acorn@8.11.2) - eslint-visitor-keys: 3.4.3 + acorn: 8.14.0 + acorn-jsx: 5.3.2(acorn@8.14.0) + eslint-visitor-keys: 4.2.0 esprima@4.0.1: {} - esquery@1.5.0: + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -4808,38 +4613,16 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 esutils@2.0.3: {} - execa@5.1.1: - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - execa@8.0.1: - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - expand-range@1.8.2: dependencies: fill-range: 2.2.4 + expect-type@1.1.0: {} + expect@29.7.0: dependencies: '@jest/expect-utils': 29.7.0 @@ -4860,7 +4643,7 @@ snapshots: iconv-lite: 0.4.24 tmp: 0.0.33 - fast-check@3.22.0: + fast-check@3.23.2: dependencies: pure-rand: 6.1.0 @@ -4876,6 +4659,14 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} @@ -4884,9 +4675,13 @@ snapshots: dependencies: reusify: 1.0.4 - file-entry-cache@6.0.1: + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + + file-entry-cache@8.0.0: dependencies: - flat-cache: 3.2.0 + flat-cache: 4.0.1 fill-range@2.2.4: dependencies: @@ -4917,15 +4712,14 @@ snapshots: micromatch: 4.0.8 pkg-dir: 4.2.0 - flat-cache@3.2.0: + flat-cache@4.0.1: dependencies: - flatted: 3.2.9 + flatted: 3.3.3 keyv: 4.5.4 - rimraf: 3.0.2 - flatted@3.2.9: {} + flatted@3.3.3: {} - for-each@0.3.3: + for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -4936,9 +4730,9 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - foreground-child@3.3.0: + foreground-child@3.3.1: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 signal-exit: 4.1.0 fp-ts@2.16.9: {} @@ -4955,43 +4749,49 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true function-bind@1.1.2: {} - function.prototype.name@1.1.6: + function.prototype.name@1.1.8: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 + call-bound: 1.0.3 define-properties: 1.2.1 - es-abstract: 1.22.3 functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 functions-have-names@1.2.3: {} gensync@1.0.0-beta.2: {} - get-func-name@2.0.2: {} - - get-intrinsic@1.2.2: + get-intrinsic@1.3.0: dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 function-bind: 1.1.2 - has-proto: 1.0.1 - has-symbols: 1.0.3 - hasown: 2.0.0 - - get-stream@6.0.1: {} + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 - get-stream@8.0.1: {} + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 - get-symbol-description@1.0.0: + get-symbol-description@1.1.0: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 - get-tsconfig@4.8.0: + get-tsconfig@4.10.0: dependencies: resolve-pkg-maps: 1.0.0 @@ -5003,50 +4803,32 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.3.12: - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.4 - minipass: 7.0.4 - path-scurry: 1.10.2 - glob@10.4.5: dependencies: - foreground-child: 3.3.0 + foreground-child: 3.1.1 jackspeak: 3.4.3 - minimatch: 9.0.5 + minimatch: 9.0.4 minipass: 7.1.2 - package-json-from-dist: 1.0.0 + package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@11.0.0: + glob@11.0.1: dependencies: - foreground-child: 3.3.0 - jackspeak: 4.0.1 + foreground-child: 3.3.1 + jackspeak: 4.1.0 minimatch: 10.0.1 minipass: 7.1.2 - package-json-from-dist: 1.0.0 + package-json-from-dist: 1.0.1 path-scurry: 2.0.0 - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - globals@11.12.0: {} - globals@13.24.0: - dependencies: - type-fest: 0.20.2 + globals@14.0.0: {} - globalthis@1.0.3: + globalthis@1.0.4: dependencies: define-properties: 1.2.1 + gopd: 1.2.0 globby@11.1.0: dependencies: @@ -5057,9 +4839,7 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 - gopd@1.0.1: - dependencies: - get-intrinsic: 1.2.2 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -5078,25 +4858,27 @@ snapshots: lodash.template: 4.5.0 through2: 2.0.5 - has-bigints@1.0.2: {} + has-bigints@1.1.0: {} has-flag@3.0.0: {} has-flag@4.0.0: {} - has-property-descriptors@1.0.1: + has-property-descriptors@1.0.2: dependencies: - get-intrinsic: 1.2.2 + es-define-property: 1.0.1 - has-proto@1.0.1: {} + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 - has-symbols@1.0.3: {} + has-symbols@1.1.0: {} - has-tostringtag@1.0.0: + has-tostringtag@1.0.2: dependencies: - has-symbols: 1.0.3 + has-symbols: 1.1.0 - hasown@2.0.0: + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -5106,46 +4888,35 @@ snapshots: human-id@1.0.2: {} - human-signals@2.1.0: {} - - human-signals@5.0.0: {} - iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 - ignore@5.3.0: {} - ignore@5.3.2: {} - import-fresh@3.3.0: + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 imurmurhash@0.1.4: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - inherits@2.0.4: {} ini@4.1.3: {} - internal-slot@1.0.6: + internal-slot@1.1.0: dependencies: - get-intrinsic: 1.2.2 - hasown: 2.0.0 - side-channel: 1.0.4 + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 io-ts-extra@0.11.6: dependencies: fp-ts: 2.16.9 - io-ts: 2.2.21(fp-ts@2.16.9) + io-ts: 2.2.22(fp-ts@2.16.9) - io-ts@2.2.21(fp-ts@2.16.9): + io-ts@2.2.22(fp-ts@2.16.9): dependencies: fp-ts: 2.16.9 @@ -5156,42 +4927,53 @@ snapshots: is-alphabetical: 1.0.4 is-decimal: 1.0.4 - is-array-buffer@3.0.2: + is-array-buffer@3.0.5: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - is-typed-array: 1.1.12 + call-bind: 1.0.8 + call-bound: 1.0.3 + get-intrinsic: 1.3.0 is-arrayish@0.2.1: {} - is-bigint@1.0.4: + is-async-function@2.1.1: dependencies: - has-bigints: 1.0.2 + async-function: 1.0.0 + call-bound: 1.0.3 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 - is-binary-path@2.1.0: + is-bigint@1.1.0: dependencies: - binary-extensions: 2.3.0 + has-bigints: 1.1.0 - is-boolean-object@1.1.2: + is-boolean-object@1.2.2: dependencies: - call-bind: 1.0.5 - has-tostringtag: 1.0.0 + call-bound: 1.0.3 + has-tostringtag: 1.0.2 is-buffer@1.1.6: {} - is-bun-module@1.1.0: + is-bun-module@1.3.0: dependencies: - semver: 7.6.3 + semver: 7.7.1 is-callable@1.2.7: {} - is-core-module@2.13.1: + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: dependencies: - hasown: 2.0.0 + call-bound: 1.0.3 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 - is-date-object@1.0.5: + is-date-object@1.1.0: dependencies: - has-tostringtag: 1.0.0 + call-bound: 1.0.3 + has-tostringtag: 1.0.2 is-decimal@1.0.4: {} @@ -5203,19 +4985,31 @@ snapshots: is-extglob@2.1.1: {} + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.3 + is-fullwidth-code-point@3.0.0: {} + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.3 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 is-hexadecimal@1.0.4: {} - is-negative-zero@2.0.2: {} + is-map@2.0.3: {} - is-number-object@1.0.7: + is-number-object@1.1.1: dependencies: - has-tostringtag: 1.0.0 + call-bound: 1.0.3 + has-tostringtag: 1.0.2 is-number@2.1.0: dependencies: @@ -5225,44 +5019,52 @@ snapshots: is-number@7.0.0: {} - is-path-inside@3.0.3: {} - is-plain-object@2.0.4: dependencies: isobject: 3.0.1 - is-regex@1.1.4: - dependencies: - call-bind: 1.0.5 - has-tostringtag: 1.0.0 - - is-shared-array-buffer@1.0.2: + is-regex@1.2.1: dependencies: - call-bind: 1.0.5 + call-bound: 1.0.3 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 - is-stream@2.0.1: {} + is-set@2.0.3: {} - is-stream@3.0.0: {} + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.3 - is-string@1.0.7: + is-string@1.1.1: dependencies: - has-tostringtag: 1.0.0 + call-bound: 1.0.3 + has-tostringtag: 1.0.2 is-subdir@1.2.0: dependencies: better-path-resolve: 1.0.0 - is-symbol@1.0.4: + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.3 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: dependencies: - has-symbols: 1.0.3 + which-typed-array: 1.1.18 + + is-weakmap@2.0.2: {} - is-typed-array@1.1.12: + is-weakref@1.1.1: dependencies: - which-typed-array: 1.1.13 + call-bound: 1.0.3 - is-weakref@1.0.2: + is-weakset@2.0.4: dependencies: - call-bind: 1.0.5 + call-bound: 1.0.3 + get-intrinsic: 1.3.0 is-windows@1.0.2: {} @@ -5289,7 +5091,7 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.25 - debug: 4.3.6 + debug: 4.4.0 istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -5299,23 +5101,15 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 - jackspeak@2.3.6: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jackspeak@4.0.1: + jackspeak@4.1.0: dependencies: '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 jest-diff@29.7.0: dependencies: @@ -5335,7 +5129,7 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.24.7 + '@babel/code-frame': 7.26.2 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -5348,7 +5142,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.5.2 + '@types/node': 22.13.5 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -5369,6 +5163,8 @@ snapshots: jsesc@2.5.2: {} + jsesc@3.1.0: {} + json-buffer@3.0.1: {} json-parse-even-better-errors@2.3.1: {} @@ -5408,7 +5204,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lilconfig@3.1.2: {} + lilconfig@3.1.3: {} lines-and-columns@1.2.4: {} @@ -5455,15 +5251,11 @@ snapshots: lodash@4.17.21: {} - loupe@3.1.1: - dependencies: - get-func-name: 2.0.2 - - lru-cache@10.2.0: {} + loupe@3.1.3: {} lru-cache@10.4.3: {} - lru-cache@11.0.0: {} + lru-cache@11.0.2: {} lru-cache@4.1.5: dependencies: @@ -5474,22 +5266,24 @@ snapshots: dependencies: yallist: 3.1.1 - magic-string@0.30.11: + magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 magicast@0.3.5: dependencies: - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 - source-map-js: 1.2.0 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + source-map-js: 1.2.1 make-dir@4.0.0: dependencies: - semver: 7.6.3 + semver: 7.7.1 markdown-link@0.1.1: {} + math-intrinsics@1.1.0: {} + math-random@1.0.4: {} mdast-util-from-markdown@0.8.5: @@ -5504,13 +5298,11 @@ snapshots: mdast-util-to-string@2.0.0: {} - merge-stream@2.0.0: {} - merge2@1.4.1: {} micromark@2.11.4: dependencies: - debug: 4.3.6 + debug: 4.4.0 parse-entities: 2.0.0 transitivePeerDependencies: - supports-color @@ -5522,10 +5314,6 @@ snapshots: mime@3.0.0: {} - mimic-fn@2.1.0: {} - - mimic-fn@4.0.0: {} - minimatch@10.0.1: dependencies: brace-expansion: 2.0.1 @@ -5544,8 +5332,6 @@ snapshots: minimist@1.2.8: {} - minipass@7.0.4: {} - minipass@7.1.2: {} mixin-deep@1.3.2: @@ -5553,12 +5339,8 @@ snapshots: for-in: 1.0.2 is-extendable: 1.0.1 - mkdirp@3.0.1: {} - mri@1.2.0: {} - ms@2.1.2: {} - ms@2.1.3: {} multipasta@0.2.5: {} @@ -5569,7 +5351,7 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nanoid@3.3.7: {} + nanoid@3.3.8: {} natural-compare-lite@1.4.0: {} @@ -5581,86 +5363,73 @@ snapshots: dependencies: whatwg-url: 5.0.0 - node-releases@2.0.18: {} + node-releases@2.0.19: {} normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.8 + resolve: 1.22.10 semver: 5.7.2 validate-npm-package-license: 3.0.4 - normalize-path@3.0.0: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - object-assign@4.1.1: {} - object-inspect@1.13.1: {} + object-inspect@1.13.4: {} object-keys@1.1.1: {} - object.assign@4.1.5: + object.assign@4.1.7: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 + call-bound: 1.0.3 define-properties: 1.2.1 - has-symbols: 1.0.3 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 object-keys: 1.1.1 - object.fromentries@2.0.7: + object.fromentries@2.0.8: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 - object.groupby@1.0.1: + object.groupby@1.0.3: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.22.3 - get-intrinsic: 1.2.2 + es-abstract: 1.23.9 object.pick@1.3.0: dependencies: isobject: 3.0.1 - object.values@1.1.7: + object.values@1.2.1: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 + call-bound: 1.0.3 define-properties: 1.2.1 - es-abstract: 1.22.3 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 + es-object-atoms: 1.1.1 - onetime@6.0.0: + optionator@0.9.4: dependencies: - mimic-fn: 4.0.0 - - optionator@0.9.3: - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 + word-wrap: 1.2.5 os-tmpdir@1.0.2: {} outdent@0.5.0: {} + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + p-filter@2.1.0: dependencies: p-map: 2.1.0 @@ -5687,6 +5456,8 @@ snapshots: package-json-from-dist@1.0.0: {} + package-json-from-dist@1.0.1: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -5702,7 +5473,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.24.7 + '@babel/code-frame': 7.26.2 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -5711,19 +5482,10 @@ snapshots: path-exists@4.0.0: {} - path-is-absolute@1.0.1: {} - path-key@3.1.1: {} - path-key@4.0.0: {} - path-parse@1.0.7: {} - path-scurry@1.10.2: - dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 - path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 @@ -5731,19 +5493,21 @@ snapshots: path-scurry@2.0.0: dependencies: - lru-cache: 11.0.0 + lru-cache: 11.0.2 minipass: 7.1.2 path-type@4.0.0: {} - pathe@1.1.2: {} + pathe@2.0.3: {} pathval@2.0.0: {} - picocolors@1.0.1: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} + picomatch@4.0.2: {} + pify@4.0.1: {} pirates@4.0.6: {} @@ -5752,19 +5516,21 @@ snapshots: dependencies: find-up: 4.1.0 - postcss-load-config@6.0.1(postcss@8.4.44)(tsx@4.19.0)(yaml@2.5.0): + possible-typed-array-names@1.1.0: {} + + postcss-load-config@6.0.1(postcss@8.5.3)(tsx@4.19.3)(yaml@2.7.0): dependencies: - lilconfig: 3.1.2 + lilconfig: 3.1.3 optionalDependencies: - postcss: 8.4.44 - tsx: 4.19.0 - yaml: 2.5.0 + postcss: 8.5.3 + tsx: 4.19.3 + yaml: 2.7.0 - postcss@8.4.44: + postcss@8.5.3: dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 preferred-pm@3.1.4: dependencies: @@ -5781,7 +5547,7 @@ snapshots: prettier@2.8.8: {} - prettier@3.2.5: {} + prettier@3.5.2: {} pretty-format@29.7.0: dependencies: @@ -5837,17 +5603,29 @@ snapshots: string_decoder: 1.1.1 util-deprecate: 1.0.2 - readdirp@3.6.0: + readdirp@4.1.2: {} + + reflect.getprototypeof@1.0.10: dependencies: - picomatch: 2.3.1 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 regenerator-runtime@0.14.1: {} - regexp.prototype.flags@1.5.1: + regexp.prototype.flags@1.5.4: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 define-properties: 1.2.1 - set-function-name: 2.0.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 remarkable@1.7.4: dependencies: @@ -5864,63 +5642,68 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve@1.22.8: + resolve@1.22.10: dependencies: - is-core-module: 2.13.1 + is-core-module: 2.16.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 reusify@1.0.4: {} - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - rimraf@6.0.1: dependencies: - glob: 11.0.0 + glob: 11.0.1 package-json-from-dist: 1.0.0 - rollup@4.21.2: + rollup@4.34.8: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.21.2 - '@rollup/rollup-android-arm64': 4.21.2 - '@rollup/rollup-darwin-arm64': 4.21.2 - '@rollup/rollup-darwin-x64': 4.21.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.21.2 - '@rollup/rollup-linux-arm-musleabihf': 4.21.2 - '@rollup/rollup-linux-arm64-gnu': 4.21.2 - '@rollup/rollup-linux-arm64-musl': 4.21.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.21.2 - '@rollup/rollup-linux-riscv64-gnu': 4.21.2 - '@rollup/rollup-linux-s390x-gnu': 4.21.2 - '@rollup/rollup-linux-x64-gnu': 4.21.2 - '@rollup/rollup-linux-x64-musl': 4.21.2 - '@rollup/rollup-win32-arm64-msvc': 4.21.2 - '@rollup/rollup-win32-ia32-msvc': 4.21.2 - '@rollup/rollup-win32-x64-msvc': 4.21.2 + '@rollup/rollup-android-arm-eabi': 4.34.8 + '@rollup/rollup-android-arm64': 4.34.8 + '@rollup/rollup-darwin-arm64': 4.34.8 + '@rollup/rollup-darwin-x64': 4.34.8 + '@rollup/rollup-freebsd-arm64': 4.34.8 + '@rollup/rollup-freebsd-x64': 4.34.8 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.8 + '@rollup/rollup-linux-arm-musleabihf': 4.34.8 + '@rollup/rollup-linux-arm64-gnu': 4.34.8 + '@rollup/rollup-linux-arm64-musl': 4.34.8 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.8 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.8 + '@rollup/rollup-linux-riscv64-gnu': 4.34.8 + '@rollup/rollup-linux-s390x-gnu': 4.34.8 + '@rollup/rollup-linux-x64-gnu': 4.34.8 + '@rollup/rollup-linux-x64-musl': 4.34.8 + '@rollup/rollup-win32-arm64-msvc': 4.34.8 + '@rollup/rollup-win32-ia32-msvc': 4.34.8 + '@rollup/rollup-win32-x64-msvc': 4.34.8 fsevents: 2.3.3 run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - safe-array-concat@1.0.1: + safe-array-concat@1.1.3: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - has-symbols: 1.0.3 + call-bind: 1.0.8 + call-bound: 1.0.3 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 isarray: 2.0.5 safe-buffer@5.1.2: {} - safe-regex-test@1.0.0: + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - is-regex: 1.1.4 + call-bound: 1.0.3 + es-errors: 1.3.0 + is-regex: 1.2.1 safer-buffer@2.1.2: {} @@ -5930,23 +5713,34 @@ snapshots: semver@7.6.3: {} - set-function-length@1.1.1: + semver@7.7.1: {} + + set-function-length@1.2.2: dependencies: - define-data-property: 1.1.1 - get-intrinsic: 1.2.2 - gopd: 1.0.1 - has-property-descriptors: 1.0.1 + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 - set-function-name@2.0.1: + set-function-name@2.0.2: dependencies: - define-data-property: 1.1.1 + define-data-property: 1.1.4 + es-errors: 1.3.0 functions-have-names: 1.2.3 - has-property-descriptors: 1.0.1 + has-property-descriptors: 1.0.2 set-getter@0.1.1: dependencies: to-object-path: 0.3.0 + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 @@ -5959,11 +5753,33 @@ snapshots: shebang-regex@3.0.0: {} - side-channel@1.0.4: + side-channel-list@1.0.0: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - object-inspect: 1.13.1 + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.3 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 siginfo@2.0.0: {} @@ -5973,7 +5789,7 @@ snapshots: slash@3.0.0: {} - source-map-js@1.2.0: {} + source-map-js@1.2.1: {} source-map@0.5.7: {} @@ -5991,26 +5807,28 @@ snapshots: spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.20 + spdx-license-ids: 3.0.21 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.20 + spdx-license-ids: 3.0.21 - spdx-license-ids@3.0.20: {} + spdx-license-ids@3.0.21: {} sprintf-js@1.0.3: {} + stable-hash@0.0.4: {} + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 stackback@0.0.2: {} - std-env@3.7.0: {} + std-env@3.8.0: {} string-width@4.2.3: dependencies: @@ -6024,23 +5842,28 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 - string.prototype.trim@1.2.8: + string.prototype.trim@1.2.10: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 + call-bound: 1.0.3 + define-data-property: 1.1.4 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 - string.prototype.trimend@1.0.7: + string.prototype.trimend@1.0.9: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 + call-bound: 1.0.3 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-object-atoms: 1.1.1 - string.prototype.trimstart@1.0.7: + string.prototype.trimstart@1.0.8: dependencies: - call-bind: 1.0.5 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.22.3 + es-object-atoms: 1.1.1 string_decoder@1.1.1: dependencies: @@ -6052,7 +5875,7 @@ snapshots: strip-ansi@7.1.0: dependencies: - ansi-regex: 6.0.1 + ansi-regex: 6.1.0 strip-bom-string@1.0.0: {} @@ -6060,17 +5883,13 @@ snapshots: strip-color@0.1.0: {} - strip-final-newline@2.0.0: {} - - strip-final-newline@3.0.0: {} - strip-json-comments@3.1.1: {} sucrase@3.35.0: dependencies: - '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/gen-mapping': 0.3.8 commander: 4.1.1 - glob: 10.3.12 + glob: 10.4.5 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.6 @@ -6096,8 +5915,6 @@ snapshots: glob: 10.4.5 minimatch: 9.0.5 - text-table@0.2.0: {} - thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -6113,18 +5930,23 @@ snapshots: tinybench@2.9.0: {} - tinypool@1.0.1: {} + tinyexec@0.3.2: {} + + tinyglobby@0.2.12: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + + tinypool@1.0.2: {} - tinyrainbow@1.2.0: {} + tinyrainbow@2.0.0: {} - tinyspy@3.0.0: {} + tinyspy@3.0.2: {} tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 - to-fast-properties@2.0.0: {} - to-object-path@0.3.0: dependencies: kind-of: 3.2.2 @@ -6143,20 +5965,20 @@ snapshots: tree-kill@1.2.2: {} - ts-api-utils@1.3.0(typescript@5.5.4): + ts-api-utils@2.0.1(typescript@5.7.3): dependencies: - typescript: 5.5.4 + typescript: 5.7.3 ts-interface-checker@0.1.13: {} - ts-morph@23.0.0: + ts-morph@25.0.1: dependencies: - '@ts-morph/common': 0.24.0 - code-block-writer: 13.0.2 + '@ts-morph/common': 0.26.1 + code-block-writer: 13.0.3 - tsconfck@3.1.3(typescript@5.5.4): + tsconfck@3.1.5(typescript@5.7.3): optionalDependencies: - typescript: 5.5.4 + typescript: 5.7.3 tsconfig-paths@3.15.0: dependencies: @@ -6165,39 +5987,37 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 - tslib@2.7.0: {} - - tsup@8.2.4(postcss@8.4.44)(tsx@4.19.0)(typescript@5.5.4)(yaml@2.5.0): + tsup@8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@5.7.3)(yaml@2.7.0): dependencies: - bundle-require: 5.0.0(esbuild@0.23.1) + bundle-require: 5.1.0(esbuild@0.25.0) cac: 6.7.14 - chokidar: 3.6.0 - consola: 3.2.3 - debug: 4.3.6 - esbuild: 0.23.1 - execa: 5.1.1 - globby: 11.1.0 + chokidar: 4.0.3 + consola: 3.4.0 + debug: 4.4.0 + esbuild: 0.25.0 joycon: 3.1.1 - picocolors: 1.0.1 - postcss-load-config: 6.0.1(postcss@8.4.44)(tsx@4.19.0)(yaml@2.5.0) + picocolors: 1.1.1 + postcss-load-config: 6.0.1(postcss@8.5.3)(tsx@4.19.3)(yaml@2.7.0) resolve-from: 5.0.0 - rollup: 4.21.2 + rollup: 4.34.8 source-map: 0.8.0-beta.0 sucrase: 3.35.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.12 tree-kill: 1.2.2 optionalDependencies: - postcss: 8.4.44 - typescript: 5.5.4 + postcss: 8.5.3 + typescript: 5.7.3 transitivePeerDependencies: - jiti - supports-color - tsx - yaml - tsx@4.19.0: + tsx@4.19.3: dependencies: - esbuild: 0.23.1 - get-tsconfig: 4.8.0 + esbuild: 0.25.0 + get-tsconfig: 4.10.0 optionalDependencies: fsevents: 2.3.3 @@ -6205,53 +6025,59 @@ snapshots: dependencies: prelude-ls: 1.2.1 - type-fest@0.20.2: {} - type-fest@0.6.0: {} type-fest@0.8.1: {} - typed-array-buffer@1.0.0: + typed-array-buffer@1.0.3: dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - is-typed-array: 1.1.12 + call-bound: 1.0.3 + es-errors: 1.3.0 + is-typed-array: 1.1.15 - typed-array-byte-length@1.0.0: + typed-array-byte-length@1.0.3: dependencies: - call-bind: 1.0.5 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 - typed-array-byte-offset@1.0.0: + typed-array-byte-offset@1.0.4: dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.5 - for-each: 0.3.3 - has-proto: 1.0.1 - is-typed-array: 1.1.12 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 - typed-array-length@1.0.4: + typed-array-length@1.0.7: dependencies: - call-bind: 1.0.5 - for-each: 0.3.3 - is-typed-array: 1.1.12 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 typedarray@0.0.6: {} - typescript@5.5.4: {} + typescript@5.7.3: {} - unbox-primitive@1.0.2: + unbox-primitive@1.1.0: dependencies: - call-bind: 1.0.5 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 + call-bound: 1.0.3 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 undici-types@6.19.8: {} - undici@6.19.8: {} + undici-types@6.20.0: {} + + undici@7.3.0: {} unist-util-stringify-position@2.0.3: dependencies: @@ -6259,11 +6085,11 @@ snapshots: universalify@0.1.2: {} - update-browserslist-db@1.1.0(browserslist@4.23.3): + update-browserslist-db@1.1.3(browserslist@4.24.4): dependencies: - browserslist: 4.23.3 + browserslist: 4.24.4 escalade: 3.2.0 - picocolors: 1.0.1 + picocolors: 1.1.1 uri-js@4.4.1: dependencies: @@ -6276,15 +6102,16 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - vite-node@2.0.5(@types/node@22.5.2): + vite-node@3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0): dependencies: cac: 6.7.14 - debug: 4.3.6 - pathe: 1.1.2 - tinyrainbow: 1.2.0 - vite: 5.4.2(@types/node@22.5.2) + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - '@types/node' + - jiti - less - lightningcss - sass @@ -6293,48 +6120,57 @@ snapshots: - sugarss - supports-color - terser + - tsx + - yaml - vite@5.4.2(@types/node@22.5.2): + vite@6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0): dependencies: - esbuild: 0.21.5 - postcss: 8.4.44 - rollup: 4.21.2 + esbuild: 0.25.0 + postcss: 8.5.3 + rollup: 4.34.8 optionalDependencies: - '@types/node': 22.5.2 + '@types/node': 22.13.5 fsevents: 2.3.3 - - vitest@2.0.5(@types/node@22.5.2): - dependencies: - '@ampproject/remapping': 2.3.0 - '@vitest/expect': 2.0.5 - '@vitest/pretty-format': 2.0.5 - '@vitest/runner': 2.0.5 - '@vitest/snapshot': 2.0.5 - '@vitest/spy': 2.0.5 - '@vitest/utils': 2.0.5 - chai: 5.1.1 - debug: 4.3.6 - execa: 8.0.1 - magic-string: 0.30.11 - pathe: 1.1.2 - std-env: 3.7.0 + tsx: 4.19.3 + yaml: 2.7.0 + + vitest@3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0): + dependencies: + '@vitest/expect': 3.0.7 + '@vitest/mocker': 3.0.7(vite@6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0)) + '@vitest/pretty-format': 3.0.7 + '@vitest/runner': 3.0.7 + '@vitest/snapshot': 3.0.7 + '@vitest/spy': 3.0.7 + '@vitest/utils': 3.0.7 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.1.0 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.8.0 tinybench: 2.9.0 - tinypool: 1.0.1 - tinyrainbow: 1.2.0 - vite: 5.4.2(@types/node@22.5.2) - vite-node: 2.0.5(@types/node@22.5.2) + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) + vite-node: 3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.5.2 + '@types/node': 22.13.5 transitivePeerDependencies: + - jiti - less - lightningcss + - msw - sass - sass-embedded - stylus - sugarss - supports-color - terser + - tsx + - yaml webidl-conversions@3.0.1: {} @@ -6351,26 +6187,50 @@ snapshots: tr46: 1.0.1 webidl-conversions: 4.0.2 - which-boxed-primitive@1.0.2: + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.3 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.0 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.18 + + which-collection@1.0.2: dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 which-pm@2.2.0: dependencies: load-yaml-file: 0.2.0 path-exists: 4.0.0 - which-typed-array@1.1.13: + which-typed-array@1.1.18: dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.5 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.3 + for-each: 0.3.5 + gopd: 1.2.0 + has-tostringtag: 1.0.2 which@1.3.1: dependencies: @@ -6385,6 +6245,8 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + word-wrap@1.2.5: {} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -6397,9 +6259,7 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 - wrappy@1.0.2: {} - - ws@8.18.0: {} + ws@8.18.1: {} xtend@4.0.2: {} @@ -6407,6 +6267,6 @@ snapshots: yallist@3.1.1: {} - yaml@2.5.0: {} + yaml@2.7.0: {} yocto-queue@0.1.0: {} diff --git a/schema.json b/schema.json index e49e438..bd48756 100644 --- a/schema.json +++ b/schema.json @@ -1,6 +1,5 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "$ref": "#/$defs/ConfigurationSchema", "$defs": { "ConfigurationSchema": { "type": "object", @@ -99,5 +98,6 @@ }, "additionalProperties": false } - } + }, + "$ref": "#/$defs/ConfigurationSchema" } \ No newline at end of file diff --git a/scripts/gen-schema.ts b/scripts/gen-schema.ts index a60a2a9..aa58820 100644 --- a/scripts/gen-schema.ts +++ b/scripts/gen-schema.ts @@ -1,16 +1,15 @@ import { ConfigurationSchema } from "@effect/docgen/Configuration" import { FileSystem } from "@effect/platform" import { NodeFileSystem, NodeRuntime } from "@effect/platform-node" -import { JSONSchema } from "@effect/schema" -import { Effect } from "effect" +import { Effect, JSONSchema } from "effect" const jsonSchema = JSON.stringify(JSONSchema.make(ConfigurationSchema), null, 2) -const program = Effect.gen(function*(_) { - const fs = yield* _(FileSystem.FileSystem) - yield* _(Effect.log("Writing config schema")) - yield* _(fs.writeFileString("schema.json", jsonSchema)) - yield* _(Effect.log("Wrote schema to ./schema.json")) +const program = Effect.gen(function*() { + const fs = yield* FileSystem.FileSystem + yield* Effect.log("Writing config schema") + yield* fs.writeFileString("schema.json", jsonSchema) + yield* Effect.log("Wrote schema to ./schema.json") }) program.pipe( diff --git a/src/CLI.ts b/src/CLI.ts index e5cdda5..4210bf6 100644 --- a/src/CLI.ts +++ b/src/CLI.ts @@ -8,12 +8,12 @@ import * as Command from "@effect/cli/Command" import * as HelpDoc from "@effect/cli/HelpDoc" import * as Options from "@effect/cli/Options" import * as ValidationError from "@effect/cli/ValidationError" -import * as Schema from "@effect/schema/Schema" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import * as Array from "effect/Array" import * as Config from "effect/Config" import * as Effect from "effect/Effect" import * as Either from "effect/Either" +import * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" import * as Configuration from "./Configuration.js" import * as Core from "./Core.js" import * as InternalVersion from "./internal/version.js" @@ -125,7 +125,7 @@ const parseCompilerOptions = Options.file("parse-tsconfig-file", { exists: "yes" Schema.decodeUnknownEither(compilerOptionsSchema)(options).pipe( Either.mapLeft((e) => { const error = HelpDoc.p( - `Invalid TypeScript compiler options:\n${TreeFormatter.formatErrorSync(e)}` + `Invalid TypeScript compiler options:\n${ParseResult.TreeFormatter.formatErrorSync(e)}` ) return ValidationError.invalidValue(error) }) @@ -145,7 +145,7 @@ const examplesCompilerOptions = Options.file("examples-tsconfig-file", { exists: Schema.decodeUnknownEither(compilerOptionsSchema)(options).pipe( Either.mapLeft((e) => { const error = HelpDoc.p( - `Invalid TypeScript compiler options:\n${TreeFormatter.formatErrorSync(e)}` + `Invalid TypeScript compiler options:\n${ParseResult.TreeFormatter.formatErrorSync(e)}` ) return ValidationError.invalidValue(error) }) diff --git a/src/Configuration.ts b/src/Configuration.ts index bbc5349..20dddbe 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -4,16 +4,16 @@ import * as FileSystem from "@effect/platform/FileSystem" import * as Path from "@effect/platform/Path" -import * as Schema from "@effect/schema/Schema" -import * as TreeFormatter from "@effect/schema/TreeFormatter" import * as Array from "effect/Array" import * as Config from "effect/Config" import * as ConfigProvider from "effect/ConfigProvider" import * as Context from "effect/Context" import * as Effect from "effect/Effect" -import { identity } from "effect/Function" +import { identity, pipe } from "effect/Function" import * as Layer from "effect/Layer" import * as Option from "effect/Option" +import * as ParseResult from "effect/ParseResult" +import * as Schema from "effect/Schema" import * as tsconfck from "tsconfck" import { DocgenError } from "./Error.js" import * as Process from "./Process.js" @@ -33,8 +33,7 @@ const compilerOptionsSchema = Schema.Union( export const ConfigurationSchema = Schema.Struct({ "$schema": Schema.optional(Schema.String), projectHomepage: Schema.optional(Schema.String).annotations({ - description: - "Will link to the project homepage from the Auxiliary Links of the generated documentation." + description: "Will link to the project homepage from the Auxiliary Links of the generated documentation." }), srcDir: Schema.optional(Schema.String).annotations({ description: "The directory in which docgen will search for TypeScript files to parse.", @@ -45,13 +44,11 @@ export const ConfigurationSchema = Schema.Struct({ default: "docs" }), theme: Schema.optional(Schema.String).annotations({ - description: - "The theme that docgen will specify should be used for GitHub Docs in the generated _config.yml file.", + description: "The theme that docgen will specify should be used for GitHub Docs in the generated _config.yml file.", default: "mikearnaldi/just-the-docs" }), enableSearch: Schema.optional(Schema.Boolean).annotations({ - description: - "Whether or not search should be enabled for GitHub Docs in the generated _config.yml file.", + description: "Whether or not search should be enabled for GitHub Docs in the generated _config.yml file.", default: true }), enforceDescriptions: Schema.optional(Schema.Boolean).annotations({ @@ -68,8 +65,7 @@ export const ConfigurationSchema = Schema.Struct({ default: true }), exclude: Schema.optional(Schema.Array(Schema.String)).annotations({ - description: - "An array of glob strings specifying files that should be excluded from the documentation.", + description: "An array of glob strings specifying files that should be excluded from the documentation.", default: [] }), parseCompilerOptions: Schema.optional(compilerOptionsSchema).annotations({ @@ -106,9 +102,7 @@ export interface ConfigurationShape { * @category service * @since 1.0.0 */ -export class Configuration - extends Context.Tag("Configuration")() -{} +export class Configuration extends Context.Tag("Configuration")() {} /** @internal */ export const defaultCompilerOptions = { @@ -126,14 +120,13 @@ export const defaultCompilerOptions = { const readJsonFile = ( path: string ): Effect.Effect => - Effect.gen(function*(_) { - const fs = yield* _(FileSystem.FileSystem) - const content = yield* _(Effect.orDie(fs.readFileString(path))) - return yield* _( + Effect.gen(function*() { + const fs = yield* FileSystem.FileSystem + const content = yield* Effect.orDie(fs.readFileString(path)) + return yield* pipe( Effect.try({ try: () => JSON.parse(content), - catch: (error) => - `[FileSystem] Unable to read and parse JSON file from '${path}': ${String(error)}` + catch: (error) => `[FileSystem] Unable to read and parse JSON file from '${path}': ${String(error)}` }), Effect.orDie ) @@ -143,13 +136,13 @@ const validateJsonFile = ( schema: Schema.Schema, path: string ): Effect.Effect => - Effect.gen(function*(_) { - const content = yield* _(readJsonFile(path)) - return yield* _( + Effect.gen(function*() { + const content = yield* readJsonFile(path) + return yield* pipe( Schema.decodeUnknown(schema)(content), Effect.orDieWith((error) => new DocgenError({ - message: `[Configuration.validateJsonFile]\n${TreeFormatter.formatErrorSync(error)}` + message: `[Configuration.validateJsonFile]\n${ParseResult.TreeFormatter.formatErrorSync(error)}` }) ) ) @@ -162,11 +155,11 @@ const readDocgenConfig = ( never, FileSystem.FileSystem > => - Effect.gen(function*(_) { - const fs = yield* _(FileSystem.FileSystem) - const exists = yield* _(Effect.orDie(fs.exists(path))) + Effect.gen(function*() { + const fs = yield* FileSystem.FileSystem + const exists = yield* Effect.orDie(fs.exists(path)) if (exists) { - const config = yield* _(validateJsonFile(ConfigurationSchema, path)) + const config = yield* validateJsonFile(ConfigurationSchema, path) return Option.some(config) } else { return Option.none() @@ -178,11 +171,11 @@ const readTSConfig = (fileName: string): Effect.Effect< never, Path.Path | Process.Process > => - Effect.gen(function*(_) { - const path = yield* _(Path.Path) - const process = yield* _(Process.Process) - const cwd = yield* _(process.cwd) - return yield* _( + Effect.gen(function*() { + const path = yield* Path.Path + const process = yield* Process.Process + const cwd = yield* process.cwd + return yield* pipe( Effect.promise(() => tsconfck.parse(path.resolve(cwd, fileName))).pipe( Effect.map(({ tsconfig }) => tsconfig.compilerOptions ?? defaultCompilerOptions), Effect.orDieWith((error) => @@ -196,9 +189,7 @@ const readTSConfig = (fileName: string): Effect.Effect< const loadCompilerOptions = (configKey: string) => Config.string(configKey).pipe( - Effect.flatMap((config) => - Schema.decodeUnknown(JsonRecordSchema)(config).pipe(Effect.orElseSucceed(() => config)) - ) + Effect.flatMap((config) => Schema.decodeUnknown(JsonRecordSchema)(config).pipe(Effect.orElseSucceed(() => config))) ) const resolveCompilerOptions = ( @@ -245,22 +236,22 @@ export const load = (args: { readonly parseCompilerOptions: Option.Option> readonly examplesCompilerOptions: Option.Option> }) => - Effect.gen(function*(_) { + Effect.gen(function*() { // Extract the requisite services - const process = yield* _(Process.Process) - const cwd = yield* _(process.cwd) - const path = yield* _(Path.Path) + const process = yield* Process.Process + const cwd = yield* process.cwd + const path = yield* Path.Path // Read and parse the required fields from the `package.json` const packageJsonPath = path.join(cwd, PACKAGE_JSON_FILE_NAME) - const packageJson = yield* _(validateJsonFile(PackageJsonSchema, packageJsonPath)) + const packageJson = yield* validateJsonFile(PackageJsonSchema, packageJsonPath) const projectName = packageJson.name const projectHomepage = Option.getOrElse(args.projectHomepage, () => packageJson.homepage) // Read the `docgen.json` configuration file to gain access to the TypeScript // configuration options const configPath = path.join(cwd, CONFIG_FILE_NAME) - const config = yield* _(readDocgenConfig(configPath)) + const config = yield* readDocgenConfig(configPath) // Resolve the excluded files const exclude = Array.match(args.exclude, { @@ -273,19 +264,15 @@ export const load = (args: { }) // Resolve the TypeScript configuration options - const examplesCompilerOptions = yield* _( - resolveCompilerOptions( - "examplesCompilerOptions", - args.examplesCompilerOptions, - Option.flatMap(config, (config) => Option.fromNullable(config.examplesCompilerOptions)) - ) + const examplesCompilerOptions = yield* resolveCompilerOptions( + "examplesCompilerOptions", + args.examplesCompilerOptions, + Option.flatMap(config, (config) => Option.fromNullable(config.examplesCompilerOptions)) ) - const parseCompilerOptions = yield* _( - resolveCompilerOptions( - "parseCompilerOptions", - args.parseCompilerOptions, - Option.flatMap(config, (config) => Option.fromNullable(config.parseCompilerOptions)) - ) + const parseCompilerOptions = yield* resolveCompilerOptions( + "parseCompilerOptions", + args.parseCompilerOptions, + Option.flatMap(config, (config) => Option.fromNullable(config.parseCompilerOptions)) ) const srcDir = config.pipe( @@ -311,14 +298,14 @@ export const load = (args: { }) /** @internal */ -export const configProviderLayer = Layer.scopedDiscard(Effect.gen(function*(_) { +export const configProviderLayer = Layer.scopedDiscard(Effect.gen(function*() { // Extract the requisite services - const process = yield* _(Process.Process) - const cwd = yield* _(process.cwd) - const path = yield* _(Path.Path) + const process = yield* Process.Process + const cwd = yield* process.cwd + const path = yield* Path.Path // Attempt to load the `docgen.json` configuration file const configPath = path.join(cwd, CONFIG_FILE_NAME) - const maybeConfig = yield* _(readDocgenConfig(configPath)) + const maybeConfig = yield* readDocgenConfig(configPath) // Construct a config provider for the environment const fromEnv = ConfigProvider.fromEnv({ pathDelim: "_", seqDelim: "," }).pipe( ConfigProvider.nested("DOCGEN"), @@ -328,5 +315,5 @@ export const configProviderLayer = Layer.scopedDiscard(Effect.gen(function*(_) { const fromDocgenJson = ConfigProvider.fromJson(Option.getOrElse(maybeConfig, () => ({}))) // Prefer the environment over the `docgen.json` file const provider = fromEnv.pipe(ConfigProvider.orElse(() => fromDocgenJson)) - yield* _(Effect.withConfigProviderScoped(provider)) + yield* Effect.withConfigProviderScoped(provider) })) diff --git a/src/Core.ts b/src/Core.ts index 4f7a6c8..f5f3950 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -46,47 +46,47 @@ const glob = (pattern: string, exclude: ReadonlyArray = []) => * Reads all TypeScript files in the source directory and returns an array of file objects. * Each file object contains the file path and its content. */ -const readSourceFiles = Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const fs = yield* _(FileSystem.FileSystem) - const path = yield* _(Path.Path, Effect.provide(NodePath.layerPosix)) +const readSourceFiles = Effect.gen(function*() { + const config = yield* Configuration.Configuration + const fs = yield* FileSystem.FileSystem + const path = yield* pipe(Path.Path, Effect.provide(NodePath.layerPosix)) const pattern = path.normalize(path.join(config.srcDir, "**", "*.ts")) - const paths = yield* _(glob(pattern, config.exclude)) - yield* _(Effect.logInfo(chalk.bold(`${paths.length} module(s) found`))) - return yield* _(Effect.forEach(paths, (path) => + const paths = yield* glob(pattern, config.exclude) + yield* Effect.logInfo(chalk.bold(`${paths.length} module(s) found`)) + return yield* Effect.forEach(paths, (path) => Effect.map( fs.readFileString(path), (content) => File.createFile(path, content, false) - ), { concurrency: "inherit" })) + ), { concurrency: "inherit" }) }) /** * Writes a file to the `config.outDir` directory, taking into account the configuration and existing files. */ const writeFileToOutDir = (file: File.File) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const fs = yield* _(FileSystem.FileSystem) - const path = yield* _(Path.Path) - const process = yield* _(Process.Process) - const cwd = yield* _(process.cwd) + Effect.gen(function*() { + const config = yield* Configuration.Configuration + const fs = yield* FileSystem.FileSystem + const path = yield* Path.Path + const process = yield* Process.Process + const cwd = yield* process.cwd const fileName = path.relative(path.join(cwd, config.outDir), file.path) - const exists = yield* _(fs.exists(file.path)) + const exists = yield* fs.exists(file.path) if (exists) { if (file.isOverwriteable) { - yield* _(Effect.logDebug(`Overwriting file ${chalk.black(fileName)}...`)) - yield* _(fs.makeDirectory(path.dirname(file.path), { recursive: true })) - yield* _(fs.writeFileString(file.path, file.content)) + yield* Effect.logDebug(`Overwriting file ${chalk.black(fileName)}...`) + yield* fs.makeDirectory(path.dirname(file.path), { recursive: true }) + yield* fs.writeFileString(file.path, file.content) } else { - yield* _(Effect.logDebug( + yield* Effect.logDebug( `File ${chalk.black(fileName)} already exists, skipping creation.` - )) + ) } } else { - yield* _(fs.makeDirectory(path.dirname(file.path), { recursive: true })) - yield* _(fs.writeFileString(file.path, file.content)) + yield* fs.makeDirectory(path.dirname(file.path), { recursive: true }) + yield* fs.writeFileString(file.path, file.content) } }) @@ -99,9 +99,7 @@ const parseModules = (files: ReadonlyArray) => Effect.mapError((errors) => new DocgenError({ message: "[Core.parseModules] The following error(s) occurred while " + - `parsing the TypeScript source files:\n${ - errors.map((errors) => errors.join("\n")).join("\n") - }` + `parsing the TypeScript source files:\n${errors.map((errors) => errors.join("\n")).join("\n")}` }) ) ) @@ -110,24 +108,24 @@ const parseModules = (files: ReadonlyArray) => * Runs the example files for the given modules, type-checking them before execution. */ const typeCheckAndRunExamples = (modules: ReadonlyArray) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) + Effect.gen(function*() { + const config = yield* Configuration.Configuration if (config.runExamples) { - yield* _(Effect.logInfo("Typechecking examples...")) - yield* _(cleanupExamples) - const files = yield* _(getExampleFiles(modules)) - const examples = yield* _(handleImports(files)) + yield* Effect.logInfo("Typechecking examples...") + yield* cleanupExamples + const files = yield* getExampleFiles(modules) + const examples = yield* handleImports(files) const len = examples.length if (len > 0) { - yield* _(Effect.logInfo(`${len} example(s) found`)) - yield* _(writeExamplesToOutDir(examples)) - yield* _(createExamplesTsConfigJson) - yield* _(runTscOnExamples) - yield* _(runTsxOnExamples) + yield* Effect.logInfo(`${len} example(s) found`) + yield* writeExamplesToOutDir(examples) + yield* createExamplesTsConfigJson + yield* runTscOnExamples + yield* runTsxOnExamples } else { - yield* _(Effect.logInfo("No examples found.")) + yield* Effect.logInfo("No examples found.") } - yield* _(cleanupExamples) + yield* cleanupExamples } }) @@ -161,9 +159,9 @@ const extractPrefixedNestedNamespaces = ( * Generates example files for the given modules. */ const getExampleFiles = (modules: ReadonlyArray) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const path = yield* _(Path.Path) + Effect.gen(function*() { + const config = yield* Configuration.Configuration + const path = yield* Path.Path return Array.flatMap(modules, (module) => { const prefix = module.path.join("-") @@ -208,13 +206,10 @@ const getExampleFiles = (modules: ReadonlyArray) => ] const interfacesExamples = Array.flatMap( allPrefixedInterfaces, - ([ns, doc]) => - getFiles(filterJoin(["interface", ns]))(doc) + ([ns, doc]) => getFiles(filterJoin(["interface", ns]))(doc) ) const allPrefixedTypeAliases = [ - ...module.typeAliases.map((typeAlias) => - ["" as string, typeAlias] as const - ), + ...module.typeAliases.map((typeAlias) => ["" as string, typeAlias] as const), ...Array.flatMap(allPrefixedNamespaces, ([prefix, namespace]) => namespace.typeAliases.map((typeAlias) => [filterJoin([prefix, namespace.name]), typeAlias] as const @@ -235,8 +230,7 @@ const getExampleFiles = (modules: ReadonlyArray) => ) const namespacesExamples = Array.flatMap( allPrefixedNamespaces, - ([ns, doc]) => - getFiles(filterJoin(["namespace", ns]))(doc) + ([ns, doc]) => getFiles(filterJoin(["namespace", ns]))(doc) ) return Array.flatten([ @@ -263,8 +257,8 @@ const addAssertImport = (code: string): string => * Replaces the project name in the given source code imports with the configured project name. */ const replaceProjectName = (source: string) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) + Effect.gen(function*() { + const config = yield* Configuration.Configuration const importRegex = (projectName: string) => new RegExp( `from (?['"])${projectName}(?:/lib)?(?:/(?.*))?\\k`, @@ -281,8 +275,8 @@ const replaceProjectName = (source: string) => const handleImports = (files: ReadonlyArray) => Effect.forEach(files, (file) => - Effect.gen(function*(_) { - const source = yield* _(replaceProjectName(file.content)) + Effect.gen(function*() { + const source = yield* replaceProjectName(file.content) const content = addAssertImport(source) return File.createFile(file.path, content, file.isOverwriteable) })) @@ -291,9 +285,9 @@ const handleImports = (files: ReadonlyArray) => * Generates an entry point file for the given examples. */ const getExamplesEntryPoint = (examples: ReadonlyArray) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const path = yield* _(Path.Path) + Effect.gen(function*() { + const config = yield* Configuration.Configuration + const path = yield* Path.Path const content = examples.map((example) => `import './${path.basename(example.path, ".ts")}'`) .join("\n") return File.createFile( @@ -306,27 +300,27 @@ const getExamplesEntryPoint = (examples: ReadonlyArray) => /** * Removes the "examples" directory from the output directory specified in the configuration. */ -const cleanupExamples = Effect.gen(function*(_) { - const fs = yield* _(FileSystem.FileSystem) - const config = yield* _(Configuration.Configuration) - const path = yield* _(Path.Path) +const cleanupExamples = Effect.gen(function*() { + const fs = yield* FileSystem.FileSystem + const config = yield* Configuration.Configuration + const path = yield* Path.Path const examplesDir = path.join(config.outDir, "examples") - const exists = yield* _(Effect.orDie(fs.exists(examplesDir))) + const exists = yield* Effect.orDie(fs.exists(examplesDir)) if (exists) { - yield* _(fs.remove(examplesDir, { recursive: true })) + yield* fs.remove(examplesDir, { recursive: true }) } }) /** * Runs tsc on the examples directory. */ -const runTscOnExamples = Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const process = yield* _(Process.Process) - const executor = yield* _(CommandExecutor.CommandExecutor) - const cwd = yield* _(process.cwd) - const path = yield* _(Path.Path) - const platform = yield* _(process.platform) +const runTscOnExamples = Effect.gen(function*() { + const config = yield* Configuration.Configuration + const process = yield* Process.Process + const executor = yield* CommandExecutor.CommandExecutor + const cwd = yield* process.cwd + const path = yield* Path.Path + const platform = yield* process.platform const tsconfig = path.normalize(path.join(cwd, config.outDir, "examples", "tsconfig.json")) const options = ["--noEmit", "--project", tsconfig] @@ -334,9 +328,9 @@ const runTscOnExamples = Effect.gen(function*(_) { ? Command.runInShell(Command.make("tsc.cmd", ...options), true) : Command.make("tsc", ...options) - yield* _(Effect.logDebug("Running tsc on examples...")) + yield* Effect.logDebug("Running tsc on examples...") - const [stdout, exitCode] = yield* _( + const [stdout, exitCode] = yield* pipe( executor.start(command), Effect.flatMap((process) => Effect.all([ @@ -352,24 +346,22 @@ const runTscOnExamples = Effect.gen(function*(_) { ) if (exitCode !== 0) { - yield* _( - new DocgenError({ - message: `Something went wrong while running tsc on examples:\n\n${stdout.join("\n")}` - }) - ) + yield* new DocgenError({ + message: `Something went wrong while running tsc on examples:\n\n${stdout.join("\n")}` + }) } }) /** * Runs tsc on the examples directory. */ -const runTsxOnExamples = Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const path = yield* _(Path.Path) - const process = yield* _(Process.Process) - const executor = yield* _(CommandExecutor.CommandExecutor) - const cwd = yield* _(process.cwd) - const platform = yield* _(process.platform) +const runTsxOnExamples = Effect.gen(function*() { + const config = yield* Configuration.Configuration + const path = yield* Path.Path + const process = yield* Process.Process + const executor = yield* CommandExecutor.CommandExecutor + const cwd = yield* process.cwd + const platform = yield* process.platform const examples = path.normalize(path.join(cwd, config.outDir, "examples")) const tsconfig = path.join(examples, "tsconfig.json") @@ -379,9 +371,9 @@ const runTsxOnExamples = Effect.gen(function*(_) { ? Command.runInShell(Command.make("tsx.cmd", ...options), true) : Command.make("tsx", ...options) - yield* _(Effect.logDebug("Running tsx on examples...")) + yield* Effect.logDebug("Running tsx on examples...") - const [stdout, exitCode] = yield* _( + const [stdout, exitCode] = yield* pipe( executor.start(command), Effect.flatMap((process) => Effect.all([ @@ -397,53 +389,51 @@ const runTsxOnExamples = Effect.gen(function*(_) { ) if (exitCode !== 0) { - yield* _( - Effect.fail( - new DocgenError({ - message: `Something went wrong while running tsx on examples:\n\n${stdout.join("\n")}` - }) - ) + yield* Effect.fail( + new DocgenError({ + message: `Something went wrong while running tsx on examples:\n\n${stdout.join("\n")}` + }) ) } }) const writeExamplesToOutDir = (examples: ReadonlyArray) => - Effect.gen(function*(_) { - yield* _(Effect.logDebug("Writing examples...")) - const entryPoint = yield* _(getExamplesEntryPoint(examples)) + Effect.gen(function*() { + yield* Effect.logDebug("Writing examples...") + const entryPoint = yield* getExamplesEntryPoint(examples) const files = [entryPoint, ...examples] - yield* _(writeFilesToOutDir(files)) + yield* writeFilesToOutDir(files) }) -const createExamplesTsConfigJson = Effect.gen(function*(_) { - yield* _(Effect.logDebug("Writing examples tsconfig...")) - const config = yield* _(Configuration.Configuration) - const process = yield* _(Process.Process) - const cwd = yield* _(process.cwd) - const path = yield* _(Path.Path) - yield* _(writeFileToOutDir( +const createExamplesTsConfigJson = Effect.gen(function*() { + yield* Effect.logDebug("Writing examples tsconfig...") + const config = yield* Configuration.Configuration + const process = yield* Process.Process + const cwd = yield* process.cwd + const path = yield* Path.Path + yield* writeFileToOutDir( File.createFile( path.join(cwd, config.outDir, "examples", "tsconfig.json"), JSON.stringify({ compilerOptions: config.examplesCompilerOptions }, null, 2), true // make the file overwritable ) - )) + ) }) const getMarkdown = (modules: ReadonlyArray) => - Effect.gen(function*(_) { - const homepage = yield* _(getMarkdownHomepage) - const index = yield* _(getMarkdownIndex) - const yml = yield* _(getMarkdownConfigYML) - const moduleFiles = yield* _(getModuleMarkdownFiles(modules)) + Effect.gen(function*() { + const homepage = yield* getMarkdownHomepage + const index = yield* getMarkdownIndex + const yml = yield* getMarkdownConfigYML + const moduleFiles = yield* getModuleMarkdownFiles(modules) return [homepage, index, yml, ...moduleFiles] }) -const getMarkdownHomepage = Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const process = yield* _(Process.Process) - const cwd = yield* _(process.cwd) - const path = yield* _(Path.Path) +const getMarkdownHomepage = Effect.gen(function*() { + const config = yield* Configuration.Configuration + const process = yield* Process.Process + const cwd = yield* process.cwd + const path = yield* Path.Path return File.createFile( path.join(cwd, config.outDir, "index.md"), String.stripMargin( @@ -457,11 +447,11 @@ const getMarkdownHomepage = Effect.gen(function*(_) { ) }) -const getMarkdownIndex = Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const process = yield* _(Process.Process) - const cwd = yield* _(process.cwd) - const path = yield* _(Path.Path) +const getMarkdownIndex = Effect.gen(function*() { + const config = yield* Configuration.Configuration + const process = yield* Process.Process + const cwd = yield* process.cwd + const path = yield* Path.Path return File.createFile( path.join(cwd, config.outDir, "modules", "index.md"), String.stripMargin( @@ -478,8 +468,8 @@ const getMarkdownIndex = Effect.gen(function*(_) { }) const resolveConfigYML = (content: string) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) + Effect.gen(function*() { + const config = yield* Configuration.Configuration return content .replace(/^remote_theme:.*$/m, `remote_theme: ${config.theme}`) .replace( @@ -496,17 +486,17 @@ const getHomepageNavigationHeader = (config: Configuration.ConfigurationShape): return isGitHub ? config.projectName + " on GitHub" : "Homepage" } -const getMarkdownConfigYML = Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const process = yield* _(Process.Process) - const fs = yield* _(FileSystem.FileSystem) - const cwd = yield* _(process.cwd) - const path = yield* _(Path.Path) +const getMarkdownConfigYML = Effect.gen(function*() { + const config = yield* Configuration.Configuration + const process = yield* Process.Process + const fs = yield* FileSystem.FileSystem + const cwd = yield* process.cwd + const path = yield* Path.Path const configPath = path.join(cwd, config.outDir, "_config.yml") - const exists = yield* _(fs.exists(configPath)) + const exists = yield* fs.exists(configPath) if (exists) { - const content = yield* _(fs.readFileString(configPath)) - const resolved = yield* _(resolveConfigYML(content)) + const content = yield* fs.readFileString(configPath) + const resolved = yield* resolveConfigYML(content) return File.createFile(configPath, resolved, true) } else { return File.createFile( @@ -540,36 +530,36 @@ const getModuleMarkdownOutputPath = (module: Domain.Module) => const getModuleMarkdownFiles = (modules: ReadonlyArray) => Effect.forEach(modules, (module, order) => - Effect.gen(function*(_) { - const outputPath = yield* _(getModuleMarkdownOutputPath(module)) - const content = yield* _(printModule(module, order + 1)) + Effect.gen(function*() { + const outputPath = yield* getModuleMarkdownOutputPath(module) + const content = yield* printModule(module, order + 1) return File.createFile(outputPath, content, true) })) const writeMarkdown = (files: ReadonlyArray) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const path = yield* _(Path.Path, Effect.provide(NodePath.layerPosix)) - const fileSystem = yield* _(FileSystem.FileSystem) + Effect.gen(function*() { + const config = yield* Configuration.Configuration + const path = yield* pipe(Path.Path, Effect.provide(NodePath.layerPosix)) + const fileSystem = yield* FileSystem.FileSystem const pattern = path.normalize(path.join(config.outDir, "**/*.ts.md")) - yield* _(Effect.logDebug(`Deleting ${chalk.black(pattern)}...`)) - const paths = yield* _(glob(pattern)) - yield* _(Effect.forEach(paths, (path) => fileSystem.remove(path, { recursive: true }), { + yield* Effect.logDebug(`Deleting ${chalk.black(pattern)}...`) + const paths = yield* glob(pattern) + yield* Effect.forEach(paths, (path) => fileSystem.remove(path, { recursive: true }), { concurrency: "unbounded" - })) - return yield* _(writeFilesToOutDir(files)) + }) + return yield* writeFilesToOutDir(files) }) /** @internal */ -export const program = Effect.gen(function*(_) { - yield* _(Effect.logInfo("Reading modules...")) - const sourceFiles = yield* _(readSourceFiles) - yield* _(Effect.logInfo("Parsing modules...")) - const modules = yield* _(parseModules(sourceFiles)) - yield* _(typeCheckAndRunExamples(modules)) - yield* _(Effect.logInfo("Creating markdown files...")) - const outputFiles = yield* _(getMarkdown(modules)) - yield* _(Effect.logInfo("Writing markdown files...")) - yield* _(writeMarkdown(outputFiles)) - yield* _(Effect.logInfo(chalk.bold.green("Docs generation succeeded!"))) +export const program = Effect.gen(function*() { + yield* Effect.logInfo("Reading modules...") + const sourceFiles = yield* readSourceFiles + yield* Effect.logInfo("Parsing modules...") + const modules = yield* parseModules(sourceFiles) + yield* typeCheckAndRunExamples(modules) + yield* Effect.logInfo("Creating markdown files...") + const outputFiles = yield* getMarkdown(modules) + yield* Effect.logInfo("Writing markdown files...") + yield* writeMarkdown(outputFiles) + yield* Effect.logInfo(chalk.bold.green("Docs generation succeeded!")) }) diff --git a/src/Markdown.ts b/src/Markdown.ts index 7e22038..e5313fc 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -20,13 +20,11 @@ type Printable = | Domain.TypeAlias | Domain.Namespace -const createHeaderPrinter = (level: number) => (content: string): string => - "#".repeat(level) + " " + content + "\n\n" +const createHeaderPrinter = (level: number) => (content: string): string => "#".repeat(level) + " " + content + "\n\n" const MarkdownPrinter = { bold: (s: string) => `**${s}**`, - fence: (start: string, content: string, end: string) => - start + "\n" + content + "\n" + end + "\n\n", + fence: (start: string, content: string, end: string) => start + "\n" + content + "\n" + end + "\n\n", paragraph: (...content: ReadonlyArray) => "\n" + content.join("") + "\n\n", strikethrough: (content: string) => `~~${content}~~`, h1: createHeaderPrinter(1), @@ -51,8 +49,7 @@ const printTitle = (s: string, deprecated: boolean, type?: string): string => { ) } -const printDescription = (d: Option.Option): string => - MarkdownPrinter.paragraph(Option.getOrElse(d, () => "")) +const printDescription = (d: Option.Option): string => MarkdownPrinter.paragraph(Option.getOrElse(d, () => "")) const printSignature = (s: string): string => MarkdownPrinter.paragraph(MarkdownPrinter.bold("Signature")) + @@ -283,7 +280,7 @@ export const printModule = ( module: Domain.Module, order: number ): Effect.Effect => - Effect.gen(function*(_) { + Effect.gen(function*() { const header = printMeta(module.path.slice(1).join("/"), order) const description = MarkdownPrinter.paragraph(printModuleDescription(module)) @@ -310,22 +307,20 @@ export const printModule = ( ) ).join("\n") - const toc = yield* _( - Effect.tryPromise({ - try: () => { - // @ts-ignore - return import("@effect/markdown-toc").then((m) => m.default) - }, - catch: identity - }).pipe(Effect.orDie) - ) + const toc = yield* Effect.tryPromise({ + try: () => { + // @ts-ignore + return import("@effect/markdown-toc").then((m) => m.default) + }, + catch: identity + }).pipe(Effect.orDie) const tableOfContents = (content: string) => "

Table of contents

\n\n" + toc(content).content + "\n\n" - return yield* _(prettify( + return yield* prettify( [ header, description, @@ -334,7 +329,7 @@ export const printModule = ( "---\n", content ].join("\n") - )) + ) }) const defaultPrettierOptions: Prettier.Options = { diff --git a/src/Parser.ts b/src/Parser.ts index 671389c..61bb55b 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -52,8 +52,7 @@ const getJSDocText: (jsdocs: ReadonlyArray) => string = Array.matchRi onNonEmpty: (_, last) => last.getText() }) -const hasTag = (tag: string) => (comment: Comment) => - pipe(comment.tags, Record.get(tag), Option.isSome) +const hasTag = (tag: string) => (comment: Comment) => pipe(comment.tags, Record.get(tag), Option.isSome) const hasInternalTag = hasTag("internal") @@ -106,13 +105,12 @@ const getMissingTagError = ( tag: string, path: ReadonlyArray, name: string -): string => - `Missing ${chalk.bold(tag)} tag in ${chalk.bold(path.join("/") + "#" + name)} documentation` +): string => `Missing ${chalk.bold(tag)} tag in ${chalk.bold(path.join("/") + "#" + name)} documentation` const getSinceTag = (name: string, comment: Comment) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const source = yield* _(Source) + Effect.gen(function*() { + const config = yield* Configuration.Configuration + const source = yield* Source const since = Record.get(comment.tags, "since").pipe( Option.flatMap(Array.headNonEmpty), Option.map(String.trim), @@ -121,14 +119,14 @@ const getSinceTag = (name: string, comment: Comment) => if ( Option.isNone(since) && (config.enforceVersion || Record.has(comment.tags, "since")) ) { - return yield* _(Effect.fail(getMissingTagError("@since", source.path, name))) + return yield* Effect.fail(getMissingTagError("@since", source.path, name)) } return since }) const getCategoryTag = (name: string, comment: Comment) => - Effect.gen(function*(_) { - const source = yield* _(Source) + Effect.gen(function*() { + const source = yield* Source const category = Record.get(comment.tags, "category").pipe( Option.flatMap(Array.headNonEmpty), Option.map(String.trim), @@ -137,29 +135,24 @@ const getCategoryTag = (name: string, comment: Comment) => if ( Option.isNone(category) && (Record.has(comment.tags, "category")) ) { - return yield* _(Effect.fail(getMissingTagError("@category", source.path, name))) + return yield* Effect.fail(getMissingTagError("@category", source.path, name)) } return category }) const getDescription = (name: string, comment: Comment) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const source = yield* _(Source) + Effect.gen(function*() { + const config = yield* Configuration.Configuration + const source = yield* Source if (Option.isNone(comment.description) && config.enforceDescriptions) { - return yield* _( - Effect.fail( - `Missing ${chalk.bold("description")} in ${ - chalk.bold(source.path.join("/") + "#" + name) - } documentation` - ) + return yield* Effect.fail( + `Missing ${chalk.bold("description")} in ${chalk.bold(source.path.join("/") + "#" + name)} documentation` ) } return comment.description }) -const fencedExampleRegex = - /^(?(```|~~~)[^\n]*)\n(?[\S\s]*)(?\n(```|~~~))$/ +const fencedExampleRegex = /^(?(```|~~~)[^\n]*)\n(?[\S\s]*)(?\n(```|~~~))$/ const parseExample = (body: string) => { const example = fencedExampleRegex.exec(body) @@ -177,15 +170,15 @@ const parseExample = (body: string) => { } const getExamplesTag = (name: string, comment: Comment, isModule: boolean) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const source = yield* _(Source) + Effect.gen(function*() { + const config = yield* Configuration.Configuration + const source = yield* Source const examples = Record.get(comment.tags, "example").pipe( Option.map(flow(Array.getSomes, Array.map(parseExample))), Option.getOrElse(() => []) ) if (Array.isEmptyArray(examples) && config.enforceExamples && !isModule) { - return yield* _(Effect.fail(getMissingTagError("@example", source.path, name))) + return yield* Effect.fail(getMissingTagError("@example", source.path, name)) } return examples }) @@ -194,12 +187,12 @@ const getExamplesTag = (name: string, comment: Comment, isModule: boolean) => * @internal */ export const getDoc = (name: string, text: string, isModule = false) => - Effect.gen(function*(_) { + Effect.gen(function*() { const comment = parseComment(text) - const since = yield* _(getSinceTag(name, comment)) - const category = yield* _(getCategoryTag(name, comment)) - const description = yield* _(getDescription(name, comment)) - const examples = yield* _(getExamplesTag(name, comment, isModule)) + const since = yield* getSinceTag(name, comment) + const category = yield* getCategoryTag(name, comment) + const description = yield* getDescription(name, comment) + const examples = yield* getExamplesTag(name, comment, isModule) const deprecated = Option.isSome(Record.get(comment.tags, "deprecated")) return Domain.createDoc( description, @@ -211,10 +204,10 @@ export const getDoc = (name: string, text: string, isModule = false) => }) const parseInterfaceDeclaration = (id: ast.InterfaceDeclaration) => - Effect.gen(function*(_) { + Effect.gen(function*() { const name = id.getName() const text = getJSDocText(id.getJsDocs()) - const doc = yield* _(getDoc(name, text)) + const doc = yield* getDoc(name, text) const signature = id.getText() return Domain.createInterface( Domain.createNamedDoc( @@ -278,18 +271,17 @@ const getFunctionDeclarationJSDocs = ( ) const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => - Effect.gen(function*(_) { - const source = yield* _(Source) - const name = yield* _(pipe( + Effect.gen(function*() { + const source = yield* Source + const name = yield* pipe( Option.fromNullable(fd.getName()), Option.flatMap(Option.liftPredicate((name) => name.length > 0)), Effect.mapError( - () => - `Missing ${chalk.bold("function name")} in module ${chalk.bold(source.path.join("/"))}` + () => `Missing ${chalk.bold("function name")} in module ${chalk.bold(source.path.join("/"))}` ) - )) + ) const text = getJSDocText(getFunctionDeclarationJSDocs(fd)) - const doc = yield* _(getDoc(name, text)) + const doc = yield* getDoc(name, text) const signatures = pipe( fd.getOverloads(), Array.matchRight({ @@ -315,11 +307,11 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => }) const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => - Effect.gen(function*(_) { + Effect.gen(function*() { const vs: any = vd.getParent().getParent() const name = vd.getName() const text = getJSDocText(vs.getJsDocs()) - const doc = yield* _(getDoc(name, text)) + const doc = yield* getDoc(name, text) const signature = `export declare const ${name}: ${ stripImportTypes( vd.getType().getText(vd) @@ -338,8 +330,8 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => ) }) -const getFunctionDeclarations = Effect.gen(function*(_) { - const source = yield* _(Source) +const getFunctionDeclarations = Effect.gen(function*() { + const source = yield* Source const functions = Array.filter( source.sourceFile.getFunctions(), (fd) => fd.isExported() && shouldNotIgnore(getFunctionDeclarationJSDocs(fd)) @@ -369,20 +361,18 @@ const getFunctionDeclarations = Effect.gen(function*(_) { * @category parsers * @since 1.0.0 */ -export const parseFunctions = Effect.gen(function*(_) { - const { arrows, functions } = yield* _(getFunctionDeclarations) - const functionDeclarations = yield* _(Effect.validateAll(functions, parseFunctionDeclaration)) - const functionVariableDeclarations = yield* _( - Effect.validateAll(arrows, parseFunctionVariableDeclaration) - ) +export const parseFunctions = Effect.gen(function*() { + const { arrows, functions } = yield* getFunctionDeclarations + const functionDeclarations = yield* Effect.validateAll(functions, parseFunctionDeclaration) + const functionVariableDeclarations = yield* Effect.validateAll(arrows, parseFunctionVariableDeclaration) return [...functionDeclarations, ...functionVariableDeclarations] }) const parseTypeAliasDeclaration = (ta: ast.TypeAliasDeclaration) => - Effect.gen(function*(_) { + Effect.gen(function*() { const name = ta.getName() const text = getJSDocText(ta.getJsDocs()) - const doc = yield* _(getDoc(name, text)) + const doc = yield* getDoc(name, text) const signature = ta.getText() return Domain.createTypeAlias( Domain.createNamedDoc( @@ -417,11 +407,11 @@ export const parseTypeAliases = Effect.flatMap( ) const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => - Effect.gen(function*(_) { + Effect.gen(function*() { const vs: any = vd.getParent().getParent() const name = vd.getName() const text = getJSDocText(vs.getJsDocs()) - const doc = yield* _(getDoc(name, text)) + const doc = yield* getDoc(name, text) const type = stripImportTypes(vd.getType().getText(vd)) const signature = `export declare const ${name}: ${type}` return Domain.createConstant( @@ -441,8 +431,8 @@ const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => * @category parsers * @since 1.0.0 */ -export const parseConstants = Effect.gen(function*(_) { - const source = yield* _(Source) +export const parseConstants = Effect.gen(function*() { + const source = yield* Source const variableDeclarations = pipe( Array.filter( source.sourceFile.getVariableDeclarations(), @@ -461,25 +451,23 @@ export const parseConstants = Effect.gen(function*(_) { } ) ) - return yield* _(Effect.validateAll(variableDeclarations, parseConstantVariableDeclaration)) + return yield* Effect.validateAll(variableDeclarations, parseConstantVariableDeclaration) }) const parseExportSpecifier = (es: ast.ExportSpecifier) => - Effect.gen(function*(_) { - const source = yield* _(Source) + Effect.gen(function*() { + const source = yield* Source const name = es.compilerNode.name.text const type = stripImportTypes(es.getType().getText(es)) const ocommentRange = Array.head(es.getLeadingCommentRanges()) if (Option.isNone(ocommentRange)) { - return yield* _( - Effect.fail( - `Missing ${chalk.bold(name)} documentation in ${chalk.bold(source.path.join("/"))}` - ) + return yield* Effect.fail( + `Missing ${chalk.bold(name)} documentation in ${chalk.bold(source.path.join("/"))}` ) } const commentRange = ocommentRange.value const text = commentRange.getText() - const doc = yield* _(getDoc(name, text)) + const doc = yield* getDoc(name, text) const signature = `export declare const ${name}: ${type}` return Domain.createExport( Domain.createNamedDoc( @@ -497,23 +485,21 @@ const parseExportSpecifier = (es: ast.ExportSpecifier) => const parseExportStar = ( ed: ast.ExportDeclaration ): Effect.Effect => - Effect.gen(function*(_) { - const source = yield* _(Source) + Effect.gen(function*() { + const source = yield* Source const es = ed.getModuleSpecifier()! const name = es.getText() const namespace = ed.getNamespaceExport()?.getName() const signature = `export *${namespace === undefined ? "" : ` as ${namespace}`} from ${name}` const ocommentRange = Array.head(ed.getLeadingCommentRanges()) if (Option.isNone(ocommentRange)) { - return yield* _( - Effect.fail( - `Missing ${chalk.bold(signature)} documentation in ${chalk.bold(source.path.join("/"))}` - ) + return yield* Effect.fail( + `Missing ${chalk.bold(signature)} documentation in ${chalk.bold(source.path.join("/"))}` ) } const commentRange = ocommentRange.value const text = commentRange.getText() - const doc = yield* _(getDoc(name, text)) + const doc = yield* getDoc(name, text) return Domain.createExport( Domain.createNamedDoc( `From ${name}`, @@ -574,11 +560,11 @@ const parseModuleDeclaration = ( ed.getTypeAliases() ) const getNamespaces = parseModuleDeclarations(ed.getModules()) - return Effect.gen(function*(_) { - const info = yield* _(getInfo) - const interfaces = yield* _(getInterfaces) - const typeAliases = yield* _(getTypeAliases) - const namespaces = yield* _(getNamespaces) + return Effect.gen(function*() { + const info = yield* getInfo + const interfaces = yield* getInterfaces + const typeAliases = yield* getTypeAliases + const namespaces = yield* getNamespaces return Domain.createNamespace( Domain.createNamedDoc( name, @@ -635,7 +621,7 @@ const getMethodSignature = (md: ast.MethodDeclaration): string => ) const parseMethod = (md: ast.MethodDeclaration) => - Effect.gen(function*(_) { + Effect.gen(function*() { const name = md.getName() const overloads = md.getOverloads() const jsdocs = pipe( @@ -647,7 +633,7 @@ const parseMethod = (md: ast.MethodDeclaration) => ) if (shouldNotIgnore(jsdocs)) { const text = getJSDocText(jsdocs) - const doc = yield* _(getDoc(name, text)) + const doc = yield* getDoc(name, text) const signatures = pipe( overloads, Array.matchRight({ @@ -677,10 +663,10 @@ const parseMethod = (md: ast.MethodDeclaration) => }) const parseProperty = (classname: string) => (pd: ast.PropertyDeclaration) => - Effect.gen(function*(_) { + Effect.gen(function*() { const name = pd.getName() const text = getJSDocText(pd.getJsDocs()) - const doc = yield* _(getDoc(`${classname}#${name}`, text)) + const doc = yield* getDoc(`${classname}#${name}`, text) const type = stripImportTypes(pd.getType().getText(pd)) const readonly = pipe( Option.fromNullable( @@ -767,21 +753,21 @@ const getClassDeclarationSignature = (name: string, c: ast.ClassDeclaration) => ) const parseClass = (c: ast.ClassDeclaration) => - Effect.gen(function*(_) { - const name = yield* _(getClassName(c)) - const doc = yield* _(getClassDoc(name, c)) - const signature = yield* _(getClassDeclarationSignature(name, c)) - const methods = yield* _(pipe( + Effect.gen(function*() { + const name = yield* getClassName(c) + const doc = yield* getClassDoc(name, c) + const signature = yield* getClassDeclarationSignature(name, c) + const methods = yield* pipe( c.getInstanceMethods(), Effect.validateAll(parseMethod), Effect.map(Array.getSomes) - )) - const staticMethods = yield* _(pipe( + ) + const staticMethods = yield* pipe( c.getStaticMethods(), Effect.validateAll(parseMethod), Effect.map(Array.getSomes) - )) - const properties = yield* _(parseProperties(name, c)) + ) + const properties = yield* parseProperties(name, c) return Domain.createClass( Domain.createNamedDoc( name, @@ -802,29 +788,27 @@ const parseClass = (c: ast.ClassDeclaration) => * @category parsers * @since 1.0.0 */ -export const parseClasses = Effect.gen(function*(_) { - const source = yield* _(Source) +export const parseClasses = Effect.gen(function*() { + const source = yield* Source const exportedClasses = Array.filter( source.sourceFile.getClasses(), (cd) => cd.isExported() && shouldNotIgnore(cd.getJsDocs()) ) - return yield* _( - Effect.validateAll(exportedClasses, parseClass).pipe( - Effect.mapBoth({ - onFailure: Array.flatten, - onSuccess: sortByName - }) - ) + return yield* Effect.validateAll(exportedClasses, parseClass).pipe( + Effect.mapBoth({ + onFailure: Array.flatten, + onSuccess: sortByName + }) ) }) /** * @internal */ -export const parseModuleDocumentation = Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const source = yield* _(Source) - const path = yield* _(Path.Path) +export const parseModuleDocumentation = Effect.gen(function*() { + const config = yield* Configuration.Configuration + const source = yield* Source + const path = yield* Path.Path const name = path.parse(Array.lastNonEmpty(source.path)).name // if any of the settings enforcing documentation are set to `true`, then // a module should have associated documentation @@ -833,10 +817,8 @@ export const parseModuleDocumentation = Effect.gen(function*(_) { const ofirstStatement = Array.head(statements) if (Option.isNone(ofirstStatement)) { if (isDocumentationRequired) { - return yield* _( - Effect.fail( - [`Empty ${chalk.bold(source.path.join("/"))} module`] - ) + return yield* Effect.fail( + [`Empty ${chalk.bold(source.path.join("/"))} module`] ) } } else { @@ -844,16 +826,14 @@ export const parseModuleDocumentation = Effect.gen(function*(_) { const ocommentRange = Array.head(firstStatement.getLeadingCommentRanges()) if (Option.isNone(ocommentRange)) { if (isDocumentationRequired) { - return yield* _(Effect.fail( + return yield* Effect.fail( [`Missing ${chalk.bold("documentation")} in ${chalk.bold(source.path.join("/"))} module`] - )) + ) } } else { const commentRange = ocommentRange.value const text = commentRange.getText() - const doc = yield* _( - getDoc("", text, true).pipe(Effect.mapError(Array.of)) - ) + const doc = yield* getDoc("", text, true).pipe(Effect.mapError(Array.of)) return Domain.createNamedDoc( name, doc.description, @@ -878,16 +858,16 @@ export const parseModuleDocumentation = Effect.gen(function*(_) { * @category parsers * @since 1.0.0 */ -export const parseModule = Effect.gen(function*(_) { - const source = yield* _(Source) - const doc = yield* _(parseModuleDocumentation) - const interfaces = yield* _(parseInterfaces) - const functions = yield* _(parseFunctions) - const typeAliases = yield* _(parseTypeAliases) - const classes = yield* _(parseClasses) - const constants = yield* _(parseConstants) - const exports = yield* _(parseExports) - const namespaces = yield* _(parseNamespaces) +export const parseModule = Effect.gen(function*() { + const source = yield* Source + const doc = yield* parseModuleDocumentation + const interfaces = yield* parseInterfaces + const functions = yield* parseFunctions + const typeAliases = yield* parseTypeAliases + const classes = yield* parseClasses + const constants = yield* parseConstants + const exports = yield* parseExports + const namespaces = yield* parseNamespaces return Domain.createModule( doc, source.path, @@ -925,10 +905,10 @@ export const parseFile = (project: ast.Project) => }) const createProject = (files: ReadonlyArray) => - Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) - const process = yield* _(Process.Process) - const cwd = yield* _(process.cwd) + Effect.gen(function*() { + const config = yield* Configuration.Configuration + const process = yield* Process.Process + const cwd = yield* process.cwd // Convert the raw config into a format that TS/TS-Morph expects const parsed = ast.ts.parseJsonConfigFileContent( { diff --git a/test/Configuration.test.ts b/test/Configuration.test.ts index 5603acc..8de7eab 100644 --- a/test/Configuration.test.ts +++ b/test/Configuration.test.ts @@ -16,7 +16,7 @@ import * as Layer from "effect/Layer" import * as Option from "effect/Option" import { assert, describe, it } from "vitest" -interface DocgenJson extends Record {} +type DocgenJson = Record class DocgenJsonTag extends Context.Tag("DocgenJsonTag")() {} From e2e3a226ca1ba668de560e9d5245c0f5dcf3755c Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 16:53:35 +0100 Subject: [PATCH 02/56] Replace vitest assert with node:assert/strict in test files --- test/Configuration.test.ts | 3 ++- test/Markdown.test.ts | 3 ++- test/Parser.test.ts | 30 ++++++++++++++++++------------ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/test/Configuration.test.ts b/test/Configuration.test.ts index 8de7eab..a01b814 100644 --- a/test/Configuration.test.ts +++ b/test/Configuration.test.ts @@ -14,7 +14,8 @@ import * as Exit from "effect/Exit" import { hole } from "effect/Function" import * as Layer from "effect/Layer" import * as Option from "effect/Option" -import { assert, describe, it } from "vitest" +import * as assert from "node:assert/strict" +import { describe, it } from "vitest" type DocgenJson = Record diff --git a/test/Markdown.test.ts b/test/Markdown.test.ts index f0eb427..c620316 100644 --- a/test/Markdown.test.ts +++ b/test/Markdown.test.ts @@ -3,7 +3,8 @@ import * as Markdown from "@effect/docgen/Markdown" import * as Effect from "effect/Effect" import { flow } from "effect/Function" import * as Option from "effect/Option" -import { assert, describe, it } from "vitest" +import * as assert from "node:assert/strict" +import { describe, it } from "vitest" const testCases = { class: Domain.createClass( diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 5d0fa6a..54af539 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -5,8 +5,9 @@ import * as Parser from "@effect/docgen/Parser" import { Path } from "@effect/platform" import chalk from "chalk" import { Effect, Exit, Option, String } from "effect" +import * as assert from "node:assert/strict" import * as ast from "ts-morph" -import { assert, describe, expect, it } from "vitest" +import { describe, it } from "vitest" let testCounter = 0 @@ -42,14 +43,15 @@ const expectFailure = ( failure: E, config?: Partial ) => { - expect( + assert.deepStrictEqual( eff.pipe( Effect.provideService(Parser.Source, getParser(sourceText)), Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), Effect.provide(Path.layer), Effect.runSyncExit - ) - ).toEqual(Exit.fail(failure)) + ), + Exit.fail(failure) + ) } const expectSuccess = ( @@ -58,15 +60,16 @@ const expectSuccess = ( a: A, config?: Partial ) => { - expect( + assert.deepStrictEqual( eff .pipe( Effect.provideService(Parser.Source, getParser(sourceText)), Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), Effect.provide(Path.layer), Effect.runSyncExit - ) - ).toEqual(Exit.succeed(a)) + ), + Exit.succeed(a) + ) } describe("Parser", () => { @@ -576,7 +579,7 @@ describe("Parser", () => { * @example * \`\`\`ts * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - * + * * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) * \`\`\` * @deprecated @@ -655,7 +658,7 @@ describe("Parser", () => { * @example * ~~~ts * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - * + * * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) * ~~~ * @deprecated @@ -1477,7 +1480,8 @@ describe("Parser", () => { Effect.provideService(Configuration.Configuration, defaultConfig), Effect.runSyncExit ) - expect(actual).toEqual( + assert.deepStrictEqual( + actual, Exit.succeed([ { _tag: "Export", @@ -1515,7 +1519,8 @@ describe("Parser", () => { Effect.runSyncExit ) - expect(actual).toEqual( + assert.deepStrictEqual( + actual, Exit.succeed([ { _tag: "Export", @@ -1553,7 +1558,8 @@ describe("Parser", () => { Effect.runSyncExit ) - expect(actual).toEqual( + assert.deepStrictEqual( + actual, Exit.succeed([ { _tag: "Export", From 772b81aee6a924b1eeb9f4985f594679414cbfd2 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 16:57:05 +0100 Subject: [PATCH 03/56] Simplify generator function syntax in Configuration test --- test/Configuration.test.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/test/Configuration.test.ts b/test/Configuration.test.ts index a01b814..b131aae 100644 --- a/test/Configuration.test.ts +++ b/test/Configuration.test.ts @@ -25,13 +25,11 @@ const makeDocgenJson = (config: Record) => Layer.succeed(Docgen const TestFileSystem = Layer.effect( FileSystem.FileSystem, - Effect.gen(function*(_) { - const path = yield* _(Path.Path) + Effect.gen(function*() { + const path = yield* Path.Path - const docgenJson = yield* _( - Effect.contextWith((context: Context.Context) => - Option.getOrElse(Context.getOption(context, DocgenJsonTag), () => ({} as DocgenJson)) - ) + const docgenJson = yield* Effect.contextWith((context: Context.Context) => + Option.getOrElse(Context.getOption(context, DocgenJsonTag), () => ({} as DocgenJson)) ) const readFileString: FileSystem.FileSystem["readFileString"] = (filePath) => { @@ -105,8 +103,8 @@ const testCliFor = (program: Effect.Effect { it("should use the default configuration if no configuration is provided", () => { - const program = Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) + const program = Effect.gen(function*() { + const config = yield* Configuration.Configuration assert.deepStrictEqual(config, { projectName: "name", projectHomepage: "homepage", @@ -140,8 +138,8 @@ describe("Configuration", () => { target: "ES2022", lib: ["ES2022", "DOM"] } - const program = Effect.gen(function*(_) { - const config = yield* _(Configuration.Configuration) + const program = Effect.gen(function*() { + const config = yield* Configuration.Configuration assert.deepStrictEqual(config, { projectName: "name", projectHomepage: "myproject", From 2a9445747d5c242cff7ead36712c870d93c8b1ee Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 18:08:53 +0100 Subject: [PATCH 04/56] Remove fences from Example type and update related parsing and generation logic --- docs/modules/Domain.ts.md | 4 ---- docs/modules/Markdown.ts.md | 10 ++++++++++ docs/modules/Parser.ts.md | 36 +++++++++++++++++++++++++++++------ src/Core.ts | 37 +++++++++++++++++++++++++----------- src/Domain.ts | 4 ---- src/Markdown.ts | 18 ++++++++++++++---- src/Parser.ts | 15 +-------------- test/Markdown.test.ts | 12 ++++++++++-- test/Parser.test.ts | 38 +++++++++++++++++++------------------ 9 files changed, 111 insertions(+), 63 deletions(-) diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 3545ecf..fa2f760 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -254,10 +254,6 @@ Added in v1.0.0 ```ts export type Example = { body: string - fences?: { - start: string - end: string - } } ``` diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index 718dff4..fbfcd50 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -21,6 +21,8 @@ Added in v1.0.0 ## printModule +Description... + **Signature** ```ts @@ -29,6 +31,8 @@ export declare const printModule: (module: Domain.Module, order: number) => Effe **Example** +**Example** (Title 1) + ```ts import * as Markdown from "@effect/docgen/Markdown" import * as Domain from "@effect/docgen/Domain" @@ -39,4 +43,10 @@ const m = Domain.createModule(doc, ["src", "tests.ts"], [], [], [], [], [], [], console.log(Markdown.printModule(m, 0)) ``` +**Example** (Title 2) + +```js +const x = 1 +``` + Added in v1.0.0 diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 86b11ae..67de6d4 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -42,7 +42,11 @@ Added in v1.0.0 **Signature** ```ts -export declare const parseConstants: Effect.Effect +export declare const parseConstants: Effect.Effect< + Domain.Constant[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` Added in v1.0.0 @@ -52,7 +56,11 @@ Added in v1.0.0 **Signature** ```ts -export declare const parseExports: Effect.Effect +export declare const parseExports: Effect.Effect< + Domain.Export[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` Added in v1.0.0 @@ -64,7 +72,11 @@ Added in v1.0.0 ```ts export declare const parseFiles: ( files: ReadonlyArray -) => Effect.Effect +) => Effect.Effect< + Domain.Module[], + [string[], ...string[][]], + Process.Process | Configuration.Configuration | Path.Path +> ``` Added in v1.0.0 @@ -74,7 +86,11 @@ Added in v1.0.0 **Signature** ```ts -export declare const parseFunctions: Effect.Effect +export declare const parseFunctions: Effect.Effect< + Domain.Function[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` Added in v1.0.0 @@ -84,7 +100,11 @@ Added in v1.0.0 **Signature** ```ts -export declare const parseInterfaces: Effect.Effect +export declare const parseInterfaces: Effect.Effect< + Domain.Interface[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` Added in v1.0.0 @@ -118,7 +138,11 @@ Added in v1.0.0 **Signature** ```ts -export declare const parseTypeAliases: Effect.Effect +export declare const parseTypeAliases: Effect.Effect< + Domain.TypeAlias[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` Added in v1.0.0 diff --git a/src/Core.ts b/src/Core.ts index f5f3950..df1440d 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -155,6 +155,17 @@ const extractPrefixedNestedNamespaces = ( return Array.prepend(namespaces, [prefix, doc]) } +/** + * Extracts all fenced code blocks from markdown content. + * Handles both ``` and ~~~ fences. + */ +const extractFencedCode = (content: string): Array => { + const fenceRegex = /(?:```|~~~)(\w*)\n([\s\S]*?)(?:```|~~~)/g + const matches = Array.fromIterable(content.matchAll(fenceRegex)) + + return Array.map(matches, (match: RegExpMatchArray) => match[2].trim()) +} + /** * Generates example files for the given modules. */ @@ -166,18 +177,22 @@ const getExampleFiles = (modules: ReadonlyArray) => const prefix = module.path.join("-") const getFiles = (exampleId: string) => (doc: Domain.NamedDoc): ReadonlyArray => - Array.map( + Array.flatMap( doc.examples, - (content, i) => - File.createFile( - path.join( - config.outDir, - "examples", - `${prefix}-${exampleId}-${doc.name}-${i}.ts` - ), - `${content.body}\n`, - true // make the file overwritable - ) + (content, i) => { + const examples = extractFencedCode(content.body) + return examples.map((example, j) => { + return File.createFile( + path.join( + config.outDir, + "examples", + `${prefix}-${exampleId}-${doc.name}-${i}-${j}.ts` + ), + example, + true // make the file overwritable + ) + }) + } ) const allPrefixedNamespaces = Array.flatMap(module.namespaces, (namespace) => diff --git a/src/Domain.ts b/src/Domain.ts index 9c93e93..918500e 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -27,10 +27,6 @@ export interface Module extends NamedDoc { */ export type Example = { body: string - fences?: { - start: string - end: string - } } /** diff --git a/src/Markdown.ts b/src/Markdown.ts index e5313fc..a06aef7 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -61,11 +61,9 @@ const printSignatures = (ss: ReadonlyArray): string => const printExamples = (es: ReadonlyArray): string => es - .map(({ body, fences }) => + .map(({ body }) => MarkdownPrinter.paragraph(MarkdownPrinter.bold("Example")) + - MarkdownPrinter.paragraph( - MarkdownPrinter.fence(fences?.start ?? "```ts", body, fences?.end ?? "```") - ) + MarkdownPrinter.paragraph(body) ) .join("\n\n") @@ -264,7 +262,12 @@ const byCategory = Order.mapInput( ) /** + * Description... + * * @example + * **Example** (Title 1) + * + * ```ts * import * as Markdown from "@effect/docgen/Markdown" * import * as Domain from "@effect/docgen/Domain" * import { Option } from "effect" @@ -272,6 +275,13 @@ const byCategory = Order.mapInput( * const doc = Domain.createNamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) * const m = Domain.createModule(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) * console.log(Markdown.printModule(m, 0)) + * ``` + * + * **Example** (Title 2) + * + * ~~~js + * const x = 1 + * ~~~ * * @category printers * @since 1.0.0 diff --git a/src/Parser.ts b/src/Parser.ts index 61bb55b..eed5151 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -152,21 +152,8 @@ const getDescription = (name: string, comment: Comment) => return comment.description }) -const fencedExampleRegex = /^(?(```|~~~)[^\n]*)\n(?[\S\s]*)(?\n(```|~~~))$/ const parseExample = (body: string) => { - const example = fencedExampleRegex.exec(body) - - if (example === null) { - return { body } - } - - return { - body: example?.groups?.body ?? "", - fences: { - start: example?.groups?.fenceStart?.trim() ?? "```ts", - end: example?.groups?.fenceEnd?.trim() ?? "```" - } - } + return { body } } const getExamplesTag = (name: string, comment: Comment, isModule: boolean) => diff --git a/test/Markdown.test.ts b/test/Markdown.test.ts index c620316..d062cd7 100644 --- a/test/Markdown.test.ts +++ b/test/Markdown.test.ts @@ -13,7 +13,11 @@ const testCases = { Option.some("a class"), Option.some("1.0.0"), false, - [{ body: "example 1", fences: { start: "```ts", end: "```" } }], + [{ + body: `\`\`\`ts +example 1 +\`\`\`` + }], Option.some("category") ), "declare class A { constructor() }", @@ -85,7 +89,11 @@ const testCases = { Option.some("a function"), Option.some("1.0.0"), true, - [{ body: "example 1", fences: { start: "```ts", end: "```" } }], + [{ + body: `\`\`\`ts +example 1 +\`\`\`` + }], Option.none() ), ["declare const func: (test: string) => string"] diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 54af539..153854e 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -560,8 +560,9 @@ describe("Parser", () => { since: Option.some("1.0.0"), examples: [ { - body: "assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 })", - fences: { start: "```ts", end: "```" } + body: `\`\`\`ts +assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) +\`\`\`` }, { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } ], @@ -598,12 +599,11 @@ describe("Parser", () => { since: Option.some("1.0.0"), examples: [ { - body: String.stripMargin( - `|assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) + body: `\`\`\`ts +assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - |assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })` - ), - fences: { start: "```ts", end: "```" } +assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) +\`\`\`` } ], category: Option.none() @@ -639,8 +639,9 @@ describe("Parser", () => { since: Option.some("1.0.0"), examples: [ { - body: "assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 })", - fences: { start: "~~~ts", end: "~~~" } + body: `~~~ts +assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) +~~~` }, { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } ], @@ -677,12 +678,11 @@ describe("Parser", () => { since: Option.some("1.0.0"), examples: [ { - body: String.stripMargin( - `|assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) + body: `~~~ts +assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - |assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })` - ), - fences: { start: "~~~ts", end: "~~~" } +assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) +~~~` } ], category: Option.none() @@ -718,8 +718,9 @@ describe("Parser", () => { since: Option.some("1.0.0"), examples: [ { - body: "assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 })", - fences: { start: "```ts twoslash", end: "```" } + body: `\`\`\`ts twoslash +assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) +\`\`\`` }, { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } ], @@ -756,8 +757,9 @@ describe("Parser", () => { since: Option.some("1.0.0"), examples: [ { - body: "assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 })", - fences: { start: "~~~ts twoslash", end: "~~~" } + body: `~~~ts twoslash +assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) +~~~` }, { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } ], From 92393abd4f20521241dc684f7c5ffa32fbaeae75 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 18:14:28 +0100 Subject: [PATCH 05/56] Support enhanced code block parsing with metadata and titles --- docs/modules/Markdown.ts.md | 4 ++-- src/Core.ts | 4 ++-- src/Markdown.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index fbfcd50..9ba5287 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -33,7 +33,7 @@ export declare const printModule: (module: Domain.Module, order: number) => Effe **Example** (Title 1) -```ts +```ts twoslash title="Title 1" import * as Markdown from "@effect/docgen/Markdown" import * as Domain from "@effect/docgen/Domain" import { Option } from "effect" @@ -45,7 +45,7 @@ console.log(Markdown.printModule(m, 0)) **Example** (Title 2) -```js +```js twoslash title="Title 2" const x = 1 ``` diff --git a/src/Core.ts b/src/Core.ts index df1440d..9fb6057 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -157,10 +157,10 @@ const extractPrefixedNestedNamespaces = ( /** * Extracts all fenced code blocks from markdown content. - * Handles both ``` and ~~~ fences. + * Handles both ``` and ~~~ fences, including any metadata like language, title, and other attributes. */ const extractFencedCode = (content: string): Array => { - const fenceRegex = /(?:```|~~~)(\w*)\n([\s\S]*?)(?:```|~~~)/g + const fenceRegex = /(?:```|~~~)(.*?)\n([\s\S]*?)(?:```|~~~)/g const matches = Array.fromIterable(content.matchAll(fenceRegex)) return Array.map(matches, (match: RegExpMatchArray) => match[2].trim()) diff --git a/src/Markdown.ts b/src/Markdown.ts index a06aef7..435ab49 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -267,7 +267,7 @@ const byCategory = Order.mapInput( * @example * **Example** (Title 1) * - * ```ts + * ```ts twoslash title="Title 1" * import * as Markdown from "@effect/docgen/Markdown" * import * as Domain from "@effect/docgen/Domain" * import { Option } from "effect" @@ -279,7 +279,7 @@ const byCategory = Order.mapInput( * * **Example** (Title 2) * - * ~~~js + * ~~~js twoslash title="Title 2" * const x = 1 * ~~~ * From b41ac331a785c42e0f64ad98493a55166ca7c2dc Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 18:19:46 +0100 Subject: [PATCH 06/56] Remove unnecessary assert import handling in Core module --- src/Core.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Core.ts b/src/Core.ts index 9fb6057..4e23dca 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -260,14 +260,6 @@ const getExampleFiles = (modules: ReadonlyArray) => }) }) -/** - * Adds an import statement for the `assert` module to the beginning of the given code, if it doesn't already exist. - */ -const addAssertImport = (code: string): string => - code.indexOf("assert.") !== -1 - ? `import * as assert from 'assert'\n${code}` - : code - /** * Replaces the project name in the given source code imports with the configured project name. */ @@ -292,8 +284,7 @@ const handleImports = (files: ReadonlyArray) => Effect.forEach(files, (file) => Effect.gen(function*() { const source = yield* replaceProjectName(file.content) - const content = addAssertImport(source) - return File.createFile(file.path, content, file.isOverwriteable) + return File.createFile(file.path, source, file.isOverwriteable) })) /** From 1406b4c97e69e50bbdfe08254a5bde3e47d865f9 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 18:21:03 +0100 Subject: [PATCH 07/56] Change "Added in" to "Since" in Markdown generation --- src/Markdown.ts | 2 +- test/Markdown.test.ts | 56 +++++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/Markdown.ts b/src/Markdown.ts index 435ab49..a77afba 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -35,7 +35,7 @@ const MarkdownPrinter = { const printSince: (v: Option.Option) => string = Option.match({ onNone: () => "", - onSome: (v) => MarkdownPrinter.paragraph(`Added in v${v}`) + onSome: (v) => MarkdownPrinter.paragraph(`Since v${v}`) }) const printTitle = (s: string, deprecated: boolean, type?: string): string => { diff --git a/test/Markdown.test.ts b/test/Markdown.test.ts index d062cd7..537107a 100644 --- a/test/Markdown.test.ts +++ b/test/Markdown.test.ts @@ -180,7 +180,7 @@ describe("Markdown", () => { await Effect.runPromise(print(testCases.namespace, 0)), `## A (namespace) -Added in v1.0.0 +Since v1.0.0 ### B (type alias) @@ -190,11 +190,11 @@ Added in v1.0.0 export type B = string \`\`\` -Added in v1.0.1 +Since v1.0.1 ### C (namespace) -Added in v1.0.2 +Since v1.0.2 #### D (type alias) @@ -204,7 +204,7 @@ Added in v1.0.2 export type D = number \`\`\` -Added in v1.0.3 +Since v1.0.3 ` ) }) @@ -231,7 +231,7 @@ declare class A { example 1 \`\`\` -Added in v1.0.0 +Since v1.0.0 ### staticTest (static method) @@ -241,7 +241,7 @@ Added in v1.0.0 static testStatic(): string; \`\`\` -Added in v1.0.0 +Since v1.0.0 ### hasOwnProperty (function) (method) @@ -251,7 +251,7 @@ Added in v1.0.0 hasOwnProperty(): boolean \`\`\` -Added in v1.0.0 +Since v1.0.0 ### foo (property) @@ -261,7 +261,7 @@ Added in v1.0.0 foo: string \`\`\` -Added in v1.0.0 +Since v1.0.0 ` ) }) @@ -280,7 +280,7 @@ the test declare const test: string \`\`\` -Added in v1.0.0 +Since v1.0.0 ` ) }) @@ -297,7 +297,7 @@ Added in v1.0.0 export declare const test: typeof test \`\`\` -Added in v1.0.0 +Since v1.0.0 ` ) }) @@ -322,7 +322,7 @@ declare const func: (test: string) => string example 1 \`\`\` -Added in v1.0.0 +Since v1.0.0 ` ) }) @@ -339,7 +339,7 @@ Added in v1.0.0 export interface A extends Record {} \`\`\` -Added in v1.0.0 +Since v1.0.0 ` ) }) @@ -356,7 +356,7 @@ Added in v1.0.0 export type A = number \`\`\` -Added in v1.0.0 +Since v1.0.0 ` ) @@ -405,7 +405,7 @@ parent: Modules ## tests overview -Added in v1.0.0 +Since v1.0.0 --- @@ -450,7 +450,7 @@ declare class A { example 1 \`\`\` -Added in v1.0.0 +Since v1.0.0 ### staticTest (static method) @@ -460,7 +460,7 @@ Added in v1.0.0 static testStatic(): string; \`\`\` -Added in v1.0.0 +Since v1.0.0 ### hasOwnProperty (function) (method) @@ -470,7 +470,7 @@ Added in v1.0.0 hasOwnProperty(): boolean \`\`\` -Added in v1.0.0 +Since v1.0.0 ### foo (property) @@ -480,7 +480,7 @@ Added in v1.0.0 foo: string \`\`\` -Added in v1.0.0 +Since v1.0.0 # constants @@ -494,7 +494,7 @@ the test declare const test: string \`\`\` -Added in v1.0.0 +Since v1.0.0 # utils @@ -506,7 +506,7 @@ Added in v1.0.0 export interface A extends Record {} \`\`\` -Added in v1.0.0 +Since v1.0.0 ## A (type alias) @@ -516,11 +516,11 @@ Added in v1.0.0 export type A = number \`\`\` -Added in v1.0.0 +Since v1.0.0 ## A (namespace) -Added in v1.0.0 +Since v1.0.0 ### B (type alias) @@ -530,11 +530,11 @@ Added in v1.0.0 export type B = string \`\`\` -Added in v1.0.1 +Since v1.0.1 ### C (namespace) -Added in v1.0.2 +Since v1.0.2 #### D (type alias) @@ -544,7 +544,7 @@ Added in v1.0.2 export type D = number \`\`\` -Added in v1.0.3 +Since v1.0.3 ## ~~func~~ @@ -562,7 +562,7 @@ declare const func: (test: string) => string example 1 \`\`\` -Added in v1.0.0 +Since v1.0.0 ## test @@ -572,7 +572,7 @@ Added in v1.0.0 export declare const test: typeof test \`\`\` -Added in v1.0.0 +Since v1.0.0 ` ) @@ -588,7 +588,7 @@ parent: Modules ## tests overview -Added in v1.0.0 +Since v1.0.0 --- From 67bdc07fe71c1f375699109ed2547a5641a171aa Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 18:27:31 +0100 Subject: [PATCH 08/56] Reorder signature and example sections in Markdown generation --- docs/modules/CLI.ts.md | 2 +- docs/modules/Configuration.ts.md | 8 ++--- docs/modules/Core.ts.md | 2 +- docs/modules/Domain.ts.md | 54 ++++++++++++++++---------------- docs/modules/Error.ts.md | 8 ++--- docs/modules/File.ts.md | 6 ++-- docs/modules/Markdown.ts.md | 16 +++++----- docs/modules/Parser.ts.md | 20 ++++++------ docs/modules/Process.ts.md | 8 ++--- src/Markdown.ts | 18 +++++------ test/Markdown.test.ts | 40 +++++++++++------------ 11 files changed, 91 insertions(+), 91 deletions(-) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index cd1a397..098ab3e 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -6,7 +6,7 @@ parent: Modules ## CLI overview -Added in v1.0.0 +Since v1.0.0 --- diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index c1773c1..63da8ff 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Configuration overview -Added in v1.0.0 +Since v1.0.0 --- @@ -29,7 +29,7 @@ Added in v1.0.0 export declare class Configuration ``` -Added in v1.0.0 +Since v1.0.0 ## ConfigurationSchema @@ -56,7 +56,7 @@ export declare const ConfigurationSchema: Schema.Struct<{ }> ``` -Added in v1.0.0 +Since v1.0.0 ## ConfigurationShape (interface) @@ -80,4 +80,4 @@ export interface ConfigurationShape { } ``` -Added in v1.0.0 +Since v1.0.0 diff --git a/docs/modules/Core.ts.md b/docs/modules/Core.ts.md index d510cf6..2073d9e 100644 --- a/docs/modules/Core.ts.md +++ b/docs/modules/Core.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Core overview -Added in v1.0.0 +Since v1.0.0 --- diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index fa2f760..bd05a33 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Domain overview -Added in v1.0.0 +Since v1.0.0 --- @@ -60,7 +60,7 @@ export declare const createClass: ( ) => Class ``` -Added in v1.0.0 +Since v1.0.0 ## createConstant @@ -70,7 +70,7 @@ Added in v1.0.0 export declare const createConstant: (doc: NamedDoc, signature: string) => Constant ``` -Added in v1.0.0 +Since v1.0.0 ## createDoc @@ -86,7 +86,7 @@ export declare const createDoc: ( ) => Doc ``` -Added in v1.0.0 +Since v1.0.0 ## createExport @@ -96,7 +96,7 @@ Added in v1.0.0 export declare const createExport: (doc: NamedDoc, signature: string) => Export ``` -Added in v1.0.0 +Since v1.0.0 ## createFunction @@ -106,7 +106,7 @@ Added in v1.0.0 export declare const createFunction: (doc: NamedDoc, signatures: ReadonlyArray) => Function ``` -Added in v1.0.0 +Since v1.0.0 ## createInterface @@ -116,7 +116,7 @@ Added in v1.0.0 export declare const createInterface: (doc: NamedDoc, signature: string) => Interface ``` -Added in v1.0.0 +Since v1.0.0 ## createMethod @@ -126,7 +126,7 @@ Added in v1.0.0 export declare const createMethod: (doc: NamedDoc, signatures: ReadonlyArray) => Method ``` -Added in v1.0.0 +Since v1.0.0 ## createModule @@ -146,7 +146,7 @@ export declare const createModule: ( ) => Module ``` -Added in v1.0.0 +Since v1.0.0 ## createNamedDoc @@ -163,7 +163,7 @@ export declare const createNamedDoc: ( ) => NamedDoc ``` -Added in v1.0.0 +Since v1.0.0 ## createNamespace @@ -178,7 +178,7 @@ export declare const createNamespace: ( ) => Namespace ``` -Added in v1.0.0 +Since v1.0.0 ## createProperty @@ -188,7 +188,7 @@ Added in v1.0.0 export declare const createProperty: (doc: NamedDoc, signature: string) => Property ``` -Added in v1.0.0 +Since v1.0.0 ## createTypeAlias @@ -198,7 +198,7 @@ Added in v1.0.0 export declare const createTypeAlias: (doc: NamedDoc, signature: string) => TypeAlias ``` -Added in v1.0.0 +Since v1.0.0 # model @@ -216,7 +216,7 @@ export interface Class extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 ## Constant (interface) @@ -229,7 +229,7 @@ export interface Constant extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 ## Doc (interface) @@ -245,7 +245,7 @@ export interface Doc { } ``` -Added in v1.0.0 +Since v1.0.0 ## Example (type alias) @@ -257,7 +257,7 @@ export type Example = { } ``` -Added in v1.0.0 +Since v1.0.0 ## Export (interface) @@ -280,7 +280,7 @@ export interface Export extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 ## Function (interface) @@ -293,7 +293,7 @@ export interface Function extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 ## Interface (interface) @@ -306,7 +306,7 @@ export interface Interface extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 ## Method (interface) @@ -318,7 +318,7 @@ export interface Method extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 ## Module (interface) @@ -337,7 +337,7 @@ export interface Module extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 ## NamedDoc (interface) @@ -349,7 +349,7 @@ export interface NamedDoc extends Doc { } ``` -Added in v1.0.0 +Since v1.0.0 ## Namespace (interface) @@ -364,7 +364,7 @@ export interface Namespace extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 ## Property (interface) @@ -376,7 +376,7 @@ export interface Property extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 ## TypeAlias (interface) @@ -389,7 +389,7 @@ export interface TypeAlias extends NamedDoc { } ``` -Added in v1.0.0 +Since v1.0.0 # sorting @@ -404,4 +404,4 @@ The file path is converted to lowercase before comparison. export declare const ByPath: Order.Order ``` -Added in v1.0.0 +Since v1.0.0 diff --git a/docs/modules/Error.ts.md b/docs/modules/Error.ts.md index 62d3f98..de42eaf 100644 --- a/docs/modules/Error.ts.md +++ b/docs/modules/Error.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Error overview -Added in v1.0.0 +Since v1.0.0 --- @@ -30,7 +30,7 @@ Added in v1.0.0 export declare class DocgenError ``` -Added in v1.0.0 +Since v1.0.0 # symbol @@ -42,7 +42,7 @@ Added in v1.0.0 export declare const DocgenErrorTypeId: typeof DocgenErrorTypeId ``` -Added in v1.0.0 +Since v1.0.0 ## DocgenErrorTypeId (type alias) @@ -52,4 +52,4 @@ Added in v1.0.0 export type DocgenErrorTypeId = typeof DocgenErrorTypeId ``` -Added in v1.0.0 +Since v1.0.0 diff --git a/docs/modules/File.ts.md b/docs/modules/File.ts.md index b9ec707..eca2eb3 100644 --- a/docs/modules/File.ts.md +++ b/docs/modules/File.ts.md @@ -6,7 +6,7 @@ parent: Modules ## File overview -Added in v1.0.0 +Since v1.0.0 --- @@ -31,7 +31,7 @@ By default files are readonly (`isOverwriteable = false`). export declare const createFile: (path: string, content: string, isOverwriteable?: boolean) => File ``` -Added in v1.0.0 +Since v1.0.0 # model @@ -49,4 +49,4 @@ export interface File { } ``` -Added in v1.0.0 +Since v1.0.0 diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index 9ba5287..21a5cce 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Markdown overview -Added in v1.0.0 +Since v1.0.0 --- @@ -23,12 +23,6 @@ Added in v1.0.0 Description... -**Signature** - -```ts -export declare const printModule: (module: Domain.Module, order: number) => Effect.Effect -``` - **Example** **Example** (Title 1) @@ -49,4 +43,10 @@ console.log(Markdown.printModule(m, 0)) const x = 1 ``` -Added in v1.0.0 +**Signature** + +```ts +export declare const printModule: (module: Domain.Module, order: number) => Effect.Effect +``` + +Since v1.0.0 diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 67de6d4..ca38cd7 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Parser overview -Added in v1.0.0 +Since v1.0.0 --- @@ -35,7 +35,7 @@ Added in v1.0.0 export declare const parseClasses: Effect.Effect ``` -Added in v1.0.0 +Since v1.0.0 ## parseConstants @@ -49,7 +49,7 @@ export declare const parseConstants: Effect.Effect< > ``` -Added in v1.0.0 +Since v1.0.0 ## parseExports @@ -63,7 +63,7 @@ export declare const parseExports: Effect.Effect< > ``` -Added in v1.0.0 +Since v1.0.0 ## parseFiles @@ -79,7 +79,7 @@ export declare const parseFiles: ( > ``` -Added in v1.0.0 +Since v1.0.0 ## parseFunctions @@ -93,7 +93,7 @@ export declare const parseFunctions: Effect.Effect< > ``` -Added in v1.0.0 +Since v1.0.0 ## parseInterfaces @@ -107,7 +107,7 @@ export declare const parseInterfaces: Effect.Effect< > ``` -Added in v1.0.0 +Since v1.0.0 ## parseModule @@ -121,7 +121,7 @@ export declare const parseModule: Effect.Effect< > ``` -Added in v1.0.0 +Since v1.0.0 ## parseNamespaces @@ -131,7 +131,7 @@ Added in v1.0.0 export declare const parseNamespaces: Effect.Effect ``` -Added in v1.0.0 +Since v1.0.0 ## parseTypeAliases @@ -145,4 +145,4 @@ export declare const parseTypeAliases: Effect.Effect< > ``` -Added in v1.0.0 +Since v1.0.0 diff --git a/docs/modules/Process.ts.md b/docs/modules/Process.ts.md index 99b22b9..e00908a 100644 --- a/docs/modules/Process.ts.md +++ b/docs/modules/Process.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Process overview -Added in v1.0.0 +Since v1.0.0 --- @@ -30,7 +30,7 @@ Added in v1.0.0 export declare const layer: Layer.Layer ``` -Added in v1.0.0 +Since v1.0.0 # service @@ -42,7 +42,7 @@ Added in v1.0.0 export declare class Process ``` -Added in v1.0.0 +Since v1.0.0 ## ProcessShape (interface) @@ -58,4 +58,4 @@ export interface ProcessShape { } ``` -Added in v1.0.0 +Since v1.0.0 diff --git a/src/Markdown.ts b/src/Markdown.ts index a77afba..536e484 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -71,8 +71,8 @@ const printStaticMethod = (m: Domain.Method): string => MarkdownPrinter.paragraph( MarkdownPrinter.h3(printTitle(m.name, m.deprecated, "(static method)")), printDescription(m.description), - printSignatures(m.signatures), printExamples(m.examples), + printSignatures(m.signatures), printSince(m.since) ) @@ -80,8 +80,8 @@ const printMethod = (m: Domain.Method): string => MarkdownPrinter.paragraph( MarkdownPrinter.h3(printTitle(m.name, m.deprecated, "(method)")), printDescription(m.description), - printSignatures(m.signatures), printExamples(m.examples), + printSignatures(m.signatures), printSince(m.since) ) @@ -89,8 +89,8 @@ const printProperty = (p: Domain.Property): string => MarkdownPrinter.paragraph( MarkdownPrinter.h3(printTitle(p.name, p.deprecated, "(property)")), printDescription(p.description), - printSignature(p.signature), printExamples(p.examples), + printSignature(p.signature), printSince(p.since) ) @@ -133,8 +133,8 @@ export const printClass = (model: Domain.Class): string => MarkdownPrinter.paragraph( MarkdownPrinter.h2(printTitle(model.name, model.deprecated, "(class)")), printDescription(model.description), - printSignature(model.signature), printExamples(model.examples), + printSignature(model.signature), printSince(model.since) ), printStaticMethods(model.staticMethods), @@ -147,8 +147,8 @@ export const printConstant = (model: Domain.Constant): string => MarkdownPrinter.paragraph( MarkdownPrinter.h2(printTitle(model.name, model.deprecated)), printDescription(model.description), - printSignature(model.signature), printExamples(model.examples), + printSignature(model.signature), printSince(model.since) ) @@ -157,8 +157,8 @@ export const printExport = (model: Domain.Export): string => MarkdownPrinter.paragraph( MarkdownPrinter.h2(printTitle(model.name, model.deprecated)), printDescription(model.description), - printSignature(model.signature), printExamples(model.examples), + printSignature(model.signature), printSince(model.since) ) @@ -167,8 +167,8 @@ export const printFunction = (model: Domain.Function): string => MarkdownPrinter.paragraph( MarkdownPrinter.h2(printTitle(model.name, model.deprecated)), printDescription(model.description), - printSignatures(model.signatures), printExamples(model.examples), + printSignatures(model.signatures), printSince(model.since) ) @@ -177,8 +177,8 @@ export const printInterface = (model: Domain.Interface, indentation: number): st MarkdownPrinter.paragraph( getHeaderByIndentation(indentation)(printTitle(model.name, model.deprecated, "(interface)")), printDescription(model.description), - printSignature(model.signature), printExamples(model.examples), + printSignature(model.signature), printSince(model.since) ) @@ -187,8 +187,8 @@ export const printTypeAlias = (model: Domain.TypeAlias, indentation: number): st MarkdownPrinter.paragraph( getHeaderByIndentation(indentation)(printTitle(model.name, model.deprecated, "(type alias)")), printDescription(model.description), - printSignature(model.signature), printExamples(model.examples), + printSignature(model.signature), printSince(model.since) ) diff --git a/test/Markdown.test.ts b/test/Markdown.test.ts index 537107a..76e56c6 100644 --- a/test/Markdown.test.ts +++ b/test/Markdown.test.ts @@ -217,18 +217,18 @@ Since v1.0.3 a class -**Signature** +**Example** \`\`\`ts -declare class A { - constructor() -} +example 1 \`\`\` -**Example** +**Signature** \`\`\`ts -example 1 +declare class A { + constructor() +} \`\`\` Since v1.0.0 @@ -310,16 +310,16 @@ Since v1.0.0 a function -**Signature** +**Example** \`\`\`ts -declare const func: (test: string) => string +example 1 \`\`\` -**Example** +**Signature** \`\`\`ts -example 1 +declare const func: (test: string) => string \`\`\` Since v1.0.0 @@ -436,18 +436,18 @@ Since v1.0.0 a class -**Signature** +**Example** \`\`\`ts -declare class A { - constructor() -} +example 1 \`\`\` -**Example** +**Signature** \`\`\`ts -example 1 +declare class A { + constructor() +} \`\`\` Since v1.0.0 @@ -550,16 +550,16 @@ Since v1.0.3 a function -**Signature** +**Example** \`\`\`ts -declare const func: (test: string) => string +example 1 \`\`\` -**Example** +**Signature** \`\`\`ts -example 1 +declare const func: (test: string) => string \`\`\` Since v1.0.0 From 7a65f053db5628f7c4b7830c636d450f8bbb7124 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 18:30:41 +0100 Subject: [PATCH 09/56] Remove redundant "Example" header in Markdown generation --- docs/modules/Markdown.ts.md | 2 -- src/Markdown.ts | 5 +---- test/Markdown.test.ts | 8 -------- 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index 21a5cce..7ac6b11 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -23,8 +23,6 @@ Since v1.0.0 Description... -**Example** - **Example** (Title 1) ```ts twoslash title="Title 1" diff --git a/src/Markdown.ts b/src/Markdown.ts index 536e484..e35b1e4 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -61,10 +61,7 @@ const printSignatures = (ss: ReadonlyArray): string => const printExamples = (es: ReadonlyArray): string => es - .map(({ body }) => - MarkdownPrinter.paragraph(MarkdownPrinter.bold("Example")) + - MarkdownPrinter.paragraph(body) - ) + .map(({ body }) => MarkdownPrinter.paragraph(body)) .join("\n\n") const printStaticMethod = (m: Domain.Method): string => diff --git a/test/Markdown.test.ts b/test/Markdown.test.ts index 76e56c6..d5ecc3d 100644 --- a/test/Markdown.test.ts +++ b/test/Markdown.test.ts @@ -217,8 +217,6 @@ Since v1.0.3 a class -**Example** - \`\`\`ts example 1 \`\`\` @@ -310,8 +308,6 @@ Since v1.0.0 a function -**Example** - \`\`\`ts example 1 \`\`\` @@ -436,8 +432,6 @@ Since v1.0.0 a class -**Example** - \`\`\`ts example 1 \`\`\` @@ -550,8 +544,6 @@ Since v1.0.3 a function -**Example** - \`\`\`ts example 1 \`\`\` From a17fdc098dfa8785fd4c0f3f1d405afbd2b67c29 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 18:35:07 +0100 Subject: [PATCH 10/56] add changeset --- .changeset/silly-insects-draw.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/silly-insects-draw.md diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md new file mode 100644 index 0000000..38a0d50 --- /dev/null +++ b/.changeset/silly-insects-draw.md @@ -0,0 +1,9 @@ +--- +"@effect/docgen": minor +--- + +- Remove fences from Example type and update related parsing and generation logic +- Remove unnecessary assert import handling in Core module +- Change "Added in" to "Since" in Markdown generation +- Reorder signature and example sections in Markdown generation +- Remove redundant "Example" header in Markdown generation From 86bd4ffed78262de6040472831dc4ebc33e3137d Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 18:44:06 +0100 Subject: [PATCH 11/56] Update Node.js version and GitHub Pages deployment action --- .github/actions/setup/action.yml | 2 +- .github/workflows/pages.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 50cd2ca..f48207a 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -4,7 +4,7 @@ inputs: node-version: description: The version of Node.js to install required: true - default: 20.16.0 + default: 23.7.0 runs: using: composite diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 3f83377..810f869 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -48,4 +48,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v2 + uses: actions/deploy-pages@v4 From a7ccb172a0dc25760ab57f1ce8b2f5952e34b9a5 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 18:46:40 +0100 Subject: [PATCH 12/56] Upgrade GitHub Pages artifact upload action to v3 --- .github/workflows/pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 810f869..7ee51ed 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -31,7 +31,7 @@ jobs: destination: ./_site - name: Upload pages artifact if: github.repository_owner == 'Effect-Ts' && github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/upload-pages-artifact@v2 + uses: actions/upload-pages-artifact@v3 deploy: if: github.repository_owner == 'Effect-Ts' && github.event_name == 'push' && github.ref == 'refs/heads/main' From cef8400dece645a73b4d74fd81c19cefbaa49af9 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 2 Mar 2025 19:03:46 +0100 Subject: [PATCH 13/56] add snapshot --- .github/workflows/snapshot.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/snapshot.yml diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 0000000..ef63606 --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,23 @@ +name: Snapshot +on: + pull_request: + branches: [main] + workflow_dispatch: + +permissions: {} + +jobs: + snapshot: + name: Snapshot + if: github.repository_owner == 'Effect-Ts' + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - name: Install dependencies + uses: ./.github/actions/setup + - name: Build package + run: pnpm build + - name: Create snapshot + id: snapshot + run: pnpx pkg-pr-new@0.0.28 publish --pnpm --comment=off From a32e68e08b20eb8727fa19c981b4739bce0f4e3b Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 09:21:42 +0100 Subject: [PATCH 14/56] remove Core.replaceProjectName --- docgen.json | 17 +++-- docs/modules/Markdown.ts.md | 11 ++-- docs/modules/Parser.ts.md | 2 +- docs/modules/Process.ts.md | 2 +- docs/modules/index.ts.md | 123 ++++++++++++++++++++++++++++++++++++ src/Core.ts | 32 +--------- src/Markdown.ts | 9 ++- src/index.ts | 43 +++++++++++++ 8 files changed, 196 insertions(+), 43 deletions(-) create mode 100644 docs/modules/index.ts.md create mode 100644 src/index.ts diff --git a/docgen.json b/docgen.json index 1aa61a3..559df04 100644 --- a/docgen.json +++ b/docgen.json @@ -8,9 +8,18 @@ "exactOptionalPropertyTypes": true, "moduleResolution": "Bundler", "target": "ES2022", - "lib": [ - "ES2022", - "DOM" - ] + "lib": ["ES2022", "DOM"] + }, + "examplesCompilerOptions": { + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "exactOptionalPropertyTypes": true, + "moduleResolution": "Bundler", + "target": "ES2022", + "lib": ["ES2022", "DOM"], + "paths": { + "@effect/docgen": ["../../src/index.js"] + } } } diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index 7ac6b11..fa76428 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -1,6 +1,6 @@ --- title: Markdown.ts -nav_order: 7 +nav_order: 8 parent: Modules --- @@ -23,11 +23,14 @@ Since v1.0.0 Description... +```ts +const a: string = 1 +``` + **Example** (Title 1) ```ts twoslash title="Title 1" -import * as Markdown from "@effect/docgen/Markdown" -import * as Domain from "@effect/docgen/Domain" +import { Domain, Markdown } from "@effect/docgen" import { Option } from "effect" const doc = Domain.createNamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) @@ -38,7 +41,7 @@ console.log(Markdown.printModule(m, 0)) **Example** (Title 2) ```js twoslash title="Title 2" -const x = 1 +const a: string = "a" ``` **Signature** diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index ca38cd7..58025f7 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -1,6 +1,6 @@ --- title: Parser.ts -nav_order: 8 +nav_order: 9 parent: Modules --- diff --git a/docs/modules/Process.ts.md b/docs/modules/Process.ts.md index e00908a..6a67120 100644 --- a/docs/modules/Process.ts.md +++ b/docs/modules/Process.ts.md @@ -1,6 +1,6 @@ --- title: Process.ts -nav_order: 9 +nav_order: 10 parent: Modules --- diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md new file mode 100644 index 0000000..c567c9f --- /dev/null +++ b/docs/modules/index.ts.md @@ -0,0 +1,123 @@ +--- +title: index.ts +nav_order: 7 +parent: Modules +--- + +## index overview + +Since v0.6.0 + +--- + +

Table of contents

+ +- [exports](#exports) + - [From "./Configuration.js"](#from-configurationjs) + - [From "./Core.js"](#from-corejs) + - [From "./Domain.js"](#from-domainjs) + - [From "./Error.js"](#from-errorjs) + - [From "./File.js"](#from-filejs) + - [From "./Markdown.js"](#from-markdownjs) + - [From "./Parser.js"](#from-parserjs) + - [From "./Process.js"](#from-processjs) + +--- + +# exports + +## From "./Configuration.js" + +Re-exports all named exports from the "./Configuration.js" module as `Configuration`. + +**Signature** + +```ts +export * as Configuration from "./Configuration.js" +``` + +Since v0.6.0 + +## From "./Core.js" + +Re-exports all named exports from the "./Core.js" module as `Core`. + +**Signature** + +```ts +export * as Core from "./Core.js" +``` + +Since v0.6.0 + +## From "./Domain.js" + +Re-exports all named exports from the "./Domain.js" module as `Domain`. + +**Signature** + +```ts +export * as Domain from "./Domain.js" +``` + +Since v0.6.0 + +## From "./Error.js" + +Re-exports all named exports from the "./Error.js" module as `Error`. + +**Signature** + +```ts +export * as Error from "./Error.js" +``` + +Since v0.6.0 + +## From "./File.js" + +Re-exports all named exports from the "./File.js" module as `File`. + +**Signature** + +```ts +export * as File from "./File.js" +``` + +Since v0.6.0 + +## From "./Markdown.js" + +Re-exports all named exports from the "./Markdown.js" module as `Markdown`. + +**Signature** + +```ts +export * as Markdown from "./Markdown.js" +``` + +Since v0.6.0 + +## From "./Parser.js" + +Re-exports all named exports from the "./Parser.js" module as `Parser`. + +**Signature** + +```ts +export * as Parser from "./Parser.js" +``` + +Since v0.6.0 + +## From "./Process.js" + +Re-exports all named exports from the "./Process.js" module as `Process`. + +**Signature** + +```ts +export * as Process from "./Process.js" +``` + +Since v0.6.0 diff --git a/src/Core.ts b/src/Core.ts index 4e23dca..e7c3d98 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -114,11 +114,10 @@ const typeCheckAndRunExamples = (modules: ReadonlyArray) => yield* Effect.logInfo("Typechecking examples...") yield* cleanupExamples const files = yield* getExampleFiles(modules) - const examples = yield* handleImports(files) - const len = examples.length + const len = files.length if (len > 0) { yield* Effect.logInfo(`${len} example(s) found`) - yield* writeExamplesToOutDir(examples) + yield* writeExamplesToOutDir(files) yield* createExamplesTsConfigJson yield* runTscOnExamples yield* runTsxOnExamples @@ -260,33 +259,6 @@ const getExampleFiles = (modules: ReadonlyArray) => }) }) -/** - * Replaces the project name in the given source code imports with the configured project name. - */ -const replaceProjectName = (source: string) => - Effect.gen(function*() { - const config = yield* Configuration.Configuration - const importRegex = (projectName: string) => - new RegExp( - `from (?['"])${projectName}(?:/lib)?(?:/(?.*))?\\k`, - "g" - ) - - const out = source.replace(importRegex(config.projectName), (...args) => { - const groups: { path?: string } = args[args.length - 1] - return `from '../../src${groups.path ? `/${groups.path}` : ""}'` - }) - - return out - }) - -const handleImports = (files: ReadonlyArray) => - Effect.forEach(files, (file) => - Effect.gen(function*() { - const source = yield* replaceProjectName(file.content) - return File.createFile(file.path, source, file.isOverwriteable) - })) - /** * Generates an entry point file for the given examples. */ diff --git a/src/Markdown.ts b/src/Markdown.ts index e35b1e4..37af19f 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -261,12 +261,15 @@ const byCategory = Order.mapInput( /** * Description... * + * ```ts + * const a: string = 1 + * ``` + * * @example * **Example** (Title 1) * * ```ts twoslash title="Title 1" - * import * as Markdown from "@effect/docgen/Markdown" - * import * as Domain from "@effect/docgen/Domain" + * import { Domain, Markdown } from "@effect/docgen" * import { Option } from "effect" * * const doc = Domain.createNamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) @@ -277,7 +280,7 @@ const byCategory = Order.mapInput( * **Example** (Title 2) * * ~~~js twoslash title="Title 2" - * const x = 1 + * const a: string = "a" * ~~~ * * @category printers diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..4e1e28f --- /dev/null +++ b/src/index.ts @@ -0,0 +1,43 @@ +/** + * @since 0.6.0 + */ + +/** + * @since 0.6.0 + */ +export * as Configuration from "./Configuration.js" + +/** + * @since 0.6.0 + */ +export * as Core from "./Core.js" + +/** + * @since 0.6.0 + */ +export * as Domain from "./Domain.js" + +/** + * @since 0.6.0 + */ +export * as Error from "./Error.js" + +/** + * @since 0.6.0 + */ +export * as File from "./File.js" + +/** + * @since 0.6.0 + */ +export * as Markdown from "./Markdown.js" + +/** + * @since 0.6.0 + */ +export * as Parser from "./Parser.js" + +/** + * @since 0.6.0 + */ +export * as Process from "./Process.js" From 29681162d8548a0b01e22b64b8db57605a2241db Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 10:10:25 +0100 Subject: [PATCH 15/56] runExamples is not false by default --- .changeset/silly-insects-draw.md | 1 + src/CLI.ts | 5 ++--- src/Configuration.ts | 1 + src/Core.ts | 25 ++++++++++++++----------- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index 38a0d50..37f3c7d 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -7,3 +7,4 @@ - Change "Added in" to "Since" in Markdown generation - Reorder signature and example sections in Markdown generation - Remove redundant "Example" header in Markdown generation +- runExamples is not false by default diff --git a/src/CLI.ts b/src/CLI.ts index 4210bf6..8ec7dd2 100644 --- a/src/CLI.ts +++ b/src/CLI.ts @@ -91,9 +91,8 @@ const enforceVersion = Options.boolean("no-enforce-version", { ) ) -const runExamples = Options.boolean("no-run-examples", { - ifPresent: false, - negationNames: ["run-examples"] +const runExamples = Options.boolean("run-examples", { + negationNames: ["no-run-examples"] }).pipe( Options.withFallbackConfig(Config.boolean("runExamples")), Options.withDescription( diff --git a/src/Configuration.ts b/src/Configuration.ts index 20dddbe..5e99cf7 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -148,6 +148,7 @@ const validateJsonFile = ( ) }) +// TODO: this is invoked twice, why? const readDocgenConfig = ( path: string ): Effect.Effect< diff --git a/src/Core.ts b/src/Core.ts index e7c3d98..fd2b16a 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -110,22 +110,25 @@ const parseModules = (files: ReadonlyArray) => const typeCheckAndRunExamples = (modules: ReadonlyArray) => Effect.gen(function*() { const config = yield* Configuration.Configuration - if (config.runExamples) { + yield* cleanupExamples + const files = yield* getExampleFiles(modules) + const len = files.length + if (len > 0) { + yield* Effect.logInfo(`${len} example(s) found`) + yield* writeExamplesToOutDir(files) + yield* createExamplesTsConfigJson yield* Effect.logInfo("Typechecking examples...") - yield* cleanupExamples - const files = yield* getExampleFiles(modules) - const len = files.length - if (len > 0) { - yield* Effect.logInfo(`${len} example(s) found`) - yield* writeExamplesToOutDir(files) - yield* createExamplesTsConfigJson - yield* runTscOnExamples + yield* runTscOnExamples + if (config.runExamples) { + yield* Effect.logInfo("Running examples...") yield* runTsxOnExamples } else { - yield* Effect.logInfo("No examples found.") + yield* Effect.logInfo("Skipping running examples") } - yield* cleanupExamples + } else { + yield* Effect.logInfo("No examples found.") } + yield* cleanupExamples }) /** From 4eec3536a8f1dbb30035a2e66804289e4b4d535c Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 10:31:39 +0100 Subject: [PATCH 16/56] Extract examples from descriptions --- .changeset/silly-insects-draw.md | 1 + docs/modules/Domain.ts.md | 2 +- docs/modules/Markdown.ts.md | 4 ++-- src/Core.ts | 40 ++++++++++++++++++-------------- src/Domain.ts | 2 +- src/Markdown.ts | 4 ++-- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index 37f3c7d..bfde383 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -8,3 +8,4 @@ - Reorder signature and example sections in Markdown generation - Remove redundant "Example" header in Markdown generation - runExamples is not false by default +- Extract examples from descriptions (disable with `skip-type-checking` metadata on fenced code blocks) diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index bd05a33..44cc6e3 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -263,7 +263,7 @@ Since v1.0.0 These are manual exports, like: -```ts +```ts skip-type-checking const _null = ... export { diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index fa76428..bc8642b 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -24,7 +24,7 @@ Since v1.0.0 Description... ```ts -const a: string = 1 +export const a: string = "a" ``` **Example** (Title 1) @@ -41,7 +41,7 @@ console.log(Markdown.printModule(m, 0)) **Example** (Title 2) ```js twoslash title="Title 2" -const a: string = "a" +export const a: string = "b" ``` **Signature** diff --git a/src/Core.ts b/src/Core.ts index fd2b16a..bf6ead2 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -12,6 +12,7 @@ import { pipe } from "effect" import * as Array from "effect/Array" import * as Chunk from "effect/Chunk" import * as Effect from "effect/Effect" +import * as Option from "effect/Option" import * as Stream from "effect/Stream" import * as String from "effect/String" import * as Glob from "glob" @@ -165,7 +166,9 @@ const extractFencedCode = (content: string): Array => { const fenceRegex = /(?:```|~~~)(.*?)\n([\s\S]*?)(?:```|~~~)/g const matches = Array.fromIterable(content.matchAll(fenceRegex)) - return Array.map(matches, (match: RegExpMatchArray) => match[2].trim()) + return matches + .filter((match) => !match[1].includes("skip-type-checking")) + .map((match) => match[2].trim()) } /** @@ -178,24 +181,27 @@ const getExampleFiles = (modules: ReadonlyArray) => return Array.flatMap(modules, (module) => { const prefix = module.path.join("-") - const getFiles = (exampleId: string) => (doc: Domain.NamedDoc): ReadonlyArray => - Array.flatMap( - doc.examples, - (content, i) => { - const examples = extractFencedCode(content.body) - return examples.map((example, j) => { - return File.createFile( - path.join( - config.outDir, - "examples", - `${prefix}-${exampleId}-${doc.name}-${i}-${j}.ts` - ), - example, - true // make the file overwritable - ) - }) + const getFiles = (exampleId: string) => (doc: Domain.NamedDoc): ReadonlyArray => { + const descriptionExamples = doc.description.pipe( + Option.map(extractFencedCode), + Option.getOrElse((): Array => []) + ) + const examples = descriptionExamples.concat(doc.examples.flatMap((e) => extractFencedCode(e.body))) + return Array.map( + examples, + (example, i) => { + return File.createFile( + path.join( + config.outDir, + "examples", + `${prefix}-${exampleId}-${doc.name}-${i}.ts` + ), + example, + true // make the file overwritable + ) } ) + } const allPrefixedNamespaces = Array.flatMap(module.namespaces, (namespace) => extractPrefixedNestedNamespaces(namespace, "")) diff --git a/src/Domain.ts b/src/Domain.ts index 918500e..3ff770b 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -116,7 +116,7 @@ export interface Constant extends NamedDoc { /** * These are manual exports, like: * - * ```ts + * ```ts skip-type-checking * const _null = ... * * export { diff --git a/src/Markdown.ts b/src/Markdown.ts index 37af19f..91be856 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -262,7 +262,7 @@ const byCategory = Order.mapInput( * Description... * * ```ts - * const a: string = 1 + * export const a: string = "a" * ``` * * @example @@ -280,7 +280,7 @@ const byCategory = Order.mapInput( * **Example** (Title 2) * * ~~~js twoslash title="Title 2" - * const a: string = "a" + * export const a: string = "b" * ~~~ * * @category printers From bad2b0a08dcd6383f46689dc3e9aa53451f6c8e9 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 11:07:49 +0100 Subject: [PATCH 17/56] Add support for @throws tag in documentation generation --- .changeset/silly-insects-draw.md | 1 + docs/modules/Domain.ts.md | 7 ++++++- docs/modules/Markdown.ts.md | 5 +++++ src/Domain.ts | 10 ++++++++-- src/Markdown.ts | 9 +++++++++ src/Parser.ts | 18 +++++++++++++++-- test/Configuration.test.ts | 4 ++-- test/Markdown.test.ts | 3 ++- test/Parser.test.ts | 33 +++++++++++++++++++++----------- 9 files changed, 71 insertions(+), 19 deletions(-) diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index bfde383..b09cdea 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -9,3 +9,4 @@ - Remove redundant "Example" header in Markdown generation - runExamples is not false by default - Extract examples from descriptions (disable with `skip-type-checking` metadata on fenced code blocks) +- Add support for `@throws` tag in documentation generation diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 44cc6e3..efdbcd2 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -103,7 +103,11 @@ Since v1.0.0 **Signature** ```ts -export declare const createFunction: (doc: NamedDoc, signatures: ReadonlyArray) => Function +export declare const createFunction: ( + doc: NamedDoc, + signatures: ReadonlyArray, + throws: ReadonlyArray +) => Function ``` Since v1.0.0 @@ -290,6 +294,7 @@ Since v1.0.0 export interface Function extends NamedDoc { readonly _tag: "Function" readonly signatures: ReadonlyArray + readonly throws: ReadonlyArray } ``` diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index bc8642b..f68ce9a 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -27,6 +27,11 @@ Description... export const a: string = "a" ``` +**Throws** + +- `Error1` - Description 1 +- `Error2` - Description 2 + **Example** (Title 1) ```ts twoslash title="Title 1" diff --git a/src/Domain.ts b/src/Domain.ts index 3ff770b..d979bb8 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -93,6 +93,7 @@ export interface Interface extends NamedDoc { export interface Function extends NamedDoc { readonly _tag: "Function" readonly signatures: ReadonlyArray + readonly throws: ReadonlyArray } /** @@ -252,10 +253,15 @@ export const createInterface = (doc: NamedDoc, signature: string): Interface => * @category constructors * @since 1.0.0 */ -export const createFunction = (doc: NamedDoc, signatures: ReadonlyArray): Function => ({ +export const createFunction = ( + doc: NamedDoc, + signatures: ReadonlyArray, + throws: ReadonlyArray +): Function => ({ _tag: "Function", ...doc, - signatures + signatures, + throws }) /** diff --git a/src/Markdown.ts b/src/Markdown.ts index 91be856..e119c8f 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -38,6 +38,11 @@ const printSince: (v: Option.Option) => string = Option.match({ onSome: (v) => MarkdownPrinter.paragraph(`Since v${v}`) }) +const printThrows = (throws: ReadonlyArray): string => + throws.length === 0 + ? "" + : MarkdownPrinter.paragraph(MarkdownPrinter.bold("Throws") + "\n\n" + throws.map((t) => `- ${t}`).join("\n")) + const printTitle = (s: string, deprecated: boolean, type?: string): string => { const name = s.trim() === "hasOwnProperty" ? `${s} (function)` : s const title = deprecated ? MarkdownPrinter.strikethrough(name) : name @@ -164,6 +169,7 @@ export const printFunction = (model: Domain.Function): string => MarkdownPrinter.paragraph( MarkdownPrinter.h2(printTitle(model.name, model.deprecated)), printDescription(model.description), + printThrows(model.throws), printExamples(model.examples), printSignatures(model.signatures), printSince(model.since) @@ -283,6 +289,9 @@ const byCategory = Order.mapInput( * export const a: string = "b" * ~~~ * + * @throws `Error1` - Description 1 + * @throws `Error2` - Description 2 + * * @category printers * @since 1.0.0 */ diff --git a/src/Parser.ts b/src/Parser.ts index eed5151..4843f5e 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -280,6 +280,12 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => ) }) ) + // TODO: parseComment is called twice, here and in getDoc + const comment = parseComment(text) + const throws: Array = Option.fromNullable(comment.tags["throws"]).pipe( + Option.map(Array.getSomes), + Option.getOrElse(() => []) + ) return Domain.createFunction( Domain.createNamedDoc( name, @@ -289,7 +295,8 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => doc.examples, doc.category ), - signatures + signatures, + throws ) }) @@ -304,6 +311,12 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => vd.getType().getText(vd) ) }` + // TODO: parseComment is called twice, here and in getDoc + const comment = parseComment(text) + const throws: Array = Option.fromNullable(comment.tags["throws"]).pipe( + Option.map(Array.getSomes), + Option.getOrElse(() => []) + ) return Domain.createFunction( Domain.createNamedDoc( name, @@ -313,7 +326,8 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => doc.examples, doc.category ), - [signature] + [signature], + throws ) }) diff --git a/test/Configuration.test.ts b/test/Configuration.test.ts index b131aae..16d7c7a 100644 --- a/test/Configuration.test.ts +++ b/test/Configuration.test.ts @@ -115,7 +115,7 @@ describe("Configuration", () => { enforceDescriptions: false, enforceExamples: false, enforceVersion: true, - runExamples: true, + runExamples: false, exclude: [], parseCompilerOptions: Configuration.defaultCompilerOptions, examplesCompilerOptions: Configuration.defaultCompilerOptions @@ -150,7 +150,7 @@ describe("Configuration", () => { enforceDescriptions: false, enforceExamples: false, enforceVersion: true, - runExamples: true, + runExamples: false, exclude: [], parseCompilerOptions, examplesCompilerOptions: Configuration.defaultCompilerOptions diff --git a/test/Markdown.test.ts b/test/Markdown.test.ts index d5ecc3d..1a80803 100644 --- a/test/Markdown.test.ts +++ b/test/Markdown.test.ts @@ -96,7 +96,8 @@ example 1 }], Option.none() ), - ["declare const func: (test: string) => string"] + ["declare const func: (test: string) => string"], + [] ), interface: Domain.createInterface( Domain.createNamedDoc( diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 153854e..f738b61 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -494,7 +494,8 @@ describe("Parser", () => { ], since: Option.some("1.0.0"), examples: [], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -527,7 +528,8 @@ describe("Parser", () => { { body: "assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 })" }, { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } ], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -566,7 +568,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }, { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } ], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -606,7 +609,8 @@ assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) \`\`\`` } ], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -645,7 +649,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }, { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } ], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -685,7 +690,8 @@ assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) ~~~` } ], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -724,7 +730,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }, { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } ], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -763,7 +770,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }, { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } ], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -787,7 +795,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) ], since: Option.some("1.0.0"), examples: [], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -813,7 +822,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) ], since: Option.some("1.0.0"), examples: [], - category: Option.none() + category: Option.none(), + throws: [] } ] ) @@ -842,7 +852,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) signatures: [ "export declare function f(a: Int, b: Int): { [key: string]: number }", "export declare function f(a: number, b: number): { [key: string]: number }" - ] + ], + throws: [] } ] ) From c73aeb2faaa34581dd8ee0019aad968ba5bb7f24 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 11:30:30 +0100 Subject: [PATCH 18/56] Enhance code block filtering --- docs/modules/Markdown.ts.md | 6 ++++++ src/Core.ts | 7 ++++++- src/Markdown.ts | 6 ++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index f68ce9a..1728664 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -27,6 +27,12 @@ Description... export const a: string = "a" ``` +```text +┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌────────┐ +│ input │───►│ func1 │───►│ func2 │───►│ ... │───►│ funcN │───►│ result │ +└───────┘ └───────┘ └───────┘ └───────┘ └───────┘ └────────┘ +``` + **Throws** - `Error1` - Description 1 diff --git a/src/Core.ts b/src/Core.ts index bf6ead2..aae92fd 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -167,7 +167,12 @@ const extractFencedCode = (content: string): Array => { const matches = Array.fromIterable(content.matchAll(fenceRegex)) return matches - .filter((match) => !match[1].includes("skip-type-checking")) + .filter((match) => { + const meta = match[1].toLocaleLowerCase() + const isTypeScript = meta.startsWith("ts") || meta.startsWith("typescript") + const isSkipTypeChecking = meta.includes("skip-type-checking") + return isTypeScript && !isSkipTypeChecking + }) .map((match) => match[2].trim()) } diff --git a/src/Markdown.ts b/src/Markdown.ts index e119c8f..a70a379 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -271,6 +271,12 @@ const byCategory = Order.mapInput( * export const a: string = "a" * ``` * + * ```text + * ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌────────┐ + * │ input │───►│ func1 │───►│ func2 │───►│ ... │───►│ funcN │───►│ result │ + * └───────┘ └───────┘ └───────┘ └───────┘ └───────┘ └────────┘ + * ``` + * * @example * **Example** (Title 1) * From 91774a93f60da7ebb5fe3f6245674de0db76d5e8 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 14:22:40 +0100 Subject: [PATCH 19/56] Refactor Domain module to use class-based implementation --- docs/modules/CLI.ts.md | 2 +- docs/modules/Configuration.ts.md | 8 +- docs/modules/Core.ts.md | 2 +- docs/modules/Domain.ts.md | 380 ++++------- docs/modules/Error.ts.md | 8 +- docs/modules/File.ts.md | 6 +- docs/modules/Markdown.ts.md | 8 +- docs/modules/Parser.ts.md | 20 +- docs/modules/Process.ts.md | 8 +- src/CLI.ts | 2 +- src/Configuration.ts | 8 +- src/Core.ts | 2 +- src/Domain.ts | 387 +++++------ src/Error.ts | 8 +- src/File.ts | 6 +- src/Markdown.ts | 8 +- src/Parser.ts | 76 +-- src/Process.ts | 8 +- src/bin.ts | 2 +- test/Markdown.test.ts | 74 +- test/Parser.test.ts | 1091 ++++++++++++++++-------------- 21 files changed, 998 insertions(+), 1116 deletions(-) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index 098ab3e..08926b5 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -6,7 +6,7 @@ parent: Modules ## CLI overview -Since v1.0.0 +Since v0.6.0 --- diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index 63da8ff..9066771 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Configuration overview -Since v1.0.0 +Since v0.6.0 --- @@ -29,7 +29,7 @@ Since v1.0.0 export declare class Configuration ``` -Since v1.0.0 +Since v0.6.0 ## ConfigurationSchema @@ -56,7 +56,7 @@ export declare const ConfigurationSchema: Schema.Struct<{ }> ``` -Since v1.0.0 +Since v0.6.0 ## ConfigurationShape (interface) @@ -80,4 +80,4 @@ export interface ConfigurationShape { } ``` -Since v1.0.0 +Since v0.6.0 diff --git a/docs/modules/Core.ts.md b/docs/modules/Core.ts.md index 2073d9e..fe3d703 100644 --- a/docs/modules/Core.ts.md +++ b/docs/modules/Core.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Core overview -Since v1.0.0 +Since v0.6.0 --- diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index efdbcd2..13db50b 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -6,395 +6,305 @@ parent: Modules ## Domain overview -Since v1.0.0 +Since v0.6.0 ---

Table of contents

-- [constructors](#constructors) - - [createClass](#createclass) - - [createConstant](#createconstant) - - [createDoc](#createdoc) - - [createExport](#createexport) - - [createFunction](#createfunction) - - [createInterface](#createinterface) - - [createMethod](#createmethod) - - [createModule](#createmodule) - - [createNamedDoc](#createnameddoc) - - [createNamespace](#createnamespace) - - [createProperty](#createproperty) - - [createTypeAlias](#createtypealias) - [model](#model) - - [Class (interface)](#class-interface) - - [Constant (interface)](#constant-interface) - - [Doc (interface)](#doc-interface) - - [Example (type alias)](#example-type-alias) - - [Export (interface)](#export-interface) - - [Function (interface)](#function-interface) - - [Interface (interface)](#interface-interface) - - [Method (interface)](#method-interface) - - [Module (interface)](#module-interface) - - [NamedDoc (interface)](#nameddoc-interface) - - [Namespace (interface)](#namespace-interface) - - [Property (interface)](#property-interface) - - [TypeAlias (interface)](#typealias-interface) + - [Class (class)](#class-class) + - [\_tag (property)](#_tag-property) + - [Constant (class)](#constant-class) + - [\_tag (property)](#_tag-property-1) + - [Doc (class)](#doc-class) + - [Example (class)](#example-class) + - [Export (class)](#export-class) + - [\_tag (property)](#_tag-property-2) + - [Function (class)](#function-class) + - [\_tag (property)](#_tag-property-3) + - [Interface (class)](#interface-class) + - [\_tag (property)](#_tag-property-4) + - [Method (class)](#method-class) + - [Module (class)](#module-class) + - [NamedDoc (class)](#nameddoc-class) + - [Namespace (class)](#namespace-class) + - [\_tag (property)](#_tag-property-5) + - [Property (class)](#property-class) + - [TypeAlias (class)](#typealias-class) + - [\_tag (property)](#_tag-property-6) - [sorting](#sorting) - [ByPath](#bypath) --- -# constructors - -## createClass - -**Signature** - -```ts -export declare const createClass: ( - doc: NamedDoc, - signature: string, - methods: ReadonlyArray, - staticMethods: ReadonlyArray, - properties: ReadonlyArray -) => Class -``` - -Since v1.0.0 - -## createConstant - -**Signature** - -```ts -export declare const createConstant: (doc: NamedDoc, signature: string) => Constant -``` - -Since v1.0.0 - -## createDoc - -**Signature** - -```ts -export declare const createDoc: ( - description: Option.Option, - since: Option.Option, - deprecated: boolean, - examples: ReadonlyArray, - category: Option.Option -) => Doc -``` - -Since v1.0.0 +# model -## createExport +## Class (class) **Signature** ```ts -export declare const createExport: (doc: NamedDoc, signature: string) => Export +export declare class Class { constructor( + doc: NamedDoc, + readonly signature: string, + readonly methods: ReadonlyArray, + readonly staticMethods: ReadonlyArray, + readonly properties: ReadonlyArray + ) } ``` -Since v1.0.0 +Since v0.6.0 -## createFunction +### \_tag (property) **Signature** ```ts -export declare const createFunction: ( - doc: NamedDoc, - signatures: ReadonlyArray, - throws: ReadonlyArray -) => Function +readonly _tag: "Class" ``` -Since v1.0.0 +Since v0.6.0 -## createInterface +## Constant (class) **Signature** ```ts -export declare const createInterface: (doc: NamedDoc, signature: string) => Interface +export declare class Constant { constructor( + doc: NamedDoc, + readonly signature: string + ) } ``` -Since v1.0.0 +Since v0.6.0 -## createMethod +### \_tag (property) **Signature** ```ts -export declare const createMethod: (doc: NamedDoc, signatures: ReadonlyArray) => Method +readonly _tag: "Constant" ``` -Since v1.0.0 +Since v0.6.0 -## createModule +## Doc (class) **Signature** ```ts -export declare const createModule: ( - doc: NamedDoc, - path: ReadonlyArray, - classes: ReadonlyArray, - interfaces: ReadonlyArray, - functions: ReadonlyArray, - typeAliases: ReadonlyArray, - constants: ReadonlyArray, - exports: ReadonlyArray, - namespaces: ReadonlyArray -) => Module +export declare class Doc { constructor( + readonly description: Option.Option, + readonly since: Option.Option, + readonly deprecated: boolean, + readonly examples: ReadonlyArray, + readonly category: Option.Option + ) } ``` -Since v1.0.0 +Since v0.6.0 -## createNamedDoc +## Example (class) **Signature** ```ts -export declare const createNamedDoc: ( - name: string, - description: Option.Option, - since: Option.Option, - deprecated: boolean, - examples: ReadonlyArray, - category: Option.Option -) => NamedDoc +export declare class Example { constructor(readonly body: string) } ``` -Since v1.0.0 - -## createNamespace - -**Signature** - -```ts -export declare const createNamespace: ( - doc: NamedDoc, - interfaces: ReadonlyArray, - typeAliases: ReadonlyArray, - namespaces: ReadonlyArray -) => Namespace -``` +Since v0.6.0 -Since v1.0.0 +## Export (class) -## createProperty +These are manual exports, like: -**Signature** +```ts skip-type-checking +const _null = ... -```ts -export declare const createProperty: (doc: NamedDoc, signature: string) => Property +export { + _null as null +} ``` -Since v1.0.0 - -## createTypeAlias - **Signature** ```ts -export declare const createTypeAlias: (doc: NamedDoc, signature: string) => TypeAlias +export declare class Export { constructor( + doc: NamedDoc, + readonly signature: string + ) } ``` -Since v1.0.0 - -# model +Since v0.6.0 -## Class (interface) +### \_tag (property) **Signature** ```ts -export interface Class extends NamedDoc { - readonly _tag: "Class" - readonly signature: string - readonly methods: ReadonlyArray - readonly staticMethods: ReadonlyArray - readonly properties: ReadonlyArray -} +readonly _tag: "Export" ``` -Since v1.0.0 +Since v0.6.0 -## Constant (interface) +## Function (class) **Signature** ```ts -export interface Constant extends NamedDoc { - readonly _tag: "Constant" - readonly signature: string -} +export declare class Function { constructor( + doc: NamedDoc, + readonly signatures: ReadonlyArray, + readonly throws: ReadonlyArray + ) } ``` -Since v1.0.0 +Since v0.6.0 -## Doc (interface) +### \_tag (property) **Signature** ```ts -export interface Doc { - readonly description: Option.Option - readonly since: Option.Option - readonly deprecated: boolean - readonly examples: ReadonlyArray - readonly category: Option.Option -} +readonly _tag: "Function" ``` -Since v1.0.0 +Since v0.6.0 -## Example (type alias) +## Interface (class) **Signature** ```ts -export type Example = { - body: string -} +export declare class Interface { constructor( + doc: NamedDoc, + readonly signature: string + ) } ``` -Since v1.0.0 +Since v0.6.0 -## Export (interface) - -These are manual exports, like: - -```ts skip-type-checking -const _null = ... - -export { - _null as null -} -``` +### \_tag (property) **Signature** ```ts -export interface Export extends NamedDoc { - readonly _tag: "Export" - readonly signature: string -} +readonly _tag: "Interface" ``` -Since v1.0.0 +Since v0.6.0 -## Function (interface) +## Method (class) **Signature** ```ts -export interface Function extends NamedDoc { - readonly _tag: "Function" - readonly signatures: ReadonlyArray - readonly throws: ReadonlyArray -} +export declare class Method { constructor( + doc: NamedDoc, + readonly signatures: ReadonlyArray + ) } ``` -Since v1.0.0 +Since v0.6.0 -## Interface (interface) +## Module (class) **Signature** ```ts -export interface Interface extends NamedDoc { - readonly _tag: "Interface" - readonly signature: string -} +export declare class Module { constructor( + doc: NamedDoc, + readonly path: ReadonlyArray, + readonly classes: ReadonlyArray, + readonly interfaces: ReadonlyArray, + readonly functions: ReadonlyArray, + readonly typeAliases: ReadonlyArray, + readonly constants: ReadonlyArray, + readonly exports: ReadonlyArray, + readonly namespaces: ReadonlyArray + ) } ``` -Since v1.0.0 +Since v0.6.0 -## Method (interface) +## NamedDoc (class) **Signature** ```ts -export interface Method extends NamedDoc { - readonly signatures: ReadonlyArray -} +export declare class NamedDoc { constructor( + readonly name: string, + description: Option.Option, + since: Option.Option, + deprecated: boolean, + examples: ReadonlyArray, + category: Option.Option + ) } ``` -Since v1.0.0 +Since v0.6.0 -## Module (interface) +## Namespace (class) **Signature** ```ts -export interface Module extends NamedDoc { - readonly path: ReadonlyArray - readonly classes: ReadonlyArray - readonly interfaces: ReadonlyArray - readonly functions: ReadonlyArray - readonly typeAliases: ReadonlyArray - readonly constants: ReadonlyArray - readonly exports: ReadonlyArray - readonly namespaces: ReadonlyArray -} +export declare class Namespace { constructor( + doc: NamedDoc, + readonly interfaces: ReadonlyArray, + readonly typeAliases: ReadonlyArray, + readonly namespaces: ReadonlyArray + ) } ``` -Since v1.0.0 +Since v0.6.0 -## NamedDoc (interface) +### \_tag (property) **Signature** ```ts -export interface NamedDoc extends Doc { - readonly name: string -} +readonly _tag: "Namespace" ``` -Since v1.0.0 +Since v0.6.0 -## Namespace (interface) +## Property (class) **Signature** ```ts -export interface Namespace extends NamedDoc { - readonly _tag: "Namespace" - readonly interfaces: ReadonlyArray - readonly typeAliases: ReadonlyArray - readonly namespaces: ReadonlyArray -} +export declare class Property { constructor( + doc: NamedDoc, + readonly signature: string + ) } ``` -Since v1.0.0 +Since v0.6.0 -## Property (interface) +## TypeAlias (class) **Signature** ```ts -export interface Property extends NamedDoc { - readonly signature: string -} +export declare class TypeAlias { constructor( + doc: NamedDoc, + readonly signature: string + ) } ``` -Since v1.0.0 +Since v0.6.0 -## TypeAlias (interface) +### \_tag (property) **Signature** ```ts -export interface TypeAlias extends NamedDoc { - readonly _tag: "TypeAlias" - readonly signature: string -} +readonly _tag: "TypeAlias" ``` -Since v1.0.0 +Since v0.6.0 # sorting @@ -409,4 +319,4 @@ The file path is converted to lowercase before comparison. export declare const ByPath: Order.Order ``` -Since v1.0.0 +Since v0.6.0 diff --git a/docs/modules/Error.ts.md b/docs/modules/Error.ts.md index de42eaf..0643c74 100644 --- a/docs/modules/Error.ts.md +++ b/docs/modules/Error.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Error overview -Since v1.0.0 +Since v0.6.0 --- @@ -30,7 +30,7 @@ Since v1.0.0 export declare class DocgenError ``` -Since v1.0.0 +Since v0.6.0 # symbol @@ -42,7 +42,7 @@ Since v1.0.0 export declare const DocgenErrorTypeId: typeof DocgenErrorTypeId ``` -Since v1.0.0 +Since v0.6.0 ## DocgenErrorTypeId (type alias) @@ -52,4 +52,4 @@ Since v1.0.0 export type DocgenErrorTypeId = typeof DocgenErrorTypeId ``` -Since v1.0.0 +Since v0.6.0 diff --git a/docs/modules/File.ts.md b/docs/modules/File.ts.md index eca2eb3..efddb3f 100644 --- a/docs/modules/File.ts.md +++ b/docs/modules/File.ts.md @@ -6,7 +6,7 @@ parent: Modules ## File overview -Since v1.0.0 +Since v0.6.0 --- @@ -31,7 +31,7 @@ By default files are readonly (`isOverwriteable = false`). export declare const createFile: (path: string, content: string, isOverwriteable?: boolean) => File ``` -Since v1.0.0 +Since v0.6.0 # model @@ -49,4 +49,4 @@ export interface File { } ``` -Since v1.0.0 +Since v0.6.0 diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index 1728664..764347d 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Markdown overview -Since v1.0.0 +Since v0.6.0 --- @@ -44,8 +44,8 @@ export const a: string = "a" import { Domain, Markdown } from "@effect/docgen" import { Option } from "effect" -const doc = Domain.createNamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) -const m = Domain.createModule(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) +const doc = new Domain.NamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) +const m = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) console.log(Markdown.printModule(m, 0)) ``` @@ -61,4 +61,4 @@ export const a: string = "b" export declare const printModule: (module: Domain.Module, order: number) => Effect.Effect ``` -Since v1.0.0 +Since v0.6.0 diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 58025f7..bbbd587 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Parser overview -Since v1.0.0 +Since v0.6.0 --- @@ -35,7 +35,7 @@ Since v1.0.0 export declare const parseClasses: Effect.Effect ``` -Since v1.0.0 +Since v0.6.0 ## parseConstants @@ -49,7 +49,7 @@ export declare const parseConstants: Effect.Effect< > ``` -Since v1.0.0 +Since v0.6.0 ## parseExports @@ -63,7 +63,7 @@ export declare const parseExports: Effect.Effect< > ``` -Since v1.0.0 +Since v0.6.0 ## parseFiles @@ -79,7 +79,7 @@ export declare const parseFiles: ( > ``` -Since v1.0.0 +Since v0.6.0 ## parseFunctions @@ -93,7 +93,7 @@ export declare const parseFunctions: Effect.Effect< > ``` -Since v1.0.0 +Since v0.6.0 ## parseInterfaces @@ -107,7 +107,7 @@ export declare const parseInterfaces: Effect.Effect< > ``` -Since v1.0.0 +Since v0.6.0 ## parseModule @@ -121,7 +121,7 @@ export declare const parseModule: Effect.Effect< > ``` -Since v1.0.0 +Since v0.6.0 ## parseNamespaces @@ -131,7 +131,7 @@ Since v1.0.0 export declare const parseNamespaces: Effect.Effect ``` -Since v1.0.0 +Since v0.6.0 ## parseTypeAliases @@ -145,4 +145,4 @@ export declare const parseTypeAliases: Effect.Effect< > ``` -Since v1.0.0 +Since v0.6.0 diff --git a/docs/modules/Process.ts.md b/docs/modules/Process.ts.md index 6a67120..56386d1 100644 --- a/docs/modules/Process.ts.md +++ b/docs/modules/Process.ts.md @@ -6,7 +6,7 @@ parent: Modules ## Process overview -Since v1.0.0 +Since v0.6.0 --- @@ -30,7 +30,7 @@ Since v1.0.0 export declare const layer: Layer.Layer ``` -Since v1.0.0 +Since v0.6.0 # service @@ -42,7 +42,7 @@ Since v1.0.0 export declare class Process ``` -Since v1.0.0 +Since v0.6.0 ## ProcessShape (interface) @@ -58,4 +58,4 @@ export interface ProcessShape { } ``` -Since v1.0.0 +Since v0.6.0 diff --git a/src/CLI.ts b/src/CLI.ts index 8ec7dd2..639135a 100644 --- a/src/CLI.ts +++ b/src/CLI.ts @@ -1,7 +1,7 @@ #!/usr/bin/env node /** - * @since 1.0.0 + * @since 0.6.0 */ import * as Command from "@effect/cli/Command" diff --git a/src/Configuration.ts b/src/Configuration.ts index 5e99cf7..fa8770b 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -1,5 +1,5 @@ /** - * @since 1.0.0 + * @since 0.6.0 */ import * as FileSystem from "@effect/platform/FileSystem" @@ -28,7 +28,7 @@ const compilerOptionsSchema = Schema.Union( /** * @category service - * @since 1.0.0 + * @since 0.6.0 */ export const ConfigurationSchema = Schema.Struct({ "$schema": Schema.optional(Schema.String), @@ -80,7 +80,7 @@ export const ConfigurationSchema = Schema.Struct({ /** * @category service - * @since 1.0.0 + * @since 0.6.0 */ export interface ConfigurationShape { readonly projectName: string @@ -100,7 +100,7 @@ export interface ConfigurationShape { /** * @category service - * @since 1.0.0 + * @since 0.6.0 */ export class Configuration extends Context.Tag("Configuration")() {} diff --git a/src/Core.ts b/src/Core.ts index aae92fd..f1fca21 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -1,5 +1,5 @@ /** - * @since 1.0.0 + * @since 0.6.0 */ import * as NodePath from "@effect/platform-node/NodePath" diff --git a/src/Domain.ts b/src/Domain.ts index d979bb8..f9b4583 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -1,5 +1,5 @@ /** - * @since 1.0.0 + * @since 0.6.0 */ import type * as Option from "effect/Option" @@ -8,110 +8,176 @@ import * as String from "effect/String" /** * @category model - * @since 1.0.0 + * @since 0.6.0 */ -export interface Module extends NamedDoc { - readonly path: ReadonlyArray - readonly classes: ReadonlyArray - readonly interfaces: ReadonlyArray - readonly functions: ReadonlyArray - readonly typeAliases: ReadonlyArray - readonly constants: ReadonlyArray - readonly exports: ReadonlyArray - readonly namespaces: ReadonlyArray +export class Example { + constructor(readonly body: string) {} } /** * @category model - * @since 1.0.0 - */ -export type Example = { - body: string + * @since 0.6.0 + */ +export class Doc { + constructor( + readonly description: Option.Option, + readonly since: Option.Option, + readonly deprecated: boolean, + readonly examples: ReadonlyArray, + readonly category: Option.Option + ) {} } /** * @category model - * @since 1.0.0 - */ -export interface Doc { - readonly description: Option.Option - readonly since: Option.Option - readonly deprecated: boolean - readonly examples: ReadonlyArray - readonly category: Option.Option + * @since 0.6.0 + */ +export class NamedDoc extends Doc { + constructor( + readonly name: string, + description: Option.Option, + since: Option.Option, + deprecated: boolean, + examples: ReadonlyArray, + category: Option.Option + ) { + super(description, since, deprecated, examples, category) + } } /** * @category model - * @since 1.0.0 - */ -export interface NamedDoc extends Doc { - readonly name: string + * @since 0.6.0 + */ +export class Module extends NamedDoc { + constructor( + doc: NamedDoc, + readonly path: ReadonlyArray, + readonly classes: ReadonlyArray, + readonly interfaces: ReadonlyArray, + readonly functions: ReadonlyArray, + readonly typeAliases: ReadonlyArray, + readonly constants: ReadonlyArray, + readonly exports: ReadonlyArray, + readonly namespaces: ReadonlyArray + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } /** * @category model - * @since 1.0.0 - */ -export interface Class extends NamedDoc { - readonly _tag: "Class" - readonly signature: string - readonly methods: ReadonlyArray - readonly staticMethods: ReadonlyArray - readonly properties: ReadonlyArray + * @since 0.6.0 + */ +export class Class extends NamedDoc { + /** + * @since 0.6.0 + */ + readonly _tag = "Class" + constructor( + doc: NamedDoc, + readonly signature: string, + readonly methods: ReadonlyArray, + readonly staticMethods: ReadonlyArray, + readonly properties: ReadonlyArray + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } /** * @category model - * @since 1.0.0 - */ -export interface Method extends NamedDoc { - readonly signatures: ReadonlyArray + * @since 0.6.0 + */ +export class Method extends NamedDoc { + constructor( + doc: NamedDoc, + readonly signatures: ReadonlyArray + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } /** * @category model - * @since 1.0.0 - */ -export interface Property extends NamedDoc { - readonly signature: string + * @since 0.6.0 + */ +export class Property extends NamedDoc { + constructor( + doc: NamedDoc, + readonly signature: string + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } /** * @category model - * @since 1.0.0 - */ -export interface Interface extends NamedDoc { - readonly _tag: "Interface" - readonly signature: string + * @since 0.6.0 + */ +export class Interface extends NamedDoc { + /** + * @since 0.6.0 + */ + readonly _tag = "Interface" + constructor( + doc: NamedDoc, + readonly signature: string + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } /** * @category model - * @since 1.0.0 - */ -export interface Function extends NamedDoc { - readonly _tag: "Function" - readonly signatures: ReadonlyArray - readonly throws: ReadonlyArray + * @since 0.6.0 + */ +export class Function extends NamedDoc { + /** + * @since 0.6.0 + */ + readonly _tag = "Function" + constructor( + doc: NamedDoc, + readonly signatures: ReadonlyArray, + readonly throws: ReadonlyArray + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } /** * @category model - * @since 1.0.0 - */ -export interface TypeAlias extends NamedDoc { - readonly _tag: "TypeAlias" - readonly signature: string + * @since 0.6.0 + */ +export class TypeAlias extends NamedDoc { + /** + * @since 0.6.0 + */ + readonly _tag = "TypeAlias" + constructor( + doc: NamedDoc, + readonly signature: string + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } /** * @category model - * @since 1.0.0 - */ -export interface Constant extends NamedDoc { - readonly _tag: "Constant" - readonly signature: string + * @since 0.6.0 + */ +export class Constant extends NamedDoc { + /** + * @since 0.6.0 + */ + readonly _tag = "Constant" + constructor( + doc: NamedDoc, + readonly signature: string + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } /** @@ -126,181 +192,46 @@ export interface Constant extends NamedDoc { * ``` * * @category model - * @since 1.0.0 - */ -export interface Export extends NamedDoc { - readonly _tag: "Export" - readonly signature: string + * @since 0.6.0 + */ +export class Export extends NamedDoc { + /** + * @since 0.6.0 + */ + readonly _tag = "Export" + constructor( + doc: NamedDoc, + readonly signature: string + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } /** * @category model - * @since 1.0.0 - */ -export interface Namespace extends NamedDoc { - readonly _tag: "Namespace" - readonly interfaces: ReadonlyArray - readonly typeAliases: ReadonlyArray - readonly namespaces: ReadonlyArray + * @since 0.6.0 + */ +export class Namespace extends NamedDoc { + /** + * @since 0.6.0 + */ + readonly _tag = "Namespace" + constructor( + doc: NamedDoc, + readonly interfaces: ReadonlyArray, + readonly typeAliases: ReadonlyArray, + readonly namespaces: ReadonlyArray + ) { + super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) + } } -// ------------------------------------------------------------------------------------- -// constructors -// ------------------------------------------------------------------------------------- - -/** - * @category constructors - * @since 1.0.0 - */ -export const createDoc = ( - description: Option.Option, - since: Option.Option, - deprecated: boolean, - examples: ReadonlyArray, - category: Option.Option -): Doc => ({ description, since, deprecated, examples, category }) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createNamedDoc = ( - name: string, - description: Option.Option, - since: Option.Option, - deprecated: boolean, - examples: ReadonlyArray, - category: Option.Option -): NamedDoc => ({ name, description, since, deprecated, examples, category }) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createModule = ( - doc: NamedDoc, - path: ReadonlyArray, - classes: ReadonlyArray, - interfaces: ReadonlyArray, - functions: ReadonlyArray, - typeAliases: ReadonlyArray, - constants: ReadonlyArray, - exports: ReadonlyArray, - namespaces: ReadonlyArray -): Module => ({ - ...doc, - path, - classes, - interfaces, - functions, - typeAliases, - constants, - exports, - namespaces -}) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createClass = ( - doc: NamedDoc, - signature: string, - methods: ReadonlyArray, - staticMethods: ReadonlyArray, - properties: ReadonlyArray -): Class => ({ _tag: "Class", ...doc, signature, methods, staticMethods, properties }) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createConstant = (doc: NamedDoc, signature: string): Constant => ({ - _tag: "Constant", - ...doc, - signature -}) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createMethod = (doc: NamedDoc, signatures: ReadonlyArray): Method => ({ - ...doc, - signatures -}) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createProperty = (doc: NamedDoc, signature: string): Property => ({ - ...doc, - signature -}) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createInterface = (doc: NamedDoc, signature: string): Interface => ({ - _tag: "Interface", - ...doc, - signature -}) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createFunction = ( - doc: NamedDoc, - signatures: ReadonlyArray, - throws: ReadonlyArray -): Function => ({ - _tag: "Function", - ...doc, - signatures, - throws -}) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createTypeAlias = (doc: NamedDoc, signature: string): TypeAlias => ({ - _tag: "TypeAlias", - ...doc, - signature -}) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createExport = (doc: NamedDoc, signature: string): Export => ({ - _tag: "Export", - ...doc, - signature -}) - -/** - * @category constructors - * @since 1.0.0 - */ -export const createNamespace = ( - doc: NamedDoc, - interfaces: ReadonlyArray, - typeAliases: ReadonlyArray, - namespaces: ReadonlyArray -): Namespace => ({ _tag: "Namespace", ...doc, interfaces, typeAliases, namespaces }) - /** * A comparator function for sorting `Module` objects by their file path, represented as a string. * The file path is converted to lowercase before comparison. * * @category sorting - * @since 1.0.0 + * @since 0.6.0 */ export const ByPath: Order.Order = Order.mapInput( String.Order, diff --git a/src/Error.ts b/src/Error.ts index 45f5dc5..c0cc6f1 100644 --- a/src/Error.ts +++ b/src/Error.ts @@ -1,24 +1,24 @@ /** - * @since 1.0.0 + * @since 0.6.0 */ import * as Data from "effect/Data" /** * @category symbol - * @since 1.0.0 + * @since 0.6.0 */ export const DocgenErrorTypeId = Symbol.for("@effect/docgen/DocgenError") /** * @category symbol - * @since 1.0.0 + * @since 0.6.0 */ export type DocgenErrorTypeId = typeof DocgenErrorTypeId /** * @category model - * @since 1.0.0 + * @since 0.6.0 */ export class DocgenError extends Data.TaggedError("DocgenError")<{ readonly message: string diff --git a/src/File.ts b/src/File.ts index 58d8c9a..c1dd62a 100644 --- a/src/File.ts +++ b/src/File.ts @@ -1,5 +1,5 @@ /** - * @since 1.0.0 + * @since 0.6.0 */ import * as Data from "effect/Data" @@ -8,7 +8,7 @@ import * as Data from "effect/Data" * Represents a file which can be optionally overwriteable. * * @category model - * @since 1.0.0 + * @since 0.6.0 */ export interface File { readonly path: string @@ -20,7 +20,7 @@ export interface File { * By default files are readonly (`isOverwriteable = false`). * * @category constructors - * @since 1.0.0 + * @since 0.6.0 */ export const createFile = (path: string, content: string, isOverwriteable = false): File => Data.struct({ path, content, isOverwriteable }) diff --git a/src/Markdown.ts b/src/Markdown.ts index a70a379..ea9bcb4 100644 --- a/src/Markdown.ts +++ b/src/Markdown.ts @@ -1,5 +1,5 @@ /** - * @since 1.0.0 + * @since 0.6.0 */ import * as Array from "effect/Array" import * as Effect from "effect/Effect" @@ -284,8 +284,8 @@ const byCategory = Order.mapInput( * import { Domain, Markdown } from "@effect/docgen" * import { Option } from "effect" * - * const doc = Domain.createNamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) - * const m = Domain.createModule(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) + * const doc = new Domain.NamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) + * const m = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) * console.log(Markdown.printModule(m, 0)) * ``` * @@ -299,7 +299,7 @@ const byCategory = Order.mapInput( * @throws `Error2` - Description 2 * * @category printers - * @since 1.0.0 + * @since 0.6.0 */ export const printModule = ( module: Domain.Module, diff --git a/src/Parser.ts b/src/Parser.ts index 4843f5e..0f57cad 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -1,5 +1,5 @@ /** - * @since 1.0.0 + * @since 0.6.0 */ import * as Path from "@effect/platform/Path" import chalk from "chalk" @@ -152,8 +152,8 @@ const getDescription = (name: string, comment: Comment) => return comment.description }) -const parseExample = (body: string) => { - return { body } +const parseExample = (body: string): Domain.Example => { + return new Domain.Example(body) } const getExamplesTag = (name: string, comment: Comment, isModule: boolean) => @@ -181,7 +181,7 @@ export const getDoc = (name: string, text: string, isModule = false) => const description = yield* getDescription(name, comment) const examples = yield* getExamplesTag(name, comment, isModule) const deprecated = Option.isSome(Record.get(comment.tags, "deprecated")) - return Domain.createDoc( + return new Domain.Doc( description, since, deprecated, @@ -196,8 +196,8 @@ const parseInterfaceDeclaration = (id: ast.InterfaceDeclaration) => const text = getJSDocText(id.getJsDocs()) const doc = yield* getDoc(name, text) const signature = id.getText() - return Domain.createInterface( - Domain.createNamedDoc( + return new Domain.Interface( + new Domain.NamedDoc( name, doc.description, doc.since, @@ -221,7 +221,7 @@ const parseInterfaceDeclarations = (interfaces: ReadonlyArray Option.map(Array.getSomes), Option.getOrElse(() => []) ) - return Domain.createFunction( - Domain.createNamedDoc( + return new Domain.Function( + new Domain.NamedDoc( name, doc.description, doc.since, @@ -317,8 +317,8 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => Option.map(Array.getSomes), Option.getOrElse(() => []) ) - return Domain.createFunction( - Domain.createNamedDoc( + return new Domain.Function( + new Domain.NamedDoc( name, doc.description, doc.since, @@ -360,7 +360,7 @@ const getFunctionDeclarations = Effect.gen(function*() { /** * @category parsers - * @since 1.0.0 + * @since 0.6.0 */ export const parseFunctions = Effect.gen(function*() { const { arrows, functions } = yield* getFunctionDeclarations @@ -375,8 +375,8 @@ const parseTypeAliasDeclaration = (ta: ast.TypeAliasDeclaration) => const text = getJSDocText(ta.getJsDocs()) const doc = yield* getDoc(name, text) const signature = ta.getText() - return Domain.createTypeAlias( - Domain.createNamedDoc( + return new Domain.TypeAlias( + new Domain.NamedDoc( name, doc.description, doc.since, @@ -400,7 +400,7 @@ const parseTypeAliasDeclarations = (typeAliases: ReadonlyArray const doc = yield* getDoc(name, text) const type = stripImportTypes(vd.getType().getText(vd)) const signature = `export declare const ${name}: ${type}` - return Domain.createConstant( - Domain.createNamedDoc( + return new Domain.Constant( + new Domain.NamedDoc( name, doc.description, doc.since, @@ -430,7 +430,7 @@ const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => /** * @category parsers - * @since 1.0.0 + * @since 0.6.0 */ export const parseConstants = Effect.gen(function*() { const source = yield* Source @@ -470,8 +470,8 @@ const parseExportSpecifier = (es: ast.ExportSpecifier) => const text = commentRange.getText() const doc = yield* getDoc(name, text) const signature = `export declare const ${name}: ${type}` - return Domain.createExport( - Domain.createNamedDoc( + return new Domain.Export( + new Domain.NamedDoc( name, doc.description, doc.since, @@ -501,8 +501,8 @@ const parseExportStar = ( const commentRange = ocommentRange.value const text = commentRange.getText() const doc = yield* getDoc(name, text) - return Domain.createExport( - Domain.createNamedDoc( + return new Domain.Export( + new Domain.NamedDoc( `From ${name}`, doc.description.pipe( Option.orElse(() => @@ -535,7 +535,7 @@ const parseNamedExports = (ed: ast.ExportDeclaration) => { /** * @category parsers - * @since 1.0.0 + * @since 0.6.0 */ export const parseExports = pipe( Effect.map(Source, (source) => source.sourceFile.getExportDeclarations()), @@ -566,8 +566,8 @@ const parseModuleDeclaration = ( const interfaces = yield* getInterfaces const typeAliases = yield* getTypeAliases const namespaces = yield* getNamespaces - return Domain.createNamespace( - Domain.createNamedDoc( + return new Domain.Namespace( + new Domain.NamedDoc( name, info.description, info.since, @@ -597,7 +597,7 @@ const parseModuleDeclarations = (namespaces: ReadonlyArray, @@ -647,8 +647,8 @@ const parseMethod = (md: ast.MethodDeclaration) => }) ) return Option.some( - Domain.createMethod( - Domain.createNamedDoc( + new Domain.Method( + new Domain.NamedDoc( name, doc.description, doc.since, @@ -679,8 +679,8 @@ const parseProperty = (classname: string) => (pd: ast.PropertyDeclaration) => }) ) const signature = `${readonly}${name}: ${type}` - return Domain.createProperty( - Domain.createNamedDoc( + return new Domain.Property( + new Domain.NamedDoc( name, doc.description, doc.since, @@ -769,8 +769,8 @@ const parseClass = (c: ast.ClassDeclaration) => Effect.map(Array.getSomes) ) const properties = yield* parseProperties(name, c) - return Domain.createClass( - Domain.createNamedDoc( + return new Domain.Class( + new Domain.NamedDoc( name, doc.description, doc.since, @@ -787,7 +787,7 @@ const parseClass = (c: ast.ClassDeclaration) => /** * @category parsers - * @since 1.0.0 + * @since 0.6.0 */ export const parseClasses = Effect.gen(function*() { const source = yield* Source @@ -835,7 +835,7 @@ export const parseModuleDocumentation = Effect.gen(function*() { const commentRange = ocommentRange.value const text = commentRange.getText() const doc = yield* getDoc("", text, true).pipe(Effect.mapError(Array.of)) - return Domain.createNamedDoc( + return new Domain.NamedDoc( name, doc.description, doc.since, @@ -845,7 +845,7 @@ export const parseModuleDocumentation = Effect.gen(function*() { ) } } - return Domain.createNamedDoc( + return new Domain.NamedDoc( name, Option.none(), Option.none(), @@ -857,7 +857,7 @@ export const parseModuleDocumentation = Effect.gen(function*() { /** * @category parsers - * @since 1.0.0 + * @since 0.6.0 */ export const parseModule = Effect.gen(function*() { const source = yield* Source @@ -869,7 +869,7 @@ export const parseModule = Effect.gen(function*() { const constants = yield* parseConstants const exports = yield* parseExports const namespaces = yield* parseNamespaces - return Domain.createModule( + return new Domain.Module( doc, source.path, classes, @@ -935,7 +935,7 @@ const createProject = (files: ReadonlyArray) => /** * @category parsers - * @since 1.0.0 + * @since 0.6.0 */ export const parseFiles = (files: ReadonlyArray) => createProject(files).pipe( diff --git a/src/Process.ts b/src/Process.ts index b0addb4..c37d7fc 100644 --- a/src/Process.ts +++ b/src/Process.ts @@ -1,5 +1,5 @@ /** - * @since 1.0.0 + * @since 0.6.0 */ import * as Context from "effect/Context" @@ -10,7 +10,7 @@ import * as Layer from "effect/Layer" * Represents a handle to the currently executing process. * * @category service - * @since 1.0.0 + * @since 0.6.0 */ export interface ProcessShape { readonly cwd: Effect.Effect @@ -20,13 +20,13 @@ export interface ProcessShape { /** * @category service - * @since 1.0.0 + * @since 0.6.0 */ export class Process extends Context.Tag("Process")() {} /** * @category layer - * @since 1.0.0 + * @since 0.6.0 */ export const layer = Layer.succeed( Process, diff --git a/src/bin.ts b/src/bin.ts index c033de8..035fe75 100644 --- a/src/bin.ts +++ b/src/bin.ts @@ -1,7 +1,7 @@ #!/usr/bin/env node /** - * @since 1.0.0 + * @since 0.6.0 */ import * as NodeContext from "@effect/platform-node/NodeContext" diff --git a/test/Markdown.test.ts b/test/Markdown.test.ts index 1a80803..0427eda 100644 --- a/test/Markdown.test.ts +++ b/test/Markdown.test.ts @@ -7,23 +7,23 @@ import * as assert from "node:assert/strict" import { describe, it } from "vitest" const testCases = { - class: Domain.createClass( - Domain.createNamedDoc( + class: new Domain.Class( + new Domain.NamedDoc( "A", Option.some("a class"), Option.some("1.0.0"), false, - [{ - body: `\`\`\`ts + [ + new Domain.Example(`\`\`\`ts example 1 -\`\`\`` - }], +\`\`\``) + ], Option.some("category") ), "declare class A { constructor() }", [ - Domain.createMethod( - Domain.createNamedDoc( + new Domain.Method( + new Domain.NamedDoc( "hasOwnProperty", Option.none(), Option.some("1.0.0"), @@ -35,8 +35,8 @@ example 1 ) ], [ - Domain.createMethod( - Domain.createNamedDoc( + new Domain.Method( + new Domain.NamedDoc( "staticTest", Option.none(), Option.some("1.0.0"), @@ -48,8 +48,8 @@ example 1 ) ], [ - Domain.createProperty( - Domain.createNamedDoc( + new Domain.Property( + new Domain.NamedDoc( "foo", Option.none(), Option.some("1.0.0"), @@ -61,8 +61,8 @@ example 1 ) ] ), - constant: Domain.createConstant( - Domain.createNamedDoc( + constant: new Domain.Constant( + new Domain.NamedDoc( "test", Option.some("the test"), Option.some("1.0.0"), @@ -72,8 +72,8 @@ example 1 ), "declare const test: string" ), - export: Domain.createExport( - Domain.createNamedDoc( + export: new Domain.Export( + new Domain.NamedDoc( "test", Option.none(), Option.some("1.0.0"), @@ -83,24 +83,24 @@ example 1 ), "export declare const test: typeof test" ), - function: Domain.createFunction( - Domain.createNamedDoc( + function: new Domain.Function( + new Domain.NamedDoc( "func", Option.some("a function"), Option.some("1.0.0"), true, - [{ - body: `\`\`\`ts + [ + new Domain.Example(`\`\`\`ts example 1 -\`\`\`` - }], +\`\`\``) + ], Option.none() ), ["declare const func: (test: string) => string"], [] ), - interface: Domain.createInterface( - Domain.createNamedDoc( + interface: new Domain.Interface( + new Domain.NamedDoc( "A", Option.none(), Option.some("1.0.0"), @@ -110,8 +110,8 @@ example 1 ), "export interface A extends Record {}" ), - typeAlias: Domain.createTypeAlias( - Domain.createNamedDoc( + typeAlias: new Domain.TypeAlias( + new Domain.NamedDoc( "A", Option.none(), Option.some("1.0.0"), @@ -121,8 +121,8 @@ example 1 ), "export type A = number" ), - namespace: Domain.createNamespace( - Domain.createNamedDoc( + namespace: new Domain.Namespace( + new Domain.NamedDoc( "A", Option.none(), Option.some("1.0.0"), @@ -132,8 +132,8 @@ example 1 ), [], [ - Domain.createTypeAlias( - Domain.createNamedDoc( + new Domain.TypeAlias( + new Domain.NamedDoc( "B", Option.none(), Option.some("1.0.1"), @@ -145,8 +145,8 @@ example 1 ) ], [ - Domain.createNamespace( - Domain.createNamedDoc( + new Domain.Namespace( + new Domain.NamedDoc( "C", Option.none(), Option.some("1.0.2"), @@ -156,8 +156,8 @@ example 1 ), [], [ - Domain.createTypeAlias( - Domain.createNamedDoc( + new Domain.TypeAlias( + new Domain.NamedDoc( "D", Option.none(), Option.some("1.0.3"), @@ -371,7 +371,7 @@ export type A = number }) it("printModule", async () => { - const doc = Domain.createNamedDoc( + const doc = new Domain.NamedDoc( "tests", Option.none(), Option.some("1.0.0"), @@ -381,7 +381,7 @@ export type A = number ) assert.strictEqual( await Effect.runPromise(Markdown.printModule( - Domain.createModule( + new Domain.Module( doc, ["src", "tests.ts"], [testCases.class], @@ -569,7 +569,7 @@ Since v1.0.0 ` ) - const empty = Domain.createModule(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) + const empty = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) assert.strictEqual( await Effect.runPromise(Markdown.printModule(empty, 1)), diff --git a/test/Parser.test.ts b/test/Parser.test.ts index f738b61..d3cee63 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -89,7 +89,7 @@ describe("Parser", () => { ]) }) - const documentableA = Domain.createNamedDoc( + const documentableA = new Domain.NamedDoc( "A", Option.none(), Option.some("1.0.0"), @@ -108,7 +108,7 @@ describe("Parser", () => { `, Parser.parseNamespaces, [ - Domain.createNamespace(documentableA, [], [], []) + new Domain.Namespace(documentableA, [], [], []) ] ) }) @@ -125,7 +125,7 @@ describe("Parser", () => { } `, Parser.parseNamespaces, - [Domain.createNamespace(documentableA, [], [], [])] + [new Domain.Namespace(documentableA, [], [], [])] ) }) @@ -145,7 +145,7 @@ describe("Parser", () => { }) it("should parse an interface", () => { - const documentableB = Domain.createNamedDoc( + const documentableB = new Domain.NamedDoc( "B", Option.none(), Option.some("1.0.1"), @@ -169,17 +169,21 @@ describe("Parser", () => { } `, Parser.parseNamespaces, - [Domain.createNamespace( - documentableA, - [Domain.createInterface( - documentableB, - `export interface B { + [ + new Domain.Namespace( + documentableA, + [ + new Domain.Interface( + documentableB, + `export interface B { readonly d: boolean }` - )], - [], - [] - )] + ) + ], + [], + [] + ) + ] ) }) }) @@ -196,7 +200,7 @@ describe("Parser", () => { } `, Parser.parseNamespaces, - [Domain.createNamespace(documentableA, [], [], [])] + [new Domain.Namespace(documentableA, [], [], [])] ) }) @@ -216,7 +220,7 @@ describe("Parser", () => { }) it("should parse a type alias", () => { - const documentableB = Domain.createNamedDoc( + const documentableB = new Domain.NamedDoc( "B", Option.none(), Option.some("1.0.1"), @@ -238,9 +242,11 @@ describe("Parser", () => { } `, Parser.parseNamespaces, - [Domain.createNamespace(documentableA, [], [ - Domain.createTypeAlias(documentableB, "export type B = string") - ], [])] + [ + new Domain.Namespace(documentableA, [], [ + new Domain.TypeAlias(documentableB, "export type B = string") + ], []) + ] ) }) }) @@ -257,7 +263,7 @@ describe("Parser", () => { } `, Parser.parseNamespaces, - [Domain.createNamespace(documentableA, [], [], [])] + [new Domain.Namespace(documentableA, [], [], [])] ) }) @@ -277,7 +283,7 @@ describe("Parser", () => { }) it("should parse a namespace", () => { - const documentableB = Domain.createNamedDoc( + const documentableB = new Domain.NamedDoc( "B", Option.none(), Option.some("1.0.1"), @@ -285,7 +291,7 @@ describe("Parser", () => { [], Option.none() ) - const documentableC = Domain.createNamedDoc( + const documentableC = new Domain.NamedDoc( "C", Option.none(), Option.some("1.0.2"), @@ -312,11 +318,13 @@ describe("Parser", () => { } `, Parser.parseNamespaces, - [Domain.createNamespace(documentableA, [], [], [ - Domain.createNamespace(documentableB, [], [ - Domain.createTypeAlias(documentableC, "export type C = string") - ], []) - ])] + [ + new Domain.Namespace(documentableA, [], [], [ + new Domain.Namespace(documentableB, [], [ + new Domain.TypeAlias(documentableC, "export type C = string") + ], []) + ]) + ] ) }) }) @@ -341,16 +349,17 @@ describe("Parser", () => { export interface A {}`, Parser.parseInterfaces, [ - { - _tag: "Interface", - deprecated: true, - description: Option.some("a description..."), - name: "A", - signature: "export interface A {}", - since: Option.some("1.0.0"), - examples: [], - category: Option.none() - } + new Domain.Interface( + new Domain.NamedDoc( + "A", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [], + Option.none() + ), + "export interface A {}" + ) ] ) }) @@ -369,26 +378,28 @@ describe("Parser", () => { `, Parser.parseInterfaces, [ - { - _tag: "Interface", - name: "A", - description: Option.none(), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - examples: [], - signature: "export interface A {}" - }, - { - _tag: "Interface", - name: "B", - description: Option.none(), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - examples: [], - signature: "export interface B {}" - } + new Domain.Interface( + new Domain.NamedDoc( + "A", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export interface A {}" + ), + new Domain.Interface( + new Domain.NamedDoc( + "B", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export interface B {}" + ) ] ) }) @@ -484,19 +495,20 @@ describe("Parser", () => { export const toNullable = (ma: A | null): A | null => ma`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: false, - description: Option.none(), - name: "toNullable", - signatures: [ + new Domain.Function( + new Domain.NamedDoc( + "toNullable", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + [ "export declare const toNullable: (ma: A | null) => A | null" ], - since: Option.some("1.0.0"), - examples: [], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -515,22 +527,23 @@ describe("Parser", () => { export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: true, - description: Option.some("a description..."), - name: "f", - signatures: [ + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [ + new Domain.Example("assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 })"), + new Domain.Example("assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })") + ], + Option.none() + ), + [ "export declare const f: (a: number, b: number) => { [key: string]: number; }" ], - since: Option.some("1.0.0"), - examples: [ - { body: "assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 })" }, - { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } - ], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -551,26 +564,25 @@ describe("Parser", () => { export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: true, - description: Option.some("a description..."), - name: "f", - signatures: [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - since: Option.some("1.0.0"), - examples: [ - { - body: `\`\`\`ts + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [ + new Domain.Example(`\`\`\`ts assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) -\`\`\`` - }, - { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } +\`\`\``), + new Domain.Example("assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })") + ], + Option.none() + ), + [ + "export declare const f: (a: number, b: number) => { [key: string]: number; }" ], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -591,27 +603,26 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: true, - description: Option.some("a description..."), - name: "f", - signatures: [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - since: Option.some("1.0.0"), - examples: [ - { - body: `\`\`\`ts + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [ + new Domain.Example(`\`\`\`ts assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) -\`\`\`` - } +\`\`\``) + ], + Option.none() + ), + [ + "export declare const f: (a: number, b: number) => { [key: string]: number; }" ], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -632,26 +643,25 @@ assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: true, - description: Option.some("a description..."), - name: "f", - signatures: [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - since: Option.some("1.0.0"), - examples: [ - { - body: `~~~ts + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [ + new Domain.Example(`~~~ts assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) -~~~` - }, - { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } +~~~`), + new Domain.Example("assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })") + ], + Option.none() + ), + [ + "export declare const f: (a: number, b: number) => { [key: string]: number; }" ], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -672,27 +682,26 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: true, - description: Option.some("a description..."), - name: "f", - signatures: [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - since: Option.some("1.0.0"), - examples: [ - { - body: `~~~ts + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [ + new Domain.Example(`~~~ts assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) -~~~` - } +~~~`) + ], + Option.none() + ), + [ + "export declare const f: (a: number, b: number) => { [key: string]: number; }" ], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -713,26 +722,25 @@ assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: true, - description: Option.some("a description..."), - name: "f", - signatures: [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - since: Option.some("1.0.0"), - examples: [ - { - body: `\`\`\`ts twoslash + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [ + new Domain.Example(`\`\`\`ts twoslash assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) -\`\`\`` - }, - { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } +\`\`\``), + new Domain.Example(`assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })`) + ], + Option.none() + ), + [ + "export declare const f: (a: number, b: number) => { [key: string]: number; }" ], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -753,26 +761,25 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: true, - description: Option.some("a description..."), - name: "f", - signatures: [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - since: Option.some("1.0.0"), - examples: [ - { - body: `~~~ts twoslash + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [ + new Domain.Example(`~~~ts twoslash assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) -~~~` - }, - { body: "assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })" } +~~~`), + new Domain.Example(`assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })`) + ], + Option.none() + ), + [ + "export declare const f: (a: number, b: number) => { [key: string]: number; }" ], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -785,19 +792,20 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export function f(a: number, b: number): { [key: string]: number } { return { a, b } }`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: false, - description: Option.none(), - name: "f", - signatures: [ + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + [ "export declare function f(a: number, b: number): { [key: string]: number }" ], - since: Option.some("1.0.0"), - examples: [], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -812,19 +820,20 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export function f(a: number, b: number): { [key: string]: number } { return { a, b } }`, Parser.parseFunctions, [ - { - _tag: "Function", - deprecated: true, - description: Option.some("a description..."), - name: "f", - signatures: [ + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [], + Option.none() + ), + [ "export declare function f(a: number, b: number): { [key: string]: number }" ], - since: Option.some("1.0.0"), - examples: [], - category: Option.none(), - throws: [] - } + [] + ) ] ) }) @@ -841,20 +850,21 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export function f(a: any, b: any): { [key: string]: number } { return { a, b } }`, Parser.parseFunctions, [ - { - _tag: "Function", - name: "f", - description: Option.some("a description..."), - since: Option.some("1.0.0"), - deprecated: true, - category: Option.none(), - examples: [], - signatures: [ + new Domain.Function( + new Domain.NamedDoc( + "f", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [], + Option.none() + ), + [ "export declare function f(a: Int, b: Int): { [key: string]: number }", "export declare function f(a: number, b: number): { [key: string]: number }" ], - throws: [] - } + [] + ) ] ) }) @@ -871,16 +881,17 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export type Option = None | Some`, Parser.parseTypeAliases, [ - { - _tag: "TypeAlias", - name: "Option", - description: Option.some("a description..."), - since: Option.some("1.0.0"), - deprecated: true, - category: Option.none(), - signature: "export type Option = None | Some", - examples: [] - } + new Domain.TypeAlias( + new Domain.NamedDoc( + "Option", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [], + Option.none() + ), + "export type Option = None | Some" + ) ] ) }) @@ -897,16 +908,17 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export const s: string = ''`, Parser.parseConstants, [ - { - _tag: "Constant", - name: "s", - description: Option.some("a description..."), - since: Option.some("1.0.0"), - deprecated: true, - category: Option.none(), - signature: "export declare const s: string", - examples: [] - } + new Domain.Constant( + new Domain.NamedDoc( + "s", + Option.some("a description..."), + Option.some("1.0.0"), + true, + [], + Option.none() + ), + "export declare const s: string" + ) ] ) }) @@ -919,16 +931,17 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export const left: (l: E) => string = T.left`, Parser.parseConstants, [ - { - _tag: "Constant", - name: "left", - description: Option.none(), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - signature: "export declare const left: (l: E) => string", - examples: [] - } + new Domain.Constant( + new Domain.NamedDoc( + "left", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare const left: (l: E) => string" + ) ] ) }) @@ -943,16 +956,17 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export const empty = new A()`, Parser.parseConstants, [ - { - _tag: "Constant", - name: "empty", - description: Option.none(), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - signature: "export declare const empty: A", - examples: [] - } + new Domain.Constant( + new Domain.NamedDoc( + "empty", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare const empty: A" + ) ] ) }) @@ -971,16 +985,17 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }`, Parser.parseConstants, [ - { - _tag: "Constant", - deprecated: false, - description: Option.none(), - name: "taskSeq", - signature: "export declare const taskSeq: { a: number; }", - since: Option.some("1.0.0"), - examples: [], - category: Option.none() - } + new Domain.Constant( + new Domain.NamedDoc( + "taskSeq", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare const taskSeq: { a: number; }" + ) ] ) }) @@ -1045,19 +1060,20 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }`, Parser.parseClasses, [ - { - _tag: "Class", - name: "MyClass", - description: Option.none(), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - examples: [], - signature: "export declare class MyClass", - methods: [], - staticMethods: [], - properties: [] - } + new Domain.Class( + new Domain.NamedDoc( + "MyClass", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare class MyClass", + [], + [], + [] + ) ] ) }) @@ -1071,19 +1087,20 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) export class C { constructor() {} }`, Parser.parseClasses, [ - { - _tag: "Class", - name: "C", - description: Option.some("description"), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - examples: [], - signature: "export declare class C { constructor() }", - methods: [], - staticMethods: [], - properties: [] - } + new Domain.Class( + new Domain.NamedDoc( + "C", + Option.some("description"), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare class C { constructor() }", + [], + [], + [] + ) ] ) }) @@ -1125,29 +1142,32 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }`, Parser.parseClasses, [ - { - _tag: "Class", - name: "C", - description: Option.some("description"), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - examples: [], - signature: "export declare class C", - methods: [], - staticMethods: [], - properties: [ - { - name: "a", - description: Option.none(), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - examples: [], - signature: "a: string" - } + new Domain.Class( + new Domain.NamedDoc( + "C", + Option.some("description"), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare class C", + [], + [], + [ + new Domain.Property( + new Domain.NamedDoc( + "a", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "a: string" + ) ] - } + ) ] ) }) @@ -1185,51 +1205,58 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }`, Parser.parseClasses, [ - { - _tag: "Class", - name: "Test", - description: Option.some("a class description..."), - since: Option.some("1.0.0"), - deprecated: true, - category: Option.none(), - examples: [], - signature: "export declare class Test { constructor(readonly value: string) }", - methods: [ - { - name: "g", - description: Option.some("a method description..."), - since: Option.some("1.1.0"), - deprecated: true, - category: Option.none(), - examples: [], - signatures: [ + new Domain.Class( + new Domain.NamedDoc( + "Test", + Option.some("a class description..."), + Option.some("1.0.0"), + true, + [], + Option.none() + ), + "export declare class Test { constructor(readonly value: string) }", + [ + new Domain.Method( + new Domain.NamedDoc( + "g", + Option.some("a method description..."), + Option.some("1.1.0"), + true, + [], + Option.none() + ), + [ "g(a: number, b: number): { [key: string]: number }" ] - } + ) ], - staticMethods: [ - { - name: "f", - description: Option.some("a static method description..."), - since: Option.some("1.1.0"), - deprecated: true, - category: Option.none(), - examples: [], - signatures: ["static f(): void"] - } + [ + new Domain.Method( + new Domain.NamedDoc( + "f", + Option.some("a static method description..."), + Option.some("1.1.0"), + true, + [], + Option.none() + ), + ["static f(): void"] + ) ], - properties: [ - { - name: "a", - description: Option.some("a property..."), - since: Option.some("1.1.0"), - deprecated: true, - category: Option.none(), - signature: "readonly a: string", - examples: [] - } + [ + new Domain.Property( + new Domain.NamedDoc( + "a", + Option.some("a property..."), + Option.some("1.1.0"), + true, + [], + Option.none() + ), + "readonly a: string" + ) ] - } + ) ] ) }) @@ -1264,45 +1291,44 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }`, Parser.parseClasses, [ - { - _tag: "Class", - name: "Test", - description: Option.some("a class description..."), - since: Option.some("1.0.0"), - deprecated: true, - category: Option.none(), - examples: [], - signature: "export declare class Test { constructor(readonly value: A) }", - methods: [ - { - name: "map", - description: Option.some("a method description..."), - since: Option.some("1.1.0"), - deprecated: true, - category: Option.none(), - examples: [], - signatures: [ - "map(f: (a: number) => number): Test", - "map(f: (a: string) => string): Test" - ] - } + new Domain.Class( + new Domain.NamedDoc( + "Test", + Option.some("a class description..."), + Option.some("1.0.0"), + true, + [], + Option.none() + ), + "export declare class Test { constructor(readonly value: A) }", + [ + new Domain.Method( + new Domain.NamedDoc( + "map", + Option.some("a method description..."), + Option.some("1.1.0"), + true, + [], + Option.none() + ), + ["map(f: (a: number) => number): Test", "map(f: (a: string) => string): Test"] + ) ], - staticMethods: [ - { - name: "f", - description: Option.some("a static method description..."), - since: Option.some("1.1.0"), - deprecated: true, - category: Option.none(), - examples: [], - signatures: [ - "static f(x: number): number", - "static f(x: string): string" - ] - } + [ + new Domain.Method( + new Domain.NamedDoc( + "f", + Option.some("a static method description..."), + Option.some("1.1.0"), + true, + [], + Option.none() + ), + ["static f(x: number): number", "static f(x: string): string"] + ) ], - properties: [] - } + [] + ) ] ) }) @@ -1327,19 +1353,20 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }`, Parser.parseClasses, [ - { - _tag: "Class", - name: "Test", - description: Option.some("a class description..."), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - examples: [], - signature: "export declare class Test", - methods: [], - staticMethods: [], - properties: [] - } + new Domain.Class( + new Domain.NamedDoc( + "Test", + Option.some("a class description..."), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare class Test", + [], + [], + [] + ) ] ) }) @@ -1358,16 +1385,17 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) */ export const a: number = 1`, Parser.parseModuleDocumentation, - { - name: "test", - description: Option.some( + new Domain.NamedDoc( + "test", + Option.some( "Manages the configuration settings for the widget" ), - since: Option.some("1.0.0"), - deprecated: true, - category: Option.none(), - examples: [] - } + Option.some("1.0.0"), + true, + [], + Option.none() + ), + { enforceVersion: false } ) }) @@ -1383,14 +1411,14 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) expectSuccess( "export const a: number = 1", Parser.parseModuleDocumentation, - { - name: "test", - description: Option.none(), - since: Option.none(), - deprecated: false, - category: Option.none(), - examples: [] - }, + new Domain.NamedDoc( + "test", + Option.none(), + Option.none(), + false, + [], + Option.none() + ), { enforceVersion: false } ) }) @@ -1412,16 +1440,17 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }`, Parser.parseExports, [ - { - _tag: "Export", - name: "b", - description: Option.none(), - deprecated: false, - since: Option.some("1.0.0"), - category: Option.none(), - examples: [], - signature: "export declare const b: 1" - } + new Domain.Export( + new Domain.NamedDoc( + "b", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare const b: 1" + ) ] ) }) @@ -1442,26 +1471,28 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) }`, Parser.parseExports, [ - { - _tag: "Export", - name: "a", - description: Option.some("description_of_a"), - since: Option.some("1.0.0"), - deprecated: false, - category: Option.none(), - signature: "export declare const a: any", - examples: [] - }, - { - _tag: "Export", - name: "b", - description: Option.some("description_of_b"), - since: Option.some("2.0.0"), - deprecated: false, - category: Option.none(), - signature: "export declare const b: any", - examples: [] - } + new Domain.Export( + new Domain.NamedDoc( + "a", + Option.some("description_of_a"), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare const a: any" + ), + new Domain.Export( + new Domain.NamedDoc( + "b", + Option.some("description_of_b"), + Option.some("2.0.0"), + false, + [], + Option.none() + ), + "export declare const b: any" + ) ] ) }) @@ -1496,16 +1527,17 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) assert.deepStrictEqual( actual, Exit.succeed([ - { - _tag: "Export", - name: "b", - description: Option.none(), - since: Option.some("1.0.0"), - deprecated: false, - signature: "export declare const b: 1", - category: Option.none(), - examples: [] - } + new Domain.Export( + new Domain.NamedDoc( + "b", + Option.none(), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + "export declare const b: 1" + ) ]) ) }) @@ -1535,16 +1567,17 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) assert.deepStrictEqual( actual, Exit.succeed([ - { - _tag: "Export", - name: "From './example'", - description: Option.some("Re-exports all named exports from the './example' module."), - since: Option.some("1.0.0"), - deprecated: false, - signature: "export * from './example'", - category: Option.some("exports"), - examples: [] - } + new Domain.Export( + new Domain.NamedDoc( + "From './example'", + Option.some("Re-exports all named exports from the './example' module."), + Option.some("1.0.0"), + false, + [], + Option.some("exports") + ), + "export * from './example'" + ) ]) ) }) @@ -1574,18 +1607,19 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) assert.deepStrictEqual( actual, Exit.succeed([ - { - _tag: "Export", - name: "From './example'", - description: Option.some( - "Re-exports all named exports from the './example' module as `example`." + new Domain.Export( + new Domain.NamedDoc( + "From './example'", + Option.some( + "Re-exports all named exports from the './example' module as `example`." + ), + Option.some("1.0.0"), + false, + [], + Option.some("exports") ), - since: Option.some("1.0.0"), - deprecated: false, - signature: "export * as example from './example'", - category: Option.some("exports"), - examples: [] - } + "export * as example from './example'" + ) ]) ) }) @@ -1620,33 +1654,36 @@ import * as assert from 'assert' */ export const foo = 'foo'`, Parser.parseModule, - { - name: "test", - description: Option.some("This is the assert module."), - since: Option.some("1.0.0"), - deprecated: false, - examples: [], - category: Option.none(), - path: ["test"], - classes: [], - interfaces: [], - functions: [], - typeAliases: [], - constants: [ - { - _tag: "Constant", - name: "foo", - description: Option.some("This is the foo export."), - since: Option.some("1.0.0"), - deprecated: false, - examples: [{ body: `import { foo } from 'test'\n\nconsole.log(foo)` }], - category: Option.some("foo"), - signature: "export declare const foo: \"foo\"" - } + new Domain.Module( + new Domain.NamedDoc( + "test", + Option.some("This is the assert module."), + Option.some("1.0.0"), + false, + [], + Option.none() + ), + ["test"], + [], + [], + [], + [], + [ + new Domain.Constant( + new Domain.NamedDoc( + "foo", + Option.some("This is the foo export."), + Option.some("1.0.0"), + false, + [new Domain.Example(`import { foo } from 'test'\n\nconsole.log(foo)`)], + Option.some("foo") + ), + "export declare const foo: \"foo\"" + ) ], - exports: [], - namespaces: [] - }, + [], + [] + ), { enforceExamples: true } ) }) @@ -1679,13 +1716,17 @@ export const foo = 'foo'`, | * @since 1.0.0 | */` ) - expectSuccess("", Parser.getDoc("name", text), { - description: Option.some("description"), - since: Option.some("1.0.0"), - category: Option.some("instances"), - deprecated: false, - examples: [] - }) + expectSuccess( + "", + Parser.getDoc("name", text), + new Domain.Doc( + Option.some("description"), + Option.some("1.0.0"), + false, + [], + Option.some("instances") + ) + ) }) it("should fail if an empty comment tag is provided", () => { @@ -1765,13 +1806,13 @@ export const foo = 'foo'`, expectSuccess( "", Parser.getDoc("name", text), - { - description: Option.some("description"), - since: Option.none(), - category: Option.some("instances"), - deprecated: false, - examples: [] - }, + new Domain.Doc( + Option.some("description"), + Option.none(), + false, + [], + Option.some("instances") + ), { enforceVersion: false } ) }) From d184b93e21b78dd4558da158383395ff4009942c Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 14:29:43 +0100 Subject: [PATCH 20/56] Remove File module and integrate File class into Domain module --- .changeset/silly-insects-draw.md | 2 ++ docs/modules/Domain.ts.md | 17 +++++++++++ docs/modules/File.ts.md | 52 -------------------------------- docs/modules/Markdown.ts.md | 2 +- docs/modules/Parser.ts.md | 4 +-- docs/modules/Process.ts.md | 2 +- docs/modules/index.ts.md | 15 +-------- src/Core.ts | 35 +++++++++++---------- src/Domain.ts | 14 +++++++++ src/File.ts | 26 ---------------- src/Parser.ts | 7 ++--- src/index.ts | 5 --- test/Parser.test.ts | 3 +- 13 files changed, 59 insertions(+), 125 deletions(-) delete mode 100644 docs/modules/File.ts.md delete mode 100644 src/File.ts diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index b09cdea..42985ae 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -10,3 +10,5 @@ - runExamples is not false by default - Extract examples from descriptions (disable with `skip-type-checking` metadata on fenced code blocks) - Add support for `@throws` tag in documentation generation +- Refactor Domain module to use class-based implementation +- Remove File module and integrate File class into Domain module diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 13db50b..136acee 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -21,6 +21,7 @@ Since v0.6.0 - [Example (class)](#example-class) - [Export (class)](#export-class) - [\_tag (property)](#_tag-property-2) + - [File (class)](#file-class) - [Function (class)](#function-class) - [\_tag (property)](#_tag-property-3) - [Interface (class)](#interface-class) @@ -148,6 +149,22 @@ readonly _tag: "Export" Since v0.6.0 +## File (class) + +Represents a file which can be optionally overwriteable. + +**Signature** + +```ts +export declare class File { constructor( + readonly path: string, + readonly content: string, + readonly isOverwriteable: boolean = false + ) } +``` + +Since v0.6.0 + ## Function (class) **Signature** diff --git a/docs/modules/File.ts.md b/docs/modules/File.ts.md deleted file mode 100644 index efddb3f..0000000 --- a/docs/modules/File.ts.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: File.ts -nav_order: 6 -parent: Modules ---- - -## File overview - -Since v0.6.0 - ---- - -

Table of contents

- -- [constructors](#constructors) - - [createFile](#createfile) -- [model](#model) - - [File (interface)](#file-interface) - ---- - -# constructors - -## createFile - -By default files are readonly (`isOverwriteable = false`). - -**Signature** - -```ts -export declare const createFile: (path: string, content: string, isOverwriteable?: boolean) => File -``` - -Since v0.6.0 - -# model - -## File (interface) - -Represents a file which can be optionally overwriteable. - -**Signature** - -```ts -export interface File { - readonly path: string - readonly content: string - readonly isOverwriteable: boolean -} -``` - -Since v0.6.0 diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index 764347d..83e38b6 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -1,6 +1,6 @@ --- title: Markdown.ts -nav_order: 8 +nav_order: 7 parent: Modules --- diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index bbbd587..122de32 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -1,6 +1,6 @@ --- title: Parser.ts -nav_order: 9 +nav_order: 8 parent: Modules --- @@ -71,7 +71,7 @@ Since v0.6.0 ```ts export declare const parseFiles: ( - files: ReadonlyArray + files: ReadonlyArray ) => Effect.Effect< Domain.Module[], [string[], ...string[][]], diff --git a/docs/modules/Process.ts.md b/docs/modules/Process.ts.md index 56386d1..df3d2f5 100644 --- a/docs/modules/Process.ts.md +++ b/docs/modules/Process.ts.md @@ -1,6 +1,6 @@ --- title: Process.ts -nav_order: 10 +nav_order: 9 parent: Modules --- diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index c567c9f..6d8a3b3 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -1,6 +1,6 @@ --- title: index.ts -nav_order: 7 +nav_order: 6 parent: Modules --- @@ -17,7 +17,6 @@ Since v0.6.0 - [From "./Core.js"](#from-corejs) - [From "./Domain.js"](#from-domainjs) - [From "./Error.js"](#from-errorjs) - - [From "./File.js"](#from-filejs) - [From "./Markdown.js"](#from-markdownjs) - [From "./Parser.js"](#from-parserjs) - [From "./Process.js"](#from-processjs) @@ -74,18 +73,6 @@ export * as Error from "./Error.js" Since v0.6.0 -## From "./File.js" - -Re-exports all named exports from the "./File.js" module as `File`. - -**Signature** - -```ts -export * as File from "./File.js" -``` - -Since v0.6.0 - ## From "./Markdown.js" Re-exports all named exports from the "./Markdown.js" module as `Markdown`. diff --git a/src/Core.ts b/src/Core.ts index f1fca21..12ad14b 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -17,9 +17,8 @@ import * as Stream from "effect/Stream" import * as String from "effect/String" import * as Glob from "glob" import * as Configuration from "./Configuration.js" -import type * as Domain from "./Domain.js" +import * as Domain from "./Domain.js" import { DocgenError } from "./Error.js" -import * as File from "./File.js" import { printModule } from "./Markdown.js" import * as Parser from "./Parser.js" import * as Process from "./Process.js" @@ -58,14 +57,14 @@ const readSourceFiles = Effect.gen(function*() { return yield* Effect.forEach(paths, (path) => Effect.map( fs.readFileString(path), - (content) => File.createFile(path, content, false) + (content) => new Domain.File(path, content, false) ), { concurrency: "inherit" }) }) /** * Writes a file to the `config.outDir` directory, taking into account the configuration and existing files. */ -const writeFileToOutDir = (file: File.File) => +const writeFileToOutDir = (file: Domain.File) => Effect.gen(function*() { const config = yield* Configuration.Configuration const fs = yield* FileSystem.FileSystem @@ -92,10 +91,10 @@ const writeFileToOutDir = (file: File.File) => }) const writeFilesToOutDir = ( - files: ReadonlyArray + files: ReadonlyArray ) => Effect.forEach(files, writeFileToOutDir, { discard: true }) -const parseModules = (files: ReadonlyArray) => +const parseModules = (files: ReadonlyArray) => Parser.parseFiles(files).pipe( Effect.mapError((errors) => new DocgenError({ @@ -186,7 +185,7 @@ const getExampleFiles = (modules: ReadonlyArray) => return Array.flatMap(modules, (module) => { const prefix = module.path.join("-") - const getFiles = (exampleId: string) => (doc: Domain.NamedDoc): ReadonlyArray => { + const getFiles = (exampleId: string) => (doc: Domain.NamedDoc): ReadonlyArray => { const descriptionExamples = doc.description.pipe( Option.map(extractFencedCode), Option.getOrElse((): Array => []) @@ -195,7 +194,7 @@ const getExampleFiles = (modules: ReadonlyArray) => return Array.map( examples, (example, i) => { - return File.createFile( + return new Domain.File( path.join( config.outDir, "examples", @@ -276,13 +275,13 @@ const getExampleFiles = (modules: ReadonlyArray) => /** * Generates an entry point file for the given examples. */ -const getExamplesEntryPoint = (examples: ReadonlyArray) => +const getExamplesEntryPoint = (examples: ReadonlyArray) => Effect.gen(function*() { const config = yield* Configuration.Configuration const path = yield* Path.Path const content = examples.map((example) => `import './${path.basename(example.path, ".ts")}'`) .join("\n") - return File.createFile( + return new Domain.File( path.normalize(path.join(config.outDir, "examples", "index.ts")), `${content}\n`, true // make the file overwritable @@ -389,7 +388,7 @@ const runTsxOnExamples = Effect.gen(function*() { } }) -const writeExamplesToOutDir = (examples: ReadonlyArray) => +const writeExamplesToOutDir = (examples: ReadonlyArray) => Effect.gen(function*() { yield* Effect.logDebug("Writing examples...") const entryPoint = yield* getExamplesEntryPoint(examples) @@ -404,7 +403,7 @@ const createExamplesTsConfigJson = Effect.gen(function*() { const cwd = yield* process.cwd const path = yield* Path.Path yield* writeFileToOutDir( - File.createFile( + new Domain.File( path.join(cwd, config.outDir, "examples", "tsconfig.json"), JSON.stringify({ compilerOptions: config.examplesCompilerOptions }, null, 2), true // make the file overwritable @@ -426,7 +425,7 @@ const getMarkdownHomepage = Effect.gen(function*() { const process = yield* Process.Process const cwd = yield* process.cwd const path = yield* Path.Path - return File.createFile( + return new Domain.File( path.join(cwd, config.outDir, "index.md"), String.stripMargin( `|--- @@ -444,7 +443,7 @@ const getMarkdownIndex = Effect.gen(function*() { const process = yield* Process.Process const cwd = yield* process.cwd const path = yield* Path.Path - return File.createFile( + return new Domain.File( path.join(cwd, config.outDir, "modules", "index.md"), String.stripMargin( `|--- @@ -489,9 +488,9 @@ const getMarkdownConfigYML = Effect.gen(function*() { if (exists) { const content = yield* fs.readFileString(configPath) const resolved = yield* resolveConfigYML(content) - return File.createFile(configPath, resolved, true) + return new Domain.File(configPath, resolved, true) } else { - return File.createFile( + return new Domain.File( configPath, String.stripMargin( `|remote_theme: ${config.theme} @@ -525,10 +524,10 @@ const getModuleMarkdownFiles = (modules: ReadonlyArray) => Effect.gen(function*() { const outputPath = yield* getModuleMarkdownOutputPath(module) const content = yield* printModule(module, order + 1) - return File.createFile(outputPath, content, true) + return new Domain.File(outputPath, content, true) })) -const writeMarkdown = (files: ReadonlyArray) => +const writeMarkdown = (files: ReadonlyArray) => Effect.gen(function*() { const config = yield* Configuration.Configuration const path = yield* pipe(Path.Path, Effect.provide(NodePath.layerPosix)) diff --git a/src/Domain.ts b/src/Domain.ts index f9b4583..9cff59a 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -237,3 +237,17 @@ export const ByPath: Order.Order = Order.mapInput( String.Order, (module: Module) => module.path.join("/").toLowerCase() ) + +/** + * Represents a file which can be optionally overwriteable. + * + * @category model + * @since 0.6.0 + */ +export class File { + constructor( + readonly path: string, + readonly content: string, + readonly isOverwriteable: boolean = false + ) {} +} diff --git a/src/File.ts b/src/File.ts deleted file mode 100644 index c1dd62a..0000000 --- a/src/File.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @since 0.6.0 - */ - -import * as Data from "effect/Data" - -/** - * Represents a file which can be optionally overwriteable. - * - * @category model - * @since 0.6.0 - */ -export interface File { - readonly path: string - readonly content: string - readonly isOverwriteable: boolean -} - -/** - * By default files are readonly (`isOverwriteable = false`). - * - * @category constructors - * @since 0.6.0 - */ -export const createFile = (path: string, content: string, isOverwriteable = false): File => - Data.struct({ path, content, isOverwriteable }) diff --git a/src/Parser.ts b/src/Parser.ts index 0f57cad..3e49f1a 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -15,7 +15,6 @@ import * as String from "effect/String" import * as ast from "ts-morph" import * as Configuration from "./Configuration.js" import * as Domain from "./Domain.js" -import type * as File from "./File.js" import * as Process from "./Process.js" /** @internal */ @@ -886,7 +885,7 @@ export const parseModule = Effect.gen(function*() { * @internal */ export const parseFile = (project: ast.Project) => -(file: File.File): Effect.Effect< +(file: Domain.File): Effect.Effect< Domain.Module, Array, Configuration.Configuration | Path.Path @@ -905,7 +904,7 @@ export const parseFile = (project: ast.Project) => return Effect.fail([`Unable to locate file: ${file.path}`]) }) -const createProject = (files: ReadonlyArray) => +const createProject = (files: ReadonlyArray) => Effect.gen(function*() { const config = yield* Configuration.Configuration const process = yield* Process.Process @@ -937,7 +936,7 @@ const createProject = (files: ReadonlyArray) => * @category parsers * @since 0.6.0 */ -export const parseFiles = (files: ReadonlyArray) => +export const parseFiles = (files: ReadonlyArray) => createProject(files).pipe( Effect.flatMap((project) => pipe( diff --git a/src/index.ts b/src/index.ts index 4e1e28f..6fbe260 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,11 +22,6 @@ export * as Domain from "./Domain.js" */ export * as Error from "./Error.js" -/** - * @since 0.6.0 - */ -export * as File from "./File.js" - /** * @since 0.6.0 */ diff --git a/test/Parser.test.ts b/test/Parser.test.ts index d3cee63..4242c95 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -1,6 +1,5 @@ import * as Configuration from "@effect/docgen/Configuration" import * as Domain from "@effect/docgen/Domain" -import * as File from "@effect/docgen/File" import * as Parser from "@effect/docgen/Parser" import { Path } from "@effect/platform" import chalk from "chalk" @@ -1691,7 +1690,7 @@ export const foo = 'foo'`, describe("parseFile", () => { it("should not parse a non-existent file", async () => { - const file = File.createFile("non-existent.ts", "") + const file = new Domain.File("non-existent.ts", "") const project = new ast.Project({ useInMemoryFileSystem: true }) assert.deepStrictEqual( From d47a928fc14b598594dc3a0a79286b82f0644434 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 14:32:59 +0100 Subject: [PATCH 21/56] Move DocgenError from Error module to Domain module --- .changeset/silly-insects-draw.md | 1 + docs/modules/Domain.ts.md | 36 +++++++++++++++++++++ docs/modules/Error.ts.md | 55 -------------------------------- docs/modules/Markdown.ts.md | 2 +- docs/modules/Parser.ts.md | 2 +- docs/modules/Process.ts.md | 2 +- docs/modules/index.ts.md | 15 +-------- src/Configuration.ts | 2 +- src/Core.ts | 9 +++--- src/Domain.ts | 22 +++++++++++++ src/Error.ts | 26 --------------- src/index.ts | 5 --- test/Configuration.test.ts | 2 +- 13 files changed, 69 insertions(+), 110 deletions(-) delete mode 100644 docs/modules/Error.ts.md delete mode 100644 src/Error.ts diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index 42985ae..fc8eb9d 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -12,3 +12,4 @@ - Add support for `@throws` tag in documentation generation - Refactor Domain module to use class-based implementation - Remove File module and integrate File class into Domain module +- Move DocgenError from Error module to Domain module diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 136acee..60eaa12 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -18,6 +18,7 @@ Since v0.6.0 - [Constant (class)](#constant-class) - [\_tag (property)](#_tag-property-1) - [Doc (class)](#doc-class) + - [DocgenError (class)](#docgenerror-class) - [Example (class)](#example-class) - [Export (class)](#export-class) - [\_tag (property)](#_tag-property-2) @@ -36,6 +37,9 @@ Since v0.6.0 - [\_tag (property)](#_tag-property-6) - [sorting](#sorting) - [ByPath](#bypath) +- [symbol](#symbol) + - [DocgenErrorTypeId](#docgenerrortypeid) + - [DocgenErrorTypeId (type alias)](#docgenerrortypeid-type-alias) --- @@ -106,6 +110,16 @@ export declare class Doc { constructor( Since v0.6.0 +## DocgenError (class) + +**Signature** + +```ts +export declare class DocgenError +``` + +Since v0.6.0 + ## Example (class) **Signature** @@ -337,3 +351,25 @@ export declare const ByPath: Order.Order ``` Since v0.6.0 + +# symbol + +## DocgenErrorTypeId + +**Signature** + +```ts +export declare const DocgenErrorTypeId: typeof DocgenErrorTypeId +``` + +Since v0.6.0 + +## DocgenErrorTypeId (type alias) + +**Signature** + +```ts +export type DocgenErrorTypeId = typeof DocgenErrorTypeId +``` + +Since v0.6.0 diff --git a/docs/modules/Error.ts.md b/docs/modules/Error.ts.md deleted file mode 100644 index 0643c74..0000000 --- a/docs/modules/Error.ts.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Error.ts -nav_order: 5 -parent: Modules ---- - -## Error overview - -Since v0.6.0 - ---- - -

Table of contents

- -- [model](#model) - - [DocgenError (class)](#docgenerror-class) -- [symbol](#symbol) - - [DocgenErrorTypeId](#docgenerrortypeid) - - [DocgenErrorTypeId (type alias)](#docgenerrortypeid-type-alias) - ---- - -# model - -## DocgenError (class) - -**Signature** - -```ts -export declare class DocgenError -``` - -Since v0.6.0 - -# symbol - -## DocgenErrorTypeId - -**Signature** - -```ts -export declare const DocgenErrorTypeId: typeof DocgenErrorTypeId -``` - -Since v0.6.0 - -## DocgenErrorTypeId (type alias) - -**Signature** - -```ts -export type DocgenErrorTypeId = typeof DocgenErrorTypeId -``` - -Since v0.6.0 diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Markdown.ts.md index 83e38b6..566c1b1 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Markdown.ts.md @@ -1,6 +1,6 @@ --- title: Markdown.ts -nav_order: 7 +nav_order: 6 parent: Modules --- diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 122de32..0fcdca7 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -1,6 +1,6 @@ --- title: Parser.ts -nav_order: 8 +nav_order: 7 parent: Modules --- diff --git a/docs/modules/Process.ts.md b/docs/modules/Process.ts.md index df3d2f5..aff2d4b 100644 --- a/docs/modules/Process.ts.md +++ b/docs/modules/Process.ts.md @@ -1,6 +1,6 @@ --- title: Process.ts -nav_order: 9 +nav_order: 8 parent: Modules --- diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index 6d8a3b3..75b0ed5 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -1,6 +1,6 @@ --- title: index.ts -nav_order: 6 +nav_order: 5 parent: Modules --- @@ -16,7 +16,6 @@ Since v0.6.0 - [From "./Configuration.js"](#from-configurationjs) - [From "./Core.js"](#from-corejs) - [From "./Domain.js"](#from-domainjs) - - [From "./Error.js"](#from-errorjs) - [From "./Markdown.js"](#from-markdownjs) - [From "./Parser.js"](#from-parserjs) - [From "./Process.js"](#from-processjs) @@ -61,18 +60,6 @@ export * as Domain from "./Domain.js" Since v0.6.0 -## From "./Error.js" - -Re-exports all named exports from the "./Error.js" module as `Error`. - -**Signature** - -```ts -export * as Error from "./Error.js" -``` - -Since v0.6.0 - ## From "./Markdown.js" Re-exports all named exports from the "./Markdown.js" module as `Markdown`. diff --git a/src/Configuration.ts b/src/Configuration.ts index fa8770b..87f97e3 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -15,7 +15,7 @@ import * as Option from "effect/Option" import * as ParseResult from "effect/ParseResult" import * as Schema from "effect/Schema" import * as tsconfck from "tsconfck" -import { DocgenError } from "./Error.js" +import { DocgenError } from "./Domain.js" import * as Process from "./Process.js" const PACKAGE_JSON_FILE_NAME = "package.json" diff --git a/src/Core.ts b/src/Core.ts index 12ad14b..8923fc3 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -18,7 +18,6 @@ import * as String from "effect/String" import * as Glob from "glob" import * as Configuration from "./Configuration.js" import * as Domain from "./Domain.js" -import { DocgenError } from "./Error.js" import { printModule } from "./Markdown.js" import * as Parser from "./Parser.js" import * as Process from "./Process.js" @@ -35,7 +34,7 @@ const glob = (pattern: string, exclude: ReadonlyArray = []) => }) ).pipe( Effect.orDieWith(() => - new DocgenError({ + new Domain.DocgenError({ message: `[Core.glob] Unable to execute glob pattern '${pattern}' ` + `excluding files matching '${exclude}'` }) @@ -97,7 +96,7 @@ const writeFilesToOutDir = ( const parseModules = (files: ReadonlyArray) => Parser.parseFiles(files).pipe( Effect.mapError((errors) => - new DocgenError({ + new Domain.DocgenError({ message: "[Core.parseModules] The following error(s) occurred while " + `parsing the TypeScript source files:\n${errors.map((errors) => errors.join("\n")).join("\n")}` }) @@ -337,7 +336,7 @@ const runTscOnExamples = Effect.gen(function*() { ) if (exitCode !== 0) { - yield* new DocgenError({ + yield* new Domain.DocgenError({ message: `Something went wrong while running tsc on examples:\n\n${stdout.join("\n")}` }) } @@ -381,7 +380,7 @@ const runTsxOnExamples = Effect.gen(function*() { if (exitCode !== 0) { yield* Effect.fail( - new DocgenError({ + new Domain.DocgenError({ message: `Something went wrong while running tsx on examples:\n\n${stdout.join("\n")}` }) ) diff --git a/src/Domain.ts b/src/Domain.ts index 9cff59a..0466df2 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -2,6 +2,7 @@ * @since 0.6.0 */ +import * as Data from "effect/Data" import type * as Option from "effect/Option" import * as Order from "effect/Order" import * as String from "effect/String" @@ -251,3 +252,24 @@ export class File { readonly isOverwriteable: boolean = false ) {} } + +/** + * @category symbol + * @since 0.6.0 + */ +export const DocgenErrorTypeId = Symbol.for("@effect/docgen/DocgenError") + +/** + * @category symbol + * @since 0.6.0 + */ +export type DocgenErrorTypeId = typeof DocgenErrorTypeId + +/** + * @category model + * @since 0.6.0 + */ +export class DocgenError extends Data.TaggedError("DocgenError")<{ + readonly message: string +}> { +} diff --git a/src/Error.ts b/src/Error.ts deleted file mode 100644 index c0cc6f1..0000000 --- a/src/Error.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @since 0.6.0 - */ - -import * as Data from "effect/Data" - -/** - * @category symbol - * @since 0.6.0 - */ -export const DocgenErrorTypeId = Symbol.for("@effect/docgen/DocgenError") - -/** - * @category symbol - * @since 0.6.0 - */ -export type DocgenErrorTypeId = typeof DocgenErrorTypeId - -/** - * @category model - * @since 0.6.0 - */ -export class DocgenError extends Data.TaggedError("DocgenError")<{ - readonly message: string -}> { -} diff --git a/src/index.ts b/src/index.ts index 6fbe260..832b378 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,11 +17,6 @@ export * as Core from "./Core.js" */ export * as Domain from "./Domain.js" -/** - * @since 0.6.0 - */ -export * as Error from "./Error.js" - /** * @since 0.6.0 */ diff --git a/test/Configuration.test.ts b/test/Configuration.test.ts index 16d7c7a..7f6cdd7 100644 --- a/test/Configuration.test.ts +++ b/test/Configuration.test.ts @@ -1,7 +1,7 @@ import * as Command from "@effect/cli/Command" import * as CLI from "@effect/docgen/CLI" import * as Configuration from "@effect/docgen/Configuration" -import { DocgenError } from "@effect/docgen/Error" +import { DocgenError } from "@effect/docgen/Domain" import * as Process from "@effect/docgen/Process" import * as NodeCommandExecutor from "@effect/platform-node/NodeCommandExecutor" import * as NodeTerminal from "@effect/platform-node/NodeTerminal" From aabd16c5aa5dbc614a75b90db732e4880d77eb9c Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 15:07:19 +0100 Subject: [PATCH 22/56] Integrate Process service into Domain module --- .changeset/silly-insects-draw.md | 1 + docs/modules/Domain.ts.md | 16 +++++++++ docs/modules/Parser.ts.md | 6 +--- docs/modules/Process.ts.md | 61 -------------------------------- docs/modules/index.ts.md | 13 ------- scripts/copy-package-json.ts | 20 +++++------ scripts/version.mjs | 9 +++-- src/Configuration.ts | 12 +++---- src/Core.ts | 15 ++++---- src/Domain.ts | 15 ++++++++ src/Parser.ts | 3 +- src/Process.ts | 38 -------------------- src/bin.ts | 4 +-- src/index.ts | 5 --- test/Configuration.test.ts | 7 ++-- 15 files changed, 66 insertions(+), 159 deletions(-) delete mode 100644 docs/modules/Process.ts.md delete mode 100644 src/Process.ts diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index fc8eb9d..c088b73 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -13,3 +13,4 @@ - Refactor Domain module to use class-based implementation - Remove File module and integrate File class into Domain module - Move DocgenError from Error module to Domain module +- Integrate Process service into Domain module diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 60eaa12..1a6eec3 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -35,6 +35,8 @@ Since v0.6.0 - [Property (class)](#property-class) - [TypeAlias (class)](#typealias-class) - [\_tag (property)](#_tag-property-6) +- [service](#service) + - [Process (class)](#process-class) - [sorting](#sorting) - [ByPath](#bypath) - [symbol](#symbol) @@ -337,6 +339,20 @@ readonly _tag: "TypeAlias" Since v0.6.0 +# service + +## Process (class) + +Represents a handle to the currently executing process. + +**Signature** + +```ts +export declare class Process +``` + +Since v0.6.0 + # sorting ## ByPath diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 0fcdca7..3dceb21 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -72,11 +72,7 @@ Since v0.6.0 ```ts export declare const parseFiles: ( files: ReadonlyArray -) => Effect.Effect< - Domain.Module[], - [string[], ...string[][]], - Process.Process | Configuration.Configuration | Path.Path -> +) => Effect.Effect ``` Since v0.6.0 diff --git a/docs/modules/Process.ts.md b/docs/modules/Process.ts.md deleted file mode 100644 index aff2d4b..0000000 --- a/docs/modules/Process.ts.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Process.ts -nav_order: 8 -parent: Modules ---- - -## Process overview - -Since v0.6.0 - ---- - -

Table of contents

- -- [layer](#layer) - - [layer](#layer-1) -- [service](#service) - - [Process (class)](#process-class) - - [ProcessShape (interface)](#processshape-interface) - ---- - -# layer - -## layer - -**Signature** - -```ts -export declare const layer: Layer.Layer -``` - -Since v0.6.0 - -# service - -## Process (class) - -**Signature** - -```ts -export declare class Process -``` - -Since v0.6.0 - -## ProcessShape (interface) - -Represents a handle to the currently executing process. - -**Signature** - -```ts -export interface ProcessShape { - readonly cwd: Effect.Effect - readonly platform: Effect.Effect - readonly argv: Effect.Effect> -} -``` - -Since v0.6.0 diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index 75b0ed5..8156e10 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -18,7 +18,6 @@ Since v0.6.0 - [From "./Domain.js"](#from-domainjs) - [From "./Markdown.js"](#from-markdownjs) - [From "./Parser.js"](#from-parserjs) - - [From "./Process.js"](#from-processjs) --- @@ -83,15 +82,3 @@ export * as Parser from "./Parser.js" ``` Since v0.6.0 - -## From "./Process.js" - -Re-exports all named exports from the "./Process.js" module as `Process`. - -**Signature** - -```ts -export * as Process from "./Process.js" -``` - -Since v0.6.0 diff --git a/scripts/copy-package-json.ts b/scripts/copy-package-json.ts index 3ddfa90..3549b4c 100644 --- a/scripts/copy-package-json.ts +++ b/scripts/copy-package-json.ts @@ -1,14 +1,14 @@ import { FileSystem, Path } from "@effect/platform" import { NodeFileSystem, NodePath } from "@effect/platform-node" -import { Effect, Layer } from "effect" +import { Effect, Layer, pipe } from "effect" -const program = Effect.gen(function*(_) { - const fs = yield* _(FileSystem.FileSystem) - const path = yield* _(Path.Path) - yield* _(Effect.log(`[Build] Copying schema.json ...`)) - yield* _(fs.copyFile("schema.json", path.join("dist", "schema.json"))) - yield* _(Effect.log(`[Build] Copying package.json ...`)) - const json: any = yield* _(fs.readFileString("package.json"), Effect.map(JSON.parse)) +const program = Effect.gen(function*() { + const fs = yield* FileSystem.FileSystem + const path = yield* Path.Path + yield* Effect.log(`[Build] Copying schema.json ...`) + yield* fs.copyFile("schema.json", path.join("dist", "schema.json")) + yield* Effect.log(`[Build] Copying package.json ...`) + const json: any = yield* pipe(fs.readFileString("package.json"), Effect.map(JSON.parse)) const pkg = { name: json.name, version: json.version, @@ -27,8 +27,8 @@ const program = Effect.gen(function*(_) { tags: json.tags, keywords: json.keywords } - yield* _(fs.writeFileString(path.join("dist", "package.json"), JSON.stringify(pkg, null, 2))) - yield* _(Effect.log("[Build] Build completed.")) + yield* fs.writeFileString(path.join("dist", "package.json"), JSON.stringify(pkg, null, 2)) + yield* Effect.log("[Build] Build completed.") }).pipe( Effect.provide(Layer.merge(NodeFileSystem.layer, NodePath.layerPosix)) ) diff --git a/scripts/version.mjs b/scripts/version.mjs index 0d78e46..f23a62c 100644 --- a/scripts/version.mjs +++ b/scripts/version.mjs @@ -1,10 +1,9 @@ -import * as Fs from "node:fs"; -import Package from "../package.json" assert { type: "json" }; +import * as Fs from "node:fs" +import Package from "../package.json" assert { type: "json" } -const tpl = Fs.readFileSync("./scripts/version.template.txt").toString("utf8"); +const tpl = Fs.readFileSync("./scripts/version.template.txt").toString("utf8") Fs.writeFileSync( "src/internal/version.ts", tpl.replace("VERSION", Package.version) -); - +) diff --git a/src/Configuration.ts b/src/Configuration.ts index 87f97e3..6075e1a 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -15,8 +15,8 @@ import * as Option from "effect/Option" import * as ParseResult from "effect/ParseResult" import * as Schema from "effect/Schema" import * as tsconfck from "tsconfck" +import * as Domain from "./Domain.js" import { DocgenError } from "./Domain.js" -import * as Process from "./Process.js" const PACKAGE_JSON_FILE_NAME = "package.json" const CONFIG_FILE_NAME = "docgen.json" @@ -170,11 +170,11 @@ const readDocgenConfig = ( const readTSConfig = (fileName: string): Effect.Effect< { readonly [x: string]: unknown }, never, - Path.Path | Process.Process + Path.Path | Domain.Process > => Effect.gen(function*() { const path = yield* Path.Path - const process = yield* Process.Process + const process = yield* Domain.Process const cwd = yield* process.cwd return yield* pipe( Effect.promise(() => tsconfck.parse(path.resolve(cwd, fileName))).pipe( @@ -197,7 +197,7 @@ const resolveCompilerOptions = ( configKey: string, fromCLI: Option.Option>, fromDocgenJson: Option.Option> -): Effect.Effect<{ readonly [x: string]: unknown }, never, Path.Path | Process.Process> => { +): Effect.Effect<{ readonly [x: string]: unknown }, never, Path.Path | Domain.Process> => { const fromConfigProvider = loadCompilerOptions(configKey) return fromCLI.pipe( Effect.orElse(() => fromConfigProvider), @@ -239,7 +239,7 @@ export const load = (args: { }) => Effect.gen(function*() { // Extract the requisite services - const process = yield* Process.Process + const process = yield* Domain.Process const cwd = yield* process.cwd const path = yield* Path.Path @@ -301,7 +301,7 @@ export const load = (args: { /** @internal */ export const configProviderLayer = Layer.scopedDiscard(Effect.gen(function*() { // Extract the requisite services - const process = yield* Process.Process + const process = yield* Domain.Process const cwd = yield* process.cwd const path = yield* Path.Path // Attempt to load the `docgen.json` configuration file diff --git a/src/Core.ts b/src/Core.ts index 8923fc3..d6ba9da 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -20,7 +20,6 @@ import * as Configuration from "./Configuration.js" import * as Domain from "./Domain.js" import { printModule } from "./Markdown.js" import * as Parser from "./Parser.js" -import * as Process from "./Process.js" /** * Find all files matching the specified `glob` pattern, optionally excluding @@ -68,7 +67,7 @@ const writeFileToOutDir = (file: Domain.File) => const config = yield* Configuration.Configuration const fs = yield* FileSystem.FileSystem const path = yield* Path.Path - const process = yield* Process.Process + const process = yield* Domain.Process const cwd = yield* process.cwd const fileName = path.relative(path.join(cwd, config.outDir), file.path) @@ -306,7 +305,7 @@ const cleanupExamples = Effect.gen(function*() { */ const runTscOnExamples = Effect.gen(function*() { const config = yield* Configuration.Configuration - const process = yield* Process.Process + const process = yield* Domain.Process const executor = yield* CommandExecutor.CommandExecutor const cwd = yield* process.cwd const path = yield* Path.Path @@ -348,7 +347,7 @@ const runTscOnExamples = Effect.gen(function*() { const runTsxOnExamples = Effect.gen(function*() { const config = yield* Configuration.Configuration const path = yield* Path.Path - const process = yield* Process.Process + const process = yield* Domain.Process const executor = yield* CommandExecutor.CommandExecutor const cwd = yield* process.cwd const platform = yield* process.platform @@ -398,7 +397,7 @@ const writeExamplesToOutDir = (examples: ReadonlyArray) => const createExamplesTsConfigJson = Effect.gen(function*() { yield* Effect.logDebug("Writing examples tsconfig...") const config = yield* Configuration.Configuration - const process = yield* Process.Process + const process = yield* Domain.Process const cwd = yield* process.cwd const path = yield* Path.Path yield* writeFileToOutDir( @@ -421,7 +420,7 @@ const getMarkdown = (modules: ReadonlyArray) => const getMarkdownHomepage = Effect.gen(function*() { const config = yield* Configuration.Configuration - const process = yield* Process.Process + const process = yield* Domain.Process const cwd = yield* process.cwd const path = yield* Path.Path return new Domain.File( @@ -439,7 +438,7 @@ const getMarkdownHomepage = Effect.gen(function*() { const getMarkdownIndex = Effect.gen(function*() { const config = yield* Configuration.Configuration - const process = yield* Process.Process + const process = yield* Domain.Process const cwd = yield* process.cwd const path = yield* Path.Path return new Domain.File( @@ -478,7 +477,7 @@ const getHomepageNavigationHeader = (config: Configuration.ConfigurationShape): const getMarkdownConfigYML = Effect.gen(function*() { const config = yield* Configuration.Configuration - const process = yield* Process.Process + const process = yield* Domain.Process const fs = yield* FileSystem.FileSystem const cwd = yield* process.cwd const path = yield* Path.Path diff --git a/src/Domain.ts b/src/Domain.ts index 0466df2..b5796ec 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -3,6 +3,7 @@ */ import * as Data from "effect/Data" +import * as Effect from "effect/Effect" import type * as Option from "effect/Option" import * as Order from "effect/Order" import * as String from "effect/String" @@ -273,3 +274,17 @@ export class DocgenError extends Data.TaggedError("DocgenError")<{ readonly message: string }> { } + +/** + * Represents a handle to the currently executing process. + * + * @category service + * @since 0.6.0 + */ +export class Process extends Effect.Service()("Process", { + succeed: { + cwd: Effect.sync(() => process.cwd()), + platform: Effect.sync(() => process.platform), + argv: Effect.sync(() => process.argv) + } +}) {} diff --git a/src/Parser.ts b/src/Parser.ts index 3e49f1a..4a11ca4 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -15,7 +15,6 @@ import * as String from "effect/String" import * as ast from "ts-morph" import * as Configuration from "./Configuration.js" import * as Domain from "./Domain.js" -import * as Process from "./Process.js" /** @internal */ export interface SourceShape { @@ -907,7 +906,7 @@ export const parseFile = (project: ast.Project) => const createProject = (files: ReadonlyArray) => Effect.gen(function*() { const config = yield* Configuration.Configuration - const process = yield* Process.Process + const process = yield* Domain.Process const cwd = yield* process.cwd // Convert the raw config into a format that TS/TS-Morph expects const parsed = ast.ts.parseJsonConfigFileContent( diff --git a/src/Process.ts b/src/Process.ts deleted file mode 100644 index c37d7fc..0000000 --- a/src/Process.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @since 0.6.0 - */ - -import * as Context from "effect/Context" -import * as Effect from "effect/Effect" -import * as Layer from "effect/Layer" - -/** - * Represents a handle to the currently executing process. - * - * @category service - * @since 0.6.0 - */ -export interface ProcessShape { - readonly cwd: Effect.Effect - readonly platform: Effect.Effect - readonly argv: Effect.Effect> -} - -/** - * @category service - * @since 0.6.0 - */ -export class Process extends Context.Tag("Process")() {} - -/** - * @category layer - * @since 0.6.0 - */ -export const layer = Layer.succeed( - Process, - Process.of({ - cwd: Effect.sync(() => process.cwd()), - platform: Effect.sync(() => process.platform), - argv: Effect.sync(() => process.argv) - }) -) diff --git a/src/bin.ts b/src/bin.ts index 035fe75..552110a 100644 --- a/src/bin.ts +++ b/src/bin.ts @@ -12,13 +12,13 @@ import * as Logger from "effect/Logger" import * as LogLevel from "effect/LogLevel" import { cli } from "./CLI.js" import * as Configuration from "./Configuration.js" -import * as Process from "./Process.js" +import * as Domain from "./Domain.js" /** @internal */ export const MainLive = Configuration.configProviderLayer.pipe( Layer.provideMerge(Layer.mergeAll( Logger.minimumLogLevel(LogLevel.Info), - Process.layer, + Domain.Process.Default, NodeContext.layer )) ) diff --git a/src/index.ts b/src/index.ts index 832b378..d1f1298 100644 --- a/src/index.ts +++ b/src/index.ts @@ -26,8 +26,3 @@ export * as Markdown from "./Markdown.js" * @since 0.6.0 */ export * as Parser from "./Parser.js" - -/** - * @since 0.6.0 - */ -export * as Process from "./Process.js" diff --git a/test/Configuration.test.ts b/test/Configuration.test.ts index 7f6cdd7..cbc9545 100644 --- a/test/Configuration.test.ts +++ b/test/Configuration.test.ts @@ -1,8 +1,7 @@ import * as Command from "@effect/cli/Command" import * as CLI from "@effect/docgen/CLI" import * as Configuration from "@effect/docgen/Configuration" -import { DocgenError } from "@effect/docgen/Domain" -import * as Process from "@effect/docgen/Process" +import * as Domain from "@effect/docgen/Domain" import * as NodeCommandExecutor from "@effect/platform-node/NodeCommandExecutor" import * as NodeTerminal from "@effect/platform-node/NodeTerminal" import * as Error from "@effect/platform/Error" @@ -88,7 +87,7 @@ const TestLive = Configuration.configProviderLayer.pipe( Layer.provideMerge(Layer.mergeAll( NodeCommandExecutor.layer.pipe(Layer.provide(TestFileSystem)), Path.layer, - Process.layer, + Domain.Process.Default, NodeTerminal.layer, TestFileSystem )) @@ -177,7 +176,7 @@ describe("Configuration", () => { assert.deepStrictEqual( result, Exit.die( - new DocgenError({ + new Domain.DocgenError({ message: `[Configuration.validateJsonFile] ConfigurationSchema └─ ["projectHomepage"] From 2ccab425b0e5f947d21f2c928d5620c50d6aed77 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 15:11:33 +0100 Subject: [PATCH 23/56] Add documentation category and version tag to CLI export --- src/CLI.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/CLI.ts b/src/CLI.ts index 639135a..1149670 100644 --- a/src/CLI.ts +++ b/src/CLI.ts @@ -173,7 +173,10 @@ const options = { /** @internal */ export const docgenCommand = Command.make("docgen", options) -/** @internal */ +/** + * @category CLI + * @since 0.6.0 + */ export const cli = docgenCommand.pipe( Command.withHandler(() => Effect.scoped(Core.program)), Command.provideEffect(Configuration.Configuration, (args) => Configuration.load(args)), From cb823e912afb4c8458bf1f8fb45feaeb78a5bb05 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 15:25:49 +0100 Subject: [PATCH 24/56] Rename Markdown module to Printer and update related imports --- docs/modules/CLI.ts.md | 21 ++++ docs/modules/Parser.ts.md | 2 +- .../modules/{Markdown.ts.md => Printer.ts.md} | 10 +- docs/modules/index.ts.md | 14 +-- src/Core.ts | 2 +- src/{Markdown.ts => Printer.ts} | 105 +++++++++--------- src/index.ts | 2 +- test/{Markdown.test.ts => Printer.test.ts} | 20 ++-- 8 files changed, 100 insertions(+), 76 deletions(-) rename docs/modules/{Markdown.ts.md => Printer.ts.md} (90%) rename src/{Markdown.ts => Printer.ts} (77%) rename test/{Markdown.test.ts => Printer.test.ts} (93%) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index 08926b5..ff18c08 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -12,4 +12,25 @@ Since v0.6.0

Table of contents

+- [CLI](#cli) + - [cli](#cli-1) + --- + +# CLI + +## cli + +**Signature** + +```ts +export declare const cli: ( + args: ReadonlyArray +) => Effect.Effect< + void, + ValidationError.ValidationError | DocgenError | PlatformError, + Process | CommandExecutor | CliApp.Environment +> +``` + +Since v0.6.0 diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 3dceb21..b699e09 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -1,6 +1,6 @@ --- title: Parser.ts -nav_order: 7 +nav_order: 6 parent: Modules --- diff --git a/docs/modules/Markdown.ts.md b/docs/modules/Printer.ts.md similarity index 90% rename from docs/modules/Markdown.ts.md rename to docs/modules/Printer.ts.md index 566c1b1..c7b2f69 100644 --- a/docs/modules/Markdown.ts.md +++ b/docs/modules/Printer.ts.md @@ -1,10 +1,10 @@ --- -title: Markdown.ts -nav_order: 6 +title: Printer.ts +nav_order: 7 parent: Modules --- -## Markdown overview +## Printer overview Since v0.6.0 @@ -41,12 +41,12 @@ export const a: string = "a" **Example** (Title 1) ```ts twoslash title="Title 1" -import { Domain, Markdown } from "@effect/docgen" +import { Domain, Printer } from "@effect/docgen" import { Option } from "effect" const doc = new Domain.NamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) const m = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) -console.log(Markdown.printModule(m, 0)) +console.log(Printer.printModule(m, 0)) ``` **Example** (Title 2) diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index 8156e10..0479571 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -16,8 +16,8 @@ Since v0.6.0 - [From "./Configuration.js"](#from-configurationjs) - [From "./Core.js"](#from-corejs) - [From "./Domain.js"](#from-domainjs) - - [From "./Markdown.js"](#from-markdownjs) - [From "./Parser.js"](#from-parserjs) + - [From "./Printer.js"](#from-printerjs) --- @@ -59,26 +59,26 @@ export * as Domain from "./Domain.js" Since v0.6.0 -## From "./Markdown.js" +## From "./Parser.js" -Re-exports all named exports from the "./Markdown.js" module as `Markdown`. +Re-exports all named exports from the "./Parser.js" module as `Parser`. **Signature** ```ts -export * as Markdown from "./Markdown.js" +export * as Parser from "./Parser.js" ``` Since v0.6.0 -## From "./Parser.js" +## From "./Printer.js" -Re-exports all named exports from the "./Parser.js" module as `Parser`. +Re-exports all named exports from the "./Printer.js" module as `Printer`. **Signature** ```ts -export * as Parser from "./Parser.js" +export * as Printer from "./Printer.js" ``` Since v0.6.0 diff --git a/src/Core.ts b/src/Core.ts index d6ba9da..304b53d 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -18,8 +18,8 @@ import * as String from "effect/String" import * as Glob from "glob" import * as Configuration from "./Configuration.js" import * as Domain from "./Domain.js" -import { printModule } from "./Markdown.js" import * as Parser from "./Parser.js" +import { printModule } from "./Printer.js" /** * Find all files matching the specified `glob` pattern, optionally excluding diff --git a/src/Markdown.ts b/src/Printer.ts similarity index 77% rename from src/Markdown.ts rename to src/Printer.ts index ea9bcb4..7b75f2c 100644 --- a/src/Markdown.ts +++ b/src/Printer.ts @@ -20,12 +20,19 @@ type Printable = | Domain.TypeAlias | Domain.Namespace -const createHeaderPrinter = (level: number) => (content: string): string => "#".repeat(level) + " " + content + "\n\n" +const createHeaderPrinter = (level: number) => (content: string): string => { + const prefix = "#".repeat(level) + return `${prefix} ${content}\n\n` +} -const MarkdownPrinter = { +/** + * @category CLI + * @since 0.6.0 + */ +const Markdown = { bold: (s: string) => `**${s}**`, - fence: (start: string, content: string, end: string) => start + "\n" + content + "\n" + end + "\n\n", - paragraph: (...content: ReadonlyArray) => "\n" + content.join("") + "\n\n", + fence: (content: string) => `\`\`\`ts\n${content}\n\`\`\`\n\n`, + p: (...content: ReadonlyArray) => "\n" + content.join("") + "\n\n", strikethrough: (content: string) => `~~${content}~~`, h1: createHeaderPrinter(1), h2: createHeaderPrinter(2), @@ -35,17 +42,17 @@ const MarkdownPrinter = { const printSince: (v: Option.Option) => string = Option.match({ onNone: () => "", - onSome: (v) => MarkdownPrinter.paragraph(`Since v${v}`) + onSome: (v) => Markdown.p(`Since v${v}`) }) const printThrows = (throws: ReadonlyArray): string => throws.length === 0 ? "" - : MarkdownPrinter.paragraph(MarkdownPrinter.bold("Throws") + "\n\n" + throws.map((t) => `- ${t}`).join("\n")) + : Markdown.p(Markdown.bold("Throws") + "\n\n" + throws.map((t) => `- ${t}`).join("\n")) const printTitle = (s: string, deprecated: boolean, type?: string): string => { const name = s.trim() === "hasOwnProperty" ? `${s} (function)` : s - const title = deprecated ? MarkdownPrinter.strikethrough(name) : name + const title = deprecated ? Markdown.strikethrough(name) : name return Option.fromNullable(type).pipe( Option.match({ onNone: () => title, @@ -54,24 +61,20 @@ const printTitle = (s: string, deprecated: boolean, type?: string): string => { ) } -const printDescription = (d: Option.Option): string => MarkdownPrinter.paragraph(Option.getOrElse(d, () => "")) - -const printSignature = (s: string): string => - MarkdownPrinter.paragraph(MarkdownPrinter.bold("Signature")) + - MarkdownPrinter.paragraph(MarkdownPrinter.fence("```ts", s, "```")) +const printDescription = (d: Option.Option): string => Markdown.p(Option.getOrElse(d, () => "")) -const printSignatures = (ss: ReadonlyArray): string => - MarkdownPrinter.paragraph(MarkdownPrinter.bold("Signature")) + - MarkdownPrinter.paragraph(MarkdownPrinter.fence("```ts", ss.join("\n"), "```")) +const printSignatures = (signatures: ReadonlyArray): string => + Markdown.p(Markdown.bold("Signature")) + + Markdown.p(Markdown.fence(signatures.join("\n"))) const printExamples = (es: ReadonlyArray): string => es - .map(({ body }) => MarkdownPrinter.paragraph(body)) + .map(({ body }) => Markdown.p(body)) .join("\n\n") const printStaticMethod = (m: Domain.Method): string => - MarkdownPrinter.paragraph( - MarkdownPrinter.h3(printTitle(m.name, m.deprecated, "(static method)")), + Markdown.p( + Markdown.h3(printTitle(m.name, m.deprecated, "(static method)")), printDescription(m.description), printExamples(m.examples), printSignatures(m.signatures), @@ -79,8 +82,8 @@ const printStaticMethod = (m: Domain.Method): string => ) const printMethod = (m: Domain.Method): string => - MarkdownPrinter.paragraph( - MarkdownPrinter.h3(printTitle(m.name, m.deprecated, "(method)")), + Markdown.p( + Markdown.h3(printTitle(m.name, m.deprecated, "(method)")), printDescription(m.description), printExamples(m.examples), printSignatures(m.signatures), @@ -88,11 +91,11 @@ const printMethod = (m: Domain.Method): string => ) const printProperty = (p: Domain.Property): string => - MarkdownPrinter.paragraph( - MarkdownPrinter.h3(printTitle(p.name, p.deprecated, "(property)")), + Markdown.p( + Markdown.h3(printTitle(p.name, p.deprecated, "(property)")), printDescription(p.description), printExamples(p.examples), - printSignature(p.signature), + printSignatures([p.signature]), printSince(p.since) ) @@ -109,15 +112,15 @@ const printProperties = (properties: ReadonlyArray): string => ).join("") const printModuleDescription = (module: Domain.Module): string => - MarkdownPrinter.paragraph( - MarkdownPrinter.h2(printTitle(module.name, module.deprecated, "overview")), + Markdown.p( + Markdown.h2(printTitle(module.name, module.deprecated, "overview")), printDescription(module.description), printExamples(module.examples), printSince(module.since) ) const printMeta = (title: string, order: number): string => - MarkdownPrinter.paragraph( + Markdown.p( "---", `\n`, `title: ${title}`, @@ -131,12 +134,12 @@ const printMeta = (title: string, order: number): string => /** @internal */ export const printClass = (model: Domain.Class): string => - MarkdownPrinter.paragraph( - MarkdownPrinter.paragraph( - MarkdownPrinter.h2(printTitle(model.name, model.deprecated, "(class)")), + Markdown.p( + Markdown.p( + Markdown.h2(printTitle(model.name, model.deprecated, "(class)")), printDescription(model.description), printExamples(model.examples), - printSignature(model.signature), + printSignatures([model.signature]), printSince(model.since) ), printStaticMethods(model.staticMethods), @@ -146,28 +149,28 @@ export const printClass = (model: Domain.Class): string => /** @internal */ export const printConstant = (model: Domain.Constant): string => - MarkdownPrinter.paragraph( - MarkdownPrinter.h2(printTitle(model.name, model.deprecated)), + Markdown.p( + Markdown.h2(printTitle(model.name, model.deprecated)), printDescription(model.description), printExamples(model.examples), - printSignature(model.signature), + printSignatures([model.signature]), printSince(model.since) ) /** @internal */ export const printExport = (model: Domain.Export): string => - MarkdownPrinter.paragraph( - MarkdownPrinter.h2(printTitle(model.name, model.deprecated)), + Markdown.p( + Markdown.h2(printTitle(model.name, model.deprecated)), printDescription(model.description), printExamples(model.examples), - printSignature(model.signature), + printSignatures([model.signature]), printSince(model.since) ) /** @internal */ export const printFunction = (model: Domain.Function): string => - MarkdownPrinter.paragraph( - MarkdownPrinter.h2(printTitle(model.name, model.deprecated)), + Markdown.p( + Markdown.h2(printTitle(model.name, model.deprecated)), printDescription(model.description), printThrows(model.throws), printExamples(model.examples), @@ -177,39 +180,39 @@ export const printFunction = (model: Domain.Function): string => /** @internal */ export const printInterface = (model: Domain.Interface, indentation: number): string => - MarkdownPrinter.paragraph( + Markdown.p( getHeaderByIndentation(indentation)(printTitle(model.name, model.deprecated, "(interface)")), printDescription(model.description), printExamples(model.examples), - printSignature(model.signature), + printSignatures([model.signature]), printSince(model.since) ) /** @internal */ export const printTypeAlias = (model: Domain.TypeAlias, indentation: number): string => - MarkdownPrinter.paragraph( + Markdown.p( getHeaderByIndentation(indentation)(printTitle(model.name, model.deprecated, "(type alias)")), printDescription(model.description), printExamples(model.examples), - printSignature(model.signature), + printSignatures([model.signature]), printSince(model.since) ) const getHeaderByIndentation = (indentation: number) => { switch (indentation) { case 0: - return MarkdownPrinter.h2 + return Markdown.h2 case 1: - return MarkdownPrinter.h3 + return Markdown.h3 default: - return MarkdownPrinter.h4 + return Markdown.h4 } } /** @internal */ export const printNamespace = (ns: Domain.Namespace, indentation: number): string => - MarkdownPrinter.paragraph( - MarkdownPrinter.paragraph( + Markdown.p( + Markdown.p( getHeaderByIndentation(indentation)(printTitle(ns.name, ns.deprecated, "(namespace)")), printDescription(ns.description), printExamples(ns.examples), @@ -281,12 +284,12 @@ const byCategory = Order.mapInput( * **Example** (Title 1) * * ```ts twoslash title="Title 1" - * import { Domain, Markdown } from "@effect/docgen" + * import { Domain, Printer } from "@effect/docgen" * import { Option } from "effect" * * const doc = new Domain.NamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) * const m = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) - * console.log(Markdown.printModule(m, 0)) + * console.log(Printer.printModule(m, 0)) * ``` * * **Example** (Title 2) @@ -308,7 +311,7 @@ export const printModule = ( Effect.gen(function*() { const header = printMeta(module.path.slice(1).join("/"), order) - const description = MarkdownPrinter.paragraph(printModuleDescription(module)) + const description = Markdown.p(printModuleDescription(module)) const content = pipe( getPrintables(module), @@ -317,7 +320,7 @@ export const printModule = ( Array.sort(byCategory), Array.map(([category, printables]) => [ - MarkdownPrinter.h1(category), + Markdown.h1(category), ...pipe( printables, Array.sort( diff --git a/src/index.ts b/src/index.ts index d1f1298..c8a3541 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,7 @@ export * as Domain from "./Domain.js" /** * @since 0.6.0 */ -export * as Markdown from "./Markdown.js" +export * as Printer from "./Printer.js" /** * @since 0.6.0 diff --git a/test/Markdown.test.ts b/test/Printer.test.ts similarity index 93% rename from test/Markdown.test.ts rename to test/Printer.test.ts index 0427eda..f4f404f 100644 --- a/test/Markdown.test.ts +++ b/test/Printer.test.ts @@ -1,5 +1,5 @@ import * as Domain from "@effect/docgen/Domain" -import * as Markdown from "@effect/docgen/Markdown" +import * as Printer from "@effect/docgen/Printer" import * as Effect from "effect/Effect" import { flow } from "effect/Function" import * as Option from "effect/Option" @@ -176,7 +176,7 @@ example 1 describe("Markdown", () => { it("printNamespace", async () => { - const print = flow(Markdown.printNamespace, Markdown.prettify) + const print = flow(Printer.printNamespace, Printer.prettify) assert.strictEqual( await Effect.runPromise(print(testCases.namespace, 0)), `## A (namespace) @@ -211,7 +211,7 @@ Since v1.0.3 }) it("printClass", async () => { - const print = flow(Markdown.printClass, Markdown.prettify) + const print = flow(Printer.printClass, Printer.prettify) assert.strictEqual( await Effect.runPromise(print(testCases.class)), `## A (class) @@ -266,7 +266,7 @@ Since v1.0.0 }) it("printConstant", async () => { - const print = flow(Markdown.printConstant, Markdown.prettify) + const print = flow(Printer.printConstant, Printer.prettify) assert.strictEqual( await Effect.runPromise(print(testCases.constant)), `## test @@ -285,7 +285,7 @@ Since v1.0.0 }) it("printExport", async () => { - const print = flow(Markdown.printExport, Markdown.prettify) + const print = flow(Printer.printExport, Printer.prettify) assert.strictEqual( await Effect.runPromise(print(testCases.export)), `## test @@ -302,7 +302,7 @@ Since v1.0.0 }) it("printFunction", async () => { - const print = flow(Markdown.printFunction, Markdown.prettify) + const print = flow(Printer.printFunction, Printer.prettify) assert.strictEqual( await Effect.runPromise(print(testCases.function)), `## ~~func~~ @@ -325,7 +325,7 @@ Since v1.0.0 }) it("printInterface", async () => { - const print = flow(Markdown.printInterface, Markdown.prettify) + const print = flow(Printer.printInterface, Printer.prettify) assert.strictEqual( await Effect.runPromise(print(testCases.interface, 0)), `## A (interface) @@ -342,7 +342,7 @@ Since v1.0.0 }) it("printTypeAlias", async () => { - const print = flow(Markdown.printTypeAlias, Markdown.prettify) + const print = flow(Printer.printTypeAlias, Printer.prettify) assert.strictEqual( await Effect.runPromise(print(testCases.typeAlias, 0)), `## A (type alias) @@ -380,7 +380,7 @@ export type A = number Option.none() ) assert.strictEqual( - await Effect.runPromise(Markdown.printModule( + await Effect.runPromise(Printer.printModule( new Domain.Module( doc, ["src", "tests.ts"], @@ -572,7 +572,7 @@ Since v1.0.0 const empty = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) assert.strictEqual( - await Effect.runPromise(Markdown.printModule(empty, 1)), + await Effect.runPromise(Printer.printModule(empty, 1)), `--- title: tests.ts nav_order: 1 From 3e08a6c55825755552ee31fa578c1ea4aaac7ffd Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 3 Mar 2025 15:52:17 +0100 Subject: [PATCH 25/56] Remove Option usage in Domain --- docs/modules/Domain.ts.md | 12 +- docs/modules/Printer.ts.md | 2 +- docs/modules/index.ts.md | 14 +- src/Core.ts | 6 +- src/Domain.ts | 13 +- src/Parser.ts | 44 +++--- src/Printer.ts | 11 +- test/Parser.test.ts | 310 ++++++++++++++++++------------------- test/Printer.test.ts | 87 +++++------ 9 files changed, 235 insertions(+), 264 deletions(-) diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 1a6eec3..2508e9b 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -102,11 +102,11 @@ Since v0.6.0 ```ts export declare class Doc { constructor( - readonly description: Option.Option, - readonly since: Option.Option, + readonly description: string | undefined, + readonly since: string | undefined, readonly deprecated: boolean, readonly examples: ReadonlyArray, - readonly category: Option.Option + readonly category: string | undefined ) } ``` @@ -268,11 +268,11 @@ Since v0.6.0 ```ts export declare class NamedDoc { constructor( readonly name: string, - description: Option.Option, - since: Option.Option, + description: string | undefined, + since: string | undefined, deprecated: boolean, examples: ReadonlyArray, - category: Option.Option + category: string | undefined ) } ``` diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index c7b2f69..e6e0dfc 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -44,7 +44,7 @@ export const a: string = "a" import { Domain, Printer } from "@effect/docgen" import { Option } from "effect" -const doc = new Domain.NamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) +const doc = new Domain.NamedDoc("tests", undefined, "1.0.0", false, [], undefined) const m = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) console.log(Printer.printModule(m, 0)) ``` diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index 0479571..9183e20 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -12,7 +12,7 @@ Since v0.6.0

Table of contents

-- [exports](#exports) +- [utils](#utils) - [From "./Configuration.js"](#from-configurationjs) - [From "./Core.js"](#from-corejs) - [From "./Domain.js"](#from-domainjs) @@ -21,12 +21,10 @@ Since v0.6.0 --- -# exports +# utils ## From "./Configuration.js" -Re-exports all named exports from the "./Configuration.js" module as `Configuration`. - **Signature** ```ts @@ -37,8 +35,6 @@ Since v0.6.0 ## From "./Core.js" -Re-exports all named exports from the "./Core.js" module as `Core`. - **Signature** ```ts @@ -49,8 +45,6 @@ Since v0.6.0 ## From "./Domain.js" -Re-exports all named exports from the "./Domain.js" module as `Domain`. - **Signature** ```ts @@ -61,8 +55,6 @@ Since v0.6.0 ## From "./Parser.js" -Re-exports all named exports from the "./Parser.js" module as `Parser`. - **Signature** ```ts @@ -73,8 +65,6 @@ Since v0.6.0 ## From "./Printer.js" -Re-exports all named exports from the "./Printer.js" module as `Printer`. - **Signature** ```ts diff --git a/src/Core.ts b/src/Core.ts index 304b53d..ea28832 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -12,7 +12,6 @@ import { pipe } from "effect" import * as Array from "effect/Array" import * as Chunk from "effect/Chunk" import * as Effect from "effect/Effect" -import * as Option from "effect/Option" import * as Stream from "effect/Stream" import * as String from "effect/String" import * as Glob from "glob" @@ -184,10 +183,7 @@ const getExampleFiles = (modules: ReadonlyArray) => const prefix = module.path.join("-") const getFiles = (exampleId: string) => (doc: Domain.NamedDoc): ReadonlyArray => { - const descriptionExamples = doc.description.pipe( - Option.map(extractFencedCode), - Option.getOrElse((): Array => []) - ) + const descriptionExamples = doc.description ? extractFencedCode(doc.description) : [] const examples = descriptionExamples.concat(doc.examples.flatMap((e) => extractFencedCode(e.body))) return Array.map( examples, diff --git a/src/Domain.ts b/src/Domain.ts index b5796ec..bbcad07 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -4,7 +4,6 @@ import * as Data from "effect/Data" import * as Effect from "effect/Effect" -import type * as Option from "effect/Option" import * as Order from "effect/Order" import * as String from "effect/String" @@ -22,11 +21,11 @@ export class Example { */ export class Doc { constructor( - readonly description: Option.Option, - readonly since: Option.Option, + readonly description: string | undefined, + readonly since: string | undefined, readonly deprecated: boolean, readonly examples: ReadonlyArray, - readonly category: Option.Option + readonly category: string | undefined ) {} } @@ -37,11 +36,11 @@ export class Doc { export class NamedDoc extends Doc { constructor( readonly name: string, - description: Option.Option, - since: Option.Option, + description: string | undefined, + since: string | undefined, deprecated: boolean, examples: ReadonlyArray, - category: Option.Option + category: string | undefined ) { super(description, since, deprecated, examples, category) } diff --git a/src/Parser.ts b/src/Parser.ts index 4a11ca4..173f668 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -26,8 +26,8 @@ export interface SourceShape { export class Source extends Context.Tag("Source")() {} interface Comment { - readonly description: Option.Option - readonly tags: Record>> + readonly description: string | undefined + readonly tags: Record> } const sortByName:
(self: Iterable) => Array = Array.sort( @@ -70,14 +70,16 @@ export const parseComment = (text: string): Comment => { Array.map((tag) => pipe( Option.fromNullable(tag.description), - Option.filter(String.isNonEmpty) + Option.filter(String.isNonEmpty), + Option.getOrUndefined ) ) ) ) const description = pipe( Option.fromNullable(annotation.description), - Option.filter(String.isNonEmpty) + Option.filter(String.isNonEmpty), + Option.getOrUndefined ) return { description, tags } } @@ -110,7 +112,7 @@ const getSinceTag = (name: string, comment: Comment) => const config = yield* Configuration.Configuration const source = yield* Source const since = Record.get(comment.tags, "since").pipe( - Option.flatMap(Array.headNonEmpty), + Option.flatMap((tags) => Option.fromNullable(Array.headNonEmpty(tags))), Option.map(String.trim), Option.filter(String.isNonEmpty) ) @@ -119,14 +121,14 @@ const getSinceTag = (name: string, comment: Comment) => ) { return yield* Effect.fail(getMissingTagError("@since", source.path, name)) } - return since + return Option.getOrUndefined(since) }) const getCategoryTag = (name: string, comment: Comment) => Effect.gen(function*() { const source = yield* Source const category = Record.get(comment.tags, "category").pipe( - Option.flatMap(Array.headNonEmpty), + Option.flatMap((tags) => Option.fromNullable(Array.headNonEmpty(tags))), Option.map(String.trim), Option.filter(String.isNonEmpty) ) @@ -135,14 +137,14 @@ const getCategoryTag = (name: string, comment: Comment) => ) { return yield* Effect.fail(getMissingTagError("@category", source.path, name)) } - return category + return Option.getOrUndefined(category) }) const getDescription = (name: string, comment: Comment) => Effect.gen(function*() { const config = yield* Configuration.Configuration const source = yield* Source - if (Option.isNone(comment.description) && config.enforceDescriptions) { + if (comment.description === undefined && config.enforceDescriptions) { return yield* Effect.fail( `Missing ${chalk.bold("description")} in ${chalk.bold(source.path.join("/") + "#" + name)} documentation` ) @@ -159,7 +161,7 @@ const getExamplesTag = (name: string, comment: Comment, isModule: boolean) => const config = yield* Configuration.Configuration const source = yield* Source const examples = Record.get(comment.tags, "example").pipe( - Option.map(flow(Array.getSomes, Array.map(parseExample))), + Option.map((tags) => tags.filter((tag) => tag !== undefined).map(parseExample)), Option.getOrElse(() => []) ) if (Array.isEmptyArray(examples) && config.enforceExamples && !isModule) { @@ -281,7 +283,7 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => // TODO: parseComment is called twice, here and in getDoc const comment = parseComment(text) const throws: Array = Option.fromNullable(comment.tags["throws"]).pipe( - Option.map(Array.getSomes), + Option.map((tags) => tags.filter((tag) => tag !== undefined)), Option.getOrElse(() => []) ) return new Domain.Function( @@ -312,7 +314,7 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => // TODO: parseComment is called twice, here and in getDoc const comment = parseComment(text) const throws: Array = Option.fromNullable(comment.tags["throws"]).pipe( - Option.map(Array.getSomes), + Option.map((tags) => tags.filter((tag) => tag !== undefined)), Option.getOrElse(() => []) ) return new Domain.Function( @@ -502,19 +504,11 @@ const parseExportStar = ( return new Domain.Export( new Domain.NamedDoc( `From ${name}`, - doc.description.pipe( - Option.orElse(() => - Option.some( - `Re-exports all named exports from the ${name} module${ - namespace === undefined ? "" : ` as \`${namespace}\`` - }.` - ) - ) - ), + doc.description, doc.since, doc.deprecated, doc.examples, - doc.category.pipe(Option.orElse(() => Option.some("exports"))) + doc.category ), signature ) @@ -845,11 +839,11 @@ export const parseModuleDocumentation = Effect.gen(function*() { } return new Domain.NamedDoc( name, - Option.none(), - Option.none(), + undefined, + undefined, false, [], - Option.none() + undefined ) }) diff --git a/src/Printer.ts b/src/Printer.ts index 7b75f2c..f876a3f 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -40,10 +40,7 @@ const Markdown = { h4: createHeaderPrinter(4) } -const printSince: (v: Option.Option) => string = Option.match({ - onNone: () => "", - onSome: (v) => Markdown.p(`Since v${v}`) -}) +const printSince = (v: string | undefined): string => v ? Markdown.p(`Since v${v}`) : "" const printThrows = (throws: ReadonlyArray): string => throws.length === 0 @@ -61,7 +58,7 @@ const printTitle = (s: string, deprecated: boolean, type?: string): string => { ) } -const printDescription = (d: Option.Option): string => Markdown.p(Option.getOrElse(d, () => "")) +const printDescription = (d: string | undefined): string => d ? Markdown.p(d) : "" const printSignatures = (signatures: ReadonlyArray): string => Markdown.p(Markdown.bold("Signature")) + @@ -287,7 +284,7 @@ const byCategory = Order.mapInput( * import { Domain, Printer } from "@effect/docgen" * import { Option } from "effect" * - * const doc = new Domain.NamedDoc("tests", Option.none(), Option.some("1.0.0"), false, [], Option.none()) + * const doc = new Domain.NamedDoc("tests", undefined, "1.0.0", false, [], undefined) * const m = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) * console.log(Printer.printModule(m, 0)) * ``` @@ -315,7 +312,7 @@ export const printModule = ( const content = pipe( getPrintables(module), - Array.groupBy(({ category }) => Option.getOrElse(category, () => DEFAULT_CATEGORY)), + Array.groupBy(({ category }) => category ?? DEFAULT_CATEGORY), Record.toEntries, Array.sort(byCategory), Array.map(([category, printables]) => diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 4242c95..27dedeb 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -3,7 +3,7 @@ import * as Domain from "@effect/docgen/Domain" import * as Parser from "@effect/docgen/Parser" import { Path } from "@effect/platform" import chalk from "chalk" -import { Effect, Exit, Option, String } from "effect" +import { Effect, Exit, String } from "effect" import * as assert from "node:assert/strict" import * as ast from "ts-morph" import { describe, it } from "vitest" @@ -90,11 +90,11 @@ describe("Parser", () => { const documentableA = new Domain.NamedDoc( "A", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ) it("should parse an empty Namespace", () => { @@ -146,11 +146,11 @@ describe("Parser", () => { it("should parse an interface", () => { const documentableB = new Domain.NamedDoc( "B", - Option.none(), - Option.some("1.0.1"), + undefined, + "1.0.1", false, [], - Option.none() + undefined ) expectSuccess( @@ -221,11 +221,11 @@ describe("Parser", () => { it("should parse a type alias", () => { const documentableB = new Domain.NamedDoc( "B", - Option.none(), - Option.some("1.0.1"), + undefined, + "1.0.1", false, [], - Option.none() + undefined ) expectSuccess( @@ -284,19 +284,19 @@ describe("Parser", () => { it("should parse a namespace", () => { const documentableB = new Domain.NamedDoc( "B", - Option.none(), - Option.some("1.0.1"), + undefined, + "1.0.1", false, [], - Option.none() + undefined ) const documentableC = new Domain.NamedDoc( "C", - Option.none(), - Option.some("1.0.2"), + undefined, + "1.0.2", false, [], - Option.none() + undefined ) expectSuccess( @@ -351,11 +351,11 @@ describe("Parser", () => { new Domain.Interface( new Domain.NamedDoc( "A", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [], - Option.none() + undefined ), "export interface A {}" ) @@ -380,22 +380,22 @@ describe("Parser", () => { new Domain.Interface( new Domain.NamedDoc( "A", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export interface A {}" ), new Domain.Interface( new Domain.NamedDoc( "B", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export interface B {}" ) @@ -497,11 +497,11 @@ describe("Parser", () => { new Domain.Function( new Domain.NamedDoc( "toNullable", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), [ "export declare const toNullable: (ma: A | null) => A | null" @@ -529,14 +529,14 @@ describe("Parser", () => { new Domain.Function( new Domain.NamedDoc( "f", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [ new Domain.Example("assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 })"), new Domain.Example("assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })") ], - Option.none() + undefined ), [ "export declare const f: (a: number, b: number) => { [key: string]: number; }" @@ -566,8 +566,8 @@ describe("Parser", () => { new Domain.Function( new Domain.NamedDoc( "f", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [ new Domain.Example(`\`\`\`ts @@ -575,7 +575,7 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) \`\`\``), new Domain.Example("assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })") ], - Option.none() + undefined ), [ "export declare const f: (a: number, b: number) => { [key: string]: number; }" @@ -605,8 +605,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Function( new Domain.NamedDoc( "f", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [ new Domain.Example(`\`\`\`ts @@ -615,7 +615,7 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) \`\`\``) ], - Option.none() + undefined ), [ "export declare const f: (a: number, b: number) => { [key: string]: number; }" @@ -645,8 +645,8 @@ assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) new Domain.Function( new Domain.NamedDoc( "f", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [ new Domain.Example(`~~~ts @@ -654,7 +654,7 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) ~~~`), new Domain.Example("assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })") ], - Option.none() + undefined ), [ "export declare const f: (a: number, b: number) => { [key: string]: number; }" @@ -684,8 +684,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Function( new Domain.NamedDoc( "f", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [ new Domain.Example(`~~~ts @@ -694,7 +694,7 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) ~~~`) ], - Option.none() + undefined ), [ "export declare const f: (a: number, b: number) => { [key: string]: number; }" @@ -724,8 +724,8 @@ assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) new Domain.Function( new Domain.NamedDoc( "f", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [ new Domain.Example(`\`\`\`ts twoslash @@ -733,7 +733,7 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) \`\`\``), new Domain.Example(`assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })`) ], - Option.none() + undefined ), [ "export declare const f: (a: number, b: number) => { [key: string]: number; }" @@ -763,8 +763,8 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Function( new Domain.NamedDoc( "f", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [ new Domain.Example(`~~~ts twoslash @@ -772,7 +772,7 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) ~~~`), new Domain.Example(`assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })`) ], - Option.none() + undefined ), [ "export declare const f: (a: number, b: number) => { [key: string]: number; }" @@ -794,11 +794,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Function( new Domain.NamedDoc( "f", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), [ "export declare function f(a: number, b: number): { [key: string]: number }" @@ -822,11 +822,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Function( new Domain.NamedDoc( "f", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [], - Option.none() + undefined ), [ "export declare function f(a: number, b: number): { [key: string]: number }" @@ -852,11 +852,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Function( new Domain.NamedDoc( "f", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [], - Option.none() + undefined ), [ "export declare function f(a: Int, b: Int): { [key: string]: number }", @@ -883,11 +883,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.TypeAlias( new Domain.NamedDoc( "Option", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [], - Option.none() + undefined ), "export type Option = None | Some" ) @@ -910,11 +910,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Constant( new Domain.NamedDoc( "s", - Option.some("a description..."), - Option.some("1.0.0"), + "a description...", + "1.0.0", true, [], - Option.none() + undefined ), "export declare const s: string" ) @@ -933,11 +933,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Constant( new Domain.NamedDoc( "left", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export declare const left: (l: E) => string" ) @@ -958,11 +958,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Constant( new Domain.NamedDoc( "empty", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export declare const empty: A" ) @@ -987,11 +987,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Constant( new Domain.NamedDoc( "taskSeq", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export declare const taskSeq: { a: number; }" ) @@ -1062,11 +1062,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Class( new Domain.NamedDoc( "MyClass", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export declare class MyClass", [], @@ -1089,11 +1089,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Class( new Domain.NamedDoc( "C", - Option.some("description"), - Option.some("1.0.0"), + "description", + "1.0.0", false, [], - Option.none() + undefined ), "export declare class C { constructor() }", [], @@ -1144,11 +1144,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Class( new Domain.NamedDoc( "C", - Option.some("description"), - Option.some("1.0.0"), + "description", + "1.0.0", false, [], - Option.none() + undefined ), "export declare class C", [], @@ -1157,11 +1157,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Property( new Domain.NamedDoc( "a", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "a: string" ) @@ -1207,22 +1207,22 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Class( new Domain.NamedDoc( "Test", - Option.some("a class description..."), - Option.some("1.0.0"), + "a class description...", + "1.0.0", true, [], - Option.none() + undefined ), "export declare class Test { constructor(readonly value: string) }", [ new Domain.Method( new Domain.NamedDoc( "g", - Option.some("a method description..."), - Option.some("1.1.0"), + "a method description...", + "1.1.0", true, [], - Option.none() + undefined ), [ "g(a: number, b: number): { [key: string]: number }" @@ -1233,11 +1233,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Method( new Domain.NamedDoc( "f", - Option.some("a static method description..."), - Option.some("1.1.0"), + "a static method description...", + "1.1.0", true, [], - Option.none() + undefined ), ["static f(): void"] ) @@ -1246,11 +1246,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Property( new Domain.NamedDoc( "a", - Option.some("a property..."), - Option.some("1.1.0"), + "a property...", + "1.1.0", true, [], - Option.none() + undefined ), "readonly a: string" ) @@ -1293,22 +1293,22 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Class( new Domain.NamedDoc( "Test", - Option.some("a class description..."), - Option.some("1.0.0"), + "a class description...", + "1.0.0", true, [], - Option.none() + undefined ), "export declare class Test { constructor(readonly value: A) }", [ new Domain.Method( new Domain.NamedDoc( "map", - Option.some("a method description..."), - Option.some("1.1.0"), + "a method description...", + "1.1.0", true, [], - Option.none() + undefined ), ["map(f: (a: number) => number): Test", "map(f: (a: string) => string): Test"] ) @@ -1317,11 +1317,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Method( new Domain.NamedDoc( "f", - Option.some("a static method description..."), - Option.some("1.1.0"), + "a static method description...", + "1.1.0", true, [], - Option.none() + undefined ), ["static f(x: number): number", "static f(x: string): string"] ) @@ -1355,11 +1355,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Class( new Domain.NamedDoc( "Test", - Option.some("a class description..."), - Option.some("1.0.0"), + "a class description...", + "1.0.0", false, [], - Option.none() + undefined ), "export declare class Test", [], @@ -1386,13 +1386,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) Parser.parseModuleDocumentation, new Domain.NamedDoc( "test", - Option.some( - "Manages the configuration settings for the widget" - ), - Option.some("1.0.0"), + "Manages the configuration settings for the widget", + "1.0.0", true, [], - Option.none() + undefined ), { enforceVersion: false } ) @@ -1412,11 +1410,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) Parser.parseModuleDocumentation, new Domain.NamedDoc( "test", - Option.none(), - Option.none(), + undefined, + undefined, false, [], - Option.none() + undefined ), { enforceVersion: false } ) @@ -1442,11 +1440,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Export( new Domain.NamedDoc( "b", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export declare const b: 1" ) @@ -1473,22 +1471,22 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Export( new Domain.NamedDoc( "a", - Option.some("description_of_a"), - Option.some("1.0.0"), + "description_of_a", + "1.0.0", false, [], - Option.none() + undefined ), "export declare const a: any" ), new Domain.Export( new Domain.NamedDoc( "b", - Option.some("description_of_b"), - Option.some("2.0.0"), + "description_of_b", + "2.0.0", false, [], - Option.none() + undefined ), "export declare const b: any" ) @@ -1529,11 +1527,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Export( new Domain.NamedDoc( "b", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export declare const b: 1" ) @@ -1569,11 +1567,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Export( new Domain.NamedDoc( "From './example'", - Option.some("Re-exports all named exports from the './example' module."), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.some("exports") + undefined ), "export * from './example'" ) @@ -1609,13 +1607,11 @@ assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) new Domain.Export( new Domain.NamedDoc( "From './example'", - Option.some( - "Re-exports all named exports from the './example' module as `example`." - ), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.some("exports") + undefined ), "export * as example from './example'" ) @@ -1656,11 +1652,11 @@ export const foo = 'foo'`, new Domain.Module( new Domain.NamedDoc( "test", - Option.some("This is the assert module."), - Option.some("1.0.0"), + "This is the assert module.", + "1.0.0", false, [], - Option.none() + undefined ), ["test"], [], @@ -1671,11 +1667,11 @@ export const foo = 'foo'`, new Domain.Constant( new Domain.NamedDoc( "foo", - Option.some("This is the foo export."), - Option.some("1.0.0"), + "This is the foo export.", + "1.0.0", false, [new Domain.Example(`import { foo } from 'test'\n\nconsole.log(foo)`)], - Option.some("foo") + "foo" ), "export declare const foo: \"foo\"" ) @@ -1719,11 +1715,11 @@ export const foo = 'foo'`, "", Parser.getDoc("name", text), new Domain.Doc( - Option.some("description"), - Option.some("1.0.0"), + "description", + "1.0.0", false, [], - Option.some("instances") + "instances" ) ) }) @@ -1806,11 +1802,11 @@ export const foo = 'foo'`, "", Parser.getDoc("name", text), new Domain.Doc( - Option.some("description"), - Option.none(), + "description", + undefined, false, [], - Option.some("instances") + "instances" ), { enforceVersion: false } ) @@ -1819,21 +1815,21 @@ export const foo = 'foo'`, it("parseComment", () => { assert.deepStrictEqual(Parser.parseComment(""), { - description: Option.none(), + description: undefined, tags: {} }) assert.deepStrictEqual(Parser.parseComment("/** description */"), { - description: Option.some("description"), + description: "description", tags: {} }) assert.deepStrictEqual( Parser.parseComment("/** description\n * @since 1.0.0\n */"), { - description: Option.some("description"), + description: "description", tags: { - since: [Option.some("1.0.0")] + since: ["1.0.0"] } } ) @@ -1841,9 +1837,9 @@ export const foo = 'foo'`, assert.deepStrictEqual( Parser.parseComment("/** description\n * @deprecated\n */"), { - description: Option.some("description"), + description: "description", tags: { - deprecated: [Option.none()] + deprecated: [undefined] } } ) @@ -1851,9 +1847,9 @@ export const foo = 'foo'`, assert.deepStrictEqual( Parser.parseComment("/** description\n * @category instance\n */"), { - description: Option.some("description"), + description: "description", tags: { - category: [Option.some("instance")] + category: ["instance"] } } ) diff --git a/test/Printer.test.ts b/test/Printer.test.ts index f4f404f..369e80d 100644 --- a/test/Printer.test.ts +++ b/test/Printer.test.ts @@ -2,7 +2,6 @@ import * as Domain from "@effect/docgen/Domain" import * as Printer from "@effect/docgen/Printer" import * as Effect from "effect/Effect" import { flow } from "effect/Function" -import * as Option from "effect/Option" import * as assert from "node:assert/strict" import { describe, it } from "vitest" @@ -10,26 +9,26 @@ const testCases = { class: new Domain.Class( new Domain.NamedDoc( "A", - Option.some("a class"), - Option.some("1.0.0"), + "a class", + "1.0.0", false, [ new Domain.Example(`\`\`\`ts example 1 \`\`\``) ], - Option.some("category") + "category" ), "declare class A { constructor() }", [ new Domain.Method( new Domain.NamedDoc( "hasOwnProperty", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), ["hasOwnProperty(): boolean"] ) @@ -38,11 +37,11 @@ example 1 new Domain.Method( new Domain.NamedDoc( "staticTest", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), ["static testStatic(): string;"] ) @@ -51,11 +50,11 @@ example 1 new Domain.Property( new Domain.NamedDoc( "foo", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "foo: string" ) @@ -64,37 +63,37 @@ example 1 constant: new Domain.Constant( new Domain.NamedDoc( "test", - Option.some("the test"), - Option.some("1.0.0"), + "the test", + "1.0.0", false, [], - Option.some("constants") + "constants" ), "declare const test: string" ), export: new Domain.Export( new Domain.NamedDoc( "test", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export declare const test: typeof test" ), function: new Domain.Function( new Domain.NamedDoc( "func", - Option.some("a function"), - Option.some("1.0.0"), + "a function", + "1.0.0", true, [ new Domain.Example(`\`\`\`ts example 1 \`\`\``) ], - Option.none() + undefined ), ["declare const func: (test: string) => string"], [] @@ -102,44 +101,44 @@ example 1 interface: new Domain.Interface( new Domain.NamedDoc( "A", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export interface A extends Record {}" ), typeAlias: new Domain.TypeAlias( new Domain.NamedDoc( "A", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), "export type A = number" ), namespace: new Domain.Namespace( new Domain.NamedDoc( "A", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ), [], [ new Domain.TypeAlias( new Domain.NamedDoc( "B", - Option.none(), - Option.some("1.0.1"), + undefined, + "1.0.1", false, [], - Option.none() + undefined ), "export type B = string" ) @@ -148,22 +147,22 @@ example 1 new Domain.Namespace( new Domain.NamedDoc( "C", - Option.none(), - Option.some("1.0.2"), + undefined, + "1.0.2", false, [], - Option.none() + undefined ), [], [ new Domain.TypeAlias( new Domain.NamedDoc( "D", - Option.none(), - Option.some("1.0.3"), + undefined, + "1.0.3", false, [], - Option.none() + undefined ), "export type D = number" ) @@ -358,7 +357,7 @@ Since v1.0.0 ) assert.strictEqual( - await Effect.runPromise(print({ ...testCases.typeAlias, since: Option.none() }, 0)), + await Effect.runPromise(print({ ...testCases.typeAlias, since: undefined }, 0)), `## A (type alias) **Signature** @@ -373,11 +372,11 @@ export type A = number it("printModule", async () => { const doc = new Domain.NamedDoc( "tests", - Option.none(), - Option.some("1.0.0"), + undefined, + "1.0.0", false, [], - Option.none() + undefined ) assert.strictEqual( await Effect.runPromise(Printer.printModule( From 78d752dc801ed62c5de2d924ed37362b33b90887 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 09:24:04 +0100 Subject: [PATCH 26/56] refactor Printer module --- docs/modules/Domain.ts.md | 15 +- docs/modules/Printer.ts.md | 10 +- src/Domain.ts | 4 + src/Printer.ts | 349 ++--- test/Parser.test.ts | 2978 +++++++++++++++++------------------- test/Printer.test.ts | 8 + 6 files changed, 1634 insertions(+), 1730 deletions(-) diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 2508e9b..561b370 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -29,12 +29,13 @@ Since v0.6.0 - [\_tag (property)](#_tag-property-4) - [Method (class)](#method-class) - [Module (class)](#module-class) + - [\_tag (property)](#_tag-property-5) - [NamedDoc (class)](#nameddoc-class) - [Namespace (class)](#namespace-class) - - [\_tag (property)](#_tag-property-5) + - [\_tag (property)](#_tag-property-6) - [Property (class)](#property-class) - [TypeAlias (class)](#typealias-class) - - [\_tag (property)](#_tag-property-6) + - [\_tag (property)](#_tag-property-7) - [service](#service) - [Process (class)](#process-class) - [sorting](#sorting) @@ -261,6 +262,16 @@ export declare class Module { constructor( Since v0.6.0 +### \_tag (property) + +**Signature** + +```ts +readonly _tag: "Module" +``` + +Since v0.6.0 + ## NamedDoc (class) **Signature** diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index e6e0dfc..f18b611 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -33,11 +33,6 @@ export const a: string = "a" └───────┘ └───────┘ └───────┘ └───────┘ └───────┘ └────────┘ ``` -**Throws** - -- `Error1` - Description 1 -- `Error2` - Description 2 - **Example** (Title 1) ```ts twoslash title="Title 1" @@ -55,6 +50,11 @@ console.log(Printer.printModule(m, 0)) export const a: string = "b" ``` +**Throws** + +`Error1` - Description 1 +`Error2` - Description 2 + **Signature** ```ts diff --git a/src/Domain.ts b/src/Domain.ts index bbcad07..4530343 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -51,6 +51,10 @@ export class NamedDoc extends Doc { * @since 0.6.0 */ export class Module extends NamedDoc { + /** + * @since 0.6.0 + */ + readonly _tag = "Module" constructor( doc: NamedDoc, readonly path: ReadonlyArray, diff --git a/src/Printer.ts b/src/Printer.ts index f876a3f..682dc0a 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -11,7 +11,8 @@ import * as String from "effect/String" import * as Prettier from "prettier" import type * as Domain from "./Domain.js" -type Printable = +/** @internal */ +export type Printable = | Domain.Class | Domain.Constant | Domain.Export @@ -19,6 +20,7 @@ type Printable = | Domain.Interface | Domain.TypeAlias | Domain.Namespace + | Domain.Module const createHeaderPrinter = (level: number) => (content: string): string => { const prefix = "#".repeat(level) @@ -32,7 +34,6 @@ const createHeaderPrinter = (level: number) => (content: string): string => { const Markdown = { bold: (s: string) => `**${s}**`, fence: (content: string) => `\`\`\`ts\n${content}\n\`\`\`\n\n`, - p: (...content: ReadonlyArray) => "\n" + content.join("") + "\n\n", strikethrough: (content: string) => `~~${content}~~`, h1: createHeaderPrinter(1), h2: createHeaderPrinter(2), @@ -40,13 +41,6 @@ const Markdown = { h4: createHeaderPrinter(4) } -const printSince = (v: string | undefined): string => v ? Markdown.p(`Since v${v}`) : "" - -const printThrows = (throws: ReadonlyArray): string => - throws.length === 0 - ? "" - : Markdown.p(Markdown.bold("Throws") + "\n\n" + throws.map((t) => `- ${t}`).join("\n")) - const printTitle = (s: string, deprecated: boolean, type?: string): string => { const name = s.trim() === "hasOwnProperty" ? `${s} (function)` : s const title = deprecated ? Markdown.strikethrough(name) : name @@ -58,66 +52,39 @@ const printTitle = (s: string, deprecated: boolean, type?: string): string => { ) } -const printDescription = (d: string | undefined): string => d ? Markdown.p(d) : "" - -const printSignatures = (signatures: ReadonlyArray): string => - Markdown.p(Markdown.bold("Signature")) + - Markdown.p(Markdown.fence(signatures.join("\n"))) - -const printExamples = (es: ReadonlyArray): string => - es - .map(({ body }) => Markdown.p(body)) - .join("\n\n") - -const printStaticMethod = (m: Domain.Method): string => - Markdown.p( - Markdown.h3(printTitle(m.name, m.deprecated, "(static method)")), - printDescription(m.description), - printExamples(m.examples), - printSignatures(m.signatures), - printSince(m.since) - ) - -const printMethod = (m: Domain.Method): string => - Markdown.p( - Markdown.h3(printTitle(m.name, m.deprecated, "(method)")), - printDescription(m.description), - printExamples(m.examples), - printSignatures(m.signatures), - printSince(m.since) - ) - -const printProperty = (p: Domain.Property): string => - Markdown.p( - Markdown.h3(printTitle(p.name, p.deprecated, "(property)")), - printDescription(p.description), - printExamples(p.examples), - printSignatures([p.signature]), - printSince(p.since) - ) - -const printStaticMethods = (methods: ReadonlyArray): string => - Array.map(methods, (method) => printStaticMethod(method) + "\n\n").join("") +const printStaticMethod = (model: Domain.Method): string => { + return printHeaderByIndentation(1) + printTitle(model.name, model.deprecated, "(static method)") + + printOptionalString(model.description) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printSignaturesArray(model.signatures) + + printOptionalSince(model.since) +} -const printMethods = (methods: ReadonlyArray): string => - Array.map(methods, (method) => printMethod(method) + "\n\n").join("") +const printMethod = (model: Domain.Method): string => { + return printHeaderByIndentation(1) + printTitle(model.name, model.deprecated, "(method)") + + printOptionalString(model.description) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printSignaturesArray(model.signatures) + + printOptionalSince(model.since) +} -const printProperties = (properties: ReadonlyArray): string => - Array.map( - properties, - (property) => printProperty(property) + "\n\n" - ).join("") +const printProperty = (model: Domain.Property): string => { + return printHeaderByIndentation(1) + printTitle(model.name, model.deprecated, "(property)") + + printOptionalString(model.description) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printSignaturesArray([model.signature]) + + printOptionalSince(model.since) +} -const printModuleDescription = (module: Domain.Module): string => - Markdown.p( - Markdown.h2(printTitle(module.name, module.deprecated, "overview")), - printDescription(module.description), - printExamples(module.examples), - printSince(module.since) - ) +const printModuleDescription = (module: Domain.Module): string => { + return printHeaderByIndentation(0) + printTitle(module.name, module.deprecated, "overview") + + printOptionalString(module.description) + + printExamplesArray(module.examples.map(({ body }) => body)) + + printOptionalSince(module.since) +} -const printMeta = (title: string, order: number): string => - Markdown.p( +const printMeta = (title: string, order: number): string => { + return [ "---", `\n`, `title: ${title}`, @@ -127,104 +94,134 @@ const printMeta = (title: string, order: number): string => `parent: Modules`, `\n`, "---" - ) + ].join("") +} /** @internal */ -export const printClass = (model: Domain.Class): string => - Markdown.p( - Markdown.p( - Markdown.h2(printTitle(model.name, model.deprecated, "(class)")), - printDescription(model.description), - printExamples(model.examples), - printSignatures([model.signature]), - printSince(model.since) - ), - printStaticMethods(model.staticMethods), - printMethods(model.methods), - printProperties(model.properties) - ) +export const printClass = (model: Domain.Class): string => { + const header = printHeaderByIndentation(0) + printTitle(model.name, model.deprecated, "(class)") + + printOptionalString(model.description) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printSignaturesArray([model.signature]) + + printOptionalSince(model.since) + return header + "\n\n" + + model.staticMethods.map((method) => printStaticMethod(method) + "\n\n").join("") + + model.methods.map((method) => printMethod(method) + "\n\n").join("") + + model.properties.map((property) => printProperty(property) + "\n\n").join("") +} /** @internal */ -export const printConstant = (model: Domain.Constant): string => - Markdown.p( - Markdown.h2(printTitle(model.name, model.deprecated)), - printDescription(model.description), - printExamples(model.examples), - printSignatures([model.signature]), - printSince(model.since) - ) +export const printConstant = (model: Domain.Constant): string => { + return printHeaderByIndentation(0) + printTitle(model.name, model.deprecated) + + printOptionalString(model.description) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printSignaturesArray([model.signature]) + + printOptionalSince(model.since) +} /** @internal */ -export const printExport = (model: Domain.Export): string => - Markdown.p( - Markdown.h2(printTitle(model.name, model.deprecated)), - printDescription(model.description), - printExamples(model.examples), - printSignatures([model.signature]), - printSince(model.since) - ) +export const printExport = (model: Domain.Export): string => { + return printHeaderByIndentation(0) + printTitle(model.name, model.deprecated) + + printOptionalString(model.description) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printSignaturesArray([model.signature]) + + printOptionalSince(model.since) +} -/** @internal */ -export const printFunction = (model: Domain.Function): string => - Markdown.p( - Markdown.h2(printTitle(model.name, model.deprecated)), - printDescription(model.description), - printThrows(model.throws), - printExamples(model.examples), - printSignatures(model.signatures), - printSince(model.since) - ) +const printOptionalString = (s: string | undefined): string => { + if (s === undefined) { + return "" + } + return `\n\n${s}` +} -/** @internal */ -export const printInterface = (model: Domain.Interface, indentation: number): string => - Markdown.p( - getHeaderByIndentation(indentation)(printTitle(model.name, model.deprecated, "(interface)")), - printDescription(model.description), - printExamples(model.examples), - printSignatures([model.signature]), - printSince(model.since) - ) +const printArray = (title: string, ss: ReadonlyArray): string => { + if (ss.length === 0) { + return "" + } + return `\n\n${Markdown.bold(title)}\n\n${ss.join("\n")}` +} -/** @internal */ -export const printTypeAlias = (model: Domain.TypeAlias, indentation: number): string => - Markdown.p( - getHeaderByIndentation(indentation)(printTitle(model.name, model.deprecated, "(type alias)")), - printDescription(model.description), - printExamples(model.examples), - printSignatures([model.signature]), - printSince(model.since) - ) +const printFence = (s: string): string => { + if (s.startsWith("```ts") || s.startsWith("~~~ts")) { + return s + } + return "```ts\n" + s + "\n```" +} + +const printSignaturesArray = (signatures: ReadonlyArray): string => { + if (signatures.length === 0) { + return "" + } + return `\n\n${Markdown.bold("Signature")}\n\n${printFence(signatures.join("\n"))}` +} + +const printThrowsArray = (throws: ReadonlyArray): string => printArray("Throws", throws) -const getHeaderByIndentation = (indentation: number) => { +const printExamplesArray = (examples: ReadonlyArray): string => { + if (examples.length === 0) { + return "" + } + return examples.map((ex) => "\n\n**Example**\n\n" + printFence(ex)).join("") +} + +const printOptionalSince = (since: string | undefined): string => { + if (since === undefined) { + return "" + } + return `\n\nSince v${since}` +} + +const printHeaderByIndentation = (indentation: number) => { switch (indentation) { case 0: - return Markdown.h2 + return "## " case 1: - return Markdown.h3 + return "### " default: - return Markdown.h4 + return "#### " } } /** @internal */ -export const printNamespace = (ns: Domain.Namespace, indentation: number): string => - Markdown.p( - Markdown.p( - getHeaderByIndentation(indentation)(printTitle(ns.name, ns.deprecated, "(namespace)")), - printDescription(ns.description), - printExamples(ns.examples), - printSince(ns.since) - ), - Array.map(ns.interfaces, (i) => printInterface(i, indentation + 1) + "\n\n").join(""), - Array.map( - ns.typeAliases, - (typeAlias) => printTypeAlias(typeAlias, indentation + 1) + "\n\n" - ).join(""), - Array.map( - ns.namespaces, - (namespace) => printNamespace(namespace, indentation + 1) + "\n\n" - ).join("") - ) +export const printFunction = (model: Domain.Function): string => { + return printHeaderByIndentation(0) + printTitle(model.name, model.deprecated) + + printOptionalString(model.description) + + printThrowsArray(model.throws) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printSignaturesArray(model.signatures) + + printOptionalSince(model.since) +} + +/** @internal */ +export const printInterface = (model: Domain.Interface, indentation: number): string => { + return printHeaderByIndentation(indentation) + printTitle(model.name, model.deprecated, "(interface)") + + printOptionalString(model.description) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printSignaturesArray([model.signature]) + + printOptionalSince(model.since) +} + +/** @internal */ +export const printTypeAlias = (model: Domain.TypeAlias, indentation: number): string => { + return printHeaderByIndentation(indentation) + printTitle(model.name, model.deprecated, "(type alias)") + + printOptionalString(model.description) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printSignaturesArray([model.signature]) + + printOptionalSince(model.since) +} + +/** @internal */ +export const printNamespace = (model: Domain.Namespace, indentation: number): string => { + const header = printHeaderByIndentation(indentation) + printTitle(model.name, model.deprecated, "(namespace)") + + printOptionalString(model.description) + + printExamplesArray(model.examples.map(({ body }) => body)) + + printOptionalSince(model.since) + return header + "\n\n" + + model.interfaces.map((inter) => printInterface(inter, indentation + 1) + "\n\n").join("") + + model.typeAliases.map((typeAlias) => printTypeAlias(typeAlias, indentation + 1) + "\n\n").join("") + + model.namespaces.map((namespace) => printNamespace(namespace, indentation + 1) + "\n\n").join("") +} /** @internal */ export const print = (p: Printable): string => { @@ -243,6 +240,10 @@ export const print = (p: Printable): string => { return printTypeAlias(p, 0) case "Namespace": return printNamespace(p, 0) + case "Module": { + const { content, description } = getModuleComponents(p) + return description + content + } } } @@ -264,6 +265,34 @@ const byCategory = Order.mapInput( ([category]: [string, ...Array]) => category ) +const getModuleComponents = (module: Domain.Module) => { + const description = printModuleDescription(module) + "\n" + + const content = pipe( + getPrintables(module), + Array.groupBy(({ category }) => category ?? DEFAULT_CATEGORY), + Record.toEntries, + Array.sort(byCategory), + Array.map(([category, printables]) => + [ + Markdown.h1(category), + ...pipe( + printables, + Array.sort( + Order.mapInput( + String.Order, + (printable: Printable) => printable.name + ) + ), + Array.map(print) + ) + ].join("\n") + ) + ).join("\n") + + return { description, content } +} + /** * Description... * @@ -277,7 +306,6 @@ const byCategory = Order.mapInput( * └───────┘ └───────┘ └───────┘ └───────┘ └───────┘ └────────┘ * ``` * - * @example * **Example** (Title 1) * * ```ts twoslash title="Title 1" @@ -301,36 +329,11 @@ const byCategory = Order.mapInput( * @category printers * @since 0.6.0 */ -export const printModule = ( - module: Domain.Module, - order: number -): Effect.Effect => +export const printModule = (module: Domain.Module, order: number): Effect.Effect => Effect.gen(function*() { const header = printMeta(module.path.slice(1).join("/"), order) - const description = Markdown.p(printModuleDescription(module)) - - const content = pipe( - getPrintables(module), - Array.groupBy(({ category }) => category ?? DEFAULT_CATEGORY), - Record.toEntries, - Array.sort(byCategory), - Array.map(([category, printables]) => - [ - Markdown.h1(category), - ...pipe( - printables, - Array.sort( - Order.mapInput( - String.Order, - (printable: Printable) => printable.name - ) - ), - Array.map(print) - ) - ].join("\n") - ) - ).join("\n") + const { content, description } = getModuleComponents(module) const toc = yield* Effect.tryPromise({ try: () => { diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 27dedeb..19e5357 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -1,9 +1,10 @@ import * as Configuration from "@effect/docgen/Configuration" import * as Domain from "@effect/docgen/Domain" import * as Parser from "@effect/docgen/Parser" +import * as Printer from "@effect/docgen/Printer" import { Path } from "@effect/platform" import chalk from "chalk" -import { Effect, Exit, String } from "effect" +import { Effect, Exit } from "effect" import * as assert from "node:assert/strict" import * as ast from "ts-morph" import { describe, it } from "vitest" @@ -25,16 +26,23 @@ const defaultConfig: Configuration.ConfigurationShape = { enforceDescriptions: false, enforceExamples: false, enforceVersion: true, - runExamples: true, + runExamples: false, exclude: [], parseCompilerOptions: {}, examplesCompilerOptions: {} } -const getParser = (sourceText: string): Parser.SourceShape => ({ - path: ["test"], - sourceFile: project.createSourceFile(`test-${testCounter++}.ts`, sourceText) -}) +const makeSourceFromString = (sourceText: string) => + Parser.Source.of({ + path: ["test"], + sourceFile: project.createSourceFile(`test-${testCounter++}.ts`, sourceText) + }) + +const makeSourceFromSourceFile = (sourceFile: ast.SourceFile) => + Parser.Source.of({ + path: ["test"], + sourceFile + }) const expectFailure = ( sourceText: string, @@ -44,7 +52,7 @@ const expectFailure = ( ) => { assert.deepStrictEqual( eff.pipe( - Effect.provideService(Parser.Source, getParser(sourceText)), + Effect.provideService(Parser.Source, makeSourceFromString(sourceText)), Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), Effect.provide(Path.layer), Effect.runSyncExit @@ -56,1661 +64,1427 @@ const expectFailure = ( const expectSuccess = ( sourceText: string, eff: Effect.Effect, - a: A, + expected: A, config?: Partial ) => { - assert.deepStrictEqual( - eff - .pipe( - Effect.provideService(Parser.Source, getParser(sourceText)), - Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), - Effect.provide(Path.layer), - Effect.runSyncExit - ), - Exit.succeed(a) + const exit = eff.pipe( + Effect.provideService(Parser.Source, makeSourceFromString(sourceText)), + Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), + Effect.provide(Path.layer), + Effect.runSyncExit + ) + assert.ok(exit._tag === "Success") + assert.deepStrictEqual(exit.value, expected) +} + +const print = (printables: ReadonlyArray) => { + const raw = printables.map((printable) => Printer.print(printable).trim()).join("\n") + return Effect.succeed(raw) + // return Printer.prettify(raw) +} + +const expectMarkdown = async ( + eff: Effect.Effect< + Printer.Printable | ReadonlyArray, + E, + Parser.Source | Configuration.Configuration | Path.Path + >, + sourceText: string, + expected: string +) => { + const exit = await eff.pipe( + Effect.flatMap((a) => { + return print(Array.isArray(a) ? a : [a]) + }), + Effect.provideService(Parser.Source, makeSourceFromString(sourceText)), + Effect.provideService(Configuration.Configuration, defaultConfig), + Effect.provide(Path.layer), + Effect.runPromiseExit ) + assert.ok(exit._tag === "Success") + if (exit.value !== expected) { + console.log(exit.value) + } + assert.strictEqual(exit.value, expected) } describe("Parser", () => { - describe("parsers", () => { - describe("parseNamespaces", () => { - it("should return no `Namespaces`s if the file is empty", () => { - expectSuccess("", Parser.parseNamespaces, []) - }) + describe("parseFunctions", () => { + it("should raise an error if the function is anonymous", () => { + expectFailure( + `export function(a: number, b: number): number { return a + b }`, + Parser.parseFunctions, + [`Missing ${chalk.bold("function name")} in module ${chalk.bold("test")}`] + ) + }) - it("should return no `Namespaces`s if there are no exported namespaces", () => { - expectSuccess("namespace A {}", Parser.parseNamespaces, []) - }) + it("description", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * description... + * @since 1.2.0 + */ + export function myfunc() {}`, + `## myfunc - it("should raise an error if the namespace is not well documented", () => { - expectFailure("export namespace A {}", Parser.parseNamespaces, [ - `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#A")} documentation` - ]) - }) +description... + +**Signature** - const documentableA = new Domain.NamedDoc( - "A", - undefined, - "1.0.0", - false, - [], - undefined +\`\`\`ts +export declare function myfunc() +\`\`\` + +Since v1.2.0` ) + }) - it("should parse an empty Namespace", () => { - expectSuccess( - ` - /** + it("example without fence", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * description... + * @example + * const x = 1 * @since 1.0.0 */ - export namespace A {} - `, - Parser.parseNamespaces, - [ - new Domain.Namespace(documentableA, [], [], []) - ] - ) - }) + export function myfunc() {}`, + `## myfunc - describe("interfaces", () => { - it("should ignore not exported interfaces", () => { - expectSuccess( - ` - /** - * @since 1.0.0 - */ - export namespace A { - interface C {} - } - `, - Parser.parseNamespaces, - [new Domain.Namespace(documentableA, [], [], [])] - ) - }) +description... - it("should raise an error if the interface is not well documented", () => { - expectFailure( - ` - /** - * @since 1.0.0 - */ - export namespace A { - export interface B {} - } - `, - Parser.parseNamespaces, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] - ) - }) +**Example** - it("should parse an interface", () => { - const documentableB = new Domain.NamedDoc( - "B", - undefined, - "1.0.1", - false, - [], - undefined - ) +\`\`\`ts +const x = 1 +\`\`\` - expectSuccess( - ` - /** - * @since 1.0.0 - */ - export namespace A { - /** - * @since 1.0.1 - */ - export interface B { - readonly d: boolean - } - } - `, - Parser.parseNamespaces, - [ - new Domain.Namespace( - documentableA, - [ - new Domain.Interface( - documentableB, - `export interface B { - readonly d: boolean - }` - ) - ], - [], - [] - ) - ] - ) - }) - }) +**Signature** - describe("type aliases", () => { - it("should ignore not exported type alias", () => { - expectSuccess( - ` - /** - * @since 1.0.0 - */ - export namespace A { - type C = number - } - `, - Parser.parseNamespaces, - [new Domain.Namespace(documentableA, [], [], [])] - ) - }) +\`\`\`ts +export declare function myfunc() +\`\`\` - it("should raise an error if the type alias is not well documented", () => { - expectFailure( - ` - /** - * @since 1.0.0 - */ - export namespace A { - export type B = string - } - `, - Parser.parseNamespaces, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] - ) - }) +Since v1.0.0` + ) + }) - it("should parse a type alias", () => { - const documentableB = new Domain.NamedDoc( - "B", - undefined, - "1.0.1", - false, - [], - undefined - ) + it("example with backtick fence", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * description... + * @example + * \`\`\`ts + * const x = 1 + * \`\`\` + * @since 1.0.0 + */ + export function myfunc() {}`, + `## myfunc - expectSuccess( - ` - /** - * @since 1.0.0 - */ - export namespace A { - /** - * @since 1.0.1 - */ - export type B = string - } - `, - Parser.parseNamespaces, - [ - new Domain.Namespace(documentableA, [], [ - new Domain.TypeAlias(documentableB, "export type B = string") - ], []) - ] - ) - }) - }) +description... - describe("nested namespaces", () => { - it("should ignore not exported namespaces", () => { - expectSuccess( - ` - /** - * @since 1.0.0 - */ - export namespace A { - namespace B {} - } - `, - Parser.parseNamespaces, - [new Domain.Namespace(documentableA, [], [], [])] - ) - }) +**Example** - it("should raise an error if the namespace is not well documented", () => { - expectFailure( - ` - /** - * @since 1.0.0 - */ - export namespace A { - export namespace B {} - } - `, - Parser.parseNamespaces, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] - ) - }) +\`\`\`ts +const x = 1 +\`\`\` - it("should parse a namespace", () => { - const documentableB = new Domain.NamedDoc( - "B", - undefined, - "1.0.1", - false, - [], - undefined - ) - const documentableC = new Domain.NamedDoc( - "C", - undefined, - "1.0.2", - false, - [], - undefined - ) +**Signature** - expectSuccess( - ` - /** - * @since 1.0.0 - */ - export namespace A { - /** - * @since 1.0.1 - */ - export namespace B { - /** - * @since 1.0.2 - */ - export type C = string - } - } - `, - Parser.parseNamespaces, - [ - new Domain.Namespace(documentableA, [], [], [ - new Domain.Namespace(documentableB, [], [ - new Domain.TypeAlias(documentableC, "export type C = string") - ], []) - ]) - ] - ) - }) - }) +\`\`\`ts +export declare function myfunc() +\`\`\` + +Since v1.0.0` + ) }) - describe("parseInterfaces", () => { - it("should return no `Interface`s if the file is empty", () => { - expectSuccess("", Parser.parseInterfaces, []) - }) + it("2 examples", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * description... + * @example + * \`\`\`ts + * const x = 1 + * \`\`\` + * @example + * \`\`\`ts + * const x = 2 + * \`\`\` + * @since 1.0.0 + */ + export function myfunc() {}`, + `## myfunc - it("should return no `Interface`s if there are no exported interfaces", () => { - expectSuccess("interface A {}", Parser.parseInterfaces, []) - }) +description... - it("should return an `Interface`", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @deprecated - */ - export interface A {}`, - Parser.parseInterfaces, - [ - new Domain.Interface( - new Domain.NamedDoc( - "A", - "a description...", - "1.0.0", - true, - [], - undefined - ), - "export interface A {}" - ) - ] - ) - }) +**Example** - it("should return interfaces sorted by name", () => { - expectSuccess( - ` - /** +\`\`\`ts +const x = 1 +\`\`\` + +**Example** + +\`\`\`ts +const x = 2 +\`\`\` + +**Signature** + +\`\`\`ts +export declare function myfunc() +\`\`\` + +Since v1.0.0` + ) + }) + + it("example with metas", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * description... + * @example + * \`\`\`ts a=1 + * const x = 1 + * \`\`\` * @since 1.0.0 */ - export interface B {} - /** + export function myfunc() {}`, + `## myfunc + +description... + +**Example** + +\`\`\`ts a=1 +const x = 1 +\`\`\` + +**Signature** + +\`\`\`ts +export declare function myfunc() +\`\`\` + +Since v1.0.0` + ) + }) + + it("example with titde fence", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * description... + * @example + * ~~~ts + * const x = 1 + * ~~~ * @since 1.0.0 */ - export interface A {} - `, - Parser.parseInterfaces, - [ - new Domain.Interface( - new Domain.NamedDoc( - "A", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export interface A {}" - ), - new Domain.Interface( - new Domain.NamedDoc( - "B", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export interface B {}" - ) - ] - ) - }) + export function myfunc() {}`, + `## myfunc + +description... + +**Example** + +~~~ts +const x = 1 +~~~ + +**Signature** + +\`\`\`ts +export declare function myfunc() +\`\`\` + +Since v1.0.0` + ) }) - describe("parseFunctions", () => { - it("should raise an error if the function is anonymous", () => { - expectFailure( - `export function(a: number, b: number): number { return a + b }`, - Parser.parseFunctions, - [`Missing ${chalk.bold("function name")} in module ${chalk.bold("test")}`] - ) - }) + it("should not return private function declarations", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * description... + */ + function myfunc() {}`, + "" + ) + }) - it("should not return private function declarations", () => { - expectSuccess( - `function sum(a: number, b: number): number { return a + b }`, - Parser.parseFunctions, - [] - ) - }) + it("should not return ignored function declarations", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * @ignore + */ + export function myfunc() {}`, + "" + ) + }) - it("should not return ignored function declarations", () => { - expectSuccess( - `/** - * @ignore - */ - export function sum(a: number, b: number): number { return a + b }`, - Parser.parseFunctions, - [] - ) - }) + it("should not return ignored function declarations with overloads", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * @ignore + */ + export function sum(a: number, b: number) + export function sum(a: number, b: number): number { return a + b }`, + "" + ) + }) - it("should not return ignored function declarations with overloads", () => { - expectSuccess( - `/** - * @ignore - */ - export function sum(a: number, b: number) - export function sum(a: number, b: number): number { return a + b }`, - Parser.parseFunctions, - [] - ) - }) + it("should not return internal function declarations", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * @internal + */ + export function sum(a: number, b: number): number { return a + b }`, + "" + ) + }) - it("should not return internal function declarations", () => { - expectSuccess( - `/** - * @internal - */ - export function sum(a: number, b: number): number { return a + b }`, - Parser.parseFunctions, - [] - ) - }) + it("should not return internal function declarations even with overloads", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * @internal + */ + export function sum(a: number, b: number) + export function sum(a: number, b: number): number { return a + b }`, + "" + ) + }) - it("should not return internal function declarations even with overloads", () => { - expectSuccess( - `/** - * @internal - */ - export function sum(a: number, b: number) - export function sum(a: number, b: number): number { return a + b }`, - Parser.parseFunctions, - [] - ) - }) + it("should not return private const function declarations", async () => { + await expectMarkdown( + Parser.parseFunctions, + `const sum = (a: number, b: number): number => a + b `, + "" + ) + }) - it("should not return private const function declarations", () => { - expectSuccess( - `const sum = (a: number, b: number): number => a + b `, - Parser.parseFunctions, - [] - ) - }) + it("should not return internal const function declarations", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * @internal + */ + export const sum = (a: number, b: number): number => a + b `, + "" + ) + }) - it("should not return internal const function declarations", () => { - expectSuccess( - `/** - * @internal - */ - export const sum = (a: number, b: number): number => a + b `, - Parser.parseFunctions, - [] - ) - }) + it("should account for nullable polymorphic return types", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * @since 1.0.0 + */ + export const toNullable = (ma: A | null): A | null => ma`, + `## toNullable - it("should account for nullable polymorphic return types", () => { - expectSuccess( - `/** - * @since 1.0.0 - */ - export const toNullable = (ma: A | null): A | null => ma`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "toNullable", - undefined, - "1.0.0", - false, - [], - undefined - ), - [ - "export declare const toNullable: (ma: A | null) => A | null" - ], - [] - ) - ] - ) - }) +**Signature** - it("should return a const function declaration", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @example - * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - * @example - * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) - * @deprecated - */ - export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - "a description...", - "1.0.0", - true, - [ - new Domain.Example("assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 })"), - new Domain.Example("assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })") - ], - undefined - ), - [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - [] - ) - ] - ) - }) +\`\`\`ts +export declare const toNullable: (ma: A | null) => A | null +\`\`\` - it("should parse examples even when enclosed in code blocks using backticks", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @example - * \`\`\`ts - * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - * \`\`\` - * @example - * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) - * @deprecated - */ - export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - "a description...", - "1.0.0", - true, - [ - new Domain.Example(`\`\`\`ts -assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) -\`\`\``), - new Domain.Example("assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })") - ], - undefined - ), - [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - [] - ) - ] - ) - }) +Since v1.0.0` + ) + }) - it("should parse multiline examples even when enclosed in code blocks using backticks", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @example - * \`\`\`ts - * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - * - * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) - * \`\`\` - * @deprecated - */ - export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - "a description...", - "1.0.0", - true, - [ - new Domain.Example(`\`\`\`ts + it("should handle a const function declaration", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * a description... + * @since 1.0.0 + * @example + * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) + * @example + * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) + * @deprecated + */ + export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, + `## ~~f~~ + +a description... + +**Example** + +\`\`\`ts assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) +\`\`\` + +**Example** +\`\`\`ts assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) -\`\`\``) - ], - undefined - ), - [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - [] - ) - ] - ) - }) +\`\`\` - it("should parse examples even when enclosed in code blocks using tildes", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @example - * ~~~ts - * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - * ~~~ - * @example - * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) - * @deprecated - */ - export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - "a description...", - "1.0.0", - true, - [ - new Domain.Example(`~~~ts -assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) -~~~`), - new Domain.Example("assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })") - ], - undefined - ), - [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - [] - ) - ] - ) - }) +**Signature** - it("should parse multiline examples even when enclosed in code blocks using backticks", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @example - * ~~~ts - * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - * - * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) - * ~~~ - * @deprecated - */ - export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - "a description...", - "1.0.0", - true, - [ - new Domain.Example(`~~~ts -assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) +\`\`\`ts +export declare const f: (a: number, b: number) => { [key: string]: number; } +\`\`\` -assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) -~~~`) - ], - undefined - ), - [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - [] - ) - ] - ) - }) +Since v1.0.0` + ) + }) - it("should parse twoslash examples using backtick fences", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @example - * \`\`\`ts twoslash - * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - * \`\`\` - * @example - * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) - * @deprecated - */ - export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - "a description...", - "1.0.0", - true, - [ - new Domain.Example(`\`\`\`ts twoslash -assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) -\`\`\``), - new Domain.Example(`assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })`) - ], - undefined - ), - [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - [] - ) - ] - ) - }) + it("should handle a function declaration", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * @since 1.0.0 + */ + export function f(a: number, b: number): { [key: string]: number } { return { a, b } }`, + `## f - it("should parse twoslash examples using tilde fences", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @example - * ~~~ts twoslash - * assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) - * ~~~ - * @example - * assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) - * @deprecated - */ - export const f = (a: number, b: number): { [key: string]: number } => ({ a, b })`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - "a description...", - "1.0.0", - true, - [ - new Domain.Example(`~~~ts twoslash -assert.deepStrictEqual(f(1, 2), { a: 1, b: 2 }) -~~~`), - new Domain.Example(`assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 })`) - ], - undefined - ), - [ - "export declare const f: (a: number, b: number) => { [key: string]: number; }" - ], - [] - ) - ] - ) - }) +**Signature** - it("should return a function declaration", () => { - expectSuccess( - `/** - * @since 1.0.0 - */ - export function f(a: number, b: number): { [key: string]: number } { return { a, b } }`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - undefined, - "1.0.0", - false, - [], - undefined - ), - [ - "export declare function f(a: number, b: number): { [key: string]: number }" - ], - [] - ) - ] - ) - }) +\`\`\`ts +export declare function f(a: number, b: number): { [key: string]: number } +\`\`\` - it("should return a function with comments", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @deprecated - */ - export function f(a: number, b: number): { [key: string]: number } { return { a, b } }`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - "a description...", - "1.0.0", - true, - [], - undefined - ), - [ - "export declare function f(a: number, b: number): { [key: string]: number }" - ], - [] - ) - ] - ) - }) +Since v1.0.0` + ) + }) - it("should handle overloadings", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @deprecated - */ - export function f(a: Int, b: Int): { [key: string]: number } - export function f(a: number, b: number): { [key: string]: number } - export function f(a: any, b: any): { [key: string]: number } { return { a, b } }`, - Parser.parseFunctions, - [ - new Domain.Function( - new Domain.NamedDoc( - "f", - "a description...", - "1.0.0", - true, - [], - undefined - ), - [ - "export declare function f(a: Int, b: Int): { [key: string]: number }", - "export declare function f(a: number, b: number): { [key: string]: number }" - ], - [] - ) - ] - ) - }) + it("should handle overloadings", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * a description... + * @since 1.0.0 + * @deprecated + */ + export function f(a: Int, b: Int): { [key: string]: number } + export function f(a: number, b: number): { [key: string]: number } + export function f(a: any, b: any): { [key: string]: number } { return { a, b } }`, + `## ~~f~~ + +a description... + +**Signature** + +\`\`\`ts +export declare function f(a: Int, b: Int): { [key: string]: number } +export declare function f(a: number, b: number): { [key: string]: number } +\`\`\` + +Since v1.0.0` + ) }) + }) - describe("parseTypeAlias", () => { - it("should return a `TypeAlias`", () => { - expectSuccess( - `/** - * a description... - * @since 1.0.0 - * @deprecated - */ - export type Option = None | Some`, - Parser.parseTypeAliases, - [ - new Domain.TypeAlias( - new Domain.NamedDoc( - "Option", - "a description...", - "1.0.0", - true, - [], - undefined - ), - "export type Option = None | Some" - ) - ] - ) - }) + describe("parseConstants", () => { + it("should handle a constant value", async () => { + await expectMarkdown( + Parser.parseConstants, + `/** + * a description... + * @since 1.0.0 + * @deprecated + */ + export const s: string = ''`, + `## ~~s~~ + +a description... + +**Signature** + +\`\`\`ts +export declare const s: string +\`\`\` + +Since v1.0.0` + ) }) - describe("parseConstants", () => { - it("should handle a constant value", () => { - expectSuccess( - `/** - * a description... + it("should support constants with default type parameters", async () => { + await expectMarkdown( + Parser.parseConstants, + `/** + * @since 1.0.0 + */ + export const left: (l: E) => string = T.left`, + `## left + +**Signature** + +\`\`\`ts +export declare const left: (l: E) => string +\`\`\` + +Since v1.0.0` + ) + }) + + it("should support untyped constants", async () => { + await expectMarkdown( + Parser.parseConstants, + ` + class A {} + /** + * @since 1.0.0 + */ + export const empty = new A()`, + `## empty + +**Signature** + +\`\`\`ts +export declare const empty: A +\`\`\` + +Since v1.0.0` + ) + }) + + it("should handle constants with typeof annotations", async () => { + await expectMarkdown( + Parser.parseConstants, + ` const task: { a: number } = { + a: 1 + } + /** + * @since 1.0.0 + */ + export const taskSeq: typeof task = { + ...task, + ap: (mab, ma) => () => mab().then(f => ma().then(a => f(a))) + }`, + `## taskSeq + +**Signature** + +\`\`\`ts +export declare const taskSeq: { a: number; } +\`\`\` + +Since v1.0.0` + ) + }) + + it("should not include variables declared in for loops", async () => { + await expectMarkdown( + Parser.parseConstants, + ` const object = { a: 1, b: 2, c: 3 }; + + for (const property in object) { + console.log(property); + }`, + "" + ) + }) + }) + + describe("parseTypeAliases", () => { + it("should return a type alias", async () => { + await expectMarkdown( + Parser.parseTypeAliases, + `/** + * a description... + * @since 1.0.0 + * @deprecated + */ + export type Option = None | Some`, + `## ~~Option~~ (type alias) + +a description... + +**Signature** + +\`\`\`ts +export type Option = None | Some +\`\`\` + +Since v1.0.0` + ) + }) + }) + + describe("parseExports", () => { + it("should return no exports if the file is empty", async () => { + await expectMarkdown( + Parser.parseExports, + "", + "" + ) + }) + + it("should handle renamimg", async () => { + await expectMarkdown( + Parser.parseExports, + `const a = 1; + export { + /** * @since 1.0.0 - * @deprecated */ - export const s: string = ''`, - Parser.parseConstants, - [ - new Domain.Constant( - new Domain.NamedDoc( - "s", - "a description...", - "1.0.0", - true, - [], - undefined - ), - "export declare const s: string" - ) - ] - ) - }) + a as b + }`, + `## b - it("should support constants with default type parameters", () => { - expectSuccess( - `/** +**Signature** + +\`\`\`ts +export declare const b: 1 +\`\`\` + +Since v1.0.0` + ) + }) + + it("should return an `Export`", async () => { + await expectMarkdown( + Parser.parseExports, + ` + const a = 1; + const b = 2; + export { + /** + * description_of_a + * @since 1.0.0 + */ + a, + /** + * description_of_b + * @since 2.0.0 + */ + b + }`, + `## a + +description_of_a + +**Signature** + +\`\`\`ts +export declare const a: 1 +\`\`\` + +Since v1.0.0 +## b + +description_of_b + +**Signature** + +\`\`\`ts +export declare const b: 2 +\`\`\` + +Since v2.0.0` + ) + }) + + it("should raise an error if `@since` tag is missing in export", () => { + expectFailure("export { a }", Parser.parseExports, [ + `Missing ${chalk.bold("a")} documentation in ${chalk.bold("test")}` + ]) + }) + + it("should handle a single re-export", () => { + project.createSourceFile("a.ts", `export const a = 1`) + const sourceFile = project.createSourceFile( + "b.ts", + `import { a } from './a' + const b = a + export { + /** * @since 1.0.0 */ - export const left: (l: E) => string = T.left`, - Parser.parseConstants, - [ - new Domain.Constant( - new Domain.NamedDoc( - "left", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export declare const left: (l: E) => string" - ) - ] - ) - }) + b + }` + ) + const actual = Parser.parseExports.pipe( + Effect.provideService(Parser.Source, makeSourceFromSourceFile(sourceFile)), + Effect.provideService(Configuration.Configuration, defaultConfig), + Effect.runSyncExit + ) + assert.deepStrictEqual( + actual, + Exit.succeed([ + new Domain.Export( + new Domain.NamedDoc( + "b", + undefined, + "1.0.0", + false, + [], + undefined + ), + "export declare const b: 1" + ) + ]) + ) + }) - it("should support untyped constants", () => { - expectSuccess( - ` - class A {} + it("should handle `export * from ...`", () => { + project.createSourceFile("example.ts", `export const a = 1`, { overwrite: true }) + + const sourceFile = project.createSourceFile( + "export-all.ts", + ` + /** + * @since 1.0.0 + */ + export * from './example' + ` + ) + + const actual = Parser.parseExports.pipe( + Effect.provideService(Parser.Source, makeSourceFromSourceFile(sourceFile)), + Effect.provideService(Configuration.Configuration, defaultConfig), + Effect.runSyncExit + ) + + assert.deepStrictEqual( + actual, + Exit.succeed([ + new Domain.Export( + new Domain.NamedDoc( + "From './example'", + undefined, + "1.0.0", + false, + [], + undefined + ), + "export * from './example'" + ) + ]) + ) + }) + + it("should handle `export * as ... from ...`", () => { + project.createSourceFile("example.ts", `export const a = 1`, { overwrite: true }) + + const sourceFile = project.createSourceFile( + "export-all-namespace.ts", + ` + /** + * @since 1.0.0 + */ + export * as example from './example' + ` + ) + + const actual = Parser.parseExports.pipe( + Effect.provideService(Parser.Source, makeSourceFromSourceFile(sourceFile)), + Effect.provideService(Configuration.Configuration, defaultConfig), + Effect.runSyncExit + ) + + assert.deepStrictEqual( + actual, + Exit.succeed([ + new Domain.Export( + new Domain.NamedDoc( + "From './example'", + undefined, + "1.0.0", + false, + [], + undefined + ), + "export * as example from './example'" + ) + ]) + ) + }) + }) + + describe("parseInterfaces", () => { + it("should return no interfaces if the file is empty", async () => { + await expectMarkdown( + Parser.parseInterfaces, + "", + "" + ) + }) + + it("should return no interfaces if there are no exported interfaces", async () => { + await expectMarkdown( + Parser.parseInterfaces, + "interface A {}", + "" + ) + }) + + it("should return an interface", async () => { + await expectMarkdown( + Parser.parseInterfaces, + `/** + * a description... + * @since 1.0.0 + * @deprecated + */ + export interface A {}`, + `## ~~A~~ (interface) + +a description... + +**Signature** + +\`\`\`ts +export interface A {} +\`\`\` + +Since v1.0.0` + ) + }) + + it("should return interfaces sorted by name", async () => { + await expectMarkdown( + Parser.parseInterfaces, + ` /** - * @since 1.0.0 - */ - export const empty = new A()`, - Parser.parseConstants, - [ - new Domain.Constant( - new Domain.NamedDoc( - "empty", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export declare const empty: A" - ) - ] + * @since 1.0.0 + */ + export interface B {} + /** + * @since 1.0.0 + */ + export interface A {} + `, + `## A (interface) + +**Signature** + +\`\`\`ts +export interface A {} +\`\`\` + +Since v1.0.0 +## B (interface) + +**Signature** + +\`\`\`ts +export interface B {} +\`\`\` + +Since v1.0.0` + ) + }) + }) + + describe("parseNamespaces", () => { + it("should return no namespaces if the file is empty", async () => { + await expectMarkdown( + Parser.parseNamespaces, + "", + "" + ) + }) + + it("should return no namespaces if there are no exported namespaces", async () => { + await expectMarkdown( + Parser.parseNamespaces, + "namespace A {}", + "" + ) + }) + + it("should raise an error if the namespace is not well documented", () => { + expectFailure("export namespace A {}", Parser.parseNamespaces, [ + `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#A")} documentation` + ]) + }) + + it("should parse an empty Namespace", async () => { + await expectMarkdown( + Parser.parseNamespaces, + ` + /** + * @since 1.0.0 + */ + export namespace A {} + `, + `## A (namespace) + +Since v1.0.0` + ) + }) + + describe("namespace > interfaces", () => { + it("should ignore not exported interfaces", async () => { + await expectMarkdown( + Parser.parseNamespaces, + ` + /** + * @since 1.0.0 + */ + export namespace A { + interface C {} + } + `, + `## A (namespace) + +Since v1.0.0` ) }) - it("should handle constants with typeof annotations", () => { - expectSuccess( - ` const task: { a: number } = { - a: 1 - } + it("should raise an error if the interface is not well documented", () => { + expectFailure( + ` /** - * @since 1.0.0 - */ - export const taskSeq: typeof task = { - ...task, - ap: (mab, ma) => () => mab().then(f => ma().then(a => f(a))) - }`, - Parser.parseConstants, - [ - new Domain.Constant( - new Domain.NamedDoc( - "taskSeq", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export declare const taskSeq: { a: number; }" - ) - ] + * @since 1.0.0 + */ + export namespace A { + export interface B {} + } + `, + Parser.parseNamespaces, + [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] ) }) - it("should not include variables declared in for loops", () => { - expectSuccess( - ` const object = { a: 1, b: 2, c: 3 }; + it("should parse an interface", async () => { + await expectMarkdown( + Parser.parseNamespaces, + ` +/** + * @since 1.0.0 + */ +export namespace A { + /** + * @since 1.0.1 + */ + export interface B { + readonly d: boolean + } +} + `, + `## A (namespace) - for (const property in object) { - console.log(property); - }`, - Parser.parseConstants, - [] +Since v1.0.0 + +### B (interface) + +**Signature** + +\`\`\`ts +export interface B { + readonly d: boolean + } +\`\`\` + +Since v1.0.1` ) }) }) - describe("parseClasses", () => { - it("should raise an error if the class is anonymous", () => { - expectFailure(`export class {}`, Parser.parseClasses, [ - `Missing ${chalk.bold("class name")} in module ${chalk.bold("test")}` - ]) + describe("namespace > type aliases", () => { + it("should ignore not exported type aliases", async () => { + await expectMarkdown( + Parser.parseNamespaces, + ` + /** + * @since 1.0.0 + */ + export namespace A { + type C = number + } + `, + `## A (namespace) + +Since v1.0.0` + ) }) - it("should raise an error if an `@since` tag is missing in a module", () => { - expectFailure(`export class MyClass {}`, Parser.parseClasses, [ - `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass")} documentation` - ]) + it("should raise an error if the type alias is not well documented", () => { + expectFailure( + ` + /** + * @since 1.0.0 + */ + export namespace A { + export type B = string + } + `, + Parser.parseNamespaces, + [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] + ) }) - it("should ignore internal classes", () => { - expectSuccess(`/** @internal */export class MyClass {}`, Parser.parseClasses, []) + it("should parse a type alias", async () => { + await expectMarkdown( + Parser.parseNamespaces, + ` + /** + * @since 1.0.0 + */ + export namespace A { + /** + * @since 1.0.1 + */ + export type B = string + } + `, + `## A (namespace) + +Since v1.0.0 + +### B (type alias) + +**Signature** + +\`\`\`ts +export type B = string +\`\`\` + +Since v1.0.1` + ) }) + }) + + describe("namespace > nested namespaces", () => { + it("should ignore not exported namespaces", async () => { + await expectMarkdown( + Parser.parseNamespaces, + ` + /** + * @since 1.0.0 + */ + export namespace A { + namespace B {} + } + `, + `## A (namespace) - it("should ignore `@ignore`d classes", () => { - expectSuccess(`/** @ignore */export class MyClass {}`, Parser.parseClasses, []) +Since v1.0.0` + ) }) - it("should raise an error if `@since` is missing in a property", () => { + it("should raise an error if the namespace is not well documented", () => { expectFailure( - `/** - * @since 1.0.0 - */ - export class MyClass { - readonly _A!: A - }`, - Parser.parseClasses, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass#_A")} documentation`] + ` + /** + * @since 1.0.0 + */ + export namespace A { + export namespace B {} + } + `, + Parser.parseNamespaces, + [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] ) }) - it("should skip ignored properties", () => { - expectSuccess( - `/** - * @since 1.0.0 - */ - export class MyClass { + it("should parse a namespace", async () => { + await expectMarkdown( + Parser.parseNamespaces, + ` + /** + * @since 1.0.0 + */ + export namespace A { /** - * @ignore + * @since 1.0.1 */ - readonly _A!: A - }`, - Parser.parseClasses, - [ - new Domain.Class( - new Domain.NamedDoc( - "MyClass", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export declare class MyClass", - [], - [], - [] - ) - ] - ) - }) + export namespace B { + /** + * @since 1.0.2 + */ + export type C = string + } + } + `, + `## A (namespace) - it("should skip the constructor body", () => { - expectSuccess( - `/** - * description - * @since 1.0.0 - */ - export class C { constructor() {} }`, - Parser.parseClasses, - [ - new Domain.Class( - new Domain.NamedDoc( - "C", - "description", - "1.0.0", - false, - [], - undefined - ), - "export declare class C { constructor() }", - [], - [], - [] - ) - ] +Since v1.0.0 + +### B (namespace) + +Since v1.0.1 + +#### C (type alias) + +**Signature** + +\`\`\`ts +export type C = string +\`\`\` + +Since v1.0.2` ) }) + }) + }) - it("should get a constructor declaration signature", () => { - const sourceFile = project.createSourceFile( - `test-${testCounter++}.ts`, - ` + describe("parseClasses", () => { + it("should raise an error if the class is anonymous", () => { + expectFailure(`export class {}`, Parser.parseClasses, [ + `Missing ${chalk.bold("class name")} in module ${chalk.bold("test")}` + ]) + }) + + it("should raise an error if an `@since` tag is missing in a module", () => { + expectFailure(`export class MyClass {}`, Parser.parseClasses, [ + `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass")} documentation` + ]) + }) + + it("should ignore internal classes", async () => { + await expectMarkdown( + Parser.parseClasses, + `/** @internal */export class MyClass {}`, + "" + ) + }) + + it("should ignore `@ignore`d classes", async () => { + await expectMarkdown( + Parser.parseClasses, + ` + /** @ignore */ + export class MyClass {} + `, + "" + ) + }) + + it("should raise an error if `@since` is missing in a property", () => { + expectFailure( + `/** + * @since 1.0.0 + */ + export class MyClass { + readonly _A!: A + }`, + Parser.parseClasses, + [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass#_A")} documentation`] + ) + }) + + it("should skip ignored properties", async () => { + await expectMarkdown( + Parser.parseClasses, + `/** + * @since 1.0.0 + */ + export class MyClass { + /** + * @ignore + */ + readonly _A!: A + }`, + `## MyClass (class) + +**Signature** + +\`\`\`ts +export declare class MyClass +\`\`\` + +Since v1.0.0` + ) + }) + + it("should skip the constructor body", async () => { + await expectMarkdown( + Parser.parseClasses, + `/** + * description + * @since 1.0.0 + */ + export class C { constructor() {} }`, + `## C (class) + +description + +**Signature** + +\`\`\`ts +export declare class C { constructor() } +\`\`\` + +Since v1.0.0` + ) + }) + + it("should get a constructor declaration signature", () => { + const sourceFile = project.createSourceFile( + `test-${testCounter++}.ts`, + ` + /** + * @since 1.0.0 + */ + declare class A { + constructor() + } + ` + ) + + const constructorDeclaration = sourceFile + .getClass("A")! + .getConstructors()[0] + + assert.deepStrictEqual( + Parser.getConstructorDeclarationSignature(constructorDeclaration), + "constructor()" + ) + }) + + it("should handle non-readonly properties", async () => { + await expectMarkdown( + Parser.parseClasses, + `/** + * description + * @since 1.0.0 + */ + export class C { /** * @since 1.0.0 */ - declare class A { - constructor() + a: string + }`, + `## C (class) + +description + +**Signature** + +\`\`\`ts +export declare class C +\`\`\` + +Since v1.0.0 + +### a (property) + +**Signature** + +\`\`\`ts +a: string +\`\`\` + +Since v1.0.0` + ) + }) + + it("should return a `Class`", async () => { + await expectMarkdown( + Parser.parseClasses, + `/** + * a class description... + * @since 1.0.0 + * @deprecated + */ + export class Test { + /** + * a property... + * @since 1.1.0 + * @deprecated + */ + readonly a: string + private readonly b: number + /** + * a static method description... + * @since 1.1.0 + * @deprecated + */ + static f(): void {} + constructor(readonly value: string) { } + /** + * a method description... + * @since 1.1.0 + * @deprecated + */ + g(a: number, b: number): { [key: string]: number } { + return { a, b } } - ` - ) + }`, + `## ~~Test~~ (class) + +a class description... + +**Signature** + +\`\`\`ts +export declare class Test { constructor(readonly value: string) } +\`\`\` + +Since v1.0.0 + +### ~~f~~ (static method) - const constructorDeclaration = sourceFile - .getClass("A")! - .getConstructors()[0] +a static method description... - assert.deepStrictEqual( - Parser.getConstructorDeclarationSignature(constructorDeclaration), - "constructor()" - ) - }) +**Signature** - it("should handle non-readonly properties", () => { - expectSuccess( - `/** - * description - * @since 1.0.0 - */ - export class C { - /** - * @since 1.0.0 - */ - a: string - }`, - Parser.parseClasses, - [ - new Domain.Class( - new Domain.NamedDoc( - "C", - "description", - "1.0.0", - false, - [], - undefined - ), - "export declare class C", - [], - [], - [ - new Domain.Property( - new Domain.NamedDoc( - "a", - undefined, - "1.0.0", - false, - [], - undefined - ), - "a: string" - ) - ] - ) - ] - ) - }) +\`\`\`ts +static f(): void +\`\`\` - it("should return a `Class`", () => { - expectSuccess( - `/** - * a class description... - * @since 1.0.0 - * @deprecated - */ - export class Test { - /** - * a property... - * @since 1.1.0 - * @deprecated - */ - readonly a: string - private readonly b: number - /** - * a static method description... - * @since 1.1.0 - * @deprecated - */ - static f(): void {} - constructor(readonly value: string) { } - /** - * a method description... - * @since 1.1.0 - * @deprecated - */ - g(a: number, b: number): { [key: string]: number } { - return { a, b } - } - }`, - Parser.parseClasses, - [ - new Domain.Class( - new Domain.NamedDoc( - "Test", - "a class description...", - "1.0.0", - true, - [], - undefined - ), - "export declare class Test { constructor(readonly value: string) }", - [ - new Domain.Method( - new Domain.NamedDoc( - "g", - "a method description...", - "1.1.0", - true, - [], - undefined - ), - [ - "g(a: number, b: number): { [key: string]: number }" - ] - ) - ], - [ - new Domain.Method( - new Domain.NamedDoc( - "f", - "a static method description...", - "1.1.0", - true, - [], - undefined - ), - ["static f(): void"] - ) - ], - [ - new Domain.Property( - new Domain.NamedDoc( - "a", - "a property...", - "1.1.0", - true, - [], - undefined - ), - "readonly a: string" - ) - ] - ) - ] - ) - }) +Since v1.1.0 - it("should handle method overloadings", () => { - expectSuccess( - `/** - * a class description... - * @since 1.0.0 - * @deprecated - */ - export class Test { - /** - * a static method description... - * @since 1.1.0 - * @deprecated - */ - static f(x: number): number - static f(x: string): string - static f(x: any): any {} - constructor(readonly value: A) { } - /** - * a method description... - * @since 1.1.0 - * @deprecated - */ - map(f: (a: number) => number): Test - map(f: (a: string) => string): Test - map(f: (a: any) => any): any { - return new Test(f(this.value)) - } - }`, - Parser.parseClasses, - [ - new Domain.Class( - new Domain.NamedDoc( - "Test", - "a class description...", - "1.0.0", - true, - [], - undefined - ), - "export declare class Test { constructor(readonly value: A) }", - [ - new Domain.Method( - new Domain.NamedDoc( - "map", - "a method description...", - "1.1.0", - true, - [], - undefined - ), - ["map(f: (a: number) => number): Test", "map(f: (a: string) => string): Test"] - ) - ], - [ - new Domain.Method( - new Domain.NamedDoc( - "f", - "a static method description...", - "1.1.0", - true, - [], - undefined - ), - ["static f(x: number): number", "static f(x: string): string"] - ) - ], - [] - ) - ] - ) - }) +### ~~g~~ (method) - it("should ignore internal/ignored methods (#42)", () => { - expectSuccess( - `/** - * a class description... - * @since 1.0.0 - */ - export class Test { - /** - * @since 0.0.1 - * @internal - **/ - private foo(): void {} - /** - * @since 0.0.1 - * @ignore - **/ - private bar(): void {} - }`, - Parser.parseClasses, - [ - new Domain.Class( - new Domain.NamedDoc( - "Test", - "a class description...", - "1.0.0", - false, - [], - undefined - ), - "export declare class Test", - [], - [], - [] - ) - ] - ) - }) - }) +a method description... - describe("parseModuleDocumentation", () => { - it("should return a description field and a deprecated field", () => { - expectSuccess( - `/** - * Manages the configuration settings for the widget - * @deprecated - * @since 1.0.0 - */ - /** - * @since 1.2.0 - */ - export const a: number = 1`, - Parser.parseModuleDocumentation, - new Domain.NamedDoc( - "test", - "Manages the configuration settings for the widget", - "1.0.0", - true, - [], - undefined - ), - { enforceVersion: false } - ) - }) +**Signature** - it("should return an error when documentation is enforced but no documentation is provided", () => { - expectFailure( - "export const a: number = 1", - Parser.parseModuleDocumentation, - [`Missing ${chalk.bold("documentation")} in ${chalk.bold("test")} module`] - ) - }) +\`\`\`ts +g(a: number, b: number): { [key: string]: number } +\`\`\` - it("should support absence of module documentation when no documentation is enforced", () => { - expectSuccess( - "export const a: number = 1", - Parser.parseModuleDocumentation, - new Domain.NamedDoc( - "test", - undefined, - undefined, - false, - [], - undefined - ), - { enforceVersion: false } - ) - }) +Since v1.1.0 + +### ~~a~~ (property) + +a property... + +**Signature** + +\`\`\`ts +readonly a: string +\`\`\` + +Since v1.1.0` + ) }) - describe("parseExports", () => { - it("should return no `Export`s if the file is empty", () => { - expectSuccess("", Parser.parseExports, []) - }) + it("should handle method overloadings", async () => { + await expectMarkdown( + Parser.parseClasses, + `/** + * a class description... + * @since 1.0.0 + * @deprecated + */ + export class Test { + /** + * a static method description... + * @since 1.1.0 + * @deprecated + */ + static f(x: number): number + static f(x: string): string + static f(x: any): any {} + constructor(readonly value: A) { } + /** + * a method description... + * @since 1.1.0 + * @deprecated + */ + map(f: (a: number) => number): Test + map(f: (a: string) => string): Test + map(f: (a: any) => any): any { + return new Test(f(this.value)) + } + }`, + `## ~~Test~~ (class) - it("should handle renamimg", () => { - expectSuccess( - `const a = 1; - export { - /** - * @since 1.0.0 - */ - a as b - }`, - Parser.parseExports, - [ - new Domain.Export( - new Domain.NamedDoc( - "b", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export declare const b: 1" - ) - ] - ) - }) +a class description... - it("should return an `Export`", () => { - expectSuccess( - `export { - /** - * description_of_a - * @since 1.0.0 - */ - a, - /** - * description_of_b - * @since 2.0.0 - */ - b - }`, - Parser.parseExports, - [ - new Domain.Export( - new Domain.NamedDoc( - "a", - "description_of_a", - "1.0.0", - false, - [], - undefined - ), - "export declare const a: any" - ), - new Domain.Export( - new Domain.NamedDoc( - "b", - "description_of_b", - "2.0.0", - false, - [], - undefined - ), - "export declare const b: any" - ) - ] - ) - }) +**Signature** - it("should raise an error if `@since` tag is missing in export", () => { - expectFailure("export { a }", Parser.parseExports, [ - `Missing ${chalk.bold("a")} documentation in ${chalk.bold("test")}` - ]) - }) +\`\`\`ts +export declare class Test { constructor(readonly value: A) } +\`\`\` - it("should retrieve an export signature", () => { - project.createSourceFile("a.ts", `export const a = 1`) - const sourceFile = project.createSourceFile( - "b.ts", - `import { a } from './a' - const b = a - export { - /** - * @since 1.0.0 - */ - b - }` - ) - const actual = Parser.parseExports.pipe( - Effect.provideService(Parser.Source, { - path: ["test"], - sourceFile - }), - Effect.provideService(Configuration.Configuration, defaultConfig), - Effect.runSyncExit - ) - assert.deepStrictEqual( - actual, - Exit.succeed([ - new Domain.Export( - new Domain.NamedDoc( - "b", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export declare const b: 1" - ) - ]) - ) - }) +Since v1.0.0 - it("parses export *", () => { - project.createSourceFile("example.ts", `export const a = 1`, { overwrite: true }) +### ~~f~~ (static method) - const sourceFile = project.createSourceFile( - "export-all.ts", - ` - /** - * @since 1.0.0 - */ - export * from './example' - ` - ) +a static method description... - const actual = Parser.parseExports.pipe( - Effect.provideService(Parser.Source, { - path: ["test"], - sourceFile - }), - Effect.provideService(Configuration.Configuration, defaultConfig), - Effect.runSyncExit - ) +**Signature** - assert.deepStrictEqual( - actual, - Exit.succeed([ - new Domain.Export( - new Domain.NamedDoc( - "From './example'", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export * from './example'" - ) - ]) - ) - }) +\`\`\`ts +static f(x: number): number +static f(x: string): string +\`\`\` - it("parse export * as", () => { - project.createSourceFile("example.ts", `export const a = 1`, { overwrite: true }) +Since v1.1.0 - const sourceFile = project.createSourceFile( - "export-all-namespace.ts", - ` - /** - * @since 1.0.0 - */ - export * as example from './example' - ` - ) +### ~~map~~ (method) - const actual = Parser.parseExports.pipe( - Effect.provideService(Parser.Source, { - path: ["test"], - sourceFile - }), - Effect.provideService(Configuration.Configuration, defaultConfig), - Effect.runSyncExit - ) +a method description... - assert.deepStrictEqual( - actual, - Exit.succeed([ - new Domain.Export( - new Domain.NamedDoc( - "From './example'", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export * as example from './example'" - ) - ]) - ) - }) +**Signature** + +\`\`\`ts +map(f: (a: number) => number): Test +map(f: (a: string) => string): Test +\`\`\` + +Since v1.1.0` + ) }) - describe("parseModule", () => { - it("should raise an error if `@since` tag is missing", async () => { - expectFailure(`import * as assert from 'assert'`, Parser.parseModule, [ - `Missing ${chalk.bold("documentation")} in ${chalk.bold("test")} module` - ]) - }) + it("should ignore internal/ignored methods (#42)", async () => { + await expectMarkdown( + Parser.parseClasses, + `/** + * a class description... + * @since 1.0.0 + */ + export class Test { + /** + * @since 0.0.1 + * @internal + **/ + private foo(): void {} + /** + * @since 0.0.1 + * @ignore + **/ + private bar(): void {} + }`, + `## Test (class) - it("should not require an example for modules when `enforceExamples` is set to true (#38)", () => { - expectSuccess( - `/** -* This is the assert module. -* -* @since 1.0.0 -*/ -import * as assert from 'assert' +a class description... -/** - * This is the foo export. - * - * @example - * import { foo } from 'test' - * - * console.log(foo) - * - * @category foo - * @since 1.0.0 - */ -export const foo = 'foo'`, - Parser.parseModule, - new Domain.Module( - new Domain.NamedDoc( - "test", - "This is the assert module.", - "1.0.0", - false, - [], - undefined - ), - ["test"], - [], - [], - [], - [], - [ - new Domain.Constant( - new Domain.NamedDoc( - "foo", - "This is the foo export.", - "1.0.0", - false, - [new Domain.Example(`import { foo } from 'test'\n\nconsole.log(foo)`)], - "foo" - ), - "export declare const foo: \"foo\"" - ) - ], - [], - [] - ), - { enforceExamples: true } - ) - }) +**Signature** + +\`\`\`ts +export declare class Test +\`\`\` + +Since v1.0.0` + ) }) + }) - describe("parseFile", () => { - it("should not parse a non-existent file", async () => { - const file = new Domain.File("non-existent.ts", "") - const project = new ast.Project({ useInMemoryFileSystem: true }) + describe("parseFile", () => { + it("should not parse a non-existent file", async () => { + const file = new Domain.File("non-existent.ts", "") + const project = new ast.Project({ useInMemoryFileSystem: true }) - assert.deepStrictEqual( - Parser.parseFile(project)(file).pipe( - Effect.provideService(Configuration.Configuration, defaultConfig), - Effect.provide(Path.layer), - Effect.runSyncExit - ), - Exit.fail(["Unable to locate file: non-existent.ts"]) - ) - }) + assert.deepStrictEqual( + Parser.parseFile(project)(file).pipe( + Effect.provideService(Configuration.Configuration, defaultConfig), + Effect.provide(Path.layer), + Effect.runSyncExit + ), + Exit.fail(["Unable to locate file: non-existent.ts"]) + ) }) }) describe("utils", () => { describe("getDoc", () => { it("should parse comment information", () => { - const text = String.stripMargin( - `|/** - | * description - | * @category instances - | * @since 1.0.0 - | */` - ) + const text = `/** + * description + * @category instances + * @since 1.0.0 + */` expectSuccess( "", Parser.getDoc("name", text), @@ -1725,12 +1499,10 @@ export const foo = 'foo'`, }) it("should fail if an empty comment tag is provided", () => { - const text = String.stripMargin( - `|/** - | * @category - | * @since 1.0.0 - | */` - ) + const text = `/** + * @category + * @since 1.0.0 + */` expectFailure( "", Parser.getDoc("name", text), @@ -1739,12 +1511,10 @@ export const foo = 'foo'`, }) it("should require a description if `enforceDescriptions` is set to true", () => { - const text = String.stripMargin( - `|/** - | * @category instances - | * @since 1.0.0 - | */` - ) + const text = `/** + * @category instances + * @since 1.0.0 + */` expectFailure( "", Parser.getDoc("name", text), @@ -1756,13 +1526,11 @@ export const foo = 'foo'`, }) it("should require at least one example if `enforceExamples` is set to true", () => { - const text = String.stripMargin( - `|/** - | * description - | * @category instances - | * @since 1.0.0 - | */` - ) + const text = `/** + * description + * @category instances + * @since 1.0.0 + */` expectFailure( "", Parser.getDoc("name", text), @@ -1774,14 +1542,12 @@ export const foo = 'foo'`, }) it("should require at least one non-empty example if `enforceExamples` is set to true", () => { - const text = String.stripMargin( - `|/** - | * description - | * @example - | * @category instances - | * @since 1.0.0 - | */` - ) + const text = `/** + * description + * @example + * @category instances + * @since 1.0.0 + */` expectFailure( "", Parser.getDoc("name", text), @@ -1871,3 +1637,115 @@ export const foo = 'foo'`, }) }) }) + +describe("Parser-old", () => { + describe("parseModuleDocumentation", () => { + it("should return a description field and a deprecated field", () => { + expectSuccess( + `/** + * Manages the configuration settings for the widget + * @deprecated + * @since 1.0.0 + */ + /** + * @since 1.2.0 + */ + export const a: number = 1`, + Parser.parseModuleDocumentation, + new Domain.NamedDoc( + "test", + "Manages the configuration settings for the widget", + "1.0.0", + true, + [], + undefined + ), + { enforceVersion: true } + ) + }) + + it("should support absence of module documentation when no documentation is enforced", () => { + expectSuccess( + "export const a: number = 1", + Parser.parseModuleDocumentation, + new Domain.NamedDoc( + "test", + undefined, + undefined, + false, + [], + undefined + ), + { enforceVersion: false } + ) + }) + + it("should return an error when documentation is enforced but no documentation is provided", () => { + expectFailure( + "export const a: number = 1", + Parser.parseModuleDocumentation, + [`Missing ${chalk.bold("documentation")} in ${chalk.bold("test")} module`] + ) + }) + }) + + describe("parseModule", () => { + it("should raise an error if `@since` tag is missing", async () => { + expectFailure(`import * as assert from 'assert'`, Parser.parseModule, [ + `Missing ${chalk.bold("documentation")} in ${chalk.bold("test")} module` + ]) + }) + + it("should not require an example for modules when `enforceExamples` is set to true", async () => { + await expectMarkdown( + Parser.parseModule, + `/** +* This is the assert module. +* +* @since 1.0.0 +*/ +import * as assert from 'assert' + +/** + * This is the foo export. + * + * @example + * import { foo } from 'test' + * + * console.log(foo) + * + * @category foo + * @since 1.0.0 + */ +export const foo = 'foo'`, + `## test overview + +This is the assert module. + +Since v1.0.0 +# foo + + +## foo + +This is the foo export. + +**Example** + +\`\`\`ts +import { foo } from 'test' + +console.log(foo) +\`\`\` + +**Signature** + +\`\`\`ts +export declare const foo: "foo" +\`\`\` + +Since v1.0.0` + ) + }) + }) +}) diff --git a/test/Printer.test.ts b/test/Printer.test.ts index 369e80d..b751af6 100644 --- a/test/Printer.test.ts +++ b/test/Printer.test.ts @@ -217,6 +217,8 @@ Since v1.0.3 a class +**Example** + \`\`\`ts example 1 \`\`\` @@ -308,6 +310,8 @@ Since v1.0.0 a function +**Example** + \`\`\`ts example 1 \`\`\` @@ -432,6 +436,8 @@ Since v1.0.0 a class +**Example** + \`\`\`ts example 1 \`\`\` @@ -544,6 +550,8 @@ Since v1.0.3 a function +**Example** + \`\`\`ts example 1 \`\`\` From 22214348730ccd1b9f8f777a4676cca97e2b2d43 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 09:37:21 +0100 Subject: [PATCH 27/56] Remove NamedDoc class and update Domain model constructors --- .changeset/silly-insects-draw.md | 1 + docs/modules/Domain.ts.md | 48 +-- docs/modules/Printer.ts.md | 4 +- src/Core.ts | 38 +- src/Domain.ts | 107 ++---- src/Parser.ts | 57 ++- src/Printer.ts | 94 ++--- test/Parser.test.ts | 18 +- test/Printer.test.ts | 601 ------------------------------- 9 files changed, 166 insertions(+), 802 deletions(-) delete mode 100644 test/Printer.test.ts diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index c088b73..51790bc 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -14,3 +14,4 @@ - Remove File module and integrate File class into Domain module - Move DocgenError from Error module to Domain module - Integrate Process service into Domain module +- Remove NamedDoc class and update Domain model constructors diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 561b370..a57c84d 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -30,7 +30,6 @@ Since v0.6.0 - [Method (class)](#method-class) - [Module (class)](#module-class) - [\_tag (property)](#_tag-property-5) - - [NamedDoc (class)](#nameddoc-class) - [Namespace (class)](#namespace-class) - [\_tag (property)](#_tag-property-6) - [Property (class)](#property-class) @@ -54,7 +53,8 @@ Since v0.6.0 ```ts export declare class Class { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string, readonly methods: ReadonlyArray, readonly staticMethods: ReadonlyArray, @@ -80,7 +80,8 @@ Since v0.6.0 ```ts export declare class Constant { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string ) } ``` @@ -149,7 +150,8 @@ export { ```ts export declare class Export { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string ) } ``` @@ -188,7 +190,8 @@ Since v0.6.0 ```ts export declare class Function { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signatures: ReadonlyArray, readonly throws: ReadonlyArray ) } @@ -212,7 +215,8 @@ Since v0.6.0 ```ts export declare class Interface { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string ) } ``` @@ -235,7 +239,8 @@ Since v0.6.0 ```ts export declare class Method { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signatures: ReadonlyArray ) } ``` @@ -248,7 +253,8 @@ Since v0.6.0 ```ts export declare class Module { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly path: ReadonlyArray, readonly classes: ReadonlyArray, readonly interfaces: ReadonlyArray, @@ -272,30 +278,14 @@ readonly _tag: "Module" Since v0.6.0 -## NamedDoc (class) - -**Signature** - -```ts -export declare class NamedDoc { constructor( - readonly name: string, - description: string | undefined, - since: string | undefined, - deprecated: boolean, - examples: ReadonlyArray, - category: string | undefined - ) } -``` - -Since v0.6.0 - ## Namespace (class) **Signature** ```ts export declare class Namespace { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly interfaces: ReadonlyArray, readonly typeAliases: ReadonlyArray, readonly namespaces: ReadonlyArray @@ -320,7 +310,8 @@ Since v0.6.0 ```ts export declare class Property { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string ) } ``` @@ -333,7 +324,8 @@ Since v0.6.0 ```ts export declare class TypeAlias { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string ) } ``` diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index f18b611..0608931 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -39,8 +39,8 @@ export const a: string = "a" import { Domain, Printer } from "@effect/docgen" import { Option } from "effect" -const doc = new Domain.NamedDoc("tests", undefined, "1.0.0", false, [], undefined) -const m = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) +const doc = new Domain.Doc(undefined, "1.0.0", false, [], undefined) +const m = new Domain.Module("tests", doc, ["src", "tests.ts"], [], [], [], [], [], [], []) console.log(Printer.printModule(m, 0)) ``` diff --git a/src/Core.ts b/src/Core.ts index ea28832..77bff2e 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -182,24 +182,26 @@ const getExampleFiles = (modules: ReadonlyArray) => return Array.flatMap(modules, (module) => { const prefix = module.path.join("-") - const getFiles = (exampleId: string) => (doc: Domain.NamedDoc): ReadonlyArray => { - const descriptionExamples = doc.description ? extractFencedCode(doc.description) : [] - const examples = descriptionExamples.concat(doc.examples.flatMap((e) => extractFencedCode(e.body))) - return Array.map( - examples, - (example, i) => { - return new Domain.File( - path.join( - config.outDir, - "examples", - `${prefix}-${exampleId}-${doc.name}-${i}.ts` - ), - example, - true // make the file overwritable - ) - } - ) - } + const getFiles = + (exampleId: string) => + (namedDoc: { readonly name: string; readonly doc: Domain.Doc }): ReadonlyArray => { + const descriptionExamples = namedDoc.doc.description ? extractFencedCode(namedDoc.doc.description) : [] + const examples = descriptionExamples.concat(namedDoc.doc.examples.flatMap((e) => extractFencedCode(e.body))) + return Array.map( + examples, + (example, i) => { + return new Domain.File( + path.join( + config.outDir, + "examples", + `${prefix}-${exampleId}-${namedDoc.name}-${i}.ts` + ), + example, + true // make the file overwritable + ) + } + ) + } const allPrefixedNamespaces = Array.flatMap(module.namespaces, (namespace) => extractPrefixedNestedNamespaces(namespace, "")) diff --git a/src/Domain.ts b/src/Domain.ts index 4530343..3e7b13d 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -33,30 +33,14 @@ export class Doc { * @category model * @since 0.6.0 */ -export class NamedDoc extends Doc { - constructor( - readonly name: string, - description: string | undefined, - since: string | undefined, - deprecated: boolean, - examples: ReadonlyArray, - category: string | undefined - ) { - super(description, since, deprecated, examples, category) - } -} - -/** - * @category model - * @since 0.6.0 - */ -export class Module extends NamedDoc { +export class Module { /** * @since 0.6.0 */ readonly _tag = "Module" constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly path: ReadonlyArray, readonly classes: ReadonlyArray, readonly interfaces: ReadonlyArray, @@ -65,124 +49,115 @@ export class Module extends NamedDoc { readonly constants: ReadonlyArray, readonly exports: ReadonlyArray, readonly namespaces: ReadonlyArray - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** * @category model * @since 0.6.0 */ -export class Class extends NamedDoc { +export class Class { /** * @since 0.6.0 */ readonly _tag = "Class" constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string, readonly methods: ReadonlyArray, readonly staticMethods: ReadonlyArray, readonly properties: ReadonlyArray - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** * @category model * @since 0.6.0 */ -export class Method extends NamedDoc { +export class Method { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signatures: ReadonlyArray - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** * @category model * @since 0.6.0 */ -export class Property extends NamedDoc { +export class Property { constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** * @category model * @since 0.6.0 */ -export class Interface extends NamedDoc { +export class Interface { /** * @since 0.6.0 */ readonly _tag = "Interface" constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** * @category model * @since 0.6.0 */ -export class Function extends NamedDoc { +export class Function { /** * @since 0.6.0 */ readonly _tag = "Function" constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signatures: ReadonlyArray, readonly throws: ReadonlyArray - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** * @category model * @since 0.6.0 */ -export class TypeAlias extends NamedDoc { +export class TypeAlias { /** * @since 0.6.0 */ readonly _tag = "TypeAlias" constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** * @category model * @since 0.6.0 */ -export class Constant extends NamedDoc { +export class Constant { /** * @since 0.6.0 */ readonly _tag = "Constant" constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** @@ -199,36 +174,34 @@ export class Constant extends NamedDoc { * @category model * @since 0.6.0 */ -export class Export extends NamedDoc { +export class Export { /** * @since 0.6.0 */ readonly _tag = "Export" constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly signature: string - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** * @category model * @since 0.6.0 */ -export class Namespace extends NamedDoc { +export class Namespace { /** * @since 0.6.0 */ readonly _tag = "Namespace" constructor( - doc: NamedDoc, + readonly name: string, + readonly doc: Doc, readonly interfaces: ReadonlyArray, readonly typeAliases: ReadonlyArray, readonly namespaces: ReadonlyArray - ) { - super(doc.name, doc.description, doc.since, doc.deprecated, doc.examples, doc.category) - } + ) {} } /** diff --git a/src/Parser.ts b/src/Parser.ts index 173f668..f6ab86a 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -197,8 +197,8 @@ const parseInterfaceDeclaration = (id: ast.InterfaceDeclaration) => const doc = yield* getDoc(name, text) const signature = id.getText() return new Domain.Interface( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -287,8 +287,8 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => Option.getOrElse(() => []) ) return new Domain.Function( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -318,8 +318,8 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => Option.getOrElse(() => []) ) return new Domain.Function( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -376,8 +376,8 @@ const parseTypeAliasDeclaration = (ta: ast.TypeAliasDeclaration) => const doc = yield* getDoc(name, text) const signature = ta.getText() return new Domain.TypeAlias( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -416,8 +416,8 @@ const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => const type = stripImportTypes(vd.getType().getText(vd)) const signature = `export declare const ${name}: ${type}` return new Domain.Constant( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -471,8 +471,8 @@ const parseExportSpecifier = (es: ast.ExportSpecifier) => const doc = yield* getDoc(name, text) const signature = `export declare const ${name}: ${type}` return new Domain.Export( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -502,8 +502,8 @@ const parseExportStar = ( const text = commentRange.getText() const doc = yield* getDoc(name, text) return new Domain.Export( - new Domain.NamedDoc( - `From ${name}`, + `From ${name}`, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -559,8 +559,8 @@ const parseModuleDeclaration = ( const typeAliases = yield* getTypeAliases const namespaces = yield* getNamespaces return new Domain.Namespace( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( info.description, info.since, info.deprecated, @@ -640,8 +640,8 @@ const parseMethod = (md: ast.MethodDeclaration) => ) return Option.some( new Domain.Method( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -672,8 +672,8 @@ const parseProperty = (classname: string) => (pd: ast.PropertyDeclaration) => ) const signature = `${readonly}${name}: ${type}` return new Domain.Property( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -762,8 +762,8 @@ const parseClass = (c: ast.ClassDeclaration) => ) const properties = yield* parseProperties(name, c) return new Domain.Class( - new Domain.NamedDoc( - name, + name, + new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -801,8 +801,6 @@ export const parseClasses = Effect.gen(function*() { export const parseModuleDocumentation = Effect.gen(function*() { const config = yield* Configuration.Configuration const source = yield* Source - const path = yield* Path.Path - const name = path.parse(Array.lastNonEmpty(source.path)).name // if any of the settings enforcing documentation are set to `true`, then // a module should have associated documentation const isDocumentationRequired = config.enforceDescriptions || config.enforceVersion @@ -827,8 +825,7 @@ export const parseModuleDocumentation = Effect.gen(function*() { const commentRange = ocommentRange.value const text = commentRange.getText() const doc = yield* getDoc("", text, true).pipe(Effect.mapError(Array.of)) - return new Domain.NamedDoc( - name, + return new Domain.Doc( doc.description, doc.since, doc.deprecated, @@ -837,8 +834,7 @@ export const parseModuleDocumentation = Effect.gen(function*() { ) } } - return new Domain.NamedDoc( - name, + return new Domain.Doc( undefined, undefined, false, @@ -861,7 +857,10 @@ export const parseModule = Effect.gen(function*() { const constants = yield* parseConstants const exports = yield* parseExports const namespaces = yield* parseNamespaces + const path = yield* Path.Path + const name = path.parse(Array.lastNonEmpty(source.path)).name return new Domain.Module( + name, doc, source.path, classes, @@ -937,7 +936,7 @@ export const parseFiles = (files: ReadonlyArray) => Effect.validateAll(parseFile(project)), Effect.map( flow( - Array.filter((module) => !module.deprecated), + Array.filter((module) => !module.doc.deprecated), sortModulesByPath ) ) diff --git a/src/Printer.ts b/src/Printer.ts index 682dc0a..ab2520f 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -53,34 +53,34 @@ const printTitle = (s: string, deprecated: boolean, type?: string): string => { } const printStaticMethod = (model: Domain.Method): string => { - return printHeaderByIndentation(1) + printTitle(model.name, model.deprecated, "(static method)") + - printOptionalString(model.description) + - printExamplesArray(model.examples.map(({ body }) => body)) + + return printHeaderByIndentation(1) + printTitle(model.name, model.doc.deprecated, "(static method)") + + printOptionalString(model.doc.description) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + printSignaturesArray(model.signatures) + - printOptionalSince(model.since) + printOptionalSince(model.doc.since) } const printMethod = (model: Domain.Method): string => { - return printHeaderByIndentation(1) + printTitle(model.name, model.deprecated, "(method)") + - printOptionalString(model.description) + - printExamplesArray(model.examples.map(({ body }) => body)) + + return printHeaderByIndentation(1) + printTitle(model.name, model.doc.deprecated, "(method)") + + printOptionalString(model.doc.description) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + printSignaturesArray(model.signatures) + - printOptionalSince(model.since) + printOptionalSince(model.doc.since) } const printProperty = (model: Domain.Property): string => { - return printHeaderByIndentation(1) + printTitle(model.name, model.deprecated, "(property)") + - printOptionalString(model.description) + - printExamplesArray(model.examples.map(({ body }) => body)) + + return printHeaderByIndentation(1) + printTitle(model.name, model.doc.deprecated, "(property)") + + printOptionalString(model.doc.description) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + printSignaturesArray([model.signature]) + - printOptionalSince(model.since) + printOptionalSince(model.doc.since) } const printModuleDescription = (module: Domain.Module): string => { - return printHeaderByIndentation(0) + printTitle(module.name, module.deprecated, "overview") + - printOptionalString(module.description) + - printExamplesArray(module.examples.map(({ body }) => body)) + - printOptionalSince(module.since) + return printHeaderByIndentation(0) + printTitle(module.name, module.doc.deprecated, "overview") + + printOptionalString(module.doc.description) + + printExamplesArray(module.doc.examples.map(({ body }) => body)) + + printOptionalSince(module.doc.since) } const printMeta = (title: string, order: number): string => { @@ -99,11 +99,11 @@ const printMeta = (title: string, order: number): string => { /** @internal */ export const printClass = (model: Domain.Class): string => { - const header = printHeaderByIndentation(0) + printTitle(model.name, model.deprecated, "(class)") + - printOptionalString(model.description) + - printExamplesArray(model.examples.map(({ body }) => body)) + + const header = printHeaderByIndentation(0) + printTitle(model.name, model.doc.deprecated, "(class)") + + printOptionalString(model.doc.description) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + printSignaturesArray([model.signature]) + - printOptionalSince(model.since) + printOptionalSince(model.doc.since) return header + "\n\n" + model.staticMethods.map((method) => printStaticMethod(method) + "\n\n").join("") + model.methods.map((method) => printMethod(method) + "\n\n").join("") + @@ -112,20 +112,20 @@ export const printClass = (model: Domain.Class): string => { /** @internal */ export const printConstant = (model: Domain.Constant): string => { - return printHeaderByIndentation(0) + printTitle(model.name, model.deprecated) + - printOptionalString(model.description) + - printExamplesArray(model.examples.map(({ body }) => body)) + + return printHeaderByIndentation(0) + printTitle(model.name, model.doc.deprecated) + + printOptionalString(model.doc.description) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + printSignaturesArray([model.signature]) + - printOptionalSince(model.since) + printOptionalSince(model.doc.since) } /** @internal */ export const printExport = (model: Domain.Export): string => { - return printHeaderByIndentation(0) + printTitle(model.name, model.deprecated) + - printOptionalString(model.description) + - printExamplesArray(model.examples.map(({ body }) => body)) + + return printHeaderByIndentation(0) + printTitle(model.name, model.doc.deprecated) + + printOptionalString(model.doc.description) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + printSignaturesArray([model.signature]) + - printOptionalSince(model.since) + printOptionalSince(model.doc.since) } const printOptionalString = (s: string | undefined): string => { @@ -185,38 +185,38 @@ const printHeaderByIndentation = (indentation: number) => { /** @internal */ export const printFunction = (model: Domain.Function): string => { - return printHeaderByIndentation(0) + printTitle(model.name, model.deprecated) + - printOptionalString(model.description) + + return printHeaderByIndentation(0) + printTitle(model.name, model.doc.deprecated) + + printOptionalString(model.doc.description) + printThrowsArray(model.throws) + - printExamplesArray(model.examples.map(({ body }) => body)) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + printSignaturesArray(model.signatures) + - printOptionalSince(model.since) + printOptionalSince(model.doc.since) } /** @internal */ export const printInterface = (model: Domain.Interface, indentation: number): string => { - return printHeaderByIndentation(indentation) + printTitle(model.name, model.deprecated, "(interface)") + - printOptionalString(model.description) + - printExamplesArray(model.examples.map(({ body }) => body)) + + return printHeaderByIndentation(indentation) + printTitle(model.name, model.doc.deprecated, "(interface)") + + printOptionalString(model.doc.description) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + printSignaturesArray([model.signature]) + - printOptionalSince(model.since) + printOptionalSince(model.doc.since) } /** @internal */ export const printTypeAlias = (model: Domain.TypeAlias, indentation: number): string => { - return printHeaderByIndentation(indentation) + printTitle(model.name, model.deprecated, "(type alias)") + - printOptionalString(model.description) + - printExamplesArray(model.examples.map(({ body }) => body)) + + return printHeaderByIndentation(indentation) + printTitle(model.name, model.doc.deprecated, "(type alias)") + + printOptionalString(model.doc.description) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + printSignaturesArray([model.signature]) + - printOptionalSince(model.since) + printOptionalSince(model.doc.since) } /** @internal */ export const printNamespace = (model: Domain.Namespace, indentation: number): string => { - const header = printHeaderByIndentation(indentation) + printTitle(model.name, model.deprecated, "(namespace)") + - printOptionalString(model.description) + - printExamplesArray(model.examples.map(({ body }) => body)) + - printOptionalSince(model.since) + const header = printHeaderByIndentation(indentation) + printTitle(model.name, model.doc.deprecated, "(namespace)") + + printOptionalString(model.doc.description) + + printExamplesArray(model.doc.examples.map(({ body }) => body)) + + printOptionalSince(model.doc.since) return header + "\n\n" + model.interfaces.map((inter) => printInterface(inter, indentation + 1) + "\n\n").join("") + model.typeAliases.map((typeAlias) => printTypeAlias(typeAlias, indentation + 1) + "\n\n").join("") + @@ -270,7 +270,7 @@ const getModuleComponents = (module: Domain.Module) => { const content = pipe( getPrintables(module), - Array.groupBy(({ category }) => category ?? DEFAULT_CATEGORY), + Array.groupBy((printable) => printable.doc.category ?? DEFAULT_CATEGORY), Record.toEntries, Array.sort(byCategory), Array.map(([category, printables]) => @@ -312,8 +312,8 @@ const getModuleComponents = (module: Domain.Module) => { * import { Domain, Printer } from "@effect/docgen" * import { Option } from "effect" * - * const doc = new Domain.NamedDoc("tests", undefined, "1.0.0", false, [], undefined) - * const m = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) + * const doc = new Domain.Doc(undefined, "1.0.0", false, [], undefined) + * const m = new Domain.Module("tests", doc, ["src", "tests.ts"], [], [], [], [], [], [], []) * console.log(Printer.printModule(m, 0)) * ``` * diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 19e5357..f409759 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -717,8 +717,8 @@ Since v2.0.0` actual, Exit.succeed([ new Domain.Export( - new Domain.NamedDoc( - "b", + "b", + new Domain.Doc( undefined, "1.0.0", false, @@ -754,8 +754,8 @@ Since v2.0.0` actual, Exit.succeed([ new Domain.Export( - new Domain.NamedDoc( - "From './example'", + "From './example'", + new Domain.Doc( undefined, "1.0.0", false, @@ -791,8 +791,8 @@ Since v2.0.0` actual, Exit.succeed([ new Domain.Export( - new Domain.NamedDoc( - "From './example'", + "From './example'", + new Domain.Doc( undefined, "1.0.0", false, @@ -1652,8 +1652,7 @@ describe("Parser-old", () => { */ export const a: number = 1`, Parser.parseModuleDocumentation, - new Domain.NamedDoc( - "test", + new Domain.Doc( "Manages the configuration settings for the widget", "1.0.0", true, @@ -1668,8 +1667,7 @@ describe("Parser-old", () => { expectSuccess( "export const a: number = 1", Parser.parseModuleDocumentation, - new Domain.NamedDoc( - "test", + new Domain.Doc( undefined, undefined, false, diff --git a/test/Printer.test.ts b/test/Printer.test.ts deleted file mode 100644 index b751af6..0000000 --- a/test/Printer.test.ts +++ /dev/null @@ -1,601 +0,0 @@ -import * as Domain from "@effect/docgen/Domain" -import * as Printer from "@effect/docgen/Printer" -import * as Effect from "effect/Effect" -import { flow } from "effect/Function" -import * as assert from "node:assert/strict" -import { describe, it } from "vitest" - -const testCases = { - class: new Domain.Class( - new Domain.NamedDoc( - "A", - "a class", - "1.0.0", - false, - [ - new Domain.Example(`\`\`\`ts -example 1 -\`\`\``) - ], - "category" - ), - "declare class A { constructor() }", - [ - new Domain.Method( - new Domain.NamedDoc( - "hasOwnProperty", - undefined, - "1.0.0", - false, - [], - undefined - ), - ["hasOwnProperty(): boolean"] - ) - ], - [ - new Domain.Method( - new Domain.NamedDoc( - "staticTest", - undefined, - "1.0.0", - false, - [], - undefined - ), - ["static testStatic(): string;"] - ) - ], - [ - new Domain.Property( - new Domain.NamedDoc( - "foo", - undefined, - "1.0.0", - false, - [], - undefined - ), - "foo: string" - ) - ] - ), - constant: new Domain.Constant( - new Domain.NamedDoc( - "test", - "the test", - "1.0.0", - false, - [], - "constants" - ), - "declare const test: string" - ), - export: new Domain.Export( - new Domain.NamedDoc( - "test", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export declare const test: typeof test" - ), - function: new Domain.Function( - new Domain.NamedDoc( - "func", - "a function", - "1.0.0", - true, - [ - new Domain.Example(`\`\`\`ts -example 1 -\`\`\``) - ], - undefined - ), - ["declare const func: (test: string) => string"], - [] - ), - interface: new Domain.Interface( - new Domain.NamedDoc( - "A", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export interface A extends Record {}" - ), - typeAlias: new Domain.TypeAlias( - new Domain.NamedDoc( - "A", - undefined, - "1.0.0", - false, - [], - undefined - ), - "export type A = number" - ), - namespace: new Domain.Namespace( - new Domain.NamedDoc( - "A", - undefined, - "1.0.0", - false, - [], - undefined - ), - [], - [ - new Domain.TypeAlias( - new Domain.NamedDoc( - "B", - undefined, - "1.0.1", - false, - [], - undefined - ), - "export type B = string" - ) - ], - [ - new Domain.Namespace( - new Domain.NamedDoc( - "C", - undefined, - "1.0.2", - false, - [], - undefined - ), - [], - [ - new Domain.TypeAlias( - new Domain.NamedDoc( - "D", - undefined, - "1.0.3", - false, - [], - undefined - ), - "export type D = number" - ) - ], - [] - ) - ] - ) -} - -describe("Markdown", () => { - it("printNamespace", async () => { - const print = flow(Printer.printNamespace, Printer.prettify) - assert.strictEqual( - await Effect.runPromise(print(testCases.namespace, 0)), - `## A (namespace) - -Since v1.0.0 - -### B (type alias) - -**Signature** - -\`\`\`ts -export type B = string -\`\`\` - -Since v1.0.1 - -### C (namespace) - -Since v1.0.2 - -#### D (type alias) - -**Signature** - -\`\`\`ts -export type D = number -\`\`\` - -Since v1.0.3 -` - ) - }) - - it("printClass", async () => { - const print = flow(Printer.printClass, Printer.prettify) - assert.strictEqual( - await Effect.runPromise(print(testCases.class)), - `## A (class) - -a class - -**Example** - -\`\`\`ts -example 1 -\`\`\` - -**Signature** - -\`\`\`ts -declare class A { - constructor() -} -\`\`\` - -Since v1.0.0 - -### staticTest (static method) - -**Signature** - -\`\`\`ts -static testStatic(): string; -\`\`\` - -Since v1.0.0 - -### hasOwnProperty (function) (method) - -**Signature** - -\`\`\`ts -hasOwnProperty(): boolean -\`\`\` - -Since v1.0.0 - -### foo (property) - -**Signature** - -\`\`\`ts -foo: string -\`\`\` - -Since v1.0.0 -` - ) - }) - - it("printConstant", async () => { - const print = flow(Printer.printConstant, Printer.prettify) - assert.strictEqual( - await Effect.runPromise(print(testCases.constant)), - `## test - -the test - -**Signature** - -\`\`\`ts -declare const test: string -\`\`\` - -Since v1.0.0 -` - ) - }) - - it("printExport", async () => { - const print = flow(Printer.printExport, Printer.prettify) - assert.strictEqual( - await Effect.runPromise(print(testCases.export)), - `## test - -**Signature** - -\`\`\`ts -export declare const test: typeof test -\`\`\` - -Since v1.0.0 -` - ) - }) - - it("printFunction", async () => { - const print = flow(Printer.printFunction, Printer.prettify) - assert.strictEqual( - await Effect.runPromise(print(testCases.function)), - `## ~~func~~ - -a function - -**Example** - -\`\`\`ts -example 1 -\`\`\` - -**Signature** - -\`\`\`ts -declare const func: (test: string) => string -\`\`\` - -Since v1.0.0 -` - ) - }) - - it("printInterface", async () => { - const print = flow(Printer.printInterface, Printer.prettify) - assert.strictEqual( - await Effect.runPromise(print(testCases.interface, 0)), - `## A (interface) - -**Signature** - -\`\`\`ts -export interface A extends Record {} -\`\`\` - -Since v1.0.0 -` - ) - }) - - it("printTypeAlias", async () => { - const print = flow(Printer.printTypeAlias, Printer.prettify) - assert.strictEqual( - await Effect.runPromise(print(testCases.typeAlias, 0)), - `## A (type alias) - -**Signature** - -\`\`\`ts -export type A = number -\`\`\` - -Since v1.0.0 -` - ) - - assert.strictEqual( - await Effect.runPromise(print({ ...testCases.typeAlias, since: undefined }, 0)), - `## A (type alias) - -**Signature** - -\`\`\`ts -export type A = number -\`\`\` -` - ) - }) - - it("printModule", async () => { - const doc = new Domain.NamedDoc( - "tests", - undefined, - "1.0.0", - false, - [], - undefined - ) - assert.strictEqual( - await Effect.runPromise(Printer.printModule( - new Domain.Module( - doc, - ["src", "tests.ts"], - [testCases.class], - [testCases.interface], - [testCases.function], - [testCases.typeAlias], - [testCases.constant], - [testCases.export], - [testCases.namespace] - ), - 1 - )), - `--- -title: tests.ts -nav_order: 1 -parent: Modules ---- - -## tests overview - -Since v1.0.0 - ---- - -

Table of contents

- -- [category](#category) - - [A (class)](#a-class) - - [staticTest (static method)](#statictest-static-method) - - [hasOwnProperty (function) (method)](#hasownproperty-function-method) - - [foo (property)](#foo-property) -- [constants](#constants) - - [test](#test) -- [utils](#utils) - - [A (interface)](#a-interface) - - [A (type alias)](#a-type-alias) - - [A (namespace)](#a-namespace) - - [B (type alias)](#b-type-alias) - - [C (namespace)](#c-namespace) - - [D (type alias)](#d-type-alias) - - [~~func~~](#func) - - [test](#test-1) - ---- - -# category - -## A (class) - -a class - -**Example** - -\`\`\`ts -example 1 -\`\`\` - -**Signature** - -\`\`\`ts -declare class A { - constructor() -} -\`\`\` - -Since v1.0.0 - -### staticTest (static method) - -**Signature** - -\`\`\`ts -static testStatic(): string; -\`\`\` - -Since v1.0.0 - -### hasOwnProperty (function) (method) - -**Signature** - -\`\`\`ts -hasOwnProperty(): boolean -\`\`\` - -Since v1.0.0 - -### foo (property) - -**Signature** - -\`\`\`ts -foo: string -\`\`\` - -Since v1.0.0 - -# constants - -## test - -the test - -**Signature** - -\`\`\`ts -declare const test: string -\`\`\` - -Since v1.0.0 - -# utils - -## A (interface) - -**Signature** - -\`\`\`ts -export interface A extends Record {} -\`\`\` - -Since v1.0.0 - -## A (type alias) - -**Signature** - -\`\`\`ts -export type A = number -\`\`\` - -Since v1.0.0 - -## A (namespace) - -Since v1.0.0 - -### B (type alias) - -**Signature** - -\`\`\`ts -export type B = string -\`\`\` - -Since v1.0.1 - -### C (namespace) - -Since v1.0.2 - -#### D (type alias) - -**Signature** - -\`\`\`ts -export type D = number -\`\`\` - -Since v1.0.3 - -## ~~func~~ - -a function - -**Example** - -\`\`\`ts -example 1 -\`\`\` - -**Signature** - -\`\`\`ts -declare const func: (test: string) => string -\`\`\` - -Since v1.0.0 - -## test - -**Signature** - -\`\`\`ts -export declare const test: typeof test -\`\`\` - -Since v1.0.0 -` - ) - - const empty = new Domain.Module(doc, ["src", "tests.ts"], [], [], [], [], [], [], []) - - assert.strictEqual( - await Effect.runPromise(Printer.printModule(empty, 1)), - `--- -title: tests.ts -nav_order: 1 -parent: Modules ---- - -## tests overview - -Since v1.0.0 - ---- - -

Table of contents

- ---- -` - ) - }) -}) From e573f3f6dcc19d9dda1fcddf9defdbeb7715bef0 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 10:57:43 +0100 Subject: [PATCH 28/56] Refactor Printer module with generic model printing function --- src/Printer.ts | 221 ++++++++++++++++++++++---------------------- test/Parser.test.ts | 31 ++++++- 2 files changed, 138 insertions(+), 114 deletions(-) diff --git a/src/Printer.ts b/src/Printer.ts index ab2520f..d67b43e 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -22,11 +22,6 @@ export type Printable = | Domain.Namespace | Domain.Module -const createHeaderPrinter = (level: number) => (content: string): string => { - const prefix = "#".repeat(level) - return `${prefix} ${content}\n\n` -} - /** * @category CLI * @since 0.6.0 @@ -34,11 +29,7 @@ const createHeaderPrinter = (level: number) => (content: string): string => { const Markdown = { bold: (s: string) => `**${s}**`, fence: (content: string) => `\`\`\`ts\n${content}\n\`\`\`\n\n`, - strikethrough: (content: string) => `~~${content}~~`, - h1: createHeaderPrinter(1), - h2: createHeaderPrinter(2), - h3: createHeaderPrinter(3), - h4: createHeaderPrinter(4) + strikethrough: (content: string) => `~~${content}~~` } const printTitle = (s: string, deprecated: boolean, type?: string): string => { @@ -52,82 +43,6 @@ const printTitle = (s: string, deprecated: boolean, type?: string): string => { ) } -const printStaticMethod = (model: Domain.Method): string => { - return printHeaderByIndentation(1) + printTitle(model.name, model.doc.deprecated, "(static method)") + - printOptionalString(model.doc.description) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printSignaturesArray(model.signatures) + - printOptionalSince(model.doc.since) -} - -const printMethod = (model: Domain.Method): string => { - return printHeaderByIndentation(1) + printTitle(model.name, model.doc.deprecated, "(method)") + - printOptionalString(model.doc.description) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printSignaturesArray(model.signatures) + - printOptionalSince(model.doc.since) -} - -const printProperty = (model: Domain.Property): string => { - return printHeaderByIndentation(1) + printTitle(model.name, model.doc.deprecated, "(property)") + - printOptionalString(model.doc.description) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printSignaturesArray([model.signature]) + - printOptionalSince(model.doc.since) -} - -const printModuleDescription = (module: Domain.Module): string => { - return printHeaderByIndentation(0) + printTitle(module.name, module.doc.deprecated, "overview") + - printOptionalString(module.doc.description) + - printExamplesArray(module.doc.examples.map(({ body }) => body)) + - printOptionalSince(module.doc.since) -} - -const printMeta = (title: string, order: number): string => { - return [ - "---", - `\n`, - `title: ${title}`, - `\n`, - `nav_order: ${order}`, - `\n`, - `parent: Modules`, - `\n`, - "---" - ].join("") -} - -/** @internal */ -export const printClass = (model: Domain.Class): string => { - const header = printHeaderByIndentation(0) + printTitle(model.name, model.doc.deprecated, "(class)") + - printOptionalString(model.doc.description) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printSignaturesArray([model.signature]) + - printOptionalSince(model.doc.since) - return header + "\n\n" + - model.staticMethods.map((method) => printStaticMethod(method) + "\n\n").join("") + - model.methods.map((method) => printMethod(method) + "\n\n").join("") + - model.properties.map((property) => printProperty(property) + "\n\n").join("") -} - -/** @internal */ -export const printConstant = (model: Domain.Constant): string => { - return printHeaderByIndentation(0) + printTitle(model.name, model.doc.deprecated) + - printOptionalString(model.doc.description) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printSignaturesArray([model.signature]) + - printOptionalSince(model.doc.since) -} - -/** @internal */ -export const printExport = (model: Domain.Export): string => { - return printHeaderByIndentation(0) + printTitle(model.name, model.doc.deprecated) + - printOptionalString(model.doc.description) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printSignaturesArray([model.signature]) + - printOptionalSince(model.doc.since) -} - const printOptionalString = (s: string | undefined): string => { if (s === undefined) { return "" @@ -135,8 +50,8 @@ const printOptionalString = (s: string | undefined): string => { return `\n\n${s}` } -const printArray = (title: string, ss: ReadonlyArray): string => { - if (ss.length === 0) { +const printArray = (title: string, ss?: ReadonlyArray): string => { + if (ss === undefined || ss.length === 0) { return "" } return `\n\n${Markdown.bold(title)}\n\n${ss.join("\n")}` @@ -149,14 +64,14 @@ const printFence = (s: string): string => { return "```ts\n" + s + "\n```" } -const printSignaturesArray = (signatures: ReadonlyArray): string => { - if (signatures.length === 0) { +const printSignaturesArray = (signatures?: ReadonlyArray): string => { + if (signatures === undefined || signatures.length === 0) { return "" } return `\n\n${Markdown.bold("Signature")}\n\n${printFence(signatures.join("\n"))}` } -const printThrowsArray = (throws: ReadonlyArray): string => printArray("Throws", throws) +const printThrowsArray = (throws?: ReadonlyArray): string => printArray("Throws", throws) const printExamplesArray = (examples: ReadonlyArray): string => { if (examples.length === 0) { @@ -183,40 +98,122 @@ const printHeaderByIndentation = (indentation: number) => { } } +const printModel = (name: string, doc: Domain.Doc, options: { + readonly indentation?: number + readonly postfix?: string + readonly signatures?: ReadonlyArray + readonly throws?: ReadonlyArray +}): string => { + return printHeaderByIndentation(options.indentation ?? 0) + printTitle(name, doc.deprecated, options.postfix) + + printOptionalString(doc.description) + + printThrowsArray(options.throws) + + printExamplesArray(doc.examples.map(({ body }) => body)) + + printSignaturesArray(options.signatures) + + printOptionalSince(doc.since) +} + +const printStaticMethod = (model: Domain.Method): string => { + return printModel(model.name, model.doc, { + indentation: 1, + postfix: "(static method)", + signatures: model.signatures + }) +} + +const printMethod = (model: Domain.Method): string => { + return printModel(model.name, model.doc, { + indentation: 1, + postfix: "(method)", + signatures: model.signatures + }) +} + +const printProperty = (model: Domain.Property): string => { + return printModel(model.name, model.doc, { + indentation: 1, + postfix: "(property)", + signatures: [model.signature] + }) +} + +const printModuleDescription = (module: Domain.Module): string => { + return printModel(module.name, module.doc, { + postfix: "overview" + }) +} + +const printMeta = (title: string, order: number): string => { + return [ + "---", + `\n`, + `title: ${title}`, + `\n`, + `nav_order: ${order}`, + `\n`, + `parent: Modules`, + `\n`, + "---" + ].join("") +} + +/** @internal */ +export const printClass = (model: Domain.Class): string => { + const header = printModel(model.name, model.doc, { + postfix: "(class)", + signatures: [model.signature] + }) + return header + "\n\n" + + model.staticMethods.map((method) => printStaticMethod(method) + "\n\n").join("") + + model.methods.map((method) => printMethod(method) + "\n\n").join("") + + model.properties.map((property) => printProperty(property) + "\n\n").join("") +} + +/** @internal */ +export const printConstant = (model: Domain.Constant): string => { + return printModel(model.name, model.doc, { + signatures: [model.signature] + }) +} + +/** @internal */ +export const printExport = (model: Domain.Export): string => { + return printModel(model.name, model.doc, { + signatures: [model.signature] + }) +} + /** @internal */ export const printFunction = (model: Domain.Function): string => { - return printHeaderByIndentation(0) + printTitle(model.name, model.doc.deprecated) + - printOptionalString(model.doc.description) + - printThrowsArray(model.throws) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printSignaturesArray(model.signatures) + - printOptionalSince(model.doc.since) + return printModel(model.name, model.doc, { + signatures: model.signatures, + throws: model.throws + }) } /** @internal */ export const printInterface = (model: Domain.Interface, indentation: number): string => { - return printHeaderByIndentation(indentation) + printTitle(model.name, model.doc.deprecated, "(interface)") + - printOptionalString(model.doc.description) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printSignaturesArray([model.signature]) + - printOptionalSince(model.doc.since) + return printModel(model.name, model.doc, { + indentation, + postfix: "(interface)", + signatures: [model.signature] + }) } /** @internal */ export const printTypeAlias = (model: Domain.TypeAlias, indentation: number): string => { - return printHeaderByIndentation(indentation) + printTitle(model.name, model.doc.deprecated, "(type alias)") + - printOptionalString(model.doc.description) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printSignaturesArray([model.signature]) + - printOptionalSince(model.doc.since) + return printModel(model.name, model.doc, { + indentation, + postfix: "(type alias)", + signatures: [model.signature] + }) } /** @internal */ export const printNamespace = (model: Domain.Namespace, indentation: number): string => { - const header = printHeaderByIndentation(indentation) + printTitle(model.name, model.doc.deprecated, "(namespace)") + - printOptionalString(model.doc.description) + - printExamplesArray(model.doc.examples.map(({ body }) => body)) + - printOptionalSince(model.doc.since) + const header = printModel(model.name, model.doc, { + indentation, + postfix: "(namespace)" + }) return header + "\n\n" + model.interfaces.map((inter) => printInterface(inter, indentation + 1) + "\n\n").join("") + model.typeAliases.map((typeAlias) => printTypeAlias(typeAlias, indentation + 1) + "\n\n").join("") + @@ -275,7 +272,7 @@ const getModuleComponents = (module: Domain.Module) => { Array.sort(byCategory), Array.map(([category, printables]) => [ - Markdown.h1(category), + `# ${category}`, ...pipe( printables, Array.sort( diff --git a/test/Parser.test.ts b/test/Parser.test.ts index f409759..efee280 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -136,6 +136,35 @@ description... export declare function myfunc() \`\`\` +Since v1.2.0` + ) + }) + + it("throws", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * description... + * @throws \`Error1\` - Description 1 + * @throws \`Error2\` - Description 2 + * @since 1.2.0 + */ + export function myfunc() {}`, + `## myfunc + +description... + +**Throws** + +\`Error1\` - Description 1 +\`Error2\` - Description 2 + +**Signature** + +\`\`\`ts +export declare function myfunc() +\`\`\` + Since v1.2.0` ) }) @@ -1722,8 +1751,6 @@ This is the assert module. Since v1.0.0 # foo - - ## foo This is the foo export. From 87ec9d344c5524a043e6fb0ef7d42ee727de1dad Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 11:34:13 +0100 Subject: [PATCH 29/56] Remove Prettier dependency and simplify markdown generation --- docs/modules/CLI.ts.md | 13 +++----- docs/modules/Configuration.ts.md | 26 +++------------- docs/modules/Core.ts.md | 5 ++- docs/modules/Domain.ts.md | 51 ++++++++++++------------------ docs/modules/Parser.ts.md | 53 ++++++-------------------------- docs/modules/Printer.ts.md | 9 +++--- docs/modules/index.ts.md | 9 ++---- package.json | 3 +- pnpm-lock.yaml | 10 ------ src/Printer.ts | 52 ++++++++++++------------------- test/Parser.test.ts | 6 ++-- 11 files changed, 74 insertions(+), 163 deletions(-) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index ff18c08..fb0b1b0 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -3,7 +3,6 @@ title: CLI.ts nav_order: 1 parent: Modules --- - ## CLI overview Since v0.6.0 @@ -15,8 +14,10 @@ Since v0.6.0 - [CLI](#cli) - [cli](#cli-1) + --- + # CLI ## cli @@ -24,13 +25,7 @@ Since v0.6.0 **Signature** ```ts -export declare const cli: ( - args: ReadonlyArray -) => Effect.Effect< - void, - ValidationError.ValidationError | DocgenError | PlatformError, - Process | CommandExecutor | CliApp.Environment -> +export declare const cli: (args: ReadonlyArray) => Effect.Effect ``` -Since v0.6.0 +Since v0.6.0 \ No newline at end of file diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index 9066771..ca77145 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -3,7 +3,6 @@ title: Configuration.ts nav_order: 2 parent: Modules --- - ## Configuration overview Since v0.6.0 @@ -17,8 +16,10 @@ Since v0.6.0 - [ConfigurationSchema](#configurationschema) - [ConfigurationShape (interface)](#configurationshape-interface) + --- + # service ## Configuration (class) @@ -30,34 +31,15 @@ export declare class Configuration ``` Since v0.6.0 - ## ConfigurationSchema **Signature** ```ts -export declare const ConfigurationSchema: Schema.Struct<{ - $schema: Schema.optional - projectHomepage: Schema.optional - srcDir: Schema.optional - outDir: Schema.optional - theme: Schema.optional - enableSearch: Schema.optional - enforceDescriptions: Schema.optional - enforceExamples: Schema.optional - enforceVersion: Schema.optional - exclude: Schema.optional> - parseCompilerOptions: Schema.optional< - Schema.Union<[typeof Schema.String, Schema.Record$]> - > - examplesCompilerOptions: Schema.optional< - Schema.Union<[typeof Schema.String, Schema.Record$]> - > -}> +export declare const ConfigurationSchema: Schema.Struct<{ $schema: Schema.optional; projectHomepage: Schema.optional; srcDir: Schema.optional; outDir: Schema.optional; theme: Schema.optional; enableSearch: Schema.optional; enforceDescriptions: Schema.optional; enforceExamples: Schema.optional; enforceVersion: Schema.optional; exclude: Schema.optional>; parseCompilerOptions: Schema.optional]>>; examplesCompilerOptions: Schema.optional]>>; }> ``` Since v0.6.0 - ## ConfigurationShape (interface) **Signature** @@ -80,4 +62,4 @@ export interface ConfigurationShape { } ``` -Since v0.6.0 +Since v0.6.0 \ No newline at end of file diff --git a/docs/modules/Core.ts.md b/docs/modules/Core.ts.md index fe3d703..d3001f3 100644 --- a/docs/modules/Core.ts.md +++ b/docs/modules/Core.ts.md @@ -3,7 +3,6 @@ title: Core.ts nav_order: 3 parent: Modules --- - ## Core overview Since v0.6.0 @@ -12,4 +11,8 @@ Since v0.6.0

Table of contents

+ + + --- + diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index a57c84d..f4c72f9 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -3,7 +3,6 @@ title: Domain.ts nav_order: 4 parent: Modules --- - ## Domain overview Since v0.6.0 @@ -14,27 +13,27 @@ Since v0.6.0 - [model](#model) - [Class (class)](#class-class) - - [\_tag (property)](#_tag-property) + - [_tag (property)](#_tag-property) - [Constant (class)](#constant-class) - - [\_tag (property)](#_tag-property-1) + - [_tag (property)](#_tag-property-1) - [Doc (class)](#doc-class) - [DocgenError (class)](#docgenerror-class) - [Example (class)](#example-class) - [Export (class)](#export-class) - - [\_tag (property)](#_tag-property-2) + - [_tag (property)](#_tag-property-2) - [File (class)](#file-class) - [Function (class)](#function-class) - - [\_tag (property)](#_tag-property-3) + - [_tag (property)](#_tag-property-3) - [Interface (class)](#interface-class) - - [\_tag (property)](#_tag-property-4) + - [_tag (property)](#_tag-property-4) - [Method (class)](#method-class) - [Module (class)](#module-class) - - [\_tag (property)](#_tag-property-5) + - [_tag (property)](#_tag-property-5) - [Namespace (class)](#namespace-class) - - [\_tag (property)](#_tag-property-6) + - [_tag (property)](#_tag-property-6) - [Property (class)](#property-class) - [TypeAlias (class)](#typealias-class) - - [\_tag (property)](#_tag-property-7) + - [_tag (property)](#_tag-property-7) - [service](#service) - [Process (class)](#process-class) - [sorting](#sorting) @@ -43,8 +42,10 @@ Since v0.6.0 - [DocgenErrorTypeId](#docgenerrortypeid) - [DocgenErrorTypeId (type alias)](#docgenerrortypeid-type-alias) + --- + # model ## Class (class) @@ -64,7 +65,7 @@ export declare class Class { constructor( Since v0.6.0 -### \_tag (property) +### _tag (property) **Signature** @@ -73,7 +74,6 @@ readonly _tag: "Class" ``` Since v0.6.0 - ## Constant (class) **Signature** @@ -88,7 +88,7 @@ export declare class Constant { constructor( Since v0.6.0 -### \_tag (property) +### _tag (property) **Signature** @@ -97,7 +97,6 @@ readonly _tag: "Constant" ``` Since v0.6.0 - ## Doc (class) **Signature** @@ -113,7 +112,6 @@ export declare class Doc { constructor( ``` Since v0.6.0 - ## DocgenError (class) **Signature** @@ -123,7 +121,6 @@ export declare class DocgenError ``` Since v0.6.0 - ## Example (class) **Signature** @@ -133,7 +130,6 @@ export declare class Example { constructor(readonly body: string) } ``` Since v0.6.0 - ## Export (class) These are manual exports, like: @@ -158,7 +154,7 @@ export declare class Export { constructor( Since v0.6.0 -### \_tag (property) +### _tag (property) **Signature** @@ -167,7 +163,6 @@ readonly _tag: "Export" ``` Since v0.6.0 - ## File (class) Represents a file which can be optionally overwriteable. @@ -183,7 +178,6 @@ export declare class File { constructor( ``` Since v0.6.0 - ## Function (class) **Signature** @@ -199,7 +193,7 @@ export declare class Function { constructor( Since v0.6.0 -### \_tag (property) +### _tag (property) **Signature** @@ -208,7 +202,6 @@ readonly _tag: "Function" ``` Since v0.6.0 - ## Interface (class) **Signature** @@ -223,7 +216,7 @@ export declare class Interface { constructor( Since v0.6.0 -### \_tag (property) +### _tag (property) **Signature** @@ -232,7 +225,6 @@ readonly _tag: "Interface" ``` Since v0.6.0 - ## Method (class) **Signature** @@ -246,7 +238,6 @@ export declare class Method { constructor( ``` Since v0.6.0 - ## Module (class) **Signature** @@ -268,7 +259,7 @@ export declare class Module { constructor( Since v0.6.0 -### \_tag (property) +### _tag (property) **Signature** @@ -277,7 +268,6 @@ readonly _tag: "Module" ``` Since v0.6.0 - ## Namespace (class) **Signature** @@ -294,7 +284,7 @@ export declare class Namespace { constructor( Since v0.6.0 -### \_tag (property) +### _tag (property) **Signature** @@ -303,7 +293,6 @@ readonly _tag: "Namespace" ``` Since v0.6.0 - ## Property (class) **Signature** @@ -317,7 +306,6 @@ export declare class Property { constructor( ``` Since v0.6.0 - ## TypeAlias (class) **Signature** @@ -332,7 +320,7 @@ export declare class TypeAlias { constructor( Since v0.6.0 -### \_tag (property) +### _tag (property) **Signature** @@ -382,7 +370,6 @@ export declare const DocgenErrorTypeId: typeof DocgenErrorTypeId ``` Since v0.6.0 - ## DocgenErrorTypeId (type alias) **Signature** @@ -391,4 +378,4 @@ Since v0.6.0 export type DocgenErrorTypeId = typeof DocgenErrorTypeId ``` -Since v0.6.0 +Since v0.6.0 \ No newline at end of file diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index b699e09..979fbf6 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -3,7 +3,6 @@ title: Parser.ts nav_order: 6 parent: Modules --- - ## Parser overview Since v0.6.0 @@ -23,8 +22,10 @@ Since v0.6.0 - [parseNamespaces](#parsenamespaces) - [parseTypeAliases](#parsetypealiases) + --- + # parsers ## parseClasses @@ -36,89 +37,60 @@ export declare const parseClasses: Effect.Effect +export declare const parseConstants: Effect.Effect ``` Since v0.6.0 - ## parseExports **Signature** ```ts -export declare const parseExports: Effect.Effect< - Domain.Export[], - [string, ...string[]], - Configuration.Configuration | Source -> +export declare const parseExports: Effect.Effect ``` Since v0.6.0 - ## parseFiles **Signature** ```ts -export declare const parseFiles: ( - files: ReadonlyArray -) => Effect.Effect +export declare const parseFiles: (files: ReadonlyArray) => Effect.Effect ``` Since v0.6.0 - ## parseFunctions **Signature** ```ts -export declare const parseFunctions: Effect.Effect< - Domain.Function[], - [string, ...string[]], - Configuration.Configuration | Source -> +export declare const parseFunctions: Effect.Effect ``` Since v0.6.0 - ## parseInterfaces **Signature** ```ts -export declare const parseInterfaces: Effect.Effect< - Domain.Interface[], - [string, ...string[]], - Configuration.Configuration | Source -> +export declare const parseInterfaces: Effect.Effect ``` Since v0.6.0 - ## parseModule **Signature** ```ts -export declare const parseModule: Effect.Effect< - Domain.Module, - string[], - Configuration.Configuration | Path.Path | Source -> +export declare const parseModule: Effect.Effect ``` Since v0.6.0 - ## parseNamespaces **Signature** @@ -128,17 +100,12 @@ export declare const parseNamespaces: Effect.Effect +export declare const parseTypeAliases: Effect.Effect ``` -Since v0.6.0 +Since v0.6.0 \ No newline at end of file diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index 0608931..0b69d39 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -3,7 +3,6 @@ title: Printer.ts nav_order: 7 parent: Modules --- - ## Printer overview Since v0.6.0 @@ -15,8 +14,10 @@ Since v0.6.0 - [printers](#printers) - [printModule](#printmodule) + --- + # printers ## printModule @@ -46,9 +47,9 @@ console.log(Printer.printModule(m, 0)) **Example** (Title 2) -```js twoslash title="Title 2" +~~~js twoslash title="Title 2" export const a: string = "b" -``` +~~~ **Throws** @@ -61,4 +62,4 @@ export const a: string = "b" export declare const printModule: (module: Domain.Module, order: number) => Effect.Effect ``` -Since v0.6.0 +Since v0.6.0 \ No newline at end of file diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index 9183e20..358d08f 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -3,7 +3,6 @@ title: index.ts nav_order: 5 parent: Modules --- - ## index overview Since v0.6.0 @@ -19,8 +18,10 @@ Since v0.6.0 - [From "./Parser.js"](#from-parserjs) - [From "./Printer.js"](#from-printerjs) + --- + # utils ## From "./Configuration.js" @@ -32,7 +33,6 @@ export * as Configuration from "./Configuration.js" ``` Since v0.6.0 - ## From "./Core.js" **Signature** @@ -42,7 +42,6 @@ export * as Core from "./Core.js" ``` Since v0.6.0 - ## From "./Domain.js" **Signature** @@ -52,7 +51,6 @@ export * as Domain from "./Domain.js" ``` Since v0.6.0 - ## From "./Parser.js" **Signature** @@ -62,7 +60,6 @@ export * as Parser from "./Parser.js" ``` Since v0.6.0 - ## From "./Printer.js" **Signature** @@ -71,4 +68,4 @@ Since v0.6.0 export * as Printer from "./Printer.js" ``` -Since v0.6.0 +Since v0.6.0 \ No newline at end of file diff --git a/package.json b/package.json index a839dd8..087756b 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,7 @@ "dependencies": { "@effect/markdown-toc": "^0.1.0", "doctrine": "^3.0.0", - "glob": "^11.0.1", - "prettier": "^3.5.2" + "glob": "^11.0.1" }, "devDependencies": { "@changesets/changelog-github": "^0.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 84107ab..b6f62a0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,9 +17,6 @@ importers: glob: specifier: ^11.0.1 version: 11.0.1 - prettier: - specifier: ^3.5.2 - version: 3.5.2 devDependencies: '@changesets/changelog-github': specifier: ^0.5.0 @@ -2391,11 +2388,6 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.5.2: - resolution: {integrity: sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==} - engines: {node: '>=14'} - hasBin: true - pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -5547,8 +5539,6 @@ snapshots: prettier@2.8.8: {} - prettier@3.5.2: {} - pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 diff --git a/src/Printer.ts b/src/Printer.ts index d67b43e..dab7741 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -8,7 +8,6 @@ import * as Option from "effect/Option" import * as Order from "effect/Order" import * as Record from "effect/Record" import * as String from "effect/String" -import * as Prettier from "prettier" import type * as Domain from "./Domain.js" /** @internal */ @@ -156,16 +155,18 @@ const printMeta = (title: string, order: number): string => { ].join("") } +const addLineBreak = (i: number): string => i === 0 ? "\n\n" : "" + /** @internal */ export const printClass = (model: Domain.Class): string => { const header = printModel(model.name, model.doc, { postfix: "(class)", signatures: [model.signature] }) - return header + "\n\n" + - model.staticMethods.map((method) => printStaticMethod(method) + "\n\n").join("") + - model.methods.map((method) => printMethod(method) + "\n\n").join("") + - model.properties.map((property) => printProperty(property) + "\n\n").join("") + return header + + model.staticMethods.map((method, i) => addLineBreak(i) + printStaticMethod(method)).join("\n\n") + + model.methods.map((method, i) => addLineBreak(i) + printMethod(method)).join("\n\n") + + model.properties.map((property, i) => addLineBreak(i) + printProperty(property)).join("\n\n") } /** @internal */ @@ -272,7 +273,7 @@ const getModuleComponents = (module: Domain.Module) => { Array.sort(byCategory), Array.map(([category, printables]) => [ - `# ${category}`, + `\n# ${category}\n`, ...pipe( printables, Array.sort( @@ -342,32 +343,19 @@ export const printModule = (module: Domain.Module, order: number): Effect.Effect const tableOfContents = (content: string) => "

Table of contents

\n\n" - + toc(content).content + + toc(content, { + bullets: "-" + }).content + "\n\n" - return yield* prettify( - [ - header, - description, - "---\n", - tableOfContents(content), - "---\n", - content - ].join("\n") - ) + const raw = [ + header, + description, + "---\n", + tableOfContents(content), + "---\n", + content + ].join("\n") + return raw + // return yield* prettify(raw) }) - -const defaultPrettierOptions: Prettier.Options = { - parser: "markdown", - semi: false, - singleQuote: false, - printWidth: 120, - trailingComma: "none" -} - -/** @internal */ -export const prettify = (s: string): Effect.Effect => - Effect.tryPromise({ - try: () => Prettier.format(s, defaultPrettierOptions), - catch: identity - }).pipe(Effect.orDie) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index efee280..7b07edf 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -1741,7 +1741,7 @@ import * as assert from 'assert' * * console.log(foo) * - * @category foo + * @category category * @since 1.0.0 */ export const foo = 'foo'`, @@ -1750,7 +1750,9 @@ export const foo = 'foo'`, This is the assert module. Since v1.0.0 -# foo + +# category + ## foo This is the foo export. From eb0304ede5f71ff07c6d5903a9cdcdcc7a3fe90c Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 12:00:51 +0100 Subject: [PATCH 30/56] Add Prettier for markdown formatting in Printer module --- .changeset/silly-insects-draw.md | 2 ++ docs/modules/CLI.ts.md | 13 +++++--- docs/modules/Configuration.ts.md | 26 +++++++++++++--- docs/modules/Core.ts.md | 5 +-- docs/modules/Domain.ts.md | 51 ++++++++++++++++++------------ docs/modules/Parser.ts.md | 53 ++++++++++++++++++++++++++------ docs/modules/Printer.ts.md | 9 +++--- docs/modules/index.ts.md | 9 ++++-- package.json | 3 +- pnpm-lock.yaml | 10 ++++++ src/Core.ts | 2 +- src/Printer.ts | 19 ++++++++++-- 12 files changed, 149 insertions(+), 53 deletions(-) diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index 51790bc..73c8983 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -14,4 +14,6 @@ - Remove File module and integrate File class into Domain module - Move DocgenError from Error module to Domain module - Integrate Process service into Domain module +- Rename Markdown module to Printer and update related imports +- Remove Option usage in Domain - Remove NamedDoc class and update Domain model constructors diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index fb0b1b0..ff18c08 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -3,6 +3,7 @@ title: CLI.ts nav_order: 1 parent: Modules --- + ## CLI overview Since v0.6.0 @@ -14,10 +15,8 @@ Since v0.6.0 - [CLI](#cli) - [cli](#cli-1) - --- - # CLI ## cli @@ -25,7 +24,13 @@ Since v0.6.0 **Signature** ```ts -export declare const cli: (args: ReadonlyArray) => Effect.Effect +export declare const cli: ( + args: ReadonlyArray +) => Effect.Effect< + void, + ValidationError.ValidationError | DocgenError | PlatformError, + Process | CommandExecutor | CliApp.Environment +> ``` -Since v0.6.0 \ No newline at end of file +Since v0.6.0 diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index ca77145..9066771 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -3,6 +3,7 @@ title: Configuration.ts nav_order: 2 parent: Modules --- + ## Configuration overview Since v0.6.0 @@ -16,10 +17,8 @@ Since v0.6.0 - [ConfigurationSchema](#configurationschema) - [ConfigurationShape (interface)](#configurationshape-interface) - --- - # service ## Configuration (class) @@ -31,15 +30,34 @@ export declare class Configuration ``` Since v0.6.0 + ## ConfigurationSchema **Signature** ```ts -export declare const ConfigurationSchema: Schema.Struct<{ $schema: Schema.optional; projectHomepage: Schema.optional; srcDir: Schema.optional; outDir: Schema.optional; theme: Schema.optional; enableSearch: Schema.optional; enforceDescriptions: Schema.optional; enforceExamples: Schema.optional; enforceVersion: Schema.optional; exclude: Schema.optional>; parseCompilerOptions: Schema.optional]>>; examplesCompilerOptions: Schema.optional]>>; }> +export declare const ConfigurationSchema: Schema.Struct<{ + $schema: Schema.optional + projectHomepage: Schema.optional + srcDir: Schema.optional + outDir: Schema.optional + theme: Schema.optional + enableSearch: Schema.optional + enforceDescriptions: Schema.optional + enforceExamples: Schema.optional + enforceVersion: Schema.optional + exclude: Schema.optional> + parseCompilerOptions: Schema.optional< + Schema.Union<[typeof Schema.String, Schema.Record$]> + > + examplesCompilerOptions: Schema.optional< + Schema.Union<[typeof Schema.String, Schema.Record$]> + > +}> ``` Since v0.6.0 + ## ConfigurationShape (interface) **Signature** @@ -62,4 +80,4 @@ export interface ConfigurationShape { } ``` -Since v0.6.0 \ No newline at end of file +Since v0.6.0 diff --git a/docs/modules/Core.ts.md b/docs/modules/Core.ts.md index d3001f3..fe3d703 100644 --- a/docs/modules/Core.ts.md +++ b/docs/modules/Core.ts.md @@ -3,6 +3,7 @@ title: Core.ts nav_order: 3 parent: Modules --- + ## Core overview Since v0.6.0 @@ -11,8 +12,4 @@ Since v0.6.0

Table of contents

- - - --- - diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index f4c72f9..a57c84d 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -3,6 +3,7 @@ title: Domain.ts nav_order: 4 parent: Modules --- + ## Domain overview Since v0.6.0 @@ -13,27 +14,27 @@ Since v0.6.0 - [model](#model) - [Class (class)](#class-class) - - [_tag (property)](#_tag-property) + - [\_tag (property)](#_tag-property) - [Constant (class)](#constant-class) - - [_tag (property)](#_tag-property-1) + - [\_tag (property)](#_tag-property-1) - [Doc (class)](#doc-class) - [DocgenError (class)](#docgenerror-class) - [Example (class)](#example-class) - [Export (class)](#export-class) - - [_tag (property)](#_tag-property-2) + - [\_tag (property)](#_tag-property-2) - [File (class)](#file-class) - [Function (class)](#function-class) - - [_tag (property)](#_tag-property-3) + - [\_tag (property)](#_tag-property-3) - [Interface (class)](#interface-class) - - [_tag (property)](#_tag-property-4) + - [\_tag (property)](#_tag-property-4) - [Method (class)](#method-class) - [Module (class)](#module-class) - - [_tag (property)](#_tag-property-5) + - [\_tag (property)](#_tag-property-5) - [Namespace (class)](#namespace-class) - - [_tag (property)](#_tag-property-6) + - [\_tag (property)](#_tag-property-6) - [Property (class)](#property-class) - [TypeAlias (class)](#typealias-class) - - [_tag (property)](#_tag-property-7) + - [\_tag (property)](#_tag-property-7) - [service](#service) - [Process (class)](#process-class) - [sorting](#sorting) @@ -42,10 +43,8 @@ Since v0.6.0 - [DocgenErrorTypeId](#docgenerrortypeid) - [DocgenErrorTypeId (type alias)](#docgenerrortypeid-type-alias) - --- - # model ## Class (class) @@ -65,7 +64,7 @@ export declare class Class { constructor( Since v0.6.0 -### _tag (property) +### \_tag (property) **Signature** @@ -74,6 +73,7 @@ readonly _tag: "Class" ``` Since v0.6.0 + ## Constant (class) **Signature** @@ -88,7 +88,7 @@ export declare class Constant { constructor( Since v0.6.0 -### _tag (property) +### \_tag (property) **Signature** @@ -97,6 +97,7 @@ readonly _tag: "Constant" ``` Since v0.6.0 + ## Doc (class) **Signature** @@ -112,6 +113,7 @@ export declare class Doc { constructor( ``` Since v0.6.0 + ## DocgenError (class) **Signature** @@ -121,6 +123,7 @@ export declare class DocgenError ``` Since v0.6.0 + ## Example (class) **Signature** @@ -130,6 +133,7 @@ export declare class Example { constructor(readonly body: string) } ``` Since v0.6.0 + ## Export (class) These are manual exports, like: @@ -154,7 +158,7 @@ export declare class Export { constructor( Since v0.6.0 -### _tag (property) +### \_tag (property) **Signature** @@ -163,6 +167,7 @@ readonly _tag: "Export" ``` Since v0.6.0 + ## File (class) Represents a file which can be optionally overwriteable. @@ -178,6 +183,7 @@ export declare class File { constructor( ``` Since v0.6.0 + ## Function (class) **Signature** @@ -193,7 +199,7 @@ export declare class Function { constructor( Since v0.6.0 -### _tag (property) +### \_tag (property) **Signature** @@ -202,6 +208,7 @@ readonly _tag: "Function" ``` Since v0.6.0 + ## Interface (class) **Signature** @@ -216,7 +223,7 @@ export declare class Interface { constructor( Since v0.6.0 -### _tag (property) +### \_tag (property) **Signature** @@ -225,6 +232,7 @@ readonly _tag: "Interface" ``` Since v0.6.0 + ## Method (class) **Signature** @@ -238,6 +246,7 @@ export declare class Method { constructor( ``` Since v0.6.0 + ## Module (class) **Signature** @@ -259,7 +268,7 @@ export declare class Module { constructor( Since v0.6.0 -### _tag (property) +### \_tag (property) **Signature** @@ -268,6 +277,7 @@ readonly _tag: "Module" ``` Since v0.6.0 + ## Namespace (class) **Signature** @@ -284,7 +294,7 @@ export declare class Namespace { constructor( Since v0.6.0 -### _tag (property) +### \_tag (property) **Signature** @@ -293,6 +303,7 @@ readonly _tag: "Namespace" ``` Since v0.6.0 + ## Property (class) **Signature** @@ -306,6 +317,7 @@ export declare class Property { constructor( ``` Since v0.6.0 + ## TypeAlias (class) **Signature** @@ -320,7 +332,7 @@ export declare class TypeAlias { constructor( Since v0.6.0 -### _tag (property) +### \_tag (property) **Signature** @@ -370,6 +382,7 @@ export declare const DocgenErrorTypeId: typeof DocgenErrorTypeId ``` Since v0.6.0 + ## DocgenErrorTypeId (type alias) **Signature** @@ -378,4 +391,4 @@ Since v0.6.0 export type DocgenErrorTypeId = typeof DocgenErrorTypeId ``` -Since v0.6.0 \ No newline at end of file +Since v0.6.0 diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 979fbf6..b699e09 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -3,6 +3,7 @@ title: Parser.ts nav_order: 6 parent: Modules --- + ## Parser overview Since v0.6.0 @@ -22,10 +23,8 @@ Since v0.6.0 - [parseNamespaces](#parsenamespaces) - [parseTypeAliases](#parsetypealiases) - --- - # parsers ## parseClasses @@ -37,60 +36,89 @@ export declare const parseClasses: Effect.Effect +export declare const parseConstants: Effect.Effect< + Domain.Constant[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` Since v0.6.0 + ## parseExports **Signature** ```ts -export declare const parseExports: Effect.Effect +export declare const parseExports: Effect.Effect< + Domain.Export[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` Since v0.6.0 + ## parseFiles **Signature** ```ts -export declare const parseFiles: (files: ReadonlyArray) => Effect.Effect +export declare const parseFiles: ( + files: ReadonlyArray +) => Effect.Effect ``` Since v0.6.0 + ## parseFunctions **Signature** ```ts -export declare const parseFunctions: Effect.Effect +export declare const parseFunctions: Effect.Effect< + Domain.Function[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` Since v0.6.0 + ## parseInterfaces **Signature** ```ts -export declare const parseInterfaces: Effect.Effect +export declare const parseInterfaces: Effect.Effect< + Domain.Interface[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` Since v0.6.0 + ## parseModule **Signature** ```ts -export declare const parseModule: Effect.Effect +export declare const parseModule: Effect.Effect< + Domain.Module, + string[], + Configuration.Configuration | Path.Path | Source +> ``` Since v0.6.0 + ## parseNamespaces **Signature** @@ -100,12 +128,17 @@ export declare const parseNamespaces: Effect.Effect +export declare const parseTypeAliases: Effect.Effect< + Domain.TypeAlias[], + [string, ...string[]], + Configuration.Configuration | Source +> ``` -Since v0.6.0 \ No newline at end of file +Since v0.6.0 diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index 0b69d39..0608931 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -3,6 +3,7 @@ title: Printer.ts nav_order: 7 parent: Modules --- + ## Printer overview Since v0.6.0 @@ -14,10 +15,8 @@ Since v0.6.0 - [printers](#printers) - [printModule](#printmodule) - --- - # printers ## printModule @@ -47,9 +46,9 @@ console.log(Printer.printModule(m, 0)) **Example** (Title 2) -~~~js twoslash title="Title 2" +```js twoslash title="Title 2" export const a: string = "b" -~~~ +``` **Throws** @@ -62,4 +61,4 @@ export const a: string = "b" export declare const printModule: (module: Domain.Module, order: number) => Effect.Effect ``` -Since v0.6.0 \ No newline at end of file +Since v0.6.0 diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index 358d08f..9183e20 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -3,6 +3,7 @@ title: index.ts nav_order: 5 parent: Modules --- + ## index overview Since v0.6.0 @@ -18,10 +19,8 @@ Since v0.6.0 - [From "./Parser.js"](#from-parserjs) - [From "./Printer.js"](#from-printerjs) - --- - # utils ## From "./Configuration.js" @@ -33,6 +32,7 @@ export * as Configuration from "./Configuration.js" ``` Since v0.6.0 + ## From "./Core.js" **Signature** @@ -42,6 +42,7 @@ export * as Core from "./Core.js" ``` Since v0.6.0 + ## From "./Domain.js" **Signature** @@ -51,6 +52,7 @@ export * as Domain from "./Domain.js" ``` Since v0.6.0 + ## From "./Parser.js" **Signature** @@ -60,6 +62,7 @@ export * as Parser from "./Parser.js" ``` Since v0.6.0 + ## From "./Printer.js" **Signature** @@ -68,4 +71,4 @@ Since v0.6.0 export * as Printer from "./Printer.js" ``` -Since v0.6.0 \ No newline at end of file +Since v0.6.0 diff --git a/package.json b/package.json index 087756b..f690f5f 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,8 @@ "dependencies": { "@effect/markdown-toc": "^0.1.0", "doctrine": "^3.0.0", - "glob": "^11.0.1" + "glob": "^11.0.1", + "prettier": "^3.5.3" }, "devDependencies": { "@changesets/changelog-github": "^0.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b6f62a0..7c5dc70 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ importers: glob: specifier: ^11.0.1 version: 11.0.1 + prettier: + specifier: ^3.5.3 + version: 3.5.3 devDependencies: '@changesets/changelog-github': specifier: ^0.5.0 @@ -2388,6 +2391,11 @@ packages: engines: {node: '>=10.13.0'} hasBin: true + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -5539,6 +5547,8 @@ snapshots: prettier@2.8.8: {} + prettier@3.5.3: {} + pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 diff --git a/src/Core.ts b/src/Core.ts index 77bff2e..c772d25 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -120,7 +120,7 @@ const typeCheckAndRunExamples = (modules: ReadonlyArray) => yield* Effect.logInfo("Running examples...") yield* runTsxOnExamples } else { - yield* Effect.logInfo("Skipping running examples") + yield* Effect.logInfo(chalk.gray("Skipping running examples")) } } else { yield* Effect.logInfo("No examples found.") diff --git a/src/Printer.ts b/src/Printer.ts index dab7741..f94450c 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -8,6 +8,7 @@ import * as Option from "effect/Option" import * as Order from "effect/Order" import * as Record from "effect/Record" import * as String from "effect/String" +import * as Prettier from "prettier" import type * as Domain from "./Domain.js" /** @internal */ @@ -356,6 +357,20 @@ export const printModule = (module: Domain.Module, order: number): Effect.Effect "---\n", content ].join("\n") - return raw - // return yield* prettify(raw) + return yield* prettify(raw) }) + +const defaultPrettierOptions: Prettier.Options = { + parser: "markdown", + semi: false, + singleQuote: false, + printWidth: 120, + trailingComma: "none" +} + +/** @internal */ +export const prettify = (s: string): Effect.Effect => + Effect.tryPromise({ + try: () => Prettier.format(s, defaultPrettierOptions), + catch: identity + }).pipe(Effect.orDie) From 8402dc60544aa7137a9e700b72153f259b57dc00 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 12:09:49 +0100 Subject: [PATCH 31/56] Refactor test utilities and simplify source file handling --- test/Configuration.test.ts | 32 +--- test/Parser.test.ts | 304 +++++++++---------------------------- 2 files changed, 74 insertions(+), 262 deletions(-) diff --git a/test/Configuration.test.ts b/test/Configuration.test.ts index cbc9545..801025d 100644 --- a/test/Configuration.test.ts +++ b/test/Configuration.test.ts @@ -10,7 +10,6 @@ import * as Path from "@effect/platform/Path" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Exit from "effect/Exit" -import { hole } from "effect/Function" import * as Layer from "effect/Layer" import * as Option from "effect/Option" import * as assert from "node:assert/strict" @@ -49,36 +48,9 @@ const TestFileSystem = Layer.effect( const exists: FileSystem.FileSystem["exists"] = (filePath) => Effect.succeed(path.basename(filePath) === "docgen.json") - return FileSystem.FileSystem.of({ - watch: hole, - access: hole, - chmod: hole, - chown: hole, - copy: hole, - copyFile: hole, + return FileSystem.makeNoop({ exists, - link: hole, - makeDirectory: hole, - makeTempDirectory: hole, - makeTempDirectoryScoped: hole, - makeTempFile: hole, - makeTempFileScoped: hole, - open: hole, - readDirectory: hole, - readFile: hole, - readFileString, - readLink: hole, - realPath: hole, - remove: hole, - rename: hole, - sink: hole, - stat: hole, - stream: hole, - symlink: hole, - truncate: hole, - utimes: hole, - writeFile: hole, - writeFileString: hole + readFileString }) }) ).pipe(Layer.provide(Path.layer)) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 7b07edf..d53ae52 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -4,7 +4,7 @@ import * as Parser from "@effect/docgen/Parser" import * as Printer from "@effect/docgen/Printer" import { Path } from "@effect/platform" import chalk from "chalk" -import { Effect, Exit } from "effect" +import { Effect, Exit, Predicate } from "effect" import * as assert from "node:assert/strict" import * as ast from "ts-morph" import { describe, it } from "vitest" @@ -32,16 +32,12 @@ const defaultConfig: Configuration.ConfigurationShape = { examplesCompilerOptions: {} } -const makeSourceFromString = (sourceText: string) => +const makeSource = (source: string | ast.SourceFile) => Parser.Source.of({ path: ["test"], - sourceFile: project.createSourceFile(`test-${testCounter++}.ts`, sourceText) - }) - -const makeSourceFromSourceFile = (sourceFile: ast.SourceFile) => - Parser.Source.of({ - path: ["test"], - sourceFile + sourceFile: Predicate.isString(source) + ? project.createSourceFile(`test-${testCounter++}.ts`, source) + : source }) const expectFailure = ( @@ -52,7 +48,7 @@ const expectFailure = ( ) => { assert.deepStrictEqual( eff.pipe( - Effect.provideService(Parser.Source, makeSourceFromString(sourceText)), + Effect.provideService(Parser.Source, makeSource(sourceText)), Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), Effect.provide(Path.layer), Effect.runSyncExit @@ -61,22 +57,6 @@ const expectFailure = ( ) } -const expectSuccess = ( - sourceText: string, - eff: Effect.Effect, - expected: A, - config?: Partial -) => { - const exit = eff.pipe( - Effect.provideService(Parser.Source, makeSourceFromString(sourceText)), - Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), - Effect.provide(Path.layer), - Effect.runSyncExit - ) - assert.ok(exit._tag === "Success") - assert.deepStrictEqual(exit.value, expected) -} - const print = (printables: ReadonlyArray) => { const raw = printables.map((printable) => Printer.print(printable).trim()).join("\n") return Effect.succeed(raw) @@ -90,14 +70,15 @@ const expectMarkdown = async ( Parser.Source | Configuration.Configuration | Path.Path >, sourceText: string, - expected: string + expected: string, + config?: Partial ) => { const exit = await eff.pipe( Effect.flatMap((a) => { return print(Array.isArray(a) ? a : [a]) }), - Effect.provideService(Parser.Source, makeSourceFromString(sourceText)), - Effect.provideService(Configuration.Configuration, defaultConfig), + Effect.provideService(Parser.Source, makeSource(sourceText)), + Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), Effect.provide(Path.layer), Effect.runPromiseExit ) @@ -738,7 +719,7 @@ Since v2.0.0` }` ) const actual = Parser.parseExports.pipe( - Effect.provideService(Parser.Source, makeSourceFromSourceFile(sourceFile)), + Effect.provideService(Parser.Source, makeSource(sourceFile)), Effect.provideService(Configuration.Configuration, defaultConfig), Effect.runSyncExit ) @@ -774,7 +755,7 @@ Since v2.0.0` ) const actual = Parser.parseExports.pipe( - Effect.provideService(Parser.Source, makeSourceFromSourceFile(sourceFile)), + Effect.provideService(Parser.Source, makeSource(sourceFile)), Effect.provideService(Configuration.Configuration, defaultConfig), Effect.runSyncExit ) @@ -811,7 +792,7 @@ Since v2.0.0` ) const actual = Parser.parseExports.pipe( - Effect.provideService(Parser.Source, makeSourceFromSourceFile(sourceFile)), + Effect.provideService(Parser.Source, makeSource(sourceFile)), Effect.provideService(Configuration.Configuration, defaultConfig), Effect.runSyncExit ) @@ -1506,207 +1487,7 @@ Since v1.0.0` }) }) - describe("utils", () => { - describe("getDoc", () => { - it("should parse comment information", () => { - const text = `/** - * description - * @category instances - * @since 1.0.0 - */` - expectSuccess( - "", - Parser.getDoc("name", text), - new Domain.Doc( - "description", - "1.0.0", - false, - [], - "instances" - ) - ) - }) - - it("should fail if an empty comment tag is provided", () => { - const text = `/** - * @category - * @since 1.0.0 - */` - expectFailure( - "", - Parser.getDoc("name", text), - `Missing ${chalk.bold("@category")} tag in ${chalk.bold("test#name")} documentation` - ) - }) - - it("should require a description if `enforceDescriptions` is set to true", () => { - const text = `/** - * @category instances - * @since 1.0.0 - */` - expectFailure( - "", - Parser.getDoc("name", text), - `Missing ${chalk.bold("description")} in ${chalk.bold("test#name")} documentation`, - { - enforceDescriptions: true - } - ) - }) - - it("should require at least one example if `enforceExamples` is set to true", () => { - const text = `/** - * description - * @category instances - * @since 1.0.0 - */` - expectFailure( - "", - Parser.getDoc("name", text), - `Missing ${chalk.bold("@example")} tag in ${chalk.bold("test#name")} documentation`, - { - enforceExamples: true - } - ) - }) - - it("should require at least one non-empty example if `enforceExamples` is set to true", () => { - const text = `/** - * description - * @example - * @category instances - * @since 1.0.0 - */` - expectFailure( - "", - Parser.getDoc("name", text), - `Missing ${chalk.bold("@example")} tag in ${chalk.bold("test#name")} documentation`, - { - enforceExamples: true - } - ) - }) - - it("should allow no since tag if `enforceVersion` is set to false", () => { - const text = `/** -* description -* @category instances -*/` - - expectSuccess( - "", - Parser.getDoc("name", text), - new Domain.Doc( - "description", - undefined, - false, - [], - "instances" - ), - { enforceVersion: false } - ) - }) - }) - - it("parseComment", () => { - assert.deepStrictEqual(Parser.parseComment(""), { - description: undefined, - tags: {} - }) - - assert.deepStrictEqual(Parser.parseComment("/** description */"), { - description: "description", - tags: {} - }) - - assert.deepStrictEqual( - Parser.parseComment("/** description\n * @since 1.0.0\n */"), - { - description: "description", - tags: { - since: ["1.0.0"] - } - } - ) - - assert.deepStrictEqual( - Parser.parseComment("/** description\n * @deprecated\n */"), - { - description: "description", - tags: { - deprecated: [undefined] - } - } - ) - - assert.deepStrictEqual( - Parser.parseComment("/** description\n * @category instance\n */"), - { - description: "description", - tags: { - category: ["instance"] - } - } - ) - }) - - it("stripImportTypes", () => { - assert.deepStrictEqual( - Parser.stripImportTypes( - "{ (refinement: import(\"/Users/giulio/Documents/Projects/github/fp-ts/src/function\").Refinement, onFalse: (a: A) => E): (ma: Either) => Either; (predicate: Predicate
, onFalse: (a: A) => E): (ma: Either) => Either; }" - ), - "{ (refinement: Refinement, onFalse: (a: A) => E): (ma: Either) => Either; (predicate: Predicate, onFalse: (a: A) => E): (ma: Either) => Either; }" - ) - assert.deepStrictEqual( - Parser.stripImportTypes( - "{ (refinementWithIndex: import(\"/Users/giulio/Documents/Projects/github/fp-ts/src/FilterableWithIndex\").RefinementWithIndex): (fa: A[]) => B[]; (predicateWithIndex: import(\"/Users/giulio/Documents/Projects/github/fp-ts/src/FilterableWithIndex\").PredicateWithIndex): (fa: A[]) => A[]; }" - ), - "{ (refinementWithIndex: RefinementWithIndex): (fa: A[]) => B[]; (predicateWithIndex: PredicateWithIndex): (fa: A[]) => A[]; }" - ) - }) - }) -}) - -describe("Parser-old", () => { describe("parseModuleDocumentation", () => { - it("should return a description field and a deprecated field", () => { - expectSuccess( - `/** - * Manages the configuration settings for the widget - * @deprecated - * @since 1.0.0 - */ - /** - * @since 1.2.0 - */ - export const a: number = 1`, - Parser.parseModuleDocumentation, - new Domain.Doc( - "Manages the configuration settings for the widget", - "1.0.0", - true, - [], - undefined - ), - { enforceVersion: true } - ) - }) - - it("should support absence of module documentation when no documentation is enforced", () => { - expectSuccess( - "export const a: number = 1", - Parser.parseModuleDocumentation, - new Domain.Doc( - undefined, - undefined, - false, - [], - undefined - ), - { enforceVersion: false } - ) - }) - it("should return an error when documentation is enforced but no documentation is provided", () => { expectFailure( "export const a: number = 1", @@ -1775,4 +1556,63 @@ Since v1.0.0` ) }) }) + + describe("utils", () => { + it("parseComment", () => { + assert.deepStrictEqual(Parser.parseComment(""), { + description: undefined, + tags: {} + }) + + assert.deepStrictEqual(Parser.parseComment("/** description */"), { + description: "description", + tags: {} + }) + + assert.deepStrictEqual( + Parser.parseComment("/** description\n * @since 1.0.0\n */"), + { + description: "description", + tags: { + since: ["1.0.0"] + } + } + ) + + assert.deepStrictEqual( + Parser.parseComment("/** description\n * @deprecated\n */"), + { + description: "description", + tags: { + deprecated: [undefined] + } + } + ) + + assert.deepStrictEqual( + Parser.parseComment("/** description\n * @category instance\n */"), + { + description: "description", + tags: { + category: ["instance"] + } + } + ) + }) + + it("stripImportTypes", () => { + assert.deepStrictEqual( + Parser.stripImportTypes( + "{ (refinement: import(\"/Users/giulio/Documents/Projects/github/fp-ts/src/function\").Refinement, onFalse: (a: A) => E): (ma: Either) => Either; (predicate: Predicate, onFalse: (a: A) => E): (ma: Either) => Either; }" + ), + "{ (refinement: Refinement, onFalse: (a: A) => E): (ma: Either) => Either; (predicate: Predicate, onFalse: (a: A) => E): (ma: Either) => Either; }" + ) + assert.deepStrictEqual( + Parser.stripImportTypes( + "{ (refinementWithIndex: import(\"/Users/giulio/Documents/Projects/github/fp-ts/src/FilterableWithIndex\").RefinementWithIndex): (fa: A[]) => B[]; (predicateWithIndex: import(\"/Users/giulio/Documents/Projects/github/fp-ts/src/FilterableWithIndex\").PredicateWithIndex): (fa: A[]) => A[]; }" + ), + "{ (refinementWithIndex: RefinementWithIndex): (fa: A[]) => B[]; (predicateWithIndex: PredicateWithIndex): (fa: A[]) => A[]; }" + ) + }) + }) }) From 83c14b5917802963947eaf48adb18e812f7b76d5 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 14:47:57 +0100 Subject: [PATCH 32/56] Refactor markdown generation with improved TOC and front matter handling --- docs/modules/CLI.ts.md | 2 +- docs/modules/Configuration.ts.md | 2 +- docs/modules/Core.ts.md | 2 +- docs/modules/Domain.ts.md | 5 +- docs/modules/Parser.ts.md | 2 +- docs/modules/Printer.ts.md | 6 +- docs/modules/index.ts.md | 32 ++++-- src/Core.ts | 23 ++++- src/Domain.ts | 3 +- src/Parser.ts | 24 ++--- src/Printer.ts | 167 ++++++++++++------------------- test/Parser.test.ts | 19 ++-- 12 files changed, 139 insertions(+), 148 deletions(-) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index ff18c08..b6bc903 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -10,7 +10,7 @@ Since v0.6.0 --- -

Table of contents

+## Exports Grouped by Category - [CLI](#cli) - [cli](#cli-1) diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index 9066771..b145b12 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -10,7 +10,7 @@ Since v0.6.0 --- -

Table of contents

+## Exports Grouped by Category - [service](#service) - [Configuration (class)](#configuration-class) diff --git a/docs/modules/Core.ts.md b/docs/modules/Core.ts.md index fe3d703..7143dcc 100644 --- a/docs/modules/Core.ts.md +++ b/docs/modules/Core.ts.md @@ -10,6 +10,6 @@ Since v0.6.0 --- -

Table of contents

+## Exports Grouped by Category --- diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index a57c84d..d195c3e 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -10,7 +10,7 @@ Since v0.6.0 --- -

Table of contents

+## Exports Grouped by Category - [model](#model) - [Class (class)](#class-class) @@ -152,7 +152,8 @@ export { export declare class Export { constructor( readonly name: string, readonly doc: Doc, - readonly signature: string + readonly signature: string, + readonly namespaceExport: boolean ) } ``` diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index b699e09..deea14b 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -10,7 +10,7 @@ Since v0.6.0 --- -

Table of contents

+## Exports Grouped by Category - [parsers](#parsers) - [parseClasses](#parseclasses) diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index 0608931..68386ae 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -10,7 +10,7 @@ Since v0.6.0 --- -

Table of contents

+## Exports Grouped by Category - [printers](#printers) - [printModule](#printmodule) @@ -41,7 +41,7 @@ import { Option } from "effect" const doc = new Domain.Doc(undefined, "1.0.0", false, [], undefined) const m = new Domain.Module("tests", doc, ["src", "tests.ts"], [], [], [], [], [], [], []) -console.log(Printer.printModule(m, 0)) +console.log(Printer.printModule(m)) ``` **Example** (Title 2) @@ -58,7 +58,7 @@ export const a: string = "b" **Signature** ```ts -export declare const printModule: (module: Domain.Module, order: number) => Effect.Effect +export declare const printModule: (module: Domain.Module) => string ``` Since v0.6.0 diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index 9183e20..f91a0ef 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -10,20 +10,22 @@ Since v0.6.0 --- -

Table of contents

+## Exports Grouped by Category - [utils](#utils) - - [From "./Configuration.js"](#from-configurationjs) - - [From "./Core.js"](#from-corejs) - - [From "./Domain.js"](#from-domainjs) - - [From "./Parser.js"](#from-parserjs) - - [From "./Printer.js"](#from-printerjs) + - [Configuration (namespace export)](#configuration-namespace-export) + - [Core (namespace export)](#core-namespace-export) + - [Domain (namespace export)](#domain-namespace-export) + - [Parser (namespace export)](#parser-namespace-export) + - [Printer (namespace export)](#printer-namespace-export) --- # utils -## From "./Configuration.js" +## Configuration (namespace export) + +Re-exports all named exports from the "./Configuration.js" module as `Configuration`. **Signature** @@ -33,7 +35,9 @@ export * as Configuration from "./Configuration.js" Since v0.6.0 -## From "./Core.js" +## Core (namespace export) + +Re-exports all named exports from the "./Core.js" module as `Core`. **Signature** @@ -43,7 +47,9 @@ export * as Core from "./Core.js" Since v0.6.0 -## From "./Domain.js" +## Domain (namespace export) + +Re-exports all named exports from the "./Domain.js" module as `Domain`. **Signature** @@ -53,7 +59,9 @@ export * as Domain from "./Domain.js" Since v0.6.0 -## From "./Parser.js" +## Parser (namespace export) + +Re-exports all named exports from the "./Parser.js" module as `Parser`. **Signature** @@ -63,7 +71,9 @@ export * as Parser from "./Parser.js" Since v0.6.0 -## From "./Printer.js" +## Printer (namespace export) + +Re-exports all named exports from the "./Printer.js" module as `Printer`. **Signature** diff --git a/src/Core.ts b/src/Core.ts index c772d25..818b773 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -18,7 +18,7 @@ import * as Glob from "glob" import * as Configuration from "./Configuration.js" import * as Domain from "./Domain.js" import * as Parser from "./Parser.js" -import { printModule } from "./Printer.js" +import * as Printer from "./Printer.js" /** * Find all files matching the specified `glob` pattern, optionally excluding @@ -516,11 +516,26 @@ const getModuleMarkdownOutputPath = (module: Domain.Module) => ) const getModuleMarkdownFiles = (modules: ReadonlyArray) => - Effect.forEach(modules, (module, order) => + Effect.forEach(modules, (module, i) => Effect.gen(function*() { const outputPath = yield* getModuleMarkdownOutputPath(module) - const content = yield* printModule(module, order + 1) - return new Domain.File(outputPath, content, true) + const moduleContent = Printer.printModule(module) + const tocgen = yield* Effect.promise(async () => { + // @ts-expect-error + return await import("@effect/markdown-toc").then((m) => m.default) + }).pipe(Effect.orDie) + const toc = tocgen(moduleContent, { bullets: "-" }).content + const frontMatter = Printer.printFrontMatter(module, i + 1) + const content = (frontMatter + "\n\n" + moduleContent).replace( + "", + `--- +## Exports Grouped by Category +${toc} +---` + ) + + const prettified = yield* Printer.prettify(content) + return new Domain.File(outputPath, prettified, true) })) const writeMarkdown = (files: ReadonlyArray) => diff --git a/src/Domain.ts b/src/Domain.ts index 3e7b13d..b29f928 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -182,7 +182,8 @@ export class Export { constructor( readonly name: string, readonly doc: Doc, - readonly signature: string + readonly signature: string, + readonly namespaceExport: boolean ) {} } diff --git a/src/Parser.ts b/src/Parser.ts index f6ab86a..6a535f7 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -7,7 +7,7 @@ import * as doctrine from "doctrine" import * as Array from "effect/Array" import * as Context from "effect/Context" import * as Effect from "effect/Effect" -import { flow, pipe } from "effect/Function" +import { pipe } from "effect/Function" import * as Option from "effect/Option" import * as Order from "effect/Order" import * as Record from "effect/Record" @@ -479,7 +479,8 @@ const parseExportSpecifier = (es: ast.ExportSpecifier) => doc.examples, doc.category ), - signature + signature, + false ) }) @@ -500,17 +501,21 @@ const parseExportStar = ( } const commentRange = ocommentRange.value const text = commentRange.getText() - const doc = yield* getDoc(name, text) + const doc = yield* getDoc(namespace ?? name, text) return new Domain.Export( - `From ${name}`, + namespace ?? name, new Domain.Doc( - doc.description, + doc.description ?? + `Re-exports all named exports from the ${name} module${ + namespace === undefined ? "" : ` as \`${namespace}\`` + }.`, doc.since, doc.deprecated, doc.examples, doc.category ), - signature + signature, + true ) }) @@ -934,12 +939,7 @@ export const parseFiles = (files: ReadonlyArray) => pipe( files, Effect.validateAll(parseFile(project)), - Effect.map( - flow( - Array.filter((module) => !module.doc.deprecated), - sortModulesByPath - ) - ) + Effect.map(sortModulesByPath) ) ) ) diff --git a/src/Printer.ts b/src/Printer.ts index f94450c..157c7fd 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -4,10 +4,10 @@ import * as Array from "effect/Array" import * as Effect from "effect/Effect" import { identity, pipe } from "effect/Function" -import * as Option from "effect/Option" import * as Order from "effect/Order" import * as Record from "effect/Record" import * as String from "effect/String" +import * as NodePath from "node:path" import * as Prettier from "prettier" import type * as Domain from "./Domain.js" @@ -32,22 +32,11 @@ const Markdown = { strikethrough: (content: string) => `~~${content}~~` } -const printTitle = (s: string, deprecated: boolean, type?: string): string => { - const name = s.trim() === "hasOwnProperty" ? `${s} (function)` : s - const title = deprecated ? Markdown.strikethrough(name) : name - return Option.fromNullable(type).pipe( - Option.match({ - onNone: () => title, - onSome: (t) => title + ` ${t}` - }) - ) -} - -const printOptionalString = (s: string | undefined): string => { - if (s === undefined) { +const printOptionalDescription = (description: string | undefined): string => { + if (description === undefined) { return "" } - return `\n\n${s}` + return `\n\n${description}` } const printArray = (title: string, ss?: ReadonlyArray): string => { @@ -57,11 +46,11 @@ const printArray = (title: string, ss?: ReadonlyArray): string => { return `\n\n${Markdown.bold(title)}\n\n${ss.join("\n")}` } -const printFence = (s: string): string => { - if (s.startsWith("```ts") || s.startsWith("~~~ts")) { - return s +const printFence = (code: string): string => { + if (code.startsWith("```ts") || code.startsWith("~~~ts")) { + return code } - return "```ts\n" + s + "\n```" + return "```ts\n" + code + "\n```" } const printSignaturesArray = (signatures?: ReadonlyArray): string => { @@ -98,14 +87,20 @@ const printHeaderByIndentation = (indentation: number) => { } } +const printTitle = (s: string, deprecated: boolean, postfix?: string): string => { + const name = s.trim() === "hasOwnProperty" ? `${s} (function)` : s + const title = deprecated ? Markdown.strikethrough(name) : name + return postfix === undefined ? title : title + ` ${postfix}` +} + const printModel = (name: string, doc: Domain.Doc, options: { readonly indentation?: number - readonly postfix?: string - readonly signatures?: ReadonlyArray - readonly throws?: ReadonlyArray + readonly postfix?: string | undefined + readonly signatures?: ReadonlyArray | undefined + readonly throws?: ReadonlyArray | undefined }): string => { return printHeaderByIndentation(options.indentation ?? 0) + printTitle(name, doc.deprecated, options.postfix) + - printOptionalString(doc.description) + + printOptionalDescription(doc.description) + printThrowsArray(options.throws) + printExamplesArray(doc.examples.map(({ body }) => body)) + printSignaturesArray(options.signatures) + @@ -136,24 +131,14 @@ const printProperty = (model: Domain.Property): string => { }) } -const printModuleDescription = (module: Domain.Module): string => { - return printModel(module.name, module.doc, { - postfix: "overview" - }) -} - -const printMeta = (title: string, order: number): string => { - return [ - "---", - `\n`, - `title: ${title}`, - `\n`, - `nav_order: ${order}`, - `\n`, - `parent: Modules`, - `\n`, - "---" - ].join("") +/** @internal */ +export const printFrontMatter = (module: Domain.Module, order: number): string => { + const filename = NodePath.basename(module.path.join(NodePath.sep)) + return `--- +title: ${filename} +nav_order: ${order} +parent: Modules +---` } const addLineBreak = (i: number): string => i === 0 ? "\n\n" : "" @@ -180,6 +165,7 @@ export const printConstant = (model: Domain.Constant): string => { /** @internal */ export const printExport = (model: Domain.Export): string => { return printModel(model.name, model.doc, { + postfix: model.namespaceExport ? "(namespace export)" : undefined, signatures: [model.signature] }) } @@ -239,10 +225,8 @@ export const print = (p: Printable): string => { return printTypeAlias(p, 0) case "Namespace": return printNamespace(p, 0) - case "Module": { - const { content, description } = getModuleComponents(p) - return description + content - } + case "Module": + return printModule(p) } } @@ -264,34 +248,6 @@ const byCategory = Order.mapInput( ([category]: [string, ...Array]) => category ) -const getModuleComponents = (module: Domain.Module) => { - const description = printModuleDescription(module) + "\n" - - const content = pipe( - getPrintables(module), - Array.groupBy((printable) => printable.doc.category ?? DEFAULT_CATEGORY), - Record.toEntries, - Array.sort(byCategory), - Array.map(([category, printables]) => - [ - `\n# ${category}\n`, - ...pipe( - printables, - Array.sort( - Order.mapInput( - String.Order, - (printable: Printable) => printable.name - ) - ), - Array.map(print) - ) - ].join("\n") - ) - ).join("\n") - - return { description, content } -} - /** * Description... * @@ -313,7 +269,7 @@ const getModuleComponents = (module: Domain.Module) => { * * const doc = new Domain.Doc(undefined, "1.0.0", false, [], undefined) * const m = new Domain.Module("tests", doc, ["src", "tests.ts"], [], [], [], [], [], [], []) - * console.log(Printer.printModule(m, 0)) + * console.log(Printer.printModule(m)) * ``` * * **Example** (Title 2) @@ -328,38 +284,41 @@ const getModuleComponents = (module: Domain.Module) => { * @category printers * @since 0.6.0 */ -export const printModule = (module: Domain.Module, order: number): Effect.Effect => - Effect.gen(function*() { - const header = printMeta(module.path.slice(1).join("/"), order) - - const { content, description } = getModuleComponents(module) - - const toc = yield* Effect.tryPromise({ - try: () => { - // @ts-ignore - return import("@effect/markdown-toc").then((m) => m.default) - }, - catch: identity - }).pipe(Effect.orDie) - - const tableOfContents = (content: string) => - "

Table of contents

\n\n" - + toc(content, { - bullets: "-" - }).content - + "\n\n" - - const raw = [ - header, - description, - "---\n", - tableOfContents(content), - "---\n", - content - ].join("\n") - return yield* prettify(raw) +export const printModule = (module: Domain.Module) => { + const description = printModel(module.name, module.doc, { + postfix: "overview" }) + const content = pipe( + getPrintables(module), + Array.groupBy((printable) => printable.doc.category ?? DEFAULT_CATEGORY), + Record.toEntries, + Array.sort(byCategory), + Array.map(([category, printables]) => + [ + `\n# ${category}\n`, + ...pipe( + printables, + Array.sort( + Order.mapInput( + String.Order, + (printable: Printable) => printable.name + ) + ), + Array.map(print) + ) + ].join("\n") + ) + ).join("\n") + + return ` +${description} + + +${content} +` +} + const defaultPrettierOptions: Prettier.Options = { parser: "markdown", semi: false, diff --git a/test/Parser.test.ts b/test/Parser.test.ts index d53ae52..002a8a8 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -735,7 +735,8 @@ Since v2.0.0` [], undefined ), - "export declare const b: 1" + "export declare const b: 1", + false ) ]) ) @@ -764,15 +765,16 @@ Since v2.0.0` actual, Exit.succeed([ new Domain.Export( - "From './example'", + "'./example'", new Domain.Doc( - undefined, + "Re-exports all named exports from the './example' module.", "1.0.0", false, [], undefined ), - "export * from './example'" + "export * from './example'", + true ) ]) ) @@ -801,15 +803,16 @@ Since v2.0.0` actual, Exit.succeed([ new Domain.Export( - "From './example'", + "example", new Domain.Doc( - undefined, + "Re-exports all named exports from the './example' module as `example`.", "1.0.0", false, [], undefined ), - "export * as example from './example'" + "export * as example from './example'", + true ) ]) ) @@ -1532,6 +1535,8 @@ This is the assert module. Since v1.0.0 + + # category ## foo From 0599be5fad6ebee7473fb991b02c4d11e1da5a1d Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 14:57:58 +0100 Subject: [PATCH 33/56] Update dependencies to latest versions --- package.json | 26 ++-- pnpm-lock.yaml | 406 ++++++++++++++++++++++++------------------------- schema.json | 16 +- 3 files changed, 222 insertions(+), 226 deletions(-) diff --git a/package.json b/package.json index f690f5f..2a4337a 100644 --- a/package.json +++ b/package.json @@ -44,20 +44,20 @@ "devDependencies": { "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.7", - "@effect/cli": "0.56.2", + "@effect/cli": "0.57.0", "@effect/eslint-plugin": "0.2.x", "@effect/language-service": "^0.2.0", - "@effect/platform": "0.77.2", - "@effect/platform-node": "0.73.2", + "@effect/platform": "0.78.0", + "@effect/platform-node": "0.74.0", "@eslint/compat": "^1.2.7", "@types/doctrine": "0.0.9", "@types/glob": "^8.1.0", - "@types/node": "^22.13.5", - "@typescript-eslint/eslint-plugin": "^8.25.0", - "@typescript-eslint/parser": "^8.25.0", - "@vitest/coverage-v8": "^3.0.7", + "@types/node": "^22.13.9", + "@typescript-eslint/eslint-plugin": "^8.26.0", + "@typescript-eslint/parser": "^8.26.0", + "@vitest/coverage-v8": "^3.0.8", "chalk": "^5.4.1", - "effect": "3.13.2", + "effect": "3.13.7", "eslint": "^9.21.0", "eslint-import-resolver-typescript": "^3.8.3", "eslint-plugin-codegen": "^0.29.0", @@ -69,12 +69,12 @@ "tsconfck": "^3.1.5", "tsup": "^8.4.0", "tsx": "^4.19.3", - "typescript": "^5.7.3", - "vite": "^6.2.0", - "vitest": "^3.0.7" + "typescript": "^5.8.2", + "vite": "^6.2.1", + "vitest": "^3.0.8" }, "peerDependencies": { - "tsx": "^4.1.0", - "typescript": "^5.2.2" + "tsx": "^4.19.3", + "typescript": "^5.8.2" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c5dc70..69da43f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,8 +28,8 @@ importers: specifier: ^2.27.7 version: 2.27.7 '@effect/cli': - specifier: 0.56.2 - version: 0.56.2(@effect/platform@0.77.2(effect@3.13.2))(@effect/printer-ansi@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2))(@effect/printer@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2))(effect@3.13.2) + specifier: 0.57.0 + version: 0.57.0(@effect/platform@0.78.0(effect@3.13.7))(@effect/printer-ansi@0.41.2(@effect/typeclass@0.32.2(effect@3.13.7))(effect@3.13.7))(@effect/printer@0.41.2(@effect/typeclass@0.32.2(effect@3.13.7))(effect@3.13.7))(effect@3.13.7) '@effect/eslint-plugin': specifier: 0.2.x version: 0.2.0 @@ -37,11 +37,11 @@ importers: specifier: ^0.2.0 version: 0.2.0 '@effect/platform': - specifier: 0.77.2 - version: 0.77.2(effect@3.13.2) + specifier: 0.78.0 + version: 0.78.0(effect@3.13.7) '@effect/platform-node': - specifier: 0.73.2 - version: 0.73.2(@effect/platform@0.77.2(effect@3.13.2))(effect@3.13.2) + specifier: 0.74.0 + version: 0.74.0(@effect/platform@0.78.0(effect@3.13.7))(effect@3.13.7) '@eslint/compat': specifier: ^1.2.7 version: 1.2.7(eslint@9.21.0) @@ -52,23 +52,23 @@ importers: specifier: ^8.1.0 version: 8.1.0 '@types/node': - specifier: ^22.13.5 - version: 22.13.5 + specifier: ^22.13.9 + version: 22.13.9 '@typescript-eslint/eslint-plugin': - specifier: ^8.25.0 - version: 8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0)(typescript@5.7.3) + specifier: ^8.26.0 + version: 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2) '@typescript-eslint/parser': - specifier: ^8.25.0 - version: 8.25.0(eslint@9.21.0)(typescript@5.7.3) + specifier: ^8.26.0 + version: 8.26.0(eslint@9.21.0)(typescript@5.8.2) '@vitest/coverage-v8': - specifier: ^3.0.7 - version: 3.0.7(vitest@3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0)) + specifier: ^3.0.8 + version: 3.0.8(vitest@3.0.8(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0)) chalk: specifier: ^5.4.1 version: 5.4.1 effect: - specifier: 3.13.2 - version: 3.13.2 + specifier: 3.13.7 + version: 3.13.7 eslint: specifier: ^9.21.0 version: 9.21.0 @@ -80,7 +80,7 @@ importers: version: 0.29.0(eslint@9.21.0) eslint-plugin-import: specifier: ^2.31.0 - version: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0) + version: 2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0) eslint-plugin-simple-import-sort: specifier: ^12.1.1 version: 12.1.1(eslint@9.21.0) @@ -95,22 +95,22 @@ importers: version: 25.0.1 tsconfck: specifier: ^3.1.5 - version: 3.1.5(typescript@5.7.3) + version: 3.1.5(typescript@5.8.2) tsup: specifier: ^8.4.0 - version: 8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@5.7.3)(yaml@2.7.0) + version: 8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@5.8.2)(yaml@2.7.0) tsx: specifier: ^4.19.3 version: 4.19.3 typescript: - specifier: ^5.7.3 - version: 5.7.3 + specifier: ^5.8.2 + version: 5.8.2 vite: - specifier: ^6.2.0 - version: 6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) + specifier: ^6.2.1 + version: 6.2.1(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0) vitest: - specifier: ^3.0.7 - version: 3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) + specifier: ^3.0.8 + version: 3.0.8(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0) publishDirectory: dist packages: @@ -260,13 +260,13 @@ packages: '@dprint/typescript@0.91.8': resolution: {integrity: sha512-tuKn4leCPItox1O4uunHcQF0QllDCvPWklnNQIh2PiWWVtRAGltJJnM4Cwj5AciplosD1Hiz7vAY3ew3crLb3A==} - '@effect/cli@0.56.2': - resolution: {integrity: sha512-hhzH/iCQkT0jNGCSzuJxEASkihKNjWtcYe0cIm/GbQ5O4Mczmhb9cl/U/EPOPwfJBbAgPrO4P6ma3sYY5GuPVw==} + '@effect/cli@0.57.0': + resolution: {integrity: sha512-okk88B9e9bPJ0LrcVcLSAdiOklWwQvw/NFZzr2N8NbRnFPJ2mWy+Op3pvaypZxJT9vwGTDT+tBMqLL9A/lFU8A==} peerDependencies: - '@effect/platform': ^0.77.2 - '@effect/printer': ^0.41.2 - '@effect/printer-ansi': ^0.41.2 - effect: ^3.13.2 + '@effect/platform': ^0.78.0 + '@effect/printer': ^0.41.7 + '@effect/printer-ansi': ^0.41.7 + effect: ^3.13.7 '@effect/eslint-plugin@0.2.0': resolution: {integrity: sha512-PC/hEDGctYGYIjZyhM6kbD4FyHxLgoYNoQNjGkCXcFEzi71vQc3PJKe2JnCgzcUDvr/Nc2qgTVU4ONYwjHzQGA==} @@ -279,22 +279,22 @@ packages: engines: {node: '>=0.10.0'} hasBin: true - '@effect/platform-node-shared@0.27.2': - resolution: {integrity: sha512-U6eXYCOEFTrQSShnzftzLcG4ybauDMLL8uwU7kKS3s6Wzaz7ivALFSVyxgQnaxO3t2QQBePWdd9b3DVsLgiBFw==} + '@effect/platform-node-shared@0.28.0': + resolution: {integrity: sha512-Pxf7i8oKr4yDkOnzhxgQ96so0/joFDXOlbjBCOBBA6wn2ZPj+ycbk/6/B6E4cLURp/Mt9VAEr5Dxn8bj+5PLew==} peerDependencies: - '@effect/platform': ^0.77.2 - effect: ^3.13.2 + '@effect/platform': ^0.78.0 + effect: ^3.13.7 - '@effect/platform-node@0.73.2': - resolution: {integrity: sha512-lO9SlcN7/Fpzu5VE/EKMxkmXt0n0vQ+rCirfGL1cNFcax9klw0A6uAJj2UvDRnX+o5YRlWNAgg5AN5uiGDUy0g==} + '@effect/platform-node@0.74.0': + resolution: {integrity: sha512-gPUcLaqAdMvV+QhkQnqjxxEUcvPvamnpRue2n6b2TMqy00XJAtOdtjYoUaT1ILPEL/3ZYfUSKswivZehV9nEnQ==} peerDependencies: - '@effect/platform': ^0.77.2 - effect: ^3.13.2 + '@effect/platform': ^0.78.0 + effect: ^3.13.7 - '@effect/platform@0.77.2': - resolution: {integrity: sha512-stvroKHJVfjd3XhZJEPUAOgzqu9DH1vnGHIAjfs2ma6Z4qcjVpFXrxa0ZYmwRaWVIFsiADMenkN0I7XrRdAgLw==} + '@effect/platform@0.78.0': + resolution: {integrity: sha512-2vGIfBtPO7zPioVy4wmSbeF0VWfj3GLpB9+6JT7K0lZVeYogHF2GTuPDB87xMILw86Ecz9iR98JuA9Co7PgxKQ==} peerDependencies: - effect: ^3.13.2 + effect: ^3.13.7 '@effect/printer-ansi@0.41.2': resolution: {integrity: sha512-6XQ2VIJ70Pfu9sGYdFt4lon/4IdQSgJr7gr17uRJReARs153gZaNqh+q5pJMSJQ5wvjii1gYioIC/4HH8+o+aQ==} @@ -834,8 +834,8 @@ packages: '@types/node@20.17.19': resolution: {integrity: sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==} - '@types/node@22.13.5': - resolution: {integrity: sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==} + '@types/node@22.13.9': + resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -855,67 +855,67 @@ packages: '@types/yargs@17.0.33': resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - '@typescript-eslint/eslint-plugin@8.25.0': - resolution: {integrity: sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA==} + '@typescript-eslint/eslint-plugin@8.26.0': + resolution: {integrity: sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.25.0': - resolution: {integrity: sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==} + '@typescript-eslint/parser@8.26.0': + resolution: {integrity: sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/scope-manager@8.25.0': - resolution: {integrity: sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==} + '@typescript-eslint/scope-manager@8.26.0': + resolution: {integrity: sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.25.0': - resolution: {integrity: sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==} + '@typescript-eslint/type-utils@8.26.0': + resolution: {integrity: sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/types@8.25.0': - resolution: {integrity: sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==} + '@typescript-eslint/types@8.26.0': + resolution: {integrity: sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.25.0': - resolution: {integrity: sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==} + '@typescript-eslint/typescript-estree@8.26.0': + resolution: {integrity: sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.25.0': - resolution: {integrity: sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==} + '@typescript-eslint/utils@8.26.0': + resolution: {integrity: sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/visitor-keys@8.25.0': - resolution: {integrity: sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==} + '@typescript-eslint/visitor-keys@8.26.0': + resolution: {integrity: sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@vitest/coverage-v8@3.0.7': - resolution: {integrity: sha512-Av8WgBJLTrfLOer0uy3CxjlVuWK4CzcLBndW1Nm2vI+3hZ2ozHututkfc7Blu1u6waeQ7J8gzPK/AsBRnWA5mQ==} + '@vitest/coverage-v8@3.0.8': + resolution: {integrity: sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==} peerDependencies: - '@vitest/browser': 3.0.7 - vitest: 3.0.7 + '@vitest/browser': 3.0.8 + vitest: 3.0.8 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@3.0.7': - resolution: {integrity: sha512-QP25f+YJhzPfHrHfYHtvRn+uvkCFCqFtW9CktfBxmB+25QqWsx7VB2As6f4GmwllHLDhXNHvqedwhvMmSnNmjw==} + '@vitest/expect@3.0.8': + resolution: {integrity: sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==} - '@vitest/mocker@3.0.7': - resolution: {integrity: sha512-qui+3BLz9Eonx4EAuR/i+QlCX6AUZ35taDQgwGkK/Tw6/WgwodSrjN1X2xf69IA/643ZX5zNKIn2svvtZDrs4w==} + '@vitest/mocker@3.0.8': + resolution: {integrity: sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==} peerDependencies: msw: ^2.4.9 vite: ^5.0.0 || ^6.0.0 @@ -925,20 +925,20 @@ packages: vite: optional: true - '@vitest/pretty-format@3.0.7': - resolution: {integrity: sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg==} + '@vitest/pretty-format@3.0.8': + resolution: {integrity: sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==} - '@vitest/runner@3.0.7': - resolution: {integrity: sha512-WeEl38Z0S2ZcuRTeyYqaZtm4e26tq6ZFqh5y8YD9YxfWuu0OFiGFUbnxNynwLjNRHPsXyee2M9tV7YxOTPZl2g==} + '@vitest/runner@3.0.8': + resolution: {integrity: sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==} - '@vitest/snapshot@3.0.7': - resolution: {integrity: sha512-eqTUryJWQN0Rtf5yqCGTQWsCFOQe4eNz5Twsu21xYEcnFJtMU5XvmG0vgebhdLlrHQTSq5p8vWHJIeJQV8ovsA==} + '@vitest/snapshot@3.0.8': + resolution: {integrity: sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==} - '@vitest/spy@3.0.7': - resolution: {integrity: sha512-4T4WcsibB0B6hrKdAZTM37ekuyFZt2cGbEGd2+L0P8ov15J1/HUsUaqkXEQPNAWr4BtPPe1gI+FYfMHhEKfR8w==} + '@vitest/spy@3.0.8': + resolution: {integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==} - '@vitest/utils@3.0.7': - resolution: {integrity: sha512-xePVpCRfooFX3rANQjwoditoXgWb1MaFbzmGuPP59MK6i13mrnDw/yEIyJudLeW6/38mCNcwCiJIGmpDPibAIg==} + '@vitest/utils@3.0.8': + resolution: {integrity: sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -1273,8 +1273,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - effect@3.13.2: - resolution: {integrity: sha512-/w+CPqHDJ33Wq7xC4YKAchrEEPtjvxh563xH9kDTZp99seNYBoBs87vl8DJwartEjj+KLQLP8PzoDne+XmGT2A==} + effect@3.13.7: + resolution: {integrity: sha512-yjDuWX5M34kB38Pwilv8QU956nA2m1a6ws0i+04VQkQJEBPI4GfVhUhtNNFRaqKIOlkqdqzJHCDOwARmaf2XzA==} electron-to-chromium@1.5.107: resolution: {integrity: sha512-dJr1o6yCntRkXElnhsHh1bAV19bo/hKyFf7tCcWgpXbuFIF0Lakjgqv5LRfSDaNzAII8Fnxg2tqgHkgCvxdbxw==} @@ -2857,8 +2857,8 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript@5.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + typescript@5.8.2: + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} engines: {node: '>=14.17'} hasBin: true @@ -2898,13 +2898,13 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - vite-node@3.0.7: - resolution: {integrity: sha512-2fX0QwX4GkkkpULXdT1Pf4q0tC1i1lFOyseKoonavXUNlQ77KpW2XqBGGNIm/J4Ows4KxgGJzDguYVPKwG/n5A==} + vite-node@3.0.8: + resolution: {integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - vite@6.2.0: - resolution: {integrity: sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==} + vite@6.2.1: + resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -2943,16 +2943,16 @@ packages: yaml: optional: true - vitest@3.0.7: - resolution: {integrity: sha512-IP7gPK3LS3Fvn44x30X1dM9vtawm0aesAa2yBIZ9vQf+qB69NXC5776+Qmcr7ohUXIQuLhk7xQR0aSUIDPqavg==} + vitest@3.0.8: + resolution: {integrity: sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@types/debug': ^4.1.12 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.0.7 - '@vitest/ui': 3.0.7 + '@vitest/browser': 3.0.8 + '@vitest/ui': 3.0.8 happy-dom: '*' jsdom: '*' peerDependenciesMeta: @@ -3354,12 +3354,12 @@ snapshots: '@dprint/typescript@0.91.8': {} - '@effect/cli@0.56.2(@effect/platform@0.77.2(effect@3.13.2))(@effect/printer-ansi@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2))(@effect/printer@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2))(effect@3.13.2)': + '@effect/cli@0.57.0(@effect/platform@0.78.0(effect@3.13.7))(@effect/printer-ansi@0.41.2(@effect/typeclass@0.32.2(effect@3.13.7))(effect@3.13.7))(@effect/printer@0.41.2(@effect/typeclass@0.32.2(effect@3.13.7))(effect@3.13.7))(effect@3.13.7)': dependencies: - '@effect/platform': 0.77.2(effect@3.13.2) - '@effect/printer': 0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2) - '@effect/printer-ansi': 0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2) - effect: 3.13.2 + '@effect/platform': 0.78.0(effect@3.13.7) + '@effect/printer': 0.41.2(@effect/typeclass@0.32.2(effect@3.13.7))(effect@3.13.7) + '@effect/printer-ansi': 0.41.2(@effect/typeclass@0.32.2(effect@3.13.7))(effect@3.13.7) + effect: 3.13.7 ini: 4.1.3 toml: 3.0.0 yaml: 2.7.0 @@ -3387,18 +3387,18 @@ snapshots: repeat-string: 1.6.1 strip-color: 0.1.0 - '@effect/platform-node-shared@0.27.2(@effect/platform@0.77.2(effect@3.13.2))(effect@3.13.2)': + '@effect/platform-node-shared@0.28.0(@effect/platform@0.78.0(effect@3.13.7))(effect@3.13.7)': dependencies: - '@effect/platform': 0.77.2(effect@3.13.2) + '@effect/platform': 0.78.0(effect@3.13.7) '@parcel/watcher': 2.5.1 - effect: 3.13.2 + effect: 3.13.7 multipasta: 0.2.5 - '@effect/platform-node@0.73.2(@effect/platform@0.77.2(effect@3.13.2))(effect@3.13.2)': + '@effect/platform-node@0.74.0(@effect/platform@0.78.0(effect@3.13.7))(effect@3.13.7)': dependencies: - '@effect/platform': 0.77.2(effect@3.13.2) - '@effect/platform-node-shared': 0.27.2(@effect/platform@0.77.2(effect@3.13.2))(effect@3.13.2) - effect: 3.13.2 + '@effect/platform': 0.78.0(effect@3.13.7) + '@effect/platform-node-shared': 0.28.0(@effect/platform@0.78.0(effect@3.13.7))(effect@3.13.7) + effect: 3.13.7 mime: 3.0.0 undici: 7.3.0 ws: 8.18.1 @@ -3406,26 +3406,26 @@ snapshots: - bufferutil - utf-8-validate - '@effect/platform@0.77.2(effect@3.13.2)': + '@effect/platform@0.78.0(effect@3.13.7)': dependencies: - effect: 3.13.2 + effect: 3.13.7 find-my-way-ts: 0.1.5 multipasta: 0.2.5 - '@effect/printer-ansi@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2)': + '@effect/printer-ansi@0.41.2(@effect/typeclass@0.32.2(effect@3.13.7))(effect@3.13.7)': dependencies: - '@effect/printer': 0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2) - '@effect/typeclass': 0.32.2(effect@3.13.2) - effect: 3.13.2 + '@effect/printer': 0.41.2(@effect/typeclass@0.32.2(effect@3.13.7))(effect@3.13.7) + '@effect/typeclass': 0.32.2(effect@3.13.7) + effect: 3.13.7 - '@effect/printer@0.41.2(@effect/typeclass@0.32.2(effect@3.13.2))(effect@3.13.2)': + '@effect/printer@0.41.2(@effect/typeclass@0.32.2(effect@3.13.7))(effect@3.13.7)': dependencies: - '@effect/typeclass': 0.32.2(effect@3.13.2) - effect: 3.13.2 + '@effect/typeclass': 0.32.2(effect@3.13.7) + effect: 3.13.7 - '@effect/typeclass@0.32.2(effect@3.13.2)': + '@effect/typeclass@0.32.2(effect@3.13.7)': dependencies: - effect: 3.13.2 + effect: 3.13.7 '@esbuild/aix-ppc64@0.25.0': optional: true @@ -3585,7 +3585,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.13.5 + '@types/node': 22.13.9 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -3784,12 +3784,12 @@ snapshots: '@types/glob@7.1.3': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.13.5 + '@types/node': 22.13.9 '@types/glob@8.1.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.13.5 + '@types/node': 22.13.9 '@types/istanbul-lib-coverage@2.0.6': {} @@ -3821,7 +3821,7 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/node@22.13.5': + '@types/node@22.13.9': dependencies: undici-types: 6.20.0 @@ -3839,84 +3839,84 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.25.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint@9.21.0)(typescript@5.7.3)': + '@typescript-eslint/eslint-plugin@8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint@9.21.0)(typescript@5.8.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.25.0(eslint@9.21.0)(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.25.0 - '@typescript-eslint/type-utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) - '@typescript-eslint/utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.25.0 + '@typescript-eslint/parser': 8.26.0(eslint@9.21.0)(typescript@5.8.2) + '@typescript-eslint/scope-manager': 8.26.0 + '@typescript-eslint/type-utils': 8.26.0(eslint@9.21.0)(typescript@5.8.2) + '@typescript-eslint/utils': 8.26.0(eslint@9.21.0)(typescript@5.8.2) + '@typescript-eslint/visitor-keys': 8.26.0 eslint: 9.21.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3)': + '@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2)': dependencies: - '@typescript-eslint/scope-manager': 8.25.0 - '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.25.0 + '@typescript-eslint/scope-manager': 8.26.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2) + '@typescript-eslint/visitor-keys': 8.26.0 debug: 4.4.0 eslint: 9.21.0 - typescript: 5.7.3 + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.25.0': + '@typescript-eslint/scope-manager@8.26.0': dependencies: - '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/visitor-keys': 8.25.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/visitor-keys': 8.26.0 - '@typescript-eslint/type-utils@8.25.0(eslint@9.21.0)(typescript@5.7.3)': + '@typescript-eslint/type-utils@8.26.0(eslint@9.21.0)(typescript@5.8.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) - '@typescript-eslint/utils': 8.25.0(eslint@9.21.0)(typescript@5.7.3) + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2) + '@typescript-eslint/utils': 8.26.0(eslint@9.21.0)(typescript@5.8.2) debug: 4.4.0 eslint: 9.21.0 - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.25.0': {} + '@typescript-eslint/types@8.26.0': {} - '@typescript-eslint/typescript-estree@8.25.0(typescript@5.7.3)': + '@typescript-eslint/typescript-estree@8.26.0(typescript@5.8.2)': dependencies: - '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/visitor-keys': 8.25.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/visitor-keys': 8.26.0 debug: 4.4.0 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.1 - ts-api-utils: 2.0.1(typescript@5.7.3) - typescript: 5.7.3 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.25.0(eslint@9.21.0)(typescript@5.7.3)': + '@typescript-eslint/utils@8.26.0(eslint@9.21.0)(typescript@5.8.2)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0) - '@typescript-eslint/scope-manager': 8.25.0 - '@typescript-eslint/types': 8.25.0 - '@typescript-eslint/typescript-estree': 8.25.0(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.26.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2) eslint: 9.21.0 - typescript: 5.7.3 + typescript: 5.8.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.25.0': + '@typescript-eslint/visitor-keys@8.26.0': dependencies: - '@typescript-eslint/types': 8.25.0 + '@typescript-eslint/types': 8.26.0 eslint-visitor-keys: 4.2.0 - '@vitest/coverage-v8@3.0.7(vitest@3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0))': + '@vitest/coverage-v8@3.0.8(vitest@3.0.8(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -3930,47 +3930,47 @@ snapshots: std-env: 3.8.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) + vitest: 3.0.8(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - supports-color - '@vitest/expect@3.0.7': + '@vitest/expect@3.0.8': dependencies: - '@vitest/spy': 3.0.7 - '@vitest/utils': 3.0.7 + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.0.7(vite@6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0))': + '@vitest/mocker@3.0.8(vite@6.2.1(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0))': dependencies: - '@vitest/spy': 3.0.7 + '@vitest/spy': 3.0.8 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.1(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0) - '@vitest/pretty-format@3.0.7': + '@vitest/pretty-format@3.0.8': dependencies: tinyrainbow: 2.0.0 - '@vitest/runner@3.0.7': + '@vitest/runner@3.0.8': dependencies: - '@vitest/utils': 3.0.7 + '@vitest/utils': 3.0.8 pathe: 2.0.3 - '@vitest/snapshot@3.0.7': + '@vitest/snapshot@3.0.8': dependencies: - '@vitest/pretty-format': 3.0.7 + '@vitest/pretty-format': 3.0.8 magic-string: 0.30.17 pathe: 2.0.3 - '@vitest/spy@3.0.7': + '@vitest/spy@3.0.8': dependencies: tinyspy: 3.0.2 - '@vitest/utils@3.0.7': + '@vitest/utils@3.0.8': dependencies: - '@vitest/pretty-format': 3.0.7 + '@vitest/pretty-format': 3.0.8 loupe: 3.1.3 tinyrainbow: 2.0.0 @@ -4296,7 +4296,7 @@ snapshots: eastasianwidth@0.2.0: {} - effect@3.13.2: + effect@3.13.7: dependencies: '@standard-schema/spec': 1.0.0 fast-check: 3.23.2 @@ -4457,15 +4457,15 @@ snapshots: stable-hash: 0.0.4 tinyglobby: 0.2.12 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0))(eslint@9.21.0): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0))(eslint@9.21.0): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.25.0(eslint@9.21.0)(typescript@5.7.3) + '@typescript-eslint/parser': 8.26.0(eslint@9.21.0)(typescript@5.8.2) eslint: 9.21.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0) @@ -4500,7 +4500,7 @@ snapshots: - eslint - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint-import-resolver-typescript@3.8.3)(eslint@9.21.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -4511,7 +4511,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.21.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.25.0(eslint@9.21.0)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0))(eslint@9.21.0) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.3(eslint-plugin-import@2.31.0)(eslint@9.21.0))(eslint@9.21.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -4523,7 +4523,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.25.0(eslint@9.21.0)(typescript@5.7.3) + '@typescript-eslint/parser': 8.26.0(eslint@9.21.0)(typescript@5.8.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -5142,7 +5142,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.13.5 + '@types/node': 22.13.9 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -5965,9 +5965,9 @@ snapshots: tree-kill@1.2.2: {} - ts-api-utils@2.0.1(typescript@5.7.3): + ts-api-utils@2.0.1(typescript@5.8.2): dependencies: - typescript: 5.7.3 + typescript: 5.8.2 ts-interface-checker@0.1.13: {} @@ -5976,9 +5976,9 @@ snapshots: '@ts-morph/common': 0.26.1 code-block-writer: 13.0.3 - tsconfck@3.1.5(typescript@5.7.3): + tsconfck@3.1.5(typescript@5.8.2): optionalDependencies: - typescript: 5.7.3 + typescript: 5.8.2 tsconfig-paths@3.15.0: dependencies: @@ -5987,7 +5987,7 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 - tsup@8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@5.7.3)(yaml@2.7.0): + tsup@8.4.0(postcss@8.5.3)(tsx@4.19.3)(typescript@5.8.2)(yaml@2.7.0): dependencies: bundle-require: 5.1.0(esbuild@0.25.0) cac: 6.7.14 @@ -6007,7 +6007,7 @@ snapshots: tree-kill: 1.2.2 optionalDependencies: postcss: 8.5.3 - typescript: 5.7.3 + typescript: 5.8.2 transitivePeerDependencies: - jiti - supports-color @@ -6064,7 +6064,7 @@ snapshots: typedarray@0.0.6: {} - typescript@5.7.3: {} + typescript@5.8.2: {} unbox-primitive@1.1.0: dependencies: @@ -6102,13 +6102,13 @@ snapshots: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - vite-node@3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0): + vite-node@3.0.8(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0): dependencies: cac: 6.7.14 debug: 4.4.0 es-module-lexer: 1.6.0 pathe: 2.0.3 - vite: 6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.1(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0) transitivePeerDependencies: - '@types/node' - jiti @@ -6123,26 +6123,26 @@ snapshots: - tsx - yaml - vite@6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0): + vite@6.2.1(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0): dependencies: esbuild: 0.25.0 postcss: 8.5.3 rollup: 4.34.8 optionalDependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.9 fsevents: 2.3.3 tsx: 4.19.3 yaml: 2.7.0 - vitest@3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0): + vitest@3.0.8(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0): dependencies: - '@vitest/expect': 3.0.7 - '@vitest/mocker': 3.0.7(vite@6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0)) - '@vitest/pretty-format': 3.0.7 - '@vitest/runner': 3.0.7 - '@vitest/snapshot': 3.0.7 - '@vitest/spy': 3.0.7 - '@vitest/utils': 3.0.7 + '@vitest/expect': 3.0.8 + '@vitest/mocker': 3.0.8(vite@6.2.1(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0)) + '@vitest/pretty-format': 3.0.8 + '@vitest/runner': 3.0.8 + '@vitest/snapshot': 3.0.8 + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 chai: 5.2.0 debug: 4.4.0 expect-type: 1.1.0 @@ -6153,11 +6153,11 @@ snapshots: tinyexec: 0.3.2 tinypool: 1.0.2 tinyrainbow: 2.0.0 - vite: 6.2.0(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) - vite-node: 3.0.7(@types/node@22.13.5)(tsx@4.19.3)(yaml@2.7.0) + vite: 6.2.1(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0) + vite-node: 3.0.8(@types/node@22.13.9)(tsx@4.19.3)(yaml@2.7.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.13.5 + '@types/node': 22.13.9 transitivePeerDependencies: - jiti - less diff --git a/schema.json b/schema.json index bd48756..2fadc49 100644 --- a/schema.json +++ b/schema.json @@ -64,11 +64,9 @@ "type": "object", "required": [], "properties": {}, - "patternProperties": { - "": { - "$id": "/schemas/unknown", - "title": "unknown" - } + "additionalProperties": { + "$id": "/schemas/unknown", + "title": "unknown" } } ], @@ -84,11 +82,9 @@ "type": "object", "required": [], "properties": {}, - "patternProperties": { - "": { - "$id": "/schemas/unknown", - "title": "unknown" - } + "additionalProperties": { + "$id": "/schemas/unknown", + "title": "unknown" } } ], From 2c518073fb1618674ece00272864a511ee0d5652 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 15:59:43 +0100 Subject: [PATCH 34/56] Add support for @see JSDoc tag in function documentation --- .changeset/silly-insects-draw.md | 1 + docs/modules/Domain.ts.md | 3 ++- docs/modules/Printer.ts.md | 5 +++++ src/Domain.ts | 3 ++- src/Parser.ts | 13 +++++++++++-- src/Printer.ts | 30 +++++++++++++++++++++++++++++- test/Parser.test.ts | 29 +++++++++++++++++++++++++++++ 7 files changed, 79 insertions(+), 5 deletions(-) diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index 73c8983..fa26034 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -17,3 +17,4 @@ - Rename Markdown module to Printer and update related imports - Remove Option usage in Domain - Remove NamedDoc class and update Domain model constructors +- Add support for @see JSDoc tag in function documentation diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index d195c3e..882886b 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -194,7 +194,8 @@ export declare class Function { constructor( readonly name: string, readonly doc: Doc, readonly signatures: ReadonlyArray, - readonly throws: ReadonlyArray + readonly throws: ReadonlyArray, + readonly sees: ReadonlyArray ) } ``` diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index 68386ae..f5d4fae 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -55,6 +55,11 @@ export const a: string = "b" `Error1` - Description 1 `Error2` - Description 2 +**See** + +- `foo` description1 +- `printFunction` description2 + **Signature** ```ts diff --git a/src/Domain.ts b/src/Domain.ts index b29f928..94a8a8c 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -124,7 +124,8 @@ export class Function { readonly name: string, readonly doc: Doc, readonly signatures: ReadonlyArray, - readonly throws: ReadonlyArray + readonly throws: ReadonlyArray, + readonly sees: ReadonlyArray ) {} } diff --git a/src/Parser.ts b/src/Parser.ts index 6a535f7..fafef78 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -257,6 +257,13 @@ const getFunctionDeclarationJSDocs = ( }) ) +const parseSeeTag = (comment: Comment): Array => { + return Option.fromNullable(comment.tags["see"]).pipe( + Option.map((tags) => tags.filter((tag) => tag !== undefined)), + Option.getOrElse(() => []) + ) +} + const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => Effect.gen(function*() { const source = yield* Source @@ -296,7 +303,8 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => doc.category ), signatures, - throws + throws, + parseSeeTag(comment) ) }) @@ -327,7 +335,8 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => doc.category ), [signature], - throws + throws, + parseSeeTag(comment) ) }) diff --git a/src/Printer.ts b/src/Printer.ts index 157c7fd..97fc599 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -93,15 +93,39 @@ const printTitle = (s: string, deprecated: boolean, postfix?: string): string => return postfix === undefined ? title : title + ` ${postfix}` } +/** + * Extracts the link from a JSDoc link tag. + * + * Given + * + * "{@link bar} description" + * + * returns + * + * "`bar` description" + */ +function parseJSDocLink(text: string): string { + return text.replace(/\{@link\s+([^}]+)\}/, "`$1`") +} + +const printSeesArray = (sees?: ReadonlyArray): string => { + if (sees === undefined || sees.length === 0) { + return "" + } + return `\n\n${Markdown.bold("See")}\n\n${sees.map((see) => `- ${parseJSDocLink(see)}`).join("\n")}` +} + const printModel = (name: string, doc: Domain.Doc, options: { readonly indentation?: number readonly postfix?: string | undefined readonly signatures?: ReadonlyArray | undefined readonly throws?: ReadonlyArray | undefined + readonly sees?: ReadonlyArray | undefined }): string => { return printHeaderByIndentation(options.indentation ?? 0) + printTitle(name, doc.deprecated, options.postfix) + printOptionalDescription(doc.description) + printThrowsArray(options.throws) + + printSeesArray(options.sees) + printExamplesArray(doc.examples.map(({ body }) => body)) + printSignaturesArray(options.signatures) + printOptionalSince(doc.since) @@ -174,7 +198,8 @@ export const printExport = (model: Domain.Export): string => { export const printFunction = (model: Domain.Function): string => { return printModel(model.name, model.doc, { signatures: model.signatures, - throws: model.throws + throws: model.throws, + sees: model.sees }) } @@ -281,6 +306,9 @@ const byCategory = Order.mapInput( * @throws `Error1` - Description 1 * @throws `Error2` - Description 2 * + * @see `foo` description1 + * @see {@link printFunction} description2 + * * @category printers * @since 0.6.0 */ diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 002a8a8..e072c56 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -146,6 +146,35 @@ description... export declare function myfunc() \`\`\` +Since v1.2.0` + ) + }) + + it("sees", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * description... + * @see \`foo\` Description 1 + * @see {@link bar} Description 2 + * @since 1.2.0 + */ + export function myfunc() {}`, + `## myfunc + +description... + +**See** + +- \`foo\` Description 1 +- \`bar\` Description 2 + +**Signature** + +\`\`\`ts +export declare function myfunc() +\`\`\` + Since v1.2.0` ) }) From 696666065208da3a0bf997dbe1930a9bad02b1f7 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 18:29:40 +0100 Subject: [PATCH 35/56] Refactor Domain and Parser modules to simplify documentation handling - Remove `Example` class and use direct string arrays for examples - Modify `Doc` class to use arrays for tags like `since`, `deprecated`, `category` - Update parsing logic to handle multiple tags and remove error-throwing validation - Simplify function and class parsing by removing redundant error checks - Remove chalk dependency and related error formatting - Modify `getDoc` function to return a more flexible `Doc` instance --- src/Checker.ts | 60 +++++++ src/Core.ts | 4 +- src/Domain.ts | 36 ++-- src/Parser.ts | 410 ++++++++++--------------------------------- src/Printer.ts | 40 ++--- test/Checker.test.ts | 195 ++++++++++++++++++++ test/Parser.test.ts | 150 ++-------------- 7 files changed, 403 insertions(+), 492 deletions(-) create mode 100644 src/Checker.ts create mode 100644 test/Checker.test.ts diff --git a/src/Checker.ts b/src/Checker.ts new file mode 100644 index 0000000..7a7f2f1 --- /dev/null +++ b/src/Checker.ts @@ -0,0 +1,60 @@ +/** + * @since 0.6.0 + */ +import type * as Domain from "./Domain.js" + +/** + * @since 0.6.0 + */ +export function checkFunctions(_functions: ReadonlyArray): ReadonlyArray { + return [] +} + +/** + * @since 0.6.0 + */ +export function checkClasses(_classes: ReadonlyArray): ReadonlyArray { + return [] +} + +/** + * @since 0.6.0 + */ +export function checkConstants(_constants: ReadonlyArray): ReadonlyArray { + return [] +} + +/** + * @since 0.6.0 + */ +export function checkInterfaces(_interfaces: ReadonlyArray): ReadonlyArray { + return [] +} + +/** + * @since 0.6.0 + */ +export function checkTypeAliases(_typeAliases: ReadonlyArray): ReadonlyArray { + return [] +} + +/** + * @since 0.6.0 + */ +export function checkNamespaces(_namespaces: ReadonlyArray): ReadonlyArray { + return [] +} + +/** + * @since 0.6.0 + */ +export function checkExports(_exports: ReadonlyArray): ReadonlyArray { + return [] +} + +/** + * @since 0.6.0 + */ +export function checkModule(_module: Domain.Module): ReadonlyArray { + return [] +} diff --git a/src/Core.ts b/src/Core.ts index 818b773..580565f 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -186,7 +186,9 @@ const getExampleFiles = (modules: ReadonlyArray) => (exampleId: string) => (namedDoc: { readonly name: string; readonly doc: Domain.Doc }): ReadonlyArray => { const descriptionExamples = namedDoc.doc.description ? extractFencedCode(namedDoc.doc.description) : [] - const examples = descriptionExamples.concat(namedDoc.doc.examples.flatMap((e) => extractFencedCode(e.body))) + const examples = descriptionExamples.concat( + namedDoc.doc.examples.flatMap((example) => extractFencedCode(example)) + ) return Array.map( examples, (example, i) => { diff --git a/src/Domain.ts b/src/Domain.ts index 94a8a8c..46d1cd7 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -7,14 +7,6 @@ import * as Effect from "effect/Effect" import * as Order from "effect/Order" import * as String from "effect/String" -/** - * @category model - * @since 0.6.0 - */ -export class Example { - constructor(readonly body: string) {} -} - /** * @category model * @since 0.6.0 @@ -22,11 +14,25 @@ export class Example { export class Doc { constructor( readonly description: string | undefined, - readonly since: string | undefined, - readonly deprecated: boolean, - readonly examples: ReadonlyArray, - readonly category: string | undefined + readonly since: ReadonlyArray, + readonly deprecated: ReadonlyArray, + readonly examples: ReadonlyArray, + readonly category: ReadonlyArray, + readonly throws: ReadonlyArray, + readonly sees: ReadonlyArray ) {} + + modifyDescription(description: string | undefined): Doc { + return new Doc( + description, + this.since, + this.deprecated, + this.examples, + this.category, + this.throws, + this.sees + ) + } } /** @@ -37,7 +43,7 @@ export class Module { /** * @since 0.6.0 */ - readonly _tag = "Module" + readonly _tag = "Module" // TODO: remove this constructor( readonly name: string, readonly doc: Doc, @@ -123,9 +129,7 @@ export class Function { constructor( readonly name: string, readonly doc: Doc, - readonly signatures: ReadonlyArray, - readonly throws: ReadonlyArray, - readonly sees: ReadonlyArray + readonly signatures: ReadonlyArray ) {} } diff --git a/src/Parser.ts b/src/Parser.ts index fafef78..9414140 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -2,7 +2,6 @@ * @since 0.6.0 */ import * as Path from "@effect/platform/Path" -import chalk from "chalk" import * as doctrine from "doctrine" import * as Array from "effect/Array" import * as Context from "effect/Context" @@ -25,11 +24,6 @@ export interface SourceShape { /** @internal */ export class Source extends Context.Tag("Source")() {} -interface Comment { - readonly description: string | undefined - readonly tags: Record> -} - const sortByName:
(self: Iterable) => Array = Array.sort( pipe( String.Order, @@ -56,6 +50,13 @@ const hasInternalTag = hasTag("internal") const hasIgnoreTag = hasTag("ignore") +class Comment { + constructor( + readonly description: string | undefined, + readonly tags: Record | undefined> + ) {} +} + /** * @internal */ @@ -63,24 +64,27 @@ export const parseComment = (text: string): Comment => { const annotation: doctrine.Annotation = doctrine.parse(text, { unwrap: true }) + + const description = pipe( + Option.fromNullable(annotation.description), + Option.map(String.trim), + Option.filter(String.isNonEmpty), + Option.getOrUndefined + ) + const tags = pipe( annotation.tags, Array.groupBy((tag) => tag.title), - Record.map( - Array.map((tag) => + Record.map((values) => + Array.map(values, (tag) => pipe( Option.fromNullable(tag.description), - Option.filter(String.isNonEmpty), - Option.getOrUndefined - ) - ) + Option.map(String.trim), + Option.getOrElse(() => "") + )) ) ) - const description = pipe( - Option.fromNullable(annotation.description), - Option.filter(String.isNonEmpty), - Option.getOrUndefined - ) + return { description, tags } } @@ -101,110 +105,31 @@ const isVariableStatement = ( | ast.ForInStatement ): u is ast.VariableStatement => u.getKind() === ast.ts.SyntaxKind.VariableStatement -const getMissingTagError = ( - tag: string, - path: ReadonlyArray, - name: string -): string => `Missing ${chalk.bold(tag)} tag in ${chalk.bold(path.join("/") + "#" + name)} documentation` - -const getSinceTag = (name: string, comment: Comment) => - Effect.gen(function*() { - const config = yield* Configuration.Configuration - const source = yield* Source - const since = Record.get(comment.tags, "since").pipe( - Option.flatMap((tags) => Option.fromNullable(Array.headNonEmpty(tags))), - Option.map(String.trim), - Option.filter(String.isNonEmpty) - ) - if ( - Option.isNone(since) && (config.enforceVersion || Record.has(comment.tags, "since")) - ) { - return yield* Effect.fail(getMissingTagError("@since", source.path, name)) - } - return Option.getOrUndefined(since) - }) - -const getCategoryTag = (name: string, comment: Comment) => - Effect.gen(function*() { - const source = yield* Source - const category = Record.get(comment.tags, "category").pipe( - Option.flatMap((tags) => Option.fromNullable(Array.headNonEmpty(tags))), - Option.map(String.trim), - Option.filter(String.isNonEmpty) - ) - if ( - Option.isNone(category) && (Record.has(comment.tags, "category")) - ) { - return yield* Effect.fail(getMissingTagError("@category", source.path, name)) - } - return Option.getOrUndefined(category) - }) - -const getDescription = (name: string, comment: Comment) => - Effect.gen(function*() { - const config = yield* Configuration.Configuration - const source = yield* Source - if (comment.description === undefined && config.enforceDescriptions) { - return yield* Effect.fail( - `Missing ${chalk.bold("description")} in ${chalk.bold(source.path.join("/") + "#" + name)} documentation` - ) - } - return comment.description - }) - -const parseExample = (body: string): Domain.Example => { - return new Domain.Example(body) -} - -const getExamplesTag = (name: string, comment: Comment, isModule: boolean) => - Effect.gen(function*() { - const config = yield* Configuration.Configuration - const source = yield* Source - const examples = Record.get(comment.tags, "example").pipe( - Option.map((tags) => tags.filter((tag) => tag !== undefined).map(parseExample)), - Option.getOrElse(() => []) - ) - if (Array.isEmptyArray(examples) && config.enforceExamples && !isModule) { - return yield* Effect.fail(getMissingTagError("@example", source.path, name)) - } - return examples - }) - /** * @internal */ -export const getDoc = (name: string, text: string, isModule = false) => - Effect.gen(function*() { - const comment = parseComment(text) - const since = yield* getSinceTag(name, comment) - const category = yield* getCategoryTag(name, comment) - const description = yield* getDescription(name, comment) - const examples = yield* getExamplesTag(name, comment, isModule) - const deprecated = Option.isSome(Record.get(comment.tags, "deprecated")) - return new Domain.Doc( - description, - since, - deprecated, - examples, - category - ) - }) +export const getDoc = (text: string) => { + const comment = parseComment(text) + return new Domain.Doc( + comment.description, + comment.tags["since"] ?? [], + comment.tags["deprecated"] ?? [], + comment.tags["example"] ?? [], + comment.tags["category"] ?? [], + comment.tags["throws"] ?? [], + comment.tags["see"] ?? [] + ) +} const parseInterfaceDeclaration = (id: ast.InterfaceDeclaration) => Effect.gen(function*() { const name = id.getName() const text = getJSDocText(id.getJsDocs()) - const doc = yield* getDoc(name, text) + const doc = getDoc(text) const signature = id.getText() return new Domain.Interface( name, - new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ), + doc, signature ) }) @@ -214,7 +139,7 @@ const parseInterfaceDeclarations = (interfaces: ReadonlyArray id.isExported() && shouldNotIgnore(id.getJsDocs()) ) - return Effect.validateAll(exportedInterfaces, parseInterfaceDeclaration).pipe( + return Effect.forEach(exportedInterfaces, parseInterfaceDeclaration).pipe( Effect.map(sortByName) ) } @@ -257,25 +182,11 @@ const getFunctionDeclarationJSDocs = ( }) ) -const parseSeeTag = (comment: Comment): Array => { - return Option.fromNullable(comment.tags["see"]).pipe( - Option.map((tags) => tags.filter((tag) => tag !== undefined)), - Option.getOrElse(() => []) - ) -} - const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => Effect.gen(function*() { - const source = yield* Source - const name = yield* pipe( - Option.fromNullable(fd.getName()), - Option.flatMap(Option.liftPredicate((name) => name.length > 0)), - Effect.mapError( - () => `Missing ${chalk.bold("function name")} in module ${chalk.bold(source.path.join("/"))}` - ) - ) + const name = fd.getName() const text = getJSDocText(getFunctionDeclarationJSDocs(fd)) - const doc = yield* getDoc(name, text) + const doc = getDoc(text) const signatures = pipe( fd.getOverloads(), Array.matchRight({ @@ -287,24 +198,10 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => ) }) ) - // TODO: parseComment is called twice, here and in getDoc - const comment = parseComment(text) - const throws: Array = Option.fromNullable(comment.tags["throws"]).pipe( - Option.map((tags) => tags.filter((tag) => tag !== undefined)), - Option.getOrElse(() => []) - ) return new Domain.Function( - name, - new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ), - signatures, - throws, - parseSeeTag(comment) + name ?? "anonymous function", + doc, + signatures ) }) @@ -313,30 +210,16 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => const vs: any = vd.getParent().getParent() const name = vd.getName() const text = getJSDocText(vs.getJsDocs()) - const doc = yield* getDoc(name, text) + const doc = getDoc(text) const signature = `export declare const ${name}: ${ stripImportTypes( vd.getType().getText(vd) ) }` - // TODO: parseComment is called twice, here and in getDoc - const comment = parseComment(text) - const throws: Array = Option.fromNullable(comment.tags["throws"]).pipe( - Option.map((tags) => tags.filter((tag) => tag !== undefined)), - Option.getOrElse(() => []) - ) return new Domain.Function( name, - new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ), - [signature], - throws, - parseSeeTag(comment) + doc, + [signature] ) }) @@ -373,8 +256,8 @@ const getFunctionDeclarations = Effect.gen(function*() { */ export const parseFunctions = Effect.gen(function*() { const { arrows, functions } = yield* getFunctionDeclarations - const functionDeclarations = yield* Effect.validateAll(functions, parseFunctionDeclaration) - const functionVariableDeclarations = yield* Effect.validateAll(arrows, parseFunctionVariableDeclaration) + const functionDeclarations = yield* Effect.forEach(functions, parseFunctionDeclaration) + const functionVariableDeclarations = yield* Effect.forEach(arrows, parseFunctionVariableDeclaration) return [...functionDeclarations, ...functionVariableDeclarations] }) @@ -382,17 +265,11 @@ const parseTypeAliasDeclaration = (ta: ast.TypeAliasDeclaration) => Effect.gen(function*() { const name = ta.getName() const text = getJSDocText(ta.getJsDocs()) - const doc = yield* getDoc(name, text) + const doc = getDoc(text) const signature = ta.getText() return new Domain.TypeAlias( name, - new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ), + doc, signature ) }) @@ -402,7 +279,7 @@ const parseTypeAliasDeclarations = (typeAliases: ReadonlyArray tad.isExported() && shouldNotIgnore(tad.getJsDocs()) ) - return Effect.validateAll(exportedTypeAliases, parseTypeAliasDeclaration).pipe( + return Effect.forEach(exportedTypeAliases, parseTypeAliasDeclaration).pipe( Effect.map(sortByName) ) } @@ -421,18 +298,12 @@ const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => const vs: any = vd.getParent().getParent() const name = vd.getName() const text = getJSDocText(vs.getJsDocs()) - const doc = yield* getDoc(name, text) + const doc = getDoc(text) const type = stripImportTypes(vd.getType().getText(vd)) const signature = `export declare const ${name}: ${type}` return new Domain.Constant( name, - new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ), + doc, signature ) }) @@ -461,33 +332,20 @@ export const parseConstants = Effect.gen(function*() { } ) ) - return yield* Effect.validateAll(variableDeclarations, parseConstantVariableDeclaration) + return yield* Effect.forEach(variableDeclarations, parseConstantVariableDeclaration) }) const parseExportSpecifier = (es: ast.ExportSpecifier) => Effect.gen(function*() { - const source = yield* Source const name = es.compilerNode.name.text const type = stripImportTypes(es.getType().getText(es)) const ocommentRange = Array.head(es.getLeadingCommentRanges()) - if (Option.isNone(ocommentRange)) { - return yield* Effect.fail( - `Missing ${chalk.bold(name)} documentation in ${chalk.bold(source.path.join("/"))}` - ) - } - const commentRange = ocommentRange.value - const text = commentRange.getText() - const doc = yield* getDoc(name, text) + const text = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) + const doc = getDoc(text) const signature = `export declare const ${name}: ${type}` return new Domain.Export( name, - new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ), + doc, signature, false ) @@ -495,33 +353,19 @@ const parseExportSpecifier = (es: ast.ExportSpecifier) => const parseExportStar = ( ed: ast.ExportDeclaration -): Effect.Effect => +) => Effect.gen(function*() { - const source = yield* Source const es = ed.getModuleSpecifier()! const name = es.getText() const namespace = ed.getNamespaceExport()?.getName() const signature = `export *${namespace === undefined ? "" : ` as ${namespace}`} from ${name}` const ocommentRange = Array.head(ed.getLeadingCommentRanges()) - if (Option.isNone(ocommentRange)) { - return yield* Effect.fail( - `Missing ${chalk.bold(signature)} documentation in ${chalk.bold(source.path.join("/"))}` - ) - } - const commentRange = ocommentRange.value - const text = commentRange.getText() - const doc = yield* getDoc(namespace ?? name, text) + const text = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) + const doc = getDoc(text) return new Domain.Export( namespace ?? name, - new Domain.Doc( - doc.description ?? - `Re-exports all named exports from the ${name} module${ - namespace === undefined ? "" : ` as \`${namespace}\`` - }.`, - doc.since, - doc.deprecated, - doc.examples, - doc.category + doc.modifyDescription( + `Re-exports all named exports from the ${name} module${namespace === undefined ? "" : ` as \`${namespace}\``}.` ), signature, true @@ -531,12 +375,9 @@ const parseExportStar = ( const parseNamedExports = (ed: ast.ExportDeclaration) => { const namedExports = ed.getNamedExports() if (namedExports.length === 0) { - return parseExportStar(ed).pipe(Effect.mapBoth({ - onFailure: Array.of, - onSuccess: Array.of - })) + return parseExportStar(ed).pipe(Effect.map(Array.of)) } - return Effect.validateAll(namedExports, parseExportSpecifier) + return Effect.forEach(namedExports, parseExportSpecifier) } /** @@ -545,42 +386,29 @@ const parseNamedExports = (ed: ast.ExportDeclaration) => { */ export const parseExports = pipe( Effect.map(Source, (source) => source.sourceFile.getExportDeclarations()), - Effect.flatMap((exportDeclarations) => Effect.validateAll(exportDeclarations, parseNamedExports)), - Effect.mapBoth({ - onFailure: Array.flatten, - onSuccess: Array.flatten - }) + Effect.flatMap((exportDeclarations) => Effect.forEach(exportDeclarations, parseNamedExports)), + Effect.map(Array.flatten) ) const parseModuleDeclaration = ( ed: ast.ModuleDeclaration -): Effect.Effect, Source | Configuration.Configuration> => +): Effect.Effect => Effect.flatMap(Source, (_source) => { const name = ed.getName() const text = getJSDocText(ed.getJsDocs()) - const getInfo = pipe( - getDoc(name, text), - Effect.mapError((e) => [e]) - ) + const doc = getDoc(text) const getInterfaces = parseInterfaceDeclarations(ed.getInterfaces()) const getTypeAliases = parseTypeAliasDeclarations( ed.getTypeAliases() ) const getNamespaces = parseModuleDeclarations(ed.getModules()) return Effect.gen(function*() { - const info = yield* getInfo const interfaces = yield* getInterfaces const typeAliases = yield* getTypeAliases const namespaces = yield* getNamespaces return new Domain.Namespace( name, - new Domain.Doc( - info.description, - info.since, - info.deprecated, - info.examples, - info.category - ), + doc, interfaces, typeAliases, namespaces @@ -593,7 +421,7 @@ const parseModuleDeclarations = (namespaces: ReadonlyArray md.isExported() && shouldNotIgnore(md.getJsDocs()) ) - return Effect.validateAll(exportedNamespaces, parseModuleDeclaration).pipe( + return Effect.forEach(exportedNamespaces, parseModuleDeclaration).pipe( Effect.mapBoth({ onFailure: Array.flatten, onSuccess: sortByName @@ -605,11 +433,10 @@ const parseModuleDeclarations = (namespaces: ReadonlyArray, - Array, - Source | Configuration.Configuration -> = Effect.flatMap(Source, (source) => parseModuleDeclarations(source.sourceFile.getModules())) +export const parseNamespaces = Effect.flatMap( + Source, + (source) => parseModuleDeclarations(source.sourceFile.getModules()) +) const getTypeParameters = ( tps: ReadonlyArray @@ -640,7 +467,7 @@ const parseMethod = (md: ast.MethodDeclaration) => ) if (shouldNotIgnore(jsdocs)) { const text = getJSDocText(jsdocs) - const doc = yield* getDoc(name, text) + const doc = getDoc(text) const signatures = pipe( overloads, Array.matchRight({ @@ -655,13 +482,7 @@ const parseMethod = (md: ast.MethodDeclaration) => return Option.some( new Domain.Method( name, - new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ), + doc, signatures ) ) @@ -669,11 +490,11 @@ const parseMethod = (md: ast.MethodDeclaration) => return Option.none() }) -const parseProperty = (classname: string) => (pd: ast.PropertyDeclaration) => +const parseProperty = (pd: ast.PropertyDeclaration) => Effect.gen(function*() { const name = pd.getName() const text = getJSDocText(pd.getJsDocs()) - const doc = yield* getDoc(`${classname}#${name}`, text) + const doc = getDoc(text) const type = stripImportTypes(pd.getType().getText(pd)) const readonly = pipe( Option.fromNullable( @@ -687,13 +508,7 @@ const parseProperty = (classname: string) => (pd: ast.PropertyDeclaration) => const signature = `${readonly}${name}: ${type}` return new Domain.Property( name, - new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ), + doc, signature ) }) @@ -708,7 +523,7 @@ const parseProperties = (name: string, c: ast.ClassDeclaration) => { Option.isNone ) ) - return Effect.validateAll(properties, parseProperty(name)) + return Effect.forEach(properties, parseProperty) } /** @@ -728,16 +543,9 @@ export const getConstructorDeclarationSignature = ( }) ) -const getClassName = (c: ast.ClassDeclaration) => - Effect.flatMap(Source, (source) => - Effect.mapError( - Option.fromNullable(c.getName()), - () => [`Missing ${chalk.bold("class name")} in module ${chalk.bold(source.path.join("/"))}`] - )) - const getClassDoc = (name: string, c: ast.ClassDeclaration) => { const text = getJSDocText(c.getJsDocs()) - return getDoc(name, text).pipe(Effect.mapError(Array.of)) + return getDoc(text) } const getClassDeclarationSignature = (name: string, c: ast.ClassDeclaration) => @@ -761,29 +569,23 @@ const getClassDeclarationSignature = (name: string, c: ast.ClassDeclaration) => const parseClass = (c: ast.ClassDeclaration) => Effect.gen(function*() { - const name = yield* getClassName(c) - const doc = yield* getClassDoc(name, c) + const name = c.getName() ?? "anonymous class" + const doc = getClassDoc(name, c) const signature = yield* getClassDeclarationSignature(name, c) const methods = yield* pipe( c.getInstanceMethods(), - Effect.validateAll(parseMethod), + Effect.forEach(parseMethod), Effect.map(Array.getSomes) ) const staticMethods = yield* pipe( c.getStaticMethods(), - Effect.validateAll(parseMethod), + Effect.forEach(parseMethod), Effect.map(Array.getSomes) ) const properties = yield* parseProperties(name, c) return new Domain.Class( name, - new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ), + doc, signature, methods, staticMethods, @@ -801,11 +603,8 @@ export const parseClasses = Effect.gen(function*() { source.sourceFile.getClasses(), (cd) => cd.isExported() && shouldNotIgnore(cd.getJsDocs()) ) - return yield* Effect.validateAll(exportedClasses, parseClass).pipe( - Effect.mapBoth({ - onFailure: Array.flatten, - onSuccess: sortByName - }) + return yield* Effect.forEach(exportedClasses, parseClass).pipe( + Effect.map(sortByName) ) }) @@ -813,48 +612,19 @@ export const parseClasses = Effect.gen(function*() { * @internal */ export const parseModuleDocumentation = Effect.gen(function*() { - const config = yield* Configuration.Configuration const source = yield* Source - // if any of the settings enforcing documentation are set to `true`, then - // a module should have associated documentation - const isDocumentationRequired = config.enforceDescriptions || config.enforceVersion const statements = source.sourceFile.getStatements() const ofirstStatement = Array.head(statements) - if (Option.isNone(ofirstStatement)) { - if (isDocumentationRequired) { - return yield* Effect.fail( - [`Empty ${chalk.bold(source.path.join("/"))} module`] - ) - } - } else { + if (Option.isSome(ofirstStatement)) { const firstStatement = ofirstStatement.value const ocommentRange = Array.head(firstStatement.getLeadingCommentRanges()) - if (Option.isNone(ocommentRange)) { - if (isDocumentationRequired) { - return yield* Effect.fail( - [`Missing ${chalk.bold("documentation")} in ${chalk.bold(source.path.join("/"))} module`] - ) - } - } else { + if (Option.isSome(ocommentRange)) { const commentRange = ocommentRange.value const text = commentRange.getText() - const doc = yield* getDoc("", text, true).pipe(Effect.mapError(Array.of)) - return new Domain.Doc( - doc.description, - doc.since, - doc.deprecated, - doc.examples, - doc.category - ) + return getDoc(text) } } - return new Domain.Doc( - undefined, - undefined, - false, - [], - undefined - ) + return getDoc("") }) /** diff --git a/src/Printer.ts b/src/Printer.ts index 97fc599..47c333f 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -69,11 +69,11 @@ const printExamplesArray = (examples: ReadonlyArray): string => { return examples.map((ex) => "\n\n**Example**\n\n" + printFence(ex)).join("") } -const printOptionalSince = (since: string | undefined): string => { - if (since === undefined) { +const printOptionalSince = (since: ReadonlyArray): string => { + if (since.length === 0) { return "" } - return `\n\nSince v${since}` + return `\n\nSince v${since.join(", ")}` } const printHeaderByIndentation = (indentation: number) => { @@ -87,9 +87,9 @@ const printHeaderByIndentation = (indentation: number) => { } } -const printTitle = (s: string, deprecated: boolean, postfix?: string): string => { +const printTitle = (s: string, deprecated: ReadonlyArray, postfix?: string): string => { const name = s.trim() === "hasOwnProperty" ? `${s} (function)` : s - const title = deprecated ? Markdown.strikethrough(name) : name + const title = deprecated.length > 0 ? Markdown.strikethrough(name) : name return postfix === undefined ? title : title + ` ${postfix}` } @@ -119,14 +119,12 @@ const printModel = (name: string, doc: Domain.Doc, options: { readonly indentation?: number readonly postfix?: string | undefined readonly signatures?: ReadonlyArray | undefined - readonly throws?: ReadonlyArray | undefined - readonly sees?: ReadonlyArray | undefined }): string => { return printHeaderByIndentation(options.indentation ?? 0) + printTitle(name, doc.deprecated, options.postfix) + printOptionalDescription(doc.description) + - printThrowsArray(options.throws) + - printSeesArray(options.sees) + - printExamplesArray(doc.examples.map(({ body }) => body)) + + printThrowsArray(doc.throws) + + printSeesArray(doc.sees) + + printExamplesArray(doc.examples) + printSignaturesArray(options.signatures) + printOptionalSince(doc.since) } @@ -197,9 +195,7 @@ export const printExport = (model: Domain.Export): string => { /** @internal */ export const printFunction = (model: Domain.Function): string => { return printModel(model.name, model.doc, { - signatures: model.signatures, - throws: model.throws, - sees: model.sees + signatures: model.signatures }) } @@ -255,6 +251,13 @@ export const print = (p: Printable): string => { } } +const DEFAULT_CATEGORY = "utils" + +const byCategory = Order.mapInput( + String.Order, + ([category]: [string, ...Array]) => category +) + const getPrintables = (module: Domain.Module): ReadonlyArray => Array.flatten([ module.classes, @@ -266,13 +269,6 @@ const getPrintables = (module: Domain.Module): ReadonlyArray => module.namespaces ]) -const DEFAULT_CATEGORY = "utils" - -const byCategory = Order.mapInput( - String.Order, - ([category]: [string, ...Array]) => category -) - /** * Description... * @@ -319,7 +315,9 @@ export const printModule = (module: Domain.Module) => { const content = pipe( getPrintables(module), - Array.groupBy((printable) => printable.doc.category ?? DEFAULT_CATEGORY), + Array.groupBy((printable) => + printable.doc.category.length === 0 ? DEFAULT_CATEGORY : printable.doc.category.join(", ") + ), Record.toEntries, Array.sort(byCategory), Array.map(([category, printables]) => diff --git a/test/Checker.test.ts b/test/Checker.test.ts new file mode 100644 index 0000000..edcd25f --- /dev/null +++ b/test/Checker.test.ts @@ -0,0 +1,195 @@ +import * as Checker from "@effect/docgen/Checker" +import * as Configuration from "@effect/docgen/Configuration" +import * as Parser from "@effect/docgen/Parser" +import { Path } from "@effect/platform" +import chalk from "chalk" +import { Effect, Exit, Predicate } from "effect" +import * as assert from "node:assert/strict" +import * as ast from "ts-morph" +import { describe, it } from "vitest" + +let testCounter = 0 + +const project = new ast.Project({ + compilerOptions: { strict: true }, + useInMemoryFileSystem: true +}) + +const defaultConfig: Configuration.ConfigurationShape = { + projectName: "docgen", + projectHomepage: "https://github.com/effect-ts/docgen", + srcDir: "src", + outDir: "docs", + theme: "pmarsceill/just-the-docs", + enableSearch: true, + enforceDescriptions: false, + enforceExamples: false, + enforceVersion: true, + runExamples: false, + exclude: [], + parseCompilerOptions: {}, + examplesCompilerOptions: {} +} + +const makeSource = (source: string | ast.SourceFile) => + Parser.Source.of({ + path: ["test"], + sourceFile: Predicate.isString(source) + ? project.createSourceFile(`test-${testCounter++}.ts`, source) + : source + }) + +const expectFailure = ( + sourceText: string, + parser: Effect.Effect, + checker: (a: A) => ReadonlyArray, + failure: E, + config?: Partial +) => { + assert.deepStrictEqual( + parser.pipe( + Effect.map(checker), + Effect.provideService(Parser.Source, makeSource(sourceText)), + Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), + Effect.provide(Path.layer), + Effect.runSyncExit + ), + Exit.succeed(failure) + ) +} + +describe.skip("Checker", () => { + describe("checkFunctions", () => { + it("should raise an error if the function is anonymous", () => { + expectFailure( + `export function(a: number, b: number): number { return a + b }`, + Parser.parseFunctions, + Checker.checkFunctions, + [`Missing ${chalk.bold("function name")} in module ${chalk.bold("test")}`] + ) + }) + }) + + describe("checkExports", () => { + it("should raise an error if `@since` tag is missing in export", () => { + expectFailure( + "export { a }", + Parser.parseExports, + Checker.checkExports, + [ + `Missing ${chalk.bold("a")} documentation in ${chalk.bold("test")}` + ] + ) + }) + }) + + describe("checkNamespaces", () => { + it("should raise an error if the namespace is not well documented", () => { + expectFailure( + "export namespace A {}", + Parser.parseNamespaces, + Checker.checkNamespaces, + [ + `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#A")} documentation` + ] + ) + }) + + it("should raise an error if the interface is not well documented", () => { + expectFailure( + ` + /** + * @since 1.0.0 + */ + export namespace A { + export interface B {} + } + `, + Parser.parseNamespaces, + Checker.checkNamespaces, + [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] + ) + }) + + it("should raise an error if the type alias is not well documented", () => { + expectFailure( + ` + /** + * @since 1.0.0 + */ + export namespace A { + export type B = string + } + `, + Parser.parseNamespaces, + Checker.checkNamespaces, + [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] + ) + }) + + it("should raise an error if the namespace is not well documented", () => { + expectFailure( + ` + /** + * @since 1.0.0 + */ + export namespace A { + export namespace B {} + } + `, + Parser.parseNamespaces, + Checker.checkNamespaces, + [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] + ) + }) + }) + + describe("checkClasses", () => { + it("should raise an error if the class is anonymous", () => { + expectFailure( + `export class {}`, + Parser.parseClasses, + Checker.checkClasses, + [ + `Missing ${chalk.bold("class name")} in module ${chalk.bold("test")}` + ] + ) + }) + + it("should raise an error if an `@since` tag is missing in a module", () => { + expectFailure( + `export class MyClass {}`, + Parser.parseClasses, + Checker.checkClasses, + [ + `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass")} documentation` + ] + ) + }) + it("should raise an error if `@since` is missing in a property", () => { + expectFailure( + `/** + * @since 1.0.0 + */ + export class MyClass { + readonly _A!: A + }`, + Parser.parseClasses, + Checker.checkClasses, + [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass#_A")} documentation`] + ) + }) + }) + + describe("checkNamespaces", () => { + }) + + describe("checkNamespaces", () => { + }) + + describe("checkNamespaces", () => { + }) + + describe("checkNamespaces", () => { + }) +}) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index e072c56..fb4729e 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -3,7 +3,6 @@ import * as Domain from "@effect/docgen/Domain" import * as Parser from "@effect/docgen/Parser" import * as Printer from "@effect/docgen/Printer" import { Path } from "@effect/platform" -import chalk from "chalk" import { Effect, Exit, Predicate } from "effect" import * as assert from "node:assert/strict" import * as ast from "ts-morph" @@ -40,23 +39,6 @@ const makeSource = (source: string | ast.SourceFile) => : source }) -const expectFailure = ( - sourceText: string, - eff: Effect.Effect, - failure: E, - config?: Partial -) => { - assert.deepStrictEqual( - eff.pipe( - Effect.provideService(Parser.Source, makeSource(sourceText)), - Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), - Effect.provide(Path.layer), - Effect.runSyncExit - ), - Exit.fail(failure) - ) -} - const print = (printables: ReadonlyArray) => { const raw = printables.map((printable) => Printer.print(printable).trim()).join("\n") return Effect.succeed(raw) @@ -91,14 +73,6 @@ const expectMarkdown = async ( describe("Parser", () => { describe("parseFunctions", () => { - it("should raise an error if the function is anonymous", () => { - expectFailure( - `export function(a: number, b: number): number { return a + b }`, - Parser.parseFunctions, - [`Missing ${chalk.bold("function name")} in module ${chalk.bold("test")}`] - ) - }) - it("description", async () => { await expectMarkdown( Parser.parseFunctions, @@ -728,12 +702,6 @@ Since v2.0.0` ) }) - it("should raise an error if `@since` tag is missing in export", () => { - expectFailure("export { a }", Parser.parseExports, [ - `Missing ${chalk.bold("a")} documentation in ${chalk.bold("test")}` - ]) - }) - it("should handle a single re-export", () => { project.createSourceFile("a.ts", `export const a = 1`) const sourceFile = project.createSourceFile( @@ -759,10 +727,12 @@ Since v2.0.0` "b", new Domain.Doc( undefined, - "1.0.0", - false, + ["1.0.0"], + [], + [], + [], [], - undefined + [] ), "export declare const b: 1", false @@ -797,10 +767,12 @@ Since v2.0.0` "'./example'", new Domain.Doc( "Re-exports all named exports from the './example' module.", - "1.0.0", - false, + ["1.0.0"], [], - undefined + [], + [], + [], + [] ), "export * from './example'", true @@ -835,10 +807,12 @@ Since v2.0.0` "example", new Domain.Doc( "Re-exports all named exports from the './example' module as `example`.", - "1.0.0", - false, + ["1.0.0"], + [], [], - undefined + [], + [], + [] ), "export * as example from './example'", true @@ -940,12 +914,6 @@ Since v1.0.0` ) }) - it("should raise an error if the namespace is not well documented", () => { - expectFailure("export namespace A {}", Parser.parseNamespaces, [ - `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#A")} documentation` - ]) - }) - it("should parse an empty Namespace", async () => { await expectMarkdown( Parser.parseNamespaces, @@ -979,21 +947,6 @@ Since v1.0.0` ) }) - it("should raise an error if the interface is not well documented", () => { - expectFailure( - ` - /** - * @since 1.0.0 - */ - export namespace A { - export interface B {} - } - `, - Parser.parseNamespaces, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] - ) - }) - it("should parse an interface", async () => { await expectMarkdown( Parser.parseNamespaces, @@ -1047,21 +1000,6 @@ Since v1.0.0` ) }) - it("should raise an error if the type alias is not well documented", () => { - expectFailure( - ` - /** - * @since 1.0.0 - */ - export namespace A { - export type B = string - } - `, - Parser.parseNamespaces, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] - ) - }) - it("should parse a type alias", async () => { await expectMarkdown( Parser.parseNamespaces, @@ -1111,21 +1049,6 @@ Since v1.0.0` ) }) - it("should raise an error if the namespace is not well documented", () => { - expectFailure( - ` - /** - * @since 1.0.0 - */ - export namespace A { - export namespace B {} - } - `, - Parser.parseNamespaces, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] - ) - }) - it("should parse a namespace", async () => { await expectMarkdown( Parser.parseNamespaces, @@ -1168,18 +1091,6 @@ Since v1.0.2` }) describe("parseClasses", () => { - it("should raise an error if the class is anonymous", () => { - expectFailure(`export class {}`, Parser.parseClasses, [ - `Missing ${chalk.bold("class name")} in module ${chalk.bold("test")}` - ]) - }) - - it("should raise an error if an `@since` tag is missing in a module", () => { - expectFailure(`export class MyClass {}`, Parser.parseClasses, [ - `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass")} documentation` - ]) - }) - it("should ignore internal classes", async () => { await expectMarkdown( Parser.parseClasses, @@ -1199,19 +1110,6 @@ Since v1.0.2` ) }) - it("should raise an error if `@since` is missing in a property", () => { - expectFailure( - `/** - * @since 1.0.0 - */ - export class MyClass { - readonly _A!: A - }`, - Parser.parseClasses, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass#_A")} documentation`] - ) - }) - it("should skip ignored properties", async () => { await expectMarkdown( Parser.parseClasses, @@ -1519,23 +1417,7 @@ Since v1.0.0` }) }) - describe("parseModuleDocumentation", () => { - it("should return an error when documentation is enforced but no documentation is provided", () => { - expectFailure( - "export const a: number = 1", - Parser.parseModuleDocumentation, - [`Missing ${chalk.bold("documentation")} in ${chalk.bold("test")} module`] - ) - }) - }) - describe("parseModule", () => { - it("should raise an error if `@since` tag is missing", async () => { - expectFailure(`import * as assert from 'assert'`, Parser.parseModule, [ - `Missing ${chalk.bold("documentation")} in ${chalk.bold("test")} module` - ]) - }) - it("should not require an example for modules when `enforceExamples` is set to true", async () => { await expectMarkdown( Parser.parseModule, @@ -1618,7 +1500,7 @@ Since v1.0.0` { description: "description", tags: { - deprecated: [undefined] + deprecated: [""] } } ) From b1554aa3ea0122fee0e0a194b739bcb51dabc9f2 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Fri, 7 Mar 2025 19:22:53 +0100 Subject: [PATCH 36/56] Update documentation module navigation order and remove sorting logic - Adjust nav_order for documentation modules to maintain correct sequence - Remove sorting logic from Parser and Printer modules - Simplify module parsing and printing by removing redundant sorting operations - Update test cases to remove sorting-related expectations --- docs/modules/CLI.ts.md | 2 +- docs/modules/Checker.ts.md | 107 ++++++++++++ docs/modules/Configuration.ts.md | 2 +- docs/modules/Core.ts.md | 2 +- docs/modules/Domain.ts.md | 31 ++-- docs/modules/Parser.ts.md | 42 +---- docs/modules/Printer.ts.md | 4 +- docs/modules/index.ts.md | 2 +- src/Domain.ts | 9 +- src/Parser.ts | 290 ++++++++++++++++--------------- src/Printer.ts | 14 +- test/Checker.test.ts | 22 --- test/Parser.test.ts | 49 ++---- 13 files changed, 318 insertions(+), 258 deletions(-) create mode 100644 docs/modules/Checker.ts.md diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index b6bc903..763a954 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -1,6 +1,6 @@ --- title: CLI.ts -nav_order: 1 +nav_order: 2 parent: Modules --- diff --git a/docs/modules/Checker.ts.md b/docs/modules/Checker.ts.md new file mode 100644 index 0000000..f484100 --- /dev/null +++ b/docs/modules/Checker.ts.md @@ -0,0 +1,107 @@ +--- +title: Checker.ts +nav_order: 1 +parent: Modules +--- + +## Checker overview + +Since v0.6.0 + +--- + +## Exports Grouped by Category + +- [utils](#utils) + - [checkClasses](#checkclasses) + - [checkConstants](#checkconstants) + - [checkExports](#checkexports) + - [checkFunctions](#checkfunctions) + - [checkInterfaces](#checkinterfaces) + - [checkModule](#checkmodule) + - [checkNamespaces](#checknamespaces) + - [checkTypeAliases](#checktypealiases) + +--- + +# utils + +## checkClasses + +**Signature** + +```ts +export declare function checkClasses(_classes: ReadonlyArray): ReadonlyArray +``` + +Since v0.6.0 + +## checkConstants + +**Signature** + +```ts +export declare function checkConstants(_constants: ReadonlyArray): ReadonlyArray +``` + +Since v0.6.0 + +## checkExports + +**Signature** + +```ts +export declare function checkExports(_exports: ReadonlyArray): ReadonlyArray +``` + +Since v0.6.0 + +## checkFunctions + +**Signature** + +```ts +export declare function checkFunctions(_functions: ReadonlyArray): ReadonlyArray +``` + +Since v0.6.0 + +## checkInterfaces + +**Signature** + +```ts +export declare function checkInterfaces(_interfaces: ReadonlyArray): ReadonlyArray +``` + +Since v0.6.0 + +## checkModule + +**Signature** + +```ts +export declare function checkModule(_module: Domain.Module): ReadonlyArray +``` + +Since v0.6.0 + +## checkNamespaces + +**Signature** + +```ts +export declare function checkNamespaces(_namespaces: ReadonlyArray): ReadonlyArray +``` + +Since v0.6.0 + +## checkTypeAliases + +**Signature** + +```ts +export declare function checkTypeAliases(_typeAliases: ReadonlyArray): ReadonlyArray +``` + +Since v0.6.0 diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index b145b12..c413772 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -1,6 +1,6 @@ --- title: Configuration.ts -nav_order: 2 +nav_order: 3 parent: Modules --- diff --git a/docs/modules/Core.ts.md b/docs/modules/Core.ts.md index 7143dcc..b600915 100644 --- a/docs/modules/Core.ts.md +++ b/docs/modules/Core.ts.md @@ -1,6 +1,6 @@ --- title: Core.ts -nav_order: 3 +nav_order: 4 parent: Modules --- diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 882886b..cad913a 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -1,6 +1,6 @@ --- title: Domain.ts -nav_order: 4 +nav_order: 5 parent: Modules --- @@ -18,8 +18,8 @@ Since v0.6.0 - [Constant (class)](#constant-class) - [\_tag (property)](#_tag-property-1) - [Doc (class)](#doc-class) + - [modifyDescription (method)](#modifydescription-method) - [DocgenError (class)](#docgenerror-class) - - [Example (class)](#example-class) - [Export (class)](#export-class) - [\_tag (property)](#_tag-property-2) - [File (class)](#file-class) @@ -105,31 +105,32 @@ Since v0.6.0 ```ts export declare class Doc { constructor( readonly description: string | undefined, - readonly since: string | undefined, - readonly deprecated: boolean, - readonly examples: ReadonlyArray, - readonly category: string | undefined + readonly since: ReadonlyArray, + readonly deprecated: ReadonlyArray, + readonly examples: ReadonlyArray, + readonly category: ReadonlyArray, + readonly throws: ReadonlyArray, + readonly sees: ReadonlyArray, + readonly tags: Record | undefined> ) } ``` Since v0.6.0 -## DocgenError (class) +### modifyDescription (method) **Signature** ```ts -export declare class DocgenError +modifyDescription(description: string | undefined): Doc ``` -Since v0.6.0 - -## Example (class) +## DocgenError (class) **Signature** ```ts -export declare class Example { constructor(readonly body: string) } +export declare class DocgenError ``` Since v0.6.0 @@ -193,9 +194,7 @@ Since v0.6.0 export declare class Function { constructor( readonly name: string, readonly doc: Doc, - readonly signatures: ReadonlyArray, - readonly throws: ReadonlyArray, - readonly sees: ReadonlyArray + readonly signatures: ReadonlyArray ) } ``` @@ -257,7 +256,7 @@ Since v0.6.0 export declare class Module { constructor( readonly name: string, readonly doc: Doc, - readonly path: ReadonlyArray, + readonly path: Array.NonEmptyReadonlyArray, readonly classes: ReadonlyArray, readonly interfaces: ReadonlyArray, readonly functions: ReadonlyArray, diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index deea14b..cc1917c 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -1,6 +1,6 @@ --- title: Parser.ts -nav_order: 6 +nav_order: 7 parent: Modules --- @@ -32,7 +32,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseClasses: Effect.Effect +export declare const parseClasses: Effect.Effect ``` Since v0.6.0 @@ -42,11 +42,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseConstants: Effect.Effect< - Domain.Constant[], - [string, ...string[]], - Configuration.Configuration | Source -> +export declare const parseConstants: Effect.Effect ``` Since v0.6.0 @@ -56,11 +52,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseExports: Effect.Effect< - Domain.Export[], - [string, ...string[]], - Configuration.Configuration | Source -> +export declare const parseExports: Effect.Effect ``` Since v0.6.0 @@ -82,11 +74,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseFunctions: Effect.Effect< - Domain.Function[], - [string, ...string[]], - Configuration.Configuration | Source -> +export declare const parseFunctions: Effect.Effect ``` Since v0.6.0 @@ -96,11 +84,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseInterfaces: Effect.Effect< - Domain.Interface[], - [string, ...string[]], - Configuration.Configuration | Source -> +export declare const parseInterfaces: Effect.Effect ``` Since v0.6.0 @@ -110,11 +94,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseModule: Effect.Effect< - Domain.Module, - string[], - Configuration.Configuration | Path.Path | Source -> +export declare const parseModule: Effect.Effect ``` Since v0.6.0 @@ -124,7 +104,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseNamespaces: Effect.Effect +export declare const parseNamespaces: Effect.Effect ``` Since v0.6.0 @@ -134,11 +114,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseTypeAliases: Effect.Effect< - Domain.TypeAlias[], - [string, ...string[]], - Configuration.Configuration | Source -> +export declare const parseTypeAliases: Effect.Effect ``` Since v0.6.0 diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index f5d4fae..bc4b597 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -1,6 +1,6 @@ --- title: Printer.ts -nav_order: 7 +nav_order: 8 parent: Modules --- @@ -39,7 +39,7 @@ export const a: string = "a" import { Domain, Printer } from "@effect/docgen" import { Option } from "effect" -const doc = new Domain.Doc(undefined, "1.0.0", false, [], undefined) +const doc = new Domain.Doc(undefined, ["1.0.0"], [], [], [], [], [], {}) const m = new Domain.Module("tests", doc, ["src", "tests.ts"], [], [], [], [], [], [], []) console.log(Printer.printModule(m)) ``` diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index f91a0ef..2c46ace 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -1,6 +1,6 @@ --- title: index.ts -nav_order: 5 +nav_order: 6 parent: Modules --- diff --git a/src/Domain.ts b/src/Domain.ts index 46d1cd7..a842bed 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -2,6 +2,7 @@ * @since 0.6.0 */ +import type * as Array from "effect/Array" import * as Data from "effect/Data" import * as Effect from "effect/Effect" import * as Order from "effect/Order" @@ -19,7 +20,8 @@ export class Doc { readonly examples: ReadonlyArray, readonly category: ReadonlyArray, readonly throws: ReadonlyArray, - readonly sees: ReadonlyArray + readonly sees: ReadonlyArray, + readonly tags: Record | undefined> ) {} modifyDescription(description: string | undefined): Doc { @@ -30,7 +32,8 @@ export class Doc { this.examples, this.category, this.throws, - this.sees + this.sees, + this.tags ) } } @@ -47,7 +50,7 @@ export class Module { constructor( readonly name: string, readonly doc: Doc, - readonly path: ReadonlyArray, + readonly path: Array.NonEmptyReadonlyArray, readonly classes: ReadonlyArray, readonly interfaces: ReadonlyArray, readonly functions: ReadonlyArray, diff --git a/src/Parser.ts b/src/Parser.ts index 9414140..ed9bc75 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -8,7 +8,6 @@ import * as Context from "effect/Context" import * as Effect from "effect/Effect" import { pipe } from "effect/Function" import * as Option from "effect/Option" -import * as Order from "effect/Order" import * as Record from "effect/Record" import * as String from "effect/String" import * as ast from "ts-morph" @@ -24,13 +23,6 @@ export interface SourceShape { /** @internal */ export class Source extends Context.Tag("Source")() {} -const sortByName: (self: Iterable) => Array = Array.sort( - pipe( - String.Order, - Order.mapInput(({ name }: { name: string }) => name) - ) -) - const sortModulesByPath: (self: Iterable) => Array = Array .sort(Domain.ByPath) @@ -44,12 +36,6 @@ const getJSDocText: (jsdocs: ReadonlyArray) => string = Array.matchRi onNonEmpty: (_, last) => last.getText() }) -const hasTag = (tag: string) => (comment: Comment) => pipe(comment.tags, Record.get(tag), Option.isSome) - -const hasInternalTag = hasTag("internal") - -const hasIgnoreTag = hasTag("ignore") - class Comment { constructor( readonly description: string | undefined, @@ -88,11 +74,6 @@ export const parseComment = (text: string): Comment => { return { description, tags } } -const shouldNotIgnore = (jsdocs: ReadonlyArray): boolean => { - const comment = parseComment(getJSDocText(jsdocs)) - return !hasInternalTag(comment) && !hasIgnoreTag(comment) -} - const isVariableDeclarationList = ( u: ast.VariableDeclarationList | ast.CatchClause ): u is ast.VariableDeclarationList => u.getKind() === ast.ts.SyntaxKind.VariableDeclarationList @@ -117,31 +98,39 @@ export const getDoc = (text: string) => { comment.tags["example"] ?? [], comment.tags["category"] ?? [], comment.tags["throws"] ?? [], - comment.tags["see"] ?? [] + comment.tags["see"] ?? [], + comment.tags ) } +const shouldIgnore = (doc: Domain.Doc): boolean => { + return Record.has(doc.tags, "internal") || Record.has(doc.tags, "ignore") +} + const parseInterfaceDeclaration = (id: ast.InterfaceDeclaration) => Effect.gen(function*() { - const name = id.getName() const text = getJSDocText(id.getJsDocs()) const doc = getDoc(text) + if (shouldIgnore(doc)) { + return [] + } + const name = id.getName() const signature = id.getText() - return new Domain.Interface( - name, - doc, - signature - ) + return [ + new Domain.Interface( + name, + doc, + signature + ) + ] }) const parseInterfaceDeclarations = (interfaces: ReadonlyArray) => { const exportedInterfaces = Array.filter( interfaces, - (id) => id.isExported() && shouldNotIgnore(id.getJsDocs()) - ) - return Effect.forEach(exportedInterfaces, parseInterfaceDeclaration).pipe( - Effect.map(sortByName) + (id) => id.isExported() ) + return Effect.forEach(exportedInterfaces, parseInterfaceDeclaration).pipe(Effect.map(Array.flatten)) } /** @@ -184,9 +173,12 @@ const getFunctionDeclarationJSDocs = ( const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => Effect.gen(function*() { - const name = fd.getName() const text = getJSDocText(getFunctionDeclarationJSDocs(fd)) const doc = getDoc(text) + if (shouldIgnore(doc)) { + return [] + } + const name = fd.getName() const signatures = pipe( fd.getOverloads(), Array.matchRight({ @@ -198,36 +190,43 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => ) }) ) - return new Domain.Function( - name ?? "anonymous function", - doc, - signatures - ) + return [ + new Domain.Function( + name ?? "anonymous function", + doc, + signatures + ) + ] }) const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => Effect.gen(function*() { const vs: any = vd.getParent().getParent() - const name = vd.getName() const text = getJSDocText(vs.getJsDocs()) const doc = getDoc(text) + if (shouldIgnore(doc)) { + return [] + } + const name = vd.getName() const signature = `export declare const ${name}: ${ stripImportTypes( vd.getType().getText(vd) ) }` - return new Domain.Function( - name, - doc, - [signature] - ) + return [ + new Domain.Function( + name, + doc, + [signature] + ) + ] }) const getFunctionDeclarations = Effect.gen(function*() { const source = yield* Source const functions = Array.filter( source.sourceFile.getFunctions(), - (fd) => fd.isExported() && shouldNotIgnore(getFunctionDeclarationJSDocs(fd)) + (fd) => fd.isExported() ) const arrows = pipe( Array.filter( @@ -236,7 +235,7 @@ const getFunctionDeclarations = Effect.gen(function*() { if (isVariableDeclarationList(vd.getParent())) { const vs: any = vd.getParent().getParent() if (isVariableStatement(vs)) { - return vs.isExported() && shouldNotIgnore(vs.getJsDocs()) && + return vs.isExported() && Option.fromNullable(vd.getInitializer()).pipe( Option.filter((expr) => ast.Node.isFunctionLikeDeclaration(expr)), Option.isSome @@ -256,32 +255,39 @@ const getFunctionDeclarations = Effect.gen(function*() { */ export const parseFunctions = Effect.gen(function*() { const { arrows, functions } = yield* getFunctionDeclarations - const functionDeclarations = yield* Effect.forEach(functions, parseFunctionDeclaration) - const functionVariableDeclarations = yield* Effect.forEach(arrows, parseFunctionVariableDeclaration) + const functionDeclarations = yield* Effect.forEach(functions, parseFunctionDeclaration).pipe( + Effect.map(Array.flatten) + ) + const functionVariableDeclarations = yield* Effect.forEach(arrows, parseFunctionVariableDeclaration).pipe( + Effect.map(Array.flatten) + ) return [...functionDeclarations, ...functionVariableDeclarations] }) const parseTypeAliasDeclaration = (ta: ast.TypeAliasDeclaration) => Effect.gen(function*() { - const name = ta.getName() const text = getJSDocText(ta.getJsDocs()) const doc = getDoc(text) + if (shouldIgnore(doc)) { + return [] + } + const name = ta.getName() const signature = ta.getText() - return new Domain.TypeAlias( - name, - doc, - signature - ) + return [ + new Domain.TypeAlias( + name, + doc, + signature + ) + ] }) const parseTypeAliasDeclarations = (typeAliases: ReadonlyArray) => { const exportedTypeAliases = Array.filter( typeAliases, - (tad) => tad.isExported() && shouldNotIgnore(tad.getJsDocs()) - ) - return Effect.forEach(exportedTypeAliases, parseTypeAliasDeclaration).pipe( - Effect.map(sortByName) + (tad) => tad.isExported() ) + return Effect.forEach(exportedTypeAliases, parseTypeAliasDeclaration).pipe(Effect.map(Array.flatten)) } /** @@ -296,16 +302,21 @@ export const parseTypeAliases = Effect.flatMap( const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => Effect.gen(function*() { const vs: any = vd.getParent().getParent() - const name = vd.getName() const text = getJSDocText(vs.getJsDocs()) const doc = getDoc(text) + if (shouldIgnore(doc)) { + return [] + } + const name = vd.getName() const type = stripImportTypes(vd.getType().getText(vd)) const signature = `export declare const ${name}: ${type}` - return new Domain.Constant( - name, - doc, - signature - ) + return [ + new Domain.Constant( + name, + doc, + signature + ) + ] }) /** @@ -321,7 +332,7 @@ export const parseConstants = Effect.gen(function*() { if (isVariableDeclarationList(vd.getParent())) { const vs: any = vd.getParent().getParent() if (isVariableStatement(vs)) { - return vs.isExported() && shouldNotIgnore(vs.getJsDocs()) && + return vs.isExported() && Option.fromNullable(vd.getInitializer()).pipe( Option.filter((expr) => !ast.Node.isFunctionLikeDeclaration(expr)), Option.isSome @@ -332,7 +343,9 @@ export const parseConstants = Effect.gen(function*() { } ) ) - return yield* Effect.forEach(variableDeclarations, parseConstantVariableDeclaration) + return yield* Effect.forEach(variableDeclarations, parseConstantVariableDeclaration).pipe( + Effect.map(Array.flatten) + ) }) const parseExportSpecifier = (es: ast.ExportSpecifier) => @@ -351,9 +364,7 @@ const parseExportSpecifier = (es: ast.ExportSpecifier) => ) }) -const parseExportStar = ( - ed: ast.ExportDeclaration -) => +const parseExportStar = (ed: ast.ExportDeclaration) => Effect.gen(function*() { const es = ed.getModuleSpecifier()! const name = es.getText() @@ -392,41 +403,40 @@ export const parseExports = pipe( const parseModuleDeclaration = ( ed: ast.ModuleDeclaration -): Effect.Effect => - Effect.flatMap(Source, (_source) => { - const name = ed.getName() - const text = getJSDocText(ed.getJsDocs()) - const doc = getDoc(text) - const getInterfaces = parseInterfaceDeclarations(ed.getInterfaces()) - const getTypeAliases = parseTypeAliasDeclarations( - ed.getTypeAliases() - ) - const getNamespaces = parseModuleDeclarations(ed.getModules()) - return Effect.gen(function*() { - const interfaces = yield* getInterfaces - const typeAliases = yield* getTypeAliases - const namespaces = yield* getNamespaces - return new Domain.Namespace( +): Effect.Effect, never, Source | Configuration.Configuration> => { + const text = getJSDocText(ed.getJsDocs()) + const doc = getDoc(text) + if (shouldIgnore(doc)) { + return Effect.succeed([]) + } + const name = ed.getName() + const getInterfaces = parseInterfaceDeclarations(ed.getInterfaces()) + const getTypeAliases = parseTypeAliasDeclarations( + ed.getTypeAliases() + ) + const getNamespaces = parseModuleDeclarations(ed.getModules()) + return Effect.gen(function*() { + const interfaces = yield* getInterfaces + const typeAliases = yield* getTypeAliases + const namespaces = yield* getNamespaces + return [ + new Domain.Namespace( name, doc, interfaces, typeAliases, namespaces ) - }) + ] }) +} const parseModuleDeclarations = (namespaces: ReadonlyArray) => { const exportedNamespaces = Array.filter( namespaces, - (md) => md.isExported() && shouldNotIgnore(md.getJsDocs()) - ) - return Effect.forEach(exportedNamespaces, parseModuleDeclaration).pipe( - Effect.mapBoth({ - onFailure: Array.flatten, - onSuccess: sortByName - }) + (md) => md.isExported() ) + return Effect.forEach(exportedNamespaces, parseModuleDeclaration).pipe(Effect.map(Array.flatten)) } /** @@ -465,36 +475,39 @@ const parseMethod = (md: ast.MethodDeclaration) => onNonEmpty: (x) => x.getJsDocs() }) ) - if (shouldNotIgnore(jsdocs)) { - const text = getJSDocText(jsdocs) - const doc = getDoc(text) - const signatures = pipe( - overloads, - Array.matchRight({ - onEmpty: () => [getMethodSignature(md)], - onNonEmpty: (init, last) => - pipe( - init.map((md) => md.getText()), - Array.append(getMethodSignature(last)) - ) - }) - ) - return Option.some( - new Domain.Method( - name, - doc, - signatures - ) - ) + const text = getJSDocText(jsdocs) + const doc = getDoc(text) + if (shouldIgnore(doc)) { + return Option.none() } - return Option.none() + const signatures = pipe( + overloads, + Array.matchRight({ + onEmpty: () => [getMethodSignature(md)], + onNonEmpty: (init, last) => + pipe( + init.map((md) => md.getText()), + Array.append(getMethodSignature(last)) + ) + }) + ) + return Option.some( + new Domain.Method( + name, + doc, + signatures + ) + ) }) const parseProperty = (pd: ast.PropertyDeclaration) => Effect.gen(function*() { - const name = pd.getName() const text = getJSDocText(pd.getJsDocs()) const doc = getDoc(text) + if (shouldIgnore(doc)) { + return [] + } + const name = pd.getName() const type = stripImportTypes(pd.getType().getText(pd)) const readonly = pipe( Option.fromNullable( @@ -506,24 +519,26 @@ const parseProperty = (pd: ast.PropertyDeclaration) => }) ) const signature = `${readonly}${name}: ${type}` - return new Domain.Property( - name, - doc, - signature - ) + return [ + new Domain.Property( + name, + doc, + signature + ) + ] }) const parseProperties = (name: string, c: ast.ClassDeclaration) => { const properties = Array.filter( c.getProperties(), (pd) => - !pd.isStatic() && shouldNotIgnore(pd.getJsDocs()) && pipe( + !pd.isStatic() && pipe( pd.getFirstModifierByKind(ast.ts.SyntaxKind.PrivateKeyword), Option.fromNullable, Option.isNone ) ) - return Effect.forEach(properties, parseProperty) + return Effect.forEach(properties, parseProperty).pipe(Effect.map(Array.flatten)) } /** @@ -543,7 +558,7 @@ export const getConstructorDeclarationSignature = ( }) ) -const getClassDoc = (name: string, c: ast.ClassDeclaration) => { +const getClassDoc = (c: ast.ClassDeclaration) => { const text = getJSDocText(c.getJsDocs()) return getDoc(text) } @@ -569,8 +584,11 @@ const getClassDeclarationSignature = (name: string, c: ast.ClassDeclaration) => const parseClass = (c: ast.ClassDeclaration) => Effect.gen(function*() { + const doc = getClassDoc(c) + if (shouldIgnore(doc)) { + return [] + } const name = c.getName() ?? "anonymous class" - const doc = getClassDoc(name, c) const signature = yield* getClassDeclarationSignature(name, c) const methods = yield* pipe( c.getInstanceMethods(), @@ -583,14 +601,16 @@ const parseClass = (c: ast.ClassDeclaration) => Effect.map(Array.getSomes) ) const properties = yield* parseProperties(name, c) - return new Domain.Class( - name, - doc, - signature, - methods, - staticMethods, - properties - ) + return [ + new Domain.Class( + name, + doc, + signature, + methods, + staticMethods, + properties + ) + ] }) /** @@ -601,11 +621,9 @@ export const parseClasses = Effect.gen(function*() { const source = yield* Source const exportedClasses = Array.filter( source.sourceFile.getClasses(), - (cd) => cd.isExported() && shouldNotIgnore(cd.getJsDocs()) - ) - return yield* Effect.forEach(exportedClasses, parseClass).pipe( - Effect.map(sortByName) + (cd) => cd.isExported() ) + return yield* Effect.forEach(exportedClasses, parseClass).pipe(Effect.map(Array.flatten)) }) /** @@ -667,9 +685,7 @@ export const parseFile = (project: ast.Project) => Configuration.Configuration | Path.Path > => Effect.flatMap(Path.Path, (_) => { - const path = file.path.split( - _.sep - ) as any as Array.NonEmptyReadonlyArray + const path = file.path.split(_.sep) as any as Array.NonEmptyReadonlyArray const sourceFile = project.getSourceFile(file.path) if (sourceFile !== undefined) { return pipe( diff --git a/src/Printer.ts b/src/Printer.ts index 47c333f..7c87199 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -7,7 +7,6 @@ import { identity, pipe } from "effect/Function" import * as Order from "effect/Order" import * as Record from "effect/Record" import * as String from "effect/String" -import * as NodePath from "node:path" import * as Prettier from "prettier" import type * as Domain from "./Domain.js" @@ -155,7 +154,7 @@ const printProperty = (model: Domain.Property): string => { /** @internal */ export const printFrontMatter = (module: Domain.Module, order: number): string => { - const filename = NodePath.basename(module.path.join(NodePath.sep)) + const filename = Array.lastNonEmpty(module.path) return `--- title: ${filename} nav_order: ${order} @@ -269,6 +268,13 @@ const getPrintables = (module: Domain.Module): ReadonlyArray => module.namespaces ]) +const sortByName: (self: Iterable) => Array = Array.sort( + pipe( + String.Order, + Order.mapInput(({ name }: { name: string }) => name) + ) +) + /** * Description... * @@ -288,7 +294,7 @@ const getPrintables = (module: Domain.Module): ReadonlyArray => * import { Domain, Printer } from "@effect/docgen" * import { Option } from "effect" * - * const doc = new Domain.Doc(undefined, "1.0.0", false, [], undefined) + * const doc = new Domain.Doc(undefined, ["1.0.0"], [], [], [], [], [], {}) * const m = new Domain.Module("tests", doc, ["src", "tests.ts"], [], [], [], [], [], [], []) * console.log(Printer.printModule(m)) * ``` @@ -314,7 +320,7 @@ export const printModule = (module: Domain.Module) => { }) const content = pipe( - getPrintables(module), + sortByName(getPrintables(module)), Array.groupBy((printable) => printable.doc.category.length === 0 ? DEFAULT_CATEGORY : printable.doc.category.join(", ") ), diff --git a/test/Checker.test.ts b/test/Checker.test.ts index edcd25f..f096773 100644 --- a/test/Checker.test.ts +++ b/test/Checker.test.ts @@ -59,17 +59,6 @@ const expectFailure = ( } describe.skip("Checker", () => { - describe("checkFunctions", () => { - it("should raise an error if the function is anonymous", () => { - expectFailure( - `export function(a: number, b: number): number { return a + b }`, - Parser.parseFunctions, - Checker.checkFunctions, - [`Missing ${chalk.bold("function name")} in module ${chalk.bold("test")}`] - ) - }) - }) - describe("checkExports", () => { it("should raise an error if `@since` tag is missing in export", () => { expectFailure( @@ -145,17 +134,6 @@ describe.skip("Checker", () => { }) describe("checkClasses", () => { - it("should raise an error if the class is anonymous", () => { - expectFailure( - `export class {}`, - Parser.parseClasses, - Checker.checkClasses, - [ - `Missing ${chalk.bold("class name")} in module ${chalk.bold("test")}` - ] - ) - }) - it("should raise an error if an `@since` tag is missing in a module", () => { expectFailure( `export class MyClass {}`, diff --git a/test/Parser.test.ts b/test/Parser.test.ts index fb4729e..2b80993 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -732,7 +732,10 @@ Since v2.0.0` [], [], [], - [] + [], + { + "since": ["1.0.0"] + } ), "export declare const b: 1", false @@ -772,7 +775,10 @@ Since v2.0.0` [], [], [], - [] + [], + { + "since": ["1.0.0"] + } ), "export * from './example'", true @@ -812,7 +818,10 @@ Since v2.0.0` [], [], [], - [] + [], + { + "since": ["1.0.0"] + } ), "export * as example from './example'", true @@ -858,40 +867,6 @@ a description... export interface A {} \`\`\` -Since v1.0.0` - ) - }) - - it("should return interfaces sorted by name", async () => { - await expectMarkdown( - Parser.parseInterfaces, - ` - /** - * @since 1.0.0 - */ - export interface B {} - /** - * @since 1.0.0 - */ - export interface A {} - `, - `## A (interface) - -**Signature** - -\`\`\`ts -export interface A {} -\`\`\` - -Since v1.0.0 -## B (interface) - -**Signature** - -\`\`\`ts -export interface B {} -\`\`\` - Since v1.0.0` ) }) From 7293550a27a65a814f7a07134b3145630a91f825 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sat, 8 Mar 2025 10:34:59 +0100 Subject: [PATCH 37/56] Add function position tracking and @since tag validation - Introduce `Position` interface in Domain module to track function source locations - Update Function constructor to include position information - Implement function position tracking in Parser module - Add @since tag validation in Checker module using Babel code frame - Modify documentation generation to use new position and filename tracking - Update tests to validate new @since tag checking functionality --- docs/modules/CLI.ts.md | 2 +- docs/modules/Checker.ts.md | 18 +++--- docs/modules/Configuration.ts.md | 2 +- docs/modules/Core.ts.md | 2 +- docs/modules/Domain.ts.md | 19 +++++- docs/modules/Parser.ts.md | 4 +- docs/modules/Printer.ts.md | 16 ++++- docs/modules/index.ts.md | 2 +- package.json | 2 + pnpm-lock.yaml | 11 ++++ src/Checker.ts | 48 +++++++++----- src/Core.ts | 21 +++--- src/Domain.ts | 12 +++- src/Parser.ts | 108 ++++++++++++++++--------------- src/Printer.ts | 46 ++++++------- test/Checker.test.ts | 93 +++++++++++++++----------- test/Parser.test.ts | 19 ++++-- 17 files changed, 261 insertions(+), 164 deletions(-) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index 763a954..8dc36f1 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -4,7 +4,7 @@ nav_order: 2 parent: Modules --- -## CLI overview +## CLI.ts overview Since v0.6.0 diff --git a/docs/modules/Checker.ts.md b/docs/modules/Checker.ts.md index f484100..4971b93 100644 --- a/docs/modules/Checker.ts.md +++ b/docs/modules/Checker.ts.md @@ -4,7 +4,7 @@ nav_order: 1 parent: Modules --- -## Checker overview +## Checker.ts overview Since v0.6.0 @@ -31,7 +31,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkClasses(_classes: ReadonlyArray): ReadonlyArray +export declare function checkClasses(_classes: ReadonlyArray) ``` Since v0.6.0 @@ -41,7 +41,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkConstants(_constants: ReadonlyArray): ReadonlyArray +export declare function checkConstants(_constants: ReadonlyArray) ``` Since v0.6.0 @@ -51,7 +51,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkExports(_exports: ReadonlyArray): ReadonlyArray +export declare function checkExports(_exports: ReadonlyArray) ``` Since v0.6.0 @@ -61,7 +61,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkFunctions(_functions: ReadonlyArray): ReadonlyArray +export declare function checkFunctions(functions: ReadonlyArray) ``` Since v0.6.0 @@ -71,7 +71,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkInterfaces(_interfaces: ReadonlyArray): ReadonlyArray +export declare function checkInterfaces(_interfaces: ReadonlyArray) ``` Since v0.6.0 @@ -81,7 +81,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkModule(_module: Domain.Module): ReadonlyArray +export declare function checkModule(_module: Domain.Module) ``` Since v0.6.0 @@ -91,7 +91,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkNamespaces(_namespaces: ReadonlyArray): ReadonlyArray +export declare function checkNamespaces(_namespaces: ReadonlyArray) ``` Since v0.6.0 @@ -101,7 +101,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkTypeAliases(_typeAliases: ReadonlyArray): ReadonlyArray +export declare function checkTypeAliases(_typeAliases: ReadonlyArray) ``` Since v0.6.0 diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index c413772..d60e597 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -4,7 +4,7 @@ nav_order: 3 parent: Modules --- -## Configuration overview +## Configuration.ts overview Since v0.6.0 diff --git a/docs/modules/Core.ts.md b/docs/modules/Core.ts.md index b600915..129da80 100644 --- a/docs/modules/Core.ts.md +++ b/docs/modules/Core.ts.md @@ -4,7 +4,7 @@ nav_order: 4 parent: Modules --- -## Core overview +## Core.ts overview Since v0.6.0 diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index cad913a..bc9db8c 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -4,7 +4,7 @@ nav_order: 5 parent: Modules --- -## Domain overview +## Domain.ts overview Since v0.6.0 @@ -32,6 +32,7 @@ Since v0.6.0 - [\_tag (property)](#_tag-property-5) - [Namespace (class)](#namespace-class) - [\_tag (property)](#_tag-property-6) + - [Position (interface)](#position-interface) - [Property (class)](#property-class) - [TypeAlias (class)](#typealias-class) - [\_tag (property)](#_tag-property-7) @@ -154,7 +155,7 @@ export declare class Export { constructor( readonly name: string, readonly doc: Doc, readonly signature: string, - readonly namespaceExport: boolean + readonly isNamespaceExport: boolean ) } ``` @@ -192,6 +193,7 @@ Since v0.6.0 ```ts export declare class Function { constructor( + readonly position: Position, readonly name: string, readonly doc: Doc, readonly signatures: ReadonlyArray @@ -305,6 +307,19 @@ readonly _tag: "Namespace" Since v0.6.0 +## Position (interface) + +**Signature** + +```ts +export interface Position { + readonly line: number + readonly column: number +} +``` + +Since v0.6.0 + ## Property (class) **Signature** diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index cc1917c..2444fe9 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -4,7 +4,7 @@ nav_order: 7 parent: Modules --- -## Parser overview +## Parser.ts overview Since v0.6.0 @@ -94,7 +94,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseModule: Effect.Effect +export declare const parseModule: Effect.Effect ``` Since v0.6.0 diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index bc4b597..21d67a1 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -4,7 +4,7 @@ nav_order: 8 parent: Modules --- -## Printer overview +## Printer.ts overview Since v0.6.0 @@ -14,6 +14,8 @@ Since v0.6.0 - [printers](#printers) - [printModule](#printmodule) +- [utils](#utils) + - [prettify](#prettify) --- @@ -67,3 +69,15 @@ export declare const printModule: (module: Domain.Module) => string ``` Since v0.6.0 + +# utils + +## prettify + +**Signature** + +```ts +export declare function prettify(s: string) +``` + +Since v0.6.0 diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index 2c46ace..be40d36 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -4,7 +4,7 @@ nav_order: 6 parent: Modules --- -## index overview +## index.ts overview Since v0.6.0 diff --git a/package.json b/package.json index 2a4337a..25405d7 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "changeset-publish": "pnpm build && TEST_DIST= pnpm vitest && changeset publish" }, "dependencies": { + "@babel/code-frame": "^7.26.2", "@effect/markdown-toc": "^0.1.0", "doctrine": "^3.0.0", "glob": "^11.0.1", @@ -50,6 +51,7 @@ "@effect/platform": "0.78.0", "@effect/platform-node": "0.74.0", "@eslint/compat": "^1.2.7", + "@types/babel__code-frame": "^7.0.6", "@types/doctrine": "0.0.9", "@types/glob": "^8.1.0", "@types/node": "^22.13.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 69da43f..d678431 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@babel/code-frame': + specifier: ^7.26.2 + version: 7.26.2 '@effect/markdown-toc': specifier: ^0.1.0 version: 0.1.0 @@ -45,6 +48,9 @@ importers: '@eslint/compat': specifier: ^1.2.7 version: 1.2.7(eslint@9.21.0) + '@types/babel__code-frame': + specifier: ^7.0.6 + version: 7.0.6 '@types/doctrine': specifier: 0.0.9 version: 0.0.9 @@ -783,6 +789,9 @@ packages: '@ts-morph/common@0.26.1': resolution: {integrity: sha512-Sn28TGl/4cFpcM+jwsH1wLncYq3FtN/BIpem+HOygfBWPT5pAeS5dB4VFVzV8FbnOKHpDLZmvAl4AjPEev5idA==} + '@types/babel__code-frame@7.0.6': + resolution: {integrity: sha512-Anitqkl3+KrzcW2k77lRlg/GfLZLWXBuNgbEcIOU6M92yw42vsd3xV/Z/yAHEj8m+KUjL6bWOVOFqX8PFPJ4LA==} + '@types/dedent@0.7.0': resolution: {integrity: sha512-EGlKlgMhnLt/cM4DbUSafFdrkeJoC9Mvnj0PUCU7tFmTjMjNRT957kXCx0wYm3JuEq4o4ZsS5vG+NlkM2DMd2A==} @@ -3770,6 +3779,8 @@ snapshots: minimatch: 9.0.5 path-browserify: 1.0.1 + '@types/babel__code-frame@7.0.6': {} + '@types/dedent@0.7.0': {} '@types/doctrine@0.0.9': {} diff --git a/src/Checker.ts b/src/Checker.ts index 7a7f2f1..7772cae 100644 --- a/src/Checker.ts +++ b/src/Checker.ts @@ -1,60 +1,76 @@ /** * @since 0.6.0 */ +import { codeFrameColumns } from "@babel/code-frame" +import { Array, Effect } from "effect" import type * as Domain from "./Domain.js" +import * as Parser from "./Parser.js" + +function checkFunction(model: Domain.Function) { + return Effect.gen(function*() { + const since = model.doc.since + if (since.length === 0) { + const source = yield* Parser.Source + const location = { start: model.position } + const result = codeFrameColumns(source.sourceFile.getFullText(), location) + return [`Missing \`@since\` tag in file ${source.sourceFile.getFilePath()}:\n\n${result}`] + } + return [] + }) +} /** * @since 0.6.0 */ -export function checkFunctions(_functions: ReadonlyArray): ReadonlyArray { - return [] +export function checkFunctions(functions: ReadonlyArray) { + return Effect.forEach(functions, checkFunction).pipe(Effect.map(Array.flatten)) } /** * @since 0.6.0 */ -export function checkClasses(_classes: ReadonlyArray): ReadonlyArray { - return [] +export function checkClasses(_classes: ReadonlyArray) { + return Effect.succeed([]) } /** * @since 0.6.0 */ -export function checkConstants(_constants: ReadonlyArray): ReadonlyArray { - return [] +export function checkConstants(_constants: ReadonlyArray) { + return Effect.succeed([]) } /** * @since 0.6.0 */ -export function checkInterfaces(_interfaces: ReadonlyArray): ReadonlyArray { - return [] +export function checkInterfaces(_interfaces: ReadonlyArray) { + return Effect.succeed([]) } /** * @since 0.6.0 */ -export function checkTypeAliases(_typeAliases: ReadonlyArray): ReadonlyArray { - return [] +export function checkTypeAliases(_typeAliases: ReadonlyArray) { + return Effect.succeed([]) } /** * @since 0.6.0 */ -export function checkNamespaces(_namespaces: ReadonlyArray): ReadonlyArray { - return [] +export function checkNamespaces(_namespaces: ReadonlyArray) { + return Effect.succeed([]) } /** * @since 0.6.0 */ -export function checkExports(_exports: ReadonlyArray): ReadonlyArray { - return [] +export function checkExports(_exports: ReadonlyArray) { + return Effect.succeed([]) } /** * @since 0.6.0 */ -export function checkModule(_module: Domain.Module): ReadonlyArray { - return [] +export function checkModule(_module: Domain.Module) { + return Effect.succeed([]) } diff --git a/src/Core.ts b/src/Core.ts index 580565f..1e24269 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -506,16 +506,17 @@ const getMarkdownConfigYML = Effect.gen(function*() { } }) -const getModuleMarkdownOutputPath = (module: Domain.Module) => - Effect.map( - Effect.all([Configuration.Configuration, Path.Path]), - ([config, path]) => - path.normalize(path.join( - config.outDir, - "modules", - `${module.path.slice(1).join(path.sep)}.md` - )) - ) +const getModuleMarkdownOutputPath = (module: Domain.Module) => { + return Effect.gen(function*() { + const config = yield* Configuration.Configuration + const path = yield* Path.Path + return path.normalize(path.join( + config.outDir, + "modules", + `${module.path.slice(1).join(path.sep)}.md` + )) + }) +} const getModuleMarkdownFiles = (modules: ReadonlyArray) => Effect.forEach(modules, (module, i) => diff --git a/src/Domain.ts b/src/Domain.ts index a842bed..7ade8ad 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -120,6 +120,15 @@ export class Interface { ) {} } +/** + * @category model + * @since 0.6.0 + */ +export interface Position { + readonly line: number + readonly column: number +} + /** * @category model * @since 0.6.0 @@ -130,6 +139,7 @@ export class Function { */ readonly _tag = "Function" constructor( + readonly position: Position, readonly name: string, readonly doc: Doc, readonly signatures: ReadonlyArray @@ -191,7 +201,7 @@ export class Export { readonly name: string, readonly doc: Doc, readonly signature: string, - readonly namespaceExport: boolean + readonly isNamespaceExport: boolean ) {} } diff --git a/src/Parser.ts b/src/Parser.ts index ed9bc75..46444a1 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -53,7 +53,7 @@ export const parseComment = (text: string): Comment => { const description = pipe( Option.fromNullable(annotation.description), - Option.map(String.trim), + Option.map((s) => s.trim()), Option.filter(String.isNonEmpty), Option.getOrUndefined ) @@ -89,7 +89,7 @@ const isVariableStatement = ( /** * @internal */ -export const getDoc = (text: string) => { +export const parseDoc = (text: string) => { const comment = parseComment(text) return new Domain.Doc( comment.description, @@ -110,7 +110,7 @@ const shouldIgnore = (doc: Domain.Doc): boolean => { const parseInterfaceDeclaration = (id: ast.InterfaceDeclaration) => Effect.gen(function*() { const text = getJSDocText(id.getJsDocs()) - const doc = getDoc(text) + const doc = parseDoc(text) if (shouldIgnore(doc)) { return [] } @@ -171,10 +171,19 @@ const getFunctionDeclarationJSDocs = ( }) ) +const parsePosition = (node: ast.Node): Effect.Effect => { + return Effect.gen(function*() { + const source = yield* Source + const startPos = node.getStart() + const position = source.sourceFile.getLineAndColumnAtPos(startPos) + return position + }) +} + const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => Effect.gen(function*() { const text = getJSDocText(getFunctionDeclarationJSDocs(fd)) - const doc = getDoc(text) + const doc = parseDoc(text) if (shouldIgnore(doc)) { return [] } @@ -190,9 +199,11 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => ) }) ) + const position = yield* parsePosition(fd) return [ new Domain.Function( - name ?? "anonymous function", + position, + name ?? "", doc, signatures ) @@ -203,7 +214,7 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => Effect.gen(function*() { const vs: any = vd.getParent().getParent() const text = getJSDocText(vs.getJsDocs()) - const doc = getDoc(text) + const doc = parseDoc(text) if (shouldIgnore(doc)) { return [] } @@ -213,9 +224,13 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => vd.getType().getText(vd) ) }` + const startPos = vd.getStart() + const source = yield* Source + const position = source.sourceFile.getLineAndColumnAtPos(startPos) return [ new Domain.Function( - name, + position, + name ?? "", doc, [signature] ) @@ -267,7 +282,7 @@ export const parseFunctions = Effect.gen(function*() { const parseTypeAliasDeclaration = (ta: ast.TypeAliasDeclaration) => Effect.gen(function*() { const text = getJSDocText(ta.getJsDocs()) - const doc = getDoc(text) + const doc = parseDoc(text) if (shouldIgnore(doc)) { return [] } @@ -303,7 +318,7 @@ const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => Effect.gen(function*() { const vs: any = vd.getParent().getParent() const text = getJSDocText(vs.getJsDocs()) - const doc = getDoc(text) + const doc = parseDoc(text) if (shouldIgnore(doc)) { return [] } @@ -354,7 +369,7 @@ const parseExportSpecifier = (es: ast.ExportSpecifier) => const type = stripImportTypes(es.getType().getText(es)) const ocommentRange = Array.head(es.getLeadingCommentRanges()) const text = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) - const doc = getDoc(text) + const doc = parseDoc(text) const signature = `export declare const ${name}: ${type}` return new Domain.Export( name, @@ -372,7 +387,7 @@ const parseExportStar = (ed: ast.ExportDeclaration) => const signature = `export *${namespace === undefined ? "" : ` as ${namespace}`} from ${name}` const ocommentRange = Array.head(ed.getLeadingCommentRanges()) const text = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) - const doc = getDoc(text) + const doc = parseDoc(text) return new Domain.Export( namespace ?? name, doc.modifyDescription( @@ -405,7 +420,7 @@ const parseModuleDeclaration = ( ed: ast.ModuleDeclaration ): Effect.Effect, never, Source | Configuration.Configuration> => { const text = getJSDocText(ed.getJsDocs()) - const doc = getDoc(text) + const doc = parseDoc(text) if (shouldIgnore(doc)) { return Effect.succeed([]) } @@ -476,7 +491,7 @@ const parseMethod = (md: ast.MethodDeclaration) => }) ) const text = getJSDocText(jsdocs) - const doc = getDoc(text) + const doc = parseDoc(text) if (shouldIgnore(doc)) { return Option.none() } @@ -503,32 +518,24 @@ const parseMethod = (md: ast.MethodDeclaration) => const parseProperty = (pd: ast.PropertyDeclaration) => Effect.gen(function*() { const text = getJSDocText(pd.getJsDocs()) - const doc = getDoc(text) + const doc = parseDoc(text) if (shouldIgnore(doc)) { return [] } const name = pd.getName() const type = stripImportTypes(pd.getType().getText(pd)) const readonly = pipe( - Option.fromNullable( - pd.getFirstModifierByKind(ast.ts.SyntaxKind.ReadonlyKeyword) - ), + Option.fromNullable(pd.getFirstModifierByKind(ast.ts.SyntaxKind.ReadonlyKeyword)), Option.match({ onNone: () => "", onSome: () => "readonly " }) ) const signature = `${readonly}${name}: ${type}` - return [ - new Domain.Property( - name, - doc, - signature - ) - ] + return [new Domain.Property(name, doc, signature)] }) -const parseProperties = (name: string, c: ast.ClassDeclaration) => { +const parseProperties = (c: ast.ClassDeclaration) => { const properties = Array.filter( c.getProperties(), (pd) => @@ -560,11 +567,12 @@ export const getConstructorDeclarationSignature = ( const getClassDoc = (c: ast.ClassDeclaration) => { const text = getJSDocText(c.getJsDocs()) - return getDoc(text) + return parseDoc(text) } -const getClassDeclarationSignature = (name: string, c: ast.ClassDeclaration) => - pipe( +const getClassDeclarationSignature = (c: ast.ClassDeclaration) => { + const name = c.getName() ?? "" + return pipe( Effect.succeed(getTypeParameters(c.getTypeParameters())), Effect.map((typeParameters) => pipe( @@ -581,6 +589,7 @@ const getClassDeclarationSignature = (name: string, c: ast.ClassDeclaration) => ) ) ) +} const parseClass = (c: ast.ClassDeclaration) => Effect.gen(function*() { @@ -588,8 +597,8 @@ const parseClass = (c: ast.ClassDeclaration) => if (shouldIgnore(doc)) { return [] } - const name = c.getName() ?? "anonymous class" - const signature = yield* getClassDeclarationSignature(name, c) + const name = c.getName() ?? "" + const signature = yield* getClassDeclarationSignature(c) const methods = yield* pipe( c.getInstanceMethods(), Effect.forEach(parseMethod), @@ -600,7 +609,7 @@ const parseClass = (c: ast.ClassDeclaration) => Effect.forEach(parseMethod), Effect.map(Array.getSomes) ) - const properties = yield* parseProperties(name, c) + const properties = yield* parseProperties(c) return [ new Domain.Class( name, @@ -639,10 +648,10 @@ export const parseModuleDocumentation = Effect.gen(function*() { if (Option.isSome(ocommentRange)) { const commentRange = ocommentRange.value const text = commentRange.getText() - return getDoc(text) + return parseDoc(text) } } - return getDoc("") + return parseDoc("") }) /** @@ -659,8 +668,7 @@ export const parseModule = Effect.gen(function*() { const constants = yield* parseConstants const exports = yield* parseExports const namespaces = yield* parseNamespaces - const path = yield* Path.Path - const name = path.parse(Array.lastNonEmpty(source.path)).name + const name = source.sourceFile.getBaseName() return new Domain.Module( name, doc, @@ -678,23 +686,19 @@ export const parseModule = Effect.gen(function*() { /** * @internal */ -export const parseFile = (project: ast.Project) => -(file: Domain.File): Effect.Effect< - Domain.Module, - Array, - Configuration.Configuration | Path.Path -> => - Effect.flatMap(Path.Path, (_) => { - const path = file.path.split(_.sep) as any as Array.NonEmptyReadonlyArray - const sourceFile = project.getSourceFile(file.path) - if (sourceFile !== undefined) { - return pipe( - parseModule, - Effect.provideService(Source, { path, sourceFile }) - ) - } - return Effect.fail([`Unable to locate file: ${file.path}`]) - }) +export const parseFile = + (project: ast.Project) => + (file: Domain.File): Effect.Effect, Configuration.Configuration | Path.Path> => { + return Effect.gen(function*() { + const path = yield* Path.Path + const filePath = file.path.split(path.sep) + const sourceFile = project.getSourceFile(file.path) + if (sourceFile !== undefined && Array.isNonEmptyArray(filePath)) { + return yield* Effect.provideService(parseModule, Source, { sourceFile, path: filePath }) + } + return yield* Effect.fail([`Unable to locate file: ${file.path}`]) + }) + } const createProject = (files: ReadonlyArray) => Effect.gen(function*() { diff --git a/src/Printer.ts b/src/Printer.ts index 7c87199..9989088 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -31,11 +31,24 @@ const Markdown = { strikethrough: (content: string) => `~~${content}~~` } +/** + * Replaces the link from a JSDoc link tag with a simple text. + * + * Given "This is a description containing two links to {@link foo} and {@link bar baz}." + * returns "This is a description containing two links to `foo` and `baz`." + */ +function replaceJSDocLinks(text: string): string { + return text.replace(/\{@link\s+([^\s}]+)(?:\s+([^}]+))?\}/g, (_, link, label) => { + // Use the label if provided; otherwise, use the link target + return `\`${(label || link).trim()}\`` + }) +} + const printOptionalDescription = (description: string | undefined): string => { if (description === undefined) { return "" } - return `\n\n${description}` + return `\n\n${replaceJSDocLinks(description)}` } const printArray = (title: string, ss?: ReadonlyArray): string => { @@ -92,26 +105,11 @@ const printTitle = (s: string, deprecated: ReadonlyArray, postfix?: stri return postfix === undefined ? title : title + ` ${postfix}` } -/** - * Extracts the link from a JSDoc link tag. - * - * Given - * - * "{@link bar} description" - * - * returns - * - * "`bar` description" - */ -function parseJSDocLink(text: string): string { - return text.replace(/\{@link\s+([^}]+)\}/, "`$1`") -} - const printSeesArray = (sees?: ReadonlyArray): string => { if (sees === undefined || sees.length === 0) { return "" } - return `\n\n${Markdown.bold("See")}\n\n${sees.map((see) => `- ${parseJSDocLink(see)}`).join("\n")}` + return `\n\n${Markdown.bold("See")}\n\n${sees.map((see) => `- ${replaceJSDocLinks(see)}`).join("\n")}` } const printModel = (name: string, doc: Domain.Doc, options: { @@ -154,9 +152,8 @@ const printProperty = (model: Domain.Property): string => { /** @internal */ export const printFrontMatter = (module: Domain.Module, order: number): string => { - const filename = Array.lastNonEmpty(module.path) return `--- -title: ${filename} +title: ${module.name} nav_order: ${order} parent: Modules ---` @@ -186,7 +183,7 @@ export const printConstant = (model: Domain.Constant): string => { /** @internal */ export const printExport = (model: Domain.Export): string => { return printModel(model.name, model.doc, { - postfix: model.namespaceExport ? "(namespace export)" : undefined, + postfix: model.isNamespaceExport ? "(namespace export)" : undefined, signatures: [model.signature] }) } @@ -359,9 +356,12 @@ const defaultPrettierOptions: Prettier.Options = { trailingComma: "none" } -/** @internal */ -export const prettify = (s: string): Effect.Effect => - Effect.tryPromise({ +/** + * @since 0.6.0 + */ +export function prettify(s: string) { + return Effect.tryPromise({ try: () => Prettier.format(s, defaultPrettierOptions), catch: identity }).pipe(Effect.orDie) +} diff --git a/test/Checker.test.ts b/test/Checker.test.ts index f096773..8768e44 100644 --- a/test/Checker.test.ts +++ b/test/Checker.test.ts @@ -3,7 +3,7 @@ import * as Configuration from "@effect/docgen/Configuration" import * as Parser from "@effect/docgen/Parser" import { Path } from "@effect/platform" import chalk from "chalk" -import { Effect, Exit, Predicate } from "effect" +import { Effect, Predicate } from "effect" import * as assert from "node:assert/strict" import * as ast from "ts-morph" import { describe, it } from "vitest" @@ -31,50 +31,76 @@ const defaultConfig: Configuration.ConfigurationShape = { examplesCompilerOptions: {} } -const makeSource = (source: string | ast.SourceFile) => - Parser.Source.of({ - path: ["test"], +const makeSource = (source: string | ast.SourceFile) => { + const filename = `test-${testCounter++}` + return Parser.Source.of({ + path: [filename], sourceFile: Predicate.isString(source) - ? project.createSourceFile(`test-${testCounter++}.ts`, source) + ? project.createSourceFile(`${filename}.ts`, source) : source }) +} -const expectFailure = ( +const expectFailure = ( + config: Partial, sourceText: string, parser: Effect.Effect, - checker: (a: A) => ReadonlyArray, - failure: E, - config?: Partial + checker: (a: A) => Effect.Effect, never, Parser.Source>, + failure: ReadonlyArray ) => { - assert.deepStrictEqual( - parser.pipe( - Effect.map(checker), - Effect.provideService(Parser.Source, makeSource(sourceText)), - Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), - Effect.provide(Path.layer), - Effect.runSyncExit - ), - Exit.succeed(failure) + const actual = parser.pipe( + Effect.flatMap(checker), + Effect.provideService(Parser.Source, makeSource(sourceText)), + Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), + Effect.provide(Path.layer), + Effect.runSyncExit ) + assert.ok(actual._tag === "Success") + // console.log(actual.value) + assert.deepStrictEqual(actual.value, failure) } -describe.skip("Checker", () => { - describe("checkExports", () => { +describe("Checker", () => { + describe("checkFunctions", () => { + it("should raise an error if `@since` tag is missing in export", () => { + expectFailure( + {}, + ` +/** @since 1.0.0 */ +export function a() {} + +/** description */ +export function b() {} + `, + Parser.parseFunctions, + Checker.checkFunctions, + [`Missing \`@since\` tag in file /test-0.ts: + + 4 | + 5 | /** description */ +> 6 | export function b() {} + | ^ + 7 | `] + ) + }) + }) + + describe.skip("checkExports", () => { it("should raise an error if `@since` tag is missing in export", () => { expectFailure( + {}, "export { a }", Parser.parseExports, Checker.checkExports, - [ - `Missing ${chalk.bold("a")} documentation in ${chalk.bold("test")}` - ] + ["Missing `@since` tag in export: a"] ) }) }) - describe("checkNamespaces", () => { + describe.skip("checkNamespaces", () => { it("should raise an error if the namespace is not well documented", () => { expectFailure( + {}, "export namespace A {}", Parser.parseNamespaces, Checker.checkNamespaces, @@ -86,6 +112,7 @@ describe.skip("Checker", () => { it("should raise an error if the interface is not well documented", () => { expectFailure( + {}, ` /** * @since 1.0.0 @@ -102,6 +129,7 @@ describe.skip("Checker", () => { it("should raise an error if the type alias is not well documented", () => { expectFailure( + {}, ` /** * @since 1.0.0 @@ -118,6 +146,7 @@ describe.skip("Checker", () => { it("should raise an error if the namespace is not well documented", () => { expectFailure( + {}, ` /** * @since 1.0.0 @@ -133,9 +162,10 @@ describe.skip("Checker", () => { }) }) - describe("checkClasses", () => { + describe.skip("checkClasses", () => { it("should raise an error if an `@since` tag is missing in a module", () => { expectFailure( + {}, `export class MyClass {}`, Parser.parseClasses, Checker.checkClasses, @@ -146,6 +176,7 @@ describe.skip("Checker", () => { }) it("should raise an error if `@since` is missing in a property", () => { expectFailure( + {}, `/** * @since 1.0.0 */ @@ -158,16 +189,4 @@ describe.skip("Checker", () => { ) }) }) - - describe("checkNamespaces", () => { - }) - - describe("checkNamespaces", () => { - }) - - describe("checkNamespaces", () => { - }) - - describe("checkNamespaces", () => { - }) }) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 2b80993..6f8b80c 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -31,13 +31,15 @@ const defaultConfig: Configuration.ConfigurationShape = { examplesCompilerOptions: {} } -const makeSource = (source: string | ast.SourceFile) => - Parser.Source.of({ - path: ["test"], +const makeSource = (source: string | ast.SourceFile) => { + const filename = `test-${testCounter++}` + return Parser.Source.of({ + path: [filename], sourceFile: Predicate.isString(source) - ? project.createSourceFile(`test-${testCounter++}.ts`, source) + ? project.createSourceFile(`${filename}.ts`, source) : source }) +} const print = (printables: ReadonlyArray) => { const raw = printables.map((printable) => Printer.print(printable).trim()).join("\n") @@ -77,13 +79,14 @@ describe("Parser", () => { await expectMarkdown( Parser.parseFunctions, `/** - * description... + * This is a description containing two links to {@link foo} and {@link bar}. + * * @since 1.2.0 */ export function myfunc() {}`, `## myfunc -description... +This is a description containing two links to \`foo\` and \`bar\`. **Signature** @@ -131,6 +134,7 @@ Since v1.2.0` * description... * @see \`foo\` Description 1 * @see {@link bar} Description 2 + * @see {@link baz quux} Description 2 * @since 1.2.0 */ export function myfunc() {}`, @@ -142,6 +146,7 @@ description... - \`foo\` Description 1 - \`bar\` Description 2 +- \`quux\` Description 2 **Signature** @@ -1415,7 +1420,7 @@ import * as assert from 'assert' * @since 1.0.0 */ export const foo = 'foo'`, - `## test overview + `## test-52.ts overview This is the assert module. From ee0650fb1268ee9ddbe9c69fbeb95f812b05e3f9 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sat, 8 Mar 2025 12:10:53 +0100 Subject: [PATCH 38/56] Refactor signature generation and type parsing in Parser module - Update type parsing to use more comprehensive type extraction - Modify function and constant signatures to use `declare const` format - Remove `stripImportTypes` utility function - Improve type signature generation for functions, type aliases, and constants - Update test cases to reflect new signature generation approach --- docs/modules/CLI.ts.md | 2 +- docs/modules/Checker.ts.md | 24 ++-- docs/modules/Configuration.ts.md | 4 +- docs/modules/Domain.ts.md | 34 ++--- docs/modules/Parser.ts.md | 24 ++-- docs/modules/Printer.ts.md | 4 +- src/Parser.ts | 86 +++++-------- test/Parser.test.ts | 214 ++++++++++++++++--------------- 8 files changed, 195 insertions(+), 197 deletions(-) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index 8dc36f1..2ced2e1 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -24,7 +24,7 @@ Since v0.6.0 **Signature** ```ts -export declare const cli: ( +declare const cli: ( args: ReadonlyArray ) => Effect.Effect< void, diff --git a/docs/modules/Checker.ts.md b/docs/modules/Checker.ts.md index 4971b93..2d0b39e 100644 --- a/docs/modules/Checker.ts.md +++ b/docs/modules/Checker.ts.md @@ -31,7 +31,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkClasses(_classes: ReadonlyArray) +declare const checkClasses: (_classes: ReadonlyArray) => Effect.Effect, never, never> ``` Since v0.6.0 @@ -41,7 +41,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkConstants(_constants: ReadonlyArray) +declare const checkConstants: (_constants: ReadonlyArray) => Effect.Effect, never, never> ``` Since v0.6.0 @@ -51,7 +51,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkExports(_exports: ReadonlyArray) +declare const checkExports: (_exports: ReadonlyArray) => Effect.Effect, never, never> ``` Since v0.6.0 @@ -61,7 +61,9 @@ Since v0.6.0 **Signature** ```ts -export declare function checkFunctions(functions: ReadonlyArray) +declare const checkFunctions: ( + functions: ReadonlyArray +) => Effect.Effect, never, Parser.Source> ``` Since v0.6.0 @@ -71,7 +73,9 @@ Since v0.6.0 **Signature** ```ts -export declare function checkInterfaces(_interfaces: ReadonlyArray) +declare const checkInterfaces: ( + _interfaces: ReadonlyArray +) => Effect.Effect, never, never> ``` Since v0.6.0 @@ -81,7 +85,7 @@ Since v0.6.0 **Signature** ```ts -export declare function checkModule(_module: Domain.Module) +declare const checkModule: (_module: Domain.Module) => Effect.Effect, never, never> ``` Since v0.6.0 @@ -91,7 +95,9 @@ Since v0.6.0 **Signature** ```ts -export declare function checkNamespaces(_namespaces: ReadonlyArray) +declare const checkNamespaces: ( + _namespaces: ReadonlyArray +) => Effect.Effect, never, never> ``` Since v0.6.0 @@ -101,7 +107,9 @@ Since v0.6.0 **Signature** ```ts -export declare function checkTypeAliases(_typeAliases: ReadonlyArray) +declare const checkTypeAliases: ( + _typeAliases: ReadonlyArray +) => Effect.Effect, never, never> ``` Since v0.6.0 diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index d60e597..a132702 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -26,7 +26,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Configuration +declare class Configuration ``` Since v0.6.0 @@ -36,7 +36,7 @@ Since v0.6.0 **Signature** ```ts -export declare const ConfigurationSchema: Schema.Struct<{ +declare const ConfigurationSchema: Schema.Struct<{ $schema: Schema.optional projectHomepage: Schema.optional srcDir: Schema.optional diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index bc9db8c..48a8913 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -53,7 +53,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Class { constructor( +declare class Class { constructor( readonly name: string, readonly doc: Doc, readonly signature: string, @@ -80,7 +80,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Constant { constructor( +declare class Constant { constructor( readonly name: string, readonly doc: Doc, readonly signature: string @@ -104,7 +104,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Doc { constructor( +declare class Doc { constructor( readonly description: string | undefined, readonly since: ReadonlyArray, readonly deprecated: ReadonlyArray, @@ -131,7 +131,7 @@ modifyDescription(description: string | undefined): Doc **Signature** ```ts -export declare class DocgenError +declare class DocgenError ``` Since v0.6.0 @@ -151,7 +151,7 @@ export { **Signature** ```ts -export declare class Export { constructor( +declare class Export { constructor( readonly name: string, readonly doc: Doc, readonly signature: string, @@ -178,7 +178,7 @@ Represents a file which can be optionally overwriteable. **Signature** ```ts -export declare class File { constructor( +declare class File { constructor( readonly path: string, readonly content: string, readonly isOverwriteable: boolean = false @@ -192,7 +192,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Function { constructor( +declare class Function { constructor( readonly position: Position, readonly name: string, readonly doc: Doc, @@ -217,7 +217,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Interface { constructor( +declare class Interface { constructor( readonly name: string, readonly doc: Doc, readonly signature: string @@ -241,7 +241,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Method { constructor( +declare class Method { constructor( readonly name: string, readonly doc: Doc, readonly signatures: ReadonlyArray @@ -255,7 +255,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Module { constructor( +declare class Module { constructor( readonly name: string, readonly doc: Doc, readonly path: Array.NonEmptyReadonlyArray, @@ -286,7 +286,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Namespace { constructor( +declare class Namespace { constructor( readonly name: string, readonly doc: Doc, readonly interfaces: ReadonlyArray, @@ -325,7 +325,7 @@ Since v0.6.0 **Signature** ```ts -export declare class Property { constructor( +declare class Property { constructor( readonly name: string, readonly doc: Doc, readonly signature: string @@ -339,7 +339,7 @@ Since v0.6.0 **Signature** ```ts -export declare class TypeAlias { constructor( +declare class TypeAlias { constructor( readonly name: string, readonly doc: Doc, readonly signature: string @@ -367,7 +367,7 @@ Represents a handle to the currently executing process. **Signature** ```ts -export declare class Process +declare class Process ``` Since v0.6.0 @@ -382,7 +382,7 @@ The file path is converted to lowercase before comparison. **Signature** ```ts -export declare const ByPath: Order.Order +declare const ByPath: Order.Order ``` Since v0.6.0 @@ -394,7 +394,7 @@ Since v0.6.0 **Signature** ```ts -export declare const DocgenErrorTypeId: typeof DocgenErrorTypeId +declare const DocgenErrorTypeId: unique symbol ``` Since v0.6.0 @@ -404,7 +404,7 @@ Since v0.6.0 **Signature** ```ts -export type DocgenErrorTypeId = typeof DocgenErrorTypeId +type DocgenErrorTypeId = typeof DocgenErrorTypeId ``` Since v0.6.0 diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 2444fe9..d051664 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -32,7 +32,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseClasses: Effect.Effect +declare const parseClasses: Effect.Effect, never, Source> ``` Since v0.6.0 @@ -42,7 +42,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseConstants: Effect.Effect +declare const parseConstants: Effect.Effect, never, Source> ``` Since v0.6.0 @@ -52,7 +52,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseExports: Effect.Effect +declare const parseExports: Effect.Effect, never, Source> ``` Since v0.6.0 @@ -62,9 +62,13 @@ Since v0.6.0 **Signature** ```ts -export declare const parseFiles: ( +declare const parseFiles: ( files: ReadonlyArray -) => Effect.Effect +) => Effect.Effect< + Array, + [Array, ...Array[]], + Configuration.Configuration | Domain.Process | Path.Path +> ``` Since v0.6.0 @@ -74,7 +78,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseFunctions: Effect.Effect +declare const parseFunctions: Effect.Effect, never, Source> ``` Since v0.6.0 @@ -84,7 +88,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseInterfaces: Effect.Effect +declare const parseInterfaces: Effect.Effect, never, Source> ``` Since v0.6.0 @@ -94,7 +98,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseModule: Effect.Effect +declare const parseModule: Effect.Effect ``` Since v0.6.0 @@ -104,7 +108,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseNamespaces: Effect.Effect +declare const parseNamespaces: Effect.Effect, never, Configuration.Configuration | Source> ``` Since v0.6.0 @@ -114,7 +118,7 @@ Since v0.6.0 **Signature** ```ts -export declare const parseTypeAliases: Effect.Effect +declare const parseTypeAliases: Effect.Effect, never, Source> ``` Since v0.6.0 diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index 21d67a1..4f614b5 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -65,7 +65,7 @@ export const a: string = "b" **Signature** ```ts -export declare const printModule: (module: Domain.Module) => string +declare const printModule: (module: Domain.Module) => string ``` Since v0.6.0 @@ -77,7 +77,7 @@ Since v0.6.0 **Signature** ```ts -export declare function prettify(s: string) +declare const prettify: (s: string) => Effect.Effect ``` Since v0.6.0 diff --git a/src/Parser.ts b/src/Parser.ts index 46444a1..89f2444 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -26,11 +26,6 @@ export class Source extends Context.Tag("Source")() {} const sortModulesByPath: (self: Iterable) => Array = Array .sort(Domain.ByPath) -/** - * @internal - */ -export const stripImportTypes = (s: string): string => s.replace(/import\("((?!").)*"\)./g, "") - const getJSDocText: (jsdocs: ReadonlyArray) => string = Array.matchRight({ onEmpty: () => "", onNonEmpty: (_, last) => last.getText() @@ -142,34 +137,24 @@ export const parseInterfaces = Effect.flatMap( (source) => parseInterfaceDeclarations(source.sourceFile.getInterfaces()) ) -const getFunctionDeclarationSignature = ( - f: ast.FunctionDeclaration -): string => { - const text = f.getText() - return pipe( - Option.fromNullable(f.compilerNode.body), - Option.match({ - onNone: () => text.replace("export function ", "export declare function "), - onSome: (body) => { - const end = body.getStart() - f.getStart() - 1 - return text - .substring(0, end) - .replace("export function ", "export declare function ") - } - }) +const parseType = (node: ast.Node) => { + const text = node.getType().getText( + node, + ast.ts.TypeFormatFlags.NoTruncation + | ast.ts.TypeFormatFlags.WriteArrayAsGenericType + | ast.ts.TypeFormatFlags.UseAliasDefinedOutsideCurrentScope + | ast.ts.TypeFormatFlags.NoTypeReduction + | ast.ts.TypeFormatFlags.AllowUniqueESSymbolType + | ast.ts.TypeFormatFlags.WriteArrowStyleSignature ) + return text } -const getFunctionDeclarationJSDocs = ( - fd: ast.FunctionDeclaration -): Array => - pipe( - fd.getOverloads(), - Array.matchLeft({ - onEmpty: () => fd.getJsDocs(), - onNonEmpty: (firstOverload) => firstOverload.getJsDocs() - }) - ) +const getFunctionDeclarationJSDocs = (fd: ast.FunctionDeclaration): Array => + Array.matchLeft(fd.getOverloads(), { + onEmpty: () => fd.getJsDocs(), + onNonEmpty: (firstOverload) => firstOverload.getJsDocs() + }) const parsePosition = (node: ast.Node): Effect.Effect => { return Effect.gen(function*() { @@ -188,24 +173,15 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => return [] } const name = fd.getName() - const signatures = pipe( - fd.getOverloads(), - Array.matchRight({ - onEmpty: () => [getFunctionDeclarationSignature(fd)], - onNonEmpty: (init, last) => - pipe( - init.map(getFunctionDeclarationSignature), - Array.append(getFunctionDeclarationSignature(last)) - ) - }) - ) + const type = parseType(fd) + const signature = `declare const ${name}: ${type}` const position = yield* parsePosition(fd) return [ new Domain.Function( position, name ?? "", doc, - signatures + [signature] ) ] }) @@ -219,11 +195,8 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => return [] } const name = vd.getName() - const signature = `export declare const ${name}: ${ - stripImportTypes( - vd.getType().getText(vd) - ) - }` + const type = parseType(vd) + const signature = `declare const ${name}: ${type}` const startPos = vd.getStart() const source = yield* Source const position = source.sourceFile.getLineAndColumnAtPos(startPos) @@ -287,7 +260,10 @@ const parseTypeAliasDeclaration = (ta: ast.TypeAliasDeclaration) => return [] } const name = ta.getName() - const signature = ta.getText() + const len = ta.getTypeParameters().length + const type = parseType(ta) + const definition = ta.getTypeNode()?.getText() + const signature = `type ${len > 0 ? type : name} = ${definition}` return [ new Domain.TypeAlias( name, @@ -323,8 +299,8 @@ const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => return [] } const name = vd.getName() - const type = stripImportTypes(vd.getType().getText(vd)) - const signature = `export declare const ${name}: ${type}` + const type = parseType(vd) + const signature = `declare const ${name}: ${type}` return [ new Domain.Constant( name, @@ -366,11 +342,11 @@ export const parseConstants = Effect.gen(function*() { const parseExportSpecifier = (es: ast.ExportSpecifier) => Effect.gen(function*() { const name = es.compilerNode.name.text - const type = stripImportTypes(es.getType().getText(es)) + const type = parseType(es) const ocommentRange = Array.head(es.getLeadingCommentRanges()) const text = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) const doc = parseDoc(text) - const signature = `export declare const ${name}: ${type}` + const signature = `declare const ${name}: ${type}` return new Domain.Export( name, doc, @@ -523,7 +499,7 @@ const parseProperty = (pd: ast.PropertyDeclaration) => return [] } const name = pd.getName() - const type = stripImportTypes(pd.getType().getText(pd)) + const type = parseType(pd) const readonly = pipe( Option.fromNullable(pd.getFirstModifierByKind(ast.ts.SyntaxKind.ReadonlyKeyword)), Option.match({ @@ -578,9 +554,9 @@ const getClassDeclarationSignature = (c: ast.ClassDeclaration) => { pipe( c.getConstructors(), Array.matchLeft({ - onEmpty: () => `export declare class ${name}${typeParameters}`, + onEmpty: () => `declare class ${name}${typeParameters}`, onNonEmpty: (head) => - `export declare class ${name}${typeParameters} { ${ + `declare class ${name}${typeParameters} { ${ getConstructorDeclarationSignature( head ) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 6f8b80c..24e4cc0 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -74,7 +74,86 @@ const expectMarkdown = async ( } describe("Parser", () => { + describe("parseModule", () => { + it("should not require an example for modules when `enforceExamples` is set to true", async () => { + await expectMarkdown( + Parser.parseModule, + `/** +* This is the assert module. +* +* @since 1.0.0 +*/ +import * as assert from 'assert' + +/** + * This is the foo export. + * + * @example + * import { foo } from 'test' + * + * console.log(foo) + * + * @category category + * @since 1.0.0 + */ +export const foo = 'foo'`, + `## test-0.ts overview + +This is the assert module. + +Since v1.0.0 + + + +# category + +## foo + +This is the foo export. + +**Example** + +\`\`\`ts +import { foo } from 'test' + +console.log(foo) +\`\`\` + +**Signature** + +\`\`\`ts +declare const foo: "foo" +\`\`\` + +Since v1.0.0` + ) + }) + }) + describe("parseFunctions", () => { + it("generics", async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * This is a description containing two links to {@link foo} and {@link bar}. + * + * @since 1.2.0 + */ + export function myfunc() {}`, + `## myfunc + +This is a description containing two links to \`foo\` and \`bar\`. + +**Signature** + +\`\`\`ts +declare const myfunc: () => void +\`\`\` + +Since v1.2.0` + ) + }) + it("description", async () => { await expectMarkdown( Parser.parseFunctions, @@ -91,7 +170,7 @@ This is a description containing two links to \`foo\` and \`bar\`. **Signature** \`\`\`ts -export declare function myfunc() +declare const myfunc: () => void \`\`\` Since v1.2.0` @@ -120,7 +199,7 @@ description... **Signature** \`\`\`ts -export declare function myfunc() +declare const myfunc: () => void \`\`\` Since v1.2.0` @@ -151,7 +230,7 @@ description... **Signature** \`\`\`ts -export declare function myfunc() +declare const myfunc: () => void \`\`\` Since v1.2.0` @@ -181,7 +260,7 @@ const x = 1 **Signature** \`\`\`ts -export declare function myfunc() +declare const myfunc: () => void \`\`\` Since v1.0.0` @@ -213,7 +292,7 @@ const x = 1 **Signature** \`\`\`ts -export declare function myfunc() +declare const myfunc: () => void \`\`\` Since v1.0.0` @@ -255,7 +334,7 @@ const x = 2 **Signature** \`\`\`ts -export declare function myfunc() +declare const myfunc: () => void \`\`\` Since v1.0.0` @@ -287,7 +366,7 @@ const x = 1 **Signature** \`\`\`ts -export declare function myfunc() +declare const myfunc: () => void \`\`\` Since v1.0.0` @@ -319,7 +398,7 @@ const x = 1 **Signature** \`\`\`ts -export declare function myfunc() +declare const myfunc: () => void \`\`\` Since v1.0.0` @@ -414,7 +493,7 @@ Since v1.0.0` **Signature** \`\`\`ts -export declare const toNullable: (ma: A | null) => A | null +declare const toNullable: (ma: A | null) => A | null \`\`\` Since v1.0.0` @@ -453,7 +532,7 @@ assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) **Signature** \`\`\`ts -export declare const f: (a: number, b: number) => { [key: string]: number; } +declare const f: (a: number, b: number) => { [key: string]: number; } \`\`\` Since v1.0.0` @@ -472,7 +551,7 @@ Since v1.0.0` **Signature** \`\`\`ts -export declare function f(a: number, b: number): { [key: string]: number } +declare const f: (a: number, b: number) => { [key: string]: number; } \`\`\` Since v1.0.0` @@ -497,8 +576,7 @@ a description... **Signature** \`\`\`ts -export declare function f(a: Int, b: Int): { [key: string]: number } -export declare function f(a: number, b: number): { [key: string]: number } +declare const f: { (a: Int, b: Int): { [key: string]: number; }; (a: number, b: number): { [key: string]: number; }; } \`\`\` Since v1.0.0` @@ -523,7 +601,7 @@ a description... **Signature** \`\`\`ts -export declare const s: string +declare const s: string \`\`\` Since v1.0.0` @@ -542,7 +620,7 @@ Since v1.0.0` **Signature** \`\`\`ts -export declare const left: (l: E) => string +declare const left: (l: E) => string \`\`\` Since v1.0.0` @@ -563,7 +641,7 @@ Since v1.0.0` **Signature** \`\`\`ts -export declare const empty: A +declare const empty: A \`\`\` Since v1.0.0` @@ -588,7 +666,7 @@ Since v1.0.0` **Signature** \`\`\`ts -export declare const taskSeq: { a: number; } +declare const taskSeq: { a: number; } \`\`\` Since v1.0.0` @@ -612,7 +690,10 @@ Since v1.0.0` it("should return a type alias", async () => { await expectMarkdown( Parser.parseTypeAliases, - `/** + ` + type None = { readonly _tag: "None" } + type Some = { readonly _tag: "Some"; readonly value: A } + /** * a description... * @since 1.0.0 * @deprecated @@ -625,7 +706,7 @@ a description... **Signature** \`\`\`ts -export type Option = None | Some +type Option = None | Some \`\`\` Since v1.0.0` @@ -657,7 +738,7 @@ Since v1.0.0` **Signature** \`\`\`ts -export declare const b: 1 +declare const b: 1 \`\`\` Since v1.0.0` @@ -689,7 +770,7 @@ description_of_a **Signature** \`\`\`ts -export declare const a: 1 +declare const a: 1 \`\`\` Since v1.0.0 @@ -700,7 +781,7 @@ description_of_b **Signature** \`\`\`ts -export declare const b: 2 +declare const b: 2 \`\`\` Since v2.0.0` @@ -742,7 +823,7 @@ Since v2.0.0` "since": ["1.0.0"] } ), - "export declare const b: 1", + "declare const b: 1", false ) ]) @@ -1003,7 +1084,7 @@ Since v1.0.0 **Signature** \`\`\`ts -export type B = string +type B = string \`\`\` Since v1.0.1` @@ -1061,7 +1142,7 @@ Since v1.0.1 **Signature** \`\`\`ts -export type C = string +type C = string \`\`\` Since v1.0.2` @@ -1107,7 +1188,7 @@ Since v1.0.2` **Signature** \`\`\`ts -export declare class MyClass +declare class MyClass \`\`\` Since v1.0.0` @@ -1129,7 +1210,7 @@ description **Signature** \`\`\`ts -export declare class C { constructor() } +declare class C { constructor() } \`\`\` Since v1.0.0` @@ -1179,7 +1260,7 @@ description **Signature** \`\`\`ts -export declare class C +declare class C \`\`\` Since v1.0.0 @@ -1235,7 +1316,7 @@ a class description... **Signature** \`\`\`ts -export declare class Test { constructor(readonly value: string) } +declare class Test { constructor(readonly value: string) } \`\`\` Since v1.0.0 @@ -1314,7 +1395,7 @@ a class description... **Signature** \`\`\`ts -export declare class Test { constructor(readonly value: A) } +declare class Test { constructor(readonly value: A) } \`\`\` Since v1.0.0 @@ -1373,7 +1454,7 @@ a class description... **Signature** \`\`\`ts -export declare class Test +declare class Test \`\`\` Since v1.0.0` @@ -1397,62 +1478,6 @@ Since v1.0.0` }) }) - describe("parseModule", () => { - it("should not require an example for modules when `enforceExamples` is set to true", async () => { - await expectMarkdown( - Parser.parseModule, - `/** -* This is the assert module. -* -* @since 1.0.0 -*/ -import * as assert from 'assert' - -/** - * This is the foo export. - * - * @example - * import { foo } from 'test' - * - * console.log(foo) - * - * @category category - * @since 1.0.0 - */ -export const foo = 'foo'`, - `## test-52.ts overview - -This is the assert module. - -Since v1.0.0 - - - -# category - -## foo - -This is the foo export. - -**Example** - -\`\`\`ts -import { foo } from 'test' - -console.log(foo) -\`\`\` - -**Signature** - -\`\`\`ts -export declare const foo: "foo" -\`\`\` - -Since v1.0.0` - ) - }) - }) - describe("utils", () => { it("parseComment", () => { assert.deepStrictEqual(Parser.parseComment(""), { @@ -1495,20 +1520,5 @@ Since v1.0.0` } ) }) - - it("stripImportTypes", () => { - assert.deepStrictEqual( - Parser.stripImportTypes( - "{ (refinement: import(\"/Users/giulio/Documents/Projects/github/fp-ts/src/function\").Refinement, onFalse: (a: A) => E): (ma: Either) => Either; (predicate: Predicate, onFalse: (a: A) => E): (ma: Either) => Either; }" - ), - "{ (refinement: Refinement, onFalse: (a: A) => E): (ma: Either) => Either; (predicate: Predicate, onFalse: (a: A) => E): (ma: Either) => Either; }" - ) - assert.deepStrictEqual( - Parser.stripImportTypes( - "{ (refinementWithIndex: import(\"/Users/giulio/Documents/Projects/github/fp-ts/src/FilterableWithIndex\").RefinementWithIndex): (fa: A[]) => B[]; (predicateWithIndex: import(\"/Users/giulio/Documents/Projects/github/fp-ts/src/FilterableWithIndex\").PredicateWithIndex): (fa: A[]) => A[]; }" - ), - "{ (refinementWithIndex: RefinementWithIndex): (fa: A[]) => B[]; (predicateWithIndex: PredicateWithIndex): (fa: A[]) => A[]; }" - ) - }) }) }) From ad3ac6a6703b3db31ae38029ff4f2757f2ba8f90 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sat, 8 Mar 2025 12:39:39 +0100 Subject: [PATCH 39/56] Refactor signature handling in Domain and Parser modules - Change `signatures` property to single `signature` in Function, Method, and related classes - Update signature generation to use `declare const` format with type information - Simplify signature printing and parsing logic - Modify documentation generation to use new signature approach - Update test cases to reflect new signature format --- docs/modules/Domain.ts.md | 6 +- src/Domain.ts | 4 +- src/Parser.ts | 117 ++++++++++++-------------------------- src/Printer.ts | 30 +++++----- test/Parser.test.ts | 10 ++-- 5 files changed, 60 insertions(+), 107 deletions(-) diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 48a8913..85d0ea4 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -123,7 +123,7 @@ Since v0.6.0 **Signature** ```ts -modifyDescription(description: string | undefined): Doc +declare const modifyDescription: (description: string | undefined) => Doc ``` ## DocgenError (class) @@ -196,7 +196,7 @@ declare class Function { constructor( readonly position: Position, readonly name: string, readonly doc: Doc, - readonly signatures: ReadonlyArray + readonly signature: string ) } ``` @@ -244,7 +244,7 @@ Since v0.6.0 declare class Method { constructor( readonly name: string, readonly doc: Doc, - readonly signatures: ReadonlyArray + readonly signature: string ) } ``` diff --git a/src/Domain.ts b/src/Domain.ts index 7ade8ad..7c2e478 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -88,7 +88,7 @@ export class Method { constructor( readonly name: string, readonly doc: Doc, - readonly signatures: ReadonlyArray + readonly signature: string ) {} } @@ -142,7 +142,7 @@ export class Function { readonly position: Position, readonly name: string, readonly doc: Doc, - readonly signatures: ReadonlyArray + readonly signature: string ) {} } diff --git a/src/Parser.ts b/src/Parser.ts index 89f2444..b565d2b 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -81,10 +81,7 @@ const isVariableStatement = ( | ast.ForInStatement ): u is ast.VariableStatement => u.getKind() === ast.ts.SyntaxKind.VariableStatement -/** - * @internal - */ -export const parseDoc = (text: string) => { +const parseDoc = (text: string) => { const comment = parseComment(text) return new Domain.Doc( comment.description, @@ -104,8 +101,7 @@ const shouldIgnore = (doc: Domain.Doc): boolean => { const parseInterfaceDeclaration = (id: ast.InterfaceDeclaration) => Effect.gen(function*() { - const text = getJSDocText(id.getJsDocs()) - const doc = parseDoc(text) + const doc = parseDoc(getJSDocText(id.getJsDocs())) if (shouldIgnore(doc)) { return [] } @@ -167,8 +163,7 @@ const parsePosition = (node: ast.Node): Effect.Effect Effect.gen(function*() { - const text = getJSDocText(getFunctionDeclarationJSDocs(fd)) - const doc = parseDoc(text) + const doc = parseDoc(getJSDocText(getFunctionDeclarationJSDocs(fd))) if (shouldIgnore(doc)) { return [] } @@ -181,7 +176,7 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => position, name ?? "", doc, - [signature] + signature ) ] }) @@ -189,8 +184,7 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => Effect.gen(function*() { const vs: any = vd.getParent().getParent() - const text = getJSDocText(vs.getJsDocs()) - const doc = parseDoc(text) + const doc = parseDoc(getJSDocText(vs.getJsDocs())) if (shouldIgnore(doc)) { return [] } @@ -205,7 +199,7 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => position, name ?? "", doc, - [signature] + signature ) ] }) @@ -254,8 +248,7 @@ export const parseFunctions = Effect.gen(function*() { const parseTypeAliasDeclaration = (ta: ast.TypeAliasDeclaration) => Effect.gen(function*() { - const text = getJSDocText(ta.getJsDocs()) - const doc = parseDoc(text) + const doc = parseDoc(getJSDocText(ta.getJsDocs())) if (shouldIgnore(doc)) { return [] } @@ -293,8 +286,7 @@ export const parseTypeAliases = Effect.flatMap( const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => Effect.gen(function*() { const vs: any = vd.getParent().getParent() - const text = getJSDocText(vs.getJsDocs()) - const doc = parseDoc(text) + const doc = parseDoc(getJSDocText(vs.getJsDocs())) if (shouldIgnore(doc)) { return [] } @@ -344,8 +336,8 @@ const parseExportSpecifier = (es: ast.ExportSpecifier) => const name = es.compilerNode.name.text const type = parseType(es) const ocommentRange = Array.head(es.getLeadingCommentRanges()) - const text = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) - const doc = parseDoc(text) + const jsDocsText = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) + const doc = parseDoc(jsDocsText) const signature = `declare const ${name}: ${type}` return new Domain.Export( name, @@ -362,8 +354,8 @@ const parseExportStar = (ed: ast.ExportDeclaration) => const namespace = ed.getNamespaceExport()?.getName() const signature = `export *${namespace === undefined ? "" : ` as ${namespace}`} from ${name}` const ocommentRange = Array.head(ed.getLeadingCommentRanges()) - const text = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) - const doc = parseDoc(text) + const jsDocsText = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) + const doc = parseDoc(jsDocsText) return new Domain.Export( namespace ?? name, doc.modifyDescription( @@ -395,16 +387,13 @@ export const parseExports = pipe( const parseModuleDeclaration = ( ed: ast.ModuleDeclaration ): Effect.Effect, never, Source | Configuration.Configuration> => { - const text = getJSDocText(ed.getJsDocs()) - const doc = parseDoc(text) + const doc = parseDoc(getJSDocText(ed.getJsDocs())) if (shouldIgnore(doc)) { return Effect.succeed([]) } const name = ed.getName() const getInterfaces = parseInterfaceDeclarations(ed.getInterfaces()) - const getTypeAliases = parseTypeAliasDeclarations( - ed.getTypeAliases() - ) + const getTypeAliases = parseTypeAliasDeclarations(ed.getTypeAliases()) const getNamespaces = parseModuleDeclarations(ed.getModules()) return Effect.gen(function*() { const interfaces = yield* getInterfaces @@ -423,78 +412,49 @@ const parseModuleDeclaration = ( } const parseModuleDeclarations = (namespaces: ReadonlyArray) => { - const exportedNamespaces = Array.filter( - namespaces, - (md) => md.isExported() - ) - return Effect.forEach(exportedNamespaces, parseModuleDeclaration).pipe(Effect.map(Array.flatten)) + return Effect.forEach( + namespaces.filter((md) => md.isExported()), + parseModuleDeclaration + ).pipe(Effect.map(Array.flatten)) } /** * @category parsers * @since 0.6.0 */ -export const parseNamespaces = Effect.flatMap( - Source, - (source) => parseModuleDeclarations(source.sourceFile.getModules()) -) +export const parseNamespaces = Effect.gen(function*() { + const source = yield* Source + return yield* parseModuleDeclarations(source.sourceFile.getModules()) +}) -const getTypeParameters = ( - tps: ReadonlyArray -): string => tps.length === 0 ? "" : `<${tps.map((p) => p.getName()).join(", ")}>` - -const getMethodSignature = (md: ast.MethodDeclaration): string => - pipe( - Option.fromNullable(md.compilerNode.body), - Option.match({ - onNone: () => md.getText(), - onSome: (body) => { - const end = body.getStart() - md.getStart() - 1 - return md.getText().substring(0, end) - } - }) - ) +const getTypeParameters = (tps: ReadonlyArray): string => + tps.length === 0 ? "" : `<${tps.map((p) => p.getName()).join(", ")}>` const parseMethod = (md: ast.MethodDeclaration) => Effect.gen(function*() { const name = md.getName() - const overloads = md.getOverloads() - const jsdocs = pipe( - overloads, - Array.matchLeft({ - onEmpty: () => md.getJsDocs(), - onNonEmpty: (x) => x.getJsDocs() - }) - ) - const text = getJSDocText(jsdocs) - const doc = parseDoc(text) + const jsdocs = Array.matchLeft(md.getOverloads(), { + onEmpty: () => md.getJsDocs(), + onNonEmpty: (head) => head.getJsDocs() + }) + const doc = parseDoc(getJSDocText(jsdocs)) if (shouldIgnore(doc)) { return Option.none() } - const signatures = pipe( - overloads, - Array.matchRight({ - onEmpty: () => [getMethodSignature(md)], - onNonEmpty: (init, last) => - pipe( - init.map((md) => md.getText()), - Array.append(getMethodSignature(last)) - ) - }) - ) + const type = parseType(md) + const signature = `declare const ${name}: ${type}` return Option.some( new Domain.Method( name, doc, - signatures + signature ) ) }) const parseProperty = (pd: ast.PropertyDeclaration) => Effect.gen(function*() { - const text = getJSDocText(pd.getJsDocs()) - const doc = parseDoc(text) + const doc = parseDoc(getJSDocText(pd.getJsDocs())) if (shouldIgnore(doc)) { return [] } @@ -541,11 +501,6 @@ export const getConstructorDeclarationSignature = ( }) ) -const getClassDoc = (c: ast.ClassDeclaration) => { - const text = getJSDocText(c.getJsDocs()) - return parseDoc(text) -} - const getClassDeclarationSignature = (c: ast.ClassDeclaration) => { const name = c.getName() ?? "" return pipe( @@ -569,7 +524,7 @@ const getClassDeclarationSignature = (c: ast.ClassDeclaration) => { const parseClass = (c: ast.ClassDeclaration) => Effect.gen(function*() { - const doc = getClassDoc(c) + const doc = parseDoc(getJSDocText(c.getJsDocs())) if (shouldIgnore(doc)) { return [] } @@ -623,8 +578,8 @@ export const parseModuleDocumentation = Effect.gen(function*() { const ocommentRange = Array.head(firstStatement.getLeadingCommentRanges()) if (Option.isSome(ocommentRange)) { const commentRange = ocommentRange.value - const text = commentRange.getText() - return parseDoc(text) + const jsDocsText = commentRange.getText() + return parseDoc(jsDocsText) } } return parseDoc("") diff --git a/src/Printer.ts b/src/Printer.ts index 9989088..e7161df 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -65,11 +65,11 @@ const printFence = (code: string): string => { return "```ts\n" + code + "\n```" } -const printSignaturesArray = (signatures?: ReadonlyArray): string => { - if (signatures === undefined || signatures.length === 0) { +const printOptionalSignature = (signature?: string): string => { + if (signature === undefined) { return "" } - return `\n\n${Markdown.bold("Signature")}\n\n${printFence(signatures.join("\n"))}` + return `\n\n${Markdown.bold("Signature")}\n\n${printFence(signature)}` } const printThrowsArray = (throws?: ReadonlyArray): string => printArray("Throws", throws) @@ -115,14 +115,14 @@ const printSeesArray = (sees?: ReadonlyArray): string => { const printModel = (name: string, doc: Domain.Doc, options: { readonly indentation?: number readonly postfix?: string | undefined - readonly signatures?: ReadonlyArray | undefined + readonly signature?: string | undefined }): string => { return printHeaderByIndentation(options.indentation ?? 0) + printTitle(name, doc.deprecated, options.postfix) + printOptionalDescription(doc.description) + printThrowsArray(doc.throws) + - printSeesArray(doc.sees) + printExamplesArray(doc.examples) + - printSignaturesArray(options.signatures) + + printSeesArray(doc.sees) + + printOptionalSignature(options.signature) + printOptionalSince(doc.since) } @@ -130,7 +130,7 @@ const printStaticMethod = (model: Domain.Method): string => { return printModel(model.name, model.doc, { indentation: 1, postfix: "(static method)", - signatures: model.signatures + signature: model.signature }) } @@ -138,7 +138,7 @@ const printMethod = (model: Domain.Method): string => { return printModel(model.name, model.doc, { indentation: 1, postfix: "(method)", - signatures: model.signatures + signature: model.signature }) } @@ -146,7 +146,7 @@ const printProperty = (model: Domain.Property): string => { return printModel(model.name, model.doc, { indentation: 1, postfix: "(property)", - signatures: [model.signature] + signature: model.signature }) } @@ -165,7 +165,7 @@ const addLineBreak = (i: number): string => i === 0 ? "\n\n" : "" export const printClass = (model: Domain.Class): string => { const header = printModel(model.name, model.doc, { postfix: "(class)", - signatures: [model.signature] + signature: model.signature }) return header + model.staticMethods.map((method, i) => addLineBreak(i) + printStaticMethod(method)).join("\n\n") + @@ -176,7 +176,7 @@ export const printClass = (model: Domain.Class): string => { /** @internal */ export const printConstant = (model: Domain.Constant): string => { return printModel(model.name, model.doc, { - signatures: [model.signature] + signature: model.signature }) } @@ -184,14 +184,14 @@ export const printConstant = (model: Domain.Constant): string => { export const printExport = (model: Domain.Export): string => { return printModel(model.name, model.doc, { postfix: model.isNamespaceExport ? "(namespace export)" : undefined, - signatures: [model.signature] + signature: model.signature }) } /** @internal */ export const printFunction = (model: Domain.Function): string => { return printModel(model.name, model.doc, { - signatures: model.signatures + signature: model.signature }) } @@ -200,7 +200,7 @@ export const printInterface = (model: Domain.Interface, indentation: number): st return printModel(model.name, model.doc, { indentation, postfix: "(interface)", - signatures: [model.signature] + signature: model.signature }) } @@ -209,7 +209,7 @@ export const printTypeAlias = (model: Domain.TypeAlias, indentation: number): st return printModel(model.name, model.doc, { indentation, postfix: "(type alias)", - signatures: [model.signature] + signature: model.signature }) } diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 24e4cc0..976c40e 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -1328,7 +1328,7 @@ a static method description... **Signature** \`\`\`ts -static f(): void +declare const f: () => void \`\`\` Since v1.1.0 @@ -1340,7 +1340,7 @@ a method description... **Signature** \`\`\`ts -g(a: number, b: number): { [key: string]: number } +declare const g: (a: number, b: number) => { [key: string]: number; } \`\`\` Since v1.1.0 @@ -1407,8 +1407,7 @@ a static method description... **Signature** \`\`\`ts -static f(x: number): number -static f(x: string): string +declare const f: { (x: number): number; (x: string): string; } \`\`\` Since v1.1.0 @@ -1420,8 +1419,7 @@ a method description... **Signature** \`\`\`ts -map(f: (a: number) => number): Test -map(f: (a: string) => string): Test +declare const map: { (f: (a: number) => number): Test; (f: (a: string) => string): Test; } \`\`\` Since v1.1.0` From 72626acbfac931260a908b6cc1844bf07425f3f8 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sat, 8 Mar 2025 14:50:37 +0100 Subject: [PATCH 40/56] Refactor Printer module visibility and add front matter documentation - Move internal printing functions to module-level scope - Add documentation for `printFrontMatter` function - Update documentation to reflect function visibility changes --- docs/modules/Printer.ts.md | 11 +++++++++ src/Printer.ts | 47 +++++++++++++++----------------------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index 4f614b5..455fe44 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -16,6 +16,7 @@ Since v0.6.0 - [printModule](#printmodule) - [utils](#utils) - [prettify](#prettify) + - [printFrontMatter](#printfrontmatter) --- @@ -81,3 +82,13 @@ declare const prettify: (s: string) => Effect.Effect ``` Since v0.6.0 + +## printFrontMatter + +**Signature** + +```ts +declare const printFrontMatter: (module: Domain.Module, nav_order: number) => string +``` + +Since v0.6.0 diff --git a/src/Printer.ts b/src/Printer.ts index e7161df..ab1059f 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -21,12 +21,8 @@ export type Printable = | Domain.Namespace | Domain.Module -/** - * @category CLI - * @since 0.6.0 - */ const Markdown = { - bold: (s: string) => `**${s}**`, + bold: (content: string) => `**${content}**`, fence: (content: string) => `\`\`\`ts\n${content}\n\`\`\`\n\n`, strikethrough: (content: string) => `~~${content}~~` } @@ -150,19 +146,9 @@ const printProperty = (model: Domain.Property): string => { }) } -/** @internal */ -export const printFrontMatter = (module: Domain.Module, order: number): string => { - return `--- -title: ${module.name} -nav_order: ${order} -parent: Modules ----` -} - const addLineBreak = (i: number): string => i === 0 ? "\n\n" : "" -/** @internal */ -export const printClass = (model: Domain.Class): string => { +const printClass = (model: Domain.Class): string => { const header = printModel(model.name, model.doc, { postfix: "(class)", signature: model.signature @@ -173,30 +159,26 @@ export const printClass = (model: Domain.Class): string => { model.properties.map((property, i) => addLineBreak(i) + printProperty(property)).join("\n\n") } -/** @internal */ -export const printConstant = (model: Domain.Constant): string => { +const printConstant = (model: Domain.Constant): string => { return printModel(model.name, model.doc, { signature: model.signature }) } -/** @internal */ -export const printExport = (model: Domain.Export): string => { +const printExport = (model: Domain.Export): string => { return printModel(model.name, model.doc, { postfix: model.isNamespaceExport ? "(namespace export)" : undefined, signature: model.signature }) } -/** @internal */ -export const printFunction = (model: Domain.Function): string => { +const printFunction = (model: Domain.Function): string => { return printModel(model.name, model.doc, { signature: model.signature }) } -/** @internal */ -export const printInterface = (model: Domain.Interface, indentation: number): string => { +const printInterface = (model: Domain.Interface, indentation: number): string => { return printModel(model.name, model.doc, { indentation, postfix: "(interface)", @@ -204,8 +186,7 @@ export const printInterface = (model: Domain.Interface, indentation: number): st }) } -/** @internal */ -export const printTypeAlias = (model: Domain.TypeAlias, indentation: number): string => { +const printTypeAlias = (model: Domain.TypeAlias, indentation: number): string => { return printModel(model.name, model.doc, { indentation, postfix: "(type alias)", @@ -213,8 +194,7 @@ export const printTypeAlias = (model: Domain.TypeAlias, indentation: number): st }) } -/** @internal */ -export const printNamespace = (model: Domain.Namespace, indentation: number): string => { +const printNamespace = (model: Domain.Namespace, indentation: number): string => { const header = printModel(model.name, model.doc, { indentation, postfix: "(namespace)" @@ -356,6 +336,17 @@ const defaultPrettierOptions: Prettier.Options = { trailingComma: "none" } +/** + * @since 0.6.0 + */ +export const printFrontMatter = (module: Domain.Module, nav_order: number): string => { + return `--- +title: ${module.name} +nav_order: ${nav_order} +parent: Modules +---` +} + /** * @since 0.6.0 */ From abf0c8fb01ba7af71b504915b1c00b782270137c Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sat, 8 Mar 2025 16:43:46 +0100 Subject: [PATCH 41/56] Add source link generation for documentation modules - Implement source link generation for functions, classes, and other printable entities - Update Printer module to dynamically generate GitHub source links - Modify Domain and Parser modules to support source position tracking - Refactor printing functions to use Effect for source link generation - Update test cases to validate new source link functionality --- docs/modules/Checker.ts.md | 16 ++++ docs/modules/Domain.ts.md | 16 +--- docs/modules/Parser.ts.md | 2 + docs/modules/Printer.ts.md | 17 ++-- src/Core.ts | 2 +- src/Domain.ts | 7 +- src/Parser.ts | 3 +- src/Printer.ts | 176 +++++++++++++++++++++---------------- test/Parser.test.ts | 46 ++++++++-- 9 files changed, 174 insertions(+), 111 deletions(-) diff --git a/docs/modules/Checker.ts.md b/docs/modules/Checker.ts.md index 2d0b39e..d0432eb 100644 --- a/docs/modules/Checker.ts.md +++ b/docs/modules/Checker.ts.md @@ -34,6 +34,8 @@ Since v0.6.0 declare const checkClasses: (_classes: ReadonlyArray) => Effect.Effect, never, never> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L32) + Since v0.6.0 ## checkConstants @@ -44,6 +46,8 @@ Since v0.6.0 declare const checkConstants: (_constants: ReadonlyArray) => Effect.Effect, never, never> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L39) + Since v0.6.0 ## checkExports @@ -54,6 +58,8 @@ Since v0.6.0 declare const checkExports: (_exports: ReadonlyArray) => Effect.Effect, never, never> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L67) + Since v0.6.0 ## checkFunctions @@ -66,6 +72,8 @@ declare const checkFunctions: ( ) => Effect.Effect, never, Parser.Source> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L25) + Since v0.6.0 ## checkInterfaces @@ -78,6 +86,8 @@ declare const checkInterfaces: ( ) => Effect.Effect, never, never> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L46) + Since v0.6.0 ## checkModule @@ -88,6 +98,8 @@ Since v0.6.0 declare const checkModule: (_module: Domain.Module) => Effect.Effect, never, never> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L74) + Since v0.6.0 ## checkNamespaces @@ -100,6 +112,8 @@ declare const checkNamespaces: ( ) => Effect.Effect, never, never> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L60) + Since v0.6.0 ## checkTypeAliases @@ -112,4 +126,6 @@ declare const checkTypeAliases: ( ) => Effect.Effect, never, never> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L53) + Since v0.6.0 diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 85d0ea4..dfd11a5 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -29,13 +29,12 @@ Since v0.6.0 - [\_tag (property)](#_tag-property-4) - [Method (class)](#method-class) - [Module (class)](#module-class) - - [\_tag (property)](#_tag-property-5) - [Namespace (class)](#namespace-class) - - [\_tag (property)](#_tag-property-6) + - [\_tag (property)](#_tag-property-5) - [Position (interface)](#position-interface) - [Property (class)](#property-class) - [TypeAlias (class)](#typealias-class) - - [\_tag (property)](#_tag-property-7) + - [\_tag (property)](#_tag-property-6) - [service](#service) - [Process (class)](#process-class) - [sorting](#sorting) @@ -256,6 +255,7 @@ Since v0.6.0 ```ts declare class Module { constructor( + readonly source: Parser.SourceShape, readonly name: string, readonly doc: Doc, readonly path: Array.NonEmptyReadonlyArray, @@ -271,16 +271,6 @@ declare class Module { constructor( Since v0.6.0 -### \_tag (property) - -**Signature** - -```ts -readonly _tag: "Module" -``` - -Since v0.6.0 - ## Namespace (class) **Signature** diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index d051664..98de277 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -71,6 +71,8 @@ declare const parseFiles: ( > ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L667) + Since v0.6.0 ## parseFunctions diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index 455fe44..17a23a7 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -39,18 +39,13 @@ export const a: string = "a" **Example** (Title 1) ```ts twoslash title="Title 1" -import { Domain, Printer } from "@effect/docgen" -import { Option } from "effect" - -const doc = new Domain.Doc(undefined, ["1.0.0"], [], [], [], [], [], {}) -const m = new Domain.Module("tests", doc, ["src", "tests.ts"], [], [], [], [], [], [], []) -console.log(Printer.printModule(m)) +export const b: string = "b" ``` **Example** (Title 2) ```js twoslash title="Title 2" -export const a: string = "b" +export const c: string = "c" ``` **Throws** @@ -66,9 +61,11 @@ export const a: string = "b" **Signature** ```ts -declare const printModule: (module: Domain.Module) => string +declare const printModule: (module: Domain.Module) => Effect.Effect ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L323) + Since v0.6.0 # utils @@ -81,6 +78,8 @@ Since v0.6.0 declare const prettify: (s: string) => Effect.Effect ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L375) + Since v0.6.0 ## printFrontMatter @@ -91,4 +90,6 @@ Since v0.6.0 declare const printFrontMatter: (module: Domain.Module, nav_order: number) => string ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L364) + Since v0.6.0 diff --git a/src/Core.ts b/src/Core.ts index 1e24269..08792af 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -522,7 +522,7 @@ const getModuleMarkdownFiles = (modules: ReadonlyArray) => Effect.forEach(modules, (module, i) => Effect.gen(function*() { const outputPath = yield* getModuleMarkdownOutputPath(module) - const moduleContent = Printer.printModule(module) + const moduleContent = yield* Printer.printModule(module) const tocgen = yield* Effect.promise(async () => { // @ts-expect-error return await import("@effect/markdown-toc").then((m) => m.default) diff --git a/src/Domain.ts b/src/Domain.ts index 7c2e478..77a0dd8 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -7,7 +7,7 @@ import * as Data from "effect/Data" import * as Effect from "effect/Effect" import * as Order from "effect/Order" import * as String from "effect/String" - +import type * as Parser from "./Parser.js" /** * @category model * @since 0.6.0 @@ -43,11 +43,8 @@ export class Doc { * @since 0.6.0 */ export class Module { - /** - * @since 0.6.0 - */ - readonly _tag = "Module" // TODO: remove this constructor( + readonly source: Parser.SourceShape, readonly name: string, readonly doc: Doc, readonly path: Array.NonEmptyReadonlyArray, diff --git a/src/Parser.ts b/src/Parser.ts index b565d2b..bc5b883 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -601,6 +601,7 @@ export const parseModule = Effect.gen(function*() { const namespaces = yield* parseNamespaces const name = source.sourceFile.getBaseName() return new Domain.Module( + source, name, doc, source.path, @@ -622,8 +623,8 @@ export const parseFile = (file: Domain.File): Effect.Effect, Configuration.Configuration | Path.Path> => { return Effect.gen(function*() { const path = yield* Path.Path - const filePath = file.path.split(path.sep) const sourceFile = project.getSourceFile(file.path) + const filePath = file.path.split(path.sep) if (sourceFile !== undefined && Array.isNonEmptyArray(filePath)) { return yield* Effect.provideService(parseModule, Source, { sourceFile, path: filePath }) } diff --git a/src/Printer.ts b/src/Printer.ts index ab1059f..5a784ce 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -8,7 +8,9 @@ import * as Order from "effect/Order" import * as Record from "effect/Record" import * as String from "effect/String" import * as Prettier from "prettier" +import * as Configuration from "./Configuration.js" import type * as Domain from "./Domain.js" +import * as Parser from "./Parser.js" /** @internal */ export type Printable = @@ -19,7 +21,6 @@ export type Printable = | Domain.Interface | Domain.TypeAlias | Domain.Namespace - | Domain.Module const Markdown = { bold: (content: string) => `**${content}**`, @@ -108,21 +109,38 @@ const printSeesArray = (sees?: ReadonlyArray): string => { return `\n\n${Markdown.bold("See")}\n\n${sees.map((see) => `- ${replaceJSDocLinks(see)}`).join("\n")}` } +const printOptionalSourceLink = (position?: Domain.Position) => { + return Effect.gen(function*() { + if (position === undefined) { + return "" + } + const config = yield* Configuration.Configuration + const source = yield* Parser.Source + const name = source.sourceFile.getBaseName() + return `\n\n[Source](${config.projectHomepage}/blob/main/src/${name}#L${position.line})` + }) +} + const printModel = (name: string, doc: Domain.Doc, options: { readonly indentation?: number readonly postfix?: string | undefined readonly signature?: string | undefined -}): string => { - return printHeaderByIndentation(options.indentation ?? 0) + printTitle(name, doc.deprecated, options.postfix) + - printOptionalDescription(doc.description) + - printThrowsArray(doc.throws) + - printExamplesArray(doc.examples) + - printSeesArray(doc.sees) + - printOptionalSignature(options.signature) + - printOptionalSince(doc.since) + readonly position?: Domain.Position | undefined +}) => { + return Effect.gen(function*() { + const sourceLink = yield* printOptionalSourceLink(options.position) + return printHeaderByIndentation(options.indentation ?? 0) + printTitle(name, doc.deprecated, options.postfix) + + printOptionalDescription(doc.description) + + printThrowsArray(doc.throws) + + printExamplesArray(doc.examples) + + printSeesArray(doc.sees) + + printOptionalSignature(options.signature) + + sourceLink + + printOptionalSince(doc.since) + }) } -const printStaticMethod = (model: Domain.Method): string => { +const printStaticMethod = (model: Domain.Method) => { return printModel(model.name, model.doc, { indentation: 1, postfix: "(static method)", @@ -130,7 +148,7 @@ const printStaticMethod = (model: Domain.Method): string => { }) } -const printMethod = (model: Domain.Method): string => { +const printMethod = (model: Domain.Method) => { return printModel(model.name, model.doc, { indentation: 1, postfix: "(method)", @@ -138,7 +156,7 @@ const printMethod = (model: Domain.Method): string => { }) } -const printProperty = (model: Domain.Property): string => { +const printProperty = (model: Domain.Property) => { return printModel(model.name, model.doc, { indentation: 1, postfix: "(property)", @@ -146,39 +164,43 @@ const printProperty = (model: Domain.Property): string => { }) } -const addLineBreak = (i: number): string => i === 0 ? "\n\n" : "" - -const printClass = (model: Domain.Class): string => { - const header = printModel(model.name, model.doc, { - postfix: "(class)", - signature: model.signature +const printClass = (model: Domain.Class) => { + return Effect.gen(function*() { + const header = yield* printModel(model.name, model.doc, { + postfix: "(class)", + signature: model.signature + }) + const staticMethods = yield* Effect.forEach(model.staticMethods, (method) => printStaticMethod(method)) + const methods = yield* Effect.forEach(model.methods, (method) => printMethod(method)) + const properties = yield* Effect.forEach(model.properties, (property) => printProperty(property)) + return header + + staticMethods.map((s) => "\n\n" + s).join("") + + methods.map((s) => "\n\n" + s).join("") + + properties.map((s) => "\n\n" + s).join("") }) - return header + - model.staticMethods.map((method, i) => addLineBreak(i) + printStaticMethod(method)).join("\n\n") + - model.methods.map((method, i) => addLineBreak(i) + printMethod(method)).join("\n\n") + - model.properties.map((property, i) => addLineBreak(i) + printProperty(property)).join("\n\n") } -const printConstant = (model: Domain.Constant): string => { +const printConstant = (model: Domain.Constant) => { return printModel(model.name, model.doc, { signature: model.signature }) } -const printExport = (model: Domain.Export): string => { +const printExport = (model: Domain.Export) => { return printModel(model.name, model.doc, { postfix: model.isNamespaceExport ? "(namespace export)" : undefined, signature: model.signature }) } -const printFunction = (model: Domain.Function): string => { +const printFunction = (model: Domain.Function) => { return printModel(model.name, model.doc, { - signature: model.signature + signature: model.signature, + position: model.position }) } -const printInterface = (model: Domain.Interface, indentation: number): string => { +const printInterface = (model: Domain.Interface, indentation: number) => { return printModel(model.name, model.doc, { indentation, postfix: "(interface)", @@ -186,7 +208,7 @@ const printInterface = (model: Domain.Interface, indentation: number): string => }) } -const printTypeAlias = (model: Domain.TypeAlias, indentation: number): string => { +const printTypeAlias = (model: Domain.TypeAlias, indentation: number) => { return printModel(model.name, model.doc, { indentation, postfix: "(type alias)", @@ -194,19 +216,33 @@ const printTypeAlias = (model: Domain.TypeAlias, indentation: number): string => }) } -const printNamespace = (model: Domain.Namespace, indentation: number): string => { - const header = printModel(model.name, model.doc, { - indentation, - postfix: "(namespace)" +const printNamespace = ( + model: Domain.Namespace, + indentation: number +): Effect.Effect => { + return Effect.gen(function*() { + const header = yield* printModel(model.name, model.doc, { + indentation, + postfix: "(namespace)" + }) + const interfaces = yield* Effect.forEach(model.interfaces, (inter) => printInterface(inter, indentation + 1)) + const typeAliases = yield* Effect.forEach( + model.typeAliases, + (typeAlias) => printTypeAlias(typeAlias, indentation + 1) + ) + const namespaces = yield* Effect.forEach( + model.namespaces, + (namespace) => printNamespace(namespace, indentation + 1) + ) + return header + + interfaces.map((s) => "\n\n" + s).join("") + + typeAliases.map((s) => "\n\n" + s).join("") + + namespaces.map((s) => "\n\n" + s).join("") }) - return header + "\n\n" + - model.interfaces.map((inter) => printInterface(inter, indentation + 1) + "\n\n").join("") + - model.typeAliases.map((typeAlias) => printTypeAlias(typeAlias, indentation + 1) + "\n\n").join("") + - model.namespaces.map((namespace) => printNamespace(namespace, indentation + 1) + "\n\n").join("") } /** @internal */ -export const print = (p: Printable): string => { +export const print = (p: Printable) => { switch (p._tag) { case "Class": return printClass(p) @@ -222,8 +258,6 @@ export const print = (p: Printable): string => { return printTypeAlias(p, 0) case "Namespace": return printNamespace(p, 0) - case "Module": - return printModule(p) } } @@ -268,18 +302,13 @@ const sortByName: (self: Iterable) => Array = * **Example** (Title 1) * * ```ts twoslash title="Title 1" - * import { Domain, Printer } from "@effect/docgen" - * import { Option } from "effect" - * - * const doc = new Domain.Doc(undefined, ["1.0.0"], [], [], [], [], [], {}) - * const m = new Domain.Module("tests", doc, ["src", "tests.ts"], [], [], [], [], [], [], []) - * console.log(Printer.printModule(m)) + * export const b: string = "b" * ``` * * **Example** (Title 2) * * ~~~js twoslash title="Title 2" - * export const a: string = "b" + * export const c: string = "c" * ~~~ * * @throws `Error1` - Description 1 @@ -292,40 +321,33 @@ const sortByName: (self: Iterable) => Array = * @since 0.6.0 */ export const printModule = (module: Domain.Module) => { - const description = printModel(module.name, module.doc, { - postfix: "overview" - }) - - const content = pipe( - sortByName(getPrintables(module)), - Array.groupBy((printable) => - printable.doc.category.length === 0 ? DEFAULT_CATEGORY : printable.doc.category.join(", ") - ), - Record.toEntries, - Array.sort(byCategory), - Array.map(([category, printables]) => - [ - `\n# ${category}\n`, - ...pipe( - printables, - Array.sort( - Order.mapInput( - String.Order, - (printable: Printable) => printable.name - ) - ), - Array.map(print) - ) - ].join("\n") + return Effect.gen(function*() { + const description = yield* printModel(module.name, module.doc, { + postfix: "overview" + }) + + const printables = pipe( + sortByName(getPrintables(module)), + Array.groupBy((printable) => + printable.doc.category.length === 0 ? DEFAULT_CATEGORY : printable.doc.category.join(", ") + ), + Record.toEntries, + Array.sort(byCategory) ) - ).join("\n") - return ` -${description} + const strings = yield* Effect.forEach(printables, ([category, printables]) => + Effect.gen(function*() { + const out = `\n\n# ${category}` + const strings = yield* Effect.forEach(sortByName(printables), (printable) => print(printable)) + return out + strings.map((s) => "\n\n" + s).join("") + })) + + const content = strings.join("") + + return `${description} - -${content} -` +${content}` + }).pipe(Effect.provideService(Parser.Source, module.source)) } const defaultPrettierOptions: Prettier.Options = { diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 976c40e..41aa17c 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -42,14 +42,19 @@ const makeSource = (source: string | ast.SourceFile) => { } const print = (printables: ReadonlyArray) => { - const raw = printables.map((printable) => Printer.print(printable).trim()).join("\n") - return Effect.succeed(raw) - // return Printer.prettify(raw) + return Effect.gen(function*() { + const strings = yield* Effect.forEach(printables, (printable) => Printer.print(printable)) + return strings.join("\n") + }) +} + +const isModule = (printableOr: ReadonlyArray | Domain.Module): printableOr is Domain.Module => { + return !Array.isArray(printableOr) } const expectMarkdown = async ( eff: Effect.Effect< - Printer.Printable | ReadonlyArray, + ReadonlyArray | Domain.Module, E, Parser.Source | Configuration.Configuration | Path.Path >, @@ -58,8 +63,11 @@ const expectMarkdown = async ( config?: Partial ) => { const exit = await eff.pipe( - Effect.flatMap((a) => { - return print(Array.isArray(a) ? a : [a]) + Effect.flatMap((printableOr) => { + if (isModule(printableOr)) { + return Printer.printModule(printableOr) + } + return print(printableOr) }), Effect.provideService(Parser.Source, makeSource(sourceText)), Effect.provideService(Configuration.Configuration, { ...defaultConfig, ...config }), @@ -150,6 +158,8 @@ This is a description containing two links to \`foo\` and \`bar\`. declare const myfunc: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-1.ts#L6) + Since v1.2.0` ) }) @@ -173,6 +183,8 @@ This is a description containing two links to \`foo\` and \`bar\`. declare const myfunc: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-2.ts#L6) + Since v1.2.0` ) }) @@ -202,6 +214,8 @@ description... declare const myfunc: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-3.ts#L7) + Since v1.2.0` ) }) @@ -233,6 +247,8 @@ description... declare const myfunc: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-4.ts#L8) + Since v1.2.0` ) }) @@ -263,6 +279,8 @@ const x = 1 declare const myfunc: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-5.ts#L7) + Since v1.0.0` ) }) @@ -295,6 +313,8 @@ const x = 1 declare const myfunc: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-6.ts#L9) + Since v1.0.0` ) }) @@ -337,6 +357,8 @@ const x = 2 declare const myfunc: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-7.ts#L13) + Since v1.0.0` ) }) @@ -369,6 +391,8 @@ const x = 1 declare const myfunc: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-8.ts#L9) + Since v1.0.0` ) }) @@ -401,6 +425,8 @@ const x = 1 declare const myfunc: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-9.ts#L9) + Since v1.0.0` ) }) @@ -496,6 +522,8 @@ Since v1.0.0` declare const toNullable: (ma: A | null) => A | null \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-17.ts#L4) + Since v1.0.0` ) }) @@ -535,6 +563,8 @@ assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) declare const f: (a: number, b: number) => { [key: string]: number; } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-18.ts#L10) + Since v1.0.0` ) }) @@ -554,6 +584,8 @@ Since v1.0.0` declare const f: (a: number, b: number) => { [key: string]: number; } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-19.ts#L4) + Since v1.0.0` ) }) @@ -579,6 +611,8 @@ a description... declare const f: { (a: Int, b: Int): { [key: string]: number; }; (a: number, b: number): { [key: string]: number; }; } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-20.ts#L8) + Since v1.0.0` ) }) From 3a451b7c490f81eb182bec09b2c10d43fe0db6b6 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sat, 8 Mar 2025 17:13:45 +0100 Subject: [PATCH 42/56] Add configurable source link generation for documentation - Introduce `srcLink` configuration option in schema and configuration - Update CLI, Configuration, and Printer modules to support custom source links - Implement fallback source link generation using project homepage - Modify test cases to validate new source link configuration --- docs/modules/Configuration.ts.md | 2 ++ schema.json | 6 +++++- src/CLI.ts | 9 +++++++++ src/Configuration.ts | 7 +++++++ src/Printer.ts | 2 +- test/Checker.test.ts | 1 + test/Configuration.test.ts | 9 ++++++--- test/Parser.test.ts | 1 + 8 files changed, 32 insertions(+), 5 deletions(-) diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index a132702..ce4233a 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -39,6 +39,7 @@ Since v0.6.0 declare const ConfigurationSchema: Schema.Struct<{ $schema: Schema.optional projectHomepage: Schema.optional + srcLink: Schema.optional srcDir: Schema.optional outDir: Schema.optional theme: Schema.optional @@ -66,6 +67,7 @@ Since v0.6.0 export interface ConfigurationShape { readonly projectName: string readonly projectHomepage: string + readonly srcLink: string readonly srcDir: string readonly outDir: string readonly theme: string diff --git a/schema.json b/schema.json index 2fadc49..77fb2a9 100644 --- a/schema.json +++ b/schema.json @@ -12,6 +12,10 @@ "type": "string", "description": "Will link to the project homepage from the Auxiliary Links of the generated documentation." }, + "srcLink": { + "type": "string", + "description": "Will link to the project source code." + }, "srcDir": { "type": "string", "description": "The directory in which docgen will search for TypeScript files to parse.", @@ -96,4 +100,4 @@ } }, "$ref": "#/$defs/ConfigurationSchema" -} \ No newline at end of file +} diff --git a/src/CLI.ts b/src/CLI.ts index 1149670..9df6a1d 100644 --- a/src/CLI.ts +++ b/src/CLI.ts @@ -27,6 +27,14 @@ const projectHomepage = Options.text("homepage").pipe( Options.optional ) +const srcLink = Options.text("srcLink").pipe( + Options.withFallbackConfig(Config.string("srcLink")), + Options.withDescription( + "The link to the project source code" + ), + Options.optional +) + const srcDir = Options.directory("src", { exists: "yes" }).pipe( Options.withFallbackConfig(Config.string("src").pipe(Config.withDefault("src"))), Options.withDescription( @@ -157,6 +165,7 @@ const examplesCompilerOptions = Options.file("examples-tsconfig-file", { exists: const options = { projectHomepage, + srcLink, srcDir, outDir, theme, diff --git a/src/Configuration.ts b/src/Configuration.ts index 6075e1a..ddd0585 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -35,6 +35,9 @@ export const ConfigurationSchema = Schema.Struct({ projectHomepage: Schema.optional(Schema.String).annotations({ description: "Will link to the project homepage from the Auxiliary Links of the generated documentation." }), + srcLink: Schema.optional(Schema.String).annotations({ + description: "Will link to the project source code." + }), srcDir: Schema.optional(Schema.String).annotations({ description: "The directory in which docgen will search for TypeScript files to parse.", default: "src" @@ -85,6 +88,7 @@ export const ConfigurationSchema = Schema.Struct({ export interface ConfigurationShape { readonly projectName: string readonly projectHomepage: string + readonly srcLink: string readonly srcDir: string readonly outDir: string readonly theme: string @@ -225,6 +229,7 @@ const PackageJsonSchema = Schema.Struct({ /** @internal */ export const load = (args: { readonly projectHomepage: Option.Option + readonly srcLink: Option.Option readonly srcDir: string readonly outDir: string readonly theme: string @@ -248,6 +253,7 @@ export const load = (args: { const packageJson = yield* validateJsonFile(PackageJsonSchema, packageJsonPath) const projectName = packageJson.name const projectHomepage = Option.getOrElse(args.projectHomepage, () => packageJson.homepage) + const srcLink = Option.getOrElse(args.srcLink, () => `${projectHomepage}/blob/main/src/`) // Read the `docgen.json` configuration file to gain access to the TypeScript // configuration options @@ -292,6 +298,7 @@ export const load = (args: { outDir, projectName, projectHomepage, + srcLink, exclude, examplesCompilerOptions, parseCompilerOptions diff --git a/src/Printer.ts b/src/Printer.ts index 5a784ce..8318aff 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -117,7 +117,7 @@ const printOptionalSourceLink = (position?: Domain.Position) => { const config = yield* Configuration.Configuration const source = yield* Parser.Source const name = source.sourceFile.getBaseName() - return `\n\n[Source](${config.projectHomepage}/blob/main/src/${name}#L${position.line})` + return `\n\n[Source](${config.srcLink}${name}#L${position.line})` }) } diff --git a/test/Checker.test.ts b/test/Checker.test.ts index 8768e44..fd33596 100644 --- a/test/Checker.test.ts +++ b/test/Checker.test.ts @@ -18,6 +18,7 @@ const project = new ast.Project({ const defaultConfig: Configuration.ConfigurationShape = { projectName: "docgen", projectHomepage: "https://github.com/effect-ts/docgen", + srcLink: "https://github.com/effect-ts/docgen/blob/main/src/", srcDir: "src", outDir: "docs", theme: "pmarsceill/just-the-docs", diff --git a/test/Configuration.test.ts b/test/Configuration.test.ts index 801025d..0f1c103 100644 --- a/test/Configuration.test.ts +++ b/test/Configuration.test.ts @@ -15,11 +15,11 @@ import * as Option from "effect/Option" import * as assert from "node:assert/strict" import { describe, it } from "vitest" -type DocgenJson = Record +type DocgenJson = typeof Configuration.ConfigurationSchema.Type class DocgenJsonTag extends Context.Tag("DocgenJsonTag")() {} -const makeDocgenJson = (config: Record) => Layer.succeed(DocgenJsonTag, config) +const makeDocgenJson = (config: DocgenJson) => Layer.succeed(DocgenJsonTag, config) const TestFileSystem = Layer.effect( FileSystem.FileSystem, @@ -79,6 +79,7 @@ describe("Configuration", () => { assert.deepStrictEqual(config, { projectName: "name", projectHomepage: "homepage", + srcLink: "homepage/blob/main/src/", srcDir: "src", outDir: "docs", theme: "mikearnaldi/just-the-docs", @@ -114,6 +115,7 @@ describe("Configuration", () => { assert.deepStrictEqual(config, { projectName: "name", projectHomepage: "myproject", + srcLink: "mygithub", srcDir: "src", outDir: "docs", theme: "mikearnaldi/just-the-docs", @@ -132,6 +134,7 @@ describe("Configuration", () => { Effect.provide(TestLive.pipe(Layer.provide( makeDocgenJson({ projectHomepage: "myproject", + srcLink: "mygithub", parseCompilerOptions }) ))), @@ -142,7 +145,7 @@ describe("Configuration", () => { it("should raise a validation error if docgen.json is not valid", async () => { const cli = testCliFor(Effect.void) const result = await cli([]).pipe( - Effect.provide(TestLive.pipe(Layer.provide(makeDocgenJson({ projectHomepage: 1 })))), + Effect.provide(TestLive.pipe(Layer.provide(makeDocgenJson({ projectHomepage: 1 } as any)))), Effect.runPromiseExit ) assert.deepStrictEqual( diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 41aa17c..7f94b9c 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -18,6 +18,7 @@ const project = new ast.Project({ const defaultConfig: Configuration.ConfigurationShape = { projectName: "docgen", projectHomepage: "https://github.com/effect-ts/docgen", + srcLink: "https://github.com/effect-ts/docgen/blob/main/src/", srcDir: "src", outDir: "docs", theme: "pmarsceill/just-the-docs", From 073cbb928edf0d04c0cdce8c2deb50af2b0a127a Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sat, 8 Mar 2025 18:57:02 +0100 Subject: [PATCH 43/56] Refactor Domain module to introduce DocEntry base class - Create a new `DocEntry` base class to consolidate common properties across documentation entities - Modify existing classes (Class, Interface, Function, etc.) to extend `DocEntry` - Update constructors to include position information consistently - Simplify inheritance and reduce code duplication in Domain module - Ensure backward compatibility with existing documentation generation logic --- docs/modules/CLI.ts.md | 2 + docs/modules/Configuration.ts.md | 6 ++ docs/modules/Domain.ts.md | 146 +++++++++++++++++++------------ docs/modules/Parser.ts.md | 18 +++- docs/modules/Printer.ts.md | 6 +- docs/modules/index.ts.md | 10 +++ src/Configuration.ts | 11 +-- src/Domain.ts | 124 ++++++++++++++------------ src/Parser.ts | 44 +++++++--- src/Printer.ts | 65 +++++++------- test/Parser.test.ts | 78 +++++++++++++++++ 11 files changed, 341 insertions(+), 169 deletions(-) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index 2ced2e1..804288b 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -33,4 +33,6 @@ declare const cli: ( > ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/CLI.ts#L189) + Since v0.6.0 diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index ce4233a..6b6e693 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -29,6 +29,8 @@ Since v0.6.0 declare class Configuration ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L109) + Since v0.6.0 ## ConfigurationSchema @@ -57,6 +59,8 @@ declare const ConfigurationSchema: Schema.Struct<{ }> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L33) + Since v0.6.0 ## ConfigurationShape (interface) @@ -82,4 +86,6 @@ export interface ConfigurationShape { } ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L88) + Since v0.6.0 diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index dfd11a5..cc65bf9 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -19,6 +19,7 @@ Since v0.6.0 - [\_tag (property)](#_tag-property-1) - [Doc (class)](#doc-class) - [modifyDescription (method)](#modifydescription-method) + - [DocEntry (class)](#docentry-class) - [DocgenError (class)](#docgenerror-class) - [Export (class)](#export-class) - [\_tag (property)](#_tag-property-2) @@ -27,12 +28,10 @@ Since v0.6.0 - [\_tag (property)](#_tag-property-3) - [Interface (class)](#interface-class) - [\_tag (property)](#_tag-property-4) - - [Method (class)](#method-class) - [Module (class)](#module-class) - [Namespace (class)](#namespace-class) - [\_tag (property)](#_tag-property-5) - [Position (interface)](#position-interface) - - [Property (class)](#property-class) - [TypeAlias (class)](#typealias-class) - [\_tag (property)](#_tag-property-6) - [service](#service) @@ -53,15 +52,18 @@ Since v0.6.0 ```ts declare class Class { constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string, - readonly methods: ReadonlyArray, - readonly staticMethods: ReadonlyArray, - readonly properties: ReadonlyArray + name: string, + doc: Doc, + signature: string, + position: Position, + readonly methods: ReadonlyArray, + readonly staticMethods: ReadonlyArray, + readonly properties: ReadonlyArray ) } ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L79) + Since v0.6.0 ### \_tag (property) @@ -72,6 +74,8 @@ Since v0.6.0 readonly _tag: "Class" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L83) + Since v0.6.0 ## Constant (class) @@ -79,13 +83,13 @@ Since v0.6.0 **Signature** ```ts -declare class Constant { constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) } +declare class Constant { + constructor(name: string, doc: Doc, signature: string, position: Position) +} ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L167) + Since v0.6.0 ### \_tag (property) @@ -96,6 +100,8 @@ Since v0.6.0 readonly _tag: "Constant" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L171) + Since v0.6.0 ## Doc (class) @@ -115,6 +121,8 @@ declare class Doc { constructor( ) } ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L29) + Since v0.6.0 ### modifyDescription (method) @@ -125,6 +133,25 @@ Since v0.6.0 declare const modifyDescription: (description: string | undefined) => Doc ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L41) + +## DocEntry (class) + +**Signature** + +```ts +declare class DocEntry { constructor( + readonly name: string, + readonly doc: Doc, + readonly signature: string, + readonly position: Position + ) } +``` + +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L16) + +Since v0.6.0 + ## DocgenError (class) **Signature** @@ -133,6 +160,8 @@ declare const modifyDescription: (description: string | undefined) => Doc declare class DocgenError ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L273) + Since v0.6.0 ## Export (class) @@ -151,13 +180,16 @@ export { ```ts declare class Export { constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string, + name: string, + doc: Doc, + signature: string, + position: Position, readonly isNamespaceExport: boolean ) } ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L196) + Since v0.6.0 ### \_tag (property) @@ -168,6 +200,8 @@ Since v0.6.0 readonly _tag: "Export" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L200) + Since v0.6.0 ## File (class) @@ -184,6 +218,8 @@ declare class File { constructor( ) } ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L249) + Since v0.6.0 ## Function (class) @@ -191,14 +227,13 @@ Since v0.6.0 **Signature** ```ts -declare class Function { constructor( - readonly position: Position, - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) } +declare class Function { + constructor(name: string, doc: Doc, signature: string, position: Position) +} ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L129) + Since v0.6.0 ### \_tag (property) @@ -209,6 +244,8 @@ Since v0.6.0 readonly _tag: "Function" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L133) + Since v0.6.0 ## Interface (class) @@ -216,13 +253,13 @@ Since v0.6.0 **Signature** ```ts -declare class Interface { constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) } +declare class Interface { + constructor(name: string, doc: Doc, signature: string, position: Position) +} ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L101) + Since v0.6.0 ### \_tag (property) @@ -233,19 +270,7 @@ Since v0.6.0 readonly _tag: "Interface" ``` -Since v0.6.0 - -## Method (class) - -**Signature** - -```ts -declare class Method { constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) } -``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L105) Since v0.6.0 @@ -269,6 +294,8 @@ declare class Module { constructor( ) } ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L59) + Since v0.6.0 ## Namespace (class) @@ -279,12 +306,15 @@ Since v0.6.0 declare class Namespace { constructor( readonly name: string, readonly doc: Doc, + readonly position: Position, readonly interfaces: ReadonlyArray, readonly typeAliases: ReadonlyArray, readonly namespaces: ReadonlyArray ) } ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L216) + Since v0.6.0 ### \_tag (property) @@ -295,6 +325,8 @@ Since v0.6.0 readonly _tag: "Namespace" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L220) + Since v0.6.0 ## Position (interface) @@ -308,19 +340,7 @@ export interface Position { } ``` -Since v0.6.0 - -## Property (class) - -**Signature** - -```ts -declare class Property { constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) } -``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L120) Since v0.6.0 @@ -329,13 +349,13 @@ Since v0.6.0 **Signature** ```ts -declare class TypeAlias { constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) } +declare class TypeAlias { + constructor(name: string, doc: Doc, signature: string, position: Position) +} ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L148) + Since v0.6.0 ### \_tag (property) @@ -346,6 +366,8 @@ Since v0.6.0 readonly _tag: "TypeAlias" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L152) + Since v0.6.0 # service @@ -360,6 +382,8 @@ Represents a handle to the currently executing process. declare class Process ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L284) + Since v0.6.0 # sorting @@ -375,6 +399,8 @@ The file path is converted to lowercase before comparison. declare const ByPath: Order.Order ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L238) + Since v0.6.0 # symbol @@ -387,6 +413,8 @@ Since v0.6.0 declare const DocgenErrorTypeId: unique symbol ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L261) + Since v0.6.0 ## DocgenErrorTypeId (type alias) @@ -397,4 +425,6 @@ Since v0.6.0 type DocgenErrorTypeId = typeof DocgenErrorTypeId ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L267) + Since v0.6.0 diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 98de277..2d668b9 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -35,6 +35,8 @@ Since v0.6.0 declare const parseClasses: Effect.Effect, never, Source> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L584) + Since v0.6.0 ## parseConstants @@ -45,6 +47,8 @@ Since v0.6.0 declare const parseConstants: Effect.Effect, never, Source> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L315) + Since v0.6.0 ## parseExports @@ -55,6 +59,8 @@ Since v0.6.0 declare const parseExports: Effect.Effect, never, Source> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L391) + Since v0.6.0 ## parseFiles @@ -71,7 +77,7 @@ declare const parseFiles: ( > ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L667) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L691) Since v0.6.0 @@ -83,6 +89,8 @@ Since v0.6.0 declare const parseFunctions: Effect.Effect, never, Source> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L240) + Since v0.6.0 ## parseInterfaces @@ -93,6 +101,8 @@ Since v0.6.0 declare const parseInterfaces: Effect.Effect, never, Source> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L133) + Since v0.6.0 ## parseModule @@ -103,6 +113,8 @@ Since v0.6.0 declare const parseModule: Effect.Effect ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L616) + Since v0.6.0 ## parseNamespaces @@ -113,6 +125,8 @@ Since v0.6.0 declare const parseNamespaces: Effect.Effect, never, Configuration.Configuration | Source> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L437) + Since v0.6.0 ## parseTypeAliases @@ -123,4 +137,6 @@ Since v0.6.0 declare const parseTypeAliases: Effect.Effect, never, Source> ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L285) + Since v0.6.0 diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index 17a23a7..9d32d6b 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -64,7 +64,7 @@ export const c: string = "c" declare const printModule: (module: Domain.Module) => Effect.Effect ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L323) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L324) Since v0.6.0 @@ -78,7 +78,7 @@ Since v0.6.0 declare const prettify: (s: string) => Effect.Effect ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L375) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L376) Since v0.6.0 @@ -90,6 +90,6 @@ Since v0.6.0 declare const printFrontMatter: (module: Domain.Module, nav_order: number) => string ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L364) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L365) Since v0.6.0 diff --git a/docs/modules/index.ts.md b/docs/modules/index.ts.md index be40d36..55787fd 100644 --- a/docs/modules/index.ts.md +++ b/docs/modules/index.ts.md @@ -33,6 +33,8 @@ Re-exports all named exports from the "./Configuration.js" module as `Configurat export * as Configuration from "./Configuration.js" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/index.ts#L8) + Since v0.6.0 ## Core (namespace export) @@ -45,6 +47,8 @@ Re-exports all named exports from the "./Core.js" module as `Core`. export * as Core from "./Core.js" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/index.ts#L13) + Since v0.6.0 ## Domain (namespace export) @@ -57,6 +61,8 @@ Re-exports all named exports from the "./Domain.js" module as `Domain`. export * as Domain from "./Domain.js" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/index.ts#L18) + Since v0.6.0 ## Parser (namespace export) @@ -69,6 +75,8 @@ Re-exports all named exports from the "./Parser.js" module as `Parser`. export * as Parser from "./Parser.js" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/index.ts#L28) + Since v0.6.0 ## Printer (namespace export) @@ -81,4 +89,6 @@ Re-exports all named exports from the "./Printer.js" module as `Printer`. export * as Printer from "./Printer.js" ``` +[Source](https://github.com/effect-ts/docgen/blob/main/src/index.ts#L23) + Since v0.6.0 diff --git a/src/Configuration.ts b/src/Configuration.ts index ddd0585..247e707 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -152,15 +152,11 @@ const validateJsonFile = ( ) }) -// TODO: this is invoked twice, why? +// TODO: this is invoked twice const readDocgenConfig = ( path: string -): Effect.Effect< - Option.Option>, - never, - FileSystem.FileSystem -> => - Effect.gen(function*() { +): Effect.Effect>, never, FileSystem.FileSystem> => { + return Effect.gen(function*() { const fs = yield* FileSystem.FileSystem const exists = yield* Effect.orDie(fs.exists(path)) if (exists) { @@ -170,6 +166,7 @@ const readDocgenConfig = ( return Option.none() } }) +} const readTSConfig = (fileName: string): Effect.Effect< { readonly [x: string]: unknown }, diff --git a/src/Domain.ts b/src/Domain.ts index 77a0dd8..140f602 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -8,6 +8,20 @@ import * as Effect from "effect/Effect" import * as Order from "effect/Order" import * as String from "effect/String" import type * as Parser from "./Parser.js" + +/** + * @category model + * @since 0.6.0 + */ +export class DocEntry { + constructor( + readonly name: string, + readonly doc: Doc, + readonly signature: string, + readonly position: Position + ) {} +} + /** * @category model * @since 0.6.0 @@ -62,59 +76,41 @@ export class Module { * @category model * @since 0.6.0 */ -export class Class { +export class Class extends DocEntry { /** * @since 0.6.0 */ readonly _tag = "Class" constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string, - readonly methods: ReadonlyArray, - readonly staticMethods: ReadonlyArray, - readonly properties: ReadonlyArray - ) {} -} - -/** - * @category model - * @since 0.6.0 - */ -export class Method { - constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) {} -} - -/** - * @category model - * @since 0.6.0 - */ -export class Property { - constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) {} + name: string, + doc: Doc, + signature: string, + position: Position, + readonly methods: ReadonlyArray, + readonly staticMethods: ReadonlyArray, + readonly properties: ReadonlyArray + ) { + super(name, doc, signature, position) + } } /** * @category model * @since 0.6.0 */ -export class Interface { +export class Interface extends DocEntry { /** * @since 0.6.0 */ readonly _tag = "Interface" constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) {} + name: string, + doc: Doc, + signature: string, + position: Position + ) { + super(name, doc, signature, position) + } } /** @@ -130,49 +126,57 @@ export interface Position { * @category model * @since 0.6.0 */ -export class Function { +export class Function extends DocEntry { /** * @since 0.6.0 */ readonly _tag = "Function" constructor( - readonly position: Position, - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) {} + name: string, + doc: Doc, + signature: string, + position: Position + ) { + super(name, doc, signature, position) + } } /** * @category model * @since 0.6.0 */ -export class TypeAlias { +export class TypeAlias extends DocEntry { /** * @since 0.6.0 */ readonly _tag = "TypeAlias" constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) {} + name: string, + doc: Doc, + signature: string, + position: Position + ) { + super(name, doc, signature, position) + } } /** * @category model * @since 0.6.0 */ -export class Constant { +export class Constant extends DocEntry { /** * @since 0.6.0 */ readonly _tag = "Constant" constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string - ) {} + name: string, + doc: Doc, + signature: string, + position: Position + ) { + super(name, doc, signature, position) + } } /** @@ -189,17 +193,20 @@ export class Constant { * @category model * @since 0.6.0 */ -export class Export { +export class Export extends DocEntry { /** * @since 0.6.0 */ readonly _tag = "Export" constructor( - readonly name: string, - readonly doc: Doc, - readonly signature: string, + name: string, + doc: Doc, + signature: string, + position: Position, readonly isNamespaceExport: boolean - ) {} + ) { + super(name, doc, signature, position) + } } /** @@ -214,6 +221,7 @@ export class Namespace { constructor( readonly name: string, readonly doc: Doc, + readonly position: Position, readonly interfaces: ReadonlyArray, readonly typeAliases: ReadonlyArray, readonly namespaces: ReadonlyArray diff --git a/src/Parser.ts b/src/Parser.ts index bc5b883..02d7373 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -107,11 +107,13 @@ const parseInterfaceDeclaration = (id: ast.InterfaceDeclaration) => } const name = id.getName() const signature = id.getText() + const position = yield* parsePosition(id) return [ new Domain.Interface( name, doc, - signature + signature, + position ) ] }) @@ -173,10 +175,10 @@ const parseFunctionDeclaration = (fd: ast.FunctionDeclaration) => const position = yield* parsePosition(fd) return [ new Domain.Function( - position, name ?? "", doc, - signature + signature, + position ) ] }) @@ -196,10 +198,10 @@ const parseFunctionVariableDeclaration = (vd: ast.VariableDeclaration) => const position = source.sourceFile.getLineAndColumnAtPos(startPos) return [ new Domain.Function( - position, name ?? "", doc, - signature + signature, + position ) ] }) @@ -257,11 +259,13 @@ const parseTypeAliasDeclaration = (ta: ast.TypeAliasDeclaration) => const type = parseType(ta) const definition = ta.getTypeNode()?.getText() const signature = `type ${len > 0 ? type : name} = ${definition}` + const position = yield* parsePosition(ta) return [ new Domain.TypeAlias( name, doc, - signature + signature, + position ) ] }) @@ -293,11 +297,13 @@ const parseConstantVariableDeclaration = (vd: ast.VariableDeclaration) => const name = vd.getName() const type = parseType(vd) const signature = `declare const ${name}: ${type}` + const position = yield* parsePosition(vd) return [ new Domain.Constant( name, doc, - signature + signature, + position ) ] }) @@ -339,10 +345,12 @@ const parseExportSpecifier = (es: ast.ExportSpecifier) => const jsDocsText = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) const doc = parseDoc(jsDocsText) const signature = `declare const ${name}: ${type}` + const position = yield* parsePosition(es) return new Domain.Export( name, doc, signature, + position, false ) }) @@ -356,12 +364,14 @@ const parseExportStar = (ed: ast.ExportDeclaration) => const ocommentRange = Array.head(ed.getLeadingCommentRanges()) const jsDocsText = ocommentRange.pipe(Option.map((range) => range.getText()), Option.getOrElse(() => "")) const doc = parseDoc(jsDocsText) + const position = yield* parsePosition(ed) return new Domain.Export( namespace ?? name, doc.modifyDescription( `Re-exports all named exports from the ${name} module${namespace === undefined ? "" : ` as \`${namespace}\``}.` ), signature, + position, true ) }) @@ -399,10 +409,12 @@ const parseModuleDeclaration = ( const interfaces = yield* getInterfaces const typeAliases = yield* getTypeAliases const namespaces = yield* getNamespaces + const position = yield* parsePosition(ed) return [ new Domain.Namespace( name, doc, + position, interfaces, typeAliases, namespaces @@ -443,11 +455,13 @@ const parseMethod = (md: ast.MethodDeclaration) => } const type = parseType(md) const signature = `declare const ${name}: ${type}` + const position = yield* parsePosition(md) return Option.some( - new Domain.Method( + new Domain.DocEntry( name, doc, - signature + signature, + position ) ) }) @@ -468,7 +482,15 @@ const parseProperty = (pd: ast.PropertyDeclaration) => }) ) const signature = `${readonly}${name}: ${type}` - return [new Domain.Property(name, doc, signature)] + const position = yield* parsePosition(pd) + return [ + new Domain.DocEntry( + name, + doc, + signature, + position + ) + ] }) const parseProperties = (c: ast.ClassDeclaration) => { @@ -541,11 +563,13 @@ const parseClass = (c: ast.ClassDeclaration) => Effect.map(Array.getSomes) ) const properties = yield* parseProperties(c) + const position = yield* parsePosition(c) return [ new Domain.Class( name, doc, signature, + position, methods, staticMethods, properties diff --git a/src/Printer.ts b/src/Printer.ts index 8318aff..1b5612e 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -122,10 +122,10 @@ const printOptionalSourceLink = (position?: Domain.Position) => { } const printModel = (name: string, doc: Domain.Doc, options: { - readonly indentation?: number - readonly postfix?: string | undefined readonly signature?: string | undefined readonly position?: Domain.Position | undefined + readonly indentation?: number | undefined + readonly postfix?: string | undefined }) => { return Effect.gen(function*() { const sourceLink = yield* printOptionalSourceLink(options.position) @@ -140,35 +140,43 @@ const printModel = (name: string, doc: Domain.Doc, options: { }) } -const printStaticMethod = (model: Domain.Method) => { +const printEntry = (model: Domain.DocEntry, options: { + readonly indentation?: number | undefined + readonly postfix?: string | undefined +}) => { return printModel(model.name, model.doc, { + signature: model.signature, + position: model.position, + indentation: options.indentation, + postfix: options.postfix + }) +} + +const printStaticMethod = (model: Domain.DocEntry) => { + return printEntry(model, { indentation: 1, - postfix: "(static method)", - signature: model.signature + postfix: "(static method)" }) } -const printMethod = (model: Domain.Method) => { - return printModel(model.name, model.doc, { +const printMethod = (model: Domain.DocEntry) => { + return printEntry(model, { indentation: 1, - postfix: "(method)", - signature: model.signature + postfix: "(method)" }) } -const printProperty = (model: Domain.Property) => { - return printModel(model.name, model.doc, { +const printProperty = (model: Domain.DocEntry) => { + return printEntry(model, { indentation: 1, - postfix: "(property)", - signature: model.signature + postfix: "(property)" }) } const printClass = (model: Domain.Class) => { return Effect.gen(function*() { - const header = yield* printModel(model.name, model.doc, { - postfix: "(class)", - signature: model.signature + const header = yield* printEntry(model, { + postfix: "(class)" }) const staticMethods = yield* Effect.forEach(model.staticMethods, (method) => printStaticMethod(method)) const methods = yield* Effect.forEach(model.methods, (method) => printMethod(method)) @@ -181,38 +189,30 @@ const printClass = (model: Domain.Class) => { } const printConstant = (model: Domain.Constant) => { - return printModel(model.name, model.doc, { - signature: model.signature - }) + return printEntry(model, {}) } const printExport = (model: Domain.Export) => { - return printModel(model.name, model.doc, { - postfix: model.isNamespaceExport ? "(namespace export)" : undefined, - signature: model.signature + return printEntry(model, { + postfix: model.isNamespaceExport ? "(namespace export)" : undefined }) } const printFunction = (model: Domain.Function) => { - return printModel(model.name, model.doc, { - signature: model.signature, - position: model.position - }) + return printEntry(model, {}) } const printInterface = (model: Domain.Interface, indentation: number) => { - return printModel(model.name, model.doc, { + return printEntry(model, { indentation, - postfix: "(interface)", - signature: model.signature + postfix: "(interface)" }) } const printTypeAlias = (model: Domain.TypeAlias, indentation: number) => { - return printModel(model.name, model.doc, { + return printEntry(model, { indentation, - postfix: "(type alias)", - signature: model.signature + postfix: "(type alias)" }) } @@ -222,6 +222,7 @@ const printNamespace = ( ): Effect.Effect => { return Effect.gen(function*() { const header = yield* printModel(model.name, model.doc, { + position: model.position, indentation, postfix: "(namespace)" }) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 7f94b9c..301d42b 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -134,6 +134,8 @@ console.log(foo) declare const foo: "foo" \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-0.ts#L19) + Since v1.0.0` ) }) @@ -639,6 +641,8 @@ a description... declare const s: string \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-21.ts#L6) + Since v1.0.0` ) }) @@ -658,6 +662,8 @@ Since v1.0.0` declare const left: (l: E) => string \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-22.ts#L4) + Since v1.0.0` ) }) @@ -679,6 +685,8 @@ Since v1.0.0` declare const empty: A \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-23.ts#L6) + Since v1.0.0` ) }) @@ -704,6 +712,8 @@ Since v1.0.0` declare const taskSeq: { a: number; } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-24.ts#L7) + Since v1.0.0` ) }) @@ -744,6 +754,8 @@ a description... type Option = None | Some \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-26.ts#L9) + Since v1.0.0` ) }) @@ -776,6 +788,8 @@ Since v1.0.0` declare const b: 1 \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-28.ts#L6) + Since v1.0.0` ) }) @@ -808,6 +822,8 @@ description_of_a declare const a: 1 \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-29.ts#L9) + Since v1.0.0 ## b @@ -819,6 +835,8 @@ description_of_b declare const b: 2 \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-29.ts#L14) + Since v2.0.0` ) }) @@ -859,6 +877,10 @@ Since v2.0.0` } ), "declare const b: 1", + { + "column": 11, + "line": 7 + }, false ) ]) @@ -902,6 +924,10 @@ Since v2.0.0` } ), "export * from './example'", + { + "column": 10, + "line": 5 + }, true ) ]) @@ -945,6 +971,10 @@ Since v2.0.0` } ), "export * as example from './example'", + { + "column": 11, + "line": 5 + }, true ) ]) @@ -988,6 +1018,8 @@ a description... export interface A {} \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-35.ts#L6) + Since v1.0.0` ) }) @@ -1021,6 +1053,8 @@ Since v1.0.0` `, `## A (namespace) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-38.ts#L5) + Since v1.0.0` ) }) @@ -1039,6 +1073,8 @@ Since v1.0.0` `, `## A (namespace) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-39.ts#L5) + Since v1.0.0` ) }) @@ -1061,6 +1097,8 @@ export namespace A { `, `## A (namespace) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-40.ts#L5) + Since v1.0.0 ### B (interface) @@ -1073,6 +1111,8 @@ export interface B { } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-40.ts#L9) + Since v1.0.1` ) }) @@ -1092,6 +1132,8 @@ Since v1.0.1` `, `## A (namespace) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-41.ts#L5) + Since v1.0.0` ) }) @@ -1112,6 +1154,8 @@ Since v1.0.0` `, `## A (namespace) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-42.ts#L5) + Since v1.0.0 ### B (type alias) @@ -1122,6 +1166,8 @@ Since v1.0.0 type B = string \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-42.ts#L9) + Since v1.0.1` ) }) @@ -1141,6 +1187,8 @@ Since v1.0.1` `, `## A (namespace) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-43.ts#L5) + Since v1.0.0` ) }) @@ -1166,10 +1214,14 @@ Since v1.0.0` `, `## A (namespace) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-44.ts#L5) + Since v1.0.0 ### B (namespace) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-44.ts#L9) + Since v1.0.1 #### C (type alias) @@ -1180,6 +1232,8 @@ Since v1.0.1 type C = string \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-44.ts#L13) + Since v1.0.2` ) }) @@ -1226,6 +1280,8 @@ Since v1.0.2` declare class MyClass \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-47.ts#L4) + Since v1.0.0` ) }) @@ -1248,6 +1304,8 @@ description declare class C { constructor() } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-48.ts#L5) + Since v1.0.0` ) }) @@ -1298,6 +1356,8 @@ description declare class C \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-50.ts#L5) + Since v1.0.0 ### a (property) @@ -1308,6 +1368,8 @@ Since v1.0.0 a: string \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-50.ts#L9) + Since v1.0.0` ) }) @@ -1354,6 +1416,8 @@ a class description... declare class Test { constructor(readonly value: string) } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-51.ts#L6) + Since v1.0.0 ### ~~f~~ (static method) @@ -1366,6 +1430,8 @@ a static method description... declare const f: () => void \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-51.ts#L19) + Since v1.1.0 ### ~~g~~ (method) @@ -1378,6 +1444,8 @@ a method description... declare const g: (a: number, b: number) => { [key: string]: number; } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-51.ts#L26) + Since v1.1.0 ### ~~a~~ (property) @@ -1390,6 +1458,8 @@ a property... readonly a: string \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-51.ts#L12) + Since v1.1.0` ) }) @@ -1433,6 +1503,8 @@ a class description... declare class Test { constructor(readonly value: A) } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-52.ts#L6) + Since v1.0.0 ### ~~f~~ (static method) @@ -1445,6 +1517,8 @@ a static method description... declare const f: { (x: number): number; (x: string): string; } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-52.ts#L14) + Since v1.1.0 ### ~~map~~ (method) @@ -1457,6 +1531,8 @@ a method description... declare const map: { (f: (a: number) => number): Test; (f: (a: string) => string): Test; } \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-52.ts#L23) + Since v1.1.0` ) }) @@ -1490,6 +1566,8 @@ a class description... declare class Test \`\`\` +[Source](https://github.com/effect-ts/docgen/blob/main/src/test-53.ts#L5) + Since v1.0.0` ) }) From 97b9f158d70753baf005928a0771d8f444127884 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sat, 8 Mar 2025 19:24:17 +0100 Subject: [PATCH 44/56] update changeset --- .changeset/silly-insects-draw.md | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/.changeset/silly-insects-draw.md b/.changeset/silly-insects-draw.md index fa26034..48255e3 100644 --- a/.changeset/silly-insects-draw.md +++ b/.changeset/silly-insects-draw.md @@ -2,19 +2,8 @@ "@effect/docgen": minor --- -- Remove fences from Example type and update related parsing and generation logic -- Remove unnecessary assert import handling in Core module -- Change "Added in" to "Since" in Markdown generation -- Reorder signature and example sections in Markdown generation -- Remove redundant "Example" header in Markdown generation -- runExamples is not false by default -- Extract examples from descriptions (disable with `skip-type-checking` metadata on fenced code blocks) -- Add support for `@throws` tag in documentation generation -- Refactor Domain module to use class-based implementation -- Remove File module and integrate File class into Domain module -- Move DocgenError from Error module to Domain module -- Integrate Process service into Domain module -- Rename Markdown module to Printer and update related imports -- Remove Option usage in Domain -- Remove NamedDoc class and update Domain model constructors -- Add support for @see JSDoc tag in function documentation +- **Extracts examples from descriptions** – This can be disabled using `skip-type-checking` metadata on fenced code blocks. `@example` tags still work, but we may remove them in the future. +- **Supports the `@throws` JSDoc tag** – Properly documents possible errors. +- **Basic support for the `@see` JSDoc tag** – Displays only the API name and description. +- **Adds GitHub source links** – Provides direct access to the corresponding source code. +- **Repositions signatures** – Now moved further down, just before the source link and `@since` tag, for better readability. From 28b1f9143909dfb10cedb04304b302154e6ce864 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 9 Mar 2025 09:05:16 +0100 Subject: [PATCH 45/56] Refactor test source file generation to use consistent filename - Add `makeSourcefile` utility function to handle source file creation and reuse - Update `makeSource` to use new utility function for consistent file naming - Modify test cases to use `test.ts` as the base filename - Simplify source file management in test parser --- test/Parser.test.ts | 113 ++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 301d42b..ce6fcca 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -32,13 +32,24 @@ const defaultConfig: Configuration.ConfigurationShape = { examplesCompilerOptions: {} } +const makeSourcefile = (source: string | ast.SourceFile) => { + if (Predicate.isString(source)) { + const filename = `test.ts` + const existing = project.getSourceFile(filename) + if (existing) { + project.removeSourceFile(existing) + } + return project.createSourceFile(filename, source) + } + return source +} + const makeSource = (source: string | ast.SourceFile) => { - const filename = `test-${testCounter++}` + const sourceFile = makeSourcefile(source) + const filename = sourceFile.getBaseName() return Parser.Source.of({ path: [filename], - sourceFile: Predicate.isString(source) - ? project.createSourceFile(`${filename}.ts`, source) - : source + sourceFile }) } @@ -106,7 +117,7 @@ import * as assert from 'assert' * @since 1.0.0 */ export const foo = 'foo'`, - `## test-0.ts overview + `## test.ts overview This is the assert module. @@ -134,7 +145,7 @@ console.log(foo) declare const foo: "foo" \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-0.ts#L19) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L19) Since v1.0.0` ) @@ -161,7 +172,7 @@ This is a description containing two links to \`foo\` and \`bar\`. declare const myfunc: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-1.ts#L6) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) Since v1.2.0` ) @@ -186,7 +197,7 @@ This is a description containing two links to \`foo\` and \`bar\`. declare const myfunc: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-2.ts#L6) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) Since v1.2.0` ) @@ -217,7 +228,7 @@ description... declare const myfunc: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-3.ts#L7) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L7) Since v1.2.0` ) @@ -250,7 +261,7 @@ description... declare const myfunc: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-4.ts#L8) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L8) Since v1.2.0` ) @@ -282,7 +293,7 @@ const x = 1 declare const myfunc: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-5.ts#L7) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L7) Since v1.0.0` ) @@ -316,7 +327,7 @@ const x = 1 declare const myfunc: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-6.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) Since v1.0.0` ) @@ -360,7 +371,7 @@ const x = 2 declare const myfunc: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-7.ts#L13) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L13) Since v1.0.0` ) @@ -394,7 +405,7 @@ const x = 1 declare const myfunc: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-8.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) Since v1.0.0` ) @@ -428,7 +439,7 @@ const x = 1 declare const myfunc: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-9.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) Since v1.0.0` ) @@ -525,7 +536,7 @@ Since v1.0.0` declare const toNullable: (ma: A | null) => A | null \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-17.ts#L4) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L4) Since v1.0.0` ) @@ -566,7 +577,7 @@ assert.deepStrictEqual(f(3, 4), { a: 3, b: 4 }) declare const f: (a: number, b: number) => { [key: string]: number; } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-18.ts#L10) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L10) Since v1.0.0` ) @@ -587,7 +598,7 @@ Since v1.0.0` declare const f: (a: number, b: number) => { [key: string]: number; } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-19.ts#L4) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L4) Since v1.0.0` ) @@ -614,7 +625,7 @@ a description... declare const f: { (a: Int, b: Int): { [key: string]: number; }; (a: number, b: number): { [key: string]: number; }; } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-20.ts#L8) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L8) Since v1.0.0` ) @@ -641,7 +652,7 @@ a description... declare const s: string \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-21.ts#L6) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) Since v1.0.0` ) @@ -662,7 +673,7 @@ Since v1.0.0` declare const left: (l: E) => string \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-22.ts#L4) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L4) Since v1.0.0` ) @@ -685,7 +696,7 @@ Since v1.0.0` declare const empty: A \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-23.ts#L6) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) Since v1.0.0` ) @@ -712,7 +723,7 @@ Since v1.0.0` declare const taskSeq: { a: number; } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-24.ts#L7) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L7) Since v1.0.0` ) @@ -754,7 +765,7 @@ a description... type Option = None | Some \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-26.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) Since v1.0.0` ) @@ -788,7 +799,7 @@ Since v1.0.0` declare const b: 1 \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-28.ts#L6) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) Since v1.0.0` ) @@ -822,7 +833,7 @@ description_of_a declare const a: 1 \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-29.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) Since v1.0.0 ## b @@ -835,7 +846,7 @@ description_of_b declare const b: 2 \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-29.ts#L14) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L14) Since v2.0.0` ) @@ -1018,7 +1029,7 @@ a description... export interface A {} \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-35.ts#L6) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) Since v1.0.0` ) @@ -1053,7 +1064,7 @@ Since v1.0.0` `, `## A (namespace) -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-38.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0` ) @@ -1073,7 +1084,7 @@ Since v1.0.0` `, `## A (namespace) -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-39.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0` ) @@ -1097,7 +1108,7 @@ export namespace A { `, `## A (namespace) -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-40.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0 @@ -1111,7 +1122,7 @@ export interface B { } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-40.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) Since v1.0.1` ) @@ -1132,7 +1143,7 @@ Since v1.0.1` `, `## A (namespace) -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-41.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0` ) @@ -1154,7 +1165,7 @@ Since v1.0.0` `, `## A (namespace) -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-42.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0 @@ -1166,7 +1177,7 @@ Since v1.0.0 type B = string \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-42.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) Since v1.0.1` ) @@ -1187,7 +1198,7 @@ Since v1.0.1` `, `## A (namespace) -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-43.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0` ) @@ -1214,13 +1225,13 @@ Since v1.0.0` `, `## A (namespace) -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-44.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0 ### B (namespace) -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-44.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) Since v1.0.1 @@ -1232,7 +1243,7 @@ Since v1.0.1 type C = string \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-44.ts#L13) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L13) Since v1.0.2` ) @@ -1280,7 +1291,7 @@ Since v1.0.2` declare class MyClass \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-47.ts#L4) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L4) Since v1.0.0` ) @@ -1304,7 +1315,7 @@ description declare class C { constructor() } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-48.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0` ) @@ -1356,7 +1367,7 @@ description declare class C \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-50.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0 @@ -1368,7 +1379,7 @@ Since v1.0.0 a: string \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-50.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) Since v1.0.0` ) @@ -1416,7 +1427,7 @@ a class description... declare class Test { constructor(readonly value: string) } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-51.ts#L6) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) Since v1.0.0 @@ -1430,7 +1441,7 @@ a static method description... declare const f: () => void \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-51.ts#L19) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L19) Since v1.1.0 @@ -1444,7 +1455,7 @@ a method description... declare const g: (a: number, b: number) => { [key: string]: number; } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-51.ts#L26) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L26) Since v1.1.0 @@ -1458,7 +1469,7 @@ a property... readonly a: string \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-51.ts#L12) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L12) Since v1.1.0` ) @@ -1503,7 +1514,7 @@ a class description... declare class Test { constructor(readonly value: A) } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-52.ts#L6) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) Since v1.0.0 @@ -1517,7 +1528,7 @@ a static method description... declare const f: { (x: number): number; (x: string): string; } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-52.ts#L14) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L14) Since v1.1.0 @@ -1531,7 +1542,7 @@ a method description... declare const map: { (f: (a: number) => number): Test; (f: (a: string) => string): Test; } \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-52.ts#L23) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L23) Since v1.1.0` ) @@ -1566,7 +1577,7 @@ a class description... declare class Test \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test-53.ts#L5) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L5) Since v1.0.0` ) From 1fa54d5166f227c072dbcda8a9a55286d18f91d7 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 9 Mar 2025 09:40:23 +0100 Subject: [PATCH 46/56] Implement comprehensive module checking with configurable validation rules - Add detailed module checking functionality in Checker module - Implement validation for functions, classes, constants, interfaces, type aliases, namespaces, and exports - Introduce configurable checks for descriptions, examples, and @since tags - Update Core module to run module checks before documentation generation - Modify Domain module to remove redundant @since tag annotations - Enhance error reporting with precise source location information --- docs/modules/Checker.ts.md | 61 +++++++++---- docs/modules/Domain.ts.md | 54 ++++------- docs/modules/Parser.ts.md | 4 +- src/Checker.ts | 182 ++++++++++++++++++++++++++++++++----- src/Core.ts | 11 ++- src/Domain.ts | 24 +---- src/Parser.ts | 5 +- test/Parser.test.ts | 14 ++- 8 files changed, 245 insertions(+), 110 deletions(-) diff --git a/docs/modules/Checker.ts.md b/docs/modules/Checker.ts.md index d0432eb..051a0e0 100644 --- a/docs/modules/Checker.ts.md +++ b/docs/modules/Checker.ts.md @@ -19,6 +19,7 @@ Since v0.6.0 - [checkFunctions](#checkfunctions) - [checkInterfaces](#checkinterfaces) - [checkModule](#checkmodule) + - [checkModules](#checkmodules) - [checkNamespaces](#checknamespaces) - [checkTypeAliases](#checktypealiases) @@ -31,10 +32,12 @@ Since v0.6.0 **Signature** ```ts -declare const checkClasses: (_classes: ReadonlyArray) => Effect.Effect, never, never> +declare const checkClasses: ( + models: ReadonlyArray +) => Effect.Effect, never, Configuration.Configuration | Parser.Source> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L32) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L112) Since v0.6.0 @@ -43,10 +46,12 @@ Since v0.6.0 **Signature** ```ts -declare const checkConstants: (_constants: ReadonlyArray) => Effect.Effect, never, never> +declare const checkConstants: ( + models: ReadonlyArray +) => Effect.Effect, never, Configuration.Configuration | Parser.Source> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L39) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L125) Since v0.6.0 @@ -55,10 +60,12 @@ Since v0.6.0 **Signature** ```ts -declare const checkExports: (_exports: ReadonlyArray) => Effect.Effect, never, never> +declare const checkExports: ( + models: ReadonlyArray +) => Effect.Effect, never, Configuration.Configuration | Parser.Source> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L67) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L177) Since v0.6.0 @@ -68,11 +75,11 @@ Since v0.6.0 ```ts declare const checkFunctions: ( - functions: ReadonlyArray -) => Effect.Effect, never, Parser.Source> + models: ReadonlyArray +) => Effect.Effect, never, Configuration.Configuration | Parser.Source> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L25) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L87) Since v0.6.0 @@ -82,11 +89,11 @@ Since v0.6.0 ```ts declare const checkInterfaces: ( - _interfaces: ReadonlyArray -) => Effect.Effect, never, never> + models: ReadonlyArray +) => Effect.Effect, never, Configuration.Configuration | Parser.Source> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L46) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L138) Since v0.6.0 @@ -95,10 +102,24 @@ Since v0.6.0 **Signature** ```ts -declare const checkModule: (_module: Domain.Module) => Effect.Effect, never, never> +declare const checkModule: (module: Domain.Module) => Effect.Effect, never, Configuration.Configuration> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L74) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L184) + +Since v0.6.0 + +## checkModules + +**Signature** + +```ts +declare const checkModules: ( + modules: ReadonlyArray +) => Effect.Effect, never, Configuration.Configuration> +``` + +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L208) Since v0.6.0 @@ -108,11 +129,11 @@ Since v0.6.0 ```ts declare const checkNamespaces: ( - _namespaces: ReadonlyArray -) => Effect.Effect, never, never> + models: ReadonlyArray +) => Effect.Effect, never, Configuration.Configuration | Parser.Source> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L60) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L164) Since v0.6.0 @@ -122,10 +143,10 @@ Since v0.6.0 ```ts declare const checkTypeAliases: ( - _typeAliases: ReadonlyArray -) => Effect.Effect, never, never> + models: ReadonlyArray +) => Effect.Effect, never, Configuration.Configuration | Parser.Source> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L53) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L151) Since v0.6.0 diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index cc65bf9..6b8f04d 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -74,9 +74,7 @@ Since v0.6.0 readonly _tag: "Class" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L83) - -Since v0.6.0 +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L80) ## Constant (class) @@ -88,7 +86,7 @@ declare class Constant { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L167) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L155) Since v0.6.0 @@ -100,9 +98,7 @@ Since v0.6.0 readonly _tag: "Constant" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L171) - -Since v0.6.0 +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L156) ## Doc (class) @@ -160,7 +156,7 @@ Since v0.6.0 declare class DocgenError ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L273) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L252) Since v0.6.0 @@ -188,7 +184,7 @@ declare class Export { constructor( ) } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L196) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L181) Since v0.6.0 @@ -200,9 +196,7 @@ Since v0.6.0 readonly _tag: "Export" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L200) - -Since v0.6.0 +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L182) ## File (class) @@ -218,7 +212,7 @@ declare class File { constructor( ) } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L249) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L228) Since v0.6.0 @@ -232,7 +226,7 @@ declare class Function { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L129) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L123) Since v0.6.0 @@ -244,9 +238,7 @@ Since v0.6.0 readonly _tag: "Function" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L133) - -Since v0.6.0 +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L124) ## Interface (class) @@ -258,7 +250,7 @@ declare class Interface { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L101) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L98) Since v0.6.0 @@ -270,9 +262,7 @@ Since v0.6.0 readonly _tag: "Interface" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L105) - -Since v0.6.0 +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L99) ## Module (class) @@ -313,7 +303,7 @@ declare class Namespace { constructor( ) } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L216) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L198) Since v0.6.0 @@ -325,9 +315,7 @@ Since v0.6.0 readonly _tag: "Namespace" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L220) - -Since v0.6.0 +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L199) ## Position (interface) @@ -340,7 +328,7 @@ export interface Position { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L120) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L114) Since v0.6.0 @@ -354,7 +342,7 @@ declare class TypeAlias { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L148) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L139) Since v0.6.0 @@ -366,9 +354,7 @@ Since v0.6.0 readonly _tag: "TypeAlias" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L152) - -Since v0.6.0 +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L140) # service @@ -382,7 +368,7 @@ Represents a handle to the currently executing process. declare class Process ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L284) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L262) Since v0.6.0 @@ -399,7 +385,7 @@ The file path is converted to lowercase before comparison. declare const ByPath: Order.Order ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L238) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L217) Since v0.6.0 @@ -413,7 +399,7 @@ Since v0.6.0 declare const DocgenErrorTypeId: unique symbol ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L261) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L240) Since v0.6.0 @@ -425,6 +411,6 @@ Since v0.6.0 type DocgenErrorTypeId = typeof DocgenErrorTypeId ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L267) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L246) Since v0.6.0 diff --git a/docs/modules/Parser.ts.md b/docs/modules/Parser.ts.md index 2d668b9..4c41e64 100644 --- a/docs/modules/Parser.ts.md +++ b/docs/modules/Parser.ts.md @@ -77,7 +77,7 @@ declare const parseFiles: ( > ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L691) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L688) Since v0.6.0 @@ -113,7 +113,7 @@ Since v0.6.0 declare const parseModule: Effect.Effect ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L616) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Parser.ts#L613) Since v0.6.0 diff --git a/src/Checker.ts b/src/Checker.ts index 7772cae..c574098 100644 --- a/src/Checker.ts +++ b/src/Checker.ts @@ -3,74 +3,208 @@ */ import { codeFrameColumns } from "@babel/code-frame" import { Array, Effect } from "effect" +import * as Configuration from "./Configuration.js" import type * as Domain from "./Domain.js" import * as Parser from "./Parser.js" -function checkFunction(model: Domain.Function) { +const makeError = ( + source: Parser.SourceShape, + position: Domain.Position, + message: (filePath: string, frame: string) => string +) => { + const location = { start: position } + const frame = codeFrameColumns(source.sourceFile.getFullText(), location) + return [message(source.sourceFile.getFilePath(), frame)] +} + +type Entry = { + readonly doc: Domain.Doc + readonly position: Domain.Position +} + +function checkEntry(model: Entry, options: { + readonly enforceVersion: boolean +}) { return Effect.gen(function*() { - const since = model.doc.since - if (since.length === 0) { - const source = yield* Parser.Source - const location = { start: model.position } - const result = codeFrameColumns(source.sourceFile.getFullText(), location) - return [`Missing \`@since\` tag in file ${source.sourceFile.getFilePath()}:\n\n${result}`] + const source = yield* Parser.Source + const config = yield* Configuration.Configuration + + let errors: Array = [] + + // description + if (config.enforceDescriptions) { + if (model.doc.description === undefined) { + errors = errors.concat(makeError( + source, + model.position, + (filePath, frame) => `Missing description in file ${filePath}:\n\n${frame}` + )) + } + } + + // @example tags + if (config.enforceExamples) { + if (model.doc.examples.length === 0) { + errors = errors.concat(makeError( + source, + model.position, + (filePath, frame) => `Missing examples in file ${filePath}:\n\n${frame}` + )) + } + } + + // @since tags + if (config.enforceVersion && options.enforceVersion !== false) { + const since = model.doc.since + if (since.length === 0) { + errors = errors.concat(makeError( + source, + model.position, + (filePath, frame) => `Missing \`@since\` tag in file ${filePath}:\n\n${frame}` + )) + } } - return [] + + return errors + }) +} + +function checkEntries(models: ReadonlyArray, options: { + readonly enforceVersion: boolean +}) { + return Effect.forEach(models, (model) => checkEntry(model, options)).pipe(Effect.map(Array.flatten)) +} + +function checkFunction(model: Domain.Function) { + return checkEntry(model, { + enforceVersion: true }) } /** * @since 0.6.0 */ -export function checkFunctions(functions: ReadonlyArray) { - return Effect.forEach(functions, checkFunction).pipe(Effect.map(Array.flatten)) +export function checkFunctions(models: ReadonlyArray) { + return Effect.forEach(models, checkFunction).pipe(Effect.map(Array.flatten)) +} + +function checkClass(model: Domain.Class) { + return Effect.gen(function*() { + const docErrors = yield* checkEntry(model, { + enforceVersion: true + }) + const staticMethodsErrors = yield* checkEntries(model.staticMethods, { + enforceVersion: false + }) + const methodsErrors = yield* checkEntries(model.methods, { + enforceVersion: false + }) + const propertiesErrors = yield* checkEntries(model.properties, { + enforceVersion: false + }) + return Array.flatten([docErrors, staticMethodsErrors, methodsErrors, propertiesErrors]) + }) } /** * @since 0.6.0 */ -export function checkClasses(_classes: ReadonlyArray) { - return Effect.succeed([]) +export function checkClasses(models: ReadonlyArray) { + return Effect.forEach(models, checkClass).pipe(Effect.map(Array.flatten)) +} + +function checkConstant(model: Domain.Constant) { + return checkEntry(model, { + enforceVersion: true + }) } /** * @since 0.6.0 */ -export function checkConstants(_constants: ReadonlyArray) { - return Effect.succeed([]) +export function checkConstants(models: ReadonlyArray) { + return Effect.forEach(models, checkConstant).pipe(Effect.map(Array.flatten)) +} + +function checkInterface(model: Domain.Interface) { + return checkEntry(model, { + enforceVersion: true + }) } /** * @since 0.6.0 */ -export function checkInterfaces(_interfaces: ReadonlyArray) { - return Effect.succeed([]) +export function checkInterfaces(models: ReadonlyArray) { + return Effect.forEach(models, checkInterface).pipe(Effect.map(Array.flatten)) +} + +function checkTypeAlias(model: Domain.TypeAlias) { + return checkEntry(model, { + enforceVersion: true + }) } /** * @since 0.6.0 */ -export function checkTypeAliases(_typeAliases: ReadonlyArray) { - return Effect.succeed([]) +export function checkTypeAliases(models: ReadonlyArray) { + return Effect.forEach(models, checkTypeAlias).pipe(Effect.map(Array.flatten)) +} + +function checkNamespace(model: Domain.Namespace) { + return checkEntry(model, { + enforceVersion: true + }) +} + +/** + * @since 0.6.0 + */ +export function checkNamespaces(models: ReadonlyArray) { + return Effect.forEach(models, checkNamespace).pipe(Effect.map(Array.flatten)) +} + +function checkExport(model: Domain.Export) { + return checkEntry(model, { + enforceVersion: true + }) } /** * @since 0.6.0 */ -export function checkNamespaces(_namespaces: ReadonlyArray) { - return Effect.succeed([]) +export function checkExports(models: ReadonlyArray) { + return Effect.forEach(models, checkExport).pipe(Effect.map(Array.flatten)) } /** * @since 0.6.0 */ -export function checkExports(_exports: ReadonlyArray) { - return Effect.succeed([]) +export function checkModule(module: Domain.Module) { + return Effect.gen(function*() { + const functionsErrors = yield* checkFunctions(module.functions) + const classesErrors = yield* checkClasses(module.classes) + const constantsErrors = yield* checkConstants(module.constants) + const interfacesErrors = yield* checkInterfaces(module.interfaces) + const typeAliasesErrors = yield* checkTypeAliases(module.typeAliases) + const namespacesErrors = yield* checkNamespaces(module.namespaces) + const exportsErrors = yield* checkExports(module.exports) + return Array.flatten([ + functionsErrors, + classesErrors, + constantsErrors, + interfacesErrors, + typeAliasesErrors, + namespacesErrors, + exportsErrors + ]) + }).pipe(Effect.provideService(Parser.Source, module.source)) } /** * @since 0.6.0 */ -export function checkModule(_module: Domain.Module) { - return Effect.succeed([]) +export function checkModules(modules: ReadonlyArray) { + return Effect.forEach(modules, checkModule).pipe(Effect.map(Array.flatten)) } diff --git a/src/Core.ts b/src/Core.ts index 08792af..695c29e 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -15,11 +15,11 @@ import * as Effect from "effect/Effect" import * as Stream from "effect/Stream" import * as String from "effect/String" import * as Glob from "glob" +import * as Checker from "./Checker.js" import * as Configuration from "./Configuration.js" import * as Domain from "./Domain.js" import * as Parser from "./Parser.js" import * as Printer from "./Printer.js" - /** * Find all files matching the specified `glob` pattern, optionally excluding * files matching the provided `exclude` patterns. @@ -561,6 +561,15 @@ export const program = Effect.gen(function*() { const sourceFiles = yield* readSourceFiles yield* Effect.logInfo("Parsing modules...") const modules = yield* parseModules(sourceFiles) + yield* Effect.logInfo("Checking modules...") + const errors = yield* Checker.checkModules(modules) + if (errors.length > 0) { + yield* Effect.fail( + new Domain.DocgenError({ + message: `The following errors occurred while checking the modules:\n\n${errors.join("\n\n")}` + }) + ) + } yield* typeCheckAndRunExamples(modules) yield* Effect.logInfo("Creating markdown files...") const outputFiles = yield* getMarkdown(modules) diff --git a/src/Domain.ts b/src/Domain.ts index 140f602..a4d3ad2 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -77,9 +77,6 @@ export class Module { * @since 0.6.0 */ export class Class extends DocEntry { - /** - * @since 0.6.0 - */ readonly _tag = "Class" constructor( name: string, @@ -99,9 +96,6 @@ export class Class extends DocEntry { * @since 0.6.0 */ export class Interface extends DocEntry { - /** - * @since 0.6.0 - */ readonly _tag = "Interface" constructor( name: string, @@ -127,9 +121,6 @@ export interface Position { * @since 0.6.0 */ export class Function extends DocEntry { - /** - * @since 0.6.0 - */ readonly _tag = "Function" constructor( name: string, @@ -146,9 +137,6 @@ export class Function extends DocEntry { * @since 0.6.0 */ export class TypeAlias extends DocEntry { - /** - * @since 0.6.0 - */ readonly _tag = "TypeAlias" constructor( name: string, @@ -165,9 +153,6 @@ export class TypeAlias extends DocEntry { * @since 0.6.0 */ export class Constant extends DocEntry { - /** - * @since 0.6.0 - */ readonly _tag = "Constant" constructor( name: string, @@ -194,9 +179,6 @@ export class Constant extends DocEntry { * @since 0.6.0 */ export class Export extends DocEntry { - /** - * @since 0.6.0 - */ readonly _tag = "Export" constructor( name: string, @@ -214,9 +196,6 @@ export class Export extends DocEntry { * @since 0.6.0 */ export class Namespace { - /** - * @since 0.6.0 - */ readonly _tag = "Namespace" constructor( readonly name: string, @@ -272,8 +251,7 @@ export type DocgenErrorTypeId = typeof DocgenErrorTypeId */ export class DocgenError extends Data.TaggedError("DocgenError")<{ readonly message: string -}> { -} +}> {} /** * Represents a handle to the currently executing process. diff --git a/src/Parser.ts b/src/Parser.ts index 02d7373..c3ab930 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -583,10 +583,7 @@ const parseClass = (c: ast.ClassDeclaration) => */ export const parseClasses = Effect.gen(function*() { const source = yield* Source - const exportedClasses = Array.filter( - source.sourceFile.getClasses(), - (cd) => cd.isExported() - ) + const exportedClasses = source.sourceFile.getClasses().filter((cd) => cd.isExported()) return yield* Effect.forEach(exportedClasses, parseClass).pipe(Effect.map(Array.flatten)) }) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index ce6fcca..013ebc7 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -1252,7 +1252,7 @@ Since v1.0.2` }) describe("parseClasses", () => { - it("should ignore internal classes", async () => { + it("should ignore `@internal` classes", async () => { await expectMarkdown( Parser.parseClasses, `/** @internal */export class MyClass {}`, @@ -1260,7 +1260,7 @@ Since v1.0.2` ) }) - it("should ignore `@ignore`d classes", async () => { + it("should ignore `@ignore` classes", async () => { await expectMarkdown( Parser.parseClasses, ` @@ -1271,6 +1271,16 @@ Since v1.0.2` ) }) + it("should ignore not exported classes", async () => { + await expectMarkdown( + Parser.parseClasses, + ` + class MyClass {} + `, + "" + ) + }) + it("should skip ignored properties", async () => { await expectMarkdown( Parser.parseClasses, From bdf507c7027e25ac6e6a69b1220e3a418e088885 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 9 Mar 2025 09:43:41 +0100 Subject: [PATCH 47/56] fix tests --- test/Checker.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Checker.test.ts b/test/Checker.test.ts index fd33596..8dd5023 100644 --- a/test/Checker.test.ts +++ b/test/Checker.test.ts @@ -46,7 +46,7 @@ const expectFailure = ( config: Partial, sourceText: string, parser: Effect.Effect, - checker: (a: A) => Effect.Effect, never, Parser.Source>, + checker: (a: A) => Effect.Effect, never, Configuration.Configuration | Parser.Source>, failure: ReadonlyArray ) => { const actual = parser.pipe( From ecfa840f67edf4d40cfa668f8de1e2f01f580d15 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Sun, 9 Mar 2025 19:22:00 +0100 Subject: [PATCH 48/56] Add theme-specific code block metadata handling - Introduce `DEFAULT_THEME` constant in Configuration module - Create `removeFenceMetadata` function to strip code block metadata for default theme - Update `printOptionalDescription` to conditionally remove code block metadata - Modify CLI and Configuration to use `DEFAULT_THEME` - Add test case for code block metadata removal - Update documentation generation to handle theme-specific code block rendering --- docs/modules/Configuration.ts.md | 22 +++++++++-- docs/modules/Core.ts.md | 19 +++++++++ docs/modules/Domain.ts.md | 2 +- docs/modules/Printer.ts.md | 40 ++----------------- src/CLI.ts | 2 +- src/Configuration.ts | 7 +++- src/Core.ts | 9 ++++- src/Printer.ts | 68 +++++++++++++++----------------- test/Checker.test.ts | 2 +- test/Parser.test.ts | 30 +++++++++++++- 10 files changed, 119 insertions(+), 82 deletions(-) diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index 6b6e693..668917b 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -16,6 +16,8 @@ Since v0.6.0 - [Configuration (class)](#configuration-class) - [ConfigurationSchema](#configurationschema) - [ConfigurationShape (interface)](#configurationshape-interface) +- [utils](#utils) + - [DEFAULT_THEME](#default_theme) --- @@ -29,7 +31,7 @@ Since v0.6.0 declare class Configuration ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L109) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L114) Since v0.6.0 @@ -59,7 +61,7 @@ declare const ConfigurationSchema: Schema.Struct<{ }> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L33) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L38) Since v0.6.0 @@ -86,6 +88,20 @@ export interface ConfigurationShape { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L88) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L93) + +Since v0.6.0 + +# utils + +## DEFAULT_THEME + +**Signature** + +```ts +declare const DEFAULT_THEME: "mikearnaldi/just-the-docs" +``` + +[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L24) Since v0.6.0 diff --git a/docs/modules/Core.ts.md b/docs/modules/Core.ts.md index 129da80..29b3044 100644 --- a/docs/modules/Core.ts.md +++ b/docs/modules/Core.ts.md @@ -12,4 +12,23 @@ Since v0.6.0 ## Exports Grouped by Category +- [utils](#utils) + - [SKIP_TYPE_CHECKING_FENCE_METADATA](#skip_type_checking_fence_metadata) + --- + +# utils + +## SKIP_TYPE_CHECKING_FENCE_METADATA + +The metadata key for skipping type-checking. + +**Signature** + +```ts +declare const SKIP_TYPE_CHECKING_FENCE_METADATA: "skip-type-checking" +``` + +[Source](https://github.com/effect-ts/docgen/blob/main/src/Core.ts#L162) + +Since v0.6.0 diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 6b8f04d..7972045 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -164,7 +164,7 @@ Since v0.6.0 These are manual exports, like: -```ts skip-type-checking +```ts const _null = ... export { diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index 9d32d6b..ee89ff2 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -24,47 +24,13 @@ Since v0.6.0 ## printModule -Description... - -```ts -export const a: string = "a" -``` - -```text -┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌────────┐ -│ input │───►│ func1 │───►│ func2 │───►│ ... │───►│ funcN │───►│ result │ -└───────┘ └───────┘ └───────┘ └───────┘ └───────┘ └────────┘ -``` - -**Example** (Title 1) - -```ts twoslash title="Title 1" -export const b: string = "b" -``` - -**Example** (Title 2) - -```js twoslash title="Title 2" -export const c: string = "c" -``` - -**Throws** - -`Error1` - Description 1 -`Error2` - Description 2 - -**See** - -- `foo` description1 -- `printFunction` description2 - **Signature** ```ts declare const printModule: (module: Domain.Module) => Effect.Effect ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L324) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L320) Since v0.6.0 @@ -78,7 +44,7 @@ Since v0.6.0 declare const prettify: (s: string) => Effect.Effect ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L376) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L372) Since v0.6.0 @@ -90,6 +56,6 @@ Since v0.6.0 declare const printFrontMatter: (module: Domain.Module, nav_order: number) => string ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L365) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L361) Since v0.6.0 diff --git a/src/CLI.ts b/src/CLI.ts index 9df6a1d..8153ba0 100644 --- a/src/CLI.ts +++ b/src/CLI.ts @@ -52,7 +52,7 @@ const outDir = Options.directory("out").pipe( const theme = Options.directory("theme").pipe( Options.withFallbackConfig( Config.string("theme").pipe( - Config.withDefault("mikearnaldi/just-the-docs") + Config.withDefault(Configuration.DEFAULT_THEME) ) ), Options.withDescription( diff --git a/src/Configuration.ts b/src/Configuration.ts index 247e707..4427e67 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -18,6 +18,11 @@ import * as tsconfck from "tsconfck" import * as Domain from "./Domain.js" import { DocgenError } from "./Domain.js" +/** + * @since 0.6.0 + */ +export const DEFAULT_THEME = "mikearnaldi/just-the-docs" + const PACKAGE_JSON_FILE_NAME = "package.json" const CONFIG_FILE_NAME = "docgen.json" @@ -48,7 +53,7 @@ export const ConfigurationSchema = Schema.Struct({ }), theme: Schema.optional(Schema.String).annotations({ description: "The theme that docgen will specify should be used for GitHub Docs in the generated _config.yml file.", - default: "mikearnaldi/just-the-docs" + default: DEFAULT_THEME }), enableSearch: Schema.optional(Schema.Boolean).annotations({ description: "Whether or not search should be enabled for GitHub Docs in the generated _config.yml file.", diff --git a/src/Core.ts b/src/Core.ts index 695c29e..c39b0b2 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -154,6 +154,13 @@ const extractPrefixedNestedNamespaces = ( return Array.prepend(namespaces, [prefix, doc]) } +/** + * The metadata key for skipping type-checking. + * + * @since 0.6.0 + */ +export const SKIP_TYPE_CHECKING_FENCE_METADATA = "skip-type-checking" + /** * Extracts all fenced code blocks from markdown content. * Handles both ``` and ~~~ fences, including any metadata like language, title, and other attributes. @@ -166,7 +173,7 @@ const extractFencedCode = (content: string): Array => { .filter((match) => { const meta = match[1].toLocaleLowerCase() const isTypeScript = meta.startsWith("ts") || meta.startsWith("typescript") - const isSkipTypeChecking = meta.includes("skip-type-checking") + const isSkipTypeChecking = meta.includes(SKIP_TYPE_CHECKING_FENCE_METADATA) return isTypeScript && !isSkipTypeChecking }) .map((match) => match[2].trim()) diff --git a/src/Printer.ts b/src/Printer.ts index 1b5612e..258e90c 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -41,11 +41,36 @@ function replaceJSDocLinks(text: string): string { }) } -const printOptionalDescription = (description: string | undefined): string => { - if (description === undefined) { - return "" - } - return `\n\n${replaceJSDocLinks(description)}` +/** + * Removes all extra metadata from fenced code blocks in a Markdown string. + * For each code fence, only the first token (the language identifier) is preserved. + * + * Examples: + * Input: "```ts skip-type-checking a=1\nexport const a: string = 1\n```" + * Output: "```ts\nexport const a: string = 1\n```" + */ +function removeFenceMetadata(markdown: string): string { + return markdown.replace(/^(`{3,})([^\n]*)/gm, (_match, fence, info) => { + // Trim the info string and split by whitespace into tokens. + // The first token (if present) is typically the language identifier. + const tokens = info.trim().split(/\s+/) + // Rebuild the fence line with just the language (if it exists) + return fence + (tokens[0] || "") + }) +} + +const printOptionalDescription = (description: string | undefined) => { + return Effect.gen(function*() { + if (description === undefined) { + return "" + } + const config = yield* Configuration.Configuration + const descriptionWithoutLinks = replaceJSDocLinks(description) + const out = config.theme === Configuration.DEFAULT_THEME + ? removeFenceMetadata(descriptionWithoutLinks) + : descriptionWithoutLinks + return `\n\n${out}` + }) } const printArray = (title: string, ss?: ReadonlyArray): string => { @@ -129,8 +154,9 @@ const printModel = (name: string, doc: Domain.Doc, options: { }) => { return Effect.gen(function*() { const sourceLink = yield* printOptionalSourceLink(options.position) + const description = yield* printOptionalDescription(doc.description) return printHeaderByIndentation(options.indentation ?? 0) + printTitle(name, doc.deprecated, options.postfix) + - printOptionalDescription(doc.description) + + description + printThrowsArray(doc.throws) + printExamplesArray(doc.examples) + printSeesArray(doc.sees) + @@ -288,36 +314,6 @@ const sortByName: (self: Iterable) => Array = ) /** - * Description... - * - * ```ts - * export const a: string = "a" - * ``` - * - * ```text - * ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ ┌────────┐ - * │ input │───►│ func1 │───►│ func2 │───►│ ... │───►│ funcN │───►│ result │ - * └───────┘ └───────┘ └───────┘ └───────┘ └───────┘ └────────┘ - * ``` - * - * **Example** (Title 1) - * - * ```ts twoslash title="Title 1" - * export const b: string = "b" - * ``` - * - * **Example** (Title 2) - * - * ~~~js twoslash title="Title 2" - * export const c: string = "c" - * ~~~ - * - * @throws `Error1` - Description 1 - * @throws `Error2` - Description 2 - * - * @see `foo` description1 - * @see {@link printFunction} description2 - * * @category printers * @since 0.6.0 */ diff --git a/test/Checker.test.ts b/test/Checker.test.ts index 8dd5023..c7ff7ab 100644 --- a/test/Checker.test.ts +++ b/test/Checker.test.ts @@ -21,7 +21,7 @@ const defaultConfig: Configuration.ConfigurationShape = { srcLink: "https://github.com/effect-ts/docgen/blob/main/src/", srcDir: "src", outDir: "docs", - theme: "pmarsceill/just-the-docs", + theme: "mikearnaldi/just-the-docs", enableSearch: true, enforceDescriptions: false, enforceExamples: false, diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 013ebc7..c6687f5 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -21,7 +21,7 @@ const defaultConfig: Configuration.ConfigurationShape = { srcLink: "https://github.com/effect-ts/docgen/blob/main/src/", srcDir: "src", outDir: "docs", - theme: "pmarsceill/just-the-docs", + theme: "mikearnaldi/just-the-docs", enableSearch: true, enforceDescriptions: false, enforceExamples: false, @@ -153,6 +153,34 @@ Since v1.0.0` }) describe("parseFunctions", () => { + it(`should remove all metadata from typedcript code blocks when the theme is ${Configuration.DEFAULT_THEME}`, async () => { + await expectMarkdown( + Parser.parseFunctions, + `/** + * \`\`\`ts skip-type-checking a=1 showLineNumbers=true + * const a: string = 1 + * \`\`\` + * + * @since 1.0.0 + */ + export function myfunc() {}`, + `## myfunc + +\`\`\`ts +const a: string = 1 +\`\`\` + +**Signature** + +\`\`\`ts +declare const myfunc: () => void +\`\`\` + +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L8) + +Since v1.0.0` + ) + }) it("generics", async () => { await expectMarkdown( Parser.parseFunctions, From 1e3501b8686c451d058a9bbafcbda433ba27fbf5 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 10 Mar 2025 10:35:38 +0100 Subject: [PATCH 49/56] Enhance error handling in CLI with domain-specific DocgenError - Update CLI to catch and transform DocgenError with project-specific context - Modify error handling to include project name in error message - Import Domain module to use DocgenError type - Refactor error propagation in docgen command handler --- docs/modules/CLI.ts.md | 6 +++--- src/CLI.ts | 13 ++++++++++++- src/bin.ts | 3 +-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index 804288b..0643e61 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -28,11 +28,11 @@ declare const cli: ( args: ReadonlyArray ) => Effect.Effect< void, - ValidationError.ValidationError | DocgenError | PlatformError, - Process | CommandExecutor | CliApp.Environment + ValidationError.ValidationError | Domain.DocgenError | PlatformError, + Domain.Process | CommandExecutor | CliApp.Environment > ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/CLI.ts#L189) +[Source](https://github.com/effect-ts/docgen/blob/main/src/CLI.ts#L190) Since v0.6.0 diff --git a/src/CLI.ts b/src/CLI.ts index 8153ba0..f0b908e 100644 --- a/src/CLI.ts +++ b/src/CLI.ts @@ -16,6 +16,7 @@ import * as ParseResult from "effect/ParseResult" import * as Schema from "effect/Schema" import * as Configuration from "./Configuration.js" import * as Core from "./Core.js" +import * as Domain from "./Domain.js" import * as InternalVersion from "./internal/version.js" const projectHomepage = Options.text("homepage").pipe( @@ -187,7 +188,17 @@ export const docgenCommand = Command.make("docgen", options) * @since 0.6.0 */ export const cli = docgenCommand.pipe( - Command.withHandler(() => Effect.scoped(Core.program)), + Command.withHandler(() => + Effect.scoped(Core.program).pipe(Effect.catchTag("DocgenError", (err) => + Effect.gen(function*() { + const config = yield* Configuration.Configuration + return yield* Effect.fail( + new Domain.DocgenError({ + message: `[${config.projectName}] ${err.message}` + }) + ) + }))) + ), Command.provideEffect(Configuration.Configuration, (args) => Configuration.load(args)), Command.run({ name: "docgen", diff --git a/src/bin.ts b/src/bin.ts index 552110a..800e4cf 100644 --- a/src/bin.ts +++ b/src/bin.ts @@ -14,8 +14,7 @@ import { cli } from "./CLI.js" import * as Configuration from "./Configuration.js" import * as Domain from "./Domain.js" -/** @internal */ -export const MainLive = Configuration.configProviderLayer.pipe( +const MainLive = Configuration.configProviderLayer.pipe( Layer.provideMerge(Layer.mergeAll( Logger.minimumLogLevel(LogLevel.Info), Domain.Process.Default, From 8c59566b88fc62bfb454a7d4d84711f097a36cac Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 10 Mar 2025 10:56:58 +0100 Subject: [PATCH 50/56] Refactor Checker module to improve namespace and test error handling - Update `checkNamespace` function to recursively check interfaces, type aliases, and nested namespaces - Modify test cases to use consistent file naming and improve error message formatting - Remove unused imports and test utilities - Enhance error reporting for namespaces, exports, and classes --- docs/modules/Checker.ts.md | 8 +-- src/Checker.ts | 14 ++++- test/Checker.test.ts | 122 ++++++++++++++++++++++++------------- 3 files changed, 93 insertions(+), 51 deletions(-) diff --git a/docs/modules/Checker.ts.md b/docs/modules/Checker.ts.md index 051a0e0..1615d88 100644 --- a/docs/modules/Checker.ts.md +++ b/docs/modules/Checker.ts.md @@ -65,7 +65,7 @@ declare const checkExports: ( ) => Effect.Effect, never, Configuration.Configuration | Parser.Source> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L177) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L185) Since v0.6.0 @@ -105,7 +105,7 @@ Since v0.6.0 declare const checkModule: (module: Domain.Module) => Effect.Effect, never, Configuration.Configuration> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L184) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L192) Since v0.6.0 @@ -119,7 +119,7 @@ declare const checkModules: ( ) => Effect.Effect, never, Configuration.Configuration> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L208) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L216) Since v0.6.0 @@ -133,7 +133,7 @@ declare const checkNamespaces: ( ) => Effect.Effect, never, Configuration.Configuration | Parser.Source> ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L164) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Checker.ts#L172) Since v0.6.0 diff --git a/src/Checker.ts b/src/Checker.ts index c574098..293e87f 100644 --- a/src/Checker.ts +++ b/src/Checker.ts @@ -152,9 +152,17 @@ export function checkTypeAliases(models: ReadonlyArray) { return Effect.forEach(models, checkTypeAlias).pipe(Effect.map(Array.flatten)) } -function checkNamespace(model: Domain.Namespace) { - return checkEntry(model, { - enforceVersion: true +function checkNamespace( + model: Domain.Namespace +): Effect.Effect, never, Parser.Source | Configuration.Configuration> { + return Effect.gen(function*() { + const docErrors = yield* checkEntry(model, { + enforceVersion: true + }) + const interfacesErrors = yield* checkInterfaces(model.interfaces) + const typeAliasesErrors = yield* checkTypeAliases(model.typeAliases) + const namespacesErrors = yield* checkNamespaces(model.namespaces) + return Array.flatten([docErrors, interfacesErrors, typeAliasesErrors, namespacesErrors]) }) } diff --git a/test/Checker.test.ts b/test/Checker.test.ts index c7ff7ab..06164ec 100644 --- a/test/Checker.test.ts +++ b/test/Checker.test.ts @@ -2,14 +2,11 @@ import * as Checker from "@effect/docgen/Checker" import * as Configuration from "@effect/docgen/Configuration" import * as Parser from "@effect/docgen/Parser" import { Path } from "@effect/platform" -import chalk from "chalk" import { Effect, Predicate } from "effect" import * as assert from "node:assert/strict" import * as ast from "ts-morph" import { describe, it } from "vitest" -let testCounter = 0 - const project = new ast.Project({ compilerOptions: { strict: true }, useInMemoryFileSystem: true @@ -32,13 +29,24 @@ const defaultConfig: Configuration.ConfigurationShape = { examplesCompilerOptions: {} } +const makeSourcefile = (source: string | ast.SourceFile) => { + if (Predicate.isString(source)) { + const filename = `test.ts` + const existing = project.getSourceFile(filename) + if (existing) { + project.removeSourceFile(existing) + } + return project.createSourceFile(filename, source) + } + return source +} + const makeSource = (source: string | ast.SourceFile) => { - const filename = `test-${testCounter++}` + const sourceFile = makeSourcefile(source) + const filename = sourceFile.getBaseName() return Parser.Source.of({ path: [filename], - sourceFile: Predicate.isString(source) - ? project.createSourceFile(`${filename}.ts`, source) - : source + sourceFile }) } @@ -63,7 +71,7 @@ const expectFailure = ( describe("Checker", () => { describe("checkFunctions", () => { - it("should raise an error if `@since` tag is missing in export", () => { + it("should raise an error if `@since` tag is missing", () => { expectFailure( {}, ` @@ -75,43 +83,53 @@ export function b() {} `, Parser.parseFunctions, Checker.checkFunctions, - [`Missing \`@since\` tag in file /test-0.ts: - - 4 | - 5 | /** description */ -> 6 | export function b() {} - | ^ - 7 | `] + [ + "Missing `@since` tag in file /test.ts:\n" + + "\n" + + " 4 |\n" + + " 5 | /** description */\n" + + "> 6 | export function b() {}\n" + + " | ^\n" + + " 7 | " + ] ) }) }) - describe.skip("checkExports", () => { - it("should raise an error if `@since` tag is missing in export", () => { + describe("checkExports", () => { + it("should raise an error if `@since` tag is missing", () => { expectFailure( {}, "export { a }", Parser.parseExports, Checker.checkExports, - ["Missing `@since` tag in export: a"] + [ + "Missing `@since` tag in file /test.ts:\n" + + "\n" + + "> 1 | export { a }\n" + + " | ^" + ] ) }) }) - describe.skip("checkNamespaces", () => { - it("should raise an error if the namespace is not well documented", () => { + describe("checkNamespaces", () => { + it("should raise an error if `@since` tag is missing", () => { expectFailure( {}, "export namespace A {}", Parser.parseNamespaces, Checker.checkNamespaces, [ - `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#A")} documentation` + "Missing `@since` tag in file /test.ts:\n" + + "\n" + + "> 1 | export namespace A {}\n" + + " | ^" ] ) }) - it("should raise an error if the interface is not well documented", () => { + it("should raise an error if `@since` tag is missing on a nested interface", () => { expectFailure( {}, ` @@ -124,11 +142,20 @@ export function b() {} `, Parser.parseNamespaces, Checker.checkNamespaces, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] + [ + "Missing `@since` tag in file /test.ts:\n" + + "\n" + + " 4 | */\n" + + " 5 | export namespace A {\n" + + "> 6 | export interface B {}\n" + + " | ^\n" + + " 7 | }\n" + + " 8 | " + ] ) }) - it("should raise an error if the type alias is not well documented", () => { + it("should raise an error if `@since` tag is missing on a nested type alias", () => { expectFailure( {}, ` @@ -141,11 +168,20 @@ export function b() {} `, Parser.parseNamespaces, Checker.checkNamespaces, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] + [ + "Missing `@since` tag in file /test.ts:\n" + + "\n" + + " 4 | */\n" + + " 5 | export namespace A {\n" + + "> 6 | export type B = string\n" + + " | ^\n" + + " 7 | }\n" + + " 8 | " + ] ) }) - it("should raise an error if the namespace is not well documented", () => { + it("should raise an error if `@since` tag is missing on a nested namespace", () => { expectFailure( {}, ` @@ -158,36 +194,34 @@ export function b() {} `, Parser.parseNamespaces, Checker.checkNamespaces, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#B")} documentation`] + [ + "Missing `@since` tag in file /test.ts:\n" + + "\n" + + " 4 | */\n" + + " 5 | export namespace A {\n" + + "> 6 | export namespace B {}\n" + + " | ^\n" + + " 7 | }\n" + + " 8 | " + ] ) }) }) - describe.skip("checkClasses", () => { - it("should raise an error if an `@since` tag is missing in a module", () => { + describe("checkClasses", () => { + it("should raise an error if `@since` tag is missing", () => { expectFailure( {}, `export class MyClass {}`, Parser.parseClasses, Checker.checkClasses, [ - `Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass")} documentation` + "Missing `@since` tag in file /test.ts:\n" + + "\n" + + "> 1 | export class MyClass {}\n" + + " | ^" ] ) }) - it("should raise an error if `@since` is missing in a property", () => { - expectFailure( - {}, - `/** - * @since 1.0.0 - */ - export class MyClass { - readonly _A!: A - }`, - Parser.parseClasses, - Checker.checkClasses, - [`Missing ${chalk.bold("@since")} tag in ${chalk.bold("test#MyClass#_A")} documentation`] - ) - }) }) }) From 73a3af852b47ec76194afb300b72066b2f570040 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 10 Mar 2025 11:16:05 +0100 Subject: [PATCH 51/56] chore --- test/Parser.test.ts | 59 +++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index c6687f5..59004b0 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -809,30 +809,6 @@ Since v1.0.0` ) }) - it("should handle renamimg", async () => { - await expectMarkdown( - Parser.parseExports, - `const a = 1; - export { - /** - * @since 1.0.0 - */ - a as b - }`, - `## b - -**Signature** - -\`\`\`ts -declare const b: 1 -\`\`\` - -[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) - -Since v1.0.0` - ) - }) - it("should return an `Export`", async () => { await expectMarkdown( Parser.parseExports, @@ -842,6 +818,10 @@ Since v1.0.0` export { /** * description_of_a + * \`\`\`ts + * const a: string = 1 + * \`\`\` + * * @since 1.0.0 */ a, @@ -854,6 +834,9 @@ Since v1.0.0` `## a description_of_a +\`\`\`ts +const a: string = 1 +\`\`\` **Signature** @@ -861,7 +844,7 @@ description_of_a declare const a: 1 \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L9) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L13) Since v1.0.0 ## b @@ -874,12 +857,36 @@ description_of_b declare const b: 2 \`\`\` -[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L14) +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L18) Since v2.0.0` ) }) + it("should handle renamimg", async () => { + await expectMarkdown( + Parser.parseExports, + `const a = 1; + export { + /** + * @since 1.0.0 + */ + a as b + }`, + `## b + +**Signature** + +\`\`\`ts +declare const b: 1 +\`\`\` + +[Source](https://github.com/effect-ts/docgen/blob/main/src/test.ts#L6) + +Since v1.0.0` + ) + }) + it("should handle a single re-export", () => { project.createSourceFile("a.ts", `export const a = 1`) const sourceFile = project.createSourceFile( From 57ff89772596201fa5bc5c6cd056684df249d099 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Mon, 10 Mar 2025 11:16:36 +0100 Subject: [PATCH 52/56] Add support for generating examples for module exports --- src/Core.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Core.ts b/src/Core.ts index c39b0b2..68c64bf 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -186,7 +186,7 @@ const getExampleFiles = (modules: ReadonlyArray) => Effect.gen(function*() { const config = yield* Configuration.Configuration const path = yield* Path.Path - return Array.flatMap(modules, (module) => { + const files = Array.flatMap(modules, (module) => { const prefix = module.path.join("-") const getFiles = @@ -216,7 +216,7 @@ const getExampleFiles = (modules: ReadonlyArray) => extractPrefixedNestedNamespaces(namespace, "")) const moduleExamples = getFiles("module")(module) - const methodsExamples = Array.flatMap(module.classes, (c) => + const classExamples = Array.flatMap(module.classes, (c) => Array.flatten([ Array.flatMap( c.methods, @@ -260,6 +260,10 @@ const getExampleFiles = (modules: ReadonlyArray) => module.functions, getFiles("function") ) + const exportsExamples = Array.flatMap( + module.exports, + getFiles("export") + ) const namespacesExamples = Array.flatMap( allPrefixedNamespaces, ([ns, doc]) => getFiles(filterJoin(["namespace", ns]))(doc) @@ -267,14 +271,17 @@ const getExampleFiles = (modules: ReadonlyArray) => return Array.flatten([ moduleExamples, - methodsExamples, + classExamples, interfacesExamples, typeAliasesExamples, constantsExamples, functionsExamples, - namespacesExamples + namespacesExamples, + exportsExamples ]) }) + + return files }) /** From d2e432058d97072950a4b8e5a66a66d3316b94e5 Mon Sep 17 00:00:00 2001 From: Tim Date: Fri, 16 Jun 2023 10:52:19 +1200 Subject: [PATCH 53/56] chore: add doc generation for AI --- docs/modules/CLI.ts.md | 2 +- docs/modules/Configuration.ts.md | 8 ++- docs/modules/Core.ts.md | 2 +- docs/modules/Domain.ts.md | 79 ++++++++++++++++------- docs/modules/Printer.ts.md | 17 +++++ schema.json | 12 +++- src/CLI.ts | 26 +++++++- src/Configuration.ts | 12 ++++ src/Core.ts | 104 ++++++++++++++++++++++++++++++- src/Domain.ts | 19 ++++++ src/Printer.ts | 14 +++++ test/Configuration.test.ts | 8 ++- test/Parser.test.ts | 2 + 13 files changed, 270 insertions(+), 35 deletions(-) diff --git a/docs/modules/CLI.ts.md b/docs/modules/CLI.ts.md index 0643e61..72eef92 100644 --- a/docs/modules/CLI.ts.md +++ b/docs/modules/CLI.ts.md @@ -33,6 +33,6 @@ declare const cli: ( > ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/CLI.ts#L190) +[Source](https://github.com/effect-ts/docgen/blob/main/src/CLI.ts#L214) Since v0.6.0 diff --git a/docs/modules/Configuration.ts.md b/docs/modules/Configuration.ts.md index 668917b..623451b 100644 --- a/docs/modules/Configuration.ts.md +++ b/docs/modules/Configuration.ts.md @@ -31,7 +31,7 @@ Since v0.6.0 declare class Configuration ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L114) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L124) Since v0.6.0 @@ -58,6 +58,8 @@ declare const ConfigurationSchema: Schema.Struct<{ examplesCompilerOptions: Schema.optional< Schema.Union<[typeof Schema.String, Schema.Record$]> > + enableAI: Schema.optional + enableJson: Schema.optional }> ``` @@ -85,10 +87,12 @@ export interface ConfigurationShape { readonly exclude: ReadonlyArray readonly parseCompilerOptions: Record readonly examplesCompilerOptions: Record + readonly enableAI: boolean + readonly enableJson: boolean } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L93) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Configuration.ts#L101) Since v0.6.0 diff --git a/docs/modules/Core.ts.md b/docs/modules/Core.ts.md index 29b3044..9a89970 100644 --- a/docs/modules/Core.ts.md +++ b/docs/modules/Core.ts.md @@ -29,6 +29,6 @@ The metadata key for skipping type-checking. declare const SKIP_TYPE_CHECKING_FENCE_METADATA: "skip-type-checking" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Core.ts#L162) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Core.ts#L164) Since v0.6.0 diff --git a/docs/modules/Domain.ts.md b/docs/modules/Domain.ts.md index 7972045..335bea2 100644 --- a/docs/modules/Domain.ts.md +++ b/docs/modules/Domain.ts.md @@ -20,6 +20,9 @@ Since v0.6.0 - [Doc (class)](#doc-class) - [modifyDescription (method)](#modifydescription-method) - [DocEntry (class)](#docentry-class) + - [modifyName (method)](#modifyname-method) + - [DocEntry (namespace)](#docentry-namespace) + - [~~Name~~ (type alias)](#name-type-alias) - [DocgenError (class)](#docgenerror-class) - [Export (class)](#export-class) - [\_tag (property)](#_tag-property-2) @@ -62,7 +65,7 @@ declare class Class { constructor( ) } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L79) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L98) Since v0.6.0 @@ -74,7 +77,7 @@ Since v0.6.0 readonly _tag: "Class" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L80) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L99) ## Constant (class) @@ -86,7 +89,7 @@ declare class Constant { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L155) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L174) Since v0.6.0 @@ -98,7 +101,7 @@ Since v0.6.0 readonly _tag: "Constant" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L156) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L175) ## Doc (class) @@ -117,7 +120,7 @@ declare class Doc { constructor( ) } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L29) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L48) Since v0.6.0 @@ -129,7 +132,7 @@ Since v0.6.0 declare const modifyDescription: (description: string | undefined) => Doc ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L41) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L60) ## DocEntry (class) @@ -148,6 +151,34 @@ declare class DocEntry { constructor( Since v0.6.0 +### modifyName (method) + +**Signature** + +```ts +declare const modifyName: (name: string) => this +``` + +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L24) + +## DocEntry (namespace) + +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L35) + +Since v0.6.0 + +### ~~Name~~ (type alias) + +**Signature** + +```ts +type Name = A["name"] +``` + +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L41) + +Since v0.6.0 + ## DocgenError (class) **Signature** @@ -156,7 +187,7 @@ Since v0.6.0 declare class DocgenError ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L252) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L271) Since v0.6.0 @@ -184,7 +215,7 @@ declare class Export { constructor( ) } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L181) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L200) Since v0.6.0 @@ -196,7 +227,7 @@ Since v0.6.0 readonly _tag: "Export" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L182) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L201) ## File (class) @@ -212,7 +243,7 @@ declare class File { constructor( ) } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L228) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L247) Since v0.6.0 @@ -226,7 +257,7 @@ declare class Function { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L123) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L142) Since v0.6.0 @@ -238,7 +269,7 @@ Since v0.6.0 readonly _tag: "Function" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L124) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L143) ## Interface (class) @@ -250,7 +281,7 @@ declare class Interface { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L98) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L117) Since v0.6.0 @@ -262,7 +293,7 @@ Since v0.6.0 readonly _tag: "Interface" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L99) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L118) ## Module (class) @@ -284,7 +315,7 @@ declare class Module { constructor( ) } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L59) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L78) Since v0.6.0 @@ -303,7 +334,7 @@ declare class Namespace { constructor( ) } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L198) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L217) Since v0.6.0 @@ -315,7 +346,7 @@ Since v0.6.0 readonly _tag: "Namespace" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L199) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L218) ## Position (interface) @@ -328,7 +359,7 @@ export interface Position { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L114) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L133) Since v0.6.0 @@ -342,7 +373,7 @@ declare class TypeAlias { } ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L139) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L158) Since v0.6.0 @@ -354,7 +385,7 @@ Since v0.6.0 readonly _tag: "TypeAlias" ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L140) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L159) # service @@ -368,7 +399,7 @@ Represents a handle to the currently executing process. declare class Process ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L262) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L281) Since v0.6.0 @@ -385,7 +416,7 @@ The file path is converted to lowercase before comparison. declare const ByPath: Order.Order ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L217) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L236) Since v0.6.0 @@ -399,7 +430,7 @@ Since v0.6.0 declare const DocgenErrorTypeId: unique symbol ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L240) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L259) Since v0.6.0 @@ -411,6 +442,6 @@ Since v0.6.0 type DocgenErrorTypeId = typeof DocgenErrorTypeId ``` -[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L246) +[Source](https://github.com/effect-ts/docgen/blob/main/src/Domain.ts#L265) Since v0.6.0 diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index ee89ff2..b79ca02 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -16,6 +16,7 @@ Since v0.6.0 - [printModule](#printmodule) - [utils](#utils) - [prettify](#prettify) + - [printForAI](#printforai) - [printFrontMatter](#printfrontmatter) --- @@ -48,6 +49,22 @@ declare const prettify: (s: string) => Effect.Effect Since v0.6.0 +## printForAI + +**Signature** + +```ts +declare const printForAI: ( + _projectName: string, + module: Domain.Module, + printable: Printable +) => Effect.Effect +``` + +[Source](https://github.com/effect-ts/docgen/blob/main/src/Printer.ts#L382) + +Since v0.6.0 + ## printFrontMatter **Signature** diff --git a/schema.json b/schema.json index 77fb2a9..a5eb6bd 100644 --- a/schema.json +++ b/schema.json @@ -94,10 +94,20 @@ ], "description": "tsconfig for the examples options (or path to a tsconfig)", "default": {} + }, + "enableAI": { + "type": "boolean", + "description": "Whether or not to enable AI for the examples", + "default": true + }, + "enableJson": { + "type": "boolean", + "description": "Whether or not to output JSON files", + "default": true } }, "additionalProperties": false } }, "$ref": "#/$defs/ConfigurationSchema" -} +} \ No newline at end of file diff --git a/src/CLI.ts b/src/CLI.ts index f0b908e..77e5ce0 100644 --- a/src/CLI.ts +++ b/src/CLI.ts @@ -164,6 +164,28 @@ const examplesCompilerOptions = Options.file("examples-tsconfig-file", { exists: Options.optional ) +const enableAI = Options.boolean("no-enable-ai", { + ifPresent: false, + negationNames: ["enable-ai"] +}).pipe( + Options.withFallbackConfig(Config.boolean("enableAI")), + Options.withDefault(true), + Options.withDescription( + "Whether or not to generate AI documentation for the project" + ) +) + +const enableJson = Options.boolean("no-enable-json", { + ifPresent: false, + negationNames: ["enable-json"] +}).pipe( + Options.withFallbackConfig(Config.boolean("enableJson")), + Options.withDefault(true), + Options.withDescription( + "Whether or not to generate JSON output for the project" + ) +) + const options = { projectHomepage, srcLink, @@ -177,7 +199,9 @@ const options = { runExamples, exclude, parseCompilerOptions, - examplesCompilerOptions + examplesCompilerOptions, + enableAI, + enableJson } /** @internal */ diff --git a/src/Configuration.ts b/src/Configuration.ts index 4427e67..7cae968 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -83,6 +83,14 @@ export const ConfigurationSchema = Schema.Struct({ examplesCompilerOptions: Schema.optional(compilerOptionsSchema).annotations({ description: "tsconfig for the examples options (or path to a tsconfig)", default: {} + }), + enableAI: Schema.optional(Schema.Boolean).annotations({ + description: "Whether or not to enable AI for the examples", + default: true + }), + enableJson: Schema.optional(Schema.Boolean).annotations({ + description: "Whether or not to output JSON files", + default: true }) }).annotations({ identifier: "ConfigurationSchema" }) @@ -105,6 +113,8 @@ export interface ConfigurationShape { readonly exclude: ReadonlyArray readonly parseCompilerOptions: Record readonly examplesCompilerOptions: Record + readonly enableAI: boolean + readonly enableJson: boolean } /** @@ -243,6 +253,8 @@ export const load = (args: { readonly exclude: ReadonlyArray readonly parseCompilerOptions: Option.Option> readonly examplesCompilerOptions: Option.Option> + readonly enableAI: boolean + readonly enableJson: boolean }) => Effect.gen(function*() { // Extract the requisite services diff --git a/src/Core.ts b/src/Core.ts index 68c64bf..c93dda2 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -8,10 +8,11 @@ import * as CommandExecutor from "@effect/platform/CommandExecutor" import * as FileSystem from "@effect/platform/FileSystem" import * as Path from "@effect/platform/Path" import chalk from "chalk" -import { pipe } from "effect" import * as Array from "effect/Array" import * as Chunk from "effect/Chunk" import * as Effect from "effect/Effect" +import { pipe } from "effect/Function" +import * as Option from "effect/Option" import * as Stream from "effect/Stream" import * as String from "effect/String" import * as Glob from "glob" @@ -20,6 +21,7 @@ import * as Configuration from "./Configuration.js" import * as Domain from "./Domain.js" import * as Parser from "./Parser.js" import * as Printer from "./Printer.js" + /** * Find all files matching the specified `glob` pattern, optionally excluding * files matching the provided `exclude` patterns. @@ -429,7 +431,9 @@ const getMarkdown = (modules: ReadonlyArray) => const index = yield* getMarkdownIndex const yml = yield* getMarkdownConfigYML const moduleFiles = yield* getModuleMarkdownFiles(modules) - return [homepage, index, yml, ...moduleFiles] + const aiFiles = yield* maybeGetAIMarkdownFiles(modules) + const jsonFiles = yield* maybeGetJsonFiles(modules) + return [homepage, index, yml, ...moduleFiles, ...aiFiles, ...jsonFiles] }) const getMarkdownHomepage = Effect.gen(function*() { @@ -532,6 +536,19 @@ const getModuleMarkdownOutputPath = (module: Domain.Module) => { }) } +const getAIMarkdownOutputPath = Effect.fnUntraced(function*( + module: Domain.Module, + printable: Printer.Printable +) { + const config = yield* Configuration.Configuration + const path = yield* Path.Path + return path.join( + config.outDir, + "ai", + `${module.path.slice(1).join("-").replace(/\.ts$/, "")}-${printable.name}.md` + ) +}) + const getModuleMarkdownFiles = (modules: ReadonlyArray) => Effect.forEach(modules, (module, i) => Effect.gen(function*() { @@ -555,10 +572,91 @@ ${toc} return new Domain.File(outputPath, prettified, true) })) +const getModulePrintables = (module: Domain.Module) => + [ + module.classes, + module.constants, + module.functions, + module.interfaces, + module.typeAliases, + module.namespaces.flatMap((ns) => + [ns.interfaces, ns.typeAliases].flat().map((doc) => doc.modifyName(`${ns.name}.${doc.name}`)) + ) + ].flat() + +const getAIMarkdownFiles = Effect.fnUntraced(function*(projectName: string, modules: ReadonlyArray) { + const aiModules = pipe( + modules, + Array.flatMap((module) => + pipe( + getModulePrintables(module), + Array.map((printable) => ({ module, printable })) + ) + ), + Array.filter(({ printable }) => printable.doc.description !== undefined) + ) + + const files = Array.empty() + for (const { module, printable } of aiModules) { + const outputPath = yield* getAIMarkdownOutputPath(module, printable) + const content = yield* Printer.printForAI(projectName, module, printable) + files.push(new Domain.File(outputPath, content, true)) + } + return files +}) + +const getJsonFiles = Effect.fnUntraced(function*( + projectName: string, + modules: ReadonlyArray +) { + const config = yield* Configuration.Configuration + const path = yield* Path.Path + const printables = pipe( + modules, + Array.bindTo("module"), + Array.bind("printable", ({ module }) => getModulePrintables(module)), + Array.map(({ module, printable }) => { + return { + _tag: printable._tag, + module: { + name: module.name, + path: module.path.join("/") + }, + project: projectName, + name: printable.name, + description: printable.doc.description, + deprecated: pipe(printable.doc.deprecated, Array.head, Option.isSome), + examples: printable.doc.examples.map((example) => example), + since: pipe(printable.doc.since, Array.head, Option.getOrNull), + category: pipe(printable.doc.category, Array.head, Option.getOrNull), + signature: "signature" in printable ? printable.signature : null + } + }) + ) + + return [ + new Domain.File( + path.join(config.outDir, `${projectName.replace("/", "-")}.json`), + JSON.stringify(printables, null, 2), + true + ) + ] +}) + +const maybeGetAIMarkdownFiles = Effect.fnUntraced(function*(modules: ReadonlyArray) { + const config = yield* Configuration.Configuration + return config.enableAI ? yield* getAIMarkdownFiles(config.projectName, modules) : [] +}) + +const maybeGetJsonFiles = Effect.fnUntraced(function*(modules: ReadonlyArray) { + const config = yield* Configuration.Configuration + return config.enableJson ? yield* getJsonFiles(config.projectName, modules) : [] +}) + const writeMarkdown = (files: ReadonlyArray) => Effect.gen(function*() { const config = yield* Configuration.Configuration - const path = yield* pipe(Path.Path, Effect.provide(NodePath.layerPosix)) + const path = yield* Effect.provide(Path.Path, NodePath.layerPosix) const fileSystem = yield* FileSystem.FileSystem const pattern = path.normalize(path.join(config.outDir, "**/*.ts.md")) yield* Effect.logDebug(`Deleting ${chalk.black(pattern)}...`) diff --git a/src/Domain.ts b/src/Domain.ts index a4d3ad2..93870c8 100644 --- a/src/Domain.ts +++ b/src/Domain.ts @@ -20,6 +20,25 @@ export class DocEntry { readonly signature: string, readonly position: Position ) {} + + modifyName(name: string): this { + const obj = { ...this, name } + Object.setPrototypeOf(obj, Object.getPrototypeOf(this)) + return obj + } +} + +/** + * @category model + * @since 0.6.0 + */ +export declare namespace DocEntry { + /** + * @category model + * @since 0.6.0 + * @deprecated + */ + export type Name = A["name"] } /** diff --git a/src/Printer.ts b/src/Printer.ts index 258e90c..e291d27 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -375,3 +375,17 @@ export function prettify(s: string) { catch: identity }).pipe(Effect.orDie) } + +/** + * @since 0.6.0 + */ +export const printForAI = Effect.fnUntraced(function*( + _projectName: string, + module: Domain.Module, + printable: Printable +) { + return yield* printModel(printable.name, printable.doc, { + signature: "signature" in printable ? printable.signature : undefined, + position: printable.position + }).pipe(Effect.provideService(Parser.Source, module.source)) +}) diff --git a/test/Configuration.test.ts b/test/Configuration.test.ts index 0f1c103..1c98e56 100644 --- a/test/Configuration.test.ts +++ b/test/Configuration.test.ts @@ -90,7 +90,9 @@ describe("Configuration", () => { runExamples: false, exclude: [], parseCompilerOptions: Configuration.defaultCompilerOptions, - examplesCompilerOptions: Configuration.defaultCompilerOptions + examplesCompilerOptions: Configuration.defaultCompilerOptions, + enableAI: true, + enableJson: true }) }) const cli = testCliFor(program) @@ -126,7 +128,9 @@ describe("Configuration", () => { runExamples: false, exclude: [], parseCompilerOptions, - examplesCompilerOptions: Configuration.defaultCompilerOptions + examplesCompilerOptions: Configuration.defaultCompilerOptions, + enableAI: true, + enableJson: true }) }) const cli = testCliFor(program) diff --git a/test/Parser.test.ts b/test/Parser.test.ts index 59004b0..af782d5 100644 --- a/test/Parser.test.ts +++ b/test/Parser.test.ts @@ -22,6 +22,8 @@ const defaultConfig: Configuration.ConfigurationShape = { srcDir: "src", outDir: "docs", theme: "mikearnaldi/just-the-docs", + enableAI: true, + enableJson: true, enableSearch: true, enforceDescriptions: false, enforceExamples: false, From 863c0a7f526d0cb1b71cf49373c942ba73793ec5 Mon Sep 17 00:00:00 2001 From: Tim Date: Fri, 14 Mar 2025 09:37:08 +1300 Subject: [PATCH 54/56] add sourceUrl to json --- src/Core.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Core.ts b/src/Core.ts index c93dda2..6fc897d 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -629,7 +629,10 @@ const getJsonFiles = Effect.fnUntraced(function*( examples: printable.doc.examples.map((example) => example), since: pipe(printable.doc.since, Array.head, Option.getOrNull), category: pipe(printable.doc.category, Array.head, Option.getOrNull), - signature: "signature" in printable ? printable.signature : null + signature: "signature" in printable ? printable.signature : null, + sourceUrl: config.srcLink + module.source.sourceFile.getBaseName() + + "#L" + + printable.position.line } }) ) From d80b45ce5b2d64c06396de1c896d93b99060c63a Mon Sep 17 00:00:00 2001 From: Tim Date: Fri, 14 Mar 2025 09:58:01 +1300 Subject: [PATCH 55/56] improve context for ai files --- docs/modules/Printer.ts.md | 2 +- src/Printer.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/modules/Printer.ts.md b/docs/modules/Printer.ts.md index b79ca02..b456833 100644 --- a/docs/modules/Printer.ts.md +++ b/docs/modules/Printer.ts.md @@ -55,7 +55,7 @@ Since v0.6.0 ```ts declare const printForAI: ( - _projectName: string, + projectName: string, module: Domain.Module, printable: Printable ) => Effect.Effect diff --git a/src/Printer.ts b/src/Printer.ts index e291d27..f9d0d94 100644 --- a/src/Printer.ts +++ b/src/Printer.ts @@ -380,12 +380,18 @@ export function prettify(s: string) { * @since 0.6.0 */ export const printForAI = Effect.fnUntraced(function*( - _projectName: string, + projectName: string, module: Domain.Module, printable: Printable ) { - return yield* printModel(printable.name, printable.doc, { + const moduleName = module.name.replace(/\.ts$/, "") + const content = yield* printModel(`${moduleName}.${printable.name}`, printable.doc, { signature: "signature" in printable ? printable.signature : undefined, position: printable.position }).pipe(Effect.provideService(Parser.Source, module.source)) + + return `Package: \`${projectName}\`
+Module: \`${moduleName}\`
+ +${content}` }) From ad4f2b9581e83df70d10f72f3b32e7e85967dfce Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 27 May 2025 15:23:11 +1200 Subject: [PATCH 56/56] add exports to getModulePrintables --- src/Core.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core.ts b/src/Core.ts index 6fc897d..3b501d0 100644 --- a/src/Core.ts +++ b/src/Core.ts @@ -579,6 +579,7 @@ const getModulePrintables = (module: Domain.Module) => module.functions, module.interfaces, module.typeAliases, + module.exports, module.namespaces.flatMap((ns) => [ns.interfaces, ns.typeAliases].flat().map((doc) => doc.modifyName(`${ns.name}.${doc.name}`)) )