@authhero/drizzle 0.57.0 → 0.58.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.
@@ -8,6 +8,13 @@
8
8
  "when": 1783004771436,
9
9
  "tag": "0000_init",
10
10
  "breakpoints": true
11
+ },
12
+ {
13
+ "idx": 1,
14
+ "version": "6",
15
+ "when": 1783242650985,
16
+ "tag": "0001_next_young_avengers",
17
+ "breakpoints": true
11
18
  }
12
19
  ]
13
20
  }
@@ -0,0 +1,47 @@
1
+ CREATE TABLE `tenant_operation_events` (
2
+ `id` text(255) PRIMARY KEY NOT NULL,
3
+ `operation_id` text(255) NOT NULL,
4
+ `step` text(255) NOT NULL,
5
+ `outcome` text(32) NOT NULL,
6
+ `detail` text,
7
+ `attempt` integer DEFAULT 1 NOT NULL,
8
+ `created_at` text(35) NOT NULL,
9
+ FOREIGN KEY (`operation_id`) REFERENCES `tenant_operations`(`id`) ON UPDATE no action ON DELETE cascade
10
+ );
11
+ --> statement-breakpoint
12
+ CREATE INDEX `tenant_operation_events_operation_id_created_at_idx` ON `tenant_operation_events` (`operation_id`,`created_at`);--> statement-breakpoint
13
+ CREATE TABLE `tenant_operations` (
14
+ `id` text(255) PRIMARY KEY NOT NULL,
15
+ `tenant_id` text(255),
16
+ `rollout_id` text(255),
17
+ `kind` text(32) NOT NULL,
18
+ `status` text(32) NOT NULL,
19
+ `current_step` text(255),
20
+ `engine` text(64) NOT NULL,
21
+ `engine_instance_id` text(100),
22
+ `target_worker_version` text(255),
23
+ `target_database_version` text(255),
24
+ `error` text,
25
+ `initiated_by` text(255),
26
+ `created_at` text(35) NOT NULL,
27
+ `updated_at` text(35) NOT NULL,
28
+ `finished_at` text(35)
29
+ );
30
+ --> statement-breakpoint
31
+ CREATE INDEX `tenant_operations_tenant_id_created_at_idx` ON `tenant_operations` (`tenant_id`,`created_at`);--> statement-breakpoint
32
+ CREATE INDEX `tenant_operations_rollout_id_idx` ON `tenant_operations` (`rollout_id`);--> statement-breakpoint
33
+ CREATE INDEX `tenant_operations_status_idx` ON `tenant_operations` (`status`);--> statement-breakpoint
34
+ CREATE TABLE `rollouts` (
35
+ `id` text(255) PRIMARY KEY NOT NULL,
36
+ `kind` text(32) NOT NULL,
37
+ `status` text(32) NOT NULL,
38
+ `target_worker_version` text(255),
39
+ `target_database_version` text(255),
40
+ `wave_size` integer DEFAULT 10 NOT NULL,
41
+ `canary_tenant_ids` text,
42
+ `filter` text,
43
+ `initiated_by` text(255),
44
+ `created_at` text(35) NOT NULL,
45
+ `updated_at` text(35) NOT NULL,
46
+ `finished_at` text(35)
47
+ );
@@ -0,0 +1,334 @@
1
+ {
2
+ "version": "6",
3
+ "dialect": "sqlite",
4
+ "id": "e2903902-b3f1-43b0-bfac-9e649c9a33d8",
5
+ "prevId": "00000000-0000-0000-0000-000000000000",
6
+ "tables": {
7
+ "tenant_operation_events": {
8
+ "name": "tenant_operation_events",
9
+ "columns": {
10
+ "id": {
11
+ "name": "id",
12
+ "type": "text(255)",
13
+ "primaryKey": true,
14
+ "notNull": true,
15
+ "autoincrement": false
16
+ },
17
+ "operation_id": {
18
+ "name": "operation_id",
19
+ "type": "text(255)",
20
+ "primaryKey": false,
21
+ "notNull": true,
22
+ "autoincrement": false
23
+ },
24
+ "step": {
25
+ "name": "step",
26
+ "type": "text(255)",
27
+ "primaryKey": false,
28
+ "notNull": true,
29
+ "autoincrement": false
30
+ },
31
+ "outcome": {
32
+ "name": "outcome",
33
+ "type": "text(32)",
34
+ "primaryKey": false,
35
+ "notNull": true,
36
+ "autoincrement": false
37
+ },
38
+ "detail": {
39
+ "name": "detail",
40
+ "type": "text",
41
+ "primaryKey": false,
42
+ "notNull": false,
43
+ "autoincrement": false
44
+ },
45
+ "attempt": {
46
+ "name": "attempt",
47
+ "type": "integer",
48
+ "primaryKey": false,
49
+ "notNull": true,
50
+ "autoincrement": false,
51
+ "default": 1
52
+ },
53
+ "created_at": {
54
+ "name": "created_at",
55
+ "type": "text(35)",
56
+ "primaryKey": false,
57
+ "notNull": true,
58
+ "autoincrement": false
59
+ }
60
+ },
61
+ "indexes": {
62
+ "tenant_operation_events_operation_id_created_at_idx": {
63
+ "name": "tenant_operation_events_operation_id_created_at_idx",
64
+ "columns": [
65
+ "operation_id",
66
+ "created_at"
67
+ ],
68
+ "isUnique": false
69
+ }
70
+ },
71
+ "foreignKeys": {
72
+ "tenant_operation_events_operation_id_constraint": {
73
+ "name": "tenant_operation_events_operation_id_constraint",
74
+ "tableFrom": "tenant_operation_events",
75
+ "tableTo": "tenant_operations",
76
+ "columnsFrom": [
77
+ "operation_id"
78
+ ],
79
+ "columnsTo": [
80
+ "id"
81
+ ],
82
+ "onDelete": "cascade",
83
+ "onUpdate": "no action"
84
+ }
85
+ },
86
+ "compositePrimaryKeys": {},
87
+ "uniqueConstraints": {},
88
+ "checkConstraints": {}
89
+ },
90
+ "tenant_operations": {
91
+ "name": "tenant_operations",
92
+ "columns": {
93
+ "id": {
94
+ "name": "id",
95
+ "type": "text(255)",
96
+ "primaryKey": true,
97
+ "notNull": true,
98
+ "autoincrement": false
99
+ },
100
+ "tenant_id": {
101
+ "name": "tenant_id",
102
+ "type": "text(255)",
103
+ "primaryKey": false,
104
+ "notNull": false,
105
+ "autoincrement": false
106
+ },
107
+ "rollout_id": {
108
+ "name": "rollout_id",
109
+ "type": "text(255)",
110
+ "primaryKey": false,
111
+ "notNull": false,
112
+ "autoincrement": false
113
+ },
114
+ "kind": {
115
+ "name": "kind",
116
+ "type": "text(32)",
117
+ "primaryKey": false,
118
+ "notNull": true,
119
+ "autoincrement": false
120
+ },
121
+ "status": {
122
+ "name": "status",
123
+ "type": "text(32)",
124
+ "primaryKey": false,
125
+ "notNull": true,
126
+ "autoincrement": false
127
+ },
128
+ "current_step": {
129
+ "name": "current_step",
130
+ "type": "text(255)",
131
+ "primaryKey": false,
132
+ "notNull": false,
133
+ "autoincrement": false
134
+ },
135
+ "engine": {
136
+ "name": "engine",
137
+ "type": "text(64)",
138
+ "primaryKey": false,
139
+ "notNull": true,
140
+ "autoincrement": false
141
+ },
142
+ "engine_instance_id": {
143
+ "name": "engine_instance_id",
144
+ "type": "text(100)",
145
+ "primaryKey": false,
146
+ "notNull": false,
147
+ "autoincrement": false
148
+ },
149
+ "target_worker_version": {
150
+ "name": "target_worker_version",
151
+ "type": "text(255)",
152
+ "primaryKey": false,
153
+ "notNull": false,
154
+ "autoincrement": false
155
+ },
156
+ "target_database_version": {
157
+ "name": "target_database_version",
158
+ "type": "text(255)",
159
+ "primaryKey": false,
160
+ "notNull": false,
161
+ "autoincrement": false
162
+ },
163
+ "error": {
164
+ "name": "error",
165
+ "type": "text",
166
+ "primaryKey": false,
167
+ "notNull": false,
168
+ "autoincrement": false
169
+ },
170
+ "initiated_by": {
171
+ "name": "initiated_by",
172
+ "type": "text(255)",
173
+ "primaryKey": false,
174
+ "notNull": false,
175
+ "autoincrement": false
176
+ },
177
+ "created_at": {
178
+ "name": "created_at",
179
+ "type": "text(35)",
180
+ "primaryKey": false,
181
+ "notNull": true,
182
+ "autoincrement": false
183
+ },
184
+ "updated_at": {
185
+ "name": "updated_at",
186
+ "type": "text(35)",
187
+ "primaryKey": false,
188
+ "notNull": true,
189
+ "autoincrement": false
190
+ },
191
+ "finished_at": {
192
+ "name": "finished_at",
193
+ "type": "text(35)",
194
+ "primaryKey": false,
195
+ "notNull": false,
196
+ "autoincrement": false
197
+ }
198
+ },
199
+ "indexes": {
200
+ "tenant_operations_tenant_id_created_at_idx": {
201
+ "name": "tenant_operations_tenant_id_created_at_idx",
202
+ "columns": [
203
+ "tenant_id",
204
+ "created_at"
205
+ ],
206
+ "isUnique": false
207
+ },
208
+ "tenant_operations_rollout_id_idx": {
209
+ "name": "tenant_operations_rollout_id_idx",
210
+ "columns": [
211
+ "rollout_id"
212
+ ],
213
+ "isUnique": false
214
+ },
215
+ "tenant_operations_status_idx": {
216
+ "name": "tenant_operations_status_idx",
217
+ "columns": [
218
+ "status"
219
+ ],
220
+ "isUnique": false
221
+ }
222
+ },
223
+ "foreignKeys": {},
224
+ "compositePrimaryKeys": {},
225
+ "uniqueConstraints": {},
226
+ "checkConstraints": {}
227
+ },
228
+ "rollouts": {
229
+ "name": "rollouts",
230
+ "columns": {
231
+ "id": {
232
+ "name": "id",
233
+ "type": "text(255)",
234
+ "primaryKey": true,
235
+ "notNull": true,
236
+ "autoincrement": false
237
+ },
238
+ "kind": {
239
+ "name": "kind",
240
+ "type": "text(32)",
241
+ "primaryKey": false,
242
+ "notNull": true,
243
+ "autoincrement": false
244
+ },
245
+ "status": {
246
+ "name": "status",
247
+ "type": "text(32)",
248
+ "primaryKey": false,
249
+ "notNull": true,
250
+ "autoincrement": false
251
+ },
252
+ "target_worker_version": {
253
+ "name": "target_worker_version",
254
+ "type": "text(255)",
255
+ "primaryKey": false,
256
+ "notNull": false,
257
+ "autoincrement": false
258
+ },
259
+ "target_database_version": {
260
+ "name": "target_database_version",
261
+ "type": "text(255)",
262
+ "primaryKey": false,
263
+ "notNull": false,
264
+ "autoincrement": false
265
+ },
266
+ "wave_size": {
267
+ "name": "wave_size",
268
+ "type": "integer",
269
+ "primaryKey": false,
270
+ "notNull": true,
271
+ "autoincrement": false,
272
+ "default": 10
273
+ },
274
+ "canary_tenant_ids": {
275
+ "name": "canary_tenant_ids",
276
+ "type": "text",
277
+ "primaryKey": false,
278
+ "notNull": false,
279
+ "autoincrement": false
280
+ },
281
+ "filter": {
282
+ "name": "filter",
283
+ "type": "text",
284
+ "primaryKey": false,
285
+ "notNull": false,
286
+ "autoincrement": false
287
+ },
288
+ "initiated_by": {
289
+ "name": "initiated_by",
290
+ "type": "text(255)",
291
+ "primaryKey": false,
292
+ "notNull": false,
293
+ "autoincrement": false
294
+ },
295
+ "created_at": {
296
+ "name": "created_at",
297
+ "type": "text(35)",
298
+ "primaryKey": false,
299
+ "notNull": true,
300
+ "autoincrement": false
301
+ },
302
+ "updated_at": {
303
+ "name": "updated_at",
304
+ "type": "text(35)",
305
+ "primaryKey": false,
306
+ "notNull": true,
307
+ "autoincrement": false
308
+ },
309
+ "finished_at": {
310
+ "name": "finished_at",
311
+ "type": "text(35)",
312
+ "primaryKey": false,
313
+ "notNull": false,
314
+ "autoincrement": false
315
+ }
316
+ },
317
+ "indexes": {},
318
+ "foreignKeys": {},
319
+ "compositePrimaryKeys": {},
320
+ "uniqueConstraints": {},
321
+ "checkConstraints": {}
322
+ }
323
+ },
324
+ "views": {},
325
+ "enums": {},
326
+ "_meta": {
327
+ "schemas": {},
328
+ "tables": {},
329
+ "columns": {}
330
+ },
331
+ "internal": {
332
+ "indexes": {}
333
+ }
334
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": "7",
3
+ "dialect": "sqlite",
4
+ "entries": [
5
+ {
6
+ "idx": 0,
7
+ "version": "6",
8
+ "when": 1783171275272,
9
+ "tag": "0000_tenant_operations",
10
+ "breakpoints": true
11
+ }
12
+ ]
13
+ }
package/package.json CHANGED
@@ -11,11 +11,12 @@
11
11
  "type": "git",
