sedentary 0.0.13 → 0.0.17

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,79 +1,117 @@
1
- import { DB, Entry, Index, Meta, Natural, Type } from "./lib/db";
2
- declare type TypeDefinition<N extends Natural, E extends Entry> = (() => Type<N, E>) | Type<N, E>;
3
- interface FieldOptions<N extends Natural, E extends Entry> {
1
+ import { DB, Entry, Meta, Natural, Type } from "./lib/db";
2
+ export { Entry, Natural, Type } from "./lib/db";
3
+ export declare type TypeDefinition<N extends Natural, E> = (() => Type<N, E>) | Type<N, E>;
4
+ export interface AttributeOptions<N extends Natural, E> {
4
5
  defaultValue?: N;
5
6
  fieldName?: string;
6
7
  notNull?: boolean;
7
8
  type: TypeDefinition<N, E>;
8
9
  unique?: boolean;
9
10
  }
10
- declare type FieldDefinition<N extends Natural, E extends Entry> = TypeDefinition<N, E> | FieldOptions<N, E>;
11
- declare type FieldsDefinition = {
12
- [key: string]: FieldDefinition<Natural, Entry>;
11
+ export declare type AttributeDefinition<N extends Natural, E> = TypeDefinition<N, E> | AttributeOptions<N, E>;
12
+ export declare type AttributesDefinition = {
13
+ [key: string]: AttributeDefinition<Natural, unknown>;
13
14
  };
14
- declare type ForeignKeyFileds<T, k> = T extends FieldDefinition<Natural, infer E> ? (E extends Entry ? k : never) : never;
15
- declare type ForeignKey<T> = T extends FieldDefinition<Natural, infer E> ? () => Promise<E> : never;
16
- declare type Keys<F extends FieldsDefinition> = {
17
- [f in keyof F]?: ForeignKeyFileds<F[f], f>;
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
18
  }[keyof F];
19
19
  declare type Methods<T> = {
20
20
  [key: string]: (this: T) => unknown;
21
21
  };
22
- declare type Native__<T> = T extends Type<infer N, Entry> ? N : never;
22
+ declare type Native__<T> = T extends Type<infer N, unknown> ? N : never;
23
23
  declare type Native_<T> = T extends () => Type<infer N, infer E> ? Native__<Type<N, E>> : Native__<T>;
24
- declare type Native<T> = T extends FieldOptions<infer N, infer E> ? Native__<Type<N, E>> : Native_<T>;
25
- declare type Parent<T> = T extends Meta<Natural, infer R> ? R : never;
26
- declare type Options<M, T> = {
27
- indexes?: {
28
- [key: string]: Index;
29
- };
24
+ 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
+ export declare type IndexAttributes = string[] | string;
27
+ export interface IndexOptions {
28
+ attributes: IndexAttributes;
29
+ type?: "btree" | "hash";
30
+ unique?: boolean;
31
+ }
32
+ export declare type IndexDefinition = IndexAttributes | IndexOptions;
33
+ export declare type IndexesDefinition = {
34
+ [key: string]: IndexDefinition;
35
+ };
36
+ declare type BaseModelOptions<T> = {
37
+ indexes?: IndexesDefinition;
30
38
  init?: (this: T) => void;
31
- methods?: M;
32
39
  sync?: boolean;
33
40
  tableName?: string;
34
41
  };
35
- declare type Model<F extends FieldsDefinition, M> = {
36
- [f in keyof F]?: Native<F[f]>;
42
+ export declare type ModelOptions<K extends string, M extends Methods<T>, P extends Meta<Natural, Entry>, T extends Entry> = BaseModelOptions<T> & {
43
+ int8id?: boolean;
44
+ methods?: M;
45
+ parent?: P;
46
+ primaryKey?: K;
47
+ };
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]>;
37
51
  } & {
38
- [f in Keys<F> & string as `${f}Load`]?: ForeignKey<F[f]>;
52
+ [a in Keys<A> & string as `${a}Load`]?: ForeignKey<A[a]>;
39
53
  } & M;
40
- declare type Ancestor<F, N extends Natural, E extends Entry> = (new () => E) & {
41
- [f in keyof F]?: Meta<Native<F[f]>, E>;
54
+ declare type Model<A extends AttributesDefinition> = {
55
+ [a in keyof A]?: Native<A[a]>;
42
56
  } & {
43
- load: (boh: boolean) => Promise<E[]>;
44
- } & Meta<N, E>;
45
- export interface SchemaOptions {
46
- log?: (message: string) => void;
57
+ [a in Keys<A> & string as `${a}Load`]?: ForeignKey<A[a]>;
58
+ };
59
+ declare type Ancestor<A, N extends Natural, T extends Entry> = (new () => T) & {
60
+ [a in keyof A]?: Meta<Native<A[a]>, T>;
61
+ } & {
62
+ load: (boh: boolean) => Promise<T[]>;
63
+ } & Meta<N, T>;
64
+ export interface SedentaryOptions {
65
+ log?: ((message: string) => void) | null;
66
+ serverless?: boolean;
47
67
  sync?: boolean;
48
68
  }
49
69
  export declare class Sedentary {
50
70
  protected db: DB;
51
- protected log: (message: string) => void;
52
- private sync;
71
+ protected log: (...data: unknown[]) => void;
72
+ protected sync: boolean;
53
73
  private models;
54
- constructor(filename: string, options?: SchemaOptions);
55
- DATETIME(): Type<Date, Entry>;
56
- FKEY<N extends Natural, E extends Entry>(field: Type<N, E>): Type<N, E>;
57
- INT(size?: number): Type<number, Entry>;
58
- INT8(): Type<string, Entry>;
59
- VARCHAR(size?: number): Type<string, Entry>;
74
+ constructor(filename: string, options?: SedentaryOptions);
75
+ DATETIME(): Type<Date, unknown>;
76
+ FKEY<N extends Natural, E extends Entry>(attribute: Type<N, E>): Type<N, E>;
77
+ INT(size?: number): Type<number, unknown>;
78
+ INT8(): Type<string, unknown>;
79
+ VARCHAR(size?: number): Type<string, unknown>;
60
80
  connect(): Promise<void>;
61
81
  end(): Promise<void>;
62
- model<F extends FieldsDefinition, M extends Methods<T>, T extends Entry & {
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 & {
63
102
  id?: string;
64
- } & Model<F, M>>(name: string, fields: F, options?: Options<M, T> & {
103
+ } & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T> & {
65
104
  int8id: true;
66
- }): Ancestor<F, string, T>;
67
- model<F extends FieldsDefinition, K extends keyof F, M extends Methods<T>, N extends K extends keyof F ? Native<F[K]> : never, T extends Entry & Model<F, M>>(name: string, fields: F, options?: Options<M, T> & {
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> & {
68
107
  primaryKey: K;
69
- }): Ancestor<F, N, T>;
70
- model<F extends FieldsDefinition, M extends Methods<T>, P extends Meta<Natural, Entry>, N extends P extends Meta<infer N, Entry> ? N : never, T extends Parent<P> & Model<F, M>>(name: string, fields: F, options?: Options<M, T> & {
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> & {
71
110
  parent: P;
72
- }): Ancestor<F, N, T>;
73
- model<F extends FieldsDefinition, M extends Methods<T>, T extends Entry & {
111
+ }): Ancestor<A, N, T>;
112
+ model<A extends AttributesDefinition, T extends Entry & {
74
113
  id?: number;
75
- } & Model<F, M>>(name: string, fields: F, options?: Options<M, T>): Ancestor<F, number, T>;
114
+ } & Model<A>>(modelName: string, attributes: A, options?: BaseModelOptions<T>): Ancestor<A, number, T>;
76
115
  checkSize(size: number, message: string): number;
77
116
  }
78
117
  export declare const Package: typeof Sedentary;
79
- export {};
package/index.js CHANGED
@@ -1,33 +1,45 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Package = exports.Sedentary = void 0;
3
+ exports.Package = exports.Sedentary = exports.Type = exports.Entry = void 0;
4
4
  const db_1 = require("./lib/db");
5
+ const log_1 = require("./lib/log");
5
6
  const minidb_1 = require("./lib/minidb");
7
+ var db_2 = require("./lib/db");
8
+ Object.defineProperty(exports, "Entry", { enumerable: true, get: function () { return db_2.Entry; } });
9
+ Object.defineProperty(exports, "Type", { enumerable: true, get: function () { return db_2.Type; } });
6
10
  const allowedOption = ["indexes", "init", "int8id", "methods", "parent", "primaryKey", "sync", "tableName", "type"];
11
+ const reservedNames = [
12
+ ...["attributeName", "base", "class", "constructor", "defaultValue", "entry", "fieldName", "init", "isModel"],
13
+ ...["load", "meta", "methods", "name", "primaryKey", "prototype", "save", "size", "tableName", "type"]
14
+ ];
7
15
  class Sedentary {
8
16
  constructor(filename, options) {
9
17
  this.sync = true;
10
18
  this.models = {};
11
19
  if (typeof filename !== "string")
12
- throw new Error("Sedentary.constructor: 'filename' argument: Wrong type, expected 'string'");
20
+ throw new Error("new Sedentary: 'filename' argument: Wrong type, expected 'string'");
13
21
  if (!options)
14
22
  options = {};
15
23
  if (!(options instanceof Object))
16
- throw new Error("Sedentary.constructor: 'options' argument: Wrong type, expected 'Object'");
17
- for (const k in options) {
18
- if (["log", "sync"].indexOf(k) === -1)
19
- throw new Error(`Sedentary.constructor: 'options' argument: Unknown '${k}' option`);
20
- this[k] = options[k];
21
- }
22
- // eslint-disable-next-line no-console
23
- this.log || (this.log = console.log);
24
+ throw new Error("new Sedentary: 'options' argument: Wrong type, expected 'Object'");
25
+ for (const k in options)
26
+ if (!["log", "sync"].includes(k))
27
+ throw new Error(`new Sedentary: 'options' argument: Unknown '${k}' option`);
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);
24
34
  this.db = new minidb_1.MiniDB(filename, this.log);
35
+ this.sync = sync;
25
36
  }
26
37
  DATETIME() {
27
38
  return new db_1.Type({ base: Date, type: "DATETIME" });
28
39
  }
29
- FKEY(field) {
30
- return new db_1.Type({ base: field.base, size: 0, type: "" });
40
+ FKEY(attribute) {
41
+ const { attributeName, base, fieldName, size, tableName, type } = attribute;
42
+ return new db_1.Type({ base, foreignKey: { attributeName, fieldName, tableName }, size, type });
31
43
  }
32
44
  INT(size) {
33
45
  const message = "Sedentary.INT: 'size' argument: Wrong value, expected 2 or 4";
@@ -49,11 +61,11 @@ class Sedentary {
49
61
  this.log("Connecting...");
50
62
  await this.db.connect();
51
63
  this.log("Connected, syncing...");
52
- await this.db.sync();
64
+ await this.db.syncDataBase();
53
65
  this.log("Synced");
54
66
  }
55
67
  catch (e) {
56
- this.log("Connecting: " + e.message);
68
+ this.log("Connecting:", e.message);
57
69
  throw e;
58
70
  }
59
71
  }
@@ -62,166 +74,173 @@ class Sedentary {
62
74
  await this.db.end();
63
75
  this.log("Connection closed");
64
76
  }
65
- model(name, fields, options) {
66
- if (typeof name !== "string")
77
+ model(modelName, attributes, options) {
78
+ if (typeof modelName !== "string")
67
79
  throw new Error("Sedentary.model: 'name' argument: Wrong type, expected 'string'");
68
- if (this.models[name])
69
- throw new Error(`Sedentary.model: '${name}' model: Model already defined`);
70
- if (!fields)
71
- fields = {};
72
- if (!(fields instanceof Object))
73
- throw new Error(`Sedentary.model: '${name}' model: 'fields' argument: Wrong type, expected 'Object'`);
80
+ if (this.models[modelName])
81
+ throw new Error(`Sedentary.model: '${modelName}' model: Model already defined`);
82
+ if (!attributes)
83
+ attributes = {};
84
+ if (!(attributes instanceof Object))
85
+ throw new Error(`Sedentary.model: '${modelName}' model: 'attributes' argument: Wrong type, expected 'Object'`);
74
86
  if (!options)
75
87
  options = {};
76
88
  if (!(options instanceof Object))
77
- 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'`);
78
90
  for (const k in options)
79
- if (allowedOption.indexOf(k) === -1)
80
- throw new Error(`Sedentary.model: '${name}' model: 'options' argument: Unknown '${k}' option`);
91
+ if (!allowedOption.includes(k))
92
+ throw new Error(`Sedentary.model: '${modelName}' model: 'options' argument: Unknown '${k}' option`);
81
93
  if (options.int8id && options.parent)
82
- 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`);
83
95
  if (options.int8id && options.primaryKey)
84
- 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`);
85
97
  if (options.parent && options.primaryKey)
86
- throw new Error(`Sedentary.model: '${name}' model: 'parent' and 'primaryKey' options conflict each other`);
87
- const constraints = [];
88
- const { indexes, int8id, parent, primaryKey, sync, tableName } = Object.assign({ sync: this.sync, tableName: name + "s" }, 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);
89
101
  let { methods } = options;
102
+ let aarray = int8id
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 }))];
105
+ let constraints = [{ attribute: aarray[0], constraintName: `${tableName}_id_unique`, type: "u" }];
90
106
  const iarray = [];
91
- const pkName = primaryKey || "id";
92
- let farray = int8id
93
- ? [new db_1.Field({ fieldName: "id", notNull: true, size: 8, type: "INT8", unique: true })]
94
- : [new db_1.Field({ fieldName: "id", notNull: true, size: 4, type: "INT", unique: true })];
107
+ const pk = aarray[0];
95
108
  if (methods && !(methods instanceof Object))
96
- 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'`);
97
110
  if (parent) {
98
- methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
99
111
  try {
100
112
  if (!parent.isModel())
101
113
  throw new Error();
102
114
  }
103
115
  catch (e) {
104
- throw new Error(`Sedentary.model: '${name}' model: 'parent' option: Wrong type, expected 'Model'`);
116
+ throw new Error(`Sedentary.model: '${modelName}' model: 'parent' option: Wrong type, expected 'Model'`);
105
117
  }
118
+ methods = (methods ? Object.assign(Object.assign({}, (parent.methods || {})), methods) : parent.methods);
106
119
  }
107
120
  if (primaryKey && typeof primaryKey !== "string")
108
- throw new Error(`Sedentary.model: '${name}' model: 'primaryKey' option: Wrong type, expected 'string'`);
109
- if (primaryKey && Object.keys(fields).indexOf(primaryKey) === -1)
110
- throw new Error(`Sedentary.model: '${name}' model: 'primaryKey' option: Field '${primaryKey}' does not exists`);
111
- if (parent || primaryKey)
112
- farray = [];
113
- if (!parent)
114
- iarray.push({ fields: [pkName], name: `${tableName}_${pkName}_unique`, type: "btree", unique: true });
115
- for (const fname in fields) {
116
- if (["base", "constructor", "load", "meta", "name", "prototype", "save", "size", "type"].indexOf(fname) !== -1)
117
- throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: Reserved name`);
118
- const field = fields[fname];
119
- // eslint-disable-next-line prefer-const
120
- let { defaultValue, fieldName, notNull, size, type, unique } = (() => {
121
+ throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Wrong type, expected 'string'`);
122
+ if (primaryKey && !Object.keys(attributes).includes(primaryKey))
123
+ throw new Error(`Sedentary.model: '${modelName}' model: 'primaryKey' option: Attribute '${primaryKey}' does not exists`);
124
+ if (parent || primaryKey) {
125
+ autoIncrement = false;
126
+ aarray = [];
127
+ constraints = [];
128
+ }
129
+ for (const attributeName of Object.keys(attributes).sort()) {
130
+ if (reservedNames.includes(attributeName))
131
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Reserved name`);
132
+ const call = (defaultValue, fieldName, notNull, unique, func, message1, message2) => {
133
+ if (func === this.FKEY)
134
+ throw new Error(`${message1} 'this.FKEY' can't be used directly`);
135
+ if (func !== this.DATETIME && func !== this.INT && func !== this.INT8 && func !== this.VARCHAR)
136
+ throw new Error(`${message1} ${message2}`);
137
+ return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique }, func()));
138
+ };
139
+ const attributeDefinition = attributes[attributeName];
140
+ let { base, defaultValue, fieldName, foreignKey, notNull, size, type, unique } = (() => {
121
141
  const ret = (() => {
122
- // eslint-disable-next-line prefer-const
123
- let { defaultValue, fieldName, notNull, unique, type } = { defaultValue: undefined, fieldName: fname, notNull: false, unique: false, type: null };
124
- const call = (defaultValue, fieldName, notNull, unique, func, message) => {
125
- if (func !== this.DATETIME && func !== this.FKEY && func !== this.INT && func !== this.INT8 && func !== this.VARCHAR)
126
- throw new Error(message);
127
- return new db_1.Field(Object.assign({ defaultValue, fieldName, notNull, unique }, func()));
128
- };
129
- if (field instanceof db_1.Type)
130
- return new db_1.Field(Object.assign({ fieldName: fname }, Object.assign({ notNull: false }, field)));
131
- if (field instanceof Function)
132
- return call(undefined, fname, false, false, field, `Sedentary.model: '${name}' model: '${fname}' field: Wrong type, expected 'Field'`);
133
- if (!(field instanceof Object))
134
- throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: Wrong field type, expected 'Field'`);
135
- ({ defaultValue, fieldName, notNull, unique, type } = Object.assign({ notNull: false }, field));
136
- if (!fieldName)
137
- fieldName = fname;
142
+ if (attributeDefinition instanceof db_1.Type)
143
+ return new db_1.Attribute(Object.assign({ attributeName, fieldName: attributeName, modelName, notNull: false, tableName }, attributeDefinition));
144
+ if (attributeDefinition instanceof Function)
145
+ return call(undefined, attributeName, false, false, attributeDefinition, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute:`, "Wrong type, expected 'Attribute'");
146
+ if (!(attributeDefinition instanceof Object))
147
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Wrong attribute type, expected 'Attribute'`);
148
+ const attributeDefaults = Object.assign({ defaultValue: undefined, fieldName: attributeName, notNull: false, unique: false }, attributeDefinition);
149
+ const { defaultValue, fieldName, notNull, unique, type } = attributeDefaults;
138
150
  if (defaultValue === null)
139
- throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: 'defaultValue' option: Does 'null' default value really makes sense?`);
151
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Does 'null' default value really makes sense?`);
140
152
  if (typeof fieldName !== "string")
141
- throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: 'fieldName' option: Wrong type, expected 'string'`);
142
- if (!type)
143
- throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: Missing 'type' option`);
153
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'fieldName' option: Wrong type, expected 'string'`);
154
+ if (typeof notNull !== "boolean")
155
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'notNull' option: Wrong type, expected 'boolean'`);
156
+ if (typeof unique !== "boolean")
157
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'unique' option: Wrong type, expected 'boolean'`);
158
+ if (type === undefined)
159
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: Missing 'type' option`);
144
160
  if (type instanceof db_1.Type)
145
- return new db_1.Field(Object.assign(Object.assign(Object.assign({}, Object.assign({ notNull: false }, field)), { fieldName }), type));
161
+ return new db_1.Attribute(Object.assign({ attributeName, defaultValue, fieldName, modelName, notNull, tableName, unique }, type));
146
162
  if (type instanceof Function)
147
- return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${name}' model: '${fname}' field: 'type' option: Wrong type, expected 'Type'`);
148
- throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: 'type' option: Wrong type, expected 'Type'`);
163
+ return call(defaultValue, fieldName, notNull, unique, type, `Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option:`, "Wrong type, expected 'Type'");
164
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'type' option: Wrong type, expected 'Type'`);
149
165
  })();
