@quatrain/backend-sqlite 1.1.1 → 1.1.2
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/SQLiteAdapter.js +18 -27
- package/package.json +2 -2
- package/src/SQLiteAdapter.ts +19 -29
package/dist/SQLiteAdapter.js
CHANGED
|
@@ -148,7 +148,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
148
148
|
id TEXT PRIMARY KEY`;
|
|
149
149
|
// Add columns based on dataObject properties
|
|
150
150
|
Object.entries(dataObject.properties).forEach(([prop, propDef]) => {
|
|
151
|
-
const propName = prop
|
|
151
|
+
const propName = prop;
|
|
152
152
|
let columnType = 'TEXT';
|
|
153
153
|
// Map property types to SQLite column types
|
|
154
154
|
if (propDef.constructor.name === 'NumberProperty') {
|
|
@@ -206,7 +206,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
206
206
|
let placeholders = ['?'];
|
|
207
207
|
let values = [uid];
|
|
208
208
|
Object.entries(data).forEach(([key, value]) => {
|
|
209
|
-
columns.push(`"${key
|
|
209
|
+
columns.push(`"${key}"`);
|
|
210
210
|
placeholders.push('?');
|
|
211
211
|
// Convert arrays and objects to JSON strings
|
|
212
212
|
if (Array.isArray(value) ||
|
|
@@ -261,7 +261,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
261
261
|
const propDef = dataObject.properties[prop];
|
|
262
262
|
if (propDef.constructor.name === 'ObjectProperty' &&
|
|
263
263
|
propDef.instanceOf) {
|
|
264
|
-
const propValue = result[prop
|
|
264
|
+
const propValue = result[prop];
|
|
265
265
|
if (propValue) {
|
|
266
266
|
let refTable = undefined;
|
|
267
267
|
if (this._params.mapping && this._params.mapping[propDef.instanceOf]) {
|
|
@@ -286,18 +286,14 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
286
286
|
else if (propDef.constructor.name === 'ArrayProperty' || propDef.constructor.name === 'MapProperty') {
|
|
287
287
|
// Parse JSON arrays and objects
|
|
288
288
|
try {
|
|
289
|
-
if (result[prop
|
|
290
|
-
result[prop] = JSON.parse(result[prop
|
|
289
|
+
if (result[prop]) {
|
|
290
|
+
result[prop] = JSON.parse(result[prop]);
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
catch (e) {
|
|
294
294
|
backend_1.Backend.warn(`[SQLA] Failed to parse JSON for ${prop}: ${e}`);
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
|
-
// Normalize property name case
|
|
298
|
-
if (prop.toLowerCase() !== prop) {
|
|
299
|
-
result[prop] = result[prop.toLowerCase()];
|
|
300
|
-
}
|
|
301
297
|
}
|
|
302
298
|
dataObject.populate(result);
|
|
303
299
|
return dataObject;
|
|
@@ -329,7 +325,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
329
325
|
let updates = [];
|
|
330
326
|
let values = [];
|
|
331
327
|
Object.entries(data).forEach(([key, value]) => {
|
|
332
|
-
updates.push(`"${key
|
|
328
|
+
updates.push(`"${key}" = ?`);
|
|
333
329
|
// Convert arrays and objects to JSON strings
|
|
334
330
|
if (Array.isArray(value) ||
|
|
335
331
|
(typeof value === 'object' && value !== null)) {
|
|
@@ -428,7 +424,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
428
424
|
Object.entries(dataObject.properties).forEach(([prop, propDef]) => {
|
|
429
425
|
if (propDef.constructor.name === 'ObjectProperty' &&
|
|
430
426
|
propDef.instanceOf) {
|
|
431
|
-
const propName = prop
|
|
427
|
+
const propName = prop;
|
|
432
428
|
const joinAlias = `${propName}_table`;
|
|
433
429
|
let table = undefined;
|
|
434
430
|
if (this._params.mapping && this._params.mapping[propDef.instanceOf]) {
|
|
@@ -459,14 +455,14 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
459
455
|
// list of filters objects
|
|
460
456
|
filters.forEach((filter, i) => {
|
|
461
457
|
query.push(parent && i === 0 ? 'AND' : i > 0 ? 'AND' : 'WHERE');
|
|
462
|
-
let realProp = filter.prop
|
|
458
|
+
let realProp = filter.prop;
|
|
463
459
|
let realOperator = operatorsMap[filter.operator];
|
|
464
460
|
let realValue = filter.value;
|
|
465
461
|
if (filter.prop === 'keywords') {
|
|
466
462
|
const keywordFilters = [];
|
|
467
463
|
const props = dataObject.getProperties(core_1.StringProperty.name);
|
|
468
464
|
Object.keys(props).forEach((rp) => {
|
|
469
|
-
keywordFilters.push(`${collection.toLowerCase()}.${rp
|
|
465
|
+
keywordFilters.push(`${collection.toLowerCase()}.${rp} LIKE ?`);
|
|
470
466
|
params.push(`%${filter.value}%`);
|
|
471
467
|
});
|
|
472
468
|
query.push(`(${keywordFilters.join(' OR ')})`);
|
|
@@ -480,7 +476,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
480
476
|
}
|
|
481
477
|
else {
|
|
482
478
|
const property = dataObject.get(filter.prop);
|
|
483
|
-
realProp = filter.prop
|
|
479
|
+
realProp = filter.prop;
|
|
484
480
|
if (property.constructor.name === 'ArrayProperty' &&
|
|
485
481
|
Array.isArray(realValue)) {
|
|
486
482
|
// Use EXISTS with json_each for array containment in SQLite
|
|
@@ -587,7 +583,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
587
583
|
if (pagination && pagination.sortings) {
|
|
588
584
|
pagination.sortings.forEach((sorting, i) => {
|
|
589
585
|
query.push(i === 0 ? `ORDER BY` : ',');
|
|
590
|
-
query.push(`${collection.toLowerCase()}.${sorting.prop
|
|
586
|
+
query.push(`${collection.toLowerCase()}.${sorting.prop} ${sorting.order}`);
|
|
591
587
|
if (sorting.prop !== undefined) {
|
|
592
588
|
sortField.push(`${sorting.prop} ${sorting.order.toUpperCase()}`);
|
|
593
589
|
}
|
|
@@ -617,15 +613,14 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
617
613
|
for (let doc of results || []) {
|
|
618
614
|
// Process document before populating
|
|
619
615
|
Object.entries(dataObject.properties).forEach(([prop, propDef]) => {
|
|
620
|
-
const lcProp = prop.toLowerCase();
|
|
621
616
|
// Handle ObjectProperty references
|
|
622
617
|
if (propDef.constructor.name === 'ObjectProperty' &&
|
|
623
618
|
propDef.instanceOf) {
|
|
624
|
-
const refValue = doc[
|
|
619
|
+
const refValue = doc[prop];
|
|
625
620
|
if (refValue) {
|
|
626
621
|
const info = joinTables[prop];
|
|
627
622
|
if (info) {
|
|
628
|
-
const label = doc[`${
|
|
623
|
+
const label = doc[`${prop}_table_name`] || '';
|
|
629
624
|
doc[prop] = {
|
|
630
625
|
ref: `${info.table}/${refValue}`,
|
|
631
626
|
path: `${info.table}/${refValue}`,
|
|
@@ -655,18 +650,14 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
655
650
|
// Handle array and map properties
|
|
656
651
|
else if (propDef.constructor.name === 'ArrayProperty' || propDef.constructor.name === 'MapProperty') {
|
|
657
652
|
try {
|
|
658
|
-
if (doc[
|
|
659
|
-
doc[prop] = JSON.parse(doc[
|
|
653
|
+
if (doc[prop] && typeof doc[prop] === 'string') {
|
|
654
|
+
doc[prop] = JSON.parse(doc[prop]);
|
|
660
655
|
}
|
|
661
656
|
}
|
|
662
657
|
catch (e) {
|
|
663
658
|
backend_1.Backend.warn(`[SQLA] Failed to parse JSON for ${prop}: ${e}`);
|
|
664
659
|
}
|
|
665
660
|
}
|
|
666
|
-
// Ensure property is available with original case
|
|
667
|
-
if (prop !== lcProp) {
|
|
668
|
-
doc[prop] = doc[lcProp];
|
|
669
|
-
}
|
|
670
661
|
});
|
|
671
662
|
// Map SQLite 'id' column back to Quatrain 'uid' property
|
|
672
663
|
if (doc.id && !doc.uid) {
|
|
@@ -711,7 +702,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
711
702
|
generateCreateSql(collection, properties) {
|
|
712
703
|
let query = `CREATE TABLE IF NOT EXISTS "${collection.toLowerCase()}" (\n id TEXT PRIMARY KEY`;
|
|
713
704
|
properties.forEach((propDef) => {
|
|
714
|
-
const propName = propDef.name
|
|
705
|
+
const propName = propDef.name;
|
|
715
706
|
let columnType = 'TEXT';
|
|
716
707
|
const type = propDef.type || propDef.constructor.name;
|
|
717
708
|
if (type === 'NumberProperty') {
|
|
@@ -745,7 +736,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
745
736
|
const downSql = [];
|
|
746
737
|
// Added columns
|
|
747
738
|
delta.added.forEach((propDef) => {
|
|
748
|
-
const propName = propDef.name
|
|
739
|
+
const propName = propDef.name;
|
|
749
740
|
let columnType = 'TEXT';
|
|
750
741
|
const type = propDef.type || propDef.constructor.name;
|
|
751
742
|
if (type === 'NumberProperty') {
|
|
@@ -763,7 +754,7 @@ class SQLiteAdapter extends backend_1.AbstractBackendAdapter {
|
|
|
763
754
|
});
|
|
764
755
|
// Removed columns
|
|
765
756
|
delta.removed.forEach((propDef) => {
|
|
766
|
-
const propName = propDef.name
|
|
757
|
+
const propName = propDef.name;
|
|
767
758
|
let columnType = 'TEXT';
|
|
768
759
|
const type = propDef.type || propDef.constructor.name;
|
|
769
760
|
if (type === 'NumberProperty')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quatrain/backend-sqlite",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"description": "Backend adapter for SQLite",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"author": "Quatrain Développement SAS <developers@quatrain.com>",
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@quatrain/backend": "^1.2.1",
|
|
24
|
-
"@quatrain/core": "^1.2.
|
|
24
|
+
"@quatrain/core": "^1.2.2",
|
|
25
25
|
"sqlite": "^5.1.1",
|
|
26
26
|
"sqlite3": "^5.1.7"
|
|
27
27
|
},
|
package/src/SQLiteAdapter.ts
CHANGED
|
@@ -178,7 +178,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
178
178
|
// Add columns based on dataObject properties
|
|
179
179
|
Object.entries(dataObject.properties).forEach(
|
|
180
180
|
([prop, propDef]: [prop: string, propDef: any]) => {
|
|
181
|
-
const propName = prop
|
|
181
|
+
const propName = prop
|
|
182
182
|
let columnType = 'TEXT'
|
|
183
183
|
|
|
184
184
|
// Map property types to SQLite column types
|
|
@@ -248,7 +248,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
248
248
|
|
|
249
249
|
Object.entries(data).forEach(
|
|
250
250
|
([key, value]: [key: string, value: any]) => {
|
|
251
|
-
columns.push(`"${key
|
|
251
|
+
columns.push(`"${key}"`)
|
|
252
252
|
placeholders.push('?')
|
|
253
253
|
|
|
254
254
|
// Convert arrays and objects to JSON strings
|
|
@@ -332,7 +332,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
332
332
|
propDef.constructor.name === 'ObjectProperty' &&
|
|
333
333
|
propDef.instanceOf
|
|
334
334
|
) {
|
|
335
|
-
const propValue = result[prop
|
|
335
|
+
const propValue = result[prop]
|
|
336
336
|
|
|
337
337
|
if (propValue) {
|
|
338
338
|
let refTable = undefined
|
|
@@ -361,18 +361,15 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
361
361
|
} else if (propDef.constructor.name === 'ArrayProperty' || propDef.constructor.name === 'MapProperty') {
|
|
362
362
|
// Parse JSON arrays and objects
|
|
363
363
|
try {
|
|
364
|
-
if (result[prop
|
|
365
|
-
result[prop] = JSON.parse(result[prop
|
|
364
|
+
if (result[prop]) {
|
|
365
|
+
result[prop] = JSON.parse(result[prop])
|
|
366
366
|
}
|
|
367
367
|
} catch (e) {
|
|
368
368
|
Backend.warn(`[SQLA] Failed to parse JSON for ${prop}: ${e}`)
|
|
369
369
|
}
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
|
|
373
|
-
if (prop.toLowerCase() !== prop) {
|
|
374
|
-
result[prop] = result[prop.toLowerCase()]
|
|
375
|
-
}
|
|
372
|
+
|
|
376
373
|
}
|
|
377
374
|
|
|
378
375
|
dataObject.populate(result)
|
|
@@ -415,7 +412,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
415
412
|
|
|
416
413
|
Object.entries(data).forEach(
|
|
417
414
|
([key, value]: [key: string, value: any]) => {
|
|
418
|
-
updates.push(`"${key
|
|
415
|
+
updates.push(`"${key}" = ?`)
|
|
419
416
|
|
|
420
417
|
// Convert arrays and objects to JSON strings
|
|
421
418
|
if (
|
|
@@ -556,7 +553,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
556
553
|
propDef.constructor.name === 'ObjectProperty' &&
|
|
557
554
|
propDef.instanceOf
|
|
558
555
|
) {
|
|
559
|
-
const propName = prop
|
|
556
|
+
const propName = prop
|
|
560
557
|
const joinAlias = `${propName}_table`
|
|
561
558
|
|
|
562
559
|
let table = undefined
|
|
@@ -595,7 +592,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
595
592
|
filters.forEach((filter, i) => {
|
|
596
593
|
query.push(parent && i === 0 ? 'AND' : i > 0 ? 'AND' : 'WHERE')
|
|
597
594
|
|
|
598
|
-
let realProp: any = filter.prop
|
|
595
|
+
let realProp: any = filter.prop
|
|
599
596
|
let realOperator: string = operatorsMap[filter.operator]
|
|
600
597
|
let realValue = filter.value
|
|
601
598
|
|
|
@@ -605,7 +602,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
605
602
|
const props = dataObject.getProperties(StringProperty.name)
|
|
606
603
|
Object.keys(props).forEach((rp) => {
|
|
607
604
|
keywordFilters.push(
|
|
608
|
-
`${collection.toLowerCase()}.${rp
|
|
605
|
+
`${collection.toLowerCase()}.${rp} LIKE ?`
|
|
609
606
|
)
|
|
610
607
|
params.push(`%${filter.value as string}%`)
|
|
611
608
|
})
|
|
@@ -624,7 +621,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
624
621
|
realProp = 'id'
|
|
625
622
|
} else {
|
|
626
623
|
const property = dataObject.get(filter.prop)
|
|
627
|
-
realProp = filter.prop
|
|
624
|
+
realProp = filter.prop
|
|
628
625
|
|
|
629
626
|
if (
|
|
630
627
|
property.constructor.name === 'ArrayProperty' &&
|
|
@@ -770,7 +767,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
770
767
|
pagination.sortings.forEach((sorting: Sorting, i) => {
|
|
771
768
|
query.push(i === 0 ? `ORDER BY` : ',')
|
|
772
769
|
query.push(
|
|
773
|
-
`${collection.toLowerCase()}.${sorting.prop
|
|
770
|
+
`${collection.toLowerCase()}.${sorting.prop} ${
|
|
774
771
|
sorting.order
|
|
775
772
|
}`
|
|
776
773
|
)
|
|
@@ -810,19 +807,17 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
810
807
|
for (let doc of results || []) {
|
|
811
808
|
// Process document before populating
|
|
812
809
|
Object.entries(dataObject.properties).forEach(([prop, propDef]: [prop: string, propDef: any]) => {
|
|
813
|
-
const lcProp = prop.toLowerCase()
|
|
814
|
-
|
|
815
810
|
// Handle ObjectProperty references
|
|
816
811
|
if (
|
|
817
812
|
propDef.constructor.name === 'ObjectProperty' &&
|
|
818
813
|
propDef.instanceOf
|
|
819
814
|
) {
|
|
820
|
-
const refValue = doc[
|
|
815
|
+
const refValue = doc[prop]
|
|
821
816
|
if (refValue) {
|
|
822
817
|
const info = joinTables[prop]
|
|
823
818
|
|
|
824
819
|
if (info) {
|
|
825
|
-
const label = doc[`${
|
|
820
|
+
const label = doc[`${prop}_table_name`] || ''
|
|
826
821
|
|
|
827
822
|
doc[prop] = {
|
|
828
823
|
ref: `${info.table}/${refValue}`,
|
|
@@ -852,8 +847,8 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
852
847
|
// Handle array and map properties
|
|
853
848
|
else if (propDef.constructor.name === 'ArrayProperty' || propDef.constructor.name === 'MapProperty') {
|
|
854
849
|
try {
|
|
855
|
-
if (doc[
|
|
856
|
-
doc[prop] = JSON.parse(doc[
|
|
850
|
+
if (doc[prop] && typeof doc[prop] === 'string') {
|
|
851
|
+
doc[prop] = JSON.parse(doc[prop])
|
|
857
852
|
}
|
|
858
853
|
} catch (e) {
|
|
859
854
|
Backend.warn(
|
|
@@ -861,11 +856,6 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
861
856
|
)
|
|
862
857
|
}
|
|
863
858
|
}
|
|
864
|
-
|
|
865
|
-
// Ensure property is available with original case
|
|
866
|
-
if (prop !== lcProp) {
|
|
867
|
-
doc[prop] = doc[lcProp]
|
|
868
|
-
}
|
|
869
859
|
})
|
|
870
860
|
|
|
871
861
|
// Map SQLite 'id' column back to Quatrain 'uid' property
|
|
@@ -931,7 +921,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
931
921
|
let query = `CREATE TABLE IF NOT EXISTS "${collection.toLowerCase()}" (\n id TEXT PRIMARY KEY`
|
|
932
922
|
|
|
933
923
|
properties.forEach((propDef: any) => {
|
|
934
|
-
const propName = propDef.name
|
|
924
|
+
const propName = propDef.name
|
|
935
925
|
let columnType = 'TEXT'
|
|
936
926
|
|
|
937
927
|
const type = propDef.type || propDef.constructor.name
|
|
@@ -967,7 +957,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
967
957
|
|
|
968
958
|
// Added columns
|
|
969
959
|
delta.added.forEach((propDef: any) => {
|
|
970
|
-
const propName = propDef.name
|
|
960
|
+
const propName = propDef.name
|
|
971
961
|
let columnType = 'TEXT'
|
|
972
962
|
|
|
973
963
|
const type = propDef.type || propDef.constructor.name
|
|
@@ -986,7 +976,7 @@ export class SQLiteAdapter extends AbstractBackendAdapter {
|
|
|
986
976
|
|
|
987
977
|
// Removed columns
|
|
988
978
|
delta.removed.forEach((propDef: any) => {
|
|
989
|
-
const propName = propDef.name
|
|
979
|
+
const propName = propDef.name
|
|
990
980
|
let columnType = 'TEXT'
|
|
991
981
|
|
|
992
982
|
const type = propDef.type || propDef.constructor.name
|