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,293 +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('Data type conversions', () => {
10
- let testDbPath
11
- let datastore
12
- let models
13
-
14
- before(async () => {
15
- testDbPath = path.join(__dirname, `test-datatypes-${Date.now()}.sqlite`)
16
- datastore = {
17
- identity: 'testDatastore',
18
- adapter: 'sails-sqlite',
19
- url: testDbPath
20
- }
21
-
22
- models = {
23
- testmodel: {
24
- identity: 'testmodel',
25
- tableName: 'test_records',
26
- primaryKey: 'id',
27
- attributes: {
28
- id: {
29
- type: 'number',
30
- autoIncrement: true,
31
- columnName: 'id'
32
- },
33
- stringField: {
34
- type: 'string',
35
- columnName: 'string_field'
36
- },
37
- numberField: {
38
- type: 'number',
39
- columnName: 'number_field'
40
- },
41
- booleanField: {
42
- type: 'boolean',
43
- columnName: 'boolean_field'
44
- },
45
- jsonField: {
46
- type: 'json',
47
- columnName: 'json_field'
48
- },
49
- timestampField: {
50
- type: 'number',
51
- columnName: 'timestamp_field'
52
- }
53
- }
54
- }
55
- }
56
-
57
- await new Promise((resolve, reject) => {
58
- adapter.registerDatastore(datastore, models, (err) => {
59
- if (err) return reject(err)
60
- resolve()
61
- })
62
- })
63
-
64
- const tableDef = {
65
- id: {
66
- type: 'number',
67
- primaryKey: true,
68
- autoIncrement: true,
69
- required: true
70
- },
71
- string_field: {
72
- type: 'string'
73
- },
74
- number_field: {
75
- type: 'number',
76
- columnType: 'float' // Specify float for decimal numbers
77
- },
78
- boolean_field: {
79
- type: 'boolean'
80
- },
81
- json_field: {
82
- type: 'json'
83
- },
84
- timestamp_field: {
85
- type: 'number'
86
- }
87
- }
88
-
89
- await new Promise((resolve, reject) => {
90
- adapter.define('testDatastore', 'test_records', tableDef, (err) => {
91
- if (err) return reject(err)
92
- resolve()
93
- })
94
- })
95
- })
96
-
97
- after(async () => {
98
- await new Promise((resolve, reject) => {
99
- adapter.teardown('testDatastore', (err) => {
100
- if (err) return reject(err)
101
- resolve()
102
- })
103
- })
104
-
105
- if (fs.existsSync(testDbPath)) {
106
- try {
107
- fs.unlinkSync(testDbPath)
108
- } catch (err) {
109
- // Ignore cleanup errors
110
- }
111
- }
112
- })
113
-
114
- test('should convert number types correctly', async () => {
115
- const testNumbers = [0, 42, 3.14159, -100, 1754501840042]
116
-
117
- for (const testNumber of testNumbers) {
118
- const query = {
119
- using: 'test_records',
120
- newRecord: {
121
- number_field: testNumber,
122
- timestamp_field: testNumber
123
- },
124
- meta: {
125
- fetch: true
126
- }
127
- }
128
-
129
- const result = await new Promise((resolve, reject) => {
130
- adapter.create('testDatastore', query, (err, result) => {
131
- if (err) return reject(err)
132
- resolve(result)
133
- })
134
- })
135
-
136
- assert.strictEqual(
137
- typeof result.number_field,
138
- 'number',
139
- `number_field should be a number, got ${typeof result.number_field}`
140
- )
141
- assert.strictEqual(
142
- typeof result.timestamp_field,
143
- 'number',
144
- `timestamp_field should be a number, got ${typeof result.timestamp_field}`
145
- )
146
- assert.strictEqual(
147
- result.number_field,
148
- testNumber,
149
- `number_field should equal ${testNumber}`
150
- )
151
- assert.strictEqual(
152
- result.timestamp_field,
153
- testNumber,
154
- `timestamp_field should equal ${testNumber}`
155
- )
156
- }
157
- })
158
-
159
- test('should convert boolean types correctly', async () => {
160
- const testCases = [
161
- { input: true, expected: true },
162
- { input: false, expected: false },
163
- { input: 1, expected: true },
164
- { input: 0, expected: false }
165
- ]
166
-
167
- for (const testCase of testCases) {
168
- const query = {
169
- using: 'test_records',
170
- newRecord: {
171
- boolean_field: testCase.input
172
- },
173
- meta: {
174
- fetch: true
175
- }
176
- }
177
-
178
- const result = await new Promise((resolve, reject) => {
179
- adapter.create('testDatastore', query, (err, result) => {
180
- if (err) return reject(err)
181
- resolve(result)
182
- })
183
- })
184
-
185
- assert.strictEqual(
186
- typeof result.boolean_field,
187
- 'boolean',
188
- 'boolean_field should be a boolean'
189
- )
190
- assert.strictEqual(
191
- result.boolean_field,
192
- testCase.expected,
193
- `boolean_field should equal ${testCase.expected}`
194
- )
195
- }
196
- })
197
-
198
- test('should convert JSON types correctly', async () => {
199
- const testObjects = [
200
- { name: 'test', value: 42 },
201
- { array: [1, 2, 3], nested: { key: 'value' } },
202
- null,
203
- 'simple string',
204
- [1, 2, 3, 4, 5]
205
- ]
206
-
207
- for (const testObject of testObjects) {
208
- const query = {
209
- using: 'test_records',
210
- newRecord: {
211
- json_field: testObject // Pass raw object, let the adapter handle JSON.stringify
212
- },
213
- meta: {
214
- fetch: true
215
- }
216
- }
217
-
218
- const result = await new Promise((resolve, reject) => {
219
- adapter.create('testDatastore', query, (err, result) => {
220
- if (err) return reject(err)
221
- resolve(result)
222
- })
223
- })
224
-
225
- // The result should be the parsed JSON object, not a string
226
- assert.deepStrictEqual(
227
- result.json_field,
228
- testObject,
229
- 'JSON field should be parsed correctly'
230
- )
231
- }
232
- })
233
-
234
- test('should handle string types correctly', async () => {
235
- const testStrings = ['hello world', '', 'unicode: 🚀', 'numbers: 123']
236
-
237
- for (const testString of testStrings) {
238
- const query = {
239
- using: 'test_records',
240
- newRecord: {
241
- string_field: testString
242
- },
243
- meta: {
244
- fetch: true
245
- }
246
- }
247
-
248
- const result = await new Promise((resolve, reject) => {
249
- adapter.create('testDatastore', query, (err, result) => {
250
- if (err) return reject(err)
251
- resolve(result)
252
- })
253
- })
254
-
255
- assert.strictEqual(
256
- typeof result.string_field,
257
- 'string',
258
- 'string_field should be a string'
259
- )
260
- assert.strictEqual(
261
- result.string_field,
262
- testString,
263
- `string_field should equal "${testString}"`
264
- )
265
- }
266
- })
267
-
268
- test('should handle auto-increment ID conversion', async () => {
269
- const query = {
270
- using: 'test_records',
271
- newRecord: {
272
- string_field: 'test'
273
- },
274
- meta: {
275
- fetch: true
276
- }
277
- }
278
-
279
- const result = await new Promise((resolve, reject) => {
280
- adapter.create('testDatastore', query, (err, result) => {
281
- if (err) return reject(err)
282
- resolve(result)
283
- })
284
- })
285
-
286
- assert.strictEqual(
287
- typeof result.id,
288
- 'number',
289
- 'Auto-increment ID should be a number'
290
- )
291
- assert(result.id > 0, 'Auto-increment ID should be positive')
292
- })
293
- })
@@ -1,153 +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('Sequence name parsing', () => {
10
- let testDbPath
11
- let datastore
12
- let models
13
-
14
- before(async () => {
15
- testDbPath = path.join(__dirname, `test-sequence-${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
- }
39
- }
40
- }
41
-
42
- await new Promise((resolve, reject) => {
43
- adapter.registerDatastore(datastore, models, (err) => {
44
- if (err) return reject(err)
45
- resolve()
46
- })
47
- })
48
-
49
- const tableDef = {
50
- id: { type: 'number', primaryKey: true, autoIncrement: true },
51
- name: { type: 'string' }
52
- }
53
-
54
- await new Promise((resolve, reject) => {
55
- adapter.define('testDatastore', 'users', tableDef, (err) => {
56
- if (err) return reject(err)
57
- resolve()
58
- })
59
- })
60
-
61
- // Create a record to establish the sequence
62
- await new Promise((resolve, reject) => {
63
- const query = {
64
- using: 'users',
65
- newRecord: {
66
- name: 'Test User'
67
- }
68
- }
69
- adapter.create('testDatastore', query, (err) => {
70
- if (err) return reject(err)
71
- resolve()
72
- })
73
- })
74
- })
75
-
76
- after(async () => {
77
- await new Promise((resolve, reject) => {
78
- adapter.teardown('testDatastore', (err) => {
79
- if (err) return reject(err)
80
- resolve()
81
- })
82
- })
83
-
84
- if (fs.existsSync(testDbPath)) {
85
- try {
86
- fs.unlinkSync(testDbPath)
87
- } catch (err) {
88
- // Ignore cleanup errors
89
- }
90
- }
91
- })
92
-
93
- test('should handle PostgreSQL-style sequence names', async () => {
94
- const testCases = [
95
- {
96
- sequenceName: 'users_id_seq',
97
- description: 'PostgreSQL-style: users_id_seq -> users'
98
- },
99
- {
100
- sequenceName: 'users_some_other_seq',
101
- description: 'Complex name: users_some_other_seq -> users'
102
- },
103
- {
104
- sequenceName: 'users',
105
- description: 'Direct table name: users -> users'
106
- }
107
- ]
108
-
109
- for (const testCase of testCases) {
110
- await new Promise((resolve, reject) => {
111
- adapter.setSequence(
112
- 'testDatastore',
113
- testCase.sequenceName,
114
- 100,
115
- (err) => {
116
- if (err) return reject(err)
117
- resolve()
118
- }
119
- )
120
- })
121
- }
122
-
123
- assert(true, 'All sequence name patterns handled successfully')
124
- })
125
-
126
- test('should extract correct table name from sequence name', async () => {
127
- // Test that 'user_id_seq' gets parsed to 'user' table (which doesn't exist)
128
- // and should gracefully handle the notFound case
129
- try {
130
- await new Promise((resolve, reject) => {
131
- adapter.setSequence('testDatastore', 'user_id_seq', 100, (err) => {
132
- // Should succeed even if table doesn't exist (handled by notFound exit)
133
- resolve()
134
- })
135
- })
136
- assert(true, 'Non-existent table handled gracefully')
137
- } catch (err) {
138
- // This should not throw due to our notFound handling
139
- assert.fail('Should handle non-existent table gracefully')
140
- }
141
- })
142
-
143
- test('should handle sequence names without underscores', async () => {
144
- await new Promise((resolve, reject) => {
145
- adapter.setSequence('testDatastore', 'users', 200, (err) => {
146
- if (err) return reject(err)
147
- resolve()
148
- })
149
- })
150
-
151
- assert(true, 'Direct table name handled successfully')
152
- })
153
- })