150
166
  const { base, defaultValue } = ret;
151
167
  if (defaultValue !== undefined) {
152
168
  if (base === Date && !(defaultValue instanceof Date))
153
- throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: 'defaultValue' option: Wrong type, expected 'Date'`);
169
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'Date'`);
154
170
  if (base === Number && typeof defaultValue !== "number")
155
- throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: 'defaultValue' option: Wrong type, expected 'number'`);
171
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'number'`);
156
172
  if (base === String && typeof defaultValue !== "string")
157
- throw new Error(`Sedentary.model: '${name}' model: '${fname}' field: 'defaultValue' option: Wrong type, expected 'string'`);
173
+ throw new Error(`Sedentary.model: '${modelName}' model: '${attributeName}' attribute: 'defaultValue' option: Wrong type, expected 'string'`);
158
174
  }
159
175
  return ret;
160
176
  })();
161
- if (primaryKey === fname) {
177
+ if (primaryKey === attributeName) {
162
178
  notNull = true;
163
179
  unique = true;
164
180
  }
165
181
  if (defaultValue)
166
182
  notNull = true;
167
- farray.push(new db_1.Field({ defaultValue, fieldName, notNull, size, type, unique }));
168
- if (unique && fname !== pkName)
169
- iarray.push({ fields: [fieldName], name: `${tableName}_${fieldName}_unique`, type: "btree", unique: true });
183
+ const attribute = new db_1.Attribute({ attributeName, base, defaultValue, fieldName, foreignKey, modelName, notNull, size, tableName, type, unique });
184
+ aarray.push(attribute);
185
+ if (foreignKey)
186
+ constraints.push({ attribute, constraintName: `fkey_${fieldName}_${foreignKey.tableName}_${foreignKey.fieldName}`, type: "f" });
187
+ if (unique)
188
+ constraints.push({ attribute, constraintName: `${tableName}_${fieldName}_unique`, type: "u" });
170
189
  }
