@yielded/auth-persistence-drizzle 0.1.0-beta.17 → 0.1.0-beta.19

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 (142) hide show
  1. package/README.md +8 -1
  2. package/dist/D1.d.mts +120 -120
  3. package/dist/Libsql.d.mts +154 -154
  4. package/dist/Mysql2.d.mts +166 -166
  5. package/dist/Pglite.d.mts +166 -166
  6. package/dist/Postgres.d.mts +152 -152
  7. package/dist/SqliteBun.d.mts +168 -168
  8. package/dist/SqliteDo.d.mts +237 -259
  9. package/dist/SqliteDo.mjs +30 -45
  10. package/dist/SqliteDo.mjs.map +1 -1
  11. package/dist/SqliteNode.d.mts +154 -154
  12. package/dist/SqliteWasm.d.mts +163 -163
  13. package/dist/drizzle/crypto.mjs +11 -0
  14. package/dist/drizzle/crypto.mjs.map +1 -0
  15. package/dist/drizzle/d1-identity.mjs +2 -2
  16. package/dist/drizzle/d1-identity.mjs.map +1 -1
  17. package/dist/drizzle/d1-oauth.d.mts +16 -16
  18. package/dist/drizzle/d1-oauth.mjs.map +1 -1
  19. package/dist/drizzle/d1-passkey.d.mts +6 -6
  20. package/dist/drizzle/d1-passkey.mjs.map +1 -1
  21. package/dist/drizzle/d1-password-prepared.mjs +3 -3
  22. package/dist/drizzle/d1-password-prepared.mjs.map +1 -1
  23. package/dist/drizzle/d1-passwords.d.mts +1 -1
  24. package/dist/drizzle/d1-passwords.mjs +1 -1
  25. package/dist/drizzle/d1-passwords.mjs.map +1 -1
  26. package/dist/drizzle/d1-phone.d.mts +3 -3
  27. package/dist/drizzle/d1-phone.mjs.map +1 -1
  28. package/dist/drizzle/d1-proofs.d.mts +1 -1
  29. package/dist/drizzle/d1-sessions.d.mts +1 -1
  30. package/dist/drizzle/d1-sessions.mjs +4 -3
  31. package/dist/drizzle/d1-sessions.mjs.map +1 -1
  32. package/dist/drizzle/d1-totp.d.mts +3 -3
  33. package/dist/drizzle/d1-totp.mjs.map +1 -1
  34. package/dist/drizzle/mysql-identity.mjs +2 -2
  35. package/dist/drizzle/mysql-identity.mjs.map +1 -1
  36. package/dist/drizzle/oauth-accounts.mjs +9 -8
  37. package/dist/drizzle/oauth-accounts.mjs.map +1 -1
  38. package/dist/drizzle/oauth-connected-collection.mjs +1 -1
  39. package/dist/drizzle/oauth-connected-collection.mjs.map +1 -1
  40. package/dist/drizzle/oauth-connected-custody.mjs +5 -4
  41. package/dist/drizzle/oauth-connected-custody.mjs.map +1 -1
  42. package/dist/drizzle/oauth-connected-drivers.mjs.map +1 -1
  43. package/dist/drizzle/oauth-connected-flow.mjs +8 -7
  44. package/dist/drizzle/oauth-connected-flow.mjs.map +1 -1
  45. package/dist/drizzle/oauth-connected-management.mjs +3 -2
  46. package/dist/drizzle/oauth-connected-management.mjs.map +1 -1
  47. package/dist/drizzle/oauth-connected-reference.mjs +8 -4
  48. package/dist/drizzle/oauth-connected-reference.mjs.map +1 -1
  49. package/dist/drizzle/oauth-connected-settlement.mjs +4 -4
  50. package/dist/drizzle/oauth-connected-settlement.mjs.map +1 -1
  51. package/dist/drizzle/oauth-connected-sign-in.mjs +11 -10
  52. package/dist/drizzle/oauth-connected-sign-in.mjs.map +1 -1
  53. package/dist/drizzle/oauth-connected-state.d.mts +265 -265
  54. package/dist/drizzle/oauth-connected-state.mjs +23 -20
  55. package/dist/drizzle/oauth-connected-state.mjs.map +1 -1
  56. package/dist/drizzle/oauth-connected-target.d.mts +105 -105
  57. package/dist/drizzle/oauth-connected-target.mjs.map +1 -1
  58. package/dist/drizzle/oauth-drivers.mjs.map +1 -1
  59. package/dist/drizzle/oauth-flow.mjs +1 -1
  60. package/dist/drizzle/oauth-flow.mjs.map +1 -1
  61. package/dist/drizzle/oauth-model.d.mts +4 -4
  62. package/dist/drizzle/oauth-model.mjs.map +1 -1
  63. package/dist/drizzle/oauth-registration.mjs +2 -2
  64. package/dist/drizzle/oauth-registration.mjs.map +1 -1
  65. package/dist/drizzle/oauth-state.mjs +11 -12
  66. package/dist/drizzle/oauth-state.mjs.map +1 -1
  67. package/dist/drizzle/oauth-target.d.mts +4 -4
  68. package/dist/drizzle/oauth-target.mjs.map +1 -1
  69. package/dist/drizzle/passkey-drivers.mjs.map +1 -1
  70. package/dist/drizzle/passkey-write-drivers.mjs.map +1 -1
  71. package/dist/drizzle/passkey-write-target.d.mts +1 -1
  72. package/dist/drizzle/password-prepared-sql.mjs +1 -1
  73. package/dist/drizzle/password-prepared-sql.mjs.map +1 -1
  74. package/dist/drizzle/password-prepared-state.mjs +1 -1
  75. package/dist/drizzle/pg-identity.mjs +2 -2
  76. package/dist/drizzle/pg-identity.mjs.map +1 -1
  77. package/dist/drizzle/phone-model.d.mts +2 -2
  78. package/dist/drizzle/phone-model.mjs +3 -3
  79. package/dist/drizzle/phone-model.mjs.map +1 -1
  80. package/dist/drizzle/phone-target.d.mts +1 -1
  81. package/dist/drizzle/phone-target.mjs +2 -2
  82. package/dist/drizzle/phone-target.mjs.map +1 -1
  83. package/dist/drizzle/sqlite-do-database.d.mts +29 -0
  84. package/dist/drizzle/sqlite-do-database.mjs +45 -0
  85. package/dist/drizzle/sqlite-do-database.mjs.map +1 -0
  86. package/dist/drizzle/sqlite-emails.mjs.map +1 -1
  87. package/dist/drizzle/sqlite-identity.mjs +2 -2
  88. package/dist/drizzle/sqlite-identity.mjs.map +1 -1
  89. package/dist/drizzle/sqlite-passwords.mjs.map +1 -1
  90. package/dist/drizzle/sqlite-proofs.mjs.map +1 -1
  91. package/dist/drizzle/sqlite-sessions.mjs.map +1 -1
  92. package/dist/drizzle/storage-validation.mjs +17 -9
  93. package/dist/drizzle/storage-validation.mjs.map +1 -1
  94. package/dist/drizzle/totp-state.mjs +8 -8
  95. package/dist/drizzle/totp-state.mjs.map +1 -1
  96. package/dist/drizzle/totp-target.d.mts +1 -1
  97. package/dist/drizzle/totp-target.mjs +2 -2
  98. package/dist/drizzle/totp-target.mjs.map +1 -1
  99. package/package.json +1 -1
  100. package/src/SqliteDo.ts +63 -70
  101. package/src/drizzle/crypto.ts +14 -0
  102. package/src/drizzle/d1-identity.ts +2 -2
  103. package/src/drizzle/d1-oauth.ts +14 -5
  104. package/src/drizzle/d1-passkey.ts +5 -1
  105. package/src/drizzle/d1-password-prepared.ts +11 -5
  106. package/src/drizzle/d1-passwords.ts +1 -1
  107. package/src/drizzle/d1-phone.ts +2 -1
  108. package/src/drizzle/d1-sessions.ts +8 -2
  109. package/src/drizzle/d1-totp.ts +6 -2
  110. package/src/drizzle/mysql-identity.ts +2 -2
  111. package/src/drizzle/oauth-accounts.ts +14 -13
  112. package/src/drizzle/oauth-connected-collection.ts +1 -1
  113. package/src/drizzle/oauth-connected-custody.ts +8 -6
  114. package/src/drizzle/oauth-connected-drivers.ts +9 -3
  115. package/src/drizzle/oauth-connected-flow.ts +6 -6
  116. package/src/drizzle/oauth-connected-management.ts +1 -1
  117. package/src/drizzle/oauth-connected-reference.ts +14 -9
  118. package/src/drizzle/oauth-connected-settlement.ts +4 -4
  119. package/src/drizzle/oauth-connected-sign-in.ts +11 -10
  120. package/src/drizzle/oauth-connected-state.ts +40 -25
  121. package/src/drizzle/oauth-connected-target.ts +9 -5
  122. package/src/drizzle/oauth-drivers.ts +13 -5
  123. package/src/drizzle/oauth-flow.ts +1 -1
  124. package/src/drizzle/oauth-model.ts +4 -4
  125. package/src/drizzle/oauth-registration.ts +2 -2
  126. package/src/drizzle/oauth-state.ts +17 -15
  127. package/src/drizzle/oauth-target.ts +11 -3
  128. package/src/drizzle/passkey-drivers.ts +7 -3
  129. package/src/drizzle/passkey-write-drivers.ts +11 -2
  130. package/src/drizzle/password-prepared-sql.ts +1 -1
  131. package/src/drizzle/pg-identity.ts +2 -2
  132. package/src/drizzle/phone-model.ts +3 -3
  133. package/src/drizzle/phone-target.ts +11 -4
  134. package/src/drizzle/sqlite-do-database.ts +87 -0
  135. package/src/drizzle/sqlite-emails.ts +1 -1
  136. package/src/drizzle/sqlite-identity.ts +2 -2
  137. package/src/drizzle/sqlite-passwords.ts +1 -1
  138. package/src/drizzle/sqlite-proofs.ts +2 -2
  139. package/src/drizzle/sqlite-sessions.ts +2 -2
  140. package/src/drizzle/storage-validation.ts +15 -6
  141. package/src/drizzle/totp-state.ts +8 -8
  142. package/src/drizzle/totp-target.ts +11 -5
