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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # sedentary
2
2
 
3
3
  [![Build Status][travis-badge]][travis-url]
4
- [![Code Climate][code-badge]][code-url]
5
- [![Test Coverage][cover-badge]][code-url]
4
+ [![Code Quality][qlty-badge]][qlty-url]
5
+ [![Test Coverage][cover-badge]][qlty-url]
6
6
 
7
7
  [![NPM version][npm-badge]][npm-url]
8
8
  [![NPM downloads][npm-downloads-badge]][npm-url]
@@ -13,27 +13,27 @@
13
13
  [![Dependents][deps-badge]][npm-url]
14
14
  [![Donate][donate-badge]][donate-url]
15
15
 
16
- [code-badge]: https://codeclimate.com/github/iccicci/sedentary/badges/gpa.svg
17
- [code-url]: https://codeclimate.com/github/iccicci/sedentary
18
- [cover-badge]: https://codeclimate.com/github/iccicci/sedentary/badges/coverage.svg
19
- [deps-badge]: https://badgen.net/npm/dependents/sedentary?icon=npm&cache=300
16
+ [cover-badge]: https://qlty.sh/gh/iccicci/projects/sedentary/coverage.svg
17
+ [qlty-badge]: https://qlty.sh/gh/iccicci/projects/sedentary/maintainability.svg
18
+ [qlty-url]: https://qlty.sh/gh/iccicci/projects/sedentary
19
+ [deps-badge]: https://img.shields.io/librariesio/dependents/npm/sedentary?logo=npm
20
20
  [doc-badge]: https://readthedocs.org/projects/sedentary/badge/?version=latest
21
21
  [doc-url]: https://sedentary.readthedocs.io/
22
- [donate-badge]: https://badgen.net/badge/donate/bitcoin?icon=bitcoin&cache=300
22
+ [donate-badge]: https://img.shields.io/static/v1?label=donate&message=bitcoin&color=blue&logo=bitcoin
23
23
  [donate-url]: https://blockchain.info/address/1Md9WFAHrXTb3yPBwQWmUfv2RmzrtbHioB
24
24
  [github-url]: https://github.com/iccicci/sedentary
25
- [npm-downloads-badge]: https://badgen.net/npm/dw/sedentary?icon=npm&cache=300
26
- [npm-badge]: https://badgen.net/npm/v/sedentary?color=green&icon=npm&cache=300
25
+ [npm-downloads-badge]: https://img.shields.io/npm/dw/sedentary?logo=npm
26
+ [npm-badge]: https://img.shields.io/npm/v/sedentary?color=green&logo=npm
27
27
  [npm-url]: https://www.npmjs.com/package/sedentary
28
- [stars-badge]: https://badgen.net/github/stars/iccicci/sedentary?icon=github&cache=300
29
- [travis-badge]: https://badgen.net/travis/iccicci/sedentary?icon=travis&cache=300
28
+ [stars-badge]: https://img.shields.io/github/stars/iccicci/sedentary?logo=github&style=flat&color=green
29
+ [travis-badge]: https://img.shields.io/travis/com/iccicci/sedentary?logo=travis
30
30
  [travis-url]: https://app.travis-ci.com/github/iccicci/sedentary
31
- [types-badge]: https://badgen.net/npm/types/sedentary?color=green&icon=typescript&cache=300
32
-
33
- # under development
31
+ [types-badge]: https://img.shields.io/static/v1?label=types&message=included&color=green&logo=typescript
34
32
 
35
33
  # Description
36
34
 