171
190
  if (indexes) {
172
- const flds = fields;
191
+ const flds = attributes;
173
192
  if (!(indexes instanceof Object))
174
- throw new Error(`Sedentary.model: '${name}' model: 'indexes' option: Wrong type, expected 'Object'`);
175
- for (const iname in indexes) {
176
- if (iarray.filter(_ => _.name === iname).length !== 0)
177
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: index name already inferred by the unique constraint on a field`);
178
- const idx = indexes[iname];
179
- const checkField = (field, l) => {
180
- if (typeof field !== "string")
181
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: #${l + 1} field: Wrong type, expected 'string'`);
182
- if (!(field in flds))
183
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: #${l + 1} field: Unknown field '${field}'`);
193
+ throw new Error(`Sedentary.model: '${modelName}' model: 'indexes' option: Wrong type, expected 'Object'`);
194
+ for (const indexName in indexes) {
195
+ if (aarray.filter(({ fieldName, unique }) => unique && `${tableName}_${fieldName}_unique` === indexName).length !== 0)
196
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: index name already inferred by the unique constraint on an attribute`);
197
+ const idx = indexes[indexName];
198
+ const checkAttribute = (attribute, l) => {
199
+ if (typeof attribute !== "string")
200
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: #${l + 1} attribute: Wrong type, expected 'string'`);
201
+ if (!(attribute in flds))
202
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: #${l + 1} attribute: Unknown attribute '${attribute}'`);
184
203
  };
