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/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.Entry = void 0;
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, "Entry", { enumerable: true, get: function () { return db_2.Entry; } });
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", "init", "int8id", "methods", "parent", "primaryKey", "sync", "tableName", "type"];
9
+ const allowedOption = ["indexes", "int8id", "parent", "primaryKey", "sync", "tableName"];
11
10
  const reservedNames = [
12
- ...["attributeName", "base", "class", "constructor", "defaultValue", "entry", "fieldName", "init", "isModel"],
13
- ...["load", "meta", "methods", "name", "primaryKey", "prototype", "save", "size", "tableName", "type"]
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
- this.log = (0, log_1.createLogger)(log);
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:", e.message);
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
- model(name, attributes, options) {
78
- if (typeof name !== "string")
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[name])
81
- throw new Error(`Sedentary.model: '${name}' model: Model already defined`);
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: '${name}' model: 'attributes' argument: Wrong type, expected 'Object'`);
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: '${name}' model: 'options' argument: Wrong type, expected 'Object'`);
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: '${name}' model: 'options' argument: Unknown '${k}' option`);
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: '${name}' model: 'int8id' and 'parent' options conflict each other`);
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: '${name}' model: 'int8id' and 'primaryKey' options conflict each other`);
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: '${name}' model: 'parent' and 'primaryKey' options conflict each other`);
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: name }, options);
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: '${name}' model: 'methods' option: Wrong type, expected 'Object'`);
110
- if (parent) {
111
- methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
112
- try {
113
- if (!parent.isModel())
114
- throw new Error();
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: '${name}' model: 'primaryKey' option: Wrong type, expected 'string'`);
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: '${name}' model: 'primaryKey' option: Attribute '${primaryKey}' does not exists`);
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 in attributes) {
131
+ for (const attributeName of Object.keys(attributes).sort()) {
130
132
  if (reservedNames.includes(attributeName))
131
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: Reserved name`);
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: '${name}' model: '${attributeName}' attribute:`, "Wrong type, expected 'Attribute'");
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: '${name}' model: '${attributeName}' attribute: Wrong attribute type, expected 'Attribute'`);
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: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really makes sense?`);
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: '${name}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
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: '${name}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
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: '${name}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
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: '${name}' model: '${attributeName}' attribute: Missing 'type' option`);
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: '${name}' model: '${attributeName}' attribute: 'type' option:`, "Wrong type, expected 'Type'");
164
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'type' option: Wrong type, expected 'Type'`);
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: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'Date'`);
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: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'number'`);
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: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'string'`);
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: '${name}' model: 'indexes' option: Wrong type, expected 'Object'`);
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: '${name}' model: '${indexName}' index: index name already inferred by the unique constraint on an attribute`);
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: '${name}' model: '${indexName}' index: #${l + 1} attribute: Wrong type, expected 'string'`);
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: '${name}' model: '${indexName}' index: #${l + 1} attribute: Unknown attribute '${attribute}'`);
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: '${name}' model: '${indexName}' index: Unknown index option '${k}'`);
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: '${name}' model: '${indexName}' index: Missing 'attributes' option`);
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: '${name}' model: '${indexName}' index: 'attributes' option: Wrong type, expected 'FieldNames'`);
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: '${name}' model: '${indexName}' index: 'type' option: Wrong type, expected 'string'`);
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: '${name}' model: '${indexName}' index: 'type' option: Wrong value, expected 'btree' or 'hash'`);
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: '${name}' model: '${indexName}' index: 'unique' option: Wrong type, expected 'boolean'`);
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: '${name}' model: '${indexName}' index: Wrong type, expected 'Object'`);
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[name] = true;
244
- const init = parent
245
- ? options.init
246
- ? function () {
247
- parent.init.call(this);
248
- options.init.call(this);
249
- }
250
- : parent.init
251
- : options.init;
252
- const flds = {};
253
- for (const key in attributes)
254
- flds[key] = null;
255
- class Class {
256
- constructor() {
257
- if (init)
258
- init.call(this);
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
- save() {
261
- return new Promise((resolve, reject) => {
262
- const save = () => reject(new Error("eh no"));
263
- Object.defineProperty(save, "name", { value: name + ".save" });
264
- setTimeout(save, 10);
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 Class()]);
314
+ return resolve([new ret()]);
271
315
  reject(new Error("boh"));
272
316
  }, 10));
273
- Object.defineProperty(load, "name", { value: name + ".load" });
274
- const meta = { base: Number, type: "meta", tableName, primaryKey, init, methods };
275
- Object.defineProperty(Class, "isModel", { value: () => true });
276
- Object.defineProperty(Class, "load", { value: load });
277
- Object.defineProperty(Class, "meta", { value: new db_1.Meta(meta) });
278
- Object.defineProperty(Class, "name", { value: name });
279
- Object.defineProperty(Class.prototype.save, "name", { value: name + ".save" });
280
- Object.assign(Class, new db_1.Meta(meta));
281
- Object.assign(Class.prototype, methods);
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(Class, attribute.attributeName, { value: attribute });
284
- for (const key of ["attributeName", "base", "fieldName", "size", "type", "unique"])
285
- Object.defineProperty(Class, key, { value: pk[key] });
286
- return Class;
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 Entry {
3
- init(): void;
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 class Type<N extends Natural, E> {
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 Meta<N extends Natural, E> extends Type<N, E> {
20
- init: () => void;
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 declare class Attribute<N extends Natural, E> extends Type<N, E> {
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: Meta<Natural, unknown>;
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: (...data: unknown[]) => void;
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(...data: unknown[]): void;
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.Meta = exports.Type = exports.Entry = void 0;
4
- class Entry {
5
- init() { }
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.Entry = Entry;
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(...data) {
76
- const args = this.sync ? data : ["NOT SYNCING:", ...data];
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;