create-authhero 0.4.0 → 0.6.0

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.
@@ -0,0 +1,26 @@
1
+ import { Context } from "hono";
2
+ import { HTTPException } from "hono/http-exception";
3
+ import { AuthHeroConfig, init } from "authhero";
4
+ import { swaggerUI } from "@hono/swagger-ui";
5
+
6
+ export default function createApp(config: AuthHeroConfig) {
7
+ const { app } = init(config);
8
+
9
+ app
10
+ .onError((err, ctx) => {
11
+ if (err instanceof HTTPException) {
12
+ return err.getResponse();
13
+ }
14
+ console.error(err);
15
+ return ctx.text(err.message, 500);
16
+ })
17
+ .get("/", async (ctx: Context) => {
18
+ return ctx.json({
19
+ name: "AuthHero Server",
20
+ status: "running",
21
+ });
22
+ })
23
+ .get("/docs", swaggerUI({ url: "/api/v2/spec" }));
24
+
25
+ return app;
26
+ }
@@ -0,0 +1,27 @@
1
+ import { OpenAPIHono } from "@hono/zod-openapi";
2
+ import { D1Dialect } from "kysely-d1";
3
+ import { Kysely } from "kysely";
4
+ import createAdapters from "@authhero/kysely-adapter";
5
+ import createApp from "./app";
6
+ import { Env } from "./types";
7
+ import { AuthHeroConfig, Bindings, Variables } from "authhero";
8
+
9
+ let app: OpenAPIHono<{ Bindings: Bindings; Variables: Variables }> | undefined;
10
+
11
+ export default {
12
+ async fetch(request: Request, env: Env): Promise<Response> {
13
+ if (!app) {
14
+ const dialect = new D1Dialect({ database: env.AUTH_DB });
15
+ const db = new Kysely<any>({ dialect });
16
+ const dataAdapter = createAdapters(db);
17
+
18
+ const config: AuthHeroConfig = {
19
+ dataAdapter,
20
+ };
21
+
22
+ app = createApp(config);
23
+ }
24
+
25
+ return app.fetch(request, env);
26
+ },
27
+ };
@@ -0,0 +1,5 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+
3
+ export interface Env {
4
+ AUTH_DB: D1Database;
5
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "types": ["@cloudflare/workers-types"]
11
+ },
12
+ "include": ["src/**/*"],
13
+ "exclude": ["node_modules"]
14
+ }
@@ -0,0 +1,21 @@
1
+ name = "authhero-server"
2
+ main = "src/index.ts"
3
+ compatibility_date = "2024-11-20"
4
+
5
+ # D1 Database binding
6
+ # Run: wrangler d1 create authhero-db
7
+ # Then uncomment and update the database_id below:
8
+ # [[d1_databases]]
9
+ # binding = "AUTH_DB"
10
+ # database_name = "authhero-db"
11
+ # database_id = "<YOUR_DATABASE_ID>"
12
+
13
+ # For local development, you can use a local D1 database:
14
+ [[d1_databases]]
15
+ binding = "AUTH_DB"
16
+ database_name = "authhero-db"
17
+ database_id = "local"
18
+
19
+ # Optional: Enable observability
20
+ # [observability]
21
+ # enabled = true
@@ -0,0 +1,344 @@
1
+ #!/usr/bin/env node
2
+ import { Command as b } from "commander";
3
+ import d from "inquirer";
4
+ import l from "fs";
5
+ import c from "path";
6
+ import { spawn as f } from "child_process";
7
+ const w = new b(), r = {
8
+ local: {
9
+ name: "Local (SQLite)",
10
+ description: "Local development setup with SQLite database - great for getting started",
11
+ templateDir: "local",
12
+ packageJson: (t) => ({
13
+ name: t,
14
+ version: "1.0.0",
15
+ type: "module",
16
+ scripts: {
17
+ dev: "npx tsx watch src/index.ts",
18
+ start: "npx tsx src/index.ts",
19
+ migrate: "npx tsx src/migrate.ts",
20
+ seed: "npx tsx src/seed.ts"
21
+ },
22
+ dependencies: {
23
+ "@authhero/kysely-adapter": "latest",
24
+ "@hono/swagger-ui": "^0.5.0",
25
+ "@hono/zod-openapi": "^0.19.0",
26
+ "@hono/node-server": "latest",
27
+ authhero: "latest",
28
+ "better-sqlite3": "latest",
29
+ hono: "^4.6.0",
30
+ kysely: "latest"
31
+ },
32
+ devDependencies: {
33
+ "@types/better-sqlite3": "^7.6.0",
34
+ "@types/node": "^20.0.0",
35
+ tsx: "^4.0.0",
36
+ typescript: "^5.5.0"
37
+ }
38
+ }),
39
+ seedFile: "seed.ts"
40
+ },
41
+ "cloudflare-simple": {
42
+ name: "Cloudflare Simple (Single Tenant)",
43
+ description: "Single-tenant Cloudflare Workers setup with D1 database",
44
+ templateDir: "cloudflare-simple",
45
+ packageJson: (t) => ({
46
+ name: t,
47
+ version: "1.0.0",
48
+ type: "module",
49
+ scripts: {
50
+ dev: "wrangler dev",
51
+ deploy: "wrangler deploy",
52
+ "db:migrate": "wrangler d1 migrations apply AUTH_DB --local",
53
+ "db:migrate:prod": "wrangler d1 migrations apply AUTH_DB --remote",
54
+ seed: "wrangler d1 execute AUTH_DB --local --file=seed.sql"
55
+ },
56
+ dependencies: {
57
+ "@authhero/kysely-adapter": "latest",
58
+ "@hono/swagger-ui": "^0.5.0",
59
+ "@hono/zod-openapi": "^0.19.0",
60
+ authhero: "latest",
61
+ hono: "^4.6.0",
62
+ kysely: "latest",
63
+ "kysely-d1": "latest"
64
+ },
65
+ devDependencies: {
66
+ "@cloudflare/workers-types": "^4.0.0",
67
+ typescript: "^5.5.0",
68
+ wrangler: "^3.0.0"
69
+ }
70
+ }),
71
+ seedFile: "seed.sql"
72
+ },
73
+ "cloudflare-multitenant": {
74
+ name: "Cloudflare Multi-Tenant (Production)",
75
+ description: "Production-grade multi-tenant setup with per-tenant D1 databases and Analytics Engine",
76
+ templateDir: "cloudflare-multitenant",
77
+ packageJson: (t) => ({
78
+ name: t,
79
+ version: "1.0.0",
80
+ type: "module",
81
+ scripts: {
82
+ dev: "wrangler dev",
83
+ deploy: "wrangler deploy",
84
+ "db:migrate": "wrangler d1 migrations apply MAIN_DB --local",
85
+ "db:migrate:prod": "wrangler d1 migrations apply MAIN_DB --remote",
86
+ seed: "wrangler d1 execute MAIN_DB --local --file=seed.sql"
87
+ },
88
+ dependencies: {
89
+ "@authhero/cloudflare-adapter": "latest",
90
+ "@authhero/kysely-adapter": "latest",
91
+ "@authhero/multi-tenancy": "latest",
92
+ "@hono/swagger-ui": "^0.5.0",
93
+ "@hono/zod-openapi": "^0.19.10",
94
+ authhero: "latest",
95
+ hono: "^4.6.0",
96
+ kysely: "latest",
97
+ "kysely-d1": "latest",
98
+ wretch: "^3.0.0"
99
+ },
100
+ devDependencies: {
101
+ "@cloudflare/workers-types": "^4.0.0",
102
+ typescript: "^5.5.0",
103
+ wrangler: "^3.0.0"
104
+ }
105
+ }),
106
+ seedFile: "seed.sql"
107
+ }
108
+ };
109
+ function v(t, e) {
110
+ l.readdirSync(t).forEach((s) => {
111
+ const n = c.join(t, s), o = c.join(e, s);
112
+ l.lstatSync(n).isDirectory() ? (l.mkdirSync(o, { recursive: !0 }), v(n, o)) : l.copyFileSync(n, o);
113
+ });
114
+ }
115
+ function D(t) {
116
+ if (t === "local")
117
+ return `import { SqliteDialect, Kysely } from "kysely";
118
+ import Database from "better-sqlite3";
119
+ import createAdapters from "@authhero/kysely-adapter";
120
+ import { seed } from "authhero";
121
+
122
+ async function main() {
123
+ const adminEmail = process.argv[2] || process.env.ADMIN_EMAIL;
124
+ const adminPassword = process.argv[3] || process.env.ADMIN_PASSWORD;
125
+
126
+ if (!adminEmail || !adminPassword) {
127
+ console.error("Usage: npm run seed <email> <password>");
128
+ console.error(" or: ADMIN_EMAIL=... ADMIN_PASSWORD=... npm run seed");
129
+ process.exit(1);
130
+ }
131
+
132
+ const dialect = new SqliteDialect({
133
+ database: new Database("db.sqlite"),
134
+ });
135
+
136
+ const db = new Kysely<any>({ dialect });
137
+ const adapters = createAdapters(db);
138
+
139
+ await seed(adapters, {
140
+ adminEmail,
141
+ adminPassword,
142
+ });
143
+
144
+ await db.destroy();
145
+ }
146
+
147
+ main().catch(console.error);
148
+ `;
149
+ {
150
+ const e = (/* @__PURE__ */ new Date()).toISOString(), a = "default";
151
+ return `-- Seed file for AuthHero
152
+ --
153
+ -- IMPORTANT: This SQL file creates the basic structure but the password
154
+ -- cannot be properly hashed in SQL. After running this seed, you should
155
+ -- use the management API or run a script to set the admin password.
156
+
157
+ -- Create default tenant
158
+ INSERT OR IGNORE INTO tenants (id, friendly_name, audience, sender_email, sender_name, created_at, updated_at)
159
+ VALUES ('${a}', 'Default Tenant', 'https://api.example.com', 'noreply@example.com', 'AuthHero', '${e}', '${e}');
160
+
161
+ -- Create password connection
162
+ INSERT OR IGNORE INTO connections (id, tenant_id, name, strategy, options, created_at, updated_at)
163
+ VALUES ('conn_default', '${a}', 'Username-Password-Authentication', 'Username-Password-Authentication', '{}', '${e}', '${e}');
164
+
165
+ -- Create default client
166
+ INSERT OR IGNORE INTO clients (client_id, tenant_id, name, callbacks, allowed_origins, web_origins, connections, created_at, updated_at)
167
+ VALUES ('default', '${a}', 'Default Application', '["https://manage.authhero.net/auth-callback","https://local.authhero.net/auth-callback"]', '[]', '[]', '["Username-Password-Authentication"]', '${e}', '${e}');
168
+
169
+ -- Note: Admin user and password should be created via the management API
170
+ -- or using a TypeScript seed script with proper bcrypt hashing.
171
+ -- Example command: curl -X POST http://localhost:3000/api/v2/users ...
172
+ `;
173
+ }
174
+ }
175
+ function u(t, e) {
176
+ return new Promise((a, s) => {
177
+ const n = f(t, [], {
178
+ cwd: e,
179
+ shell: !0,
180
+ stdio: "inherit"
181
+ });
182
+ n.on("close", (o) => {
183
+ o === 0 ? a() : s(new Error(`Command failed with exit code ${o}`));
184
+ }), n.on("error", s);
185
+ });
186
+ }
187
+ function k(t, e, a) {
188
+ return new Promise((s, n) => {
189
+ const o = f(t, [], {
190
+ cwd: e,
191
+ shell: !0,
192
+ stdio: "inherit",
193
+ env: { ...process.env, ...a }
194
+ });
195
+ o.on("close", (m) => {
196
+ m === 0 ? s() : n(new Error(`Command failed with exit code ${m}`));
197
+ }), o.on("error", n);
198
+ });
199
+ }
200
+ w.version("1.0.0").description("Create a new AuthHero project").argument("[project-name]", "name of the project").action(async (t) => {
201
+ console.log(`
202
+ 🔐 Welcome to AuthHero!
203
+ `), t || (t = (await d.prompt([
204
+ {
205
+ type: "input",
206
+ name: "projectName",
207
+ message: "Project name:",
208
+ default: "auth-server",
209
+ validate: (p) => p !== "" || "Project name cannot be empty"
210
+ }
211
+ ])).projectName);
212
+ const e = c.join(process.cwd(), t);
213
+ l.existsSync(e) && (console.error(`❌ Project "${t}" already exists.`), process.exit(1));
214
+ const { setupType: a } = await d.prompt([
215
+ {
216
+ type: "list",
217
+ name: "setupType",
218
+ message: "Select your setup type:",
219
+ choices: [
220
+ {
221
+ name: `${r.local.name}
222
+ ${r.local.description}`,
223
+ value: "local",
224
+ short: r.local.name
225
+ },
226
+ {
227
+ name: `${r["cloudflare-simple"].name}
228
+ ${r["cloudflare-simple"].description}`,
229
+ value: "cloudflare-simple",
230
+ short: r["cloudflare-simple"].name
231
+ },
232
+ {
233
+ name: `${r["cloudflare-multitenant"].name}
234
+ ${r["cloudflare-multitenant"].description}`,
235
+ value: "cloudflare-multitenant",
236
+ short: r["cloudflare-multitenant"].name
237
+ }
238
+ ]
239
+ }
240
+ ]), s = r[a];
241
+ l.mkdirSync(e, { recursive: !0 }), l.writeFileSync(
242
+ c.join(e, "package.json"),
243
+ JSON.stringify(s.packageJson(t), null, 2)
244
+ );
245
+ const n = c.join(
246
+ import.meta.url.replace("file://", "").replace("/create-authhero.js", ""),
247
+ s.templateDir
248
+ );
249
+ l.existsSync(n) ? v(n, e) : (console.error(`❌ Template directory not found: ${n}`), process.exit(1));
250
+ const o = D(a), m = a === "local" ? "src/seed.ts" : "seed.sql";
251
+ l.writeFileSync(c.join(e, m), o), console.log(
252
+ `
253
+ ✅ Project "${t}" has been created with ${s.name} setup!
254
+ `
255
+ );
256
+ const { shouldInstall: h } = await d.prompt([
257
+ {
258
+ type: "confirm",
259
+ name: "shouldInstall",
260
+ message: "Would you like to install dependencies now?",
261
+ default: !0
262
+ }
263
+ ]);
264
+ if (h) {
265
+ const { packageManager: i } = await d.prompt([
266
+ {
267
+ type: "list",
268
+ name: "packageManager",
269
+ message: "Which package manager would you like to use?",
270
+ choices: [
271
+ { name: "npm", value: "npm" },
272
+ { name: "yarn", value: "yarn" },
273
+ { name: "pnpm", value: "pnpm" },
274
+ { name: "bun", value: "bun" }
275
+ ],
276
+ default: "npm"
277
+ }
278
+ ]);
279
+ console.log(`
280
+ 📦 Installing dependencies with ${i}...
281
+ `);
282
+ try {
283
+ const p = i === "pnpm" ? "pnpm install --ignore-workspace" : `${i} install`;
284
+ if (await u(p, e), a === "local" && (console.log(`
285
+ 🔧 Building native modules...
286
+ `), await u("npm rebuild better-sqlite3", e)), console.log(`
287
+ ✅ Dependencies installed successfully!
288
+ `), a === "local") {
289
+ const { shouldSetup: A } = await d.prompt([
290
+ {
291
+ type: "confirm",
292
+ name: "shouldSetup",
293
+ message: "Would you like to run migrations and seed the database?",
294
+ default: !0
295
+ }
296
+ ]);
297
+ if (A) {
298
+ const y = await d.prompt([
299
+ {
300
+ type: "input",
301
+ name: "username",
302
+ message: "Admin email:",
303
+ default: "admin@example.com",
304
+ validate: (g) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(g) || "Please enter a valid email address"
305
+ },
306
+ {
307
+ type: "password",
308
+ name: "password",
309
+ message: "Admin password:",
310
+ mask: "*",
311
+ validate: (g) => g.length < 8 ? "Password must be at least 8 characters" : !0
312
+ }
313
+ ]);
314
+ console.log(`
315
+ 🔄 Running migrations...
316
+ `), await u(`${i} run migrate`, e), console.log(`
317
+ 🌱 Seeding database...
318
+ `), await k(`${i} run seed`, e, {
319
+ ADMIN_EMAIL: y.username,
320
+ ADMIN_PASSWORD: y.password
321
+ });
322
+ }
323
+ }
324
+ const { shouldStart: S } = await d.prompt([
325
+ {
326
+ type: "confirm",
327
+ name: "shouldStart",
328
+ message: "Would you like to start the development server?",
329
+ default: !0
330
+ }
331
+ ]);
332
+ S && (console.log(`
333
+ 🚀 Starting development server...
334
+ `), await u(`${i} run dev`, e));
335
+ } catch (p) {
336
+ console.error(`
337
+ ❌ An error occurred:`, p);
338
+ }
339
+ }
340
+ h || (console.log("Next steps:"), console.log(` cd ${t}`), a === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(" npm run seed -- <email> <password>"), console.log(" npm run dev")) : (console.log(" npm install"), console.log(" npm run db:migrate"), console.log(" npm run seed"), console.log(" npm run dev")), console.log(`
341
+ For more information, visit: https://authhero.net/docs
342
+ `));
343
+ });
344
+ w.parse(process.argv);
@@ -0,0 +1,50 @@
1
+ # AuthHero Local Server
2
+
3
+ A local AuthHero authentication server using SQLite for development.
4
+
5
+ ## Getting Started
6
+
7
+ 1. Install dependencies:
8
+
9
+ ```bash
10
+ npm install
11
+ ```
12
+
13
+ 2. Run database migrations:
14
+
15
+ ```bash
16
+ npm run migrate
17
+ ```
18
+
19
+ 3. Start the development server:
20
+ ```bash
21
+ npm run dev
22
+ ```
23
+
24
+ The server will be available at `http://localhost:3000`.
25
+
26
+ ## Project Structure
27
+
28
+ ```
29
+ ├── src/
30
+ │ ├── index.ts # Server entry point
31
+ │ ├── app.ts # AuthHero app configuration
32
+ │ ├── migrate.ts # Database migration script
33
+ │ └── seed.ts # Database seeding script
34
+ ├── db.sqlite # SQLite database (created after first run)
35
+ └── package.json
36
+ ```
37
+
38
+ ## API Documentation
39
+
40
+ Visit `http://localhost:3000/docs` to see the Swagger UI documentation.
41
+
42
+ ## Configuration
43
+
44
+ You can customize the AuthHero configuration in `src/app.ts`. Common options include:
45
+
46
+ - Custom hooks for login/signup events
47
+ - Custom email templates
48
+ - Session configuration
49
+
50
+ For more information, visit [https://authhero.net/docs](https://authhero.net/docs).
@@ -0,0 +1,26 @@
1
+ import { Context } from "hono";
2
+ import { HTTPException } from "hono/http-exception";
3
+ import { AuthHeroConfig, init } from "authhero";
4
+ import { swaggerUI } from "@hono/swagger-ui";
5
+
6
+ export default function createApp(config: AuthHeroConfig) {
7
+ const { app } = init(config);
8
+
9
+ app
10
+ .onError((err, ctx) => {
11
+ if (err instanceof HTTPException) {
12
+ return err.getResponse();
13
+ }
14
+ console.error(err);
15
+ return ctx.text(err.message, 500);
16
+ })
17
+ .get("/", async (ctx: Context) => {
18
+ return ctx.json({
19
+ name: "AuthHero Server",
20
+ status: "running",
21
+ });
22
+ })
23
+ .get("/docs", swaggerUI({ url: "/api/v2/spec" }));
24
+
25
+ return app;
26
+ }
@@ -0,0 +1,117 @@
1
+ import { serve } from "@hono/node-server";
2
+ import { SqliteDialect } from "kysely";
3
+ import { Kysely } from "kysely";
4
+ import Database from "better-sqlite3";
5
+ import createAdapters from "@authhero/kysely-adapter";
6
+ import createApp from "./app";
7
+ import fs from "fs";
8
+ import path from "path";
9
+ import { execSync } from "child_process";
10
+ import https from "https";
11
+
12
+ // Generate self-signed certificates for local HTTPS if they don't exist
13
+ const certDir = path.join(process.cwd(), ".certs");
14
+ const keyPath = path.join(certDir, "localhost-key.pem");
15
+ const certPath = path.join(certDir, "localhost.pem");
16
+
17
+ function ensureCertificates() {
18
+ if (!fs.existsSync(certDir)) {
19
+ fs.mkdirSync(certDir, { recursive: true });
20
+ }
21
+
22
+ if (!fs.existsSync(keyPath) || !fs.existsSync(certPath)) {
23
+ console.log("🔑 Generating self-signed certificates for local HTTPS...");
24
+
25
+ // Try mkcert first (if installed), otherwise fall back to openssl
26
+ try {
27
+ execSync(`which mkcert`, { stdio: "ignore" });
28
+ execSync(
29
+ `mkcert -key-file ${keyPath} -cert-file ${certPath} localhost 127.0.0.1`,
30
+ {
31
+ stdio: "inherit",
32
+ },
33
+ );
34
+ console.log("✅ Certificates generated with mkcert");
35
+ } catch {
36
+ // Fall back to openssl
37
+ try {
38
+ execSync(
39
+ `openssl req -x509 -newkey rsa:2048 -keyout "${keyPath}" -out "${certPath}" -days 365 -nodes -subj "/CN=localhost"`,
40
+ { stdio: "inherit" },
41
+ );
42
+ console.log("✅ Self-signed certificates generated with openssl");
43
+ console.log(
44
+ "⚠️ You may need to trust the certificate in your browser",
45
+ );
46
+ } catch (err) {
47
+ console.error(
48
+ "❌ Failed to generate certificates. Please install mkcert or openssl",
49
+ );
50
+ console.error(
51
+ " Install mkcert: brew install mkcert && mkcert -install",
52
+ );
53
+ process.exit(1);
54
+ }
55
+ }
56
+ }
57
+
58
+ return {
59
+ key: fs.readFileSync(keyPath),
60
+ cert: fs.readFileSync(certPath),
61
+ };
62
+ }
63
+
64
+ // Initialize SQLite database
65
+ let db: Kysely<any>;
66
+ try {
67
+ const dialect = new SqliteDialect({
68
+ database: new Database("db.sqlite"),
69
+ });
70
+ db = new Kysely<any>({ dialect });
71
+ } catch (error) {
72
+ console.error("❌ Failed to initialize database:");
73
+ console.error(
74
+ error instanceof Error ? error.message : "Unknown error occurred",
75
+ );
76
+ console.error("\nPossible causes:");
77
+ console.error(" - File permissions issue");
78
+ console.error(" - Disk space is full");
79
+ console.error(" - Database file is corrupted");
80
+ console.error("\nTry running: npm run migrate");
81
+ process.exit(1);
82
+ }
83
+
84
+ const dataAdapter = createAdapters(db);
85
+
86
+ // Create the AuthHero app
87
+ const app = createApp({
88
+ dataAdapter,
89
+ allowedOrigins: [
90
+ "https://manage.authhero.net",
91
+ "https://local.authhero.net",
92
+ "http://localhost:5173",
93
+ ],
94
+ });
95
+
96
+ // Start the server
97
+ const port = Number(process.env.PORT) || 3000;
98
+ const issuer = process.env.ISSUER || `https://localhost:${port}/`;
99
+
100
+ // Get or generate certificates
101
+ const { key, cert } = ensureCertificates();
102
+
103
+ console.log(`🔐 AuthHero server running at https://localhost:${port}`);
104
+ console.log(`📚 API documentation available at https://localhost:${port}/docs`);
105
+ console.log(`🌐 Portal available at https://local.authhero.net`);
106
+
107
+ serve({
108
+ fetch: (request) => {
109
+ return app.fetch(request, {
110
+ ISSUER: issuer,
111
+ data: dataAdapter,
112
+ });
113
+ },
114
+ port,
115
+ createServer: https.createServer,
116
+ serverOptions: { key, cert },
117
+ });
@@ -0,0 +1,25 @@
1
+ import { SqliteDialect, Kysely } from "kysely";
2
+ import Database from "better-sqlite3";
3
+ import { migrateToLatest } from "@authhero/kysely-adapter";
4
+
5
+ async function migrate() {
6
+ const dialect = new SqliteDialect({
7
+ database: new Database("db.sqlite"),
8
+ });
9
+
10
+ const db = new Kysely<any>({ dialect });
11
+
12
+ console.log("Running migrations...");
13
+
14
+ try {
15
+ await migrateToLatest(db, true);
16
+ console.log("✅ All migrations completed successfully");
17
+ } catch (error) {
18
+ console.error("Migration failed:", error);
19
+ process.exit(1);
20
+ } finally {
21
+ await db.destroy();
22
+ }
23
+ }
24
+
25
+ migrate();
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "outDir": "./dist",
11
+ "rootDir": "./src",
12
+ "types": ["node"]
13
+ },
14
+ "include": ["src/**/*"],
15
+ "exclude": ["node_modules"]
16
+ }
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "https://github.com/markusahlstrand/authhero"
7
7
  },
8
- "version": "0.4.0",
8
+ "version": "0.6.0",
9
9
  "type": "module",
10
10
  "main": "dist/create-authhero.js",
11
11
  "bin": {