185
- let fields;
204
+ let attributes;
186
205
  let type = "btree";
187
206
  let unique = false;
188
207
  if (idx instanceof Array) {
189
- idx.forEach(checkField);
190
- fields = idx;
208
+ idx.forEach(checkAttribute);
209
+ attributes = idx;
191
210
  }
192
211
  else if (typeof idx === "string") {
193
- checkField(idx, 0);
194
- fields = [idx];
212
+ checkAttribute(idx, 0);
213
+ attributes = [idx];
195
214
  }
196
215
  else if (idx instanceof Object) {
197
216
  for (const k in idx)
198
- if (["fields", "type", "unique"].indexOf(k) === -1)
199
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: Unknown index option '${k}'`);
200
- ({ fields, type, unique } = Object.assign({ type: "btree", unique: false }, idx));
201
- if (!fields)
202
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: Missing 'fields' option`);
203
- if (fields instanceof Array)
204
- fields.forEach(checkField);
205
- else if (typeof fields === "string") {
206
- checkField(fields, 0);
207
- fields = [fields];
217
+ if (!["attributes", "type", "unique"].includes(k))
218
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Unknown index option '${k}'`);
219
+ ({ attributes, type, unique } = Object.assign({ type: "btree", unique: false }, idx));
220
+ if (!attributes)
221
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Missing 'attributes' option`);
222
+ if (attributes instanceof Array)
223
+ attributes.forEach(checkAttribute);
224
+ else if (typeof attributes === "string") {
225
+ checkAttribute(attributes, 0);
226
+ attributes = [attributes];
208
227
  }
