turbine-orm 0.5.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/README.md +194 -26
- package/dist/cjs/cli/config.js +5 -15
- package/dist/cjs/cli/index.js +240 -41
- package/dist/cjs/cli/migrate.js +71 -46
- package/dist/cjs/cli/ui.js +5 -9
- package/dist/cjs/client.js +109 -46
- package/dist/cjs/errors.js +293 -0
- package/dist/cjs/generate.js +33 -13
- package/dist/cjs/index.js +39 -20
- package/dist/cjs/introspect.js +3 -5
- package/dist/cjs/pipeline.js +9 -2
- package/dist/cjs/query.js +442 -109
- package/dist/cjs/schema-builder.js +93 -24
- package/dist/cjs/schema-sql.js +157 -19
- package/dist/cjs/schema.js +5 -2
- package/dist/cjs/serverless.js +87 -176
- package/dist/cli/config.js +6 -16
- package/dist/cli/index.js +245 -46
- package/dist/cli/migrate.d.ts +6 -1
- package/dist/cli/migrate.js +72 -47
- package/dist/cli/ui.js +5 -9
- package/dist/client.d.ts +77 -4
- package/dist/client.js +109 -46
- package/dist/errors.d.ts +138 -0
- package/dist/errors.js +278 -0
- package/dist/generate.d.ts +1 -1
- package/dist/generate.js +36 -16
- package/dist/index.d.ts +11 -9
- package/dist/index.js +16 -12
- package/dist/introspect.d.ts +1 -1
- package/dist/introspect.js +4 -6
- package/dist/pipeline.d.ts +1 -1
- package/dist/pipeline.js +9 -2
- package/dist/query.d.ts +257 -36
- package/dist/query.js +443 -110
- package/dist/schema-builder.d.ts +2 -2
- package/dist/schema-builder.js +93 -25
- package/dist/schema-sql.d.ts +7 -3
- package/dist/schema-sql.js +157 -19
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +5 -2
- package/dist/serverless.d.ts +91 -139
- package/dist/serverless.js +86 -173
- package/package.json +33 -16
- package/dist/types.d.ts +0 -93
- package/dist/types.js +0 -126
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* turbine-orm — Error types
|
|
4
|
+
*
|
|
5
|
+
* Typed errors with error codes for programmatic handling.
|
|
6
|
+
* All Turbine errors extend TurbineError which includes a `code` property.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.CheckConstraintError = exports.NotNullViolationError = exports.ForeignKeyError = exports.UniqueConstraintError = exports.CircularRelationError = exports.MigrationError = exports.RelationError = exports.ConnectionError = exports.ValidationError = exports.TimeoutError = exports.NotFoundError = exports.TurbineError = exports.TurbineErrorCode = void 0;
|
|
10
|
+
exports.wrapPgError = wrapPgError;
|
|
11
|
+
/** Error codes for all Turbine errors */
|
|
12
|
+
exports.TurbineErrorCode = {
|
|
13
|
+
NOT_FOUND: 'TURBINE_E001',
|
|
14
|
+
TIMEOUT: 'TURBINE_E002',
|
|
15
|
+
VALIDATION: 'TURBINE_E003',
|
|
16
|
+
CONNECTION: 'TURBINE_E004',
|
|
17
|
+
RELATION: 'TURBINE_E005',
|
|
18
|
+
MIGRATION: 'TURBINE_E006',
|
|
19
|
+
CIRCULAR_RELATION: 'TURBINE_E007',
|
|
20
|
+
UNIQUE_VIOLATION: 'TURBINE_E008',
|
|
21
|
+
FOREIGN_KEY_VIOLATION: 'TURBINE_E009',
|
|
22
|
+
NOT_NULL_VIOLATION: 'TURBINE_E010',
|
|
23
|
+
CHECK_VIOLATION: 'TURBINE_E011',
|
|
24
|
+
};
|
|
25
|
+
/** Base error class for all Turbine errors */
|
|
26
|
+
class TurbineError extends Error {
|
|
27
|
+
code;
|
|
28
|
+
constructor(code, message, options) {
|
|
29
|
+
super(message, options);
|
|
30
|
+
this.name = 'TurbineError';
|
|
31
|
+
this.code = code;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.TurbineError = TurbineError;
|
|
35
|
+
/**
|
|
36
|
+
* Thrown when a record is not found (findUniqueOrThrow, findFirstOrThrow,
|
|
37
|
+
* update/delete against a non-matching row, etc.)
|
|
38
|
+
*
|
|
39
|
+
* Supports two call styles for back-compat:
|
|
40
|
+
* - `new NotFoundError()` / `new NotFoundError('custom message')`
|
|
41
|
+
* - `new NotFoundError({ table, where, operation, cause, message })`
|
|
42
|
+
*
|
|
43
|
+
* When called with an options object and no explicit `message`, a Prisma-style
|
|
44
|
+
* message is built automatically, e.g.:
|
|
45
|
+
* `[turbine] findUniqueOrThrow on "users" found no record matching where: {"id":1}`
|
|
46
|
+
*/
|
|
47
|
+
class NotFoundError extends TurbineError {
|
|
48
|
+
table;
|
|
49
|
+
where;
|
|
50
|
+
operation;
|
|
51
|
+
constructor(input) {
|
|
52
|
+
// Back-compat: string argument (or undefined) — replicate legacy behavior.
|
|
53
|
+
if (typeof input === 'string' || input === undefined) {
|
|
54
|
+
super(exports.TurbineErrorCode.NOT_FOUND, input ?? 'Record not found');
|
|
55
|
+
this.name = 'NotFoundError';
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const { table, where, operation, cause } = input;
|
|
59
|
+
let message = input.message;
|
|
60
|
+
if (!message) {
|
|
61
|
+
if (operation && table) {
|
|
62
|
+
const wherePart = where !== undefined ? ` matching where: ${JSON.stringify(where)}` : '';
|
|
63
|
+
message = `[turbine] ${operation} on "${table}" found no record${wherePart}`;
|
|
64
|
+
}
|
|
65
|
+
else if (table) {
|
|
66
|
+
const wherePart = where !== undefined ? ` matching where ${JSON.stringify(where)}` : '';
|
|
67
|
+
message = `[turbine] No record found in "${table}"${wherePart}`;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
message = '[turbine] Record not found';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
super(exports.TurbineErrorCode.NOT_FOUND, message, { cause });
|
|
74
|
+
this.name = 'NotFoundError';
|
|
75
|
+
this.table = table;
|
|
76
|
+
this.where = where;
|
|
77
|
+
this.operation = operation;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.NotFoundError = NotFoundError;
|
|
81
|
+
/** Thrown when a query or transaction exceeds the configured timeout */
|
|
82
|
+
class TimeoutError extends TurbineError {
|
|
83
|
+
timeoutMs;
|
|
84
|
+
constructor(timeoutMs, context = 'Query') {
|
|
85
|
+
super(exports.TurbineErrorCode.TIMEOUT, `[turbine] ${context} timed out after ${timeoutMs}ms`);
|
|
86
|
+
this.name = 'TimeoutError';
|
|
87
|
+
this.timeoutMs = timeoutMs;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.TimeoutError = TimeoutError;
|
|
91
|
+
/** Thrown when query arguments fail validation (unknown column, invalid operator, etc.) */
|
|
92
|
+
class ValidationError extends TurbineError {
|
|
93
|
+
constructor(message) {
|
|
94
|
+
super(exports.TurbineErrorCode.VALIDATION, message);
|
|
95
|
+
this.name = 'ValidationError';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.ValidationError = ValidationError;
|
|
99
|
+
/** Thrown when a database connection fails */
|
|
100
|
+
class ConnectionError extends TurbineError {
|
|
101
|
+
constructor(message) {
|
|
102
|
+
super(exports.TurbineErrorCode.CONNECTION, message);
|
|
103
|
+
this.name = 'ConnectionError';
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.ConnectionError = ConnectionError;
|
|
107
|
+
/** Thrown when a relation reference is invalid */
|
|
108
|
+
class RelationError extends TurbineError {
|
|
109
|
+
constructor(message) {
|
|
110
|
+
super(exports.TurbineErrorCode.RELATION, message);
|
|
111
|
+
this.name = 'RelationError';
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.RelationError = RelationError;
|
|
115
|
+
/** Thrown when a migration operation fails */
|
|
116
|
+
class MigrationError extends TurbineError {
|
|
117
|
+
constructor(message) {
|
|
118
|
+
super(exports.TurbineErrorCode.MIGRATION, message);
|
|
119
|
+
this.name = 'MigrationError';
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.MigrationError = MigrationError;
|
|
123
|
+
/** Thrown when circular relation nesting is detected */
|
|
124
|
+
class CircularRelationError extends TurbineError {
|
|
125
|
+
path;
|
|
126
|
+
constructor(path) {
|
|
127
|
+
super(exports.TurbineErrorCode.CIRCULAR_RELATION, `[turbine] Circular or too-deep relation nesting detected: ${path.join(' → ')}. Maximum nesting depth is 10.`);
|
|
128
|
+
this.name = 'CircularRelationError';
|
|
129
|
+
this.path = path;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.CircularRelationError = CircularRelationError;
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Database constraint violation errors
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
/**
|
|
137
|
+
* Extract the `detail` string from a pg-style error stored as `cause`.
|
|
138
|
+
* Returns undefined if the cause is not an object or has no detail.
|
|
139
|
+
*/
|
|
140
|
+
function detailFromCause(cause) {
|
|
141
|
+
if (!cause || typeof cause !== 'object')
|
|
142
|
+
return undefined;
|
|
143
|
+
const d = cause.detail;
|
|
144
|
+
return typeof d === 'string' && d.length > 0 ? d : undefined;
|
|
145
|
+
}
|
|
146
|
+
/** Thrown when a UNIQUE constraint is violated (pg code 23505) */
|
|
147
|
+
class UniqueConstraintError extends TurbineError {
|
|
148
|
+
constraint;
|
|
149
|
+
columns;
|
|
150
|
+
table;
|
|
151
|
+
constructor(opts = {}) {
|
|
152
|
+
const { constraint, columns, table, cause } = opts;
|
|
153
|
+
let message = opts.message;
|
|
154
|
+
if (!message) {
|
|
155
|
+
const constraintPart = constraint ? ` on ${constraint}` : '';
|
|
156
|
+
const columnsPart = columns && columns.length > 0 ? ` (${columns.join(', ')})` : '';
|
|
157
|
+
message = `[turbine] Unique constraint violation${constraintPart}${columnsPart}`;
|
|
158
|
+
const detail = detailFromCause(cause);
|
|
159
|
+
if (detail)
|
|
160
|
+
message += `: ${detail}`;
|
|
161
|
+
}
|
|
162
|
+
super(exports.TurbineErrorCode.UNIQUE_VIOLATION, message, { cause });
|
|
163
|
+
this.name = 'UniqueConstraintError';
|
|
164
|
+
this.constraint = constraint;
|
|
165
|
+
this.columns = columns;
|
|
166
|
+
this.table = table;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.UniqueConstraintError = UniqueConstraintError;
|
|
170
|
+
/** Thrown when a FOREIGN KEY constraint is violated (pg code 23503) */
|
|
171
|
+
class ForeignKeyError extends TurbineError {
|
|
172
|
+
constraint;
|
|
173
|
+
table;
|
|
174
|
+
constructor(opts = {}) {
|
|
175
|
+
const { constraint, table, cause } = opts;
|
|
176
|
+
let message = opts.message;
|
|
177
|
+
if (!message) {
|
|
178
|
+
const constraintPart = constraint ? ` on ${constraint}` : '';
|
|
179
|
+
message = `[turbine] Foreign key constraint violation${constraintPart}`;
|
|
180
|
+
const detail = detailFromCause(cause);
|
|
181
|
+
if (detail)
|
|
182
|
+
message += `: ${detail}`;
|
|
183
|
+
}
|
|
184
|
+
super(exports.TurbineErrorCode.FOREIGN_KEY_VIOLATION, message, { cause });
|
|
185
|
+
this.name = 'ForeignKeyError';
|
|
186
|
+
this.constraint = constraint;
|
|
187
|
+
this.table = table;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
exports.ForeignKeyError = ForeignKeyError;
|
|
191
|
+
/** Thrown when a NOT NULL constraint is violated (pg code 23502) */
|
|
192
|
+
class NotNullViolationError extends TurbineError {
|
|
193
|
+
column;
|
|
194
|
+
table;
|
|
195
|
+
constructor(opts = {}) {
|
|
196
|
+
const { column, table, cause } = opts;
|
|
197
|
+
let message = opts.message;
|
|
198
|
+
if (!message) {
|
|
199
|
+
const columnPart = column ? ` on column "${column}"` : '';
|
|
200
|
+
message = `[turbine] NOT NULL constraint violation${columnPart}`;
|
|
201
|
+
const detail = detailFromCause(cause);
|
|
202
|
+
if (detail)
|
|
203
|
+
message += `: ${detail}`;
|
|
204
|
+
}
|
|
205
|
+
super(exports.TurbineErrorCode.NOT_NULL_VIOLATION, message, { cause });
|
|
206
|
+
this.name = 'NotNullViolationError';
|
|
207
|
+
this.column = column;
|
|
208
|
+
this.table = table;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
exports.NotNullViolationError = NotNullViolationError;
|
|
212
|
+
/** Thrown when a CHECK constraint is violated (pg code 23514) */
|
|
213
|
+
class CheckConstraintError extends TurbineError {
|
|
214
|
+
constraint;
|
|
215
|
+
table;
|
|
216
|
+
constructor(opts = {}) {
|
|
217
|
+
const { constraint, table, cause } = opts;
|
|
218
|
+
let message = opts.message;
|
|
219
|
+
if (!message) {
|
|
220
|
+
const constraintPart = constraint ? ` on ${constraint}` : '';
|
|
221
|
+
message = `[turbine] Check constraint violation${constraintPart}`;
|
|
222
|
+
const detail = detailFromCause(cause);
|
|
223
|
+
if (detail)
|
|
224
|
+
message += `: ${detail}`;
|
|
225
|
+
}
|
|
226
|
+
super(exports.TurbineErrorCode.CHECK_VIOLATION, message, { cause });
|
|
227
|
+
this.name = 'CheckConstraintError';
|
|
228
|
+
this.constraint = constraint;
|
|
229
|
+
this.table = table;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
exports.CheckConstraintError = CheckConstraintError;
|
|
233
|
+
/**
|
|
234
|
+
* Parse column names out of a pg `detail` string like:
|
|
235
|
+
* "Key (email)=(foo@bar) already exists."
|
|
236
|
+
* "Key (col1, col2)=(v1, v2) already exists."
|
|
237
|
+
*/
|
|
238
|
+
function parseColumnsFromDetail(detail) {
|
|
239
|
+
const m = detail.match(/^Key \(([^)]+)\)/);
|
|
240
|
+
if (!m)
|
|
241
|
+
return undefined;
|
|
242
|
+
return m[1].split(',').map((s) => s.trim());
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Translate a pg driver error into a typed Turbine error.
|
|
246
|
+
* If the error doesn't match a known constraint code, returns it unchanged.
|
|
247
|
+
*
|
|
248
|
+
* Maps:
|
|
249
|
+
* 23505 (unique_violation) -> UniqueConstraintError
|
|
250
|
+
* 23503 (foreign_key_violation) -> ForeignKeyError
|
|
251
|
+
* 23502 (not_null_violation) -> NotNullViolationError
|
|
252
|
+
* 23514 (check_violation) -> CheckConstraintError
|
|
253
|
+
*
|
|
254
|
+
* The original pg error is preserved as `.cause` on the wrapped error.
|
|
255
|
+
*/
|
|
256
|
+
function wrapPgError(err) {
|
|
257
|
+
if (!err || typeof err !== 'object')
|
|
258
|
+
return err;
|
|
259
|
+
const e = err;
|
|
260
|
+
if (!e.code)
|
|
261
|
+
return err;
|
|
262
|
+
switch (e.code) {
|
|
263
|
+
case '23505': {
|
|
264
|
+
const cols = e.detail ? parseColumnsFromDetail(e.detail) : undefined;
|
|
265
|
+
return new UniqueConstraintError({
|
|
266
|
+
constraint: e.constraint,
|
|
267
|
+
columns: cols,
|
|
268
|
+
table: e.table,
|
|
269
|
+
cause: err,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
case '23503':
|
|
273
|
+
return new ForeignKeyError({
|
|
274
|
+
constraint: e.constraint,
|
|
275
|
+
table: e.table,
|
|
276
|
+
cause: err,
|
|
277
|
+
});
|
|
278
|
+
case '23502':
|
|
279
|
+
return new NotNullViolationError({
|
|
280
|
+
column: e.column,
|
|
281
|
+
table: e.table,
|
|
282
|
+
cause: err,
|
|
283
|
+
});
|
|
284
|
+
case '23514':
|
|
285
|
+
return new CheckConstraintError({
|
|
286
|
+
constraint: e.constraint,
|
|
287
|
+
table: e.table,
|
|
288
|
+
cause: err,
|
|
289
|
+
});
|
|
290
|
+
default:
|
|
291
|
+
return err;
|
|
292
|
+
}
|
|
293
|
+
}
|
package/dist/cjs/generate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* turbine-orm — Code generator
|
|
4
4
|
*
|
|
5
5
|
* Takes an IntrospectedSchema and emits TypeScript files:
|
|
6
6
|
* - types.ts — Entity interfaces, Create/Update input types
|
|
@@ -55,18 +55,16 @@ function generate(options) {
|
|
|
55
55
|
function generatedFileHeader() {
|
|
56
56
|
return [
|
|
57
57
|
'/**',
|
|
58
|
-
' * Auto-generated by
|
|
58
|
+
' * Auto-generated by turbine-orm — DO NOT EDIT',
|
|
59
59
|
' *',
|
|
60
60
|
` * Generated at: ${new Date().toISOString()}`,
|
|
61
|
-
' * @see https://
|
|
61
|
+
' * @see https://turbineorm.dev',
|
|
62
62
|
' */',
|
|
63
63
|
'',
|
|
64
64
|
];
|
|
65
65
|
}
|
|
66
66
|
function generateTypes(schema) {
|
|
67
|
-
const lines = [
|
|
68
|
-
...generatedFileHeader(),
|
|
69
|
-
];
|
|
67
|
+
const lines = [...generatedFileHeader()];
|
|
70
68
|
// Generate enum types
|
|
71
69
|
for (const [enumName, labels] of Object.entries(schema.enums)) {
|
|
72
70
|
const typeName = (0, schema_js_1.snakeToPascal)(enumName);
|
|
@@ -116,9 +114,23 @@ function generateTypes(schema) {
|
|
|
116
114
|
}
|
|
117
115
|
lines.push('};');
|
|
118
116
|
lines.push('');
|
|
119
|
-
// ---
|
|
117
|
+
// --- Relations map (for type-safe `with` clauses) ---
|
|
120
118
|
const hasRelations = Object.keys(table.relations).length > 0;
|
|
121
119
|
if (hasRelations) {
|
|
120
|
+
lines.push(`/** Available relations for the \`${table.name}\` table */`);
|
|
121
|
+
lines.push(`export interface ${typeName}Relations {`);
|
|
122
|
+
for (const [relName, rel] of Object.entries(table.relations)) {
|
|
123
|
+
const targetType = entityName(rel.to);
|
|
124
|
+
if (rel.type === 'hasMany') {
|
|
125
|
+
lines.push(` ${relName}: ${targetType}[];`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
lines.push(` ${relName}: ${targetType} | null;`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
lines.push('}');
|
|
132
|
+
lines.push('');
|
|
133
|
+
// --- Legacy per-relation interfaces (kept for backward compatibility) ---
|
|
122
134
|
for (const [relName, rel] of Object.entries(table.relations)) {
|
|
123
135
|
const targetType = entityName(rel.to);
|
|
124
136
|
if (rel.type === 'hasMany') {
|
|
@@ -145,7 +157,7 @@ function generateTypes(schema) {
|
|
|
145
157
|
function generateMetadata(schema) {
|
|
146
158
|
const lines = [
|
|
147
159
|
...generatedFileHeader(),
|
|
148
|
-
"import type { SchemaMetadata } from '
|
|
160
|
+
"import type { SchemaMetadata } from 'turbine-orm';",
|
|
149
161
|
'',
|
|
150
162
|
'export const SCHEMA: SchemaMetadata = {',
|
|
151
163
|
' tables: {',
|
|
@@ -218,12 +230,18 @@ function generateIndex(schema) {
|
|
|
218
230
|
const tableEntries = Object.values(schema.tables);
|
|
219
231
|
const lines = [
|
|
220
232
|
...generatedFileHeader(),
|
|
221
|
-
"import { TurbineClient as BaseTurbineClient, QueryInterface } from '
|
|
222
|
-
"import type { TurbineConfig } from '
|
|
233
|
+
"import { TurbineClient as BaseTurbineClient, QueryInterface } from 'turbine-orm';",
|
|
234
|
+
"import type { TurbineConfig } from 'turbine-orm';",
|
|
223
235
|
"import { SCHEMA } from './metadata.js';",
|
|
224
236
|
];
|
|
225
|
-
// Import all entity types
|
|
226
|
-
const typeImports =
|
|
237
|
+
// Import all entity types and relations maps
|
|
238
|
+
const typeImports = [];
|
|
239
|
+
for (const t of tableEntries) {
|
|
240
|
+
typeImports.push(entityName(t.name));
|
|
241
|
+
if (Object.keys(t.relations).length > 0) {
|
|
242
|
+
typeImports.push(`${entityName(t.name)}Relations`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
227
245
|
lines.push(`import type { ${typeImports.join(', ')} } from './types.js';`);
|
|
228
246
|
lines.push('');
|
|
229
247
|
// Generate the client class with JSDoc
|
|
@@ -249,8 +267,10 @@ function generateIndex(schema) {
|
|
|
249
267
|
for (const table of tableEntries) {
|
|
250
268
|
const typeName = entityName(table.name);
|
|
251
269
|
const accessor = snakeToCamelStr(table.name);
|
|
270
|
+
const hasRelations = Object.keys(table.relations).length > 0;
|
|
271
|
+
const genericArgs = hasRelations ? `${typeName}, ${typeName}Relations` : typeName;
|
|
252
272
|
lines.push(` /** Query interface for the \`${table.name}\` table */`);
|
|
253
|
-
lines.push(` declare readonly ${accessor}: QueryInterface<${
|
|
273
|
+
lines.push(` declare readonly ${accessor}: QueryInterface<${genericArgs}>;`);
|
|
254
274
|
}
|
|
255
275
|
lines.push('');
|
|
256
276
|
lines.push(' constructor(config?: TurbineConfig) {');
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* turbine-orm
|
|
4
4
|
*
|
|
5
5
|
* Turbine TypeScript SDK — type-safe Postgres queries with nested relations
|
|
6
6
|
* and pipeline batching. Feels like Prisma, runs at raw-SQL speed.
|
|
@@ -34,42 +34,61 @@
|
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
exports.schemaPush = exports.schemaDiff = exports.
|
|
37
|
+
exports.turbineHttp = exports.schemaToSQLString = exports.schemaToSQL = exports.schemaPush = exports.schemaDiff = exports.table = exports.defineSchema = exports.column = exports.ColumnBuilder = exports.snakeToPascal = exports.snakeToCamel = exports.singularize = exports.pgTypeToTs = exports.pgArrayType = exports.isDateType = exports.camelToSnake = exports.QueryInterface = exports.executePipeline = exports.introspect = exports.generate = exports.wrapPgError = exports.ValidationError = exports.UniqueConstraintError = exports.TurbineErrorCode = exports.TurbineError = exports.TimeoutError = exports.RelationError = exports.NotNullViolationError = exports.NotFoundError = exports.MigrationError = exports.ForeignKeyError = exports.ConnectionError = exports.CircularRelationError = exports.CheckConstraintError = exports.TurbineClient = exports.TransactionClient = void 0;
|
|
38
38
|
// Client
|
|
39
39
|
var client_js_1 = require("./client.js");
|
|
40
|
-
Object.defineProperty(exports, "TurbineClient", { enumerable: true, get: function () { return client_js_1.TurbineClient; } });
|
|
41
40
|
Object.defineProperty(exports, "TransactionClient", { enumerable: true, get: function () { return client_js_1.TransactionClient; } });
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
Object.defineProperty(exports, "TurbineClient", { enumerable: true, get: function () { return client_js_1.TurbineClient; } });
|
|
42
|
+
// Error types
|
|
43
|
+
var errors_js_1 = require("./errors.js");
|
|
44
|
+
Object.defineProperty(exports, "CheckConstraintError", { enumerable: true, get: function () { return errors_js_1.CheckConstraintError; } });
|
|
45
|
+
Object.defineProperty(exports, "CircularRelationError", { enumerable: true, get: function () { return errors_js_1.CircularRelationError; } });
|
|
46
|
+
Object.defineProperty(exports, "ConnectionError", { enumerable: true, get: function () { return errors_js_1.ConnectionError; } });
|
|
47
|
+
Object.defineProperty(exports, "ForeignKeyError", { enumerable: true, get: function () { return errors_js_1.ForeignKeyError; } });
|
|
48
|
+
Object.defineProperty(exports, "MigrationError", { enumerable: true, get: function () { return errors_js_1.MigrationError; } });
|
|
49
|
+
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return errors_js_1.NotFoundError; } });
|
|
50
|
+
Object.defineProperty(exports, "NotNullViolationError", { enumerable: true, get: function () { return errors_js_1.NotNullViolationError; } });
|
|
51
|
+
Object.defineProperty(exports, "RelationError", { enumerable: true, get: function () { return errors_js_1.RelationError; } });
|
|
52
|
+
Object.defineProperty(exports, "TimeoutError", { enumerable: true, get: function () { return errors_js_1.TimeoutError; } });
|
|
53
|
+
Object.defineProperty(exports, "TurbineError", { enumerable: true, get: function () { return errors_js_1.TurbineError; } });
|
|
54
|
+
Object.defineProperty(exports, "TurbineErrorCode", { enumerable: true, get: function () { return errors_js_1.TurbineErrorCode; } });
|
|
55
|
+
Object.defineProperty(exports, "UniqueConstraintError", { enumerable: true, get: function () { return errors_js_1.UniqueConstraintError; } });
|
|
56
|
+
Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return errors_js_1.ValidationError; } });
|
|
57
|
+
Object.defineProperty(exports, "wrapPgError", { enumerable: true, get: function () { return errors_js_1.wrapPgError; } });
|
|
58
|
+
// Code generation
|
|
59
|
+
var generate_js_1 = require("./generate.js");
|
|
60
|
+
Object.defineProperty(exports, "generate", { enumerable: true, get: function () { return generate_js_1.generate; } });
|
|
61
|
+
// Introspection
|
|
62
|
+
var introspect_js_1 = require("./introspect.js");
|
|
63
|
+
Object.defineProperty(exports, "introspect", { enumerable: true, get: function () { return introspect_js_1.introspect; } });
|
|
45
64
|
// Pipeline
|
|
46
65
|
var pipeline_js_1 = require("./pipeline.js");
|
|
47
66
|
Object.defineProperty(exports, "executePipeline", { enumerable: true, get: function () { return pipeline_js_1.executePipeline; } });
|
|
67
|
+
// Query builder
|
|
68
|
+
var query_js_1 = require("./query.js");
|
|
69
|
+
Object.defineProperty(exports, "QueryInterface", { enumerable: true, get: function () { return query_js_1.QueryInterface; } });
|
|
48
70
|
// Schema utilities
|
|
49
71
|
var schema_js_1 = require("./schema.js");
|
|
50
|
-
Object.defineProperty(exports, "snakeToCamel", { enumerable: true, get: function () { return schema_js_1.snakeToCamel; } });
|
|
51
72
|
Object.defineProperty(exports, "camelToSnake", { enumerable: true, get: function () { return schema_js_1.camelToSnake; } });
|
|
52
|
-
Object.defineProperty(exports, "snakeToPascal", { enumerable: true, get: function () { return schema_js_1.snakeToPascal; } });
|
|
53
|
-
Object.defineProperty(exports, "singularize", { enumerable: true, get: function () { return schema_js_1.singularize; } });
|
|
54
|
-
Object.defineProperty(exports, "pgTypeToTs", { enumerable: true, get: function () { return schema_js_1.pgTypeToTs; } });
|
|
55
73
|
Object.defineProperty(exports, "isDateType", { enumerable: true, get: function () { return schema_js_1.isDateType; } });
|
|
56
74
|
Object.defineProperty(exports, "pgArrayType", { enumerable: true, get: function () { return schema_js_1.pgArrayType; } });
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Object.defineProperty(exports, "
|
|
60
|
-
|
|
61
|
-
var generate_js_1 = require("./generate.js");
|
|
62
|
-
Object.defineProperty(exports, "generate", { enumerable: true, get: function () { return generate_js_1.generate; } });
|
|
75
|
+
Object.defineProperty(exports, "pgTypeToTs", { enumerable: true, get: function () { return schema_js_1.pgTypeToTs; } });
|
|
76
|
+
Object.defineProperty(exports, "singularize", { enumerable: true, get: function () { return schema_js_1.singularize; } });
|
|
77
|
+
Object.defineProperty(exports, "snakeToCamel", { enumerable: true, get: function () { return schema_js_1.snakeToCamel; } });
|
|
78
|
+
Object.defineProperty(exports, "snakeToPascal", { enumerable: true, get: function () { return schema_js_1.snakeToPascal; } });
|
|
63
79
|
// Schema builder — define schemas in TypeScript
|
|
64
80
|
var schema_builder_js_1 = require("./schema-builder.js");
|
|
81
|
+
Object.defineProperty(exports, "ColumnBuilder", { enumerable: true, get: function () { return schema_builder_js_1.ColumnBuilder; } });
|
|
82
|
+
Object.defineProperty(exports, "column", { enumerable: true, get: function () { return schema_builder_js_1.column; } });
|
|
65
83
|
Object.defineProperty(exports, "defineSchema", { enumerable: true, get: function () { return schema_builder_js_1.defineSchema; } });
|
|
66
84
|
// Legacy compat (deprecated — use object format with defineSchema)
|
|
67
85
|
Object.defineProperty(exports, "table", { enumerable: true, get: function () { return schema_builder_js_1.table; } });
|
|
68
|
-
Object.defineProperty(exports, "column", { enumerable: true, get: function () { return schema_builder_js_1.column; } });
|
|
69
|
-
Object.defineProperty(exports, "ColumnBuilder", { enumerable: true, get: function () { return schema_builder_js_1.ColumnBuilder; } });
|
|
70
86
|
// Schema SQL — generate DDL, diff, and push
|
|
71
87
|
var schema_sql_js_1 = require("./schema-sql.js");
|
|
72
|
-
Object.defineProperty(exports, "schemaToSQL", { enumerable: true, get: function () { return schema_sql_js_1.schemaToSQL; } });
|
|
73
|
-
Object.defineProperty(exports, "schemaToSQLString", { enumerable: true, get: function () { return schema_sql_js_1.schemaToSQLString; } });
|
|
74
88
|
Object.defineProperty(exports, "schemaDiff", { enumerable: true, get: function () { return schema_sql_js_1.schemaDiff; } });
|
|
75
89
|
Object.defineProperty(exports, "schemaPush", { enumerable: true, get: function () { return schema_sql_js_1.schemaPush; } });
|
|
90
|
+
Object.defineProperty(exports, "schemaToSQL", { enumerable: true, get: function () { return schema_sql_js_1.schemaToSQL; } });
|
|
91
|
+
Object.defineProperty(exports, "schemaToSQLString", { enumerable: true, get: function () { return schema_sql_js_1.schemaToSQLString; } });
|
|
92
|
+
// Serverless / edge factory
|
|
93
|
+
var serverless_js_1 = require("./serverless.js");
|
|
94
|
+
Object.defineProperty(exports, "turbineHttp", { enumerable: true, get: function () { return serverless_js_1.turbineHttp; } });
|
package/dist/cjs/introspect.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* turbine-orm — Schema introspection
|
|
4
4
|
*
|
|
5
5
|
* Connects to a live Postgres database, reads information_schema + pg_catalog,
|
|
6
6
|
* and produces a SchemaMetadata object describing every table, column, relation,
|
|
@@ -105,7 +105,7 @@ async function introspect(options) {
|
|
|
105
105
|
});
|
|
106
106
|
try {
|
|
107
107
|
// Run all information_schema queries in parallel
|
|
108
|
-
const [tablesResult, columnsResult, pkResult, fkResult, uniqueResult, indexResult, enumResult
|
|
108
|
+
const [tablesResult, columnsResult, pkResult, fkResult, uniqueResult, indexResult, enumResult] = await Promise.all([
|
|
109
109
|
pool.query(SQL_TABLES, [schema]),
|
|
110
110
|
pool.query(SQL_COLUMNS, [schema]),
|
|
111
111
|
pool.query(SQL_PRIMARY_KEYS, [schema]),
|
|
@@ -178,9 +178,7 @@ async function introspect(options) {
|
|
|
178
178
|
const isUnique = row.indexdef.includes('UNIQUE');
|
|
179
179
|
// Extract column names from indexdef (e.g. "CREATE INDEX idx ON tbl USING btree (col1, col2)")
|
|
180
180
|
const colMatch = row.indexdef.match(/\((.+)\)/);
|
|
181
|
-
const columns = colMatch
|
|
182
|
-
? colMatch[1].split(',').map((c) => c.trim().replace(/ (ASC|DESC)/i, ''))
|
|
183
|
-
: [];
|
|
181
|
+
const columns = colMatch ? colMatch[1].split(',').map((c) => c.trim().replace(/ (ASC|DESC)/i, '')) : [];
|
|
184
182
|
indexesByTable.get(row.tablename).push({
|
|
185
183
|
name: row.indexname,
|
|
186
184
|
columns,
|
package/dist/cjs/pipeline.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* turbine-orm — Pipeline execution
|
|
4
4
|
*
|
|
5
5
|
* Pipelines batch multiple independent queries into a single database round-trip.
|
|
6
6
|
* Instead of N sequential awaits (N round-trips), you get 1 round-trip for all N queries.
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
20
|
exports.executePipeline = executePipeline;
|
|
21
|
+
const errors_js_1 = require("./errors.js");
|
|
21
22
|
// ---------------------------------------------------------------------------
|
|
22
23
|
// Pipeline executor
|
|
23
24
|
// ---------------------------------------------------------------------------
|
|
@@ -55,7 +56,13 @@ async function executePipeline(pool, queries) {
|
|
|
55
56
|
// Future: use actual Postgres pipeline protocol for true pipelining.
|
|
56
57
|
const results = [];
|
|
57
58
|
for (const q of queries) {
|
|
58
|
-
|
|
59
|
+
let raw;
|
|
60
|
+
try {
|
|
61
|
+
raw = await client.query(q.sql, q.params);
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
throw (0, errors_js_1.wrapPgError)(err);
|
|
65
|
+
}
|
|
59
66
|
results.push(q.transform(raw));
|
|
60
67
|
}
|
|
61
68
|
await client.query('COMMIT');
|