create-authhero 0.16.0 → 0.18.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.
- package/README.md +105 -26
- package/dist/cloudflare-multitenant/README.md +145 -7
- package/dist/cloudflare-multitenant/copy-assets.js +66 -0
- package/dist/cloudflare-multitenant/wrangler.toml +44 -10
- package/dist/cloudflare-simple/README.md +153 -27
- package/dist/cloudflare-simple/copy-assets.js +66 -0
- package/dist/cloudflare-simple/wrangler.toml +44 -10
- package/dist/create-authhero.js +247 -149
- package/dist/local/src/app.ts +10 -1
- package/package.json +1 -1
|
@@ -7,90 +7,117 @@ A single-tenant AuthHero authentication server using Cloudflare Workers and D1.
|
|
|
7
7
|
- [Cloudflare Account](https://dash.cloudflare.com/sign-up)
|
|
8
8
|
- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/install-and-update/)
|
|
9
9
|
|
|
10
|
+
## Security & Privacy
|
|
11
|
+
|
|
12
|
+
This project is designed to be **open-source friendly**. Sensitive Cloudflare IDs are kept out of version control:
|
|
13
|
+
|
|
14
|
+
| File | Purpose | In Git? |
|
|
15
|
+
| --------------------- | ---------------------------------- | ------- |
|
|
16
|
+
| `wrangler.toml` | Base config (safe for public repo) | ✅ Yes |
|
|
17
|
+
| `wrangler.local.toml` | Your private IDs (database_id) | ❌ No |
|
|
18
|
+
| `.dev.vars` | Local secrets (API tokens, etc.) | ❌ No |
|
|
19
|
+
| `.dev.vars.example` | Template for .dev.vars | ✅ Yes |
|
|
20
|
+
|
|
21
|
+
**For GitHub Actions / CI:**
|
|
22
|
+
|
|
23
|
+
- Set `CLOUDFLARE_API_TOKEN` as a GitHub Secret
|
|
24
|
+
- Set `CLOUDFLARE_ACCOUNT_ID` as a GitHub Secret (if needed)
|
|
25
|
+
- The wrangler action will use these automatically
|
|
26
|
+
|
|
10
27
|
## Getting Started
|
|
11
28
|
|
|
29
|
+
### Local Development (Quick Start)
|
|
30
|
+
|
|
12
31
|
1. Install dependencies:
|
|
13
32
|
|
|
14
33
|
```bash
|
|
15
34
|
npm install
|
|
16
35
|
```
|
|
17
36
|
|
|
18
|
-
2.
|
|
37
|
+
2. Run database migrations (uses local SQLite-backed D1):
|
|
19
38
|
|
|
20
39
|
```bash
|
|
21
|
-
|
|
40
|
+
npm run migrate
|
|
22
41
|
```
|
|
23
42
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
3. Run database migrations:
|
|
27
|
-
|
|
28
|
-
**For local development:**
|
|
43
|
+
3. Seed the database with an admin user:
|
|
29
44
|
|
|
30
45
|
```bash
|
|
31
|
-
npm run
|
|
46
|
+
ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed
|
|
32
47
|
```
|
|
33
48
|
|
|
34
|
-
|
|
49
|
+
4. Start the development server:
|
|
35
50
|
|
|
36
51
|
```bash
|
|
37
|
-
npm run
|
|
52
|
+
npm run dev
|
|
38
53
|
```
|
|
39
54
|
|
|
40
|
-
|
|
55
|
+
The server will be available at `https://localhost:3000`.
|
|
41
56
|
|
|
42
|
-
|
|
57
|
+
### Remote Development (Your Cloudflare Account)
|
|
58
|
+
|
|
59
|
+
1. Create a D1 database:
|
|
43
60
|
|
|
44
61
|
```bash
|
|
45
|
-
|
|
62
|
+
npx wrangler d1 create authhero-db
|
|
46
63
|
```
|
|
47
64
|
|
|
48
|
-
|
|
65
|
+
2. Copy the `database_id` from the output and update `wrangler.local.toml`:
|
|
49
66
|
|
|
50
|
-
```
|
|
51
|
-
|
|
67
|
+
```toml
|
|
68
|
+
[[d1_databases]]
|
|
69
|
+
binding = "AUTH_DB"
|
|
70
|
+
database_name = "authhero-db"
|
|
71
|
+
database_id = "paste-your-database-id-here"
|
|
72
|
+
migrations_dir = "node_modules/@authhero/drizzle/drizzle"
|
|
52
73
|
```
|
|
53
74
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
**For local mode (local D1 database):**
|
|
75
|
+
3. Run remote migrations:
|
|
57
76
|
|
|
58
77
|
```bash
|
|
59
|
-
npm run
|
|
78
|
+
npm run db:migrate:remote
|
|
60
79
|
```
|
|
61
80
|
|
|
62
|
-
|
|
81
|
+
4. Seed the remote database:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed:remote
|
|
85
|
+
```
|
|
63
86
|
|
|
87
|
+
5. Start with remote D1:
|
|
64
88
|
```bash
|
|
65
89
|
npm run dev:remote
|
|
66
90
|
```
|
|
67
91
|
|
|
68
92
|
## Available Scripts
|
|
69
93
|
|
|
70
|
-
- `npm run dev
|
|
71
|
-
- `npm run dev:remote` - Start
|
|
94
|
+
- `npm run dev` - Start development server with local D1 database
|
|
95
|
+
- `npm run dev:remote` - Start with remote D1 database
|
|
72
96
|
- `npm run deploy` - Deploy to Cloudflare Workers
|
|
73
97
|
- `npm run migrate` - Run migrations on local database
|
|
74
98
|
- `npm run db:migrate:local` - Run migrations on local database (alias)
|
|
75
99
|
- `npm run db:migrate:remote` - Run migrations on remote database
|
|
76
|
-
- `npm run seed
|
|
100
|
+
- `npm run seed` - Seed local database with admin user
|
|
77
101
|
- `npm run seed:remote` - Seed remote database with admin user
|
|
102
|
+
- `npm run setup` - Create wrangler.local.toml and .dev.vars from templates
|
|
78
103
|
|
|
79
104
|
## Deployment
|
|
80
105
|
|
|
81
|
-
1.
|
|
106
|
+
1. Ensure `wrangler.local.toml` has your production `database_id`.
|
|
107
|
+
|
|
108
|
+
2. Deploy to Cloudflare:
|
|
82
109
|
|
|
83
110
|
```bash
|
|
84
111
|
npm run deploy
|
|
85
112
|
```
|
|
86
113
|
|
|
87
|
-
|
|
114
|
+
3. Run production migrations:
|
|
88
115
|
|
|
89
116
|
```bash
|
|
90
117
|
npm run db:migrate:remote
|
|
91
118
|
```
|
|
92
119
|
|
|
93
|
-
|
|
120
|
+
4. Seed the production database:
|
|
94
121
|
```bash
|
|
95
122
|
ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed:remote
|
|
96
123
|
```
|
|
@@ -103,12 +130,34 @@ A single-tenant AuthHero authentication server using Cloudflare Workers and D1.
|
|
|
103
130
|
│ ├── app.ts # AuthHero app configuration
|
|
104
131
|
│ ├── seed.ts # Database seeding worker
|
|
105
132
|
│ └── types.ts # TypeScript type definitions
|
|
133
|
+
├── dist/
|
|
134
|
+
│ └── assets/ # Copied static assets (CSS, JS, Widget)
|
|
135
|
+
├── copy-assets.js # Build script to copy assets from authhero package
|
|
106
136
|
├── drizzle.config.ts # Drizzle configuration (reference only)
|
|
107
137
|
├── seed-helper.js # Helper script for automated seeding
|
|
108
138
|
├── wrangler.toml # Cloudflare Worker configuration
|
|
109
139
|
└── package.json
|
|
110
140
|
```
|
|
111
141
|
|
|
142
|
+
## Static Assets
|
|
143
|
+
|
|
144
|
+
The authentication widget, CSS, and client-side JavaScript are served as static assets via Cloudflare Workers Assets.
|
|
145
|
+
|
|
146
|
+
### How It Works
|
|
147
|
+
|
|
148
|
+
1. **Source**: Assets are bundled with the `authhero` package in `node_modules/authhero/dist/assets`
|
|
149
|
+
2. **Build Step**: The `copy-assets.js` script copies these files to `./dist/assets` before dev/deploy
|
|
150
|
+
3. **Serving**: Wrangler serves files from `./dist/assets` (configured in `wrangler.toml`)
|
|
151
|
+
4. **Automatic**: The copy happens automatically when you run `npm run dev` or `npm run deploy`
|
|
152
|
+
|
|
153
|
+
> **Note**: Wrangler's Assets feature does not support serving files directly from `node_modules`, which is why the copy step is necessary.
|
|
154
|
+
|
|
155
|
+
Assets are served at:
|
|
156
|
+
|
|
157
|
+
- `/u/widget/*` - AuthHero login widget (Stencil web component)
|
|
158
|
+
- `/u/css/*` - Tailwind CSS for universal login pages
|
|
159
|
+
- `/u/js/*` - Client-side JavaScript bundle
|
|
160
|
+
|
|
112
161
|
## Database Migrations
|
|
113
162
|
|
|
114
163
|
Database migrations are pre-generated and shipped with the `@authhero/drizzle` package. The schema is managed by AuthHero to ensure compatibility with future updates.
|
|
@@ -136,6 +185,83 @@ routes = [
|
|
|
136
185
|
|
|
137
186
|
For more information, visit [https://authhero.net/docs](https://authhero.net/docs).
|
|
138
187
|
|
|
188
|
+
## CI/CD with GitHub Actions
|
|
189
|
+
|
|
190
|
+
If you selected GitHub CI during setup, your project includes automated workflows for continuous integration and deployment.
|
|
191
|
+
|
|
192
|
+
### Workflow Overview
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
┌─────────────────────────────────────────────────────────────────────────┐
|
|
196
|
+
│ GitHub Actions │
|
|
197
|
+
├─────────────────────────────────────────────────────────────────────────┤
|
|
198
|
+
│ │
|
|
199
|
+
│ ┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
|
|
200
|
+
│ │ Any Push │ │ Push to main │ │ GitHub Release │ │
|
|
201
|
+
│ │ │ │ │ │ (released) │ │
|
|
202
|
+
│ └──────┬───────┘ └────────┬─────────┘ └────────┬─────────┘ │
|
|
203
|
+
│ │ │ │ │
|
|
204
|
+
│ ▼ ▼ ▼ │
|
|
205
|
+
│ ┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
|
|
206
|
+
│ │ Unit Tests │ │ Semantic Release │ │ Deploy to │ │
|
|
207
|
+
│ │ Type Check │ │ + Deploy Dev │ │ Production │ │
|
|
208
|
+
│ └──────────────┘ └──────────────────┘ └──────────────────┘ │
|
|
209
|
+
│ │
|
|
210
|
+
└─────────────────────────────────────────────────────────────────────────┘
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Workflows
|
|
214
|
+
|
|
215
|
+
1. **Unit Tests** (`.github/workflows/unit-tests.yml`)
|
|
216
|
+
- **Trigger**: All pushes to any branch
|
|
217
|
+
- **Actions**: Runs type checking and tests
|
|
218
|
+
|
|
219
|
+
2. **Deploy to Dev** (`.github/workflows/deploy-dev.yml`)
|
|
220
|
+
- **Trigger**: Push to `main` branch
|
|
221
|
+
- **Actions**:
|
|
222
|
+
- Runs semantic-release to create version tags
|
|
223
|
+
- Deploys to Cloudflare Workers (dev environment)
|
|
224
|
+
|
|
225
|
+
3. **Deploy to Production** (`.github/workflows/release.yml`)
|
|
226
|
+
- **Trigger**: GitHub Release (when "released")
|
|
227
|
+
- **Actions**: Deploys to Cloudflare Workers (production environment)
|
|
228
|
+
|
|
229
|
+
### Required Secrets
|
|
230
|
+
|
|
231
|
+
Configure these secrets in your GitHub repository settings:
|
|
232
|
+
|
|
233
|
+
| Secret | Description |
|
|
234
|
+
| --------------------------- | ----------------------------------------------- |
|
|
235
|
+
| `CLOUDFLARE_API_TOKEN` | Cloudflare API token for dev deployments |
|
|
236
|
+
| `PROD_CLOUDFLARE_API_TOKEN` | Cloudflare API token for production deployments |
|
|
237
|
+
|
|
238
|
+
### Semantic Versioning
|
|
239
|
+
|
|
240
|
+
Commits to `main` are analyzed to determine version bumps:
|
|
241
|
+
|
|
242
|
+
- `fix:` - Patch release (1.0.0 → 1.0.1)
|
|
243
|
+
- `feat:` - Minor release (1.0.0 → 1.1.0)
|
|
244
|
+
- `BREAKING CHANGE:` - Major release (1.0.0 → 2.0.0)
|
|
245
|
+
|
|
246
|
+
### Production Deployment
|
|
247
|
+
|
|
248
|
+
To deploy to production:
|
|
249
|
+
|
|
250
|
+
1. Go to GitHub → Releases → "Draft a new release"
|
|
251
|
+
2. Create a new tag (e.g., `v1.0.0`)
|
|
252
|
+
3. Click "Publish release"
|
|
253
|
+
4. The `release.yml` workflow will deploy to production
|
|
254
|
+
|
|
255
|
+
### Wrangler Configuration
|
|
256
|
+
|
|
257
|
+
For production deployments, add an environment to `wrangler.toml`:
|
|
258
|
+
|
|
259
|
+
```toml
|
|
260
|
+
[env.production]
|
|
261
|
+
name = "your-worker-production"
|
|
262
|
+
# Add production-specific settings here
|
|
263
|
+
```
|
|
264
|
+
|
|
139
265
|
## Optional Features
|
|
140
266
|
|
|
141
267
|
### Analytics Engine (Centralized Logging)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Copy AuthHero assets to dist directory
|
|
5
|
+
*
|
|
6
|
+
* This script copies static assets from the authhero package to the dist directory
|
|
7
|
+
* so they can be served by Wrangler's Assets feature. Wrangler does not support
|
|
8
|
+
* serving files directly from node_modules.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import { fileURLToPath } from "url";
|
|
14
|
+
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = path.dirname(__filename);
|
|
17
|
+
|
|
18
|
+
const sourceDir = path.join(
|
|
19
|
+
__dirname,
|
|
20
|
+
"node_modules",
|
|
21
|
+
"authhero",
|
|
22
|
+
"dist",
|
|
23
|
+
"assets",
|
|
24
|
+
);
|
|
25
|
+
const targetDir = path.join(__dirname, "dist", "assets");
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Recursively copy directory contents
|
|
29
|
+
*/
|
|
30
|
+
function copyDirectory(src, dest) {
|
|
31
|
+
// Create destination directory if it doesn't exist
|
|
32
|
+
if (!fs.existsSync(dest)) {
|
|
33
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Read source directory
|
|
37
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
38
|
+
|
|
39
|
+
for (const entry of entries) {
|
|
40
|
+
const srcPath = path.join(src, entry.name);
|
|
41
|
+
const destPath = path.join(dest, entry.name);
|
|
42
|
+
|
|
43
|
+
if (entry.isDirectory()) {
|
|
44
|
+
copyDirectory(srcPath, destPath);
|
|
45
|
+
} else {
|
|
46
|
+
fs.copyFileSync(srcPath, destPath);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
console.log("📦 Copying AuthHero assets...");
|
|
53
|
+
|
|
54
|
+
if (!fs.existsSync(sourceDir)) {
|
|
55
|
+
console.error(`❌ Source directory not found: ${sourceDir}`);
|
|
56
|
+
console.error("Make sure the authhero package is installed.");
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
copyDirectory(sourceDir, targetDir);
|
|
61
|
+
|
|
62
|
+
console.log(`✅ Assets copied to ${targetDir}`);
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error("❌ Error copying assets:", error.message);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
@@ -1,23 +1,57 @@
|
|
|
1
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
2
|
+
# AuthHero Cloudflare Worker Configuration
|
|
3
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
4
|
+
# This file is safe for version control. Sensitive IDs should go in:
|
|
5
|
+
# - wrangler.local.toml (local development - gitignored)
|
|
6
|
+
# - GitHub Secrets / Cloudflare Dashboard (production)
|
|
7
|
+
#
|
|
8
|
+
# For local development with your own Cloudflare resources:
|
|
9
|
+
# cp wrangler.toml wrangler.local.toml
|
|
10
|
+
# # Add your database_id to wrangler.local.toml
|
|
11
|
+
# npm run dev # Uses wrangler.local.toml automatically
|
|
12
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
13
|
+
|
|
1
14
|
name = "authhero-server"
|
|
2
15
|
main = "src/index.ts"
|
|
3
16
|
compatibility_date = "2024-11-20"
|
|
4
17
|
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
18
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
19
|
+
# Static Assets (CSS, JS, Widget)
|
|
20
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
21
|
+
# Serve static assets from the authhero package.
|
|
22
|
+
# This includes the widget, CSS, and client-side JavaScript.
|
|
23
|
+
# Assets are copied from node_modules/authhero/dist/assets to dist/assets
|
|
24
|
+
# during the build process (see copy-assets.js).
|
|
25
|
+
# Assets are served at their path: /u/widget/*, /u/css/*, /u/js/*
|
|
26
|
+
[assets]
|
|
27
|
+
directory = "./dist/assets"
|
|
13
28
|
|
|
14
|
-
#
|
|
29
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
30
|
+
# D1 Database binding
|
|
31
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
32
|
+
# This configuration uses a local D1 database by default.
|
|
33
|
+
# For remote development/production, copy to wrangler.local.toml and update.
|
|
34
|
+
#
|
|
35
|
+
# Setup:
|
|
36
|
+
# 1. Create database: npx wrangler d1 create authhero-db
|
|
37
|
+
# 2. Copy to local config: cp wrangler.toml wrangler.local.toml
|
|
38
|
+
# 3. Update database_id in wrangler.local.toml with the ID from step 1
|
|
39
|
+
#
|
|
15
40
|
[[d1_databases]]
|
|
16
41
|
binding = "AUTH_DB"
|
|
17
42
|
database_name = "authhero-db"
|
|
18
|
-
database_id = "local"
|
|
43
|
+
database_id = "local" # Use "local" for local dev, or your actual ID in wrangler.local.toml
|
|
19
44
|
migrations_dir = "node_modules/@authhero/drizzle/drizzle"
|
|
20
45
|
|
|
46
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
47
|
+
# OPTIONAL: Custom Domain
|
|
48
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
49
|
+
# To route your worker to a custom domain, use zone_name (not zone_id):
|
|
50
|
+
#
|
|
51
|
+
# [[routes]]
|
|
52
|
+
# pattern = "auth.yourdomain.com/*"
|
|
53
|
+
# zone_name = "yourdomain.com"
|
|
54
|
+
|
|
21
55
|
# ════════════════════════════════════════════════════════════════════════════
|
|
22
56
|
# OPTIONAL: Analytics Engine for centralized logging
|
|
23
57
|
# ════════════════════════════════════════════════════════════════════════════
|