209
228
  else
210
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: 'fields' option: Wrong type, expected 'FieldNames'`);
229
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'attributes' option: Wrong type, expected 'FieldNames'`);
211
230
  if (typeof type !== "string")
212
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: 'type' option: Wrong type, expected 'string'`);
213
- if (["btree", "hash"].indexOf(type) === -1)
214
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: 'type' option: Wrong value, expected 'btree' or 'hash'`);
231
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'type' option: Wrong type, expected 'string'`);
232
+ if (!["btree", "hash"].includes(type))
233
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'type' option: Wrong value, expected 'btree' or 'hash'`);
215
234
  if (typeof unique !== "boolean")
216
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: 'unique' option: Wrong type, expected 'boolean'`);
235
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: 'unique' option: Wrong type, expected 'boolean'`);
217
236
  }
218
237
  else
219
- throw new Error(`Sedentary.model: '${name}' model: '${iname}' index: Wrong type, expected 'Object'`);
220
- iarray.push({ fields, name: iname, type, unique });
238
+ throw new Error(`Sedentary.model: '${modelName}' model: '${indexName}' index: Wrong type, expected 'Object'`);
239
+ iarray.push({ fields: attributes, indexName, type, unique });
221
240
  }
222
241
  }
223
- this.db.addTable(new db_1.Table({ constraints, fields: farray, indexes: iarray, parent, primaryKey, sync, tableName }));
224
- this.models[name] = true;
242
+ this.db.tables.push(new db_1.Table({ autoIncrement, constraints, attributes: aarray, indexes: iarray, parent, sync, tableName }));
243
+ this.models[modelName] = true;
225
244
  const init = parent
