@mintlify/cli 4.0.1813 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/dist/assets/export-scripts/README.classic.md +15 -0
  2. package/dist/assets/export-scripts/README.md +14 -0
  3. package/dist/assets/export-scripts/serve.js +114 -0
  4. package/dist/assets/export-scripts/start-docs.bat +10 -0
  5. package/dist/assets/export-scripts/start-docs.sh +9 -0
  6. package/dist/assets/og/Inter-Bold.ttf +0 -0
  7. package/dist/assets/og/Inter-Medium.ttf +0 -0
  8. package/dist/assets/og/Inter-Regular.ttf +0 -0
  9. package/dist/assets/og/Inter-SemiBold.ttf +0 -0
  10. package/dist/assets/og/PaperMono-Regular.ttf +0 -0
  11. package/dist/assets/og/index_bg.wasm +0 -0
  12. package/dist/assets/openChrome.applescript +94 -0
  13. package/dist/assets/socket.io/socket.io.esm.min.js +7 -0
  14. package/dist/assets/socket.io/socket.io.esm.min.js.map +1 -0
  15. package/dist/assets/socket.io/socket.io.js +4907 -0
  16. package/dist/assets/socket.io/socket.io.js.map +1 -0
  17. package/dist/assets/socket.io/socket.io.min.js +7 -0
  18. package/dist/assets/socket.io/socket.io.min.js.map +1 -0
  19. package/dist/assets/socket.io/socket.io.msgpack.min.js +7 -0
  20. package/dist/assets/socket.io/socket.io.msgpack.min.js.map +1 -0
  21. package/dist/assets/xdg-open +1066 -0
  22. package/dist/assets/yargs-locales/be.json +46 -0
  23. package/dist/assets/yargs-locales/cs.json +51 -0
  24. package/dist/assets/yargs-locales/de.json +46 -0
  25. package/dist/assets/yargs-locales/en.json +55 -0
  26. package/dist/assets/yargs-locales/es.json +46 -0
  27. package/dist/assets/yargs-locales/fi.json +49 -0
  28. package/dist/assets/yargs-locales/fr.json +53 -0
  29. package/dist/assets/yargs-locales/hi.json +49 -0
  30. package/dist/assets/yargs-locales/hu.json +46 -0
  31. package/dist/assets/yargs-locales/id.json +50 -0
  32. package/dist/assets/yargs-locales/it.json +46 -0
  33. package/dist/assets/yargs-locales/ja.json +51 -0
  34. package/dist/assets/yargs-locales/ko.json +49 -0
  35. package/dist/assets/yargs-locales/nb.json +44 -0
  36. package/dist/assets/yargs-locales/nl.json +49 -0
  37. package/dist/assets/yargs-locales/nn.json +44 -0
  38. package/dist/assets/yargs-locales/pirate.json +13 -0
  39. package/dist/assets/yargs-locales/pl.json +49 -0
  40. package/dist/assets/yargs-locales/pt.json +45 -0
  41. package/dist/assets/yargs-locales/pt_BR.json +48 -0
  42. package/dist/assets/yargs-locales/ru.json +51 -0
  43. package/dist/assets/yargs-locales/th.json +46 -0
  44. package/dist/assets/yargs-locales/tr.json +48 -0
  45. package/dist/assets/yargs-locales/uk_UA.json +51 -0
  46. package/dist/assets/yargs-locales/uz.json +52 -0
  47. package/dist/assets/yargs-locales/zh_CN.json +48 -0
  48. package/dist/assets/yargs-locales/zh_TW.json +51 -0
  49. package/dist/converter-d8O3xkdU.js +102 -0
  50. package/dist/devtools-CGNZQKFV.js +24 -0
  51. package/dist/index.js +8 -0
  52. package/dist/rolldown-runtime-CEAe2Uac.js +7 -0
  53. package/dist/schemas-CBsmCNpK.js +372 -0
  54. package/dist/start.js +2310 -0
  55. package/package.json +38 -31
  56. package/.oxlintrc.json +0 -5
  57. package/.prettierignore +0 -2
  58. package/.turbo/turbo-build.log +0 -1
  59. package/CONTRIBUTING.md +0 -45
  60. package/__test__/agent-auth.test.ts +0 -114
  61. package/__test__/agent-claim.test.ts +0 -164
  62. package/__test__/agent-credentials.test.ts +0 -149
  63. package/__test__/agent-deployment.test.ts +0 -106
  64. package/__test__/agent-setup-config.test.ts +0 -324
  65. package/__test__/agent-setup.test.ts +0 -207
  66. package/__test__/agent.test.ts +0 -64
  67. package/__test__/analytics/client.test.ts +0 -180
  68. package/__test__/analytics/dates.test.ts +0 -12
  69. package/__test__/analytics/filters.test.ts +0 -116
  70. package/__test__/analytics/format.test.ts +0 -137
  71. package/__test__/authenticatedFetch.test.ts +0 -182
  72. package/__test__/brokenLinks.test.ts +0 -283
  73. package/__test__/checkPort.test.ts +0 -92
  74. package/__test__/deploy-github-actions.test.ts +0 -202
  75. package/__test__/deploy-github-setup.test.ts +0 -240
  76. package/__test__/deploy-instructions.test.ts +0 -155
  77. package/__test__/deploy.test.ts +0 -202
  78. package/__test__/feedback.test.ts +0 -34
  79. package/__test__/foreignSyntax.test.ts +0 -73
  80. package/__test__/format.test.ts +0 -72
  81. package/__test__/helpers.test.ts +0 -52
  82. package/__test__/init.test.ts +0 -119
  83. package/__test__/instructions.test.ts +0 -53
  84. package/__test__/keyring.test.ts +0 -82
  85. package/__test__/mdxAccessibility.test.ts +0 -81
  86. package/__test__/migrate.test.ts +0 -186
  87. package/__test__/openApiCheck.test.ts +0 -185
  88. package/__test__/pathValidation.test.ts +0 -25
  89. package/__test__/resolveFiles.test.ts +0 -70
  90. package/__test__/sessionId.test.ts +0 -46
  91. package/__test__/signup.test.ts +0 -36
  92. package/__test__/update.test.ts +0 -117
  93. package/__test__/utils.ts +0 -25
  94. package/__test__/validateCommand.test.ts +0 -647
  95. package/__test__/validateEngine.test.ts +0 -245
  96. package/__test__/validateRules.test.ts +0 -1275
  97. package/__test__/welcome.test.ts +0 -15
  98. package/__test__/workflows/client.test.ts +0 -126
  99. package/bin/accessibility.js +0 -111
  100. package/bin/accessibilityCheck.js +0 -82
  101. package/bin/addDomain.js +0 -130
  102. package/bin/agent-auth.js +0 -104
  103. package/bin/agent-claim.js +0 -97
  104. package/bin/agent-credentials.js +0 -124
  105. package/bin/agent-deployment.js +0 -96
  106. package/bin/agent-http.js +0 -45
  107. package/bin/agent-setup-config.js +0 -141
  108. package/bin/agent-setup.js +0 -146
  109. package/bin/agent.js +0 -42
  110. package/bin/analytics/client.js +0 -60
  111. package/bin/analytics/dates.js +0 -6
  112. package/bin/analytics/filters.js +0 -27
  113. package/bin/analytics/format.js +0 -13
  114. package/bin/analytics/index.js +0 -496
  115. package/bin/analytics/output.js +0 -75
  116. package/bin/analytics/types.js +0 -1
  117. package/bin/authenticatedFetch.js +0 -46
  118. package/bin/brokenLinks.js +0 -122
  119. package/bin/callbackServer.js +0 -65
  120. package/bin/cli.js +0 -813
  121. package/bin/comingSoon.js +0 -26
  122. package/bin/config.js +0 -78
  123. package/bin/constants.js +0 -16
  124. package/bin/deploy-base.js +0 -20
  125. package/bin/deploy-github-actions.js +0 -102
  126. package/bin/deploy-github-setup.js +0 -165
  127. package/bin/deploy-instructions.js +0 -71
  128. package/bin/deploy.js +0 -123
  129. package/bin/feedback.js +0 -36
  130. package/bin/format.js +0 -121
  131. package/bin/helpers.js +0 -238
  132. package/bin/idToken.js +0 -14
  133. package/bin/index.js +0 -102
  134. package/bin/init.js +0 -182
  135. package/bin/instructions.js +0 -101
  136. package/bin/keyring.js +0 -78
  137. package/bin/login.js +0 -123
  138. package/bin/logout.js +0 -18
  139. package/bin/mdxAccessibility.js +0 -113
  140. package/bin/mdxLinter.js +0 -55
  141. package/bin/middlewares/subdomainMiddleware.js +0 -28
  142. package/bin/middlewares/telemetryMiddleware.js +0 -61
  143. package/bin/migrate.js +0 -54
  144. package/bin/og.js +0 -145
  145. package/bin/openApiCheck.js +0 -99
  146. package/bin/resolveFiles.js +0 -114
  147. package/bin/score/client.js +0 -40
  148. package/bin/score/index.js +0 -211
  149. package/bin/score/types.js +0 -1
  150. package/bin/signup.js +0 -118
  151. package/bin/start.js +0 -36
  152. package/bin/status.js +0 -106
  153. package/bin/telemetry/client.js +0 -53
  154. package/bin/telemetry/distinctId.js +0 -68
  155. package/bin/telemetry/sessionId.js +0 -36
  156. package/bin/telemetry/track.js +0 -149
  157. package/bin/templates.js +0 -127
  158. package/bin/tokenRefresh.js +0 -50
  159. package/bin/tsconfig.build.tsbuildinfo +0 -1
  160. package/bin/update.js +0 -65
  161. package/bin/validate/command.js +0 -127
  162. package/bin/validate/engine.js +0 -154
  163. package/bin/validate/files.js +0 -163
  164. package/bin/validate/mdx.js +0 -238
  165. package/bin/validate/output.js +0 -44
  166. package/bin/validate/report.js +0 -11
  167. package/bin/validate/rules/build.js +0 -102
  168. package/bin/validate/rules/content/duplicateH1.js +0 -57
  169. package/bin/validate/rules/content/foreignSyntax.js +0 -120
  170. package/bin/validate/rules/content/katex.js +0 -34
  171. package/bin/validate/rules/content/missingSnippet.js +0 -34
  172. package/bin/validate/rules/content/undefinedVariable.js +0 -13
  173. package/bin/validate/rules/content/unknownComponent.js +0 -121
  174. package/bin/validate/rules/content/voidTags.js +0 -38
  175. package/bin/validate/rules/index.js +0 -21
  176. package/bin/validate/rules/openapi.js +0 -50
  177. package/bin/validate/rules/parseError.js +0 -7
  178. package/bin/validate/site.js +0 -57
  179. package/bin/validate/types.js +0 -1
  180. package/bin/vendor/converter.js +0 -30882
  181. package/bin/welcome.js +0 -108
  182. package/bin/workflows/client.js +0 -34
  183. package/bin/workflows/index.js +0 -269
  184. package/bin/workflows/types.js +0 -11
  185. package/scripts/bundle-converter.mjs +0 -26
  186. package/scripts/generate-logo.mjs +0 -79
  187. package/src/accessibility.ts +0 -180
  188. package/src/accessibilityCheck.tsx +0 -150
  189. package/src/addDomain.tsx +0 -206
  190. package/src/agent-auth.ts +0 -119
  191. package/src/agent-claim.ts +0 -124
  192. package/src/agent-credentials.ts +0 -104
  193. package/src/agent-deployment.ts +0 -116
  194. package/src/agent-http.ts +0 -34
  195. package/src/agent-setup-config.ts +0 -144
  196. package/src/agent-setup.ts +0 -165
  197. package/src/agent.ts +0 -56
  198. package/src/analytics/client.ts +0 -153
  199. package/src/analytics/dates.ts +0 -6
  200. package/src/analytics/filters.ts +0 -50
  201. package/src/analytics/format.ts +0 -13
  202. package/src/analytics/index.tsx +0 -599
  203. package/src/analytics/output.ts +0 -99
  204. package/src/analytics/types.ts +0 -145
  205. package/src/authenticatedFetch.ts +0 -42
  206. package/src/brokenLinks.tsx +0 -152
  207. package/src/callbackServer.ts +0 -64
  208. package/src/cli.tsx +0 -1105
  209. package/src/comingSoon.tsx +0 -29
  210. package/src/config.ts +0 -75
  211. package/src/constants.ts +0 -28
  212. package/src/deploy-base.ts +0 -18
  213. package/src/deploy-github-actions.ts +0 -139
  214. package/src/deploy-github-setup.ts +0 -189
  215. package/src/deploy-instructions.ts +0 -76
  216. package/src/deploy.ts +0 -165
  217. package/src/feedback.tsx +0 -31
  218. package/src/format.tsx +0 -82
  219. package/src/helpers.tsx +0 -279
  220. package/src/idToken.ts +0 -17
  221. package/src/index.ts +0 -109
  222. package/src/init.tsx +0 -237
  223. package/src/instructions.ts +0 -99
  224. package/src/keyring.ts +0 -65
  225. package/src/login.tsx +0 -166
  226. package/src/logout.tsx +0 -8
  227. package/src/mdxAccessibility.ts +0 -134
  228. package/src/mdxLinter.tsx +0 -88
  229. package/src/middlewares/subdomainMiddleware.ts +0 -20
  230. package/src/middlewares/telemetryMiddleware.ts +0 -55
  231. package/src/migrate.ts +0 -76
  232. package/src/og.tsx +0 -185
  233. package/src/openApiCheck.tsx +0 -125
  234. package/src/resolveFiles.ts +0 -101
  235. package/src/score/client.ts +0 -36
  236. package/src/score/index.tsx +0 -205
  237. package/src/score/types.ts +0 -15
  238. package/src/signup.tsx +0 -172
  239. package/src/start.ts +0 -27
  240. package/src/status.tsx +0 -129
  241. package/src/telemetry/client.ts +0 -46
  242. package/src/telemetry/distinctId.ts +0 -70
  243. package/src/telemetry/sessionId.ts +0 -40
  244. package/src/telemetry/track.ts +0 -163
  245. package/src/templates.tsx +0 -143
  246. package/src/tokenRefresh.ts +0 -53
  247. package/src/update.tsx +0 -89
  248. package/src/validate/command.tsx +0 -135
  249. package/src/validate/engine.ts +0 -210
  250. package/src/validate/files.ts +0 -249
  251. package/src/validate/mdx.ts +0 -290
  252. package/src/validate/output.tsx +0 -76
  253. package/src/validate/report.ts +0 -40
  254. package/src/validate/rules/build.ts +0 -146
  255. package/src/validate/rules/content/duplicateH1.ts +0 -78
  256. package/src/validate/rules/content/foreignSyntax.ts +0 -144
  257. package/src/validate/rules/content/katex.ts +0 -33
  258. package/src/validate/rules/content/missingSnippet.ts +0 -36
  259. package/src/validate/rules/content/undefinedVariable.ts +0 -20
  260. package/src/validate/rules/content/unknownComponent.ts +0 -130
  261. package/src/validate/rules/content/voidTags.ts +0 -43
  262. package/src/validate/rules/index.ts +0 -23
  263. package/src/validate/rules/openapi.ts +0 -59
  264. package/src/validate/rules/parseError.ts +0 -9
  265. package/src/validate/site.ts +0 -53
  266. package/src/validate/types.ts +0 -102
  267. package/src/vendor/converter.ts +0 -1
  268. package/src/welcome.ts +0 -154
  269. package/src/workflows/client.ts +0 -39
  270. package/src/workflows/index.tsx +0 -287
  271. package/src/workflows/types.ts +0 -73
  272. package/tsconfig.build.json +0 -4
  273. package/tsconfig.json +0 -10
  274. package/vitest.config.ts +0 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mintlify/cli",
