appflare 0.2.25 → 0.2.26
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/Documentation.md +758 -758
- package/cli/commands/index.ts +238 -238
- package/cli/generate.ts +178 -178
- package/cli/index.ts +120 -120
- package/cli/load-config.ts +184 -184
- package/cli/schema-compiler.ts +1183 -1183
- package/cli/templates/auth/README.md +156 -156
- package/cli/templates/auth/config.ts +61 -61
- package/cli/templates/auth/route-config.ts +1 -1
- package/cli/templates/auth/route-handler.ts +1 -1
- package/cli/templates/auth/route-request-utils.ts +5 -5
- package/cli/templates/auth/route.config.ts +18 -18
- package/cli/templates/auth/route.handler.ts +18 -18
- package/cli/templates/auth/route.request-utils.ts +55 -55
- package/cli/templates/auth/route.ts +14 -14
- package/cli/templates/core/README.md +266 -266
- package/cli/templates/core/app-creation.ts +19 -19
- package/cli/templates/core/client/appflare.ts +112 -112
- package/cli/templates/core/client/handlers/index.ts +748 -748
- package/cli/templates/core/client/handlers.ts +1 -1
- package/cli/templates/core/client/index.ts +7 -7
- package/cli/templates/core/client/storage.ts +180 -180
- package/cli/templates/core/client/types.ts +184 -184
- package/cli/templates/core/client-modules/appflare.ts +1 -1
- package/cli/templates/core/client-modules/handlers.ts +1 -1
- package/cli/templates/core/client-modules/index.ts +1 -1
- package/cli/templates/core/client-modules/storage.ts +1 -1
- package/cli/templates/core/client-modules/types.ts +1 -1
- package/cli/templates/core/client.artifacts.ts +39 -39
- package/cli/templates/core/client.ts +4 -4
- package/cli/templates/core/drizzle.ts +15 -15
- package/cli/templates/core/export.ts +14 -14
- package/cli/templates/core/handlers.route.ts +24 -24
- package/cli/templates/core/handlers.ts +1 -1
- package/cli/templates/core/imports.ts +9 -9
- package/cli/templates/core/server.ts +38 -38
- package/cli/templates/core/types.ts +6 -6
- package/cli/templates/core/wrangler.ts +109 -109
- package/cli/templates/dashboard/builders/functions/index.ts +17 -17
- package/cli/templates/dashboard/builders/functions/render-page/header.ts +20 -20
- package/cli/templates/dashboard/builders/functions/render-page/index.ts +33 -33
- package/cli/templates/dashboard/builders/functions/render-page/request-panel.ts +171 -171
- package/cli/templates/dashboard/builders/functions/render-page/result-panel.ts +85 -85
- package/cli/templates/dashboard/builders/functions/render-page/scripts.ts +554 -554
- package/cli/templates/dashboard/builders/navigation.ts +122 -122
- package/cli/templates/dashboard/builders/storage/index.ts +13 -13
- package/cli/templates/dashboard/builders/storage/routes/create-directory-route.ts +29 -29
- package/cli/templates/dashboard/builders/storage/routes/delete-route.ts +18 -18
- package/cli/templates/dashboard/builders/storage/routes/download-route.ts +23 -23
- package/cli/templates/dashboard/builders/storage/routes/index.ts +22 -22
- package/cli/templates/dashboard/builders/storage/routes/list-route.ts +25 -25
- package/cli/templates/dashboard/builders/storage/routes/preview-route.ts +21 -21
- package/cli/templates/dashboard/builders/storage/routes/upload-route.ts +21 -21
- package/cli/templates/dashboard/builders/storage/runtime/helpers.ts +72 -72
- package/cli/templates/dashboard/builders/storage/runtime/storage-page.ts +130 -130
- package/cli/templates/dashboard/builders/table-routes/common/drawer-panel.ts +27 -27
- package/cli/templates/dashboard/builders/table-routes/common/pagination.ts +30 -30
- package/cli/templates/dashboard/builders/table-routes/common/search-bar.ts +23 -23
- package/cli/templates/dashboard/builders/table-routes/fragments.ts +217 -217
- package/cli/templates/dashboard/builders/table-routes/helpers.ts +45 -45
- package/cli/templates/dashboard/builders/table-routes/index.ts +8 -8
- package/cli/templates/dashboard/builders/table-routes/table/actions-cell.ts +71 -71
- package/cli/templates/dashboard/builders/table-routes/table/get-route.ts +291 -291
- package/cli/templates/dashboard/builders/table-routes/table/index.ts +80 -80
- package/cli/templates/dashboard/builders/table-routes/table/post-routes.ts +163 -163
- package/cli/templates/dashboard/builders/table-routes/table-route.ts +7 -7
- package/cli/templates/dashboard/builders/table-routes/users/get-route.ts +69 -69
- package/cli/templates/dashboard/builders/table-routes/users/html/modals.ts +57 -57
- package/cli/templates/dashboard/builders/table-routes/users/html/page.ts +27 -27
- package/cli/templates/dashboard/builders/table-routes/users/html/table.ts +128 -128
- package/cli/templates/dashboard/builders/table-routes/users/index.ts +32 -32
- package/cli/templates/dashboard/builders/table-routes/users/post-routes.ts +150 -150
- package/cli/templates/dashboard/builders/table-routes/users/redirect.ts +14 -14
- package/cli/templates/dashboard/builders/table-routes/users-route.ts +10 -10
- package/cli/templates/dashboard/components/dashboard-home.ts +23 -23
- package/cli/templates/dashboard/components/layout.ts +388 -388
- package/cli/templates/dashboard/components/login-page.ts +65 -65
- package/cli/templates/dashboard/index.ts +61 -61
- package/cli/templates/dashboard/types.ts +9 -9
- package/cli/templates/handlers/README.md +353 -353
- package/cli/templates/handlers/auth.ts +37 -37
- package/cli/templates/handlers/execution.ts +42 -42
- package/cli/templates/handlers/generators/context/context-creation.ts +101 -101
- package/cli/templates/handlers/generators/context/error-helpers.ts +11 -11
- package/cli/templates/handlers/generators/context/scheduler.ts +24 -24
- package/cli/templates/handlers/generators/context/storage-api.ts +134 -112
- package/cli/templates/handlers/generators/context/storage-helpers.ts +59 -59
- package/cli/templates/handlers/generators/context/types.ts +18 -18
- package/cli/templates/handlers/generators/context.ts +43 -43
- package/cli/templates/handlers/generators/execution.ts +15 -15
- package/cli/templates/handlers/generators/handlers.ts +13 -13
- package/cli/templates/handlers/generators/registration/modules/cron.ts +26 -26
- package/cli/templates/handlers/generators/registration/modules/realtime/auth.ts +75 -75
- package/cli/templates/handlers/generators/registration/modules/realtime/durable-object.ts +144 -144
- package/cli/templates/handlers/generators/registration/modules/realtime/index.ts +14 -14
- package/cli/templates/handlers/generators/registration/modules/realtime/publisher.ts +102 -102
- package/cli/templates/handlers/generators/registration/modules/realtime/routes.ts +164 -164
- package/cli/templates/handlers/generators/registration/modules/realtime/types.ts +30 -30
- package/cli/templates/handlers/generators/registration/modules/realtime/utils.ts +516 -516
- package/cli/templates/handlers/generators/registration/modules/scheduler.ts +56 -56
- package/cli/templates/handlers/generators/registration/modules/storage.ts +196 -194
- package/cli/templates/handlers/generators/registration/sections.ts +210 -210
- package/cli/templates/handlers/generators/types/context.ts +68 -66
- package/cli/templates/handlers/generators/types/core.ts +106 -106
- package/cli/templates/handlers/generators/types/operations.ts +135 -135
- package/cli/templates/handlers/generators/types/query-definitions/filter-and-where-types.ts +259 -259
- package/cli/templates/handlers/generators/types/query-definitions/query-api-types.ts +135 -135
- package/cli/templates/handlers/generators/types/query-definitions/query-helper-functions.ts +1031 -1031
- package/cli/templates/handlers/generators/types/query-definitions/schema-and-table-types.ts +246 -246
- package/cli/templates/handlers/generators/types/query-definitions.ts +13 -13
- package/cli/templates/handlers/generators/types/query-runtime/handled-error.ts +13 -13
- package/cli/templates/handlers/generators/types/query-runtime/runtime-aggregate-and-footer.ts +174 -174
- package/cli/templates/handlers/generators/types/query-runtime/runtime-read.ts +121 -121
- package/cli/templates/handlers/generators/types/query-runtime/runtime-setup.ts +45 -45
- package/cli/templates/handlers/generators/types/query-runtime/runtime-write.ts +676 -676
- package/cli/templates/handlers/generators/types/query-runtime.ts +15 -15
- package/cli/templates/handlers/index.ts +43 -43
- package/cli/templates/handlers/operations.ts +116 -116
- package/cli/templates/handlers/registration.ts +91 -91
- package/cli/templates/handlers/types.ts +15 -15
- package/cli/templates/handlers/utils.ts +48 -48
- package/cli/types.ts +110 -110
- package/cli/utils/handler-discovery.ts +466 -466
- package/cli/utils/json-utils.ts +24 -24
- package/cli/utils/path-utils.ts +19 -19
- package/cli/utils/schema-discovery.ts +399 -399
- package/dist/cli/index.js +43 -17
- package/dist/cli/index.mjs +43 -17
- package/index.ts +18 -18
- package/package.json +58 -58
- package/react/index.ts +5 -5
- package/react/use-infinite-query.ts +252 -252
- package/react/use-mutation.ts +89 -89
- package/react/use-query.ts +207 -207
- package/schema.ts +415 -415
- package/test-better-auth-hash.ts +2 -2
- package/tsconfig.json +6 -6
- package/tsup.config.ts +82 -82
- package/dist/cli/index.d.mts +0 -2
- package/dist/cli/index.d.ts +0 -2
|
@@ -1,156 +1,156 @@
|
|
|
1
|
-
# Auth Template Generators
|
|
2
|
-
|
|
3
|
-
This directory contains source generators used by the Appflare CLI to scaffold authentication integration for a Cloudflare Worker backend.
|
|
4
|
-
|
|
5
|
-
The files here **do not directly implement runtime auth logic** in this folder. Instead, they generate TypeScript source strings that are written into generated backend files (for example under `backend/_generated`).
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Purpose
|
|
10
|
-
|
|
11
|
-
The auth template layer provides:
|
|
12
|
-
|
|
13
|
-
- A generated `createAuth()` factory based on `better-auth` + Cloudflare integrations.
|
|
14
|
-
- Route-level wiring for auth endpoints (`GET`/`POST` on an auth base path).
|
|
15
|
-
- Request sanitization helpers to normalize header forwarding behavior.
|
|
16
|
-
- Small composition utilities so the CLI can include/exclude KV support based on config.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## File-by-file breakdown
|
|
21
|
-
|
|
22
|
-
## `config.ts`
|
|
23
|
-
|
|
24
|
-
### `generateAuthConfigSource(configPathImport: string): string`
|
|
25
|
-
|
|
26
|
-
Builds the full source code for an auth configuration module.
|
|
27
|
-
|
|
28
|
-
Generated module characteristics:
|
|
29
|
-
|
|
30
|
-
- Imports:
|
|
31
|
-
- `better-auth`
|
|
32
|
-
- `withCloudflare` from `better-auth-cloudflare`
|
|
33
|
-
- `drizzleAdapter` from `better-auth/adapters/drizzle`
|
|
34
|
-
- `drizzle` from `drizzle-orm/d1`
|
|
35
|
-
- Cloudflare worker types (`D1Database`, `KVNamespace`, `IncomingRequestCfProperties`)
|
|
36
|
-
- Local `auth.schema`
|
|
37
|
-
- User config module from `configPathImport`
|
|
38
|
-
- Defines `CloudflareBindings` with:
|
|
39
|
-
- required `DATABASE: D1Database`
|
|
40
|
-
- optional `KV?: KVNamespace`
|
|
41
|
-
- Exposes:
|
|
42
|
-
- `createAuth(env?, cf?)`
|
|
43
|
-
- `auth = createAuth()`
|
|
44
|
-
|
|
45
|
-
Behavior details:
|
|
46
|
-
|
|
47
|
-
- If `env` is provided:
|
|
48
|
-
- Creates a Drizzle D1 database instance.
|
|
49
|
-
- Configures `withCloudflare` with D1 and optional KV.
|
|
50
|
-
- If `env` is missing:
|
|
51
|
-
- Falls back to a placeholder `drizzleAdapter` setup to keep type-level/runtime shape valid in non-worker contexts.
|
|
52
|
-
- Merges Cloudflare options with `config.auth.options` so user config can extend behavior.
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## `route.config.ts`
|
|
57
|
-
|
|
58
|
-
### `generateKvField(kvBinding?: string): string`
|
|
59
|
-
|
|
60
|
-
Returns a generated object field snippet for KV binding when configured.
|
|
61
|
-
|
|
62
|
-
- If `kvBinding` is missing: returns empty string.
|
|
63
|
-
- If present: returns `KV: c.env["<binding>"] as KVNamespace` (prefixed with comma/newline for embedding).
|
|
64
|
-
|
|
65
|
-
### `generateAuthConfig(databaseBinding: string, kvBinding?: string): string`
|
|
66
|
-
|
|
67
|
-
Generates the `env` argument payload passed into `createAuth()` in route handlers:
|
|
68
|
-
|
|
69
|
-
- Always includes `DATABASE: c.env["<databaseBinding>"] as D1Database`.
|
|
70
|
-
- Optionally includes `KV` using `generateKvField()`.
|
|
71
|
-
|
|
72
|
-
This keeps route generation dynamic for projects that may or may not enable KV.
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
## `route.handler.ts`
|
|
77
|
-
|
|
78
|
-
### `generateAuthHandler(authBasePath: string, databaseBinding: string, kvBinding?: string): string`
|
|
79
|
-
|
|
80
|
-
Generates the auth route registration snippet:
|
|
81
|
-
|
|
82
|
-
- Registers `app.on(["GET", "POST"], "<authBasePath>/*", async (c) => { ... })`.
|
|
83
|
-
- Creates an auth instance per request:
|
|
84
|
-
- injects generated env bindings from `generateAuthConfig(...)`
|
|
85
|
-
- injects `c.req.raw.cf` as Cloudflare request metadata
|
|
86
|
-
- Returns `auth.handler(getSanitizedRequest(c.req.raw))`.
|
|
87
|
-
|
|
88
|
-
This is the bridge between framework routing and Better Auth request handling.
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## `route.request-utils.ts`
|
|
93
|
-
|
|
94
|
-
Contains generated helper functions to sanitize incoming request headers.
|
|
95
|
-
|
|
96
|
-
### `generateGetHeadersFunction(): string`
|
|
97
|
-
|
|
98
|
-
Generates `getHeaders(headers: Headers)`:
|
|
99
|
-
|
|
100
|
-
- Converts headers into a plain object.
|
|
101
|
-
- Detects whether a `cookie` header exists.
|
|
102
|
-
- Keeps `authorization` only when it contains a `Bearer` token.
|
|
103
|
-
- If cookies are present, suppresses `authorization` to avoid conflicting auth sources.
|
|
104
|
-
- Returns a rebuilt header object cast back to `Headers`.
|
|
105
|
-
|
|
106
|
-
### `generateSanitizedRequestFunction(): string`
|
|
107
|
-
|
|
108
|
-
Generates `getSanitizedRequest(req: Request)`:
|
|
109
|
-
|
|
110
|
-
- Creates a cloned `Request` with filtered headers from `getHeaders()`.
|
|
111
|
-
|
|
112
|
-
### `generateRequestUtilities(): string`
|
|
113
|
-
|
|
114
|
-
Concatenates both helper function source blocks into one string for route output.
|
|
115
|
-
|
|
116
|
-
---
|
|
117
|
-
|
|
118
|
-
## `route.ts`
|
|
119
|
-
|
|
120
|
-
### `generateAuthRoute(authBasePath: string, databaseBinding: string, kvBinding?: string): string`
|
|
121
|
-
|
|
122
|
-
Top-level composition entry for route generation.
|
|
123
|
-
|
|
124
|
-
- Combines:
|
|
125
|
-
- `generateAuthHandler(...)`
|
|
126
|
-
- `generateRequestUtilities()`
|
|
127
|
-
- Returns one complete source block ready to be written to generated route files.
|
|
128
|
-
|
|
129
|
-
---
|
|
130
|
-
|
|
131
|
-
## Generation flow in this directory
|
|
132
|
-
|
|
133
|
-
1. CLI calls `generateAuthRoute(...)` when producing backend route code.
|
|
134
|
-
2. Route snippet includes handler + request sanitizers.
|
|
135
|
-
3. Handler calls `createAuth(...)` with bindings generated by `generateAuthConfig(...)`.
|
|
136
|
-
4. Separately, CLI can emit full auth configuration module using `generateAuthConfigSource(...)`.
|
|
137
|
-
5. Resulting generated backend code is ready for Cloudflare Worker runtime with D1 (and optional KV).
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## Design notes
|
|
142
|
-
|
|
143
|
-
- **String-template based generation**: keeps template logic small and explicit.
|
|
144
|
-
- **Conditional KV support**: avoids forcing KV binding when not configured.
|
|
145
|
-
- **Request normalization**: helps prevent ambiguous auth precedence between cookies and authorization headers.
|
|
146
|
-
- **Cloudflare-first integration**: targets Worker runtime (`cf`, D1, KV) while preserving local compatibility shape.
|
|
147
|
-
|
|
148
|
-
---
|
|
149
|
-
|
|
150
|
-
## Expected consumers
|
|
151
|
-
|
|
152
|
-
These generators are intended to be used by internal CLI code under:
|
|
153
|
-
|
|
154
|
-
- `packages/appflare/cli/...`
|
|
155
|
-
|
|
156
|
-
They are implementation details of scaffolding and are not meant as public runtime APIs.
|
|
1
|
+
# Auth Template Generators
|
|
2
|
+
|
|
3
|
+
This directory contains source generators used by the Appflare CLI to scaffold authentication integration for a Cloudflare Worker backend.
|
|
4
|
+
|
|
5
|
+
The files here **do not directly implement runtime auth logic** in this folder. Instead, they generate TypeScript source strings that are written into generated backend files (for example under `backend/_generated`).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
The auth template layer provides:
|
|
12
|
+
|
|
13
|
+
- A generated `createAuth()` factory based on `better-auth` + Cloudflare integrations.
|
|
14
|
+
- Route-level wiring for auth endpoints (`GET`/`POST` on an auth base path).
|
|
15
|
+
- Request sanitization helpers to normalize header forwarding behavior.
|
|
16
|
+
- Small composition utilities so the CLI can include/exclude KV support based on config.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## File-by-file breakdown
|
|
21
|
+
|
|
22
|
+
## `config.ts`
|
|
23
|
+
|
|
24
|
+
### `generateAuthConfigSource(configPathImport: string): string`
|
|
25
|
+
|
|
26
|
+
Builds the full source code for an auth configuration module.
|
|
27
|
+
|
|
28
|
+
Generated module characteristics:
|
|
29
|
+
|
|
30
|
+
- Imports:
|
|
31
|
+
- `better-auth`
|
|
32
|
+
- `withCloudflare` from `better-auth-cloudflare`
|
|
33
|
+
- `drizzleAdapter` from `better-auth/adapters/drizzle`
|
|
34
|
+
- `drizzle` from `drizzle-orm/d1`
|
|
35
|
+
- Cloudflare worker types (`D1Database`, `KVNamespace`, `IncomingRequestCfProperties`)
|
|
36
|
+
- Local `auth.schema`
|
|
37
|
+
- User config module from `configPathImport`
|
|
38
|
+
- Defines `CloudflareBindings` with:
|
|
39
|
+
- required `DATABASE: D1Database`
|
|
40
|
+
- optional `KV?: KVNamespace`
|
|
41
|
+
- Exposes:
|
|
42
|
+
- `createAuth(env?, cf?)`
|
|
43
|
+
- `auth = createAuth()`
|
|
44
|
+
|
|
45
|
+
Behavior details:
|
|
46
|
+
|
|
47
|
+
- If `env` is provided:
|
|
48
|
+
- Creates a Drizzle D1 database instance.
|
|
49
|
+
- Configures `withCloudflare` with D1 and optional KV.
|
|
50
|
+
- If `env` is missing:
|
|
51
|
+
- Falls back to a placeholder `drizzleAdapter` setup to keep type-level/runtime shape valid in non-worker contexts.
|
|
52
|
+
- Merges Cloudflare options with `config.auth.options` so user config can extend behavior.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## `route.config.ts`
|
|
57
|
+
|
|
58
|
+
### `generateKvField(kvBinding?: string): string`
|
|
59
|
+
|
|
60
|
+
Returns a generated object field snippet for KV binding when configured.
|
|
61
|
+
|
|
62
|
+
- If `kvBinding` is missing: returns empty string.
|
|
63
|
+
- If present: returns `KV: c.env["<binding>"] as KVNamespace` (prefixed with comma/newline for embedding).
|
|
64
|
+
|
|
65
|
+
### `generateAuthConfig(databaseBinding: string, kvBinding?: string): string`
|
|
66
|
+
|
|
67
|
+
Generates the `env` argument payload passed into `createAuth()` in route handlers:
|
|
68
|
+
|
|
69
|
+
- Always includes `DATABASE: c.env["<databaseBinding>"] as D1Database`.
|
|
70
|
+
- Optionally includes `KV` using `generateKvField()`.
|
|
71
|
+
|
|
72
|
+
This keeps route generation dynamic for projects that may or may not enable KV.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## `route.handler.ts`
|
|
77
|
+
|
|
78
|
+
### `generateAuthHandler(authBasePath: string, databaseBinding: string, kvBinding?: string): string`
|
|
79
|
+
|
|
80
|
+
Generates the auth route registration snippet:
|
|
81
|
+
|
|
82
|
+
- Registers `app.on(["GET", "POST"], "<authBasePath>/*", async (c) => { ... })`.
|
|
83
|
+
- Creates an auth instance per request:
|
|
84
|
+
- injects generated env bindings from `generateAuthConfig(...)`
|
|
85
|
+
- injects `c.req.raw.cf` as Cloudflare request metadata
|
|
86
|
+
- Returns `auth.handler(getSanitizedRequest(c.req.raw))`.
|
|
87
|
+
|
|
88
|
+
This is the bridge between framework routing and Better Auth request handling.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## `route.request-utils.ts`
|
|
93
|
+
|
|
94
|
+
Contains generated helper functions to sanitize incoming request headers.
|
|
95
|
+
|
|
96
|
+
### `generateGetHeadersFunction(): string`
|
|
97
|
+
|
|
98
|
+
Generates `getHeaders(headers: Headers)`:
|
|
99
|
+
|
|
100
|
+
- Converts headers into a plain object.
|
|
101
|
+
- Detects whether a `cookie` header exists.
|
|
102
|
+
- Keeps `authorization` only when it contains a `Bearer` token.
|
|
103
|
+
- If cookies are present, suppresses `authorization` to avoid conflicting auth sources.
|
|
104
|
+
- Returns a rebuilt header object cast back to `Headers`.
|
|
105
|
+
|
|
106
|
+
### `generateSanitizedRequestFunction(): string`
|
|
107
|
+
|
|
108
|
+
Generates `getSanitizedRequest(req: Request)`:
|
|
109
|
+
|
|
110
|
+
- Creates a cloned `Request` with filtered headers from `getHeaders()`.
|
|
111
|
+
|
|
112
|
+
### `generateRequestUtilities(): string`
|
|
113
|
+
|
|
114
|
+
Concatenates both helper function source blocks into one string for route output.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## `route.ts`
|
|
119
|
+
|
|
120
|
+
### `generateAuthRoute(authBasePath: string, databaseBinding: string, kvBinding?: string): string`
|
|
121
|
+
|
|
122
|
+
Top-level composition entry for route generation.
|
|
123
|
+
|
|
124
|
+
- Combines:
|
|
125
|
+
- `generateAuthHandler(...)`
|
|
126
|
+
- `generateRequestUtilities()`
|
|
127
|
+
- Returns one complete source block ready to be written to generated route files.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Generation flow in this directory
|
|
132
|
+
|
|
133
|
+
1. CLI calls `generateAuthRoute(...)` when producing backend route code.
|
|
134
|
+
2. Route snippet includes handler + request sanitizers.
|
|
135
|
+
3. Handler calls `createAuth(...)` with bindings generated by `generateAuthConfig(...)`.
|
|
136
|
+
4. Separately, CLI can emit full auth configuration module using `generateAuthConfigSource(...)`.
|
|
137
|
+
5. Resulting generated backend code is ready for Cloudflare Worker runtime with D1 (and optional KV).
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Design notes
|
|
142
|
+
|
|
143
|
+
- **String-template based generation**: keeps template logic small and explicit.
|
|
144
|
+
- **Conditional KV support**: avoids forcing KV binding when not configured.
|
|
145
|
+
- **Request normalization**: helps prevent ambiguous auth precedence between cookies and authorization headers.
|
|
146
|
+
- **Cloudflare-first integration**: targets Worker runtime (`cf`, D1, KV) while preserving local compatibility shape.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Expected consumers
|
|
151
|
+
|
|
152
|
+
These generators are intended to be used by internal CLI code under:
|
|
153
|
+
|
|
154
|
+
- `packages/appflare/cli/...`
|
|
155
|
+
|
|
156
|
+
They are implementation details of scaffolding and are not meant as public runtime APIs.
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
export function generateAuthConfigSource(configPathImport: string): string {
|
|
2
|
-
return `import { betterAuth } from "better-auth";
|
|
3
|
-
import { withCloudflare } from "better-auth-cloudflare";
|
|
4
|
-
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
5
|
-
import { drizzle } from "drizzle-orm/d1";
|
|
6
|
-
import type {
|
|
7
|
-
D1Database,
|
|
8
|
-
IncomingRequestCfProperties,
|
|
9
|
-
KVNamespace,
|
|
10
|
-
} from "@cloudflare/workers-types";
|
|
11
|
-
import * as Schema from "./auth.schema";
|
|
12
|
-
import config from "${configPathImport}";
|
|
13
|
-
|
|
14
|
-
type CloudflareBindings = {
|
|
15
|
-
DATABASE: D1Database;
|
|
16
|
-
KV?: KVNamespace;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const createAuth = (
|
|
20
|
-
env?: CloudflareBindings,
|
|
21
|
-
cf?: IncomingRequestCfProperties,
|
|
22
|
-
) => {
|
|
23
|
-
const db = env
|
|
24
|
-
? drizzle(env.DATABASE, {
|
|
25
|
-
schema: Schema,
|
|
26
|
-
})
|
|
27
|
-
: ({} as any);
|
|
28
|
-
|
|
29
|
-
const cloudflareOptions = withCloudflare(
|
|
30
|
-
{
|
|
31
|
-
autoDetectIpAddress: true,
|
|
32
|
-
geolocationTracking: true,
|
|
33
|
-
cf: cf ?? {},
|
|
34
|
-
d1: env
|
|
35
|
-
? {
|
|
36
|
-
db,
|
|
37
|
-
options: {
|
|
38
|
-
usePlural: true,
|
|
39
|
-
},
|
|
40
|
-
}
|
|
41
|
-
: undefined,
|
|
42
|
-
kv: env?.KV,
|
|
43
|
-
},
|
|
44
|
-
config.auth.options as any,
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
return betterAuth({
|
|
48
|
-
...(cloudflareOptions as any),
|
|
49
|
-
...(env
|
|
50
|
-
? {}
|
|
51
|
-
: {
|
|
52
|
-
database: drizzleAdapter({} as D1Database, {
|
|
53
|
-
provider: "sqlite",
|
|
54
|
-
usePlural: true,
|
|
55
|
-
}),
|
|
56
|
-
}),
|
|
57
|
-
});
|
|
58
|
-
};
|
|
59
|
-
export const auth = createAuth();
|
|
60
|
-
`;
|
|
61
|
-
}
|
|
1
|
+
export function generateAuthConfigSource(configPathImport: string): string {
|
|
2
|
+
return `import { betterAuth } from "better-auth";
|
|
3
|
+
import { withCloudflare } from "better-auth-cloudflare";
|
|
4
|
+
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
5
|
+
import { drizzle } from "drizzle-orm/d1";
|
|
6
|
+
import type {
|
|
7
|
+
D1Database,
|
|
8
|
+
IncomingRequestCfProperties,
|
|
9
|
+
KVNamespace,
|
|
10
|
+
} from "@cloudflare/workers-types";
|
|
11
|
+
import * as Schema from "./auth.schema";
|
|
12
|
+
import config from "${configPathImport}";
|
|
13
|
+
|
|
14
|
+
type CloudflareBindings = {
|
|
15
|
+
DATABASE: D1Database;
|
|
16
|
+
KV?: KVNamespace;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const createAuth = (
|
|
20
|
+
env?: CloudflareBindings,
|
|
21
|
+
cf?: IncomingRequestCfProperties,
|
|
22
|
+
) => {
|
|
23
|
+
const db = env
|
|
24
|
+
? drizzle(env.DATABASE, {
|
|
25
|
+
schema: Schema,
|
|
26
|
+
})
|
|
27
|
+
: ({} as any);
|
|
28
|
+
|
|
29
|
+
const cloudflareOptions = withCloudflare(
|
|
30
|
+
{
|
|
31
|
+
autoDetectIpAddress: true,
|
|
32
|
+
geolocationTracking: true,
|
|
33
|
+
cf: cf ?? {},
|
|
34
|
+
d1: env
|
|
35
|
+
? {
|
|
36
|
+
db,
|
|
37
|
+
options: {
|
|
38
|
+
usePlural: true,
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
: undefined,
|
|
42
|
+
kv: env?.KV,
|
|
43
|
+
},
|
|
44
|
+
config.auth.options as any,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return betterAuth({
|
|
48
|
+
...(cloudflareOptions as any),
|
|
49
|
+
...(env
|
|
50
|
+
? {}
|
|
51
|
+
: {
|
|
52
|
+
database: drizzleAdapter({} as D1Database, {
|
|
53
|
+
provider: "sqlite",
|
|
54
|
+
usePlural: true,
|
|
55
|
+
}),
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
export const auth = createAuth();
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { generateAuthConfig, generateKvField } from "./route.config";
|
|
1
|
+
export { generateAuthConfig, generateKvField } from "./route.config";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { generateAuthHandler } from "./route.handler";
|
|
1
|
+
export { generateAuthHandler } from "./route.handler";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
generateGetHeadersFunction,
|
|
3
|
-
generateRequestUtilities,
|
|
4
|
-
generateSanitizedRequestFunction,
|
|
5
|
-
} from "./route.request-utils";
|
|
1
|
+
export {
|
|
2
|
+
generateGetHeadersFunction,
|
|
3
|
+
generateRequestUtilities,
|
|
4
|
+
generateSanitizedRequestFunction,
|
|
5
|
+
} from "./route.request-utils";
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
function generateKvField(kvBinding?: string): string {
|
|
2
|
-
if (!kvBinding) {
|
|
3
|
-
return "";
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
return `,\n\t\t\tKV: c.env["${kvBinding}"] as KVNamespace`;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function generateAuthConfig(
|
|
10
|
-
databaseBinding: string,
|
|
11
|
-
kvBinding?: string,
|
|
12
|
-
): string {
|
|
13
|
-
return `{
|
|
14
|
-
DATABASE: c.env["${databaseBinding}"] as D1Database${generateKvField(kvBinding)}
|
|
15
|
-
}`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export { generateKvField, generateAuthConfig };
|
|
1
|
+
function generateKvField(kvBinding?: string): string {
|
|
2
|
+
if (!kvBinding) {
|
|
3
|
+
return "";
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
return `,\n\t\t\tKV: c.env["${kvBinding}"] as KVNamespace`;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function generateAuthConfig(
|
|
10
|
+
databaseBinding: string,
|
|
11
|
+
kvBinding?: string,
|
|
12
|
+
): string {
|
|
13
|
+
return `{
|
|
14
|
+
DATABASE: c.env["${databaseBinding}"] as D1Database${generateKvField(kvBinding)}
|
|
15
|
+
}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { generateKvField, generateAuthConfig };
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { generateAuthConfig } from "./route.config";
|
|
2
|
-
|
|
3
|
-
function generateAuthHandler(
|
|
4
|
-
authBasePath: string,
|
|
5
|
-
databaseBinding: string,
|
|
6
|
-
kvBinding?: string,
|
|
7
|
-
): string {
|
|
8
|
-
return `app.on(["GET", "POST"], "${authBasePath}/*", async (c) => {
|
|
9
|
-
const auth = createAuth(
|
|
10
|
-
${generateAuthConfig(databaseBinding, kvBinding)},
|
|
11
|
-
c.req.raw.cf as IncomingRequestCfProperties | undefined,
|
|
12
|
-
);
|
|
13
|
-
return auth.handler(getSanitizedRequest(c.req.raw));
|
|
14
|
-
});
|
|
15
|
-
`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export { generateAuthHandler };
|
|
1
|
+
import { generateAuthConfig } from "./route.config";
|
|
2
|
+
|
|
3
|
+
function generateAuthHandler(
|
|
4
|
+
authBasePath: string,
|
|
5
|
+
databaseBinding: string,
|
|
6
|
+
kvBinding?: string,
|
|
7
|
+
): string {
|
|
8
|
+
return `app.on(["GET", "POST"], "${authBasePath}/*", async (c) => {
|
|
9
|
+
const auth = createAuth(
|
|
10
|
+
${generateAuthConfig(databaseBinding, kvBinding)},
|
|
11
|
+
c.req.raw.cf as IncomingRequestCfProperties | undefined,
|
|
12
|
+
);
|
|
13
|
+
return auth.handler(getSanitizedRequest(c.req.raw));
|
|
14
|
+
});
|
|
15
|
+
`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { generateAuthHandler };
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
function generateGetHeadersFunction(): string {
|
|
2
|
-
return `export const getHeaders = (headers: Headers) => {
|
|
3
|
-
const newHeaders = Object.fromEntries(headers as any);
|
|
4
|
-
const headerObject: Record<string, any> = {};
|
|
5
|
-
let hasCookie = false;
|
|
6
|
-
|
|
7
|
-
for (const key in newHeaders) {
|
|
8
|
-
if (key.toLowerCase() === "cookie") {
|
|
9
|
-
hasCookie = true;
|
|
10
|
-
break;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
for (const key in newHeaders) {
|
|
15
|
-
const isAuthorization =
|
|
16
|
-
key.toLowerCase() === "authorization" &&
|
|
17
|
-
newHeaders[key]?.includes("Bearer");
|
|
18
|
-
|
|
19
|
-
if (hasCookie && key.toLowerCase() === "authorization") {
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (key.toLowerCase() === "authorization" && !isAuthorization) {
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
headerObject[key] = newHeaders[key];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return headerObject as any as Headers;
|
|
31
|
-
};
|
|
32
|
-
`;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function generateSanitizedRequestFunction(): string {
|
|
36
|
-
return `export const getSanitizedRequest = (req: Request) => {
|
|
37
|
-
const newRequest = new Request(req, {
|
|
38
|
-
headers: getHeaders(req.headers),
|
|
39
|
-
});
|
|
40
|
-
return newRequest;
|
|
41
|
-
};
|
|
42
|
-
`;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function generateRequestUtilities(): string {
|
|
46
|
-
return (
|
|
47
|
-
generateGetHeadersFunction() + "\n" + generateSanitizedRequestFunction()
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export {
|
|
52
|
-
generateGetHeadersFunction,
|
|
53
|
-
generateSanitizedRequestFunction,
|
|
54
|
-
generateRequestUtilities,
|
|
55
|
-
};
|
|
1
|
+
function generateGetHeadersFunction(): string {
|
|
2
|
+
return `export const getHeaders = (headers: Headers) => {
|
|
3
|
+
const newHeaders = Object.fromEntries(headers as any);
|
|
4
|
+
const headerObject: Record<string, any> = {};
|
|
5
|
+
let hasCookie = false;
|
|
6
|
+
|
|
7
|
+
for (const key in newHeaders) {
|
|
8
|
+
if (key.toLowerCase() === "cookie") {
|
|
9
|
+
hasCookie = true;
|
|
10
|
+
break;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
for (const key in newHeaders) {
|
|
15
|
+
const isAuthorization =
|
|
16
|
+
key.toLowerCase() === "authorization" &&
|
|
17
|
+
newHeaders[key]?.includes("Bearer");
|
|
18
|
+
|
|
19
|
+
if (hasCookie && key.toLowerCase() === "authorization") {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (key.toLowerCase() === "authorization" && !isAuthorization) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
headerObject[key] = newHeaders[key];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return headerObject as any as Headers;
|
|
31
|
+
};
|
|
32
|
+
`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function generateSanitizedRequestFunction(): string {
|
|
36
|
+
return `export const getSanitizedRequest = (req: Request) => {
|
|
37
|
+
const newRequest = new Request(req, {
|
|
38
|
+
headers: getHeaders(req.headers),
|
|
39
|
+
});
|
|
40
|
+
return newRequest;
|
|
41
|
+
};
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function generateRequestUtilities(): string {
|
|
46
|
+
return (
|
|
47
|
+
generateGetHeadersFunction() + "\n" + generateSanitizedRequestFunction()
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
generateGetHeadersFunction,
|
|
53
|
+
generateSanitizedRequestFunction,
|
|
54
|
+
generateRequestUtilities,
|
|
55
|
+
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { generateAuthHandler } from "./route.handler";
|
|
2
|
-
import { generateRequestUtilities } from "./route.request-utils";
|
|
3
|
-
|
|
4
|
-
export function generateAuthRoute(
|
|
5
|
-
authBasePath: string,
|
|
6
|
-
databaseBinding: string,
|
|
7
|
-
kvBinding?: string,
|
|
8
|
-
): string {
|
|
9
|
-
return (
|
|
10
|
-
generateAuthHandler(authBasePath, databaseBinding, kvBinding) +
|
|
11
|
-
"\n" +
|
|
12
|
-
generateRequestUtilities()
|
|
13
|
-
);
|
|
14
|
-
}
|
|
1
|
+
import { generateAuthHandler } from "./route.handler";
|
|
2
|
+
import { generateRequestUtilities } from "./route.request-utils";
|
|
3
|
+
|
|
4
|
+
export function generateAuthRoute(
|
|
5
|
+
authBasePath: string,
|
|
6
|
+
databaseBinding: string,
|
|
7
|
+
kvBinding?: string,
|
|
8
|
+
): string {
|
|
9
|
+
return (
|
|
10
|
+
generateAuthHandler(authBasePath, databaseBinding, kvBinding) +
|
|
11
|
+
"\n" +
|
|
12
|
+
generateRequestUtilities()
|
|
13
|
+
);
|
|
14
|
+
}
|