@yielded/auth-persistence-drizzle 0.1.0-beta.21 → 0.1.0-beta.23

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.
Files changed (66) hide show
  1. package/dist/Libsql.d.mts +19 -19
  2. package/dist/Mysql2.d.mts +14 -14
  3. package/dist/Pglite.d.mts +14 -14
  4. package/dist/Postgres.d.mts +6 -6
  5. package/dist/SqliteBun.d.mts +27 -27
  6. package/dist/SqliteDo.d.mts +13 -13
  7. package/dist/SqliteNode.d.mts +23 -23
  8. package/dist/SqliteWasm.d.mts +13 -13
  9. package/dist/drizzle/d1-password-prepared.d.mts +3 -3
  10. package/dist/drizzle/d1-password-prepared.mjs.map +1 -1
  11. package/dist/drizzle/d1-passwords.d.mts +8 -9
  12. package/dist/drizzle/d1-passwords.mjs +103 -173
  13. package/dist/drizzle/d1-passwords.mjs.map +1 -1
  14. package/dist/drizzle/d1-proofs.d.mts +1 -1
  15. package/dist/drizzle/d1-sessions.d.mts +1 -1
  16. package/dist/drizzle/mysql-password-prepared.d.mts +5 -5
  17. package/dist/drizzle/mysql-password-prepared.mjs.map +1 -1
  18. package/dist/drizzle/mysql-passwords.d.mts +9 -9
  19. package/dist/drizzle/mysql-passwords.mjs.map +1 -1
  20. package/dist/drizzle/native-sql-table.mjs +110 -0
  21. package/dist/drizzle/native-sql-table.mjs.map +1 -0
  22. package/dist/drizzle/oauth-connected-target.d.mts +5 -5
  23. package/dist/drizzle/oauth-target.d.mts +1 -1
  24. package/dist/drizzle/password-model.d.mts +5 -7
  25. package/dist/drizzle/password-prepared-model.d.mts +5 -5
  26. package/dist/drizzle/password-prepared-model.mjs.map +1 -1
  27. package/dist/drizzle/password-sql.mjs +2 -1
  28. package/dist/drizzle/password-sql.mjs.map +1 -1
  29. package/dist/drizzle/password-target.mjs +13 -2
  30. package/dist/drizzle/password-target.mjs.map +1 -1
  31. package/dist/drizzle/pg-password-prepared.d.mts +5 -5
  32. package/dist/drizzle/pg-password-prepared.mjs.map +1 -1
  33. package/dist/drizzle/pg-passwords.d.mts +9 -9
  34. package/dist/drizzle/pg-passwords.mjs.map +1 -1
  35. package/dist/drizzle/phone-target.d.mts +1 -1
  36. package/dist/drizzle/session-sql.mjs +2 -1
  37. package/dist/drizzle/session-sql.mjs.map +1 -1
  38. package/dist/drizzle/sqlite-password-prepared.mjs.map +1 -1
  39. package/dist/drizzle/sqlite-passwords.mjs.map +1 -1
  40. package/dist/drizzle/storage-validation.mjs +0 -13
  41. package/dist/drizzle/storage-validation.mjs.map +1 -1
  42. package/dist/drizzle/totp-target.d.mts +1 -1
  43. package/dist/index.d.mts +2 -2
  44. package/dist/internal/drizzle-postgres.mjs +2 -0
  45. package/dist/internal/drizzle-postgres.mjs.map +1 -1
  46. package/dist/internal/drizzle-sqlite.mjs +2 -0
  47. package/dist/internal/drizzle-sqlite.mjs.map +1 -1
  48. package/package.json +1 -1
  49. package/src/drizzle/d1-password-prepared.ts +2 -20
  50. package/src/drizzle/d1-passwords.ts +232 -519
  51. package/src/drizzle/mysql-password-prepared.ts +4 -12
  52. package/src/drizzle/mysql-passwords.ts +5 -15
  53. package/src/drizzle/native-sql-table.ts +229 -0
  54. package/src/drizzle/password-model.ts +0 -20
  55. package/src/drizzle/password-prepared-model.ts +0 -12
  56. package/src/drizzle/password-sql.ts +3 -0
  57. package/src/drizzle/password-target.ts +41 -4
  58. package/src/drizzle/pg-password-prepared.ts +4 -12
  59. package/src/drizzle/pg-passwords.ts +5 -15
  60. package/src/drizzle/session-sql.ts +2 -1
  61. package/src/drizzle/sqlite-password-prepared.ts +4 -48
  62. package/src/drizzle/sqlite-passwords.ts +7 -21
  63. package/src/drizzle/storage-validation.ts +0 -8
  64. package/src/index.ts +0 -4
  65. package/src/internal/drizzle-postgres.ts +2 -0
  66. package/src/internal/drizzle-sqlite.ts +2 -0
