create-authenik8-app 1.0.7 → 2.0.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.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+
2
+ MIT License
3
+
4
+ Copyright (c) 2026 TheSBD
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md CHANGED
@@ -1,8 +1,4 @@
1
1
 
2
-
3
-
4
- ---
5
-
6
2
  # create-authenik8-app
7
3
 
8
4
  <p align="center">
@@ -15,7 +11,7 @@
15
11
 
16
12
  ---
17
13
 
18
- ## 📦 Usage
14
+ ## Usage
19
15
 
20
16
  Create a new project:
21
17
 
@@ -27,8 +23,8 @@ Then:
27
23
  cd my-app
28
24
  npm install
29
25
  npm run dev
30
- ```
31
26
 
27
+ ```
32
28
  ---
33
29
 
34
30
  ## What you get instantly
@@ -37,19 +33,19 @@ A fully working Express authentication starter with:
37
33
 
38
34
  JWT authentication (access + refresh tokens)
39
35
 
40
- Secure refresh token rotation
36
+ Secure refresh token rotation
41
37
 
42
- Redis-based token storage
38
+ Redis-based token storage
43
39
 
44
- Role-Based Access Control (RBAC)
40
+ Role-Based Access Control (RBAC)
45
41
 
46
42
  TypeScript setup
47
43
 
48
- Express server preconfigured
44
+ Express server preconfigured
49
45
 
50
46
  Clean scalable folder structure
51
47
 
52
- .env file generated automatically
48
+ .env file generated automatically
53
49
 
54
50
 
55
51
 
@@ -83,8 +79,8 @@ Redis (required for refresh tokens)
83
79
 
84
80
  ---
85
81
 
86
- ## Redis Setup
87
- ```
82
+ ## Redis Setup
83
+ ```
88
84
 
89
85
  Local
90
86
 
@@ -93,11 +89,10 @@ redis-server
93
89
  Docker
94
90
 
95
91
  docker run -p 6379:6379 redis
96
-
97
92
  ```
98
93
  ---
99
94
 
100
- ## Environment Variables
95
+ Environment Variables
101
96
 
102
97
  Generated automatically:
103
98
  ```
@@ -106,22 +101,22 @@ REFRESH_SECRET=your-refresh-secret
106
101
 
107
102
  REDIS_HOST=127.0.0.1
108
103
  REDIS_PORT=6379
109
-
110
104
  ```
105
+
111
106
  ---
112
107
 
113
- ## RBAC Example
114
- ```
115
- Example of a protected route:
108
+ RBAC Example
116
109
 
110
+ Example of a protected route:
111
+ ```
117
112
  app.get("/admin", auth.requireAdmin, (req, res) => {
118
113
  res.json({ message: "Admin only route" });
119
114
  });
120
-
121
115
  ```
116
+
122
117
  ---
123
118
 
124
- 📦 Powered by
119
+ ## Powered by
125
120
 
126
121
  authenik8-core
127
122
 
@@ -131,10 +126,9 @@ authenik8-core
131
126
 
132
127
  ## Project Structure
