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.
- package/README.md +34 -516
- package/dist/src/bin/cli.d.ts +3 -0
- package/dist/src/bin/cli.d.ts.map +1 -0
- package/dist/src/bin/cli.js +112 -0
- package/dist/src/bin/cli.js.map +1 -0
- package/dist/src/bin/index.js +108 -23
- package/dist/src/bin/index.js.map +1 -1
- package/dist/src/commands/add/apply.d.ts +6 -0
- package/dist/src/commands/add/apply.d.ts.map +1 -0
- package/dist/src/commands/add/apply.js +123 -0
- package/dist/src/commands/add/apply.js.map +1 -0
- package/dist/src/commands/add/ci.d.ts +6 -0
- package/dist/src/commands/add/ci.d.ts.map +1 -0
- package/dist/src/commands/add/ci.js +108 -0
- package/dist/src/commands/add/ci.js.map +1 -0
- package/dist/src/commands/add/context.d.ts +5 -0
- package/dist/src/commands/add/context.d.ts.map +1 -0
- package/dist/src/commands/add/context.js +19 -0
- package/dist/src/commands/add/context.js.map +1 -0
- package/dist/src/commands/add/diff.d.ts +4 -0
- package/dist/src/commands/add/diff.d.ts.map +1 -0
- package/dist/src/commands/add/diff.js +114 -0
- package/dist/src/commands/add/diff.js.map +1 -0
- package/dist/src/commands/add/index.d.ts +6 -0
- package/dist/src/commands/add/index.d.ts.map +1 -0
- package/dist/src/commands/add/index.js +61 -0
- package/dist/src/commands/add/index.js.map +1 -0
- package/dist/src/commands/add/output.d.ts +5 -0
- package/dist/src/commands/add/output.d.ts.map +1 -0
- package/dist/src/commands/add/output.js +58 -0
- package/dist/src/commands/add/output.js.map +1 -0
- package/dist/src/commands/add/plan.d.ts +6 -0
- package/dist/src/commands/add/plan.d.ts.map +1 -0
- package/dist/src/commands/add/plan.js +93 -0
- package/dist/src/commands/add/plan.js.map +1 -0
- package/dist/src/commands/add/registry.d.ts +4 -0
- package/dist/src/commands/add/registry.d.ts.map +1 -0
- package/dist/src/commands/add/registry.js +37 -0
- package/dist/src/commands/add/registry.js.map +1 -0
- package/dist/src/commands/add/types.d.ts +37 -0
- package/dist/src/commands/add/types.d.ts.map +1 -0
- package/dist/src/commands/add/types.js +2 -0
- package/dist/src/commands/add/types.js.map +1 -0
- package/dist/src/commands/doctor/checks.d.ts +3 -0
- package/dist/src/commands/doctor/checks.d.ts.map +1 -0
- package/dist/src/commands/doctor/checks.js +353 -0
- package/dist/src/commands/doctor/checks.js.map +1 -0
- package/dist/src/commands/doctor/context.d.ts +5 -0
- package/dist/src/commands/doctor/context.d.ts.map +1 -0
- package/dist/src/commands/doctor/context.js +134 -0
- package/dist/src/commands/doctor/context.js.map +1 -0
- package/dist/src/commands/doctor/index.d.ts +9 -0
- package/dist/src/commands/doctor/index.d.ts.map +1 -0
- package/dist/src/commands/doctor/index.js +80 -0
- package/dist/src/commands/doctor/index.js.map +1 -0
- package/dist/src/commands/doctor/output.d.ts +4 -0
- package/dist/src/commands/doctor/output.d.ts.map +1 -0
- package/dist/src/commands/doctor/output.js +53 -0
- package/dist/src/commands/doctor/output.js.map +1 -0
- package/dist/src/commands/doctor/postGeneration.d.ts +7 -0
- package/dist/src/commands/doctor/postGeneration.d.ts.map +1 -0
- package/dist/src/commands/doctor/postGeneration.js +22 -0
- package/dist/src/commands/doctor/postGeneration.js.map +1 -0
- package/dist/src/commands/doctor/services.d.ts +5 -0
- package/dist/src/commands/doctor/services.d.ts.map +1 -0
- package/dist/src/commands/doctor/services.js +80 -0
- package/dist/src/commands/doctor/services.js.map +1 -0
- package/dist/src/commands/doctor/types.d.ts +69 -0
- package/dist/src/commands/doctor/types.d.ts.map +1 -0
- package/dist/src/commands/doctor/types.js +2 -0
- package/dist/src/commands/doctor/types.js.map +1 -0
- package/dist/src/commands/upgrade/context.d.ts +5 -0
- package/dist/src/commands/upgrade/context.d.ts.map +1 -0
- package/dist/src/commands/upgrade/context.js +57 -0
- package/dist/src/commands/upgrade/context.js.map +1 -0
- package/dist/src/commands/upgrade/index.d.ts +7 -0
- package/dist/src/commands/upgrade/index.d.ts.map +1 -0
- package/dist/src/commands/upgrade/index.js +35 -0
- package/dist/src/commands/upgrade/index.js.map +1 -0
- package/dist/src/commands/upgrade/migrations.d.ts +4 -0
- package/dist/src/commands/upgrade/migrations.d.ts.map +1 -0
- package/dist/src/commands/upgrade/migrations.js +22 -0
- package/dist/src/commands/upgrade/migrations.js.map +1 -0
- package/dist/src/commands/upgrade/output.d.ts +4 -0
- package/dist/src/commands/upgrade/output.d.ts.map +1 -0
- package/dist/src/commands/upgrade/output.js +52 -0
- package/dist/src/commands/upgrade/output.js.map +1 -0
- package/dist/src/commands/upgrade/plan.d.ts +3 -0
- package/dist/src/commands/upgrade/plan.d.ts.map +1 -0
- package/dist/src/commands/upgrade/plan.js +119 -0
- package/dist/src/commands/upgrade/plan.js.map +1 -0
- package/dist/src/commands/upgrade/types.d.ts +48 -0
- package/dist/src/commands/upgrade/types.d.ts.map +1 -0
- package/dist/src/commands/upgrade/types.js +2 -0
- package/dist/src/commands/upgrade/types.js.map +1 -0
- package/dist/src/lib/args.d.ts +21 -0
- package/dist/src/lib/args.d.ts.map +1 -1
- package/dist/src/lib/args.js +119 -1
- package/dist/src/lib/args.js.map +1 -1
- package/dist/src/lib/constants.d.ts +1 -1
- package/dist/src/lib/constants.d.ts.map +1 -1
- package/dist/src/lib/constants.js +3 -1
- package/dist/src/lib/constants.js.map +1 -1
- package/dist/src/lib/expressOAuth.d.ts +10 -0
- package/dist/src/lib/expressOAuth.d.ts.map +1 -0
- package/dist/src/lib/expressOAuth.js +164 -0
- package/dist/src/lib/expressOAuth.js.map +1 -0
- package/dist/src/lib/interruption.d.ts +14 -0
- package/dist/src/lib/interruption.d.ts.map +1 -0
- package/dist/src/lib/interruption.js +16 -0
- package/dist/src/lib/interruption.js.map +1 -0
- package/dist/src/lib/nonInteractive.d.ts +8 -0
- package/dist/src/lib/nonInteractive.d.ts.map +1 -0
- package/dist/src/lib/nonInteractive.js +111 -0
- package/dist/src/lib/nonInteractive.js.map +1 -0
- package/dist/src/lib/oauth.d.ts +9 -0
- package/dist/src/lib/oauth.d.ts.map +1 -0
- package/dist/src/lib/oauth.js +62 -0
- package/dist/src/lib/oauth.js.map +1 -0
- package/dist/src/lib/onboarding.d.ts +8 -0
- package/dist/src/lib/onboarding.d.ts.map +1 -0
- package/dist/src/lib/onboarding.js +35 -0
- package/dist/src/lib/onboarding.js.map +1 -0
- package/dist/src/lib/packageManagerCommands.d.ts +11 -0
- package/dist/src/lib/packageManagerCommands.d.ts.map +1 -0
- package/dist/src/lib/packageManagerCommands.js +34 -0
- package/dist/src/lib/packageManagerCommands.js.map +1 -0
- package/dist/src/lib/process.d.ts.map +1 -1
- package/dist/src/lib/process.js +9 -0
- package/dist/src/lib/process.js.map +1 -1
- package/dist/src/lib/projectManifest.d.ts +67 -0
- package/dist/src/lib/projectManifest.d.ts.map +1 -0
- package/dist/src/lib/projectManifest.js +134 -0
- package/dist/src/lib/projectManifest.js.map +1 -0
- package/dist/src/lib/release.d.ts +9 -0
- package/dist/src/lib/release.d.ts.map +1 -0
- package/dist/src/lib/release.js +48 -0
- package/dist/src/lib/release.js.map +1 -0
- package/dist/src/lib/rootCommand.d.ts +15 -0
- package/dist/src/lib/rootCommand.d.ts.map +1 -0
- package/dist/src/lib/rootCommand.js +17 -0
- package/dist/src/lib/rootCommand.js.map +1 -0
- package/dist/src/lib/schemas.d.ts +15 -6
- package/dist/src/lib/schemas.d.ts.map +1 -1
- package/dist/src/lib/schemas.js +8 -1
- package/dist/src/lib/schemas.js.map +1 -1
- package/dist/src/lib/semver.d.ts +10 -0
- package/dist/src/lib/semver.d.ts.map +1 -0
- package/dist/src/lib/semver.js +51 -0
- package/dist/src/lib/semver.js.map +1 -0
- package/dist/src/lib/types.d.ts +5 -1
- package/dist/src/lib/types.d.ts.map +1 -1
- package/dist/src/steps/configurePrisma.d.ts.map +1 -1
- package/dist/src/steps/configurePrisma.js +18 -23
- package/dist/src/steps/configurePrisma.js.map +1 -1
- package/dist/src/steps/configureReadme.d.ts +4 -0
- package/dist/src/steps/configureReadme.d.ts.map +1 -0
- package/dist/src/steps/configureReadme.js +22 -0
- package/dist/src/steps/configureReadme.js.map +1 -0
- package/dist/src/steps/createProject.d.ts.map +1 -1
- package/dist/src/steps/createProject.js +16 -170
- package/dist/src/steps/createProject.js.map +1 -1
- package/dist/src/steps/finalSetup.d.ts +3 -2
- package/dist/src/steps/finalSetup.d.ts.map +1 -1
- package/dist/src/steps/finalSetup.js +14 -9
- package/dist/src/steps/finalSetup.js.map +1 -1
- package/dist/src/steps/installDeps.d.ts +1 -0
- package/dist/src/steps/installDeps.d.ts.map +1 -1
- package/dist/src/steps/installDeps.js +11 -0
- package/dist/src/steps/installDeps.js.map +1 -1
- package/dist/src/steps/prompts.d.ts.map +1 -1
- package/dist/src/steps/prompts.js +32 -13
- package/dist/src/steps/prompts.js.map +1 -1
- package/dist/src/utils/output.d.ts.map +1 -1
- package/dist/src/utils/output.js +23 -11
- package/dist/src/utils/output.js.map +1 -1
- package/package.json +5 -4
- package/templates/express-auth/README.md +21 -12
- package/templates/express-auth/package.json +11 -7
- package/templates/express-auth/src/config/redis.ts +109 -0
- package/templates/express-auth/src/server.ts +2 -0
- package/templates/express-auth+/README.md +25 -18
- package/templates/express-auth+/package.json +11 -7
- package/templates/express-auth+/src/auth/auth.ts +2 -0
- package/templates/express-auth+/src/auth/controllers/password.controller.ts +12 -1
- package/templates/express-auth+/src/auth/routes/password.route.ts +1 -0
- package/templates/express-auth+/src/config/redis.ts +109 -0
- package/templates/express-auth+/src/utils/security.ts +12 -0
- package/templates/express-base/README.md +21 -12
- package/templates/express-base/package.json +11 -8
- package/templates/express-base/src/.env.example +1 -1
- package/templates/express-base/src/config/redis.ts +109 -0
- package/templates/express-base/src/server.ts +2 -0
- package/templates/fullstack/.env.example +3 -2
- package/templates/fullstack/PRESET_CONTRACT.md +7 -3
- package/templates/fullstack/README.md +45 -7
- package/templates/fullstack/apps/api/package.json +6 -4
- package/templates/fullstack/apps/api/prisma/migrations/20260721000000_init/migration.sql +163 -0
- package/templates/fullstack/apps/api/prisma/migrations/migration_lock.toml +3 -0
- package/templates/fullstack/apps/api/src/auth/authenik8.ts +13 -4
- package/templates/fullstack/apps/api/src/config/env.ts +9 -1
- package/templates/fullstack/apps/api/src/config/logger.ts +21 -11
- package/templates/fullstack/apps/api/tests/logger.test.ts +43 -0
- package/templates/fullstack/apps/web/package.json +3 -1
- package/templates/fullstack/apps/web/src/App.tsx +1 -1
- package/templates/fullstack/apps/web/src/auth/RouteGuards.tsx +1 -1
- package/templates/fullstack/apps/web/src/components/AppShell.tsx +90 -45
- package/templates/fullstack/apps/web/src/components/AuthShell.tsx +10 -7
- package/templates/fullstack/apps/web/src/components/Page.tsx +6 -3
- package/templates/fullstack/apps/web/src/features/projects/ProjectPages.tsx +1 -1
- package/templates/fullstack/apps/web/src/main.tsx +13 -6
- package/templates/fullstack/apps/web/src/pages/DashboardPage.tsx +163 -23
- package/templates/fullstack/apps/web/src/pages/StatusPages.tsx +1 -1
- package/templates/fullstack/apps/web/src/pages/auth/LoginPage.tsx +93 -17
- package/templates/fullstack/apps/web/src/pages/auth/OAuthCallbackPage.tsx +1 -1
- package/templates/fullstack/apps/web/src/pages/auth/RecoveryPages.tsx +1 -1
- package/templates/fullstack/apps/web/src/pages/auth/RegisterPage.tsx +1 -1
- package/templates/fullstack/apps/web/src/pages/auth/VerifyEmailPage.tsx +1 -1
- package/templates/fullstack/apps/web/src/styles.css +119 -43
- package/templates/fullstack/apps/web/vite.config.ts +12 -0
- package/templates/fullstack/docker-compose.yml +2 -2
- package/templates/fullstack/gitignore.template +1 -0
- package/templates/fullstack/package.json +17 -8
- package/templates/fullstack/scripts/run-local.mjs +157 -0
- package/templates/prisma/postgresql/.env.example +1 -2
- package/templates/prisma/sqlite/.env.example +1 -2
- package/templates/prisma/sqlite/client.ts +2 -2
package/README.md
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
<div align="center">
|
|
3
2
|
|
|
4
3
|

