| 682 | * @category repository |
| 683 | */ |
| 684 | export const makeRepository = < |
| 685 | S extends Any, |
| 686 | Id extends (keyof S["Type"]) & (keyof S["update"]["Type"]) & (keyof S["fields"]) |
| 687 | >(Model: S, options: { |
| 688 | readonly tableName: string |
| 689 | readonly spanPrefix: string |
| 690 | readonly idColumn: Id |
| 691 | }): Effect.Effect< |
| 692 | { |
| 693 | readonly insert: ( |
| 694 | insert: S["insert"]["Type"] |
| 695 | ) => Effect.Effect<S["Type"], never, S["Context"] | S["insert"]["Context"]> |
| 696 | readonly insertVoid: ( |
| 697 | insert: S["insert"]["Type"] |
| 698 | ) => Effect.Effect<void, never, S["Context"] | S["insert"]["Context"]> |
| 699 | readonly update: ( |
| 700 | update: S["update"]["Type"] |
| 701 | ) => Effect.Effect<S["Type"], never, S["Context"] | S["update"]["Context"]> |
| 702 | readonly updateVoid: ( |
| 703 | update: S["update"]["Type"] |
| 704 | ) => Effect.Effect<void, never, S["Context"] | S["update"]["Context"]> |
| 705 | readonly findById: ( |
| 706 | id: Schema.Schema.Type<S["fields"][Id]> |
| 707 | ) => Effect.Effect<Option.Option<S["Type"]>, never, S["Context"] | Schema.Schema.Context<S["fields"][Id]>> |
| 708 | readonly delete: ( |
| 709 | id: Schema.Schema.Type<S["fields"][Id]> |
| 710 | ) => Effect.Effect<void, never, Schema.Schema.Context<S["fields"][Id]>> |
| 711 | }, |
| 712 | never, |
| 713 | SqlClient |
| 714 | > => |
| 715 | Effect.gen(function*() { |
| 716 | const sql = yield* SqlClient |
| 717 | const idSchema = Model.fields[options.idColumn] as Schema.Schema.Any |
| 718 | const idColumn = options.idColumn as string |
| 719 | |
| 720 | const insertSchema = SqlSchema.single({ |
| 721 | Request: Model.insert, |
| 722 | Result: Model, |
| 723 | execute: (request) => |
| 724 | sql.onDialectOrElse({ |
| 725 | mysql: () => |
| 726 | sql`insert into ${sql(options.tableName)} ${sql.insert(request)}; |
| 727 | select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID();`.unprepared.pipe( |
| 728 | Effect.map(([, results]) => results as any) |
| 729 | ), |
| 730 | orElse: () => sql`insert into ${sql(options.tableName)} ${sql.insert(request).returning("*")}` |
| 731 | }) |
| 732 | }) |
| 733 | const insert = ( |
| 734 | insert: S["insert"]["Type"] |
| 735 | ): Effect.Effect<S["Type"], never, S["Context"] | S["insert"]["Context"]> => |
| 736 | insertSchema(insert).pipe( |
| 737 | Effect.orDie, |
| 738 | Effect.withSpan(`${options.spanPrefix}.insert`, { |
| 739 | captureStackTrace: false, |
| 740 | attributes: { insert } |
| 741 | }) |