turbine-orm 0.19.2 → 0.22.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.
Files changed (53) hide show
  1. package/README.md +99 -18
  2. package/dist/adapters/cockroachdb.js +4 -9
  3. package/dist/cjs/adapters/cockroachdb.js +4 -9
  4. package/dist/cjs/cli/index.js +6 -3
  5. package/dist/cjs/cli/observe-ui.js +12 -2
  6. package/dist/cjs/cli/observe.js +6 -7
  7. package/dist/cjs/cli/studio.js +6 -7
  8. package/dist/cjs/client.js +44 -22
  9. package/dist/cjs/dialect.js +116 -0
  10. package/dist/cjs/errors.js +19 -1
  11. package/dist/cjs/generate.js +4 -0
  12. package/dist/cjs/index.js +3 -2
  13. package/dist/cjs/introspect.js +20 -0
  14. package/dist/cjs/mssql.js +1338 -0
  15. package/dist/cjs/mysql.js +1052 -0
  16. package/dist/cjs/powdb.js +851 -0
  17. package/dist/cjs/powql.js +903 -0
  18. package/dist/cjs/query/builder.js +293 -73
  19. package/dist/cjs/sqlite.js +849 -0
  20. package/dist/cjs/typed-sql.js +9 -7
  21. package/dist/cli/index.js +6 -3
  22. package/dist/cli/observe-ui.d.ts +1 -1
  23. package/dist/cli/observe-ui.js +12 -2
  24. package/dist/cli/observe.js +7 -8
  25. package/dist/cli/studio.js +7 -8
  26. package/dist/cli/ui.d.ts +1 -1
  27. package/dist/client.d.ts +23 -1
  28. package/dist/client.js +45 -23
  29. package/dist/dialect.d.ts +258 -1
  30. package/dist/dialect.js +83 -0
  31. package/dist/errors.d.ts +12 -0
  32. package/dist/errors.js +17 -0
  33. package/dist/generate.js +4 -0
  34. package/dist/index.d.ts +3 -3
  35. package/dist/index.js +1 -1
  36. package/dist/introspect.d.ts +18 -0
  37. package/dist/introspect.js +19 -0
  38. package/dist/mssql.d.ts +233 -0
  39. package/dist/mssql.js +1298 -0
  40. package/dist/mysql.d.ts +174 -0
  41. package/dist/mysql.js +1012 -0
  42. package/dist/powdb.d.ts +338 -0
  43. package/dist/powdb.js +802 -0
  44. package/dist/powql.d.ts +153 -0
  45. package/dist/powql.js +900 -0
  46. package/dist/query/builder.d.ts +105 -0
  47. package/dist/query/builder.js +294 -74
  48. package/dist/query/index.d.ts +1 -1
  49. package/dist/sqlite.d.ts +144 -0
  50. package/dist/sqlite.js +842 -0
  51. package/dist/typed-sql.d.ts +7 -5
  52. package/dist/typed-sql.js +9 -7
  53. package/package.json +45 -1