133
128
  ```
134
-
135
129
  my-app/
136
130
  ├── src/
137
- |
131
+
138
132
  │ ├
139
133
  │ └── server.ts
140
134
  ├── .env
@@ -156,7 +150,7 @@ RBAC is included via middleware (e.g. requireAdmin)
156
150
 
157
151
  ---
158
152
 
159
- ## Roadmap
153
+ ## Roadmap
160
154
 
161
155
  OAuth providers (Google, GitHub)
162
156
 
@@ -168,6 +162,3 @@ Admin dashboard
168
162
 
169
163
  Production presets
170
164
 
171
-
172
-
173
- ---
package/dist/bin/index.js CHANGED
@@ -3,6 +3,7 @@ import fs from "fs-extra";
3
3
  import path from "path";
4
4
  import chalk from "chalk";
5
5
  import inquirer from "inquirer";
6
+ import { ExitPromptError } from "@inquirer/core";
6
7
  import ora from "ora";
7
8
  import { execSync } from "child_process";
8
9
  import { fileURLToPath } from "url";
@@ -14,6 +15,7 @@ if (!projectName) {
14
15
  process.exit(1);
15
16
  }
16
17
  const targetDir = path.join(process.cwd(), projectName);
18
+ let projectCreated = false;
17
19
  async function main() {
18
20
  console.log(chalk.blue.bold("\n🚀 Authenik8 App Generator\n"));
19
21
  if (process.argv.includes("--help")) {
@@ -72,8 +74,8 @@ Available options:
72
74
  name: "database",
73
75
  message: "Choose database:",
74
76
  choices: [
75
- { name: "PostgreSQL", value: "postgresql" },
76
- { name: "SQLite (quick start)", value: "sqlite" }
77
+ { name: "PostgreSQL", value: "postgresql(recommended for auth)" },
78
+ { name: "SQLite (quick start, limited features)", value: "sqlite" }
77
79
  ],
78
80
  when: (answers) => answers.usePrisma,
79
81
  },
@@ -83,6 +85,13 @@ Available options:
83
85
  message: "Initialize git?",
84
86
  default: true,
85
87
  },
88
+ {
89
+ type: "confirm",
90
+ name: "usePasswordAuth",
91
+ message: "Include email/password authentication?",
92
+ default: true,
93
+ when: (answers) => answers.usePrisma && answers.database === "postgresql"
94
+ },
86
95
  ]);
87
96
  // 🚫 Prevent overwrite
88
97
  if (fs.existsSync(targetDir)) {
@@ -91,13 +100,16 @@ Available options:
91
100
  }
92
101
  console.log(chalk.cyan("\n⚙️ Setting things up...\n"));
93
102
  const templateRoot = path.resolve(__dirname, "../../templates");
94
- const templatePath = answers.framework === "Express"
95
- ? path.join(templateRoot, "express-ts")
96
- : path.join(templateRoot, "express-ts"); // fallback for now
103
+ let templateName = "express-base";
104
+ if (answers.usePasswordAuth && answers.usePrisma) {
105
+ templateName = "express-auth";
106
+ }
107
+ const templatePath = path.join(templateRoot, templateName);
97
108
  // 📁 Create project (SPINNER)
98
109
  const createSpinner = ora("Creating project structure...").start();
99
110
  try {
100
111
  await fs.copy(templatePath, targetDir);
112
+ projectCreated = true;
101
113
  createSpinner.succeed("Project files created");
102
114
  }
103
115
  catch (err) {
@@ -108,8 +120,8 @@ Available options:
108
120
  if (answers.usePrisma) {
109
121
  const prismaSpinner = ora("Adding Prisma setup...").start();
110
122
  try {
111
- const dbType = answers.database.toLowerCase().includes("post")
112
- ? "postgresql"
123
+ const dbType = answers.database ===
124
+ "postgresql" ? "postgresql"
113
125
  : "sqlite";
114
126
  const prismaTemplatePath = path.join(templateRoot, `prisma/${dbType}`);
115
127
  // Copy prisma schema
@@ -118,14 +130,15 @@ Available options:
118
130
  await fs.copy(path.join(prismaTemplatePath, ".env"), path.join(targetDir, ".env"));
119
131
  const pkgPath = path.join(targetDir, "package.json");
120
132
  const pkg = await fs.readJson(pkgPath);
133
+ await fs.writeJson(pkgPath, pkg, { spaces: 2 });
121
134
  // Inject dependencies
122
135
  pkg.dependencies = {
123
136
  ...pkg.dependencies,
124
- "@prisma/client": "^5.0.0",
137
+ "@prisma/client": "5.22.0",
125
138
  };
126
139
  pkg.devDependencies = {
127
140
  ...pkg.devDependencies,
128
- prisma: "^5.0.0",
141
+ prisma: "5.22.0",
129
142
  };
130
143
  // Add scripts
131
144
  pkg.scripts = {
@@ -133,26 +146,52 @@ Available options:
133
146
  "prisma:generate": "prisma generate",
134
147
  "prisma:migrate": "prisma migrate dev",
135
148
  };
136
- prismaSpinner.succeed(`Prisma (${answers.database}) configured`);
149
+ prismaSpinner.succeed(`Prisma (${dbType}) configured`);
137
150
  }
138
151
  catch (err) {
139
152
  prismaSpinner.fail("Failed to setup Prisma");
140
153
  console.error(err);
141
154
  }
142
- }
143
- //
144
- const installSpinner = ora("Installing dependencies...(this may take a few minutes)").start();
145
- try {
146
- execSync("npm install", {
147
- cwd: targetDir,
148
- stdio: "ignore",
149
- });
150
- installSpinner.succeed("Dependencies installed");
151
- }
152
- catch (err) {
153
- installSpinner.fail("Failed to install dependencies");
154
- console.error(err);
155
- process.exit(1);
155
+ const installSpinner = ora("Installing dependencies...(this may take a few minutes)").start();
156
+ try {
157
+ execSync("npm install", {
158
+ cwd: targetDir,
159
+ stdio: "ignore",
160
+ });
161
+ installSpinner.succeed("Dependencies installed");
162
+ }
163
+ catch (err) {
164
+ installSpinner.fail("Failed to install dependencies");
165
+ console.error(err);
166
+ process.exit(1);
167
+ }
168
+ if (answers.usePrisma) {
169
+ const prismaGenSpinner = ora("Generating Prisma client...").start();
170
+ try {
171
+ execSync("npx prisma@5.22.0 generate", {
172
+ cwd: targetDir,
173
+ stdio: "ignore"
174
+ });
175
+ prismaGenSpinner.succeed("Prisma client generated");
176
+ }
177
+ catch (err) {
178
+ prismaGenSpinner.fail("Failed to generate Prisma client");
179
+ console.error(err);
180
+ }
181
+ }
182
+ const authSpinner = ora("Installing password auth...").start();
183
+ try {
184
+ execSync("npm install argon2", {
185
+ cwd: targetDir,
186
+ stdio: "ignore",
187
+ });
188
+ authSpinner.succeed("Password auth ready (argon2)");
189
+ }
190
+ catch (err) {
191
+ authSpinner.fail("Failed to install password auth");
192
+ console.error(err);
193
+ process.exit(1);
194
+ }
156
195
  }
157
196
  if (answers.useGit) {
158
197
  const gitSpinner = ora("Initializing git...").start();
@@ -177,6 +216,35 @@ Next steps:
177
216
 
178
217
  🔥 Your Authenik8 server is ready to go!
179
218
  `));
