{"version":3,"file":"totp-target.mjs","names":[],"sources":["../../src/drizzle/totp-target.ts"],"sourcesContent":["import { makeNativeTotpServices, type NativeTotpMapping } from \"@yielded/auth-persistence/Adapter\";\nimport type { LifecycleHooks } from \"@yielded/auth/Hooks\";\nimport {\n  TotpConfigurationError,\n  TotpUnavailable,\n  TotpPolicy,\n  TotpPersistence,\n} from \"@yielded/auth/Totp\";\nimport type { Table } from \"drizzle-orm\";\nimport * as Cause from \"effect/Cause\";\nimport type * as Context from \"effect/Context\";\nimport type * as Digest from \"effect/crypto/Digest\";\nimport type * as SecureRandom from \"effect/crypto/SecureRandom\";\nimport * as Effect from \"effect/Effect\";\nimport * as Schema from \"effect/Schema\";\n\nimport type { D1BatchStatements } from \"./D1BatchStatements\";\nimport type { NativeDriverDatabase, NativeDriverTransaction } from \"./driver-types\";\nimport type { PersistenceMappingError } from \"./model\";\nimport { nativeClock } from \"./native-clock\";\nimport { NativeDatabase, nativeDatabase } from \"./native-database\";\nimport {\n  nativeTarget,\n  coordinateNativeTarget,\n  type NativeTargetConfiguration,\n} from \"./native-target\";\nimport { validateDrizzleStorage } from \"./storage-validation\";\nimport type { SuppliedService } from \"./SuppliedService\";\nimport type { TotpMapping, TotpMappingSource } from \"./totp-model\";\n\nconst unavailable = () => TotpUnavailable.make({});\n\n/** Driver metadata is compiled once; the factor workflow and commit owner are shared. */\nexport const makeTotpTarget = <DatabaseId, D extends NativeDriverDatabase>(\n  databaseService: Context.Service<DatabaseId, D>,\n  configuration: NativeTargetConfiguration,\n) => {\n  const validate = Effect.fnUntraced(\n    function* (mapping: NativeTotpMapping) {\n      yield* validateDrizzleStorage(mapping);\n      yield* Schema.decodeEffect(TotpPolicy)(mapping.policy);\n      if (\n        mapping.moduleId.length === 0 ||\n        (configuration.mode === \"batch\" &&\n          (mapping.d1?.primary !== true || mapping.subject.requirementColumns === undefined))\n      )\n        return yield* TotpConfigurationError.make({});\n    },\n    Effect.catchCause((cause) =>\n      Effect.failCause(Cause.map(cause, () => TotpConfigurationError.make({}))),\n    ),\n  );\n\n  const services = Effect.fnUntraced(function* (mapping: NativeTotpMapping) {\n    const target = yield* nativeTarget(configuration);\n\n    return yield* target.provide(makeNativeTotpServices(target.tables, mapping));\n  });\n\n  const mapping = <S extends Table, F extends Table, C extends Table, N, P extends Table>(\n    value: TotpMapping<S, F, C, N, P>,\n  ): NativeTotpMapping =>\n    ({\n      ...value,\n      ...(value.pending === undefined\n        ? {}\n        : { pending: { ...value.pending, clock: nativeClock(value.pending.clock) } }),\n    }) as unknown as NativeTotpMapping;\n\n  function coordinateTotpPersistence<\n    DB extends D,\n    S extends Table,\n    F extends Table,\n    C extends Table,\n    N,\n    P extends Table,\n    A,\n    E,\n    R,\n    DE,\n    DR,\n    RS = never,\n  >(\n    acquire: Effect.Effect<DB, DE, DR>,\n    options: {\n      readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N, P>, RS>;\n      readonly transaction?: never;\n    },\n    body: Effect.Effect<A, E, R>,\n  ): Effect.Effect<\n    A,\n    E | DE | TotpUnavailable | TotpConfigurationError | PersistenceMappingError,\n    | Exclude<R, TotpPersistence | D1BatchStatements>\n    | DR\n    | RS\n    | LifecycleHooks\n    | (SecureRandom.SecureRandom | Digest.Digest)\n  >;\n  function coordinateTotpPersistence<\n    DB extends D,\n    S extends Table,\n    F extends Table,\n    C extends Table,\n    N,\n    P extends Table,\n    A,\n    E,\n    R,\n    DE,\n    DR,\n    TxId,\n    TxShape,\n    RS = never,\n  >(\n    acquire: Effect.Effect<DB, DE, DR>,\n    options: {\n      readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N, P>, RS>;\n      readonly transaction: SuppliedService<TxId, NoInfer<NativeDriverTransaction<DB>>, TxShape>;\n    },\n    body: Effect.Effect<A, E, R>,\n  ): Effect.Effect<\n    A,\n    E | DE | TotpUnavailable | TotpConfigurationError | PersistenceMappingError,\n    | Exclude<R, TotpPersistence | D1BatchStatements | TxId>\n    | DR\n    | RS\n    | LifecycleHooks\n    | (SecureRandom.SecureRandom | Digest.Digest)\n  >;\n  function coordinateTotpPersistence<\n    DB extends D,\n    S extends Table,\n    F extends Table,\n    C extends Table,\n    N,\n    P extends Table,\n    A,\n    E,\n    R,\n    DE,\n    DR,\n    TxId,\n    TxShape,\n    RS = never,\n  >(\n    acquire: Effect.Effect<DB, DE, DR>,\n    options: {\n      readonly mapping: TotpMappingSource<TotpMapping<S, F, C, N, P>, RS>;\n      readonly transaction?: SuppliedService<TxId, NoInfer<NativeDriverTransaction<DB>>, TxShape>;\n    },\n    body: Effect.Effect<A, E, R>,\n  ) {\n    return Effect.gen(function* () {\n      const value = mapping(\n        yield* Effect.isEffect(options.mapping) ? options.mapping : Effect.succeed(options.mapping),\n      );\n\n      const database = yield* nativeDatabase(acquire);\n\n      yield* validate(value).pipe(Effect.provideService(NativeDatabase, database));\n\n      return yield* coordinateNativeTarget(\n        unavailable,\n        database,\n        configuration,\n        services(value),\n        (\n          transaction: NativeDriverTransaction<DB>,\n          bound,\n        ): Effect.Effect<A, E, Exclude<R, TotpPersistence>> => {\n          const work = body.pipe(Effect.provideService(TotpPersistence, bound.totpPersistence));\n\n          return options.transaction === undefined\n            ? work\n            : Effect.provideService(work, options.transaction, options.transaction.of(transaction));\n        },\n      );\n    });\n  }\n\n  return {\n    coordinateTotpPersistence,\n    makeTotpPersistenceServices: Effect.fnUntraced(\n      function* <\n        S extends Table,\n        F extends Table,\n        C extends Table,\n        N,\n        P extends Table = Table,\n        RS = never,\n      >(source: TotpMappingSource<TotpMapping<S, F, C, N, P>, RS>) {\n        const value = mapping(yield* Effect.isEffect(source) ? source : Effect.succeed(source));\n\n        yield* validate(value);\n\n        return yield* services(value);\n      },\n      Effect.provideServiceEffect(NativeDatabase, nativeDatabase(databaseService)),\n    ),\n  };\n};\n"],"mappings":";;;;;;;;;;AA8BA,MAAM,oBAAoB,gBAAgB,KAAK,CAAC,CAAC;;AAGjD,MAAa,kBACX,iBACA,kBACG;CACH,MAAM,WAAW,OAAO,WACtB,WAAW,SAA4B;EACrC,OAAO,uBAAuB,OAAO;EACrC,OAAO,OAAO,aAAa,UAAU,CAAC,CAAC,QAAQ,MAAM;EACrD,IACE,QAAQ,SAAS,WAAW,KAC3B,cAAc,SAAS,YACrB,QAAQ,IAAI,YAAY,QAAQ,QAAQ,QAAQ,uBAAuB,KAAA,IAE1E,OAAO,OAAO,uBAAuB,KAAK,CAAC,CAAC;CAChD,GACA,OAAO,YAAY,UACjB,OAAO,UAAU,MAAM,IAAI,aAAa,uBAAuB,KAAK,CAAC,CAAC,CAAC,CAAC,CAC1E,CACF;CAEA,MAAM,WAAW,OAAO,WAAW,WAAW,SAA4B;EACxE,MAAM,SAAS,OAAO,aAAa,aAAa;EAEhD,OAAO,OAAO,OAAO,QAAQ,uBAAuB,OAAO,QAAQ,OAAO,CAAC;CAC7E,CAAC;CAED,MAAM,WACJ,WAEC;EACC,GAAG;EACH,GAAI,MAAM,YAAY,KAAA,IAClB,CAAC,IACD,EAAE,SAAS;GAAE,GAAG,MAAM;GAAS,OAAO,YAAY,MAAM,QAAQ,KAAK;EAAE,EAAE;CAC/E;CA8DF,SAAS,0BAgBP,SACA,SAIA,MACA;EACA,OAAO,OAAO,IAAI,aAAa;GAC7B,MAAM,QAAQ,QACZ,OAAO,OAAO,SAAS,QAAQ,OAAO,IAAI,QAAQ,UAAU,OAAO,QAAQ,QAAQ,OAAO,CAC5F;GAEA,MAAM,WAAW,OAAO,eAAe,OAAO;GAE9C,OAAO,SAAS,KAAK,CAAC,CAAC,KAAK,OAAO,eAAe,gBAAgB,QAAQ,CAAC;GAE3E,OAAO,OAAO,uBACZ,aACA,UACA,eACA,SAAS,KAAK,IAEZ,aACA,UACqD;IACrD,MAAM,OAAO,KAAK,KAAK,OAAO,eAAe,iBAAiB,MAAM,eAAe,CAAC;IAEpF,OAAO,QAAQ,gBAAgB,KAAA,IAC3B,OACA,OAAO,eAAe,MAAM,QAAQ,aAAa,QAAQ,YAAY,GAAG,WAAW,CAAC;GAC1F,CACF;EACF,CAAC;CACH;CAEA,OAAO;EACL;EACA,6BAA6B,OAAO,WAClC,WAOE,QAA2D;GAC3D,MAAM,QAAQ,QAAQ,OAAO,OAAO,SAAS,MAAM,IAAI,SAAS,OAAO,QAAQ,MAAM,CAAC;GAEtF,OAAO,SAAS,KAAK;GAErB,OAAO,OAAO,SAAS,KAAK;EAC9B,GACA,OAAO,qBAAqB,gBAAgB,eAAe,eAAe,CAAC,CAC7E;CACF;AACF"}