@@ -0,0 +1,233 @@
1
+ /**
2
+ * turbine-orm/mssql — Microsoft SQL Server engine (driver-injected, optional peer)
3
+ *
4
+ * Binds Turbine to SQL Server 2016+ via the `mssql` driver (which wraps
5
+ * `tedious`). `mssql` is **not** a root dependency — it is an **optional peer**:
6
+ * `npm i turbine-orm` pulls nothing extra, and only consumers who
7
+ * `import 'turbine-orm/mssql'` install `mssql` themselves. The factory loads it
8
+ * through a dynamic `import('mssql')` so importing this module never crashes when
9
+ * `mssql` is absent for a consumer who does not use it. Turbine's root runtime
10
+ * dependency stays exactly `pg`.
11
+ *
12
+ * ## The three hard SQL Server realities this engine solves
13
+ *
14
+ * 1. **No `RETURNING`.** `INSERT`/`UPDATE`/`DELETE` cannot trail a `RETURNING`
15
+ * clause; SQL Server returns affected rows via `OUTPUT INSERTED.*` /
16
+ * `OUTPUT DELETED.*` injected MID-statement (between the column list and
17
+ * `VALUES`, or between `SET …` and `WHERE …`). `mssqlDialect.resultStrategy =
18
+ * 'output'`: the statement returns its own rows in ONE round-trip (executed
19
+ * exactly like the PostgreSQL `'returning'` path). Upsert becomes a
20
+ * `MERGE … WHEN MATCHED … WHEN NOT MATCHED … OUTPUT INSERTED.* ;` (a MERGE
21
+ * must end with `;`). This is the first shipped engine to exercise the
22
+ * Phase-0 `'output'` result strategy.
23
+ * 2. **No `json_agg`.** SQL Server has no JSON aggregate function; the idiomatic
24
+ * single-query nested-relation path is `(SELECT child cols … FOR JSON PATH)`,
25
+ * whose object shape is expressed by the child SELECT's column ALIASES rather
26
+ * than an explicit `JSON_OBJECT(...)`. That does NOT map onto
27
+ * `buildJsonObject`/`buildJsonArrayAgg`, so `mssqlDialect` defines the
28
+ * additive `Dialect.buildRelationSubquery` override (the sanctioned Phase-3
29
+ * seam extension) and owns the whole correlated subquery. To-many wraps
30
+ * `ISNULL((… FOR JSON PATH), '[]')` (FOR JSON over zero rows is NULL, not
31
+ * `[]`); to-one adds `, WITHOUT_ARRAY_WRAPPER` and lets NULL be the no-row
32
+ * value. Nested relations are embedded with `JSON_QUERY(...)` so they stay
33
+ * real JSON instead of being escaped as a string. `INCLUDE_NULL_VALUES`
34
+ * keeps NULL columns present (matching PostgreSQL `json_build_object`).
35
+ * 3. **No `LIMIT`.** Paging is `ORDER BY … OFFSET n ROWS FETCH NEXT m ROWS ONLY`,
36
+ * which requires an ORDER BY — a stable `ORDER BY (SELECT NULL)` is injected
37
+ * when the query has none (`Dialect.buildLimitOffset`).
38
+ *
39
+ * ## Named `@pN` placeholders (no positional `?`)
40
+ *
41
+ * `mssqlDialect.paramPlaceholder = (i) => '@p' + i`. The driver shim binds via
42
+ * `request.input('p' + i, value)`, so binding is by NAME and independent of where
43
+ * each placeholder lands in the SQL text — exactly the guarantee PostgreSQL's
44
+ * numbered `$N` gives. (SQL Server is naturally named-param friendly, sidestepping
45
+ * the positional-`?` mis-bind bug the SQLite/MySQL phases hit.)
46
+ *
47
+ * ## Capabilities & limits (vs PostgreSQL)
48
+ *
49
+ * - **Single query nested relations preserved** via `FOR JSON PATH` (SQL Server
50
+ * 2016+). Ordered/limited to-many uses `ORDER BY … OFFSET/FETCH` inside the FOR
51
+ * JSON subquery (no inner-subquery rewrite needed — FOR JSON aggregates AFTER
52
+ * the row selection).
53
+ * - **Result strategy `'output'`:** create/update/delete/upsert return their rows
54
+ * from the same statement. `createMany` returns the inserted rows via
55
+ * `OUTPUT INSERTED.*` on the multi-row VALUES insert (≤ 1000 rows / 2100 params
56
+ * per statement — exceeding either throws a clear `ValidationError`; chunk
57
+ * yourself or use single `create`s).
58
+ * - **MERGE concurrency caveat:** `MERGE` is the upsert primitive; under high
59
+ * concurrency a `MERGE` can still race (it is NOT a substitute for a unique
60
+ * constraint). Keep the conflict target backed by a real `UNIQUE`/`PK` index,
61
+ * and rely on the typed `UniqueConstraintError` (2627/2601 → E008) for the
62
+ * loser of a race.
63
+ * - **Unsupported (throw `UnsupportedFeatureError`):** pgvector distance ops,
64
+ * LISTEN/NOTIFY (`$listen`/`$notify`), RLS `sessionContext` (sp_set_session_context
65
+ * exists but is connection-scoped, not transaction-local, so it is not wired —
66
+ * throws rather than silently leaking context across pooled connections).
67
+ * - **Advisory-lock migration locking** is available in principle via
68
+ * `sp_getapplock`/`sp_releaseapplock` (`supportsAdvisoryLock = true`); the
69
+ * migrate CLI is still PostgreSQL-only, so this flag documents intent for a
70
+ * future adapter.
71
+ * - **Case-insensitive matching** uses `LOWER(col) LIKE LOWER(ref)` — deterministic
72
+ * regardless of the column's collation (note this can defeat an index unless a
73
+ * computed/persisted `LOWER()` index exists).
74
+ * - **bignum:** the shim applies the same safe-int policy Turbine uses for Postgres
75
+ * `int8` (number when it fits in 2^53, decimal string otherwise) WITHOUT mutating
76
+ * any global driver state. `DECIMAL`/`NUMERIC`/`MONEY` come back as strings;
77
+ * `BIT` binds/returns booleans.
78
+ * - **`DISTINCT ON`** is PostgreSQL-only and is not translated — avoid `distinct`
79
+ * on SQL Server.
80
+ *
81
+ * ## Example
82
+ *
83
+ * ```ts
84
+ * import { turbineMssql } from 'turbine-orm/mssql';
85
+ * import { SCHEMA } from './generated/turbine/metadata.js';
86
+ *
87
+ * const db = await turbineMssql('mssql://sa:Passw0rd!@localhost:1433/app', SCHEMA);
88
+ * const users = await db.users.findMany({ with: { posts: true }, limit: 10 });
89
+ * await db.disconnect();
90
+ * ```
91
+ */
92
+ import { type PgCompatPool, type PgCompatPoolClient, TurbineClient, type TurbineConfig } from './client.js';
93
+ import { type Dialect, type IntrospectOptions } from './dialect.js';
94
+ import { type SchemaMetadata } from './schema.js';
95
+ interface MssqlRequest {
96
+ input(name: string, value: unknown): MssqlRequest;
97
+ query<R = Record<string, unknown>>(text: string): Promise<MssqlQueryResult<R>>;
98
+ batch<R = Record<string, unknown>>(text: string): Promise<MssqlQueryResult<R>>;
99
+ }
100
+ /** Per-column metadata `mssql` attaches to a recordset (`recordset.columns`). */
101
+ interface MssqlColumnMeta {
102
+ [name: string]: {
103
+ type?: {
104
+ name?: string;
105
+ declaration?: string;
106
+ };
107
+ } | undefined;
108
+ }
109
+ interface MssqlQueryResult<R = Record<string, unknown>> {
110
+ recordset?: R[] & {
111
+ columns?: MssqlColumnMeta;
112
+ };
113
+ recordsets?: R[][];
114
+ rowsAffected?: number[];
115
+ }
116
+ interface MssqlTransaction {
117
+ begin(isolationLevel?: number): Promise<unknown>;
118
+ commit(): Promise<unknown>;
119
+ rollback(): Promise<unknown>;
120
+ }
121
+ interface MssqlConnectionPool {
122
+ connect(): Promise<MssqlConnectionPool>;
123
+ request(): MssqlRequest;
124
+ close(): Promise<unknown>;
125
+ readonly connected?: boolean;
126
+ }
127
+ /** The subset of the `mssql` module namespace the shim constructs. */
128
+ interface MssqlModule {
129
+ connect(config: any): Promise<MssqlConnectionPool>;
130
+ ConnectionPool: new (config: any) => MssqlConnectionPool;
131
+ Request: new (parent: MssqlConnectionPool | MssqlTransaction) => MssqlRequest;
132
+ Transaction: new (pool: MssqlConnectionPool) => MssqlTransaction;
133
+ ISOLATION_LEVEL: Record<string, number>;
134
+ }
135
+ /** pg-style query argument: a SQL string or a `{ text, values }` config object. */
136
+ type QueryArg = string | {
137
+ name?: string;
138
+ text: string;
139
+ values?: unknown[];
140
+ };
141
+ /**
142
+ * A {@link PgCompatPool} backed by an `mssql` ConnectionPool. Non-transaction
143
+ * queries run on a fresh pooled `Request`; `connect()` returns a
144
+ * {@link MssqlTxClient} that drives a single transaction through the mssql
145
+ * `Transaction` API so `BEGIN`/`COMMIT`/`ROLLBACK`/savepoints all run on the same
146
+ * physical connection.
147
+ */
148
+ export declare class MssqlPool implements PgCompatPool {
149
+ /** The underlying `mssql` ConnectionPool — exposed as an escape hatch (seed / DDL / advanced ops). */
150
+ readonly pool: MssqlConnectionPool;
151
+ private readonly sqlNS;
152
+ private closed;
153
+ constructor(pool: MssqlConnectionPool, sqlNS: MssqlModule);
154
+ query(text: QueryArg, values?: unknown[]): Promise<any>;
155
+ connect(): Promise<PgCompatPoolClient>;
156
+ end(): Promise<void>;
157
+ }
158
+ /**
159
+ * Map a SQL Server column type to a TypeScript type. `dialectType` is the
160
+ * `INFORMATION_SCHEMA.COLUMNS.DATA_TYPE` (lowercase, e.g. `bigint`, `nvarchar`,
161
+ * `datetime2`, `bit`, `uniqueidentifier`).
162
+ */
163
+ export declare function mssqlTypeToTs(dialectType: string, nullable: boolean): string;
164
+ /**
165
+ * SQL Server 2016+ implementation of the {@link Dialect} contract. Bracket
166
+ * identifier quoting (`[…]`), named `@pN` placeholders, the `FOR JSON PATH`
167
+ * nested-relation override (no `json_agg`), no `RETURNING`
168
+ * (`resultStrategy = 'output'` via `OUTPUT INSERTED.*` / `MERGE`), `OFFSET/FETCH`
169
+ * paging, and the Postgres-only capabilities disabled (vector / LISTEN-NOTIFY /
170
+ * RLS).
171
+ */
172
+ export declare const mssqlDialect: Dialect;
173
+ /** Async executor that returns plain row objects for a parameterized (`@pN`) query. */
174
+ export type MssqlRowExecutor = (sql: string, params: unknown[]) => Promise<Record<string, unknown>[]>;
175
+ /**
176
+ * Introspect a SQL Server database into the same {@link SchemaMetadata} shape the
177
+ * Postgres catalog introspector produces, using a caller-supplied query executor
178
+ * (so tests can dogfood an already-open `mssql` pool/connection). Reads
179
+ * `INFORMATION_SCHEMA.*` plus `sys.identity_columns` / `sys.foreign_keys` /
180
+ * `sys.indexes`.
181
+ *
182
+ * @param exec Runs a parameterized (`@p1`, `@p2`, …) query and returns rows.
183
+ * @param schema The SQL Server schema to introspect (default `dbo`).
184
+ */
185
+ export declare function introspectMssqlWith(exec: MssqlRowExecutor, schema?: string, options?: {
186
+ include?: string[];
187
+ exclude?: string[];
188
+ }): Promise<SchemaMetadata>;
189
+ /**
190
+ * Open a short-lived `mssql` connection from `options.connectionString`, introspect
191
+ * the database (schema = `options.schema` or `dbo`), and close it. Wraps
192
+ * {@link introspectMssqlWith} for the {@link DialectIntrospector} seam used by
193
+ * `introspect()` / `npx turbine generate`.
194
+ */
195
+ export declare function introspectMssql(options: IntrospectOptions): Promise<SchemaMetadata>;
196
+ interface MssqlConnectionConfig {
197
+ server?: string;
198
+ port?: number;
199
+ user?: string;
200
+ password?: string;
201
+ database?: string;
202
+ options?: {
203
+ encrypt?: boolean;
204
+ trustServerCertificate?: boolean;
205
+ };
206
+ }
207
+ /** Options for {@link turbineMssql}. Mirrors the relevant {@link TurbineConfig} fields. */
208
+ export interface TurbineMssqlOptions extends Pick<TurbineConfig, 'logging' | 'defaultLimit' | 'warnOnUnlimited'> {
209
+ /** SQL Server schema for introspection / DDL (default `dbo`). */
210
+ schema?: string;
211
+ }
212
+ /**
213
+ * Create a {@link TurbineClient} bound to SQL Server 2016+ via `mssql`.
214
+ *
215
+ * Pass one of:
216
+ * - a connection string (`'mssql://sa:pass@host:1433/db'`),
217
+ * - an `mssql` config object (`{ server, user, password, database, options }`),
218
+ * - an existing `MssqlPool` (injection — you own its lifecycle, `disconnect()` is
219
+ * a no-op).
220
+ *
221
+ * When Turbine builds the pool (string/config), it probes
222
+ * `SERVERPROPERTY('ProductMajorVersion')` to reject SQL Server < 2016, and
223
+ * `disconnect()` closes the pool it created.
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * import { turbineMssql } from 'turbine-orm/mssql';
228
+ * const db = await turbineMssql('mssql://sa:Passw0rd!@localhost:1433/app', SCHEMA);
229
+ * ```
230
+ */
231
+ export declare function turbineMssql(target: string | MssqlConnectionConfig | MssqlPool, schema: SchemaMetadata, options?: TurbineMssqlOptions): Promise<TurbineClient>;
232
+ export {};
233
+ //# sourceMappingURL=mssql.d.ts.map