@3lineas/d1-orm 1.0.3 → 1.0.4

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/dist/index.js CHANGED
@@ -36,30 +36,73 @@ module.exports = __toCommonJS(index_exports);
36
36
 
37
37
  // src/core/connection.ts
38
38
  var Connection = class {
39
+ /**
40
+ * The underlying D1Database instance.
41
+ */
39
42
  db;
43
+ /**
44
+ * Create a new Connection instance.
45
+ *
46
+ * @param database - The D1Database instance.
47
+ */
40
48
  constructor(database) {
41
49
  this.db = database;
42
50
  }
51
+ /**
52
+ * Execute a SELECT statement.
53
+ *
54
+ * @param query - The SQL query string.
55
+ * @param bindings - The parameter bindings.
56
+ * @returns A promise that resolves to an array of results.
57
+ */
43
58
  async select(query, bindings = []) {
44
59
  const stmt = this.db.prepare(query).bind(...bindings);
45
60
  const result = await stmt.all();
46
61
  return result.results || [];
47
62
  }
63
+ /**
64
+ * Execute an INSERT statement.
65
+ *
66
+ * @param query - The SQL query string.
67
+ * @param bindings - The parameter bindings.
68
+ * @returns A promise that resolves to true on success.
69
+ */
48
70
  async insert(query, bindings = []) {
49
71
  const stmt = this.db.prepare(query).bind(...bindings);
50
72
  const result = await stmt.run();
51
73
  return result.success;
52
74
  }
75
+ /**
76
+ * Execute an UPDATE statement.
77
+ *
78
+ * @param query - The SQL query string.
79
+ * @param bindings - The parameter bindings.
80
+ * @returns A promise that resolves to true on success.
81
+ */
53
82
  async update(query, bindings = []) {
54
83
  const stmt = this.db.prepare(query).bind(...bindings);
55
84
  const result = await stmt.run();
56
85
  return result.success;
57
86
  }
87
+ /**
88
+ * Execute a DELETE statement.
89
+ *
90
+ * @param query - The SQL query string.
91
+ * @param bindings - The parameter bindings.
92
+ * @returns A promise that resolves to true on success.
93
+ */
58
94
  async delete(query, bindings = []) {
59
95
  const stmt = this.db.prepare(query).bind(...bindings);
60
96
  const result = await stmt.run();
61
97
  return result.success;
62
98
  }
99
+ /**
100
+ * Execute an arbitrary SQL statement.
101
+ *
102
+ * @param query - The SQL query string.
103
+ * @param bindings - The parameter bindings.
104
+ * @returns A promise that resolves to true on success.
105
+ */
63
106
  async statement(query, bindings = []) {
64
107
  const stmt = this.db.prepare(query).bind(...bindings);
65
108
  const result = await stmt.run();
@@ -69,22 +112,66 @@ var Connection = class {
69
112
 
70
113
  // src/core/query-builder.ts
71
114
  var QueryBuilder = class {
115
+ /**
116
+ * The database connection.
117
+ */
72
118
  connection;
119
+ /**
120
+ * The table to query.
121
+ */
73
122
  table;
123
+ /**
124
+ * The columns to select.
125
+ */
74
126
  columns = ["*"];
127
+ /**
128
+ * The where constraints for the query.
129
+ */
75
130
  wheres = [];
131
+ /**
132
+ * The bindings for the query.
133
+ */
76
134
  bindings = [];
135
+ /**
136
+ * The orderings for the query.
137
+ */
77
138
  orders = [];
139
+ /**
140
+ * The maximum number of records to return.
141
+ */
78
142
  limitValue = null;
143
+ /**
144
+ * The number of records to skip.
145
+ */
79
146
  offsetValue = null;
147
+ /**
148
+ * Create a new QueryBuilder instance.
149
+ *
150
+ * @param connection - The connection instance.
151
+ * @param table - The table name.
152
+ */
80
153
  constructor(connection, table) {
81
154
  this.connection = connection;
82
155
  this.table = table;
83
156
  }
157
+ /**
158
+ * Add a SELECT clause to the query.
159
+ *
160
+ * @param columns - The columns to select.
161
+ * @returns The QueryBuilder instance.
162
+ */
84
163
  select(...columns) {
85
164
  this.columns = columns.length > 0 ? columns : ["*"];
86
165
  return this;
87
166
  }
167
+ /**
168
+ * Add a basic WHERE clause to the query.
169
+ *
170
+ * @param column - The column name.
171
+ * @param operator - The operator or value.
172
+ * @param value - The value if operator is provided.
173
+ * @returns The QueryBuilder instance.
174
+ */
88
175
  where(column, operator, value) {
89
176
  if (value === void 0) {
90
177
  value = operator;
@@ -94,6 +181,14 @@ var QueryBuilder = class {
94
181
  this.bindings.push(value);
95
182
  return this;
96
183
  }
184
+ /**
185
+ * Add an OR WHERE clause to the query.
186
+ *
187
+ * @param column - The column name.
188
+ * @param operator - The operator or value.
189
+ * @param value - The value if operator is provided.
190
+ * @returns The QueryBuilder instance.
191
+ */
97
192
  orWhere(column, operator, value) {
98
193
  if (value === void 0) {
99
194
  value = operator;
@@ -103,18 +198,42 @@ var QueryBuilder = class {
103
198
  this.bindings.push(value);
104
199
  return this;
105
200
  }
201
+ /**
202
+ * Add an ORDER BY clause to the query.
203
+ *
204
+ * @param column - The column name.
205
+ * @param direction - The direction of the order.
206
+ * @returns The QueryBuilder instance.
207
+ */
106
208
  orderBy(column, direction = "asc") {
107
209
  this.orders.push(`${column} ${direction.toUpperCase()}`);
108
210
  return this;
109
211
  }
212
+ /**
213
+ * Add a LIMIT clause to the query.
214
+ *
215
+ * @param limit - The limit value.
216
+ * @returns The QueryBuilder instance.
217
+ */
110
218
  limit(limit) {
111
219
  this.limitValue = limit;
112
220
  return this;
113
221
  }
222
+ /**
223
+ * Add an OFFSET clause to the query.
224
+ *
225
+ * @param offset - The offset value.
226
+ * @returns The QueryBuilder instance.
227
+ */
114
228
  offset(offset) {
115
229
  this.offsetValue = offset;
116
230
  return this;
117
231
  }
232
+ /**
233
+ * Get the SQL representation of the query.
234
+ *
235
+ * @returns An object containing the SQL string and the bindings.
236
+ */
118
237
  toSql() {
119
238
  let sql = `SELECT ${this.columns.join(", ")} FROM ${this.table}`;
120
239
  if (this.wheres.length > 0) {
@@ -135,15 +254,31 @@ var QueryBuilder = class {
135
254
  }
136
255
  return { sql, bindings: this.bindings };
137
256
  }
257
+ /**
258
+ * Execute the query and get the results.
259
+ *
260
+ * @returns A promise that resolves to an array of records.
261
+ */
138
262
  async get() {
139
263
  const { sql, bindings } = this.toSql();
140
264
  return this.connection.select(sql, bindings);
141
265
  }
266
+ /**
267
+ * Execute the query and get the first result.
268
+ *
269
+ * @returns A promise that resolves to the first record or null.
270
+ */
142
271
  async first() {
143
272
  this.limit(1);
144
273
  const results = await this.get();
145
274
  return results.length > 0 ? results[0] : null;
146
275
  }
276
+ /**
277
+ * Insert a new record into the database.
278
+ *
279
+ * @param data - The data to insert.
280
+ * @returns A promise that resolves to true on success.
281
+ */
147
282
  async insert(data) {
148
283
  const columns = Object.keys(data);
149
284
  const values = Object.values(data);
@@ -151,6 +286,12 @@ var QueryBuilder = class {
151
286
  const sql = `INSERT INTO ${this.table} (${columns.join(", ")}) VALUES (${placeholders})`;
152
287
  return this.connection.insert(sql, values);
153
288
  }
289
+ /**
290
+ * Update records in the database.
291
+ *
292
+ * @param data - The data to update.
293
+ * @returns A promise that resolves to true on success.
294
+ */
154
295
  async update(data) {
155
296
  const columns = Object.keys(data);
156
297
  const values = Object.values(data);
@@ -162,10 +303,14 @@ var QueryBuilder = class {
162
303
  return w.startsWith("OR") ? w : `AND ${w}`;
163
304
  });
164
305
  sql += ` WHERE ${constraints.join(" ")}`;
165
- } else {
166
306
  }
167
307
  return this.connection.update(sql, [...values, ...this.bindings]);
168
308
  }
309
+ /**
310
+ * Delete records from the database.
311
+ *
312
+ * @returns A promise that resolves to true on success.
313
+ */
169
314
  async delete() {
170
315
  let sql = `DELETE FROM ${this.table}`;
171
316
  if (this.wheres.length > 0) {
@@ -181,11 +326,26 @@ var QueryBuilder = class {
181
326
 
182
327
  // src/core/model-query-builder.ts
183
328
  var ModelQueryBuilder = class extends QueryBuilder {
329
+ /**
330
+ * The class of the model being queried.
331
+ */
184
332
  modelClass;
333
+ /**
334
+ * Create a new ModelQueryBuilder instance.
335
+ *
336
+ * @param connection - The database connection.
337
+ * @param table - The table name.
338
+ * @param modelClass - The class constructor for the model.
339
+ */
185
340
  constructor(connection, table, modelClass) {
186
341
  super(connection, table);
187
342
  this.modelClass = modelClass;
188
343
  }
344
+ /**
345
+ * Execute the query and return model instances.
346
+ *
347
+ * @returns A promise that resolves to an array of model instances.
348
+ */
189
349
  async get() {
190
350
  const { sql, bindings } = this.toSql();
191
351
  const results = await this.connection.select(sql, bindings);
@@ -196,11 +356,21 @@ var ModelQueryBuilder = class extends QueryBuilder {
196
356
  return instance;
197
357
  });
198
358
  }
359
+ /**
360
+ * Execute the query and return the first matching model instance.
361
+ *
362
+ * @returns A promise that resolves to the model instance or null.
363
+ */
199
364
  async first() {
200
365
  this.limit(1);
201
366
  const results = await this.get();
202
367
  return results.length > 0 ? results[0] : null;
203
368
  }
369
+ /**
370
+ * Get the underlying model class.
371
+ *
372
+ * @returns The model class constructor.
373
+ */
204
374
  getModel() {
205
375
  return this.modelClass;
206
376
  }
@@ -208,14 +378,36 @@ var ModelQueryBuilder = class extends QueryBuilder {
208
378
 
209
379
  // src/core/database.ts
210
380
  var Database = class _Database {
381
+ /**
382
+ * The singleton instance of the Database.
383
+ */
211
384
  static instance;
385
+ /**
386
+ * The active database connection.
387
+ */
212
388
  connection;
389
+ /**
390
+ * Private constructor to enforce singleton pattern.
391
+ *
392
+ * @param d1 - The D1Database instance from Cloudflare.
393
+ */
213
394
  constructor(d1) {
214
395
  this.connection = new Connection(d1);
215
396
  }
397
+ /**
398
+ * Setup the database connection.
399
+ *
400
+ * @param d1 - The D1Database instance from Cloudflare environment (env.DB).
401
+ */
216
402
  static setup(d1) {
217
403
  _Database.instance = new _Database(d1);
218
404
  }
405
+ /**
406
+ * Get the singleton Database instance.
407
+ *
408
+ * @throws Error if setup() has not been called.
409
+ * @returns The Database instance.
410
+ */
219
411
  static getInstance() {
220
412
  if (!_Database.instance) {
221
413
  throw new Error(
@@ -300,43 +492,106 @@ var BelongsTo = class extends Relationship {
300
492
 
301
493
  // src/models/model.ts
302
494
  var Model = class {
495
+ /**
496
+ * The table associated with the model.
497
+ */
303
498
  static table;
499
+ /**
500
+ * Resolver function for the database connection.
501
+ */
304
502
  static connectionResolver;
503
+ /**
504
+ * The model's attributes.
505
+ */
305
506
  attributes = {};
507
+ /**
508
+ * The attributes that are mass assignable.
509
+ */
306
510
  fillable = [];
511
+ /**
512
+ * The attributes that should be hidden for serialization.
513
+ */
307
514
  hidden = [];
515
+ /**
516
+ * Indicates if the model exists in the database.
517
+ */
308
518
  exists = false;
519
+ /**
520
+ * The model's original attribute values.
521
+ */
309
522
  original = {};
523
+ /**
524
+ * Create a new Model instance.
525
+ *
526
+ * @param attributes - Initial attributes for the model.
527
+ */
310
528
  constructor(attributes = {}) {
311
529
  this.fill(attributes);
312
530
  }
313
- // Static Query Builder
531
+ /**
532
+ * Begin querying the model.
533
+ *
534
+ * @returns A new ModelQueryBuilder instance.
535
+ */
314
536
  static query() {
315
537
  const instance = new this();
316
538
  const table = instance.getTable();
317
539
  const connection = Database.getInstance().connection;
318
540
  return new ModelQueryBuilder(connection, table, this);
319
541
  }
542
+ /**
543
+ * Start a query on a specific connection (currently uses default).
544
+ *
545
+ * @param connectionName - The name of the connection.
546
+ * @returns A new ModelQueryBuilder instance.
547
+ */
320
548
  static on(connectionName) {
321
549
  return this.query();
322
550
  }
551
+ /**
552
+ * Retrieve all records for the model.
553
+ *
554
+ * @returns A promise that resolves to an array of model instances.
555
+ */
323
556
  static async all() {
324
557
  return this.query().get();
325
558
  }
559
+ /**
560
+ * Find a model by its primary key.
561
+ *
562
+ * @param id - The ID of the record.
563
+ * @returns A promise that resolves to the model instance or null if not found.
564
+ */
326
565
  static async find(id) {
327
566
  return this.query().where("id", "=", id).first();
328
567
  }
568
+ /**
569
+ * Save a new model and return the instance.
570
+ *
571
+ * @param attributes - Attributes for the new record.
572
+ * @returns A promise that resolves to the created model instance.
573
+ */
329
574
  static async create(attributes) {
330
575
  const instance = new this();
331
576
  instance.fill(attributes);
332
577
  await instance.save();
333
578
  return instance;
334
579
  }
335
- // Instance Methods
580
+ /**
581
+ * Fill the model with an array of attributes.
582
+ *
583
+ * @param attributes - Attributes to fill.
584
+ * @returns The model instance.
585
+ */
336
586
  fill(attributes) {
337
587
  Object.assign(this.attributes, attributes);
338
588
  return this;
339
589
  }
590
+ /**
591
+ * Save the model to the database.
592
+ *
593
+ * @returns A promise that resolves to true on success, false otherwise.
594
+ */
340
595
  async save() {
341
596
  const query = this.constructor.query();
342
597
  if (this.exists) {
@@ -356,6 +611,11 @@ var Model = class {
356
611
  return false;
357
612
  }
358
613
  }
614
+ /**
615
+ * Delete the model from the database.
616
+ *
617
+ * @returns A promise that resolves to true on success, false otherwise.
618
+ */
359
619
  async delete() {
360
620
  if (!this.exists) return false;
361
621
  const query = this.constructor.query();
@@ -364,12 +624,22 @@ var Model = class {
364
624
  this.exists = false;
365
625
  return true;
366
626
  }
627
+ /**
628
+ * Get the table associated with the model.
629
+ *
630
+ * @returns The table name.
631
+ */
367
632
  getTable() {
368
633
  if (this.constructor.table) {
369
634
  return this.constructor.table;
370
635
  }
371
636
  return this.constructor.name.toLowerCase() + "s";
372
637
  }
638
+ /**
639
+ * Get the attributes that have been changed since the last sync.
640
+ *
641
+ * @returns A record of dirty attributes.
642
+ */
373
643
  getDirty() {
374
644
  const dirty = {};
375
645
  for (const key in this.attributes) {
@@ -379,31 +649,67 @@ var Model = class {
379
649
  }
380
650
  return dirty;
381
651
  }
652
+ /**
653
+ * Sync the original attributes with the current attributes.
654
+ */
382
655
  syncOriginal() {
383
656
  this.original = { ...this.attributes };
384
657
  }
385
- // Relationships
658
+ /**
659
+ * Define a one-to-one relationship.
660
+ *
661
+ * @param related - The related model class.
662
+ * @param foreignKey - The foreign key on the related table.
663
+ * @param localKey - The local key on the current table.
664
+ * @returns A HasOne relationship instance.
665
+ */
386
666
  hasOne(related, foreignKey, localKey) {
387
667
  const instance = new related();
388
668
  const fk = foreignKey || this.getForeignKey();
389
669
  const lk = localKey || "id";
390
670
  return new HasOne(instance.newQuery(), this, fk, lk);
391
671
  }
672
+ /**
673
+ * Define a one-to-many relationship.
674
+ *
675
+ * @param related - The related model class.
676
+ * @param foreignKey - The foreign key on the related table.
677
+ * @param localKey - The local key on the current table.
678
+ * @returns A HasMany relationship instance.
679
+ */
392
680
  hasMany(related, foreignKey, localKey) {
393
681
  const instance = new related();
394
682
  const fk = foreignKey || this.getForeignKey();
395
683
  const lk = localKey || "id";
396
684
  return new HasMany(instance.newQuery(), this, fk, lk);
397
685
  }
686
+ /**
687
+ * Define an inverse one-to-one or many relationship.
688
+ *
689
+ * @param related - The related model class.
690
+ * @param foreignKey - The foreign key on the current table.
691
+ * @param ownerKey - The owner key on the related table.
692
+ * @returns A BelongsTo relationship instance.
693
+ */
398
694
  belongsTo(related, foreignKey, ownerKey) {
399
695
  const instance = new related();
400
696
  const fk = foreignKey || instance.getForeignKey();
401
697
  const ok = ownerKey || "id";
402
698
  return new BelongsTo(instance.newQuery(), this, fk, ok);
403
699
  }
700
+ /**
701
+ * Get the default foreign key name for the model.
702
+ *
703
+ * @returns The foreign key name.
704
+ */
404
705
  getForeignKey() {
405
706
  return this.getTable().slice(0, -1) + "_id";
406
707
  }
708
+ /**
709
+ * Get a new query builder for the model's table.
710
+ *
711
+ * @returns A ModelQueryBuilder instance.
712
+ */
407
713
  newQuery() {
408
714
  return this.constructor.query();
409
715
  }