@shivaedev/effect-test-sql 0.6.0 → 0.7.0

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0 - 2026-10-19
4
+
5
+ ### Added
6
+
7
+ - `PostgresTestOptions` accepts effect-sql's `SqlNameTransforms`, including the options returned by `clientOptions`, for preparation, shared and isolated PostgreSQL clients. Reuse the app's client options without a test-only name mapping.
8
+ - `assertModelColumns` uses the current PostgreSQL client's name transforms to compare database columns with model fields and report mismatches in model field names. Calls without a configured mapping retain literal column comparisons.
9
+
10
+ ## 0.6.1 - 2026-10-18
11
+
12
+ ### Changed
13
+
14
+ - Release with updated workspace dependencies.
15
+
3
16
  ## 0.6.0 - 2026-10-18
4
17
 
5
18
  ### Added
package/README.md CHANGED
@@ -79,6 +79,20 @@ const layer = makePostgresTestLayer({
79
79
  });
80
80
  ```
81
81
 
82
+ ### Reuse the app's SQL name mapping
83
+
84
+ `PostgresTestOptions` accepts effect-sql's native `transformQueryNames` and `transformResultNames`. Spread the same options returned by `clientOptions` that the app host uses; the test layer carries them into preparation, the shared database, `withIsolatedDatabase` and story clones:
85
+
86
+ ```ts
87
+ const layer = makePostgresTestLayer({
88
+ ...appClientOptions,
89
+ url: testDatabaseUrl,
90
+ migrations: appMigrations,
91
+ });
92
+ ```
93
+
94
+ Declare the mapping once in `appClientOptions`, for example with `clientOptions(config, { snakeCase: true })`. The test URL selects the administrative database independently of the app's database URL. Omitting transforms preserves SQL names.
95
+
82
96
  ### Budget PostgreSQL connections
83
97
 
84
98
  Each database pool opens connections on demand, with a default maximum of **two**: the shared database can use two, and each active per-test or per-story clone can use another two. Preparation uses the same limit and closes before tests start. An administrative connection exists only during a create or drop operation and closes as soon as that operation finishes; idle workers keep no administrative connection. Set `maxConnections` on `makePostgresTestLayer` to override the limit for the suite's preparation, shared and isolated pools:
@@ -202,6 +216,8 @@ yield* assertModelColumns(columns, Item, {
202
216
 
203
217
  Use `prepare: false` when preparing the test Layer, and `withIsolatedDatabase` for the upgrade test. The helper requires the native `SqlClient`; loader dependencies remain Effect requirements. Unknown starting ids, populated ledgers and wrapping transactions fail with `MigrationError`. Native loader and SQL failures retain their failure channel.
204
218
 
219
+ With a PostgreSQL client in the current Context, the assertion compares names through that client's query and result name transforms and reports problems in model field terms. Without a client or configured transforms it compares literal names.
220
+
205
221
  The assertion uses the SQL `Model`'s selected database fields, including generated ids and excluding JSON-only fields. Supply an exact PostgreSQL type for every field: schemas such as `Schema.Number` do not determine whether storage is `integer`, `numeric` or `double precision`. It fails with a typed `ModelColumnMismatch` containing all detected missing, extra and wrongly typed column problems. The type map is checked against the model both by TypeScript and at runtime. This check covers names and types; it does not check defaults, nullability, constraints or application data transformations.
206
222
 
207
223
  ### API
@@ -210,7 +226,7 @@ Import each name from the module that defines it. The package has no root entry.
210
226
 
211
227
  | Module | Exports |
212
228
  | --- | --- |
213
- | `@shivaedev/effect-test-sql/postgres.ts` | `makePostgresTestLayer({ url, migrations, fixtures?, maxConnections?, prepare? })`, `PostgresTestOptions`, `PostgresTestLoader` |
229
+ | `@shivaedev/effect-test-sql/postgres.ts` | `makePostgresTestLayer({ url, migrations, fixtures?, maxConnections?, prepare?, transformQueryNames?, transformResultNames? })`, `PostgresTestOptions`, `PostgresTestLoader` |
214
230
  | `@shivaedev/effect-test-sql/withTestTransaction.ts` | `withTestTransaction(effect)` |
215
231
  | `@shivaedev/effect-test-sql/withIsolatedDatabase.ts` | `withIsolatedDatabase(effect, { template? }?)` |
216
232
  | `@shivaedev/effect-test-sql/database.ts` | `PostgresTestDatabase`, `PostgresTestDatabaseService`, `PostgresTestServices`, `PostgresTestTemplate` |
@@ -8,8 +8,6 @@ export declare class ModelColumnMismatch extends ModelColumnMismatch_base<{
8
8
  readonly problems: readonly string[];
9
9
  }> {
10
10
  }
11
- export declare function assertModelColumns<TModel extends Model.Any>(columns: readonly PostgresColumn[], model: TModel, types: {
12
- readonly [TField in keyof NoInfer<TModel>["fields"]]: string;
13
- }): Effect.Effect<void, never, never> | Effect.Effect<never, ModelColumnMismatch, never>;
11
+ export declare const assertModelColumns: <TModel extends Model.Any>(columns: readonly PostgresColumn[], model: TModel, types: { readonly [TField in keyof NoInfer<TModel>["fields"]]: string; }) => Effect.Effect<void, ModelColumnMismatch, never>;
14
12
  export {};
15
13
  //# sourceMappingURL=assertModelColumns.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assertModelColumns.d.ts","sourceRoot":"","sources":["../../src/server/assertModelColumns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;;;;AAE5D,qBAAa,mBAAoB,SAAQ,yBAAwC;IAChF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC,CAAC;CAAG;AAEL,wBAAgB,kBAAkB,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,EAC1D,OAAO,EAAE,SAAS,cAAc,EAAE,EAClC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,IAAI,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,MAAM;CAAE,wFA2BvE"}
1
+ {"version":3,"file":"assertModelColumns.d.ts","sourceRoot":"","sources":["../../src/server/assertModelColumns.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,MAAM,EAAU,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;;;;AAE5D,qBAAa,mBAAoB,SAAQ,yBAAwC;IAChF,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC,CAAC;CAAG;AAEL,eAAO,MAAM,kBAAkB,GAA2D,MAAM,SAAS,KAAK,CAAC,GAAG,wEAG9F,MAAM,mGAqCxB,CAAC"}
@@ -1,12 +1,22 @@
1
- import { Data, Effect } from "effect";
1
+ import * as PgClient from "@effect/sql-pg/PgClient";
2
+ import { Data, Effect, Option } from "effect";
2
3
  export class ModelColumnMismatch extends Data.TaggedError("ModelColumnMismatch") {
3
4
  }
4
- export function assertModelColumns(columns, model, types) {
5
+ export const assertModelColumns = Effect.fn("PostgresTest.assertModelColumns")(function* (columns, model, types) {
6
+ const client = yield* Effect.serviceOption(PgClient.PgClient);
7
+ const config = Option.getOrUndefined(client)?.config;
8
+ const queryFields = new Map(Object.keys(model.fields).map((name) => [config?.transformQueryNames?.(name) ?? name, name]));
9
+ function fieldName(name) {
10
+ return queryFields.get(name) ?? config?.transformResultNames?.(name) ?? name;
11
+ }
5
12
  const expectedTypes = types;
6
- const actual = new Map(columns.map(({ name, type }) => [name, type]));
13
+ function columnKey(name) {
14
+ return config?.transformQueryNames === undefined ? fieldName(name) : name;
15
+ }
16
+ const actual = new Map(columns.map(({ name, type }) => [columnKey(name), type]));
7
17
  const problems = [];
8
18
  for (const name of Object.keys(model.fields)) {
9
- const type = actual.get(name);
19
+ const type = actual.get(config?.transformQueryNames?.(name) ?? name);
10
20
  if (type === undefined) {
11
21
  problems.push(`Missing column: ${name}`);
12
22
  }
@@ -17,8 +27,9 @@ export function assertModelColumns(columns, model, types) {
17
27
  problems.push(`Missing expected PostgreSQL type: ${name}`);
18
28
  }
19
29
  }
20
- for (const { name } of columns) {
21
- if (!Object.hasOwn(model.fields, name)) {
30
+ for (const column of columns) {
31
+ const name = fieldName(column.name);
32
+ if (!queryFields.has(columnKey(column.name))) {
22
33
  problems.push(`Extra column: ${name}`);
23
34
  }
24
35
  }
@@ -27,6 +38,6 @@ export function assertModelColumns(columns, model, types) {
27
38
  problems.push(`Extra expected PostgreSQL type: ${name}`);
28
39
  }
29
40
  }
30
- return problems.length === 0 ? Effect.void : Effect.fail(new ModelColumnMismatch({ problems }));
31
- }
41
+ return yield* problems.length === 0 ? Effect.void : Effect.fail(new ModelColumnMismatch({ problems }));
42
+ });
32
43
  //# sourceMappingURL=assertModelColumns.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assertModelColumns.js","sourceRoot":"","sources":["../../src/server/assertModelColumns.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAItC,MAAM,OAAO,mBAAoB,SAAQ,IAAI,CAAC,WAAW,CAAC,qBAAqB,CAE7E;CAAG;AAEL,MAAM,UAAU,kBAAkB,CACjC,OAAkC,EAClC,KAAa,EACb,KAAuE;IAEvE,MAAM,aAAa,GAAqC,KAAK,CAAC;IAC9D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,IAAI,KAAK,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,QAAQ,CAAC,IAAI,CAAC,kBAAkB,IAAI,cAAc,aAAa,CAAC,IAAI,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC;YACzC,QAAQ,CAAC,IAAI,CAAC,qCAAqC,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;IACF,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;IACF,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC,mCAAmC,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;IACF,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,mBAAmB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;AACjG,CAAC"}
1
+ {"version":3,"file":"assertModelColumns.js","sourceRoot":"","sources":["../../src/server/assertModelColumns.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,8 @@ import { Effect, Layer, Redacted } from "effect";
3
3
  import * as Reactivity from "effect/reactivity/Reactivity";
4
4
  import { SqlClient } from "effect/sql";
5
5
  import type { SqlError } from "effect/sql/SqlError";
6
- export declare function connection(url: Redacted.Redacted<string>, maxConnections: number): Layer.Layer<PgClient.PgClient | Reactivity.Reactivity | SqlClient.SqlClient, SqlError, never>;
6
+ import type { SqlNameTransforms } from "@shivaedev/effect-sql/clientOptions.ts";
7
+ export declare function connection(url: Redacted.Redacted<string>, maxConnections: number, transforms: SqlNameTransforms): Layer.Layer<PgClient.PgClient | Reactivity.Reactivity | SqlClient.SqlClient, SqlError, never>;
7
8
  export declare const administer: <A>(url: Redacted.Redacted<string>, operation: (admin: PgClient.PgClient) => Effect.Effect<A, SqlError>) => Effect.Effect<A, SqlError, never>;
8
9
  export declare const database: (url: Redacted.Redacted<string>, release: (name: string) => Effect.Effect<unknown>, template?: any) => Effect.Effect<{
9
10
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"databases.d.ts","sourceRoot":"","sources":["../../../src/server/internal/databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAW,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,MAAM,iGAMhF;AAED,eAAO,MAAM,UAAU,GAAmD,CAAC,qDAEvD,QAAQ,CAAC,QAAQ,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,sCAKlE,CAAC;AAEH,eAAO,MAAM,QAAQ,mDAEJ,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;0CAYhD,CAAC"}
1
+ {"version":3,"file":"databases.d.ts","sourceRoot":"","sources":["../../../src/server/internal/databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAW,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAIhF,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,iGAY/G;AAED,eAAO,MAAM,UAAU,GAAmD,CAAC,qDAEvD,QAAQ,CAAC,QAAQ,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,sCAKlE,CAAC;AAEH,eAAO,MAAM,QAAQ,mDAEJ,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;;;0CAYhD,CAAC"}
@@ -4,8 +4,13 @@ import * as Reactivity from "effect/reactivity/Reactivity";
4
4
  import { SqlClient } from "effect/sql";
5
5
  import { connectionLimitHint } from "./connectionLimitHint.js";
6
6
  import { databaseName } from "./databaseOwner.js";
7
- export function connection(url, maxConnections) {
8
- return Layer.effectContext(Effect.map(PgClient.make({ maxConnections, url }), (client) => Context.make(SqlClient.SqlClient, client).pipe(Context.add(PgClient.PgClient, client)))).pipe(Layer.provideMerge(Layer.fresh(Reactivity.layer)));
7
+ export function connection(url, maxConnections, transforms) {
8
+ return Layer.effectContext(Effect.map(PgClient.make({
9
+ maxConnections,
10
+ transformQueryNames: transforms.transformQueryNames,
11
+ transformResultNames: transforms.transformResultNames,
12
+ url,
13
+ }), (client) => Context.make(SqlClient.SqlClient, client).pipe(Context.add(PgClient.PgClient, client)))).pipe(Layer.provideMerge(Layer.fresh(Reactivity.layer)));
9
14
  }
10
15
  export const administer = Effect.fn("PostgresTest.administer")(function* (url, operation) {
11
16
  return yield* Effect.scoped(Effect.flatMap(PgClient.makeClient({ url }), operation).pipe(Effect.mapError(connectionLimitHint))).pipe(Effect.provide(Reactivity.layer));
@@ -1 +1 @@
1
- {"version":3,"file":"databases.js","sourceRoot":"","sources":["../../../src/server/internal/databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,UAAU,CAAC,GAA8B,EAAE,cAAsB;IAChF,OAAO,KAAK,CAAC,aAAa,CACzB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAC7D,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CACtF,CACD,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,QAAQ,CAAC,EACvE,GAA8B,EAC9B,SAAmE;IAEnE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,IAAI,CACnI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAChC,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,QAAQ,CAAC,EACnE,GAA8B,EAC9B,OAAiD,EACjD,QAAQ,GAAG,WAAW;IAEtB,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACvC,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAC3B,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAA,mBAAmB,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAC7F,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CACnB,CAAC;IACF,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"databases.js","sourceRoot":"","sources":["../../../src/server/internal/databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,UAAU,UAAU,CAAC,GAA8B,EAAE,cAAsB,EAAE,UAA6B;IAC/G,OAAO,KAAK,CAAC,aAAa,CACzB,MAAM,CAAC,GAAG,CACT,QAAQ,CAAC,IAAI,CAAC;QACb,cAAc;QACd,mBAAmB,EAAE,UAAU,CAAC,mBAAmB;QACnD,oBAAoB,EAAE,UAAU,CAAC,oBAAoB;QACrD,GAAG;KACH,CAAC,EACF,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAClG,CACD,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,QAAQ,CAAC,EACvE,GAA8B,EAC9B,SAAmE;IAEnE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,IAAI,CACnI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAChC,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,QAAQ,CAAC,EACnE,GAA8B,EAC9B,OAAiD,EACjD,QAAQ,GAAG,WAAW;IAEtB,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACvC,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAC3B,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAA,mBAAmB,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAC7F,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CACnB,CAAC;IACF,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC,CAAC,CAAC"}
@@ -1,14 +1,15 @@
1
1
  import { Effect, Layer, type Redacted, type Scope } from "effect";
2
2
  import * as Reactivity from "effect/reactivity/Reactivity";
3
+ import type { SqlNameTransforms } from "@shivaedev/effect-sql/clientOptions.ts";
3
4
  import { type PostgresMigrationOptions } from "@shivaedev/effect-sql/migrations.ts";
4
5
  import { PostgresTestDatabase, type PostgresTestServices } from "#database.ts";
5
6
  export type PostgresTestLoader<E = never, R = never> = (url: Redacted.Redacted<string>) => Effect.Effect<unknown, E, R | PostgresTestServices | Scope.Scope>;
6
- export interface PostgresTestOptions<E = never, R = never, TFixtures = never> {
7
+ export interface PostgresTestOptions<E = never, R = never, TFixtures = never> extends SqlNameTransforms {
7
8
  readonly fixtures?: Effect.Effect<unknown, E, TFixtures | PostgresTestServices | Scope.Scope> | PostgresTestLoader<E, TFixtures>;
8
9
  readonly maxConnections?: number;
9
10
  readonly migrations: PostgresMigrationOptions<R>;
10
11
  readonly prepare?: boolean;
11
12
  readonly url: Redacted.Redacted<string>;
12
13
  }
13
- export declare function makePostgresTestLayer<E = never, R = never, TFixtures = never>(options: PostgresTestOptions<E, R, TFixtures>): Layer.Layer<import("@effect/sql-pg/PgClient").PgClient | PostgresTestDatabase | Reactivity.Reactivity | import("effect/sql/SqlClient").SqlClient, E | import("effect/sql/Migrator").MigrationError | import("effect/sql/SqlError").SqlError, Exclude<Exclude<Exclude<Exclude<R, import("@effect/sql-pg/PgClient").PgClient | Reactivity.Reactivity | import("effect/sql/SqlClient").SqlClient>, Scope.Scope>, Scope.Scope>, Reactivity.Reactivity> | Exclude<Exclude<Exclude<Exclude<TFixtures, import("@effect/sql-pg/PgClient").PgClient | Reactivity.Reactivity | import("effect/sql/SqlClient").SqlClient>, Scope.Scope>, Scope.Scope>, Reactivity.Reactivity>>;
14
+ export declare function makePostgresTestLayer<E = never, R = never, TFixtures = never>(options: PostgresTestOptions<E, R, TFixtures>): Layer.Layer<import("@effect/sql-pg/PgClient").PgClient | PostgresTestDatabase | Reactivity.Reactivity | import("effect/sql/SqlClient").SqlClient, E | import("effect/sql/Migrator").MigrationError | import("effect/sql/SqlError").SqlError, Exclude<Exclude<Exclude<Exclude<TFixtures, import("@effect/sql-pg/PgClient").PgClient | Reactivity.Reactivity | import("effect/sql/SqlClient").SqlClient>, Scope.Scope>, Scope.Scope>, Reactivity.Reactivity> | Exclude<Exclude<Exclude<Exclude<Exclude<R, Reactivity.Reactivity>, import("@effect/sql-pg/PgClient").PgClient | Reactivity.Reactivity | import("effect/sql/SqlClient").SqlClient>, Scope.Scope>, Scope.Scope>, Reactivity.Reactivity>>;
14
15
  //# sourceMappingURL=postgres.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/server/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,KAAK,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC3E,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAmB,KAAK,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AACrG,OAAO,EAAE,oBAAoB,EAAoC,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAKjH,MAAM,MAAM,kBAAkB,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,IAAI,CACtD,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,KAC1B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,GAAG,oBAAoB,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;AAEvE,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK;IAC3E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,SAAS,GAAG,oBAAoB,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACjI,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;CACxC;AAED,wBAAgB,qBAAqB,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,uoBA+B3H"}
1
+ {"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/server/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,MAAM,EAAE,KAAK,EAAE,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC3E,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAmB,KAAK,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AACrG,OAAO,EAAE,oBAAoB,EAAoC,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAKjH,MAAM,MAAM,kBAAkB,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,IAAI,CACtD,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,KAC1B,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,GAAG,oBAAoB,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;AAEvE,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK,CAAE,SAAQ,iBAAiB;IACtG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,SAAS,GAAG,oBAAoB,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,kBAAkB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACjI,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,wBAAwB,CAAC,CAAC,CAAC,CAAC;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;CACxC;AAED,wBAAgB,qBAAqB,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,uqBA+B3H"}
@@ -13,7 +13,7 @@ export function makePostgresTestLayer(options) {
13
13
  const template = options.prepare === false ? empty : yield* database(options.url, release, empty.name);
14
14
  if (options.prepare !== false) {
15
15
  yield* Effect.scoped(Effect.gen(function* () {
16
- const services = yield* Layer.build(connection(template.url, maxConnections));
16
+ const services = yield* Layer.build(connection(template.url, maxConnections, options));
17
17
  yield* migratePostgres(options.migrations).pipe(Effect.provideContext(services));
18
18
  if (options.fixtures !== undefined) {
19
19
  const fixtures = typeof options.fixtures === "function" ? options.fixtures(template.url) : options.fixtures;
@@ -22,10 +22,10 @@ export function makePostgresTestLayer(options) {
22
22
  }));
23
23
  }
24
24
  const shared = yield* database(options.url, release, template.name);
25
- const services = yield* Layer.build(connection(shared.url, maxConnections));
25
+ const services = yield* Layer.build(connection(shared.url, maxConnections, options));
26
26
  const clone = (source) => Effect.gen(function* () {
27
27
  const target = yield* database(options.url, release, source === "empty" ? empty.name : template.name);
28
- const context = yield* Layer.build(connection(target.url, maxConnections));
28
+ const context = yield* Layer.build(connection(target.url, maxConnections, options));
29
29
  return Context.add(context, PostgresTestDatabase, { awaitCleanup, clone, isolated, url: target.url });
30
30
  });
31
31
  const isolated = clone("migrated");
@@ -1 +1 @@
1
- {"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/server/postgres.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/server/postgres.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/effect-test-sql",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "PostgreSQL rollback and real-commit test isolation for Effect",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/effect-test-sql#readme",
6
6
  "bugs": {
@@ -41,16 +41,17 @@
41
41
  "README.md"
42
42
  ],
43
43
  "dependencies": {
44
- "@shivaedev/effect-sql": "0.6.0"
44
+ "@shivaedev/effect-sql": "0.7.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@effect/sql-pg": "4.0.4",
48
48
  "@effect/vitest": "4.0.4",
49
- "@shivaedev/effect-test": "0.6.0",
50
- "@shivaedev/quality": "0.27.1",
51
- "@shivaedev/test-story": "0.10.0",
49
+ "@shivaedev/effect-test": "0.7.1",
50
+ "@shivaedev/quality": "0.28.0",
51
+ "@shivaedev/test-story": "0.12.0",
52
52
  "@types/node": "24.19.2",
53
53
  "effect": "4.0.4",
54
+ "pg-boss": "12.37.1",
54
55
  "typescript": "7.0.2",
55
56
  "vitest": "5.0.3"
56
57
  },
@@ -1,4 +1,5 @@
1
- import { Data, Effect } from "effect";
1
+ import * as PgClient from "@effect/sql-pg/PgClient";
2
+ import { Data, Effect, Option } from "effect";
2
3
  import type { Model } from "effect/schema";
3
4
  import type { PostgresColumn } from "./migrationUpgrade.ts";
4
5
 
@@ -6,16 +7,25 @@ export class ModelColumnMismatch extends Data.TaggedError("ModelColumnMismatch")
6
7
  readonly problems: readonly string[];
7
8
  }> {}
8
9
 
9
- export function assertModelColumns<TModel extends Model.Any>(
10
+ export const assertModelColumns = Effect.fn("PostgresTest.assertModelColumns")(function* <TModel extends Model.Any>(
10
11
  columns: readonly PostgresColumn[],
11
12
  model: TModel,
12
13
  types: { readonly [TField in keyof NoInfer<TModel>["fields"]]: string },
13
14
  ) {
15
+ const client = yield* Effect.serviceOption(PgClient.PgClient);
16
+ const config = Option.getOrUndefined(client)?.config;
17
+ const queryFields = new Map(Object.keys(model.fields).map((name) => [config?.transformQueryNames?.(name) ?? name, name]));
18
+ function fieldName(name: string) {
19
+ return queryFields.get(name) ?? config?.transformResultNames?.(name) ?? name;
20
+ }
14
21
  const expectedTypes: Readonly<Record<string, string>> = types;
15
- const actual = new Map(columns.map(({ name, type }) => [name, type]));
22
+ function columnKey(name: string) {
23
+ return config?.transformQueryNames === undefined ? fieldName(name) : name;
24
+ }
25
+ const actual = new Map(columns.map(({ name, type }) => [columnKey(name), type]));
16
26
  const problems: string[] = [];
17
27
  for (const name of Object.keys(model.fields)) {
18
- const type = actual.get(name);
28
+ const type = actual.get(config?.transformQueryNames?.(name) ?? name);
19
29
  if (type === undefined) {
20
30
  problems.push(`Missing column: ${name}`);
21
31
  } else if (type !== expectedTypes[name]) {
@@ -25,8 +35,9 @@ export function assertModelColumns<TModel extends Model.Any>(
25
35
  problems.push(`Missing expected PostgreSQL type: ${name}`);
26
36
  }
27
37
  }
28
- for (const { name } of columns) {
29
- if (!Object.hasOwn(model.fields, name)) {
38
+ for (const column of columns) {
39
+ const name = fieldName(column.name);
40
+ if (!queryFields.has(columnKey(column.name))) {
30
41
  problems.push(`Extra column: ${name}`);
31
42
  }
32
43
  }
@@ -35,5 +46,5 @@ export function assertModelColumns<TModel extends Model.Any>(
35
46
  problems.push(`Extra expected PostgreSQL type: ${name}`);
36
47
  }
37
48
  }
38
- return problems.length === 0 ? Effect.void : Effect.fail(new ModelColumnMismatch({ problems }));
39
- }
49
+ return yield* problems.length === 0 ? Effect.void : Effect.fail(new ModelColumnMismatch({ problems }));
50
+ });
@@ -3,13 +3,20 @@ import { Context, Effect, Layer, Redacted } from "effect";
3
3
  import * as Reactivity from "effect/reactivity/Reactivity";
4
4
  import { SqlClient } from "effect/sql";
5
5
  import type { SqlError } from "effect/sql/SqlError";
6
+ import type { SqlNameTransforms } from "@shivaedev/effect-sql/clientOptions.ts";
6
7
  import { connectionLimitHint } from "./connectionLimitHint.ts";
7
8
  import { databaseName } from "./databaseOwner.ts";
8
9
 
9
- export function connection(url: Redacted.Redacted<string>, maxConnections: number) {
10
+ export function connection(url: Redacted.Redacted<string>, maxConnections: number, transforms: SqlNameTransforms) {
10
11
  return Layer.effectContext(
11
- Effect.map(PgClient.make({ maxConnections, url }), (client) =>
12
- Context.make(SqlClient.SqlClient, client).pipe(Context.add(PgClient.PgClient, client)),
12
+ Effect.map(
13
+ PgClient.make({
14
+ maxConnections,
15
+ transformQueryNames: transforms.transformQueryNames,
16
+ transformResultNames: transforms.transformResultNames,
17
+ url,
18
+ }),
19
+ (client) => Context.make(SqlClient.SqlClient, client).pipe(Context.add(PgClient.PgClient, client)),
13
20
  ),
14
21
  ).pipe(Layer.provideMerge(Layer.fresh(Reactivity.layer)));
15
22
  }
@@ -1,5 +1,6 @@
1
1
  import { Context, Effect, Layer, type Redacted, type Scope } from "effect";
2
2
  import * as Reactivity from "effect/reactivity/Reactivity";
3
+ import type { SqlNameTransforms } from "@shivaedev/effect-sql/clientOptions.ts";
3
4
  import { migratePostgres, type PostgresMigrationOptions } from "@shivaedev/effect-sql/migrations.ts";
4
5
  import { PostgresTestDatabase, type PostgresTestDatabaseService, type PostgresTestServices } from "#database.ts";
5
6
  import { connectionLimitHint } from "#internal/connectionLimitHint.ts";
@@ -10,7 +11,7 @@ export type PostgresTestLoader<E = never, R = never> = (
10
11
  url: Redacted.Redacted<string>,
11
12
  ) => Effect.Effect<unknown, E, R | PostgresTestServices | Scope.Scope>;
12
13
 
13
- export interface PostgresTestOptions<E = never, R = never, TFixtures = never> {
14
+ export interface PostgresTestOptions<E = never, R = never, TFixtures = never> extends SqlNameTransforms {
14
15
  readonly fixtures?: Effect.Effect<unknown, E, TFixtures | PostgresTestServices | Scope.Scope> | PostgresTestLoader<E, TFixtures>;
15
16
  readonly maxConnections?: number;
16
17
  readonly migrations: PostgresMigrationOptions<R>;
@@ -28,7 +29,7 @@ export function makePostgresTestLayer<E = never, R = never, TFixtures = never>(o
28
29
  if (options.prepare !== false) {
29
30
  yield* Effect.scoped(
30
31
  Effect.gen(function* () {
31
- const services = yield* Layer.build(connection(template.url, maxConnections));
32
+ const services = yield* Layer.build(connection(template.url, maxConnections, options));
32
33
  yield* migratePostgres(options.migrations).pipe(Effect.provideContext(services));
33
34
  if (options.fixtures !== undefined) {
34
35
  const fixtures = typeof options.fixtures === "function" ? options.fixtures(template.url) : options.fixtures;
@@ -38,11 +39,11 @@ export function makePostgresTestLayer<E = never, R = never, TFixtures = never>(o
38
39
  );
39
40
  }
40
41
  const shared = yield* database(options.url, release, template.name);
41
- const services = yield* Layer.build(connection(shared.url, maxConnections));
42
+ const services = yield* Layer.build(connection(shared.url, maxConnections, options));
42
43
  const clone: PostgresTestDatabaseService["clone"] = (source) =>
43
44
  Effect.gen(function* () {
44
45
  const target = yield* database(options.url, release, source === "empty" ? empty.name : template.name);
45
- const context = yield* Layer.build(connection(target.url, maxConnections));
46
+ const context = yield* Layer.build(connection(target.url, maxConnections, options));
46
47
  return Context.add(context, PostgresTestDatabase, { awaitCleanup, clone, isolated, url: target.url });
47
48
  });
48
49
  const isolated = clone("migrated");