3
- "version": "4.0.1813",
3
+ "version": "4.1.1",
4
4
  "description": "The Mintlify CLI",
5
5
  "engines": {
6
6
  "node": ">=18.0.0"
@@ -25,18 +25,22 @@
25
25
  "url": "https://github.com/mintlify/mint",
26
26
  "directory": "packages/cli"
27
27
  },
28
- "exports": "./bin/index.js",
28
+ "files": [
29
+ "dist",
30
+ "migrate"
31
+ ],
32
+ "exports": "./dist/index.js",
29
33
  "bin": {
30
- "mint": "bin/index.js",
31
- "mintlify": "bin/index.js"
34
+ "mint": "dist/index.js",
35
+ "mintlify": "dist/index.js"
32
36
  },
33
37
  "scripts": {
34
38
  "dev": "pnpm build && NODE_NO_WARNINGS=1 node bin/index.js",
35
39
  "prepack": "npm run build",
36
- "build": "tsc --project tsconfig.build.json && node scripts/bundle-converter.mjs",
37
- "clean:build": "rimraf bin",
40
+ "build": "tsc --project tsconfig.build.json && node scripts/bundle-converter.mjs && node scripts/bundle.ts",
41
+ "clean:build": "rimraf bin dist",
38
42
  "clean:all": "rimraf node_modules .eslintcache && pnpm clean:build",
39
- "watch": "tsc --watch",
43
+ "watch": "node scripts/watch.ts",
40
44
  "lint": "oxlint src",
41
45
  "test": "vitest run",
42
46
  "type": "tsgo --noEmit",
@@ -44,18 +48,35 @@
44
48
  "format:check": "oxfmt --check"
45
49
  },