@@ -30,8 +30,6 @@ export const makeMySqlPasswordPreparedPersistenceServices = <
30
30
  C extends AnyMySqlTable,
31
31
  AC extends AnyMySqlTable,
32
32
  A extends AnyMySqlTable,
33
- RS extends AnyMySqlTable,
34
- CE extends AnyMySqlTable,
35
33
  M extends AnyMySqlTable,
36
34
  T extends AnyMySqlTable,
37
35
  B extends AnyMySqlTable,
@@ -44,7 +42,7 @@ export const makeMySqlPasswordPreparedPersistenceServices = <
44
42
  PCr extends AnyMySqlTable = AnyMySqlTable,
45
43
  PNativeId = unknown,
46
44
  >(
47
- mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, RS, CE, M, T, B, NativeId>,
45
+ mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, M, T, B, NativeId>,
48
46
  proofMapping?: PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>,
49
47
  ) =>
50
48
  Effect.flatMap(
@@ -64,8 +62,6 @@ export function coordinateMySqlPasswordPreparedPersistence<
64
62
  C extends AnyMySqlTable,
65
63
  AC extends AnyMySqlTable,
66
64
  A extends AnyMySqlTable,
67
- RS extends AnyMySqlTable,
68
- CE extends AnyMySqlTable,
69
65
  M extends AnyMySqlTable,
70
66
  T extends AnyMySqlTable,
71
67
  B extends AnyMySqlTable,
@@ -85,7 +81,7 @@ export function coordinateMySqlPasswordPreparedPersistence<
85
81
  >(
86
82
  acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,
87
83
  options: {
88
- readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, RS, CE, M, T, B, NativeId>;
84
+ readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, M, T, B, NativeId>;
89
85
  readonly proofMapping?:
90
86
  | PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>
91
87
  | undefined;
@@ -107,8 +103,6 @@ export function coordinateMySqlPasswordPreparedPersistence<
107
103
  C extends AnyMySqlTable,
108
104
  AC extends AnyMySqlTable,
109
105
  A extends AnyMySqlTable,
110
- RS extends AnyMySqlTable,
111
- CE extends AnyMySqlTable,
112
106
  M extends AnyMySqlTable,
113
107
  T extends AnyMySqlTable,
114
108
  B extends AnyMySqlTable,
@@ -130,7 +124,7 @@ export function coordinateMySqlPasswordPreparedPersistence<
130
124
  >(
131
125
  acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,
132
126
  options: {
133
- readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, RS, CE, M, T, B, NativeId>;
127
+ readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, M, T, B, NativeId>;
134
128
  readonly proofMapping?:
135
129
  | PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>
136
130
  | undefined;
@@ -152,8 +146,6 @@ export function coordinateMySqlPasswordPreparedPersistence<
152
146
  C extends AnyMySqlTable,
153
147
  AC extends AnyMySqlTable,
154
148
  A extends AnyMySqlTable,
155
- RS extends AnyMySqlTable,
156
- CE extends AnyMySqlTable,
157
149
  M extends AnyMySqlTable,
158
150
  T extends AnyMySqlTable,
159
151
  B extends AnyMySqlTable,
@@ -175,7 +167,7 @@ export function coordinateMySqlPasswordPreparedPersistence<
175
167
  >(
176
168
  acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,
177
169
  options: {
178
- readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, RS, CE, M, T, B, NativeId>;
170
+ readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, M, T, B, NativeId>;
179
171
  readonly proofMapping?:
180
172
  | PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>
181
173
  | undefined;
@@ -56,11 +56,9 @@ type Mapping<
56
56
  C extends AnyMySqlTable,
57
57
  AC extends AnyMySqlTable,
58
58
  A extends AnyMySqlTable,
59
- RS extends AnyMySqlTable,
60
- CE extends AnyMySqlTable,
61
59
  M extends AnyMySqlTable,
62
60
  NativeId,
63
- > = PasswordPersistenceMapping<S, I, C, AC, A, RS, CE, M, NativeId>;
61
+ > = PasswordPersistenceMapping<S, I, C, AC, A, M, NativeId>;
64
62
 
65
63
  export const makeMysqlPasswordPersistenceServices = <
66
64
  S extends AnyMySqlTable,
@@ -68,12 +66,10 @@ export const makeMysqlPasswordPersistenceServices = <
68
66
  C extends AnyMySqlTable,
69
67
  AC extends AnyMySqlTable,
70
68
  A extends AnyMySqlTable,
71
- RS extends AnyMySqlTable,
72
- CE extends AnyMySqlTable,
73
69
  M extends AnyMySqlTable,
74
70
  NativeId,
75
71
  >(
76
- mapping: Mapping<S, I, C, AC, A, RS, CE, M, NativeId>,
72
+ mapping: Mapping<S, I, C, AC, A, M, NativeId>,
77
73
  proofMapping?: ProofPersistenceMapping<
78
74
  any,
79
75
  any,
@@ -104,8 +100,6 @@ export function coordinateMysqlPasswordPersistence<
104
100
  C extends AnyMySqlTable,
105
101
  AC extends AnyMySqlTable,
106
102
  A extends AnyMySqlTable,
107
- RS extends AnyMySqlTable,
108
- CE extends AnyMySqlTable,
109
103
  M extends AnyMySqlTable,
110
104
  NativeId,
111
105
  PM extends
@@ -119,7 +113,7 @@ export function coordinateMysqlPasswordPersistence<
119
113
  >(
120
114
  acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,
121
115
  options: {
122
- readonly mapping: Mapping<S, I, C, AC, A, RS, CE, M, NativeId>;
116
+ readonly mapping: Mapping<S, I, C, AC, A, M, NativeId>;
123
117
  readonly proofMapping?: PM;
124
118
  readonly transaction?: never;
125
119
  },
@@ -137,8 +131,6 @@ export function coordinateMysqlPasswordPersistence<
137
131
  C extends AnyMySqlTable,
138
132
  AC extends AnyMySqlTable,
139
133
  A extends AnyMySqlTable,
140
- RS extends AnyMySqlTable,
141
- CE extends AnyMySqlTable,
142
134
  M extends AnyMySqlTable,
143
135
  NativeId,
144
136
  PM extends
@@ -154,7 +146,7 @@ export function coordinateMysqlPasswordPersistence<
154
146
  >(
155
147
  acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,
156
148
  options: {
157
- readonly mapping: Mapping<S, I, C, AC, A, RS, CE, M, NativeId>;
149
+ readonly mapping: Mapping<S, I, C, AC, A, M, NativeId>;
158
150
  readonly proofMapping?: PM;
159
151
  readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;
160
152
  },
@@ -172,8 +164,6 @@ export function coordinateMysqlPasswordPersistence<
172
164
  C extends AnyMySqlTable,
173
165
  AC extends AnyMySqlTable,
174
166
  A extends AnyMySqlTable,
175
- RS extends AnyMySqlTable,
176
- CE extends AnyMySqlTable,
177
167
  M extends AnyMySqlTable,
178
168
  NativeId,
179
169
  PM extends
@@ -189,7 +179,7 @@ export function coordinateMysqlPasswordPersistence<
189
179
  >(
190
180
  acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,
191
181
  options: {
192
- readonly mapping: Mapping<S, I, C, AC, A, RS, CE, M, NativeId>;
182
+ readonly mapping: Mapping<S, I, C, AC, A, M, NativeId>;
193
183
  readonly proofMapping?: PM;
194
184
  readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<D>>, TxShape>;
195
185
  },
@@ -0,0 +1,229 @@
1
+ import {
2
+ PersistenceMappingError,
3
+ makeNativeSqlTables,
4
+ nativeSqlAlias,
5
+ type NativeSqlTables,
6
+ type SqlTable,
7
+ } from "@yielded/auth-persistence/Adapter";
8
+ import {
9
+ getTableColumns,
10
+ is,
11
+ Param,
12
+ Placeholder,
13
+ type SQL,
14
+ Table,
15
+ sql,
16
+ type BuildQueryConfig,
17
+ type SQLWrapper,
18
+ } from "drizzle-orm";
19
+ import { Predicate } from "effect";
20
+ import type { SqlClient } from "effect/sql/SqlClient";
21
+ import * as Statement from "effect/sql/Statement";
22
+
23
+ type CapturedDialect = Pick<BuildQueryConfig, "escapeName" | "escapeString" | "codecs">;
24
+
25
+ /** Foreign compiler boundary only: builders are used to materialize SQL, never
26
+ * executed. The select builder exposes the original dialect even through the
27
+ * Durable Object database projection, which retains bound query methods. */
28
+ interface CapturedDatabase {
29
+ readonly select: () => { readonly dialect: CapturedDialect };
30
+ readonly insert: (table: Table) => {
31
+ readonly values: (values: Record<string, unknown>) => SQLWrapper;
32
+ };
33
+ readonly update: (table: Table) => {
34
+ readonly set: (values: Record<string, unknown>) => SQLWrapper;
35
+ };
36
+ }
37
+
38
+ const invalid = (cause: string): never => {
39
+ throw PersistenceMappingError.make({ operation: "mapping", cause });
40
+ };
41
+
42
+ const capture = (
43
+ database: object,
44
+ ): { readonly database: CapturedDatabase; readonly dialect: CapturedDialect } => {
45
+ if (
46
+ !Predicate.hasProperty(database, "select") ||
47
+ typeof database.select !== "function" ||
48
+ !Predicate.hasProperty(database, "insert") ||
49
+ typeof database.insert !== "function" ||
50
+ !Predicate.hasProperty(database, "update") ||
51
+ typeof database.update !== "function"
52
+ )
53
+ return invalid("Expected a captured Drizzle database");
54
+
55
+ const selection: unknown = database.select();
56
+
57
+ if (!Predicate.hasProperty(selection, "dialect"))
58
+ return invalid("Expected a captured Drizzle dialect");
59
+ const dialect = selection.dialect;
60
+
61
+ if (
62
+ !Predicate.hasProperty(dialect, "escapeName") ||
63
+ typeof dialect.escapeName !== "function" ||
64
+ !Predicate.hasProperty(dialect, "escapeString") ||
65
+ typeof dialect.escapeString !== "function"
66
+ )
67
+ return invalid("Expected Drizzle dialect escaping methods");
68
+
69
+ if (
70
+ Predicate.hasProperty(dialect, "codecs") &&
71
+ dialect.codecs !== undefined &&
72
+ (!Predicate.hasProperty(dialect.codecs, "apply") || typeof dialect.codecs.apply !== "function")
73
+ )
74
+ return invalid("Expected Drizzle dialect codecs");
75
+
76
+ // Drizzle's private dialect and generic query builders are erased only here.
77
+ return { database: database as CapturedDatabase, dialect: dialect as CapturedDialect };
78
+ };
79
+
80
+ const compileWith =
81
+ (dialect: CapturedDialect) =>
82
+ (expression: SQL): Statement.Fragment => {
83
+ const slots: string[] = [];
84
+
85
+ const query = expression.toQuery({
86
+ escapeName: (name) => {
87
+ if (name.includes("\0")) return invalid("NUL in SQL identifier");
88
+
89
+ return dialect.escapeName(name);
90
+ },
91
+ escapeString: (value) => {
92
+ if (value.includes("\0")) return invalid("NUL in SQL literal");
93
+
94
+ return dialect.escapeString(value);
95
+ },
96
+ escapeParam: (index) => {
97
+ if (index !== slots.length) return invalid("Invalid Drizzle parameter order");
98
+ const slot = `yielded_parameter_${index}`;
99
+
100
+ slots.push(slot);
101
+
102
+ return `\0${slot}\0`;
103
+ },
104
+ ...(dialect.codecs === undefined ? {} : { codecs: dialect.codecs }),
105
+ });
106
+
107
+ // Only compiler-emitted slots are translated. Native Statement parameters
108
+ // receive their final positions when composed; SQL literals containing $1 or
109
+ // ? are never inspected or rewritten. NUL is reserved for this compilation.
110
+ const parts = query.sql.split("\0");
111
+
112
+ if (parts.length !== slots.length * 2 + 1 || query.params.length !== slots.length)
113
+ return invalid("NUL or parameter marker collision in Drizzle SQL");
114
+
115
+ const segments: Statement.Segment[] = [];
116
+ const consumed = new Set<number>();
117
+
118
+ for (let offset = 0; offset < parts.length; offset += 2) {
119
+ segments.push(Statement.literal(parts[offset]));
120
+ if (offset + 1 === parts.length) break;
121
+ const index = slots.indexOf(parts[offset + 1]);
122
+
123
+ if (index < 0 || consumed.has(index))
124
+ return invalid("NUL or parameter marker collision in Drizzle SQL");
125
+ consumed.add(index);
126
+ const value: unknown = query.params[index];
127
+
128
+ if (is(value, Placeholder) || is(value, Param)) return invalid("Unbound Drizzle placeholder");
129
+ if (Statement.isFragment(value)) segments.push(...value.segments);
130
+ else segments.push(Statement.parameter(value));
131
+ }
132
+
133
+ return Statement.fragment(segments);
134
+ };
135
+
136
+ /** Preserve native Statement expressions in writes without applying a column
137
+ * codec to them. Ordinary values still pass through Drizzle's own builders. */
138
+ const writeValues = (values: Readonly<Record<string, unknown>>) =>
139
+ Object.fromEntries(
140
+ Object.entries(values).map(([key, value]) => [
141
+ key,
142
+ Statement.isFragment(value) ? sql`${sql.param(value)}` : value,
143
+ ]),
144
+ );
145
+
146
+ /** Capture the root database's compiler, not a later transaction object's
147
+ * client. Call insert/update inside the operation to materialize hooks once. */
148
+ export const makeDrizzleSqlTables = (
149
+ client: SqlClient,
150
+ capturedDatabase: object,
151
+ ): NativeSqlTables => {
152
+ const { database, dialect } = capture(capturedDatabase);
153
+ const compile = compileWith(dialect);
154
+
155
+ return makeNativeSqlTables(client, (_client, physical): SqlTable => {
156
+ if (!is(physical, Table)) return invalid("Expected a Drizzle table");
157
+ const columns = getTableColumns(physical);
158
+ const entries = Object.entries(columns);
159
+
160
+ const getColumn = (key: string) => {
161
+ const column = Object.hasOwn(columns, key) ? columns[key] : undefined;
162
+
163
+ if (column === undefined) return invalid("Missing Drizzle column");
164
+
165
+ return column;
166
+ };
167
+
168
+ const bind = (alias?: string): SqlTable => {
169
+ const reference = (key: string) => {
170
+ const column = getColumn(key);
171
+
172
+ return alias === undefined
173
+ ? sql`${column}`
174
+ : sql`${sql.identifier(alias)}.${sql.identifier(column.name)}`;
175
+ };
176
+
177
+ return {
178
+ name: compile(
179
+ alias === undefined ? sql`${physical}` : sql`${physical} AS ${sql.identifier(alias)}`,
180
+ ),
181
+ as: bind,
182
+ column: (key) => compile(reference(key)),
183
+ fields: (prefix) =>
184
+ compile(
185
+ sql.join(
186
+ entries.map(([key, column], index) => {
187
+ const selection =
188
+ dialect.codecs === undefined
189
+ ? reference(key)
190
+ : dialect.codecs.apply(column, "cast", reference(key));
191
+
192
+ return sql`${selection} as ${sql.identifier(nativeSqlAlias(prefix, index))}`;
193
+ }),
194
+ sql`, `,
195
+ ),
196
+ ),
197
+ decode: (row, prefix) =>
198
+ Object.fromEntries(
199
+ entries.map(([key, column], index) => {
200
+ const alias = nativeSqlAlias(prefix, index);
201
+
202
+ if (!Object.hasOwn(row, alias)) return invalid("Missing SQL projection field");
203
+ const value = row[alias];
204
+
205
+ return [
206
+ key,
207
+ value === null
208
+ ? null
209
+ : column.mapFromDriverValue(
210
+ dialect.codecs === undefined
211
+ ? value
212
+ : dialect.codecs.apply(column, "normalize", value),
213
+ ),
214
+ ];
215
+ }),
216
+ ),
217
+ value: (key, value) => {
218
+ const column = getColumn(key);
219
+
220
+ return Statement.isFragment(value) ? value : compile(sql`${sql.param(value, column)}`);
221
+ },
222
+ insert: (values) => compile(database.insert(physical).values(writeValues(values)).getSQL()),
223
+ update: (values) => compile(database.update(physical).set(writeValues(values)).getSQL()),
224
+ };
225
+ };
226
+
227
+ return bind();
228
+ });
229
+ };
@@ -6,8 +6,6 @@ import type { DrizzleTableModel } from "./table-model";
6
6
  export {
7
7
  type PasswordAttemptAction,
8
8
  type PasswordAttemptState,
9
- type PasswordRateScopeKind,
10
- type PasswordScopeKeys,
11
9
  type PasswordAttemptRecord,
12
10
  type RequiredPasswordConstraints,
13
11
  requiredPasswordConstraints,
@@ -51,14 +49,6 @@ export type PasswordAttemptTable<
51
49
  NativeSubjectId,
52
50
  > = Shared.PasswordAttemptTable<DrizzleTableModel<Attempt>, NativeSubjectId>;
53
51
 
54
- export type PasswordRateScopeTable<RateScope extends Table> = Shared.PasswordRateScopeTable<
55
- DrizzleTableModel<RateScope>
56
- >;
57
-
58
- export type PasswordChargeTable<Charge extends Table> = Shared.PasswordChargeTable<
59
- DrizzleTableModel<Charge>
60
- >;
61
-
62
52
  export type PasswordCommandTable<Command extends Table> = Shared.PasswordCommandTable<
63
53
  DrizzleTableModel<Command>
64
54
  >;
@@ -71,8 +61,6 @@ export type PasswordPersistenceMapping<
71
61
  Credential extends Table,
72
62
  AuthorityCredential extends Table,
73
63
  Attempt extends Table,
74
- RateScope extends Table,
75
- Charge extends Table,
76
64
  Command extends Table,
77
65
  NativeSubjectId,
78
66
  > = Shared.PasswordPersistenceMapping<
@@ -81,8 +69,6 @@ export type PasswordPersistenceMapping<
81
69
  DrizzleTableModel<Credential>,
82
70
  DrizzleTableModel<AuthorityCredential>,
83
71
  DrizzleTableModel<Attempt>,
84
- DrizzleTableModel<RateScope>,
85
- DrizzleTableModel<Charge>,
86
72
  DrizzleTableModel<Command>,
87
73
  NativeSubjectId,
88
74
  SQL
@@ -94,8 +80,6 @@ export type D1PasswordPersistenceMapping<
94
80
  Credential extends Table,
95
81
  AuthorityCredential extends Table,
96
82
  Attempt extends Table,
97
- RateScope extends Table,
98
- Charge extends Table,
99
83
  Command extends Table,
100
84
  NativeSubjectId,
101
85
  > = Shared.D1PasswordPersistenceMapping<
@@ -104,8 +88,6 @@ export type D1PasswordPersistenceMapping<
104
88
  DrizzleTableModel<Credential>,
105
89
  DrizzleTableModel<AuthorityCredential>,
106
90
  DrizzleTableModel<Attempt>,
107
- DrizzleTableModel<RateScope>,
108
- DrizzleTableModel<Charge>,
109
91
  DrizzleTableModel<Command>,
110
92
  NativeSubjectId,
111
93
  SQL
@@ -153,8 +135,6 @@ export type AnyPasswordPersistenceMapping = PasswordPersistenceMapping<
153
135
  Table,
154
136
  Table,
155
137
  Table,
156
- Table,
157
- Table,
158
138
  unknown
159
139
  >;
160
140
 
@@ -87,8 +87,6 @@ export interface PasswordPreparedPersistenceMapping<
87
87
  Credential extends Table,
88
88
  AuthorityCredential extends Table,
89
89
  Attempt extends Table,
90
- RateScope extends Table,
91
- Charge extends Table,
92
90
  Command extends Table,
93
91
  Intent extends Table,
94
92
  Admission extends Table,
@@ -100,8 +98,6 @@ export interface PasswordPreparedPersistenceMapping<
100
98
  Credential,
101
99
  AuthorityCredential,
102
100
  Attempt,
103
- RateScope,
104
- Charge,
105
101
  Command,
106
102
  NativeSubjectId
107
103
  >;
@@ -119,8 +115,6 @@ export type D1PasswordPreparedPersistenceMapping<
119
115
  Credential extends Table,
120
116
  AuthorityCredential extends Table,
121
117
  Attempt extends Table,
122
- RateScope extends Table,
123
- Charge extends Table,
124
118
  Command extends Table,
125
119
  Intent extends Table,
126
120
  Admission extends Table,
@@ -131,8 +125,6 @@ export type D1PasswordPreparedPersistenceMapping<
131
125
  Credential,
132
126
  AuthorityCredential,
133
127
  Attempt,
134
- RateScope,
135
- Charge,
136
128
  Command,
137
129
  Intent,
138
130
  Admission,
@@ -146,8 +138,6 @@ export type D1PasswordPreparedPersistenceMapping<
146
138
  Credential,
147
139
  AuthorityCredential,
148
140
  Attempt,
149
- RateScope,
150
- Charge,
151
141
  Command,
152
142
  NativeSubjectId
153
143
  >;
@@ -253,7 +243,5 @@ export type AnyPasswordPreparedPersistenceMapping = PasswordPreparedPersistenceM
253
243
  Table,
254
244
  Table,
255
245
  Table,
256
- Table,
257
- Table,
258
246
  unknown
259
247
  >;
@@ -1,13 +1,16 @@
1
1
  import { makePasswordKernel } from "@yielded/auth-persistence/Adapter";
2
2
 
3
+ import { makeDrizzleSqlTables } from "./native-sql-table";
3
4
  import { completeProofPlanIn } from "./proof-sql";
4
5
  import { drizzleQueryOperations } from "./query-operations";
5
6
  export type { PasswordSqlQuery } from "@yielded/auth-persistence/Adapter";
6
7
  export type { PasswordSqlDatabase } from "@yielded/auth-persistence/Adapter";
7
8
  export { CurrentPasswordSql } from "@yielded/auth-persistence/Adapter";
9
+
8
10
  export type { PasswordSqlConfiguration } from "@yielded/auth-persistence/Adapter";
9
11
 
10
12
  export const { makeSqlPasswordPersistence, passwordSqlKernel } = makePasswordKernel(
11
13
  drizzleQueryOperations,
12
14
  { completeProofPlanIn },
15
+ makeDrizzleSqlTables,
13
16
  );
@@ -1,4 +1,9 @@
1
- import type { NativeDatabase } from "@yielded/auth-persistence/Adapter";
1
+ import {
2
+ CurrentPasswordPreparedTransaction,
3
+ type NativeDatabase,
4
+ type PasswordPreparedPostcondition,
5
+ PasswordPreparedPostconditions,
6
+ } from "@yielded/auth-persistence/Adapter";
2
7
  import {
3
8
  coordinateCommit,
4
9
  hasCommitScope,
@@ -7,7 +12,7 @@ import {
7
12
  } from "@yielded/auth/Hooks";
8
13
  import { PasswordUnavailable, PasswordPersistence } from "@yielded/auth/Password";
9
14
  /* oxlint-disable no-explicit-any -- public driver wrappers restore concrete Drizzle generics. */
10
- import { type Context, Effect, Layer } from "effect";
15
+ import { Cause, type Context, Effect, Layer } from "effect";
11
16
  import type * as SqlError from "effect/sql/SqlError";
12
17
 
13
18
  import {
@@ -154,7 +159,10 @@ export const coordinateTargetPasswordPersistence = <Transaction, A, E, R>(
154
159
  () =>
155
160
  database.transaction((transaction) =>
156
161
  Effect.gen(function* () {
157
- return yield* owner(transaction, {
162
+ const postconditions: Array<PasswordPreparedPostcondition> = [];
163
+ let acceptingPostconditions = true;
164
+
165
+ const value = yield* owner(transaction, {
158
166
  passwordPersistence: yield* makeSqlPasswordPersistence(
159
167
  mapping,
160
168
  passwordOptions(configuration, proofMapping, true),
@@ -164,7 +172,36 @@ export const coordinateTargetPasswordPersistence = <Transaction, A, E, R>(
164
172
  transaction as unknown as PasswordSqlDatabase,
165
173
  ),
166
174
  ),
167
- });
175
+ }).pipe(
176
+ Effect.provideService(PasswordPreparedPostconditions, {
177
+ register: (check) => {
178
+ if (!acceptingPostconditions) return false;
179
+ postconditions.push(check);
180
+
181
+ return true;
182
+ },
183
+ }),
184
+ Effect.ensuring(
185
+ Effect.sync(() => {
186
+ acceptingPostconditions = false;
187
+ }),
188
+ ),
189
+ );
190
+
191
+ // Application work in this transaction must not change what the
192
+ // password mutations committed to; a failure here rolls back both.
193
+ for (const check of postconditions)
194
+ yield* check.pipe(
195
+ Effect.provideService(
196
+ CurrentPasswordPreparedTransaction,
197
+ transaction as unknown as PasswordSqlDatabase,
198
+ ),
199
+ Effect.catchCause((cause) =>
200
+ Effect.failCause(Cause.map(cause, () => PasswordUnavailable.make({}))),
201
+ ),
202
+ );
203
+
204
+ return value;
168
205
  }),
169
206
  ),
170
207
  { mode: configuration.mode },
@@ -31,8 +31,6 @@ export const makePgPasswordPreparedPersistenceServices = <
31
31
  C extends AnyPgTable,
32
32
  AC extends AnyPgTable,
33
33
  A extends AnyPgTable,
34
- RS extends AnyPgTable,
35
- CE extends AnyPgTable,
36
34
  M extends AnyPgTable,
37
35
  T extends AnyPgTable,
38
36
  B extends AnyPgTable,
@@ -45,7 +43,7 @@ export const makePgPasswordPreparedPersistenceServices = <
45
43
  PCr extends AnyPgTable = AnyPgTable,
46
44
  PNativeId = unknown,
47
45
  >(
48
- mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, RS, CE, M, T, B, NativeId>,
46
+ mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, M, T, B, NativeId>,
49
47
  proofMapping?: PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>,
50
48
  ) =>
51
49
  Effect.flatMap(
@@ -65,8 +63,6 @@ export function coordinatePgPasswordPreparedPersistence<
65
63
  C extends AnyPgTable,
66
64
  AC extends AnyPgTable,
67
65
  A extends AnyPgTable,
68
- RS extends AnyPgTable,
69
- CE extends AnyPgTable,
70
66
  M extends AnyPgTable,
71
67
  T extends AnyPgTable,
72
68
  B extends AnyPgTable,
@@ -86,7 +82,7 @@ export function coordinatePgPasswordPreparedPersistence<
86
82
  >(
87
83
  acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,
88
84
  options: {
89
- readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, RS, CE, M, T, B, NativeId>;
85
+ readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, M, T, B, NativeId>;
90
86
  readonly proofMapping?:
91
87
  | PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>
92
88
  | undefined;
@@ -108,8 +104,6 @@ export function coordinatePgPasswordPreparedPersistence<
108
104
  C extends AnyPgTable,
109
105
  AC extends AnyPgTable,
110
106
  A extends AnyPgTable,
111
- RS extends AnyPgTable,
112
- CE extends AnyPgTable,
113
107
  M extends AnyPgTable,
114
108
  T extends AnyPgTable,
115
109
  B extends AnyPgTable,
@@ -131,7 +125,7 @@ export function coordinatePgPasswordPreparedPersistence<
131
125
  >(
132
126
  acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,
133
127
  options: {
134
- readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, RS, CE, M, T, B, NativeId>;
128
+ readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, M, T, B, NativeId>;
135
129
  readonly proofMapping?:
136
130
  | PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>
137
131
  | undefined;
@@ -153,8 +147,6 @@ export function coordinatePgPasswordPreparedPersistence<
153
147
  C extends AnyPgTable,
154
148
  AC extends AnyPgTable,
155
149
  A extends AnyPgTable,
156
- RS extends AnyPgTable,
157
- CE extends AnyPgTable,
158
150
  M extends AnyPgTable,
159
151
  T extends AnyPgTable,
160
152
  B extends AnyPgTable,
@@ -176,7 +168,7 @@ export function coordinatePgPasswordPreparedPersistence<
176
168
  >(
177
169
  acquire: Effect.Effect<D, DatabaseError, DatabaseRequirements>,
178
170
  options: {
179
- readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, RS, CE, M, T, B, NativeId>;
171
+ readonly mapping: PasswordPreparedPersistenceMapping<S, I, C, AC, A, M, T, B, NativeId>;
180
172
  readonly proofMapping?:
181
173
  | PasswordPreparedProofMapping<PS, PC, PM, PSub, PI, PCr, PNativeId>
182
174
  | undefined;