@prisma-next/sqlite 0.0.1

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/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # @prisma-next/sqlite
2
+
3
+ Composition-root SQLite helper that builds a Prisma Next runtime client and exposes SQL, ORM, and schema query access.
4
+
5
+ ## Package Classification
6
+
7
+ - **Domain**: extensions
8
+ - **Layer**: adapters
9
+ - **Plane**: runtime
10
+
11
+ ## Overview
12
+
13
+ `@prisma-next/sqlite/runtime` exposes a single `sqlite(...)` helper that composes the SQLite execution stack and returns query/runtime roots:
14
+
15
+ - `db.sql`
16
+ - `db.orm`
17
+ - `db.context`
18
+ - `db.stack`
19
+
20
+ Runtime resources are deferred until `db.runtime()` or `db.connect(...)` is called.
21
+ Connection binding can be provided up front (`path`) or deferred via `db.connect(...)`.
22
+
23
+ ## Responsibilities
24
+
25
+ - Build a static SQLite execution stack from target, adapter, and driver descriptors
26
+ - Build typed SQL surface from the execution context via `sql-query-builder-new`
27
+ - Build ORM surface from the execution context
28
+ - Normalize runtime binding input (file path or `:memory:`)
29
+ - Lazily instantiate runtime resources on first `db.runtime()` or `db.connect(...)` call
30
+ - Connect the internal SQLite driver through `db.connect(...)` or from initial binding options
31
+ - Memoize runtime so repeated `db.runtime()` calls return one instance
32
+
33
+ ## Dependencies
34
+
35
+ - **`@prisma-next/sql-runtime`** for stack/context/runtime primitives
36
+ - **`@prisma-next/framework-components`** for stack instantiation
37
+ - **`@prisma-next/target-sqlite`** for target descriptor
38
+ - **`@prisma-next/adapter-sqlite`** for adapter descriptor
39
+ - **`@prisma-next/driver-sqlite`** for driver descriptor
40
+ - **`@prisma-next/sql-builder`** for `sql(...)` query builder
41
+ - **`@prisma-next/sql-relational-core`** for `schema(...)`
42
+ - **`@prisma-next/sql-orm-client`** for `orm(...)`
43
+ - **`@prisma-next/sql-contract`** for `validateContract(...)` and contract types
44
+
45
+ ## Architecture
46
+
47
+ ```mermaid
48
+ flowchart TD
49
+ App[App Code] --> Client["sqlite(...)"]
50
+ Client --> Static["Roots: sql orm context stack"]
51
+ Client --> Lazy["runtime()"]
52
+
53
+ Lazy --> Instantiate[instantiateExecutionStack]
54
+ Lazy --> Bind["Resolve binding: path or :memory:"]
55
+ Bind --> DB["DatabaseSync via node:sqlite"]
56
+ Lazy --> Runtime[createRuntime]
57
+
58
+ Runtime --> Target["@prisma-next/target-sqlite"]
59
+ Runtime --> Adapter["@prisma-next/adapter-sqlite"]
60
+ Runtime --> Driver["@prisma-next/driver-sqlite"]
61
+ Runtime --> SqlRuntime["@prisma-next/sql-runtime"]
62
+ Runtime --> ExecPlane["@prisma-next/framework-components/execution"]
63
+ ```
64
+
65
+ ## Related Docs
66
+
67
+ - Architecture: `docs/Architecture Overview.md`
68
+ - Subsystem: `docs/architecture docs/subsystems/4. Runtime & Middleware Framework.md`
69
+ - Subsystem: `docs/architecture docs/subsystems/5. Adapters & Targets.md`
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@prisma-next/sqlite",
3
+ "version": "0.0.1",
4
+ "type": "module",
5
+ "sideEffects": false,
6
+ "description": "One-liner lazy SQLite client composition for Prisma Next",
7
+ "scripts": {
8
+ "build": "tsdown",
9
+ "test": "vitest run --passWithNoTests",
10
+ "test:coverage": "vitest run --coverage --passWithNoTests",
11
+ "typecheck": "tsc --project tsconfig.json --noEmit",
12
+ "lint": "biome check . --error-on-warnings",
13
+ "lint:fix": "biome check --write .",
14
+ "lint:fix:unsafe": "biome check --write --unsafe .",
15
+ "clean": "rm -rf dist dist-tsc dist-tsc-prod coverage .tmp-output"
16
+ },
17
+ "dependencies": {
18
+ "@prisma-next/adapter-sqlite": "workspace:*",
19
+ "@prisma-next/contract": "workspace:*",
20
+ "@prisma-next/driver-sqlite": "workspace:*",
21
+ "@prisma-next/framework-components": "workspace:*",
22
+ "@prisma-next/sql-builder": "workspace:*",
23
+ "@prisma-next/sql-contract": "workspace:*",
24
+ "@prisma-next/sql-orm-client": "workspace:*",
25
+ "@prisma-next/sql-relational-core": "workspace:*",
26
+ "@prisma-next/sql-runtime": "workspace:*",
27
+ "@prisma-next/target-sqlite": "workspace:*"
28
+ },
29
+ "devDependencies": {
30
+ "@prisma-next/test-utils": "workspace:*",
31
+ "@prisma-next/tsconfig": "workspace:*",
32
+ "@prisma-next/tsdown": "workspace:*",
33
+ "tsdown": "catalog:",
34
+ "typescript": "catalog:",
35
+ "vitest": "catalog:"
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "src"
40
+ ],
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/prisma/prisma-next.git",
44
+ "directory": "packages/3-extensions/sqlite"
45
+ },
46
+ "exports": {
47
+ "./runtime": "./dist/runtime.mjs",
48
+ "./package.json": "./package.json"
49
+ },
50
+ "main": "./dist/runtime.mjs",
51
+ "module": "./dist/runtime.mjs",
52
+ "types": "./dist/runtime.d.mts"
53
+ }
@@ -0,0 +1,10 @@
1
+ export type { SqliteBindingInput } from '../runtime/binding';
2
+ export type {
3
+ SqliteClient,
4
+ SqliteOptions,
5
+ SqliteOptionsBase,
6
+ SqliteOptionsWithContract,
7
+ SqliteOptionsWithContractJson,
8
+ SqliteTargetId,
9
+ } from '../runtime/sqlite';
10
+ export { default } from '../runtime/sqlite';
@@ -0,0 +1,16 @@
1
+ import type { SqliteBinding } from '@prisma-next/driver-sqlite/runtime';
2
+
3
+ export type SqliteBindingInput = { readonly path: string };
4
+
5
+ export function resolveSqliteBinding(input: SqliteBindingInput): SqliteBinding {
6
+ return { kind: 'path', path: input.path };
7
+ }
8
+
9
+ export function resolveOptionalSqliteBinding(options: {
10
+ readonly path?: string;
11
+ }): SqliteBinding | undefined {
12
+ if (options.path === undefined) {
13
+ return undefined;
14
+ }
15
+ return { kind: 'path', path: options.path };
16
+ }
@@ -0,0 +1,199 @@
1
+ import sqliteAdapter from '@prisma-next/adapter-sqlite/runtime';
2
+ import type { Contract } from '@prisma-next/contract/types';
3
+ import type { SqliteBinding } from '@prisma-next/driver-sqlite/runtime';
4
+ import sqliteDriver from '@prisma-next/driver-sqlite/runtime';
5
+ import { emptyCodecLookup } from '@prisma-next/framework-components/codec';
6
+ import { instantiateExecutionStack } from '@prisma-next/framework-components/execution';
7
+ import { sql as sqlBuilder } from '@prisma-next/sql-builder/runtime';
8
+ import type { Db } from '@prisma-next/sql-builder/types';
9
+ import type { SqlStorage } from '@prisma-next/sql-contract/types';
10
+ import { validateContract } from '@prisma-next/sql-contract/validate';
11
+ import { orm as ormBuilder } from '@prisma-next/sql-orm-client';
12
+ import type {
13
+ ExecutionContext,
14
+ Middleware,
15
+ Runtime,
16
+ RuntimeVerifyOptions,
17
+ SqlExecutionStackWithDriver,
18
+ SqlRuntimeExtensionDescriptor,
19
+ } from '@prisma-next/sql-runtime';
20
+ import {
21
+ createExecutionContext,
22
+ createRuntime,
23
+ createSqlExecutionStack,
24
+ } from '@prisma-next/sql-runtime';
25
+ import sqliteTarget from '@prisma-next/target-sqlite/runtime';
26
+ import { resolveOptionalSqliteBinding, resolveSqliteBinding } from './binding';
27
+
28
+ export type SqliteTargetId = 'sqlite';
29
+ type OrmClient<TContract extends Contract<SqlStorage>> = ReturnType<typeof ormBuilder<TContract>>;
30
+
31
+ export interface SqliteClient<TContract extends Contract<SqlStorage>> {
32
+ readonly sql: Db<TContract>;
33
+ readonly orm: OrmClient<TContract>;
34
+ readonly context: ExecutionContext<TContract>;
35
+ readonly stack: SqlExecutionStackWithDriver<SqliteTargetId>;
36
+ connect(bindingInput?: { readonly path: string }): Promise<Runtime>;
37
+ runtime(): Runtime;
38
+ }
39
+
40
+ export interface SqliteOptionsBase<TContract extends Contract<SqlStorage>> {
41
+ readonly extensions?: readonly SqlRuntimeExtensionDescriptor<SqliteTargetId>[];
42
+ readonly middleware?: readonly Middleware<TContract>[];
43
+ readonly verify?: RuntimeVerifyOptions;
44
+ }
45
+
46
+ export type SqliteOptionsWithContract<TContract extends Contract<SqlStorage>> = {
47
+ readonly path?: string;
48
+ } & SqliteOptionsBase<TContract> & {
49
+ readonly contract: TContract;
50
+ readonly contractJson?: never;
51
+ };
52
+
53
+ export type SqliteOptionsWithContractJson<TContract extends Contract<SqlStorage>> = {
54
+ readonly path?: string;
55
+ } & SqliteOptionsBase<TContract> & {
56
+ readonly contractJson: unknown;
57
+ readonly contract?: never;
58
+ };
59
+
60
+ export type SqliteOptions<TContract extends Contract<SqlStorage>> =
61
+ | SqliteOptionsWithContract<TContract>
62
+ | SqliteOptionsWithContractJson<TContract>;
63
+
64
+ function resolveContract<TContract extends Contract<SqlStorage>>(
65
+ options: SqliteOptions<TContract>,
66
+ ): TContract {
67
+ const contractInput =
68
+ 'contractJson' in options && options.contractJson !== undefined
69
+ ? options.contractJson
70
+ : (options as SqliteOptionsWithContract<TContract>).contract;
71
+ return validateContract<TContract>(contractInput, emptyCodecLookup);
72
+ }
73
+
74
+ export default function sqlite<TContract extends Contract<SqlStorage>>(
75
+ options: SqliteOptionsWithContract<TContract>,
76
+ ): SqliteClient<TContract>;
77
+ export default function sqlite<TContract extends Contract<SqlStorage>>(
78
+ options: SqliteOptionsWithContractJson<TContract>,
79
+ ): SqliteClient<TContract>;
80
+ export default function sqlite<TContract extends Contract<SqlStorage>>(
81
+ options: SqliteOptions<TContract>,
82
+ ): SqliteClient<TContract> {
83
+ const contract = resolveContract(options);
84
+ let binding = resolveOptionalSqliteBinding(options);
85
+ const stack = createSqlExecutionStack({
86
+ target: sqliteTarget,
87
+ adapter: sqliteAdapter,
88
+ driver: sqliteDriver,
89
+ extensionPacks: options.extensions ?? [],
90
+ });
91
+
92
+ const context = createExecutionContext({
93
+ contract,
94
+ stack,
95
+ });
96
+
97
+ const sql: Db<TContract> = sqlBuilder<TContract>({ context });
98
+ let runtimeInstance: Runtime | undefined;
99
+ let runtimeDriver: { connect(binding: unknown): Promise<void> } | undefined;
100
+ let driverConnected = false;
101
+ let connectPromise: Promise<void> | undefined;
102
+ let backgroundConnectError: unknown;
103
+
104
+ const connectDriver = async (resolvedBinding: SqliteBinding): Promise<void> => {
105
+ if (driverConnected) return;
106
+ if (!runtimeDriver) throw new Error('SQLite runtime driver missing');
107
+ if (connectPromise) return connectPromise;
108
+ connectPromise = runtimeDriver
109
+ .connect(resolvedBinding)
110
+ .then(() => {
111
+ driverConnected = true;
112
+ })
113
+ .catch((err) => {
114
+ backgroundConnectError = err;
115
+ connectPromise = undefined;
116
+ throw err;
117
+ });
118
+ return connectPromise;
119
+ };
120
+
121
+ const getRuntime = (): Runtime => {
122
+ if (backgroundConnectError !== undefined) {
123
+ throw backgroundConnectError;
124
+ }
125
+
126
+ if (runtimeInstance) {
127
+ return runtimeInstance;
128
+ }
129
+
130
+ const stackInstance = instantiateExecutionStack(stack);
131
+ const driverDescriptor = stack.driver;
132
+ if (!driverDescriptor) {
133
+ throw new Error('Driver descriptor missing from execution stack');
134
+ }
135
+
136
+ const driver = driverDescriptor.create();
137
+ runtimeDriver = driver;
138
+ if (binding !== undefined) {
139
+ void connectDriver(binding).catch(() => undefined);
140
+ }
141
+
142
+ runtimeInstance = createRuntime({
143
+ stackInstance,
144
+ context,
145
+ driver,
146
+ verify: options.verify ?? { mode: 'onFirstUse', requireMarker: false },
147
+ ...(options.middleware ? { middleware: options.middleware } : {}),
148
+ });
149
+
150
+ return runtimeInstance;
151
+ };
152
+
153
+ const orm: OrmClient<TContract> = ormBuilder({
154
+ context,
155
+ runtime: {
156
+ execute(plan) {
157
+ return getRuntime().execute(plan);
158
+ },
159
+ connection() {
160
+ return getRuntime().connection();
161
+ },
162
+ },
163
+ });
164
+
165
+ return {
166
+ sql,
167
+ orm,
168
+ context,
169
+ stack,
170
+ async connect(bindingInput) {
171
+ if (driverConnected || connectPromise) {
172
+ throw new Error('SQLite client already connected');
173
+ }
174
+
175
+ backgroundConnectError = undefined;
176
+
177
+ if (bindingInput !== undefined) {
178
+ binding = resolveSqliteBinding(bindingInput);
179
+ }
180
+
181
+ if (binding === undefined) {
182
+ throw new Error(
183
+ 'SQLite binding not configured. Pass path to sqlite(...) or call db.connect({ path }).',
184
+ );
185
+ }
186
+
187
+ const runtime = getRuntime();
188
+ if (driverConnected) {
189
+ return runtime;
190
+ }
191
+
192
+ await connectDriver(binding);
193
+ return runtime;
194
+ },
195
+ runtime() {
196
+ return getRuntime();
197
+ },
198
+ };
199
+ }