sedentary 0.0.14 → 0.0.18

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
@@ -9,6 +9,7 @@
9
9
  [![Stars][stars-badge]][github-url]
10
10
 
11
11
  [![Types][types-badge]][npm-url]
12
+ [![Documentation][doc-badge]][doc-url]
12
13
  [![Dependents][deps-badge]][npm-url]
13
14
  [![Donate][donate-badge]][donate-url]
14
15
 
@@ -16,6 +17,8 @@
16
17
  [code-url]: https://codeclimate.com/github/iccicci/sedentary
17
18
  [cover-badge]: https://codeclimate.com/github/iccicci/sedentary/badges/coverage.svg
18
19
  [deps-badge]: https://badgen.net/npm/dependents/sedentary?icon=npm&cache=300
20
+ [doc-badge]: https://readthedocs.org/projects/sedentary/badge/?version=latest
21
+ [doc-url]: https://sedentary.readthedocs.io/
19
22
  [donate-badge]: https://badgen.net/badge/donate/bitcoin?icon=bitcoin&cache=300
20
23
  [donate-url]: https://blockchain.info/address/1Md9WFAHrXTb3yPBwQWmUfv2RmzrtbHioB
21
24
  [github-url]: https://github.com/iccicci/sedentary
@@ -115,10 +118,6 @@ To work with the package under Windows, be sure to configure `bash.exe` as your
115
118
 
116
119
  Do not hesitate to report any bug or inconsistency [@github](https://github.com/iccicci/sedentary/issues).
117
120
 
118
- # ChangeLog
119
-
120
- [ChangeLog](https://github.com/iccicci/sedentary/blob/master/CHANGELOG.md)
121
-
122
121
  # Donating
123
122
 
124
123
  If you find useful this package, please consider the opportunity to donate some satoshis to this bitcoin address:
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { DB, Entry, Meta, Natural, Type } from "./lib/db";
2
- export { Entry, Natural, Type } from "./lib/db";
1
+ import { DB, Entry, ForeignKeyOptions, Meta, Natural, Type } from "./lib/db";
2
+ export { Entry, ForeignKeyActions, ForeignKeyOptions, Natural, Type } from "./lib/db";
3
3
  export declare type TypeDefinition<N extends Natural, E> = (() => Type<N, E>) | Type<N, E>;
4
4
  export interface AttributeOptions<N extends Natural, E> {
5
5
  defaultValue?: N;
@@ -30,10 +30,11 @@ export interface IndexOptions {
30
30
  unique?: boolean;
31
31
  }
32
32
  export declare type IndexDefinition = IndexAttributes | IndexOptions;
33
- export declare type BaseModelOptions<T> = {
34
- indexes?: {
35
- [key: string]: IndexDefinition;
36
- };
33
+ export declare type IndexesDefinition = {
34
+ [key: string]: IndexDefinition;
35
+ };
36
+ declare type BaseModelOptions<T> = {
37
+ indexes?: IndexesDefinition;
37
38
  init?: (this: T) => void;
38
39
  sync?: boolean;
39
40
  tableName?: string;
@@ -60,18 +61,19 @@ declare type Ancestor<A, N extends Natural, T extends Entry> = (new () => T) & {
60
61
  } & {
61
62
  load: (boh: boolean) => Promise<T[]>;
62
63
  } & Meta<N, T>;
63
- export interface SchemaOptions {
64
+ export interface SedentaryOptions {
64
65
  log?: ((message: string) => void) | null;
66
+ serverless?: boolean;
65
67
  sync?: boolean;
66
68
  }
67
69
  export declare class Sedentary {
68
70
  protected db: DB;
69
71
  protected log: (...data: unknown[]) => void;
70
- private sync;
72
+ protected sync: boolean;
71
73
  private models;
72
- constructor(filename: string, options?: SchemaOptions);
74
+ constructor(filename: string, options?: SedentaryOptions);
73
75
  DATETIME(): Type<Date, unknown>;
74
- FKEY<N extends Natural, E extends Entry>(attribute: Type<N, E>): Type<N, E>;
76
+ FKEY<N extends Natural, E extends Entry>(attribute: Type<N, E>, options?: ForeignKeyOptions): Type<N, E>;
75
77
  INT(size?: number): Type<number, unknown>;
76
78
  INT8(): Type<string, unknown>;
77
79
  VARCHAR(size?: number): Type<string, unknown>;
@@ -79,37 +81,37 @@ export declare class Sedentary {
79
81
  end(): Promise<void>;
80
82
  model<A extends AttributesDefinition, M extends Methods<T>, T extends Entry & {
81
83
  id?: string;
82
- } & ModelWithMetods<A, M>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
84
+ } & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
83
85
  int8id: true;
84
86
  methods: M;
85
87
  }): Ancestor<A, string, T>;
86
- model<A extends AttributesDefinition, K extends keyof A, M extends Methods<T>, N extends K extends keyof A ? Native<A[K]> : never, T extends Entry & ModelWithMetods<A, M>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
88
+ model<A extends AttributesDefinition, K extends keyof A, M extends Methods<T>, N extends K extends keyof A ? Native<A[K]> : never, T extends Entry & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
87
89
  methods: M;
88
90
  primaryKey: K;
89
91
  }): Ancestor<A, N, T>;
90
- model<A extends AttributesDefinition, M extends Methods<T>, P extends Meta<Natural, Entry>, N extends P extends Meta<infer N, Entry> ? N : never, T extends Parent<P> & ModelWithMetods<A, M>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
92
+ model<A extends AttributesDefinition, M extends Methods<T>, P extends Meta<Natural, Entry>, N extends P extends Meta<infer N, Entry> ? N : never, T extends Parent<P> & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
91
93
  methods: M;
92
94
  parent: P;
93
95
  }): Ancestor<A, N, T>;
94
96
  model<A extends AttributesDefinition, M extends Methods<T>, T extends Entry & {
95
97
  id?: number;
96
- } & ModelWithMetods<A, M>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
98
+ } & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
97
99
  methods: M;
