sedentary 0.0.16 → 0.0.20
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 +0 -4
- package/index.d.ts +63 -65
- package/index.js +149 -172
- package/lib/db.d.ts +22 -18
- package/lib/db.js +11 -14
- package/lib/minidb.js +77 -53
- package/lib/transaction.d.ts +2 -0
- package/lib/transaction.js +6 -0
- package/package.json +25 -7
- package/utils.d.ts +1 -0
- package/utils.js +130 -0
- package/lib/log.d.ts +0 -4
- package/lib/log.js +0 -20
- package/lib/log.ts +0 -22
package/index.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Package = exports.Sedentary = exports.Type = exports.
|
|
3
|
+
exports.Package = exports.Sedentary = exports.Type = exports.EntryBase = void 0;
|
|
4
4
|
const db_1 = require("./lib/db");
|
|
5
|
-
const log_1 = require("./lib/log");
|
|
6
5
|
const minidb_1 = require("./lib/minidb");
|
|
7
6
|
var db_2 = require("./lib/db");
|
|
8
|
-
Object.defineProperty(exports, "
|
|
7
|
+
Object.defineProperty(exports, "EntryBase", { enumerable: true, get: function () { return db_2.EntryBase; } });
|
|
9
8
|
Object.defineProperty(exports, "Type", { enumerable: true, get: function () { return db_2.Type; } });
|
|
10
|
-
const allowedOption = ["indexes", "
|
|
9
|
+
const allowedOption = ["indexes", "int8id", "parent", "primaryKey", "sync", "tableName"];
|
|
11
10
|
const reservedNames = [
|
|
12
|
-
...["attributeName", "base", "class", "constructor", "defaultValue", "entry", "fieldName", "
|
|
13
|
-
...["
|
|
11
|
+
...["attributeName", "attributes", "base", "class", "construct", "constructor", "defaultValue", "entry", "fieldName", "foreignKeys", "load"],
|
|
12
|
+
...["methods", "name", "postLoad", "postSave", "preLoad", "preSave", "primaryKey", "prototype", "save", "size", "tableName", "type"]
|
|
14
13
|
];
|
|
15
14
|
class Sedentary {
|
|
16
15
|
constructor(filename, options) {
|
|
@@ -30,16 +29,17 @@ class Sedentary {
|
|
|
30
29
|
throw new Error("new Sedentary: 'log' option: Wrong type, expected 'null' or 'Function'");
|
|
31
30
|
if (typeof sync !== "boolean")
|
|
32
31
|
throw new Error("new Sedentary: 'sync' option: Wrong type, expected 'boolean'");
|
|
33
|
-
|
|
32
|
+
// eslint-disable-next-line no-console
|
|
33
|
+
this.log = log ? log : log === null ? () => { } : console.log;
|
|
34
34
|
this.db = new minidb_1.MiniDB(filename, this.log);
|
|
35
35
|
this.sync = sync;
|
|
36
36
|
}
|
|
37
37
|
DATETIME() {
|
|
38
38
|
return new db_1.Type({ base: Date, type: "DATETIME" });
|
|
39
39
|
}
|
|
40
|
-
FKEY(attribute) {
|
|
40
|
+
FKEY(attribute, options) {
|
|
41
41
|
const { attributeName, base, fieldName, size, tableName, type } = attribute;
|
|
42
|
-
return new db_1.Type({ base, foreignKey: { attributeName, fieldName, tableName }, size, type });
|
|
42
|
+
return new db_1.Type({ base, foreignKey: { attributeName, fieldName, options, tableName }, size, type });
|
|
43
43
|
}
|
|
44
44
|
INT(size) {
|
|
45
45
|
const message = "Sedentary.INT: 'size' argument: Wrong value, expected 2 or 4";
|
|
@@ -56,6 +56,13 @@ class Sedentary {
|
|
|
56
56
|
size = size ? this.checkSize(size, message) : undefined;
|
|
57
57
|
return new db_1.Type({ base: String, size, type: "VARCHAR" });
|
|
58
58
|
}
|
|
59
|
+
checkSize(size, message) {
|
|
60
|
+
const str = size.toString();
|
|
61
|
+
const parsed = parseInt(str, 10);
|
|
62
|
+
if (str !== parsed.toString())
|
|
63
|
+
throw new Error(message);
|
|
64
|
+
return parsed;
|
|
65
|
+
}
|
|
59
66
|
async connect() {
|
|
60
67
|
try {
|
|
61
68
|
this.log("Connecting...");
|
|
@@ -65,7 +72,7 @@ class Sedentary {
|
|
|
65
72
|
this.log("Synced");
|
|
66
73
|
}
|
|
67
74
|
catch (e) {
|
|
68
|
-
this.log("Connecting:"
|
|
75
|
+
this.log("Connecting: " + (e instanceof Error ? e.message : JSON.stringify(e)));
|
|
69
76
|
throw e;
|
|
70
77
|
}
|
|
71
78
|
}
|
|
@@ -74,113 +81,125 @@ class Sedentary {
|
|
|
74
81
|
await this.db.end();
|
|
75
82
|
this.log("Connection closed");
|
|
76
83
|
}
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
85
|
+
model(modelName, attributes, options, methods) {
|
|
86
|
+
if (typeof modelName !== "string")
|
|
79
87
|
throw new Error("Sedentary.model: 'name' argument: Wrong type, expected 'string'");
|
|
80
|
-
if (this.models[
|
|
81
|
-
throw new Error(`Sedentary.model: '${
|
|
88
|
+
if (this.models[modelName])
|
|
89
|
+
throw new Error(`Sedentary.model: '${modelName}' model: Model already defined`);
|
|
82
90
|
if (!attributes)
|
|
83
91
|
attributes = {};
|
|
84
92
|
if (!(attributes instanceof Object))
|
|
85
|
-
throw new Error(`Sedentary.model: '${
|
|
93
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'attributes' argument: Wrong type, expected 'Object'`);
|
|
86
94
|
if (!options)
|
|
87
95
|
options = {};
|
|
88
96
|
if (!(options instanceof Object))
|
|
89
|
-
throw new Error(`Sedentary.model: '${
|
|
97
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'options' argument: Wrong type, expected 'Object'`);
|
|
90
98
|
for (const k in options)
|
|
91
99
|
if (!allowedOption.includes(k))
|
|
92
|
-
throw new Error(`Sedentary.model: '${
|
|
100
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'options' argument: Unknown '${k}' option`);
|
|
93
101
|
if (options.int8id && options.parent)
|
|
94
|
-
throw new Error(`Sedentary.model: '${
|
|
102
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'int8id' and 'parent' options conflict each other`);
|
|
95
103
|
if (options.int8id && options.primaryKey)
|
|
96
|
-
throw new Error(`Sedentary.model: '${
|
|
104
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'int8id' and 'primaryKey' options conflict each other`);
|
|
97
105
|
if (options.parent && options.primaryKey)
|
|
98
|
-
throw new Error(`Sedentary.model: '${
|
|
106
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'parent' and 'primaryKey' options conflict each other`);
|
|
99
107
|
let autoIncrement = true;
|
|
100
|
-
const { indexes, int8id, parent, primaryKey, sync, tableName } = Object.assign({ sync: this.sync, tableName:
|
|
101
|
-
let { methods } = options;
|
|
108
|
+
const { indexes, int8id, parent, primaryKey, sync, tableName } = Object.assign({ sync: this.sync, tableName: modelName }, options);
|
|
102
109
|
let aarray = int8id
|
|
103
|
-
? [new db_1.Attribute(Object.assign(Object.assign({}, this.INT8()), { attributeName: "id", fieldName: "id", notNull: true, tableName, unique: true }))]
|
|
104
|
-
: [new db_1.Attribute(Object.assign(Object.assign({}, this.INT(4)), { attributeName: "id", fieldName: "id", notNull: true, tableName, unique: true }))];
|
|
110
|
+
? [new db_1.Attribute(Object.assign(Object.assign({}, this.INT8()), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))]
|
|
111
|
+
: [new db_1.Attribute(Object.assign(Object.assign({}, this.INT(4)), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))];
|
|
105
112
|
let constraints = [{ attribute: aarray[0], constraintName: `${tableName}_id_unique`, type: "u" }];
|
|
106
113
|
const iarray = [];
|
|
107
114
|
const pk = aarray[0];
|
|
108
115
|
if (methods && !(methods instanceof Object))
|
|
109
|
-
throw new Error(`Sedentary.model: '${
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
catch (e) {
|
|
117
|
-
throw new Error(`Sedentary.model: '${name}' model: 'parent' option: Wrong type, expected 'Model'`);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
116
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'methods' option: Wrong type, expected 'Object'`);
|
|
117
|
+
const originalMethods = methods;
|
|
118
|
+
if (parent)
|
|
119
|
+
if (!parent.attributes)
|
|
120
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'parent' option: Wrong type, expected 'Model'`);
|
|
121
|
+
//methods = (methods ? { ...(parent.methods || {}), ...methods } : parent.methods) as never;
|
|
120
122
|
if (primaryKey && typeof primaryKey !== "string")
|
|
121
|
-
throw new Error(`Sedentary.model: '${
|
|
123
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Wrong type, expected 'string'`);
|
|
122
124
|
if (primaryKey && !Object.keys(attributes).includes(primaryKey))
|
|
123
|
-
throw new Error(`Sedentary.model: '${
|
|
125
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Attribute '${primaryKey}' does not exists`);
|
|
124
126
|
if (parent || primaryKey) {
|
|
125
127
|
autoIncrement = false;
|
|
126
128
|
aarray = [];
|
|
127
129
|
constraints = [];
|
|
128
130
|
}
|
|
129
|
-
for (const attributeName
|
|
131
|
+
for (const attributeName of Object.keys(attributes).sort()) {
|
|
130
132
|
if (reservedNames.includes(attributeName))
|
|
131
|
-
throw new Error(`Sedentary.model: '${
|
|
133
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Reserved name`);
|
|
132
134
|
const call = (defaultValue, fieldName, notNull, unique, func, message1, message2) => {
|
|
133
135
|
if (func === this.FKEY)
|
|
134
136
|
throw new Error(`${message1} 'this.FKEY' can't be used directly`);
|
|
135
137
|
if (func !== this.DATETIME && func !== this.INT && func !== this.INT8 && func !== this.VARCHAR)
|
|
136
138
|
throw new Error(`${message1} ${message2}`);
|
|
137
|
-
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, notNull, tableName, unique }, func()));
|
|
139
|
+
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique }, func()));
|
|
138
140
|
};
|
|
139
141
|
const attributeDefinition = attributes[attributeName];
|
|
140
142
|
let { base, defaultValue, fieldName, foreignKey, notNull, size, type, unique } = (() => {
|
|
141
143
|
const ret = (() => {
|
|
142
144
|
if (attributeDefinition instanceof db_1.Type)
|
|
143
|
-
return new db_1.Attribute(Object.assign({ attributeName, fieldName: attributeName, notNull: false, tableName }, attributeDefinition));
|
|
145
|
+
return new db_1.Attribute(Object.assign({ attributeName, fieldName: attributeName, modelName, notNull: false, tableName }, attributeDefinition));
|
|
144
146
|
if (attributeDefinition instanceof Function)
|
|
145
|
-
return call(undefined, attributeName, false, false, attributeDefinition, `Sedentary.model: '${
|
|
147
|
+
return call(undefined, attributeName, false, false, attributeDefinition, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute:`, "Wrong type, expected 'Attribute'");
|
|
146
148
|
if (!(attributeDefinition instanceof Object))
|
|
147
|
-
throw new Error(`Sedentary.model: '${
|
|
149
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Wrong attribute type, expected 'Attribute'`);
|
|
148
150
|
const attributeDefaults = Object.assign({ defaultValue: undefined, fieldName: attributeName, notNull: false, unique: false }, attributeDefinition);
|
|
149
151
|
const { defaultValue, fieldName, notNull, unique, type } = attributeDefaults;
|
|
150
152
|
if (defaultValue === null)
|
|
151
|
-
throw new Error(`Sedentary.model: '${
|
|
153
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really makes sense?`);
|
|
152
154
|
if (typeof fieldName !== "string")
|
|
153
|
-
throw new Error(`Sedentary.model: '${
|
|
155
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
|
|
154
156
|
if (typeof notNull !== "boolean")
|
|
155
|
-
throw new Error(`Sedentary.model: '${
|
|
157
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
|
|
156
158
|
if (typeof unique !== "boolean")
|
|
157
|
-
throw new Error(`Sedentary.model: '${
|
|
159
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
|
|
158
160
|
if (type === undefined)
|
|
159
|
-
throw new Error(`Sedentary.model: '${
|
|
161
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Missing 'type' option`);
|
|
160
162
|
if (type instanceof db_1.Type)
|
|
161
|
-
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, notNull, tableName, unique }, type));
|
|
163
|
+
return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique }, type));
|
|
162
164
|
if (type instanceof Function)
|
|
163
|
-
return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${
|
|
164
|
-
throw new Error(`Sedentary.model: '${
|
|
165
|
+
return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option:`, "Wrong type, expected 'Type'");
|
|
166
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option: Wrong type, expected 'Type'`);
|
|
165
167
|
})();
|
|
166
168
|
const { base, defaultValue } = ret;
|
|
167
169
|
if (defaultValue !== undefined) {
|
|
168
170
|
if (base === Date && !(defaultValue instanceof Date))
|
|
169
|
-
throw new Error(`Sedentary.model: '${
|
|
171
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'Date'`);
|
|
170
172
|
if (base === Number && typeof defaultValue !== "number")
|
|
171
|
-
throw new Error(`Sedentary.model: '${
|
|
173
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'number'`);
|
|
172
174
|
if (base === String && typeof defaultValue !== "string")
|
|
173
|
-
throw new Error(`Sedentary.model: '${
|
|
175
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'string'`);
|
|
174
176
|
}
|
|
175
177
|
return ret;
|
|
176
178
|
})();
|
|
179
|
+
if (foreignKey) {
|
|
180
|
+
const options = foreignKey.options || {};
|
|
181
|
+
if (foreignKey.options !== undefined && !(foreignKey.options instanceof Object))
|
|
182
|
+
throw new Error(`Sedentary.FKEY: '${modelName}' model: '${attributeName}' attribute: Wrong options type, expected 'Object'`);
|
|
183
|
+
for (const k in options)
|
|
184
|
+
if (!["onDelete", "onUpdate"].includes(k))
|
|
185
|
+
throw new Error(`Sedentary.FKEY: '${modelName}' model: '${attributeName}' attribute: Unknown option '${k}'`);
|
|
186
|
+
for (const onChange of ["onDelete", "onUpdate"]) {
|
|
187
|
+
const actions = ["cascade", "no action", "restrict", "set default", "set null"];
|
|
188
|
+
let action = options[onChange];
|
|
189
|
+
if (!action)
|
|
190
|
+
action = options[onChange] = "no action";
|
|
191
|
+
if (action && !actions.includes(action))
|
|
192
|
+
throw new Error(`Sedentary.FKEY: '${modelName}' model: '${attributeName}' attribute: '${onChange}' option: Wrong value, expected ${actions.map(_ => `'${_}'`).join(" | ")}`);
|
|
193
|
+
}
|
|
194
|
+
foreignKey.options = options;
|
|
195
|
+
}
|
|
177
196
|
if (primaryKey === attributeName) {
|
|
178
197
|
notNull = true;
|
|
179
198
|
unique = true;
|
|
180
199
|
}
|
|
181
200
|
if (defaultValue)
|
|
182
201
|
notNull = true;
|
|
183
|
-
const attribute = new db_1.Attribute({ attributeName, base, defaultValue, fieldName, foreignKey, notNull, size, tableName, type, unique });
|
|
202
|
+
const attribute = new db_1.Attribute({ attributeName, base, defaultValue, fieldName, foreignKey, modelName, notNull, size, tableName, type, unique });
|
|
184
203
|
aarray.push(attribute);
|
|
185
204
|
if (foreignKey)
|
|
186
205
|
constraints.push({ attribute, constraintName: `fkey_${fieldName}_${foreignKey.tableName}_${foreignKey.fieldName}`, type: "f" });
|
|
@@ -190,16 +209,16 @@ class Sedentary {
|
|
|
190
209
|
if (indexes) {
|
|
191
210
|
const flds = attributes;
|
|
192
211
|
if (!(indexes instanceof Object))
|
|
193
|
-
throw new Error(`Sedentary.model: '${
|
|
212
|
+
throw new Error(`Sedentary.model: '${modelName}' model: 'indexes' option: Wrong type, expected 'Object'`);
|
|
194
213
|
for (const indexName in indexes) {
|
|
195
214
|
if (aarray.filter(({ fieldName, unique }) => unique && `${tableName}_${fieldName}_unique` === indexName).length !== 0)
|
|
196
|
-
throw new Error(`Sedentary.model: '${
|
|
215
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: index name already inferred by the unique constraint on an attribute`);
|
|
197
216
|
const idx = indexes[indexName];
|
|
198
217
|
const checkAttribute = (attribute, l) => {
|
|
199
218
|
if (typeof attribute !== "string")
|
|
200
|
-
throw new Error(`Sedentary.model: '${
|
|
219
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: #${l + 1} attribute: Wrong type, expected 'string'`);
|
|
201
220
|
if (!(attribute in flds))
|
|
202
|
-
throw new Error(`Sedentary.model: '${
|
|
221
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: #${l + 1} attribute: Unknown attribute '${attribute}'`);
|
|
203
222
|
};
|
|
204
223
|
let attributes;
|
|
205
224
|
let type = "btree";
|
|
@@ -215,10 +234,10 @@ class Sedentary {
|
|
|
215
234
|
else if (idx instanceof Object) {
|
|
216
235
|
for (const k in idx)
|
|
217
236
|
if (!["attributes", "type", "unique"].includes(k))
|
|
218
|
-
throw new Error(`Sedentary.model: '${
|
|
237
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Unknown index option '${k}'`);
|
|
219
238
|
({ attributes, type, unique } = Object.assign({ type: "btree", unique: false }, idx));
|
|
220
239
|
if (!attributes)
|
|
221
|
-
throw new Error(`Sedentary.model: '${
|
|
240
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Missing 'attributes' option`);
|
|
222
241
|
if (attributes instanceof Array)
|
|
223
242
|
attributes.forEach(checkAttribute);
|
|
224
243
|
else if (typeof attributes === "string") {
|
|
@@ -226,134 +245,92 @@ class Sedentary {
|
|
|
226
245
|
attributes = [attributes];
|
|
227
246
|
}
|
|
228
247
|
else
|
|
229
|
-
throw new Error(`Sedentary.model: '${
|
|
248
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'attributes' option: Wrong type, expected 'FieldNames'`);
|
|
230
249
|
if (typeof type !== "string")
|
|
231
|
-
throw new Error(`Sedentary.model: '${
|
|
250
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'type' option: Wrong type, expected 'string'`);
|
|
232
251
|
if (!["btree", "hash"].includes(type))
|
|
233
|
-
throw new Error(`Sedentary.model: '${
|
|
252
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'type' option: Wrong value, expected 'btree' or 'hash'`);
|
|
234
253
|
if (typeof unique !== "boolean")
|
|
235
|
-
throw new Error(`Sedentary.model: '${
|
|
254
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'unique' option: Wrong type, expected 'boolean'`);
|
|
236
255
|
}
|
|
237
256
|
else
|
|
238
|
-
throw new Error(`Sedentary.model: '${
|
|
257
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Wrong type, expected 'Object'`);
|
|
239
258
|
iarray.push({ fields: attributes, indexName, type, unique });
|
|
240
259
|
}
|
|
241
260
|
}
|
|
242
261
|
this.db.tables.push(new db_1.Table({ autoIncrement, constraints, attributes: aarray, indexes: iarray, parent, sync, tableName }));
|
|
243
|
-
this.models[
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
262
|
+
this.models[modelName] = true;
|
|
263
|
+
const foreignKeys = aarray
|
|
264
|
+
.filter(_ => _.foreignKey)
|
|
265
|
+
.reduce((ret, curr) => {
|
|
266
|
+
ret[curr.attributeName] = true;
|
|
267
|
+
return ret;
|
|
268
|
+
}, {});
|
|
269
|
+
for (const foreignKey in foreignKeys) {
|
|
270
|
+
if (foreignKey + "Load" in attributes)
|
|
271
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute`);
|
|
272
|
+
if (originalMethods && foreignKey + "Load" in originalMethods)
|
|
273
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method`);
|
|
274
|
+
}
|
|
275
|
+
if (originalMethods)
|
|
276
|
+
for (const method in originalMethods)
|
|
277
|
+
if (method in attributes)
|
|
278
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute`);
|
|
279
|
+
const checkParent = (parent) => {
|
|
280
|
+
if (!parent)
|
|
281
|
+
return;
|
|
282
|
+
for (const attribute in attributes) {
|
|
283
|
+
if (attribute in parent.attributes)
|
|
284
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an attribute of '${parent.modelName}' model`);
|
|
285
|
+
if (attribute in parent.methods)
|
|
286
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with a method of '${parent.modelName}' model`);
|
|
287
|
+
for (const foreignKey in parent.foreignKeys)
|
|
288
|
+
if (attribute === foreignKey + "Load")
|
|
289
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an inferred methods of '${parent.modelName}' model`);
|
|
259
290
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
});
|
|
291
|
+
for (const foreignKey in foreignKeys) {
|
|
292
|
+
if (foreignKey + "Load" in parent.attributes)
|
|
293
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute of '${parent.modelName}' model`);
|
|
294
|
+
if (foreignKey + "Load" in parent.methods)
|
|
295
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method of '${parent.modelName}' model`);
|
|
266
296
|
}
|
|
267
|
-
|
|
297
|
+
if (originalMethods) {
|
|
298
|
+
for (const method in originalMethods) {
|
|
299
|
+
if (method in parent.attributes)
|
|
300
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute of '${parent.modelName}' model`);
|
|
301
|
+
for (const foreignKey in parent.foreignKeys)
|
|
302
|
+
if (foreignKey + "Load" === method)
|
|
303
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an inferred methods of '${parent.modelName}' model`);
|
|
304
|
+
if (method in parent.methods)
|
|
305
|
+
throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with a method of '${parent.modelName}' model`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
checkParent(parent.parent);
|
|
309
|
+
};
|
|
310
|
+
checkParent(parent);
|
|
311
|
+
const ret = function () { };
|
|
268
312
|
const load = (boh) => new Promise((resolve, reject) => setTimeout(() => {
|
|
269
313
|
if (boh)
|
|
270
|
-
return resolve([new
|
|
314
|
+
return resolve([new ret()]);
|
|
271
315
|
reject(new Error("boh"));
|
|
272
316
|
}, 10));
|
|
273
|
-
Object.defineProperty(load, "name", { value:
|
|
274
|
-
|
|
275
|
-
Object.defineProperty(
|
|
276
|
-
Object.defineProperty(
|
|
277
|
-
Object.defineProperty(
|
|
278
|
-
Object.defineProperty(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
317
|
+
Object.defineProperty(load, "name", { value: modelName + ".load" });
|
|
318
|
+
Object.defineProperty(ret, "name", { value: modelName });
|
|
319
|
+
Object.defineProperty(ret, "load", { value: load });
|
|
320
|
+
Object.defineProperty(ret, "attributes", { value: attributes });
|
|
321
|
+
Object.defineProperty(ret, "foreignKeys", { value: foreignKeys });
|
|
322
|
+
Object.defineProperty(ret, "methods", { value: methods || {} });
|
|
323
|
+
if (methods)
|
|
324
|
+
Object.assign(ret.prototype, methods);
|
|
325
|
+
ret.prototype.save = function () {
|
|
326
|
+
return Promise.resolve(false);
|
|
327
|
+
};
|
|
282
328
|
for (const attribute of aarray)
|
|
283
|
-
Object.defineProperty(
|
|
284
|
-
for (const key of ["attributeName", "base", "fieldName", "size", "type", "unique"])
|
|
285
|
-
Object.defineProperty(
|
|
286
|
-
return
|
|
287
|
-
}
|
|
288
|
-
checkSize(size, message) {
|
|
289
|
-
const str = size.toString();
|
|
290
|
-
const parsed = parseInt(str, 10);
|
|
291
|
-
if (str !== parsed.toString())
|
|
292
|
-
throw new Error(message);
|
|
293
|
-
return parsed;
|
|
329
|
+
Object.defineProperty(ret, attribute.attributeName, { value: attribute });
|
|
330
|
+
for (const key of ["attributeName", "base", "fieldName", "modelName", "size", "tableName", "type", "unique"])
|
|
331
|
+
Object.defineProperty(ret, key, { value: pk[key] });
|
|
332
|
+
return ret;
|
|
294
333
|
}
|
|
295
334
|
}
|
|
296
335
|
exports.Sedentary = Sedentary;
|
|
297
336
|
exports.Package = Sedentary;
|
|
298
|
-
const db = new Sedentary("gino");
|
|
299
|
-
const Users = db.model("User", { foo: db.INT(), bar: { type: db.VARCHAR(), unique: true } }, {});
|
|
300
|
-
class Item extends db.model("Item", {
|
|
301
|
-
num: db.FKEY(Users),
|
|
302
|
-
str: db.VARCHAR()
|
|
303
|
-
}, {
|
|
304
|
-
init: function () {
|
|
305
|
-
this.num = 0;
|
|
306
|
-
this.str = "0";
|
|
307
|
-
},
|
|
308
|
-
int8id: true,
|
|
309
|
-
methods: {
|
|
310
|
-
prova: () => "ok"
|
|
311
|
-
}
|
|
312
|
-
}) {
|
|
313
|
-
}
|
|
314
|
-
class Super extends db.model("Super", {
|
|
315
|
-
a: db.INT,
|
|
316
|
-
n: db.FKEY(Item),
|
|
317
|
-
s: db.FKEY(Users.bar)
|
|
318
|
-
}, {
|
|
319
|
-
parent: Item,
|
|
320
|
-
init: async function () {
|
|
321
|
-
this.n = "23";
|
|
322
|
-
this.id = "0";
|
|
323
|
-
this.num = 0;
|
|
324
|
-
const a = this.nLoad ? await this.nLoad() : { prova: () => null };
|
|
325
|
-
a.prova();
|
|
326
|
-
}
|
|
327
|
-
}) {
|
|
328
|
-
}
|
|
329
|
-
class Next extends db.model("Next", { a: db.INT, b: db.INT }, {
|
|
330
|
-
init: function () {
|
|
331
|
-
this.a = 23;
|
|
332
|
-
},
|
|
333
|
-
primaryKey: "a"
|
|
334
|
-
}) {
|
|
335
|
-
}
|
|
336
|
-
class Current extends db.model("Current", { b: { type: db.FKEY(Next), unique: true } }, {
|
|
337
|
-
init: function () {
|
|
338
|
-
this.b = 24;
|
|
339
|
-
}
|
|
340
|
-
}) {
|
|
341
|
-
}
|
|
342
|
-
class Last extends db.model("Last", { b: db.FKEY(Current.b) }, {
|
|
343
|
-
init: function () {
|
|
344
|
-
this.b = 24;
|
|
345
|
-
},
|
|
346
|
-
parent: Next
|
|
347
|
-
}) {
|
|
348
|
-
}
|
|
349
|
-
(async function () {
|
|
350
|
-
const item = new Super();
|
|
351
|
-
try {
|
|
352
|
-
await item.save();
|
|
353
|
-
}
|
|
354
|
-
catch (e) {
|
|
355
|
-
console.log(Item.load, item.save, await Item.load(true), item, e.message);
|
|
356
|
-
console.log(new Next(), Next.load, await Next.load(true), new Last(), item.prova());
|
|
357
|
-
}
|
|
358
|
-
return true;
|
|
359
|
-
})();
|
package/lib/db.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
export declare type Natural = Date | Record<string, unknown> | boolean | number | string;
|
|
2
|
-
export declare class
|
|
3
|
-
|
|
2
|
+
export declare class EntryBase {
|
|
3
|
+
construct(): void;
|
|
4
|
+
postLoad(): void;
|
|
5
|
+
preLoad(): void;
|
|
6
|
+
preSave(): void;
|
|
4
7
|
save(): Promise<boolean>;
|
|
5
8
|
}
|
|
6
|
-
export declare
|
|
9
|
+
export declare type ForeignKeyActions = "cascade" | "no action" | "restrict" | "set default" | "set null";
|
|
10
|
+
export interface ForeignKeyOptions {
|
|
11
|
+
onDelete?: ForeignKeyActions;
|
|
12
|
+
onUpdate?: ForeignKeyActions;
|
|
13
|
+
}
|
|
14
|
+
export interface Type<N extends Natural, E> {
|
|
7
15
|
base: unknown;
|
|
8
16
|
entry?: E;
|
|
9
17
|
native?: N;
|
|
@@ -12,27 +20,23 @@ export declare class Type<N extends Natural, E> {
|
|
|
12
20
|
foreignKey?: {
|
|
13
21
|
attributeName: string;
|
|
14
22
|
fieldName: string;
|
|
23
|
+
options?: ForeignKeyOptions;
|
|
15
24
|
tableName: string;
|
|
16
25
|
};
|
|
17
|
-
constructor(from: Type<N, E>);
|
|
18
26
|
}
|
|
19
|
-
export declare class
|
|
20
|
-
|
|
21
|
-
isModel?: () => boolean;
|
|
22
|
-
methods: {
|
|
23
|
-
[key: string]: () => unknown;
|
|
24
|
-
};
|
|
25
|
-
primaryKey: string;
|
|
26
|
-
tableName: string;
|
|
27
|
-
constructor(from: Meta<N, E>);
|
|
27
|
+
export declare class Type<N extends Natural, E> {
|
|
28
|
+
constructor(from: Type<N, E>);
|
|
28
29
|
}
|
|
29
|
-
export
|
|
30
|
+
export interface Attribute<N extends Natural, E> extends Type<N, E> {
|
|
30
31
|
attributeName: string;
|
|
31
32
|
defaultValue?: unknown;
|
|
32
33
|
fieldName: string;
|
|
34
|
+
modelName: string;
|
|
33
35
|
notNull: boolean;
|
|
34
36
|
tableName: string;
|
|
35
37
|
unique?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare class Attribute<N extends Natural, E> extends Type<N, E> {
|
|
36
40
|
constructor(from: Attribute<N, E>);
|
|
37
41
|
}
|
|
38
42
|
export interface Constraint {
|
|
@@ -51,11 +55,11 @@ interface ITable {
|
|
|
51
55
|
autoIncrement: boolean;
|
|
52
56
|
constraints: Constraint[];
|
|
53
57
|
indexes: Index[];
|
|
54
|
-
parent:
|
|
58
|
+
parent: any;
|
|
55
59
|
sync: boolean;
|
|
56
60
|
tableName: string;
|
|
57
61
|
}
|
|
58
|
-
declare const Table_base: new (defaults?: ITable) => ITable;
|
|
62
|
+
declare const Table_base: new (defaults?: ITable | undefined) => ITable;
|
|
59
63
|
export declare class Table extends Table_base {
|
|
60
64
|
autoIncrementOwn?: boolean;
|
|
61
65
|
oid?: number;
|
|
@@ -63,7 +67,7 @@ export declare class Table extends Table_base {
|
|
|
63
67
|
}
|
|
64
68
|
export declare abstract class DB {
|
|
65
69
|
tables: Table[];
|
|
66
|
-
protected log: (
|
|
70
|
+
protected log: (message: string) => void;
|
|
67
71
|
protected sync: boolean;
|
|
68
72
|
abstract connect(): Promise<void>;
|
|
69
73
|
abstract end(): Promise<void>;
|
|
@@ -71,7 +75,7 @@ export declare abstract class DB {
|
|
|
71
75
|
findTable(name: string): Table;
|
|
72
76
|
protected indexesEq(a: Index, b: Index): boolean;
|
|
73
77
|
syncDataBase(): Promise<void>;
|
|
74
|
-
protected syncLog(
|
|
78
|
+
protected syncLog(message: string): void;
|
|
75
79
|
abstract dropConstraints(table: Table): Promise<number[]>;
|
|
76
80
|
abstract dropFields(table: Table): Promise<void>;
|
|
77
81
|
abstract dropIndexes(table: Table, constraintIndexes: number[]): Promise<void>;
|
package/lib/db.js
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DB = exports.Table = exports.Attribute = exports.
|
|
4
|
-
class
|
|
5
|
-
|
|
3
|
+
exports.DB = exports.Table = exports.Attribute = exports.Type = exports.EntryBase = void 0;
|
|
4
|
+
class EntryBase {
|
|
5
|
+
construct() { }
|
|
6
|
+
postLoad() { }
|
|
7
|
+
preLoad() { }
|
|
8
|
+
preSave() { }
|
|
6
9
|
async save() {
|
|
7
10
|
return false;
|
|
8
11
|
}
|
|
9
12
|
}
|
|
10
|
-
exports.
|
|
13
|
+
exports.EntryBase = EntryBase;
|
|
11
14
|
class Type {
|
|
12
15
|
constructor(from) {
|
|
13
16
|
Object.assign(this, from);
|
|
14
17
|
}
|
|
15
18
|
}
|
|
16
19
|
exports.Type = Type;
|
|
17
|
-
class Meta extends Type {
|
|
18
|
-
constructor(from) {
|
|
19
|
-
super(from);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
exports.Meta = Meta;
|
|
23
20
|
class Attribute extends Type {
|
|
24
21
|
constructor(from) {
|
|
25
22
|
super(from);
|
|
@@ -29,7 +26,7 @@ exports.Attribute = Attribute;
|
|
|
29
26
|
function autoImplement() {
|
|
30
27
|
return class {
|
|
31
28
|
constructor(defaults) {
|
|
32
|
-
Object.assign(this, defaults
|
|
29
|
+
Object.assign(this, defaults);
|
|
33
30
|
}
|
|
34
31
|
};
|
|
35
32
|
}
|
|
@@ -42,6 +39,7 @@ exports.Table = Table;
|
|
|
42
39
|
class DB {
|
|
43
40
|
constructor(log) {
|
|
44
41
|
this.tables = [];
|
|
42
|
+
this.sync = true;
|
|
45
43
|
this.log = log;
|
|
46
44
|
}
|
|
47
45
|
findTable(name) {
|
|
@@ -72,9 +70,8 @@ class DB {
|
|
|
72
70
|
await this.syncIndexes(table);
|
|
73
71
|
}
|
|
74
72
|
}
|
|
75
|
-
syncLog(
|
|
76
|
-
|
|
77
|
-
this.log(...args);
|
|
73
|
+
syncLog(message) {
|
|
74
|
+
this.log(this.sync ? message : "NOT SYNCING: " + message);
|
|
78
75
|
}
|
|
79
76
|
}
|
|
80
77
|
exports.DB = DB;
|