sedentary 0.0.17 → 0.0.21

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.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 { Attribute, DB, EntryBase, ForeignKeyOptions, Natural, Type } from "./lib/db";
2
+ export { EntryBase, 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;
@@ -12,17 +12,13 @@ export declare type AttributeDefinition<N extends Natural, E> = TypeDefinition<N
12
12
  export declare type AttributesDefinition = {
13
13
  [key: string]: AttributeDefinition<Natural, unknown>;
14
14
  };
15
- declare type KeysAttributes<T, k> = T extends AttributeDefinition<Natural, infer E> ? (E extends Entry ? k : never) : never;
16
- declare type Keys<F extends AttributesDefinition> = {
17
- [f in keyof F]?: KeysAttributes<F[f], f>;
18
- }[keyof F];
19
- declare type Methods<T> = {
20
- [key: string]: (this: T) => unknown;
21
- };
15
+ declare type ForeignKeysAttributes<T, k> = T extends AttributeDefinition<Natural, infer E> ? (E extends EntryBase ? k : never) : never;
16
+ declare type ForeignKeys<A extends AttributesDefinition> = {
17
+ [a in keyof A]?: ForeignKeysAttributes<A[a], a>;
18
+ }[keyof A];
22
19
  declare type Native__<T> = T extends Type<infer N, unknown> ? N : never;
23
20
  declare type Native_<T> = T extends () => Type<infer N, infer E> ? Native__<Type<N, E>> : Native__<T>;
24
21
  declare type Native<T> = T extends AttributeOptions<infer N, infer E> ? Native__<Type<N, E>> : Native_<T>;
25
- declare type Parent<T> = T extends Meta<Natural, infer E> ? E : never;
26
22
  export declare type IndexAttributes = string[] | string;
27
23
  export interface IndexOptions {
28
24
  attributes: IndexAttributes;
@@ -33,34 +29,59 @@ export declare type IndexDefinition = IndexAttributes | IndexOptions;
33
29
  export declare type IndexesDefinition = {
34
30
  [key: string]: IndexDefinition;
35
31
  };
36
- declare type BaseModelOptions<T> = {
32
+ interface BaseModelOptions {
37
33
  indexes?: IndexesDefinition;
38
- init?: (this: T) => void;
39
34
  sync?: boolean;
40
35
  tableName?: string;
41
- };
42
- export declare type ModelOptions<K extends string, M extends Methods<T>, P extends Meta<Natural, Entry>, T extends Entry> = BaseModelOptions<T> & {
36
+ }
37
+ export interface ModelOptions extends BaseModelOptions {
43
38
  int8id?: boolean;
44
- methods?: M;
45
- parent?: P;
46
- primaryKey?: K;
39
+ parent?: Type<Natural, EntryBase>;
40
+ primaryKey?: string;
41
+ }
42
+ declare type ConditionAttribute<N extends Natural> = N | [">" | "<" | ">=" | "<=" | "<>", N] | ["LIKE", string] | ["IN", ...N[]];
43
+ declare type ConditionBase<A extends AttributesDefinition> = string | {
44
+ [a in keyof A]?: ConditionAttribute<Native<A[a]>>;
47
45
  };
48
- declare type ForeignKey<T> = T extends AttributeDefinition<Natural, infer E> ? () => Promise<E> : never;
49
- declare type ModelWithMetods<A extends AttributesDefinition, M> = {
50
- [a in keyof A]?: Native<A[a]>;
51
- } & {
52
- [a in Keys<A> & string as `${a}Load`]?: ForeignKey<A[a]>;
53
- } & M;
54
- declare type Model<A extends AttributesDefinition> = {
46
+ declare type Condition<A extends AttributesDefinition> = ConditionBase<A> | ["NOT", Condition<A>] | ["AND", ...Condition<A>[]] | ["OR", ...Condition<A>[]];
47
+ declare type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
48
+ declare type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;
49
+ declare type BaseKeyType<B extends boolean> = IsUnion<B> extends true ? number : B extends true ? string : number;
50
+ declare type KeyType<B extends boolean, P extends ModelStd> = P extends new () => EntryBase ? (P extends Attribute<infer T, EntryBase> ? T : never) : BaseKeyType<B>;
51
+ declare type ForeignKey<A> = A extends AttributeDefinition<Natural, infer E> ? () => Promise<E> : never;
52
+ declare type EntryBaseAttributes<A extends AttributesDefinition> = {
55
53
  [a in keyof A]?: Native<A[a]>;
56
- } & {
57
- [a in Keys<A> & string as `${a}Load`]?: ForeignKey<A[a]>;
58
54
  };
59
- declare type Ancestor<A, N extends Natural, T extends Entry> = (new () => T) & {
60
- [a in keyof A]?: Meta<Native<A[a]>, T>;
55
+ declare type EntryMethodsBase<P extends ModelStd> = P extends new () => EntryBase ? P["methods"] : EntryBase;
56
+ declare type EntryMethodsFK<A extends AttributesDefinition> = {
57
+ [a in ForeignKeys<A> & string as `${a}Load`]: ForeignKey<A[a]>;
58
+ };
59
+ declare type EntryMethods<A extends AttributesDefinition, P extends ModelStd> = keyof EntryMethodsFK<A> extends never ? EntryMethodsBase<P> : EntryMethodsBase<P> & EntryMethodsFK<A>;
60
+ declare type ModelAttributesIf<A extends AttributesDefinition, T> = keyof A extends never ? T : T & A;
61
+ declare type ModelAttributes<A extends AttributesDefinition, B extends boolean, K extends string, P extends ModelStd> = K extends keyof A ? A : ModelAttributesIf<A, P extends new () => EntryBase ? P["attributes"] : {
62
+ id: Type<BaseKeyType<B>, unknown>;
63
+ }>;
64
+ declare type ModelBase<N extends Natural, A extends AttributesDefinition, EA extends Record<string, Natural | undefined>, EM extends EntryBase, E extends EntryBase> = (new (from?: EA) => E) & Attribute<N, E> & {
65
+ attributes: A;
66
+ foreignKeys: Record<string, boolean>;
67
+ methods: EM;
68
+ parent?: ModelStd;
69
+ tableName: string;
70
+ load: (where?: Condition<A>) => Promise<E[]>;
61
71
  } & {
62
- load: (boh: boolean) => Promise<T[]>;
63
- } & Meta<N, T>;
72
+ [a in keyof A]: Attribute<Native<A[a]>, E>;
73
+ };
74
+ declare type Model<N extends Natural, A extends AttributesDefinition, EM extends EntryBase> = ModelBase<N, A, EntryBaseAttributes<A>, EM, EntryBaseAttributes<A> & EM>;
75
+ declare type ModelStd = Attribute<Natural, EntryBase> & {
76
+ attributes: AttributesDefinition;
77
+ foreignKeys: Record<string, boolean>;
78
+ methods: EntryBase;
79
+ parent?: ModelStd;
80
+ };
81
+ export declare type Entry<M> = M extends new () => infer E ? E : never;
82
+ export declare type Where<M> = M extends {
83
+ load: (where: infer T) => void;
84
+ } ? Exclude<T, undefined> : never;
64
85
  export interface SedentaryOptions {
65
86
  log?: ((message: string) => void) | null;
66
87
  serverless?: boolean;
@@ -73,45 +94,22 @@ export declare class Sedentary {
73
94
  private models;
74
95
  constructor(filename: string, options?: SedentaryOptions);
75
96
  DATETIME(): Type<Date, unknown>;
76
- FKEY<N extends Natural, E extends Entry>(attribute: Type<N, E>): Type<N, E>;
97
+ FKEY<N extends Natural, E extends EntryBase>(attribute: Attribute<N, E>, options?: ForeignKeyOptions): Type<N, E>;
77
98
  INT(size?: number): Type<number, unknown>;
78
99
  INT8(): Type<string, unknown>;
79
100
  VARCHAR(size?: number): Type<string, unknown>;
101
+ checkSize(size: number, message: string): number;
80
102
  connect(): Promise<void>;
81
103
  end(): Promise<void>;
82
- model<A extends AttributesDefinition, M extends Methods<T>, T extends Entry & {
83
- id?: string;
84
- } & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
85
- int8id: true;
86
- methods: M;
87
- }): Ancestor<A, string, 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> & {
89
- methods: M;
90
- primaryKey: K;
91
- }): Ancestor<A, N, 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> & {
93
- methods: M;
94
- parent: P;
95
- }): Ancestor<A, N, T>;
96
- model<A extends AttributesDefinition, M extends Methods<T>, T extends Entry & {
97
- id?: number;
98
- } & ModelWithMetods<A, M>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
99
- methods: M;
100
- }): Ancestor<A, number, T>;
101
- model<A extends AttributesDefinition, T extends Entry & {
102
- id?: string;
103
- } & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
104
- int8id: true;
105
- }): Ancestor<A, string, 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> & {
107
- primaryKey: K;
108
- }): Ancestor<A, N, 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> & {
110
- parent: P;
111
- }): Ancestor<A, N, T>;
112
- model<A extends AttributesDefinition, T extends Entry & {
113
- id?: number;
114
- } & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T>): Ancestor<A, number, T>;
115
- checkSize(size: number, message: string): number;
104
+ model<A extends AttributesDefinition, B extends boolean, K extends string, P extends ModelStd, EM extends EntryMethods<A, P>>(modelName: string, attributes: A, options?: BaseModelOptions & {
105
+ int8id?: B;
106
+ parent?: P;
107
+ primaryKey?: K | keyof A;
108
+ }): Model<K extends keyof A ? Native<A[K]> : KeyType<B, P>, ModelAttributes<A, B, K, P>, EM>;
109
+ model<A extends AttributesDefinition, B extends boolean, K extends string, P extends ModelStd, EA extends EntryBaseAttributes<ModelAttributes<A, B, K, P>>, EM extends EntryMethods<A, P>, M extends Record<string, <S extends M>(this: EA & EM & S, ...args: any[]) => void>>(modelName: string, attributes: A, options: BaseModelOptions & {
110
+ int8id?: B;
111
+ parent?: P;
112
+ primaryKey?: K | keyof A;
113
+ }, methods: M & Record<keyof M, (this: EA & EM & M, ...args: any[]) => void>): Model<K extends keyof A ? Native<A[K]> : KeyType<B, P>, ModelAttributes<A, B, K, P>, EM & M>;
116
114
  }