@@ -1 +1 @@
1
- {"version":3,"file":"totp-target.mjs","names":[],"sources":["../../src/drizzle/totp-target.ts"],"sourcesContent":["import { randomId } from \"@yielded/auth-crypto\";\nimport { NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport {\n TotpConfigurationError,\n type TotpUnavailable,\n TotpMutation,\n TotpPolicy,\n TotpPersistence,\n} from \"@yielded/auth/Totp\";\nimport type { Table } from \"drizzle-orm\";\n/* oxlint-disable no-explicit-any -- shared native implementation; driver entrypoints retain exact database and table types. */\nimport { Context, Effect, Schema } from \"effect\";\nimport type { Statement } from \"effect/sql/Statement\";\n\nimport type { PersistenceMappingError } from \"./model\";\nimport { nativeDatabase } from \"./native-database\";\nimport { validateDrizzleStorage } from \"./storage-validation\";\nimport type { SuppliedService } from \"./SuppliedService\";\nimport {\n type TotpMapping,\n type TotpMappingSource,\n type TotpPersistenceServices,\n requiredTotpConstraints,\n} from \"./totp-model\";\nimport {\n captureTotp,\n CurrentTotpTransaction,\n invariant,\n mutateTotp,\n unavailable,\n} from \"./totp-state\";\nimport {\n coordinateTransactionOwner,\n makeTransactionExecution,\n sqlClientTransactionStandaloneGuard,\n type TransactionExecution,\n type TransactionTargetConfiguration,\n type TransactionCoordinatorError,\n} from \"./transaction-execution\";\nimport type { TransactionNativeDatabase } from \"./transaction-owner\";\nexport type TotpTargetConfiguration = TransactionTargetConfiguration<TotpUnavailable>;\n\nexport type TotpCoordinatorError<E> =\n | TransactionCoordinatorError<E, TotpUnavailable>\n | TotpConfigurationError\n | PersistenceMappingError;\n\nexport const sqlClientTotpStandaloneGuard = (\n service: Parameters<typeof sqlClientTransactionStandaloneGuard>[1],\n) => sqlClientTransactionStandaloneGuard(unavailable, service);\n\nconst validateMapping = <M>(original: M, configuration: TotpTargetConfiguration): M => {\n const mapping = original as any;\n\n invariant(mapping.moduleId.length > 0);\n Schema.decodeSync(TotpPolicy)(mapping.policy);\n for (const [key, value] of Object.entries(requiredTotpConstraints))\n invariant(mapping.constraints?.[key] === value);\n if (configuration.mode === \"batch\") invariant(mapping.d1?.primary === true);\n\n return Object.freeze({\n ...mapping,\n policy: Object.freeze({ ...mapping.policy }),\n subject: Object.freeze({ ...mapping.subject }),\n factor: Object.freeze({ ...mapping.factor }),\n credential: Object.freeze({ ...mapping.credential }),\n subjectIds: Object.freeze({ ...mapping.subjectIds }),\n });\n};\n\nconst services = Effect.fnUntraced(function* (\n mapping: any,\n execution: TransactionExecution<TotpUnavailable, CurrentTotpTransaction>,\n): Effect.fn.Return<TotpPersistenceServices, never, LifecycleHooks> {\n const hooks = yield* LifecycleHooks;\n\n return {\n totpPersistence: TotpPersistence.of({\n snapshot: Effect.fn(\"TotpNative.snapshot\")(\n function* (input) {\n const captured = { ...input };\n\n invariant(captured.moduleId === mapping.moduleId);\n yield* execution.admit;\n\n return yield* execution\n .run(\n Effect.map(captureTotp(mapping, captured.subjectId), (value) => value?.snapshot),\n false,\n )\n .pipe(Effect.provideService(LifecycleHooks, hooks));\n },\n Effect.catchDefect(() => Effect.fail(unavailable())),\n ),\n mutate: (original, prepare) =>\n Effect.suspend(() => {\n // Detach caller-owned payloads before any driver or hook can suspend.\n const codec = Schema.toCodecIso(TotpMutation);\n const input = Schema.decodeSync(codec)(Schema.encodeSync(codec)(original));\n\n return execution.admit.pipe(\n Effect.andThen(\n execution.run(\n Effect.gen(function* () {\n const decision = yield* mutateTotp(mapping, input),\n owner = yield* CurrentTotpTransaction;\n\n owner.guards.push(owner.journal.prepare(undefined));\n const receipt = prepare(decision, owner.journal);\n\n invariant(receipt?._tag === \"PreparedCommit\" && Effect.isEffect(receipt.read));\n owner.guards.push(receipt as any);\n\n return receipt;\n }),\n ),\n ),\n Effect.provideService(LifecycleHooks, hooks),\n );\n }).pipe(Effect.catchDefect(() => Effect.fail(unavailable()))),\n }),\n };\n});\n\nexport const makeTargetTotpPersistence = <\n S extends Table,\n F extends Table,\n C extends Table,\n N,\n RSetup = never,\n>(\n source: TotpMappingSource<TotpMapping<S, F, C, N>, RSetup>,\n configuration: TotpTargetConfiguration,\n) =>\n Effect.gen(function* () {\n const original = yield* Effect.isEffect(source) ? source : Effect.succeed(source);\n\n const mapping = yield* Effect.try({\n try: () => validateMapping(original, configuration),\n catch: () => TotpConfigurationError.make({}),\n });\n\n yield* validateDrizzleStorage(mapping).pipe(\n Effect.mapError(() => TotpConfigurationError.make({})),\n );\n\n const execution = yield* makeTransactionExecution(\n CurrentTotpTransaction,\n configuration,\n unavailable,\n randomId,\n );\n\n return yield* services(mapping, execution);\n });\n\nexport const coordinateTargetTotp = <M, A, E, R, RSetup = never>(\n database: TransactionNativeDatabase,\n source: TotpMappingSource<M, RSetup>,\n configuration: TotpTargetConfiguration,\n body: (\n transaction: any,\n services: TotpPersistenceServices,\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n): Effect.Effect<A, TotpCoordinatorError<E>, R | RSetup | LifecycleHooks | NativeDatabase> =>\n Effect.gen(function* () {\n const original = yield* Effect.isEffect(source) ? source : Effect.succeed(source);\n\n const mapping = yield* Effect.try({\n try: () => validateMapping(original, configuration),\n catch: () => TotpConfigurationError.make({}),\n });\n\n yield* validateDrizzleStorage(mapping).pipe(\n Effect.mapError(() => TotpConfigurationError.make({})),\n );\n\n return yield* coordinateTransactionOwner(\n database,\n CurrentTotpTransaction,\n configuration,\n Effect.void,\n unavailable,\n randomId,\n (execution) => services(mapping, execution),\n (transaction, acquireServices, append) =>\n Effect.flatMap(acquireServices, (boundServices) =>\n body(transaction, boundServices, append),\n ),\n );\n });\n\ntype TransactionOf<D> = D extends { readonly transaction: (...args: any[]) => any }\n ? Parameters<Parameters<D[\"transaction\"]>[0]>[0]\n : never;\n\n/** Concrete driver wrappers select transaction mode; cryptography always precedes these owners. */\nexport const makeTotpTarget = <\n DatabaseId,\n D extends { readonly transaction: any },\n T extends Table,\n Extra = unknown,\n Synchronous extends boolean = false,\n>(\n databaseService: Context.Service<DatabaseId, D>,\n configuration: TotpTargetConfiguration,\n) => {\n function coordinateTotpPersistence<\n Database extends D,\n S extends T,\n F extends T,\n C extends T,\n N,\n A,\n E,\n R,\n RSetup = never,\n DatabaseError = never,\n DatabaseRequirements = never,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N> & Extra, RSetup>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TotpPersistence> : R>,\n ): Effect.Effect<\n A,\n TotpCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TotpPersistence>)\n | LifecycleHooks\n | RSetup\n | DatabaseRequirements\n >;\n function coordinateTotpPersistence<\n Database extends D,\n S extends T,\n F extends T,\n C extends T,\n N,\n A,\n E,\n R,\n TxId,\n TxShape,\n RSetup = never,\n DatabaseError = never,\n DatabaseRequirements = never,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N> & Extra, RSetup>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TotpPersistence | TxId> : R>,\n ): Effect.Effect<\n A,\n TotpCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TotpPersistence | TxId>)\n | LifecycleHooks\n | RSetup\n | DatabaseRequirements\n >;\n function coordinateTotpPersistence<\n Database extends D,\n S extends T,\n F extends T,\n C extends T,\n N,\n A,\n E,\n R,\n TxId,\n TxShape,\n RSetup = never,\n DatabaseError = never,\n DatabaseRequirements = never,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N> & Extra, RSetup>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n TotpCoordinatorError<E> | DatabaseError,\n Exclude<R, TotpPersistence> | LifecycleHooks | RSetup | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetTotp(\n database as any,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services,\n ): Effect.Effect<A, E, Exclude<R, TotpPersistence>> => {\n const provided = Context.make(TotpPersistence, services.totpPersistence);\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n\n return {\n makeTotpPersistenceServices: <S extends T, F extends T, C extends T, N, RSetup = never>(\n mapping: TotpMappingSource<TotpMapping<S, F, C, N> & Extra, RSetup>,\n ) =>\n makeTargetTotpPersistence(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateTotpPersistence,\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"totp-target.mjs","names":[],"sources":["../../src/drizzle/totp-target.ts"],"sourcesContent":["import { NativeDatabase } from \"@yielded/auth-persistence/Adapter\";\nimport { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport {\n TotpConfigurationError,\n type TotpUnavailable,\n TotpMutation,\n TotpPolicy,\n TotpPersistence,\n} from \"@yielded/auth/Totp\";\nimport type { Table } from \"drizzle-orm\";\n/* oxlint-disable no-explicit-any -- shared native implementation; driver entrypoints retain exact database and table types. */\nimport { type Crypto, Context, Effect, Schema } from \"effect\";\nimport type { Statement } from \"effect/sql/Statement\";\n\nimport { randomId } from \"./crypto\";\nimport type { PersistenceMappingError } from \"./model\";\nimport { nativeDatabase } from \"./native-database\";\nimport { validateDrizzleStorage } from \"./storage-validation\";\nimport type { SuppliedService } from \"./SuppliedService\";\nimport {\n type TotpMapping,\n type TotpMappingSource,\n type TotpPersistenceServices,\n requiredTotpConstraints,\n} from \"./totp-model\";\nimport {\n captureTotp,\n CurrentTotpTransaction,\n invariant,\n mutateTotp,\n unavailable,\n} from \"./totp-state\";\nimport {\n coordinateTransactionOwner,\n makeTransactionExecution,\n sqlClientTransactionStandaloneGuard,\n type TransactionExecution,\n type TransactionTargetConfiguration,\n type TransactionCoordinatorError,\n} from \"./transaction-execution\";\nimport type { TransactionNativeDatabase } from \"./transaction-owner\";\nexport type TotpTargetConfiguration = TransactionTargetConfiguration<TotpUnavailable>;\n\nexport type TotpCoordinatorError<E> =\n | TransactionCoordinatorError<E, TotpUnavailable>\n | TotpConfigurationError\n | PersistenceMappingError;\n\nexport const sqlClientTotpStandaloneGuard = (\n service: Parameters<typeof sqlClientTransactionStandaloneGuard>[1],\n) => sqlClientTransactionStandaloneGuard(unavailable, service);\n\nconst validateMapping = <M>(original: M, configuration: TotpTargetConfiguration): M => {\n const mapping = original as any;\n\n invariant(mapping.moduleId.length > 0);\n Schema.decodeSync(TotpPolicy)(mapping.policy);\n for (const [key, value] of Object.entries(requiredTotpConstraints))\n invariant(mapping.constraints?.[key] === value);\n if (configuration.mode === \"batch\") invariant(mapping.d1?.primary === true);\n\n return Object.freeze({\n ...mapping,\n policy: Object.freeze({ ...mapping.policy }),\n subject: Object.freeze({ ...mapping.subject }),\n factor: Object.freeze({ ...mapping.factor }),\n credential: Object.freeze({ ...mapping.credential }),\n subjectIds: Object.freeze({ ...mapping.subjectIds }),\n });\n};\n\nconst services = Effect.fnUntraced(function* (\n mapping: any,\n execution: TransactionExecution<TotpUnavailable, CurrentTotpTransaction>,\n): Effect.fn.Return<TotpPersistenceServices, never, LifecycleHooks> {\n const hooks = yield* LifecycleHooks;\n\n return {\n totpPersistence: TotpPersistence.of({\n snapshot: Effect.fn(\"TotpNative.snapshot\")(\n function* (input) {\n const captured = { ...input };\n\n invariant(captured.moduleId === mapping.moduleId);\n yield* execution.admit;\n\n return yield* execution\n .run(\n Effect.map(captureTotp(mapping, captured.subjectId), (value) => value?.snapshot),\n false,\n )\n .pipe(Effect.provideService(LifecycleHooks, hooks));\n },\n Effect.catchDefect(() => Effect.fail(unavailable())),\n ),\n mutate: (original, prepare) =>\n Effect.suspend(() => {\n // Detach caller-owned payloads before any driver or hook can suspend.\n const codec = Schema.toCodecIso(TotpMutation);\n const input = Schema.decodeSync(codec)(Schema.encodeSync(codec)(original));\n\n return execution.admit.pipe(\n Effect.andThen(\n execution.run(\n Effect.gen(function* () {\n const decision = yield* mutateTotp(mapping, input),\n owner = yield* CurrentTotpTransaction;\n\n owner.guards.push(owner.journal.prepare(undefined));\n const receipt = prepare(decision, owner.journal);\n\n invariant(receipt?._tag === \"PreparedCommit\" && Effect.isEffect(receipt.read));\n owner.guards.push(receipt as any);\n\n return receipt;\n }),\n ),\n ),\n Effect.provideService(LifecycleHooks, hooks),\n );\n }).pipe(Effect.catchDefect(() => Effect.fail(unavailable()))),\n }),\n };\n});\n\nexport const makeTargetTotpPersistence = <\n S extends Table,\n F extends Table,\n C extends Table,\n N,\n RSetup = never,\n>(\n source: TotpMappingSource<TotpMapping<S, F, C, N>, RSetup>,\n configuration: TotpTargetConfiguration,\n) =>\n Effect.gen(function* () {\n const original = yield* Effect.isEffect(source) ? source : Effect.succeed(source);\n\n const mapping = yield* Effect.try({\n try: () => validateMapping(original, configuration),\n catch: () => TotpConfigurationError.make({}),\n });\n\n yield* validateDrizzleStorage(mapping).pipe(\n Effect.mapError(() => TotpConfigurationError.make({})),\n );\n\n const execution = yield* makeTransactionExecution(\n CurrentTotpTransaction,\n configuration,\n unavailable,\n randomId,\n );\n\n return yield* services(mapping, execution);\n });\n\nexport const coordinateTargetTotp = <M, A, E, R, RSetup = never>(\n database: TransactionNativeDatabase,\n source: TotpMappingSource<M, RSetup>,\n configuration: TotpTargetConfiguration,\n body: (\n transaction: any,\n services: TotpPersistenceServices,\n append: (statement: Statement<any>) => void,\n ) => Effect.Effect<A, E, R>,\n): Effect.Effect<\n A,\n TotpCoordinatorError<E>,\n R | RSetup | Crypto.Crypto | LifecycleHooks | NativeDatabase\n> =>\n Effect.gen(function* () {\n const original = yield* Effect.isEffect(source) ? source : Effect.succeed(source);\n\n const mapping = yield* Effect.try({\n try: () => validateMapping(original, configuration),\n catch: () => TotpConfigurationError.make({}),\n });\n\n yield* validateDrizzleStorage(mapping).pipe(\n Effect.mapError(() => TotpConfigurationError.make({})),\n );\n\n return yield* coordinateTransactionOwner(\n database,\n CurrentTotpTransaction,\n configuration,\n Effect.void,\n unavailable,\n randomId,\n (execution) => services(mapping, execution),\n (transaction, acquireServices, append) =>\n Effect.flatMap(acquireServices, (boundServices) =>\n body(transaction, boundServices, append),\n ),\n );\n });\n\ntype TransactionOf<D> = D extends { readonly transaction: (...args: any[]) => any }\n ? Parameters<Parameters<D[\"transaction\"]>[0]>[0]\n : never;\n\n/** Concrete driver wrappers select transaction mode. */\nexport const makeTotpTarget = <\n DatabaseId,\n D extends { readonly transaction: any },\n T extends Table,\n Extra = unknown,\n Synchronous extends boolean = false,\n>(\n databaseService: Context.Service<DatabaseId, D>,\n configuration: TotpTargetConfiguration,\n) => {\n function coordinateTotpPersistence<\n Database extends D,\n S extends T,\n F extends T,\n C extends T,\n N,\n A,\n E,\n R,\n RSetup = never,\n DatabaseError = never,\n DatabaseRequirements = never,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N> & Extra, RSetup>;\n readonly transaction?: never;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TotpPersistence> : R>,\n ): Effect.Effect<\n A,\n TotpCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TotpPersistence>)\n | Crypto.Crypto\n | LifecycleHooks\n | RSetup\n | DatabaseRequirements\n >;\n function coordinateTotpPersistence<\n Database extends D,\n S extends T,\n F extends T,\n C extends T,\n N,\n A,\n E,\n R,\n TxId,\n TxShape,\n RSetup = never,\n DatabaseError = never,\n DatabaseRequirements = never,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N> & Extra, RSetup>;\n readonly transaction: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, Synchronous extends true ? NoInfer<TotpPersistence | TxId> : R>,\n ): Effect.Effect<\n A,\n TotpCoordinatorError<E> | DatabaseError,\n | (Synchronous extends true ? never : Exclude<R, TotpPersistence | TxId>)\n | Crypto.Crypto\n | LifecycleHooks\n | RSetup\n | DatabaseRequirements\n >;\n function coordinateTotpPersistence<\n Database extends D,\n S extends T,\n F extends T,\n C extends T,\n N,\n A,\n E,\n R,\n TxId,\n TxShape,\n RSetup = never,\n DatabaseError = never,\n DatabaseRequirements = never,\n >(\n acquire: Effect.Effect<Database, DatabaseError, DatabaseRequirements>,\n options: {\n readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N> & Extra, RSetup>;\n readonly transaction?: SuppliedService<TxId, NoInfer<TransactionOf<Database>>, TxShape>;\n },\n body: Effect.Effect<A, E, R>,\n ): Effect.Effect<\n A,\n TotpCoordinatorError<E> | DatabaseError,\n Exclude<R, TotpPersistence> | Crypto.Crypto | LifecycleHooks | RSetup | DatabaseRequirements\n > {\n return Effect.flatMap(nativeDatabase(acquire), (database) =>\n coordinateTargetTotp(\n database as any,\n options.mapping,\n configuration,\n (\n transaction: TransactionOf<Database>,\n services,\n ): Effect.Effect<A, E, Exclude<R, TotpPersistence>> => {\n const provided = Context.make(TotpPersistence, services.totpPersistence);\n const work = Effect.provideContext(body, provided);\n\n return options.transaction === undefined\n ? work\n : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n },\n ).pipe(Effect.provideService(NativeDatabase, database)),\n );\n }\n\n return {\n makeTotpPersistenceServices: <S extends T, F extends T, C extends T, N, RSetup = never>(\n mapping: TotpMappingSource<TotpMapping<S, F, C, N> & Extra, RSetup>,\n ) =>\n makeTargetTotpPersistence(mapping, configuration).pipe(\n Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n ),\n coordinateTotpPersistence,\n };\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@yielded/auth-persistence-drizzle","version":"0.1.0-beta.17","dependencies":{"@noble/hashes":"2.3.0","@yielded/auth":"0.1.0-beta.17","@yielded/auth-crypto":"0.1.0-beta.17","@yielded/auth-persistence":"0.1.0-beta.17"},"devDependencies":{"@effect/platform-bun":"4.0.0","@effect/platform-node":"4.0.0","@effect/sql-d1":"4.0.0","@effect/sql-libsql":"4.0.0","@effect/sql-mysql2":"4.0.0","@effect/sql-pg":"4.0.0","@effect/sql-pglite":"4.0.0","@effect/sql-sqlite-bun":"4.0.0","@effect/sql-sqlite-do":"4.0.0","@effect/sql-sqlite-node":"4.0.0","@effect/sql-sqlite-wasm":"4.0.0","@effect/vitest":"4.0.0","drizzle-orm":"1.0.0-rc.4","effect":"4.0.0","typescript":"7.0.2","vite-plus":"0.3.3"},"peerDependencies":{"@effect/sql-d1":">=4.0.0","@effect/sql-libsql":">=4.0.0","@effect/sql-mysql2":">=4.0.0","@effect/sql-pg":">=4.0.0","@effect/sql-pglite":">=4.0.0","@effect/sql-sqlite-bun":">=4.0.0","@effect/sql-sqlite-do":">=4.0.0","@effect/sql-sqlite-node":">=4.0.0","@effect/sql-sqlite-wasm":">=4.0.0","drizzle-orm":">=1.0.0-rc.4","effect":"^4.0.0"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./D1":{"types":"./dist/D1.d.mts","default":"./dist/D1.mjs"},"./Libsql":{"types":"./dist/Libsql.d.mts","default":"./dist/Libsql.mjs"},"./Mysql2":{"types":"./dist/Mysql2.d.mts","default":"./dist/Mysql2.mjs"},"./Pglite":{"types":"./dist/Pglite.d.mts","default":"./dist/Pglite.mjs"},"./Postgres":{"types":"./dist/Postgres.d.mts","default":"./dist/Postgres.mjs"},"./SqliteBun":{"types":"./dist/SqliteBun.d.mts","default":"./dist/SqliteBun.mjs"},"./SqliteDo":{"types":"./dist/SqliteDo.d.mts","default":"./dist/SqliteDo.mjs"},"./SqliteNode":{"types":"./dist/SqliteNode.d.mts","default":"./dist/SqliteNode.mjs"},"./SqliteWasm":{"types":"./dist/SqliteWasm.d.mts","default":"./dist/SqliteWasm.mjs"}},"description":"Drizzle persistence, table mappings, and migration adapters for Yielded Auth.","homepage":"https://yielded.dev/auth/","bugs":{"url":"https://github.com/yielded-dev/auth/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/yielded-dev/auth.git","directory":"packages/auth-persistence-drizzle"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests","example:totp":"bun test/fixtures/totp-sqlite-bun.ts"},"peerDependenciesMeta":{"@effect/sql-d1":{"optional":true},"@effect/sql-libsql":{"optional":true},"@effect/sql-mysql2":{"optional":true},"@effect/sql-pg":{"optional":true},"@effect/sql-pglite":{"optional":true},"@effect/sql-sqlite-bun":{"optional":true},"@effect/sql-sqlite-do":{"optional":true},"@effect/sql-sqlite-node":{"optional":true},"@effect/sql-sqlite-wasm":{"optional":true}}}
1
+ {"name":"@yielded/auth-persistence-drizzle","version":"0.1.0-beta.19","dependencies":{"@yielded/auth":"0.1.0-beta.19","@yielded/auth-persistence":"0.1.0-beta.19"},"devDependencies":{"@effect/platform-bun":"4.0.0","@effect/platform-node":"4.0.0","@effect/sql-d1":"4.0.0","@effect/sql-libsql":"4.0.0","@effect/sql-mysql2":"4.0.0","@effect/sql-pg":"4.0.0","@effect/sql-pglite":"4.0.0","@effect/sql-sqlite-bun":"4.0.0","@effect/sql-sqlite-do":"4.0.0","@effect/sql-sqlite-node":"4.0.0","@effect/sql-sqlite-wasm":"4.0.0","@effect/vitest":"4.0.0","@yielded/crypto":"0.1.0-beta.19","drizzle-orm":"1.0.0-rc.4","effect":"4.0.0","typescript":"7.0.2","vite-plus":"0.3.3"},"peerDependencies":{"@effect/sql-d1":">=4.0.0","@effect/sql-libsql":">=4.0.0","@effect/sql-mysql2":">=4.0.0","@effect/sql-pg":">=4.0.0","@effect/sql-pglite":">=4.0.0","@effect/sql-sqlite-bun":">=4.0.0","@effect/sql-sqlite-do":">=4.0.0","@effect/sql-sqlite-node":">=4.0.0","@effect/sql-sqlite-wasm":">=4.0.0","drizzle-orm":">=1.0.0-rc.4","effect":"^4.0.0"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./D1":{"types":"./dist/D1.d.mts","default":"./dist/D1.mjs"},"./Libsql":{"types":"./dist/Libsql.d.mts","default":"./dist/Libsql.mjs"},"./Mysql2":{"types":"./dist/Mysql2.d.mts","default":"./dist/Mysql2.mjs"},"./Pglite":{"types":"./dist/Pglite.d.mts","default":"./dist/Pglite.mjs"},"./Postgres":{"types":"./dist/Postgres.d.mts","default":"./dist/Postgres.mjs"},"./SqliteBun":{"types":"./dist/SqliteBun.d.mts","default":"./dist/SqliteBun.mjs"},"./SqliteDo":{"types":"./dist/SqliteDo.d.mts","default":"./dist/SqliteDo.mjs"},"./SqliteNode":{"types":"./dist/SqliteNode.d.mts","default":"./dist/SqliteNode.mjs"},"./SqliteWasm":{"types":"./dist/SqliteWasm.d.mts","default":"./dist/SqliteWasm.mjs"}},"description":"Drizzle persistence, table mappings, and migration adapters for Yielded Auth.","homepage":"https://yielded.dev/auth/","bugs":{"url":"https://github.com/yielded-dev/auth/issues"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/yielded-dev/auth.git","directory":"packages/auth-persistence-drizzle"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests","example:totp":"bun test/fixtures/totp-sqlite-bun.ts"},"peerDependenciesMeta":{"@effect/sql-d1":{"optional":true},"@effect/sql-libsql":{"optional":true},"@effect/sql-mysql2":{"optional":true},"@effect/sql-pg":{"optional":true},"@effect/sql-pglite":{"optional":true},"@effect/sql-sqlite-bun":{"optional":true},"@effect/sql-sqlite-do":{"optional":true},"@effect/sql-sqlite-node":{"optional":true},"@effect/sql-sqlite-wasm":{"optional":true}}}
package/src/SqliteDo.ts CHANGED
@@ -1,18 +1,21 @@
1
1
  import { SqliteClient } from "@effect/sql-sqlite-do/SqliteClient";
2
2
  import { NativeDatabase, PersistenceConfigurationError } from "@yielded/auth-persistence/Adapter";
3
3
  import type { AnyRelations } from "drizzle-orm";
4
- import { type EffectSQLiteDoDatabase, makeWithDefaults } from "drizzle-orm/effect-sqlite-do";
4
+ import { makeWithDefaults } from "drizzle-orm/effect-sqlite-do";
5
+
6
+ import { type DatabaseValue, makeDatabase } from "./drizzle/sqlite-do-database";
7
+ export { type DatabaseValue, type Transaction, makeDatabase } from "./drizzle/sqlite-do-database";
5
8
  import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
6
9
  import { Context, Effect, Layer } from "effect";
7
10
 
8
11
  import { nativeDatabase } from "./drizzle/native-database";
9
12
 
10
- /** The application-owned Drizzle database used to construct persistence services. */
11
- export class Database extends Context.Service<Database, EffectSQLiteDoDatabase<AnyRelations>>()(
13
+ /** The application-owned Drizzle queries with Effect SQL transaction ownership. */
14
+ export class Database extends Context.Service<Database, DatabaseValue<AnyRelations>>()(
12
15
  "effect-auth/persistence-drizzle/SqliteDo/Database",
13
16
  ) {}
14
17
 
15
- /** The SQL-client Layer must configure storage so Drizzle owns transactionSync. */
18
+ /** Construct Drizzle with asynchronous transactions owned by Effect SQL. */
16
19
  export const databaseLayer = Layer.effect(
17
20
  Database,
18
21
  Effect.gen(function* () {
@@ -21,19 +24,22 @@ export const databaseLayer = Layer.effect(
21
24
 
22
25
  if (storage === undefined)
23
26
  return yield* PersistenceConfigurationError.make({
24
- reason:
25
- "SqliteDo requires a SQL client configured with storage for synchronous transactions",
27
+ reason: "SqliteDo requires a SQL client configured with Durable Object storage",
26
28
  });
27
29
 
28
- return yield* makeWithDefaults({ storage });
30
+ return yield* makeDatabase(yield* makeWithDefaults({ storage }));
29
31
  }),
30
32
  );
31
33
 
34
+ import { sqlClientEmailStandaloneGuard } from "./drizzle/email-target";
32
35
  import type {
33
36
  ExternalIdentityTables,
34
37
  IdentityTables,
35
38
  SubjectProvisioningTables,
36
39
  } from "./drizzle/model";
40
+ import { sqlClientPasswordStandaloneGuard } from "./drizzle/password-target";
41
+ import { sqlClientProofStandaloneGuard } from "./drizzle/proof-target";
42
+ import { sqlClientSessionStandaloneGuard } from "./drizzle/session-target";
37
43
  import { makeSqliteEmailTarget, sqliteEmailConfiguration } from "./drizzle/sqlite-emails";
38
44
  import {
39
45
  makeSqliteExternalIdentityServices,
@@ -44,31 +50,36 @@ import { makeSqlitePasswordTarget, sqlitePasswordConfiguration } from "./drizzle
44
50
  import { makeSqliteProofTarget, sqliteProofConfiguration } from "./drizzle/sqlite-proofs";
45
51
  import { makeSqliteSessionTarget, sqliteSessionConfiguration } from "./drizzle/sqlite-sessions";
46
52
 
47
- const sessionTarget = makeSqliteSessionTarget<Database, EffectSQLiteDoDatabase<AnyRelations>, true>(
53
+ const sessionTarget = makeSqliteSessionTarget<Database, DatabaseValue<AnyRelations>>(
48
54
  Database,
49
- sqliteSessionConfiguration("synchronous", Effect.void),
55
+ (service) => sqliteSessionConfiguration("interactive", sqlClientSessionStandaloneGuard(service)),
50
56
  );
51
57
 
52
- const proofTarget = makeSqliteProofTarget<Database, EffectSQLiteDoDatabase<AnyRelations>, true>(
58
+ const proofTarget = makeSqliteProofTarget<Database, DatabaseValue<AnyRelations>>(
53
59
  Database,
54
- sqliteProofConfiguration("synchronous", Effect.void),
60
+ (service) => sqliteProofConfiguration("interactive", sqlClientProofStandaloneGuard(service)),
55
61
  );
56
62
 
57
- const passwordTarget = makeSqlitePasswordTarget<
63
+ const passwordTarget = makeSqlitePasswordTarget<Database, DatabaseValue<AnyRelations>>(
58
64
  Database,
59
- EffectSQLiteDoDatabase<AnyRelations>,
60
- true
61
- >(Database, sqlitePasswordConfiguration("synchronous", Effect.void, Effect.void));
65
+ (service) =>
66
+ sqlitePasswordConfiguration(
67
+ "interactive",
68
+ sqlClientPasswordStandaloneGuard(service),
69
+ sqlClientProofStandaloneGuard(service),
70
+ ),
71
+ );
62
72
 
63
- const emailTarget = makeSqliteEmailTarget<Database, EffectSQLiteDoDatabase<AnyRelations>, true>(
73
+ const emailTarget = makeSqliteEmailTarget<Database, DatabaseValue<AnyRelations>>(
64
74
  Database,
65
- sqliteEmailConfiguration("synchronous", Effect.void, Effect.void),
75
+ (service) =>
76
+ sqliteEmailConfiguration(
77
+ "interactive",
78
+ sqlClientEmailStandaloneGuard(service),
79
+ sqlClientProofStandaloneGuard(service),
80
+ ),
66
81
  );
67
82
 
68
- /**
69
- * Email mutations must own their outer transactionSync. Arbitrary raw Drizzle
70
- * nesting is not detectable; owner bodies and mapping allocators stay runSync-compatible.
71
- */
72
83
  export const {
73
84
  coordinateEmailAddress,
74
85
  coordinateEmailRegistration,
@@ -77,11 +88,6 @@ export const {
77
88
  makeEmailSignInServices,
78
89
  } = emailTarget;
79
90
 
80
- /**
81
- * Password mutations and registration must own their outer transactionSync.
82
- * Arbitrary raw Drizzle nesting is not detectable; owner bodies must remain
83
- * runSync-compatible. Detectable Effect commit scopes are rejected pre-write.
84
- */
85
91
  export const {
86
92
  coordinatePasswordPersistence,
87
93
  coordinatePasswordRegistration,
@@ -89,21 +95,8 @@ export const {
89
95
  makePasswordRegistrationServices,
90
96
  } = passwordTarget;
91
97
 
92
- /**
93
- * Proof mutations and coordinateProofPersistence must own their outermost
94
- * transactionSync call. The installed driver cannot detect an arbitrary raw
95
- * Drizzle outer transaction; calling either boundary from one is unsupported.
96
- * The owner body must remain runSync-compatible.
97
- */
98
98
  export const { coordinateProofPersistence, makeProofPersistenceServices } = proofTarget;
99
99
 
100
- /**
101
- * Session mutation methods and coordinate* functions must own their outermost
102
- * transactionSync call. The installed Drizzle driver exposes no context marker
103
- * for an arbitrary raw outer database.transaction call, so invoking either
104
- * boundary from one is unsupported and cannot be detected. Detectable Effect
105
- * commit scopes are rejected before writes.
106
- */
107
100
  export const {
108
101
  coordinateAuthenticationAuthority,
109
102
  coordinatePendingAuthentication,
@@ -117,7 +110,7 @@ export const {
117
110
  makeStatefulSessionServices,
118
111
  } = sessionTarget;
119
112
 
120
- export const commitMode = "synchronous" as const;
113
+ export const commitMode = "interactive" as const;
121
114
 
122
115
  export const makeIdentityServices = <
123
116
  Subject extends AnySQLiteTable,
@@ -128,7 +121,7 @@ export const makeIdentityServices = <
128
121
  >(
129
122
  mapping: IdentityTables<Subject, Identifier, External, Request, NativeId>,
130
123
  ) =>
131
- makeSqliteIdentityServices(mapping, "synchronous").pipe(
124
+ makeSqliteIdentityServices(mapping, "interactive").pipe(
132
125
  Effect.provideServiceEffect(NativeDatabase, nativeDatabase(Database)),
133
126
  );
134
127
 
@@ -140,7 +133,7 @@ export const makeSubjectProvisioningServices = <
140
133
  >(
141
134
  mapping: SubjectProvisioningTables<Subject, Identifier, Request, NativeId>,
142
135
  ) =>
143
- makeSqliteSubjectProvisioningServices(mapping, "synchronous").pipe(
136
+ makeSqliteSubjectProvisioningServices(mapping, "interactive").pipe(
144
137
  Effect.provideServiceEffect(NativeDatabase, nativeDatabase(Database)),
145
138
  );
146
139
 
@@ -159,9 +152,14 @@ import { makeSqlitePasswordPreparedTarget } from "./drizzle/sqlite-password-prep
159
152
 
160
153
  const passwordPreparedTarget = makeSqlitePasswordPreparedTarget<
161
154
  Database,
162
- EffectSQLiteDoDatabase<AnyRelations>,
163
- true
164
- >(Database, sqlitePasswordConfiguration("synchronous", Effect.void, Effect.void));
155
+ DatabaseValue<AnyRelations>
156
+ >(Database, (service) =>
157
+ sqlitePasswordConfiguration(
158
+ "interactive",
159
+ sqlClientPasswordStandaloneGuard(service),
160
+ sqlClientProofStandaloneGuard(service),
161
+ ),
162
+ );
165
163
 
166
164
  export const { makePasswordPreparedPersistenceServices, coordinatePasswordPreparedPersistence } =
167
165
  passwordPreparedTarget;
@@ -169,17 +167,17 @@ export const { makePasswordPreparedPersistenceServices, coordinatePasswordPrepar
169
167
  export { passwordPreparedPersistenceLayer } from "./drizzle/password-prepared-target";
170
168
 
171
169
  import { makeOAuthTarget } from "./drizzle/oauth-drivers";
170
+ import { sqlClientOAuthStandaloneGuard } from "./drizzle/oauth-target";
172
171
 
173
172
  const oauthTarget = makeOAuthTarget<
174
173
  Database,
175
- EffectSQLiteDoDatabase<AnyRelations>,
176
- AnySQLiteTable<{ dialect: "sqlite" }>,
177
- true
174
+ DatabaseValue<AnyRelations>,
175
+ AnySQLiteTable<{ dialect: "sqlite" }>
178
176
  >(Database, {
179
- mode: "synchronous",
177
+ mode: "interactive",
180
178
  dialect: "sqlite",
181
179
  locking: false,
182
- standaloneGuard: () => Effect.void,
180
+ standaloneGuard: sqlClientOAuthStandaloneGuard,
183
181
  });
184
182
 
185
183
  export const {
@@ -198,18 +196,17 @@ export const {
198
196
  } = oauthTarget;
199
197
 
200
198
  import { makePasskeyTarget } from "./drizzle/passkey-drivers";
199
+ import { sqlClientPasskeyStandaloneGuard } from "./drizzle/passkey-target";
201
200
 
202
201
  const passkeyTarget = makePasskeyTarget<
203
202
  Database,
204
- EffectSQLiteDoDatabase<AnyRelations>,
205
- AnySQLiteTable<{ dialect: "sqlite" }>,
206
- unknown,
207
- true
203
+ DatabaseValue<AnyRelations>,
204
+ AnySQLiteTable<{ dialect: "sqlite" }>
208
205
  >(Database, {
209
- mode: "synchronous",
206
+ mode: "interactive",
210
207
  dialect: "sqlite",
211
208
  locking: false,
212
- standaloneGuard: () => Effect.void,
209
+ standaloneGuard: sqlClientPasskeyStandaloneGuard,
213
210
  });
214
211
 
215
212
  export const {
@@ -225,36 +222,32 @@ export const {
225
222
  coordinatePasskeyRegistration,
226
223
  } = passkeyTarget;
227
224
 
228
- import { makeTotpTarget } from "./drizzle/totp-target";
225
+ import { makeTotpTarget, sqlClientTotpStandaloneGuard } from "./drizzle/totp-target";
229
226
 
230
227
  const totpTarget = makeTotpTarget<
231
228
  Database,
232
- EffectSQLiteDoDatabase<AnyRelations>,
233
- AnySQLiteTable<{ dialect: "sqlite" }>,
234
- unknown,
235
- true
229
+ DatabaseValue<AnyRelations>,
230
+ AnySQLiteTable<{ dialect: "sqlite" }>
236
231
  >(Database, {
237
- mode: "synchronous",
232
+ mode: "interactive",
238
233
  dialect: "sqlite",
239
234
  locking: false,
240
- standaloneGuard: () => Effect.void,
235
+ standaloneGuard: sqlClientTotpStandaloneGuard,
241
236
  });
242
237
 
243
238
  export const { makeTotpPersistenceServices, coordinateTotpPersistence } = totpTarget;
244
239
 
245
- import { makePhoneTarget } from "./drizzle/phone-target";
240
+ import { makePhoneTarget, sqlClientPhoneStandaloneGuard } from "./drizzle/phone-target";
246
241
 
247
242
  const phoneTarget = makePhoneTarget<
248
243
  Database,
249
- EffectSQLiteDoDatabase<AnyRelations>,
250
- AnySQLiteTable<{ dialect: "sqlite" }>,
251
- unknown,
252
- true
244
+ DatabaseValue<AnyRelations>,
245
+ AnySQLiteTable<{ dialect: "sqlite" }>
253
246
  >(Database, {
254
- mode: "synchronous",
247
+ mode: "interactive",
255
248
  dialect: "sqlite",
256
249
  locking: false,
257
- standaloneGuard: () => Effect.void,
250
+ standaloneGuard: sqlClientPhoneStandaloneGuard,
258
251
  });
259
252
 
260
253
  export const { makePhonePersistenceServices, coordinatePhonePersistence } = phoneTarget;
@@ -0,0 +1,14 @@
1
+ import { TokenDigest } from "@yielded/auth/Schema";
2
+ import { Crypto, Effect } from "effect";
3
+ import { Base64Url } from "effect/encoding";
4
+
5
+ const encoder = new TextEncoder();
6
+
7
+ export const randomId = Effect.flatMap(Crypto.Crypto, (crypto) =>
8
+ crypto.randomBytes(32).pipe(Effect.map(Base64Url.encode)),
9
+ );
10
+
11
+ export const digest = (value: string) =>
12
+ Effect.flatMap(Crypto.Crypto, (crypto) => crypto.digest("SHA-256", encoder.encode(value))).pipe(
13
+ Effect.map((bytes) => TokenDigest.make(Base64Url.encode(bytes))),
14
+ );
@@ -1,5 +1,5 @@
1
1
  import type { D1Client } from "@effect/sql-d1/D1Client";
2
- import { NativeDatabase } from "@yielded/auth-persistence/Adapter";
2
+ import { withStorageValidation, NativeDatabase } from "@yielded/auth-persistence/Adapter";
3
3
  import {
4
4
  ExternalIdentityMutation,
5
5
  type ExternalIdentity,
@@ -382,4 +382,4 @@ export const makeD1IdentityServices = Effect.fnUntraced(function* <
382
382
  ...(yield* makeD1SubjectProvisioningServices(mapping)),
383
383
  ...(yield* makeD1ExternalIdentityServices(mapping)),
384
384
  };
385
- });
385
+ }, withStorageValidation);
@@ -10,7 +10,7 @@ import {
10
10
  import type { AnyRelations } from "drizzle-orm";
11
11
  import type { EffectSQLiteD1Database } from "drizzle-orm/effect-d1";
12
12
  import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
13
- import { Effect, Context } from "effect";
13
+ import { type Crypto, Effect, Context } from "effect";
14
14
 
15
15
  import { Database as DatabaseService } from "./d1-database";
16
16
  import { makeD1Owner } from "./d1-planning";
@@ -129,7 +129,10 @@ export function coordinateD1OAuthSignIn<
129
129
  ): Effect.Effect<
130
130
  A,
131
131
  OAuthCoordinatorError<E> | DatabaseError,
132
- Exclude<R, OAuthSignInPersistence | D1BatchStatements> | LifecycleHooks | DatabaseRequirements
132
+ | Exclude<R, OAuthSignInPersistence | D1BatchStatements>
133
+ | Crypto.Crypto
134
+ | LifecycleHooks
135
+ | DatabaseRequirements
133
136
  > {
134
137
  return Effect.flatMap(nativeDatabase(acquire), (database) =>
135
138
  coordinateTargetOAuthSignIn<
@@ -189,7 +192,10 @@ export function coordinateD1OAuthRegistrationIntents<
189
192
  ): Effect.Effect<
190
193
  A,
191
194
  OAuthCoordinatorError<E> | DatabaseError,
192
- Exclude<R, OAuthRegistrationIntents | D1BatchStatements> | LifecycleHooks | DatabaseRequirements
195
+ | Exclude<R, OAuthRegistrationIntents | D1BatchStatements>
196
+ | Crypto.Crypto
197
+ | LifecycleHooks
198
+ | DatabaseRequirements
193
199
  > {
194
200
  return Effect.flatMap(nativeDatabase(acquire), (database) =>
195
201
  coordinateTargetOAuthRegistrationIntents<
@@ -244,7 +250,10 @@ export function coordinateD1OAuthAccounts<
244
250
  ): Effect.Effect<
245
251
  A,
246
252
  OAuthCoordinatorError<E> | DatabaseError,
247
- Exclude<R, OAuthAccountsPersistence | D1BatchStatements> | LifecycleHooks | DatabaseRequirements
253
+ | Exclude<R, OAuthAccountsPersistence | D1BatchStatements>
254
+ | Crypto.Crypto
255
+ | LifecycleHooks
256
+ | DatabaseRequirements
248
257
  > {
249
258
  return Effect.flatMap(nativeDatabase(acquire), (database) =>
250
259
  coordinateTargetOAuthAccounts<
@@ -312,7 +321,7 @@ export function coordinateD1OAuthRegistration<
312
321
  ): Effect.Effect<
313
322
  A,
314
323
  OAuthCoordinatorError<E> | DatabaseError,
315
- Exclude<R, TargetId | D1BatchStatements> | LifecycleHooks | DatabaseRequirements
324
+ Exclude<R, TargetId | D1BatchStatements> | Crypto.Crypto | LifecycleHooks | DatabaseRequirements
316
325
  > {
317
326
  return Effect.flatMap(nativeDatabase(acquire), (database) =>
318
327
  coordinateTargetOAuthRegistration<
@@ -9,7 +9,7 @@ import {
9
9
  import type { AnyRelations } from "drizzle-orm";
10
10
  import type { EffectSQLiteD1Database } from "drizzle-orm/effect-d1";
11
11
  import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
12
- import { Effect, Context } from "effect";
12
+ import { type Crypto, Effect, Context } from "effect";
13
13
 
14
14
  import { Database as DatabaseService } from "./d1-database";
15
15
  import { makeD1Owner } from "./d1-planning";
@@ -94,6 +94,7 @@ export function coordinatePasskeyPersistence<
94
94
  A,
95
95
  PasskeyCoordinatorError<E> | DatabaseError,
96
96
  | Exclude<R, PasskeyPersistence | D1BatchStatements>
97
+ | Crypto.Crypto
97
98
  | LifecycleHooks
98
99
  | DatabaseRequirements
99
100
  | RSetup
@@ -156,6 +157,7 @@ export function coordinatePasskeyRegistrationCeremony<
156
157
  A,
157
158
  PasskeyCoordinatorError<E> | DatabaseError,
158
159
  | Exclude<R, PasskeyPersistence | D1BatchStatements>
160
+ | Crypto.Crypto
159
161
  | LifecycleHooks
160
162
  | DatabaseRequirements
161
163
  | RSetup
@@ -239,6 +241,7 @@ export function coordinatePasskeyManagement<
239
241
  A,
240
242
  PasskeyCoordinatorError<E> | DatabaseError,
241
243
  | Exclude<R, PasskeyPersistence | PasskeyManagementPersistence | D1BatchStatements>
244
+ | Crypto.Crypto
242
245
  | LifecycleHooks
243
246
  | DatabaseRequirements
244
247
  | RSetup
@@ -328,6 +331,7 @@ export function coordinatePasskeyRegistration<
328
331
  A,
329
332
  PasskeyCoordinatorError<E> | DatabaseError,
330
333
  | Exclude<R, PasskeyPersistence | AuthorityId | D1BatchStatements>
334
+ | Crypto.Crypto
331
335
  | LifecycleHooks
332
336
  | DatabaseRequirements
333
337
  | RSetup
@@ -209,9 +209,13 @@ const makePreparedPlans = (mapping: Mapping, proofMapping?: any) => {
209
209
  statements: planned.statements.map((statement) =>
210
210
  compactD1GeneratedStatement(database.$client, statement, unavailable),
211
211
  ),
212
- postconditions: planned.postconditions?.map((statement) =>
213
- compactD1GeneratedStatement(database.$client, statement, unavailable),
214
- ),
212
+ ...(planned.postconditions === undefined
213
+ ? {}
214
+ : {
215
+ postconditions: planned.postconditions.map((statement) =>
216
+ compactD1GeneratedStatement(database.$client, statement, unavailable),
217
+ ),
218
+ }),
215
219
  }),
216
220
  catch: (cause) =>
217
221
  Schema.is(PasswordUnavailable)(cause)
@@ -418,7 +422,9 @@ const makePreparedPlans = (mapping: Mapping, proofMapping?: any) => {
418
422
  ))),
419
423
  receipt: receipt ?? prepare("rejected", journal),
420
424
  statements: compiled.statements,
421
- postconditions: compiled.postconditions,
425
+ ...(compiled.postconditions === undefined
426
+ ? {}
427
+ : { postconditions: compiled.postconditions }),
422
428
  };
423
429
  }
424
430
 
@@ -520,7 +526,7 @@ const makePreparedPlans = (mapping: Mapping, proofMapping?: any) => {
520
526
 
521
527
  const now = yield* kernel.readEngineNowMillis(p),
522
528
  scope = identifierScope({
523
- credential: authority.snapshot,
529
+ ...(authority.snapshot === undefined ? {} : { credential: authority.snapshot }),
524
530
  revision: authority.revision,
525
531
  });
526
532
 
@@ -1622,7 +1622,7 @@ const makePasswordPlans = (
1622
1622
  return {
1623
1623
  receipt: prepare(compiled === undefined ? "rejected" : "changed", journal),
1624
1624
  statements: compiled?.statements ?? [],
1625
- retryable: compiled?.retryable,
1625
+ ...(compiled?.retryable === undefined ? {} : { retryable: compiled.retryable }),
1626
1626
  };
1627
1627
  }),
1628
1628
  );
@@ -10,7 +10,7 @@ import {
10
10
  import type { AnyRelations } from "drizzle-orm";
11
11
  import type { EffectSQLiteD1Database } from "drizzle-orm/effect-d1";
12
12
  import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
13
- import { Context, Effect } from "effect";
13
+ import { type Crypto, Context, Effect } from "effect";
14
14
 
15
15
  import { Database as DatabaseService } from "./d1-database";
16
16
  import { makeD1Owner } from "./d1-planning";
@@ -59,6 +59,7 @@ export const coordinatePhonePersistence = <
59
59
  A,
60
60
  PhoneCoordinatorError<E> | DatabaseError,
61
61
  | Exclude<R, PhonePersistence | PhoneAdmission | PhoneSignInTargets | D1BatchStatements>
62
+ | Crypto.Crypto
62
63
  | LifecycleHooks
63
64
  | RSetup
64
65
  | DatabaseRequirements
@@ -341,7 +341,11 @@ function runPlanned<A, E, GuardE extends D1PlanError = never>(
341
341
  recoverGuard?: Effect.Effect<never, GuardE, CurrentD1PlanningDatabase>,
342
342
  ) {
343
343
  const planned = plan.pipe(
344
- Effect.map((value) => ({ ...value, isConstraintConflict, recoverGuard })),
344
+ Effect.map((value) => ({
345
+ ...value,
346
+ ...(isConstraintConflict === undefined ? {} : { isConstraintConflict }),
347
+ ...(recoverGuard === undefined ? {} : { recoverGuard }),
348
+ })),
345
349
  );
346
350
 
347
351
  const execution = Effect.gen(function* () {
@@ -1498,9 +1502,11 @@ export const makeD1StatefulSessions = <Claims>(
1498
1502
  Schema.encodeEffect(codec)(record).pipe(Effect.flatMap(Schema.decodeEffect(codec))),
1499
1503
  );
1500
1504
 
1505
+ const nextCursor = decoded.length <= input.limit ? undefined : sessions.at(-1)?.sessionId;
1506
+
1501
1507
  return {
1502
1508
  sessions,
1503
- ...(decoded.length <= input.limit ? {} : { nextCursor: sessions.at(-1)?.sessionId }),
1509
+ ...(nextCursor === undefined ? {} : { nextCursor }),
1504
1510
  };
1505
1511
  }).pipe(terminalD1),
1506
1512
  };
@@ -5,7 +5,7 @@ import { TotpUnavailable, TotpPersistence } from "@yielded/auth/Totp";
5
5
  import type { AnyRelations } from "drizzle-orm";
6
6
  import type { EffectSQLiteD1Database } from "drizzle-orm/effect-d1";
7
7
  import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
8
- import { Context, Effect } from "effect";
8
+ import { type Crypto, Context, Effect } from "effect";
9
9
 
10
10
  import { Database as DatabaseService } from "./d1-database";
11
11
  import { makeD1Owner } from "./d1-planning";
@@ -50,7 +50,11 @@ export const coordinateTotpPersistence = <
50
50
  ): Effect.Effect<
51
51
  A,
52
52
  TotpCoordinatorError<E> | DatabaseError,
53
- Exclude<R, TotpPersistence | D1BatchStatements> | LifecycleHooks | RSetup | DatabaseRequirements
53
+ | Exclude<R, TotpPersistence | D1BatchStatements>
54
+ | Crypto.Crypto
55
+ | LifecycleHooks
56
+ | RSetup
57
+ | DatabaseRequirements
54
58
  > =>
55
59
  Effect.flatMap(nativeDatabase(acquire), (database) =>
56
60
  coordinateTargetTotp(
@@ -1,4 +1,4 @@
1
- import { NativeDatabase } from "@yielded/auth-persistence/Adapter";
1
+ import { withStorageValidation, NativeDatabase } from "@yielded/auth-persistence/Adapter";
2
2
  import {
3
3
  ExternalIdentityMutation,
4
4
  type ExternalIdentity,
@@ -331,4 +331,4 @@ export const makeMysqlIdentityServices = Effect.fnUntraced(function* <
331
331
  ...(yield* makeMysqlSubjectProvisioningServices(mapping)),
332
332
  ...(yield* makeMysqlExternalIdentityServices(mapping)),
333
333
  };
334
- });
334
+ }, withStorageValidation);