226
245
  ? options.init
227
246
  ? function () {
@@ -231,7 +250,7 @@ class Sedentary {
231
250
  : parent.init
232
251
  : options.init;
233
252
  const flds = {};
234
- for (const key in fields)
253
+ for (const key in attributes)
235
254
  flds[key] = null;
236
255
  class Class {
237
256
  constructor() {
@@ -241,7 +260,7 @@ class Sedentary {
241
260
  save() {
242
261
  return new Promise((resolve, reject) => {
243
262
  const save = () => reject(new Error("eh no"));
244
- Object.defineProperty(save, "name", { value: name + ".save" });
263
+ Object.defineProperty(save, "name", { value: modelName + ".save" });
245
264
  setTimeout(save, 10);
246
265
  });
247
266
  }
@@ -251,15 +270,19 @@ class Sedentary {
251
270
  return resolve([new Class()]);
252
271
  reject(new Error("boh"));
253
272
  }, 10));
254
- Object.defineProperty(load, "name", { value: name + "s.load" });
255
- const meta = { tableName, primaryKey, init, methods };
256
- Object.defineProperty(Class, "name", { value: name });
273
+ 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 });
257
276
  Object.defineProperty(Class, "load", { value: load });
258
277
  Object.defineProperty(Class, "meta", { value: new db_1.Meta(meta) });
259
- Object.defineProperty(Class.prototype.save, "name", { value: name + ".save" });
278
+ Object.defineProperty(Class, "name", { value: modelName });
279
+ Object.defineProperty(Class.prototype.save, "name", { value: modelName + ".save" });
260
280
  Object.assign(Class, new db_1.Meta(meta));
261
- Object.assign(Class, Object.assign(Object.assign({}, fields), { isModel: () => true }));
262
281
  Object.assign(Class.prototype, methods);
282
+ 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] });
263
286
  return Class;