98
100
  }): Ancestor<A, number, T>;
99
101
  model<A extends AttributesDefinition, T extends Entry & {
100
102
  id?: string;
101
- } & Model<A>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
103
+ } & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
102
104
  int8id: true;
103
105
  }): Ancestor<A, string, T>;
104
- model<A extends AttributesDefinition, K extends keyof A, N extends K extends keyof A ? Native<A[K]> : never, T extends Entry & Model<A>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
106
+ model<A extends AttributesDefinition, K extends keyof A, N extends K extends keyof A ? Native<A[K]> : never, T extends Entry & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
105
107
  primaryKey: K;
106
108
  }): Ancestor<A, N, T>;
107
- model<A extends AttributesDefinition, P extends Meta<Natural, Entry>, N extends P extends Meta<infer N, Entry> ? N : never, T extends Parent<P> & Model<A>>(name: string, attributes: A, options?: BaseModelOptions<T> & {
109
+ model<A extends AttributesDefinition, P extends Meta<Natural, Entry>, N extends P extends Meta<infer N, Entry> ? N : never, T extends Parent<P> & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
108
110
  parent: P;
109
111
  }): Ancestor<A, N, T>;
110
112
  model<A extends AttributesDefinition, T extends Entry & {
111
113
  id?: number;
112
- } & Model<A>>(name: string, attributes: A, options?: BaseModelOptions<T>): Ancestor<A, number, T>;
114
+ } & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T>): Ancestor<A, number, T>;
113
115
  checkSize(size: number, message: string): number;
114
116
  }
115
117
  export declare const Package: typeof Sedentary;
package/index.js CHANGED
@@ -25,19 +25,21 @@ class Sedentary {
25
25
  for (const k in options)
26
26
  if (!["log", "sync"].includes(k))
27
27
  throw new Error(`new Sedentary: 'options' argument: Unknown '${k}' option`);
28
- this.log = (0, log_1.createLogger)(options.log);
29
- if ("sync" in options)
30
- this.sync = options.sync;
28
+ const { log, sync } = Object.assign({ sync: true }, options);
29
+ if (log !== null && log !== undefined && !(log instanceof Function))
30
+ throw new Error("new Sedentary: 'log' option: Wrong type, expected 'null' or 'Function'");
31
+ if (typeof sync !== "boolean")
32
+ throw new Error("new Sedentary: 'sync' option: Wrong type, expected 'boolean'");
33
+ this.log = (0, log_1.createLogger)(log);
31
34
  this.db = new minidb_1.MiniDB(filename, this.log);
35
+ this.sync = sync;
32
36
  }