46
50
  "dependencies": {
51
+ "sharp": "0.33.5"
52
+ },
53
+ "optionalDependencies": {
54
+ "@mintlify/package-builder": "0.0.138",
55
+ "fsevents": "2.3.3",
56
+ "keytar": "7.9.0"
57
+ },
58
+ "devDependencies": {
47
59
  "@inquirer/prompts": "7.9.0",
48
60
  "@mintlify/common": "1.0.1349",
61
+ "@mintlify/editor": "0.0.627",
49
62
  "@mintlify/link-rot": "3.0.1591",
50
63
  "@mintlify/models": "0.0.389",
51
64
  "@mintlify/og": "0.0.148",
52
65
  "@mintlify/prebuild": "1.0.1522",
53
66
  "@mintlify/previewing": "4.0.1609",
67
+ "@mintlify/ts-config": "2.0.2",
54
68
  "@mintlify/validation": "0.1.962",
69
+ "@tsconfig/recommended": "1.0.2",
70
+ "@types/detect-port": "1.3.2",
71
+ "@types/keytar": "4.4.2",
72
+ "@types/mdast": "4.0.4",
73
+ "@types/node": "18.15.0",
74
+ "@types/yargs": "17.0.22",
55
75
  "adm-zip": "0.6.0",
56
76
  "chalk": "5.2.0",
57
77
  "color": "4.2.3",
58
78
  "detect-port": "1.5.1",
79
+ "esbuild": "0.25.12",
59
80
  "fs-extra": "11.2.0",
60
81
  "html-void-elements": "3.0.0",
61
82
  "ink": "6.3.0",
@@ -65,7 +86,11 @@
65
86
  "katex": "0.16.47",
66
87
  "mdast-util-mdx-jsx": "3.2.0",
67
88
  "open": "8.4.2",
89
+ "openapi-types": "12.1.3",
68
90
  "openid-client": "6.8.2",
91
+ "oxfmt": "^0.51.0",
92
+ "oxlint": "1.66.0",
93
+ "oxlint-tsgolint": "^0.23.0",
69
94
  "posthog-node": "5.17.2",
70
95
  "prosemirror-model": "1.25.4",
71
96
  "react": "19.2.3",
@@ -76,35 +101,17 @@
76
101
  "remark-mdx": "3.1.1",
77
102
  "remark-smartypants": "3.0.2",
78
103
  "remark-stringify": "11.0.0",
104
+ "rimraf": "5.0.1",
105
+ "rolldown": "1.2.14",
79
106
  "smol-toml": "1.6.0",
107
+ "typescript": "5.5.3",
80
108
  "unified": "11.0.5",
81
109
  "unist-util-visit": "5.0.0",
110
+ "vitest": "2.1.9",
111
+ "vitest-mock-process": "1.0.4",
82
112
  "yaml": "2.8.3",
83
113
  "yargs": "17.7.1",
84
114
  "zod": "4.3.6"
85
115
  },