35
+ This package contains the base logic and types for the Sedentary ORM. **It must not be used directly** because it does not implement any DB engine; use a dedicated extension such as [sedentary-pg](https://www.npmjs.com/package/sedentary-pg) instead.
36
+
37
37
  An ORM which automatically syncs the DB schema on models change, no migrations between versions are required.
38
38
 
39
39
  This package is designed **to make easy the process of applying changes to the database after model definition
@@ -46,19 +46,19 @@ changes to the models (or the database schema). This package tries to solve thes
46
46
  # Usage
47
47
 
48
48
  ```javascript
49
- import { Sedentary } from "sedentary";
49
+ import { SedentaryPG } from "sedentary-pg";
50
50
 
51
- const db = new Sedentary("file.db");
51
+ const db = new SedentaryPG({ database: "db", user: "user", password: "pass" });
52
52
 
53
- class Items extends db.model("Item", {
54
- num: db.INT,
55
- str: db.VarChar(30)
53
+ const Items = db.model("Item", {
54
+ num: db.Int(),
55
+ str: db.VarChar({ size: 30 })
56
56
  });
57
57
 
58
58
  (async function () {
59
59
  await db.connect();
60
60
 
61
- const item = Items.create();
61
+ const item = new Items();
62
62
 
63
63
  item.num = 0;
64
64
  item.str = "0";
@@ -71,6 +71,22 @@ class Items extends db.model("Item", {
71
71
  })();
72
72
  ```
73
73
 
74
+ With TypeScript the instance can be typed using `Entry<typeof Model>`:
75
+
76
+ ```typescript
77
+ import { Entry, SedentaryPG } from "sedentary-pg";
78
+
79
+ const db = new SedentaryPG({ database: "db", user: "user", password: "pass" });
80
+
81
+ const Items = db.model("Item", { num: db.Int(), str: db.VarChar({ size: 30 }) });
82
+ type Item = Entry<typeof Items>;
83
+
84
+ const item: Item = new Items();
85
+
86
+ item.num = 0;
87
+ item.str = "0";
88
+ ```
89
+
74
90
  # Installation
75
91
 
76
92
  With [npm](https://www.npmjs.com/package/sedentary):
@@ -85,9 +101,9 @@ $ npm install --save sedentary
85
101
 
86
102
  A _DB engine dedicated extension_ must be used:
87
103
 
88
- - MySQL: planned
89
- - PostgreSQL: [sedentary-pg](https://github.com/iccicci/sedentary-pg#readme)
90
- - SQLite: planned
104
+ - MySQL: in todo, not yet planned
105
+ - PostgreSQL: [sedentary-pg](https://www.npmjs.com/package/sedentary-pg)
106
+ - SQLite: in todo, not yet planned
91
107
 
92
108
  # Documentation
93
109
 
@@ -97,13 +113,13 @@ The full documentation is on [sedentary.readthedocs.io](https://sedentary.readth
97
113
 
98
114
  Requires:
99
115
 
100
- - Node.js: **v14**
101
- - TypeScript: **v4.6** (or none if used in a JavaScript project).
116
+ - Node.js: **v20**
117
+ - TypeScript: **v5.7** (or none if used in a JavaScript project).
102
118
 
103
119
  The package is tested under [all Node.js versions](https://app.travis-ci.com/github/iccicci/sedentary)
104
120
  currently supported accordingly to [Node.js Release](https://github.com/nodejs/Release#readme).
105
121
 
106
- To work with the package under Windows, be sure to configure `bash.exe` as your _script-shell_.
122
+ To work with the package under Windows, `bash.exe` can be configured as the _script-shell_.
107
123
 
108
124
  ```
109
125
  > npm config set script-shell bash.exe
@@ -115,9 +131,12 @@ To work with the package under Windows, be sure to configure `bash.exe` as your
115
131
 
116
132
  # Bugs
117
133
 
118
- Do not hesitate to report any bug or inconsistency [@github](https://github.com/iccicci/sedentary/issues).
134
+ Bugs and inconsistencies can be reported [@github](https://github.com/iccicci/sedentary/issues).
119
135
 
120
136
  # Donating
121
137
 
122
- If you find useful this package, please consider the opportunity to donate some satoshis to this bitcoin address:
138
+ Satoshis can be donated to this bitcoin address if the package is found useful:
139
+
140
+ <!-- cSpell: disable -->
141
+
123
142
  **1Md9WFAHrXTb3yPBwQWmUfv2RmzrtbHioB**
package/dist/cjs/db.js CHANGED
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deepDiff = exports.deepCopy = exports.Transaction = exports.DB = exports.Table = exports.Attribute = exports.Type = exports.EntryBase = exports.transaction = exports.size = exports.loaded = exports.base = exports.actions = void 0;
3
+ exports.Transaction = exports.DB = exports.Table = exports.Attribute = exports.Type = exports.EntryBase = exports.transaction = exports.size = exports.loaded = exports.base = exports.actions = void 0;
4
+ exports.deepCopy = deepCopy;
5
+ exports.deepDiff = deepDiff;
4
6
  exports.actions = Symbol("actions");
5
7
  exports.base = Symbol("base");
6
8
  exports.loaded = Symbol("loaded");
@@ -29,21 +31,24 @@ class EntryBase {
29
31
  preLoad() { }
30
32
  preRemove() { }
31
33
  preSave() { }
32
- async remove() {
33
- return false;
34
+ remove() {
35
+ return Promise.resolve(false);
34
36
  }
35
- async save() {
36
- return false;
37
+ save() {
38
+ return Promise.resolve(false);
37
39
  }
38
40
  }
39
41
  exports.EntryBase = EntryBase;
42
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
40
43
  class Type {
41
44
  constructor(from) {
42
45
  Object.assign(this, from);
43
46
  }
44
47
  }
45
48
  exports.Type = Type;
49
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
46
50
  class Attribute extends Type {
51
+ // eslint-disable-next-line @typescript-eslint/no-useless-constructor
47
52
  constructor(from) {
48
53
  super(from);
49
54
  }
@@ -58,10 +63,10 @@ function autoImplement() {
58
63
  }
59
64
  class Table extends autoImplement() {
60
65
  findAttribute(name) {
61
- return this.attributes.filter(_ => _.attributeName === name)[0];
66
+ return this.attributes.find(_ => _.attributeName === name);
62
67
  }
63
68
  findField(name) {
64
- return this.attributes.filter(_ => _.fieldName === name)[0];
69
+ return this.attributes.find(_ => _.fieldName === name);
65
70
  }
66
71
  }
67
72
  exports.Table = Table;
@@ -72,12 +77,12 @@ class DB {
72
77
  this.log = log;
73
78
  }
74
79
  findTable(name) {
75
- return this.tables.filter(_ => _.tableName === name)[0];
80
+ return this.tables.find(_ => _.tableName === name);
76
81
  }
77
82
  indexesEq(a, b) {
78
83
  if (a.fields.length !== b.fields.length)
79
84
  return false;
80
- for (const i in a.fields)
85
+ for (let i = 0; i < a.fields.length; ++i)
81
86
  if (a.fields[i] !== b.fields[i])
82
87
  return false;
83
88
  if (a.type !== b.type)
@@ -100,7 +105,7 @@ class DB {
100
105
  }
101
106
  }
102
107
  syncLog(message) {
103
- this.log(this.sync ? message : "NOT SYNCING: " + message);
108
+ this.log(this.sync ? message : `NOT SYNCING: ${message}`);
104
109
  }
105
110
  }
106
111
  exports.DB = DB;
@@ -121,12 +126,13 @@ class Transaction {
121
126
  }
122
127
  this.entries = [];
123
128
  }
124
- async commit() {
129
+ commit() {
125
130
  const { entries } = this;
126
131
  for (const entry of entries)
127
132
  if (entry[exports.actions])
128
133
  entry.postCommit(entry[exports.actions]);
129
134
  this.clean();
135
+ return Promise.resolve();
130
136
  }
131
137
  preCommit() {
132
138
  const { entries } = this;
@@ -134,8 +140,9 @@ class Transaction {
134
140
  if (entry[exports.actions])
135
141
  entry.preCommit(entry[exports.actions]);
136
142
  }
137
- async rollback() {
143
+ rollback() {
138
144
  this.clean();
145
+ return Promise.resolve();
139
146
  }
140
147
  }
141
148
  exports.Transaction = Transaction;
@@ -149,7 +156,6 @@ function deepCopy(o) {
149
156
  ret[k] = deepCopy(v);
150
157
  return ret;
151
158
  }
152
- exports.deepCopy = deepCopy;
153
159
  function deepDiff(a, b) {
154
160
  if (typeof a !== "object")
155
161
  return a !== b;
@@ -176,4 +182,3 @@ function deepDiff(a, b) {
176
182
  return true;
177
183
  return false;
178
184
  }
179
- exports.deepDiff = deepDiff;
package/dist/cjs/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Sedentary = exports.Type = exports.transaction = exports.Transaction = exports.Table = exports.size = exports.loaded = exports.EntryBase = exports.deepDiff = exports.deepCopy = exports.DB = exports.base = exports.Attribute = void 0;
4
+ exports.toSqlName = toSqlName;
4
5
  const db_1 = require("./db");
5
6
  var db_2 = require("./db");
6
7
  Object.defineProperty(exports, "Attribute", { enumerable: true, get: function () { return db_2.Attribute; } });
@@ -20,9 +21,53 @@ const methods = Symbol("methods");
20
21
  const operators = ["=", ">", "<", ">=", "<=", "<>", "IN", "IS NULL", "LIKE", "NOT"];
21
22
  const allowedOption = ["indexes", "int8id", "parent", "primaryKey", "sync", "tableName"];
22
23
  const reservedNames = [
23
- ...["attr2field", "attributeName", "cancel", "class", "construct", "constructor", "defaultValue", "fieldName", "foreignKeys", "load", "name"],
24
- ...["postCommit", "postLoad", "postRemove", "postSave", "preCommit", "preLoad", "preRemove", "preSave", "primaryKey", "prototype", "save", "tableName", "type"]
24
+ "attr2field",
25
+ "attributeName",
26
+ "cancel",
27
+ "class",
28
+ "construct",
29
+ "constructor",
30
+ "defaultValue",
31
+ "fieldName",
32
+ "foreignKeys",
33
+ "load",
34
+ "modelName",
35
+ "name",
36
+ "postCommit",
37
+ "postLoad",
38
+ "postRemove",
39
+ "postSave",
40
+ "preCommit",
41
+ "preLoad",
42
+ "preRemove",
43
+ "preSave",
44
+ "primaryKey",
45
+ "prototype",
46
+ "remove",
47
+ "save",
48
+ "tableName",
49
+ "type",
50
+ "unique"
25
51
  ];
52
+ /** Model and attribute names: ASCII letters, digits, underscore; cannot start with digit. */
53
+ const reModelAttributeName = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
54
+ /** tableName and fieldName: ASCII lowercase letters, digits, underscore; cannot start with digit. */
55
+ const reSqlName = /^[a-z_][a-z0-9_]*$/;
56
+ /**
57
+ * Converts a JavaScript name to the default SQL name (snake_case).
58
+ * Uppercase letters become lowercase preceded by underscore, except the first character
59
+ * which is only lowercased without underscore.
60
+ */
61
+ function toSqlName(name) {
62
+ if (typeof name !== "string" || name.length === 0)
63
+ throw new Error("toSqlName: 'name' must be a non-empty string");
64
+ let result = name[0].toLowerCase();
65
+ for (let i = 1; i < name.length; i++) {
66
+ const c = name[i];
67
+ result += c >= "A" && c <= "Z" ? `_${c.toLowerCase()}` : c;
68
+ }
69
+ return result;
70
+ }
26
71
  class Sedentary {
27
72
  constructor(options) {
28
73
  this.doSync = true;
@@ -47,46 +92,56 @@ class Sedentary {
47
92
  this.log = log ? log : log === null ? () => { } : console.log;
48
93
  this.doSync = sync;
49
94
  }
50
- Boolean() {
51
- return new db_1.Type({ [db_1.base]: Boolean, type: "BOOLEAN" });
95
+ Boolean(options) {
96
+ return new db_1.Type({ ...options, [db_1.base]: Boolean, type: "BOOLEAN" });
52
97
  }
53
- DateTime() {
54
- return new db_1.Type({ [db_1.base]: Date, type: "DATETIME" });
98
+ DateTime(options) {
99
+ return new db_1.Type({ ...options, [db_1.base]: Date, type: "DATETIME" });
55
100
  }
56
101
  FKey(attribute, options) {
57
- const { attributeName, fieldName, tableName, type, [db_1.base]: _base, [db_1.size]: _size } = attribute;
102
+ const { attributeName, fieldName, modelName, tableName, type, unique, [db_1.base]: _base, [db_1.size]: _size } = attribute;
103
+ if (!unique)
104
+ throw new Error(`Sedentary.FKey: '${modelName}' model: '${attributeName}' attribute: is not unique: can't be used as FKey target`);
58
105
  return new db_1.Type({ [db_1.base]: _base, foreignKey: { attributeName, fieldName, options, tableName }, [db_1.size]: _size, type });
59
106
  }
60
- Float(_size) {
61
- const message = "Sedentary.Float: 'size' argument: Wrong value, expected 4 or 8";
62
- _size = _size ? this.checkSize(_size, message) : 8;
63
- if (_size !== 4 && _size !== 8)
64
- throw new Error(message);
65
- return new db_1.Type({ [db_1.base]: Number, [db_1.size]: _size, type: "FLOAT" });
107
+ Float(options) {
108
+ const sizeFloat = "Sedentary.Float: 'size' argument: Wrong value, expected 4 or 8";
109
+ let storageSize;
110
+ let rest;
111
+ [storageSize, rest] = this.checkSize(sizeFloat, options);
112
+ if (storageSize === undefined)
113
+ storageSize = 8;
114
+ if (storageSize !== 4 && storageSize !== 8)
115
+ throw new Error(sizeFloat);
116
+ return new db_1.Type({ ...rest, [db_1.base]: Number, [db_1.size]: storageSize, type: "FLOAT" });
66
117
  }
67
- Int(_size) {
68
- const message = "Sedentary.Int: 'size' argument: Wrong value, expected 2 or 4";
69
- _size = _size ? this.checkSize(_size, message) : 4;
70
- if (_size !== 2 && _size !== 4)
71
- throw new Error(message);
72
- return new db_1.Type({ [db_1.base]: Number, [db_1.size]: _size, type: "INT" });
118
+ Int(options) {
119
+ const sizeInt = "Sedentary.Int: 'size' argument: Wrong value, expected 2 or 4";
120
+ let storageSize;
121
+ let rest;
122
+ [storageSize, rest] = this.checkSize(sizeInt, options);
123
+ if (storageSize === undefined)
124
+ storageSize = 4;
125
+ if (storageSize !== 2 && storageSize !== 4)
126
+ throw new Error(sizeInt);
127
+ return new db_1.Type({ ...rest, [db_1.base]: Number, [db_1.size]: storageSize, type: "INT" });
73
128
  }
74
- Int8() {
75
- return new db_1.Type({ [db_1.base]: BigInt, [db_1.size]: 8, type: "INT8" });
129
+ Int8(options) {
130
+ return new db_1.Type({ ...options, [db_1.base]: BigInt, [db_1.size]: 8, type: "INT8" });
76
131
  }
77
- JSON() {
78
- return new db_1.Type({ [db_1.base]: Object, type: "JSON" });
132
+ JSON(options) {
133
+ return new db_1.Type({ ...options, [db_1.base]: Object, type: "JSON" });
79
134
  }
80
- Number() {
81
- return new db_1.Type({ [db_1.base]: Number, type: "NUMBER" });
135
+ Number(options) {
136
+ return new db_1.Type({ ...options, [db_1.base]: Number, type: "NUMBER" });
82
137
  }
83
- None() {
84
- return new db_1.Type({ [db_1.base]: undefined, type: "NONE" });
138
+ None(options) {
139
+ return new db_1.Type({ ...options, [db_1.base]: undefined, type: "NONE" });
85
140
  }
86
- VarChar(_size) {
141
+ VarChar(options) {
87
142
  const message = "Sedentary.VarChar: 'size' argument: Wrong value, expected positive integer";
88
- _size = _size ? this.checkSize(_size, message) : undefined;
89
- return new db_1.Type({ [db_1.base]: String, [db_1.size]: _size, type: "VARCHAR" });
143
+ const [maxSize, rest] = this.checkSize(message, options);
144
+ return new db_1.Type({ ...rest, [db_1.base]: String, [db_1.size]: maxSize, type: "VARCHAR" });
90
145
  }
91
146
  checkDB() {
92
147
  if (!this.db)
@@ -115,12 +170,19 @@ class Sedentary {
115
170
  }
116
171
  return true;
117
172
  }
118
- checkSize(size, message) {
119
- const str = size.toString();
120
- const parsed = parseInt(str, 10);
121
- if (str !== parsed.toString())
173
+ checkSize(message, options) {
174
+ if (!options)
175
+ return [undefined, {}];
176
+ const { size, ...rest } = options;
177
+ if (size === undefined)
178
+ return [undefined, rest];
179
+ if (typeof size !== "number")
122
180
  throw new Error(message);
123
- return parsed;
181
+ if (size !== parseInt(size.toString(), 10))
182
+ throw new Error(message);
183
+ if (size <= 0)
184
+ throw new Error(message);
185
+ return [size, rest];
124
186
  }
125
187
  createWhere(modelName, attributes, where) {
126
188
  if (typeof where === "string")
@@ -201,9 +263,9 @@ class Sedentary {
201
263
  if (this.autoSync || sync)
202
264
  await this.sync();
203
265
  }
204
- catch (e) {
205
- this.log("Connecting: " + (e instanceof Error ? e.message : JSON.stringify(e)));
206
- throw e;
266
+ catch (error) {
267
+ this.log(`Connecting: ${error instanceof Error ? error.message : JSON.stringify(error)}`);
268
+ throw error;
207
269
  }
208
270
  }
209
271
  async sync() {
@@ -227,6 +289,8 @@ class Sedentary {
227
289
  this.checkDB();
228
290
  if (typeof modelName !== "string")
229
291
  throw new Error("Sedentary.model: 'name' argument: Wrong type, expected 'string'");
292
+ if (!reModelAttributeName.test(modelName))
293
+ throw new Error(`Sedentary.model: '${modelName}' model: Invalid model name, expected ASCII letters, digits or underscore, cannot start with digit`);
230
294
  if (this.models[modelName])
231
295
  throw new Error(`Sedentary.model: '${modelName}' model: Model already defined`);
232
296
  if (!_attributes)
@@ -247,10 +311,12 @@ class Sedentary {
247
311
  if (options.parent && options.primaryKey)
248
312
  throw new Error(`Sedentary.model: '${modelName}' model: 'parent' and 'primaryKey' options conflict each other`);
249
313
  let autoIncrement = true;
250
- const { indexes, int8id, parent, primaryKey, sync, tableName } = { sync: this.doSync, tableName: modelName, ...options };
314
+ const { indexes, int8id, parent, primaryKey, sync, tableName } = { sync: this.doSync, tableName: toSqlName(modelName), ...options };
315
+ if (!reSqlName.test(tableName))
316
+ throw new Error(`Sedentary.model: '${modelName}' model: Invalid tableName '${tableName}', expected lowercase ASCII letters, digits or underscore, cannot start with digit`);
251
317
  let aArray = int8id
252
- ? [new db_1.Attribute({ ...this.Int8(), attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true })]
253
- : [new db_1.Attribute({ ...this.Int(4), attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true })];
318
+ ? [new db_1.Attribute({ ...this.Int8(), attributeName: "id", fieldName: toSqlName("id"), modelName, notNull: true, tableName, unique: true })]
319
+ : [new db_1.Attribute({ ...this.Int({ size: 4 }), attributeName: "id", fieldName: toSqlName("id"), modelName, notNull: true, tableName, unique: true })];
254
320
  let constraints = [{ attribute: aArray[0], constraintName: `${tableName}_id_unique`, type: "u" }];
255
321
  const iArray = [];
256
322
  let pk = aArray[0];
@@ -274,51 +340,37 @@ class Sedentary {
274
340
  constraints = [];
275
341
  }
276
342
  for (const attributeName of Object.keys(_attributes).sort()) {
343
+ if (!reModelAttributeName.test(attributeName))
344
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Invalid attribute name, expected ASCII letters, digits or underscore, cannot start with digit`);
277
345
  if (reservedNames.includes(attributeName))
278
346
  throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Reserved name`);
279
- const call = (defaultValue, fieldName, notNull, unique, func, message1, message2) => {
280
- if (func === this.FKey)
281
- throw new Error(`${message1} 'this.FKey' can't be used directly`);
282
- if (![this.Boolean, this.DateTime, this.Float, this.Int, this.JSON, this.Int8, this.None, this.Number, this.VarChar].includes(func))
283
- throw new Error(`${message1} ${message2}`);
284
- return new db_1.Attribute({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique, ...func() });
285
- };
286
347
  const attributeDefinition = _attributes[attributeName];
287
348
  let { [db_1.base]: _base, defaultValue, fieldName, foreignKey, notNull, [db_1.size]: _size, type, unique } = (() => {
288
- const ret = (() => {
289
- if (attributeDefinition instanceof db_1.Type)
290
- return new db_1.Attribute({ attributeName, fieldName: attributeName, modelName, notNull: false, tableName, ...attributeDefinition });
291
- if (attributeDefinition instanceof Function)
292
- return call(undefined, attributeName, false, false, attributeDefinition, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute:`, "Wrong type, expected 'Attribute'");
293
- if (!(attributeDefinition instanceof Object))
294
- throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Wrong attribute type, expected 'Attribute'`);
295
- const attributeDefaults = { defaultValue: undefined, fieldName: attributeName, notNull: false, unique: false, ...attributeDefinition };
296
- const { defaultValue, fieldName, notNull, unique, type } = attributeDefaults;
297
- if (defaultValue === null)
298
- throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really makes sense?`);
299
- if (typeof fieldName !== "string")
300
- throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
301
- if (typeof notNull !== "boolean")
302
- throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
303
- if (typeof unique !== "boolean")
304
- throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
305
- if (type === undefined)
306
- throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Missing 'type' option`);
307
- if (type instanceof db_1.Type)
308
- return new db_1.Attribute({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique, ...type });
309
- if (type instanceof Function)
310
- return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option:`, "Wrong type, expected 'Type'");
311
- throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option: Wrong type, expected 'Type'`);
312
- })();
313
- const { [db_1.base]: _base, defaultValue } = ret;
314
- if (defaultValue !== undefined) {
315
- if (_base === BigInt && typeof defaultValue !== "bigint")
349
+ if (!(attributeDefinition instanceof db_1.Type))
350
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: '${attributeName}': Wrong type, expected 'Type'`);
351
+ const ret = new db_1.Attribute({ attributeName, fieldName: toSqlName(attributeName), modelName, notNull: false, tableName, unique: false, ...attributeDefinition });
352
+ const { defaultValue, fieldName, notNull, unique } = ret;
353
+ if (defaultValue === null)
354
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really make sense?`);
355
+ if (typeof fieldName !== "string")
356
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
357
+ if (!reSqlName.test(fieldName)) {
358
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Invalid fieldName '${fieldName}', ` +
359
+ "expected lowercase ASCII letters, digits or underscore, cannot start with digit");
360
+ }
361
+ if (typeof notNull !== "boolean")
362
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
363
+ if (typeof unique !== "boolean")
364
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
365
+ const { [db_1.base]: _base, defaultValue: _defaultValue } = ret;
366
+ if (_defaultValue !== undefined) {
367
+ if (_base === BigInt && typeof _defaultValue !== "bigint")
316
368
  throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'BigInt'`);
317
- if (_base === Date && !(defaultValue instanceof Date))
369
+ if (_base === Date && !(_defaultValue instanceof Date))
318
370
  throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'Date'`);
319
- if (_base === Number && typeof defaultValue !== "number")
371
+ if (_base === Number && typeof _defaultValue !== "number")
320
372
  throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'number'`);
321
- if (_base === String && typeof defaultValue !== "string")
373
+ if (_base === String && typeof _defaultValue !== "string")
322
374
  throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'string'`);
323
375
  }
324
376
  return ret;
@@ -417,9 +469,9 @@ class Sedentary {
417
469
  return ret;
418
470
  }, {});
419
471
  for (const foreignKey in foreignKeys) {
420
- if (foreignKey + "Load" in _attributes)
472
+ if (`${foreignKey}Load` in _attributes)
421
473
  throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute`);
422
- if (foreignKey + "Load" in _methods)
474
+ if (`${foreignKey}Load` in _methods)
423
475
  throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method`);
424
476
  }
425
477
  for (const method in _methods)
@@ -434,20 +486,20 @@ class Sedentary {
434
486
  if (attribute in parent[methods])
435
487
  throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with a method of '${parent.modelName}' model`);
436
488
  for (const foreignKey in parent.foreignKeys)
437
- if (attribute === foreignKey + "Load")
489
+ if (attribute === `${foreignKey}Load`)
438
490
  throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an inferred methods of '${parent.modelName}' model`);
439
491
  }
440
492
  for (const foreignKey in foreignKeys) {
441
- if (foreignKey + "Load" in parent[attributes])
493
+ if (`${foreignKey}Load` in parent[attributes])
442
494
  throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute of '${parent.modelName}' model`);
443
- if (foreignKey + "Load" in parent[methods])
495
+ if (`${foreignKey}Load` in parent[methods])
444
496
  throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method of '${parent.modelName}' model`);
445
497
  }
446
498
  for (const method in _methods) {
447
499
  if (method in parent[attributes])
448
500
  throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute of '${parent.modelName}' model`);
449
501
  for (const foreignKey in parent.foreignKeys)
450
- if (foreignKey + "Load" === method)
502
+ if (`${foreignKey}Load` === method)
451
503
  throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an inferred methods of '${parent.modelName}' model`);
452
504
  }
453
505
  checkParent(parent.parent);
@@ -464,7 +516,7 @@ class Sedentary {
464
516
  this.db.tables.push(table);
465
517
  const cancel_ = this.db.cancel(tableName);
466
518
  const cancel = (where, tx) => cancel_(this.createWhere(modelName, attr2field, where)[0], tx);
467
- Object.defineProperty(cancel, "name", { value: modelName + ".cancel" });
519
+ Object.defineProperty(cancel, "name", { value: `${modelName}.cancel` });
468
520
  const load_ = this.db.load(tableName, attr2field, pk, ret, table);
469
521
  const load = (where, ...args) => {
470
522
  let order = undefined;
@@ -501,7 +553,7 @@ class Sedentary {
501
553
  throw new Error(`${modelName}.load: 'tx' argument: Wrong type, expected 'Transaction'`);
502
554
  return load_(this.createWhere(modelName, attr2field, where)[0], order, limit, tx, lock);
503
555
  };
504
- Object.defineProperty(load, "name", { value: modelName + ".load" });
556
+ Object.defineProperty(load, "name", { value: `${modelName}.load` });
505
557
  Object.defineProperty(ret, "cancel", { value: cancel });
506
558
  Object.defineProperty(ret, "name", { value: modelName });
507
559
  Object.defineProperty(ret, "load", { value: load });
@@ -526,7 +578,7 @@ class Sedentary {
526
578
  ensureActions(this).push({ action: "remove", records });
527
579
  return records;
528
580
  };
529
- Object.defineProperty(ret.prototype.remove, "name", { value: modelName + ".remove" });
581
+ Object.defineProperty(ret.prototype.remove, "name", { value: `${modelName}.remove` });
530
582
  const save = this.db.save(tableName, attr2field, pk);
531
583
  ret.prototype.save = async function () {
532
584
  this.preSave();
@@ -536,7 +588,7 @@ class Sedentary {
536
588
  ensureActions(this).push({ action: "save", records });
537
589
  return records;
538
590
  };
539
- Object.defineProperty(ret.prototype.save, "name", { value: modelName + ".save" });
591
+ Object.defineProperty(ret.prototype.save, "name", { value: `${modelName}.save` });
540
592
  for (const attribute of aArray)
541
593
  Object.defineProperty(ret, attribute.attributeName, { value: attribute });
542
594
  for (const key of ["attributeName", db_1.base, "fieldName", "modelName", db_1.size, "tableName", "type", "unique"])
@@ -0,0 +1 @@
1
+ {\"type\":\"commonjs\"}