create-authenik8-app 2.4.14 → 2.4.15

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 (227) hide show
  1. package/README.md +34 -516
  2. package/dist/src/bin/cli.d.ts +3 -0
  3. package/dist/src/bin/cli.d.ts.map +1 -0
  4. package/dist/src/bin/cli.js +112 -0
  5. package/dist/src/bin/cli.js.map +1 -0
  6. package/dist/src/bin/index.js +108 -23
  7. package/dist/src/bin/index.js.map +1 -1
  8. package/dist/src/commands/add/apply.d.ts +6 -0
  9. package/dist/src/commands/add/apply.d.ts.map +1 -0
  10. package/dist/src/commands/add/apply.js +123 -0
  11. package/dist/src/commands/add/apply.js.map +1 -0
  12. package/dist/src/commands/add/ci.d.ts +6 -0
  13. package/dist/src/commands/add/ci.d.ts.map +1 -0
  14. package/dist/src/commands/add/ci.js +108 -0
  15. package/dist/src/commands/add/ci.js.map +1 -0
  16. package/dist/src/commands/add/context.d.ts +5 -0
  17. package/dist/src/commands/add/context.d.ts.map +1 -0
  18. package/dist/src/commands/add/context.js +19 -0
  19. package/dist/src/commands/add/context.js.map +1 -0
  20. package/dist/src/commands/add/diff.d.ts +4 -0
  21. package/dist/src/commands/add/diff.d.ts.map +1 -0
  22. package/dist/src/commands/add/diff.js +114 -0
  23. package/dist/src/commands/add/diff.js.map +1 -0
  24. package/dist/src/commands/add/index.d.ts +6 -0
  25. package/dist/src/commands/add/index.d.ts.map +1 -0
  26. package/dist/src/commands/add/index.js +61 -0
  27. package/dist/src/commands/add/index.js.map +1 -0
  28. package/dist/src/commands/add/output.d.ts +5 -0
  29. package/dist/src/commands/add/output.d.ts.map +1 -0
  30. package/dist/src/commands/add/output.js +58 -0
  31. package/dist/src/commands/add/output.js.map +1 -0
  32. package/dist/src/commands/add/plan.d.ts +6 -0
  33. package/dist/src/commands/add/plan.d.ts.map +1 -0
  34. package/dist/src/commands/add/plan.js +93 -0
  35. package/dist/src/commands/add/plan.js.map +1 -0
  36. package/dist/src/commands/add/registry.d.ts +4 -0
  37. package/dist/src/commands/add/registry.d.ts.map +1 -0
  38. package/dist/src/commands/add/registry.js +37 -0
  39. package/dist/src/commands/add/registry.js.map +1 -0
  40. package/dist/src/commands/add/types.d.ts +37 -0
  41. package/dist/src/commands/add/types.d.ts.map +1 -0
  42. package/dist/src/commands/add/types.js +2 -0
  43. package/dist/src/commands/add/types.js.map +1 -0
  44. package/dist/src/commands/doctor/checks.d.ts +3 -0
  45. package/dist/src/commands/doctor/checks.d.ts.map +1 -0
  46. package/dist/src/commands/doctor/checks.js +353 -0
  47. package/dist/src/commands/doctor/checks.js.map +1 -0
  48. package/dist/src/commands/doctor/context.d.ts +5 -0
  49. package/dist/src/commands/doctor/context.d.ts.map +1 -0
  50. package/dist/src/commands/doctor/context.js +134 -0
  51. package/dist/src/commands/doctor/context.js.map +1 -0
  52. package/dist/src/commands/doctor/index.d.ts +9 -0
  53. package/dist/src/commands/doctor/index.d.ts.map +1 -0
  54. package/dist/src/commands/doctor/index.js +80 -0
  55. package/dist/src/commands/doctor/index.js.map +1 -0
  56. package/dist/src/commands/doctor/output.d.ts +4 -0
  57. package/dist/src/commands/doctor/output.d.ts.map +1 -0
  58. package/dist/src/commands/doctor/output.js +53 -0
  59. package/dist/src/commands/doctor/output.js.map +1 -0
  60. package/dist/src/commands/doctor/postGeneration.d.ts +7 -0
  61. package/dist/src/commands/doctor/postGeneration.d.ts.map +1 -0
  62. package/dist/src/commands/doctor/postGeneration.js +22 -0
  63. package/dist/src/commands/doctor/postGeneration.js.map +1 -0
  64. package/dist/src/commands/doctor/services.d.ts +5 -0
  65. package/dist/src/commands/doctor/services.d.ts.map +1 -0
  66. package/dist/src/commands/doctor/services.js +80 -0
  67. package/dist/src/commands/doctor/services.js.map +1 -0
  68. package/dist/src/commands/doctor/types.d.ts +69 -0
  69. package/dist/src/commands/doctor/types.d.ts.map +1 -0
  70. package/dist/src/commands/doctor/types.js +2 -0
  71. package/dist/src/commands/doctor/types.js.map +1 -0
  72. package/dist/src/commands/upgrade/context.d.ts +5 -0
  73. package/dist/src/commands/upgrade/context.d.ts.map +1 -0
  74. package/dist/src/commands/upgrade/context.js +57 -0
  75. package/dist/src/commands/upgrade/context.js.map +1 -0
  76. package/dist/src/commands/upgrade/index.d.ts +7 -0
  77. package/dist/src/commands/upgrade/index.d.ts.map +1 -0
  78. package/dist/src/commands/upgrade/index.js +35 -0
  79. package/dist/src/commands/upgrade/index.js.map +1 -0
  80. package/dist/src/commands/upgrade/migrations.d.ts +4 -0
  81. package/dist/src/commands/upgrade/migrations.d.ts.map +1 -0
  82. package/dist/src/commands/upgrade/migrations.js +22 -0
  83. package/dist/src/commands/upgrade/migrations.js.map +1 -0
  84. package/dist/src/commands/upgrade/output.d.ts +4 -0
  85. package/dist/src/commands/upgrade/output.d.ts.map +1 -0
  86. package/dist/src/commands/upgrade/output.js +52 -0
  87. package/dist/src/commands/upgrade/output.js.map +1 -0
  88. package/dist/src/commands/upgrade/plan.d.ts +3 -0
  89. package/dist/src/commands/upgrade/plan.d.ts.map +1 -0
  90. package/dist/src/commands/upgrade/plan.js +119 -0
  91. package/dist/src/commands/upgrade/plan.js.map +1 -0
  92. package/dist/src/commands/upgrade/types.d.ts +48 -0
  93. package/dist/src/commands/upgrade/types.d.ts.map +1 -0
  94. package/dist/src/commands/upgrade/types.js +2 -0
  95. package/dist/src/commands/upgrade/types.js.map +1 -0
  96. package/dist/src/lib/args.d.ts +21 -0
  97. package/dist/src/lib/args.d.ts.map +1 -1
  98. package/dist/src/lib/args.js +119 -1
  99. package/dist/src/lib/args.js.map +1 -1
  100. package/dist/src/lib/constants.d.ts +1 -1
  101. package/dist/src/lib/constants.d.ts.map +1 -1
  102. package/dist/src/lib/constants.js +3 -1
  103. package/dist/src/lib/constants.js.map +1 -1
  104. package/dist/src/lib/expressOAuth.d.ts +10 -0
  105. package/dist/src/lib/expressOAuth.d.ts.map +1 -0
  106. package/dist/src/lib/expressOAuth.js +164 -0
  107. package/dist/src/lib/expressOAuth.js.map +1 -0
  108. package/dist/src/lib/interruption.d.ts +14 -0
  109. package/dist/src/lib/interruption.d.ts.map +1 -0
  110. package/dist/src/lib/interruption.js +16 -0
  111. package/dist/src/lib/interruption.js.map +1 -0
  112. package/dist/src/lib/nonInteractive.d.ts +8 -0
  113. package/dist/src/lib/nonInteractive.d.ts.map +1 -0
  114. package/dist/src/lib/nonInteractive.js +111 -0
  115. package/dist/src/lib/nonInteractive.js.map +1 -0
  116. package/dist/src/lib/oauth.d.ts +9 -0
  117. package/dist/src/lib/oauth.d.ts.map +1 -0
  118. package/dist/src/lib/oauth.js +62 -0
  119. package/dist/src/lib/oauth.js.map +1 -0
  120. package/dist/src/lib/onboarding.d.ts +8 -0
  121. package/dist/src/lib/onboarding.d.ts.map +1 -0
  122. package/dist/src/lib/onboarding.js +35 -0
  123. package/dist/src/lib/onboarding.js.map +1 -0
  124. package/dist/src/lib/packageManagerCommands.d.ts +11 -0
  125. package/dist/src/lib/packageManagerCommands.d.ts.map +1 -0
  126. package/dist/src/lib/packageManagerCommands.js +34 -0
  127. package/dist/src/lib/packageManagerCommands.js.map +1 -0
  128. package/dist/src/lib/process.d.ts.map +1 -1
  129. package/dist/src/lib/process.js +9 -0
  130. package/dist/src/lib/process.js.map +1 -1
  131. package/dist/src/lib/projectManifest.d.ts +67 -0
  132. package/dist/src/lib/projectManifest.d.ts.map +1 -0
  133. package/dist/src/lib/projectManifest.js +134 -0
  134. package/dist/src/lib/projectManifest.js.map +1 -0
  135. package/dist/src/lib/release.d.ts +9 -0
  136. package/dist/src/lib/release.d.ts.map +1 -0
  137. package/dist/src/lib/release.js +48 -0
  138. package/dist/src/lib/release.js.map +1 -0
  139. package/dist/src/lib/rootCommand.d.ts +15 -0
  140. package/dist/src/lib/rootCommand.d.ts.map +1 -0
  141. package/dist/src/lib/rootCommand.js +17 -0
  142. package/dist/src/lib/rootCommand.js.map +1 -0
  143. package/dist/src/lib/schemas.d.ts +15 -6
  144. package/dist/src/lib/schemas.d.ts.map +1 -1
  145. package/dist/src/lib/schemas.js +8 -1
  146. package/dist/src/lib/schemas.js.map +1 -1
  147. package/dist/src/lib/semver.d.ts +10 -0
  148. package/dist/src/lib/semver.d.ts.map +1 -0
  149. package/dist/src/lib/semver.js +51 -0
  150. package/dist/src/lib/semver.js.map +1 -0
  151. package/dist/src/lib/types.d.ts +5 -1
  152. package/dist/src/lib/types.d.ts.map +1 -1
  153. package/dist/src/steps/configurePrisma.d.ts.map +1 -1
  154. package/dist/src/steps/configurePrisma.js +18 -23
  155. package/dist/src/steps/configurePrisma.js.map +1 -1
  156. package/dist/src/steps/configureReadme.d.ts +4 -0
  157. package/dist/src/steps/configureReadme.d.ts.map +1 -0
  158. package/dist/src/steps/configureReadme.js +22 -0
  159. package/dist/src/steps/configureReadme.js.map +1 -0
  160. package/dist/src/steps/createProject.d.ts.map +1 -1
  161. package/dist/src/steps/createProject.js +16 -170
  162. package/dist/src/steps/createProject.js.map +1 -1
  163. package/dist/src/steps/finalSetup.d.ts +3 -2
  164. package/dist/src/steps/finalSetup.d.ts.map +1 -1
  165. package/dist/src/steps/finalSetup.js +14 -9
  166. package/dist/src/steps/finalSetup.js.map +1 -1
  167. package/dist/src/steps/installDeps.d.ts +1 -0
  168. package/dist/src/steps/installDeps.d.ts.map +1 -1
  169. package/dist/src/steps/installDeps.js +11 -0
  170. package/dist/src/steps/installDeps.js.map +1 -1
  171. package/dist/src/steps/prompts.d.ts.map +1 -1
  172. package/dist/src/steps/prompts.js +32 -13
  173. package/dist/src/steps/prompts.js.map +1 -1
  174. package/dist/src/utils/output.d.ts.map +1 -1
  175. package/dist/src/utils/output.js +23 -11
  176. package/dist/src/utils/output.js.map +1 -1
  177. package/package.json +5 -4
  178. package/templates/express-auth/README.md +21 -12
  179. package/templates/express-auth/package.json +11 -7
  180. package/templates/express-auth/src/config/redis.ts +109 -0
  181. package/templates/express-auth/src/server.ts +2 -0
  182. package/templates/express-auth+/README.md +25 -18
  183. package/templates/express-auth+/package.json +11 -7
  184. package/templates/express-auth+/src/auth/auth.ts +2 -0
  185. package/templates/express-auth+/src/auth/controllers/password.controller.ts +12 -1
  186. package/templates/express-auth+/src/auth/routes/password.route.ts +1 -0
  187. package/templates/express-auth+/src/config/redis.ts +109 -0
  188. package/templates/express-auth+/src/utils/security.ts +12 -0
  189. package/templates/express-base/README.md +21 -12
  190. package/templates/express-base/package.json +11 -8
  191. package/templates/express-base/src/.env.example +1 -1
  192. package/templates/express-base/src/config/redis.ts +109 -0
  193. package/templates/express-base/src/server.ts +2 -0
  194. package/templates/fullstack/.env.example +3 -2
  195. package/templates/fullstack/PRESET_CONTRACT.md +7 -3
  196. package/templates/fullstack/README.md +45 -7
  197. package/templates/fullstack/apps/api/package.json +6 -4
  198. package/templates/fullstack/apps/api/prisma/migrations/20260721000000_init/migration.sql +163 -0
  199. package/templates/fullstack/apps/api/prisma/migrations/migration_lock.toml +3 -0
  200. package/templates/fullstack/apps/api/src/auth/authenik8.ts +13 -4
  201. package/templates/fullstack/apps/api/src/config/env.ts +9 -1
  202. package/templates/fullstack/apps/api/src/config/logger.ts +21 -11
  203. package/templates/fullstack/apps/api/tests/logger.test.ts +43 -0
  204. package/templates/fullstack/apps/web/package.json +3 -1
  205. package/templates/fullstack/apps/web/src/App.tsx +1 -1
  206. package/templates/fullstack/apps/web/src/auth/RouteGuards.tsx +1 -1
  207. package/templates/fullstack/apps/web/src/components/AppShell.tsx +90 -45
  208. package/templates/fullstack/apps/web/src/components/AuthShell.tsx +10 -7
  209. package/templates/fullstack/apps/web/src/components/Page.tsx +6 -3
  210. package/templates/fullstack/apps/web/src/features/projects/ProjectPages.tsx +1 -1
  211. package/templates/fullstack/apps/web/src/main.tsx +13 -6
  212. package/templates/fullstack/apps/web/src/pages/DashboardPage.tsx +163 -23
  213. package/templates/fullstack/apps/web/src/pages/StatusPages.tsx +1 -1
  214. package/templates/fullstack/apps/web/src/pages/auth/LoginPage.tsx +93 -17
  215. package/templates/fullstack/apps/web/src/pages/auth/OAuthCallbackPage.tsx +1 -1
  216. package/templates/fullstack/apps/web/src/pages/auth/RecoveryPages.tsx +1 -1
  217. package/templates/fullstack/apps/web/src/pages/auth/RegisterPage.tsx +1 -1
  218. package/templates/fullstack/apps/web/src/pages/auth/VerifyEmailPage.tsx +1 -1
  219. package/templates/fullstack/apps/web/src/styles.css +119 -43
  220. package/templates/fullstack/apps/web/vite.config.ts +12 -0
  221. package/templates/fullstack/docker-compose.yml +2 -2
  222. package/templates/fullstack/gitignore.template +1 -0
  223. package/templates/fullstack/package.json +17 -8
  224. package/templates/fullstack/scripts/run-local.mjs +157 -0
  225. package/templates/prisma/postgresql/.env.example +1 -2
  226. package/templates/prisma/sqlite/.env.example +1 -2
  227. package/templates/prisma/sqlite/client.ts +2 -2
