sedentary 0.0.54 → 0.1.1
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 +47 -28
- package/dist/cjs/db.js +19 -14
- package/dist/cjs/index.js +141 -89
- package/dist/cjs/package.json +1 -0
- package/dist/es/db.js +16 -11
- package/dist/es/index.js +140 -89
- package/dist/types/db.d.ts +27 -23
- package/dist/types/index.d.ts +55 -37
- package/package.json +8 -31
package/dist/es/db.js
CHANGED
|
@@ -26,19 +26,22 @@ export class EntryBase {
|
|
|
26
26
|
preLoad() { }
|
|
27
27
|
preRemove() { }
|
|
28
28
|
preSave() { }
|
|
29
|
-
|
|
30
|
-
return false;
|
|
29
|
+
remove() {
|
|
30
|
+
return Promise.resolve(false);
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
return false;
|
|
32
|
+
save() {
|
|
33
|
+
return Promise.resolve(false);
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
36
37
|
export class Type {
|
|
37
38
|
constructor(from) {
|
|
38
39
|
Object.assign(this, from);
|
|
39
40
|
}
|
|
40
41
|
}
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
41
43
|
export class Attribute extends Type {
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
42
45
|
constructor(from) {
|
|
43
46
|
super(from);
|
|
44
47
|
}
|
|
@@ -54,10 +57,10 @@ export class Table extends autoImplement() {
|
|
|
54
57
|
autoIncrementOwn;
|
|
55
58
|
oid;
|
|
56
59
|
findAttribute(name) {
|
|
57
|
-
return this.attributes.
|
|
60
|
+
return this.attributes.find(_ => _.attributeName === name);
|
|
58
61
|
}
|
|
59
62
|
findField(name) {
|
|
60
|
-
return this.attributes.
|
|
63
|
+
return this.attributes.find(_ => _.fieldName === name);
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
66
|
export class DB {
|
|
@@ -68,12 +71,12 @@ export class DB {
|
|
|
68
71
|
this.log = log;
|
|
69
72
|
}
|
|
70
73
|
findTable(name) {
|
|
71
|
-
return this.tables.
|
|
74
|
+
return this.tables.find(_ => _.tableName === name);
|
|
72
75
|
}
|
|
73
76
|
indexesEq(a, b) {
|
|
74
77
|
if (a.fields.length !== b.fields.length)
|
|
75
78
|
return false;
|
|
76
|
-
for (
|
|
79
|
+
for (let i = 0; i < a.fields.length; ++i)
|
|
77
80
|
if (a.fields[i] !== b.fields[i])
|
|
78
81
|
return false;
|
|
79
82
|
if (a.type !== b.type)
|
|
@@ -96,7 +99,7 @@ export class DB {
|
|
|
96
99
|
}
|
|
97
100
|
}
|
|
98
101
|
syncLog(message) {
|
|
99
|
-
this.log(this.sync ? message :
|
|
102
|
+
this.log(this.sync ? message : `NOT SYNCING: ${message}`);
|
|
100
103
|
}
|
|
101
104
|
}
|
|
102
105
|
export class Transaction {
|
|
@@ -117,12 +120,13 @@ export class Transaction {
|
|
|
117
120
|
}
|
|
118
121
|
this.entries = [];
|
|
119
122
|
}
|
|
120
|
-
|
|
123
|
+
commit() {
|
|
121
124
|
const { entries } = this;
|
|
122
125
|
for (const entry of entries)
|
|
123
126
|
if (entry[actions])
|
|
124
127
|
entry.postCommit(entry[actions]);
|
|
125
128
|
this.clean();
|
|
129
|
+
return Promise.resolve();
|
|
126
130
|
}
|
|
127
131
|
preCommit() {
|
|
128
132
|
const { entries } = this;
|
|
@@ -130,8 +134,9 @@ export class Transaction {
|
|
|
130
134
|
if (entry[actions])
|
|
131
135
|
entry.preCommit(entry[actions]);
|
|
132
136
|
}
|
|
133
|
-
|
|
137
|
+
rollback() {
|
|
134
138
|
this.clean();
|
|
139
|
+
return Promise.resolve();
|
|
135
140
|
}
|
|
136
141
|
}
|
|
137
142
|
const sortedEntries = (obj) => Object.entries(obj).sort((entryA, entryB) => (entryA[0] > entryB[0] ? -1 : 1));
|
package/dist/es/index.js
CHANGED
|
@@ -5,9 +5,53 @@ const methods = Symbol("methods");
|
|
|
5
5
|
const operators = ["=", ">", "<", ">=", "<=", "<>", "IN", "IS NULL", "LIKE", "NOT"];
|
|
6
6
|
const allowedOption = ["indexes", "int8id", "parent", "primaryKey", "sync", "tableName"];
|
|
7
7
|
const reservedNames = [
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
"attr2field",
|
|
9
|
+
"attributeName",
|
|
10
|
+
"cancel",
|
|
11
|
+
"class",
|
|
12
|
+
"construct",
|
|
13
|
+
"constructor",
|
|
14
|
+
"defaultValue",
|
|
15
|
+
"fieldName",
|
|
16
|
+
"foreignKeys",
|
|
17
|
+
"load",
|
|
18
|
+
"modelName",
|
|
19
|
+
"name",
|
|
20
|
+
"postCommit",
|
|
21
|
+
"postLoad",
|
|
22
|
+
"postRemove",
|
|
23
|
+
"postSave",
|
|
24
|
+
"preCommit",
|
|
25
|
+
"preLoad",
|
|
26
|
+
"preRemove",
|
|
27
|
+
"preSave",
|
|
28
|
+
"primaryKey",
|
|
29
|
+
"prototype",
|
|
30
|
+
"remove",
|
|
31
|
+
"save",
|
|
32
|
+
"tableName",
|
|
33
|
+
"type",
|
|
34
|
+
"unique"
|
|
10
35
|
];
|
|
36
|
+
/** Model and attribute names: ASCII letters, digits, underscore; cannot start with digit. */
|
|
37
|
+
const reModelAttributeName = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
|
|
38
|
+
/** tableName and fieldName: ASCII lowercase letters, digits, underscore; cannot start with digit. */
|
|
39
|
+
const reSqlName = /^[a-z_][a-z0-9_]*$/;
|
|
40
|
+
/**
|
|
41
|
+
* Converts a JavaScript name to the default SQL name (snake_case).
|
|
42
|
+
* Uppercase letters become lowercase preceded by underscore, except the first character
|
|
43
|
+
* which is only lowercased without underscore.
|
|
44
|
+
*/
|
|
45
|
+
export function toSqlName(name) {
|
|
46
|
+
if (typeof name !== "string" || name.length === 0)
|
|
47
|
+
throw new Error("toSqlName: 'name' must be a non-empty string");
|
|
48
|
+
let result = name[0].toLowerCase();
|
|
49
|
+
for (let i = 1; i < name.length; i++) {
|
|
50
|
+
const c = name[i];
|
|
51
|
+
result += c >= "A" && c <= "Z" ? `_${c.toLowerCase()}` : c;
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
11
55
|
export class Sedentary {
|
|
12
56
|
autoSync;
|
|
13
57
|
db;
|
|
@@ -35,46 +79,56 @@ export class Sedentary {
|
|
|
35
79
|
this.log = log ? log : log === null ? () => { } : console.log;
|
|
36
80
|
this.doSync = sync;
|
|
37
81
|
}
|
|
38
|
-
Boolean() {
|
|
39
|
-
return new Type({ [base]: Boolean, type: "BOOLEAN" });
|
|
82
|
+
Boolean(options) {
|
|
83
|
+
return new Type({ ...options, [base]: Boolean, type: "BOOLEAN" });
|
|
40
84
|
}
|
|
41
|
-
DateTime() {
|
|
42
|
-
return new Type({ [base]: Date, type: "DATETIME" });
|
|
85
|
+
DateTime(options) {
|
|
86
|
+
return new Type({ ...options, [base]: Date, type: "DATETIME" });
|
|
43
87
|
}
|
|
44
88
|
FKey(attribute, options) {
|
|
45
|
-
const { attributeName, fieldName, tableName, type, [base]: _base, [size]: _size } = attribute;
|
|
89
|
+
const { attributeName, fieldName, modelName, tableName, type, unique, [base]: _base, [size]: _size } = attribute;
|
|
90
|
+
if (!unique)
|
|
91
|
+
throw new Error(`Sedentary.FKey: '${modelName}' model: '${attributeName}' attribute: is not unique: can't be used as FKey target`);
|
|
46
92
|
return new Type({ [base]: _base, foreignKey: { attributeName, fieldName, options, tableName }, [size]: _size, type });
|
|
47
93
|
}
|
|
48
|
-
Float(
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
94
|
+
Float(options) {
|
|
95
|
+
const sizeFloat = "Sedentary.Float: 'size' argument: Wrong value, expected 4 or 8";
|
|
96
|
+
let storageSize;
|
|
97
|
+
let rest;
|
|
98
|
+
[storageSize, rest] = this.checkSize(sizeFloat, options);
|
|
99
|
+
if (storageSize === undefined)
|
|
100
|
+
storageSize = 8;
|
|
101
|
+
if (storageSize !== 4 && storageSize !== 8)
|
|
102
|
+
throw new Error(sizeFloat);
|
|
103
|
+
return new Type({ ...rest, [base]: Number, [size]: storageSize, type: "FLOAT" });
|
|
54
104
|
}
|
|
55
|
-
Int(
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
105
|
+
Int(options) {
|
|
106
|
+
const sizeInt = "Sedentary.Int: 'size' argument: Wrong value, expected 2 or 4";
|
|
107
|
+
let storageSize;
|
|
108
|
+
let rest;
|
|
109
|
+
[storageSize, rest] = this.checkSize(sizeInt, options);
|
|
110
|
+
if (storageSize === undefined)
|
|
111
|
+
storageSize = 4;
|
|
112
|
+
if (storageSize !== 2 && storageSize !== 4)
|
|
113
|
+
throw new Error(sizeInt);
|
|
114
|
+
return new Type({ ...rest, [base]: Number, [size]: storageSize, type: "INT" });
|
|
61
115
|
}
|
|
62
|
-
Int8() {
|
|
63
|
-
return new Type({ [base]: BigInt, [size]: 8, type: "INT8" });
|
|
116
|
+
Int8(options) {
|
|
117
|
+
return new Type({ ...options, [base]: BigInt, [size]: 8, type: "INT8" });
|
|
64
118
|
}
|
|
65
|
-
JSON() {
|
|
66
|
-
return new Type({ [base]: Object, type: "JSON" });
|
|
119
|
+
JSON(options) {
|
|
120
|
+
return new Type({ ...options, [base]: Object, type: "JSON" });
|
|
67
121
|
}
|
|
68
|
-
Number() {
|
|
69
|
-
return new Type({ [base]: Number, type: "NUMBER" });
|
|
122
|
+
Number(options) {
|
|
123
|
+
return new Type({ ...options, [base]: Number, type: "NUMBER" });
|
|
70
124
|
}
|
|
71
|
-
None() {
|
|
72
|
-
return new Type({ [base]: undefined, type: "NONE" });
|
|
125
|
+
None(options) {
|
|
126
|
+
return new Type({ ...options, [base]: undefined, type: "NONE" });
|
|
73
127
|
}
|
|
74
|
-
VarChar(
|
|
128
|
+
VarChar(options) {
|
|
75
129
|
const message = "Sedentary.VarChar: 'size' argument: Wrong value, expected positive integer";
|
|
76
|
-
|
|
77
|
-
return new Type({ [base]: String, [size]:
|
|
130
|
+
const [maxSize, rest] = this.checkSize(message, options);
|
|
131
|
+
return new Type({ ...rest, [base]: String, [size]: maxSize, type: "VARCHAR" });
|
|
78
132
|
}
|
|
79
133
|
checkDB() {
|
|
80
134
|
if (!this.db)
|
|
@@ -103,12 +157,19 @@ export class Sedentary {
|
|
|
103
157
|
}
|
|
104
158
|
return true;
|
|
105
159
|
}
|
|
106
|
-
checkSize(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
160
|
+
checkSize(message, options) {
|
|
161
|
+
if (!options)
|
|
162
|
+
return [undefined, {}];
|
|
163
|
+
const { size, ...rest } = options;
|
|
164
|
+
if (size === undefined)
|
|
165
|
+
return [undefined, rest];
|
|
166
|
+
if (typeof size !== "number")
|
|
110
167
|
throw new Error(message);
|
|
111
|
-
|
|
168
|
+
if (size !== parseInt(size.toString(), 10))
|
|
169
|
+
throw new Error(message);
|
|
170
|
+
if (size <= 0)
|
|
171
|
+
throw new Error(message);
|
|
172
|
+
return [size, rest];
|
|
112
173
|
}
|
|
113
174
|
createWhere(modelName, attributes, where) {
|
|
114
175
|
if (typeof where === "string")
|
|
@@ -189,9 +250,9 @@ export class Sedentary {
|
|
|
189
250
|
if (this.autoSync || sync)
|
|
190
251
|
await this.sync();
|
|
191
252
|
}
|
|
192
|
-
catch (
|
|
193
|
-
this.log(
|
|
194
|
-
throw
|
|
253
|
+
catch (error) {
|
|
254
|
+
this.log(`Connecting: ${error instanceof Error ? error.message : JSON.stringify(error)}`);
|
|
255
|
+
throw error;
|
|
195
256
|
}
|
|
196
257
|
}
|
|
197
258
|
async sync() {
|
|
@@ -215,6 +276,8 @@ export class Sedentary {
|
|
|
215
276
|
this.checkDB();
|
|
216
277
|
if (typeof modelName !== "string")
|
|
217
278
|
throw new Error("Sedentary.model: 'name' argument: Wrong type, expected 'string'");
|
|
279
|
+
if (!reModelAttributeName.test(modelName))
|
|
280
|
+
throw new Error(`Sedentary.model: '${modelName}' model: Invalid model name, expected ASCII letters, digits or underscore, cannot start with digit`);
|
|
218
281
|
if (this.models[modelName])
|
|
219
282
|
throw new Error(`Sedentary.model: '${modelName}' model: Model already defined`);
|
|
220
283
|
if (!_attributes)
|
|
@@ -235,10 +298,12 @@ export class Sedentary {
|
|
|
235
298
|
if (options.parent && options.primaryKey)
|
|
236
299
|
throw new Error(`Sedentary.model: '${modelName}' model: 'parent' and 'primaryKey' options conflict each other`);
|
|
237
300
|
let autoIncrement = true;
|
|
238
|
-
const { indexes, int8id, parent, primaryKey, sync, tableName } = { sync: this.doSync, tableName: modelName, ...options };
|
|
301
|
+
const { indexes, int8id, parent, primaryKey, sync, tableName } = { sync: this.doSync, tableName: toSqlName(modelName), ...options };
|
|
302
|
+
if (!reSqlName.test(tableName))
|
|
303
|
+
throw new Error(`Sedentary.model: '${modelName}' model: Invalid tableName '${tableName}', expected lowercase ASCII letters, digits or underscore, cannot start with digit`);
|
|
239
304
|
let aArray = int8id
|
|
240
|
-
? [new Attribute({ ...this.Int8(), attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true })]
|
|
241
|
-
: [new Attribute({ ...this.Int(4), attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true })];
|
|
305
|
+
? [new Attribute({ ...this.Int8(), attributeName: "id", fieldName: toSqlName("id"), modelName, notNull: true, tableName, unique: true })]
|
|
306
|
+
: [new Attribute({ ...this.Int({ size: 4 }), attributeName: "id", fieldName: toSqlName("id"), modelName, notNull: true, tableName, unique: true })];
|
|
242
307
|
let constraints = [{ attribute: aArray[0], constraintName: `${tableName}_id_unique`, type: "u" }];
|
|
243
308
|
const iArray = [];
|
|
244
309
|
let pk = aArray[0];
|
|
@@ -262,51 +327,37 @@ export class Sedentary {
|
|
|
262
327
|
constraints = [];
|
|
263
328
|
}
|
|
264
329
|
for (const attributeName of Object.keys(_attributes).sort()) {
|
|
330
|
+
if (!reModelAttributeName.test(attributeName))
|
|
331
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Invalid attribute name, expected ASCII letters, digits or underscore, cannot start with digit`);
|
|
265
332
|
if (reservedNames.includes(attributeName))
|
|
266
333
|
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Reserved name`);
|
|
267
|
-
const call = (defaultValue, fieldName, notNull, unique, func, message1, message2) => {
|
|
268
|
-
if (func === this.FKey)
|
|
269
|
-
throw new Error(`${message1} 'this.FKey' can't be used directly`);
|
|
270
|
-
if (![this.Boolean, this.DateTime, this.Float, this.Int, this.JSON, this.Int8, this.None, this.Number, this.VarChar].includes(func))
|
|
271
|
-
throw new Error(`${message1} ${message2}`);
|
|
272
|
-
return new Attribute({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique, ...func() });
|
|
273
|
-
};
|
|
274
334
|
const attributeDefinition = _attributes[attributeName];
|
|
275
335
|
let { [base]: _base, defaultValue, fieldName, foreignKey, notNull, [size]: _size, type, unique } = (() => {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if (type instanceof Type)
|
|
296
|
-
return new Attribute({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique, ...type });
|
|
297
|
-
if (type instanceof Function)
|
|
298
|
-
return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option:`, "Wrong type, expected 'Type'");
|
|
299
|
-
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option: Wrong type, expected 'Type'`);
|
|
300
|
-
})();
|
|
301
|
-
const { [base]: _base, defaultValue } = ret;
|
|
302
|
-
if (defaultValue !== undefined) {
|
|
303
|
-
if (_base === BigInt && typeof defaultValue !== "bigint")
|
|
336
|
+
if (!(attributeDefinition instanceof Type))
|
|
337
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: '${attributeName}': Wrong type, expected 'Type'`);
|
|
338
|
+
const ret = new Attribute({ attributeName, fieldName: toSqlName(attributeName), modelName, notNull: false, tableName, unique: false, ...attributeDefinition });
|
|
339
|
+
const { defaultValue, fieldName, notNull, unique } = ret;
|
|
340
|
+
if (defaultValue === null)
|
|
341
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really make sense?`);
|
|
342
|
+
if (typeof fieldName !== "string")
|
|
343
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
|
|
344
|
+
if (!reSqlName.test(fieldName)) {
|
|
345
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Invalid fieldName '${fieldName}', ` +
|
|
346
|
+
"expected lowercase ASCII letters, digits or underscore, cannot start with digit");
|
|
347
|
+
}
|
|
348
|
+
if (typeof notNull !== "boolean")
|
|
349
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
|
|
350
|
+
if (typeof unique !== "boolean")
|
|
351
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
|
|
352
|
+
const { [base]: _base, defaultValue: _defaultValue } = ret;
|
|
353
|
+
if (_defaultValue !== undefined) {
|
|
354
|
+
if (_base === BigInt && typeof _defaultValue !== "bigint")
|
|
304
355
|
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'BigInt'`);
|
|
305
|
-
if (_base === Date && !(
|
|
356
|
+
if (_base === Date && !(_defaultValue instanceof Date))
|
|
306
357
|
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'Date'`);
|
|
307
|
-
if (_base === Number && typeof
|
|
358
|
+
if (_base === Number && typeof _defaultValue !== "number")
|
|
308
359
|
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'number'`);
|
|
309
|
-
if (_base === String && typeof
|
|
360
|
+
if (_base === String && typeof _defaultValue !== "string")
|
|
310
361
|
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'string'`);
|
|
311
362
|
}
|
|
312
363
|
return ret;
|
|
@@ -405,9 +456,9 @@ export class Sedentary {
|
|
|
405
456
|
return ret;
|
|
406
457
|
}, {});
|
|
407
458
|
for (const foreignKey in foreignKeys) {
|
|
408
|
-
if (foreignKey
|
|
459
|
+
if (`${foreignKey}Load` in _attributes)
|
|
409
460
|
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute`);
|
|
410
|
-
if (foreignKey
|
|
461
|
+
if (`${foreignKey}Load` in _methods)
|
|
411
462
|
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method`);
|
|
412
463
|
}
|
|
413
464
|
for (const method in _methods)
|
|
@@ -422,20 +473,20 @@ export class Sedentary {
|
|
|
422
473
|
if (attribute in parent[methods])
|
|
423
474
|
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with a method of '${parent.modelName}' model`);
|
|
424
475
|
for (const foreignKey in parent.foreignKeys)
|
|
425
|
-
if (attribute === foreignKey
|
|
476
|
+
if (attribute === `${foreignKey}Load`)
|
|
426
477
|
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an inferred methods of '${parent.modelName}' model`);
|
|
427
478
|
}
|
|
428
479
|
for (const foreignKey in foreignKeys) {
|
|
429
|
-
if (foreignKey
|
|
480
|
+
if (`${foreignKey}Load` in parent[attributes])
|
|
430
481
|
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute of '${parent.modelName}' model`);
|
|
431
|
-
if (foreignKey
|
|
482
|
+
if (`${foreignKey}Load` in parent[methods])
|
|
432
483
|
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method of '${parent.modelName}' model`);
|
|
433
484
|
}
|
|
434
485
|
for (const method in _methods) {
|
|
435
486
|
if (method in parent[attributes])
|
|
436
487
|
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute of '${parent.modelName}' model`);
|
|
437
488
|
for (const foreignKey in parent.foreignKeys)
|
|
438
|
-
if (foreignKey
|
|
489
|
+
if (`${foreignKey}Load` === method)
|
|
439
490
|
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an inferred methods of '${parent.modelName}' model`);
|
|
440
491
|
}
|
|
441
492
|
checkParent(parent.parent);
|
|
@@ -452,7 +503,7 @@ export class Sedentary {
|
|
|
452
503
|
this.db.tables.push(table);
|
|
453
504
|
const cancel_ = this.db.cancel(tableName);
|
|
454
505
|
const cancel = (where, tx) => cancel_(this.createWhere(modelName, attr2field, where)[0], tx);
|
|
455
|
-
Object.defineProperty(cancel, "name", { value: modelName
|
|
506
|
+
Object.defineProperty(cancel, "name", { value: `${modelName}.cancel` });
|
|
456
507
|
const load_ = this.db.load(tableName, attr2field, pk, ret, table);
|
|
457
508
|
const load = (where, ...args) => {
|
|
458
509
|
let order = undefined;
|
|
@@ -489,7 +540,7 @@ export class Sedentary {
|
|
|
489
540
|
throw new Error(`${modelName}.load: 'tx' argument: Wrong type, expected 'Transaction'`);
|
|
490
541
|
return load_(this.createWhere(modelName, attr2field, where)[0], order, limit, tx, lock);
|
|
491
542
|
};
|
|
492
|
-
Object.defineProperty(load, "name", { value: modelName
|
|
543
|
+
Object.defineProperty(load, "name", { value: `${modelName}.load` });
|
|
493
544
|
Object.defineProperty(ret, "cancel", { value: cancel });
|
|
494
545
|
Object.defineProperty(ret, "name", { value: modelName });
|
|
495
546
|
Object.defineProperty(ret, "load", { value: load });
|
|
@@ -514,7 +565,7 @@ export class Sedentary {
|
|
|
514
565
|
ensureActions(this).push({ action: "remove", records });
|
|
515
566
|
return records;
|
|
516
567
|
};
|
|
517
|
-
Object.defineProperty(ret.prototype.remove, "name", { value: modelName
|
|
568
|
+
Object.defineProperty(ret.prototype.remove, "name", { value: `${modelName}.remove` });
|
|
518
569
|
const save = this.db.save(tableName, attr2field, pk);
|
|
519
570
|
ret.prototype.save = async function () {
|
|
520
571
|
this.preSave();
|
|
@@ -524,7 +575,7 @@ export class Sedentary {
|
|
|
524
575
|
ensureActions(this).push({ action: "save", records });
|
|
525
576
|
return records;
|
|
526
577
|
};
|
|
527
|
-
Object.defineProperty(ret.prototype.save, "name", { value: modelName
|
|
578
|
+
Object.defineProperty(ret.prototype.save, "name", { value: `${modelName}.save` });
|
|
528
579
|
for (const attribute of aArray)
|
|
529
580
|
Object.defineProperty(ret, attribute.attributeName, { value: attribute });
|
|
530
581
|
for (const key of ["attributeName", base, "fieldName", "modelName", size, "tableName", "type", "unique"])
|
package/dist/types/db.d.ts
CHANGED
|
@@ -3,33 +3,37 @@ export declare const base: unique symbol;
|
|
|
3
3
|
export declare const loaded: unique symbol;
|
|
4
4
|
export declare const size: unique symbol;
|
|
5
5
|
export declare const transaction: unique symbol;
|
|
6
|
-
export
|
|
7
|
-
action: "remove"
|
|
6
|
+
export type TxAction = {
|
|
7
|
+
action: "remove";
|
|
8
|
+
records: number;
|
|
9
|
+
} | {
|
|
10
|
+
action: "save";
|
|
8
11
|
records: number | false;
|
|
9
|
-
}
|
|
12
|
+
};
|
|
10
13
|
export declare class EntryBase {
|
|
11
14
|
constructor(from?: Partial<EntryBase>);
|
|
12
15
|
construct(): void;
|
|
13
|
-
postCommit(actions:
|
|
16
|
+
postCommit(actions: TxAction[]): void;
|
|
14
17
|
postLoad(): void;
|
|
15
18
|
postRemove(deletedRecords: number): void;
|
|
16
19
|
postSave(savedRecords: number | false): void;
|
|
17
|
-
preCommit(actions:
|
|
20
|
+
preCommit(actions: TxAction[]): void;
|
|
18
21
|
preLoad(): void;
|
|
19
22
|
preRemove(): void;
|
|
20
23
|
preSave(): void;
|
|
21
24
|
remove(): Promise<boolean>;
|
|
22
|
-
save(): Promise<
|
|
25
|
+
save(): Promise<number | false>;
|
|
23
26
|
}
|
|
24
27
|
export type ForeignKeyActions = "cascade" | "no action" | "restrict" | "set default" | "set null";
|
|
25
28
|
export interface ForeignKeyOptions {
|
|
26
29
|
onDelete?: ForeignKeyActions;
|
|
27
30
|
onUpdate?: ForeignKeyActions;
|
|
28
31
|
}
|
|
29
|
-
export interface Type<T, E> {
|
|
32
|
+
export interface Type<T, N extends boolean, E> {
|
|
30
33
|
[base]: unknown;
|
|
31
34
|
entry?: E;
|
|
32
35
|
native?: T;
|
|
36
|
+
notNull?: N;
|
|
33
37
|
[size]?: number;
|
|
34
38
|
type: string;
|
|
35
39
|
foreignKey?: {
|
|
@@ -39,23 +43,23 @@ export interface Type<T, E> {
|
|
|
39
43
|
tableName: string;
|
|
40
44
|
};
|
|
41
45
|
}
|
|
42
|
-
export declare class Type<T, E> {
|
|
43
|
-
constructor(from: Type<T, E>);
|
|
46
|
+
export declare class Type<T, N extends boolean, E> {
|
|
47
|
+
constructor(from: Type<T, N, E>);
|
|
44
48
|
}
|
|
45
|
-
export interface Attribute<T, E> extends Type<T, E> {
|
|
49
|
+
export interface Attribute<T, N extends boolean, E> extends Type<T, N, E> {
|
|
46
50
|
attributeName: string;
|
|
47
51
|
defaultValue?: unknown;
|
|
48
52
|
fieldName: string;
|
|
49
53
|
modelName: string;
|
|
50
|
-
notNull:
|
|
54
|
+
notNull: N;
|
|
51
55
|
tableName: string;
|
|
52
56
|
unique?: boolean;
|
|
53
57
|
}
|
|
54
|
-
export declare class Attribute<T, E> extends Type<T, E> {
|
|
55
|
-
constructor(from: Attribute<T, E>);
|
|
58
|
+
export declare class Attribute<T, N extends boolean, E> extends Type<T, N, E> {
|
|
59
|
+
constructor(from: Attribute<T, N, E>);
|
|
56
60
|
}
|
|
57
61
|
export interface Constraint {
|
|
58
|
-
attribute: Attribute<unknown, unknown>;
|
|
62
|
+
attribute: Attribute<unknown, boolean, unknown>;
|
|
59
63
|
constraintName: string;
|
|
60
64
|
type: "f" | "u";
|
|
61
65
|
}
|
|
@@ -66,15 +70,15 @@ export interface Index {
|
|
|
66
70
|
unique: boolean;
|
|
67
71
|
}
|
|
68
72
|
interface ITable {
|
|
69
|
-
attributes: Attribute<unknown, unknown>[];
|
|
73
|
+
attributes: Attribute<unknown, boolean, unknown>[];
|
|
70
74
|
autoIncrement: boolean;
|
|
71
75
|
constraints: Constraint[];
|
|
72
76
|
indexes: Index[];
|
|
73
77
|
model: {
|
|
74
|
-
load: (where: any, order?:
|
|
78
|
+
load: (where: any, order?: any, tx?: Transaction) => Promise<EntryBase[]>;
|
|
75
79
|
};
|
|
76
|
-
parent?: Attribute<unknown, unknown>;
|
|
77
|
-
pk: Attribute<unknown, unknown>;
|
|
80
|
+
parent?: Attribute<unknown, boolean, unknown>;
|
|
81
|
+
pk: Attribute<unknown, boolean, unknown>;
|
|
78
82
|
sync: boolean;
|
|
79
83
|
tableName: string;
|
|
80
84
|
}
|
|
@@ -82,8 +86,8 @@ declare const Table_base: new (defaults?: ITable | undefined) => ITable;
|
|
|
82
86
|
export declare class Table extends Table_base {
|
|
83
87
|
autoIncrementOwn?: boolean;
|
|
84
88
|
oid?: number;
|
|
85
|
-
findAttribute(name: string): Attribute<unknown, unknown>;
|
|
86
|
-
findField(name: string): Attribute<unknown, unknown>;
|
|
89
|
+
findAttribute(name: string): Attribute<unknown, boolean, unknown>;
|
|
90
|
+
findField(name: string): Attribute<unknown, boolean, unknown>;
|
|
87
91
|
}
|
|
88
92
|
export declare abstract class DB<T extends Transaction> {
|
|
89
93
|
tables: Table[];
|
|
@@ -99,9 +103,9 @@ export declare abstract class DB<T extends Transaction> {
|
|
|
99
103
|
abstract begin(): Promise<T>;
|
|
100
104
|
abstract cancel(tableName: string): (where: string, tx?: Transaction) => Promise<number>;
|
|
101
105
|
abstract escape(value: unknown): string;
|
|
102
|
-
abstract load(tableName: string, attributes: Record<string, string>, pk: Attribute<unknown, unknown>, model: new () => EntryBase, table: Table): (where: string, order?: string | string[], limit?: number, tx?: Transaction, lock?: boolean) => Promise<EntryBase[]>;
|
|
103
|
-
abstract remove(tableName: string, pk: Attribute<unknown, unknown>): (this: EntryBase & Record<string, unknown>) => Promise<number>;
|
|
104
|
-
abstract save(tableName: string, attr2field: Record<string, string>, pk: Attribute<unknown, unknown>): (this: EntryBase & Record<string, unknown>) => Promise<number | false>;
|
|
106
|
+
abstract load(tableName: string, attributes: Record<string, string>, pk: Attribute<unknown, boolean, unknown>, model: new () => EntryBase, table: Table): (where: string, order?: string | string[], limit?: number, tx?: Transaction, lock?: boolean) => Promise<EntryBase[]>;
|
|
107
|
+
abstract remove(tableName: string, pk: Attribute<unknown, boolean, unknown>): (this: EntryBase & Record<string, unknown>) => Promise<number>;
|
|
108
|
+
abstract save(tableName: string, attr2field: Record<string, string>, pk: Attribute<unknown, boolean, unknown>): (this: EntryBase & Record<string, unknown>) => Promise<number | false>;
|
|
105
109
|
abstract dropConstraints(table: Table): Promise<number[]>;
|
|
106
110
|
abstract dropFields(table: Table): Promise<void>;
|
|
107
111
|
abstract dropIndexes(table: Table, constraintIndexes: number[]): Promise<void>;
|