219
+ console.log(`
220
+ ✔ Auth: ${answers.usePasswordAuth ? "JWT + Password" : "JWT only"}
221
+ ✔ Database: ${answers.usePrisma ? answers.database : "None"}
222
+ ✔ ORM: ${answers.usePrisma ? "Prisma" : "None"}
223
+ `);
180
224
  }
181
- main();
225
+ process.on("SIGINT", async () => {
226
+ console.log("\n👋 Authenik8 setup cancelled.");
227
+ if (projectCreated && fs.existsSync(targetDir)) {
228
+ await fs.remove(targetDir);
229
+ console.log("🧹 Cleaned up incomplete project.");
230
+ }
231
+ process.exit(0);
232
+ });
233
+ main().catch(async (err) => {
234
+ if (err instanceof ExitPromptError) {
235
+ console.log("\n👋 Authenik8 setup cancelled.");
236
+ if (projectCreated && fs.existsSync(targetDir)) {
237
+ await fs.remove(targetDir);
238
+ console.log("🧹 Cleaned up incomplete project.");
239
+ }
240
+ process.exit(0);
241
+ }
242
+ console.error("\n❌ Unexpected error:");
243
+ console.error(err);
244
+ if (projectCreated && fs.existsSync(targetDir)) {
245
+ await fs.remove(targetDir);
246
+ console.log("🧹 Cleaned up incomplete project.");
247
+ }
248
+ process.exit(1);
249
+ });
182
250
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-authenik8-app",
3
- "version": "1.0.7",
3
+ "version": "2.0.1",
4
4
  "description":"Create production-ready backend APIs in seconds. Authenik8 scaffolds Express + Prisma projects with JWT authentication, database setup (PostgreSQL or SQLite), and scalable architecture out of the box.",
