@3lineas/d1-orm 1.0.3 → 1.0.5
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 +79 -69
- package/dist/cli/index.js +147 -49
- package/dist/cli/index.mjs +150 -53
- package/dist/index.d.mts +384 -5
- package/dist/index.d.ts +384 -5
- package/dist/index.js +395 -13
- package/dist/index.mjs +394 -13
- package/package.json +6 -4
package/dist/index.mjs
CHANGED
|
@@ -2,30 +2,73 @@ import "./chunk-X6BYQHVC.mjs";
|
|
|
2
2
|
|
|
3
3
|
// src/core/connection.ts
|
|
4
4
|
var Connection = class {
|
|
5
|
+
/**
|
|
6
|
+
* The underlying D1Database instance.
|
|
7
|
+
*/
|
|
5
8
|
db;
|
|
9
|
+
/**
|
|
10
|
+
* Create a new Connection instance.
|
|
11
|
+
*
|
|
12
|
+
* @param database - The D1Database instance.
|
|
13
|
+
*/
|
|
6
14
|
constructor(database) {
|
|
7
15
|
this.db = database;
|
|
8
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Execute a SELECT statement.
|
|
19
|
+
*
|
|
20
|
+
* @param query - The SQL query string.
|
|
21
|
+
* @param bindings - The parameter bindings.
|
|
22
|
+
* @returns A promise that resolves to an array of results.
|
|
23
|
+
*/
|
|
9
24
|
async select(query, bindings = []) {
|
|
10
25
|
const stmt = this.db.prepare(query).bind(...bindings);
|
|
11
26
|
const result = await stmt.all();
|
|
12
27
|
return result.results || [];
|
|
13
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Execute an INSERT statement.
|
|
31
|
+
*
|
|
32
|
+
* @param query - The SQL query string.
|
|
33
|
+
* @param bindings - The parameter bindings.
|
|
34
|
+
* @returns A promise that resolves to true on success.
|
|
35
|
+
*/
|
|
14
36
|
async insert(query, bindings = []) {
|
|
15
37
|
const stmt = this.db.prepare(query).bind(...bindings);
|
|
16
38
|
const result = await stmt.run();
|
|
17
39
|
return result.success;
|
|
18
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Execute an UPDATE statement.
|
|
43
|
+
*
|
|
44
|
+
* @param query - The SQL query string.
|
|
45
|
+
* @param bindings - The parameter bindings.
|
|
46
|
+
* @returns A promise that resolves to true on success.
|
|
47
|
+
*/
|
|
19
48
|
async update(query, bindings = []) {
|
|
20
49
|
const stmt = this.db.prepare(query).bind(...bindings);
|
|
21
50
|
const result = await stmt.run();
|
|
22
51
|
return result.success;
|
|
23
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Execute a DELETE statement.
|
|
55
|
+
*
|
|
56
|
+
* @param query - The SQL query string.
|
|
57
|
+
* @param bindings - The parameter bindings.
|
|
58
|
+
* @returns A promise that resolves to true on success.
|
|
59
|
+
*/
|
|
24
60
|
async delete(query, bindings = []) {
|
|
25
61
|
const stmt = this.db.prepare(query).bind(...bindings);
|
|
26
62
|
const result = await stmt.run();
|
|
27
63
|
return result.success;
|
|
28
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Execute an arbitrary SQL statement.
|
|
67
|
+
*
|
|
68
|
+
* @param query - The SQL query string.
|
|
69
|
+
* @param bindings - The parameter bindings.
|
|
70
|
+
* @returns A promise that resolves to true on success.
|
|
71
|
+
*/
|
|
29
72
|
async statement(query, bindings = []) {
|
|
30
73
|
const stmt = this.db.prepare(query).bind(...bindings);
|
|
31
74
|
const result = await stmt.run();
|
|
@@ -35,22 +78,66 @@ var Connection = class {
|
|
|
35
78
|
|
|
36
79
|
// src/core/query-builder.ts
|
|
37
80
|
var QueryBuilder = class {
|
|
81
|
+
/**
|
|
82
|
+
* The database connection.
|
|
83
|
+
*/
|
|
38
84
|
connection;
|
|
85
|
+
/**
|
|
86
|
+
* The table to query.
|
|
87
|
+
*/
|
|
39
88
|
table;
|
|
89
|
+
/**
|
|
90
|
+
* The columns to select.
|
|
91
|
+
*/
|
|
40
92
|
columns = ["*"];
|
|
93
|
+
/**
|
|
94
|
+
* The where constraints for the query.
|
|
95
|
+
*/
|
|
41
96
|
wheres = [];
|
|
97
|
+
/**
|
|
98
|
+
* The bindings for the query.
|
|
99
|
+
*/
|
|
42
100
|
bindings = [];
|
|
101
|
+
/**
|
|
102
|
+
* The orderings for the query.
|
|
103
|
+
*/
|
|
43
104
|
orders = [];
|
|
105
|
+
/**
|
|
106
|
+
* The maximum number of records to return.
|
|
107
|
+
*/
|
|
44
108
|
limitValue = null;
|
|
109
|
+
/**
|
|
110
|
+
* The number of records to skip.
|
|
111
|
+
*/
|
|
45
112
|
offsetValue = null;
|
|
113
|
+
/**
|
|
114
|
+
* Create a new QueryBuilder instance.
|
|
115
|
+
*
|
|
116
|
+
* @param connection - The connection instance.
|
|
117
|
+
* @param table - The table name.
|
|
118
|
+
*/
|
|
46
119
|
constructor(connection, table) {
|
|
47
120
|
this.connection = connection;
|
|
48
121
|
this.table = table;
|
|
49
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Add a SELECT clause to the query.
|
|
125
|
+
*
|
|
126
|
+
* @param columns - The columns to select.
|
|
127
|
+
* @returns The QueryBuilder instance.
|
|
128
|
+
*/
|
|
50
129
|
select(...columns) {
|
|
51
130
|
this.columns = columns.length > 0 ? columns : ["*"];
|
|
52
131
|
return this;
|
|
53
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Add a basic WHERE clause to the query.
|
|
135
|
+
*
|
|
136
|
+
* @param column - The column name.
|
|
137
|
+
* @param operator - The operator or value.
|
|
138
|
+
* @param value - The value if operator is provided.
|
|
139
|
+
* @returns The QueryBuilder instance.
|
|
140
|
+
*/
|
|
54
141
|
where(column, operator, value) {
|
|
55
142
|
if (value === void 0) {
|
|
56
143
|
value = operator;
|
|
@@ -60,6 +147,14 @@ var QueryBuilder = class {
|
|
|
60
147
|
this.bindings.push(value);
|
|
61
148
|
return this;
|
|
62
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Add an OR WHERE clause to the query.
|
|
152
|
+
*
|
|
153
|
+
* @param column - The column name.
|
|
154
|
+
* @param operator - The operator or value.
|
|
155
|
+
* @param value - The value if operator is provided.
|
|
156
|
+
* @returns The QueryBuilder instance.
|
|
157
|
+
*/
|
|
63
158
|
orWhere(column, operator, value) {
|
|
64
159
|
if (value === void 0) {
|
|
65
160
|
value = operator;
|
|
@@ -69,18 +164,42 @@ var QueryBuilder = class {
|
|
|
69
164
|
this.bindings.push(value);
|
|
70
165
|
return this;
|
|
71
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Add an ORDER BY clause to the query.
|
|
169
|
+
*
|
|
170
|
+
* @param column - The column name.
|
|
171
|
+
* @param direction - The direction of the order.
|
|
172
|
+
* @returns The QueryBuilder instance.
|
|
173
|
+
*/
|
|
72
174
|
orderBy(column, direction = "asc") {
|
|
73
175
|
this.orders.push(`${column} ${direction.toUpperCase()}`);
|
|
74
176
|
return this;
|
|
75
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* Add a LIMIT clause to the query.
|
|
180
|
+
*
|
|
181
|
+
* @param limit - The limit value.
|
|
182
|
+
* @returns The QueryBuilder instance.
|
|
183
|
+
*/
|
|
76
184
|
limit(limit) {
|
|
77
185
|
this.limitValue = limit;
|
|
78
186
|
return this;
|
|
79
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Add an OFFSET clause to the query.
|
|
190
|
+
*
|
|
191
|
+
* @param offset - The offset value.
|
|
192
|
+
* @returns The QueryBuilder instance.
|
|
193
|
+
*/
|
|
80
194
|
offset(offset) {
|
|
81
195
|
this.offsetValue = offset;
|
|
82
196
|
return this;
|
|
83
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Get the SQL representation of the query.
|
|
200
|
+
*
|
|
201
|
+
* @returns An object containing the SQL string and the bindings.
|
|
202
|
+
*/
|
|
84
203
|
toSql() {
|
|
85
204
|
let sql = `SELECT ${this.columns.join(", ")} FROM ${this.table}`;
|
|
86
205
|
if (this.wheres.length > 0) {
|
|
@@ -101,15 +220,31 @@ var QueryBuilder = class {
|
|
|
101
220
|
}
|
|
102
221
|
return { sql, bindings: this.bindings };
|
|
103
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Execute the query and get the results.
|
|
225
|
+
*
|
|
226
|
+
* @returns A promise that resolves to an array of records.
|
|
227
|
+
*/
|
|
104
228
|
async get() {
|
|
105
229
|
const { sql, bindings } = this.toSql();
|
|
106
230
|
return this.connection.select(sql, bindings);
|
|
107
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Execute the query and get the first result.
|
|
234
|
+
*
|
|
235
|
+
* @returns A promise that resolves to the first record or null.
|
|
236
|
+
*/
|
|
108
237
|
async first() {
|
|
109
238
|
this.limit(1);
|
|
110
239
|
const results = await this.get();
|
|
111
240
|
return results.length > 0 ? results[0] : null;
|
|
112
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Insert a new record into the database.
|
|
244
|
+
*
|
|
245
|
+
* @param data - The data to insert.
|
|
246
|
+
* @returns A promise that resolves to true on success.
|
|
247
|
+
*/
|
|
113
248
|
async insert(data) {
|
|
114
249
|
const columns = Object.keys(data);
|
|
115
250
|
const values = Object.values(data);
|
|
@@ -117,6 +252,12 @@ var QueryBuilder = class {
|
|
|
117
252
|
const sql = `INSERT INTO ${this.table} (${columns.join(", ")}) VALUES (${placeholders})`;
|
|
118
253
|
return this.connection.insert(sql, values);
|
|
119
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* Update records in the database.
|
|
257
|
+
*
|
|
258
|
+
* @param data - The data to update.
|
|
259
|
+
* @returns A promise that resolves to true on success.
|
|
260
|
+
*/
|
|
120
261
|
async update(data) {
|
|
121
262
|
const columns = Object.keys(data);
|
|
122
263
|
const values = Object.values(data);
|
|
@@ -128,10 +269,14 @@ var QueryBuilder = class {
|
|
|
128
269
|
return w.startsWith("OR") ? w : `AND ${w}`;
|
|
129
270
|
});
|
|
130
271
|
sql += ` WHERE ${constraints.join(" ")}`;
|
|
131
|
-
} else {
|
|
132
272
|
}
|
|
133
273
|
return this.connection.update(sql, [...values, ...this.bindings]);
|
|
134
274
|
}
|
|
275
|
+
/**
|
|
276
|
+
* Delete records from the database.
|
|
277
|
+
*
|
|
278
|
+
* @returns A promise that resolves to true on success.
|
|
279
|
+
*/
|
|
135
280
|
async delete() {
|
|
136
281
|
let sql = `DELETE FROM ${this.table}`;
|
|
137
282
|
if (this.wheres.length > 0) {
|
|
@@ -147,11 +292,26 @@ var QueryBuilder = class {
|
|
|
147
292
|
|
|
148
293
|
// src/core/model-query-builder.ts
|
|
149
294
|
var ModelQueryBuilder = class extends QueryBuilder {
|
|
295
|
+
/**
|
|
296
|
+
* The class of the model being queried.
|
|
297
|
+
*/
|
|
150
298
|
modelClass;
|
|
299
|
+
/**
|
|
300
|
+
* Create a new ModelQueryBuilder instance.
|
|
301
|
+
*
|
|
302
|
+
* @param connection - The database connection.
|
|
303
|
+
* @param table - The table name.
|
|
304
|
+
* @param modelClass - The class constructor for the model.
|
|
305
|
+
*/
|
|
151
306
|
constructor(connection, table, modelClass) {
|
|
152
307
|
super(connection, table);
|
|
153
308
|
this.modelClass = modelClass;
|
|
154
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* Execute the query and return model instances.
|
|
312
|
+
*
|
|
313
|
+
* @returns A promise that resolves to an array of model instances.
|
|
314
|
+
*/
|
|
155
315
|
async get() {
|
|
156
316
|
const { sql, bindings } = this.toSql();
|
|
157
317
|
const results = await this.connection.select(sql, bindings);
|
|
@@ -162,11 +322,21 @@ var ModelQueryBuilder = class extends QueryBuilder {
|
|
|
162
322
|
return instance;
|
|
163
323
|
});
|
|
164
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Execute the query and return the first matching model instance.
|
|
327
|
+
*
|
|
328
|
+
* @returns A promise that resolves to the model instance or null.
|
|
329
|
+
*/
|
|
165
330
|
async first() {
|
|
166
331
|
this.limit(1);
|
|
167
332
|
const results = await this.get();
|
|
168
333
|
return results.length > 0 ? results[0] : null;
|
|
169
334
|
}
|
|
335
|
+
/**
|
|
336
|
+
* Get the underlying model class.
|
|
337
|
+
*
|
|
338
|
+
* @returns The model class constructor.
|
|
339
|
+
*/
|
|
170
340
|
getModel() {
|
|
171
341
|
return this.modelClass;
|
|
172
342
|
}
|
|
@@ -174,14 +344,36 @@ var ModelQueryBuilder = class extends QueryBuilder {
|
|
|
174
344
|
|
|
175
345
|
// src/core/database.ts
|
|
176
346
|
var Database = class _Database {
|
|
347
|
+
/**
|
|
348
|
+
* The singleton instance of the Database.
|
|
349
|
+
*/
|
|
177
350
|
static instance;
|
|
351
|
+
/**
|
|
352
|
+
* The active database connection.
|
|
353
|
+
*/
|
|
178
354
|
connection;
|
|
355
|
+
/**
|
|
356
|
+
* Private constructor to enforce singleton pattern.
|
|
357
|
+
*
|
|
358
|
+
* @param d1 - The D1Database instance from Cloudflare.
|
|
359
|
+
*/
|
|
179
360
|
constructor(d1) {
|
|
180
361
|
this.connection = new Connection(d1);
|
|
181
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Setup the database connection.
|
|
365
|
+
*
|
|
366
|
+
* @param d1 - The D1Database instance from Cloudflare environment (env.DB).
|
|
367
|
+
*/
|
|
182
368
|
static setup(d1) {
|
|
183
369
|
_Database.instance = new _Database(d1);
|
|
184
370
|
}
|
|
371
|
+
/**
|
|
372
|
+
* Get the singleton Database instance.
|
|
373
|
+
*
|
|
374
|
+
* @throws Error if setup() has not been called.
|
|
375
|
+
* @returns The Database instance.
|
|
376
|
+
*/
|
|
185
377
|
static getInstance() {
|
|
186
378
|
if (!_Database.instance) {
|
|
187
379
|
throw new Error(
|
|
@@ -266,43 +458,106 @@ var BelongsTo = class extends Relationship {
|
|
|
266
458
|
|
|
267
459
|
// src/models/model.ts
|
|
268
460
|
var Model = class {
|
|
461
|
+
/**
|
|
462
|
+
* The table associated with the model.
|
|
463
|
+
*/
|
|
269
464
|
static table;
|
|
465
|
+
/**
|
|
466
|
+
* Resolver function for the database connection.
|
|
467
|
+
*/
|
|
270
468
|
static connectionResolver;
|
|
469
|
+
/**
|
|
470
|
+
* The model's attributes.
|
|
471
|
+
*/
|
|
271
472
|
attributes = {};
|
|
473
|
+
/**
|
|
474
|
+
* The attributes that are mass assignable.
|
|
475
|
+
*/
|
|
272
476
|
fillable = [];
|
|
477
|
+
/**
|
|
478
|
+
* The attributes that should be hidden for serialization.
|
|
479
|
+
*/
|
|
273
480
|
hidden = [];
|
|
481
|
+
/**
|
|
482
|
+
* Indicates if the model exists in the database.
|
|
483
|
+
*/
|
|
274
484
|
exists = false;
|
|
485
|
+
/**
|
|
486
|
+
* The model's original attribute values.
|
|
487
|
+
*/
|
|
275
488
|
original = {};
|
|
489
|
+
/**
|
|
490
|
+
* Create a new Model instance.
|
|
491
|
+
*
|
|
492
|
+
* @param attributes - Initial attributes for the model.
|
|
493
|
+
*/
|
|
276
494
|
constructor(attributes = {}) {
|
|
277
495
|
this.fill(attributes);
|
|
278
496
|
}
|
|
279
|
-
|
|
497
|
+
/**
|
|
498
|
+
* Begin querying the model.
|
|
499
|
+
*
|
|
500
|
+
* @returns A new ModelQueryBuilder instance.
|
|
501
|
+
*/
|
|
280
502
|
static query() {
|
|
281
503
|
const instance = new this();
|
|
282
504
|
const table = instance.getTable();
|
|
283
505
|
const connection = Database.getInstance().connection;
|
|
284
506
|
return new ModelQueryBuilder(connection, table, this);
|
|
285
507
|
}
|
|
508
|
+
/**
|
|
509
|
+
* Start a query on a specific connection (currently uses default).
|
|
510
|
+
*
|
|
511
|
+
* @param connectionName - The name of the connection.
|
|
512
|
+
* @returns A new ModelQueryBuilder instance.
|
|
513
|
+
*/
|
|
286
514
|
static on(connectionName) {
|
|
287
515
|
return this.query();
|
|
288
516
|
}
|
|
517
|
+
/**
|
|
518
|
+
* Retrieve all records for the model.
|
|
519
|
+
*
|
|
520
|
+
* @returns A promise that resolves to an array of model instances.
|
|
521
|
+
*/
|
|
289
522
|
static async all() {
|
|
290
523
|
return this.query().get();
|
|
291
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* Find a model by its primary key.
|
|
527
|
+
*
|
|
528
|
+
* @param id - The ID of the record.
|
|
529
|
+
* @returns A promise that resolves to the model instance or null if not found.
|
|
530
|
+
*/
|
|
292
531
|
static async find(id) {
|
|
293
532
|
return this.query().where("id", "=", id).first();
|
|
294
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* Save a new model and return the instance.
|
|
536
|
+
*
|
|
537
|
+
* @param attributes - Attributes for the new record.
|
|
538
|
+
* @returns A promise that resolves to the created model instance.
|
|
539
|
+
*/
|
|
295
540
|
static async create(attributes) {
|
|
296
541
|
const instance = new this();
|
|
297
542
|
instance.fill(attributes);
|
|
298
543
|
await instance.save();
|
|
299
544
|
return instance;
|
|
300
545
|
}
|
|
301
|
-
|
|
546
|
+
/**
|
|
547
|
+
* Fill the model with an array of attributes.
|
|
548
|
+
*
|
|
549
|
+
* @param attributes - Attributes to fill.
|
|
550
|
+
* @returns The model instance.
|
|
551
|
+
*/
|
|
302
552
|
fill(attributes) {
|
|
303
553
|
Object.assign(this.attributes, attributes);
|
|
304
554
|
return this;
|
|
305
555
|
}
|
|
556
|
+
/**
|
|
557
|
+
* Save the model to the database.
|
|
558
|
+
*
|
|
559
|
+
* @returns A promise that resolves to true on success, false otherwise.
|
|
560
|
+
*/
|
|
306
561
|
async save() {
|
|
307
562
|
const query = this.constructor.query();
|
|
308
563
|
if (this.exists) {
|
|
@@ -322,6 +577,11 @@ var Model = class {
|
|
|
322
577
|
return false;
|
|
323
578
|
}
|
|
324
579
|
}
|
|
580
|
+
/**
|
|
581
|
+
* Delete the model from the database.
|
|
582
|
+
*
|
|
583
|
+
* @returns A promise that resolves to true on success, false otherwise.
|
|
584
|
+
*/
|
|
325
585
|
async delete() {
|
|
326
586
|
if (!this.exists) return false;
|
|
327
587
|
const query = this.constructor.query();
|
|
@@ -330,12 +590,22 @@ var Model = class {
|
|
|
330
590
|
this.exists = false;
|
|
331
591
|
return true;
|
|
332
592
|
}
|
|
593
|
+
/**
|
|
594
|
+
* Get the table associated with the model.
|
|
595
|
+
*
|
|
596
|
+
* @returns The table name.
|
|
597
|
+
*/
|
|
333
598
|
getTable() {
|
|
334
599
|
if (this.constructor.table) {
|
|
335
600
|
return this.constructor.table;
|
|
336
601
|
}
|
|
337
602
|
return this.constructor.name.toLowerCase() + "s";
|
|
338
603
|
}
|
|
604
|
+
/**
|
|
605
|
+
* Get the attributes that have been changed since the last sync.
|
|
606
|
+
*
|
|
607
|
+
* @returns A record of dirty attributes.
|
|
608
|
+
*/
|
|
339
609
|
getDirty() {
|
|
340
610
|
const dirty = {};
|
|
341
611
|
for (const key in this.attributes) {
|
|
@@ -345,37 +615,122 @@ var Model = class {
|
|
|
345
615
|
}
|
|
346
616
|
return dirty;
|
|
347
617
|
}
|
|
618
|
+
/**
|
|
619
|
+
* Sync the original attributes with the current attributes.
|
|
620
|
+
*/
|
|
348
621
|
syncOriginal() {
|
|
349
622
|
this.original = { ...this.attributes };
|
|
350
623
|
}
|
|
351
|
-
|
|
624
|
+
/**
|
|
625
|
+
* Define a one-to-one relationship.
|
|
626
|
+
*
|
|
627
|
+
* @param related - The related model class.
|
|
628
|
+
* @param foreignKey - The foreign key on the related table.
|
|
629
|
+
* @param localKey - The local key on the current table.
|
|
630
|
+
* @returns A HasOne relationship instance.
|
|
631
|
+
*/
|
|
352
632
|
hasOne(related, foreignKey, localKey) {
|
|
353
633
|
const instance = new related();
|
|
354
634
|
const fk = foreignKey || this.getForeignKey();
|
|
355
635
|
const lk = localKey || "id";
|
|
356
636
|
return new HasOne(instance.newQuery(), this, fk, lk);
|
|
357
637
|
}
|
|
638
|
+
/**
|
|
639
|
+
* Define a one-to-many relationship.
|
|
640
|
+
*
|
|
641
|
+
* @param related - The related model class.
|
|
642
|
+
* @param foreignKey - The foreign key on the related table.
|
|
643
|
+
* @param localKey - The local key on the current table.
|
|
644
|
+
* @returns A HasMany relationship instance.
|
|
645
|
+
*/
|
|
358
646
|
hasMany(related, foreignKey, localKey) {
|
|
359
647
|
const instance = new related();
|
|
360
648
|
const fk = foreignKey || this.getForeignKey();
|
|
361
649
|
const lk = localKey || "id";
|
|
362
650
|
return new HasMany(instance.newQuery(), this, fk, lk);
|
|
363
651
|
}
|
|
652
|
+
/**
|
|
653
|
+
* Define an inverse one-to-one or many relationship.
|
|
654
|
+
*
|
|
655
|
+
* @param related - The related model class.
|
|
656
|
+
* @param foreignKey - The foreign key on the current table.
|
|
657
|
+
* @param ownerKey - The owner key on the related table.
|
|
658
|
+
* @returns A BelongsTo relationship instance.
|
|
659
|
+
*/
|
|
364
660
|
belongsTo(related, foreignKey, ownerKey) {
|
|
365
661
|
const instance = new related();
|
|
366
662
|
const fk = foreignKey || instance.getForeignKey();
|
|
367
663
|
const ok = ownerKey || "id";
|
|
368
664
|
return new BelongsTo(instance.newQuery(), this, fk, ok);
|
|
369
665
|
}
|
|
666
|
+
/**
|
|
667
|
+
* Get the default foreign key name for the model.
|
|
668
|
+
*
|
|
669
|
+
* @returns The foreign key name.
|
|
670
|
+
*/
|
|
370
671
|
getForeignKey() {
|
|
371
672
|
return this.getTable().slice(0, -1) + "_id";
|
|
372
673
|
}
|
|
674
|
+
/**
|
|
675
|
+
* Get a new query builder for the model's table.
|
|
676
|
+
*
|
|
677
|
+
* @returns A ModelQueryBuilder instance.
|
|
678
|
+
*/
|
|
373
679
|
newQuery() {
|
|
374
680
|
return this.constructor.query();
|
|
375
681
|
}
|
|
376
682
|
};
|
|
377
683
|
|
|
378
684
|
// src/database/blueprint.ts
|
|
685
|
+
var Column = class {
|
|
686
|
+
name;
|
|
687
|
+
type;
|
|
688
|
+
isNullable = false;
|
|
689
|
+
isUnique = false;
|
|
690
|
+
defaultValue = null;
|
|
691
|
+
constructor(name, type) {
|
|
692
|
+
this.name = name;
|
|
693
|
+
this.type = type;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Set the column as nullable.
|
|
697
|
+
*/
|
|
698
|
+
nullable() {
|
|
699
|
+
this.isNullable = true;
|
|
700
|
+
return this;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Set the column as unique.
|
|
704
|
+
*/
|
|
705
|
+
unique() {
|
|
706
|
+
this.isUnique = true;
|
|
707
|
+
return this;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Set the default value for the column.
|
|
711
|
+
*/
|
|
712
|
+
default(value) {
|
|
713
|
+
this.defaultValue = value;
|
|
714
|
+
return this;
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Convert the column definition to SQL.
|
|
718
|
+
*/
|
|
719
|
+
toSql() {
|
|
720
|
+
let sql = `${this.name} ${this.type}`;
|
|
721
|
+
if (this.isUnique) {
|
|
722
|
+
sql += " UNIQUE";
|
|
723
|
+
}
|
|
724
|
+
if (!this.isNullable) {
|
|
725
|
+
sql += " NOT NULL";
|
|
726
|
+
}
|
|
727
|
+
if (this.defaultValue !== null) {
|
|
728
|
+
const formattedValue = typeof this.defaultValue === "string" ? `'${this.defaultValue}'` : this.defaultValue;
|
|
729
|
+
sql += ` DEFAULT ${formattedValue}`;
|
|
730
|
+
}
|
|
731
|
+
return sql;
|
|
732
|
+
}
|
|
733
|
+
};
|
|
379
734
|
var Blueprint = class {
|
|
380
735
|
table;
|
|
381
736
|
columns = [];
|
|
@@ -383,30 +738,55 @@ var Blueprint = class {
|
|
|
383
738
|
constructor(table) {
|
|
384
739
|
this.table = table;
|
|
385
740
|
}
|
|
741
|
+
/**
|
|
742
|
+
* Add an auto-incrementing ID column.
|
|
743
|
+
*/
|
|
386
744
|
id() {
|
|
387
745
|
this.columns.push("id INTEGER PRIMARY KEY AUTOINCREMENT");
|
|
388
746
|
return this;
|
|
389
747
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
748
|
+
/**
|
|
749
|
+
* Add a string (TEXT) column.
|
|
750
|
+
*/
|
|
751
|
+
string(column) {
|
|
752
|
+
const col = new Column(column, "TEXT");
|
|
753
|
+
this.columns.push(col);
|
|
754
|
+
return col;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Add an integer column.
|
|
758
|
+
*/
|
|
394
759
|
integer(column) {
|
|
395
|
-
|
|
396
|
-
|
|
760
|
+
const col = new Column(column, "INTEGER");
|
|
761
|
+
this.columns.push(col);
|
|
762
|
+
return col;
|
|
397
763
|
}
|
|
764
|
+
/**
|
|
765
|
+
* Add a boolean column.
|
|
766
|
+
*/
|
|
398
767
|
boolean(column) {
|
|
399
|
-
|
|
400
|
-
|
|
768
|
+
const col = new Column(column, "BOOLEAN");
|
|
769
|
+
this.columns.push(col);
|
|
770
|
+
return col;
|
|
401
771
|
}
|
|
772
|
+
/**
|
|
773
|
+
* Add created_at and updated_at timestamp columns.
|
|
774
|
+
*/
|
|
402
775
|
timestamps() {
|
|
403
776
|
this.columns.push("created_at DATETIME DEFAULT CURRENT_TIMESTAMP");
|
|
404
777
|
this.columns.push("updated_at DATETIME DEFAULT CURRENT_TIMESTAMP");
|
|
405
778
|
return this;
|
|
406
779
|
}
|
|
780
|
+
/**
|
|
781
|
+
* Convert the blueprint to a set of SQL statements.
|
|
782
|
+
*/
|
|
407
783
|
toSql() {
|
|
408
784
|
if (this.columns.length > 0) {
|
|
409
|
-
const
|
|
785
|
+
const colDefinitions = this.columns.map((col) => {
|
|
786
|
+
if (typeof col === "string") return col;
|
|
787
|
+
return col.toSql();
|
|
788
|
+
});
|
|
789
|
+
const cols = colDefinitions.join(", ");
|
|
410
790
|
return [`CREATE TABLE IF NOT EXISTS ${this.table} (${cols})`];
|
|
411
791
|
}
|
|
412
792
|
return this.commands;
|
|
@@ -427,6 +807,7 @@ var Schema = class {
|
|
|
427
807
|
export {
|
|
428
808
|
BelongsTo,
|
|
429
809
|
Blueprint,
|
|
810
|
+
Column,
|
|
430
811
|
Connection,
|
|
431
812
|
Database,
|
|
432
813
|
HasMany,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@3lineas/d1-orm",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "A lightweight and powerful ORM for Cloudflare D1, inspired by Laravel Eloquent.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"bin": {
|
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsup src/index.ts src/cli/index.ts --format cjs,esm --dts --clean",
|
|
15
15
|
"orm": "npx tsx src/cli/index.ts",
|
|
16
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
17
|
-
"postinstall": "node scripts/postinstall.js"
|
|
16
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
18
17
|
},
|
|
19
18
|
"keywords": [],
|
|
20
19
|
"author": "",
|
|
@@ -34,5 +33,8 @@
|
|
|
34
33
|
"sharp",
|
|
35
34
|
"workerd"
|
|
36
35
|
]
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@clack/prompts": "^0.11.0"
|
|
37
39
|
}
|
|
38
40
|
}
|