zero-http 0.2.4 → 0.3.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 +1250 -283
- package/documentation/config/db.js +25 -0
- package/documentation/config/middleware.js +44 -0
- package/documentation/config/tls.js +12 -0
- package/documentation/controllers/cookies.js +34 -0
- package/documentation/controllers/tasks.js +108 -0
- package/documentation/full-server.js +28 -177
- package/documentation/models/Task.js +21 -0
- package/documentation/public/data/api.json +404 -24
- package/documentation/public/data/docs.json +1139 -0
- package/documentation/public/data/examples.json +80 -2
- package/documentation/public/data/options.json +23 -8
- package/documentation/public/index.html +138 -99
- package/documentation/public/scripts/app.js +1 -3
- package/documentation/public/scripts/custom-select.js +189 -0
- package/documentation/public/scripts/data-sections.js +233 -250
- package/documentation/public/scripts/playground.js +270 -0
- package/documentation/public/scripts/ui.js +4 -3
- package/documentation/public/styles.css +56 -5
- package/documentation/public/vendor/icons/compress.svg +17 -17
- package/documentation/public/vendor/icons/database.svg +21 -0
- package/documentation/public/vendor/icons/env.svg +21 -0
- package/documentation/public/vendor/icons/fetch.svg +11 -14
- package/documentation/public/vendor/icons/security.svg +15 -0
- package/documentation/public/vendor/icons/sse.svg +12 -13
- package/documentation/public/vendor/icons/static.svg +12 -26
- package/documentation/public/vendor/icons/stream.svg +7 -13
- package/documentation/public/vendor/icons/validate.svg +17 -0
- package/documentation/routes/api.js +41 -0
- package/documentation/routes/core.js +20 -0
- package/documentation/routes/playground.js +29 -0
- package/documentation/routes/realtime.js +49 -0
- package/documentation/routes/uploads.js +71 -0
- package/index.js +62 -1
- package/lib/app.js +200 -8
- package/lib/body/json.js +28 -5
- package/lib/body/multipart.js +29 -1
- package/lib/body/raw.js +1 -1
- package/lib/body/sendError.js +1 -0
- package/lib/body/text.js +1 -1
- package/lib/body/typeMatch.js +6 -2
- package/lib/body/urlencoded.js +5 -2
- package/lib/debug.js +345 -0
- package/lib/env/index.js +440 -0
- package/lib/errors.js +231 -0
- package/lib/http/request.js +219 -1
- package/lib/http/response.js +410 -6
- package/lib/middleware/compress.js +39 -6
- package/lib/middleware/cookieParser.js +237 -0
- package/lib/middleware/cors.js +13 -2
- package/lib/middleware/csrf.js +135 -0
- package/lib/middleware/errorHandler.js +90 -0
- package/lib/middleware/helmet.js +176 -0
- package/lib/middleware/index.js +7 -2
- package/lib/middleware/rateLimit.js +12 -1
- package/lib/middleware/requestId.js +54 -0
- package/lib/middleware/static.js +95 -11
- package/lib/middleware/timeout.js +72 -0
- package/lib/middleware/validator.js +257 -0
- package/lib/orm/adapters/json.js +215 -0
- package/lib/orm/adapters/memory.js +383 -0
- package/lib/orm/adapters/mongo.js +444 -0
- package/lib/orm/adapters/mysql.js +272 -0
- package/lib/orm/adapters/postgres.js +394 -0
- package/lib/orm/adapters/sql-base.js +142 -0
- package/lib/orm/adapters/sqlite.js +311 -0
- package/lib/orm/index.js +276 -0
- package/lib/orm/model.js +895 -0
- package/lib/orm/query.js +807 -0
- package/lib/orm/schema.js +172 -0
- package/lib/router/index.js +136 -47
- package/lib/sse/stream.js +15 -3
- package/lib/ws/connection.js +19 -3
- package/lib/ws/handshake.js +3 -0
- package/lib/ws/index.js +3 -1
- package/lib/ws/room.js +222 -0
- package/package.json +15 -5
- package/types/app.d.ts +120 -0
- package/types/env.d.ts +80 -0
- package/types/errors.d.ts +147 -0
- package/types/fetch.d.ts +43 -0
- package/types/index.d.ts +135 -0
- package/types/middleware.d.ts +292 -0
- package/types/orm.d.ts +610 -0
- package/types/request.d.ts +99 -0
- package/types/response.d.ts +142 -0
- package/types/router.d.ts +78 -0
- package/types/sse.d.ts +78 -0
- package/types/websocket.d.ts +119 -0
package/types/orm.d.ts
ADDED
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
// --- Schema Types ------------------------------------------------
|
|
2
|
+
|
|
3
|
+
export interface SchemaColumnDef {
|
|
4
|
+
/** Column data type. */
|
|
5
|
+
type: typeof TYPES[keyof typeof TYPES];
|
|
6
|
+
/** Field is required. */
|
|
7
|
+
required?: boolean;
|
|
8
|
+
/** Default value or factory function. */
|
|
9
|
+
default?: any | (() => any);
|
|
10
|
+
/** Allow null values. */
|
|
11
|
+
nullable?: boolean;
|
|
12
|
+
/** Is primary key. */
|
|
13
|
+
primaryKey?: boolean;
|
|
14
|
+
/** Auto-increment. */
|
|
15
|
+
autoIncrement?: boolean;
|
|
16
|
+
/** Unique constraint. */
|
|
17
|
+
unique?: boolean;
|
|
18
|
+
/** Minimum string length. */
|
|
19
|
+
minLength?: number;
|
|
20
|
+
/** Maximum string length. */
|
|
21
|
+
maxLength?: number;
|
|
22
|
+
/** Minimum numeric value. */
|
|
23
|
+
min?: number;
|
|
24
|
+
/** Maximum numeric value. */
|
|
25
|
+
max?: number;
|
|
26
|
+
/** Pattern constraint (string). */
|
|
27
|
+
match?: RegExp;
|
|
28
|
+
/** Allowed values (string). */
|
|
29
|
+
enum?: string[];
|
|
30
|
+
/** Mass-assignment protection — exclude from bulk writes. */
|
|
31
|
+
guarded?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const TYPES: {
|
|
35
|
+
readonly STRING: 'string';
|
|
36
|
+
readonly INTEGER: 'integer';
|
|
37
|
+
readonly FLOAT: 'float';
|
|
38
|
+
readonly BOOLEAN: 'boolean';
|
|
39
|
+
readonly DATE: 'date';
|
|
40
|
+
readonly DATETIME: 'datetime';
|
|
41
|
+
readonly JSON: 'json';
|
|
42
|
+
readonly TEXT: 'text';
|
|
43
|
+
readonly BLOB: 'blob';
|
|
44
|
+
readonly UUID: 'uuid';
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Validate a single value against a column definition.
|
|
49
|
+
* Throws on validation failure.
|
|
50
|
+
*/
|
|
51
|
+
export function validateValue(value: any, colDef: SchemaColumnDef, colName: string): any;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validate an object against a column schema.
|
|
55
|
+
*/
|
|
56
|
+
export function validate(
|
|
57
|
+
data: object,
|
|
58
|
+
columns: Record<string, SchemaColumnDef>,
|
|
59
|
+
options?: { partial?: boolean }
|
|
60
|
+
): { valid: boolean; errors: string[]; sanitized: object };
|
|
61
|
+
|
|
62
|
+
// --- Query Builder -----------------------------------------------
|
|
63
|
+
|
|
64
|
+
export class Query {
|
|
65
|
+
constructor(model: typeof Model, adapter: any);
|
|
66
|
+
|
|
67
|
+
/** Select specific fields. */
|
|
68
|
+
select(...fields: string[]): Query;
|
|
69
|
+
/** Return distinct rows. */
|
|
70
|
+
distinct(): Query;
|
|
71
|
+
|
|
72
|
+
/** Filter by condition. */
|
|
73
|
+
where(field: string, value: any): Query;
|
|
74
|
+
where(field: string, op: string, value: any): Query;
|
|
75
|
+
where(conditions: Record<string, any>): Query;
|
|
76
|
+
/** OR filter. */
|
|
77
|
+
orWhere(field: string, value: any): Query;
|
|
78
|
+
orWhere(field: string, op: string, value: any): Query;
|
|
79
|
+
/** Filter where field IS NULL. */
|
|
80
|
+
whereNull(field: string): Query;
|
|
81
|
+
/** Filter where field IS NOT NULL. */
|
|
82
|
+
whereNotNull(field: string): Query;
|
|
83
|
+
/** Filter where field is in a set of values. */
|
|
84
|
+
whereIn(field: string, values: any[]): Query;
|
|
85
|
+
/** Filter where field is NOT in a set of values. */
|
|
86
|
+
whereNotIn(field: string, values: any[]): Query;
|
|
87
|
+
/** Filter where field is between two values. */
|
|
88
|
+
whereBetween(field: string, low: any, high: any): Query;
|
|
89
|
+
/** Filter where field is NOT between two values. */
|
|
90
|
+
whereNotBetween(field: string, low: any, high: any): Query;
|
|
91
|
+
/** Filter where field matches a LIKE pattern (% and _ wildcards). */
|
|
92
|
+
whereLike(field: string, pattern: string): Query;
|
|
93
|
+
|
|
94
|
+
/** Order results. */
|
|
95
|
+
orderBy(field: string, dir?: 'asc' | 'desc'): Query;
|
|
96
|
+
/** Limit result count. */
|
|
97
|
+
limit(n: number): Query;
|
|
98
|
+
/** Offset results. */
|
|
99
|
+
offset(n: number): Query;
|
|
100
|
+
/** Paginate results. */
|
|
101
|
+
page(page: number, perPage?: number): Query;
|
|
102
|
+
|
|
103
|
+
/** Group results by fields. */
|
|
104
|
+
groupBy(...fields: string[]): Query;
|
|
105
|
+
/** Having clause for aggregates. */
|
|
106
|
+
having(field: string, op?: string, value?: any): Query;
|
|
107
|
+
|
|
108
|
+
/** Inner join. */
|
|
109
|
+
join(table: string, localKey: string, foreignKey: string): Query;
|
|
110
|
+
/** Left join. */
|
|
111
|
+
leftJoin(table: string, localKey: string, foreignKey: string): Query;
|
|
112
|
+
/** Right join. */
|
|
113
|
+
rightJoin(table: string, localKey: string, foreignKey: string): Query;
|
|
114
|
+
|
|
115
|
+
/** Include soft-deleted records. */
|
|
116
|
+
withDeleted(): Query;
|
|
117
|
+
/** Apply a named scope from the model's static scopes. */
|
|
118
|
+
scope(name: string, ...args: any[]): Query;
|
|
119
|
+
|
|
120
|
+
/** Build the adapter-agnostic query descriptor. */
|
|
121
|
+
build(): object;
|
|
122
|
+
/** Execute the query and return model instances. */
|
|
123
|
+
exec(): Promise<Model[]>;
|
|
124
|
+
/** Execute the query and return the first result. */
|
|
125
|
+
first(): Promise<Model | null>;
|
|
126
|
+
/** Execute a count query. */
|
|
127
|
+
count(): Promise<number>;
|
|
128
|
+
/** Returns true if any matching records exist. */
|
|
129
|
+
exists(): Promise<boolean>;
|
|
130
|
+
/** Returns an array of values for a single column. */
|
|
131
|
+
pluck(field: string): Promise<any[]>;
|
|
132
|
+
/** Returns the sum of a numeric column. */
|
|
133
|
+
sum(field: string): Promise<number>;
|
|
134
|
+
/** Returns the average of a numeric column. */
|
|
135
|
+
avg(field: string): Promise<number>;
|
|
136
|
+
/** Returns the minimum value of a column. */
|
|
137
|
+
min(field: string): Promise<any>;
|
|
138
|
+
/** Returns the maximum value of a column. */
|
|
139
|
+
max(field: string): Promise<any>;
|
|
140
|
+
|
|
141
|
+
// -- LINQ-Inspired Methods --------------------------
|
|
142
|
+
|
|
143
|
+
/** Alias for limit (LINQ naming). */
|
|
144
|
+
take(n: number): Query;
|
|
145
|
+
/** Alias for offset (LINQ naming). */
|
|
146
|
+
skip(n: number): Query;
|
|
147
|
+
/** Alias for exec — explicitly convert to array. */
|
|
148
|
+
toArray(): Promise<Model[]>;
|
|
149
|
+
/** Shorthand for orderBy(field, 'desc'). */
|
|
150
|
+
orderByDesc(field: string): Query;
|
|
151
|
+
/** Execute and return the last result. */
|
|
152
|
+
last(): Promise<Model | null>;
|
|
153
|
+
|
|
154
|
+
/** Conditionally apply query logic when condition is truthy. */
|
|
155
|
+
when(condition: any, fn: (query: Query) => void): Query;
|
|
156
|
+
/** Conditionally apply query logic when condition is falsy. */
|
|
157
|
+
unless(condition: any, fn: (query: Query) => void): Query;
|
|
158
|
+
/** Inspect the query without breaking the chain (for debugging/logging). */
|
|
159
|
+
tap(fn: (query: Query) => void): Query;
|
|
160
|
+
|
|
161
|
+
/** Process results in batches. Calls fn(batch, batchIndex) for each chunk. */
|
|
162
|
+
chunk(size: number, fn: (batch: Model[], index: number) => void | Promise<void>): Promise<void>;
|
|
163
|
+
/** Execute and iterate each result with a callback. */
|
|
164
|
+
each(fn: (item: Model, index: number) => void | Promise<void>): Promise<void>;
|
|
165
|
+
/** Execute, transform results with a mapper, and return the mapped array. */
|
|
166
|
+
map<T>(fn: (item: Model, index: number) => T): Promise<T[]>;
|
|
167
|
+
/** Execute, filter results with a predicate, and return matches. */
|
|
168
|
+
filter(fn: (item: Model, index: number) => boolean): Promise<Model[]>;
|
|
169
|
+
/** Execute and reduce results to a single value. */
|
|
170
|
+
reduce<T>(fn: (acc: T, item: Model, index: number) => T, initial: T): Promise<T>;
|
|
171
|
+
|
|
172
|
+
/** Rich pagination with metadata: { data, total, page, perPage, pages, hasNext, hasPrev }. */
|
|
173
|
+
paginate(page: number, perPage?: number): Promise<PaginatedResult>;
|
|
174
|
+
|
|
175
|
+
/** Inject a raw WHERE clause for SQL adapters (ignored by memory/mongo). */
|
|
176
|
+
whereRaw(sql: string, ...params: any[]): Query;
|
|
177
|
+
|
|
178
|
+
/** Thenable support — `await query`. */
|
|
179
|
+
then<TResult1 = Model[], TResult2 = never>(
|
|
180
|
+
onfulfilled?: ((value: Model[]) => TResult1 | PromiseLike<TResult1>) | null,
|
|
181
|
+
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
182
|
+
): Promise<TResult1 | TResult2>;
|
|
183
|
+
catch<TResult = never>(
|
|
184
|
+
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
|
185
|
+
): Promise<Model[] | TResult>;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// --- Pagination Result -------------------------------------------
|
|
189
|
+
|
|
190
|
+
export interface PaginatedResult {
|
|
191
|
+
data: Model[];
|
|
192
|
+
total: number;
|
|
193
|
+
page: number;
|
|
194
|
+
perPage: number;
|
|
195
|
+
pages: number;
|
|
196
|
+
hasNext: boolean;
|
|
197
|
+
hasPrev: boolean;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// --- Model -------------------------------------------------------
|
|
201
|
+
|
|
202
|
+
export interface ModelHooks {
|
|
203
|
+
beforeCreate?: (data: object) => void | Promise<void>;
|
|
204
|
+
afterCreate?: (instance: Model) => void | Promise<void>;
|
|
205
|
+
beforeUpdate?: (instance: Model, data: object) => void | Promise<void>;
|
|
206
|
+
afterUpdate?: (instance: Model) => void | Promise<void>;
|
|
207
|
+
beforeDelete?: (instance: Model) => void | Promise<void>;
|
|
208
|
+
afterDelete?: (instance: Model) => void | Promise<void>;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export interface FindOrCreateResult {
|
|
212
|
+
instance: Model;
|
|
213
|
+
created: boolean;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export class Model {
|
|
217
|
+
/** Table name (override in subclass). */
|
|
218
|
+
static table: string;
|
|
219
|
+
/** Column schema (override in subclass). */
|
|
220
|
+
static schema: Record<string, SchemaColumnDef>;
|
|
221
|
+
/** Enable automatic timestamps (createdAt, updatedAt). */
|
|
222
|
+
static timestamps: boolean;
|
|
223
|
+
/** Enable soft deletes (deletedAt). */
|
|
224
|
+
static softDelete: boolean;
|
|
225
|
+
/** Lifecycle hooks. */
|
|
226
|
+
static hooks: ModelHooks;
|
|
227
|
+
/** Fields excluded from toJSON() output. */
|
|
228
|
+
static hidden: string[];
|
|
229
|
+
/** Reusable named query conditions: { name: (query, ...args) => query }. */
|
|
230
|
+
static scopes: Record<string, (query: Query, ...args: any[]) => Query>;
|
|
231
|
+
|
|
232
|
+
constructor(data?: object);
|
|
233
|
+
|
|
234
|
+
/** Whether the instance has been persisted. */
|
|
235
|
+
_persisted: boolean;
|
|
236
|
+
|
|
237
|
+
/** Save the instance (insert or update dirty fields). */
|
|
238
|
+
save(): Promise<Model>;
|
|
239
|
+
/** Update fields on the instance. */
|
|
240
|
+
update(data: object): Promise<Model>;
|
|
241
|
+
/** Delete the instance (soft or hard). */
|
|
242
|
+
delete(): Promise<void>;
|
|
243
|
+
/** Restore a soft-deleted instance. */
|
|
244
|
+
restore(): Promise<Model>;
|
|
245
|
+
/** Reload the instance from the database. */
|
|
246
|
+
reload(): Promise<Model>;
|
|
247
|
+
/** Return a plain object representation (respects static hidden). */
|
|
248
|
+
toJSON(): object;
|
|
249
|
+
/** Load a named relationship. */
|
|
250
|
+
load(relationName: string): Promise<Model | Model[] | null>;
|
|
251
|
+
/** Increment a numeric field by amount (default 1). */
|
|
252
|
+
increment(field: string, by?: number): Promise<Model>;
|
|
253
|
+
/** Decrement a numeric field by amount (default 1). */
|
|
254
|
+
decrement(field: string, by?: number): Promise<Model>;
|
|
255
|
+
|
|
256
|
+
/** Create a new record. */
|
|
257
|
+
static create(data: object): Promise<Model>;
|
|
258
|
+
/** Create multiple records. */
|
|
259
|
+
static createMany(dataArray: object[]): Promise<Model[]>;
|
|
260
|
+
/** Find records matching conditions. */
|
|
261
|
+
static find(conditions?: object): Promise<Model[]>;
|
|
262
|
+
/** Find a single record matching conditions. */
|
|
263
|
+
static findOne(conditions: object): Promise<Model | null>;
|
|
264
|
+
/** Find a record by primary key. */
|
|
265
|
+
static findById(id: any): Promise<Model | null>;
|
|
266
|
+
/** Find or create a record. */
|
|
267
|
+
static findOrCreate(conditions: object, defaults?: object): Promise<FindOrCreateResult>;
|
|
268
|
+
/** Update records matching conditions. */
|
|
269
|
+
static updateWhere(conditions: object, data: object): Promise<number>;
|
|
270
|
+
/** Delete records matching conditions. */
|
|
271
|
+
static deleteWhere(conditions: object): Promise<number>;
|
|
272
|
+
/** Count records matching conditions. */
|
|
273
|
+
static count(conditions?: object): Promise<number>;
|
|
274
|
+
/** Check if any records match the conditions. */
|
|
275
|
+
static exists(conditions?: object): Promise<boolean>;
|
|
276
|
+
/** Insert or update a record. Returns { instance, created }. */
|
|
277
|
+
static upsert(conditions: object, data: object): Promise<FindOrCreateResult>;
|
|
278
|
+
/** Start a fluent query builder with a named scope applied. */
|
|
279
|
+
static scope(name: string, ...args: any[]): Query;
|
|
280
|
+
/** Start a fluent query builder. */
|
|
281
|
+
static query(): Query;
|
|
282
|
+
|
|
283
|
+
// -- LINQ-Inspired Static Shortcuts ------------------
|
|
284
|
+
|
|
285
|
+
/** Find the first record matching optional conditions. */
|
|
286
|
+
static first(conditions?: object): Promise<Model | null>;
|
|
287
|
+
/** Find the last record matching optional conditions. */
|
|
288
|
+
static last(conditions?: object): Promise<Model | null>;
|
|
289
|
+
/** Get all records (alias for find). */
|
|
290
|
+
static all(conditions?: object): Promise<Model[]>;
|
|
291
|
+
/** Rich pagination with metadata. */
|
|
292
|
+
static paginate(page: number, perPage?: number, conditions?: object): Promise<PaginatedResult>;
|
|
293
|
+
/** Process all matching records in batches. */
|
|
294
|
+
static chunk(size: number, fn: (batch: Model[], index: number) => void | Promise<void>, conditions?: object): Promise<void>;
|
|
295
|
+
/** Get a random record. */
|
|
296
|
+
static random(conditions?: object): Promise<Model | null>;
|
|
297
|
+
/** Pluck values for a single column. */
|
|
298
|
+
static pluck(field: string, conditions?: object): Promise<any[]>;
|
|
299
|
+
|
|
300
|
+
/** Define a has-many relationship. */
|
|
301
|
+
static hasMany(RelatedModel: typeof Model, foreignKey: string, localKey?: string): void;
|
|
302
|
+
/** Define a has-one relationship. */
|
|
303
|
+
static hasOne(RelatedModel: typeof Model, foreignKey: string, localKey?: string): void;
|
|
304
|
+
/** Define a belongs-to relationship. */
|
|
305
|
+
static belongsTo(RelatedModel: typeof Model, foreignKey: string, otherKey?: string): void;
|
|
306
|
+
/** Define a many-to-many relationship through a junction table. */
|
|
307
|
+
static belongsToMany(RelatedModel: typeof Model, options: {
|
|
308
|
+
through: string;
|
|
309
|
+
foreignKey: string;
|
|
310
|
+
otherKey: string;
|
|
311
|
+
localKey?: string;
|
|
312
|
+
relatedKey?: string;
|
|
313
|
+
}): void;
|
|
314
|
+
|
|
315
|
+
/** Create/sync the table in the database. */
|
|
316
|
+
static sync(): Promise<void>;
|
|
317
|
+
/** Drop the table from the database. */
|
|
318
|
+
static drop(): Promise<void>;
|
|
319
|
+
|
|
320
|
+
/** Allow index access for model fields. */
|
|
321
|
+
[key: string]: any;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// --- SQLite Options ----------------------------------------------
|
|
325
|
+
|
|
326
|
+
export interface SqlitePragmas {
|
|
327
|
+
journal_mode?: 'WAL' | 'DELETE' | 'TRUNCATE' | 'MEMORY' | 'OFF';
|
|
328
|
+
foreign_keys?: 'ON' | 'OFF';
|
|
329
|
+
busy_timeout?: string;
|
|
330
|
+
synchronous?: 'OFF' | 'NORMAL' | 'FULL' | 'EXTRA';
|
|
331
|
+
cache_size?: string;
|
|
332
|
+
temp_store?: 'DEFAULT' | 'FILE' | 'MEMORY';
|
|
333
|
+
mmap_size?: string;
|
|
334
|
+
page_size?: string;
|
|
335
|
+
auto_vacuum?: 'NONE' | 'FULL' | 'INCREMENTAL';
|
|
336
|
+
secure_delete?: 'ON' | 'OFF';
|
|
337
|
+
wal_autocheckpoint?: string;
|
|
338
|
+
locking_mode?: 'NORMAL' | 'EXCLUSIVE';
|
|
339
|
+
[key: string]: string | undefined;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export interface SqliteOptions {
|
|
343
|
+
filename?: string;
|
|
344
|
+
readonly?: boolean;
|
|
345
|
+
fileMustExist?: boolean;
|
|
346
|
+
verbose?: boolean;
|
|
347
|
+
createDir?: boolean;
|
|
348
|
+
pragmas?: SqlitePragmas;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export interface MySqlOptions {
|
|
352
|
+
host?: string;
|
|
353
|
+
port?: number;
|
|
354
|
+
user?: string;
|
|
355
|
+
password?: string;
|
|
356
|
+
database?: string;
|
|
357
|
+
connectionLimit?: number;
|
|
358
|
+
waitForConnections?: boolean;
|
|
359
|
+
queueLimit?: number;
|
|
360
|
+
connectTimeout?: number;
|
|
361
|
+
charset?: string;
|
|
362
|
+
timezone?: string;
|
|
363
|
+
ssl?: string | object;
|
|
364
|
+
multipleStatements?: boolean;
|
|
365
|
+
decimalNumbers?: boolean;
|
|
366
|
+
[key: string]: any;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export interface PostgresOptions {
|
|
370
|
+
host?: string;
|
|
371
|
+
port?: number;
|
|
372
|
+
user?: string;
|
|
373
|
+
password?: string;
|
|
374
|
+
database?: string;
|
|
375
|
+
connectionString?: string;
|
|
376
|
+
ssl?: boolean | object;
|
|
377
|
+
max?: number;
|
|
378
|
+
idleTimeoutMillis?: number;
|
|
379
|
+
connectionTimeoutMillis?: number;
|
|
380
|
+
application_name?: string;
|
|
381
|
+
statement_timeout?: number;
|
|
382
|
+
[key: string]: any;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export interface MongoOptions {
|
|
386
|
+
url?: string;
|
|
387
|
+
database?: string;
|
|
388
|
+
maxPoolSize?: number;
|
|
389
|
+
minPoolSize?: number;
|
|
390
|
+
connectTimeoutMS?: number;
|
|
391
|
+
socketTimeoutMS?: number;
|
|
392
|
+
serverSelectionTimeoutMS?: number;
|
|
393
|
+
retryWrites?: boolean;
|
|
394
|
+
retryReads?: boolean;
|
|
395
|
+
authSource?: string;
|
|
396
|
+
replicaSet?: string;
|
|
397
|
+
clientOptions?: object;
|
|
398
|
+
[key: string]: any;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export interface JsonOptions {
|
|
402
|
+
dir: string;
|
|
403
|
+
pretty?: boolean;
|
|
404
|
+
flushInterval?: number;
|
|
405
|
+
autoFlush?: boolean;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export type AdapterOptions = SqliteOptions | MySqlOptions | PostgresOptions | MongoOptions | JsonOptions | object;
|
|
409
|
+
|
|
410
|
+
// --- SQLite Adapter ----------------------------------------------
|
|
411
|
+
|
|
412
|
+
export interface SqliteAdapter {
|
|
413
|
+
/** Read a single PRAGMA value. */
|
|
414
|
+
pragma(key: string): any;
|
|
415
|
+
/** Force a WAL checkpoint. */
|
|
416
|
+
checkpoint(mode?: 'PASSIVE' | 'FULL' | 'RESTART' | 'TRUNCATE'): { busy: number; log: number; checkpointed: number };
|
|
417
|
+
/** Run PRAGMA integrity_check. Returns 'ok' or a problem description. */
|
|
418
|
+
integrity(): string;
|
|
419
|
+
/** Rebuild the database file, reclaiming free pages. */
|
|
420
|
+
vacuum(): void;
|
|
421
|
+
/** Get the database file size in bytes (0 for in-memory). */
|
|
422
|
+
fileSize(): number;
|
|
423
|
+
/** List all user-created table names. */
|
|
424
|
+
tables(): string[];
|
|
425
|
+
/** Run a raw SQL SELECT query. */
|
|
426
|
+
raw(sql: string, ...params: any[]): any[];
|
|
427
|
+
/** Close the database connection. */
|
|
428
|
+
close(): void;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// --- MySQL Adapter -----------------------------------------------
|
|
432
|
+
|
|
433
|
+
export interface MySqlAdapter {
|
|
434
|
+
/** List all tables in the current database. */
|
|
435
|
+
tables(): Promise<string[]>;
|
|
436
|
+
/** Get column info for a table. */
|
|
437
|
+
columns(table: string): Promise<Array<{ Field: string; Type: string; Null: string; Key: string; Default: any; Extra: string }>>;
|
|
438
|
+
/** Get total database size in bytes. */
|
|
439
|
+
databaseSize(): Promise<number>;
|
|
440
|
+
/** Get connection pool status. */
|
|
441
|
+
poolStatus(): { total: number; idle: number; used: number; queued: number };
|
|
442
|
+
/** Get MySQL server version string. */
|
|
443
|
+
version(): Promise<string>;
|
|
444
|
+
/** Ping the server. Returns true if healthy. */
|
|
445
|
+
ping(): Promise<boolean>;
|
|
446
|
+
/** Execute a raw write/DDL statement. Returns affected rows and insert ID. */
|
|
447
|
+
exec(sql: string, ...params: any[]): Promise<{ affectedRows: number; insertId: number }>;
|
|
448
|
+
/** Run a raw SQL SELECT query. */
|
|
449
|
+
raw(sql: string, ...params: any[]): Promise<any[]>;
|
|
450
|
+
/** Run a function inside a transaction. */
|
|
451
|
+
transaction(fn: (connection: any) => Promise<void>): Promise<void>;
|
|
452
|
+
/** Close the connection pool. */
|
|
453
|
+
close(): Promise<void>;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// --- PostgreSQL Adapter ------------------------------------------
|
|
457
|
+
|
|
458
|
+
export interface PostgresAdapter {
|
|
459
|
+
/** List all tables in a schema (default: 'public'). */
|
|
460
|
+
tables(schema?: string): Promise<string[]>;
|
|
461
|
+
/** Get column info for a table. */
|
|
462
|
+
columns(table: string, schema?: string): Promise<Array<{ column_name: string; data_type: string; is_nullable: string; column_default: string | null }>>;
|
|
463
|
+
/** Get total database size in bytes. */
|
|
464
|
+
databaseSize(): Promise<number>;
|
|
465
|
+
/** Get total size of a table including indexes, in bytes. */
|
|
466
|
+
tableSize(table: string): Promise<number>;
|
|
467
|
+
/** Get connection pool status. */
|
|
468
|
+
poolStatus(): { total: number; idle: number; waiting: number };
|
|
469
|
+
/** Get PostgreSQL server version string. */
|
|
470
|
+
version(): Promise<string>;
|
|
471
|
+
/** Ping the server. Returns true if healthy. */
|
|
472
|
+
ping(): Promise<boolean>;
|
|
473
|
+
/** Execute a raw write/DDL statement. Returns row count. */
|
|
474
|
+
exec(sql: string, ...params: any[]): Promise<{ rowCount: number }>;
|
|
475
|
+
/** Subscribe to PostgreSQL LISTEN/NOTIFY channel. Returns an unlisten function. */
|
|
476
|
+
listen(channel: string, callback: (msg: { channel: string; payload?: string }) => void): Promise<() => Promise<void>>;
|
|
477
|
+
/** Run a raw SQL SELECT query. */
|
|
478
|
+
raw(sql: string, ...params: any[]): Promise<any[]>;
|
|
479
|
+
/** Run a function inside a transaction. */
|
|
480
|
+
transaction(fn: (client: any) => Promise<void>): Promise<void>;
|
|
481
|
+
/** Close the connection pool. */
|
|
482
|
+
close(): Promise<void>;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// --- MongoDB Adapter ---------------------------------------------
|
|
486
|
+
|
|
487
|
+
export interface MongoAdapter {
|
|
488
|
+
/** List all collections in the database. */
|
|
489
|
+
collections(): Promise<string[]>;
|
|
490
|
+
/** Get database-level stats. */
|
|
491
|
+
stats(): Promise<{ collections: number; objects: number; dataSize: number; storageSize: number; indexes: number; indexSize: number }>;
|
|
492
|
+
/** Get stats for a specific collection. */
|
|
493
|
+
collectionStats(name: string): Promise<{ count: number; size: number; avgObjSize: number; storageSize: number; nindexes: number }>;
|
|
494
|
+
/** Create an index on a collection. */
|
|
495
|
+
createIndex(collection: string, keys: Record<string, 1 | -1 | 'text'>, options?: { unique?: boolean; sparse?: boolean; [key: string]: any }): Promise<string>;
|
|
496
|
+
/** List all indexes on a collection. */
|
|
497
|
+
indexes(collection: string): Promise<any[]>;
|
|
498
|
+
/** Drop an index by name. */
|
|
499
|
+
dropIndex(collection: string, indexName: string): Promise<void>;
|
|
500
|
+
/** Ping the MongoDB server. Returns true if healthy. */
|
|
501
|
+
ping(): Promise<boolean>;
|
|
502
|
+
/** Get the MongoDB server version. */
|
|
503
|
+
version(): Promise<string>;
|
|
504
|
+
/** Whether the client is currently connected. */
|
|
505
|
+
readonly isConnected: boolean;
|
|
506
|
+
/** Run a raw MongoDB command. */
|
|
507
|
+
raw(command: object): Promise<any>;
|
|
508
|
+
/** Run a function inside a transaction (requires replica set). */
|
|
509
|
+
transaction(fn: (session: any) => Promise<void>): Promise<void>;
|
|
510
|
+
/** Close the connection. */
|
|
511
|
+
close(): Promise<void>;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// --- Memory Adapter ----------------------------------------------
|
|
515
|
+
|
|
516
|
+
export interface MemoryAdapter {
|
|
517
|
+
/** List all registered table names. */
|
|
518
|
+
tables(): string[];
|
|
519
|
+
/** Count all rows across all tables. */
|
|
520
|
+
totalRows(): number;
|
|
521
|
+
/** Get memory stats. */
|
|
522
|
+
stats(): { tables: number; totalRows: number; estimatedBytes: number };
|
|
523
|
+
/** Export all data as a plain object. */
|
|
524
|
+
toJSON(): Record<string, any[]>;
|
|
525
|
+
/** Import data from a plain object. */
|
|
526
|
+
fromJSON(data: Record<string, any[]>): void;
|
|
527
|
+
/** Deep-clone the entire database into a new MemoryAdapter. */
|
|
528
|
+
clone(): MemoryAdapter;
|
|
529
|
+
/** Delete all rows from all tables. */
|
|
530
|
+
clear(): void;
|
|
531
|
+
/** Run a raw query (memory adapter supports select/insert/update/delete descriptors). */
|
|
532
|
+
execute(query: object): any[];
|
|
533
|
+
/** Close (no-op for memory). */
|
|
534
|
+
close(): void;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// --- JSON Adapter ------------------------------------------------
|
|
538
|
+
|
|
539
|
+
export interface JsonAdapter extends MemoryAdapter {
|
|
540
|
+
/** The resolved directory path where JSON files are stored. */
|
|
541
|
+
readonly directory: string;
|
|
542
|
+
/** Get total size of all JSON files in bytes. */
|
|
543
|
+
fileSize(): number;
|
|
544
|
+
/** Whether there are unflushed writes. */
|
|
545
|
+
readonly hasPendingWrites: boolean;
|
|
546
|
+
/** Re-serialize and save a table's JSON file. */
|
|
547
|
+
compact(table: string): void;
|
|
548
|
+
/** Copy all JSON files to a target directory. */
|
|
549
|
+
backup(destDir: string): void;
|
|
550
|
+
/** Immediately write all pending changes to disk. */
|
|
551
|
+
flush(): Promise<void>;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// --- Database ----------------------------------------------------
|
|
555
|
+
|
|
556
|
+
export type AdapterType = 'memory' | 'json' | 'sqlite' | 'mysql' | 'postgres' | 'mongo';
|
|
557
|
+
|
|
558
|
+
export class Database {
|
|
559
|
+
/** The underlying adapter instance. */
|
|
560
|
+
adapter: any;
|
|
561
|
+
|
|
562
|
+
constructor(adapter: any);
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Connect to a database using the specified adapter type.
|
|
566
|
+
* Validates credentials for network adapters (mysql, postgres, mongo).
|
|
567
|
+
*/
|
|
568
|
+
static connect(type: 'sqlite', options?: SqliteOptions): Database & { adapter: SqliteAdapter };
|
|
569
|
+
static connect(type: 'mysql', options?: MySqlOptions): Database & { adapter: MySqlAdapter };
|
|
570
|
+
static connect(type: 'postgres', options?: PostgresOptions): Database & { adapter: PostgresAdapter };
|
|
571
|
+
static connect(type: 'mongo', options?: MongoOptions): Database & { adapter: MongoAdapter };
|
|
572
|
+
static connect(type: 'memory', options?: object): Database & { adapter: MemoryAdapter };
|
|
573
|
+
static connect(type: 'json', options?: JsonOptions): Database & { adapter: JsonAdapter };
|
|
574
|
+
static connect(type: AdapterType, options?: AdapterOptions): Database;
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Register a Model class with this database connection.
|
|
578
|
+
*/
|
|
579
|
+
register(ModelClass: typeof Model): Database;
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Register multiple Model classes.
|
|
583
|
+
*/
|
|
584
|
+
registerAll(...models: Array<typeof Model>): Database;
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Sync all registered models (create tables).
|
|
588
|
+
*/
|
|
589
|
+
sync(): Promise<void>;
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Drop all registered model tables.
|
|
593
|
+
*/
|
|
594
|
+
drop(): Promise<void>;
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Close the database connection.
|
|
598
|
+
*/
|
|
599
|
+
close(): Promise<void>;
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Get a registered model by name.
|
|
603
|
+
*/
|
|
604
|
+
model(name: string): typeof Model | undefined;
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Run a function inside a transaction (begin/commit/rollback if supported).
|
|
608
|
+
*/
|
|
609
|
+
transaction(fn: () => Promise<void>): Promise<void>;
|
|
610
|
+
}
|