86
- "optionalDependencies": {
87
- "keytar": "7.9.0"
88
- },
89
- "devDependencies": {
90
- "@mintlify/editor": "0.0.627",
91
- "@mintlify/ts-config": "2.0.2",
92
- "@tsconfig/recommended": "1.0.2",
93
- "@types/detect-port": "1.3.2",
94
- "@types/keytar": "4.4.2",
95
- "@types/mdast": "4.0.4",
96
- "@types/node": "18.15.0",
97
- "@types/yargs": "17.0.22",
98
- "esbuild": "0.25.12",
99
- "openapi-types": "12.1.3",
100
- "oxfmt": "^0.51.0",
101
- "oxlint": "1.66.0",
102
- "oxlint-tsgolint": "^0.23.0",
103
- "rimraf": "5.0.1",
104
- "sharp": "^0.33.1",
105
- "typescript": "5.5.3",
106
- "vitest": "2.1.9",
107
- "vitest-mock-process": "1.0.4"
108
- },
109
- "gitHead": "8ba12109669f80e5d70d3639460a775040ffba54"
116
+ "gitHead": "4836ab3b098b4bfa0ec91ba7e74e53b61108ce6c"
110
117
  }
package/.oxlintrc.json DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "$schema": "../../node_modules/oxlint/configuration_schema.json",
3
- "extends": ["../../oxlint.base.json"],
4
- "ignorePatterns": [".oxlintrc.json", "bin"]
5
- }
package/.prettierignore DELETED
@@ -1,2 +0,0 @@
1
- /bin
2
- /node_modules
@@ -1 +0,0 @@
1
- $ tsc --project tsconfig.build.json && node scripts/bundle-converter.mjs
package/CONTRIBUTING.md DELETED
@@ -1,45 +0,0 @@
1
- # Running CLI Locally
2
-
3
- Note: contributing requires `pnpm` and it's recommended you install it as a global installation. If you don't have pnpm installed already run `npm install -g pnpm` in your terminal.
4
-
5
- Run `./scripts/with-registry-auth.sh pnpm install` from the repository root to install dependencies. Then, run `npm link` once to link to your local version of the CLI in the npm global namespace (`npm list -g`). Make sure you are working in `packages/cli` and not its alias package, `packages/mintlify`.
6
-
7
- If you already have a non-local version of the CLI, you will need to uninstall it (`npm uninstall -g mint`) or force overwrite the executable file. Otherwise, you will get an `EEXIST` error on the mintlify binary. You can overwrite the file using the `--force` flag (`npm link --force`), but always double check the file(s) you are overwriting.
8
-
9
- Make sure to build the CLI using `pnpm build` or `pnpm watch` to see your local changes reflected. Tip: keep `pnpm watch` running in a separate terminal for changes to be quickly and continuously reflected while developing.
10
-
11
- To uninstall locally, run `npm uninstall -g @mintlify/cli`.
12
-
13
- If you wish to continue using the production version of the CLI, you will need to reinstall it (`npm install -g mint`). If you do not uninstall `@mintlify/cli`, then you will need to force overwrite the executable file (`npm install -g mint --force`) for the same reasons as mentioned above. As a best practice, we recommend always uninstalling `@mintlify/cli` first.
14
-
15
- ## Updating Version of Mint Client
16
-
17
- The CLI uses GitHub releases to download specific versions of the client code used in `mintlify dev`. It will attempt to fetch the latest version of the client app specified by our [`mint-version.txt`](https://d1ctpt7j8wusba.cloudfront.net/mint-version.txt) file. The mint-version.txt and compressed versions of the client live in S3 under `mint-client-releases`.
18
-
19
- Here's how new client changes are published, they should usually require no manual intervention:
20
-
21
- 1. When a PR is merged to main, we check whether or not the client app or any of its dependencies have changed with the `check-changes` workflow job
22
- 2. The `bump-packages` job always runs, which increments the version of any package that has changed in our monorepo packages, commits the version increment to github, and publishes the update to npm
23
- 3. If `check-changes` detected a client change, the `client-release` workflow is triggered after `bump-packages`
24
- 4. The `client-release` workflow creates a standalone zip of the client app and uploads it to S3 as mint-${version}.tar.gz
25
- 5. The `cli-test` workflow is triggered, which uses a local build of the CLI package and the new client version that was just zipped and shipped. It tests the CLI output has not changed (no new errors) and that the starter-kit passes some simple Puppeteer tests.
26
- 6. If the `cli-test` workflow passes, the `update-release-version` workflow is triggered, which uploads an updated version of the mint-version.txt file to S3 with the new version number, and invalidates the cache for that file.
27
-
28
- ## Manually triggering a client release and version update
29
-
30
- You can still create a new client version whenever by dispatching the `client-release` workflow from the [Actions tab for the mint repo](https://github.com/mintlify/mint/actions). Click the "Run workflow" dropdown button and enter the version number you want to set it to, then click the green "Run workflow" button. This should run the steps 4-6 detailed above, creating a new package of the client app and updating the version number used by the CLI.
31
-
32
- ## Manually updating the version of the client app used by the CLI
33
-
34
- If for some reason we need to roll back a client version, we can update the mint-version.txt file to swiftly change which version is downloaded by the CLI. This can be done 2 ways:
35
-
36
- 1. Via github workflow: Go to the [Actions tab for the mint repo](https://github.com/mintlify/mint/actions) and select the Update Release Version workflow. Click the "Run workflow" dropdown button and enter the version number you want to set it to, then click the green "Run workflow" button.
37
- 2. Manually: If you have S3 access, simply upload a new version of the mint-version.txt file in the `mint-client-releases` folder
38
-
39
- ## Manually uploading a packaged version of the client app
40
-
41
- If for some reason the release workflow is broken or we can't access AWS programmatically, the newly zipped version of the client app is retained in the `client-release` workflow as a Github artifact for 1 day. We can download it manually from Github after the release and upload it wherever needed.
42
-
43
- ## Manually overriding the client version used locally
44
-
45
- Run `mintlify dev --client-version x.x.xxxx` with the client version you would like to use and that version will be downloaded instead of the latest client version.
@@ -1,114 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from 'vitest';
2
-
3
- import {
4
- discoverAgentAuth,
5
- exchangeAgentToken,
6
- getAgentIdentity,
7
- registerAgent,
8
- } from '../src/agent-auth.js';
9
- import { agentRequest, AgentApiError } from '../src/agent-http.js';
10
-
11
- const issuer = 'https://auth.example.com';
12
- const discovery = {
13
- issuer,
14
- token_endpoint: `${issuer}/oauth2/token`,
15
- agent_auth: {
16
- identity_endpoint: `${issuer}/agent/identity`,
17
- claim_endpoint: `${issuer}/agent/identity/claim`,
18
- identity_types_supported: ['anonymous'],
19
- },
20
- };
21
- const credentials = {
22
- registrationId: 'reg_1',
23
- issuer,
24
- assertion: 'assertion-secret',
25
- claimToken: 'claim-secret',
26
- };
27
- function respond(body: unknown, status = 200) {
28
- return new Response(JSON.stringify(body), { status });
29
- }
30
- afterEach(() => vi.unstubAllGlobals());
31
-
32
- describe('agent authentication', () => {
33
- it('preserves caller cancellation alongside the request timeout', async () => {
34
- const controller = new AbortController();
35
- let requestSignal: AbortSignal | undefined;
36
- vi.stubGlobal(
37
- 'fetch',
38
- vi.fn(async (_url, init: RequestInit) => {
39
- requestSignal = init.signal ?? undefined;
40
- return respond({});
41
- })
42
- );
43
- await agentRequest('https://api.example.com', { signal: controller.signal });
44
- expect(requestSignal?.aborted).toBe(false);
45
- controller.abort();
46
- expect(requestSignal?.aborted).toBe(true);
47
- });
48
- it('discovers endpoints from Mintlify and validates their origin', async () => {
49
- const request = vi
50
- .fn()
51
- .mockResolvedValueOnce(respond({ authorization_servers: [issuer] }))
52
- .mockResolvedValueOnce(respond(discovery));
53
- vi.stubGlobal('fetch', request);
54
- expect(await discoverAgentAuth('https://api.example.com')).toEqual(discovery);
55
- expect(request.mock.calls[0]?.[0]).toBe(
56
- 'https://api.example.com/api/agent/.well-known/oauth-protected-resource'
57
- );
58
- });
59
- it('does not send credentials to endpoints on a different origin', async () => {
60
- vi.stubGlobal(
61
- 'fetch',
62
- vi
63
- .fn()
64
- .mockResolvedValueOnce(respond({ authorization_servers: [issuer] }))
65
- .mockResolvedValueOnce(
66
- respond({ ...discovery, token_endpoint: 'https://other.example.com/token' })
67
- )
68
- );
69
- await expect(discoverAgentAuth('https://api.example.com')).rejects.toThrow('do not match');
70
- });
71
- it('parses the hosted registration response and exchanges without resource', async () => {
72
- const request = vi
73
- .fn()
74
- .mockResolvedValueOnce(
75
- respond({
76
- id: 'reg_1',
77
- identity: { assertion: credentials.assertion },
78
- claim: { token: credentials.claimToken },
79
- })
80
- )
81
- .mockResolvedValueOnce(
82
- respond({ access_token: 'access', token_type: 'Bearer', expires_in: 300 })
83
- );
84
- vi.stubGlobal('fetch', request);
85
- expect(await registerAgent(discovery)).toEqual(credentials);
86
- expect((await exchangeAgentToken(discovery, credentials)).accessToken).toBe('access');
87
- const body = request.mock.calls[1]?.[1].body;
88
- expect(body.get('assertion')).toBe(credentials.assertion);
89
- expect(body.has('resource')).toBe(false);
90
- });
91
- it('sends the agent token without reading human credentials', async () => {
92
- const request = vi
93
- .fn()
94
- .mockResolvedValue(respond({ registrationId: 'reg_1', identityType: 'anonymous' }));
95
- vi.stubGlobal('fetch', request);
96
- await getAgentIdentity('https://api.example.com', 'agent-token');
97
- expect(request.mock.calls[0]?.[1].headers.Authorization).toBe('Bearer agent-token');
98
- });
99
- it('does not register again on outages or print upstream secrets', async () => {
100
- const request = vi
101
- .fn()
102
- .mockResolvedValue(respond({ error: 'unavailable', message: credentials.assertion }, 503));
103
- vi.stubGlobal('fetch', request);
104
- await expect(exchangeAgentToken(discovery, credentials)).rejects.toThrow(AgentApiError);
105
- expect(request).toHaveBeenCalledTimes(1);
106
- });
107
- it('rejects malformed successful responses without exposing them', async () => {
108
- vi.stubGlobal(
109
- 'fetch',
110
- vi.fn().mockResolvedValue(respond({ assertion: credentials.assertion }))
111
- );
112
- await expect(registerAgent(discovery)).rejects.toThrow('unexpected response');
113
- });
114
- });
@@ -1,164 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
-
3
- import { claimDeployment } from '../src/agent-claim.js';
4
- import { loadAgentCredentials, saveAgentCredentials } from '../src/agent-credentials.js';
5
- import { trackEvent } from '../src/telemetry/track.js';
6
-
7
- vi.mock('../src/agent-credentials.js', () => ({
8
- loadAgentCredentials: vi.fn(),
9
- saveAgentCredentials: vi.fn(),
10
- }));
11
- vi.mock('../src/telemetry/track.js', () => ({ trackEvent: vi.fn() }));
12
- const issuer = 'https://auth.example.com';
13
- const apiUrl = 'https://api.example.com';
14
- const options = { apiUrl, directory: '/docs', code: 'ABCDEFGH' };
15
- const original = {
16
- registrationId: 'reg',
17
- issuer,
18
- assertion: 'old-assertion',
19
- claimToken: 'secret-claim',
20
- accessToken: 'anonymous-token',
21
- accessTokenExpiresAt: Date.now() + 300_000,
22
- };
23
- const discovery = {
24
- issuer,
25
- token_endpoint: `${issuer}/oauth2/token`,
26
- agent_auth: {
27
- identity_endpoint: `${issuer}/agent/identity`,
28
- claim_endpoint: `${issuer}/agent/identity/claim`,
29
- identity_types_supported: ['anonymous'],
30
- },
31
- };
32
- const response = (body: unknown, status = 200) => new Response(JSON.stringify(body), { status });
33
- const fetchMock = vi.fn();
34
- beforeEach(() => {
35
- vi.resetAllMocks();
36
- vi.stubGlobal('fetch', fetchMock);
37
- vi.mocked(loadAgentCredentials).mockResolvedValue({ ...original });
38
- vi.mocked(saveAgentCredentials).mockResolvedValue(undefined);
39
- fetchMock.mockImplementation(async (url: string) => {
40
- if (url.endsWith('oauth-protected-resource'))
41
- return response({ authorization_servers: [issuer] });
42
- if (url.endsWith('oauth-authorization-server')) return response(discovery);
43
- if (url.endsWith('/complete'))
44
- return response({ identity: { assertion: 'claimed-assertion' } });
45
- if (url.endsWith('/oauth2/token'))
46
- return response({ access_token: 'claimed-token', expires_in: 300, token_type: 'Bearer' });
47
- if (url.endsWith('/signup')) return response({ orgId: 'org', claimed: true });
48
- if (url.endsWith('/claim'))
49
- return response({ attempt: { verification_uri: `${issuer}/verify?token=attempt` } });
50
- throw new Error('Unexpected endpoint');
51
- });
52
- });
53
- afterEach(() => vi.unstubAllGlobals());
54
-
55
- describe('claim command', () => {
56
- it('completes the existing claim, saves the new identity, and signs up with a fresh token', async () => {
57
- expect(await claimDeployment(options)).toContain('successfully');
58
- expect(fetchMock).toHaveBeenCalledWith(
59
- `${issuer}/agent/identity/claim/complete`,
60
- expect.objectContaining({
61
- body: JSON.stringify({ claim_token: 'secret-claim', user_code: options.code }),
62
- })
63
- );
64
- expect(fetchMock).not.toHaveBeenCalledWith(`${issuer}/agent/identity/claim`, expect.anything());
65
- expect(fetchMock).toHaveBeenCalledWith(
66
- `${apiUrl}/api/agent/signup`,
67
- expect.objectContaining({ headers: { Authorization: 'Bearer claimed-token' } })
68
- );
69
- expect(vi.mocked(saveAgentCredentials).mock.calls[0]?.[2]).toMatchObject({
70
- assertion: 'claimed-assertion',
71
- claimVerified: true,
72
- accessToken: undefined,
73
- });
74
- expect(vi.mocked(saveAgentCredentials).mock.invocationCallOrder[0]).toBeLessThan(
75
- fetchMock.mock.invocationCallOrder[3]!
76
- );
77
- expect(vi.mocked(trackEvent).mock.calls).toEqual([
78
- ['agent_signup.claim_completed', { registration_id: 'reg' }],
79
- ]);
80
- });
81
- it('resumes after signup fails without consuming the code again', async () => {
82
- const implementation = fetchMock.getMockImplementation()!;
83
- fetchMock.mockImplementation((url, init) =>
84
- url.endsWith('/signup') ? response({ code: 'unavailable' }, 503) : implementation(url, init)
85
- );
86
- await expect(claimDeployment(options)).rejects.toThrow('503');
87
- const saved = vi.mocked(saveAgentCredentials).mock.calls[0]![2];
88
- vi.mocked(loadAgentCredentials).mockResolvedValue(saved);
89
- fetchMock.mockClear().mockImplementation(implementation);
90
- expect(await claimDeployment(options)).toContain('successfully');
91
- expect(fetchMock.mock.calls.some(([url]) => url.endsWith('/complete'))).toBe(false);
92
- });
93
- it('does not save or sign up after an invalid code', async () => {
94
- const implementation = fetchMock.getMockImplementation()!;
95
- fetchMock.mockImplementation((url, init) =>
96
- url.endsWith('/complete')
97
- ? response({ code: 'invalid_user_code' }, 400)
98
- : implementation(url, init)
99
- );
100
- await expect(claimDeployment(options)).rejects.toThrow('invalid_user_code');
101
- expect(saveAgentCredentials).not.toHaveBeenCalled();
102
- expect(trackEvent).not.toHaveBeenCalled();
103
- expect(fetchMock.mock.calls.some(([url]) => url.endsWith('/signup'))).toBe(false);
104
- });
105
- it('fails before signup when credentials cannot be saved', async () => {
106
- vi.mocked(saveAgentCredentials).mockRejectedValue(new Error('disk full'));
107
- await expect(claimDeployment(options)).rejects.toThrow('disk full');
108
- expect(fetchMock.mock.calls.some(([url]) => url.endsWith('/signup'))).toBe(false);
109
- });
110
- it('creates only a claim link for --email', async () => {
111
- const output = await claimDeployment({
112
- apiUrl,
113
- directory: '/docs',
114
- email: 'person@example.com',
115
- });
116
- expect(new URL(output.match(/https?:\/\/\S+/)![0]).searchParams.get('registration')).toBe(
117
- 'reg'
118
- );
119
- expect(vi.mocked(trackEvent).mock.calls).toEqual([
120
- ['agent_signup.claim_started', { registration_id: 'reg' }],
121
- ]);
122
- expect(
123
- fetchMock.mock.calls.some(([url]) => url.endsWith('/signup') || url.endsWith('/complete'))
124
- ).toBe(false);
125
- });
126
- it('explains a claim link refused for too many pending attempts', async () => {
127
- const respond = fetchMock.getMockImplementation()!;
128
- fetchMock.mockImplementation(async (url: string) =>
129
- url.endsWith('/claim') ? response({ error: 'too_many_attempts' }, 429) : respond(url)
130
- );
131
- await expect(
132
- claimDeployment({ apiUrl, directory: '/docs', email: 'person@example.com' })
133
- ).rejects.toThrow('Too many claim links are still pending');
134
- });
135
- it('fails before network calls when credentials are missing', async () => {
136
- vi.mocked(loadAgentCredentials).mockResolvedValue(null);
137
- await expect(claimDeployment(options)).rejects.toThrow('No saved agent registration');
138
- expect(fetchMock).not.toHaveBeenCalled();
139
- });
140
- it.each([{ code: undefined }, { code: ' ', email: undefined }, { email: 'person@example.com' }])(
141
- 'rejects missing or conflicting arguments: %o',
142
- async (override) => {
143
- await expect(claimDeployment({ ...options, ...override })).rejects.toThrow('Provide either');
144
- expect(fetchMock).not.toHaveBeenCalled();
145
- }
146
- );
147
- it('rejects a different issuer without sending the claim token', async () => {
148
- vi.mocked(loadAgentCredentials).mockResolvedValue({
149
- ...original,
150
- issuer: 'https://other.example.com',
151
- });
152
- await expect(claimDeployment(options)).rejects.toThrow('another issuer');
153
- expect(fetchMock.mock.calls).toHaveLength(2);
154
- });
155
- it('does not report success if signup returns an anonymous identity', async () => {
156
- const implementation = fetchMock.getMockImplementation()!;
157
- fetchMock.mockImplementation((url, init) =>
158
- url.endsWith('/signup')
159
- ? response({ orgId: 'org', claimed: false })
160
- : implementation(url, init)
161
- );
162
- await expect(claimDeployment(options)).rejects.toThrow('unexpected response');
163
- });
164
- });
@@ -1,149 +0,0 @@
1
- import fs from 'node:fs';
2
- import os from 'node:os';
3
- import path from 'node:path';
4
- import { beforeEach, describe, expect, it, vi } from 'vitest';
5
-
6
- const entries = new Map<string, string>();
7
- const keytar = vi.hoisted(() => ({
8
- getPassword: vi.fn(),
9
- setPassword: vi.fn(),
10
- deletePassword: vi.fn(),
11
- }));
12
- vi.mock('../src/keyring.js', () => ({ getKeytar: async () => keytar }));
13
- const configDir = vi.hoisted(() => ({ path: '' }));
14
- vi.mock('../src/constants.js', () => ({
15
- get CONFIG_DIR() {
16
- return configDir.path;
17
- },
18
- }));
19
-
20
- import { loadAgentCredentials, saveAgentCredentials } from '../src/agent-credentials.js';
21
-
22
- const credentials = {
23
- registrationId: 'reg_1',
24
- issuer: 'https://auth.example.com',
25
- assertion: 'assertion',
26
- claimToken: 'claim',
27
- };
28
-
29
- describe('agent credentials', () => {
30
- beforeEach(() => {
31
- entries.clear();
32
- vi.resetAllMocks();
33
- configDir.path = fs.mkdtempSync(path.join(os.tmpdir(), 'mint-agent-'));
34
- keytar.getPassword.mockImplementation(
35
- async (service, account) => entries.get(`${service}/${account}`) ?? null
36
- );
37
- keytar.setPassword.mockImplementation(async (service, account, value) => {
38
- entries.set(`${service}/${account}`, value);
39
- });
40
- keytar.deletePassword.mockImplementation(async (service, account) =>
41
- entries.delete(`${service}/${account}`)
42
- );
43
- });
44
-
45
- it('isolates projects and environments from each other and human credentials', async () => {
46
- await saveAgentCredentials('https://api.example.com', '/docs', credentials);
47
- expect(await loadAgentCredentials('https://api.example.com', '/docs')).toEqual(credentials);
48
- expect(await loadAgentCredentials('https://dev.example.com', '/docs')).toBeNull();
49
- expect(await loadAgentCredentials('https://api.example.com', '/other')).toBeNull();
50
- expect([...entries.keys()].every((key) => key.startsWith('mintlify-agent/'))).toBe(true);
51
- });
52
-
53
- it('retains old registrations when the current project starts a new site', async () => {
54
- await saveAgentCredentials('https://api.example.com', '/docs', credentials);
55
- await saveAgentCredentials('https://api.example.com', '/docs', {
56
- ...credentials,
57
- registrationId: 'reg_2',
58
- });
59
- expect((await loadAgentCredentials('https://api.example.com', '/docs'))?.registrationId).toBe(
60
- 'reg_2'
61
- );
62
- expect(entries.has('mintlify-agent/https://api.example.com:reg_1')).toBe(true);
63
- });
64
-
65
- it('falls back to a local file when the keyring cannot be written or read', async () => {
66
- keytar.setPassword.mockRejectedValue(new Error('locked'));
67
- await saveAgentCredentials('https://api.example.com', '/docs', credentials);
68
- expect(entries.size).toBe(0);
69
- const file = path.join(configDir.path, 'agent-credentials.json');
70
- if (process.platform !== 'win32') expect(fs.statSync(file).mode & 0o777).toBe(0o600);
71
- keytar.getPassword.mockRejectedValue(new Error('locked'));
72
- expect(await loadAgentCredentials('https://api.example.com', '/docs')).toEqual(credentials);
73
- });
74
-
75
- it('removes stale fallback entries once the keyring is writable again', async () => {
76
- keytar.setPassword.mockRejectedValueOnce(new Error('locked'));
77
- await saveAgentCredentials('https://api.example.com', '/docs', credentials);
78
- await saveAgentCredentials('https://api.example.com', '/docs', {
79
- ...credentials,
80
- assertion: 'next',
81
- });
82
- expect((await loadAgentCredentials('https://api.example.com', '/docs'))?.assertion).toBe(
83
- 'next'
84
- );
85
- const file = path.join(configDir.path, 'agent-credentials.json');
86
- expect(JSON.parse(fs.readFileSync(file, 'utf-8'))).toEqual({});
87
- });
88
-
89
- it('reads the keyring before the fallback file', async () => {
90
- await saveAgentCredentials('https://api.example.com', '/docs', credentials);
91
- fs.writeFileSync(
92
- path.join(configDir.path, 'agent-credentials.json'),
93
- JSON.stringify({
94
- 'https://api.example.com:reg_1': JSON.stringify({ ...credentials, assertion: 'stale' }),
95
- })
96
- );
97
- expect(await loadAgentCredentials('https://api.example.com', '/docs')).toEqual(credentials);
98
- });
99
-
100
- it('ignores a corrupt fallback file when the keyring has the credentials', async () => {
101
- await saveAgentCredentials('https://api.example.com', '/docs', credentials);
102
- fs.writeFileSync(path.join(configDir.path, 'agent-credentials.json'), '{');
103
- expect(await loadAgentCredentials('https://api.example.com', '/docs')).toEqual(credentials);
104
- });
105
-
106
- it('drops the stale keyring entry when a write falls back to the file', async () => {
107
- await saveAgentCredentials('https://api.example.com', '/docs', credentials);
108
- keytar.setPassword.mockRejectedValueOnce(new Error('locked'));
109
- await saveAgentCredentials('https://api.example.com', '/docs', {
110
- ...credentials,
111
- assertion: 'next',
112
- });
113
- expect((await loadAgentCredentials('https://api.example.com', '/docs'))?.assertion).toBe(
114
- 'next'
115
- );
116
- });
117
-
118
- it('succeeds when the keyring write works but fallback cleanup fails', async () => {
119
- keytar.setPassword.mockRejectedValueOnce(new Error('locked'));
120
- await saveAgentCredentials('https://api.example.com', '/docs', credentials);
121
- fs.chmodSync(configDir.path, 0o500);
122
- await expect(
123
- saveAgentCredentials('https://api.example.com', '/docs', {
124
- ...credentials,
125
- assertion: 'next',
126
- })
127
- ).resolves.toBeUndefined();
128
- fs.chmodSync(configDir.path, 0o700);
129
- expect((await loadAgentCredentials('https://api.example.com', '/docs'))?.assertion).toBe(
130
- 'next'
131
- );
132
- });
133
-
134
- it('fails when neither the keyring nor the local file can be written', async () => {
135
- keytar.setPassword.mockRejectedValue(new Error('locked'));
136
- configDir.path = path.join(configDir.path, 'not-a-directory');
137
- fs.writeFileSync(configDir.path, '');
138
- await expect(
139
- saveAgentCredentials('https://api.example.com', '/docs', credentials)
140
- ).rejects.toThrow();
141
- });
142
-
143
- it('preserves read failures instead of treating them as an absent registration', async () => {
144
- keytar.getPassword.mockRejectedValueOnce(new Error('locked'));
145
- await expect(loadAgentCredentials('https://api.example.com', '/docs')).rejects.toThrow(
146
- 'locked'
147
- );
148
- });
149
- });