diff --git a/.changeset/famous-otters-wonder.md b/.changeset/famous-otters-wonder.md new file mode 100644 index 0000000000..9f7777d103 --- /dev/null +++ b/.changeset/famous-otters-wonder.md @@ -0,0 +1,5 @@ +--- +"@effect/sql": patch +--- + +infer Model repository id schema from id column name diff --git a/packages/sql/src/Model.ts b/packages/sql/src/Model.ts index 4f2b4c7fc1..660196d381 100644 --- a/packages/sql/src/Model.ts +++ b/packages/sql/src/Model.ts @@ -596,11 +596,13 @@ export const JsonFromString = (Model: S, options: { +export const makeRepository = < + S extends Any, + Id extends (keyof S["Type"]) & (keyof S["update"]["Type"]) & (keyof S["fields"]) +>(Model: S, options: { readonly tableName: string readonly spanPrefix: string - readonly idColumn: (keyof S["Type"]) & (keyof S["update"]["Type"]) - readonly idSchema: Id + readonly idColumn: Id }): Effect.Effect< { readonly insert: ( @@ -609,14 +611,19 @@ export const makeRepository = (Mode readonly update: ( update: S["update"]["Type"] ) => Effect.Effect - readonly findById: (id: Id["Type"]) => Effect.Effect, never, S["Context"] | Id["Context"]> - readonly delete: (id: Id["Type"]) => Effect.Effect + readonly findById: ( + id: Schema.Schema.Type + ) => Effect.Effect, never, S["Context"] | Schema.Schema.Context> + readonly delete: ( + id: Schema.Schema.Type + ) => Effect.Effect> }, never, SqlClient > => Effect.gen(function*() { const sql = yield* SqlClient + const idSchema = Model.fields[options.idColumn] as Schema.Schema.Any const insertSchema = SqlSchema.single({ Request: Model.insert, @@ -654,11 +661,13 @@ export const makeRepository = (Mode ) as any const findByIdSchema = SqlSchema.findOne({ - Request: options.idSchema, + Request: idSchema, Result: Model, execute: (id) => sql`select * from ${sql(options.tableName)} where ${sql(options.idColumn as string)} = ${id}` }) - const findById = (id: Id["Type"]): Effect.Effect, never, S["Context"] | Id["Context"]> => + const findById = ( + id: Schema.Schema.Type + ): Effect.Effect, never, S["Context"] | Schema.Schema.Context> => findByIdSchema(id).pipe( Effect.orDie, Effect.withSpan(`${options.spanPrefix}.findById`, { @@ -668,10 +677,12 @@ export const makeRepository = (Mode ) as any const deleteSchema = SqlSchema.void({ - Request: options.idSchema, + Request: idSchema, execute: (id) => sql`delete from ${sql(options.tableName)} where ${sql(options.idColumn as string)} = ${id}` }) - const delete_ = (id: Id["Type"]): Effect.Effect => + const delete_ = ( + id: Schema.Schema.Type + ): Effect.Effect> => deleteSchema(id).pipe( Effect.orDie, Effect.withSpan(`${options.spanPrefix}.delete`, { @@ -689,24 +700,30 @@ export const makeRepository = (Mode * @since 1.0.0 * @category repository */ -export const makeDataLoaders = (Model: S, options: { - readonly tableName: string - readonly spanPrefix: string - readonly idColumn: (keyof S["Type"]) & (keyof S["update"]["Type"]) - readonly idSchema: Id - readonly window: number - readonly maxBatchSize?: number | undefined -}): Effect.Effect< +export const makeDataLoaders = < + S extends AnyNoContext, + Id extends (keyof S["Type"]) & (keyof S["update"]["Type"]) & (keyof S["fields"]) +>( + Model: S, + options: { + readonly tableName: string + readonly spanPrefix: string + readonly idColumn: Id + readonly window: number + readonly maxBatchSize?: number | undefined + } +): Effect.Effect< { readonly insert: (insert: S["insert"]["Type"]) => Effect.Effect - readonly findById: (id: Id["Type"]) => Effect.Effect> - readonly delete: (id: Id["Type"]) => Effect.Effect + readonly findById: (id: Schema.Schema.Type) => Effect.Effect> + readonly delete: (id: Schema.Schema.Type) => Effect.Effect }, never, SqlClient | Scope > => Effect.gen(function*() { const sql = yield* SqlClient + const idSchema = Model.fields[options.idColumn] as Schema.Schema.Any const insertResolver = yield* SqlResolver.ordered(`${options.spanPrefix}/insert`, { Request: Model.insert, @@ -730,7 +747,7 @@ export const makeDataLoaders = > => + const findById = (id: Schema.Schema.Type): Effect.Effect> => findByIdExecute(id).pipe( Effect.orDie, Effect.withSpan(`${options.spanPrefix}.findById`, { @@ -755,7 +772,7 @@ export const makeDataLoaders = sql`delete from ${sql(options.tableName)} where ${sql.in(options.idColumn as string, ids)}` }) const deleteLoader = yield* RRX.dataLoader(deleteResolver, { @@ -763,7 +780,7 @@ export const makeDataLoaders = => + const delete_ = (id: Schema.Schema.Type): Effect.Effect => deleteExecute(id).pipe( Effect.orDie, Effect.withSpan(`${options.spanPrefix}.delete`, {