33
37
  DATETIME() {
34
38
  return new db_1.Type({ base: Date, type: "DATETIME" });
35
39
  }
36
- FKEY(attribute) {
37
- const { attributeName, base, fieldName, size, tableName, type, unique } = attribute;
38
- if (!unique)
39
- throw new Error(`Sedentary.FKEY: '${tableName}' table: '${attributeName}' attribute: is not unique: can't be used as FKEY target`);
40
- return new db_1.Type({ base, foreignKey: { attributeName, fieldName, tableName }, size, type });
40
+ FKEY(attribute, options) {
41
+ const { attributeName, base, fieldName, size, tableName, type } = attribute;
42
+ return new db_1.Type({ base, foreignKey: { attributeName, fieldName, options, tableName }, size, type });
41
43
  }
42
44
  INT(size) {
43
45
  const message = "Sedentary.INT: 'size' argument: Wrong value, expected 2 or 4";
@@ -59,7 +61,7 @@ class Sedentary {
59
61
  this.log("Connecting...");
60
62
  await this.db.connect();
61
63
  this.log("Connected, syncing...");
62
- await this.db.sync();
64
+ await this.db.syncDataBase();
63
65
  this.log("Synced");
64
66
  }
65
67
  catch (e) {
@@ -72,111 +74,131 @@ class Sedentary {
72
74
  await this.db.end();
73
75
  this.log("Connection closed");
74
76
  }
75
- model(name, attributes, options) {
76
- if (typeof name !== "string")
77
+ model(modelName, attributes, options) {
78
+ if (typeof modelName !== "string")
77
79
  throw new Error("Sedentary.model: 'name' argument: Wrong type, expected 'string'");
78
- if (this.models[name])
79
- throw new Error(`Sedentary.model: '${name}' model: Model already defined`);
80
+ if (this.models[modelName])
81
+ throw new Error(`Sedentary.model: '${modelName}' model: Model already defined`);
80
82
  if (!attributes)
81
83
  attributes = {};
82
84
  if (!(attributes instanceof Object))
83
- throw new Error(`Sedentary.model: '${name}' model: 'attributes' argument: Wrong type, expected 'Object'`);
85
+ throw new Error(`Sedentary.model: '${modelName}' model: 'attributes' argument: Wrong type, expected 'Object'`);
84
86
  if (!options)
85
87
  options = {};
86
88
  if (!(options instanceof Object))
87
- throw new Error(`Sedentary.model: '${name}' model: 'options' argument: Wrong type, expected 'Object'`);
89
+ throw new Error(`Sedentary.model: '${modelName}' model: 'options' argument: Wrong type, expected 'Object'`);
88
90
  for (const k in options)
89
91
  if (!allowedOption.includes(k))
90
- throw new Error(`Sedentary.model: '${name}' model: 'options' argument: Unknown '${k}' option`);
92
+ throw new Error(`Sedentary.model: '${modelName}' model: 'options' argument: Unknown '${k}' option`);
91
93
  if (options.int8id && options.parent)
92
- throw new Error(`Sedentary.model: '${name}' model: 'int8id' and 'parent' options conflict each other`);
94
+ throw new Error(`Sedentary.model: '${modelName}' model: 'int8id' and 'parent' options conflict each other`);
93
95
  if (options.int8id && options.primaryKey)
94
- throw new Error(`Sedentary.model: '${name}' model: 'int8id' and 'primaryKey' options conflict each other`);
96
+ throw new Error(`Sedentary.model: '${modelName}' model: 'int8id' and 'primaryKey' options conflict each other`);
95
97
  if (options.parent && options.primaryKey)
96
- throw new Error(`Sedentary.model: '${name}' model: 'parent' and 'primaryKey' options conflict each other`);
97
- const { indexes, int8id, parent, primaryKey, sync, tableName } = Object.assign({ sync: this.sync, tableName: name }, options);
98
+ throw new Error(`Sedentary.model: '${modelName}' model: 'parent' and 'primaryKey' options conflict each other`);
99
+ let autoIncrement = true;
100
+ const { indexes, int8id, parent, primaryKey, sync, tableName } = Object.assign({ sync: this.sync, tableName: modelName }, options);
98
101
  let { methods } = options;
99
102
  let aarray = int8id
100
- ? [new db_1.Attribute(Object.assign(Object.assign({}, this.INT8()), { attributeName: "id", fieldName: "id", notNull: true, tableName, unique: true }))]
101
- : [new db_1.Attribute(Object.assign(Object.assign({}, this.INT(4)), { attributeName: "id", fieldName: "id", notNull: true, tableName, unique: true }))];
103
+ ? [new db_1.Attribute(Object.assign(Object.assign({}, this.INT8()), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))]
104
+ : [new db_1.Attribute(Object.assign(Object.assign({}, this.INT(4)), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))];
102
105
  let constraints = [{ attribute: aarray[0], constraintName: `${tableName}_id_unique`, type: "u" }];
103
106
  const iarray = [];
104
107
  const pk = aarray[0];
105
108
  if (methods && !(methods instanceof Object))
106
- throw new Error(`Sedentary.model: '${name}' model: 'methods' option: Wrong type, expected 'Object'`);
109
+ throw new Error(`Sedentary.model: '${modelName}' model: 'methods' option: Wrong type, expected 'Object'`);
110
+ const originalMethods = methods;
107
111
  if (parent) {
108
- methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
109
112
  try {
110
113
  if (!parent.isModel())
111
114
  throw new Error();
112
115
  }
113
116
  catch (e) {
114
- throw new Error(`Sedentary.model: '${name}' model: 'parent' option: Wrong type, expected 'Model'`);
117
+ throw new Error(`Sedentary.model: '${modelName}' model: 'parent' option: Wrong type, expected 'Model'`);
115
118
  }
119
+ methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
116
120
  }
117
121
  if (primaryKey && typeof primaryKey !== "string")
118
- throw new Error(`Sedentary.model: '${name}' model: 'primaryKey' option: Wrong type, expected 'string'`);
122
+ throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Wrong type, expected 'string'`);
119
123
  if (primaryKey && !Object.keys(attributes).includes(primaryKey))
120
- throw new Error(`Sedentary.model: '${name}' model: 'primaryKey' option: Attribute '${primaryKey}' does not exists`);
124
+ throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Attribute '${primaryKey}' does not exists`);
121
125
  if (parent || primaryKey) {
126
+ autoIncrement = false;
122
127
  aarray = [];
123
128
  constraints = [];
124
129
  }
125
- for (const attributeName in attributes) {
130
+ for (const attributeName of Object.keys(attributes).sort()) {
126
131
  if (reservedNames.includes(attributeName))
127
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: Reserved name`);
132
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Reserved name`);
128
133
  const call = (defaultValue, fieldName, notNull, unique, func, message1, message2) => {
129
134
  if (func === this.FKEY)
130
135
  throw new Error(`${message1} 'this.FKEY' can't be used directly`);
131
136
  if (func !== this.DATETIME && func !== this.INT && func !== this.INT8 && func !== this.VARCHAR)
132
137
  throw new Error(`${message1} ${message2}`);
133
- return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, notNull, tableName, unique }, func()));
138
+ return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique }, func()));
134
139
  };
