diff --git a/.gitignore b/.gitignore
index f655c8d..c952826 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,4 +56,7 @@ logs
*.tsbuildinfo
# Optional REPL history
-.node_repl_history
\ No newline at end of file
+.node_repl_history
+
+# Docs
+docs/
\ No newline at end of file
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..1e86a94
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+npm_config_registry=https://registry.npmjs.org
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 81dbe31..f66137a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,15 +14,19 @@
"uuid": "^13.0.0"
},
"devDependencies": {
+ "@types/hast": "^3.0.4",
"@types/node": "^25.0.1",
+ "@types/unist": "^3.0.3",
"@vitest/coverage-istanbul": "^1.0.0",
"@vitest/coverage-v8": "^1.0.0",
"@vitest/ui": "^1.0.0",
"dotenv": "^16.3.1",
"eslint": "^8.54.0",
"nock": "^13.4.0",
+ "typedoc": "^0.28.14",
+ "typedoc-plugin-markdown": "^4.9.0",
"typescript": "^5.3.2",
- "vitest": "^1.0.0"
+ "vitest": "^1.6.1"
}
},
"node_modules/@ampproject/remapping": {
@@ -40,24 +44,24 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.26.2",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
- "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.27.1",
"js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
+ "picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/compat-data": {
- "version": "7.26.8",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz",
- "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
+ "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -65,22 +69,22 @@
}
},
"node_modules/@babel/core": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz",
- "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@ampproject/remapping": "^2.2.0",
- "@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/helpers": "^7.26.9",
- "@babel/parser": "^7.26.9",
- "@babel/template": "^7.26.9",
- "@babel/traverse": "^7.26.9",
- "@babel/types": "^7.26.9",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
+ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.28.3",
+ "@babel/helpers": "^7.28.4",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/remapping": "^2.3.5",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -95,17 +99,27 @@
"url": "https://opencollective.com/babel"
}
},
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
"node_modules/@babel/generator": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz",
- "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
+ "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.26.9",
- "@babel/types": "^7.26.9",
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25",
+ "@babel/parser": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
},
"engines": {
@@ -113,14 +127,14 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.26.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz",
- "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==",
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.26.5",
- "@babel/helper-validator-option": "^7.25.9",
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
"browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
@@ -129,30 +143,50 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@babel/helper-module-imports": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
- "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/traverse": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
- "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
+ "version": "7.28.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
+ "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9",
- "@babel/traverse": "^7.25.9"
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.28.3"
},
"engines": {
"node": ">=6.9.0"
@@ -162,9 +196,9 @@
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
- "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -172,9 +206,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
- "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -182,9 +216,9 @@
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
- "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -192,27 +226,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz",
- "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==",
+ "version": "7.28.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
+ "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.26.9",
- "@babel/types": "^7.26.9"
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz",
- "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.26.9"
+ "@babel/types": "^7.28.5"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -222,48 +256,48 @@
}
},
"node_modules/@babel/template": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz",
- "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==",
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.26.2",
- "@babel/parser": "^7.26.9",
- "@babel/types": "^7.26.9"
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz",
- "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
+ "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@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.3.1",
- "globals": "^11.1.0"
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.5",
+ "debug": "^4.3.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": {
- "version": "7.26.9",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz",
- "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
},
"engines": {
"node": ">=6.9.0"
@@ -668,9 +702,9 @@
}
},
"node_modules/@eslint-community/eslint-utils": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
- "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
+ "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -687,9 +721,9 @@
}
},
"node_modules/@eslint-community/regexpp": {
- "version": "4.12.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
- "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
"dev": true,
"license": "MIT",
"engines": {
@@ -720,55 +754,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/@eslint/eslintrc/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "license": "Python-2.0"
- },
- "node_modules/@eslint/eslintrc/node_modules/globals": {
- "version": "13.24.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
- "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/@eslint/js": {
"version": "8.57.1",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
@@ -779,6 +764,20 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
+ "node_modules/@gerrit0/mini-shiki": {
+ "version": "3.20.0",
+ "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.20.0.tgz",
+ "integrity": "sha512-Wa57i+bMpK6PGJZ1f2myxo3iO+K/kZikcyvH8NIqNNZhQUbDav7V9LQmWOXhf946mz5c1NZ19WMsGYiDKTryzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/engine-oniguruma": "^3.20.0",
+ "@shikijs/langs": "^3.20.0",
+ "@shikijs/themes": "^3.20.0",
+ "@shikijs/types": "^3.20.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
@@ -841,34 +840,31 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.8",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
- "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/set-array": "^1.2.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
}
},
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">=6.0.0"
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
}
},
- "node_modules/@jridgewell/set-array": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
- "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -876,16 +872,16 @@
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
- "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.25",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
- "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -939,9 +935,9 @@
"license": "MIT"
},
"node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz",
- "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.54.0.tgz",
+ "integrity": "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng==",
"cpu": [
"arm"
],
@@ -953,9 +949,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz",
- "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.54.0.tgz",
+ "integrity": "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw==",
"cpu": [
"arm64"
],
@@ -967,9 +963,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz",
- "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.54.0.tgz",
+ "integrity": "sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw==",
"cpu": [
"arm64"
],
@@ -981,9 +977,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz",
- "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.54.0.tgz",
+ "integrity": "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A==",
"cpu": [
"x64"
],
@@ -995,9 +991,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz",
- "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.54.0.tgz",
+ "integrity": "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA==",
"cpu": [
"arm64"
],
@@ -1009,9 +1005,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz",
- "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.54.0.tgz",
+ "integrity": "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ==",
"cpu": [
"x64"
],
@@ -1023,9 +1019,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz",
- "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.54.0.tgz",
+ "integrity": "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==",
"cpu": [
"arm"
],
@@ -1037,9 +1033,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz",
- "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.54.0.tgz",
+ "integrity": "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==",
"cpu": [
"arm"
],
@@ -1051,9 +1047,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz",
- "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.54.0.tgz",
+ "integrity": "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==",
"cpu": [
"arm64"
],
@@ -1065,9 +1061,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz",
- "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.54.0.tgz",
+ "integrity": "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==",
"cpu": [
"arm64"
],
@@ -1078,10 +1074,10 @@
"linux"
]
},
- "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz",
- "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==",
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.54.0.tgz",
+ "integrity": "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==",
"cpu": [
"loong64"
],
@@ -1092,10 +1088,10 @@
"linux"
]
},
- "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz",
- "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==",
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.54.0.tgz",
+ "integrity": "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==",
"cpu": [
"ppc64"
],
@@ -1107,9 +1103,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz",
- "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.54.0.tgz",
+ "integrity": "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==",
"cpu": [
"riscv64"
],
@@ -1121,9 +1117,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz",
- "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.54.0.tgz",
+ "integrity": "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==",
"cpu": [
"riscv64"
],
@@ -1135,9 +1131,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz",
- "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.54.0.tgz",
+ "integrity": "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==",
"cpu": [
"s390x"
],
@@ -1149,9 +1145,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz",
- "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.54.0.tgz",
+ "integrity": "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==",
"cpu": [
"x64"
],
@@ -1163,9 +1159,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz",
- "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.54.0.tgz",
+ "integrity": "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==",
"cpu": [
"x64"
],
@@ -1176,10 +1172,24 @@
"linux"
]
},
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.54.0.tgz",
+ "integrity": "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
"node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz",
- "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.54.0.tgz",
+ "integrity": "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw==",
"cpu": [
"arm64"
],
@@ -1191,9 +1201,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz",
- "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.54.0.tgz",
+ "integrity": "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ==",
"cpu": [
"ia32"
],
@@ -1204,10 +1214,24 @@
"win32"
]
},
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.54.0.tgz",
+ "integrity": "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
"node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz",
- "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.54.0.tgz",
+ "integrity": "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg==",
"cpu": [
"x64"
],
@@ -1218,6 +1242,55 @@
"win32"
]
},
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "3.20.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.20.0.tgz",
+ "integrity": "sha512-Yx3gy7xLzM0ZOjqoxciHjA7dAt5tyzJE3L4uQoM83agahy+PlW244XJSrmJRSBvGYELDhYXPacD4R/cauV5bzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.20.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@shikijs/langs": {
+ "version": "3.20.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.20.0.tgz",
+ "integrity": "sha512-le+bssCxcSHrygCWuOrYJHvjus6zhQ2K7q/0mgjiffRbkhM4o1EWu2m+29l0yEsHDbWaWPNnDUTRVVBvBBeKaA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.20.0"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "3.20.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.20.0.tgz",
+ "integrity": "sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.20.0"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "3.20.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.20.0.tgz",
+ "integrity": "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
+ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@@ -1238,16 +1311,33 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
"node_modules/@types/node": {
- "version": "25.0.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.1.tgz",
- "integrity": "sha512-czWPzKIAXucn9PtsttxmumiQ9N0ok9FrBwgRWrwmVLlp86BrMExzvXRLFYRJ+Ex3g6yqj+KuaxfX1JTgV2lpfg==",
+ "version": "25.0.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.3.tgz",
+ "integrity": "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
}
},
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@ungap/structured-clone": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
@@ -1279,51 +1369,6 @@
"vitest": "1.6.1"
}
},
- "node_modules/@vitest/coverage-istanbul/node_modules/istanbul-lib-instrument": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
- "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@babel/core": "^7.23.9",
- "@babel/parser": "^7.23.9",
- "@istanbuljs/schema": "^0.1.3",
- "istanbul-lib-coverage": "^3.2.0",
- "semver": "^7.5.4"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@vitest/coverage-istanbul/node_modules/istanbul-lib-source-maps": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
- "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.23",
- "debug": "^4.1.1",
- "istanbul-lib-coverage": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@vitest/coverage-istanbul/node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@vitest/coverage-v8": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.6.1.tgz",
@@ -1352,21 +1397,6 @@
"vitest": "1.6.1"
}
},
- "node_modules/@vitest/coverage-v8/node_modules/istanbul-lib-source-maps": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
- "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.23",
- "debug": "^4.1.1",
- "istanbul-lib-coverage": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@vitest/expect": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz",
@@ -1414,9 +1444,9 @@
}
},
"node_modules/@vitest/runner/node_modules/yocto-queue": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz",
- "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz",
+ "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1492,20 +1522,10 @@
"url": "https://opencollective.com/vitest"
}
},
- "node_modules/@vitest/utils/node_modules/estree-walker": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
- "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/estree": "^1.0.0"
- }
- },
"node_modules/acorn": {
- "version": "8.14.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
- "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"bin": {
@@ -1581,6 +1601,13 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
"node_modules/assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
@@ -1598,13 +1625,13 @@
"license": "MIT"
},
"node_modules/axios": {
- "version": "1.7.9",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
- "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
+ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
- "form-data": "^4.0.0",
+ "form-data": "^4.0.4",
"proxy-from-env": "^1.1.0"
}
},
@@ -1615,10 +1642,20 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.9.11",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz",
+ "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
"node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1640,9 +1677,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.24.4",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
- "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
"dev": true,
"funding": [
{
@@ -1660,10 +1697,11 @@
],
"license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001688",
- "electron-to-chromium": "^1.5.73",
- "node-releases": "^2.0.19",
- "update-browserslist-db": "^1.1.1"
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
},
"bin": {
"browserslist": "cli.js"
@@ -1706,9 +1744,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001700",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz",
- "integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==",
+ "version": "1.0.30001761",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz",
+ "integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==",
"dev": true,
"funding": [
{
@@ -1745,16 +1783,6 @@
"node": ">=4"
}
},
- "node_modules/chai/node_modules/type-detect": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz",
- "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -1854,10 +1882,9 @@
}
},
"node_modules/debug": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
- "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
- "dev": true,
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
@@ -1924,9 +1951,9 @@
}
},
"node_modules/dotenv": {
- "version": "16.4.7",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
- "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
+ "version": "16.6.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+ "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
@@ -1951,42 +1978,25 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.104",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.104.tgz",
- "integrity": "sha512-Us9M2L4cO/zMBqVkJtnj353nQhMju9slHm62NprKTmdF3HH8wYOtNvDFq/JB2+ZRoGLzdvYDiATlMHs98XBM1g==",
+ "version": "1.5.267",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz",
+ "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==",
"dev": true,
"license": "ISC"
},
"node_modules/engine.io-client": {
- "version": "6.6.3",
- "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
- "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
+ "version": "6.6.4",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.4.tgz",
+ "integrity": "sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.3.1",
+ "debug": "~4.4.1",
"engine.io-parser": "~5.2.1",
- "ws": "~8.17.1",
+ "ws": "~8.18.3",
"xmlhttprequest-ssl": "~2.1.1"
}
},
- "node_modules/engine.io-client/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
"node_modules/engine.io-parser": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
@@ -1996,6 +2006,19 @@
"node": ">=10.0.0"
}
},
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -2190,104 +2213,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/eslint/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "license": "Python-2.0"
- },
- "node_modules/eslint/node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint/node_modules/globals": {
- "version": "13.24.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
- "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/eslint/node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint/node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-limit": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/espree": {
"version": "9.6.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
@@ -2342,6 +2267,16 @@
"node": ">=4.0"
}
},
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -2352,6 +2287,30 @@
"node": ">=0.10.0"
}
},
+ "node_modules/execa": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
+ "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
+ "dev": true,
+ "license": "MIT",
+ "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.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^4.1.0",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=16.17"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -2404,9 +2363,9 @@
"license": "MIT"
},
"node_modules/fastq": {
- "version": "1.19.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
- "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
"dev": true,
"license": "ISC",
"dependencies": {
@@ -2446,6 +2405,23 @@
"node": ">=8"
}
},
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/flat-cache": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
@@ -2469,9 +2445,9 @@
"license": "ISC"
},
"node_modules/follow-redirects": {
- "version": "1.15.9",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
- "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
"funding": [
{
"type": "individual",
@@ -2489,14 +2465,15 @@
}
},
"node_modules/form-data": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
- "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
@@ -2591,6 +2568,41 @@
"node": ">= 0.4"
}
},
+ "node_modules/get-stream": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
+ "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -2605,13 +2617,19 @@
}
},
"node_modules/globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
"engines": {
- "node": ">=4"
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/gopd": {
@@ -2689,6 +2707,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/human-signals": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
+ "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=16.17.0"
+ }
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -2716,16 +2744,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/import-fresh/node_modules/resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -2798,6 +2816,19 @@
"node": ">=8"
}
},
+ "node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -2815,6 +2846,23 @@
"node": ">=8"
}
},
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/istanbul-lib-report": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
@@ -2830,10 +2878,25 @@
"node": ">=10"
}
},
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
+ "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.23",
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/istanbul-reports": {
- "version": "3.1.7",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
- "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
+ "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -2851,6 +2914,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
@@ -2929,6 +3005,16 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "uc.micro": "^2.0.0"
+ }
+ },
"node_modules/local-pkg": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz",
@@ -2946,10 +3032,26 @@
"url": "https://github.com/sponsors/antfu"
}
},
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true,
"license": "MIT"
},
@@ -2973,14 +3075,21 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/lunr": {
+ "version": "2.3.9",
+ "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
+ "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/magic-string": {
- "version": "0.30.17",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
- "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0"
+ "@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/magicast": {
@@ -3011,17 +3120,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/make-dir/node_modules/semver": {
- "version": "7.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
- "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "node_modules/markdown-it": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
+ "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "^4.4.0",
+ "linkify-it": "^5.0.0",
+ "mdurl": "^2.0.0",
+ "punycode.js": "^2.3.1",
+ "uc.micro": "^2.1.0"
},
- "engines": {
- "node": ">=10"
+ "bin": {
+ "markdown-it": "bin/markdown-it.mjs"
}
},
"node_modules/math-intrinsics": {
@@ -3033,6 +3147,13 @@
"node": ">= 0.4"
}
},
+ "node_modules/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -3064,19 +3185,6 @@
"node": ">=8.6"
}
},
- "node_modules/micromatch/node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -3098,6 +3206,19 @@
"node": ">= 0.6"
}
},
+ "node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -3112,16 +3233,16 @@
}
},
"node_modules/mlly": {
- "version": "1.7.4",
- "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz",
- "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz",
+ "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "acorn": "^8.14.0",
- "pathe": "^2.0.1",
- "pkg-types": "^1.3.0",
- "ufo": "^1.5.4"
+ "acorn": "^8.15.0",
+ "pathe": "^2.0.3",
+ "pkg-types": "^1.3.1",
+ "ufo": "^1.6.1"
}
},
"node_modules/mlly/node_modules/pathe": {
@@ -3189,12 +3310,41 @@
}
},
"node_modules/node-releases": {
- "version": "2.0.19",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
- "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+ "version": "2.0.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
"dev": true,
"license": "MIT"
},
+ "node_modules/npm-run-path": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
+ "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-run-path/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -3205,6 +3355,22 @@
"wrappy": "1"
}
},
+ "node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -3239,6 +3405,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -3306,6 +3488,19 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/pkg-types": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
@@ -3418,6 +3613,16 @@
"node": ">=6"
}
},
+ "node_modules/punycode.js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -3446,10 +3651,20 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3474,32 +3689,10 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/rimraf/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/rollup": {
- "version": "4.44.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz",
- "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==",
+ "version": "4.54.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.54.0.tgz",
+ "integrity": "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3513,26 +3706,28 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.44.1",
- "@rollup/rollup-android-arm64": "4.44.1",
- "@rollup/rollup-darwin-arm64": "4.44.1",
- "@rollup/rollup-darwin-x64": "4.44.1",
- "@rollup/rollup-freebsd-arm64": "4.44.1",
- "@rollup/rollup-freebsd-x64": "4.44.1",
- "@rollup/rollup-linux-arm-gnueabihf": "4.44.1",
- "@rollup/rollup-linux-arm-musleabihf": "4.44.1",
- "@rollup/rollup-linux-arm64-gnu": "4.44.1",
- "@rollup/rollup-linux-arm64-musl": "4.44.1",
- "@rollup/rollup-linux-loongarch64-gnu": "4.44.1",
- "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1",
- "@rollup/rollup-linux-riscv64-gnu": "4.44.1",
- "@rollup/rollup-linux-riscv64-musl": "4.44.1",
- "@rollup/rollup-linux-s390x-gnu": "4.44.1",
- "@rollup/rollup-linux-x64-gnu": "4.44.1",
- "@rollup/rollup-linux-x64-musl": "4.44.1",
- "@rollup/rollup-win32-arm64-msvc": "4.44.1",
- "@rollup/rollup-win32-ia32-msvc": "4.44.1",
- "@rollup/rollup-win32-x64-msvc": "4.44.1",
+ "@rollup/rollup-android-arm-eabi": "4.54.0",
+ "@rollup/rollup-android-arm64": "4.54.0",
+ "@rollup/rollup-darwin-arm64": "4.54.0",
+ "@rollup/rollup-darwin-x64": "4.54.0",
+ "@rollup/rollup-freebsd-arm64": "4.54.0",
+ "@rollup/rollup-freebsd-x64": "4.54.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.54.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.54.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.54.0",
+ "@rollup/rollup-linux-arm64-musl": "4.54.0",
+ "@rollup/rollup-linux-loong64-gnu": "4.54.0",
+ "@rollup/rollup-linux-ppc64-gnu": "4.54.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.54.0",
+ "@rollup/rollup-linux-riscv64-musl": "4.54.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.54.0",
+ "@rollup/rollup-linux-x64-gnu": "4.54.0",
+ "@rollup/rollup-linux-x64-musl": "4.54.0",
+ "@rollup/rollup-openharmony-arm64": "4.54.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.54.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.54.0",
+ "@rollup/rollup-win32-x64-gnu": "4.54.0",
+ "@rollup/rollup-win32-x64-msvc": "4.54.0",
"fsevents": "~2.3.2"
}
},
@@ -3561,13 +3756,16 @@
}
},
"node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/shebang-command": {
@@ -3600,6 +3798,19 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/sirv": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz",
@@ -3616,13 +3827,13 @@
}
},
"node_modules/socket.io-client": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
- "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
+ "version": "4.8.3",
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz",
+ "integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.3.2",
+ "debug": "~4.4.1",
"engine.io-client": "~6.6.1",
"socket.io-parser": "~4.2.4"
},
@@ -3630,53 +3841,19 @@
"node": ">=10.0.0"
}
},
- "node_modules/socket.io-client/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
"node_modules/socket.io-parser": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
- "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz",
+ "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.3.1"
+ "debug": "~4.4.1"
},
"engines": {
"node": ">=10.0.0"
}
},
- "node_modules/socket.io-parser/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -3695,9 +3872,9 @@
"license": "MIT"
},
"node_modules/std-env": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz",
- "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==",
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
+ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
"dev": true,
"license": "MIT"
},
@@ -3714,6 +3891,19 @@
"node": ">=8"
}
},
+ "node_modules/strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -3775,28 +3965,6 @@
"node": ">=8"
}
},
- "node_modules/test-exclude/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -3868,19 +4036,95 @@
}
},
"node_modules/type-detect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz",
+ "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typedoc": {
+ "version": "0.28.15",
+ "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.15.tgz",
+ "integrity": "sha512-mw2/2vTL7MlT+BVo43lOsufkkd2CJO4zeOSuWQQsiXoV2VuEn7f6IZp2jsUDPmBMABpgR0R5jlcJ2OGEFYmkyg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@gerrit0/mini-shiki": "^3.17.0",
+ "lunr": "^2.3.9",
+ "markdown-it": "^14.1.0",
+ "minimatch": "^9.0.5",
+ "yaml": "^2.8.1"
+ },
+ "bin": {
+ "typedoc": "bin/typedoc"
+ },
+ "engines": {
+ "node": ">= 18",
+ "pnpm": ">= 10"
+ },
+ "peerDependencies": {
+ "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x"
+ }
+ },
+ "node_modules/typedoc-plugin-markdown": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.9.0.tgz",
+ "integrity": "sha512-9Uu4WR9L7ZBgAl60N/h+jqmPxxvnC9nQAlnnO/OujtG2ubjnKTVUFY1XDhcMY+pCqlX3N2HsQM2QTYZIU9tJuw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "typedoc": "0.28.x"
+ }
+ },
+ "node_modules/typedoc/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/typedoc/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/typescript": {
- "version": "5.7.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
- "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -3891,6 +4135,13 @@
"node": ">=14.17"
}
},
+ "node_modules/uc.micro": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/ufo": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
@@ -3906,9 +4157,9 @@
"license": "MIT"
},
"node_modules/update-browserslist-db": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
- "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==",
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
"dev": true,
"funding": [
{
@@ -3960,9 +4211,9 @@
}
},
"node_modules/vite": {
- "version": "5.4.19",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz",
- "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==",
+ "version": "5.4.21",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz",
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4108,150 +4359,6 @@
}
}
},
- "node_modules/vitest/node_modules/execa": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
- "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
- "dev": true,
- "license": "MIT",
- "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.1.0",
- "onetime": "^6.0.0",
- "signal-exit": "^4.1.0",
- "strip-final-newline": "^3.0.0"
- },
- "engines": {
- "node": ">=16.17"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
- "node_modules/vitest/node_modules/get-stream": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
- "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/vitest/node_modules/human-signals": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
- "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=16.17.0"
- }
- },
- "node_modules/vitest/node_modules/is-stream": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
- "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/vitest/node_modules/mimic-fn": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
- "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/vitest/node_modules/npm-run-path": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
- "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^4.0.0"
- },
- "engines": {
- "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/vitest/node_modules/onetime": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
- "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^4.0.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/vitest/node_modules/path-key": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
- "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/vitest/node_modules/signal-exit": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/vitest/node_modules/strip-final-newline": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
- "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -4303,9 +4410,9 @@
"license": "ISC"
},
"node_modules/ws": {
- "version": "8.17.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
- "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
+ "version": "8.18.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
@@ -4338,6 +4445,22 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/yaml": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
+ "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index b7f492c..15caa74 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,12 @@
"test:e2e": "vitest run tests/e2e",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
- "prepublishOnly": "npm run build"
+ "docs": "typedoc",
+ "prepublishOnly": "npm run build",
+ "create-docs": "npm run create-docs:generate && npm run create-docs:process",
+ "push-docs": "node scripts/mintlify-post-processing/push-to-docs-repo.js",
+ "create-docs:generate": "typedoc",
+ "create-docs:process": "node scripts/mintlify-post-processing/file-processing/file-processing.js"
},
"dependencies": {
"axios": "^1.6.2",
@@ -24,15 +29,19 @@
"uuid": "^13.0.0"
},
"devDependencies": {
+ "@types/hast": "^3.0.4",
"@types/node": "^25.0.1",
+ "@types/unist": "^3.0.3",
"@vitest/coverage-istanbul": "^1.0.0",
"@vitest/coverage-v8": "^1.0.0",
"@vitest/ui": "^1.0.0",
"dotenv": "^16.3.1",
"eslint": "^8.54.0",
"nock": "^13.4.0",
+ "typedoc": "^0.28.14",
+ "typedoc-plugin-markdown": "^4.9.0",
"typescript": "^5.3.2",
- "vitest": "^1.0.0"
+ "vitest": "^1.6.1"
},
"keywords": [
"base44",
diff --git a/scripts/mintlify-post-processing/appended-articles.json b/scripts/mintlify-post-processing/appended-articles.json
new file mode 100644
index 0000000..100bcc4
--- /dev/null
+++ b/scripts/mintlify-post-processing/appended-articles.json
@@ -0,0 +1,4 @@
+{
+ "interfaces/EntitiesModule": "interfaces/EntityHandler",
+ "type-aliases/integrations": "interfaces/CoreIntegrations"
+}
diff --git a/scripts/mintlify-post-processing/category-map.json b/scripts/mintlify-post-processing/category-map.json
new file mode 100644
index 0000000..bab74cd
--- /dev/null
+++ b/scripts/mintlify-post-processing/category-map.json
@@ -0,0 +1,5 @@
+{
+ "functions": "Client",
+ "interfaces": "Modules",
+ "type-aliases": "Modules"
+}
diff --git a/scripts/mintlify-post-processing/file-processing/docs-json-template.json b/scripts/mintlify-post-processing/file-processing/docs-json-template.json
new file mode 100644
index 0000000..b0dc864
--- /dev/null
+++ b/scripts/mintlify-post-processing/file-processing/docs-json-template.json
@@ -0,0 +1,62 @@
+{
+ "$schema": "https://mintlify.com/docs.json",
+ "theme": "mint",
+ "name": "Base44 Support Documentation",
+ "integrations": {
+ "mixpanel": {
+ "projectToken": "cc6e9e106e4b833fc3a3819c11b74138"
+ }
+ },
+ "colors": {
+ "primary": "#FF5500",
+ "light": "#EEE2C0",
+ "dark": "#FF5500"
+ },
+ "navigation": {
+ "tabs": [
+ {
+ "tab": "SDK Reference",
+ "groups": [
+ {
+ "group": "Main Methods",
+ "pages": [
+ "content/functions/createClient",
+ "content/functions/createClientFromRequest",
+ "content/functions/getAccessToken",
+ "content/functions/saveAccessToken",
+ "content/functions/removeAccessToken",
+ "content/functions/getLoginUrl"
+ ]
+ },
+ {
+ "group": "Modules",
+ "pages": ["content/interfaces/Auth"]
+ }
+ ]
+ }
+ ]
+ },
+ "navbar": {
+ "links": [
+ {
+ "label": "Support",
+ "href": "https://app.base44.com/support/conversations"
+ }
+ ],
+ "primary": {
+ "type": "button",
+ "label": "Base44",
+ "href": "https://base44.com/?utm_source=Mintlify&utm_medium=Main&utm_content=menu"
+ }
+ },
+ "footer": {
+ "socials": {
+ "twitter": "https://x.com/base_44",
+ "discord": "https://discord.com/invite/ThpYPZpVts",
+ "linkedin": "https://www.linkedin.com/company/base44"
+ }
+ },
+ "custom": {
+ "stylesheets": ["/styling.css"]
+ }
+}
diff --git a/scripts/mintlify-post-processing/file-processing/file-processing.js b/scripts/mintlify-post-processing/file-processing/file-processing.js
new file mode 100755
index 0000000..b14b347
--- /dev/null
+++ b/scripts/mintlify-post-processing/file-processing/file-processing.js
@@ -0,0 +1,814 @@
+#!/usr/bin/env node
+
+/**
+ * Post-processing script for TypeDoc-generated MDX files
+ *
+ * TypeDoc now emits .mdx files directly, so this script:
+ * 1. Processes links to make them Mintlify-compatible
+ * 2. Removes files for linked types that should be suppressed
+ * 3. Cleans up the temporary linked types tracking file
+ * 4. Generates docs.json with navigation structure
+ * 5. Copies styling.css to docs directory
+ */
+
+import fs from "fs";
+import path from "path";
+import { fileURLToPath } from "url";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const DOCS_DIR = path.join(__dirname, "..", "..", "..", "docs");
+const CONTENT_DIR = path.join(DOCS_DIR, "content");
+const LINKED_TYPES_FILE = path.join(CONTENT_DIR, ".linked-types.json");
+const TEMPLATE_PATH = path.join(__dirname, "docs-json-template.json");
+const STYLING_CSS_PATH = path.join(__dirname, "styling.css");
+const CATEGORY_MAP_PATH = path.join(__dirname, "../category-map.json");
+const TYPES_TO_EXPOSE_PATH = path.join(__dirname, "..", "types-to-expose.json");
+const APPENDED_ARTICLES_PATH = path.join(
+ __dirname,
+ "../appended-articles.json"
+);
+
+// Controlled via env var so we can re-enable Panel injection when needed.
+const PANELS_ENABLED = process.env.MINTLIFY_INCLUDE_PANELS === "true";
+
+const MODULE_RENAMES = {
+ AgentsModule: "agents",
+ AppLogsModule: "app-logs",
+ AuthModule: "auth",
+ ConnectorsModule: "connectors",
+ EntitiesModule: "entities",
+ FunctionsModule: "functions",
+ IntegrationsModule: "integrations",
+ SsoModule: "sso",
+};
+
+const REVERSE_MODULE_RENAMES = Object.entries(MODULE_RENAMES).reduce(
+ (acc, [k, v]) => {
+ acc[v] = k;
+ return acc;
+ },
+ {}
+);
+
+/**
+ * Get list of linked type names that should be suppressed
+ */
+function getLinkedTypeNames() {
+ try {
+ if (fs.existsSync(LINKED_TYPES_FILE)) {
+ const content = fs.readFileSync(LINKED_TYPES_FILE, "utf-8");
+ return new Set(JSON.parse(content));
+ }
+ } catch (e) {
+ // If file doesn't exist or can't be read, return empty set
+ }
+ return new Set();
+}
+
+/**
+ * Load allow-listed type names that should remain in the docs output
+ */
+function getTypesToExpose() {
+ try {
+ const content = fs.readFileSync(TYPES_TO_EXPOSE_PATH, "utf-8");
+ const parsed = JSON.parse(content);
+ if (!Array.isArray(parsed)) {
+ throw new Error("types-to-expose.json must be an array of strings");
+ }
+ return new Set(parsed);
+ } catch (e) {
+ console.error(
+ `Error: Unable to read types-to-expose file: ${TYPES_TO_EXPOSE_PATH}`
+ );
+ console.error(e.message);
+ process.exit(1);
+ }
+}
+
+/**
+ * Process links in a file to make them Mintlify-compatible
+ */
+function processLinksInFile(filePath) {
+ let content = fs.readFileSync(filePath, "utf-8");
+ let modified = false;
+
+ // Remove undesirable lines like "> **IntegrationsModule** = `object` & `object`"
+ // This typically appears in type alias files using intersection types
+ const typeDefinitionRegex = /^> \*\*\w+\*\* = `object` & `object`\s*$/m;
+ if (typeDefinitionRegex.test(content)) {
+ content = content.replace(typeDefinitionRegex, "");
+ modified = true;
+ }
+
+ // Manually add Indexable section if missing for IntegrationsModule
+ if (
+ filePath.includes("integrations.mdx") &&
+ !content.includes("## Indexable")
+ ) {
+ const indexableSection = `
+## Indexable
+
+\\[\`packageName\`: \`string\`\\]: [\`IntegrationPackage\`](IntegrationPackage)
+
+Access to additional integration packages.
+
+### Example
+
+
+
+\`\`\`typescript Access additional packages
+// Access a custom integration package
+base44.integrations.MyCustomPackage.MyFunction({ param: 'value' });
+\`\`\`
+
+
+`;
+ // Append it before the "Type Declaration" or "Core" section if possible, or just at the end before methods if any
+ // Finding a good insertion point
+ const typeDeclarationIndex = content.indexOf("## Type Declaration");
+ if (typeDeclarationIndex !== -1) {
+ content =
+ content.slice(0, typeDeclarationIndex) +
+ indexableSection +
+ "\n" +
+ content.slice(typeDeclarationIndex);
+ modified = true;
+ } else {
+ // If no Type Declaration, maybe append after the main description?
+ // Look for the first horizontal rule or similar
+ const firstHR = content.indexOf("***", 10); // skip first few chars
+ if (firstHR !== -1) {
+ content =
+ content.slice(0, firstHR) +
+ indexableSection +
+ "\n" +
+ content.slice(firstHR);
+ modified = true;
+ }
+ }
+ }
+
+ // Remove .md and .mdx extensions from markdown links
+ // This handles both relative and absolute paths
+ // Regex breakdown:
+ // \[([^\]]+)\] : Match [LinkText]
+ // \( : Match opening (
+ // ([^)]+) : Match path (Group 2)
+ // (\.mdx?)? : Optionally match .md or .mdx extension (Group 3), making it optional to catch links that might have already lost extension or never had it if inconsistent
+ // \) : Match closing )
+ const linkRegex = /\[([^\]]+)\]\(([^)]+?)(\.mdx?)?\)/g;
+ let newContent = content.replace(
+ linkRegex,
+ (match, linkText, linkPath, ext) => {
+ modified = true;
+
+ // Check if the link points to a renamed module
+ const pathParts = linkPath.split("/");
+ const filename = pathParts[pathParts.length - 1];
+
+ // If filename has extension, strip it for checking map
+ const nameWithoutExt = filename.replace(/\.mdx?$/, "");
+
+ if (MODULE_RENAMES[nameWithoutExt]) {
+ pathParts[pathParts.length - 1] = MODULE_RENAMES[nameWithoutExt];
+ linkPath = pathParts.join("/");
+ }
+
+ // Handle relative links that might be missing context (basic cleanup)
+ // e.g. if linkPath is just "entities" but it should be relative
+
+ return `[${linkText}](${linkPath})`;
+ }
+ );
+
+ // Also check for links that might have already been processed (no extension)
+ // or if the above regex missed them (though it matches .mdx?)
+ // The regex requires .md or .mdx extension. If links are already extensionless, this won't run.
+ // But TypeDoc usually outputs links with extensions.
+
+ if (modified) {
+ fs.writeFileSync(filePath, newContent, "utf-8");
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Renames module files and updates their titles
+ */
+function performModuleRenames(dir) {
+ if (!fs.existsSync(dir)) return;
+
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
+
+ for (const entry of entries) {
+ const entryPath = path.join(dir, entry.name);
+
+ if (entry.isDirectory()) {
+ performModuleRenames(entryPath);
+ } else if (
+ entry.isFile() &&
+ (entry.name.endsWith(".mdx") || entry.name.endsWith(".md"))
+ ) {
+ const nameWithoutExt = path.basename(
+ entry.name,
+ path.extname(entry.name)
+ );
+
+ // Check if it's a renamed file or one that needs renaming
+ // e.g. "EntitiesModule" needs renaming. "entities" might need title update.
+
+ let targetName = nameWithoutExt;
+ let needsRename = false;
+
+ if (MODULE_RENAMES[nameWithoutExt]) {
+ targetName = MODULE_RENAMES[nameWithoutExt];
+ needsRename = true;
+ } else if (REVERSE_MODULE_RENAMES[nameWithoutExt]) {
+ // It's already renamed (e.g. "entities"), but we should ensure title is correct
+ targetName = nameWithoutExt;
+ }
+
+ if (needsRename || REVERSE_MODULE_RENAMES[targetName]) {
+ const newPath = path.join(dir, `${targetName}.mdx`); // Always use .mdx
+
+ let content = fs.readFileSync(entryPath, "utf-8");
+
+ // Update title in frontmatter
+ const titleRegex = /^title:\s*["']?([^"'\n]+)["']?/m;
+ if (titleRegex.test(content)) {
+ // Force the title to be the target name
+ content = content.replace(titleRegex, `title: "${targetName}"`);
+ }
+
+ // Write to new path (if renaming) or overwrite (if just updating title)
+ fs.writeFileSync(newPath, content, "utf-8");
+
+ // Delete old file if name is different
+ if (entryPath !== newPath) {
+ fs.unlinkSync(entryPath);
+ console.log(`Renamed module: ${entry.name} -> ${targetName}.mdx`);
+ } else {
+ // If we just updated the title in place
+ // console.log(`Updated title for: ${targetName}`);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Scan docs content directory and build navigation structure
+ */
+function scanDocsContent() {
+ const result = {
+ functions: [],
+ interfaces: [],
+ classes: [],
+ typeAliases: [],
+ };
+
+ const sections = ["functions", "interfaces", "classes", "type-aliases"];
+
+ for (const section of sections) {
+ const sectionDir = path.join(CONTENT_DIR, section);
+ if (!fs.existsSync(sectionDir)) continue;
+
+ const files = fs.readdirSync(sectionDir);
+ const mdxFiles = files
+ .filter((file) => file.endsWith(".mdx"))
+ .map((file) => path.basename(file, ".mdx"))
+ .sort()
+ .map((fileName) => `content/${section}/${fileName}`);
+
+ const key = section === "type-aliases" ? "typeAliases" : section;
+ result[key] = mdxFiles;
+ }
+
+ return result;
+}
+
+/**
+ * Get group name for a section, using category map or default
+ */
+function getGroupName(section, categoryMap) {
+ if (categoryMap[section]) {
+ return categoryMap[section];
+ }
+
+ return section;
+}
+
+/**
+ * Generate docs.json from template and scanned content
+ */
+function generateDocsJson(docsContent) {
+ const template = JSON.parse(fs.readFileSync(TEMPLATE_PATH, "utf-8"));
+ let categoryMap = {};
+ try {
+ categoryMap = JSON.parse(fs.readFileSync(CATEGORY_MAP_PATH, "utf-8"));
+ } catch (e) {
+ // If file doesn't exist or can't be read, return empty object
+ console.error(`Error: Category map file not found: ${CATEGORY_MAP_PATH}`);
+ }
+
+ const groups = [];
+
+ if (docsContent.functions.length > 0 && categoryMap.functions) {
+ groups.push({
+ group: getGroupName("functions", categoryMap),
+ pages: docsContent.functions,
+ });
+ }
+
+ if (docsContent.interfaces.length > 0 && categoryMap.interfaces) {
+ groups.push({
+ group: getGroupName("interfaces", categoryMap),
+ pages: docsContent.interfaces,
+ });
+ }
+
+ if (docsContent.classes.length > 0 && categoryMap.classes) {
+ groups.push({
+ group: getGroupName("classes", categoryMap),
+ pages: docsContent.classes,
+ });
+ }
+
+ if (docsContent.typeAliases.length > 0 && categoryMap["type-aliases"]) {
+ // Merge into existing group if name matches
+ const groupName = getGroupName("type-aliases", categoryMap);
+ // "type-aliases" key in categoryMap is "Modules", so groupName is "Modules".
+ const existingGroup = groups.find((g) => g.group === groupName);
+
+ if (existingGroup) {
+ existingGroup.pages.push(...docsContent.typeAliases);
+ existingGroup.pages.sort(); // Sort combined pages alphabetically
+ } else {
+ groups.push({
+ group: groupName,
+ pages: docsContent.typeAliases,
+ });
+ }
+ }
+
+ // Find or create SDK Reference tab
+ let sdkTab = template.navigation.tabs.find(
+ (tab) => tab.tab === "SDK Reference"
+ );
+ if (!sdkTab) {
+ sdkTab = { tab: "SDK Reference", groups: [] };
+ template.navigation.tabs.push(sdkTab);
+ }
+
+ sdkTab.groups = groups;
+
+ const docsJsonPath = path.join(DOCS_DIR, "docs.json");
+ fs.writeFileSync(
+ docsJsonPath,
+ JSON.stringify(template, null, 2) + "\n",
+ "utf-8"
+ );
+ console.log(`Generated docs.json`);
+}
+
+/**
+ * Copy styling.css to docs directory
+ */
+function copyStylingCss() {
+ const targetPath = path.join(DOCS_DIR, "styling.css");
+ fs.copyFileSync(STYLING_CSS_PATH, targetPath);
+ console.log(`Copied styling.css`);
+}
+
+/**
+ * Recursively process all MDX files
+ */
+function isTypeDocPath(relativePath) {
+ const normalized = relativePath.split(path.sep).join("/");
+ return (
+ normalized.startsWith("content/interfaces/") ||
+ normalized.startsWith("content/type-aliases/") ||
+ normalized.startsWith("content/classes/") ||
+ // Also check root level for when fallback processing happens
+ normalized.startsWith("interfaces/") ||
+ normalized.startsWith("type-aliases/") ||
+ normalized.startsWith("classes/")
+ );
+}
+
+/**
+ * Recursively process all MDX files
+ */
+function processAllFiles(dir, linkedTypeNames, exposedTypeNames) {
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
+
+ for (const entry of entries) {
+ const entryPath = path.join(dir, entry.name);
+
+ if (entry.isDirectory()) {
+ processAllFiles(entryPath, linkedTypeNames, exposedTypeNames);
+ } else if (
+ entry.isFile() &&
+ (entry.name.endsWith(".mdx") || entry.name.endsWith(".md"))
+ ) {
+ // Extract the type name from the file path
+ // e.g., "docs/interfaces/LoginViaEmailPasswordResponse.mdx" -> "LoginViaEmailPasswordResponse"
+ const fileName = path.basename(entryPath, path.extname(entryPath));
+ const relativePath = path.relative(DOCS_DIR, entryPath);
+ const isTypeDoc = isTypeDocPath(relativePath);
+
+ // Check if exposed. Handle renamed modules by checking reverse map.
+ // Use both the raw filename and any potential original name
+ const originalName = REVERSE_MODULE_RENAMES[fileName] || fileName;
+
+ // If it's a renamed module (e.g. "entities"), treat it as exposed if "EntitiesModule" is exposed
+ const isRenamedModule = !!REVERSE_MODULE_RENAMES[fileName];
+
+ const isExposedType =
+ !isTypeDoc ||
+ exposedTypeNames.has(originalName) ||
+ exposedTypeNames.has(fileName) ||
+ isRenamedModule;
+
+ // Remove any type doc files that are not explicitly exposed
+ if (isTypeDoc && !isExposedType) {
+ fs.unlinkSync(entryPath);
+ console.log(`Removed (not exposed): ${relativePath}`);
+ continue;
+ }
+
+ // Remove suppressed linked type files (legacy behavior) as long as they aren't exposed
+ if (linkedTypeNames.has(fileName) && !exposedTypeNames.has(fileName)) {
+ fs.unlinkSync(entryPath);
+ console.log(`Removed (suppressed): ${relativePath}`);
+ } else {
+ // Process links in the file
+ if (processLinksInFile(entryPath)) {
+ console.log(`Processed links: ${relativePath}`);
+ }
+ }
+ }
+ }
+}
+
+function loadAppendedArticlesConfig() {
+ try {
+ const content = fs.readFileSync(APPENDED_ARTICLES_PATH, "utf-8");
+ const parsed = JSON.parse(content);
+ if (parsed && typeof parsed === "object") {
+ const normalized = {};
+ for (const [host, value] of Object.entries(parsed)) {
+ if (Array.isArray(value)) {
+ normalized[host] = value;
+ } else if (typeof value === "string" && value.trim()) {
+ normalized[host] = [value];
+ }
+ }
+ return normalized;
+ }
+ } catch (e) {
+ // Missing or invalid config is not fatal; simply skip appends
+ }
+ return {};
+}
+
+function stripFrontMatter(content) {
+ if (!content.startsWith("---")) {
+ return { title: null, content: content.trimStart() };
+ }
+ const endIndex = content.indexOf("\n---", 3);
+ if (endIndex === -1) {
+ return { title: null, content: content.trimStart() };
+ }
+ const frontMatter = content.slice(0, endIndex + 4);
+ const rest = content.slice(endIndex + 4).trimStart();
+ const titleMatch = frontMatter.match(/title:\s*["']?([^"'\n]+)["']?/i);
+ return {
+ title: titleMatch ? titleMatch[1].trim() : null,
+ content: rest,
+ };
+}
+
+function removeFirstPanelBlock(content) {
+ const panelStart = content.indexOf("");
+ const panelEnd = content.indexOf("");
+ if (panelStart === -1 || panelEnd === -1 || panelEnd < panelStart) {
+ return content;
+ }
+ const before = content.slice(0, panelStart);
+ const after = content.slice(panelEnd + "".length);
+ return (before + after).trimStart();
+}
+
+function normalizeHeadings(content) {
+ const lines = content.split("\n");
+ const headingRegex = /^(#{1,6})\s+(.*)$/;
+ let minLevel = Infinity;
+ for (const line of lines) {
+ const match = line.match(headingRegex);
+ if (match) {
+ minLevel = Math.min(minLevel, match[1].length);
+ }
+ }
+ if (minLevel === Infinity) {
+ return { content: content.trim(), headings: [] };
+ }
+ const baseLevel = 2; // clamp appended content so its top-level headings render as H2
+ const headings = [];
+ const adjusted = lines.map((line) => {
+ const match = line.match(headingRegex);
+ if (!match) {
+ return line;
+ }
+ const originalLevel = match[1].length;
+ let newLevel = originalLevel - minLevel + baseLevel;
+ newLevel = Math.max(baseLevel, Math.min(6, newLevel));
+ const text = match[2].trim();
+ headings.push({ text, level: newLevel });
+ return `${"#".repeat(newLevel)} ${text}`;
+ });
+ return { content: adjusted.join("\n").trim(), headings };
+}
+
+function slugifyHeading(text) {
+ return text
+ .toLowerCase()
+ .replace(/[`~!@#$%^&*()+={}\[\]|\\:;"'<>,.?]/g, "")
+ .replace(/\s+/g, "-");
+}
+
+function ensurePanelSpacing(content) {
+ const panelRegex = /([\s\S]*?)(\n*)(<\/Panel>)/;
+ return content.replace(panelRegex, (match, body, newlineSection, closing) => {
+ const trimmedBody = body.replace(/\s+$/, "");
+ return `${trimmedBody}\n\n${closing}`;
+ });
+}
+
+function updatePanelWithHeadings(hostContent, headings) {
+ if (!PANELS_ENABLED) {
+ return hostContent;
+ }
+ if (!headings || headings.length === 0) {
+ return ensurePanelSpacing(hostContent);
+ }
+ const panelStart = hostContent.indexOf("");
+ if (panelStart === -1) {
+ return ensurePanelSpacing(hostContent);
+ }
+ const panelEnd = hostContent.indexOf("", panelStart);
+ if (panelEnd === -1) {
+ return ensurePanelSpacing(hostContent);
+ }
+ const beforePanel = hostContent.slice(0, panelStart);
+ const panelBlock = hostContent.slice(panelStart, panelEnd);
+ const afterPanel = hostContent.slice(panelEnd);
+
+ const panelLines = panelBlock.split("\n");
+ const existingSlugs = new Set();
+ const slugMatchRegex = /- \[[^\]]+\]\(#([^)]+)\)/;
+ for (const line of panelLines) {
+ const match = line.match(slugMatchRegex);
+ if (match) {
+ existingSlugs.add(match[1]);
+ }
+ }
+
+ const newEntries = [];
+ for (const heading of headings) {
+ const text = heading.text.trim();
+ if (!text) continue;
+ const slug = slugifyHeading(text);
+ if (existingSlugs.has(slug)) {
+ continue;
+ }
+ existingSlugs.add(slug);
+ newEntries.push(`- [${text}](#${slug})`);
+ }
+
+ if (newEntries.length === 0) {
+ return ensurePanelSpacing(hostContent);
+ }
+
+ const insertion =
+ (panelBlock.endsWith("\n") ? "" : "\n") + newEntries.join("\n");
+ const updatedPanelBlock = panelBlock + insertion;
+ const updatedContent = beforePanel + updatedPanelBlock + afterPanel;
+ return ensurePanelSpacing(updatedContent);
+}
+
+function prepareAppendedSection(appendPath) {
+ const rawContent = fs.readFileSync(appendPath, "utf-8");
+ const { title, content: withoutFrontMatter } = stripFrontMatter(rawContent);
+ const withoutPanel = removeFirstPanelBlock(withoutFrontMatter);
+ const { content: normalizedContent, headings } =
+ normalizeHeadings(withoutPanel);
+ const fileTitle =
+ title || path.basename(appendPath, path.extname(appendPath));
+ const sectionHeading = `## ${fileTitle.trim()}`;
+ const trimmedContent = normalizedContent ? `\n\n${normalizedContent}` : "";
+ const section = `${sectionHeading}${trimmedContent}\n`;
+ const headingList = [{ text: fileTitle.trim(), level: 2 }, ...headings];
+ return { section, headings: headingList };
+}
+
+function applyAppendedArticles(appendedArticles) {
+ const hosts = Object.keys(appendedArticles);
+ if (hosts.length === 0) {
+ return;
+ }
+
+ for (const hostKey of hosts) {
+ const appendList = appendedArticles[hostKey];
+ if (!Array.isArray(appendList) || appendList.length === 0) {
+ continue;
+ }
+
+ // Check if host was renamed
+ let effectiveHostKey = hostKey;
+ const pathParts = hostKey.split("/");
+ const hostName = pathParts[pathParts.length - 1];
+ if (MODULE_RENAMES[hostName]) {
+ pathParts[pathParts.length - 1] = MODULE_RENAMES[hostName];
+ effectiveHostKey = pathParts.join("/");
+ }
+
+ const hostPath = path.join(CONTENT_DIR, `${effectiveHostKey}.mdx`);
+ if (!fs.existsSync(hostPath)) {
+ // Try checking if it exists as .md just in case, though we standardized on .mdx
+ console.warn(
+ `Warning: Host article not found for append: ${hostKey} (checked ${effectiveHostKey}.mdx)`
+ );
+ continue;
+ }
+
+ let hostContent = fs.readFileSync(hostPath, "utf-8");
+ let combinedSections = "";
+ const collectedHeadings = PANELS_ENABLED ? [] : null;
+
+ for (const appendKey of appendList) {
+ // Check if appended file was renamed (unlikely for EntityHandler but good for consistency)
+ let effectiveAppendKey = appendKey;
+ const appendParts = appendKey.split("/");
+ const appendName = appendParts[appendParts.length - 1];
+ if (MODULE_RENAMES[appendName]) {
+ appendParts[appendParts.length - 1] = MODULE_RENAMES[appendName];
+ effectiveAppendKey = appendParts.join("/");
+ }
+
+ // Try looking in CONTENT_DIR with .mdx (default)
+ let appendPath = path.join(CONTENT_DIR, `${effectiveAppendKey}.mdx`);
+ let foundExtension = ".mdx";
+
+ if (!fs.existsSync(appendPath)) {
+ // Try .md in CONTENT_DIR
+ appendPath = path.join(CONTENT_DIR, `${effectiveAppendKey}.md`);
+ foundExtension = ".md";
+
+ if (!fs.existsSync(appendPath)) {
+ // Try looking in DOCS_DIR directly (for un-moved files)
+ // Assuming the key (e.g. interfaces/EntityHandler) is relative to DOCS_DIR too
+ appendPath = path.join(DOCS_DIR, `${effectiveAppendKey}.mdx`);
+ foundExtension = ".mdx";
+
+ if (!fs.existsSync(appendPath)) {
+ appendPath = path.join(DOCS_DIR, `${effectiveAppendKey}.md`);
+ foundExtension = ".md";
+
+ if (!fs.existsSync(appendPath)) {
+ console.warn(
+ `Warning: Appended article not found: ${appendKey} (checked content/ and docs/ roots)`
+ );
+ continue;
+ }
+ }
+ }
+ }
+
+ const { section, headings } = prepareAppendedSection(appendPath);
+ combinedSections += `\n\n${section}`;
+ if (PANELS_ENABLED && collectedHeadings) {
+ collectedHeadings.push(...headings);
+ }
+
+ try {
+ fs.unlinkSync(appendPath);
+ console.log(
+ `Appended ${effectiveAppendKey}${foundExtension} -> ${effectiveHostKey}.mdx`
+ );
+ } catch (e) {
+ console.warn(
+ `Warning: Unable to remove appended article ${effectiveAppendKey}${foundExtension}`
+ );
+ }
+ }
+
+ if (!combinedSections) {
+ continue;
+ }
+
+ hostContent = hostContent.trimEnd() + combinedSections + "\n";
+ hostContent = updatePanelWithHeadings(hostContent, collectedHeadings);
+ fs.writeFileSync(hostPath, hostContent, "utf-8");
+ }
+}
+
+function demoteNonCallableHeadings(content) {
+ const lines = content.split("\n");
+ let inFence = false;
+ let modified = false;
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i];
+ const trimmed = line.trim();
+ if (trimmed.startsWith("```")) {
+ inFence = !inFence;
+ continue;
+ }
+ if (inFence) {
+ continue;
+ }
+ if (line.startsWith("### ")) {
+ const headingText = line.slice(4).trim();
+ if (!headingText.includes("(")) {
+ lines[i] = `#### ${headingText}`;
+ modified = true;
+ }
+ }
+ }
+ return { content: lines.join("\n"), modified };
+}
+
+function applyHeadingDemotion(dir) {
+ if (!fs.existsSync(dir)) return;
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
+ for (const entry of entries) {
+ const entryPath = path.join(dir, entry.name);
+ if (entry.isDirectory()) {
+ applyHeadingDemotion(entryPath);
+ } else if (
+ entry.isFile() &&
+ (entry.name.endsWith(".mdx") || entry.name.endsWith(".md"))
+ ) {
+ const content = fs.readFileSync(entryPath, "utf-8");
+ const { content: updated, modified } = demoteNonCallableHeadings(content);
+ if (modified) {
+ fs.writeFileSync(entryPath, updated, "utf-8");
+ console.log(`Adjusted headings: ${path.relative(DOCS_DIR, entryPath)}`);
+ }
+ }
+ }
+}
+
+/**
+ * Main function
+ */
+function main() {
+ console.log("Processing TypeDoc MDX files for Mintlify...\n");
+
+ if (!fs.existsSync(DOCS_DIR)) {
+ console.error(`Error: Documentation directory not found: ${DOCS_DIR}`);
+ console.error('Please run "npm run docs:generate" first.');
+ process.exit(1);
+ }
+
+ // Get list of linked types to suppress
+ const linkedTypeNames = getLinkedTypeNames();
+ const exposedTypeNames = getTypesToExpose();
+
+ // First, perform module renames (EntitiesModule -> entities, etc.)
+ performModuleRenames(DOCS_DIR);
+
+ // Process all files (remove suppressed ones and fix links)
+ processAllFiles(DOCS_DIR, linkedTypeNames, exposedTypeNames);
+
+ // Append configured articles
+ const appendedArticles = loadAppendedArticlesConfig();
+ applyAppendedArticles(appendedArticles);
+
+ applyHeadingDemotion(DOCS_DIR);
+
+ // Clean up the linked types file
+ try {
+ if (fs.existsSync(LINKED_TYPES_FILE)) {
+ fs.unlinkSync(LINKED_TYPES_FILE);
+ }
+ } catch (e) {
+ // Ignore errors
+ }
+
+ // Scan content and generate docs.json
+ const docsContent = scanDocsContent();
+ generateDocsJson(docsContent);
+
+ // Copy styling.css
+ copyStylingCss();
+
+ console.log(`\n✓ Post-processing complete!`);
+ console.log(` Documentation directory: ${DOCS_DIR}`);
+}
+
+main();
diff --git a/scripts/mintlify-post-processing/file-processing/styling.css b/scripts/mintlify-post-processing/file-processing/styling.css
new file mode 100644
index 0000000..87bc800
--- /dev/null
+++ b/scripts/mintlify-post-processing/file-processing/styling.css
@@ -0,0 +1,128 @@
+@import url("https://fonts.googleapis.com/css2?family=Wix+Madefor+Display:wght@400..800&family=Wix+Madefor+Text:ital,wght@0,400..800;1,400..800&display=swap");
+
+/* Apply Wix Madefor Text for body text */
+body,
+.mint-container {
+ font-family: "Wix Madefor Text", sans-serif;
+ font-weight: 400;
+ font-style: normal;
+ font-optical-sizing: auto;
+}
+
+/* Apply Wix Madefor Display for headings */
+h1,
+h2,
+h3 {
+ font-family: "Wix Madefor Display", sans-serif;
+ font-weight: 600;
+ font-style: normal;
+ font-optical-sizing: auto;
+}
+
+@media (prefers-color-scheme: light) {
+ body,
+ .mint-container,
+ h1,
+ h2,
+ h3 {
+ color: #111111;
+ }
+}
+
+/* Mintlify primary navbar CTA button color override */
+.mint-navbar .mint-button-primary,
+.mint-navbar li#topbar-cta-button a > span.bg-primary-dark {
+ background-color: #ff5500 !important; /* updated brand orange */
+ color: #111111 !important;
+ font-weight: 600;
+ border: none;
+}
+
+/* If button has hover/focus/active states, ensure text stays black: */
+.mint-navbar .mint-navbarPrimaryButton:hover,
+.mint-navbar .mint-navbarPrimaryButton:focus,
+.mint-navbar .mint-navbarPrimaryButton:active,
+.mint-navbar .mint-button-primary:hover,
+.mint-navbar .mint-button-primary:focus,
+.mint-navbar .mint-button-primary:active {
+ color: #111111 !important;
+}
+
+/* Optional: Remove box-shadow on click, if present */
+.mint-navbar .mint-navbarPrimaryButton:active {
+ box-shadow: none !important;
+}
+
+/* ---- NEW: Force the Base44 button text to black ---- */
+a[href*="base44.com"] span,
+a[href*="base44.com"] .text-white,
+.mint-navbar a span.text-white {
+ color: #111111 !important;
+}
+/* Force the ">" icon in the Base44 button to orange for consistency and accessibility */
+a[href*="base44.com"] svg,
+a[href*="base44.com"] .text-white,
+a[href*="base44.com"] svg path,
+.mint-navbar a svg.text-white {
+ color: #111111 !important; /* Works if color is set by text utility */
+ fill: #111111 !important; /* Ensures SVG/path fill is overridden */
+}
+/* Restore thin chevron style for the navbar's "Base44" button arrow */
+a[href*="base44.com"] svg,
+.mint-navbar a svg {
+ color: #111111 !important;
+ fill: none !important;
+ stroke: currentColor !important;
+ stroke-width: 2px !important;
+}
+a[href*="base44.com"] path,
+.mint-navbar a svg path {
+ color: #111111 !important;
+ fill: none !important;
+ stroke: currentColor !important;
+ stroke-width: 2px !important;
+}
+/* Make the ">" icon (chevron) in Base44 navbar button thin and on-brand */
+a[href*="base44.com"] svg,
+.mint-navbar a svg {
+ color: #111111 !important;
+}
+
+a[href*="base44.com"] svg path,
+.mint-navbar a svg path {
+ color: #111111 !important;
+ fill: none !important;
+ stroke: currentColor !important;
+ stroke-width: 1.5 !important; /* set to the original */
+ stroke-linecap: round !important; /* keep the smooth end */
+}
+
+/* Optional: if you want it even thinner, try 1.2 or 1 */
+
+/* Always use Mintlify's built-in theme variables! */
+div.prose.mt-1.font-normal.text-sm.leading-6.text-gray-600.dark\:text-gray-400,
+div.prose.mt-1.font-normal.text-sm.leading-6.text-gray-600.dark\:text-gray-400
+ span,
+.card .prose,
+.card .prose span,
+.mint-card .prose,
+.mint-card .prose span {
+ color: var(--mint-text-secondary) !important;
+}
+
+/* Remove bottom border from anchor elements containing code elements */
+a:has(code) {
+ border-bottom: none !important;
+ text-decoration: none !important;
+ color: #ff8844 !important; /* light orange */
+}
+
+/* Hide nested TOC items on interface and type-alias pages */
+body:has([data-page-href*="/content/interfaces/"])
+ .toc
+ li[data-depth]:not([data-depth="1"]),
+body:has([data-page-href*="/content/type-aliases/"])
+ .toc
+ li[data-depth]:not([data-depth="1"]) {
+ display: none !important;
+}
diff --git a/scripts/mintlify-post-processing/push-to-docs-repo.js b/scripts/mintlify-post-processing/push-to-docs-repo.js
new file mode 100644
index 0000000..3eb3dc4
--- /dev/null
+++ b/scripts/mintlify-post-processing/push-to-docs-repo.js
@@ -0,0 +1,264 @@
+#!/usr/bin/env node
+
+import fs from "fs";
+import path from "path";
+import os from "os";
+import { execSync } from "child_process";
+
+console.debug = () => {}; // Disable debug logging. Comment this out to enable debug logging.
+
+const DOCS_SOURCE_PATH = path.join(import.meta.dirname, "../../docs/content");
+const TARGET_DOCS_REPO_URL = "git@github.com:base44-dev/mintlify-docs.git";
+const CATEGORY_MAP_PATH = path.join(import.meta.dirname, "./category-map.json");
+
+function parseArgs() {
+ const args = process.argv.slice(2);
+ let branch = null;
+
+ for (let i = 0; i < args.length; i++) {
+ const arg = args[i];
+
+ if (arg === "--branch" && i + 1 < args.length) {
+ branch = args[++i];
+ }
+ }
+ return { branch };
+}
+
+function scanSdkDocs(sdkDocsDir) {
+ const result = {};
+
+ // Get a list of all the subdirectories in the sdkDocsDir
+ const subdirectories = fs
+ .readdirSync(sdkDocsDir)
+ .filter((file) => fs.statSync(path.join(sdkDocsDir, file)).isDirectory());
+ console.log(`Subdirectories: ${subdirectories}`);
+
+ for (const subdirectory of subdirectories) {
+ const subdirectoryPath = path.join(sdkDocsDir, subdirectory);
+ const files = fs
+ .readdirSync(subdirectoryPath)
+ .filter((file) => file.endsWith(".mdx"));
+ result[subdirectory] = files.map((file) => path.basename(file, ".mdx"));
+ }
+ return result;
+}
+
+function updateDocsJson(repoDir, sdkFiles) {
+ const docsJsonPath = path.join(repoDir, "docs.json");
+ let categoryMap = {};
+ try {
+ categoryMap = JSON.parse(fs.readFileSync(CATEGORY_MAP_PATH, "utf8"));
+ } catch (e) {
+ console.error(`Error: Category map file not found: ${CATEGORY_MAP_PATH}`);
+ process.exit(1);
+ }
+
+ console.log(`Reading docs.json from ${docsJsonPath}...`);
+ const docsContent = fs.readFileSync(docsJsonPath, "utf8");
+ const docs = JSON.parse(docsContent);
+
+ // Find the "SDK Reference" tab
+ const sdkTabIndex = docs.navigation.tabs.findIndex(
+ (tab) => tab.tab === "SDK Reference"
+ );
+ let sdkTab = docs.navigation.tabs[sdkTabIndex];
+
+ if (sdkTabIndex === -1) {
+ console.log(
+ "Could not find 'SDK Reference' tab in docs.json. Creating it..."
+ );
+ sdkTab = {
+ tab: "SDK Reference",
+ groups: [],
+ };
+ }
+
+ // Update the groups - merge categories that map to the same group name
+ const groupMap = new Map(); // group name -> pages array
+
+ const addToGroup = (groupName, pages) => {
+ if (!groupName || pages.length === 0) return;
+ if (!groupMap.has(groupName)) {
+ groupMap.set(groupName, []);
+ }
+ groupMap.get(groupName).push(...pages);
+ };
+
+ if (sdkFiles.functions?.length > 0 && categoryMap.functions) {
+ addToGroup(
+ categoryMap.functions,
+ sdkFiles.functions.map((file) => `sdk-docs/functions/${file}`)
+ );
+ }
+
+ if (sdkFiles.interfaces?.length > 0 && categoryMap.interfaces) {
+ addToGroup(
+ categoryMap.interfaces,
+ sdkFiles.interfaces.map((file) => `sdk-docs/interfaces/${file}`)
+ );
+ }
+
+ if (sdkFiles.classes?.length > 0 && categoryMap.classes) {
+ addToGroup(
+ categoryMap.classes,
+ sdkFiles.classes.map((file) => `sdk-docs/classes/${file}`)
+ );
+ }
+
+ if (sdkFiles["type-aliases"]?.length > 0 && categoryMap["type-aliases"]) {
+ addToGroup(
+ categoryMap["type-aliases"],
+ sdkFiles["type-aliases"].map((file) => `sdk-docs/type-aliases/${file}`)
+ );
+ }
+
+ // Convert map to array of groups
+ const newGroups = Array.from(groupMap.entries()).map(
+ ([groupName, pages]) => ({
+ group: groupName,
+ pages: pages.sort(), // Sort pages alphabetically within each group
+ })
+ );
+
+ const newGroupNames = new Set(newGroups.map((group) => group.group));
+ const preservedGroups = [];
+ let insertionIndex;
+
+ for (const existingGroup of sdkTab.groups ?? []) {
+ if (newGroupNames.has(existingGroup.group)) {
+ if (insertionIndex === undefined) {
+ insertionIndex = preservedGroups.length;
+ }
+ continue;
+ }
+ preservedGroups.push(existingGroup);
+ }
+
+ const finalGroups = [...preservedGroups];
+ const targetIndex = insertionIndex ?? finalGroups.length;
+ finalGroups.splice(targetIndex, 0, ...newGroups);
+ sdkTab.groups = finalGroups;
+
+ if (sdkTabIndex === -1) {
+ docs.navigation.tabs.push(sdkTab);
+ } else {
+ docs.navigation.tabs[sdkTabIndex] = sdkTab;
+ }
+
+ console.debug(
+ `New groups for docs.json: ${JSON.stringify(newGroups, null, 2)}`
+ );
+
+ // Write updated docs.json
+ console.log(`Writing updated docs.json to ${docsJsonPath}...`);
+ fs.writeFileSync(docsJsonPath, JSON.stringify(docs, null, 2) + "\n", "utf8");
+
+ console.log("Successfully updated docs.json");
+}
+
+function main() {
+ const { branch } = parseArgs();
+ if (!branch) {
+ console.error("Error: --branch is required");
+ process.exit(1);
+ }
+
+ if (!/^[a-zA-Z0-9\-_\/]+$/.test(branch)) {
+ console.error(
+ "Error: Invalid branch name. Branch name must contain only letters, numbers, hyphens, underscores, and forward slashes."
+ );
+ process.exit(1);
+ }
+
+ console.log(`Branch: ${branch}`);
+
+ if (
+ !fs.existsSync(DOCS_SOURCE_PATH) ||
+ !fs.statSync(DOCS_SOURCE_PATH).isDirectory()
+ ) {
+ console.error(`Error: docs directory does not exist: ${DOCS_SOURCE_PATH}`);
+ process.exit(1);
+ }
+
+ let tempRepoDir;
+ try {
+ // Create temporary directory
+ tempRepoDir = fs.mkdtempSync(path.join(os.tmpdir(), "mintlify-docs-"));
+ // Clone the repository
+ console.log(`Cloning repository to ${tempRepoDir}...`);
+ execSync(`git clone ${TARGET_DOCS_REPO_URL} ${tempRepoDir}`);
+
+ // Check if the specified branch already exists remotely
+ const branchExists =
+ execSync(`git ls-remote --heads origin ${branch}`, {
+ cwd: tempRepoDir,
+ encoding: "utf8",
+ }).trim().length > 0;
+
+ if (branchExists) {
+ console.log(`Branch ${branch} already exists. Checking it out...`);
+ execSync(`git checkout -b ${branch} origin/${branch}`, {
+ cwd: tempRepoDir,
+ });
+ } else {
+ console.log(`Branch ${branch} does not exist. Creating it...`);
+ execSync(`git checkout -b ${branch}`, { cwd: tempRepoDir });
+ }
+
+ // Remove the existing sdk-docs directory
+ fs.rmSync(path.join(tempRepoDir, "sdk-docs"), {
+ recursive: true,
+ force: true,
+ });
+
+ // Copy the docs directory to the temporary repository
+ fs.cpSync(DOCS_SOURCE_PATH, path.join(tempRepoDir, "sdk-docs"), {
+ recursive: true,
+ });
+
+ // Scan the sdk-docs directory
+ const sdkDocsDir = path.join(tempRepoDir, "sdk-docs");
+ const sdkFiles = scanSdkDocs(sdkDocsDir);
+
+ console.debug(`SDK files: ${JSON.stringify(sdkFiles, null, 2)}`);
+
+ // Update the docs.json file
+ updateDocsJson(tempRepoDir, sdkFiles);
+
+ // Commit the changes
+ execSync(`git add docs.json`, { cwd: tempRepoDir });
+ execSync(`git add sdk-docs`, { cwd: tempRepoDir });
+
+ const stagedOutput = execSync(`git diff --cached --name-only`, {
+ cwd: tempRepoDir,
+ encoding: "utf8",
+ });
+
+ const stagedChanges = stagedOutput.trim();
+
+ if (!stagedChanges.length) {
+ console.log(
+ "No staged changes detected (docs.json / sdk-docs). Skipping commit and push."
+ );
+ return;
+ }
+
+ console.log(`Changes staged for commit:\n${stagedChanges}`);
+
+ execSync(`git commit -m "Auto-updates to SDK Reference Docs"`, {
+ cwd: tempRepoDir,
+ });
+ execSync(`git push --set-upstream origin ${branch}`, { cwd: tempRepoDir });
+
+ console.log("Successfully committed and pushed the changes");
+ } catch (e) {
+ console.error(`Error: Failed to commit and push changes: ${e}`);
+ process.exit(1);
+ } finally {
+ // Remove the temporary directory
+ fs.rmSync(tempRepoDir, { recursive: true, force: true });
+ }
+}
+
+main();
diff --git a/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-content.js b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-content.js
new file mode 100644
index 0000000..6bf1e0a
--- /dev/null
+++ b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-content.js
@@ -0,0 +1,124 @@
+/**
+ * Content transformation functions (examples, frontmatter, etc.)
+ */
+
+/**
+ * Add headings to CodeGroups that don't have them
+ */
+export function addHeadingsToCodeGroups(content) {
+ const lines = content.split('\n');
+ const result = [];
+
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i];
+
+ // Check if this line contains
+ if (line.trim() === '' || line.includes('')) {
+ // Look back up to 3 lines to see if there's a heading
+ let hasHeading = false;
+ for (let j = Math.max(0, i - 3); j < i; j++) {
+ const prevLine = lines[j].trim();
+ if (/^#{2,4}\s+/.test(prevLine)) {
+ hasHeading = true;
+ break;
+ }
+ }
+
+ // If no heading found, add one
+ if (!hasHeading) {
+ result.push('## Examples');
+ result.push('');
+ }
+ }
+
+ result.push(line);
+ }
+
+ return result.join('\n');
+}
+
+/**
+ * Convert code examples to Mintlify CodeGroup
+ */
+export function convertExamplesToCodeGroup(content) {
+ // Match Example/Examples headings from level 2-4 and capture their content until next section
+ const exampleSectionRegex = /^(#{2,4})\s+(Example|Examples)\s*$([\s\S]*?)(?=^#{2,4}\s|\n<\/ResponseField>|\n\*\*\*|$(?!\n))/gm;
+
+ return content.replace(exampleSectionRegex, (match, headingLevel, exampleHeading, exampleContent) => {
+ const codeBlockRegex = /```([\w-]*)\s*([^\n]*)\n([\s\S]*?)```/g;
+ const examples = [];
+ let codeMatch;
+
+ while ((codeMatch = codeBlockRegex.exec(exampleContent)) !== null) {
+ const language = codeMatch[1] || 'typescript';
+ const titleFromCodeFence = codeMatch[2].trim();
+ const code = codeMatch[3].trimEnd();
+
+ let title;
+ if (titleFromCodeFence && titleFromCodeFence.length > 0 && titleFromCodeFence.length < 100) {
+ // Strip comment markers from title (e.g., "// Basic example" -> "Basic example")
+ title = titleFromCodeFence.replace(/^\/\/\s*/, '').replace(/^\/\*\s*|\s*\*\/$/g, '').trim();
+ } else {
+ title = examples.length === 0 ? 'Example' : `Example ${examples.length + 1}`;
+ }
+
+ examples.push({
+ title,
+ language,
+ code,
+ });
+ }
+
+ if (examples.length === 0) {
+ return match;
+ }
+
+ // Use the original heading level, default to ## if not specified
+ const headingPrefix = headingLevel || '##';
+ // Use "Examples" if multiple examples, otherwise "Example"
+ const headingText = examples.length > 1 ? 'Examples' : 'Example';
+
+ let codeGroup = `${headingPrefix} ${headingText}\n\n\n\n`;
+
+ for (const example of examples) {
+ codeGroup += '```' + example.language + ' ' + example.title + '\n';
+ codeGroup += example.code + '\n';
+ codeGroup += '```\n\n';
+ }
+
+ codeGroup += '\n';
+
+ return codeGroup;
+ });
+}
+
+/**
+ * Add Mintlify frontmatter to the page
+ */
+export function addMintlifyFrontmatter(content, page) {
+ const titleMatch = content.match(/^#\s+(.+)$/m);
+ let title = titleMatch ? titleMatch[1].trim() : page?.model?.name || 'Documentation';
+
+ // Clean up title
+ title = title.replace(/\*\*/g, '').replace(/`/g, '').trim();
+ title = title.replace(/^(?:Interface|Class|Type|Module|Function|Variable|Constant|Enum):\s*/i, '').trim();
+
+ const escapeYaml = (str) => {
+ if (str.includes(':') || str.includes('"') || str.includes("'") || str.includes('\n')) {
+ return str.replace(/"/g, '\\"');
+ }
+ return str;
+ };
+
+ const frontmatter = `---
+title: "${escapeYaml(title)}"
+---
+
+`;
+
+ // Remove the original h1 title (it's now in frontmatter)
+ const processedContent = content.replace(/^#\s+.+\n\n?/, '');
+
+ return frontmatter + processedContent;
+}
+
diff --git a/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-linked-types.js b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-linked-types.js
new file mode 100644
index 0000000..5c3958d
--- /dev/null
+++ b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-linked-types.js
@@ -0,0 +1,862 @@
+/**
+ * Linked type extraction and property parsing functions
+ */
+
+import * as fs from "fs";
+import * as path from "path";
+import { ReflectionKind } from "typedoc";
+
+const TYPES_TO_EXPOSE_PATH = path.resolve(
+ process.cwd(),
+ "scripts/mintlify-post-processing/types-to-expose.json"
+);
+let exposedTypeNames = null;
+try {
+ const raw = fs.readFileSync(TYPES_TO_EXPOSE_PATH, "utf-8");
+ const parsed = JSON.parse(raw);
+ if (Array.isArray(parsed)) {
+ exposedTypeNames = new Set(parsed);
+ }
+} catch (err) {
+ // Ignore; fall back to linking based on path existence
+ exposedTypeNames = null;
+}
+
+const PROPERTY_KINDS = new Set([
+ ReflectionKind.Property,
+ ReflectionKind.PropertySignature,
+]);
+
+const PRIMITIVE_REFERENCES = new Set([
+ "any",
+ "string",
+ "number",
+ "boolean",
+ "void",
+ "null",
+ "undefined",
+ "object",
+ "Array",
+ "Promise",
+ "Record",
+ "Map",
+ "Set",
+ "Date",
+]);
+
+const KIND_DIRECTORY_MAP = {
+ [ReflectionKind.Class]: "classes",
+ [ReflectionKind.Interface]: "interfaces",
+ [ReflectionKind.TypeAlias]: "type-aliases",
+};
+
+function resolveTypePath(typeName, context, targetKind = null) {
+ if (!context?.app || !typeName) {
+ return null;
+ }
+
+ if (exposedTypeNames && !exposedTypeNames.has(typeName)) {
+ return null;
+ }
+
+ const { app, currentPagePath } = context;
+ const outputDir = app.options.getValue("out") || "docs";
+
+ const directory = KIND_DIRECTORY_MAP[targetKind] || "interfaces";
+ const filePath = path.join(outputDir, directory, `${typeName}.mdx`);
+
+ if (currentPagePath) {
+ const currentDir = path.dirname(path.join(outputDir, currentPagePath));
+ const relativePath = path
+ .relative(currentDir, filePath)
+ .replace(/\\/g, "/");
+ return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
+ }
+
+ return path.relative(outputDir, filePath).replace(/\\/g, "/");
+}
+
+/**
+ * Extract properties from a linked type using TypeDoc's reflection API
+ * Returns { properties: [], indexSignature: null } or just properties array for backward compatibility
+ */
+export function extractPropertiesFromLinkedType(
+ linkedTypeInfo,
+ context,
+ visited = new Set(),
+ options = {}
+) {
+ const emptyResult = options.includeIndexSignature
+ ? { properties: [], indexSignature: null }
+ : [];
+
+ if (!linkedTypeInfo || !context) {
+ return emptyResult;
+ }
+
+ const { typeName } = linkedTypeInfo;
+ const visitKey = typeName;
+
+ if (!typeName || visited.has(visitKey)) {
+ return emptyResult;
+ }
+
+ visited.add(visitKey);
+
+ try {
+ // First, try to get the type from TypeDoc's reflection API
+ const {
+ properties: reflectionProps,
+ description: reflectionDescription,
+ indexSignature,
+ } = extractPropertiesFromReflection(typeName, context, visited);
+ if (reflectionProps.length > 0 || indexSignature) {
+ if (reflectionDescription && linkedTypeInfo) {
+ linkedTypeInfo.description = reflectionDescription;
+ }
+ if (options.includeIndexSignature) {
+ return { properties: reflectionProps, indexSignature };
+ }
+ return reflectionProps;
+ }
+
+ // Fallback: try to read from generated markdown file
+ const {
+ properties: markdownProps,
+ description: markdownDescription,
+ indexSignature: mdIndexSig,
+ } = extractPropertiesFromMarkdownFile(linkedTypeInfo, context);
+ if (markdownDescription && linkedTypeInfo) {
+ linkedTypeInfo.description = markdownDescription;
+ }
+ if (options.includeIndexSignature) {
+ return { properties: markdownProps, indexSignature: mdIndexSig || null };
+ }
+ return markdownProps;
+ } catch (error) {
+ console.warn(
+ `Error extracting properties for type ${typeName}:`,
+ error.message
+ );
+ return emptyResult;
+ } finally {
+ visited.delete(visitKey);
+ }
+}
+
+export function getLinkedTypeDescription(linkedTypeInfo, context) {
+ if (!linkedTypeInfo || !context) {
+ return "";
+ }
+ if (linkedTypeInfo.description) {
+ return linkedTypeInfo.description;
+ }
+
+ const { typeName } = linkedTypeInfo;
+ if (!typeName) {
+ return "";
+ }
+
+ try {
+ const project =
+ context.page?.model?.project || context.app?.converter?.project;
+ if (project) {
+ const reflection = findReflectionByName(project, typeName);
+ if (reflection) {
+ const description = getCommentSummary(reflection, context);
+ if (description) {
+ linkedTypeInfo.description = description;
+ return description;
+ }
+ }
+ }
+ } catch {
+ // ignore reflection lookup issues
+ }
+
+ try {
+ const { description } = extractPropertiesFromMarkdownFile(
+ linkedTypeInfo,
+ context
+ );
+ if (description) {
+ linkedTypeInfo.description = description;
+ return description;
+ }
+ } catch {
+ // ignore markdown fallback issues
+ }
+
+ return "";
+}
+
+/**
+ * Extract properties from TypeDoc's reflection API (preferred method)
+ */
+function extractPropertiesFromReflection(typeName, context, visited) {
+ if (!context) {
+ return { properties: [], description: "", indexSignature: null };
+ }
+
+ const { app, page } = context;
+
+ try {
+ // Access the project through the page's model
+ const project = page?.model?.project || app?.converter?.project;
+ if (!project) {
+ return { properties: [], description: "", indexSignature: null };
+ }
+
+ // Find the type reflection in the project
+ const typeReflection = findReflectionByName(project, typeName);
+ if (!typeReflection) {
+ return { properties: [], description: "", indexSignature: null };
+ }
+
+ // Extract properties from the reflection
+ const properties = [];
+ const propertyNodes = getPropertyNodesFromReflection(typeReflection);
+
+ for (const child of propertyNodes) {
+ const property = buildPropertyFromReflection(child, context, visited);
+ if (property) {
+ properties.push(property);
+ }
+ }
+
+ // Extract index signature if present
+ const indexSignature = extractIndexSignature(typeReflection, context);
+
+ const description = getCommentSummary(typeReflection, context);
+ return { properties, description, indexSignature };
+ } catch (error) {
+ console.warn(
+ `Error extracting properties from reflection for ${typeName}:`,
+ error.message
+ );
+ return { properties: [], description: "", indexSignature: null };
+ }
+}
+
+/**
+ * Extract index signature from a reflection (e.g., [key: string]: any)
+ */
+function extractIndexSignature(reflection, context) {
+ if (!reflection) {
+ return null;
+ }
+
+ // Check for indexSignatures array on the reflection
+ const indexSigs = reflection.indexSignatures || reflection.indexSignature;
+ if (!indexSigs) {
+ return null;
+ }
+
+ const sigArray = Array.isArray(indexSigs) ? indexSigs : [indexSigs];
+ if (sigArray.length === 0) {
+ return null;
+ }
+
+ // Get the first index signature
+ const sig = sigArray[0];
+ if (!sig) {
+ return null;
+ }
+
+ // Extract key type (usually string)
+ let keyType = "string";
+ if (sig.parameters && sig.parameters.length > 0) {
+ const keyParam = sig.parameters[0];
+ keyType = getTypeString(keyParam.type) || "string";
+ }
+
+ // Extract value type
+ const valueType = getTypeString(sig.type) || "any";
+
+ // Extract description from comment
+ const description = getCommentSummary(sig, context) || "";
+
+ return {
+ keyType,
+ valueType,
+ description,
+ };
+}
+
+/**
+ * Find a reflection by name in the project
+ */
+function findReflectionByName(reflection, name) {
+ if (reflection.name === name) {
+ return reflection;
+ }
+
+ if (reflection.children) {
+ for (const child of reflection.children) {
+ const found = findReflectionByName(child, name);
+ if (found) return found;
+ }
+ }
+
+ return null;
+}
+
+/**
+ * Get a string representation of a type
+ */
+function getTypeString(type) {
+ if (!type) return "any";
+
+ switch (type.type) {
+ case "intrinsic":
+ return type.name;
+ case "reference":
+ return formatReferenceType(type);
+ case "array":
+ return `${getTypeString(type.elementType)}[]`;
+ case "union":
+ return type.types?.map((t) => getTypeString(t)).join(" | ") || "any";
+ case "intersection":
+ return type.types?.map((t) => getTypeString(t)).join(" & ") || "any";
+ case "literal":
+ return JSON.stringify(type.value);
+ case "reflection": {
+ // Check if this is a function type (has call signatures)
+ const decl = type.declaration;
+ if (decl?.signatures?.length > 0) {
+ const sig = decl.signatures[0];
+ const params =
+ sig.parameters
+ ?.map((p) => `${p.name}: ${getTypeString(p.type)}`)
+ .join(", ") || "";
+ const returnType = getTypeString(sig.type) || "void";
+ return `(${params}) => ${returnType}`;
+ }
+ // Otherwise it's an object type
+ return "object";
+ }
+ default:
+ return type.name || "any";
+ }
+}
+
+/**
+ * Check if a property is optional
+ */
+function isOptional(child) {
+ return child.flags?.isOptional || false;
+}
+
+/**
+ * Check if a type is object-like (has properties)
+ */
+function isObjectLikeType(type) {
+ return type?.type === "reflection" && type.declaration?.children;
+}
+
+/**
+ * Extract nested properties from an object type
+ */
+function extractNestedPropertiesFromReflectionType(type, context, visited) {
+ if (!isObjectLikeType(type)) {
+ return [];
+ }
+
+ const nested = [];
+ if (type.declaration?.children) {
+ for (const child of type.declaration.children) {
+ const property = buildPropertyFromReflection(child, context, visited);
+ if (property) {
+ nested.push(property);
+ }
+ }
+ }
+
+ return nested;
+}
+
+/**
+ * Fallback: Extract properties from a linked type's markdown file
+ */
+function extractPropertiesFromMarkdownFile(linkedTypeInfo, context) {
+ const { typePath, typeName } = linkedTypeInfo;
+ const { currentPagePath, app } = context;
+
+ if (!app || !app.options) {
+ return { properties: [], description: "" };
+ }
+
+ try {
+ // Get the output directory from TypeDoc (usually 'docs')
+ const outputDir = app.options.getValue("out") || "docs";
+
+ // Convert relative link to file path
+ // Links can be:
+ // - Just the type name: "LoginViaEmailPasswordResponse"
+ // - Relative path: "../interfaces/LoginViaEmailPasswordResponse" or "./interfaces/LoginViaEmailPasswordResponse"
+ // - Absolute-looking: "interfaces/LoginViaEmailPasswordResponse"
+ let filePath;
+
+ // Remove .md or .mdx extension if present
+ let cleanTypePath = typePath.replace(/\.(md|mdx)$/, "");
+
+ if (cleanTypePath.startsWith("../") || cleanTypePath.startsWith("./")) {
+ // Relative path - resolve from current page's directory
+ const currentDir = path.dirname(
+ path.join(outputDir, currentPagePath || "")
+ );
+ const basePath = path.resolve(currentDir, cleanTypePath);
+
+ // Try .mdx first, then .md
+ if (!basePath.endsWith(".md") && !basePath.endsWith(".mdx")) {
+ const mdxPath = basePath + ".mdx";
+ const mdPath = basePath + ".md";
+ filePath = fs.existsSync(mdxPath) ? mdxPath : mdPath;
+ } else {
+ filePath = basePath;
+ }
+ } else if (cleanTypePath.includes("/")) {
+ // Path with directory separator
+ filePath = path.join(outputDir, cleanTypePath);
+
+ // Try .mdx first, then .md
+ if (!filePath.endsWith(".md") && !filePath.endsWith(".mdx")) {
+ const mdxPath = filePath + ".mdx";
+ const mdPath = filePath + ".md";
+ filePath = fs.existsSync(mdxPath) ? mdxPath : mdPath;
+ }
+ } else {
+ // Just the type name - try interfaces/ first, then type-aliases/
+ // Try .mdx first, then .md
+ filePath = path.join(outputDir, "interfaces", cleanTypePath + ".mdx");
+ if (!fs.existsSync(filePath)) {
+ filePath = path.join(outputDir, "interfaces", cleanTypePath + ".md");
+ }
+ if (!fs.existsSync(filePath)) {
+ filePath = path.join(outputDir, "type-aliases", cleanTypePath + ".mdx");
+ }
+ if (!fs.existsSync(filePath)) {
+ filePath = path.join(outputDir, "type-aliases", cleanTypePath + ".md");
+ }
+ }
+
+ // Normalize the path
+ filePath = path.normalize(filePath);
+
+ // Check if file exists
+ if (!fs.existsSync(filePath)) {
+ // Don't warn during generation - the file might not exist yet
+ return { properties: [], description: "" };
+ }
+
+ const content = fs.readFileSync(filePath, "utf-8");
+ return parsePropertiesFromTypeFile(content);
+ } catch (error) {
+ // Silent failure during generation
+ return { properties: [], description: "" };
+ }
+}
+
+/**
+ * Parse properties from a type file's markdown content
+ */
+function parsePropertiesFromTypeFile(content) {
+ const properties = [];
+ const lines = content.split("\n");
+
+ // Collect intro description until Properties section
+ const introLines = [];
+ let descriptionCaptured = false;
+
+ // Extract Indexable section if present
+ const indexSignature = parseIndexableSection(content);
+
+ // Find the Properties section
+ let inPropertiesSection = false;
+ let i = 0;
+
+ while (i < lines.length) {
+ const line = lines[i];
+
+ // Start of Properties section
+ if (line.match(/^##\s+Properties\s*$/)) {
+ inPropertiesSection = true;
+ i++;
+ continue;
+ }
+
+ if (!inPropertiesSection) {
+ if (line.trim()) {
+ introLines.push(line);
+ descriptionCaptured = true;
+ } else if (descriptionCaptured) {
+ introLines.push("");
+ }
+ }
+
+ // Stop at next top-level heading (##)
+ if (
+ inPropertiesSection &&
+ line.match(/^##\s+/) &&
+ !line.match(/^##\s+Properties\s*$/)
+ ) {
+ break;
+ }
+
+ // Parse property: ### propertyName or ### propertyName?
+ if (inPropertiesSection && line.match(/^###\s+/)) {
+ const propMatch = line.match(/^###\s+(.+)$/);
+ if (propMatch) {
+ const rawName = propMatch[1].trim();
+ const optional = rawName.endsWith("?");
+ // Unescape markdown escapes (e.g., access\_token -> access_token)
+ let name = optional ? rawName.slice(0, -1).trim() : rawName.trim();
+ name = name
+ .replace(/\\_/g, "_")
+ .replace(/\\\*/g, "*")
+ .replace(/\\`/g, "`");
+
+ i++;
+ // Skip blank lines
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ // Get type from next line: > **name**: `type` or > `optional` **name**: `type`
+ let type = "any";
+ if (i < lines.length && lines[i].includes("`")) {
+ const typeMatch = lines[i].match(/`([^`]+)`/);
+ if (typeMatch) {
+ type = typeMatch[1].trim();
+ }
+ i++;
+ }
+
+ // Skip blank lines
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ // Collect description and nested properties
+ const descriptionLines = [];
+ const nested = [];
+
+ // Look for nested properties (#### heading)
+ while (i < lines.length) {
+ const nextLine = lines[i];
+ // Stop at next property (###) or section end (## or ***)
+ if (
+ nextLine.match(/^###\s+/) ||
+ nextLine.match(/^##\s+/) ||
+ nextLine === "***"
+ ) {
+ break;
+ }
+
+ // Check for nested property (####)
+ if (nextLine.match(/^####\s+/)) {
+ const nestedMatch = nextLine.match(/^####\s+(.+)$/);
+ if (nestedMatch) {
+ const nestedRawName = nestedMatch[1].trim();
+ const nestedOptional = nestedRawName.endsWith("?");
+ // Unescape markdown escapes
+ let nestedName = nestedOptional
+ ? nestedRawName.slice(0, -1).trim()
+ : nestedRawName.trim();
+ nestedName = nestedName
+ .replace(/\\_/g, "_")
+ .replace(/\\\*/g, "*")
+ .replace(/\\`/g, "`");
+
+ i++;
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ let nestedType = "any";
+ if (i < lines.length && lines[i].includes("`")) {
+ const nestedTypeMatch = lines[i].match(/`([^`]+)`/);
+ if (nestedTypeMatch) {
+ nestedType = nestedTypeMatch[1].trim();
+ }
+ i++;
+ }
+
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ const nestedDescLines = [];
+ while (
+ i < lines.length &&
+ !lines[i].match(/^####\s+/) &&
+ !lines[i].match(/^###\s+/) &&
+ !lines[i].match(/^##\s+/) &&
+ lines[i] !== "***"
+ ) {
+ nestedDescLines.push(lines[i]);
+ i++;
+ }
+
+ nested.push({
+ name: nestedName,
+ type: nestedType,
+ description: nestedDescLines.join("\n").trim(),
+ optional: nestedOptional,
+ });
+ continue;
+ }
+ }
+
+ descriptionLines.push(nextLine);
+ i++;
+ }
+
+ properties.push({
+ name,
+ type,
+ description: descriptionLines.join("\n").trim(),
+ optional,
+ nested,
+ });
+ continue;
+ }
+ }
+
+ i++;
+ }
+
+ const description = introLines.join("\n").trim();
+ return { properties, description, indexSignature };
+}
+
+/**
+ * Parse the Indexable section from markdown content
+ * TypeDoc generates: ## Indexable\n\n\\[`key`: `string`\\]: `valueType`\n\nDescription
+ */
+function parseIndexableSection(content) {
+ const indexableMatch = content.match(
+ /##\s+Indexable\s*\n+([^\n]+)\n*([\s\S]*?)(?=\n##|\n\*\*\*|$)/i
+ );
+ if (!indexableMatch) {
+ return null;
+ }
+
+ // Parse the signature line: \[`key`: `string`\]: `valueType` or [`key`: `string`]: `valueType`
+ const signatureLine = indexableMatch[1].trim();
+ const description = (indexableMatch[2] || "").trim();
+
+ // Extract key type and value type from the signature
+ // Pattern: \[`keyName`: `keyType`\]: `valueType` or similar
+ const sigMatch = signatureLine.match(
+ /\[`?(\w+)`?\s*:\s*`?(\w+)`?\s*\]\s*:\s*`?([^`\n]+)`?/
+ );
+ if (!sigMatch) {
+ // Try simpler pattern
+ const simpleMatch = signatureLine.match(/`(\w+)`/g);
+ if (simpleMatch && simpleMatch.length >= 2) {
+ return {
+ keyType: simpleMatch[0].replace(/`/g, ""),
+ valueType: simpleMatch[simpleMatch.length - 1].replace(/`/g, ""),
+ description,
+ };
+ }
+ return null;
+ }
+
+ return {
+ keyType: sigMatch[2] || "string",
+ valueType: sigMatch[3] || "any",
+ description,
+ };
+}
+
+function buildPropertyFromReflection(child, context, visited) {
+ if (!child || !PROPERTY_KINDS.has(child.kind)) {
+ return null;
+ }
+
+ const property = {
+ name: child.name,
+ type: getTypeString(child.type),
+ description: getCommentSummary(child, context),
+ optional: isOptional(child),
+ nested: [],
+ };
+
+ const nestedFromType = extractNestedPropertiesFromType(
+ child.type,
+ context,
+ visited
+ );
+ if (nestedFromType.length > 0) {
+ property.nested = nestedFromType;
+ }
+
+ return property;
+}
+
+function getPropertyNodesFromReflection(reflection) {
+ if (!reflection) {
+ return [];
+ }
+
+ if (Array.isArray(reflection.children) && reflection.children.length > 0) {
+ return reflection.children;
+ }
+
+ if (reflection.type?.declaration?.children?.length) {
+ return reflection.type.declaration.children;
+ }
+
+ if (reflection.declaration?.children?.length) {
+ return reflection.declaration.children;
+ }
+
+ return [];
+}
+
+function extractNestedPropertiesFromType(type, context, visited) {
+ if (!type) {
+ return [];
+ }
+
+ switch (type.type) {
+ case "reference": {
+ const referencedName = getReferenceTypeName(type);
+ if (!referencedName || PRIMITIVE_REFERENCES.has(referencedName)) {
+ return [];
+ }
+ return extractPropertiesFromLinkedType(
+ { typeName: referencedName, typePath: referencedName },
+ context,
+ visited
+ );
+ }
+ case "array":
+ return extractNestedPropertiesFromType(
+ type.elementType,
+ context,
+ visited
+ );
+ case "union":
+ case "intersection": {
+ if (!Array.isArray(type.types)) {
+ return [];
+ }
+ for (const subType of type.types) {
+ const nested = extractNestedPropertiesFromType(
+ subType,
+ context,
+ visited
+ );
+ if (nested.length > 0) {
+ return nested;
+ }
+ }
+ return [];
+ }
+ case "reflection":
+ return extractNestedPropertiesFromReflectionType(type, context, visited);
+ default:
+ return [];
+ }
+}
+
+function getReferenceTypeName(type) {
+ if (!type) {
+ return null;
+ }
+
+ if (typeof type.name === "string" && type.name) {
+ return type.name;
+ }
+
+ if (typeof type.qualifiedName === "string" && type.qualifiedName) {
+ const segments = type.qualifiedName.split(".");
+ return segments[segments.length - 1];
+ }
+
+ if (type.reflection?.name) {
+ return type.reflection.name;
+ }
+
+ return null;
+}
+
+function getCommentSummary(reflection, context) {
+ if (!reflection?.comment) {
+ return "";
+ }
+
+ const parts = [];
+ if (Array.isArray(reflection.comment.summary)) {
+ parts.push(...reflection.comment.summary);
+ }
+ if (reflection.comment.blockTags) {
+ for (const tag of reflection.comment.blockTags) {
+ if (tag.tag === "@remarks" && Array.isArray(tag.content)) {
+ parts.push(...tag.content);
+ }
+ if (
+ (tag.tag === "@see" ||
+ tag.tag === "@link" ||
+ tag.tag === "@linkcode" ||
+ tag.tag === "@returns") &&
+ Array.isArray(tag.content)
+ ) {
+ parts.push(...tag.content);
+ }
+ }
+ }
+
+ if (parts.length === 0) {
+ return "";
+ }
+
+ return parts.map((part) => renderCommentPart(part, context)).join("") || "";
+}
+
+function renderCommentPart(part, context) {
+ if (!part) {
+ return "";
+ }
+
+ switch (part.kind) {
+ case "text":
+ return part.text || "";
+ case "code":
+ return part.text ? `\`${part.text}\`` : "";
+ case "inline-tag":
+ if (part.tag === "@link") {
+ const linkText = (part.text || part.target?.name || "").trim();
+ const typeName = part.target?.name || null;
+ const linkTarget = typeName
+ ? resolveTypePath(typeName, context, part.target?.kind)
+ : null;
+ if (linkTarget && linkText) {
+ return `[${linkText}](${linkTarget})`;
+ }
+ if (linkText) {
+ return linkText;
+ }
+ return typeName || "";
+ }
+ return part.text || "";
+ default:
+ return part.text || "";
+ }
+}
+
+function formatReferenceType(type) {
+ if (!type) {
+ return "any";
+ }
+
+ let typeName = type.name || "any";
+ if (type.typeArguments && type.typeArguments.length > 0) {
+ const args = type.typeArguments.map((arg) => getTypeString(arg)).join(", ");
+ typeName += `<${args}>`;
+ }
+ return typeName;
+}
diff --git a/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-parameters.js b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-parameters.js
new file mode 100644
index 0000000..a5388be
--- /dev/null
+++ b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-parameters.js
@@ -0,0 +1,1008 @@
+/**
+ * Parameter conversion functions for TypeDoc Mintlify plugin
+ */
+
+import { escapeAttribute } from "./typedoc-mintlify-utils.js";
+import { extractPropertiesFromLinkedType } from "./typedoc-mintlify-linked-types.js";
+import * as fs from "fs";
+import * as path from "path";
+
+const PRIMITIVE_TYPES = [
+ "any",
+ "string",
+ "number",
+ "boolean",
+ "void",
+ "null",
+ "undefined",
+ "object",
+ "Array",
+ "Promise",
+];
+const WRAPPER_TYPE_NAMES = new Set([
+ "Partial",
+ "Required",
+ "Readonly",
+ "Omit",
+ "Pick",
+]);
+
+// Helper function to resolve type paths (similar to returns file)
+function resolveTypePath(typeName, app, currentPagePath = null) {
+ // Skip primitive types
+ if (PRIMITIVE_TYPES.includes(typeName)) {
+ return null;
+ }
+
+ if (!app || !app.options) {
+ return null;
+ }
+
+ const outputDir = app.options.getValue("out") || "docs";
+
+ // Try interfaces/ first, then type-aliases/
+ let filePath = path.join(outputDir, "interfaces", typeName + ".mdx");
+ if (!fs.existsSync(filePath)) {
+ filePath = path.join(outputDir, "interfaces", typeName + ".md");
+ }
+ if (!fs.existsSync(filePath)) {
+ filePath = path.join(outputDir, "type-aliases", typeName + ".mdx");
+ }
+ if (!fs.existsSync(filePath)) {
+ filePath = path.join(outputDir, "type-aliases", typeName + ".md");
+ }
+
+ if (fs.existsSync(filePath)) {
+ // Convert to relative path from current page if possible
+ if (currentPagePath) {
+ const currentDir = path.dirname(path.join(outputDir, currentPagePath));
+ const relativePath = path
+ .relative(currentDir, filePath)
+ .replace(/\\/g, "/");
+ return relativePath.startsWith(".") ? relativePath : "./" + relativePath;
+ }
+ // Otherwise return path relative to outputDir
+ return path.relative(outputDir, filePath).replace(/\\/g, "/");
+ }
+
+ return null;
+}
+
+/**
+ * Convert top-level function parameters (## Parameters with ### param names)
+ */
+export function convertFunctionParameters(
+ content,
+ app = null,
+ page = null,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ // Split content by ## headings to isolate the Parameters section
+ const sections = content.split(/\n(?=##\s+\w)/);
+
+ return sections
+ .map((section) => {
+ // Only process ## Parameters sections (must start with exactly ##, not ###)
+ if (!section.match(/^##\s+Parameters\s*$/m)) {
+ return section;
+ }
+
+ // Extract the content after "## Parameters"
+ const lines = section.split("\n");
+ const paramStartIdx = lines.findIndex((l) =>
+ l.match(/^##\s+Parameters\s*$/)
+ );
+
+ if (paramStartIdx === -1) return section;
+
+ // Get everything after "## Parameters" line
+ const paramLines = lines.slice(paramStartIdx + 1);
+ const paramContent = paramLines.join("\n");
+
+ // Parse parameters with context for linked type resolution
+ const context =
+ app && page ? { app, page, currentPagePath: page.url } : null;
+ const params = parseParametersWithExpansion(
+ paramContent,
+ "###",
+ "####",
+ context,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+
+ if (params.length === 0) return section;
+
+ // Rebuild section with ParamFields
+ const beforeParams = lines.slice(0, paramStartIdx + 1).join("\n");
+ return (
+ beforeParams +
+ "\n\n" +
+ buildParamFieldsSection(params, linkedTypeNames, writeLinkedTypesFile)
+ );
+ })
+ .join("\n");
+}
+
+/**
+ * Convert interface method parameters (#### Parameters with ##### param names)
+ */
+export function convertInterfaceMethodParameters(
+ content,
+ app = null,
+ page = null,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ const context = app && page ? { app, page, currentPagePath: page.url } : null;
+ return rewriteParameterSections(
+ content,
+ "#### Parameters",
+ "#####",
+ "######",
+ context,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+}
+
+/**
+ * Convert class method parameters (#### Parameters with ##### param names)
+ */
+export function convertClassMethodParameters(
+ content,
+ app = null,
+ page = null,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ const context = app && page ? { app, page, currentPagePath: page.url } : null;
+ return rewriteParameterSections(
+ content,
+ "#### Parameters",
+ "#####",
+ "######",
+ context,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+}
+
+function rewriteParameterSections(
+ content,
+ sectionHeading,
+ paramLevel,
+ nestedLevel,
+ context = null,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ const lines = content.split("\n");
+ const result = [];
+ let i = 0;
+
+ const isTerminatorLine = (line) => {
+ return (
+ line.startsWith("#### Returns") ||
+ line.startsWith("#### Example") ||
+ line === "***" ||
+ line.startsWith("### ") ||
+ line.startsWith("## ")
+ );
+ };
+
+ while (i < lines.length) {
+ const line = lines[i];
+ if (line.startsWith(sectionHeading)) {
+ result.push(line);
+ i++;
+ const sectionStart = i;
+ while (i < lines.length && !isTerminatorLine(lines[i])) {
+ i++;
+ }
+ const sectionContentLines = lines.slice(sectionStart, i);
+ const sectionContent = sectionContentLines.join("\n").trim();
+ // Use parseParametersWithExpansion if context is available, otherwise use parseParameters
+ const params = context
+ ? parseParametersWithExpansion(
+ sectionContent,
+ paramLevel,
+ nestedLevel,
+ context,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ )
+ : parseParameters(
+ sectionContent,
+ paramLevel,
+ nestedLevel,
+ context,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+ if (params.length > 0) {
+ const block = buildParamFieldsSection(
+ params,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ ).trim();
+ if (block) {
+ result.push("");
+ result.push(...block.split("\n"));
+ result.push("");
+ }
+ } else {
+ result.push(...sectionContentLines);
+ }
+ continue;
+ }
+
+ result.push(line);
+ i++;
+ }
+
+ return result.join("\n");
+}
+
+/**
+ * Parse parameters with type expansion (for functions)
+ */
+function parseParametersWithExpansion(
+ paramContent,
+ paramLevel,
+ nestedLevel,
+ context = null,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ const lines = paramContent.split("\n");
+ const params = [];
+
+ const isParamHeading = (line) => line.startsWith(paramLevel + " ");
+ const isNestedHeading = nestedLevel
+ ? (line) => line.startsWith(nestedLevel + " ")
+ : () => false;
+ const isTerminator = (line) => {
+ const trimmed = line.trim();
+ if (!trimmed) return false;
+ if (
+ trimmed.startsWith("#### Returns") ||
+ trimmed.startsWith("#### Example") ||
+ trimmed === "***"
+ ) {
+ return true;
+ }
+ const nestedPrefix = nestedLevel ? nestedLevel + " " : null;
+ if (/^#{1,3}\s+/.test(trimmed)) {
+ if (
+ !trimmed.startsWith(paramLevel + " ") &&
+ !(nestedPrefix && trimmed.startsWith(nestedPrefix))
+ ) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ const extractType = (line) => {
+ if (!line) return null;
+ const trimmed = line.trim();
+
+ // Handle [`TypeName`](link) format first (backticks inside the link)
+ const linkWithBackticksMatch = trimmed.match(/^\[`([^`]+)`\]\(([^)]+)\)$/);
+ if (linkWithBackticksMatch) {
+ return {
+ type: linkWithBackticksMatch[1],
+ link: linkWithBackticksMatch[2],
+ };
+ }
+
+ // Handle [TypeName](link) format
+ const linkMatch = trimmed.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
+ if (linkMatch) {
+ return { type: linkMatch[1], link: linkMatch[2] };
+ }
+
+ // Handle simple `TypeName` format
+ const simpleMatch = trimmed.match(/^`([^`]+)`$/);
+ if (simpleMatch) {
+ return { type: simpleMatch[1], link: null };
+ }
+
+ // Handle function type format: (`param`) => `returnType` or (`param`: `Type`) => `returnType`
+ // e.g., (`conversation`) => `void` or (`error`: `Error`) => `void`
+ if (trimmed.startsWith("(") && trimmed.includes("=>")) {
+ const sanitized = trimmed
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1") // Remove markdown links
+ .replace(/`/g, "") // Remove backticks
+ .replace(/\\/g, "") // Remove escapes
+ .replace(/\s+/g, " ") // Normalize whitespace
+ .trim();
+ if (sanitized) {
+ return { type: sanitized, link: null };
+ }
+ }
+
+ // Fallback: sanitize markdown-heavy type definitions such as `Partial`<[`Type`](link)>
+ if (trimmed.startsWith("`")) {
+ const sanitized = trimmed
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1")
+ .replace(/`/g, "")
+ .replace(/\\/g, "")
+ .replace(/\s+/g, " ")
+ .trim();
+ if (sanitized) {
+ return { type: sanitized, link: null };
+ }
+ }
+
+ return null;
+ };
+
+ let i = 0;
+ while (i < lines.length) {
+ const line = lines[i];
+ if (!isParamHeading(line)) {
+ i++;
+ continue;
+ }
+
+ let rawName = line.slice(paramLevel.length).trim();
+ const optional = rawName.endsWith("?");
+ const cleanName = optional ? rawName.slice(0, -1).trim() : rawName.trim();
+ i++;
+
+ // Skip blank lines
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ let type = "any";
+ let typeLink = null;
+ if (i < lines.length) {
+ const maybeType = extractType(lines[i]);
+ if (maybeType) {
+ if (typeof maybeType === "object") {
+ type = maybeType.type;
+ typeLink = maybeType.link;
+ } else {
+ type = maybeType;
+ }
+ i++;
+ }
+ }
+
+ // Skip blank lines after type
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ // Check if the next line has an array indicator (...[])
+ if (i < lines.length && lines[i].trim() === "...[]") {
+ // If type is still 'any' (default), it means no type was specified
+ // TypeDoc-Markdown sometimes omits the type line for arrays
+ // Default to 'string' as the base type in this case
+ if (type === "any") {
+ type = "string[]";
+ } else {
+ type = type + "[]";
+ }
+ i++; // Skip the array indicator line
+
+ // Skip blank lines after array indicator
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+ }
+
+ const descriptionLines = [];
+ while (
+ i < lines.length &&
+ !isParamHeading(lines[i]) &&
+ !isNestedHeading(lines[i]) &&
+ !isTerminator(lines[i])
+ ) {
+ descriptionLines.push(lines[i]);
+ i++;
+ }
+
+ // Check if we should expand this type inline
+ let linkedTypeInfo = getLinkedTypeInfo(type, typeLink, context);
+ let nested = [];
+
+ // Track linked types for suppression (for types with explicit links)
+
+ // Try to extract properties from the linked type
+ if (linkedTypeInfo && context) {
+ const properties = extractPropertiesFromLinkedType(
+ linkedTypeInfo,
+ context
+ );
+ if (properties.length > 0) {
+ nested = normalizePropertiesForParams(properties);
+ }
+ }
+
+ // If no linked properties were found, check for manually specified nested fields
+ if (nested.length === 0) {
+ while (i < lines.length && isNestedHeading(lines[i])) {
+ let nestedRawName = lines[i].slice(nestedLevel.length).trim();
+ const nestedOptional = nestedRawName.endsWith("?");
+ const nestedName = nestedOptional
+ ? nestedRawName.slice(0, -1).trim()
+ : nestedRawName.trim();
+ i++;
+
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ let nestedType = "any";
+ let nestedTypeLink = null;
+ if (i < lines.length) {
+ const maybeNestedType = extractType(lines[i]);
+ if (maybeNestedType) {
+ if (typeof maybeNestedType === "object") {
+ nestedType = maybeNestedType.type;
+ nestedTypeLink = maybeNestedType.link;
+ } else {
+ nestedType = maybeNestedType;
+ }
+ i++;
+ }
+ }
+
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ // Check if the next line has an array indicator (...[])
+ if (i < lines.length && lines[i].trim() === "...[]") {
+ // If type is still 'any' (default), it means no type was specified
+ // TypeDoc-Markdown sometimes omits the type line for arrays
+ // Default to 'string' as the base type in this case
+ if (nestedType === "any") {
+ nestedType = "string[]";
+ } else {
+ nestedType = nestedType + "[]";
+ }
+ i++; // Skip the array indicator line
+
+ // Skip blank lines after array indicator
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+ }
+
+ const nestedDescLines = [];
+ while (
+ i < lines.length &&
+ !isNestedHeading(lines[i]) &&
+ !isParamHeading(lines[i]) &&
+ !isTerminator(lines[i])
+ ) {
+ nestedDescLines.push(lines[i]);
+ i++;
+ }
+
+ const nestedField = {
+ name: nestedName,
+ type: nestedType,
+ description: nestedDescLines.join("\n").trim(),
+ optional: nestedOptional,
+ nested: [],
+ };
+
+ if (nestedField.nested.length === 0) {
+ const nestedLinkedInfo = getLinkedTypeInfo(
+ nestedType,
+ nestedTypeLink,
+ context
+ );
+ if (nestedLinkedInfo && context) {
+ const nestedProps = extractPropertiesFromLinkedType(
+ nestedLinkedInfo,
+ context
+ );
+ if (nestedProps.length > 0) {
+ nestedField.nested = normalizePropertiesForParams(nestedProps);
+ }
+ }
+ }
+
+ nested.push(nestedField);
+ }
+ }
+
+ params.push({
+ name: cleanName,
+ type: type,
+ description: descriptionLines.join("\n").trim(),
+ optional,
+ nested,
+ });
+ }
+
+ return params;
+}
+
+/**
+ * Parse parameters from markdown content (for interface/class methods - no expansion)
+ */
+function parseParameters(
+ paramContent,
+ paramLevel,
+ nestedLevel,
+ context = null,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ const lines = paramContent.split("\n");
+ const params = [];
+
+ const isParamHeading = (line) => line.startsWith(paramLevel + " ");
+ const isNestedHeading = nestedLevel
+ ? (line) => line.startsWith(nestedLevel + " ")
+ : () => false;
+ const isTerminator = (line) => {
+ const trimmed = line.trim();
+ if (!trimmed) return false;
+ if (
+ trimmed.startsWith("#### Returns") ||
+ trimmed.startsWith("#### Example") ||
+ trimmed === "***"
+ ) {
+ return true;
+ }
+ const nestedPrefix = nestedLevel ? nestedLevel + " " : null;
+ if (/^#{1,3}\s+/.test(trimmed)) {
+ if (
+ !trimmed.startsWith(paramLevel + " ") &&
+ !(nestedPrefix && trimmed.startsWith(nestedPrefix))
+ ) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ const extractType = (line) => {
+ if (!line) return null;
+ const trimmed = line.trim();
+
+ // Handle [`TypeName`](link) format first (backticks inside the link)
+ const linkWithBackticksMatch = trimmed.match(/^\[`([^`]+)`\]\(([^)]+)\)$/);
+ if (linkWithBackticksMatch) {
+ return {
+ type: linkWithBackticksMatch[1],
+ link: linkWithBackticksMatch[2],
+ };
+ }
+
+ // Handle [TypeName](link) format
+ const linkMatch = trimmed.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
+ if (linkMatch) {
+ return { type: linkMatch[1], link: linkMatch[2] };
+ }
+
+ // Handle simple `TypeName` format
+ const simpleMatch = trimmed.match(/^`([^`]+)`$/);
+ if (simpleMatch) {
+ return { type: simpleMatch[1], link: null };
+ }
+
+ // Handle function type format: (`param`) => `returnType` or (`param`: `Type`) => `returnType`
+ // e.g., (`conversation`) => `void` or (`error`: `Error`) => `void`
+ if (trimmed.startsWith("(") && trimmed.includes("=>")) {
+ const sanitized = trimmed
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1") // Remove markdown links
+ .replace(/`/g, "") // Remove backticks
+ .replace(/\\/g, "") // Remove escapes
+ .replace(/\s+/g, " ") // Normalize whitespace
+ .trim();
+ if (sanitized) {
+ return { type: sanitized, link: null };
+ }
+ }
+
+ // Fallback: sanitize markdown-heavy type definitions such as `Partial`<[`Type`](link)>
+ if (trimmed.startsWith("`")) {
+ const sanitized = trimmed
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1")
+ .replace(/`/g, "")
+ .replace(/\\/g, "")
+ .replace(/\s+/g, " ")
+ .trim();
+ if (sanitized) {
+ return { type: sanitized, link: null };
+ }
+ }
+
+ return null;
+ };
+
+ let i = 0;
+ while (i < lines.length) {
+ const line = lines[i];
+ if (!isParamHeading(line)) {
+ i++;
+ continue;
+ }
+
+ let rawName = line.slice(paramLevel.length).trim();
+ const optional = rawName.endsWith("?");
+ const cleanName = optional ? rawName.slice(0, -1).trim() : rawName.trim();
+ i++;
+
+ // Skip blank lines
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ let type = "any";
+ let typeLink = null;
+ if (i < lines.length) {
+ const maybeType = extractType(lines[i]);
+ if (maybeType) {
+ if (typeof maybeType === "object") {
+ type = maybeType.type;
+ typeLink = maybeType.link;
+ } else {
+ type = maybeType;
+ }
+ i++;
+ }
+ }
+
+ // Skip blank lines after type
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ // Check if the next line has an array indicator (...[])
+ if (i < lines.length && lines[i].trim() === "...[]") {
+ // If type is still 'any' (default), it means no type was specified
+ // TypeDoc-Markdown sometimes omits the type line for arrays
+ // Default to 'string' as the base type in this case
+ if (type === "any") {
+ type = "string[]";
+ } else {
+ type = type + "[]";
+ }
+ i++; // Skip the array indicator line
+
+ // Skip blank lines after array indicator
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+ }
+
+ const descriptionLines = [];
+ while (
+ i < lines.length &&
+ !isParamHeading(lines[i]) &&
+ !isNestedHeading(lines[i]) &&
+ !isTerminator(lines[i])
+ ) {
+ descriptionLines.push(lines[i]);
+ i++;
+ }
+
+ // Check if we should expand this type inline
+ const linkedTypeInfo = getLinkedTypeInfo(type, typeLink, context);
+ let nested = [];
+
+ // Try to extract properties from the linked type
+ if (linkedTypeInfo && context) {
+ const properties = extractPropertiesFromLinkedType(
+ linkedTypeInfo,
+ context
+ );
+ if (properties.length > 0) {
+ nested = normalizePropertiesForParams(properties);
+ // Keep the type as the original type name (without expanding to 'object')
+ // This preserves the type name in the ParamField
+ }
+ }
+
+ // If no linked properties were found, check for manually specified nested fields
+ if (nested.length === 0) {
+ while (i < lines.length && isNestedHeading(lines[i])) {
+ let nestedRawName = lines[i].slice(nestedLevel.length).trim();
+ const nestedOptional = nestedRawName.endsWith("?");
+ const nestedName = nestedOptional
+ ? nestedRawName.slice(0, -1).trim()
+ : nestedRawName.trim();
+ i++;
+
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ let nestedType = "any";
+ let nestedTypeLink = null;
+ if (i < lines.length) {
+ const maybeNestedType = extractType(lines[i]);
+ if (maybeNestedType) {
+ if (typeof maybeNestedType === "object") {
+ nestedType = maybeNestedType.type;
+ nestedTypeLink = maybeNestedType.link;
+ } else {
+ nestedType = maybeNestedType;
+ }
+ i++;
+ }
+ }
+
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+
+ // Check if the next line has an array indicator (...[])
+ if (i < lines.length && lines[i].trim() === "...[]") {
+ // If type is still 'any' (default), it means no type was specified
+ // TypeDoc-Markdown sometimes omits the type line for arrays
+ // Default to 'string' as the base type in this case
+ if (nestedType === "any") {
+ nestedType = "string[]";
+ } else {
+ nestedType = nestedType + "[]";
+ }
+ i++; // Skip the array indicator line
+
+ // Skip blank lines after array indicator
+ while (i < lines.length && lines[i].trim() === "") {
+ i++;
+ }
+ }
+
+ const nestedDescLines = [];
+ while (
+ i < lines.length &&
+ !isNestedHeading(lines[i]) &&
+ !isParamHeading(lines[i]) &&
+ !isTerminator(lines[i])
+ ) {
+ nestedDescLines.push(lines[i]);
+ i++;
+ }
+
+ const nestedField = {
+ name: nestedName,
+ type: nestedType,
+ description: nestedDescLines.join("\n").trim(),
+ optional: nestedOptional,
+ nested: [],
+ };
+
+ if (nestedField.nested.length === 0) {
+ const nestedLinkedInfo = getLinkedTypeInfo(
+ nestedType,
+ nestedTypeLink,
+ context
+ );
+ if (nestedLinkedInfo && context) {
+ const nestedProps = extractPropertiesFromLinkedType(
+ nestedLinkedInfo,
+ context
+ );
+ if (nestedProps.length > 0) {
+ nestedField.nested = normalizePropertiesForParams(nestedProps);
+ }
+ }
+ }
+
+ nested.push(nestedField);
+ }
+ }
+
+ params.push({
+ name: cleanName,
+ type: nested.length > 0 ? type : type, // Keep original type name
+ description: descriptionLines.join("\n").trim(),
+ optional,
+ nested,
+ });
+ }
+
+ return params;
+}
+
+/**
+ * Build ParamField components from parsed parameters
+ */
+function buildParamFieldsSection(
+ params,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ if (!params || params.length === 0) {
+ return "";
+ }
+
+ let fieldsOutput = "";
+
+ for (const param of params) {
+ const requiredAttr = param.optional ? "" : " required";
+
+ // Track non-primitive parameter types for suppression
+
+ fieldsOutput += `\n`;
+
+ // Always show description in ParamField if it exists
+ if (param.description) {
+ fieldsOutput += `\n${param.description}\n`;
+ }
+
+ fieldsOutput += "\n\n";
+
+ // If param has nested fields, wrap them in an Accordion
+ if (param.nested.length > 0) {
+ // Accordion title is always "Properties"
+ fieldsOutput += `\n\n\n`;
+
+ fieldsOutput += renderNestedParamFields(param.nested);
+
+ fieldsOutput += "\n\n";
+ } else {
+ fieldsOutput += "\n";
+ }
+ }
+
+ // Wrap multiple parameters in an Accordion (but not single parameters, even if they have nested fields)
+ const hasMultipleParams = params.length > 1;
+
+ if (hasMultipleParams) {
+ return `\n\n${fieldsOutput.trim()}\n`;
+ }
+
+ return fieldsOutput;
+}
+
+function renderNestedParamFields(fields) {
+ if (!fields || fields.length === 0) {
+ return "";
+ }
+
+ let output = "";
+ for (const field of fields) {
+ const requiredAttr = field.optional ? "" : " required";
+ output += `\n`;
+
+ if (field.description) {
+ output += `\n${field.description}\n`;
+ }
+
+ if (Array.isArray(field.nested) && field.nested.length > 0) {
+ output += `\n\n\n`;
+ output += renderNestedParamFields(field.nested);
+ output += "\n";
+ }
+
+ output += "\n\n\n";
+ }
+
+ return output;
+}
+
+function getLinkedTypeInfo(typeName, typeLink, context) {
+ if (!typeName) {
+ return null;
+ }
+
+ if (typeLink) {
+ const simpleFromLink = simplifyTypeName(typeName) || typeName;
+ return { typeName: simpleFromLink, typePath: typeLink };
+ }
+
+ if (!context) {
+ return null;
+ }
+
+ const simpleTypeName = simplifyTypeName(typeName);
+ if (!simpleTypeName || PRIMITIVE_TYPES.includes(simpleTypeName)) {
+ return null;
+ }
+
+ const typePath = resolveTypePath(
+ simpleTypeName,
+ context.app,
+ context.currentPagePath
+ );
+ return { typeName: simpleTypeName, typePath: typePath || simpleTypeName };
+}
+
+function simplifyTypeName(typeName) {
+ if (!typeName) {
+ return null;
+ }
+
+ let cleaned = typeName.trim();
+
+ // Unwrap helper types like Partial, Required, etc.
+ cleaned = unwrapHelperType(cleaned);
+
+ // Remove generics/array indicators and take the first union/intersection entry
+ cleaned = cleaned
+ .replace(/[\[\]]/g, "")
+ .split("|")[0]
+ .split("&")[0]
+ .trim();
+ return cleaned.replace(/<.*?>/g, "").trim();
+}
+
+function unwrapHelperType(typeName) {
+ let current = typeName.trim();
+ let changed = true;
+
+ while (changed) {
+ changed = false;
+ const match = current.match(/^([A-Za-z0-9_]+)\s*<(.+)>$/);
+ if (!match) {
+ break;
+ }
+
+ const wrapperName = match[1];
+ if (!WRAPPER_TYPE_NAMES.has(wrapperName)) {
+ break;
+ }
+
+ const genericBlock = match[2];
+ const inner = getFirstGenericArgument(genericBlock);
+ if (!inner) {
+ break;
+ }
+
+ current = inner.trim();
+ changed = true;
+ }
+
+ return current;
+}
+
+function getFirstGenericArgument(genericBlock) {
+ if (!genericBlock) {
+ return "";
+ }
+
+ let depth = 0;
+ let buffer = "";
+ for (let i = 0; i < genericBlock.length; i++) {
+ const char = genericBlock[i];
+ if (char === "<") {
+ depth++;
+ buffer += char;
+ continue;
+ }
+ if (char === ">") {
+ if (depth > 0) {
+ depth--;
+ }
+ buffer += char;
+ continue;
+ }
+ if (char === "," && depth === 0) {
+ return buffer.trim();
+ }
+ buffer += char;
+ }
+
+ return buffer.trim();
+}
+
+function normalizePropertiesForParams(properties) {
+ if (!Array.isArray(properties)) {
+ return [];
+ }
+
+ return properties.map((prop) => ({
+ name: prop.name,
+ type: prop.type || "any",
+ description: prop.description || "",
+ optional: !!prop.optional,
+ nested: normalizePropertiesForParams(prop.nested || []),
+ }));
+}
diff --git a/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-plugin.js b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-plugin.js
new file mode 100644
index 0000000..966c4a3
--- /dev/null
+++ b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-plugin.js
@@ -0,0 +1,260 @@
+/**
+ * TypeDoc plugin for Mintlify MDX output
+ * Hooks into TypeDoc's markdown renderer to customize output for Mintlify
+ */
+
+import { MarkdownPageEvent } from "typedoc-plugin-markdown";
+import { ReflectionKind, RendererEvent } from "typedoc";
+import * as fs from "fs";
+import * as path from "path";
+import {
+ convertFunctionParameters,
+ convertInterfaceMethodParameters,
+ convertClassMethodParameters,
+} from "./typedoc-mintlify-parameters.js";
+import {
+ convertFunctionReturns,
+ convertInterfaceMethodReturns,
+ convertClassMethodReturns,
+} from "./typedoc-mintlify-returns.js";
+import {
+ convertExamplesToCodeGroup,
+ addMintlifyFrontmatter,
+ addHeadingsToCodeGroups,
+} from "./typedoc-mintlify-content.js";
+
+// Shared flag with the post-processing script so Panel output can be toggled.
+const PANELS_ENABLED = process.env.MINTLIFY_INCLUDE_PANELS === "true";
+
+/**
+ * Plugin load function called by TypeDoc
+ */
+// Track interfaces that are linked types and should be suppressed
+const linkedTypeNames = new Set();
+
+/**
+ * Load function called by TypeDoc
+ */
+export function load(app) {
+ console.log("Loading Mintlify TypeDoc plugin...");
+
+ app.renderer.on(MarkdownPageEvent.END, (page) => {
+ if (!page.contents) return;
+
+ let content = page.contents;
+
+ // Determine what kind of page this is.
+ const isFunction = page.model?.kind === ReflectionKind.Function;
+ const isClass = page.model?.kind === ReflectionKind.Class;
+ const isInterface = page.model?.kind === ReflectionKind.Interface;
+
+ // 1. Remove breadcrumbs navigation
+ content = content.replace(/^\[.*?\]\(.*?\)\s*\n+/m, "");
+
+ // 2. Convert parameters to ParamField components and returns to ResponseField components
+ // Functions: ## Parameters/Returns with ### field names
+ // Interface methods: #### Parameters/Returns with ##### field names
+ // Class methods: #### Parameters/Returns with ##### field names
+ const writeLinkedTypesFile = createWriteLinkedTypesFile(app);
+
+ if (isFunction) {
+ content = convertFunctionParameters(
+ content,
+ app,
+ page,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+ content = convertFunctionReturns(
+ content,
+ app,
+ page,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+ } else if (isInterface) {
+ content = convertInterfaceMethodParameters(content, app, page);
+ content = convertInterfaceMethodReturns(
+ content,
+ app,
+ page,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+ } else if (isClass) {
+ content = convertClassMethodParameters(content, app, page);
+ content = convertClassMethodReturns(
+ content,
+ app,
+ page,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+ }
+
+ // 3. Convert code examples to CodeGroup
+ content = convertExamplesToCodeGroup(content);
+
+ // 3a. Add headings to CodeGroups that don't have them
+ content = addHeadingsToCodeGroups(content);
+
+ // 4. Remove auto-generated type links from signatures (keep manual doc links)
+ content = stripAutoGeneratedTypeLinks(content);
+
+ // 5. Remove .md and .mdx extensions from links
+ content = content.replace(/\[([^\]]+)\]\(([^)]+)\.mdx?\)/g, "[$1]($2)");
+
+ // 6. Add on-page navigation panel
+ content = addOnThisPagePanel(content, page);
+
+ // 7. Add frontmatter
+ content = addMintlifyFrontmatter(content, page);
+
+ // 8. Fix escaped characters in type signatures that shouldn't be escaped in MDX
+ content = fixEscapedTypeCharacters(content);
+
+ page.contents = content;
+ });
+
+ // Write linked types file once at the end of all processing
+ app.renderer.on(MarkdownPageEvent.END, () => {
+ // This will run after all pages are processed
+ // We'll write the file in a different event
+ });
+
+ // Write linked types file after all pages are processed
+ app.renderer.on(RendererEvent.END, () => {
+ const writeLinkedTypesFile = createWriteLinkedTypesFile(app);
+ writeLinkedTypesFile();
+ });
+}
+
+/**
+ * Write linked types file
+ */
+function createWriteLinkedTypesFile(app) {
+ return () => {
+ if (!app || !app.options) {
+ return;
+ }
+ const outputDir = app.options.getValue("out") || "docs";
+ const resolvedOutputDir = path.resolve(outputDir);
+ const linkedTypesFile = path.join(resolvedOutputDir, ".linked-types.json");
+ try {
+ // Ensure content directory exists
+ if (!fs.existsSync(resolvedOutputDir)) {
+ fs.mkdirSync(resolvedOutputDir, { recursive: true });
+ }
+ fs.writeFileSync(
+ linkedTypesFile,
+ JSON.stringify(Array.from(linkedTypeNames)),
+ "utf-8"
+ );
+ } catch (e) {
+ // Ignore errors writing the file
+ console.warn("Warning: Could not write linked types file:", e.message);
+ }
+ };
+}
+
+/**
+ * Insert a Mintlify Panel with links to method headings (###) for type docs
+ */
+function addOnThisPagePanel(content, page) {
+ if (!PANELS_ENABLED) {
+ return content;
+ }
+ const links = getPanelLinksForPage(page, content);
+ if (!links || links.length === 0) {
+ return content;
+ }
+ if (content.includes(' **On this page**')) {
+ return content;
+ }
+
+ const panelLines = [
+ "",
+ "",
+ ' **On this page**',
+ "",
+ ...links.map(({ heading, anchor }) => `- [${heading}](#${anchor})`),
+ "",
+ "",
+ "",
+ ];
+
+ const panelBlock = panelLines.join("\n");
+ const firstSectionIndex = content.indexOf("\n## ");
+ if (firstSectionIndex === -1) {
+ return `${content}\n\n${panelBlock}`;
+ }
+ const insertionPoint = firstSectionIndex + 1;
+ return `${content.slice(0, insertionPoint)}${panelBlock}${content.slice(
+ insertionPoint
+ )}`;
+}
+
+function getPanelLinksForPage(page, content) {
+ if (!page?.model || !page.url) {
+ return null;
+ }
+ if (isTypeDoc(page)) {
+ return extractHeadings(content, /^###\s+(.+?)\s*$/gm);
+ }
+ if (isFunctionDoc(page)) {
+ return extractHeadings(content, /^##\s+(.+?)\s*$/gm);
+ }
+ return null;
+}
+
+function isTypeDoc(page) {
+ const allowedKinds = new Set([
+ ReflectionKind.Interface,
+ ReflectionKind.Class,
+ ]);
+ return (
+ allowedKinds.has(page.model.kind) &&
+ (page.url.startsWith("interfaces/") || page.url.startsWith("classes/"))
+ );
+}
+
+function isFunctionDoc(page) {
+ return (
+ page.model.kind === ReflectionKind.Function &&
+ page.url.startsWith("functions/")
+ );
+}
+
+function extractHeadings(content, regex) {
+ const headings = [];
+ let match;
+ while ((match = regex.exec(content)) !== null) {
+ const heading = match[1].trim();
+ if (!heading) {
+ continue;
+ }
+ headings.push({ heading, anchor: slugifyHeading(heading) });
+ }
+ return headings;
+}
+
+function slugifyHeading(text) {
+ return text
+ .toLowerCase()
+ .replace(/[`~!@#$%^&*()+={}\[\]|\\:;"'<>,.?]/g, "")
+ .replace(/\s+/g, "-");
+}
+
+function stripAutoGeneratedTypeLinks(content) {
+ return content.replace(/^>\s*\*\*.*$/gm, (line) => {
+ const withoutCodeLinks = line.replace(/\[`([^`]+)`\]\([^)]+\)/g, "`$1`");
+ return withoutCodeLinks.replace(/\[([A-Za-z0-9_.]+)\]\(([^)]+)\)/g, "$1");
+ });
+}
+
+function fixEscapedTypeCharacters(content) {
+ // Fix escaped pipes - TypeDoc escapes | as \| in the output
+ // This is visible in the rendered Mintlify pages
+ // Simply replace all instances of \| with | in the entire content
+ return content.replace(/\\\|/g, "|");
+}
diff --git a/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-returns.js b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-returns.js
new file mode 100644
index 0000000..38e1374
--- /dev/null
+++ b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-returns.js
@@ -0,0 +1,1161 @@
+/**
+ * Return/Response field conversion functions for TypeDoc Mintlify plugin
+ */
+
+import * as fs from "fs";
+import * as path from "path";
+import {
+ extractPropertiesFromLinkedType,
+ getLinkedTypeDescription,
+} from "./typedoc-mintlify-linked-types.js";
+import { escapeAttribute } from "./typedoc-mintlify-utils.js";
+
+const PRIMITIVE_TYPES = [
+ "any",
+ "string",
+ "number",
+ "boolean",
+ "void",
+ "null",
+ "undefined",
+ "object",
+ "Array",
+ "Promise",
+];
+
+function extractReturnsDescription(page) {
+ if (!page?.model) {
+ return "";
+ }
+
+ const signature =
+ Array.isArray(page.model.signatures) && page.model.signatures.length > 0
+ ? page.model.signatures[0]
+ : null;
+
+ const returnsTag = signature?.comment?.blockTags?.find(
+ (tag) => tag.tag === "@returns" || tag.tag === "@return"
+ );
+
+ if (!returnsTag || !returnsTag.content) {
+ return "";
+ }
+
+ return renderCommentParts(returnsTag.content).trim();
+}
+
+function renderCommentParts(parts) {
+ if (!Array.isArray(parts)) {
+ return "";
+ }
+
+ return parts
+ .map((part) => {
+ if (!part) return "";
+ switch (part.kind) {
+ case "text":
+ return part.text || "";
+ case "code":
+ return part.text ? "`" + part.text + "`" : "";
+ case "inline-tag":
+ if (part.tag === "@link") {
+ return (part.text || part.target?.name || "").trim();
+ }
+ return part.text || "";
+ default:
+ return part.text || "";
+ }
+ })
+ .join("");
+}
+
+/**
+ * Extract signature information from content lines
+ */
+/**
+ * Try to resolve a type name to a documentation file path
+ */
+function resolveTypePath(typeName, app, currentPagePath = null) {
+ // Skip primitive types
+ if (PRIMITIVE_TYPES.includes(typeName)) {
+ return null;
+ }
+
+ if (!app || !app.options) {
+ return null;
+ }
+
+ const outputDir = app.options.getValue("out") || "docs";
+
+ // Try interfaces/ first, then type-aliases/
+ let filePath = path.join(outputDir, "interfaces", typeName + ".mdx");
+ if (!fs.existsSync(filePath)) {
+ filePath = path.join(outputDir, "interfaces", typeName + ".md");
+ }
+ if (!fs.existsSync(filePath)) {
+ filePath = path.join(outputDir, "type-aliases", typeName + ".mdx");
+ }
+ if (!fs.existsSync(filePath)) {
+ filePath = path.join(outputDir, "type-aliases", typeName + ".md");
+ }
+
+ if (fs.existsSync(filePath)) {
+ // Convert to relative path from current page if possible
+ if (currentPagePath) {
+ const currentDir = path.dirname(path.join(outputDir, currentPagePath));
+ const relativePath = path
+ .relative(currentDir, filePath)
+ .replace(/\\/g, "/");
+ return relativePath.startsWith(".") ? relativePath : "./" + relativePath;
+ }
+ // Otherwise return path relative to outputDir
+ return path.relative(outputDir, filePath).replace(/\\/g, "/");
+ }
+
+ return null;
+}
+
+export function extractSignatureInfo(
+ lines,
+ linkedTypeNames,
+ writeLinkedTypesFile,
+ app,
+ currentPagePath = null
+) {
+ const signatureMap = new Map();
+ const linkedTypeMap = new Map();
+
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i];
+ // Match function signature: > **methodName**(...): `returnType` or `returnType`\<`generic`\>
+ // Handle both simple types and generic types like `Promise`\<`any`\> or `Promise`\<[`TypeName`](link)\>
+ const sigMatch = line.match(
+ /^>\s*\*\*(\w+)\*\*\([^)]*\):\s*`([^`]+)`(?:\\<(.+?)\\>)?/
+ );
+ if (sigMatch) {
+ const methodName = sigMatch[1];
+ let returnType = sigMatch[2];
+ const genericParam = sigMatch[3];
+
+ // Check if generic parameter is a markdown link: [`TypeName`](link)
+ if (genericParam) {
+ const linkMatch = genericParam.match(/\[`([^`]+)`\]\(([^)]+)\)/);
+ if (linkMatch) {
+ const linkedTypeName = linkMatch[1];
+ const linkedTypePath = linkMatch[2];
+ returnType = `${returnType}<${linkedTypeName}>`;
+ linkedTypeMap.set(i, {
+ typeName: linkedTypeName,
+ typePath: linkedTypePath,
+ });
+ // Track this type name so we can suppress its documentation page
+ if (linkedTypeNames) {
+ linkedTypeNames.add(linkedTypeName);
+ if (writeLinkedTypesFile) writeLinkedTypesFile();
+ }
+ } else {
+ // Simple generic type without link - try to resolve it
+ const simpleGeneric = genericParam.replace(/`/g, "").trim();
+ returnType = `${returnType}<${simpleGeneric}>`;
+
+ // Try to resolve the type to a documentation file
+ const typePath = resolveTypePath(simpleGeneric, app, currentPagePath);
+ if (typePath) {
+ linkedTypeMap.set(i, {
+ typeName: simpleGeneric,
+ typePath: typePath,
+ });
+ if (linkedTypeNames) {
+ linkedTypeNames.add(simpleGeneric);
+ if (writeLinkedTypesFile) writeLinkedTypesFile();
+ }
+ }
+ }
+ }
+ // Store the return type with the signature line index as the key
+ signatureMap.set(i, returnType);
+
+ // If we don't already have linked type info (e.g., non-generic return),
+ // try to resolve the return type to a documentation file
+ if (!linkedTypeMap.has(i)) {
+ const simpleTypeName = getSimpleTypeName(returnType);
+ if (simpleTypeName && !PRIMITIVE_TYPES.includes(simpleTypeName)) {
+ let typePath = resolveTypePath(simpleTypeName, app, currentPagePath);
+ if (!typePath) {
+ // Fallback to the raw type name so downstream parsing can still attempt resolution
+ typePath = simpleTypeName;
+ }
+ linkedTypeMap.set(i, { typeName: simpleTypeName, typePath });
+ if (linkedTypeNames) {
+ linkedTypeNames.add(simpleTypeName);
+ if (writeLinkedTypesFile) writeLinkedTypesFile();
+ }
+ }
+ }
+ }
+ }
+
+ return { signatureMap, linkedTypeMap };
+}
+
+/**
+ * Convert function returns
+ */
+export function convertFunctionReturns(
+ content,
+ app,
+ page,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ // For functions, we need to extract signature info with linked types
+ const lines = content.split("\n");
+ // Use provided linkedTypeNames Set or create a local one
+ const localLinkedTypeNames = linkedTypeNames || new Set();
+ const localWriteLinkedTypesFile = writeLinkedTypesFile || (() => {});
+ const { signatureMap, linkedTypeMap } = extractSignatureInfo(
+ lines,
+ localLinkedTypeNames,
+ localWriteLinkedTypesFile,
+ app,
+ page?.url
+ );
+
+ return rewriteReturnSections(content, {
+ heading: "## Returns",
+ fieldHeading: "###",
+ nestedHeading: "####",
+ stopOnLevel3: false,
+ signatureMap,
+ linkedTypeMap,
+ app,
+ page,
+ linkedTypeNames: localLinkedTypeNames,
+ writeLinkedTypesFile: localWriteLinkedTypesFile,
+ });
+}
+
+/**
+ * Convert interface method returns
+ */
+export function convertInterfaceMethodReturns(
+ content,
+ app,
+ page,
+ linkedTypeNames,
+ writeLinkedTypesFile
+) {
+ const lines = content.split("\n");
+ const { signatureMap, linkedTypeMap } = extractSignatureInfo(
+ lines,
+ linkedTypeNames,
+ writeLinkedTypesFile,
+ app,
+ page?.url
+ );
+
+ return rewriteReturnSections(content, {
+ heading: "#### Returns",
+ fieldHeading: "#####",
+ nestedHeading: "######",
+ stopOnLevel3: true,
+ signatureMap,
+ linkedTypeMap,
+ app,
+ page,
+ });
+}
+
+/**
+ * Convert class method returns
+ */
+export function convertClassMethodReturns(
+ content,
+ app,
+ page,
+ linkedTypeNames,
+ writeLinkedTypesFile
+) {
+ const lines = content.split("\n");
+ const { signatureMap, linkedTypeMap } = extractSignatureInfo(
+ lines,
+ linkedTypeNames,
+ writeLinkedTypesFile,
+ app,
+ page?.url
+ );
+
+ return rewriteReturnSections(content, {
+ heading: "#### Returns",
+ fieldHeading: "#####",
+ nestedHeading: "######",
+ stopOnLevel3: true,
+ signatureMap,
+ linkedTypeMap,
+ app,
+ page,
+ });
+}
+
+function rewriteReturnSections(content, options) {
+ const {
+ heading,
+ fieldHeading,
+ nestedHeading,
+ stopOnLevel3,
+ signatureMap = new Map(),
+ linkedTypeMap = new Map(),
+ app,
+ page,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null,
+ } = options;
+ const lines = content.split("\n");
+ const result = [];
+ let i = 0;
+
+ const isTerminatorLine = (line) => {
+ const trimmed = line.trim();
+ if (!trimmed) return false;
+ if (trimmed.match(/^#{2,4}\s+Examples?/i) || trimmed === "***") {
+ return true;
+ }
+ if (heading !== "## Returns" && trimmed.startsWith("## ")) {
+ return true;
+ }
+ // For function Returns, stop at nested method definitions (#### methodName())
+ if (heading === "## Returns" && trimmed.match(/^####\s+\w+\.?\w*\(\)/)) {
+ return true;
+ }
+ if (stopOnLevel3 && trimmed.startsWith("### ")) {
+ return true;
+ }
+ return false;
+ };
+
+ while (i < lines.length) {
+ const line = lines[i];
+ if (line.startsWith(heading)) {
+ result.push(line);
+ i++;
+ const sectionStart = i;
+ while (i < lines.length && !isTerminatorLine(lines[i])) {
+ i++;
+ }
+ const sectionLines = lines.slice(sectionStart, i);
+ const sectionContent = sectionLines.join("\n").trim();
+
+ // For function Returns sections, parse nested fields (### headings)
+ if (heading === "## Returns") {
+ // Look backwards to find the function signature
+ let sigLineIdx = i - 2; // Go back past the Returns heading
+ while (
+ sigLineIdx >= 0 &&
+ !lines[sigLineIdx].match(/^>\s*\*\*\w+\*\*\(/)
+ ) {
+ sigLineIdx--;
+ }
+
+ // If we didn't find it by pattern, try to find it in our signature map
+ if (sigLineIdx < 0 || !signatureMap.has(sigLineIdx)) {
+ // Try searching a bit further back (up to 10 lines)
+ for (let j = i - 2; j >= Math.max(0, i - 12); j--) {
+ if (signatureMap.has(j)) {
+ sigLineIdx = j;
+ break;
+ }
+ }
+ }
+
+ const returnTypeFromSignature =
+ sigLineIdx >= 0 ? signatureMap.get(sigLineIdx) : null;
+ const linkedTypeInfo =
+ sigLineIdx >= 0 ? linkedTypeMap.get(sigLineIdx) : null;
+ const context =
+ app && page ? { app, page, currentPagePath: page.url } : null;
+
+ // Get the type name for display - prefer linkedTypeInfo.typeName, fallback to returnTypeFromSignature
+ const returnTypeName =
+ linkedTypeInfo?.typeName || returnTypeFromSignature;
+
+ // Track linked type if found
+ if (linkedTypeInfo && linkedTypeNames) {
+ linkedTypeNames.add(linkedTypeInfo.typeName);
+ if (writeLinkedTypesFile) {
+ writeLinkedTypesFile();
+ }
+ }
+
+ const {
+ fields,
+ leadingText,
+ extractedTypeName,
+ typeDescription,
+ indexSignature,
+ } = parseReturnFields(
+ sectionContent,
+ fieldHeading,
+ nestedHeading,
+ returnTypeFromSignature,
+ linkedTypeInfo,
+ context,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+ if (fields.length === 0 && !indexSignature) {
+ result.push(...sectionLines);
+ } else {
+ const typeNameForDisplay = extractedTypeName || returnTypeName;
+ if (typeNameForDisplay) {
+ result.push("");
+ result.push(`\`${typeNameForDisplay}\``);
+ }
+ const descriptionParts = [];
+ if (typeDescription) {
+ descriptionParts.push(typeDescription);
+ }
+ if (leadingText) {
+ descriptionParts.push(leadingText);
+ }
+ const returnsDescription = extractReturnsDescription(page);
+ if (returnsDescription) {
+ descriptionParts.push(returnsDescription);
+ }
+ if (descriptionParts.length > 0) {
+ result.push("");
+ result.push(descriptionParts.join("\n\n"));
+ }
+ const fieldsBlock = formatReturnFieldsOutput(
+ fields,
+ null,
+ linkedTypeNames,
+ writeLinkedTypesFile,
+ indexSignature
+ );
+ if (fieldsBlock) {
+ result.push("");
+ result.push(fieldsBlock);
+ result.push("");
+ }
+ }
+ continue;
+ }
+
+ // For interface/class method Returns sections
+ // The Returns section starts at i-1 (after the heading line)
+ // Look backwards to find the function signature
+ let sigLineIdx = i - 2; // Go back past the Returns heading
+ while (
+ sigLineIdx >= 0 &&
+ !lines[sigLineIdx].match(/^>\s*\*\*\w+\*\*\(/)
+ ) {
+ sigLineIdx--;
+ }
+
+ // If we didn't find it by pattern, try to find it in our signature map
+ // by checking a few lines before the Returns section
+ if (sigLineIdx < 0 || !signatureMap.has(sigLineIdx)) {
+ // Try searching a bit further back (up to 10 lines)
+ for (let j = i - 2; j >= Math.max(0, i - 12); j--) {
+ if (signatureMap.has(j)) {
+ sigLineIdx = j;
+ break;
+ }
+ }
+ }
+
+ const returnTypeFromSignature =
+ sigLineIdx >= 0 ? signatureMap.get(sigLineIdx) : null;
+ const linkedTypeInfo =
+ sigLineIdx >= 0 ? linkedTypeMap.get(sigLineIdx) : null;
+
+ // Get the type name for display - prefer linkedTypeInfo.typeName, fallback to returnTypeFromSignature
+ const returnTypeName =
+ linkedTypeInfo?.typeName || returnTypeFromSignature;
+
+ // Track linked type if found
+ if (linkedTypeInfo && linkedTypeNames) {
+ linkedTypeNames.add(linkedTypeInfo.typeName);
+ if (writeLinkedTypesFile) {
+ writeLinkedTypesFile();
+ }
+ }
+
+ const {
+ fields,
+ leadingText,
+ extractedTypeName,
+ typeDescription,
+ indexSignature,
+ } = parseReturnFields(
+ sectionContent,
+ fieldHeading,
+ nestedHeading,
+ returnTypeFromSignature,
+ linkedTypeInfo,
+ { app, page, currentPagePath: page.url },
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+ if (fields.length === 0 && !indexSignature) {
+ result.push(...sectionLines);
+ } else {
+ const typeNameForDisplay = extractedTypeName || returnTypeName;
+ if (typeNameForDisplay) {
+ result.push("");
+ result.push(`\`${typeNameForDisplay}\``);
+ }
+ const descriptionParts = [];
+ if (typeDescription) {
+ descriptionParts.push(typeDescription);
+ }
+ if (leadingText) {
+ descriptionParts.push(leadingText);
+ }
+ if (descriptionParts.length > 0) {
+ result.push("");
+ result.push(descriptionParts.join("\n\n"));
+ }
+ const fieldsBlock = formatReturnFieldsOutput(
+ fields,
+ null,
+ linkedTypeNames,
+ writeLinkedTypesFile,
+ indexSignature
+ );
+ if (fieldsBlock) {
+ result.push("");
+ result.push(fieldsBlock);
+ result.push("");
+ }
+ }
+ continue;
+ }
+
+ result.push(line);
+ i++;
+ }
+
+ return result.join("\n");
+}
+
+function parseReturnFields(
+ sectionContent,
+ fieldHeading,
+ nestedHeading,
+ returnTypeFromSignature = null,
+ linkedTypeInfo = null,
+ context = null,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ let infoForDescription = linkedTypeInfo;
+
+ if (!sectionContent) {
+ // If we have a linked type but no section content, try to extract from the linked type
+ if (linkedTypeInfo && context) {
+ const result = extractPropertiesFromLinkedType(
+ linkedTypeInfo,
+ context,
+ new Set(),
+ { includeIndexSignature: true }
+ );
+ const properties = result.properties || result;
+ const indexSignature = result.indexSignature || null;
+
+ if (properties.length > 0 || indexSignature) {
+ // Return separate ResponseFields for each property (skip the default "result" field)
+ const resultFields = [];
+
+ // Add a separate ResponseField for each property
+ for (const prop of properties) {
+ resultFields.push({
+ name: prop.name,
+ type: prop.type,
+ description: prop.description,
+ optional: prop.optional,
+ nested: prop.nested || [],
+ });
+ }
+
+ return {
+ fields: resultFields,
+ leadingText: "",
+ extractedTypeName: linkedTypeInfo.typeName,
+ typeDescription:
+ getLinkedTypeDescription(linkedTypeInfo, context) || "",
+ indexSignature,
+ };
+ }
+ }
+ return {
+ fields: [],
+ leadingText: "",
+ extractedTypeName: null,
+ typeDescription:
+ getLinkedTypeDescription(infoForDescription, context) || "",
+ indexSignature: null,
+ };
+ }
+
+ const lines = sectionContent.split("\n");
+ const fields = [];
+ const headingPrefix = fieldHeading ? `${fieldHeading} ` : null;
+ const nestedPrefix = nestedHeading ? `${nestedHeading} ` : null;
+
+ const extractTypeFromLine = (line) => {
+ if (!line) return null;
+ const trimmed = line.trim();
+ if (!trimmed) return null;
+ if (trimmed.startsWith(">")) {
+ // Handle lines like: > **entities**: `object` or > **auth**: [`AuthMethods`](../interfaces/AuthMethods)
+ const blockMatch = trimmed.match(/^>\s*\*\*([^*]+)\*\*:\s*(.+)$/);
+ if (blockMatch) {
+ const typePart = blockMatch[2].replace(/`/g, "").trim();
+ // Check if it's a markdown link: [TypeName](link)
+ const linkMatch = typePart.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
+ if (linkMatch) {
+ return { type: linkMatch[1], link: linkMatch[2] };
+ }
+ return { type: typePart, link: null };
+ }
+ }
+ if (trimmed.includes("`")) {
+ // Extract type from backticks, could be a link: [`AuthMethods`](../interfaces/AuthMethods)
+ const typeMatch = trimmed.match(/`([^`]+)`/);
+ if (typeMatch) {
+ const typePart = typeMatch[1].trim();
+ // Check if there's a link after the backticks
+ const linkMatch = trimmed.match(/`[^`]+`\s*\[([^\]]+)\]\(([^)]+)\)/);
+ if (linkMatch) {
+ return { type: linkMatch[1], link: linkMatch[2] };
+ }
+ // Check if the type itself is a link format
+ const inlineLinkMatch = typePart.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
+ if (inlineLinkMatch) {
+ return { type: inlineLinkMatch[1], link: inlineLinkMatch[2] };
+ }
+ return { type: typePart, link: null };
+ }
+ }
+ // Check for standalone markdown links
+ const linkMatch = trimmed.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
+ if (linkMatch) {
+ return { type: linkMatch[1], link: linkMatch[2] };
+ }
+ return null;
+ };
+
+ const isHeadingLine = (line) =>
+ headingPrefix && line.startsWith(headingPrefix);
+ const isNestedHeadingLine = (line) =>
+ nestedPrefix && line.startsWith(nestedPrefix);
+
+ const leadingLines = [];
+ let index = 0;
+ if (headingPrefix) {
+ while (index < lines.length && !isHeadingLine(lines[index])) {
+ if (lines[index].trim()) {
+ leadingLines.push(lines[index]);
+ }
+ index++;
+ }
+ }
+
+ // If no field headings found, treat as simple return
+ if (!headingPrefix || index >= lines.length) {
+ let type = returnTypeFromSignature || "any";
+ const descriptionLines = [];
+
+ // Check if there's an existing ResponseField in the content
+ const responseFieldMatch = sectionContent.match(
+ /]*type="([^"]+)"[^>]*>/
+ );
+ if (responseFieldMatch) {
+ // Extract type from existing ResponseField
+ const existingType = responseFieldMatch[1];
+ if (existingType && existingType !== "any") {
+ type = existingType;
+ }
+ }
+
+ for (const line of lines) {
+ // Skip ResponseField tags - we'll replace them
+ if (
+ line.trim().startsWith(""
+ ) {
+ continue;
+ }
+ const maybeType = extractTypeFromLine(line);
+ if (maybeType && type === "any") {
+ type = typeof maybeType === "object" ? maybeType.type : maybeType;
+ continue;
+ }
+ if (
+ line.trim() &&
+ !line.trim().startsWith("`") &&
+ !line.trim().startsWith("<")
+ ) {
+ descriptionLines.push(line);
+ }
+ }
+ let description = descriptionLines.join("\n").trim();
+
+ // Check if we have a linked type to inline
+ let typeInfoToUse = linkedTypeInfo;
+
+ // If we don't have linkedTypeInfo but we have a type name, try to resolve it
+ if (!typeInfoToUse && type && context && context.app) {
+ const simpleTypeName = getSimpleTypeName(type);
+ if (simpleTypeName && !PRIMITIVE_TYPES.includes(simpleTypeName)) {
+ const typePath = resolveTypePath(
+ simpleTypeName,
+ context.app,
+ context.currentPagePath
+ );
+ if (typePath) {
+ typeInfoToUse = { typeName: simpleTypeName, typePath };
+ } else if (simpleTypeName) {
+ // Even if we can't resolve the path, try with just the name
+ typeInfoToUse = {
+ typeName: simpleTypeName,
+ typePath: simpleTypeName,
+ };
+ }
+ if (typeInfoToUse) {
+ infoForDescription = typeInfoToUse;
+ }
+
+ // Track resolved linked type
+ if (typeInfoToUse && linkedTypeNames) {
+ linkedTypeNames.add(typeInfoToUse.typeName);
+ if (writeLinkedTypesFile) {
+ writeLinkedTypesFile();
+ }
+ }
+ }
+ }
+
+ if (typeInfoToUse && context) {
+ const result = extractPropertiesFromLinkedType(
+ typeInfoToUse,
+ context,
+ new Set(),
+ { includeIndexSignature: true }
+ );
+ const properties = result.properties || result;
+ const indexSignature = result.indexSignature || null;
+
+ if (properties.length > 0 || indexSignature) {
+ // Return separate ResponseFields for each property (skip the default "result" field)
+ const resultFields = [];
+
+ // Add a separate ResponseField for each property
+ for (const prop of properties) {
+ resultFields.push({
+ name: prop.name,
+ type: prop.type,
+ description: prop.description,
+ optional: prop.optional,
+ nested: prop.nested || [],
+ });
+ }
+
+ return {
+ fields: resultFields,
+ leadingText: "",
+ extractedTypeName: typeInfoToUse.typeName, // Pass the type name for display
+ typeDescription:
+ getLinkedTypeDescription(typeInfoToUse, context) || "",
+ indexSignature,
+ };
+ }
+ }
+
+ // Use 'result' as default name, or extract from description
+ let name = "result";
+ if (description) {
+ // Check if description contains a type hint
+ const typeHint = description.match(/(\w+)\s+(?:instance|object|value)/i);
+ if (typeHint) {
+ name = typeHint[1].toLowerCase();
+ }
+ }
+ return {
+ fields: [
+ {
+ name,
+ type,
+ description,
+ optional: false,
+ nested: [],
+ },
+ ],
+ leadingText: "",
+ extractedTypeName: null,
+ typeDescription:
+ getLinkedTypeDescription(
+ infoForDescription || typeInfoToUse,
+ context
+ ) || "",
+ };
+ }
+
+ // Parse fields with headings
+ while (index < lines.length) {
+ const headingLine = lines[index];
+ if (!isHeadingLine(headingLine)) {
+ index++;
+ continue;
+ }
+
+ let rawName = headingLine.slice(headingPrefix.length).trim();
+ const optional = rawName.endsWith("?");
+ const name = optional ? rawName.slice(0, -1).trim() : rawName.trim();
+ index++;
+
+ while (index < lines.length && lines[index].trim() === "") {
+ index++;
+ }
+
+ let type = "any";
+ if (index < lines.length) {
+ const maybeType = extractTypeFromLine(lines[index]);
+ if (maybeType) {
+ type = typeof maybeType === "object" ? maybeType.type : maybeType;
+ index++;
+ }
+ }
+
+ while (index < lines.length && lines[index].trim() === "") {
+ index++;
+ }
+
+ const descriptionLines = [];
+ const nested = [];
+
+ // Collect description and nested fields
+ while (
+ index < lines.length &&
+ !isHeadingLine(lines[index]) &&
+ !(nestedPrefix && isNestedHeadingLine(lines[index]))
+ ) {
+ descriptionLines.push(lines[index]);
+ index++;
+ }
+
+ // Parse nested fields if any
+ while (index < lines.length && isNestedHeadingLine(lines[index])) {
+ const nestedHeadingLine = lines[index];
+ let nestedRawName = nestedHeadingLine.slice(nestedPrefix.length).trim();
+ const nestedOptional = nestedRawName.endsWith("?");
+ const nestedName = nestedOptional
+ ? nestedRawName.slice(0, -1).trim()
+ : nestedRawName.trim();
+ index++;
+
+ while (index < lines.length && lines[index].trim() === "") {
+ index++;
+ }
+
+ let nestedType = "any";
+ if (index < lines.length) {
+ const maybeNestedType = extractTypeFromLine(lines[index]);
+ if (maybeNestedType) {
+ nestedType =
+ typeof maybeNestedType === "object"
+ ? maybeNestedType.type
+ : maybeNestedType;
+ index++;
+ }
+ }
+
+ while (index < lines.length && lines[index].trim() === "") {
+ index++;
+ }
+
+ const nestedDescLines = [];
+ while (
+ index < lines.length &&
+ !isNestedHeadingLine(lines[index]) &&
+ !isHeadingLine(lines[index])
+ ) {
+ nestedDescLines.push(lines[index]);
+ index++;
+ }
+
+ nested.push({
+ name: nestedName,
+ type: nestedType,
+ description: nestedDescLines.join("\n").trim(),
+ optional: nestedOptional,
+ });
+ }
+
+ let description = descriptionLines.join("\n").trim();
+
+ // Check if this field's type is a linked type that should be expanded
+ // Only expand if we don't already have nested fields from headings
+ if (nested.length === 0 && context && type && type !== "any") {
+ const simpleTypeName = getSimpleTypeName(type);
+ if (simpleTypeName && !PRIMITIVE_TYPES.includes(simpleTypeName)) {
+ // Try to resolve the type to a linked type
+ const typePath = resolveTypePath(
+ simpleTypeName,
+ context.app,
+ context.currentPagePath
+ );
+ const linkedTypeInfo = typePath
+ ? { typeName: simpleTypeName, typePath }
+ : { typeName: simpleTypeName, typePath: simpleTypeName };
+
+ // Extract properties from the linked type
+ const properties = extractPropertiesFromLinkedType(
+ linkedTypeInfo,
+ context
+ );
+ if (properties.length > 0) {
+ // Add properties as nested fields
+ for (const prop of properties) {
+ nested.push({
+ name: prop.name,
+ type: prop.type,
+ description: prop.description || "",
+ optional: prop.optional,
+ });
+ }
+
+ // Track the linked type
+ if (linkedTypeNames) {
+ linkedTypeNames.add(simpleTypeName);
+ if (writeLinkedTypesFile) {
+ writeLinkedTypesFile();
+ }
+ }
+ }
+ }
+ }
+
+ fields.push({
+ name,
+ type,
+ description,
+ optional,
+ nested,
+ });
+ }
+
+ return {
+ fields,
+ leadingText: leadingLines.join("\n").trim(),
+ extractedTypeName: null,
+ typeDescription:
+ getLinkedTypeDescription(infoForDescription, context) || "",
+ indexSignature: null,
+ };
+}
+
+function buildResponseFieldsSection(
+ fields,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ let output = "";
+
+ const PRIMITIVE_TYPES = [
+ "any",
+ "string",
+ "number",
+ "boolean",
+ "void",
+ "null",
+ "undefined",
+ "object",
+ "Array",
+ "Promise",
+ ];
+
+ for (const field of fields) {
+ const requiredAttr = field.optional ? "" : " required";
+ const defaultAttr = field.default
+ ? ` default="${escapeAttribute(field.default)}"`
+ : "";
+
+ // Track non-primitive return field types for suppression
+ if (
+ linkedTypeNames &&
+ field.type &&
+ !PRIMITIVE_TYPES.includes(field.type)
+ ) {
+ const simpleTypeName = field.type.replace(/[<>\[\]]/g, "").trim();
+ if (simpleTypeName && !PRIMITIVE_TYPES.includes(simpleTypeName)) {
+ linkedTypeNames.add(simpleTypeName);
+ if (writeLinkedTypesFile) {
+ writeLinkedTypesFile();
+ }
+ }
+ }
+
+ output += `\n`;
+
+ if (field.description) {
+ output += `\n${field.description}\n`;
+ }
+
+ if (field.nested && field.nested.length > 0) {
+ // Wrap nested fields in an Accordion component
+ output += `\n\n\n`;
+ output += renderNestedResponseFields(
+ field.nested,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+ output += "\n";
+ }
+
+ output += "\n\n\n";
+ }
+
+ return output;
+}
+
+function formatReturnFieldsOutput(
+ fields,
+ returnType = null,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null,
+ indexSignature = null
+) {
+ if ((!fields || fields.length === 0) && !indexSignature) {
+ return "";
+ }
+
+ const isSingleSimpleField =
+ fields.length === 1 &&
+ (!fields[0].nested || fields[0].nested.length === 0) &&
+ !indexSignature;
+
+ if (isSingleSimpleField) {
+ // For a single, non-object field, we only need to return its description text.
+ // The type is already rendered separately (`typeNameForDisplay`), so avoid wrapping
+ // it in a ResponseField to keep the output concise.
+ return fields[0].description || "";
+ }
+
+ const fieldsBlock = buildResponseFieldsSection(
+ fields,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ ).trimEnd();
+
+ // Build index signature as a ResponseField if present
+ let indexSignatureBlock = "";
+ if (indexSignature) {
+ const keyName = `[key: ${indexSignature.keyType}]`;
+ const description = indexSignature.description || "";
+ indexSignatureBlock = `\n\n${description}\n\n\n\n`;
+ }
+
+ if (!fieldsBlock && !indexSignatureBlock) {
+ return "";
+ }
+
+ const hasMultipleFields = fields.length > 1;
+ const hasNestedFields = fields.some(
+ (field) => Array.isArray(field.nested) && field.nested.length > 0
+ );
+
+ if (hasMultipleFields || hasNestedFields || indexSignature) {
+ // Extract the simple type name to display above the Accordion
+ let typeDisplay = "";
+ if (returnType) {
+ const simpleTypeName = getSimpleTypeName(returnType);
+ if (simpleTypeName && !PRIMITIVE_TYPES.includes(simpleTypeName)) {
+ typeDisplay = `\`${simpleTypeName}\`\n\n`;
+ }
+ }
+ // If we still don't have a type display and have multiple fields,
+ // try to infer from the context (e.g., if all fields are from the same type)
+ if (!typeDisplay && hasMultipleFields && fields.length > 0) {
+ // Check if we can get a type hint from the first field's description or context
+ // This is a fallback for cases where returnType wasn't passed correctly
+ }
+ return `${typeDisplay}\n\n${fieldsBlock}${indexSignatureBlock}\n`;
+ }
+
+ return fieldsBlock + indexSignatureBlock;
+}
+
+function renderNestedResponseFields(
+ fields,
+ linkedTypeNames = null,
+ writeLinkedTypesFile = null
+) {
+ if (!fields || fields.length === 0) {
+ return "";
+ }
+
+ let output = "";
+ for (const field of fields) {
+ const requiredAttr = field.optional ? "" : " required";
+ const defaultAttr = field.default
+ ? ` default="${escapeAttribute(field.default)}"`
+ : "";
+
+ if (
+ linkedTypeNames &&
+ field.type &&
+ !PRIMITIVE_TYPES.includes(field.type)
+ ) {
+ const simpleTypeName = field.type.replace(/[<>\[\]]/g, "").trim();
+ if (simpleTypeName && !PRIMITIVE_TYPES.includes(simpleTypeName)) {
+ linkedTypeNames.add(simpleTypeName);
+ if (writeLinkedTypesFile) {
+ writeLinkedTypesFile();
+ }
+ }
+ }
+
+ output += `\n`;
+
+ if (field.description) {
+ output += `\n${field.description}\n`;
+ }
+
+ if (field.nested && field.nested.length > 0) {
+ output += `\n\n\n`;
+ output += renderNestedResponseFields(
+ field.nested,
+ linkedTypeNames,
+ writeLinkedTypesFile
+ );
+ output += "\n";
+ }
+
+ output += "\n\n\n";
+ }
+
+ return output;
+}
+
+function getSimpleTypeName(typeName) {
+ if (!typeName) {
+ return null;
+ }
+
+ // Remove generic arguments if they are still present (e.g., Promise)
+ const withoutGenerics = typeName.split("<")[0].trim();
+
+ // Type names can include dots for namespaces, so allow those
+ const match = withoutGenerics.match(/^[A-Za-z0-9_.]+$/);
+ return match ? match[0] : null;
+}
diff --git a/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-utils.js b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-utils.js
new file mode 100644
index 0000000..497bf79
--- /dev/null
+++ b/scripts/mintlify-post-processing/typedoc-plugin/typedoc-mintlify-utils.js
@@ -0,0 +1,12 @@
+/**
+ * Utility functions for TypeDoc Mintlify plugin
+ */
+
+/**
+ * Escape special characters for use in HTML attributes
+ */
+export function escapeAttribute(value) {
+ return String(value).replace(/"/g, '"');
+}
+
+
diff --git a/scripts/mintlify-post-processing/types-to-expose.json b/scripts/mintlify-post-processing/types-to-expose.json
new file mode 100644
index 0000000..94bd563
--- /dev/null
+++ b/scripts/mintlify-post-processing/types-to-expose.json
@@ -0,0 +1,12 @@
+[
+ "AgentsModule",
+ "AppLogsModule",
+ "AuthModule",
+ "ConnectorsModule",
+ "EntitiesModule",
+ "EntityHandler",
+ "FunctionsModule",
+ "IntegrationsModule",
+ "CoreIntegrations",
+ "SsoModule"
+]
diff --git a/src/client.ts b/src/client.ts
index 1732e69..34afc83 100644
--- a/src/client.ts
+++ b/src/client.ts
@@ -10,35 +10,51 @@ import { createAgentsModule } from "./modules/agents.js";
import { createAppLogsModule } from "./modules/app-logs.js";
import { createUsersModule } from "./modules/users.js";
import { RoomsSocket, RoomsSocketConfig } from "./utils/socket-utils.js";
+import type {
+ Base44Client,
+ CreateClientConfig,
+ CreateClientOptions,
+} from "./client.types.js";
-export type CreateClientOptions = {
- onError?: (error: Error) => void;
-};
-
-export type Base44Client = ReturnType;
+// Re-export client types
+export type { Base44Client, CreateClientConfig, CreateClientOptions };
/**
- * Create a Base44 client instance
- * @param {Object} config - Client configuration
- * @param {string} [config.serverUrl='https://base44.app'] - API server URL
- * @param {string} [config.appBaseUrl] - Application base URL
- * @param {string|number} config.appId - Application ID
- * @param {string} [config.token] - Authentication token
- * @param {string} [config.serviceToken] - Service role authentication token
- * @param {boolean} [config.requiresAuth=false] - Whether the app requires authentication
- * @returns {Object} Base44 client instance
+ * Creates a Base44 client.
+ *
+ * This is the main entry point for the Base44 SDK. It creates a client that provides access to the SDK's modules, such as {@linkcode EntitiesModule | entities}, {@linkcode AuthModule | auth}, and {@linkcode FunctionsModule | functions}.
+ *
+ * Typically, you don't need to call this function because Base44 creates the client for you. You can then import and use the client to make API calls. The client takes care of managing authentication for you.
+ *
+ * The client supports three authentication modes:
+ * - **Anonymous**: Access modules anonymously without authentication using `base44.moduleName`. Operations are scoped to public data and permissions.
+ * - **User authentication**: Access modules with user-level permissions using `base44.moduleName`. Operations are scoped to the authenticated user's data and permissions.
+ * - **Service role authentication**: Access modules with elevated permissions using `base44.asServiceRole.moduleName`. Operations can access any data available to the app's admin. Can only be used in the backend. Typically, you create a client with service role authentication using the {@linkcode createClientFromRequest | createClientFromRequest()} function in your backend functions.
+ *
+ * For example, when using the {@linkcode EntitiesModule | entities} module:
+ * - **Anonymous**: Can only read public data.
+ * - **User authentication**: Can access the current user's data.
+ * - **Service role authentication**: Can access all data that admins can access.
+ *
+ * Most modules are available in all three modes, but with different permission levels. However, some modules are only available in specific authentication modes.
+ *
+ * @param config - Configuration object for the client.
+ * @returns A configured Base44 client instance with access to all SDK modules.
+ *
+ * @example
+ * ```typescript
+ * // Create a client for your app
+ * import { createClient } from '@base44/sdk';
+ *
+ * const base44 = createClient({
+ * appId: 'my-app-id'
+ * });
+ *
+ * // Use the client to access your data
+ * const products = await base44.entities.Products.list();
+ * ```
*/
-export function createClient(config: {
- serverUrl?: string;
- appBaseUrl?: string;
- appId: string;
- token?: string;
- serviceToken?: string;
- requiresAuth?: boolean;
- functionsVersion?: string;
- headers?: Record;
- options?: CreateClientOptions;
-}) {
+export function createClient(config: CreateClientConfig): Base44Client {
const {
serverUrl = "https://base44.app",
appId,
@@ -186,8 +202,19 @@ export function createClient(config: {
...userModules,
/**
- * Set authentication token for all requests
- * @param {string} newToken - New auth token
+ * Sets a new authentication token for all subsequent requests.
+ *
+ * @param newToken - The new authentication token
+ *
+ * @example
+ * ```typescript
+ * // Update token after login
+ * const { access_token } = await base44.auth.loginViaEmailPassword(
+ * 'user@example.com',
+ * 'password'
+ * );
+ * base44.setToken(access_token);
+ * ```
*/
setToken(newToken: string) {
userModules.auth.setToken(newToken);
@@ -200,8 +227,9 @@ export function createClient(config: {
},
/**
- * Get current configuration
- * @returns {Object} Current configuration
+ * Gets the current client configuration.
+ *
+ * @internal
*/
getConfig() {
return {
@@ -212,8 +240,22 @@ export function createClient(config: {
},
/**
- * Access service role modules - throws error if no service token was provided
- * @throws {Error} When accessed without a service token
+ * Provides access to service role modules.
+ *
+ * Service role authentication provides elevated permissions for server-side operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication has access to the data and operations available to the app's admin.
+ *
+ * @throws {Error} When accessed without providing a serviceToken during client creation.
+ *
+ * @example
+ * ```typescript
+ * const base44 = createClient({
+ * appId: 'my-app-id',
+ * serviceToken: 'service-role-token'
+ * });
+ *
+ * // Also access a module with elevated permissions
+ * const allUsers = await base44.asServiceRole.entities.User.list();
+ * ```
*/
get asServiceRole() {
if (!serviceToken) {
@@ -228,7 +270,60 @@ export function createClient(config: {
return client;
}
-export function createClientFromRequest(request: Request) {
+/**
+ * Creates a Base44 client from an HTTP request.
+ *
+ * The client is created by automatically extracting authentication tokens from a request to a backend function. Base44 inserts the necessary headers when forwarding requests to backend functions.
+ *
+ * To learn more about the Base44 client, see {@linkcode createClient | createClient()}.
+ *
+ * @param request - The incoming HTTP request object containing Base44 authentication headers.
+ * @returns A configured Base44 client instance with authentication from the incoming request.
+ *
+ * @example
+ * ```typescript
+ * // User authentication in backend function
+ * import { createClientFromRequest } from 'npm:@base44/sdk';
+ *
+ * Deno.serve(async (req) => {
+ * try {
+ * const base44 = createClientFromRequest(req);
+ * const user = await base44.auth.me();
+ *
+ * if (!user) {
+ * return Response.json({ error: 'Unauthorized' }, { status: 401 });
+ * }
+ *
+ * // Access user's data
+ * const userOrders = await base44.entities.Orders.filter({ userId: user.id });
+ * return Response.json({ orders: userOrders });
+ * } catch (error) {
+ * return Response.json({ error: error.message }, { status: 500 });
+ * }
+ * });
+ * ```
+ *
+ * @example
+ * ```typescript
+ * // Service role authentication in backend function
+ * import { createClientFromRequest } from 'npm:@base44/sdk';
+ *
+ * Deno.serve(async (req) => {
+ * try {
+ * const base44 = createClientFromRequest(req);
+ *
+ * // Access admin data with service role permissions
+ * const recentOrders = await base44.asServiceRole.entities.Orders.list('-created_at', 50);
+ *
+ * return Response.json({ orders: recentOrders });
+ * } catch (error) {
+ * return Response.json({ error: error.message }, { status: 500 });
+ * }
+ * });
+ * ```
+ *
+ */
+export function createClientFromRequest(request: Request): Base44Client {
const authHeader = request.headers.get("Authorization");
const serviceRoleAuthHeader = request.headers.get(
"Base44-Service-Authorization"
diff --git a/src/client.types.ts b/src/client.types.ts
new file mode 100644
index 0000000..40e3c87
--- /dev/null
+++ b/src/client.types.ts
@@ -0,0 +1,133 @@
+import type { EntitiesModule } from "./modules/entities.types.js";
+import type { IntegrationsModule } from "./modules/integrations.types.js";
+import type { AuthModule } from "./modules/auth.types.js";
+import type { SsoModule } from "./modules/sso.types.js";
+import type { ConnectorsModule } from "./modules/connectors.types.js";
+import type { FunctionsModule } from "./modules/functions.types.js";
+import type { AgentsModule } from "./modules/agents.types.js";
+import type { AppLogsModule } from "./modules/app-logs.types.js";
+
+/**
+ * Options for creating a Base44 client.
+ */
+export interface CreateClientOptions {
+ /**
+ * Optional error handler that will be called whenever an API error occurs.
+ */
+ onError?: (error: Error) => void;
+}
+
+/**
+ * Configuration for creating a Base44 client.
+ */
+export interface CreateClientConfig {
+ /**
+ * The Base44 server URL. Defaults to "https://base44.app".
+ * @internal
+ */
+ serverUrl?: string;
+ /**
+ * The base URL of the app, which is used for login redirects.
+ * @internal
+ */
+ appBaseUrl?: string;
+ /**
+ * The Base44 app ID.
+ *
+ * You can find the `appId` in the browser URL when you're in the app editor.
+ * It's the string between `/apps/` and `/editor/`.
+ */
+ appId: string;
+ /**
+ * User authentication token. Used to authenticate as a specific user.
+ */
+ token?: string;
+ /**
+ * Service role authentication token. Use this in the backend when you need elevated permissions to access data available to the app's admin or perform admin operations. This token should be kept secret and never exposed in the app's frontend. Typically, you get this token from a request to a backend function using {@linkcode createClientFromRequest | createClientFromRequest()}.
+ */
+ serviceToken?: string;
+ /**
+ * Whether authentication is required. If true, redirects to login if not authenticated.
+ * @internal
+ */
+ requiresAuth?: boolean;
+ /**
+ * Version string for functions API.
+ * @internal
+ */
+ functionsVersion?: string;
+ /**
+ * Additional headers to include in API requests.
+ * @internal
+ */
+ headers?: Record;
+ /**
+ * Additional client options.
+ */
+ options?: CreateClientOptions;
+}
+
+/**
+ * The Base44 client instance.
+ *
+ * Provides access to all SDK modules for interacting with the app.
+ */
+export interface Base44Client {
+ /** {@link EntitiesModule | Entities module} for CRUD operations on your data models. */
+ entities: EntitiesModule;
+ /** {@link IntegrationsModule | Integrations module} for calling pre-built integration endpoints. */
+ integrations: IntegrationsModule;
+ /** {@link AuthModule | Auth module} for user authentication and management. */
+ auth: AuthModule;
+ /** {@link FunctionsModule | Functions module} for invoking custom backend functions. */
+ functions: FunctionsModule;
+ /** {@link AgentsModule | Agents module} for managing AI agent conversations. */
+ agents: AgentsModule;
+ /** {@link AppLogsModule | App logs module} for tracking app usage. */
+ appLogs: AppLogsModule;
+ /** Cleanup function to disconnect WebSocket connections. Call when you're done with the client. */
+ cleanup: () => void;
+
+ /**
+ * Sets a new authentication token for all subsequent requests.
+ *
+ * Updates the token for both HTTP requests and WebSocket connections.
+ *
+ * @param newToken - The new authentication token.
+ */
+ setToken(newToken: string): void;
+
+ /**
+ * Gets the current client configuration.
+ * @internal
+ */
+ getConfig(): { serverUrl: string; appId: string; requiresAuth: boolean };
+
+ /**
+ * Provides access to supported modules with elevated permissions.
+ *
+ * Service role authentication provides elevated permissions for backend operations. Unlike user authentication, which is scoped to a specific user's permissions, service role authentication has access to the data and operations available to the app's admin.
+ *
+ * @throws {Error} When accessed without providing a serviceToken during client creation
+ */
+ readonly asServiceRole: {
+ /** {@link EntitiesModule | Entities module} with elevated permissions. */
+ entities: EntitiesModule;
+ /** {@link IntegrationsModule | Integrations module} with elevated permissions. */
+ integrations: IntegrationsModule;
+ /** {@link SsoModule | SSO module} for generating SSO tokens.
+ * @internal
+ */
+ sso: SsoModule;
+ /** {@link ConnectorsModule | Connectors module} for OAuth token retrieval. */
+ connectors: ConnectorsModule;
+ /** {@link FunctionsModule | Functions module} with elevated permissions. */
+ functions: FunctionsModule;
+ /** {@link AgentsModule | Agents module} with elevated permissions. */
+ agents: AgentsModule;
+ /** {@link AppLogsModule | App logs module} with elevated permissions. */
+ appLogs: AppLogsModule;
+ /** Cleanup function to disconnect WebSocket connections. */
+ cleanup: () => void;
+ };
+}
diff --git a/src/index.ts b/src/index.ts
index 7a4b962..dbaa1ce 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,11 @@
-import { createClient, createClientFromRequest, type Base44Client } from "./client.js";
-import { Base44Error } from "./utils/axios-client.js";
+import {
+ createClient,
+ createClientFromRequest,
+ type Base44Client,
+ type CreateClientConfig,
+ type CreateClientOptions,
+} from "./client.js";
+import { Base44Error, type Base44ErrorJSON } from "./utils/axios-client.js";
import {
getAccessToken,
saveAccessToken,
@@ -17,6 +23,75 @@ export {
getLoginUrl,
};
-export type { Base44Client };
+export type {
+ Base44Client,
+ CreateClientConfig,
+ CreateClientOptions,
+ Base44ErrorJSON,
+};
export * from "./types.js";
+
+// Module types
+export type {
+ EntitiesModule,
+ EntityHandler,
+} from "./modules/entities.types.js";
+
+export type {
+ AuthModule,
+ LoginResponse,
+ RegisterParams,
+ VerifyOtpParams,
+ ChangePasswordParams,
+ ResetPasswordParams,
+ User,
+} from "./modules/auth.types.js";
+
+export type {
+ IntegrationsModule,
+ IntegrationPackage,
+ IntegrationEndpointFunction,
+ CoreIntegrations,
+ InvokeLLMParams,
+ GenerateImageParams,
+ GenerateImageResult,
+ UploadFileParams,
+ UploadFileResult,
+ SendEmailParams,
+ SendEmailResult,
+ ExtractDataFromUploadedFileParams,
+ ExtractDataFromUploadedFileResult,
+ UploadPrivateFileParams,
+ UploadPrivateFileResult,
+ CreateFileSignedUrlParams,
+ CreateFileSignedUrlResult,
+} from "./modules/integrations.types.js";
+
+export type { FunctionsModule } from "./modules/functions.types.js";
+
+export type {
+ AgentsModule,
+ AgentConversation,
+ AgentMessage,
+ AgentMessageReasoning,
+ AgentMessageToolCall,
+ AgentMessageUsage,
+ AgentMessageCustomContext,
+ AgentMessageMetadata,
+ CreateConversationParams,
+} from "./modules/agents.types.js";
+
+export type { AppLogsModule } from "./modules/app-logs.types.js";
+
+export type { SsoModule, SsoAccessTokenResponse } from "./modules/sso.types.js";
+
+export type { ConnectorsModule } from "./modules/connectors.types.js";
+
+// Auth utils types
+export type {
+ GetAccessTokenOptions,
+ SaveAccessTokenOptions,
+ RemoveAccessTokenOptions,
+ GetLoginUrlOptions,
+} from "./utils/auth-utils.types.js";
diff --git a/src/modules/agents.ts b/src/modules/agents.ts
index c573cd1..3b8974c 100644
--- a/src/modules/agents.ts
+++ b/src/modules/agents.ts
@@ -1,16 +1,12 @@
-import { RoomsSocket } from "../utils/socket-utils.js";
-import { AgentConversation, AgentMessage } from "./agents.types.js";
-import { AxiosInstance } from "axios";
-import { ModelFilterParams } from "../types.js";
import { getAccessToken } from "../utils/auth-utils.js";
-
-export type AgentsModuleConfig = {
- axios: AxiosInstance;
- getSocket: () => ReturnType;
- appId: string;
- serverUrl?: string;
- token?: string;
-};
+import { ModelFilterParams } from "../types.js";
+import {
+ AgentConversation,
+ AgentMessage,
+ AgentsModule,
+ AgentsModuleConfig,
+ CreateConversationParams,
+} from "./agents.types.js";
export function createAgentsModule({
axios,
@@ -18,7 +14,7 @@ export function createAgentsModule({
appId,
serverUrl,
token,
-}: AgentsModuleConfig) {
+}: AgentsModuleConfig): AgentsModule {
const baseURL = `/apps/${appId}/agents`;
const getConversations = () => {
@@ -37,29 +33,23 @@ export function createAgentsModule({
});
};
- const createConversation = (conversation: {
- agent_name: string;
- metadata?: Record;
- }) => {
+ const createConversation = (conversation: CreateConversationParams) => {
return axios.post(
`${baseURL}/conversations`,
conversation
);
};
-
+
const addMessage = async (
conversation: AgentConversation,
message: AgentMessage
) => {
const room = `/agent-conversations/${conversation.id}`;
const socket = getSocket();
- await socket.updateModel(
- room,
- {
- ...conversation,
- messages: [...(conversation.messages || []), message],
- }
- );
+ await socket.updateModel(room, {
+ ...conversation,
+ messages: [...(conversation.messages || []), message],
+ });
return axios.post(
`${baseURL}/conversations/${conversation.id}/messages`,
message
@@ -82,7 +72,9 @@ export function createAgentsModule({
};
const getWhatsAppConnectURL = (agentName: string) => {
- const baseUrl = `${serverUrl}/api/apps/${appId}/agents/${encodeURIComponent(agentName)}/whatsapp`;
+ const baseUrl = `${serverUrl}/api/apps/${appId}/agents/${encodeURIComponent(
+ agentName
+ )}/whatsapp`;
const accessToken = token ?? getAccessToken();
if (accessToken) {
diff --git a/src/modules/agents.types.ts b/src/modules/agents.types.ts
index a6c1337..355ad15 100644
--- a/src/modules/agents.types.ts
+++ b/src/modules/agents.types.ts
@@ -1,43 +1,368 @@
-export type AgentConversation = {
+import { AxiosInstance } from "axios";
+import { RoomsSocket } from "../utils/socket-utils";
+import { ModelFilterParams } from "../types";
+
+/**
+ * Reasoning information for an agent message.
+ *
+ * Contains details about the agent's reasoning process when generating a response.
+ */
+export interface AgentMessageReasoning {
+ /** When reasoning started. */
+ start_date: string;
+ /** When reasoning ended. */
+ end_date?: string;
+ /** Reasoning content. */
+ content: string;
+}
+
+/**
+ * A tool call made by the agent.
+ *
+ * Represents a function or tool that the agent invoked during message generation.
+ */
+export interface AgentMessageToolCall {
+ /** Tool call ID. */
id: string;
+ /** Name of the tool called. */
+ name: string;
+ /** Arguments passed to the tool as JSON string. */
+ arguments_string: string;
+ /** Status of the tool call. */
+ status: "running" | "success" | "error" | "stopped";
+ /** Results from the tool call. */
+ results?: string;
+}
+
+/**
+ * Token usage statistics for an agent message.
+ *
+ * Tracks the number of tokens consumed when generating the message.
+ */
+export interface AgentMessageUsage {
+ /** Number of tokens in the prompt. */
+ prompt_tokens?: number;
+ /** Number of tokens in the completion. */
+ completion_tokens?: number;
+}
+
+/**
+ * Custom context provided with an agent message.
+ *
+ * Additional contextual information that can be passed to the agent.
+ */
+export interface AgentMessageCustomContext {
+ /** Context message. */
+ message: string;
+ /** Associated data for the context. */
+ data: Record;
+ /** Type of context. */
+ type: string;
+}
+
+/**
+ * Metadata about when and by whom a message was created.
+ */
+export interface AgentMessageMetadata {
+ /** When the message was created. */
+ created_date: string;
+ /** Email of the user who created the message. */
+ created_by_email: string;
+ /** Full name of the user who created the message. */
+ created_by_full_name: string;
+}
+
+/**
+ * An agent conversation containing messages exchanged with an AI agent.
+ */
+export interface AgentConversation {
+ /** Unique identifier for the conversation. */
+ id: string;
+ /** Application ID. */
app_id: string;
+ /** Name of the agent in this conversation. */
agent_name: string;
+ /** ID of the user who created the conversation. */
created_by_id: string;
+ /** When the conversation was created. */
+ created_date: string;
+ /** When the conversation was last updated. */
+ updated_date: string;
+ /** Array of messages in the conversation. */
messages: AgentMessage[];
+ /** Optional metadata associated with the conversation. */
metadata?: Record;
-};
+}
-export type AgentMessage = {
+/**
+ * A message in an agent conversation.
+ */
+export interface AgentMessage {
+ /** Unique identifier for the message. */
id: string;
+ /** Role of the message sender. */
role: "user" | "assistant" | "system";
- reasoning?: {
- start_date: string;
- end_date?: string;
- content: string;
- };
- content?: string | Record | null;
- file_urls?: string[] | null;
- tool_calls?:
- | {
- id: string;
- name: string;
- arguments_string: string;
- status: "running" | "success" | "error" | "stopped";
- results?: string | null;
- }[]
- | null;
-
- usage?: { prompt_tokens?: number; completion_tokens?: number } | null;
+ /** When the message was created. */
+ created_date: string;
+ /** When the message was last updated. */
+ updated_date: string;
+ /** Optional reasoning information for the message. */
+ reasoning?: AgentMessageReasoning | null;
+ /** Message content. */
+ content?: string | Record;
+ /** URLs to files attached to the message. */
+ file_urls?: string[];
+ /** Tool calls made by the agent. */
+ tool_calls?: AgentMessageToolCall[];
+ /** Token usage statistics. */
+ usage?: AgentMessageUsage;
+ /** Whether the message is hidden from the user. */
hidden?: boolean;
- custom_context?:
- | { message: string; data: Record; type: string }[]
- | null;
- model?: string | null;
- checkpoint_id?: string | null;
- metadata?: {
- created_date: string;
- created_by_email: string;
- created_by_full_name: string | null;
- };
+ /** Custom context provided with the message. */
+ custom_context?: AgentMessageCustomContext[];
+ /** Model used to generate the message. */
+ model?: string;
+ /** Checkpoint ID for the message. */
+ checkpoint_id?: string;
+ /** Metadata about when and by whom the message was created. */
+ metadata?: AgentMessageMetadata;
+ /** Additional custom parameters for the message. */
additional_message_params?: Record;
-};
+}
+
+/**
+ * Parameters for creating a new conversation.
+ */
+export interface CreateConversationParams {
+ /** The name of the agent to create a conversation with. */
+ agent_name: string;
+ /** Optional metadata to attach to the conversation. */
+ metadata?: Record;
+}
+
+/**
+ * Configuration for creating the agents module.
+ * @internal
+ */
+export interface AgentsModuleConfig {
+ /** Axios instance for HTTP requests */
+ axios: AxiosInstance;
+ /** Function to get WebSocket instance for real-time updates (lazy initialization) */
+ getSocket: () => ReturnType;
+ /** Application ID */
+ appId: string;
+ /** Server URL */
+ serverUrl?: string;
+ /** Authentication token */
+ token?: string;
+}
+
+/**
+ * Agents module for managing AI agent conversations.
+ *
+ * This module provides methods to create and manage conversations with AI agents,
+ * send messages, and subscribe to real-time updates. Conversations can be used
+ * for chat interfaces, support systems, or any interactive AI app.
+ *
+ * The agents module enables you to:
+ *
+ * - **Create conversations** with agents defined in the app.
+ * - **Send messages** from users to agents and receive AI-generated responses.
+ * - **Retrieve conversations** individually or as filtered lists with sorting and pagination.
+ * - **Subscribe to real-time updates** using WebSocket connections to receive instant notifications when new messages arrive.
+ * - **Attach metadata** to conversations for tracking context, categories, priorities, or linking to external systems.
+ * - **Generate WhatsApp connection URLs** for users to interact with agents through WhatsApp.
+ *
+ * The agents module operates with a two-level hierarchy:
+ *
+ * 1. **Conversations**: Top-level containers that represent a dialogue with a specific agent. Each conversation has a unique ID, is associated with an agent by name, and belongs to the user who created it. Conversations can include optional metadata for tracking app-specific context like ticket IDs, categories, or custom fields.
+ *
+ * 2. **Messages**: Individual exchanges within a conversation. Each message has a role, content, and optional metadata like token usage, tool calls, file attachments, and reasoning information. Messages are stored as an array within their parent conversation.
+ *
+ * This module is available to use with a client in all authentication modes:
+ *
+ * - **Anonymous or User authentication** (`base44.agents`): Access is scoped to the current user's permissions. Anonymous users can create conversations but can't retrieve them later, while authenticated users can access conversations they created.
+ * - **Service role authentication** (`base44.asServiceRole.agents`): Operations have elevated admin-level permissions. Can access all conversations that the app's admin role has access to.
+ *
+ */
+export interface AgentsModule {
+ /**
+ * Gets all conversations from all agents in the app.
+ *
+ * Retrieves all conversations. Use {@linkcode listConversations | listConversations()} to filter which conversations are returned, apply sorting, or paginate results. Use {@linkcode getConversation | getConversation()} to retrieve a specific conversation by ID.
+ *
+ * @returns Promise resolving to an array of conversations.
+ *
+ * @example
+ * ```typescript
+ * // Get all conversations
+ * const conversations = await base44.agents.getConversations();
+ * console.log(`Total conversations: ${conversations.length}`);
+ * ```
+ *
+ * @see {@linkcode listConversations | listConversations()} for filtering, sorting, and pagination
+ * @see {@linkcode getConversation | getConversation()} for retrieving a specific conversation by ID
+ */
+ getConversations(): Promise;
+
+ /**
+ * Gets a specific conversation by ID.
+ *
+ * Retrieves a single conversation using its unique identifier. To retrieve
+ * all conversations, use {@linkcode getConversations | getConversations()} To filter, sort, or paginate conversations, use {@linkcode listConversations | listConversations()}.
+ *
+ * @param conversationId - The unique identifier of the conversation.
+ * @returns Promise resolving to the conversation, or undefined if not found.
+ *
+ * @example
+ * ```typescript
+ * // Get a specific conversation by ID
+ * const conversation = await base44.agents.getConversation('conv-123');
+ * if (conversation) {
+ * console.log(`Conversation has ${conversation.messages.length} messages`);
+ * }
+ * ```
+ *
+ * @see {@linkcode getConversations | getConversations()} for retrieving all conversations
+ * @see {@linkcode listConversations | listConversations()} for filtering and sorting conversations
+ */
+ getConversation(
+ conversationId: string
+ ): Promise;
+
+ /**
+ * Lists conversations with filtering, sorting, and pagination.
+ *
+ * Provides querying capabilities including filtering by fields, sorting, pagination, and field selection. For cases where you need all conversations without filtering, use {@linkcode getConversations | getConversations()}. To retrieve a specific conversation by ID, use {@linkcode getConversation | getConversation()}.
+ *
+ * @param filterParams - Filter parameters for querying conversations.
+ * @returns Promise resolving to an array of filtered conversations.
+ *
+ * @example
+ * ```typescript
+ * // List recent conversations with pagination
+ * const recentConversations = await base44.agents.listConversations({
+ * limit: 10,
+ * sort: '-created_date'
+ * });
+ * ```
+ *
+ * @example
+ * ```typescript
+ * // Filter by agent and metadata
+ * const supportConversations = await base44.agents.listConversations({
+ * q: {
+ * agent_name: 'support-agent',
+ * 'metadata.priority': 'high'
+ * },
+ * sort: '-created_date',
+ * limit: 20
+ * });
+ * ```
+ *
+ * @see {@linkcode getConversations | getConversations()} for retrieving all conversations without filtering
+ * @see {@linkcode getConversation | getConversation()} for retrieving a specific conversation by ID
+ */
+ listConversations(
+ filterParams: ModelFilterParams
+ ): Promise;
+
+ /**
+ * Creates a new conversation with an agent.
+ *
+ * @param conversation - Conversation details including agent name and optional metadata.
+ * @returns Promise resolving to the created conversation.
+ *
+ * @example
+ * ```typescript
+ * // Create a new conversation with metadata
+ * const conversation = await base44.agents.createConversation({
+ * agent_name: 'support-agent',
+ * metadata: {
+ * order_id: 'ORD-789',
+ * product_id: 'PROD-456',
+ * category: 'technical-support'
+ * }
+ * });
+ * console.log(`Created conversation: ${conversation.id}`);
+ * ```
+ */
+ createConversation(
+ conversation: CreateConversationParams
+ ): Promise;
+
+ /**
+ * Adds a message to a conversation.
+ *
+ * Sends a message to the agent and updates the conversation. This method
+ * also updates the real-time socket to notify any subscribers.
+ *
+ * @param conversation - The conversation to add the message to.
+ * @param message - The message to add.
+ * @returns Promise resolving to the created message.
+ *
+ * @example
+ * ```typescript
+ * // Send a message to the agent
+ * const message = await base44.agents.addMessage(conversation, {
+ * role: 'user',
+ * content: 'Hello, I need help with my order #12345'
+ * });
+ * console.log(`Message sent with ID: ${message.id}`);
+ * ```
+ */
+ addMessage(
+ conversation: AgentConversation,
+ message: Partial
+ ): Promise;
+
+ /**
+ * Subscribes to real-time updates for a conversation.
+ *
+ * Establishes a WebSocket connection to receive instant updates when new
+ * messages are added to the conversation. Returns an unsubscribe function
+ * to clean up the connection.
+ *
+ * @param conversationId - The conversation ID to subscribe to.
+ * @param onUpdate - Callback function called when the conversation is updated.
+ * @returns Unsubscribe function to stop receiving updates.
+ *
+ * @example
+ * ```typescript
+ * // Subscribe to real-time updates
+ * const unsubscribe = base44.agents.subscribeToConversation(
+ * 'conv-123',
+ * (updatedConversation) => {
+ * const latestMessage = updatedConversation.messages[updatedConversation.messages.length - 1];
+ * console.log('New message:', latestMessage.content);
+ * }
+ * );
+ *
+ * // Later, clean up the subscription
+ * unsubscribe();
+ * ```
+ */
+ subscribeToConversation(
+ conversationId: string,
+ onUpdate?: (conversation: AgentConversation) => void
+ ): () => void;
+
+ /**
+ * Gets WhatsApp connection URL for an agent.
+ *
+ * Generates a URL that users can use to connect with the agent through WhatsApp.
+ * The URL includes authentication if a token is available.
+ *
+ * @param agentName - The name of the agent.
+ * @returns WhatsApp connection URL.
+ *
+ * @example
+ * ```typescript
+ * // Get WhatsApp connection URL
+ * const whatsappUrl = base44.agents.getWhatsAppConnectURL('support-agent');
+ * console.log(`Connect through WhatsApp: ${whatsappUrl}`);
+ * // User can open this URL to start a WhatsApp conversation
+ * ```
+ */
+ getWhatsAppConnectURL(agentName: string): string;
+}
diff --git a/src/modules/app-logs.ts b/src/modules/app-logs.ts
index b461cb9..ec072f8 100644
--- a/src/modules/app-logs.ts
+++ b/src/modules/app-logs.ts
@@ -1,43 +1,36 @@
import { AxiosInstance } from "axios";
+import { AppLogsModule } from "./app-logs.types";
/**
- * Creates the app logs module for the Base44 SDK
- * @param {AxiosInstance} axios - Axios instance
- * @param {string} appId - Application ID
- * @returns {Object} App logs module
+ * Creates the app logs module for the Base44 SDK.
+ *
+ * @param axios - Axios instance
+ * @param appId - Application ID
+ * @returns App logs module with methods for tracking and analyzing app usage
+ * @internal
*/
-export function createAppLogsModule(axios: AxiosInstance, appId: string) {
+export function createAppLogsModule(
+ axios: AxiosInstance,
+ appId: string
+): AppLogsModule {
const baseURL = `/app-logs/${appId}`;
return {
- /**
- * Log user activity in the app
- * @param {string} pageName - Name of the page being visited
- * @returns {Promise}
- */
+ // Log user activity in the app
async logUserInApp(pageName: string): Promise {
await axios.post(`${baseURL}/log-user-in-app/${pageName}`);
},
- /**
- * Fetch app logs with optional parameters
- * @param {Object} params - Query parameters for filtering logs
- * @returns {Promise} App logs data
- */
+ // Fetch app logs with optional parameters
async fetchLogs(params: Record = {}): Promise {
const response = await axios.get(baseURL, { params });
return response;
},
- /**
- * Get app statistics
- * @param {Object} params - Query parameters for filtering stats
- * @returns {Promise} App statistics
- */
+ // Get app statistics
async getStats(params: Record = {}): Promise {
const response = await axios.get(`${baseURL}/stats`, { params });
return response;
},
};
}
-
diff --git a/src/modules/app-logs.types.ts b/src/modules/app-logs.types.ts
new file mode 100644
index 0000000..ab1b9b7
--- /dev/null
+++ b/src/modules/app-logs.types.ts
@@ -0,0 +1,46 @@
+/**
+ * App Logs module for tracking and analyzing app usage.
+ *
+ * This module provides a method to log user activity. The logs are reflected in the Analytics page in the app dashboard.
+ *
+ * This module is available to use with a client in all authentication modes.
+ */
+export interface AppLogsModule {
+ /**
+ * Log user activity in the app.
+ *
+ * Records when a user visits a specific page or section of the app. Useful for tracking user navigation patterns and popular features. The logs are reflected in the Analytics page in the app dashboard.
+ *
+ * The specified page name doesn't have to be the name of an actual page in the app, it can be any string you want to use to track the activity.
+ *
+ * @param pageName - Name of the page or section being visited.
+ * @returns Promise that resolves when the log is recorded.
+ *
+ * @example
+ * ```typescript
+ * // Log page visit or feature usage
+ * await base44.appLogs.logUserInApp('home');
+ * await base44.appLogs.logUserInApp('features-section');
+ * await base44.appLogs.logUserInApp('button-click');
+ * ```
+ */
+ logUserInApp(pageName: string): Promise;
+
+ /**
+ * Fetch app logs with optional parameters.
+ *
+ * @param params - Optional query parameters for filtering logs.
+ * @returns Promise resolving to the logs data.
+ * @internal
+ */
+ fetchLogs(params?: Record): Promise;
+
+ /**
+ * Get app statistics.
+ *
+ * @param params - Optional query parameters for filtering stats.
+ * @returns Promise resolving to the stats data.
+ * @internal
+ */
+ getStats(params?: Record): Promise;
+}
diff --git a/src/modules/app.types.ts b/src/modules/app.types.ts
index fc2f360..680126c 100644
--- a/src/modules/app.types.ts
+++ b/src/modules/app.types.ts
@@ -1,5 +1,6 @@
-
-
+/**
+ * @internal
+ */
export interface AppMessageContent {
content?: string;
file_urls?: string[];
@@ -8,11 +9,17 @@ export interface AppMessageContent {
[key: string]: unknown;
}
+/**
+ * @internal
+ */
export interface AppConversationMessage extends AppMessageContent {
id?: string | null;
role?: "user" | "assistant" | string;
}
+/**
+ * @internal
+ */
export interface AppConversationLike {
id?: string | null;
messages?: AppMessageContent[] | null;
@@ -20,15 +27,19 @@ export interface AppConversationLike {
functions_fail_silently?: boolean;
}
-
-export interface DenoProjectLike {
- project_id: string
- project_name: string
- app_id: string
- deployment_name_to_info: Record
-
+/**
+ * @internal
+ */
+export interface DenoProjectLike {
+ project_id: string;
+ project_name: string;
+ app_id: string;
+ deployment_name_to_info: Record;
}
+/**
+ * @internal
+ */
export interface AppLike {
id?: string;
conversation?: AppConversationLike | null;
@@ -48,7 +59,12 @@ export interface AppLike {
agents?: Record;
logo_url?: string;
slug?: string;
- public_settings?: "private_with_login" | "public_with_login" | "public_without_login" | "workspace_with_login" | string;
+ public_settings?:
+ | "private_with_login"
+ | "public_with_login"
+ | "public_without_login"
+ | "workspace_with_login"
+ | string;
is_blocked?: boolean;
github_repo_url?: string;
main_page?: string;
@@ -79,13 +95,19 @@ export interface AppLike {
function_names?: string[];
user_entity?: UserEntityLike;
app_code_hash?: string;
- has_backend_functions_enabled?: boolean;
+ has_backend_functions_enabled?: boolean;
}
+/**
+ * @internal
+ */
export interface UserLike {
id?: string | null;
}
+/**
+ * @internal
+ */
export interface UserEntityLike {
type: string;
name: string;
@@ -108,7 +130,9 @@ export interface UserEntityLike {
required: string[];
}
-
+/**
+ * @internal
+ */
export interface AuthConfigLike {
enable_username_password?: boolean;
enable_google_login?: boolean;
@@ -118,9 +142,9 @@ export interface AuthConfigLike {
enable_sso_login?: boolean;
}
-
-
-
+/**
+ * @internal
+ */
export type LoginInfoResponse = Pick<
AppLike,
| "id"
@@ -132,4 +156,4 @@ export type LoginInfoResponse = Pick<
| "created_date"
| "auth_config"
| "platform_version"
->;
\ No newline at end of file
+>;
diff --git a/src/modules/auth.ts b/src/modules/auth.ts
index 412b65a..0736da2 100644
--- a/src/modules/auth.ts
+++ b/src/modules/auth.ts
@@ -1,43 +1,40 @@
import { AxiosInstance } from "axios";
+import {
+ AuthModule,
+ AuthModuleOptions,
+ VerifyOtpParams,
+ ChangePasswordParams,
+ ResetPasswordParams,
+} from "./auth.types";
/**
- * Creates the auth module for the Base44 SDK
- * @param {import('axios').AxiosInstance} axios - Axios instance
- * @param {string|number} appId - Application ID
- * @param {string} serverUrl - Server URL
- * @returns {Object} Auth module with authentication methods
+ * Creates the auth module for the Base44 SDK.
+ *
+ * @param axios - Axios instance for API requests
+ * @param functionsAxiosClient - Axios instance for functions API requests
+ * @param appId - Application ID
+ * @param options - Configuration options including server URLs
+ * @returns Auth module with authentication and user management methods
+ * @internal
*/
export function createAuthModule(
axios: AxiosInstance,
functionsAxiosClient: AxiosInstance,
appId: string,
- options: {
- serverUrl: string;
- appBaseUrl?: string;
- }
-) {
+ options: AuthModuleOptions
+): AuthModule {
return {
- /**
- * Get current user information
- * @returns {Promise