@@ -0,0 +1,353 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import fs from "fs-extra";
3
+ import path from "node:path";
4
+ import { parseEnv } from "node:util";
5
+ import { supportsFullstackPreset } from "../../lib/preflight.js";
6
+ import { PROJECT_MANIFEST_FILENAME } from "../../lib/projectManifest.js";
7
+ import { redisEndpointFromEnv } from "./services.js";
8
+ const AGENT_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
9
+ const AGENT_SCOPE = /^[a-z][a-z0-9._/-]*(?::[a-z][a-z0-9._/-]*)+$/;
10
+ function check(id, label, status, message, fix) {
11
+ return { id, label, status, message, ...(fix ? { fix } : {}) };
12
+ }
13
+ function isRecord(value) {
14
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
15
+ }
16
+ function validateSigningKeys(source, activeKid) {
17
+ if (!source?.trim())
18
+ return "AUTHENIK8_SIGNING_JWKS is missing";
19
+ let parsed;
20
+ try {
21
+ parsed = JSON.parse(source);
22
+ }
23
+ catch {
24
+ return "AUTHENIK8_SIGNING_JWKS is not valid JSON";
25
+ }
26
+ if (!Array.isArray(parsed) || parsed.length === 0) {
27
+ return "AUTHENIK8_SIGNING_JWKS must contain at least one key";
28
+ }
29
+ const keys = parsed.filter(isRecord);
30
+ if (keys.length !== parsed.length || keys.some((key) => key.kty !== "EC" || key.crv !== "P-256" ||
31
+ typeof key.kid !== "string" || !key.kid ||
32
+ typeof key.x !== "string" || !key.x ||
33
+ typeof key.y !== "string" || !key.y ||
34
+ (key.alg !== undefined && key.alg !== "ES256"))) {
35
+ return "the signing key ring must contain only ES256 P-256 JWKs with kid, x, and y";
36
+ }
37
+ const keyIds = keys.map((key) => key.kid);
38
+ if (new Set(keyIds).size !== keyIds.length)
39
+ return "signing key IDs must be unique";
40
+ if (!activeKid?.trim())
41
+ return "AUTHENIK8_ACTIVE_KID is missing";
42
+ const active = keys.find((key) => key.kid === activeKid);
43
+ if (!active)
44
+ return "AUTHENIK8_ACTIVE_KID does not select a key in the signing key ring";
45
+ if (typeof active.d !== "string" || !active.d) {
46
+ return "AUTHENIK8_ACTIVE_KID must select a private signing key";
47
+ }
48
+ return undefined;
49
+ }
50
+ function validHttpUrl(value) {
51
+ if (!value?.trim())
52
+ return false;
53
+ try {
54
+ const url = new URL(value);
55
+ return url.protocol === "http:" || url.protocol === "https:";
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ function validAgentRegistry(source) {
62
+ if (!source?.trim())
63
+ return true;
64
+ try {
65
+ const registry = JSON.parse(source);
66
+ return isRecord(registry) && Object.entries(registry).every(([agentId, scopes]) => AGENT_ID.test(agentId) && Array.isArray(scopes) && scopes.length > 0 && scopes.length <= 64 &&
67
+ scopes.every((scope) => typeof scope === "string" && scope.length <= 128 && AGENT_SCOPE.test(scope)));
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ }
73
+ function looksLikePlaceholder(value) {
74
+ if (!value?.trim())
75
+ return true;
76
+ return /^(?:change-me|your-|replace-|example|todo)|(?:client-id|client-secret)/i.test(value.trim());
77
+ }
78
+ async function requiredFilesCheck(context) {
79
+ const files = [
80
+ ".env",
81
+ ".env.example",
82
+ ".gitignore",
83
+ "README.md",
84
+ "THREAT_MODEL.md",
85
+ "AGENT_IDENTITY.md",
86
+ context.preset === "fullstack" ? "apps/api/src/server.ts" : "src/server.ts",
87
+ ];
88
+ if (context.preset === "fullstack") {
89
+ files.push("scripts/run-local.mjs");
90
+ }
91
+ else {
92
+ files.push("docker-compose.yml");
93
+ }
94
+ if (context.usesPrisma) {
95
+ files.push(path.relative(context.rootDir, path.join(context.appDir, "prisma/schema.prisma")));
96
+ files.push(path.relative(context.rootDir, path.join(context.appDir, "prisma.config.ts")));
97
+ if (context.preset === "fullstack") {
98
+ files.push(path.relative(context.rootDir, path.join(context.appDir, "prisma/migrations/migration_lock.toml")));
99
+ }
100
+ }
101
+ const missing = (await Promise.all(files.map(async (file) => await fs.pathExists(path.join(context.rootDir, file)) ? undefined : file))).filter((file) => Boolean(file));
102
+ return missing.length === 0
103
+ ? check("project.files", "Project structure", "pass", "Required Authenik8 project files are present")
104
+ : check("project.files", "Project structure", "fail", `Missing required files: ${missing.join(", ")}`, "Restore the files from source control or regenerate the project before changing auth code.");
105
+ }
106
+ function scriptsCheck(context) {
107
+ const required = ["dev", "build"];
108
+ if (context.preset === "fullstack") {
109
+ required.push("setup", "db:seed");
110
+ }
111
+ const scripts = context.packageJson.scripts ?? {};
112
+ const missing = required.filter((name) => !scripts[name]);
113
+ if (context.usesPrisma) {
114
+ const hasMigrationScript = context.preset === "fullstack"
115
+ ? Boolean(scripts["db:migrate"])
116
+ : Boolean(scripts["db:migrate"] || scripts["prisma:migrate"]);
117
+ if (!hasMigrationScript)
118
+ missing.push("db:migrate");
119
+ }
120
+ return missing.length === 0
121
+ ? check("project.scripts", "Project scripts", "pass", "Development, build, and migration scripts are wired")
122
+ : check("project.scripts", "Project scripts", "fail", `Missing package scripts: ${missing.join(", ")}`, "Restore the generated package.json scripts before running the application.");
123
+ }
124
+ function declaredCoreVersion(packageJson) {
125
+ return packageJson.dependencies?.["authenik8-core"] ?? packageJson.devDependencies?.["authenik8-core"];
126
+ }
127
+ async function coreDependencyCheck(context, allowMissingCore = false) {
128
+ const declared = declaredCoreVersion(context.appPackageJson);
129
+ if (!declared) {
130
+ return check("dependency.core", "Identity engine", "fail", "authenik8-core is not declared", `${context.packageManager} install`);
131
+ }
132
+ const candidates = [
133
+ path.join(context.appDir, "node_modules/authenik8-core/package.json"),
134
+ path.join(context.rootDir, "node_modules/authenik8-core/package.json"),
135
+ ];
136
+ const installedPath = (await Promise.all(candidates.map(async (candidate) => await fs.pathExists(candidate) ? candidate : undefined))).find(Boolean);
137
+ if (!installedPath) {
138
+ return check("dependency.core", "Identity engine", allowMissingCore ? "warn" : "fail", `authenik8-core ${declared} is declared but not installed`, `${context.packageManager} install`);
139
+ }
140
+ let installed;
141
+ try {
142
+ installed = await fs.readJson(installedPath);
143
+ }
144
+ catch {
145
+ return check("dependency.core", "Identity engine", "fail", "The installed authenik8-core package metadata is unreadable", `${context.packageManager} install`);
146
+ }
147
+ if (!installed.version) {
148
+ return check("dependency.core", "Identity engine", "fail", "The installed authenik8-core version is missing", `${context.packageManager} install`);
149
+ }
150
+ if (/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(declared) && declared !== installed.version) {
151
+ return check("dependency.core", "Identity engine", "fail", `Declared authenik8-core ${declared}, but installed ${installed.version}`, `${context.packageManager} install`);
152
+ }
153
+ return check("dependency.core", "Identity engine", "pass", `authenik8-core ${installed.version} is installed`);
154
+ }
155
+ async function projectManifestCheck(context) {
156
+ if (context.manifest.status === "missing") {
157
+ return check("project.manifest", "Project manifest", "warn", `${PROJECT_MANIFEST_FILENAME} is missing; structural compatibility mode is active`, "Regenerate with a current create-authenik8-app release before using future upgrade automation.");
158
+ }
159
+ if (context.manifest.status === "invalid") {
160
+ return check("project.manifest", "Project manifest", "fail", context.manifest.message, `Restore ${PROJECT_MANIFEST_FILENAME} from source control; never add secrets to it.`);
161
+ }
162
+ const manifest = context.manifest.manifest;
163
+ const differences = [];
164
+ const declaredCore = declaredCoreVersion(context.appPackageJson);
165
+ const actualOAuth = [...context.oauthProviders].sort().join(",");
166
+ const manifestOAuth = [...manifest.features.oauthProviders].sort().join(",");
167
+ const hasPm2 = Boolean(context.packageJson.scripts?.["pm2:start"]);
168
+ if (manifest.projectName !== context.packageJson.name)
169
+ differences.push("project name");
170
+ if (manifest.preset !== context.preset)
171
+ differences.push("preset");
172
+ if (manifest.packageManager !== context.packageManager)
173
+ differences.push("package manager");
174
+ if (manifest.engine.version !== declaredCore)
175
+ differences.push("authenik8-core version");
176
+ if (manifest.features.prisma !== context.usesPrisma)
177
+ differences.push("Prisma feature");
178
+ if (manifest.database !== (context.databaseProvider ?? null))
179
+ differences.push("database provider");
180
+ if (manifestOAuth !== actualOAuth)
181
+ differences.push("OAuth providers");
182
+ if (manifest.features.pm2 !== hasPm2)
183
+ differences.push("PM2 feature");
184
+ if (manifest.features.pm2) {
185
+ const pm2Path = path.join(context.rootDir, "ecosystem.config.js");
186
+ if (await fs.pathExists(pm2Path)) {
187
+ const pm2Source = await fs.readFile(pm2Path, "utf8");
188
+ const runtime = /interpreter:\s*["']bun["']/.test(pm2Source) ? "bun" : "node";
189
+ if (manifest.runtime !== runtime)
190
+ differences.push("production runtime");
191
+ }
192
+ else {
193
+ differences.push("PM2 configuration");
194
+ }
195
+ }
196
+ return differences.length === 0
197
+ ? check("project.manifest", "Project manifest", "pass", `Schema v${manifest.schemaVersion} matches the generated project and authenik8-core declaration`)
198
+ : check("project.manifest", "Project manifest", "fail", `Manifest drift detected: ${differences.join(", ")}`, "Review intentional architecture changes, then update the manifest as one audited change.");
199
+ }
200
+ async function environmentSafetyCheck(context) {
201
+ const ignorePath = path.join(context.rootDir, ".gitignore");
202
+ if (!(await fs.pathExists(ignorePath))) {
203
+ return check("security.env", "Secret-file safety", "fail", ".gitignore is missing", "Add .env to .gitignore immediately.");
204
+ }
205
+ const ignored = (await fs.readFile(ignorePath, "utf8"))
206
+ .split(/\r?\n/)
207
+ .map((line) => line.trim())
208
+ .some((line) => line === ".env" || line === ".env*" || line === ".env.*");
209
+ if (!ignored) {
210
+ return check("security.env", "Secret-file safety", "fail", ".env is not ignored by Git", "Add .env to .gitignore immediately.");
211
+ }
212
+ const insideGit = spawnSync("git", ["-C", context.rootDir, "rev-parse", "--is-inside-work-tree"], {
213
+ encoding: "utf8",
214
+ stdio: ["ignore", "pipe", "ignore"],
215
+ });
216
+ if (insideGit.status === 0) {
217
+ const tracked = spawnSync("git", ["-C", context.rootDir, "ls-files", "--error-unmatch", ".env"], {
218
+ stdio: "ignore",
219
+ });
220
+ if (tracked.status === 0) {
221
+ return check("security.env", "Secret-file safety", "fail", ".env is tracked by Git and may expose signing or refresh secrets", "Remove .env from Git history and rotate every exposed signing key and refresh secret.");
222
+ }
223
+ }
224
+ const examplePath = path.join(context.rootDir, ".env.example");
225
+ if (await fs.pathExists(examplePath)) {
226
+ const source = await fs.readFile(examplePath, "utf8");
227
+ let example = {};
228
+ try {
229
+ example = parseEnv(source);
230
+ }
231
+ catch {
232
+ return check("security.env", "Secret-file safety", "warn", ".env.example could not be parsed", "Keep the example file valid and free of real secrets.");
233
+ }
234
+ if (/\"d\"\s*:/.test(example.AUTHENIK8_SIGNING_JWKS ?? "")) {
235
+ return check("security.env", "Secret-file safety", "fail", ".env.example contains a private signing JWK", "Remove the private key and rotate it if the file was committed.");
236
+ }
237
+ const exampleSecret = example.REFRESH_SECRET?.trim();
238
+ if (exampleSecret && exampleSecret.length >= 32 && !/(?:replace|change|example|generated|random)/i.test(exampleSecret)) {
239
+ return check("security.env", "Secret-file safety", "fail", ".env.example appears to contain a real refresh secret", "Replace it with an obvious placeholder and rotate the secret.");
240
+ }
241
+ }
242
+ return check("security.env", "Secret-file safety", "pass", ".env is ignored, untracked, and examples contain no private signing material");
243
+ }
244
+ async function databaseCheck(context) {
245
+ const value = context.env.DATABASE_URL?.trim();
246
+ const provider = context.databaseProvider;
247
+ const valid = provider === "sqlite"
248
+ ? value?.startsWith("file:")
249
+ : provider === "postgresql"
250
+ ? /^(?:postgresql|postgres):\/\//.test(value ?? "")
251
+ : false;
252
+ return valid
253
+ ? check("environment.database", "Database configuration", "pass", `${provider} DATABASE_URL matches the Prisma provider`)
254
+ : check("environment.database", "Database configuration", "fail", `DATABASE_URL does not match the ${provider ?? "unknown"} Prisma provider`, provider === "sqlite" ? "Use a file: URL." : "Use a postgresql:// URL.");
255
+ }
256
+ function oauthChecks(context) {
257
+ return context.oauthProviders.map((provider) => {
258
+ const prefix = provider.toUpperCase();
259
+ const clientId = context.env[`${prefix}_CLIENT_ID`];
260
+ const clientSecret = context.env[`${prefix}_CLIENT_SECRET`];
261
+ const redirect = context.env[`${prefix}_REDIRECT_URI`];
262
+ const expectedPath = context.preset === "fullstack"
263
+ ? `/api/auth/oauth/${provider}/callback`
264
+ : `/auth/${provider}/callback`;
265
+ let validRedirect = false;
266
+ try {
267
+ validRedirect = validHttpUrl(redirect) && new URL(redirect).pathname === expectedPath;
268
+ }
269
+ catch { }
270
+ if (looksLikePlaceholder(clientId) || looksLikePlaceholder(clientSecret)) {
271
+ return check(`oauth.${provider}`, `${provider} OAuth`, "warn", `${provider} is enabled, but its client credentials are not configured`, `Set ${prefix}_CLIENT_ID and ${prefix}_CLIENT_SECRET before testing ${provider} sign-in.`);
272
+ }
273
+ if (!validRedirect) {
274
+ return check(`oauth.${provider}`, `${provider} OAuth`, "fail", `${prefix}_REDIRECT_URI must be an HTTP(S) URL ending in ${expectedPath}`, `Use the exact same callback URL in .env and the ${provider} provider console.`);
275
+ }
276
+ return check(`oauth.${provider}`, `${provider} OAuth`, "pass", `${provider} credentials and callback shape are configured`);
277
+ });
278
+ }
279
+ function runtimeEnvironmentChecks(context) {
280
+ const portSource = context.env.PORT?.trim() || "3000";
281
+ const port = Number(portSource);
282
+ const portValid = Number.isInteger(port) && port >= 1 && port <= 65_535;
283
+ const checks = [portValid
284
+ ? check("environment.port", "Application port", "pass", `PORT ${port} is valid`)
285
+ : check("environment.port", "Application port", "fail", "PORT must be an integer from 1 to 65535", "Set a valid, available application port.")];
286
+ if (context.preset === "fullstack") {
287
+ checks.push(validHttpUrl(context.env.WEB_ORIGIN)
288
+ ? check("environment.origin", "Web origin", "pass", "WEB_ORIGIN is a valid HTTP(S) URL")
289
+ : check("environment.origin", "Web origin", "fail", "WEB_ORIGIN must be a valid HTTP(S) URL", "Set it to the exact browser origin allowed to call the API."));
290
+ }
291
+ const redisUrl = context.env.REDIS_URL?.trim();
292
+ const usesMemoryRedis = redisUrl === "memory://";
293
+ if (usesMemoryRedis) {
294
+ checks.push(context.env.NODE_ENV === "production"
295
+ ? check("environment.redis", "Redis configuration", "fail", "The in-process Redis store is for local development only", "Set REDIS_URL to a redis:// or rediss:// endpoint in production.")
296
+ : check("environment.redis", "Redis configuration", "pass", "The in-process Redis-compatible store is configured for local development"));
297
+ return checks;
298
+ }
299
+ const usesRedisUrl = context.preset === "fullstack" || Boolean(redisUrl);
300
+ try {
301
+ const endpoint = redisEndpointFromEnv(context.env, usesRedisUrl);
302
+ if (!endpoint.host
303
+ || !Number.isInteger(endpoint.port)
304
+ || endpoint.port < 1
305
+ || endpoint.port > 65_535) {
306
+ throw new Error("invalid Redis endpoint");
307
+ }
308
+ checks.push(check("environment.redis", "Redis configuration", "pass", "Redis host and port are structurally valid"));
309
+ }
310
+ catch {
311
+ checks.push(check("environment.redis", "Redis configuration", "fail", usesRedisUrl ? "REDIS_URL is invalid" : "REDIS_HOST or REDIS_PORT is invalid", usesRedisUrl ? "Use a redis:// or rediss:// URL." : "Set a host and a port from 1 to 65535."));
312
+ }
313
+ return checks;
314
+ }
315
+ export async function runStaticChecks(context, nodeVersion = process.versions.node, allowMissingCore = false) {
316
+ const checks = [];
317
+ checks.push(supportsFullstackPreset(nodeVersion)
318
+ ? check("runtime.node", "Node.js runtime", "pass", `Node.js ${nodeVersion} is supported`)
319
+ : check("runtime.node", "Node.js runtime", "fail", `Node.js ${nodeVersion} is unsupported`, "Use Node.js 20.19+, 22.12+, or 24+."));
320
+ checks.push(await requiredFilesCheck(context));
321
+ checks.push(await projectManifestCheck(context));
322
+ checks.push(scriptsCheck(context));
323
+ checks.push(await coreDependencyCheck(context, allowMissingCore));
324
+ checks.push(await environmentSafetyCheck(context));
325
+ if (context.envParseError) {
326
+ checks.push(check("environment.syntax", "Environment file", "fail", `.env is invalid: ${context.envParseError}`, "Fix .env syntax without printing or committing its values."));
327
+ return checks;
328
+ }
329
+ const signingError = validateSigningKeys(context.env.AUTHENIK8_SIGNING_JWKS, context.env.AUTHENIK8_ACTIVE_KID);
330
+ checks.push(signingError
331
+ ? check("auth.signing", "Signing key ring", "fail", signingError, "Restore the generated private ES256 key ring or rotate it deliberately.")
332
+ : check("auth.signing", "Signing key ring", "pass", "The active ES256 P-256 signing key is private and selectable"));
333
+ const issuerValid = validHttpUrl(context.env.AUTHENIK8_ISSUER);
334
+ const audienceValid = Boolean(context.env.AUTHENIK8_AUDIENCE?.trim());
335
+ checks.push(issuerValid && audienceValid
336
+ ? check("auth.claims", "Token claims", "pass", "Issuer and audience are configured")
337
+ : check("auth.claims", "Token claims", "fail", "AUTHENIK8_ISSUER must be an HTTP(S) URL and AUTHENIK8_AUDIENCE must be non-empty", "Set stable issuer and audience values before issuing tokens."));
338
+ checks.push((context.env.REFRESH_SECRET?.length ?? 0) >= 32
339
+ ? check("auth.refresh", "Refresh-token secret", "pass", "REFRESH_SECRET meets the minimum length")
340
+ : check("auth.refresh", "Refresh-token secret", "fail", "REFRESH_SECRET must contain at least 32 characters", "Generate a high-entropy secret and store it outside source control."));
341
+ checks.push(validAgentRegistry(context.env.AUTHENIK8_AGENTS)
342
+ ? check("auth.agents", "Agent identity", "pass", "Agent scopes are structurally valid (an empty registry disables agent identity)")
343
+ : check("auth.agents", "Agent identity", "fail", "AUTHENIK8_AGENTS must map valid agent IDs to 1-64 exact resource:action scopes", "Use {} to disable agent identity or grant only explicit, least-privilege scopes."));
344
+ checks.push(...runtimeEnvironmentChecks(context));
345
+ if (context.usesPrisma)
346
+ checks.push(await databaseCheck(context));
347
+ if (context.preset === "auth-oauth" && context.oauthProviders.length === 0) {
348
+ checks.push(check("oauth.routes", "OAuth routes", "fail", "The OAuth preset has no recognized provider routes", "Restore at least one generated Google or GitHub route and its matching configuration."));
349
+ }
350
+ checks.push(...oauthChecks(context));
351
+ return checks;
352
+ }
353
+ //# sourceMappingURL=checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../../../../src/commands/doctor/checks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { DoctorContext } from "./types.js";
2
+ export declare class DoctorProjectError extends Error {
3
+ }
4
+ export declare function createDoctorContext(directory: string): Promise<DoctorContext>;
5
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../src/commands/doctor/context.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,aAAa,EAId,MAAM,YAAY,CAAC;AAEpB,qBAAa,kBAAmB,SAAQ,KAAK;CAAG;AAyGhD,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAgDnF"}
@@ -0,0 +1,134 @@
1
+ import fs from "fs-extra";
2
+ import path from "node:path";
3
+ import { parseEnv } from "node:util";
4
+ import { supportedOAuthProviders } from "../../lib/oauth.js";
5
+ import { readProjectManifest } from "../../lib/projectManifest.js";
6
+ export class DoctorProjectError extends Error {
7
+ }
8
+ function dependency(packageJson, name) {
9
+ return packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name];
10
+ }
11
+ async function readPackageJson(filename) {
12
+ try {
13
+ return await fs.readJson(filename);
14
+ }
15
+ catch (error) {
16
+ const detail = error instanceof Error ? error.message : String(error);
17
+ throw new DoctorProjectError(`Could not read ${filename}: ${detail}`);
18
+ }
19
+ }
20
+ async function detectPackageManager(rootDir, packageJson, manifestPackageManager) {
21
+ if (await fs.pathExists(path.join(rootDir, "pnpm-lock.yaml")))
22
+ return "pnpm";
23
+ if (await fs.pathExists(path.join(rootDir, "pnpm-workspace.yaml")))
24
+ return "pnpm";
25
+ if (await fs.pathExists(path.join(rootDir, "bun.lock")) ||
26
+ await fs.pathExists(path.join(rootDir, "bun.lockb")) ||
27
+ Array.isArray(packageJson.trustedDependencies)) {
28
+ return "bun";
29
+ }
30
+ return manifestPackageManager ?? "npm";
31
+ }
32
+ function parseExpressProviders(source) {
33
+ const matches = [...source.matchAll(/router\.get\("\/(google|github)(?:\/|\")/g)];
34
+ const providers = matches
35
+ .map((match) => match[1])
36
+ .filter((provider) => typeof provider === "string");
37
+ return supportedOAuthProviders([...new Set(providers)]);
38
+ }
39
+ function parseFullstackProviders(source) {
40
+ const arraySource = source.match(/enabledOAuthProviders[^=]*=\s*(\[[^;]*\])/s)?.[1];
41
+ if (!arraySource)
42
+ return [];
43
+ try {
44
+ const providers = JSON.parse(arraySource);
45
+ return Array.isArray(providers)
46
+ ? supportedOAuthProviders(providers.filter((value) => typeof value === "string"))
47
+ : [];
48
+ }
49
+ catch {
50
+ return [];
51
+ }
52
+ }
53
+ async function readOAuthProviders(rootDir, preset) {
54
+ const filename = preset === "fullstack"
55
+ ? path.join(rootDir, "apps/web/src/auth/providers.ts")
56
+ : path.join(rootDir, "src/auth/routes/oauth.routes.ts");
57
+ if (!(await fs.pathExists(filename)))
58
+ return [];
59
+ const source = await fs.readFile(filename, "utf8");
60
+ return preset === "fullstack"
61
+ ? parseFullstackProviders(source)
62
+ : parseExpressProviders(source);
63
+ }
64
+ async function detectPreset(rootDir, rootPackage) {
65
+ const apiPackagePath = path.join(rootDir, "apps/api/package.json");
66
+ const fullstackServerPath = path.join(rootDir, "apps/api/src/server.ts");
67
+ if (Array.isArray(rootPackage.workspaces) &&
68
+ await fs.pathExists(apiPackagePath) &&
69
+ await fs.pathExists(fullstackServerPath)) {
70
+ const appDir = path.join(rootDir, "apps/api");
71
+ const appPackageJson = await readPackageJson(apiPackagePath);
72
+ if (!dependency(appPackageJson, "authenik8-core")) {
73
+ throw new DoctorProjectError("The API workspace does not declare authenik8-core.");
74
+ }
75
+ return { preset: "fullstack", appDir, appPackageJson };
76
+ }
77
+ if (dependency(rootPackage, "authenik8-core") &&
78
+ await fs.pathExists(path.join(rootDir, "src/server.ts"))) {
79
+ const oauthRoutes = path.join(rootDir, "src/auth/routes/oauth.routes.ts");
80
+ const authRoutes = path.join(rootDir, "src/routes/auth.routes.ts");
81
+ const preset = await fs.pathExists(oauthRoutes)
82
+ ? "auth-oauth"
83
+ : await fs.pathExists(authRoutes)
84
+ ? "auth"
85
+ : "base";
86
+ return { preset, appDir: rootDir, appPackageJson: rootPackage };
87
+ }
88
+ throw new DoctorProjectError("This directory is not a recognized Authenik8 project. Run doctor from the generated project root.");
89
+ }
90
+ export async function createDoctorContext(directory) {
91
+ const rootDir = path.resolve(directory);
92
+ const rootPackagePath = path.join(rootDir, "package.json");
93
+ if (!(await fs.pathExists(rootPackagePath))) {
94
+ throw new DoctorProjectError(`No package.json found in ${rootDir}.`);
95
+ }
96
+ const packageJson = await readPackageJson(rootPackagePath);
97
+ const manifest = await readProjectManifest(rootDir);
98
+ const { preset, appDir, appPackageJson } = await detectPreset(rootDir, packageJson);
99
+ const prismaSchemaPath = path.join(appDir, "prisma/schema.prisma");
100
+ const usesPrisma = await fs.pathExists(prismaSchemaPath);
101
+ let databaseProvider;
102
+ if (usesPrisma) {
103
+ const prismaSchema = await fs.readFile(prismaSchemaPath, "utf8");
104
+ const provider = prismaSchema.match(/provider\s*=\s*"(sqlite|postgresql)"/)?.[1];
105
+ if (provider === "sqlite" || provider === "postgresql")
106
+ databaseProvider = provider;
107
+ }
108
+ const envPath = path.join(rootDir, ".env");
109
+ let env = {};
110
+ let envParseError;
111
+ if (await fs.pathExists(envPath)) {
112
+ try {
113
+ env = parseEnv(await fs.readFile(envPath, "utf8"));
114
+ }
115
+ catch {
116
+ envParseError = "invalid dotenv syntax";
117
+ }
118
+ }
119
+ return {
120
+ rootDir,
121
+ appDir,
122
+ preset,
123
+ packageManager: await detectPackageManager(rootDir, packageJson, manifest.status === "valid" ? manifest.manifest.packageManager : undefined),
124
+ packageJson,
125
+ appPackageJson,
126
+ env,
127
+ ...(envParseError ? { envParseError } : {}),
128
+ oauthProviders: await readOAuthProviders(rootDir, preset),
129
+ usesPrisma,
130
+ ...(databaseProvider ? { databaseProvider } : {}),
131
+ manifest,
132
+ };
133
+ }
134
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../../src/commands/doctor/context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { DoctorOptions, DoctorReport, DoctorRuntimeOptions } from "./types.js";
2
+ export declare class DoctorUsageError extends Error {
3
+ }
4
+ export type ParsedDoctorArguments = DoctorOptions & {
5
+ help: boolean;
6
+ };
7
+ export declare function parseDoctorArguments(args: readonly string[], cwd?: string): ParsedDoctorArguments;
8
+ export declare function runDoctor(options: DoctorOptions, runtime?: DoctorRuntimeOptions): Promise<DoctorReport>;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/doctor/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAEV,aAAa,EACb,YAAY,EACZ,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAEpB,qBAAa,gBAAiB,SAAQ,KAAK;CAAG;AAE9C,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtE,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,SAAgB,GAClB,qBAAqB,CAqBvB;AAgBD,wBAAsB,SAAS,CAC7B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,YAAY,CAAC,CA6CvB"}
@@ -0,0 +1,80 @@
1
+ import path from "node:path";
2
+ import { createDoctorContext } from "./context.js";
3
+ import { runStaticChecks } from "./checks.js";
4
+ import { redisEndpointFromEnv, probeRedis } from "./services.js";
5
+ export class DoctorUsageError extends Error {
6
+ }
7
+ export function parseDoctorArguments(args, cwd = process.cwd()) {
8
+ let directory;
9
+ let json = false;
10
+ let skipServices = false;
11
+ let help = false;
12
+ for (const argument of args) {
13
+ if (argument === "--json")
14
+ json = true;
15
+ else if (argument === "--skip-services")
16
+ skipServices = true;
17
+ else if (argument === "--help" || argument === "-h")
18
+ help = true;
19
+ else if (argument.startsWith("-"))
20
+ throw new DoctorUsageError(`Unknown doctor option: ${argument}`);
21
+ else if (directory)
22
+ throw new DoctorUsageError("Doctor accepts at most one project directory.");
23
+ else
24
+ directory = argument;
25
+ }
26
+ return {
27
+ directory: path.resolve(cwd, directory ?? "."),
28
+ json,
29
+ skipServices,
30
+ help,
31
+ };
32
+ }
33
+ function serviceCheck(status, message, fix) {
34
+ return {
35
+ id: "service.redis",
36
+ label: "Redis",
37
+ status,
38
+ message,
39
+ ...(fix ? { fix } : {}),
40
+ };
41
+ }
42
+ export async function runDoctor(options, runtime = {}) {
43
+ const context = await createDoctorContext(options.directory);
44
+ const checks = await runStaticChecks(context, runtime.nodeVersion, runtime.allowMissingCore);
45
+ if (options.skipServices) {
46
+ checks.push(serviceCheck("warn", "Live service checks were skipped"));
47
+ }
48
+ else if (context.envParseError) {
49
+ checks.push(serviceCheck("warn", "Redis was not checked because .env is invalid"));
50
+ }
51
+ else if (context.env.REDIS_URL?.trim() === "memory://") {
52
+ checks.push(serviceCheck("pass", "In-process Redis will initialize with the API process"));
53
+ }
54
+ else {
55
+ try {
56
+ const usesRedisUrl = context.preset === "fullstack"
57
+ || Boolean(context.env.REDIS_URL?.trim());
58
+ const endpoint = redisEndpointFromEnv(context.env, usesRedisUrl);
59
+ if (!endpoint.host
60
+ || !Number.isInteger(endpoint.port)
61
+ || endpoint.port < 1
62
+ || endpoint.port > 65_535) {
63
+ throw new Error("Redis host or port is invalid");
64
+ }
65
+ await (runtime.redisProbe ?? probeRedis)(endpoint);
66
+ checks.push(serviceCheck("pass", `Redis answered PING at ${endpoint.host}:${endpoint.port}`));
67
+ }
68
+ catch (error) {
69
+ const detail = error instanceof Error ? error.message : String(error);
70
+ checks.push(serviceCheck("fail", `Redis is not ready: ${detail}`, "Start the configured Redis service, then rerun doctor."));
71
+ }
72
+ }
73
+ const summary = {
74
+ passed: checks.filter((item) => item.status === "pass").length,
75
+ warnings: checks.filter((item) => item.status === "warn").length,
76
+ failed: checks.filter((item) => item.status === "fail").length,
77
+ };
78
+ return { rootDir: context.rootDir, preset: context.preset, checks, summary };
79
+ }
80
+ //# sourceMappingURL=index.js.map