sails-sqlite 0.1.0 → 0.2.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.
Files changed (29) hide show
  1. package/lib/index.js +204 -28
  2. package/lib/private/build-std-adapter-method.js +8 -4
  3. package/lib/private/machines/avg-records.js +1 -1
  4. package/lib/private/machines/begin-transaction.js +51 -0
  5. package/lib/private/machines/commit-transaction.js +50 -0
  6. package/lib/private/machines/count-records.js +1 -1
  7. package/lib/private/machines/create-each-record.js +1 -1
  8. package/lib/private/machines/create-record.js +2 -2
  9. package/lib/private/machines/define-physical-model.js +18 -9
  10. package/lib/private/machines/destroy-records.js +21 -8
  11. package/lib/private/machines/drop-physical-model.js +2 -2
  12. package/lib/private/machines/find-records.js +3 -3
  13. package/lib/private/machines/join.js +232 -66
  14. package/lib/private/machines/lease-connection.js +58 -0
  15. package/lib/private/machines/private/build-sqlite-where-clause.js +10 -8
  16. package/lib/private/machines/private/compile-statement.js +334 -0
  17. package/lib/private/machines/private/generate-join-sql-query.js +14 -6
  18. package/lib/private/machines/private/process-each-record.js +9 -2
  19. package/lib/private/machines/private/process-native-error.js +85 -40
  20. package/lib/private/machines/rollback-transaction.js +50 -0
  21. package/lib/private/machines/sum-records.js +1 -1
  22. package/lib/private/machines/update-records.js +27 -10
  23. package/package.json +8 -3
  24. package/tests/index.js +1 -1
  25. package/tests/runner.js +99 -0
  26. package/tests/transaction.test.js +562 -0
  27. package/tests/adapter.test.js +0 -534
  28. package/tests/datatypes.test.js +0 -293
  29. package/tests/sequence.test.js +0 -153