135
140
  const attributeDefinition = attributes[attributeName];
136
141
  let { base, defaultValue, fieldName, foreignKey, notNull, size, type, unique } = (() => {
137
142
  const ret = (() => {
138
143
  if (attributeDefinition instanceof db_1.Type)
139
- return new db_1.Attribute(Object.assign({ attributeName, fieldName: attributeName, notNull: false, tableName }, attributeDefinition));
144
+ return new db_1.Attribute(Object.assign({ attributeName, fieldName: attributeName, modelName, notNull: false, tableName }, attributeDefinition));
140
145
  if (attributeDefinition instanceof Function)
141
- return call(undefined, attributeName, false, false, attributeDefinition, `Sedentary.model: '${name}' model: '${attributeName}' attribute:`, "Wrong type, expected 'Attribute'");
146
+ return call(undefined, attributeName, false, false, attributeDefinition, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute:`, "Wrong type, expected 'Attribute'");
142
147
  if (!(attributeDefinition instanceof Object))
143
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: Wrong attribute type, expected 'Attribute'`);
148
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Wrong attribute type, expected 'Attribute'`);
144
149
  const attributeDefaults = Object.assign({ defaultValue: undefined, fieldName: attributeName, notNull: false, unique: false }, attributeDefinition);
145
150
  const { defaultValue, fieldName, notNull, unique, type } = attributeDefaults;
146
151
  if (defaultValue === null)
147
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really makes sense?`);
152
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really makes sense?`);
148
153
  if (typeof fieldName !== "string")
149
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
154
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
150
155
  if (typeof notNull !== "boolean")
151
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
156
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
152
157
  if (typeof unique !== "boolean")
153
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
158
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
154
159
  if (type === undefined)
155
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: Missing 'type' option`);
160
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Missing 'type' option`);
156
161
  if (type instanceof db_1.Type)
157
- return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, notNull, tableName, unique }, type));
162
+ return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique }, type));
158
163
  if (type instanceof Function)
159
- return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${name}' model: '${attributeName}' attribute: 'type' option:`, "Wrong type, expected 'Type'");
160
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'type' option: Wrong type, expected 'Type'`);
164
+ return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option:`, "Wrong type, expected 'Type'");
165
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option: Wrong type, expected 'Type'`);
161
166
  })();
162
167
  const { base, defaultValue } = ret;
163
168
  if (defaultValue !== undefined) {
164
169
  if (base === Date && !(defaultValue instanceof Date))
165
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'Date'`);
170
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'Date'`);
166
171
  if (base === Number && typeof defaultValue !== "number")
167
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'number'`);
172
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'number'`);
168
173
  if (base === String && typeof defaultValue !== "string")
169
- throw new Error(`Sedentary.model: '${name}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'string'`);
174
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'string'`);
170
175
  }
171
176
  return ret;
172
177
  })();
178
+ if (foreignKey) {
179
+ if (!foreignKey.options)
180
+ foreignKey.options = {};
181
+ if (!(foreignKey.options instanceof Object))
182
+ throw new Error(`Sedentary.FKEY: '${modelName}' model: '${attributeName}' attribute: Wrong options type, expected 'Object'`);
183
+ for (const k in foreignKey.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 = foreignKey.options[onChange];
189
+ if (!action)
190
+ action = foreignKey.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
+ }
173
195
  if (primaryKey === attributeName) {
174
196
  notNull = true;
175
197
  unique = true;
176
198
  }
177
199
  if (defaultValue)
178
200
  notNull = true;
179
- const attribute = new db_1.Attribute({ attributeName, base, defaultValue, fieldName, foreignKey, notNull, size, tableName, type, unique });
201
+ const attribute = new db_1.Attribute({ attributeName, base, defaultValue, fieldName, foreignKey, modelName, notNull, size, tableName, type, unique });
180
202
  aarray.push(attribute);
181
203
  if (foreignKey)
182
204
  constraints.push({ attribute, constraintName: `fkey_${fieldName}_${foreignKey.tableName}_${foreignKey.fieldName}`, type: "f" });
@@ -186,16 +208,16 @@ class Sedentary {
186
208
  if (indexes) {
187
209
  const flds = attributes;
188
210
  if (!(indexes instanceof Object))
189
- throw new Error(`Sedentary.model: '${name}' model: 'indexes' option: Wrong type, expected 'Object'`);
211
+ throw new Error(`Sedentary.model: '${modelName}' model: 'indexes' option: Wrong type, expected 'Object'`);
190
212
  for (const indexName in indexes) {
191
213
  if (aarray.filter(({ fieldName, unique }) => unique && `${tableName}_${fieldName}_unique` === indexName).length !== 0)
192
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: index name already inferred by the unique constraint on an attribute`);
214
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: index name already inferred by the unique constraint on an attribute`);
193
215
  const idx = indexes[indexName];
194
216
  const checkAttribute = (attribute, l) => {
195
217
  if (typeof attribute !== "string")
196
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: #${l + 1} attribute: Wrong type, expected 'string'`);
218
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: #${l + 1} attribute: Wrong type, expected 'string'`);
197
219
  if (!(attribute in flds))