117
115
  export declare const Package: typeof Sedentary;
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,7 +81,8 @@ class Sedentary {
74
81
  await this.db.end();
75
82
  this.log("Connection closed");
76
83
  }
77
- model(modelName, attributes, options) {
84
+ /* eslint-enable @typescript-eslint/no-explicit-any */
85
+ model(modelName, attributes, options, methods) {
78
86
  if (typeof modelName !== "string")
79
87
  throw new Error("Sedentary.model: 'name' argument: Wrong type, expected 'string'");
80
88
  if (this.models[modelName])
@@ -98,7 +106,6 @@ class Sedentary {
98
106
  throw new Error(`Sedentary.model: '${modelName}' model: 'parent' and 'primaryKey' options conflict each other`);
99
107
  let autoIncrement = true;
100
108
  const { indexes, int8id, parent, primaryKey, sync, tableName } = Object.assign({ sync: this.sync, tableName: modelName }, options);
101
- let { methods } = options;
102
109
  let aarray = int8id
103
110
  ? [new db_1.Attribute(Object.assign(Object.assign({}, this.INT8()), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))]
104
111
  : [new db_1.Attribute(Object.assign(Object.assign({}, this.INT(4)), { attributeName: "id", fieldName: "id", modelName, notNull: true, tableName, unique: true }))];
@@ -107,16 +114,11 @@ class Sedentary {
107
114
  const pk = aarray[0];
108
115
  if (methods && !(methods instanceof Object))
109
116
  throw new Error(`Sedentary.model: '${modelName}' model: 'methods' option: Wrong type, expected 'Object'`);
110
- if (parent) {
111
- try {
112
- if (!parent.isModel())
113
- throw new Error();
114
- }
115
- catch (e) {
117
+ const originalMethods = methods;
118
+ if (parent)
119
+ if (!parent.attributes)
116
120
  throw new Error(`Sedentary.model: '${modelName}' model: 'parent' option: Wrong type, expected 'Model'`);
117
- }
118
- methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
119
- }
121
+ //methods = (methods ? { ...(parent.methods || {}), ...methods } : parent.methods) as never;
120
122
  if (primaryKey && typeof primaryKey !== "string")
121
123
  throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Wrong type, expected 'string'`);
122
124
  if (primaryKey && !Object.keys(attributes).includes(primaryKey))
@@ -174,6 +176,23 @@ class Sedentary {
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;
@@ -241,120 +260,77 @@ class Sedentary {
241
260
  }
242
261
  this.db.tables.push(new db_1.Table({ autoIncrement, constraints, attributes: aarray, indexes: iarray, parent, sync, tableName }));
243
262
  this.models[modelName] = 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);
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: modelName + ".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
317
  Object.defineProperty(load, "name", { value: modelName + ".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: modelName });
279
- Object.defineProperty(Class.prototype.save, "name", { value: modelName + ".save" });
280
- Object.assign(Class, new db_1.Meta(meta));
281
- Object.assign(Class.prototype, methods);
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", "modelName", "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
- this.prova();
327
- }
328
- }) {
329
- }
330
- class Next extends db.model("Next", { a: db.INT, b: db.INT }, {
331
- init: function () {
332
- this.a = 23;
333
- },
334
- primaryKey: "a"
335
- }) {
336
- }
337
- class Current extends db.model("Current", { b: { type: db.FKEY(Next), unique: true } }, {
338
- init: function () {
339
- this.b = 24;
340
- }
341
- }) {
342
- }
343
- class Last extends db.model("Last", { b: db.FKEY(Current.b) }, {
344
- init: function () {
345
- this.b = 24;
346
- },
347
- parent: Next
348
- }) {
349
- }
350
- (async function () {
351
- const item = new Super();
352
- try {
353
- await item.save();
354
- }
355
- catch (e) {
356
- console.log(Item.load, item.save, await Item.load(true), item, e.message);
357
- console.log(new Next(), Next.load, await Next.load(true), new Last(), item.prova());
358
- }
359
- return true;
360
- })();
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,21 +20,14 @@ 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,6 +35,8 @@ export declare class Attribute<N extends Natural, E> extends Type<N, E> {
34
35
  notNull: boolean;
35
36
  tableName: string;
36
37
  unique?: boolean;
38
+ }
39
+ export declare class Attribute<N extends Natural, E> extends Type<N, E> {
37
40
  constructor(from: Attribute<N, E>);
38
41
  }
39
42
  export interface Constraint {
@@ -52,11 +55,11 @@ interface ITable {
52
55
  autoIncrement: boolean;
53
56
  constraints: Constraint[];
54
57
  indexes: Index[];
55
- parent: Meta<Natural, unknown>;
58
+ parent: any;
56
59
  sync: boolean;
57
60
  tableName: string;
58
61
  }
59
- declare const Table_base: new (defaults?: ITable) => ITable;
62
+ declare const Table_base: new (defaults?: ITable | undefined) => ITable;
60
63
  export declare class Table extends Table_base {
61
64
  autoIncrementOwn?: boolean;
62
65
  oid?: number;
@@ -64,7 +67,7 @@ export declare class Table extends Table_base {
64
67
  }
65
68
  export declare abstract class DB {
66
69
  tables: Table[];
67
- protected log: (...data: unknown[]) => void;
70
+ protected log: (message: string) => void;
68
71
  protected sync: boolean;
69
72
  abstract connect(): Promise<void>;
70
73
  abstract end(): Promise<void>;
@@ -72,7 +75,7 @@ export declare abstract class DB {
72
75
  findTable(name: string): Table;
73
76
  protected indexesEq(a: Index, b: Index): boolean;
74
77
  syncDataBase(): Promise<void>;
75
- protected syncLog(...data: unknown[]): void;
78
+ protected syncLog(message: string): void;
76
79
  abstract dropConstraints(table: Table): Promise<number[]>;
77
80
  abstract dropFields(table: Table): Promise<void>;
78
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);
@@ -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;
package/lib/minidb.js CHANGED
@@ -16,14 +16,18 @@ class MiniDB extends db_1.DB {
16
16
  this.body = JSON.parse((await readFile(this.file)).toString());
17
17
  }
18
18
  catch (e) {
19
- if (e.code !== "ENOENT")
19
+ const err = e;
20
+ if (err.code !== "ENOENT")
20
21
  throw e;
21
22
  }
22
23
  }
23
24
  async dropConstraints(table) {
24
25
  const { constraints } = this.body.tables[table.tableName] || { constraints: { f: {}, u: {} } };
25
26
  for (const constraint of Object.keys(constraints.f).sort()) {
26
- if (!table.constraints.filter(({ constraintName, type }) => constraintName === constraint && type === "f").length) {
27
+ const arr = table.constraints.filter(({ constraintName, type }) => constraintName === constraint && type === "f");
28
+ const dbOptions = arr.length ? arr[0].attribute.foreignKey.options : { onDelete: "delete", onUpdate: "delete" };
29
+ const inOptions = constraints.f[constraint].options;
30
+ if (dbOptions.onDelete !== inOptions.onDelete || dbOptions.onUpdate !== inOptions.onUpdate) {
27
31
  this.syncLog(`'${table.tableName}': Removing foreign key: '${constraint}'`);
28
32
  if (this.sync)
29
33
  delete constraints.f[constraint];
@@ -31,7 +35,7 @@ class MiniDB extends db_1.DB {
31
35
  }
32
36
  for (const constraint of Object.keys(constraints.u).sort()) {
33
37
  if (!table.constraints.filter(({ constraintName, type }) => constraintName === constraint && type === "u").length) {
34
- this.syncLog(`'${table.tableName}': Removing unique constraint from field: '${constraints.u[constraint].fieldName}'`);
38
+ this.syncLog(`'${table.tableName}': Removing unique constraint from field: '${constraints.u[constraint].on}'`);
35
39
  if (this.sync)
36
40
  delete constraints.u[constraint];
37
41
  }
@@ -70,20 +74,20 @@ class MiniDB extends db_1.DB {
70
74
  async syncConstraints(table) {
71
75
  const { constraints } = this.body.tables[table.tableName] || { constraints: { f: {}, u: {} } };
72
76
  for (const constraint of table.constraints) {
73
- const { constraintName, type } = constraint;
74
- const { fieldName, foreignKey } = constraint.attribute;
77
+ const { attribute, constraintName, type } = constraint;
75
78
  if (!constraints[type][constraintName]) {
76
- switch (type) {
77
- case "f":
78
- this.syncLog(`'${table.tableName}': Adding foreign key '${constraint.constraintName}' on field: '${fieldName}' references '${foreignKey.tableName}(${foreignKey.fieldName})'`);
79
- if (this.sync)
80
- constraints[type][constraintName] = { fieldName, toField: foreignKey.fieldName, toTable: foreignKey.tableName };
81
- break;
82
- case "u":
83
- this.syncLog(`'${table.tableName}': Adding unique constraint on field: '${fieldName}'`);
84
- if (this.sync)
85
- constraints[type][constraintName] = { fieldName };
86
- break;
79
+ if (type === "f") {
80
+ const { fieldName, options, tableName } = attribute.foreignKey;
81
+ const onDelete = options.onDelete !== "no action" ? ` on delete ${options.onDelete}` : "";
82
+ const onUpdate = options.onUpdate !== "no action" ? ` on update ${options.onUpdate}` : "";
83
+ this.syncLog(`'${table.tableName}': Adding foreign key '${constraint.constraintName}' on field: '${attribute.fieldName}' references '${tableName}(${fieldName})'${onDelete}${onUpdate}`);
84
+ if (this.sync)
85
+ constraints[type][constraintName] = { on: attribute.fieldName, options, fieldName, tableName };
86
+ }
87
+ else {
88
+ this.syncLog(`'${table.tableName}': Adding unique constraint on field: '${attribute.fieldName}'`);
89
+ if (this.sync)
90
+ constraints[type][constraintName] = { on: attribute.fieldName };
87
91
  }
88
92
  }
89
93
  }
@@ -0,0 +1,2 @@
1
+ export declare class Transaction {
2
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Transaction = void 0;
4
+ class Transaction {
5
+ }
6
+ exports.Transaction = Transaction;
package/package.json CHANGED
@@ -5,16 +5,17 @@
5
5
  "description": "The ORM which never needs to migrate",
6
6
  "devDependencies": {
7
7
  "@types/mocha": "9.0.0",
8
- "@types/node": "16.11.10",
8
+ "@types/node": "17.0.5",
9
9
  "@types/yamljs": "0.2.31",
10
- "@typescript-eslint/eslint-plugin": "5.4.0",
11
- "@typescript-eslint/parser": "5.4.0",
12
- "eslint": "8.3.0",
10
+ "@typescript-eslint/eslint-plugin": "5.8.1",
11
+ "@typescript-eslint/parser": "5.8.1",
12
+ "eslint": "8.5.0",
13
13
  "mocha": "9.1.3",
14
14
  "nyc": "15.1.0",
15
- "prettier": "2.5.0",
15
+ "prettier": "2.5.1",
16
16
  "ts-node": "10.4.0",
17
- "typescript": "4.5.2",
17
+ "tsd": "0.19.0",
18
+ "typescript": "4.5.4",
18
19
  "yamljs": "0.3.0"
19
20
  },
20
21
  "engines": {
@@ -55,6 +56,23 @@
55
56
  "tsc": "tsc --declaration",
56
57
  "version": "node -r ts-node/register utils.ts version"
57
58
  },
59
+ "tsd": {
60
+ "compilerOptions": {
61
+ "alwaysStrict": true,
62
+ "declaration": true,
63
+ "esModuleInterop": true,
64
+ "module": "commonjs",
65
+ "noImplicitAny": true,
66
+ "noImplicitReturns": true,
67
+ "noImplicitThis": true,
68
+ "strict": true,
69
+ "strictBindCallApply": true,
70
+ "strictFunctionTypes": true,
71
+ "strictNullChecks": true,
72
+ "strictPropertyInitialization": true,
73
+ "target": "es2017"
74
+ }
75
+ },
58
76
  "types": "index.d.ts",
59
- "version": "0.0.17"
77
+ "version": "0.0.21"
60
78
  }
package/lib/log.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export declare function createLogger(log: ((message: string) => void) | null | undefined): {
2
- (...data: any[]): void;
3
- (message?: any, ...optionalParams: any[]): void;
4
- };
package/lib/log.js DELETED
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createLogger = void 0;
4
- const console_1 = require("console");
5
- const stream_1 = require("stream");
6
- class Logger extends stream_1.Writable {
7
- constructor(log) {
8
- super();
9
- this.log = log;
10
- }
11
- _write(chunk, encoding, callback) {
12
- this.log(chunk.toString());
13
- callback();
14
- }
15
- }
16
- function createLogger(log) {
17
- // eslint-disable-next-line no-console
18
- return log ? new console_1.Console(new Logger(log)).log : log === null ? () => { } : console.log;
19
- }
20
- exports.createLogger = createLogger;
package/lib/log.ts DELETED
@@ -1,22 +0,0 @@
1
- import { Console } from "console";
2
- import { Writable } from "stream";
3
-
4
- class Logger extends Writable {
5
- private log: (message: string) => void;
6
-
7
- constructor(log: (message: string) => void) {
8
- super();
9
-
10
- this.log = log;
11
- }
12
-
13
- _write(chunk: Buffer, encoding: string, callback: () => void) {
14
- this.log(chunk.toString());
15
- callback();
16
- }
17
- }
18
-
19
- export function createLogger(log: ((message: string) => void) | null | undefined) {
20
- // eslint-disable-next-line no-console
21
- return log ? new Console(new Logger(log)).log : log === null ? () => {} : console.log;
22
- }
package/requirements.txt DELETED
@@ -1,2 +0,0 @@
1
- sphinx
2
- sphinx_rtd_theme