@superfunctions/db 0.1.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 +341 -0
- package/dist/adapter/capabilities.d.ts +51 -0
- package/dist/adapter/capabilities.d.ts.map +1 -0
- package/dist/adapter/capabilities.js +56 -0
- package/dist/adapter/capabilities.js.map +1 -0
- package/dist/adapter/errors.d.ts +111 -0
- package/dist/adapter/errors.d.ts.map +1 -0
- package/dist/adapter/errors.js +172 -0
- package/dist/adapter/errors.js.map +1 -0
- package/dist/adapter/factory.d.ts +10 -0
- package/dist/adapter/factory.d.ts.map +1 -0
- package/dist/adapter/factory.js +232 -0
- package/dist/adapter/factory.js.map +1 -0
- package/dist/adapter/types.d.ts +255 -0
- package/dist/adapter/types.d.ts.map +1 -0
- package/dist/adapter/types.js +5 -0
- package/dist/adapter/types.js.map +1 -0
- package/dist/adapters/drizzle/index.d.ts +20 -0
- package/dist/adapters/drizzle/index.d.ts.map +1 -0
- package/dist/adapters/drizzle/index.js +346 -0
- package/dist/adapters/drizzle/index.js.map +1 -0
- package/dist/adapters/index.d.ts +12 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +12 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/kysely/index.d.ts +18 -0
- package/dist/adapters/kysely/index.d.ts.map +1 -0
- package/dist/adapters/kysely/index.js +305 -0
- package/dist/adapters/kysely/index.js.map +1 -0
- package/dist/adapters/memory/index.d.ts +17 -0
- package/dist/adapters/memory/index.d.ts.map +1 -0
- package/dist/adapters/memory/index.js +362 -0
- package/dist/adapters/memory/index.js.map +1 -0
- package/dist/adapters/prisma/index.d.ts +16 -0
- package/dist/adapters/prisma/index.d.ts.map +1 -0
- package/dist/adapters/prisma/index.js +247 -0
- package/dist/adapters/prisma/index.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/runtime-validation.d.ts +7 -0
- package/dist/migrations/runtime-validation.d.ts.map +1 -0
- package/dist/migrations/runtime-validation.js +40 -0
- package/dist/migrations/runtime-validation.js.map +1 -0
- package/dist/migrations/schema-tracker.d.ts +56 -0
- package/dist/migrations/schema-tracker.d.ts.map +1 -0
- package/dist/migrations/schema-tracker.js +121 -0
- package/dist/migrations/schema-tracker.js.map +1 -0
- package/dist/testing/contract-tests.d.ts +64 -0
- package/dist/testing/contract-tests.d.ts.map +1 -0
- package/dist/testing/contract-tests.js +391 -0
- package/dist/testing/contract-tests.js.map +1 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +10 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/mocks.d.ts +92 -0
- package/dist/testing/mocks.d.ts.map +1 -0
- package/dist/testing/mocks.js +197 -0
- package/dist/testing/mocks.js.map +1 -0
- package/dist/utils/namespace.d.ts +49 -0
- package/dist/utils/namespace.d.ts.map +1 -0
- package/dist/utils/namespace.js +85 -0
- package/dist/utils/namespace.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core type definitions for the adapter system
|
|
3
|
+
*/
|
|
4
|
+
import type { AdapterCapabilities } from './capabilities.js';
|
|
5
|
+
export interface Adapter {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly version: string;
|
|
9
|
+
readonly capabilities: AdapterCapabilities;
|
|
10
|
+
create<T = any>(params: CreateParams): Promise<T>;
|
|
11
|
+
findOne<T = any>(params: FindOneParams): Promise<T | null>;
|
|
12
|
+
findMany<T = any>(params: FindManyParams): Promise<T[]>;
|
|
13
|
+
update<T = any>(params: UpdateParams): Promise<T>;
|
|
14
|
+
delete(params: DeleteParams): Promise<void>;
|
|
15
|
+
createMany<T = any>(params: CreateManyParams): Promise<T[]>;
|
|
16
|
+
updateMany(params: UpdateManyParams): Promise<number>;
|
|
17
|
+
deleteMany(params: DeleteManyParams): Promise<number>;
|
|
18
|
+
upsert<T = any>(params: UpsertParams): Promise<T>;
|
|
19
|
+
count(params: CountParams): Promise<number>;
|
|
20
|
+
transaction<R>(callback: (trx: TransactionAdapter) => Promise<R>): Promise<R>;
|
|
21
|
+
initialize(): Promise<void>;
|
|
22
|
+
isHealthy(): Promise<HealthStatus>;
|
|
23
|
+
close(): Promise<void>;
|
|
24
|
+
getSchemaVersion(namespace: string): Promise<number>;
|
|
25
|
+
setSchemaVersion(namespace: string, version: number): Promise<void>;
|
|
26
|
+
validateSchema(schema: TableSchema): Promise<ValidationResult>;
|
|
27
|
+
createSchema?(params: CreateSchemaParams): Promise<SchemaCreation>;
|
|
28
|
+
}
|
|
29
|
+
export interface TransactionAdapter extends Omit<Adapter, 'transaction' | 'close'> {
|
|
30
|
+
commit(): Promise<void>;
|
|
31
|
+
rollback(): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export interface HealthStatus {
|
|
34
|
+
healthy: boolean;
|
|
35
|
+
connections?: {
|
|
36
|
+
active: number;
|
|
37
|
+
idle: number;
|
|
38
|
+
max: number;
|
|
39
|
+
};
|
|
40
|
+
lastError?: Error;
|
|
41
|
+
uptime: number;
|
|
42
|
+
}
|
|
43
|
+
export interface CreateParams {
|
|
44
|
+
model: string;
|
|
45
|
+
data: Record<string, any>;
|
|
46
|
+
select?: string[];
|
|
47
|
+
namespace?: string;
|
|
48
|
+
}
|
|
49
|
+
export interface FindOneParams {
|
|
50
|
+
model: string;
|
|
51
|
+
where: WhereClause[];
|
|
52
|
+
select?: string[];
|
|
53
|
+
join?: JoinConfig;
|
|
54
|
+
namespace?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface FindManyParams extends FindOneParams {
|
|
57
|
+
limit?: number;
|
|
58
|
+
offset?: number;
|
|
59
|
+
orderBy?: OrderBy[];
|
|
60
|
+
}
|
|
61
|
+
export interface UpdateParams {
|
|
62
|
+
model: string;
|
|
63
|
+
where: WhereClause[];
|
|
64
|
+
data: Record<string, any>;
|
|
65
|
+
select?: string[];
|
|
66
|
+
namespace?: string;
|
|
67
|
+
}
|
|
68
|
+
export interface DeleteParams {
|
|
69
|
+
model: string;
|
|
70
|
+
where: WhereClause[];
|
|
71
|
+
namespace?: string;
|
|
72
|
+
}
|
|
73
|
+
export interface CreateManyParams {
|
|
74
|
+
model: string;
|
|
75
|
+
data: Record<string, any>[];
|
|
76
|
+
select?: string[];
|
|
77
|
+
namespace?: string;
|
|
78
|
+
}
|
|
79
|
+
export interface UpdateManyParams {
|
|
80
|
+
model: string;
|
|
81
|
+
where: WhereClause[];
|
|
82
|
+
data: Record<string, any>;
|
|
83
|
+
namespace?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface DeleteManyParams {
|
|
86
|
+
model: string;
|
|
87
|
+
where: WhereClause[];
|
|
88
|
+
namespace?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface UpsertParams {
|
|
91
|
+
model: string;
|
|
92
|
+
where: WhereClause[];
|
|
93
|
+
create: Record<string, any>;
|
|
94
|
+
update: Record<string, any>;
|
|
95
|
+
select?: string[];
|
|
96
|
+
namespace?: string;
|
|
97
|
+
}
|
|
98
|
+
export interface CountParams {
|
|
99
|
+
model: string;
|
|
100
|
+
where?: WhereClause[];
|
|
101
|
+
namespace?: string;
|
|
102
|
+
}
|
|
103
|
+
export interface WhereClause {
|
|
104
|
+
field: string;
|
|
105
|
+
operator: 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'not_in' | 'contains' | 'starts_with' | 'ends_with';
|
|
106
|
+
value: any;
|
|
107
|
+
connector?: 'AND' | 'OR';
|
|
108
|
+
}
|
|
109
|
+
export interface OrderBy {
|
|
110
|
+
field: string;
|
|
111
|
+
direction: 'asc' | 'desc';
|
|
112
|
+
}
|
|
113
|
+
export interface JoinConfig {
|
|
114
|
+
model: string;
|
|
115
|
+
on: {
|
|
116
|
+
field: string;
|
|
117
|
+
foreignField: string;
|
|
118
|
+
};
|
|
119
|
+
type?: 'inner' | 'left' | 'right';
|
|
120
|
+
}
|
|
121
|
+
export interface TableSchema {
|
|
122
|
+
modelName: string;
|
|
123
|
+
fields: Record<string, FieldSchema>;
|
|
124
|
+
indexes?: IndexSchema[];
|
|
125
|
+
constraints?: ConstraintSchema[];
|
|
126
|
+
}
|
|
127
|
+
export interface FieldSchema {
|
|
128
|
+
type: 'string' | 'number' | 'boolean' | 'date' | 'json' | 'bigint';
|
|
129
|
+
required?: boolean;
|
|
130
|
+
unique?: boolean;
|
|
131
|
+
defaultValue?: any;
|
|
132
|
+
references?: {
|
|
133
|
+
model: string;
|
|
134
|
+
field: string;
|
|
135
|
+
onDelete?: 'cascade' | 'set null' | 'restrict';
|
|
136
|
+
onUpdate?: 'cascade' | 'set null' | 'restrict';
|
|
137
|
+
};
|
|
138
|
+
fieldName?: string;
|
|
139
|
+
}
|
|
140
|
+
export interface IndexSchema {
|
|
141
|
+
name: string;
|
|
142
|
+
fields: string[];
|
|
143
|
+
unique?: boolean;
|
|
144
|
+
}
|
|
145
|
+
export interface ConstraintSchema {
|
|
146
|
+
name: string;
|
|
147
|
+
type: 'check' | 'unique' | 'foreign_key';
|
|
148
|
+
fields: string[];
|
|
149
|
+
check?: string;
|
|
150
|
+
}
|
|
151
|
+
export type TableSchemaMap = Record<string, TableSchema>;
|
|
152
|
+
export interface ValidationResult {
|
|
153
|
+
valid: boolean;
|
|
154
|
+
errors?: string[];
|
|
155
|
+
}
|
|
156
|
+
export interface CreateSchemaParams {
|
|
157
|
+
schema: TableSchemaMap;
|
|
158
|
+
namespace?: string;
|
|
159
|
+
}
|
|
160
|
+
export interface SchemaCreation {
|
|
161
|
+
sql?: string;
|
|
162
|
+
success: boolean;
|
|
163
|
+
errors?: string[];
|
|
164
|
+
}
|
|
165
|
+
export interface AdapterFactoryConfig {
|
|
166
|
+
adapterId: string;
|
|
167
|
+
adapterName?: string;
|
|
168
|
+
capabilities?: Partial<AdapterCapabilities>;
|
|
169
|
+
supportsJSON?: boolean;
|
|
170
|
+
supportsDates?: boolean;
|
|
171
|
+
supportsBooleans?: boolean;
|
|
172
|
+
supportsNumericIds?: boolean;
|
|
173
|
+
usePlural?: boolean;
|
|
174
|
+
caseStyle?: 'snake_case' | 'camelCase' | 'PascalCase';
|
|
175
|
+
namespace?: {
|
|
176
|
+
enabled: boolean;
|
|
177
|
+
separator?: string;
|
|
178
|
+
prefix?: string;
|
|
179
|
+
schemaSupport?: boolean;
|
|
180
|
+
};
|
|
181
|
+
transaction?: boolean | {
|
|
182
|
+
enabled: boolean;
|
|
183
|
+
isolationLevel?: TransactionIsolation;
|
|
184
|
+
timeout?: number;
|
|
185
|
+
};
|
|
186
|
+
mapKeysInput?: Record<string, string>;
|
|
187
|
+
mapKeysOutput?: Record<string, string>;
|
|
188
|
+
customIdGenerator?: () => string | number;
|
|
189
|
+
disableIdGeneration?: boolean;
|
|
190
|
+
debug?: boolean | {
|
|
191
|
+
logQueries?: boolean;
|
|
192
|
+
logResults?: boolean;
|
|
193
|
+
logTransactions?: boolean;
|
|
194
|
+
};
|
|
195
|
+
performance?: {
|
|
196
|
+
maxBatchSize?: number;
|
|
197
|
+
queryTimeout?: number;
|
|
198
|
+
maxConnections?: number;
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
export type TransactionIsolation = 'read_uncommitted' | 'read_committed' | 'repeatable_read' | 'serializable';
|
|
202
|
+
export interface LibraryOptions {
|
|
203
|
+
namespace?: string;
|
|
204
|
+
schema?: TableSchemaMap;
|
|
205
|
+
validateSchema?: boolean;
|
|
206
|
+
autoMigrate?: boolean;
|
|
207
|
+
}
|
|
208
|
+
export interface AdapterContext {
|
|
209
|
+
options: LibraryOptions;
|
|
210
|
+
schema: TableSchemaMap;
|
|
211
|
+
getModelName: (model: string) => string;
|
|
212
|
+
getFieldName: (params: {
|
|
213
|
+
model: string;
|
|
214
|
+
field: string;
|
|
215
|
+
}) => string;
|
|
216
|
+
getDefaultModelName: (model: string) => string;
|
|
217
|
+
getDefaultFieldName: (params: {
|
|
218
|
+
model: string;
|
|
219
|
+
field: string;
|
|
220
|
+
}) => string;
|
|
221
|
+
transformInput: (data: any, model: string, action: 'create' | 'update') => Promise<any>;
|
|
222
|
+
transformOutput: (data: any, model: string) => Promise<any>;
|
|
223
|
+
log: Logger;
|
|
224
|
+
}
|
|
225
|
+
export interface Logger {
|
|
226
|
+
debug: (message: string, ...args: any[]) => void;
|
|
227
|
+
info: (message: string, ...args: any[]) => void;
|
|
228
|
+
warn: (message: string, ...args: any[]) => void;
|
|
229
|
+
error: (message: string, ...args: any[]) => void;
|
|
230
|
+
}
|
|
231
|
+
export interface AdapterImplementation {
|
|
232
|
+
create<T = any>(params: CreateParams): Promise<T>;
|
|
233
|
+
findOne<T = any>(params: FindOneParams): Promise<T | null>;
|
|
234
|
+
findMany<T = any>(params: FindManyParams): Promise<T[]>;
|
|
235
|
+
update<T = any>(params: UpdateParams): Promise<T>;
|
|
236
|
+
delete(params: DeleteParams): Promise<void>;
|
|
237
|
+
createMany<T = any>(params: CreateManyParams): Promise<T[]>;
|
|
238
|
+
updateMany(params: UpdateManyParams): Promise<number>;
|
|
239
|
+
deleteMany(params: DeleteManyParams): Promise<number>;
|
|
240
|
+
upsert<T = any>(params: UpsertParams): Promise<T>;
|
|
241
|
+
count(params: CountParams): Promise<number>;
|
|
242
|
+
transaction<R>(callback: (trx: TransactionAdapter) => Promise<R>): Promise<R>;
|
|
243
|
+
initialize(): Promise<void>;
|
|
244
|
+
isHealthy(): Promise<HealthStatus>;
|
|
245
|
+
close(): Promise<void>;
|
|
246
|
+
getSchemaVersion(namespace: string): Promise<number>;
|
|
247
|
+
setSchemaVersion(namespace: string, version: number): Promise<void>;
|
|
248
|
+
validateSchema(schema: TableSchema): Promise<ValidationResult>;
|
|
249
|
+
createSchema?(params: CreateSchemaParams): Promise<SchemaCreation>;
|
|
250
|
+
}
|
|
251
|
+
export interface AdapterFactoryOptions {
|
|
252
|
+
config: AdapterFactoryConfig;
|
|
253
|
+
adapter: (context: AdapterContext) => AdapterImplementation;
|
|
254
|
+
}
|
|
255
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapter/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/adapter/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drizzle adapter
|
|
3
|
+
*
|
|
4
|
+
* Generic adapter that maps the Superfunctions Adapter interface to Drizzle ORM.
|
|
5
|
+
* It requires callers to provide a mapping from model names to Drizzle table objects,
|
|
6
|
+
* plus (optionally) conflict targets for upsert and a schema versions table.
|
|
7
|
+
*/
|
|
8
|
+
import type { Adapter, AdapterFactoryOptions } from '../../adapter/types.js';
|
|
9
|
+
export type DrizzleDialect = 'postgres' | 'mysql' | 'sqlite';
|
|
10
|
+
export interface DrizzleAdapterConfig {
|
|
11
|
+
db: any;
|
|
12
|
+
schema: Record<string, any>;
|
|
13
|
+
dialect: DrizzleDialect;
|
|
14
|
+
upsertKeys?: Record<string, string | string[]>;
|
|
15
|
+
schemaVersionsTable?: any;
|
|
16
|
+
namespace?: AdapterFactoryOptions['config']['namespace'];
|
|
17
|
+
debug?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare function drizzleAdapter(config: DrizzleAdapterConfig): Adapter;
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/drizzle/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,OAAO,EAEP,qBAAqB,EAatB,MAAM,wBAAwB,CAAC;AAkBhC,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE7D,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,GAAG,CAAC;IACR,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,OAAO,EAAE,cAAc,CAAC;IAExB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAE/C,mBAAmB,CAAC,EAAE,GAAG,CAAC;IAC1B,SAAS,CAAC,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,CAAC;IACzD,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AA0DD,wBAAgB,cAAc,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CA2QpE"}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Drizzle adapter
|
|
3
|
+
*
|
|
4
|
+
* Generic adapter that maps the Superfunctions Adapter interface to Drizzle ORM.
|
|
5
|
+
* It requires callers to provide a mapping from model names to Drizzle table objects,
|
|
6
|
+
* plus (optionally) conflict targets for upsert and a schema versions table.
|
|
7
|
+
*/
|
|
8
|
+
import { createAdapterFactory } from '../../adapter/factory.js';
|
|
9
|
+
import { OperationNotSupportedError } from '../../adapter/errors.js';
|
|
10
|
+
// Import Drizzle helpers loosely to avoid strict peer typing
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
12
|
+
// These are type-unsafe on purpose to avoid hard binding to a specific driver.
|
|
13
|
+
// Drizzle exports these from 'drizzle-orm'.
|
|
14
|
+
// We fall back to minimal shims if not present at runtime.
|
|
15
|
+
let drizzleOps = {};
|
|
16
|
+
try {
|
|
17
|
+
// dynamic import to keep peer dep optional
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
drizzleOps = await import('drizzle-orm');
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// no-op: will throw if used without drizzle installed
|
|
23
|
+
}
|
|
24
|
+
function buildWhere(tbl, where) {
|
|
25
|
+
if (!where || where.length === 0)
|
|
26
|
+
return undefined;
|
|
27
|
+
const { and, or, not, eq, ne, gt, gte, lt, lte, inArray, sql } = drizzleOps;
|
|
28
|
+
const parts = where.map((clause) => {
|
|
29
|
+
const col = tbl[clause.field];
|
|
30
|
+
const op = clause.operator;
|
|
31
|
+
const val = clause.value;
|
|
32
|
+
switch (op) {
|
|
33
|
+
case 'eq':
|
|
34
|
+
return eq(col, val);
|
|
35
|
+
case 'ne':
|
|
36
|
+
return ne(col, val);
|
|
37
|
+
case 'gt':
|
|
38
|
+
return gt(col, val);
|
|
39
|
+
case 'gte':
|
|
40
|
+
return gte(col, val);
|
|
41
|
+
case 'lt':
|
|
42
|
+
return lt(col, val);
|
|
43
|
+
case 'lte':
|
|
44
|
+
return lte(col, val);
|
|
45
|
+
case 'in':
|
|
46
|
+
return inArray(col, Array.isArray(val) ? val : [val]);
|
|
47
|
+
case 'not_in':
|
|
48
|
+
return not(inArray(col, Array.isArray(val) ? val : [val]));
|
|
49
|
+
case 'contains':
|
|
50
|
+
return sql `${col} LIKE ${'%' + val + '%'}`;
|
|
51
|
+
case 'starts_with':
|
|
52
|
+
return sql `${col} LIKE ${val + '%'}`;
|
|
53
|
+
case 'ends_with':
|
|
54
|
+
return sql `${col} LIKE ${'%' + val}`;
|
|
55
|
+
default:
|
|
56
|
+
throw new Error(`Unsupported operator: ${op}`);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
// Combine using connectors (default AND)
|
|
60
|
+
if (parts.length === 0)
|
|
61
|
+
return undefined;
|
|
62
|
+
if (parts.length === 1)
|
|
63
|
+
return parts[0];
|
|
64
|
+
let combined = parts[0];
|
|
65
|
+
for (let i = 1; i < parts.length; i++) {
|
|
66
|
+
const connector = where[i]?.connector ?? 'AND';
|
|
67
|
+
combined = connector === 'OR' ? or(combined, parts[i]) : and(combined, parts[i]);
|
|
68
|
+
}
|
|
69
|
+
return combined;
|
|
70
|
+
}
|
|
71
|
+
function buildOrder(tbl, orderBy) {
|
|
72
|
+
if (!orderBy || orderBy.length === 0)
|
|
73
|
+
return undefined;
|
|
74
|
+
const { asc, desc } = drizzleOps;
|
|
75
|
+
return orderBy.map((o) => {
|
|
76
|
+
const col = tbl[o.field];
|
|
77
|
+
return o.direction === 'desc' ? desc(col) : asc(col);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
export function drizzleAdapter(config) {
|
|
81
|
+
if (!config?.db)
|
|
82
|
+
throw new Error('drizzleAdapter: config.db is required');
|
|
83
|
+
if (!config?.schema)
|
|
84
|
+
throw new Error('drizzleAdapter: config.schema is required');
|
|
85
|
+
if (!drizzleOps?.eq)
|
|
86
|
+
throw new Error('drizzle-orm is required as a peerDependency to use drizzleAdapter');
|
|
87
|
+
const createImpl = (ctx) => {
|
|
88
|
+
const { db, schema, dialect, schemaVersionsTable } = config;
|
|
89
|
+
const resolveTable = (model) => {
|
|
90
|
+
const tbl = schema[ctx.getModelName(model)];
|
|
91
|
+
if (!tbl)
|
|
92
|
+
throw new Error(`Drizzle adapter: no table mapping for model "${model}"`);
|
|
93
|
+
return tbl;
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
async create({ model, data, select }) {
|
|
97
|
+
const tbl = resolveTable(model);
|
|
98
|
+
const q = db.insert(tbl).values(data);
|
|
99
|
+
if (dialect === 'mysql') {
|
|
100
|
+
await q.execute();
|
|
101
|
+
// MySQL has no returning; fetch the inserted row if selection present
|
|
102
|
+
if (select && select.length > 0) {
|
|
103
|
+
const where = Object.keys(data)
|
|
104
|
+
.filter((k) => k in tbl)
|
|
105
|
+
.slice(0, 1)
|
|
106
|
+
.map((k) => ({ field: k, operator: 'eq', value: data[k] }));
|
|
107
|
+
const row = await this.findOne({ model, where, select });
|
|
108
|
+
return row;
|
|
109
|
+
}
|
|
110
|
+
return data;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const returning = select && select.length > 0 ? Object.fromEntries(select.map((k) => [k, tbl[k]])) : undefined;
|
|
114
|
+
const res = await (returning ? q.returning(returning) : q.returning()).execute();
|
|
115
|
+
return (res?.[0] ?? data);
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
async createMany({ model, data }) {
|
|
119
|
+
const tbl = resolveTable(model);
|
|
120
|
+
const q = db.insert(tbl).values(data);
|
|
121
|
+
if (dialect === 'mysql') {
|
|
122
|
+
await q.execute();
|
|
123
|
+
return data; // no returning
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
const res = await q.returning().execute();
|
|
127
|
+
return (res ?? data);
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
async findOne({ model, where, select }) {
|
|
131
|
+
const tbl = resolveTable(model);
|
|
132
|
+
const selection = select && select.length > 0 ? Object.fromEntries(select.map((k) => [k, tbl[k]])) : undefined;
|
|
133
|
+
const q = db.select(selection).from(tbl);
|
|
134
|
+
const cond = buildWhere(tbl, where);
|
|
135
|
+
const rows = await q.where(cond).limit(1).execute();
|
|
136
|
+
return rows?.[0] ?? null;
|
|
137
|
+
},
|
|
138
|
+
async findMany({ model, where, select, orderBy, limit, offset }) {
|
|
139
|
+
const tbl = resolveTable(model);
|
|
140
|
+
const selection = select && select.length > 0 ? Object.fromEntries(select.map((k) => [k, tbl[k]])) : undefined;
|
|
141
|
+
let q = db.select(selection).from(tbl);
|
|
142
|
+
const cond = buildWhere(tbl, where);
|
|
143
|
+
if (cond)
|
|
144
|
+
q = q.where(cond);
|
|
145
|
+
const order = buildOrder(tbl, orderBy);
|
|
146
|
+
if (order && order.length > 0)
|
|
147
|
+
q = q.orderBy(...order);
|
|
148
|
+
if (typeof limit === 'number')
|
|
149
|
+
q = q.limit(limit);
|
|
150
|
+
if (typeof offset === 'number')
|
|
151
|
+
q = q.offset(offset);
|
|
152
|
+
const rows = await q.execute();
|
|
153
|
+
return rows;
|
|
154
|
+
},
|
|
155
|
+
async update({ model, where, data, select }) {
|
|
156
|
+
const tbl = resolveTable(model);
|
|
157
|
+
const cond = buildWhere(tbl, where);
|
|
158
|
+
const q = db.update(tbl).set(data).where(cond);
|
|
159
|
+
if (dialect === 'mysql') {
|
|
160
|
+
await q.execute();
|
|
161
|
+
const row = await this.findOne({ model, where, select });
|
|
162
|
+
if (!row)
|
|
163
|
+
throw new Error('Update affected zero rows');
|
|
164
|
+
return row;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
const returning = select && select.length > 0 ? Object.fromEntries(select.map((k) => [k, tbl[k]])) : undefined;
|
|
168
|
+
const res = await (returning ? q.returning(returning) : q.returning()).execute();
|
|
169
|
+
return (Array.isArray(res) ? res[0] : res);
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
async updateMany({ model, where, data }) {
|
|
173
|
+
const tbl = resolveTable(model);
|
|
174
|
+
const cond = buildWhere(tbl, where);
|
|
175
|
+
const q = db.update(tbl).set(data).where(cond);
|
|
176
|
+
const result = await q.execute();
|
|
177
|
+
// drizzle returns driver-dependent result; for better-sqlite3 it's { changes: N, lastInsertRowid: X }
|
|
178
|
+
const n = result?.changes ?? result?.rowsAffected ?? result?.rowCount ?? 0;
|
|
179
|
+
return typeof n === 'number' ? n : 0;
|
|
180
|
+
},
|
|
181
|
+
async delete({ model, where }) {
|
|
182
|
+
const tbl = resolveTable(model);
|
|
183
|
+
const cond = buildWhere(tbl, where);
|
|
184
|
+
const q = db.delete(tbl).where(cond);
|
|
185
|
+
if (dialect === 'mysql') {
|
|
186
|
+
// MySQL no returning; attempt to fetch first then delete
|
|
187
|
+
const existing = await this.findOne({ model, where });
|
|
188
|
+
await db.delete(tbl).where(cond).execute();
|
|
189
|
+
return existing ?? null;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
const res = await q.execute();
|
|
193
|
+
void res; // ignore value; delete returns void
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
async deleteMany({ model, where }) {
|
|
197
|
+
const tbl = resolveTable(model);
|
|
198
|
+
const cond = buildWhere(tbl, where);
|
|
199
|
+
const res = await db.delete(tbl).where(cond).execute();
|
|
200
|
+
const n = res?.changes ?? res?.rowsAffected ?? res?.rowCount ?? 0;
|
|
201
|
+
return typeof n === 'number' ? n : 0;
|
|
202
|
+
},
|
|
203
|
+
async upsert({ model, where, create, update, select }) {
|
|
204
|
+
const tbl = resolveTable(model);
|
|
205
|
+
if (!where || where.length === 0)
|
|
206
|
+
throw new Error('upsert requires a non-empty where clause targeting unique columns');
|
|
207
|
+
// Determine conflict target
|
|
208
|
+
let target = config.upsertKeys?.[model];
|
|
209
|
+
if (!target) {
|
|
210
|
+
// derive from where fields
|
|
211
|
+
target = where.length === 1 ? where[0].field : where.map((w) => w.field);
|
|
212
|
+
}
|
|
213
|
+
if (config.dialect === 'mysql') {
|
|
214
|
+
const q = db.insert(tbl).values(create).onDuplicateKeyUpdate({ set: update });
|
|
215
|
+
if (select && select.length > 0) {
|
|
216
|
+
await q.execute();
|
|
217
|
+
// reselect
|
|
218
|
+
const row = await this.findOne({ model, where, select });
|
|
219
|
+
if (!row)
|
|
220
|
+
throw new Error('Upsert failed to return a row');
|
|
221
|
+
return row;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
await q.execute();
|
|
225
|
+
return create;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
const keys = Array.isArray(target) ? target.map((k) => tbl[k]) : [tbl[target]];
|
|
230
|
+
const returning = select && select.length > 0 ? Object.fromEntries(select.map((k) => [k, tbl[k]])) : undefined;
|
|
231
|
+
const q = db
|
|
232
|
+
.insert(tbl)
|
|
233
|
+
.values(create)
|
|
234
|
+
.onConflictDoUpdate({ target: keys, set: update });
|
|
235
|
+
const res = await (returning ? q.returning(returning) : q.returning()).execute();
|
|
236
|
+
return (Array.isArray(res) ? res[0] : res);
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
async count({ model, where }) {
|
|
240
|
+
const tbl = resolveTable(model);
|
|
241
|
+
const { sql } = drizzleOps;
|
|
242
|
+
const cond = buildWhere(tbl, where);
|
|
243
|
+
const rows = await db
|
|
244
|
+
.select({ value: sql `count(*)`.as('value') })
|
|
245
|
+
.from(tbl)
|
|
246
|
+
.where(cond)
|
|
247
|
+
.execute();
|
|
248
|
+
const v = rows?.[0]?.value;
|
|
249
|
+
return typeof v === 'number' ? v : Number(v ?? 0);
|
|
250
|
+
},
|
|
251
|
+
async transaction(fn) {
|
|
252
|
+
// Drizzle's transaction API varies by dialect
|
|
253
|
+
// For async dialects (postgres, mysql): db.transaction returns Promise
|
|
254
|
+
// For better-sqlite3: db.transaction must be synchronous
|
|
255
|
+
if (dialect === 'sqlite') {
|
|
256
|
+
// better-sqlite3 doesn't support async transaction callbacks natively
|
|
257
|
+
// fallback: execute directly without transaction wrapper for now
|
|
258
|
+
const child = drizzleAdapter({ ...config, db });
|
|
259
|
+
const txAdapter = {
|
|
260
|
+
...child,
|
|
261
|
+
transaction: async () => {
|
|
262
|
+
throw new OperationNotSupportedError('transaction', 'DrizzleAdapter (nested transaction)');
|
|
263
|
+
},
|
|
264
|
+
close: async () => { },
|
|
265
|
+
commit: async () => { },
|
|
266
|
+
rollback: async () => { },
|
|
267
|
+
};
|
|
268
|
+
return await fn(txAdapter);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
// Async transaction for postgres/mysql
|
|
272
|
+
return await db.transaction(async (trx) => {
|
|
273
|
+
const child = drizzleAdapter({ ...config, db: trx });
|
|
274
|
+
const txAdapter = {
|
|
275
|
+
...child,
|
|
276
|
+
transaction: async () => {
|
|
277
|
+
throw new OperationNotSupportedError('transaction', 'DrizzleAdapter (nested transaction)');
|
|
278
|
+
},
|
|
279
|
+
close: async () => { },
|
|
280
|
+
commit: async () => { },
|
|
281
|
+
rollback: async () => { },
|
|
282
|
+
};
|
|
283
|
+
return await fn(txAdapter);
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
async initialize() { return; },
|
|
288
|
+
async isHealthy() {
|
|
289
|
+
return { healthy: true, uptime: 0 };
|
|
290
|
+
},
|
|
291
|
+
async close() { return; },
|
|
292
|
+
async getSchemaVersion(namespace) {
|
|
293
|
+
if (!schemaVersionsTable)
|
|
294
|
+
return 0;
|
|
295
|
+
const rows = await db
|
|
296
|
+
.select({ version: schemaVersionsTable.version })
|
|
297
|
+
.from(schemaVersionsTable)
|
|
298
|
+
.where(drizzleOps.eq(schemaVersionsTable.namespace, namespace))
|
|
299
|
+
.limit(1)
|
|
300
|
+
.execute();
|
|
301
|
+
return rows?.[0]?.version ?? 0;
|
|
302
|
+
},
|
|
303
|
+
async setSchemaVersion(namespace, version) {
|
|
304
|
+
if (!schemaVersionsTable)
|
|
305
|
+
throw new OperationNotSupportedError('setSchemaVersion', 'DrizzleAdapter (schemaVersionsTable not configured)');
|
|
306
|
+
// Try update, then insert
|
|
307
|
+
const existing = await this.getSchemaVersion(namespace);
|
|
308
|
+
const now = new Date().toISOString();
|
|
309
|
+
if (existing === 0) {
|
|
310
|
+
await db.insert(schemaVersionsTable).values({ namespace, version, appliedAt: now }).execute();
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
await db
|
|
314
|
+
.update(schemaVersionsTable)
|
|
315
|
+
.set({ version, appliedAt: now })
|
|
316
|
+
.where(drizzleOps.eq(schemaVersionsTable.namespace, namespace))
|
|
317
|
+
.execute();
|
|
318
|
+
}
|
|
319
|
+
},
|
|
320
|
+
async validateSchema() {
|
|
321
|
+
// Drizzle is strongly typed; runtime validation is out-of-scope here
|
|
322
|
+
return { valid: true };
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
};
|
|
326
|
+
const factory = createAdapterFactory({
|
|
327
|
+
config: {
|
|
328
|
+
adapterId: 'drizzle',
|
|
329
|
+
adapterName: 'Drizzle Adapter',
|
|
330
|
+
debug: config.debug ?? false,
|
|
331
|
+
namespace: config.namespace,
|
|
332
|
+
capabilities: {
|
|
333
|
+
types: { json: true, dates: true, booleans: true, bigint: true, uuid: true, enum: true },
|
|
334
|
+
operations: { batch: true, upsert: true, streaming: false, fulltext: false, returning: config.dialect !== 'mysql' },
|
|
335
|
+
transactions: { supported: true, nested: false, isolation: undefined },
|
|
336
|
+
performance: { supportsJoins: true, supportsPreparedStatements: true },
|
|
337
|
+
schema: { migrations: false, constraints: true, indexes: true },
|
|
338
|
+
advanced: { customIdGeneration: false, numericIds: true, schemaNamespaces: true, customTypes: true },
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
adapter: createImpl,
|
|
342
|
+
});
|
|
343
|
+
// Return an adapter instance for default (no library-provided overrides)
|
|
344
|
+
return factory({});
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=index.js.map
|