leoric 2.6.3 → 2.7.2

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/src/decorators.ts CHANGED
@@ -1,17 +1,16 @@
1
- import Bone from './bone';
2
- import DataType from './data_types';
3
- import { ASSOCIATE_METADATA_MAP } from './constants';
4
1
  import 'reflect-metadata';
5
2
 
6
- type DataTypes<T> = {
7
- [Property in keyof T as Exclude<Property, "toSqlString">]: T[Property];
8
- }
3
+ import Bone from './bone';
4
+ import DataTypes, { DataType, DATA_TYPE } from './data_types';
5
+ import { ASSOCIATE_METADATA_MAP } from './constants';
6
+ import { ColumnBase, Validator, AssociateOptions } from './types/common';
9
7
 
10
- interface ColumnOption {
11
- type?: DataTypes<DataType>;
8
+ interface ColumnOption extends Omit<ColumnBase, 'columnName'| 'columnType'> {
9
+ type?: DataType;
12
10
  name?: string;
13
- defaultValue?: null | boolean | number | string | Date | JSON;
14
- allowNull?: boolean;
11
+ validate?: {
12
+ [key: string]: Validator;
13
+ }
15
14
  }
16
15
 
17
16
  function findType(tsType) {
@@ -20,7 +19,7 @@ function findType(tsType) {
20
19
  DATE,
21
20
  STRING,
22
21
  BOOLEAN,
23
- } = DataType;
22
+ } = DataTypes;
24
23
 
25
24
  switch (tsType) {
26
25
  case BigInt:
@@ -38,9 +37,13 @@ function findType(tsType) {
38
37
  }
39
38
  }
40
39
 
41
- export function Column(options: ColumnOption | DataTypes<DataType> = {}) {
40
+ export function Column(options?: ColumnOption | DATA_TYPE<DataType>) {
42
41
  return function(target: Bone, propertyKey: string) {
43
- if (options['prototype'] instanceof DataType) options = { type: options };
42
+ if (options == null) {
43
+ options = {};
44
+ }
45
+ // target refers to model prototype, an internal instance of `Bone {}`
46
+ if (options['prototype'] instanceof DataType) options = { type: options as DATA_TYPE<DataType> };
44
47
 
45
48
  if (!('type' in options)) {
46
49
  const tsType = Reflect.getMetadata('design:type', target, propertyKey);
@@ -58,11 +61,6 @@ export function Column(options: ColumnOption | DataTypes<DataType> = {}) {
58
61
  };
59
62
  }
60
63
 
61
- interface AssociateOptions {
62
- className?: string;
63
- foreignKey?: string;
64
- }
65
-
66
64
  const { hasMany, hasOne, belongsTo } = ASSOCIATE_METADATA_MAP;
67
65
 
68
66
  export function HasMany(options?: AssociateOptions) {
@@ -73,10 +73,12 @@ function createType(DataTypes, params) {
73
73
  case 'MEDIUMINT':
74
74
  case 'INTEGER':
75
75
  case 'BIGINT':
76
+ return new DataType(type.dataLength, type.unsigned, type.zerofill);
76
77
  case 'BINARY':
77
78
  case 'VARBINARY':
78
79
  case 'CHAR':
79
80
  case 'VARCHAR':
81
+ case 'STRING':
80
82
  return new DataType(type.dataLength);
81
83
  default:
82
84
  return new DataType();
@@ -36,8 +36,8 @@ class AbstractDriver {
36
36
 
37
37
  /**
38
38
  * query with spell
39
- * @param {Spell} spell
40
- * @returns
39
+ * @param {Spell} spell
40
+ * @returns
41
41
  */
42
42
  async cast(spell) {
43
43
  const { sql, values } = this.format(spell);
@@ -47,9 +47,9 @@ class AbstractDriver {
47
47
 
48
48
  /**
49
49
  * raw query
50
- * @param {object|string} query
51
- * @param {object | array} values
52
- * @param {object} opts
50
+ * @param {object|string} query
51
+ * @param {object | array} values
52
+ * @param {object} opts
53
53
  */
54
54
  async query(query, values, opts) {
55
55
  throw new Error('unimplemented!');
@@ -57,7 +57,7 @@ class AbstractDriver {
57
57
 
58
58
  /**
59
59
  * disconnect manually
60
- * @param {Function} callback
60
+ * @param {Function} callback
61
61
  */
62
62
  async disconnect(callback) {
63
63
  debug('[disconnect] called');
@@ -69,8 +69,8 @@ class AbstractDriver {
69
69
 
70
70
  /**
71
71
  * use spellbook to format spell
72
- * @param {Spell} spell
73
- * @returns
72
+ * @param {Spell} spell
73
+ * @returns
74
74
  */
75
75
  format(spell) {
76
76
  return this.spellbook.format(spell);
@@ -163,11 +163,11 @@ class SpellBook {
163
163
  const { shardingKey } = Model;
164
164
  const { createdAt } = Model.timestamps;
165
165
  const { escapeId } = Model.driver;
166
- let columns = [];
167
- let updateOnDuplicateColumns = [];
166
+ const columns = [];
167
+ const updateOnDuplicateColumns = [];
168
168
 
169
- let values = [];
170
- let placeholders = [];
169
+ const values = [];
170
+ const placeholders = [];
171
171
  if (Array.isArray(sets)) {
172
172
  // merge records to get the big picture of involved columnAttributes
173
173
  const involved = sets.reduce((result, entry) => {
@@ -318,7 +318,7 @@ class SpellBook {
318
318
  spell.updateOnDuplicate = true;
319
319
  }
320
320
 
321
- let { sql, values } = this.formatInsert(spell);
321
+ const { sql, values } = this.formatInsert(spell);
322
322
  return {
323
323
  sql,
324
324
  values,
@@ -347,7 +347,7 @@ class SpellBook {
347
347
  * @param {Array} columns columns for value set
348
348
  */
349
349
  formatUpdateOnDuplicate(spell, columns) {
350
- const { updateOnDuplicate, uniqueKeys, Model } = spell;
350
+ const { updateOnDuplicate, uniqueKeys, Model, sets } = spell;
351
351
  if (!updateOnDuplicate) return '';
352
352
  const { columnAttributes, primaryColumn } = Model;
353
353
  const { escapeId } = Model.driver;
@@ -358,25 +358,27 @@ class SpellBook {
358
358
  actualUniqueKeys.push(escapeId(field));
359
359
  }
360
360
  } else {
361
+ const setFields = Object.keys(sets);
361
362
  // conflict_target must be unique
362
363
  // get all unique keys
363
364
  if (columnAttributes) {
364
365
  for (const key in columnAttributes) {
365
366
  const att = columnAttributes[key];
366
367
  // use the first unique key
367
- if (att.unique) {
368
+ if (att.unique || (att.primaryKey && setFields.includes(att.name))) {
368
369
  actualUniqueKeys.push(escapeId(att.columnName));
369
370
  break;
370
371
  }
371
372
  }
372
373
  }
374
+
373
375
  if (!actualUniqueKeys.length) actualUniqueKeys.push(escapeId(primaryColumn));
374
376
  // default use id as primary key
375
377
  if (!actualUniqueKeys.length) actualUniqueKeys.push(escapeId('id'));
376
378
  }
377
379
 
378
380
  if (Array.isArray(updateOnDuplicate) && updateOnDuplicate.length) {
379
- columns = updateOnDuplicate.map(column => (columnAttributes[column] && columnAttributes[column].columnName )|| column);
381
+ columns = updateOnDuplicate.map(column => (columnAttributes[column] && columnAttributes[column].columnName)|| column);
380
382
  } else if (!columns.length) {
381
383
  columns = Object.values(columnAttributes).map(({ columnName }) => columnName);
382
384
  }
@@ -21,6 +21,7 @@ class MysqlAttribute extends Attribute {
21
21
  allowNull, defaultValue,
22
22
  primaryKey,
23
23
  comment,
24
+ unique,
24
25
  } = this;
25
26
 
26
27
  const chunks = [
@@ -34,6 +35,10 @@ class MysqlAttribute extends Attribute {
34
35
 
35
36
  if (!primaryKey && !allowNull) chunks.push('NOT NULL');
36
37
 
38
+ if (unique === true) {
39
+ chunks.push('UNIQUE');
40
+ }
41
+
37
42
  if (defaultValue != null) {
38
43
  chunks.push(`DEFAULT ${escape(defaultValue)}`);
39
44
  }
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const DataTypes = require('../../data_types');
3
+ const { default: DataTypes } = require('../../data_types');
4
4
 
5
5
  class Mysql_BOOLEAN extends DataTypes.BOOLEAN {
6
6
  constructor() {
@@ -18,7 +18,6 @@ class MysqlDriver extends AbstractDriver {
18
18
 
19
19
  /**
20
20
  * Create a connection pool
21
- * @param {string} clientName
22
21
  * @param {Object} opts
23
22
  * @param {string} opts.host
24
23
  * @param {string} opts.port
@@ -30,6 +29,7 @@ class MysqlDriver extends AbstractDriver {
30
29
  * @param {number} opts.connectTimeout - The milliseconds before a timeout occurs during the initial connection to the MySQL server. (Default: `10000`)
31
30
  * @param {string} opts.charset
32
31
  * @param {boolean} opts.stringifyObjects - stringify object value in dataValues
32
+ * @param {string} opts.client
33
33
  */
34
34
  constructor(opts = {}) {
35
35
  super(opts);
@@ -54,7 +54,7 @@ class MysqlDriver extends AbstractDriver {
54
54
  } = opts;
55
55
 
56
56
  if (client !== 'mysql' && client !== 'mysql2') {
57
- throw new Error(`Unsupported mysql client ${client}`);
57
+ console.warn(`[leoric] mysql client "${client}" not tested`);
58
58
  }
59
59
 
60
60
  return require(client).createPool({
@@ -15,7 +15,7 @@ class PostgresAttribute extends Attribute {
15
15
 
16
16
  toSqlString() {
17
17
  const {
18
- columnName, type, columnType, allowNull, defaultValue, primaryKey,
18
+ columnName, type, columnType, allowNull, defaultValue, primaryKey, unique,
19
19
  } = this;
20
20
  const chunks = [
21
21
  escapeId(columnName),
@@ -29,6 +29,10 @@ class PostgresAttribute extends Attribute {
29
29
 
30
30
  if (!primaryKey && !allowNull) chunks.push('NOT NULL');
31
31
 
32
+ if (unique === true) {
33
+ chunks.push('UNIQUE');
34
+ }
35
+
32
36
  if (defaultValue != null) {
33
37
  chunks.push(`DEFAULT ${escape(defaultValue)}`);
34
38
  }
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const DataTypes = require('../../data_types');
3
+ const { default: DataTypes } = require('../../data_types');
4
4
  const util = require('util');
5
5
  const Raw = require('../../raw');
6
6
 
@@ -29,7 +29,7 @@ class Postgres_JSONB extends DataTypes.JSONB {
29
29
  }
30
30
  }
31
31
 
32
- class Postgres_BINARY extends DataTypes {
32
+ class Postgres_BINARY extends DataTypes.BINARY {
33
33
  constructor() {
34
34
  super();
35
35
  this.dataType = 'bytea';
@@ -41,8 +41,8 @@ class Postgres_BINARY extends DataTypes {
41
41
  }
42
42
 
43
43
  class Postgres_INTEGER extends DataTypes.INTEGER {
44
- constructor(dataLength) {
45
- super(dataLength);
44
+ constructor(dataLength, unsigned, zerofill) {
45
+ super(dataLength, unsigned, zerofill);
46
46
  }
47
47
 
48
48
  uncast(value) {
@@ -55,8 +55,8 @@ class Postgres_INTEGER extends DataTypes.INTEGER {
55
55
  }
56
56
 
57
57
  class Postgres_BIGINT extends Postgres_INTEGER {
58
- constructor() {
59
- super();
58
+ constructor(dataLength, unsigned, zerofill) {
59
+ super(dataLength, unsigned, zerofill);
60
60
  this.dataType = 'bigint';
61
61
  }
62
62
  }
@@ -127,7 +127,8 @@ class PostgresDriver extends AbstractDriver {
127
127
  for (const row of rows) {
128
128
  const tableName = row.table_name;
129
129
  const columns = schemaInfo[tableName] || (schemaInfo[tableName] = []);
130
- let { data_type: dataType, character_maximum_length: length } = row;
130
+ const { character_maximum_length: length } = row;
131
+ let { data_type: dataType } = row;
131
132
 
132
133
  if (dataType === 'character varying') dataType = 'varchar';
133
134
  if (dataType === 'timestamp without time zone') dataType = 'timestamp';
@@ -14,8 +14,7 @@ class SqliteAttribute extends Attribute {
14
14
  }
15
15
 
16
16
  toSqlString() {
17
- const { allowNull, defaultValue, primaryKey } = this;
18
- const { columnName, columnType, type } = this;
17
+ const { columnName, columnType, type, allowNull, defaultValue, primaryKey, unique } = this;
19
18
  const chunks = [
20
19
  escapeId(columnName),
21
20
  columnType.toUpperCase() || type.toSqlString(),
@@ -28,6 +27,10 @@ class SqliteAttribute extends Attribute {
28
27
 
29
28
  if (!primaryKey && !allowNull) chunks.push('NOT NULL');
30
29
 
30
+ if (unique === true) {
31
+ chunks.push('UNIQUE');
32
+ }
33
+
31
34
  if (defaultValue != null) {
32
35
  chunks.push(`DEFAULT ${escape(defaultValue)}`);
33
36
  }
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const DataTypes = require('../../data_types');
3
+ const { default: DataTypes } = require('../../data_types');
4
4
 
5
5
  class Sqlite_DATE extends DataTypes.DATE {
6
6
  constructor(precision, timezone) {
@@ -34,8 +34,8 @@ class Sqlite_DATEONLY extends DataTypes.DATEONLY {
34
34
  }
35
35
 
36
36
  class Sqlite_INTEGER extends DataTypes.INTEGER {
37
- constructor(dataLength) {
38
- super(dataLength);
37
+ constructor(dataLength, unsigned, zerofill) {
38
+ super(dataLength, unsigned, zerofill);
39
39
  }
40
40
 
41
41
  uncast(value) {
@@ -44,8 +44,8 @@ class Sqlite_INTEGER extends DataTypes.INTEGER {
44
44
 
45
45
  }
46
46
  class Sqlite_BIGINT extends DataTypes.BIGINT {
47
- constructor() {
48
- super();
47
+ constructor(dataLength, unsigned, zerofill) {
48
+ super(dataLength, unsigned, zerofill);
49
49
  this.dataType = 'integer';
50
50
  }
51
51
 
@@ -53,7 +53,7 @@ class Sqlite_BIGINT extends DataTypes.BIGINT {
53
53
  return this.dataType.toUpperCase();
54
54
  }
55
55
  }
56
- class Sqlite_BINARY extends DataTypes {
56
+ class Sqlite_BINARY extends DataTypes.BINARY {
57
57
  constructor(dataLength = 255) {
58
58
  super(dataLength);
59
59
  this.dataLength = dataLength;
package/src/realm.js CHANGED
@@ -102,11 +102,14 @@ const rReplacementKey = /\s:(\w+)\b/g;
102
102
 
103
103
  class Realm {
104
104
  constructor(opts = {}) {
105
- let { client, dialect, database, driver: CustomDriver, ...restOpts } = {
106
- dialect: 'mysql',
107
- database: opts.db || opts.storage,
108
- ...opts
109
- };
105
+ const {
106
+ dialect = 'mysql',
107
+ dialectModulePath,
108
+ client = dialectModulePath,
109
+ database = opts.db || opts.storage,
110
+ driver: CustomDriver,
111
+ ...restOpts
112
+ } = opts;
110
113
  const Spine = createSpine(opts);
111
114
  const models = {};
112
115
 
@@ -214,7 +217,7 @@ class Realm {
214
217
  const { rows, ...restRes } = await this.driver.query(query, values, opts);
215
218
  const results = [];
216
219
 
217
- if (rows && rows.length && opts.model && opts.model.prototype instanceof this.Bone) {
220
+ if (rows && rows.length && opts.model && isBone(opts.model)) {
218
221
  const { attributeMap } = opts.model;
219
222
 
220
223
  for (const data of rows) {
@@ -0,0 +1,57 @@
1
+
2
+ export type Literal = null | undefined | boolean | number | bigint | string | Date | object | ArrayBuffer;
3
+
4
+ type BaseValidateArgs = boolean | RegExp | Function | Array<Array<Literal>> | string;
5
+
6
+ export type Validator = BaseValidateArgs | {
7
+ args: BaseValidateArgs,
8
+ msg?: string;
9
+ };
10
+
11
+ export interface ColumnBase {
12
+ allowNull?: boolean;
13
+ defaultValue?: Literal;
14
+ primaryKey?: boolean;
15
+ comment?: string;
16
+ unique?: boolean;
17
+ columnName?: string;
18
+ columnType?: string;
19
+ autoIncrement?: boolean;
20
+ }
21
+
22
+ export interface QueryResult {
23
+ insertId?: number;
24
+ affectedRows?: number;
25
+ rows?: Array<Record<string, Literal>>,
26
+ fields?: Array<{ table: string, name: string }>,
27
+ }
28
+
29
+ export interface Connection {
30
+ /**
31
+ * MySQL
32
+ */
33
+ query(
34
+ query: string,
35
+ values: Array<Literal | Literal[]>,
36
+ ): Promise<QueryResult>;
37
+ }
38
+
39
+ export interface QueryOptions {
40
+ validate?: boolean;
41
+ individualHooks?: boolean;
42
+ hooks?: boolean;
43
+ paranoid?: boolean;
44
+ silent?: boolean;
45
+ connection?: Connection;
46
+ }
47
+
48
+ export interface AssociateOptions {
49
+ className?: string;
50
+ foreignKey?: string;
51
+ }
52
+
53
+ export type command = 'select' | 'insert' | 'bulkInsert' | 'update' | 'delete' | 'upsert';
54
+
55
+ export type ResultSet = {
56
+ [key: string]: Literal
57
+ };
File without changes
@@ -1,105 +0,0 @@
1
- type LENGTH_VARIANTS = 'tiny' | '' | 'medium' | 'long';
2
-
3
- interface INVOKABLE<T> extends DataType {
4
- (dataLength?: LENGTH_VARIANTS): T;
5
- (dataLength?: number): T;
6
- }
7
-
8
- export default class DataType {
9
- toSqlString(): string;
10
-
11
- static STRING: INVOKABLE<STRING>;
12
- static INTEGER: INTEGER & INVOKABLE<INTEGER>;
13
- static BIGINT: BIGINT & INVOKABLE<BIGINT>;
14
- static DECIMAL: DECIMAL & INVOKABLE<DECIMAL>;
15
- static TEXT: INVOKABLE<TEXT>;
16
- static BLOB: INVOKABLE<BLOB>;
17
- static JSON: JSON;
18
- static JSONB: JSONB;
19
- static BINARY: BINARY & INVOKABLE<BINARY>;
20
- static VARBINARY: VARBINARY & INVOKABLE<VARBINARY>;
21
- static DATE: DATE & INVOKABLE<DATE>;
22
- static DATEONLY: DATEONLY;
23
- static BOOLEAN: BOOLEAN;
24
- static VIRTUAL: VIRTUAL;
25
-
26
- }
27
-
28
- declare class STRING extends DataType {
29
- dataType: 'varchar';
30
- dataLength: number;
31
- constructor(dataLength: number);
32
- }
33
-
34
- declare class INTEGER extends DataType {
35
- dataType: 'integer' | 'bigint' | 'decimal';
36
- dataLength: number;
37
- constructor(dataLength: number);
38
- // avoid INTEGER.UNSIGNED.ZEROFILL.UNSIGNED.UNSIGNED
39
- get UNSIGNED(): Omit<this, 'UNSIGNED' | 'ZEROFILL'>;
40
- get ZEROFILL(): Omit<this, 'UNSIGNED' | 'ZEROFILL'>;
41
- }
42
-
43
- declare class BIGINT extends INTEGER {
44
- dataType: 'bigint';
45
- }
46
-
47
- declare class DECIMAL_INNER extends INTEGER {
48
- dataType: 'decimal';
49
- precision: number;
50
- scale: number;
51
- constructor(precision: number, scale: number);
52
- }
53
-
54
- declare type DECIMAL = Omit<DECIMAL_INNER, 'dataLength'>;
55
-
56
- declare class TEXT extends DataType {
57
- dataType: 'text';
58
- dataLength: LENGTH_VARIANTS;
59
- constructor(dataLength: LENGTH_VARIANTS);
60
- }
61
-
62
- declare class BLOB extends DataType {
63
- dataType: 'blob';
64
- dataLength: LENGTH_VARIANTS;
65
- constructor(dataLength: LENGTH_VARIANTS)
66
- }
67
-
68
- declare class JSON extends DataType {
69
- dataType: 'text' | 'json';
70
- }
71
-
72
- declare class JSONB extends JSON {
73
- dataType: 'json';
74
- }
75
-
76
- declare class BINARY extends DataType {
77
- dataType: 'binary';
78
- dataLength: number;
79
- constructor(dataLength: number);
80
- }
81
-
82
- declare class VARBINARY extends DataType {
83
- dataType: 'varbinary';
84
- dataLength: number;
85
- constructor(dataLength: number);
86
- }
87
-
88
- declare class DATE extends DataType {
89
- dataType: 'date';
90
- precision: number;
91
- timezone: boolean;
92
- constructor(precision: number, timezone?: boolean)
93
- }
94
-
95
- declare class DATEONLY extends DataType {
96
- dataType: 'dateonly';
97
- }
98
-
99
- declare class BOOLEAN extends DataType {
100
- dataType: 'boolean'
101
- }
102
-
103
- declare class VIRTUAL extends DataType {
104
- dataType: 'virtual'
105
- }