|
|
@@ -16,538 +15,57 @@
|
|
|
16
15
|

|
|
17
16
|
[](https://github.com/COD434/create-authenik8-app/actions/workflows/ci.yml)
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
---
|
|
18
|
+
See a real generated project in [create-authenik8-app-example](https://github.com/COD434/create-authenik8-app-example).
|
|
23
19
|
|
|
24
20
|
## Quickstart
|
|
25
21
|
|
|
26
|
-
Create a new project:
|
|
27
|
-
|
|
28
22
|
```bash
|
|
29
23
|
npx create-authenik8-app my-app
|
|
30
24
|
```
|
|
31
25
|
|
|
32
|
-
Choose the
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npx create-authenik8-app my-api --package-manager pnpm
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
The CLI uses the invoking package manager when it can identify one, otherwise it defaults to npm. Install commands use the local package cache first and suppress registry audit/funding requests during scaffolding. Set `AUTHENIK8_VERBOSE=1` to show complete installer output.
|
|
39
|
-
|
|
40
|
-
Choose **Full-stack application** for the complete App Kit, or select one of the three Express API presets.
|
|
41
|
-
|
|
42
|
-
### Full-stack application
|
|
43
|
-
|
|
44
|
-
Requirements: Node.js 20.19+, 22.12+, or 24+, npm, and Docker with Compose.
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
cd my-app
|
|
48
|
-
npm run docker:up
|
|
49
|
-
npm run db:migrate
|
|
50
|
-
npm run db:seed
|
|
51
|
-
npm run dev
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Open `http://localhost:5173`. Vite proxies `/api` to Express on `http://localhost:3000`.
|
|
55
|
-
|
|
56
|
-
### Express API
|
|
57
|
-
|
|
58
|
-
Requirements: Node.js 20.19+, 22.12+, or 24+.
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
cd my-app
|
|
62
|
-
npm run docker:up
|
|
63
|
-
npm run prisma:migrate # Skip only when JWT-only was generated without Prisma
|
|
64
|
-
npm run dev
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## Presets
|
|
70
|
-
|
|
71
|
-
| Preset | Best for | Included |
|
|
72
|
-
| --- | --- | --- |
|
|
73
|
-
| **Express API (JWT only)** | APIs that manage identities elsewhere | Protected routes, rotating refresh tokens, RBAC, optional Prisma |
|
|
74
|
-
| **Express API + email/password** | First-party accounts | Registration, login, password hashing, Prisma |
|
|
75
|
-
| **Express API + OAuth** | Multiple sign-in methods | Password auth, Google and/or GitHub OAuth, account linking |
|
|
76
|
-
| **Full-stack application** | Starting a complete product | React/Vite, Express, shared contracts, typed client, PostgreSQL, Redis, account/admin UI, Project CRUD |
|
|
77
|
-
|
|
78
|
-
## Full-stack App Kit
|
|
79
|
-
|
|
80
|
-
The fullstack preset is an npm workspace with connected frontend, backend, and shared packages:
|
|
81
|
-
|
|
82
|
-
```text
|
|
83
|
-
apps/
|
|
84
|
-
api/ Express, Authenik8, Prisma, PostgreSQL, Redis
|
|
85
|
-
web/ React, Vite, React Router, TanStack Query
|
|
86
|
-
packages/
|
|
87
|
-
contracts/ Shared Zod request schemas and response types
|
|
88
|
-
api-client/ Typed browser client and refresh handling
|
|
89
|
-
ui/ Reusable application primitives
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
It includes:
|
|
93
|
-
|
|
94
|
-
- Registration, login, logout, OAuth, password recovery, and email verification
|
|
95
|
-
- Profile, password, linked-provider, session, and session-revocation screens
|
|
96
|
-
- Admin users, roles, status controls, session revocation, and audit events
|
|
97
|
-
- An owned Project resource across database, API, policy, client, and UI layers
|
|
98
|
-
- OpenAPI 3.1 output, health checks, structured logs, request IDs, and security middleware
|
|
99
|
-
- Docker Compose for PostgreSQL and Redis, Prisma migrations, seed data, tests, and production docs
|
|
100
|
-
|
|
101
|
-
Access tokens remain in browser memory. Refresh tokens use a restricted HttpOnly cookie, and server-side policies remain the authorization boundary.
|
|
102
|
-
|
|
103
|
-
### Full-stack commands
|
|
104
|
-
|
|
105
|
-
| Command | Purpose |
|
|
106
|
-
| --- | --- |
|
|
107
|
-
| `npm run dev` | Build shared packages and watch the API, web app, contracts, client, and UI |
|
|
108
|
-
| `npm run build` | Build all production bundles |
|
|
109
|
-
| `npm start` | Start Express and serve the built SPA and `/api` |
|
|
110
|
-
| `npm run db:migrate` | Apply the Prisma development migration |
|
|
111
|
-
| `npm run db:seed` | Create the configured administrator and example data |
|
|
112
|
-
| `npm test` | Run API policy/security tests and web storage tests |
|
|
113
|
-
| `npm run typecheck` | Type-check every workspace |
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## Core authentication features
|
|
118
|
-
|
|
119
|
-
• JWT authentication (access + refresh tokens) with secure rotation
|
|
120
|
-
|
|
121
|
-
• Redis-based token storage
|
|
122
|
-
|
|
123
|
-
• Role-Based Access Control (RBAC)
|
|
124
|
-
|
|
125
|
-
• TypeScript setup
|
|
126
|
-
|
|
127
|
-
• Express server preconfigured with security middleware
|
|
128
|
-
|
|
129
|
-
• Clean scalable folder structure
|
|
130
|
-
|
|
131
|
-
• .env file generated automatically
|
|
132
|
-
|
|
133
|
-
• Generated threat model and production guidance
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
---
|
|
137
|
-
|
|
138
|
-
## Why create-authenik8-app
|
|
139
|
-
|
|
140
|
-
Most developers waste days (or weeks) on:
|
|
141
|
-
|
|
142
|
-
• Manual JWT setup
|
|
143
|
-
|
|
144
|
-
• Secure refresh token handling
|
|
145
|
-
|
|
146
|
-
• Redis session configuration
|
|
147
|
-
|
|
148
|
-
• Proper access control
|
|
149
|
-
|
|
150
|
-
Authenik8 provides these foundations so you can start with a secure API or a connected application instead of rebuilding identity infrastructure.
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## Requirements
|
|
156
|
-
|
|
157
|
-
• Node.js 20.19+, 22.12+, or 24+ for every preset
|
|
158
|
-
|
|
159
|
-
• Docker with Compose for the generated PostgreSQL and Redis services
|
|
160
|
-
|
|
161
|
-
• Redis is required for refresh-token rotation, OAuth state, rate limits, and session controls
|
|
162
|
-
|
|
163
|
-
### CLI compatibility
|
|
164
|
-
|
|
165
|
-
The CLI is tested on Linux, Windows, and macOS. Express presets support npm, pnpm, and Bun dependency installation; the fullstack preset uses npm workspaces. Prisma-backed pnpm and Bun projects include explicit approvals for the native dependency build steps they require.
|
|
166
|
-
|
|
167
|
-
| Option | Purpose |
|
|
168
|
-
| --- | --- |
|
|
169
|
-
| `--package-manager npm\|pnpm\|bun` | Select the installer for an Express preset |
|
|
170
|
-
| `--no-install` | Generate files without installing dependencies |
|
|
171
|
-
| `--resume` | Continue an interrupted generation |
|
|
172
|
-
| `--production-ready` | Add PM2 configuration to an Express preset |
|
|
173
|
-
| `--version` | Print the installed CLI version |
|
|
174
|
-
|
|
175
|
-
Git initialization is skipped with a clear status when Git is unavailable. Installer failures retain the package manager's diagnostic output, while successful interactive runs keep the progress display concise.
|
|
176
|
-
|
|
177
|
-
---
|
|
178
|
-
|
|
179
|
-
## Environment Variables
|
|
180
|
-
|
|
181
|
-
The CLI creates a git-ignored `.env` with a unique ES256 signing key and refresh secret. Move those values into your deployment secret manager; never commit the private JWK.
|
|
182
|
-
|
|
183
|
-
### Express API presets
|
|
184
|
-
|
|
185
|
-
```dotenv
|
|
186
|
-
DATABASE_URL=file:./dev.db
|
|
187
|
-
AUTHENIK8_SIGNING_JWKS='[{"kty":"EC","crv":"P-256","kid":"<key-id>","x":"...","y":"...","d":"...","alg":"ES256"}]'
|
|
188
|
-
AUTHENIK8_ACTIVE_KID=<key-id>
|
|
189
|
-
AUTHENIK8_ISSUER=http://localhost:3000
|
|
190
|
-
AUTHENIK8_AUDIENCE=my-app-api
|
|
191
|
-
REFRESH_SECRET=<generated-random-secret>
|
|
192
|
-
REDIS_HOST=127.0.0.1
|
|
193
|
-
REDIS_PORT=6379
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
For password + OAuth, also configure the enabled providers:
|
|
197
|
-
|
|
198
|
-
```dotenv
|
|
199
|
-
GOOGLE_CLIENT_ID=your-google-client-id
|
|
200
|
-
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
|
201
|
-
GOOGLE_REDIRECT_URI=http://localhost:3000/auth/google/callback
|
|
202
|
-
GITHUB_CLIENT_ID=your-github-client-id
|
|
203
|
-
GITHUB_CLIENT_SECRET=your-github-client-secret
|
|
204
|
-
GITHUB_REDIRECT_URI=http://localhost:3000/auth/github/callback
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
### Full-stack preset
|
|
208
|
-
|
|
209
|
-
```dotenv
|
|
210
|
-
WEB_ORIGIN=http://localhost:5173
|
|
211
|
-
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/authenik8?schema=public
|
|
212
|
-
REDIS_URL=redis://localhost:6379
|
|
213
|
-
AUTHENIK8_SIGNING_JWKS='[{"kty":"EC","crv":"P-256","kid":"<key-id>","x":"...","y":"...","d":"...","alg":"ES256"}]'
|
|
214
|
-
AUTHENIK8_ACTIVE_KID=<key-id>
|
|
215
|
-
AUTHENIK8_ISSUER=http://localhost:3000
|
|
216
|
-
AUTHENIK8_AUDIENCE=my-app-api
|
|
217
|
-
REFRESH_SECRET=<generated-random-secret>
|
|
218
|
-
GOOGLE_REDIRECT_URI=http://localhost:3000/api/auth/oauth/google/callback
|
|
219
|
-
GITHUB_REDIRECT_URI=http://localhost:3000/api/auth/oauth/github/callback
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
OAuth variables are generated only for selected providers. The fullstack `.env.example` also documents cookie, proxy, logging, mail delivery, and seed-admin settings.
|
|
223
|
-
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
## RBAC Example
|
|
228
|
-
|
|
229
|
-
Example of a protected route:
|
|
230
|
-
```
|
|
231
|
-
app.get("/admin", auth.requireAdmin, (req, res) => {
|
|
232
|
-
res.json({ message: "Admin only route" });
|
|
233
|
-
});
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
---
|
|
237
|
-
|
|
238
|
-
### Testing
|
|
239
|
-
|
|
240
|
-
- Full test suite with ``80%`` coverage (actively improving)
|
|
241
|
-
|
|
242
|
-
- CI runs tests + coverage on every push and PR
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
## How It Works (Key Concept)
|
|
247
|
-
|
|
248
|
-
Authenik8 is not just another auth library.
|
|
249
|
-
It is an auth system generator.
|
|
250
|
-
At its core is the Identity Engine ``(authenik8-core)`` that treats authentication as an
|
|
251
|
-
|
|
252
|
-
# identity resolution problem:
|
|
253
|
-
|
|
254
|
-
• Unifies credentials (email/password) + OAuth providers
|
|
255
|
-
|
|
256
|
-
• Prevents duplicate identities
|
|
257
|
-
|
|
258
|
-
• Handles account linking intelligently
|
|
259
|
-
|
|
260
|
-
• Normalizes data across providers
|
|
261
|
-
|
|
262
|
-
This design makes future additions (MFA, WebAuthn, etc.) much cleaner.
|
|
263
|
-
|
|
264
|
-
---
|
|
265
|
-
## Powered by
|
|
266
|
-
|
|
267
|
-
authenik8-core (v2.0.3) JOSE/JWK human + agent identity engine (beta)
|
|
268
|
-
|
|
269
|
-
---
|
|
270
|
-
|
|
271
|
-
## How authenik8-core works in generated apps
|
|
272
|
-
|
|
273
|
-
Generated projects call:
|
|
274
|
-
|
|
275
|
-
```ts
|
|
276
|
-
const auth = await createAuthenik8({
|
|
277
|
-
jwt: authJwkConfig(),
|
|
278
|
-
refreshSecret: requiredSecret("REFRESH_SECRET"),
|
|
279
|
-
agent: agentIdentityConfig(),
|
|
280
|
-
oauth: {
|
|
281
|
-
google: {
|
|
282
|
-
clientId: requiredEnv("GOOGLE_CLIENT_ID"),
|
|
283
|
-
clientSecret: requiredEnv("GOOGLE_CLIENT_SECRET"),
|
|
284
|
-
redirectUri: requiredEnv("GOOGLE_REDIRECT_URI"),
|
|
285
|
-
},
|
|
286
|
-
github: {
|
|
287
|
-
clientId: requiredEnv("GITHUB_CLIENT_ID"),
|
|
288
|
-
clientSecret: requiredEnv("GITHUB_CLIENT_SECRET"),
|
|
289
|
-
redirectUri: requiredEnv("GITHUB_REDIRECT_URI"),
|
|
290
|
-
},
|
|
291
|
-
},
|
|
292
|
-
});
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
That factory returns one auth object used by the generated routes:
|
|
296
|
-
|
|
297
|
-
• `signToken(payload)` creates access tokens.
|
|
298
|
-
|
|
299
|
-
• `verifyToken(token)` verifies access tokens.
|
|
300
|
-
|
|
301
|
-
• `requireAuth` verifies the token and rejects Redis-revoked sessions.
|
|
302
|
-
|
|
303
|
-
• `getJwks()` returns only public verification keys for the generated JWKS endpoint.
|
|
304
|
-
|
|
305
|
-
• `generateRefreshToken(payload)` creates stateful refresh tokens.
|
|
306
|
-
|
|
307
|
-
• `refreshToken(refreshToken)` rotates refresh tokens and returns a new access/refresh pair.
|
|
308
|
-
|
|
309
|
-
• `helmet`, `rateLimit`, and `ipWhitelist` are Express middleware.
|
|
310
|
-
|
|
311
|
-
• `requireAdmin` protects admin-only routes by checking `role: "admin"`.
|
|
312
|
-
|
|
313
|
-
• `oauth.google` and `oauth.github` provide redirect and callback handlers.
|
|
314
|
-
|
|
315
|
-
• `issueTokens(payload)` creates an access/refresh pair with one shared session ID.
|
|
316
|
-
|
|
317
|
-
• `agent.issueToken(...)` creates a scoped, Redis-session-backed M2M identity after your application authenticates the workload.
|
|
318
|
-
|
|
319
|
-
• `agent.issueDelegatedToken(...)` creates an agent token bound to an active human session and explicit delegation policy.
|
|
320
|
-
|
|
321
|
-
• `agent.requireScopes(...)`, `agent.revokeSession(...)`, and `agent.revokeAgent(...)` enforce machine authorization and revocation.
|
|
322
|
-
|
|
323
|
-
### Agent identity mapping
|
|
324
|
-
|
|
325
|
-
Generated projects keep agent identity disabled with `AUTHENIK8_AGENTS={}`.
|
|
326
|
-
Adding a validated agent-to-scope mapping enables the optional core API. Every
|
|
327
|
-
project also receives `AGENT_IDENTITY.md` with a database-registry example,
|
|
328
|
-
trusted workload exchange, scoped route, delegated-user flow, and revocation.
|
|
329
|
-
|
|
330
|
-
The CLI intentionally does not scaffold a public token-minting endpoint. It
|
|
331
|
-
cannot safely infer whether your workload uses mTLS, a cloud workload identity,
|
|
332
|
-
or a signed client assertion. Applications must authenticate that workload
|
|
333
|
-
before calling the privileged `agent.issueToken()` primitive.
|
|
334
|
-
|
|
335
|
-
### Redis-backed token lifecycle
|
|
336
|
-
|
|
337
|
-
Authenik8-core intentionally makes JWT auth stateful:
|
|
338
|
-
|
|
339
|
-
1. Access tokens are signed with the active ES256 JWK and carry its `kid`, issuer, audience, and token purpose.
|
|
340
|
-
2. Refresh tokens are signed with `REFRESH_SECRET` and include a unique `jti`.
|
|
341
|
-
3. Each session's current refresh token is stored under `refresh:<userId>:<sessionId>` and indexed for complete user-wide revocation.
|
|
342
|
-
4. Refresh calls acquire a Redis lock with `lock:<userId>:<sessionId>`.
|
|
343
|
-
5. The submitted refresh token must match the Redis value.
|
|
344
|
-
6. A new access token and refresh token are issued.
|
|
345
|
-
7. The new refresh token atomically replaces the old one.
|
|
346
|
-
8. Reusing the old refresh token fails.
|
|
347
|
-
|
|
348
|
-
This is why Redis is required. It enables refresh-token replay protection, concurrent refresh protection, and server-side session control.
|
|
349
|
-
|
|
350
|
-
To rotate keys, append a new private JWK to `AUTHENIK8_SIGNING_JWKS`, set `AUTHENIK8_ACTIVE_KID` to its `kid`, and retain old public JWKs until all tokens signed by them have expired. `/.well-known/jwks.json` publishes every verification key without private fields.
|
|
351
|
-
|
|
352
|
-
### OAuth identity resolution
|
|
353
|
-
|
|
354
|
-
OAuth is not handled as separate unrelated Passport-style strategies. Provider callbacks are normalized into this profile shape:
|
|
355
|
-
|
|
356
|
-
```ts
|
|
357
|
-
{
|
|
358
|
-
email: "user@example.com",
|
|
359
|
-
name: "User Name",
|
|
360
|
-
provider: "google",
|
|
361
|
-
providerId: "provider-user-id",
|
|
362
|
-
email_verified: true
|
|
363
|
-
}
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
The Identity Engine then decides:
|
|
367
|
-
|
|
368
|
-
• Existing provider login: provider is already linked, so tokens are issued.
|
|
369
|
-
|
|
370
|
-
• New user creation: no matching identity exists, so a new user identity is created.
|
|
371
|
-
|
|
372
|
-
• Link required: an email match exists but policy requires explicit account linking.
|
|
373
|
-
|
|
374
|
-
• Link provider: an authenticated user links Google or GitHub to their existing account.
|
|
375
|
-
|
|
376
|
-
OAuth state is stored in Redis for five minutes under `oauth:state:<state>`, and Redis-backed identity records use:
|
|
377
|
-
|
|
378
|
-
```text
|
|
379
|
-
oauth:v1:user:<userId>
|
|
380
|
-
oauth:v1:email:<email>
|
|
381
|
-
oauth:v1:provider:<provider>:<providerId>
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
### Security middleware
|
|
385
|
-
|
|
386
|
-
Generated apps use the middleware returned by core:
|
|
387
|
-
|
|
388
|
-
```ts
|
|
389
|
-
app.use(auth.helmet);
|
|
390
|
-
app.use(auth.rateLimit);
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
`helmet` applies secure HTTP headers. `rateLimit` is Redis-backed and defaults to 100 requests per 60 seconds with a 300-second block. `ipWhitelist` is available for stricter APIs and allows localhost by default.
|
|
394
|
-
|
|
395
|
-
### Common core errors
|
|
396
|
-
|
|
397
|
-
• `MissingTokenError`: no refresh token was sent.
|
|
398
|
-
|
|
399
|
-
• `InvalidTokenError`: refresh token is invalid, expired, reused, or replaced.
|
|
400
|
-
|
|
401
|
-
• `Concurrent refresh detected`: two refresh requests tried to rotate the same token at once.
|
|
402
|
-
|
|
403
|
-
• `OAuthError:Invalid or expired state`: OAuth callback state is missing from Redis.
|
|
404
|
-
|
|
405
|
-
• `OAuth profile email must be verified before issuing tokens`: provider email was not verified.
|
|
406
|
-
|
|
407
|
-
• `Provider already linked to another user`: account linking tried to attach an already-owned provider.
|
|
408
|
-
|
|
409
|
-
---
|
|
410
|
-
|
|
411
|
-
## Threat Model
|
|
412
|
-
|
|
413
|
-
Generated apps include a `THREAT_MODEL.md` file. It explains:
|
|
414
|
-
|
|
415
|
-
• what the generated app protects,
|
|
416
|
-
|
|
417
|
-
• what `authenik8-core` handles with Redis-backed token state,
|
|
418
|
-
|
|
419
|
-
• what threats remain your responsibility,
|
|
420
|
-
|
|
421
|
-
• and what must be configured before production.
|
|
422
|
-
|
|
423
|
-
Key protections include refresh-token replay detection, concurrent refresh locking, OAuth state validation, verified-email OAuth token issuance, Redis-backed rate limiting, secure headers, human and agent session tracking, scoped agent middleware, delegated actor chains, and revocation.
|
|
424
|
-
|
|
425
|
-
Key non-goals include frontend XSS protection, CSRF for cookie-based auth, object-level authorization, MFA/WebAuthn, password reset, provider dashboard security, and protection from leaked secrets.
|
|
426
|
-
|
|
427
|
-
Before production, replace generated secrets, keep Redis private, use HTTPS, review CORS, configure exact OAuth callback URLs, and add business-level authorization checks to your own routes.
|
|
428
|
-
|
|
429
|
-
---
|
|
430
|
-
|
|
431
|
-
## Production Enhancements
|
|
432
|
-
|
|
433
|
-
• PM2 cluster mode + auto-restart
|
|
434
|
-
|
|
435
|
-
• Memory usage guardrails
|
|
436
|
-
|
|
437
|
-
• Security middleware (Helmet, rate limiting, etc.)
|
|
438
|
-
|
|
439
|
-
---
|
|
440
|
-
|
|
441
|
-
## The Identity Engine
|
|
442
|
-
|
|
443
|
-
At the heart of Authenik8 is the **Identity Engine** , a unified authentication core built into `authenik8-core`.
|
|
444
|
-
|
|
445
|
-
---
|
|
446
|
-
|
|
447
|
-
### Why a dedicated Identity Engine?
|
|
448
|
-
|
|
449
|
-
Traditional auth systems treat login as separate, isolated flows:
|
|
450
|
-
|
|
451
|
-
• Email/password goes one way
|
|
452
|
-
|
|
453
|
-
• Google OAuth another way
|
|
454
|
-
|
|
455
|
-
• GitHub yet another
|
|
456
|
-
|
|
457
|
-
This leads to duplicate accounts, inconsistent data, fragile linking logic, and security gaps.
|
|
458
|
-
|
|
459
|
-
The **Identity Engine** solves this by treating authentication as an **identity resolution problem** instead of just credential validation.
|
|
460
|
-
|
|
461
|
-
---
|
|
462
|
-
|
|
463
|
-
### What the Identity Engine does
|
|
464
|
-
|
|
465
|
-
• **Unified Identity Resolution**
|
|
466
|
-
It intelligently resolves any login method (credentials, OAuth, or future strategies) into a single, consistent user identity in your system.
|
|
467
|
-
|
|
468
|
-
• **Smart Account Linking**
|
|
469
|
-
Automatically detects when a user already exists (via email or other signals) and offers secure linking instead of creating duplicates.
|
|
470
|
-
|
|
471
|
-
• **Profile Normalization**
|
|
472
|
-
Converts provider-specific data (Google profile, GitHub profile, etc.) into your app’s clean, unified user schema.
|
|
473
|
-
|
|
474
|
-
• **Secure Token Lifecycle Management**
|
|
475
|
-
Handles JWT access + refresh tokens with rotation, JTI-based replay protection, and Redis-backed stateful control.
|
|
476
|
-
|
|
477
|
-
- **Consistent Security Layer**
|
|
478
|
-
Applies the same high-security rules (rate limiting, IP awareness, session controls) across all authentication methods.
|
|
479
|
-
|
|
480
|
-
---
|
|
481
|
-
|
|
482
|
-
### OAuth Through the Identity Engine
|
|
483
|
-
|
|
484
|
-
OAuth (Google, GitHub, and more coming) is **not** implemented as direct Passport.js-style routes. Instead:
|
|
485
|
-
|
|
486
|
-
1. The provider callback is received
|
|
487
|
-
|
|
488
|
-
2. The Identity Engine resolves/normalizes the profile
|
|
489
|
-
|
|
490
|
-
3. It decides: login existing user, link to existing account, or create new identity
|
|
491
|
-
|
|
492
|
-
4. Returns consistent tokens and user data
|
|
493
|
-
|
|
494
|
-
This design makes adding new providers or authentication methods much cleaner and more secure.
|
|
495
|
-
|
|
496
|
-
---
|
|
497
|
-
|
|
498
|
-
## Authenik8 vs Passport.js
|
|
499
|
-
|
|
500
|
-
| Aspect | **Authenik8** | **Passport.js** |
|
|
501
|
-
|---------------------------|----------------------------------------------------|------------------------------------------|
|
|
502
|
-
| **Purpose** | Full auth system generator | Authentication middleware |
|
|
503
|
-
| **Setup Time** | \~30 seconds (complete project) | Hours to days |
|
|
504
|
-
| **JWT + Refresh Tokens** | Secure rotation + replay protection built-in | Manual implementation required |
|
|
505
|
-
| **OAuth** | Unified via Identity Engine (smart linking) | Separate strategies per provider |
|
|
506
|
-
| **RBAC** | Built-in middleware | Not included |
|
|
507
|
-
| **Production Features** | PM2, Helmet, rate limiting, memory guards | None (you add them) |
|
|
508
|
-
| **Identity Management** | Centralized Identity Engine | None |
|
|
509
|
-
| **Flexibility** | Medium (opinionated & extensible) | Very high |
|
|
510
|
-
| **Best For** | Fast, secure, consistent backends | Maximum customization |
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
Passport.js is a great flexible tool, but it leaves you to build secure JWT, refresh logic, OAuth linking, and RBAC yourself.
|
|
514
|
-
Authenik8 gives you a complete, production-ready authentication system from day one.
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
---
|
|
518
|
-
|
|
519
|
-
### Benefits for you
|
|
520
|
-
|
|
521
|
-
• No more duplicate user headaches
|
|
522
|
-
|
|
523
|
-
• Consistent security behavior across all login methods
|
|
524
|
-
|
|
525
|
-
• Easier future-proofing (MFA, WebAuthn, enterprise SSO, etc.)
|
|
526
|
-
|
|
527
|
-
• Cleaner, more maintainable codebase in your generated project
|
|
528
|
-
|
|
529
|
-
The Identity Engine is what makes Authenik8 feel like a coherent **authentication system** rather than a collection of routes and middleware.
|
|
26
|
+
Choose the fullstack application for a connected React and Express project, or select one of the focused Express API presets. Start with the [quickstart guide](docs/quickstart.md) for requirements and generated-project commands.
|
|
530
27
|
|
|
531
|
-
|
|
28
|
+
## Documentation
|
|
532
29
|
|
|
533
|
-
## Notes
|
|
534
30
|
|
|
535
|
-
|
|
31
|
+
### Create and maintain projects
|
|
536
32
|
|
|
537
|
-
|
|
33
|
+
- [Quickstart](docs/quickstart.md)
|
|
34
|
+
- [Non-interactive generation](docs/non-interactive-generation.md)
|
|
35
|
+
- [Project diagnostics](docs/project-diagnostics.md)
|
|
36
|
+
- [Post-generation recipes](docs/post-generation-recipes.md)
|
|
37
|
+
- [Upgrade planning and CI policy](docs/upgrades-and-ci.md)
|
|
38
|
+
- [CLI reference](docs/cli-reference.md)
|
|
538
39
|
|
|
539
|
-
|
|
40
|
+
### Choose an application shape
|
|
540
41
|
|
|
42
|
+
- [Presets](docs/presets.md)
|
|
43
|
+
- [Fullstack App Kit](docs/fullstack-app-kit.md)
|
|
44
|
+
- [Core authentication features](docs/authentication-features.md)
|
|
45
|
+
- [Why create-authenik8-app](docs/why-create-authenik8-app.md)
|
|
46
|
+
- [Requirements](docs/requirements.md)
|
|
541
47
|
|
|
48
|
+
### Configure authentication
|
|
542
49
|
|
|
543
|
-
|
|
50
|
+
- [Environment variables](docs/environment-variables.md)
|
|
51
|
+
- [RBAC example](docs/rbac-example.md)
|
|
52
|
+
- [Identity Engine](docs/identity-engine.md)
|
|
53
|
+
- [Using authenik8-core](docs/authenik8-core.md)
|
|
54
|
+
- [Threat model](docs/threat-model.md)
|
|
544
55
|
|
|
545
|
-
## Roadmap
|
|
546
56
|
|
|
547
|
-
|
|
57
|
+
### Operate and evaluate
|
|
548
58
|
|
|
549
|
-
|
|
59
|
+
- [Testing](docs/testing.md)
|
|
60
|
+
- [Production enhancements](docs/production-enhancements.md)
|
|
61
|
+
- [Authenik8 compared with Passport.js](docs/authenik8-vs-passport.md)
|
|
62
|
+
- [Project notes](docs/notes.md)
|
|
63
|
+
- [Roadmap](docs/roadmap.md)
|
|
550
64
|
|
|
551
|
-
|
|
65
|
+
## Contributing and support
|
|
552
66
|
|
|
553
|
-
|
|
67
|
+
- [Contributing](CONTRIBUTING.md)
|
|
68
|
+
- [Testing this repository](TESTING.md)
|
|
69
|
+
- [Security policy](SECURITY.md)
|
|
70
|
+
- [Code of conduct](CODE_OF_CONDUCT.md)
|
|
71
|
+
- [Changelog](CHANGELOG.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/bin/cli.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { doctorHelp, formatDoctorReport } from "../commands/doctor/output.js";
|
|
3
|
+
import { DoctorUsageError, parseDoctorArguments, runDoctor, } from "../commands/doctor/index.js";
|
|
4
|
+
import { DoctorProjectError } from "../commands/doctor/context.js";
|
|
5
|
+
import { addHelp, formatAddResult, formatRecipeList } from "../commands/add/output.js";
|
|
6
|
+
import { AddUsageError, parseAddArguments, runAdd } from "../commands/add/index.js";
|
|
7
|
+
import { AddProjectError } from "../commands/add/context.js";
|
|
8
|
+
import { AddRecipeError } from "../commands/add/plan.js";
|
|
9
|
+
import { formatUpgradePlan, upgradeHelp } from "../commands/upgrade/output.js";
|
|
10
|
+
import { parseUpgradeArguments, runUpgrade, upgradeCheckExitCode, UpgradeUsageError, } from "../commands/upgrade/index.js";
|
|
11
|
+
import { UpgradeProjectError } from "../commands/upgrade/context.js";
|
|
12
|
+
import { resolveRootCommand } from "../lib/rootCommand.js";
|
|
13
|
+
function write(stream, value) {
|
|
14
|
+
stream.write(value.endsWith("\n") ? value : `${value}\n`);
|
|
15
|
+
}
|
|
16
|
+
async function main() {
|
|
17
|
+
const route = resolveRootCommand(process.argv.slice(2));
|
|
18
|
+
if (route.name === "create") {
|
|
19
|
+
process.argv = [process.argv[0] ?? "node", process.argv[1] ?? "create-authenik8-app", ...route.args];
|
|
20
|
+
await import("./index.js");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (route.name === "add") {
|
|
24
|
+
try {
|
|
25
|
+
const options = parseAddArguments(route.args);
|
|
26
|
+
if (options.help)
|
|
27
|
+
write(process.stdout, addHelp());
|
|
28
|
+
else if (options.list)
|
|
29
|
+
write(process.stdout, formatRecipeList());
|
|
30
|
+
else
|
|
31
|
+
write(process.stdout, formatAddResult(await runAdd(options)));
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof AddUsageError) {
|
|
35
|
+
write(process.stderr, `Error: ${error.message}\n${addHelp()}`);
|
|
36
|
+
process.exitCode = 2;
|
|
37
|
+
}
|
|
38
|
+
else if (error instanceof AddProjectError || error instanceof AddRecipeError) {
|
|
39
|
+
write(process.stderr, `Error: ${error.message}`);
|
|
40
|
+
process.exitCode = 1;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
44
|
+
write(process.stderr, `Error: Recipe could not complete: ${detail}`);
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (route.name === "upgrade") {
|
|
51
|
+
try {
|
|
52
|
+
const options = parseUpgradeArguments(route.args);
|
|
53
|
+
if (options.help)
|
|
54
|
+
write(process.stdout, upgradeHelp());
|
|
55
|
+
else {
|
|
56
|
+
const plan = await runUpgrade(options);
|
|
57
|
+
write(process.stdout, formatUpgradePlan(plan, options.json));
|
|
58
|
+
if (options.check)
|
|
59
|
+
process.exitCode = upgradeCheckExitCode(plan);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof UpgradeUsageError) {
|
|
64
|
+
write(process.stderr, `Error: ${error.message}\n${upgradeHelp()}`);
|
|
65
|
+
process.exitCode = 2;
|
|
66
|
+
}
|
|
67
|
+
else if (error instanceof UpgradeProjectError) {
|
|
68
|
+
write(process.stderr, `Error: ${error.message}`);
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
73
|
+
write(process.stderr, `Error: Upgrade plan could not complete: ${detail}`);
|
|
74
|
+
process.exitCode = 1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const options = parseDoctorArguments(route.args);
|
|
81
|
+
if (options.help) {
|
|
82
|
+
write(process.stdout, doctorHelp());
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const report = await runDoctor(options);
|
|
86
|
+
write(process.stdout, formatDoctorReport(report, options.json));
|
|
87
|
+
if (report.summary.failed > 0)
|
|
88
|
+
process.exitCode = 1;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
if (error instanceof DoctorUsageError) {
|
|
93
|
+
write(process.stderr, `Error: ${error.message}\n${doctorHelp()}`);
|
|
94
|
+
process.exitCode = 2;
|
|
95
|
+
}
|
|
96
|
+
else if (error instanceof DoctorProjectError) {
|
|
97
|
+
write(process.stderr, `Error: ${error.message}`);
|
|
98
|
+
process.exitCode = 1;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
102
|
+
write(process.stderr, `Error: Doctor could not complete: ${detail}`);
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
void main().catch((error) => {
|
|
108
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
109
|
+
write(process.stderr, `Error: ${detail}`);
|
|
110
|
+
process.exitCode = 1;
|
|
111
|
+
});
|
|
112
|
+
//# sourceMappingURL=cli.js.map
|