12
12
  "url": "https://github.com/markusahlstrand/authhero"
13
13
  },
14
- "version": "0.57.0",
14
+ "version": "0.58.1",
15
15
  "files": [
16
16
  "dist",
17
17
  "src/schema",
18
- "drizzle"
18
+ "drizzle",
19
+ "drizzle-control-plane"
19
20
  ],
20
21
  "main": "dist/drizzle-adapter.cjs",
21
22
  "module": "dist/drizzle-adapter.mjs",
@@ -34,8 +35,8 @@
34
35
  "dependencies": {
35
36
  "drizzle-orm": "^0.44.2",
36
37
  "nanoid": "^5.1.11",
37
- "@authhero/adapter-interfaces": "3.5.0",
38
- "@authhero/proxy": "0.8.1"
38
+ "@authhero/adapter-interfaces": "3.7.0",
39
+ "@authhero/proxy": "0.8.3"
39
40
  },
40
41
  "devDependencies": {
41
42
  "@hono/zod-openapi": "^1.4.0",
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Control-plane-only tables (issue #1026). These are deliberately kept out
3
+ * of the core `sqlite` schema: the core migration set in `drizzle/` is
4
+ * applied to every WFP tenant D1, while this set (generated into
5
+ * `drizzle-control-plane/` via `drizzle.config.control-plane.ts`) is applied
6
+ * only to control-plane databases. Both sets can share one database — apply
7
+ * this one with a distinct `migrationsTable` so the journals don't collide:
8
+ *
9
+ * ```typescript
10
+ * import { migrate } from "drizzle-orm/better-sqlite3/migrator";
11
+ *
12
+ * migrate(db, { migrationsFolder: coreFolder });
13
+ * migrate(db, {
14
+ * migrationsFolder: controlPlaneFolder,
15
+ * migrationsTable: "__drizzle_migrations_control_plane",
16
+ * });
17
+ * ```
18
+ */
19
+ export * from "./tenantOperations";
20
+ export * from "./rollouts";
@@ -0,0 +1,21 @@
1
+ import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
2
+
3
+ /**
4
+ * Fleet rollout records (issue #1026). Progress is derived by querying
5
+ * `tenant_operations` rows carrying this rollout's id — no denormalized
6
+ * counters. Mirrors the kysely adapter's `rollouts` table.
7
+ */
8
+ export const rollouts = sqliteTable("rollouts", {
9
+ id: text("id", { length: 255 }).primaryKey(),
10
+ kind: text("kind", { length: 32 }).notNull(),
11
+ status: text("status", { length: 32 }).notNull(),
12
+ target_worker_version: text("target_worker_version", { length: 255 }),
13
+ target_database_version: text("target_database_version", { length: 255 }),
14
+ wave_size: integer("wave_size").notNull().default(10),
15
+ canary_tenant_ids: text("canary_tenant_ids"), // JSON array of tenant ids
16
+ filter: text("filter"), // JSON tenant filter
17
+ initiated_by: text("initiated_by", { length: 255 }),
18
+ created_at: text("created_at", { length: 35 }).notNull(),
19
+ updated_at: text("updated_at", { length: 35 }).notNull(),
20
+ finished_at: text("finished_at", { length: 35 }),
21
+ });
@@ -0,0 +1,70 @@
1
+ import {
2
+ sqliteTable,
3
+ text,
4
+ integer,
5
+ index,
6
+ foreignKey,
7
+ } from "drizzle-orm/sqlite-core";
8
+
9
+ /**
10
+ * Durable tenant lifecycle operations (issue #1026): one row per
11
+ * provision / seed / upgrade / backup / deprovision run. Intentionally no
12
+ * FK to `tenants` — the log must survive tenant deletion, and `tenant_id`
13
+ * is NULL for fleet-level operations. Mirrors the kysely adapter's
14
+ * `tenant_operations` table.
15
+ */
16
+ export const tenantOperations = sqliteTable(
17
+ "tenant_operations",
18
+ {
19
+ id: text("id", { length: 255 }).primaryKey(),
20
+ tenant_id: text("tenant_id", { length: 255 }),
21
+ rollout_id: text("rollout_id", { length: 255 }),
22
+ kind: text("kind", { length: 32 }).notNull(),
23
+ status: text("status", { length: 32 }).notNull(),
24
+ current_step: text("current_step", { length: 255 }),
25
+ engine: text("engine", { length: 64 }).notNull(),
26
+ engine_instance_id: text("engine_instance_id", { length: 100 }),
27
+ target_worker_version: text("target_worker_version", { length: 255 }),
28
+ target_database_version: text("target_database_version", { length: 255 }),
29
+ error: text("error"),
30
+ initiated_by: text("initiated_by", { length: 255 }),
31
+ created_at: text("created_at", { length: 35 }).notNull(),
32
+ updated_at: text("updated_at", { length: 35 }).notNull(),
33
+ finished_at: text("finished_at", { length: 35 }),
34
+ },
35
+ (table) => [
36
+ index("tenant_operations_tenant_id_created_at_idx").on(
37
+ table.tenant_id,
38
+ table.created_at,
39
+ ),
40
+ index("tenant_operations_rollout_id_idx").on(table.rollout_id),
41
+ index("tenant_operations_status_idx").on(table.status),
42
+ ],
43
+ );
44
+
45
+ /**
46
+ * Append-only per-step history for tenant operations.
47
+ */
48
+ export const tenantOperationEvents = sqliteTable(
49
+ "tenant_operation_events",
50
+ {
51
+ id: text("id", { length: 255 }).primaryKey(),
52
+ operation_id: text("operation_id", { length: 255 }).notNull(),
53
+ step: text("step", { length: 255 }).notNull(),
54
+ outcome: text("outcome", { length: 32 }).notNull(),
55
+ detail: text("detail"), // JSON
56
+ attempt: integer("attempt").notNull().default(1),
57
+ created_at: text("created_at", { length: 35 }).notNull(),
58
+ },
59
+ (table) => [
60
+ foreignKey({
61
+ columns: [table.operation_id],
62
+ foreignColumns: [tenantOperations.id],
63
+ name: "tenant_operation_events_operation_id_constraint",
64
+ }).onDelete("cascade"),
65
+ index("tenant_operation_events_operation_id_created_at_idx").on(
66
+ table.operation_id,
67
+ table.created_at,
68
+ ),
69
+ ],
70
+ );
@@ -0,0 +1,43 @@
1
+ import {
2
+ sqliteTable,
3
+ text,
4
+ index,
5
+ uniqueIndex,
6
+ foreignKey,
7
+ } from "drizzle-orm/sqlite-core";
8
+ import { tenants } from "./tenants";
9
+ import { users } from "./users";
10
+
11
+ // Per-(user, client, audience) OAuth consent grants — the store behind the
12
+ // consent screen and the management API /grants endpoints. Mirrors the
13
+ // kysely `grants` table: audience defaults to "" so the natural-key unique
14
+ // index treats "no audience" as a single slot per (user, client).
15
+ export const grants = sqliteTable(
16
+ "grants",
17
+ {
18
+ id: text("id", { length: 21 }).primaryKey(),
19
+ tenant_id: text("tenant_id", { length: 255 })
20
+ .notNull()
21
+ .references(() => tenants.id, { onDelete: "cascade" }),
22
+ user_id: text("user_id", { length: 255 }).notNull(),
23
+ client_id: text("client_id", { length: 100 }).notNull(),
24
+ audience: text("audience", { length: 100 }).notNull().default(""),
25
+ scope: text("scope").notNull().default("[]"),
26
+ created_at: text("created_at", { length: 35 }).notNull(),
27
+ updated_at: text("updated_at", { length: 35 }).notNull(),
28
+ },
29
+ (table) => [
30
+ foreignKey({
31
+ columns: [table.user_id, table.tenant_id],
32
+ foreignColumns: [users.user_id, users.tenant_id],
33
+ name: "grants_user_id_constraint",
34
+ }).onDelete("cascade"),
35
+ uniqueIndex("grants_natural_key_idx").on(
36
+ table.tenant_id,
37
+ table.user_id,
38
+ table.client_id,
39
+ table.audience,
40
+ ),
41
+ index("grants_tenant_user_idx").on(table.tenant_id, table.user_id),
42
+ ],
43
+ );
@@ -21,6 +21,7 @@ export * from "./sessions";
21
21
 
22
22
  // Clients & Grants
23
23
  export * from "./clients";
24
+ export * from "./grants";
24
25
 
25
26
  // Connections & Domains
26
27
  export * from "./connections";