264
287
  }
265
288
  checkSize(size, message) {
@@ -273,12 +296,11 @@ class Sedentary {
273
296
  exports.Sedentary = Sedentary;
274
297
  exports.Package = Sedentary;
275
298
  const db = new Sedentary("gino");
276
- const Users = db.model("User", { foo: db.INT(), bar: db.VARCHAR() }, {});
277
- const fields = {
299
+ const Users = db.model("User", { foo: db.INT(), bar: { type: db.VARCHAR(), unique: true } }, {});
300
+ class Item extends db.model("Item", {
278
301
  num: db.FKEY(Users),
279
302
  str: db.VARCHAR()
280
- };
281
- class Item extends db.model("Item", fields, {
303
+ }, {
282
304
  init: function () {
283
305
  this.num = 0;
284
306
  this.str = "0";
@@ -301,6 +323,7 @@ class Super extends db.model("Super", {
301
323
  this.num = 0;
302
324
  const a = this.nLoad ? await this.nLoad() : { prova: () => null };
303
325
  a.prova();
326
+ this.prova();
304
327
  }
305
328
  }) {
306
329
  }
@@ -311,7 +334,7 @@ class Next extends db.model("Next", { a: db.INT, b: db.INT }, {
311
334
  primaryKey: "a"
312
335
  }) {
313
336
  }
314
- class Current extends db.model("Current", { b: db.FKEY(Next) }, {
337
+ class Current extends db.model("Current", { b: { type: db.FKEY(Next), unique: true } }, {
315
338
  init: function () {
316
339
  this.b = 24;
317
340
  }