5
5
  "bin": {
6
6
  "create-authenik8-app": "dist/bin/index.js"
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "authenik8-app",
3
+ "version": "1.0.6",
4
+ "description": "Authenik8 generated Express auth app",
5
+ "main": "dist/server.js",
6
+ "type": "commonjs",
7
+ "scripts": {
8
+ "dev": "ts-node-dev --respawn --transpile-only src/server.ts",
9
+ "build": "tsc",
10
+ "start": "node dist/server.js",
11
+ "prisma:generate": "prisma generate",
12
+ "prisma:migrate": "prisma migrate dev"
13
+ },
14
+ "dependencies": {
15
+ "authenik8-core": "0.1.5",
16
+ "express": "^4.19.2"
17
+ },
18
+ "devDependencies": {
19
+ "@types/express": "^4.17.21",
20
+ "@types/node": "^20.0.0",
21
+ "ts-node-dev": "^2.0.0",
22
+ "typescript": "^5.0.0"
23
+ }
24
+ }
@@ -0,0 +1,15 @@
1
+ import { PrismaClient } from "@prisma/client";
2
+
3
+ const globalForPrisma = globalThis as unknown as {
4
+ prisma: PrismaClient | undefined;
5
+ };
6
+
7
+ export const prisma =
8
+ globalForPrisma.prisma ??
9
+ new PrismaClient({
10
+ log: ["error", "warn"],
11
+ });
12
+
13
+ if (process.env.NODE_ENV !== "production") {
14
+ globalForPrisma.prisma = prisma;
15
+ }
@@ -0,0 +1,78 @@
1
+ import express from "express";
2
+ import { createAuthenik8 } from "authenik8-core";
3
+ import { hashPassword, comparePassword } from "./utils/hash";
4
+ import {prisma} from "./prisma/client"
5
+
6
+ const app = express();
7
+ app.use(express.json());
8
+
9
+ async function start() {
10
+ const auth = await createAuthenik8({
11
+ jwtSecret: process.env.JWT_SECRET!,
12
+ refreshSecret: process.env.REFRESH_SECRET!,
13
+ });
14
+
15
+
16
+ app.post("/register", async (req, res) => {
17
+ const { email, password } = req.body;
18
+
19
+ const hashedPassword = await hashPassword(password);
20
+
21
+ const user = await prisma.user.create({
22
+ data: {
23
+ email,
24
+ password: hashedPassword,
25
+ },
26
+ });
27
+
28
+ res.json({ message: "User created", userId: user.id });
29
+ });
30
+
31
+
32
+ app.post("/login", async (req, res) => {
33
+ const { email, password } = req.body;
34
+
35
+ const user = await prisma.user.findUnique({
36
+ where: { email },
37
+ });
38
+
39
+ if (!user) {
40
+ return res.status(401).json({ error: "Invalid credentials" });
41
+ }
42
+
43
+ const isValid = await comparePassword(password, user.password);
44
+
45
+ if (!isValid) {
46
+ return res.status(401).json({ error: "Invalid credentials" });
47
+ }
48
+
49
+ const accessToken = auth.signToken({
50
+ id: user.id,
51
+ email: user.email,
52
+ });
53
+
54
+ const refreshToken = await auth.generateRefreshToken({
55
+ id: user.id,
56
+ email: user.email,
57
+ });
58
+
59
+ res.json({ accessToken, refreshToken });
60
+ });
61
+
62
+
63
+ app.post("/refresh", async (req, res) => {
64
+ const tokens = await auth.refreshToken(req.body.refreshToken);
65
+ res.json(tokens);
66
+ });
67
+
68
+ // ✅ PROTECTED
69
+ app.get("/protected", auth.requireAdmin, (req, res) => {
70
+ res.json({ message: "Protected route" });
71
+ });
72
+
73
+ app.listen(3000, () => {
74
+ console.log("🚀 Server running on http://localhost:3000");
75
+ });
76
+ }
77
+
78
+ start();
@@ -0,0 +1,12 @@
1
+ import argon2 from "argon2";
2
+
3
+ export const hashPassword = async (password: string): Promise<string> => {
4
+ return argon2.hash(password);
5
+ };
6
+
7
+ export const comparePassword = async (
8
+ password: string,
9
+ hash: string
10
+ ): Promise<boolean> => {
11
+ return argon2.verify(hash, password);
12
+ };
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "rootDir": "./src",
6
+ "outDir": "./dist",
7
+
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+
12
+ "forceConsistentCasingInFileNames": true
13
+ },
14
+ "include": ["src"],
15
+ "exclude": ["node_modules", "dist"]
16
+ }
@@ -0,0 +1,56 @@
1
+ import express from "express";
2
+ import { createAuthenik8 } from "authenik8-core";
3
+
4
+ const app = express();
5
+ app.use(express.json());
6
+
7
+ async function start() {
8
+ const auth = await createAuthenik8({
9
+ jwtSecret: process.env.JWT_SECRET!,
10
+ refreshSecret: process.env.REFRESH_SECRET!,
11
+ });
12
+
13
+ app.use(auth.helmet);
14
+ app.use(auth.rateLimit);
15
+
16
+
17
+ app.get("/public", (req, res) => {
18
+ res.json({ message: "Public route" });
19
+ });
20
+
21
+
22
+ app.get("/guest", async (req, res) => {
23
+ const token = await auth.guestToken({ role: "guest" });
24
+ res.json({ token });
25
+ });
26
+
27
+
28
+
29
+ app.get("/protected", async (req, res) => {
30
+ const token = req.headers.authorization?.split(" ")[1];
31
+
32
+ try {
33
+ const decoded = await auth.verifyToken(token);
34
+ res.json({ message: "Protected data", user: decoded });
35
+ } catch {
36
+ res.status(401).json({ error: "Unauthorized" });
37
+ }
38
+ });
39
+
40
+
41
+ app.post("/refresh", async (req, res) => {
42
+ const tokens = await auth.refreshToken(req.body.refreshToken);
43
+ res.json(tokens);
44
+ });
45
+
46
+ // 🛡️ Admin route
47
+ app.get("/admin", auth.requireAdmin, (req, res) => {
48
+ res.json({ message: "Admin only" });
49
+ });
50
+
51
+ app.listen(3000, () => {
52
+ console.log("🚀 Server running on http://localhost:3000");
53
+ });
54
+ }
55
+
56
+ start();
@@ -11,7 +11,7 @@ model User {
11
11
  id String @id @default(uuid())
12
12
  email String @unique
13
13
  password String
14
- role Role @default(USER)
14
+ role String @default("USER")
15
15
  verified Boolean @default(false)
16
16
 
17
17
  createdAt DateTime @default(now())
@@ -30,8 +30,3 @@ model Session {
30
30
 
31
31
  createdAt DateTime @default(now())
32
32
  }
33
-
34
- enum Role {
35
- USER
36
- ADMIN
37
- }
@@ -1,36 +0,0 @@
1
- import express from "express";
2
- import { createAuthenik8 } from "authenik8-core";
3
-
4
- const app = express();
5
- app.use(express.json());
6
-
7
- async function start() {
8
- const auth = await createAuthenik8({
9
- jwtSecret: process.env.JWT_SECRET!,
10
- refreshSecret: process.env.REFRESH_SECRET!,
11
- });
12
-
13
- app.post("/login", async (req, res) => {
14
- const user = { id: "123", email: "test@test.com" };
15
-
16
- const accessToken = auth.signToken(user);
17
- const refreshToken = await auth.generateRefreshToken(user);
18
-
19
- res.json({ accessToken, refreshToken });
20
- });
21
-
22
- app.post("/refresh", async (req, res) => {
23
- const tokens = await auth.refreshToken(req.body.refreshToken);
24
- res.json(tokens);
25
- });
26
-
27
- app.get("/protected", auth.requireAdmin, (req, res) => {
28
- res.json({ message: "Protected route" });
29
- });
30
-
31
- app.listen(3000, () => {
32
- console.log("🚀 Server running on http://localhost:3000");
33
- });
34
- }
35
-
36
- start();