From 2f2ca45bf9d181bdcb3c86bc11a6e78d6a922356 Mon Sep 17 00:00:00 2001 From: JimmyDaddy Date: Wed, 27 Apr 2022 11:14:49 +0800 Subject: [PATCH] fix: realm.Bone.DataTypes should be invokable, Invokable.TYPE.toSqlString() get wrong default length(1), DataType definitions (#307) * fix: realm.Bone.DataTypes should be invokable * chore: ts type definition correct, doc * fix: DataType.invokable.INTEGER.toString() = "INTEGER(1)" and type definitions * fix: dataLength in sqlite, decimal ts definition and doc Co-authored-by: JimmyDaddy --- docs/api/INTEGER.html | 4 +- docs/api/STRING.html | 4 +- docs/basics.md | 2 +- docs/querying.md | 1 + docs/zh/basics.md | 2 +- docs/zh/querying.md | 1 + src/bone.js | 4 +- src/data_types.js | 64 +++++------ src/drivers/abstract/attribute.js | 2 +- src/drivers/postgres/data_types.js | 4 +- src/drivers/sqlite/data_types.js | 18 +-- src/utils/invokable.js | 3 + ...custom_driver.ts => custom_driver.test.ts} | 16 ++- test/types/data_types.test.ts | 103 ++++++++++++++++++ test/types/data_types.ts | 31 ------ test/unit/data_types.test.js | 30 ++++- test/unit/realm.test.js | 19 ++++ types/data_types.d.ts | 67 ++++++------ types/index.d.ts | 8 +- 19 files changed, 260 insertions(+), 123 deletions(-) rename test/types/{custom_driver.ts => custom_driver.test.ts} (94%) create mode 100644 test/types/data_types.test.ts delete mode 100644 test/types/data_types.ts diff --git a/docs/api/INTEGER.html b/docs/api/INTEGER.html index 5fc5b491..64ad44a1 100644 --- a/docs/api/INTEGER.html +++ b/docs/api/INTEGER.html @@ -57,7 +57,7 @@

Constructor

-

new INTEGER(length)

+

new INTEGER(dataLength)

@@ -135,7 +135,7 @@
Parameters:
- length + dataLength diff --git a/docs/api/STRING.html b/docs/api/STRING.html index 372804c0..ffed34b0 100644 --- a/docs/api/STRING.html +++ b/docs/api/STRING.html @@ -50,7 +50,7 @@

-

new STRING(length)

+

new STRING(dataLength)

@@ -128,7 +128,7 @@
Parameters:
- length + dataLength diff --git a/docs/basics.md b/docs/basics.md index 4c0f84ad..60bcda6e 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -100,7 +100,7 @@ const { BIGINT, STRING } = Bone.DataTypes; class Shop extends Bone { static attributes = { id: { type: BIGINT, primaryKey: true }, - name: { type: STRING }, + name: STRING, } } diff --git a/docs/querying.md b/docs/querying.md index 991ebd7b..b04c3604 100644 --- a/docs/querying.md +++ b/docs/querying.md @@ -507,6 +507,7 @@ We can reference these table aliases futher after the join, such as `.where()` o ```js Post.join(Comment, 'posts.id = comments.postId').where('comments.id = 1') +Post.join(Comment, 'posts.id = comments.postId').where({ 'comments.id': 1 }) ``` ## Scopes diff --git a/docs/zh/basics.md b/docs/zh/basics.md index 32493990..763cf947 100644 --- a/docs/zh/basics.md +++ b/docs/zh/basics.md @@ -99,7 +99,7 @@ const { BIGINT, STRING } = Bone.DataTypes; class Shop extends Bone { static attributes = { id: { type: BIGINT, primaryKey: true }, - name: { type: STRING }, + name: STRING, } } diff --git a/docs/zh/querying.md b/docs/zh/querying.md index e9ed4e7c..598b6b83 100644 --- a/docs/zh/querying.md +++ b/docs/zh/querying.md @@ -501,6 +501,7 @@ SELECT * FROM posts LEFT JOIN comments ON posts.id = comments.post_id LEFT JOIN ```js Post.join(Comment, 'posts.id = comments.postId').where('comments.id = 1') +Post.join(Comment, 'posts.id = comments.postId').where({ 'comments.id': 1 }) ``` ## 查询限定 diff --git a/src/bone.js b/src/bone.js index 0d796d85..8a754700 100644 --- a/src/bone.js +++ b/src/bone.js @@ -138,6 +138,8 @@ function valuesValidate(values, attributes, ctx) { */ class Bone { + static DataTypes = DataTypes.invokable; + // private variables #raw = {}; #rawSaved = {}; @@ -1712,6 +1714,4 @@ for (const getter of Spell_getters) { }); } -Object.assign(Bone, { DataTypes }); - module.exports = Bone; diff --git a/src/data_types.js b/src/data_types.js index 0808f9b6..e7c44a6c 100644 --- a/src/data_types.js +++ b/src/data_types.js @@ -110,20 +110,20 @@ class DataType { * STRING * STRING(127) * STRING.BINARY - * @param {number} length + * @param {number} dataLength */ class STRING extends DataType { - constructor(length = 255) { + constructor(dataLength = 255) { super(); this.dataType = 'varchar'; - this.length = length; + this.dataLength = dataLength; } toSqlString() { - const { length } = this; + const { dataLength } = this; const dataType = this.dataType.toUpperCase(); const chunks = []; - chunks.push(length > 0 ? `${dataType}(${length})` : dataType); + chunks.push(dataLength > 0 ? `${dataType}(${dataLength})` : dataType); return chunks.join(' '); } @@ -134,17 +134,17 @@ class STRING extends DataType { } class BINARY extends DataType { - constructor(length = 255) { + constructor(dataLength = 255) { super(); - this.length = length; + this.dataLength = dataLength; this.dataType = 'binary'; } toSqlString() { - const { length } = this; + const { dataLength } = this; const dataType = this.dataType.toUpperCase(); const chunks = []; - chunks.push(length > 0 ? `${dataType}(${length})` : dataType); + chunks.push(dataLength > 0 ? `${dataType}(${dataLength})` : dataType); return chunks.join(' '); } @@ -156,8 +156,8 @@ class BINARY extends DataType { } class VARBINARY extends BINARY { - constructor(length) { - super(length); + constructor(dataLength) { + super(dataLength); this.dataType = 'varbinary'; } } @@ -170,12 +170,12 @@ class VARBINARY extends BINARY { * INTEGER.UNSIGNED * INTEGER.UNSIGNED.ZEROFILL * INTEGER(10) - * @param {number} length + * @param {number} dataLength */ class INTEGER extends DataType { - constructor(length) { + constructor(dataLength) { super(); - this.length = length; + this.dataLength = dataLength; this.dataType = 'integer'; } @@ -190,10 +190,10 @@ class INTEGER extends DataType { } toSqlString() { - const { length, unsigned, zerofill } = this; + const { dataLength, unsigned, zerofill } = this; const dataType = this.dataType.toUpperCase(); const chunks = []; - chunks.push(length > 0 ? `${dataType}(${length})` : dataType); + chunks.push(dataLength > 0 ? `${dataType}(${dataLength})` : dataType); if (unsigned) chunks.push('UNSIGNED'); if (zerofill) chunks.push('ZEROFILL'); return chunks.join(' '); @@ -222,11 +222,11 @@ class INTEGER extends DataType { * TINYINT * TINYINT.UNSIGNED * TINYINT(1) - * @param {number} length + * @param {number} dataLength */ class TINYINT extends INTEGER { - constructor(length) { - super(length); + constructor(dataLength) { + super(dataLength); this.dataType = 'tinyint'; } } @@ -237,11 +237,11 @@ class TINYINT extends INTEGER { * SMALLINT * SMALLINT.UNSIGNED * SMALLINT(2) - * @param {number} length + * @param {number} dataLength */ class SMALLINT extends INTEGER { - constructor(length) { - super(length); + constructor(dataLength) { + super(dataLength); this.dataType = 'smallint'; } } @@ -252,11 +252,11 @@ class SMALLINT extends INTEGER { * MEDIUMINT * MEDIUMINT.UNSIGNED * MEDIUMINT(3) - * @param {number} length + * @param {number} dataLength */ class MEDIUMINT extends INTEGER { - constructor(length) { - super(length); + constructor(dataLength) { + super(dataLength); this.dataType = 'mediumint'; } } @@ -268,11 +268,11 @@ class MEDIUMINT extends INTEGER { * BIGINT * BIGINT.UNSIGNED * BIGINT(8) - * @param {number} length + * @param {number} dataLength */ class BIGINT extends INTEGER { - constructor(length) { - super(length); + constructor(dataLength) { + super(dataLength); this.dataType = 'bigint'; } } @@ -442,11 +442,11 @@ class TEXT extends DataType { } super(); this.dataType = 'text'; - this.length = length; + this.dataLength = length; } toSqlString() { - return [ this.length, this.dataType ].join('').toUpperCase(); + return [ this.dataLength, this.dataType ].join('').toUpperCase(); } } @@ -457,11 +457,11 @@ class BLOB extends DataType { } super(); this.dataType = 'blob'; - this.length = length; + this.dataLength = length; } toSqlString() { - return [ this.length, this.dataType ].join('').toUpperCase(); + return [ this.dataLength, this.dataType ].join('').toUpperCase(); } cast(value) { diff --git a/src/drivers/abstract/attribute.js b/src/drivers/abstract/attribute.js index a5432686..fcdbb2a0 100644 --- a/src/drivers/abstract/attribute.js +++ b/src/drivers/abstract/attribute.js @@ -77,7 +77,7 @@ function createType(DataTypes, params) { case 'VARBINARY': case 'CHAR': case 'VARCHAR': - return new DataType(type.length); + return new DataType(type.dataLength); default: return new DataType(); } diff --git a/src/drivers/postgres/data_types.js b/src/drivers/postgres/data_types.js index 9d9beec0..9bc56166 100644 --- a/src/drivers/postgres/data_types.js +++ b/src/drivers/postgres/data_types.js @@ -41,8 +41,8 @@ class Postgres_BINARY extends DataTypes { } class Postgres_INTEGER extends DataTypes.INTEGER { - constructor(length) { - super(length); + constructor(dataLength) { + super(dataLength); } uncast(value) { diff --git a/src/drivers/sqlite/data_types.js b/src/drivers/sqlite/data_types.js index 8c7d1ca4..96ddc991 100644 --- a/src/drivers/sqlite/data_types.js +++ b/src/drivers/sqlite/data_types.js @@ -34,8 +34,8 @@ class Sqlite_DATEONLY extends DataTypes.DATEONLY { } class Sqlite_INTEGER extends DataTypes.INTEGER { - constructor(length) { - super(length); + constructor(dataLength) { + super(dataLength); } uncast(value) { @@ -54,24 +54,24 @@ class Sqlite_BIGINT extends DataTypes.BIGINT { } } class Sqlite_BINARY extends DataTypes { - constructor(length = 255) { - super(length); - this.length = length; + constructor(dataLength = 255) { + super(dataLength); + this.dataLength = dataLength; this.dataType = 'binary'; } toSqlString() { - const { length } = this; + const { dataLength } = this; const dataType = this.dataType.toUpperCase(); const chunks = []; chunks.push('VARCHAR'); - chunks.push(length > 0 ? `${dataType}(${length})` : dataType); + chunks.push(dataLength > 0 ? `${dataType}(${dataLength})` : dataType); return chunks.join(' '); } } class Sqlite_VARBINARY extends Sqlite_BINARY { - constructor(length) { - super(length); + constructor(dataLength) { + super(dataLength); this.dataType = 'varbinary'; } } diff --git a/src/utils/invokable.js b/src/utils/invokable.js index cbf7ca7a..1e2381dc 100644 --- a/src/utils/invokable.js +++ b/src/utils/invokable.js @@ -18,6 +18,9 @@ function invokable(DataType) { // INTEGER.UNSIGNED get(target, p) { + // ref: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/length + // The length property indicates the number of parameters expected by the function. + // invokable INTEGER.toSqlString() will default to return "INTEGER(1)" return target.hasOwnProperty(p) ? target[p] : new target()[p]; } }); diff --git a/test/types/custom_driver.ts b/test/types/custom_driver.test.ts similarity index 94% rename from test/types/custom_driver.ts rename to test/types/custom_driver.test.ts index a2e8017d..f0b000b4 100644 --- a/test/types/custom_driver.ts +++ b/test/types/custom_driver.test.ts @@ -186,17 +186,21 @@ describe('=> Realm (TypeScript)', function () { }); }); + afterEach(async () => { + await realm?.driver?.dropTable('test_user'); + }); + describe('realm.define(name, attributes, options, descriptors)', async function() { it('options and descriptors should be optional', async function() { assert.doesNotThrow(function() { const { STRING } = realm.DataTypes; - realm.define('User', { name: STRING }); + realm.define('TestUser', { name: STRING }); }); }); it('can customize attributes with descriptors', async function() { const { STRING } = realm.DataTypes; - const User = realm.define('User', { name: STRING }, {}, { + const User = realm.define('TestUser', { name: STRING }, {}, { get name() { return this.attribute('name').replace(/^([a-z])/, function(m, chr) { return chr.toUpperCase(); @@ -216,7 +220,7 @@ describe('=> Realm (TypeScript)', function () { it('options should be optional', async function() { assert.doesNotThrow(async () => { const { STRING } = realm.DataTypes; - realm.define('User', { name: STRING }); + realm.define('TestUser', { name: STRING }); await realm.sync(); }); }); @@ -224,7 +228,7 @@ describe('=> Realm (TypeScript)', function () { it('`force` can be passed individually', async function() { assert.doesNotThrow(async () => { const { STRING } = realm.DataTypes; - realm.define('User', { name: STRING }); + realm.define('TestUser', { name: STRING }); await realm.sync({ force: true }); }); }); @@ -232,7 +236,7 @@ describe('=> Realm (TypeScript)', function () { it('`alter` can be passed individually', async function() { assert.doesNotThrow(async () => { const { STRING } = realm.DataTypes; - realm.define('User', { name: STRING }); + realm.define('TestUser', { name: STRING }); await realm.sync({ alter: true }); }); }); @@ -240,7 +244,7 @@ describe('=> Realm (TypeScript)', function () { it('`force` and `alter` can be passed together', async function() { assert.doesNotThrow(async () => { const { STRING } = realm.DataTypes; - realm.define('User', { name: STRING }); + realm.define('TestUser', { name: STRING }); await realm.sync({ force: true, alter: true }); }); }); diff --git a/test/types/data_types.test.ts b/test/types/data_types.test.ts new file mode 100644 index 00000000..cb76c6c4 --- /dev/null +++ b/test/types/data_types.test.ts @@ -0,0 +1,103 @@ +import { strict as assert } from 'assert'; +import Realm, { DataTypes } from '../..'; + +describe('=> Data types (TypeScript)', function() { + const { STRING, TEXT, BLOB, INTEGER, BIGINT, DATE, BOOLEAN, BINARY, VARBINARY, VIRTUAL, JSON, JSONB, DECIMAL } = DataTypes; + + it('realm.Bone.DataTypes', async function() { + const realm = new Realm({ + dialect: 'sqlite', + database: '/tmp/leoric.sqlite3', + }); + // should be mixed with dialect overrides + assert.notEqual(realm.Bone.DataTypes, DataTypes); + }) + + it('STRING', async function() { + assert.equal(STRING(255).toSqlString(), 'VARCHAR(255)'); + // default 255 + assert.equal(STRING.toSqlString(), 'VARCHAR(255)'); + }); + + it('INTEGER', async function() { + assert.equal(INTEGER(255).toSqlString(), 'INTEGER(255)'); + assert.equal(INTEGER(255).UNSIGNED.toSqlString(), 'INTEGER(255) UNSIGNED'); + assert.equal(INTEGER(255).ZEROFILL.toSqlString(), 'INTEGER(255) ZEROFILL'); + + assert.equal(INTEGER.toSqlString(), 'INTEGER'); + assert.equal(INTEGER.UNSIGNED.toSqlString(), 'INTEGER UNSIGNED'); + assert.equal(INTEGER.ZEROFILL.toSqlString(), 'INTEGER ZEROFILL'); + + assert.equal(INTEGER(255).toSqlString(), 'INTEGER(255)'); + assert.equal(INTEGER(255).UNSIGNED.toSqlString(), 'INTEGER(255) UNSIGNED'); + assert.equal(INTEGER(255).ZEROFILL.toSqlString(), 'INTEGER(255) ZEROFILL'); + }); + + it('BIGINT', async function() { + assert.equal(BIGINT(255).toSqlString(), 'BIGINT(255)'); + assert.equal(BIGINT(255).UNSIGNED.toSqlString(), 'BIGINT(255) UNSIGNED'); + assert.equal(BIGINT(255).ZEROFILL.toSqlString(), 'BIGINT(255) ZEROFILL'); + + assert.equal(BIGINT.toSqlString(), 'BIGINT'); + assert.equal(BIGINT.UNSIGNED.toSqlString(), 'BIGINT UNSIGNED'); + + assert.equal(BIGINT.ZEROFILL.toSqlString(), 'BIGINT ZEROFILL'); + assert.equal(BIGINT(255).toSqlString(), 'BIGINT(255)'); + assert.equal(BIGINT(255).UNSIGNED.toSqlString(), 'BIGINT(255) UNSIGNED'); + assert.equal(BIGINT(255).ZEROFILL.toSqlString(), 'BIGINT(255) ZEROFILL'); + }); + + it('TEXT', async function() { + assert.equal(TEXT('long').toSqlString(), 'LONGTEXT'); + assert.equal(TEXT.toSqlString(), 'TEXT'); + }); + + it('BLOB', async function() { + assert.equal(BLOB('medium').toSqlString(), 'MEDIUMBLOB'); + assert.equal(BLOB.toSqlString(), 'BLOB'); + }); + + it('DATE', () => { + assert.equal(DATE.toSqlString(), 'DATETIME'); + assert.equal(DATE(3).toSqlString(), 'DATETIME(3)'); + }); + + it('BOOLEAN', () => { + assert.equal(BOOLEAN.toSqlString(), 'BOOLEAN'); + }) + + it('BINARY', () => { + // default 255 + assert.equal(BINARY.toSqlString(), 'BINARY(255)'); + assert.equal(BINARY(3).toSqlString(), 'BINARY(3)'); + }); + + it('VARBINARY', () => { + // default 255 + assert.equal(VARBINARY.toSqlString(), 'VARBINARY(255)'); + assert.equal(VARBINARY(3).toSqlString(), 'VARBINARY(3)'); + }); + + it('VIRTUAL', () => { + assert.equal(VIRTUAL.toSqlString(), 'VIRTUAL'); + }); + + it('JSON', () => { + assert.equal(JSON.toSqlString(), 'TEXT'); + }); + + it('JSONB', () => { + assert.equal(JSONB.toSqlString(), 'JSON'); + }); + + it('DECIMAL', () => { + assert.equal(DECIMAL.toSqlString(), 'DECIMAL'); + assert.equal(DECIMAL(10).toSqlString(), 'DECIMAL(10)'); + + assert.equal(DECIMAL.UNSIGNED.toSqlString(), 'DECIMAL UNSIGNED'); + assert.equal(DECIMAL(10).UNSIGNED.toSqlString(), 'DECIMAL(10) UNSIGNED'); + + assert.equal(DECIMAL.ZEROFILL.toSqlString(), 'DECIMAL ZEROFILL'); + assert.equal(DECIMAL(10).ZEROFILL.toSqlString(), 'DECIMAL(10) ZEROFILL'); + }) +}); diff --git a/test/types/data_types.ts b/test/types/data_types.ts deleted file mode 100644 index 3412c2b0..00000000 --- a/test/types/data_types.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { strict as assert } from 'assert'; -import Realm, { Bone, DataTypes } from '../..'; - -describe('=> Data types (TypeScript)', function() { - const { STRING, TEXT, BLOB } = DataTypes; - - it('Bone.DataTypes', async function() { - assert.equal(Bone.DataTypes, DataTypes); - }); - - it('realm.Bone.DataTypes', async function() { - const realm = new Realm({ - dialect: 'sqlite', - database: '/tmp/leoric.sqlite3', - }); - // should be mixed with dialect overrides - assert.notEqual(realm.Bone.DataTypes, DataTypes); - }) - - it('STRING', async function() { - assert.equal(STRING(255).toSqlString(), 'VARCHAR(255)'); - }); - - it('TEXT', async function() { - assert.equal(TEXT('long').toSqlString(), 'LONGTEXT'); - }); - - it('BLOB', async function() { - assert.equal(BLOB('medium').toSqlString(), 'MEDIUMBLOB'); - }); -}); diff --git a/test/unit/data_types.test.js b/test/unit/data_types.test.js index bf96669c..b5be6daa 100644 --- a/test/unit/data_types.test.js +++ b/test/unit/data_types.test.js @@ -303,9 +303,37 @@ describe('=> DataTypes.findType()', () => { }); describe('=> DataTypes.invokable', function() { - const { STRING } = DataTypes.invokable; + const { STRING, INTEGER, TEXT, BLOB, BIGINT } = DataTypes.invokable; it('should wrap data types to support flexible invoking', async function() { assert.equal(STRING(255).toSqlString(), 'VARCHAR(255)'); + assert.equal(STRING.toSqlString(), 'VARCHAR(255)'); + + // NOT "INTEGER(1)" + // ref: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/length + // The length property indicates the number of parameters expected by the function. + assert.equal(INTEGER.toSqlString(), 'INTEGER'); + assert.equal(INTEGER.UNSIGNED.toSqlString(), 'INTEGER UNSIGNED'); + assert.equal(INTEGER.ZEROFILL.toSqlString(), 'INTEGER ZEROFILL'); + + assert.equal(INTEGER(10).UNSIGNED.toSqlString(), 'INTEGER(10) UNSIGNED'); + assert.equal(INTEGER(10).ZEROFILL.toSqlString(), 'INTEGER(10) ZEROFILL'); + assert.equal(INTEGER(10).toSqlString(), 'INTEGER(10)'); + + assert.equal(BIGINT.toSqlString(), 'BIGINT'); + assert.equal(BIGINT.UNSIGNED.toSqlString(), 'BIGINT UNSIGNED'); + assert.equal(BIGINT.ZEROFILL.toSqlString(), 'BIGINT ZEROFILL'); + + assert.equal(BIGINT(10).UNSIGNED.toSqlString(), 'BIGINT(10) UNSIGNED'); + assert.equal(BIGINT(10).ZEROFILL.toSqlString(), 'BIGINT(10) ZEROFILL'); + assert.equal(BIGINT(10).toSqlString(), 'BIGINT(10)'); + + // NOT "0TEXT" + assert.equal(TEXT.toSqlString(), 'TEXT'); + assert.equal(TEXT('tiny').toSqlString(), 'TINYTEXT'); + + assert.equal(BLOB.toSqlString(), 'BLOB'); + assert.equal(BLOB('tiny').toSqlString(), 'TINYBLOB'); + }); }); diff --git a/test/unit/realm.test.js b/test/unit/realm.test.js index d8330992..688a2010 100644 --- a/test/unit/realm.test.js +++ b/test/unit/realm.test.js @@ -144,6 +144,25 @@ describe('=> Realm', () => { }); }); + describe('DataTypes', () => { + it('invokable', () => { + const realm = new Realm({ subclass: true }); + assert(realm.DataTypes.INTEGER.UNSIGNED); + assert(realm.Bone.DataTypes.INTEGER.UNSIGNED instanceof DataTypes.INTEGER); + assert(realm.Bone.DataTypes.INTEGER.ZEROFILL instanceof DataTypes.INTEGER); + + assert(realm.Bone.DataTypes.BIGINT.UNSIGNED instanceof DataTypes.INTEGER); + assert(realm.Bone.DataTypes.BIGINT.ZEROFILL instanceof DataTypes.INTEGER); + + assert.equal(realm.Bone.DataTypes.INTEGER.UNSIGNED.unsigned, true); + assert.equal(realm.Bone.DataTypes.BIGINT.UNSIGNED.unsigned, true); + + assert.equal(realm.Bone.DataTypes.INTEGER.ZEROFILL.zerofill, true); + assert.equal(realm.Bone.DataTypes.BIGINT.ZEROFILL.zerofill, true); + + }); + }); + describe('realm.query', async () => { class Post extends Bone { diff --git a/types/data_types.d.ts b/types/data_types.d.ts index af89cea4..84c281ac 100644 --- a/types/data_types.d.ts +++ b/types/data_types.d.ts @@ -1,65 +1,68 @@ type LENGTH_VARIANTS = 'tiny' | '' | 'medium' | 'long'; -interface INVOKABLE { - (length: LENGTH_VARIANTS): T; - (length: number): T; +interface INVOKABLE extends DataType { + (dataLength?: LENGTH_VARIANTS): T; + (dataLength?: number): T; } export default class DataType { toSqlString(): string; - static STRING: typeof STRING & INVOKABLE; - static INTEGER: typeof INTEGER & INVOKABLE; - static BIGINT: typeof BIGINT & INVOKABLE; - static DECIMAL: typeof DECIMAL & INVOKABLE; - static TEXT: typeof TEXT & INVOKABLE; - static BLOB: typeof BLOB & INVOKABLE; - static JSON: typeof JSON & INVOKABLE; - static JSONB: typeof JSONB & INVOKABLE; - static BINARY: typeof BINARY & INVOKABLE; - static VARBINARY: typeof VARBINARY & INVOKABLE; - static DATE: typeof DATE & INVOKABLE; - static DATEONLY: typeof DATEONLY & INVOKABLE; - static BOOLEAN: typeof BOOLEAN & INVOKABLE; - static VIRTUAL: typeof VIRTUAL & INVOKABLE; + static STRING: INVOKABLE; + static INTEGER: INTEGER & INVOKABLE; + static BIGINT: BIGINT & INVOKABLE; + static DECIMAL: DECIMAL & INVOKABLE; + static TEXT: INVOKABLE; + static BLOB: INVOKABLE; + static JSON: JSON; + static JSONB: JSONB; + static BINARY: BINARY & INVOKABLE; + static VARBINARY: VARBINARY & INVOKABLE; + static DATE: DATE & INVOKABLE; + static DATEONLY: DATEONLY; + static BOOLEAN: BOOLEAN; + static VIRTUAL: VIRTUAL; } declare class STRING extends DataType { dataType: 'varchar'; - length: number; - constructor(length: number); + dataLength: number; + constructor(dataLength: number); } declare class INTEGER extends DataType { dataType: 'integer' | 'bigint' | 'decimal'; - length: number; - constructor(length: number); - get UNSIGNED(): this; - get ZEROFILL(): this; + dataLength: number; + constructor(dataLength: number); + // avoid INTEGER.UNSIGNED.ZEROFILL.UNSIGNED.UNSIGNED + get UNSIGNED(): Omit; + get ZEROFILL(): Omit; } declare class BIGINT extends INTEGER { dataType: 'bigint'; } -declare class DECIMAL extends INTEGER { +declare class DECIMAL_INNER extends INTEGER { dataType: 'decimal'; precision: number; scale: number; constructor(precision: number, scale: number); } +declare type DECIMAL = Omit; + declare class TEXT extends DataType { dataType: 'text'; - length: LENGTH_VARIANTS; - constructor(length: LENGTH_VARIANTS); + dataLength: LENGTH_VARIANTS; + constructor(dataLength: LENGTH_VARIANTS); } declare class BLOB extends DataType { dataType: 'blob'; - length: LENGTH_VARIANTS; - constructor(length: LENGTH_VARIANTS) + dataLength: LENGTH_VARIANTS; + constructor(dataLength: LENGTH_VARIANTS) } declare class JSON extends DataType { @@ -72,14 +75,14 @@ declare class JSONB extends JSON { declare class BINARY extends DataType { dataType: 'binary'; - length: number; - constructor(length: number); + dataLength: number; + constructor(dataLength: number); } declare class VARBINARY extends DataType { dataType: 'varbinary'; - length: number; - constructor(length: number); + dataLength: number; + constructor(dataLength: number); } declare class DATE extends DataType { diff --git a/types/index.d.ts b/types/index.d.ts index 2d81bea0..bee7e37b 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -179,11 +179,17 @@ export interface ColumnMeta { comment?: string; datetimePrecision?: string; } + +declare type validator = Literal | Function | Array; + export interface AttributeMeta extends ColumnMeta { jsType?: Literal; type: DataType; virtual?: boolean, toSqlString: () => string; + validate: { + [key: string]: validator; + } } interface RelateOptions { @@ -442,7 +448,7 @@ export class Collection extends Array { } export class Bone { - static DataTypes: DataType; + static DataTypes: typeof DataType; /** * get the connection pool of the driver