198
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: #${l + 1} attribute: Unknown attribute '${attribute}'`);
220
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: #${l + 1} attribute: Unknown attribute '${attribute}'`);
199
221
  };
200
222
  let attributes;
201
223
  let type = "btree";
@@ -211,10 +233,10 @@ class Sedentary {
211
233
  else if (idx instanceof Object) {
212
234
  for (const k in idx)
213
235
  if (!["attributes", "type", "unique"].includes(k))
214
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: Unknown index option '${k}'`);
236
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Unknown index option '${k}'`);
215
237
  ({ attributes, type, unique } = Object.assign({ type: "btree", unique: false }, idx));
216
238
  if (!attributes)
217
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: Missing 'attributes' option`);
239
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Missing 'attributes' option`);
218
240
  if (attributes instanceof Array)
219
241
  attributes.forEach(checkAttribute);
220
242
  else if (typeof attributes === "string") {
@@ -222,21 +244,21 @@ class Sedentary {
222
244
  attributes = [attributes];
223
245
  }
224
246
  else
225
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: 'attributes' option: Wrong type, expected 'FieldNames'`);
247
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'attributes' option: Wrong type, expected 'FieldNames'`);
226
248
  if (typeof type !== "string")
227
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: 'type' option: Wrong type, expected 'string'`);
249
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'type' option: Wrong type, expected 'string'`);
228
250
  if (!["btree", "hash"].includes(type))
