sedentary 0.0.17 → 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/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;
@@ -73,7 +73,7 @@ export declare class Sedentary {
73
73
  private models;
74
74
  constructor(filename: string, options?: SedentaryOptions);
75
75
  DATETIME(): Type<Date, unknown>;
76
- 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>;
77
77
  INT(size?: number): Type<number, unknown>;
78
78
  INT8(): Type<string, unknown>;
79
79
  VARCHAR(size?: number): Type<string, unknown>;
package/index.js CHANGED
@@ -37,9 +37,9 @@ class Sedentary {
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";
@@ -107,6 +107,7 @@ class Sedentary {
107
107
  const pk = aarray[0];
108
108
  if (methods && !(methods instanceof Object))
109
109
  throw new Error(`Sedentary.model: '${modelName}' model: 'methods' option: Wrong type, expected 'Object'`);
110
+ const originalMethods = methods;
110
111
  if (parent) {
111
112
  try {
112
113
  if (!parent.isModel())
@@ -174,6 +175,23 @@ class Sedentary {
174
175
  }
175
176
  return ret;
176
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
+ }
177
195
  if (primaryKey === attributeName) {
178
196
  notNull = true;
179
197
  unique = true;
@@ -249,9 +267,6 @@ class Sedentary {
249
267
  }
250
268
  : parent.init
251
269
  : options.init;
252
- const flds = {};
253
- for (const key in attributes)
254
- flds[key] = null;
255
270
  class Class {
256
271
  constructor() {
257
272
  if (init)
@@ -271,13 +286,65 @@ class Sedentary {
271
286
  reject(new Error("boh"));
272
287
  }, 10));
273
288
  Object.defineProperty(load, "name", { value: modelName + ".load" });
274
- const meta = { base: Number, type: "meta", tableName, primaryKey, init, methods };
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);
275
342
  Object.defineProperty(Class, "isModel", { value: () => true });
276
343
  Object.defineProperty(Class, "load", { value: load });
277
- Object.defineProperty(Class, "meta", { value: new db_1.Meta(meta) });
344
+ Object.defineProperty(Class, "meta", { value: meta });
278
345
  Object.defineProperty(Class, "name", { value: modelName });
279
346
  Object.defineProperty(Class.prototype.save, "name", { value: modelName + ".save" });
280
- Object.assign(Class, new db_1.Meta(meta));
347
+ Object.assign(Class, meta);
281
348
  Object.assign(Class.prototype, methods);
282
349
  for (const attribute of aarray)
283
350
  Object.defineProperty(Class, attribute.attributeName, { value: attribute });
@@ -340,9 +407,9 @@ class Current extends db.model("Current", { b: { type: db.FKEY(Next), unique: tr
340
407
  }
341
408
  }) {
342
409
  }
343
- class Last extends db.model("Last", { b: db.FKEY(Current.b) }, {
410
+ class Last extends db.model("Last", { c: db.FKEY(Current.b) }, {
344
411
  init: function () {
345
- this.b = 24;
412
+ this.c = 24;
346
413
  },
347
414
  parent: Next
348
415
  }) {
@@ -358,3 +425,29 @@ class Last extends db.model("Last", { b: db.FKEY(Current.b) }, {
358
425
  }
359
426
  return true;
360
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>);
package/lib/minidb.js CHANGED
@@ -23,7 +23,10 @@ class MiniDB extends db_1.DB {
23
23
  async dropConstraints(table) {
24
24
  const { constraints } = this.body.tables[table.tableName] || { constraints: { f: {}, u: {} } };
25
25
  for (const constraint of Object.keys(constraints.f).sort()) {
26
- if (!table.constraints.filter(({ constraintName, type }) => constraintName === constraint && type === "f").length) {
26
+ const arr = table.constraints.filter(({ constraintName, type }) => constraintName === constraint && type === "f");
27
+ const dbOptions = arr.length ? arr[0].attribute.foreignKey.options : { onDelete: "delete", onUpdate: "delete" };
28
+ const inOptions = constraints.f[constraint].options;
29
+ if (dbOptions.onDelete !== inOptions.onDelete || dbOptions.onUpdate !== inOptions.onUpdate) {
27
30
  this.syncLog(`'${table.tableName}': Removing foreign key: '${constraint}'`);
28
31
  if (this.sync)
29
32
  delete constraints.f[constraint];
@@ -31,7 +34,7 @@ class MiniDB extends db_1.DB {
31
34
  }
32
35
  for (const constraint of Object.keys(constraints.u).sort()) {
33
36
  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}'`);
37
+ this.syncLog(`'${table.tableName}': Removing unique constraint from field: '${constraints.u[constraint].on}'`);
35
38
  if (this.sync)
36
39
  delete constraints.u[constraint];
37
40
  }
@@ -70,20 +73,20 @@ class MiniDB extends db_1.DB {
70
73
  async syncConstraints(table) {
71
74
  const { constraints } = this.body.tables[table.tableName] || { constraints: { f: {}, u: {} } };
72
75
  for (const constraint of table.constraints) {
73
- const { constraintName, type } = constraint;
74
- const { fieldName, foreignKey } = constraint.attribute;
76
+ const { attribute, constraintName, type } = constraint;
75
77
  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;
78
+ if (type === "f") {
79
+ const { fieldName, options, tableName } = attribute.foreignKey;
80
+ const onDelete = options.onDelete !== "no action" ? ` on delete ${options.onDelete}` : "";
81
+ const onUpdate = options.onUpdate !== "no action" ? ` on update ${options.onUpdate}` : "";
82
+ this.syncLog(`'${table.tableName}': Adding foreign key '${constraint.constraintName}' on field: '${attribute.fieldName}' references '${tableName}(${fieldName})'${onDelete}${onUpdate}`);
83
+ if (this.sync)
84
+ constraints[type][constraintName] = { on: attribute.fieldName, options, fieldName, tableName };
85
+ }
86
+ else {
87
+ this.syncLog(`'${table.tableName}': Adding unique constraint on field: '${attribute.fieldName}'`);
88
+ if (this.sync)
89
+ constraints[type][constraintName] = { on: attribute.fieldName };
87
90
  }
88
91
  }
89
92
  }
package/package.json CHANGED
@@ -56,5 +56,5 @@
56
56
  "version": "node -r ts-node/register utils.ts version"
57
57
  },
58
58
  "types": "index.d.ts",
59
- "version": "0.0.17"
59
+ "version": "0.0.18"
60
60
  }