@shivaedev/effect-prisma 0.7.1 → 0.9.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 +22 -0
- package/README.md +198 -155
- package/dist/database.d.ts +7 -7
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +12 -8
- package/dist/database.js.map +1 -1
- package/dist/databaseTypes.d.ts +33 -0
- package/dist/databaseTypes.d.ts.map +1 -0
- package/dist/{internal/database-types.js → databaseTypes.js} +1 -1
- package/dist/databaseTypes.js.map +1 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/internal/adapters/transaction-settlement.d.ts.map +1 -1
- package/dist/internal/adapters/transaction-settlement.js +9 -7
- package/dist/internal/adapters/transaction-settlement.js.map +1 -1
- package/dist/internal/client-lifecycle.d.ts.map +1 -1
- package/dist/internal/contract-normalization.d.ts.map +1 -1
- package/dist/internal/database-facade.d.ts +12 -12
- package/dist/internal/database-facade.d.ts.map +1 -1
- package/dist/internal/database-facade.js.map +1 -1
- package/dist/internal/database-factory.d.ts +2 -2
- package/dist/internal/database-factory.d.ts.map +1 -1
- package/dist/internal/database-factory.js +3 -3
- package/dist/internal/database-factory.js.map +1 -1
- package/dist/internal/dynamic.d.ts.map +1 -1
- package/dist/internal/dynamic.js +3 -1
- package/dist/internal/dynamic.js.map +1 -1
- package/dist/internal/executor.d.ts +6 -6
- package/dist/internal/executor.d.ts.map +1 -1
- package/dist/internal/promise.d.ts.map +1 -1
- package/dist/internal/query-execution.d.ts.map +1 -1
- package/dist/internal/recipe.d.ts.map +1 -1
- package/dist/internal/recipe.js +10 -10
- package/dist/internal/recipe.js.map +1 -1
- package/dist/internal/relation-plan.d.ts.map +1 -1
- package/dist/internal/relation-result.d.ts.map +1 -1
- package/dist/internal/relation-result.js +6 -2
- package/dist/internal/relation-result.js.map +1 -1
- package/dist/internal/relation-runtime.d.ts +1 -1
- package/dist/internal/relation-runtime.d.ts.map +1 -1
- package/dist/internal/relation-runtime.js +11 -6
- package/dist/internal/relation-runtime.js.map +1 -1
- package/dist/internal/relation-stream.d.ts +1 -1
- package/dist/internal/relation-stream.d.ts.map +1 -1
- package/dist/internal/relation-stream.js +9 -7
- package/dist/internal/relation-stream.js.map +1 -1
- package/dist/internal/sqlite-datetime.d.ts.map +1 -1
- package/dist/internal/sqlite-datetime.js +11 -9
- package/dist/internal/sqlite-datetime.js.map +1 -1
- package/dist/internal/sqlite-pragmas.d.ts.map +1 -1
- package/dist/internal/testing.d.ts +5 -5
- package/dist/internal/testing.d.ts.map +1 -1
- package/dist/internal/testing.js.map +1 -1
- package/dist/internal/transaction.d.ts +6 -6
- package/dist/internal/transaction.d.ts.map +1 -1
- package/dist/internal/transaction.js +5 -3
- package/dist/internal/transaction.js.map +1 -1
- package/dist/relation/include.d.ts +20 -20
- package/dist/relation/include.d.ts.map +1 -1
- package/dist/relation.d.ts +23 -23
- package/dist/relation.d.ts.map +1 -1
- package/dist/sqlite.d.ts +1 -1
- package/dist/sqlite.d.ts.map +1 -1
- package/dist/sqlite.js +8 -6
- package/dist/sqlite.js.map +1 -1
- package/dist/testing/transaction.d.ts +1 -1
- package/dist/testing/transaction.d.ts.map +1 -1
- package/dist/testing/transaction.js.map +1 -1
- package/dist/testing/types.d.ts +2 -3
- package/dist/testing/types.d.ts.map +1 -1
- package/dist/testing/vitest.d.ts +2 -1
- package/dist/testing/vitest.d.ts.map +1 -1
- package/dist/testing/vitest.js +1 -1
- package/dist/testing/vitest.js.map +1 -1
- package/docs/north-star.md +47 -0
- package/docs/roadmap.md +32 -0
- package/package.json +33 -40
- package/src/database.ts +30 -30
- package/src/databaseTypes.ts +65 -0
- package/src/internal/adapters/transaction-settlement.ts +9 -8
- package/src/internal/database-facade.ts +28 -28
- package/src/internal/database-factory.ts +15 -15
- package/src/internal/dynamic.ts +3 -1
- package/src/internal/executor.ts +6 -6
- package/src/internal/recipe.ts +10 -10
- package/src/internal/relation-result.ts +6 -3
- package/src/internal/relation-runtime.ts +25 -20
- package/src/internal/relation-stream.ts +5 -4
- package/src/internal/sqlite-datetime.ts +11 -9
- package/src/internal/testing.ts +8 -8
- package/src/internal/transaction.ts +16 -15
- package/src/relation/include.ts +48 -48
- package/src/relation.ts +38 -38
- package/src/sqlite.ts +9 -7
- package/src/testing/transaction.ts +1 -1
- package/src/testing/types.ts +2 -3
- package/src/testing/vitest.ts +4 -2
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -1
- package/dist/internal/database-types.d.ts +0 -33
- package/dist/internal/database-types.d.ts.map +0 -1
- package/dist/internal/database-types.js.map +0 -1
- package/dist/testing.d.ts +0 -4
- package/dist/testing.d.ts.map +0 -1
- package/dist/testing.js +0 -3
- package/dist/testing.js.map +0 -1
- package/src/index.ts +0 -17
- package/src/internal/database-types.ts +0 -65
- package/src/testing.ts +0 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0 - 2026-10-13
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Use `T`-prefixed descriptive type parameter names in Relation types and internal testing and transaction helpers, preserving their type behavior.
|
|
8
|
+
- Document the package purpose, query and transaction model, API and limits; add agent guidance and package north star and roadmap, and publish `docs/` with the README.
|
|
9
|
+
- Build package JavaScript, declarations and source maps with TypeScript 7.
|
|
10
|
+
|
|
11
|
+
### Breaking
|
|
12
|
+
|
|
13
|
+
- Requires stable Effect 4.0.4 in place of 4.0.0-rc.112. Effect 4.0.4 moves the former `effect/unstable/*` modules to `effect/*` and renames constructors such as `Config.string` to `Config.String`. Install `@effect/vitest` 4.0.4 alongside it, which requires Vitest 5.
|
|
14
|
+
|
|
15
|
+
## 0.8.0 - 2026-10-04
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Breaking: no root entry and no module that re-exports another. `exports` maps one `"./*.ts"` pattern to every module outside `internal/` (`src` under the `source` condition, `dist` otherwise), and `"./internal/*": null` keeps `internal/` modules private, so you import the module that defines a name, and a bundler sees only the modules you use. Where each name now lives:
|
|
20
|
+
- `@shivaedev/effect-prisma`: `@prisma-next/sql-orm-client` (`all`, `and`, `not`, `or`), `@shivaedev/effect-prisma/databaseTypes.ts` (`AnyDatabase`, `DatabaseService`, `DatabaseServiceOf`), `@shivaedev/effect-prisma/database.ts` (`DatabaseDefinition`, `DatabaseLayerOptions`, `makeDatabase`), `@shivaedev/effect-prisma/error.ts` (`PrismaConnectionFailure`, `PrismaError`, `PrismaErrorReason`, `PrismaQueryFailure`, `PrismaRuntimeFailure`), `@shivaedev/effect-prisma/relation.ts` (`Relation`)
|
|
21
|
+
- `@shivaedev/effect-prisma/testing`: `@shivaedev/effect-prisma/testing/transaction.ts` (`withTestTransaction`), `@shivaedev/effect-prisma/databaseTypes.ts` (`AnyDatabase`), `@shivaedev/effect-prisma/testing/types.ts` (`DatabaseIt`, `DatabaseService`, `DatabaseTest`, `DatabaseTester`, `MakeDatabaseItOptions`), `@shivaedev/effect-prisma/testing/vitest.ts` (`makeDatabaseIt`)
|
|
22
|
+
- `@shivaedev/effect-prisma/sqlite`: `@shivaedev/effect-prisma/sqlite.ts`
|
|
23
|
+
- `all`, `and`, `not` and `or` are no longer re-exported: import them from `@prisma-next/sql-orm-client`. `AnyDatabase`, `DatabaseService` and `DatabaseServiceOf` live in `databaseTypes.ts`, moved out of `internal/` because they are public, and `database.ts` and `testing/types.ts` no longer re-export them.
|
|
24
|
+
|
|
3
25
|
## 0.7.1 - 2026-10-04
|
|
4
26
|
|
|
5
27
|
### Changed
|
package/README.md
CHANGED
|
@@ -1,234 +1,277 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @shivaedev/effect-prisma
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Use Prisma Next's generated model queries in Effect, with typed rows, database transactions and tests that roll their writes back. Keep the contract your application already owns while making database work compose with its Effect services.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
Prisma Next. It is built for ShivaeDev applications and may change without a
|
|
7
|
-
deprecation period.
|
|
5
|
+
## Why you want this
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
A Promise-based database client leaves every Effect application to rebuild the same boundary: translate failures, pass the transaction client through its services and clean up test writes. This package gives that work one Database service:
|
|
10
8
|
|
|
11
|
-
```
|
|
12
|
-
|
|
9
|
+
```ts
|
|
10
|
+
const createUser = Effect.gen(function* () {
|
|
11
|
+
const db = yield* Database;
|
|
12
|
+
return yield* db.transaction(
|
|
13
|
+
Effect.gen(function* () {
|
|
14
|
+
const tx = yield* Database;
|
|
15
|
+
return yield* tx.User.create({
|
|
16
|
+
id: crypto.randomUUID(),
|
|
17
|
+
email: "ada@example.test",
|
|
18
|
+
name: "Ada",
|
|
19
|
+
});
|
|
20
|
+
}),
|
|
21
|
+
);
|
|
22
|
+
});
|
|
13
23
|
```
|
|
14
24
|
|
|
15
|
-
|
|
16
|
-
service:
|
|
25
|
+
`Database` is your application's exported definition. The transaction body yields that same service and uses the same generated models. A successful body commits; a failed body rolls back. The test harness runs that work in a rollback-only transaction, so a test can create real rows without leaving them behind.
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
```
|
|
27
|
+
## Using it
|
|
28
|
+
|
|
29
|
+
### How to think about it
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
There are three things to keep separate:
|
|
32
|
+
|
|
33
|
+
- The **contract** is Prisma Next's description of your database and generated TypeScript model types.
|
|
34
|
+
- A **Database definition** is an Effect service for that contract. Its Layer provides a live database facade.
|
|
35
|
+
- A **Relation** is a reusable model query, such as `db.User.where({ name: "Ada" })`. It is also an Effect: yielding a collection Relation returns its rows.
|
|
36
|
+
|
|
37
|
+
A Relation keeps the calls that describe its query. Branching it creates another query without changing the base. A root Relation resolves the active transaction when it runs; one made from a transaction facade belongs to that transaction's lifetime and context. You do not provide a separate executor service to queries or Streams.
|
|
38
|
+
|
|
39
|
+
Organize application work around these boundaries: define the Database and its Layer once, write reusable queries in each feature's repository, and run those Effects or rollback tests every day. The examples use a contract with `User` and `Post` models: users have `id`, `email`, `name`, `createdAt`, `verifiedAt` and `posts`; posts have `title`, `user` and an optional `reviewer`.
|
|
40
|
+
|
|
41
|
+
### Once per application: define the database
|
|
27
42
|
|
|
28
43
|
```ts
|
|
29
|
-
import { makeDatabase } from "@shivaedev/effect-prisma"
|
|
30
|
-
import {
|
|
44
|
+
import { makeDatabase } from "@shivaedev/effect-prisma/database.ts";
|
|
45
|
+
import type { Contract } from "./generated/contract.d.ts";
|
|
46
|
+
import contractJson from "./generated/contract.json" with { type: "json" };
|
|
31
47
|
|
|
32
48
|
export const Database = makeDatabase<Contract>()("@app/Database", {
|
|
33
49
|
contractJson,
|
|
34
|
-
})
|
|
50
|
+
});
|
|
35
51
|
|
|
36
52
|
export const DatabaseLive = Database.layer({
|
|
37
|
-
url:
|
|
38
|
-
})
|
|
53
|
+
url: "postgresql://localhost/application",
|
|
54
|
+
});
|
|
39
55
|
```
|
|
40
56
|
|
|
41
|
-
|
|
42
|
-
runtime provides one live Layer for that definition. Reuse that singleton;
|
|
43
|
-
duplicate identifiers and multiple simultaneous Layers for one definition are
|
|
44
|
-
outside the supported composition.
|
|
45
|
-
|
|
46
|
-
The Layer owns the PostgreSQL client and closes it with its structured Effect
|
|
47
|
-
scope. Database values do not outlive that scope.
|
|
57
|
+
The type parameter is the generated contract type; `contractJson` is its emitted JSON. Choose one literal identifier for each exported definition. Different identifiers keep two databases distinct even when they use the same contract, including in the types of included queries. Widened strings, unions and template patterns cannot identify one Database.
|
|
48
58
|
|
|
49
|
-
|
|
59
|
+
Reuse the definition and provide one live Layer for it in a composed runtime. Keep values within that Layer's scope: a root Stream or Database facade used after the owning Layer closes fails with `RUNTIME.DATABASE_CLOSED`. A transaction-bound value instead closes with its transaction and fails with `RUNTIME.TRANSACTION_CLOSED` after settlement.
|
|
50
60
|
|
|
51
|
-
|
|
52
|
-
separate entrypoint. Its `DateTime` fields already declare `Date`, so the
|
|
53
|
-
normalization step above is PostgreSQL-only.
|
|
61
|
+
SQLite uses the same query and transaction facade through its own factory:
|
|
54
62
|
|
|
55
63
|
```ts
|
|
56
|
-
import { makeSqliteDatabase } from "@shivaedev/effect-prisma/sqlite"
|
|
57
|
-
import {
|
|
64
|
+
import { makeSqliteDatabase } from "@shivaedev/effect-prisma/sqlite.ts";
|
|
65
|
+
import type { Contract } from "./generated/contract.d.ts";
|
|
66
|
+
import contractJson from "./generated/contract.json" with { type: "json" };
|
|
58
67
|
|
|
59
68
|
export const Database = makeSqliteDatabase<Contract>()("@app/Database", {
|
|
60
69
|
contractJson,
|
|
61
|
-
})
|
|
70
|
+
});
|
|
62
71
|
|
|
63
|
-
export const DatabaseLive = Database.layer({
|
|
64
|
-
path: "app.db",
|
|
65
|
-
})
|
|
72
|
+
export const DatabaseLive = Database.layer({ path: "application.db" });
|
|
66
73
|
```
|
|
67
74
|
|
|
68
|
-
The
|
|
69
|
-
that list. Prisma Next's SQLite driver already sets `foreign_keys` and
|
|
70
|
-
`busy_timeout` on every connection it opens, and it opens a separate connection
|
|
71
|
-
per transaction, so in-memory databases are rejected.
|
|
75
|
+
Use a SQLite contract for this definition. The default connect-time pragma sets `journal_mode=WAL`. SQLite's serialization and file requirements are described under limits below.
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
because SQLite allows a single writer, overlapping write transactions wait for
|
|
75
|
-
`busy_timeout` while blocking that event loop. The supported Database Layer
|
|
76
|
-
therefore serializes finite root query effects and explicit transaction
|
|
77
|
-
lifetimes through one access permit. Transaction-internal queries use a private
|
|
78
|
-
permit for their single connection, while root Streams remain incremental. Do
|
|
79
|
-
not coordinate multiple Database Layers against the same SQLite file.
|
|
77
|
+
### Once per feature: write reusable queries
|
|
80
78
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
79
|
+
```ts
|
|
80
|
+
import { Effect } from "effect";
|
|
81
|
+
import { Database } from "./database.ts";
|
|
82
|
+
|
|
83
|
+
export const findUsersNamed = (name: string) =>
|
|
84
|
+
Effect.gen(function* () {
|
|
85
|
+
const db = yield* Database;
|
|
86
|
+
const matching = db.User.where({ name });
|
|
87
|
+
const names = matching.orderBy((user) => user.email.asc()).select("id", "email");
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
rows: yield* names.take(20),
|
|
91
|
+
first: yield* matching.first(),
|
|
92
|
+
exists: yield* matching.exists(),
|
|
93
|
+
count: yield* matching.count(),
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
```
|
|
88
97
|
|
|
89
|
-
|
|
98
|
+
`matching` remains the full filtered Relation after `names` adds an order and selection. A selection keeps only its named fields in the result type. `first()` returns an Effect `Option`, `exists()` returns a boolean and `count()` returns a number. Object filters and callback filters retain the contract's field types.
|
|
90
99
|
|
|
91
|
-
|
|
100
|
+
Load relations by their contract names:
|
|
92
101
|
|
|
93
102
|
```ts
|
|
94
|
-
|
|
103
|
+
export const userPostOverview = Effect.gen(function* () {
|
|
104
|
+
const db = yield* Database;
|
|
105
|
+
const titles = db.Post.orderBy((post) => post.title.asc()).select("title");
|
|
106
|
+
const page = titles.take(1);
|
|
107
|
+
|
|
108
|
+
return yield* db.User.include("posts", {
|
|
109
|
+
items: page,
|
|
110
|
+
fullCount: db.Post.count(),
|
|
111
|
+
pageCount: page.count(),
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
```
|
|
95
115
|
|
|
96
|
-
|
|
97
|
-
const db = yield* Database
|
|
116
|
+
The `posts` property contains the named projections: a page of titles, the full related count and the page count. `include("posts")` loads the related rows directly; passing a Relation refines them. Includes can nest, as in `db.User.include("posts", db.Post.include("user"))`, and chain, as in `db.Post.include("user").include("reviewer")`. To-many values are arrays; an optional reviewer stays `User | null`.
|
|
98
117
|
|
|
99
|
-
|
|
100
|
-
const newest = active.orderBy((user) => user.createdAt.desc())
|
|
118
|
+
An included query must come from the same Database and use the related model. A named query record must be nonempty and applies only to a to-many relation. The compiler rejects these mismatches; runtime checks also reject foreign databases, wrong models and transaction-bound queries used outside their owner.
|
|
101
119
|
|
|
102
|
-
|
|
103
|
-
const first = yield* active.first()
|
|
104
|
-
const exists = yield* active.exists()
|
|
105
|
-
const count = yield* active.count()
|
|
120
|
+
For grouped summaries and bulk changes, use the generated collection operations:
|
|
106
121
|
|
|
107
|
-
|
|
108
|
-
|
|
122
|
+
```ts
|
|
123
|
+
export const renameUsers = (name: string, replacement: string) =>
|
|
124
|
+
Effect.gen(function* () {
|
|
125
|
+
const db = yield* Database;
|
|
126
|
+
const matching = db.User.where({ name });
|
|
127
|
+
const summary = yield* matching.aggregate((aggregate) => ({
|
|
128
|
+
total: aggregate.count(),
|
|
129
|
+
}));
|
|
130
|
+
const groups = yield* matching.groupBy("name").aggregate((aggregate) => ({
|
|
131
|
+
total: aggregate.count(),
|
|
132
|
+
}));
|
|
133
|
+
const changed = yield* matching.updateAll({ name: replacement });
|
|
134
|
+
return { summary, groups, changed };
|
|
135
|
+
});
|
|
109
136
|
```
|
|
110
137
|
|
|
111
|
-
|
|
112
|
-
the original, and each Relation closes over the Database implementation that
|
|
113
|
-
created it.
|
|
138
|
+
`aggregate` returns the named summary; grouped aggregates also include the grouped fields. `createAll`, `updateAll` and `deleteAll` return rows. Update and delete methods require an explicit filter in the typed API.
|
|
114
139
|
|
|
115
|
-
|
|
140
|
+
### Every day: run effects and transactions
|
|
116
141
|
|
|
117
142
|
```ts
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
143
|
+
const result = await Effect.runPromise(
|
|
144
|
+
findUsersNamed("Ada").pipe(Effect.provide(DatabaseLive)),
|
|
145
|
+
);
|
|
146
|
+
```
|
|
121
147
|
|
|
122
|
-
|
|
148
|
+
Provide the Database Layer to the program that yields its definition. Repository queries remain ordinary Effects that a larger application's Layer can provide.
|
|
123
149
|
|
|
124
|
-
|
|
125
|
-
```
|
|
150
|
+
A transaction body must yield its Database definition. The boundary provides that service for the body while retaining any other service requirements. Nested package transactions reuse the active transaction and its facade; they do not create independent rollback boundaries.
|
|
126
151
|
|
|
127
|
-
|
|
128
|
-
nullable to-one relations remain nullable in the result type.
|
|
152
|
+
A root query captured before a transaction participates when run inside it. A Database, Relation or Stream created from the transaction facade cannot be used after settlement, outside that transaction or in a concurrent sibling transaction. Closed values fail with `RUNTIME.TRANSACTION_CLOSED`; values used in another active context fail with `RUNTIME.TRANSACTION_CONTEXT_MISMATCH`.
|
|
129
153
|
|
|
130
|
-
|
|
154
|
+
Successful transactions commit. Typed failures and interruption roll back before returning. Queries sharing the transaction connection execute one at a time. Once such a query starts, interruption waits for it to settle before another query or transaction settlement uses the connection.
|
|
155
|
+
|
|
156
|
+
Collection Relations also expose reusable Streams:
|
|
131
157
|
|
|
132
158
|
```ts
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
})
|
|
159
|
+
import { Stream } from "effect";
|
|
160
|
+
|
|
161
|
+
export const userEmails = Effect.gen(function* () {
|
|
162
|
+
const db = yield* Database;
|
|
163
|
+
return yield* Stream.runCollect(
|
|
164
|
+
db.User.select("email").stream.pipe(Stream.map((user) => user.email)),
|
|
165
|
+
);
|
|
166
|
+
});
|
|
142
167
|
```
|
|
143
168
|
|
|
144
|
-
|
|
169
|
+
Outside transactions the source emits incrementally. Inside a transaction the package buffers the source before downstream work runs, so a downstream database query can use the same connection. Account for the full result's memory use in a transaction.
|
|
170
|
+
|
|
171
|
+
### Every day: test real writes with rollback
|
|
172
|
+
|
|
173
|
+
Define the application's database test harness once:
|
|
145
174
|
|
|
146
175
|
```ts
|
|
147
|
-
|
|
176
|
+
import { makeDatabaseIt } from "@shivaedev/effect-prisma/testing/vitest.ts";
|
|
177
|
+
import { Database, DatabaseTest } from "./database-test.ts";
|
|
178
|
+
|
|
179
|
+
export const it = makeDatabaseIt({
|
|
180
|
+
database: Database,
|
|
181
|
+
layer: DatabaseTest,
|
|
182
|
+
});
|
|
148
183
|
```
|
|
149
184
|
|
|
150
|
-
|
|
151
|
-
ordering, pagination, distinct queries, aggregates, grouping, and
|
|
152
|
-
create/update/delete terminals. Model variants are deliberately deferred rather
|
|
153
|
-
than exposed with weakened types.
|
|
185
|
+
`DatabaseTest` is the application's Layer for an initialized test database. A test receives the typed facade and Vitest context:
|
|
154
186
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
187
|
+
```ts
|
|
188
|
+
import { expect } from "vitest";
|
|
189
|
+
import { it } from "./database-it.ts";
|
|
158
190
|
|
|
159
|
-
|
|
191
|
+
it.effectDB("creates a user", function* (db, context) {
|
|
192
|
+
const email = `${crypto.randomUUID()}@example.test`;
|
|
193
|
+
const user = yield* db.User.create({
|
|
194
|
+
id: crypto.randomUUID(),
|
|
195
|
+
email,
|
|
196
|
+
name: "Ada",
|
|
197
|
+
});
|
|
160
198
|
|
|
161
|
-
|
|
199
|
+
expect(user.email).toBe(email);
|
|
200
|
+
expect(context.task.name).toContain("creates a user");
|
|
201
|
+
});
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Successful and failing test bodies both roll back their writes. `effectDB.each` takes each table item before the database and context; `effectDB.fails` declares an expected failure. Ordinary transactions nested inside a rollback test share its scope and are rolled back with it.
|
|
205
|
+
|
|
206
|
+
For another test runner, wrap an Effect with the rollback primitive:
|
|
162
207
|
|
|
163
208
|
```ts
|
|
164
|
-
|
|
209
|
+
import { withTestTransaction } from "@shivaedev/effect-prisma/testing/transaction.ts";
|
|
210
|
+
|
|
211
|
+
const testProgram = withTestTransaction(
|
|
212
|
+
Database,
|
|
165
213
|
Effect.gen(function* () {
|
|
166
|
-
const db = yield* Database
|
|
167
|
-
yield* db.User.
|
|
168
|
-
id,
|
|
169
|
-
email,
|
|
170
|
-
name,
|
|
171
|
-
})
|
|
214
|
+
const db = yield* Database;
|
|
215
|
+
return yield* db.User.count();
|
|
172
216
|
}),
|
|
173
|
-
)
|
|
217
|
+
).pipe(Effect.provide(DatabaseTest));
|
|
174
218
|
```
|
|
175
219
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
settlement.
|
|
220
|
+
The primitive returns the body's value or preserves its failure while rolling back. A rollback-only boundary inside an ordinary commit transaction is refused with `RUNTIME.TEST_TRANSACTION_INSIDE_TRANSACTION_UNSUPPORTED`; nesting another boundary inside an existing rollback test shares that test's transaction.
|
|
221
|
+
|
|
222
|
+
### API
|
|
223
|
+
|
|
224
|
+
Import the defining module; the package has no root entry point.
|
|
182
225
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
226
|
+
| Module | Public surface |
|
|
227
|
+
| --- | --- |
|
|
228
|
+
| `database.ts` | `makeDatabase<Contract>()(identifier, { contractJson })`, `DatabaseDefinition`, `DatabaseLayerOptions`. Factory options also accept an already typed `contract`. |
|
|
229
|
+
| `sqlite.ts` | `makeSqliteDatabase<Contract>()(identifier, options)`, `defaultSqlitePragmas`, `SqliteDatabaseDefinition`, `SqliteDatabaseLayerOptions`. Layer options include `path` and `pragmas`. |
|
|
230
|
+
| `databaseTypes.ts` | `DatabaseService<Contract, Identifier>`, `DatabaseServiceOf<typeof Database>`, `AnyDatabase`, `DatabaseIdentifier`, `DatabaseIdentifierLiteral`, `DatabaseServiceHolder`, `DefaultModels`, `SqlDatabase`, `internalContextIdentifierPrefix`. |
|
|
231
|
+
| `relation.ts` | `Relation`, `RelationQuery`, `CollectionResult`. |
|
|
232
|
+
| `error.ts` | `PrismaError`, `PrismaErrorReason`, `PrismaRuntimeFailure`, `PrismaQueryFailure`, `PrismaConnectionFailure`, `isPrismaFailure`, `toPrismaError`. |
|
|
233
|
+
| `testing/vitest.ts` | `makeDatabaseIt({ database, layer, clock? })`. |
|
|
234
|
+
| `testing/transaction.ts` | `withTestTransaction(database, program)` and `withTestTransaction(database)(program)`. |
|
|
235
|
+
| `testing/types.ts` | `DatabaseIt`, `DatabaseTester`, `DatabaseTest`, `DatabaseService`, `MakeDatabaseItOptions`. |
|
|
236
|
+
| `relation/include.ts`, `relation/include-metadata.ts`, `relation/prisma-methods.ts` | Supporting types: `IncludeMethod`, `AnyPostgresContract`, `IsToManyRelation`, `RelatedModelNameOf`, `IncludedRelationValue`, `PrismaRelationMethods`. |
|
|
237
|
+
| `effect-prisma-normalize` | Executable taking one generated contract declaration path. |
|
|
187
238
|
|
|
188
|
-
|
|
189
|
-
on its single connection. Once a transaction query starts, interruption waits
|
|
190
|
-
for it to settle before releasing that connection. PostgreSQL query effects
|
|
191
|
-
outside transactions remain parallel. SQLite root query effects execute one at
|
|
192
|
-
a time and do not overlap an explicit transaction lifetime, so a root write
|
|
193
|
-
cannot invalidate the transaction's WAL snapshot.
|
|
239
|
+
The Relation surface follows Prisma Next's collections. Its typed operations include filters and ordering; `select`, `take`, `cursor`, `distinct`, `distinctOn`; `include`, `count`, `exists`, `first`; `aggregate`, `groupBy`; and create, update and delete terminals. Cursor and distinct-on types require an order first. Import boolean filter combinators such as `and`, `or`, `not` and `all` from `@prisma-next/sql-orm-client`.
|
|
194
240
|
|
|
195
|
-
|
|
196
|
-
releases the connection before downstream Stream effects run database queries.
|
|
197
|
-
Streams outside transactions retain incremental fetching.
|
|
241
|
+
A `PrismaError` carries a tagged `reason`. Unique-constraint tests verify `PrismaQueryFailure` with `sqlState` and `constraint`; scope and transaction guards use `PrismaRuntimeFailure` with `code`. Unknown Promise rejections remain defects rather than becoming typed database failures.
|
|
198
242
|
|
|
199
|
-
|
|
243
|
+
`effectDB` also exposes the declared `skip`, `skipIf`, `runIf` and `only` methods. Its options and factory accept `clock`; see the [Effect test runner](https://github.com/ShivaeDev/platform/tree/main/packages/effect-test#readme) for the shared option types and clock model.
|
|
200
244
|
|
|
201
|
-
Install
|
|
245
|
+
### Install and contract setup
|
|
202
246
|
|
|
203
247
|
```sh
|
|
204
|
-
pnpm add
|
|
248
|
+
pnpm add @shivaedev/effect-prisma effect@4.0.4
|
|
249
|
+
pnpm add --save-dev @effect/vitest@4.0.4 vitest@5.0.3
|
|
205
250
|
```
|
|
206
251
|
|
|
207
|
-
|
|
252
|
+
The Vitest dependencies are needed only for `testing/vitest.ts`. Use Node.js 24 or newer and compatible versions of the package's Effect and Prisma Next dependencies.
|
|
208
253
|
|
|
209
|
-
|
|
210
|
-
|
|
254
|
+
The application owns its Prisma Next CLI/configuration, initialized schema and
|
|
255
|
+
migration workflow. This package does not apply schema changes. Emit that
|
|
256
|
+
application's contract, then normalize its PostgreSQL declaration:
|
|
211
257
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
})
|
|
258
|
+
```sh
|
|
259
|
+
prisma-next contract emit
|
|
260
|
+
effect-prisma-normalize path/to/generated/contract.d.ts
|
|
216
261
|
```
|
|
217
262
|
|
|
218
|
-
|
|
263
|
+
Normalization replaces supported PostgreSQL timestamp declarations with `Date`, preserves other fields and can run twice. An unsupported timestamp declaration fails without overwriting the generated file. PostgreSQL timestamp and timestamp-with-time-zone fields accept and return JavaScript `Date` values; the tests exercise writes, reads and equality filters. SQLite `DateTime` declarations already use `Date` and do not need this PostgreSQL step.
|
|
219
264
|
|
|
220
|
-
|
|
221
|
-
it.effectDB("creates a user", function* (db) {
|
|
222
|
-
const user = yield* db.User.create({
|
|
223
|
-
id,
|
|
224
|
-
email,
|
|
225
|
-
name,
|
|
226
|
-
})
|
|
265
|
+
SQLite datetime text without a zone is decoded as UTC, including the `datetime('now')` column default. Text that already contains `Z` or a numeric offset is left unchanged. That generated default has whole-second precision.
|
|
227
266
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
267
|
+
### Limits
|
|
268
|
+
|
|
269
|
+
- Use one exported definition and one live Layer per identifier. Duplicate identifiers or multiple simultaneous Layers for one definition are outside the supported composition.
|
|
270
|
+
- Keep Database values inside their Layer and transaction lifetimes. Return rows from a transaction rather than its facade or queries.
|
|
271
|
+
- PostgreSQL contracts must have one domain namespace. A model named `transaction` conflicts with the facade's transaction method.
|
|
272
|
+
- SQLite needs a file-backed database; `:memory:` and an empty path are rejected. Its driver uses synchronous database calls. Treat it as a local database path and avoid coordinating separate Layers against the same file.
|
|
273
|
+
- One SQLite Layer serializes finite root query Effects with the entire explicit transaction lifetime. Transaction queries have a separate permit. Root Streams remain incremental; do not treat them as holding that lifetime permit.
|
|
274
|
+
- Transaction Streams buffer the full result. Refine large queries before collecting them in a transaction.
|
|
275
|
+
- The API excludes model variants and direct scalar aggregate shortcuts; use the typed `aggregate` callback. Prisma Next features are not automatically package guarantees.
|
|
231
276
|
|
|
232
|
-
|
|
233
|
-
`fails` variants. Tests install TestClock unless you pass `clock: "live"`.
|
|
234
|
-
`withTestTransaction` is also exported for custom harnesses.
|
|
277
|
+
The [roadmap](https://github.com/ShivaeDev/platform/blob/main/packages/effect-prisma/docs/roadmap.md) records package status and maintainer questions. The tests distinguish real PostgreSQL behavior, file-backed SQLite behavior and controlled execution tests; PostgreSQL tests skip when their database URL is absent.
|
package/dist/database.d.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { type PostgresOptionsBase } from "@prisma-next/postgres/runtime";
|
|
2
2
|
import { type Layer, Redacted } from "effect";
|
|
3
|
-
import type { DatabaseIdentifier, DatabaseIdentifierLiteral, DatabaseServiceHolder } from "#
|
|
3
|
+
import type { DatabaseIdentifier, DatabaseIdentifierLiteral, DatabaseServiceHolder } from "#databaseTypes.ts";
|
|
4
4
|
import type { AnySqlContract } from "#internal/executor.ts";
|
|
5
5
|
import type { PrismaError } from "./error.ts";
|
|
6
|
-
export type { AnyDatabase, DatabaseService, DatabaseServiceOf, } from "#internal/database-types.ts";
|
|
7
6
|
export interface DatabaseLayerOptions extends PostgresOptionsBase {
|
|
8
7
|
readonly url: string | Redacted.Redacted<string>;
|
|
9
8
|
}
|
|
10
|
-
type DatabaseFactoryOptions<
|
|
11
|
-
readonly contract:
|
|
9
|
+
type DatabaseFactoryOptions<TContract extends AnySqlContract> = {
|
|
10
|
+
readonly contract: TContract;
|
|
12
11
|
readonly contractJson?: never;
|
|
13
12
|
} | {
|
|
14
13
|
readonly contractJson: unknown;
|
|
15
14
|
readonly contract?: never;
|
|
16
15
|
};
|
|
17
|
-
export interface DatabaseDefinition<
|
|
18
|
-
readonly layer: (options: DatabaseLayerOptions) => Layer.Layer<DatabaseIdentifier<
|
|
16
|
+
export interface DatabaseDefinition<TContract extends AnySqlContract, TIdentifier extends string> extends DatabaseServiceHolder<TContract, TIdentifier> {
|
|
17
|
+
readonly layer: (options: DatabaseLayerOptions) => Layer.Layer<DatabaseIdentifier<TContract, TIdentifier>, PrismaError>;
|
|
19
18
|
}
|
|
20
|
-
export declare const makeDatabase: <const
|
|
19
|
+
export declare const makeDatabase: <const TContract extends AnySqlContract>() => <const TIdentifier extends string>(identifier: DatabaseIdentifierLiteral<TIdentifier>, options: DatabaseFactoryOptions<TContract>) => DatabaseDefinition<TContract, TIdentifier>;
|
|
20
|
+
export {};
|
|
21
21
|
//# sourceMappingURL=database.d.ts.map
|
package/dist/database.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAiB,EAAuB,KAAK,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACxG,OAAO,EAAE,KAAK,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAiB,EAAuB,KAAK,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACxG,OAAO,EAAE,KAAK,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,qBAAqB,EAAiB,MAAM,mBAAmB,CAAC;AAI7H,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAChE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;CACjD;AAED,KAAK,sBAAsB,CAAC,SAAS,SAAS,cAAc,IACzD;IACA,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC;CAC7B,GACD;IACA,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,KAAK,CAAC;CACzB,CAAC;AAEL,MAAM,WAAW,kBAAkB,CAAC,SAAS,SAAS,cAAc,EAAE,WAAW,SAAS,MAAM,CAC/F,SAAQ,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;CACxH;AAkBD,eAAO,MAAM,YAAY,GACvB,KAAK,CAAC,SAAS,SAAS,cAAc,QACtC,KAAK,CAAC,WAAW,SAAS,MAAM,cACpB,yBAAyB,CAAC,WAAW,CAAC,WACzC,sBAAsB,CAAC,SAAS,CAAC,KACxC,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAgC3C,CAAC"}
|
package/dist/database.js
CHANGED
|
@@ -4,14 +4,18 @@ import { acquireConnectedClient } from "#internal/client-lifecycle.ts";
|
|
|
4
4
|
import { namespaceModels } from "#internal/database-facade.ts";
|
|
5
5
|
import { makeSqlDatabase } from "#internal/database-factory.ts";
|
|
6
6
|
import { fromPrismaPromise } from "#internal/promise.ts";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
})
|
|
14
|
-
|
|
7
|
+
function clientOptions({ url, extensions, middleware, poolOptions, verifyMarker }) {
|
|
8
|
+
return {
|
|
9
|
+
url: typeof url === "string" ? url : Redacted.value(url),
|
|
10
|
+
...(extensions === undefined ? {} : { extensions }),
|
|
11
|
+
...(middleware === undefined ? {} : { middleware }),
|
|
12
|
+
...(poolOptions === undefined ? {} : { poolOptions }),
|
|
13
|
+
...(verifyMarker === undefined ? {} : { verifyMarker }),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function defaultModels(client) {
|
|
17
|
+
return namespaceModels(client.contract, client.orm);
|
|
18
|
+
}
|
|
15
19
|
export const makeDatabase = () => (identifier, options) => {
|
|
16
20
|
return makeSqlDatabase(identifier, (layerOptions) => {
|
|
17
21
|
const forwarded = clientOptions(layerOptions);
|
package/dist/database.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAiD,MAAM,+BAA+B,CAAC;AACxG,OAAO,EAAc,QAAQ,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAiD,MAAM,+BAA+B,CAAC;AACxG,OAAO,EAAc,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAsBzD,SAAS,aAAa,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAwB;IACtG,OAAO;QACN,GAAG,EAAE,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;QACxD,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;QACnD,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;QACnD,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACrD,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC;KACvD,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CACrB,MAA2D;IAE3D,OAAO,eAAe,CAAqB,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GACxB,GAA2C,EAAE,CAC7C,CACC,UAAkD,EAClD,OAA0C,EACG,EAAE;IAG/C,OAAO,eAAe,CAA+C,UAAU,EAAE,CAAC,YAAY,EAAE,EAAE;QACjG,MAAM,SAAS,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;QAC9C,MAAM,MAAM,GACX,OAAO,CAAC,QAAQ,KAAK,SAAS;YAC7B,CAAC,CAAC,QAAQ,CAAY;gBACpB,GAAG,SAAS;gBACZ,YAAY,EAAE,OAAO,CAAC,YAAY;aAClC,CAAC;YACH,CAAC,CAAC,QAAQ,CAAY;gBACpB,GAAG,SAAS;gBACZ,QAAQ,EAAE,OAAO,CAAC,QAAQ;aAC1B,CAAC,CAAC;QAEN,OAAO,iBAAiB,CAAC,GAAG,EAAE,CAC7B,sBAAsB,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACrC,MAAM;YACN,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE;gBACT,UAAU,EAAE,yBAAyB;gBACrC,IAAI,EAAE,IAAI;aACV;YACD,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,aAAa,CAAoB,MAAM,CAAC;YAChD,cAAc,EAAE,SAAS;YACzB,mBAAmB,EAAE,SAAS;YAC9B,oBAAoB,EAAE,SAAS;SAC/B,CAAC,CAAC,CACH,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { orm } from "@prisma-next/sql-orm-client";
|
|
2
|
+
import type { Context, Effect, Layer } from "effect";
|
|
3
|
+
import type { PrismaError } from "#error.ts";
|
|
4
|
+
import type { AnySqlContract } from "#internal/executor.ts";
|
|
5
|
+
import type { Relation } from "#relation.ts";
|
|
6
|
+
type OrmFor<TContract extends AnySqlContract> = ReturnType<typeof orm<TContract>>;
|
|
7
|
+
type DefaultNamespaceId<TContract extends AnySqlContract> = "__unbound__" extends keyof OrmFor<TContract> ? "__unbound__" : "public" extends keyof OrmFor<TContract> ? "public" : keyof OrmFor<TContract>;
|
|
8
|
+
export type DefaultModels<TContract extends AnySqlContract> = OrmFor<TContract>[DefaultNamespaceId<TContract>] extends infer TModels extends object ? TModels : never;
|
|
9
|
+
type IsUnion<TValue, TWhole = TValue> = TValue extends unknown ? ([TWhole] extends [TValue] ? false : true) : never;
|
|
10
|
+
type IsSingletonString<TValue extends string> = Record<never, never> extends Record<TValue, never> ? false : true;
|
|
11
|
+
export declare const internalContextIdentifierPrefix = "\0@shivaedev/effect-prisma/internal/";
|
|
12
|
+
export type DatabaseIdentifierLiteral<TIdentifier extends string> = [TIdentifier] extends [`\0@shivaedev/effect-prisma/internal/${string}`] ? never : string extends TIdentifier ? never : true extends IsUnion<TIdentifier> ? never : IsSingletonString<TIdentifier> extends true ? TIdentifier : never;
|
|
13
|
+
export interface DatabaseIdentifier<TContract extends AnySqlContract, TIdentifier extends string> {
|
|
14
|
+
readonly _contract: (contract: TContract) => TContract;
|
|
15
|
+
readonly _databaseIdentifier: (identifier: TIdentifier) => TIdentifier;
|
|
16
|
+
}
|
|
17
|
+
type DatabaseModels<TContract extends AnySqlContract, TIdentifier extends string> = {
|
|
18
|
+
readonly [TModel in keyof DefaultModels<TContract>]: Relation<DefaultModels<TContract>[TModel], TContract, TModel & string, DatabaseIdentifier<TContract, TIdentifier>>;
|
|
19
|
+
};
|
|
20
|
+
export type DatabaseService<TContract extends AnySqlContract, TIdentifier extends string> = DatabaseModels<TContract, TIdentifier> & {
|
|
21
|
+
transaction: <A, E, R>(program: Effect.Effect<A, E, R> & (DatabaseIdentifier<TContract, TIdentifier> extends R ? unknown : never)) => Effect.Effect<A, E | PrismaError, Exclude<R, DatabaseIdentifier<TContract, TIdentifier>>>;
|
|
22
|
+
};
|
|
23
|
+
export interface DatabaseServiceHolder<TContract extends AnySqlContract, TIdentifier extends string> extends Context.Service<DatabaseIdentifier<TContract, TIdentifier>, DatabaseService<TContract, TIdentifier>> {
|
|
24
|
+
}
|
|
25
|
+
export type AnyDatabase = Effect.Effect<unknown, never, unknown> & {
|
|
26
|
+
readonly layer: (...arguments_: readonly never[]) => Layer.Any;
|
|
27
|
+
};
|
|
28
|
+
export type DatabaseServiceOf<TDatabase extends AnyDatabase> = Effect.Success<TDatabase>;
|
|
29
|
+
export interface SqlDatabase<TContract extends AnySqlContract, TIdentifier extends string, TOptions> extends DatabaseServiceHolder<TContract, TIdentifier> {
|
|
30
|
+
readonly layer: (options: TOptions) => Layer.Layer<DatabaseIdentifier<TContract, TIdentifier>, PrismaError>;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=databaseTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"databaseTypes.d.ts","sourceRoot":"","sources":["../src/databaseTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const internalContextIdentifierPrefix = "\0@shivaedev/effect-prisma/internal/";
|
|
2
|
-
//# sourceMappingURL=
|
|
2
|
+
//# sourceMappingURL=databaseTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"databaseTypes.js","sourceRoot":"","sources":["../src/databaseTypes.ts"],"names":[],"mappings":"AAoBA,MAAM,CAAC,MAAM,+BAA+B,GAAG,sCAAsC,CAAC"}
|
package/dist/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,QAAQ,EAAE,MAAM,QAAQ,CAAC;;;;AAExC,qBAAa,oBAAqB,SAAQ,0BAAyC;IAClF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;CAC9C,CAAC;CAAG;;;;AAEL,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;CAC9C,CAAC;CAAG;;;;AAEL,qBAAa,uBAAwB,SAAQ,6BAA4C;IACxF,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;CAC9C,CAAC;CAAG;AAEL,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,uBAAuB,CAAC;;;;AAEpG,qBAAa,WAAY,SAAQ,iBAAgC;IAChE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;CACnC,CAAC;CAAG;AAEL,KAAK,aAAa,GACf;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IACA,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACxB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEL,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,QAAQ,EAAE,MAAM,QAAQ,CAAC;;;;AAExC,qBAAa,oBAAqB,SAAQ,0BAAyC;IAClF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;CAC9C,CAAC;CAAG;;;;AAEL,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC9E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;CAC9C,CAAC;CAAG;;;;AAEL,qBAAa,uBAAwB,SAAQ,6BAA4C;IACxF,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;CAC9C,CAAC;CAAG;AAEL,MAAM,MAAM,iBAAiB,GAAG,oBAAoB,GAAG,kBAAkB,GAAG,uBAAuB,CAAC;;;;AAEpG,qBAAa,WAAY,SAAQ,iBAAgC;IAChE,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;CACnC,CAAC;CAAG;AAEL,KAAK,aAAa,GACf;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IACA,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACxB,GACD;IACA,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEL,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,KAAK,IAAI,aAQzD,CAAC;AAEF,eAAO,MAAM,aAAa,UAAW,aAAa,KAAG,WA4BpD,CAAC"}
|