@@ -1,534 +0,0 @@
1
- const { test, describe, before, after } = require('node:test')
2
- const assert = require('node:assert')
3
- const path = require('node:path')
4
- const fs = require('node:fs')
5
-
6
- // Import the adapter
7
- const adapter = require('../lib/index.js')
8
-
9
- describe('sails-sqlite adapter', () => {
10
- let testDbPath
11
- let datastore
12
- let models
13
-
14
- before(async () => {
15
- testDbPath = path.join(__dirname, `test-adapter-${Date.now()}.sqlite`)
16
- datastore = {
17
- identity: 'testDatastore',
18
- adapter: 'sails-sqlite',
19
- url: testDbPath
20
- }
21
-
22
- models = {
23
- user: {
24
- identity: 'user',
25
- tableName: 'users',
26
- primaryKey: 'id',
27
- attributes: {
28
- id: {
29
- type: 'number',
30
- autoIncrement: true,
31
- columnName: 'id'
32
- },
33
- name: {
34
- type: 'string',
35
- required: true,
36
- columnName: 'name'
37
- },
38
- email: {
39
- type: 'string',
40
- required: true,
41
- unique: true,
42
- isEmail: true,
43
- columnName: 'email'
44
- },
45
- age: {
46
- type: 'number',
47
- columnName: 'age'
48
- },
49
- isActive: {
50
- type: 'boolean',
51
- defaultsTo: true,
52
- columnName: 'is_active'
53
- },
54
- metadata: {
55
- type: 'json',
56
- columnName: 'metadata'
57
- },
58
- createdAt: {
59
- type: 'number',
60
- autoCreatedAt: true,
61
- columnName: 'created_at'
62
- },
63
- updatedAt: {
64
- type: 'number',
65
- autoUpdatedAt: true,
66
- columnName: 'updated_at'
67
- }
68
- }
69
- }
70
- }
71
-
72
- // Register datastore once for all tests
73
- await new Promise((resolve, reject) => {
74
- adapter.registerDatastore(datastore, models, (err) => {
75
- if (err) return reject(err)
76
- resolve()
77
- })
78
- })
79
-
80
- // Create table schema once for all tests
81
- const tableDef = {
82
- id: {
83
- type: 'number',
84
- primaryKey: true,
85
- autoIncrement: true,
86
- required: true
87
- },
88
- name: {
89
- type: 'string',
90
- required: true
91
- },
92
- email: {
93
- type: 'string',
94
- required: true,
95
- unique: true
96
- },
97
- age: {
98
- type: 'number'
99
- },
100
- is_active: {
101
- type: 'boolean',
102
- defaultsTo: true
103
- },
104
- metadata: {
105
- type: 'json'
106
- },
107
- created_at: {
108
- type: 'number'
109
- },
110
- updated_at: {
111
- type: 'number'
112
- }
113
- }
114
-
115
- await new Promise((resolve, reject) => {
116
- adapter.define('testDatastore', 'users', tableDef, (err) => {
117
- if (err) return reject(err)
118
- resolve()
119
- })
120
- })
121
- })
122
-
123
- after(async () => {
124
- // Teardown datastore
125
- await new Promise((resolve, reject) => {
126
- adapter.teardown('testDatastore', (err) => {
127
- if (err) return reject(err)
128
- resolve()
129
- })
130
- })
131
-
132
- // Clean up test database
133
- if (fs.existsSync(testDbPath)) {
134
- try {
135
- fs.unlinkSync(testDbPath)
136
- } catch (err) {
137
- // Ignore cleanup errors
138
- }
139
- }
140
- })
141
-
142
- describe('DDL Methods', () => {
143
- test('define should create table schema', async () => {
144
- const tableDef = {
145
- id: {
146
- type: 'number',
147
- primaryKey: true,
148
- autoIncrement: true,
149
- required: true
150
- },
151
- name: {
152
- type: 'string',
153
- required: true
154
- },
155
- description: {
156
- type: 'string'
157
- }
158
- }
159
-
160
- await new Promise((resolve, reject) => {
161
- adapter.define(
162
- 'testDatastore',
163
- 'test_define_table',
164
- tableDef,
165
- (err) => {
166
- if (err) return reject(err)
167
- resolve()
168
- }
169
- )
170
- })
171
-
172
- assert(true, 'Table created successfully')
173
- })
174
-
175
- test('drop should remove table', async () => {
176
- const tableDef = {
177
- id: { type: 'number', primaryKey: true },
178
- name: { type: 'string' }
179
- }
180
-
181
- // Create table first
182
- await new Promise((resolve, reject) => {
183
- adapter.define('testDatastore', 'test_drop_table', tableDef, (err) => {
184
- if (err) return reject(err)
185
- resolve()
186
- })
187
- })
188
-
189
- // Then drop it
190
- await new Promise((resolve, reject) => {
191
- adapter.drop('testDatastore', 'test_drop_table', null, (err) => {
192
- if (err) return reject(err)
193
- resolve()
194
- })
195
- })
196
-
197
- assert(true, 'Table dropped successfully')
198
- })
199
-
200
- test('setSequence should handle PostgreSQL-style sequence names', async () => {
201
- const tableDef = {
202
- id: { type: 'number', primaryKey: true, autoIncrement: true },
203
- name: { type: 'string' }
204
- }
205
-
206
- await new Promise((resolve, reject) => {
207
- adapter.define(
208
- 'testDatastore',
209
- 'test_sequence_table',
210
- tableDef,
211
- (err) => {
212
- if (err) return reject(err)
213
- resolve()
214
- }
215
- )
216
- })
217
-
218
- // Test PostgreSQL-style sequence name
219
- await new Promise((resolve, reject) => {
220
- adapter.setSequence(
221
- 'testDatastore',
222
- 'test_sequence_table_id_seq',
223
- 100,
224
- (err) => {
225
- if (err) return reject(err)
226
- resolve()
227
- }
228
- )
229
- })
230
-
231
- assert(true, 'Sequence reset with PostgreSQL-style name')
232
- })
233
- })
234
-
235
- describe('DML Methods', () => {
236
- test('create should insert single record', async () => {
237
- const query = {
238
- using: 'users',
239
- newRecord: {
240
- name: 'John Doe',
241
- email: 'john@example.com',
242
- age: 30,
243
- is_active: 1,
244
- metadata: JSON.stringify({ role: 'admin' }),
245
- created_at: Date.now(),
246
- updated_at: Date.now()
247
- },
248
- meta: {
249
- fetch: true
250
- }
251
- }
252
-
253
- const result = await new Promise((resolve, reject) => {
254
- adapter.create('testDatastore', query, (err, result) => {
255
- if (err) return reject(err)
256
- resolve(result)
257
- })
258
- })
259
-
260
- assert(result, 'Should return created record')
261
- assert.strictEqual(result.name, 'John Doe')
262
- assert.strictEqual(result.email, 'john@example.com')
263
- assert.strictEqual(typeof result.age, 'number') // Test number conversion
264
- assert.strictEqual(typeof result.created_at, 'number') // Test timestamp conversion
265
- })
266
-
267
- test('createEach should insert multiple records', async () => {
268
- const query = {
269
- using: 'users',
270
- newRecords: [
271
- {
272
- name: 'Jane Smith',
273
- email: 'jane@example.com',
274
- age: 25,
275
- is_active: 1,
276
- metadata: JSON.stringify({ role: 'user' }),
277
- created_at: Date.now(),
278
- updated_at: Date.now()
279
- },
280
- {
281
- name: 'Bob Johnson',
282
- email: 'bob@example.com',
283
- age: 35,
284
- is_active: 0,
285
- metadata: JSON.stringify({ role: 'moderator' }),
286
- created_at: Date.now(),
287
- updated_at: Date.now()
288
- }
289
- ],
290
- meta: {
291
- fetch: true
292
- }
293
- }
294
-
295
- const result = await new Promise((resolve, reject) => {
296
- adapter.createEach('testDatastore', query, (err, result) => {
297
- if (err) return reject(err)
298
- resolve(result)
299
- })
300
- })
301
-
302
- assert(Array.isArray(result), 'Should return array of records')
303
- assert.strictEqual(result.length, 2)
304
- assert.strictEqual(result[0].name, 'Jane Smith')
305
- assert.strictEqual(result[1].name, 'Bob Johnson')
306
- })
307
-
308
- test('find should retrieve records', async () => {
309
- // Create some test data first
310
- await new Promise((resolve, reject) => {
311
- const query = {
312
- using: 'users',
313
- newRecords: [
314
- {
315
- name: 'Alice Find',
316
- email: 'alice.find@example.com',
317
- age: 28,
318
- is_active: 1,
319
- created_at: Date.now(),
320
- updated_at: Date.now()
321
- },
322
- {
323
- name: 'Charlie Find',
324
- email: 'charlie.find@example.com',
325
- age: 32,
326
- is_active: 0,
327
- created_at: Date.now(),
328
- updated_at: Date.now()
329
- }
330
- ]
331
- }
332
- adapter.createEach('testDatastore', query, (err) => {
333
- if (err) return reject(err)
334
- resolve()
335
- })
336
- })
337
-
338
- // Test basic find all
339
- const query = {
340
- using: 'users',
341
- criteria: {
342
- where: {},
343
- sort: [{ name: 'ASC' }],
344
- limit: 10,
345
- skip: 0
346
- },
347
- meta: {
348
- logSqliteS3Qs: true
349
- }
350
- }
351
-
352
- const result = await new Promise((resolve, reject) => {
353
- adapter.find('testDatastore', query, (err, result) => {
354
- if (err) return reject(err)
355
- resolve(result)
356
- })
357
- })
358
-
359
- assert(Array.isArray(result), 'Should return array of records')
360
- assert(result.length >= 2, 'Should find the records we just created')
361
-
362
- // Test finding with boolean criteria
363
- const activeQuery = {
364
- using: 'users',
365
- criteria: {
366
- where: {
367
- is_active: true
368
- }
369
- }
370
- }
371
-
372
- const activeResult = await new Promise((resolve, reject) => {
373
- adapter.find('testDatastore', activeQuery, (err, result) => {
374
- if (err) return reject(err)
375
- resolve(result)
376
- })
377
- })
378
-
379
- assert(
380
- Array.isArray(activeResult),
381
- 'Should return array of active records'
382
- )
383
- assert(activeResult.length >= 1, 'Should find at least one active user')
384
-
385
- // Verify all returned records have is_active = true
386
- activeResult.forEach((record) => {
387
- assert.strictEqual(
388
- record.is_active,
389
- true,
390
- 'All returned records should have is_active = true'
391
- )
392
- })
393
- })
394
-
395
- test('count should return record count', async () => {
396
- // Create test data first
397
- await new Promise((resolve, reject) => {
398
- const query = {
399
- using: 'users',
400
- newRecords: [
401
- {
402
- name: 'User 1',
403
- email: 'user1@example.com',
404
- created_at: Date.now(),
405
- updated_at: Date.now()
406
- },
407
- {
408
- name: 'User 2',
409
- email: 'user2@example.com',
410
- created_at: Date.now(),
411
- updated_at: Date.now()
412
- },
413
- {
414
- name: 'User 3',
415
- email: 'user3@example.com',
416
- created_at: Date.now(),
417
- updated_at: Date.now()
418
- }
419
- ]
420
- }
421
- adapter.createEach('testDatastore', query, (err) => {
422
- if (err) return reject(err)
423
- resolve()
424
- })
425
- })
426
-
427
- const query = {
428
- using: 'users',
429
- criteria: {
430
- where: {}
431
- }
432
- }
433
-
434
- const result = await new Promise((resolve, reject) => {
435
- adapter.count('testDatastore', query, (err, result) => {
436
- if (err) return reject(err)
437
- resolve(result)
438
- })
439
- })
440
-
441
- assert.strictEqual(typeof result, 'number')
442
- assert(result >= 3, 'Should count all created records')
443
- })
444
-
445
- test('update should modify records', async () => {
446
- // Create test data first
447
- await new Promise((resolve, reject) => {
448
- const query = {
449
- using: 'users',
450
- newRecord: {
451
- name: 'Test User',
452
- email: 'test@example.com',
453
- age: 25,
454
- created_at: Date.now(),
455
- updated_at: Date.now()
456
- },
457
- meta: { fetch: true }
458
- }
459
- adapter.create('testDatastore', query, (err) => {
460
- if (err) return reject(err)
461
- resolve()
462
- })
463
- })
464
-
465
- const query = {
466
- using: 'users',
467
- criteria: {
468
- where: {
469
- email: 'test@example.com'
470
- }
471
- },
472
- valuesToSet: {
473
- age: 26,
474
- updated_at: Date.now()
475
- },
476
- meta: {
477
- fetch: true
478
- }
479
- }
480
-
481
- const result = await new Promise((resolve, reject) => {
482
- adapter.update('testDatastore', query, (err, result) => {
483
- if (err) return reject(err)
484
- resolve(result)
485
- })
486
- })
487
-
488
- assert(Array.isArray(result), 'Should return array of updated records')
489
- assert(result.length > 0, 'Should update at least one record')
490
- assert.strictEqual(result[0].age, 26, 'Should update age field')
491
- })
492
-
493
- test('destroy should delete records', async () => {
494
- // Create test data first
495
- await new Promise((resolve, reject) => {
496
- const query = {
497
- using: 'users',
498
- newRecord: {
499
- name: 'Delete Me',
500
- email: 'delete@example.com',
501
- created_at: Date.now(),
502
- updated_at: Date.now()
503
- }
504
- }
505
- adapter.create('testDatastore', query, (err) => {
506
- if (err) return reject(err)
507
- resolve()
508
- })
509
- })
510
-
511
- const query = {
512
- using: 'users',
513
- criteria: {
514
- where: {
515
- email: 'delete@example.com'
516
- }
517
- },
518
- meta: {
519
- fetch: true
520
- }
521
- }
522
-
523
- const result = await new Promise((resolve, reject) => {
524
- adapter.destroy('testDatastore', query, (err, result) => {
525
- if (err) return reject(err)
526
- resolve(result)
527
- })
528
- })
529
-
530
- assert(Array.isArray(result), 'Should return array of destroyed records')
531
- assert(result.length > 0, 'Should destroy at least one record')
532
- })
533
- })
534
- })