229
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: 'type' option: Wrong value, expected 'btree' or 'hash'`);
251
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'type' option: Wrong value, expected 'btree' or 'hash'`);
230
252
  if (typeof unique !== "boolean")
231
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: 'unique' option: Wrong type, expected 'boolean'`);
253
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'unique' option: Wrong type, expected 'boolean'`);
232
254
  }
233
255
  else
234
- throw new Error(`Sedentary.model: '${name}' model: '${indexName}' index: Wrong type, expected 'Object'`);
256
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Wrong type, expected 'Object'`);
235
257
  iarray.push({ fields: attributes, indexName, type, unique });
236
258
  }
237
259
  }
238
- this.db.addTable(new db_1.Table({ constraints, attributes: aarray, indexes: iarray, parent, primaryKey, sync, tableName }));
239
- this.models[name] = true;
260
+ this.db.tables.push(new db_1.Table({ autoIncrement, constraints, attributes: aarray, indexes: iarray, parent, sync, tableName }));
261
+ this.models[modelName] = true;
240
262
  const init = parent
241
263
  ? options.init
242
264
  ? function () {
@@ -245,9 +267,6 @@ class Sedentary {
245
267
  }
246
268
  : parent.init
247
269
  : options.init;
248
- const flds = {};
249
- for (const key in attributes)
250
- flds[key] = null;
251
270
  class Class {
252
271
  constructor() {
253
272
  if (init)
@@ -256,7 +275,7 @@ class Sedentary {
256
275
  save() {
257
276
  return new Promise((resolve, reject) => {
258
277
  const save = () => reject(new Error("eh no"));
259
- Object.defineProperty(save, "name", { value: name + ".save" });
278
+ Object.defineProperty(save, "name", { value: modelName + ".save" });
260
279
  setTimeout(save, 10);
261
280
  });
262
281
  }
@@ -266,18 +285,70 @@ class Sedentary {
266
285
  return resolve([new Class()]);
267
286
  reject(new Error("boh"));
268
287
  }, 10));
269
- Object.defineProperty(load, "name", { value: name + ".load" });
270
- const meta = { base: Number, type: "meta", tableName, primaryKey, init, methods };
288
+ Object.defineProperty(load, "name", { value: modelName + ".load" });
289
+ const metaAttributes = aarray.reduce((ret, curr) => {
290
+ ret[curr.attributeName] = curr;
291
+ return ret;
292
+ }, {});
293
+ const metaForeignKeys = aarray
294
+ .filter(_ => _.foreignKey)
295
+ .reduce((ret, curr) => {
296
+ ret[curr.attributeName] = curr;
297
+ return ret;
298
+ }, {});
299
+ const meta = new db_1.Meta({ base: Number, attributes: metaAttributes, foreignKeys: metaForeignKeys, modelName, parent: parent, type: "meta", tableName, primaryKey, init, methods });
300
+ for (const foreignKey in metaForeignKeys) {
301
+ if (foreignKey + "Load" in metaAttributes)
302
+ throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute`);
303
+ if (originalMethods && foreignKey + "Load" in originalMethods)
304
+ throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method`);
305
+ }
306
+ if (originalMethods)
307
+ for (const method in originalMethods)
308
+ if (method in metaAttributes)
309
+ throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute`);
310
+ const checkParent = (parent) => {
311
+ if (!parent)
312
+ return;
313
+ for (const attribute in metaAttributes) {
314
+ if (attribute in parent.attributes)
315
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an attribute of '${parent.modelName}' model`);
316
+ if (parent.methods && attribute in parent.methods)
317
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with a method of '${parent.modelName}' model`);
318
+ for (const foreignKey in parent.foreignKeys)
319
+ if (attribute === foreignKey + "Load")
320
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attribute}' attribute: conflicts with an inferred methods of '${parent.modelName}' model`);
321
+ }
322
+ for (const foreignKey in metaForeignKeys) {
323
+ if (foreignKey + "Load" in parent.attributes)
324
+ throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with an attribute of '${parent.modelName}' model`);
325
+ if (parent.methods && foreignKey + "Load" in parent.methods)
326
+ throw new Error(`Sedentary.model: '${modelName}' model: '${foreignKey}' attribute: '${foreignKey}Load' inferred methods conflicts with a method of '${parent.modelName}' model`);
327
+ }
328
+ if (originalMethods) {
329
+ for (const method in originalMethods) {
330
+ if (method in parent.attributes)
331
+ throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an attribute of '${parent.modelName}' model`);
332
+ for (const foreignKey in parent.foreignKeys)
333
+ if (foreignKey + "Load" === method)
334
+ throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with an inferred methods of '${parent.modelName}' model`);
335
+ if (parent.methods && method in parent.methods)
336
+ throw new Error(`Sedentary.model: '${modelName}' model: '${method}' method: conflicts with a method of '${parent.modelName}' model`);
337
+ }
338
+ }
339
+ checkParent(parent.parent);
340
+ };
341
+ checkParent(parent);
271
342
  Object.defineProperty(Class, "isModel", { value: () => true });
272
343
  Object.defineProperty(Class, "load", { value: load });
273
- Object.defineProperty(Class, "meta", { value: new db_1.Meta(meta) });
274
- Object.defineProperty(Class, "name", { value: name });
275
- Object.defineProperty(Class.prototype.save, "name", { value: name + ".save" });
276
- Object.assign(Class, new db_1.Meta(meta));
344
+ Object.defineProperty(Class, "meta", { value: meta });
345
+ Object.defineProperty(Class, "name", { value: modelName });
346
+ Object.defineProperty(Class.prototype.save, "name", { value: modelName + ".save" });
347
+ Object.assign(Class, meta);
277
348
  Object.assign(Class.prototype, methods);
278
349
  for (const attribute of aarray)
279
350
  Object.defineProperty(Class, attribute.attributeName, { value: attribute });
280
- for (const key of ["attributeName", "base", "fieldName", "size", "type", "unique"])
351
+ for (const key of ["attributeName", "base", "fieldName", "modelName", "size", "type", "unique"])
281
352
  Object.defineProperty(Class, key, { value: pk[key] });
282
353
  return Class;
283
354
  }
@@ -319,6 +390,7 @@ class Super extends db.model("Super", {
319
390
  this.num = 0;
320
391
  const a = this.nLoad ? await this.nLoad() : { prova: () => null };
321
392
  a.prova();
393
+ this.prova();
322
394
  }
323
395
  }) {
324
396
  }
@@ -335,9 +407,9 @@ class Current extends db.model("Current", { b: { type: db.FKEY(Next), unique: tr
335
407
  }
336
408
  }) {
337
409
  }
338
- class Last extends db.model("Last", { b: db.FKEY(Current.b) }, {
410
+ class Last extends db.model("Last", { c: db.FKEY(Current.b) }, {
339
411
  init: function () {
340
- this.b = 24;
412
+ this.c = 24;
341
413
  },
342
414
  parent: Next
343
415
  }) {
@@ -353,3 +425,29 @@ class Last extends db.model("Last", { b: db.FKEY(Current.b) }, {
353
425
  }
354
426
  return true;
355
427
  })();
428
+ /*
429
+ export let factory = () => {
430
+ class Foo {
431
+ a = 3;
432
+ b = 'bar'
433
+ c?: boolean
434
+ }
435
+ return Foo as (new () => { [key in keyof Foo]: Foo[key] })
436
+ };
437
+
438
+ export const FooConstr = factory()
439
+ export type TypeExtractor<T> = T extends (new() => infer E) ? E : never;
440
+ export type FooType = TypeExtractor<typeof FooConstr>;
441
+
442
+ const foo = new FooConstr()
443
+
444
+ function rino(a:FooType){
445
+ if(a instanceof FooConstr){console.log("sisi")}
446
+ if(a instanceof FooType){console.log("sisi")}
447
+ }
448
+
449
+ rino(foo);
450
+
451
+
452
+ B.prototype instanceof A
453
+ */
package/lib/db.d.ts CHANGED
@@ -3,6 +3,11 @@ export declare class Entry {
3
3
  init(): void;
4
4
  save(): Promise<boolean>;
5
5
  }
6
+ export declare type ForeignKeyActions = "cascade" | "no action" | "restrict" | "set default" | "set null";
7
+ export interface ForeignKeyOptions {
8
+ onDelete?: ForeignKeyActions;
9
+ onUpdate?: ForeignKeyActions;
10
+ }
6
11
  export declare class Type<N extends Natural, E> {
7
12
  base: unknown;
8
13
  entry?: E;
@@ -12,16 +17,25 @@ export declare class Type<N extends Natural, E> {
12
17
  foreignKey?: {
13
18
  attributeName: string;
14
19
  fieldName: string;
20
+ options?: ForeignKeyOptions;
15
21
  tableName: string;
16
22
  };
17
23
  constructor(from: Type<N, E>);
18
24
  }
19
25
  export declare class Meta<N extends Natural, E> extends Type<N, E> {
26
+ attributes: {
27
+ [key: string]: unknown;
28
+ };
29
+ foreignKeys: {
30
+ [key: string]: unknown;
31
+ };
20
32
  init: () => void;
21
33
  isModel?: () => boolean;
22
34
  methods: {
23
35
  [key: string]: () => unknown;
24
36
  };
37
+ modelName: string;
38
+ parent?: Meta<Natural, E>;
25
39
  primaryKey: string;
26
40
  tableName: string;
27
41
  constructor(from: Meta<N, E>);
@@ -30,6 +44,7 @@ export declare class Attribute<N extends Natural, E> extends Type<N, E> {
30
44
  attributeName: string;
31
45
  defaultValue?: unknown;
32
46
  fieldName: string;
47
+ modelName: string;
33
48
  notNull: boolean;
34
49
  tableName: string;
35
50
  unique?: boolean;
@@ -48,32 +63,30 @@ export interface Index {
48
63
  }
49
64
  interface ITable {
50
65
  attributes: Attribute<Natural, unknown>[];
66
+ autoIncrement: boolean;
51
67
  constraints: Constraint[];
52
68
  indexes: Index[];
53
- oid?: number;
54
69
  parent: Meta<Natural, unknown>;
55
- primaryKey: string;
56
70
  sync: boolean;
57
71
  tableName: string;
58
72
  }
59
73
  declare const Table_base: new (defaults?: ITable) => ITable;
60
74
  export declare class Table extends Table_base {
61
- autoIncrement: boolean;
62
- autoIncrementOwn: boolean;
63
- constructor(defaults: ITable);
75
+ autoIncrementOwn?: boolean;
76
+ oid?: number;
77
+ findField(name: string): Attribute<Natural, unknown>;
64
78
  }
65
79
  export declare abstract class DB {
66
- tables: {
67
- [key: string]: Table;
68
- };
69
- tablesArr: Table[];
80
+ tables: Table[];
70
81
  protected log: (...data: unknown[]) => void;
82
+ protected sync: boolean;
71
83
  abstract connect(): Promise<void>;
72
84
  abstract end(): Promise<void>;
73
85
  constructor(log: (message: string) => void);
74
- addTable(table: Table): void;
86
+ findTable(name: string): Table;
75
87
  protected indexesEq(a: Index, b: Index): boolean;
76
- sync(): Promise<void>;
88
+ syncDataBase(): Promise<void>;
89
+ protected syncLog(...data: unknown[]): void;
77
90
  abstract dropConstraints(table: Table): Promise<number[]>;
78
91
  abstract dropFields(table: Table): Promise<void>;
79
92
  abstract dropIndexes(table: Table, constraintIndexes: number[]): Promise<void>;