Skip to content

Commit

Permalink
feat: support Blob type (#303)
Browse files Browse the repository at this point in the history
  • Loading branch information
sixmen committed Jun 12, 2024
1 parent 909ddce commit 6fe4e5c
Show file tree
Hide file tree
Showing 13 changed files with 104 additions and 14 deletions.
3 changes: 3 additions & 0 deletions packages/cormo/lib/adapters/mongodb.js
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,9 @@ class MongoDBAdapter extends base_1.AdapterBase {
return value && _objectIdToString(value);
}
}
else if (property.type_class === types.Blob) {
return value.read(0, value.length);
}
else {
return value;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/cormo/lib/adapters/mysql.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ function _typeToSQL(property, support_fractional_seconds, major_version) {
return 'TEXT';
case types.Text:
return 'TEXT';
case types.Blob:
return 'BLOB';
}
}
function _propertyToSQL(property, support_fractional_seconds, major_version) {
Expand Down Expand Up @@ -1015,7 +1017,9 @@ class MySQLAdapter extends sql_base_1.SQLAdapterBase {
? new types.Date()
: /^text/i.test(column.Type)
? new types.Text()
: undefined;
: /^blob/i.test(column.Type)
? new types.Blob()
: undefined;
schema.columns[column.Field] = {
required: column.Null === 'NO',
type,
Expand Down
6 changes: 5 additions & 1 deletion packages/cormo/lib/adapters/postgresql.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ function _typeToSQL(property) {
return 'JSON';
case types.Text:
return 'TEXT';
case types.Blob:
return 'BYTEA';
}
}
function _propertyToSQL(property) {
Expand Down Expand Up @@ -742,7 +744,9 @@ class PostgreSQLAdapter extends sql_base_1.SQLAdapterBase {
? new types.Object()
: column.data_type === 'text'
? new types.Text()
: undefined;
: column.data_type === 'bytea'
? new types.Blob()
: undefined;
let adapter_type_string = column.data_type.toUpperCase();
if (column.data_type === 'character varying') {
adapter_type_string += `(${column.character_maximum_length || 255})`;
Expand Down
6 changes: 5 additions & 1 deletion packages/cormo/lib/adapters/sqlite3.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ function _typeToSQL(property) {
return 'TEXT';
case types.Text:
return 'TEXT';
case types.Blob:
return 'BLOB';
}
}
function _propertyToSQL(property) {
Expand Down Expand Up @@ -695,7 +697,9 @@ class SQLite3Adapter extends sql_base_1.SQLAdapterBase {
? new types.Date()
: /^text/i.test(column.type)
? new types.Text()
: undefined;
: /^blob/i.test(column.type)
? new types.Blob()
: undefined;
schema.columns[column.name] = {
required: column.notnull === 1,
type,
Expand Down
21 changes: 17 additions & 4 deletions packages/cormo/lib/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,30 @@ interface CormoTypesTextConstructor {
(): CormoTypesText;
}
declare const CormoTypesText: CormoTypesTextConstructor;
export type ColumnTypeInternal = CormoTypesString | CormoTypesNumber | CormoTypesBoolean | CormoTypesDate | CormoTypesObject | CormoTypesInteger | CormoTypesBigInteger | CormoTypesGeoPoint | CormoTypesRecordID | CormoTypesText;
export type ColumnTypeInternalConstructor = CormoTypesStringConstructor | CormoTypesNumberConstructor | CormoTypesBooleanConstructor | CormoTypesDateConstructor | CormoTypesObjectConstructor | CormoTypesIntegerConstructor | CormoTypesBigIntegerConstructor | CormoTypesGeoPointConstructor | CormoTypesRecordIDConstructor | CormoTypesTextConstructor;
/**
* Represents a blob, used in model schemas.
* @namespace types
* @class Blob
*/
export interface CormoTypesBlob {
_type: 'blob';
}
interface CormoTypesBlobConstructor {
new (): CormoTypesBlob;
(): CormoTypesBlob;
}
declare const CormoTypesBlob: CormoTypesBlobConstructor;
export type ColumnTypeInternal = CormoTypesString | CormoTypesNumber | CormoTypesBoolean | CormoTypesDate | CormoTypesObject | CormoTypesInteger | CormoTypesBigInteger | CormoTypesGeoPoint | CormoTypesRecordID | CormoTypesText | CormoTypesBlob;
export type ColumnTypeInternalConstructor = CormoTypesStringConstructor | CormoTypesNumberConstructor | CormoTypesBooleanConstructor | CormoTypesDateConstructor | CormoTypesObjectConstructor | CormoTypesIntegerConstructor | CormoTypesBigIntegerConstructor | CormoTypesGeoPointConstructor | CormoTypesRecordIDConstructor | CormoTypesTextConstructor | CormoTypesBlobConstructor;
type ColumnTypeNativeConstructor = StringConstructor | NumberConstructor | BooleanConstructor | DateConstructor | ObjectConstructor;
type ColumnTypeString = 'string' | 'number' | 'boolean' | 'date' | 'object' | 'integer' | 'biginteger' | 'geopoint' | 'recordid' | 'text';
type ColumnTypeString = 'string' | 'number' | 'boolean' | 'date' | 'object' | 'integer' | 'biginteger' | 'geopoint' | 'recordid' | 'text' | 'blob';
export type ColumnType = ColumnTypeInternal | ColumnTypeInternalConstructor | ColumnTypeNativeConstructor | ColumnTypeString;
/**
* Converts JavaScript built-in class to CORMO type
* @private
*/
declare function _toCORMOType(type: ColumnType): ColumnTypeInternal;
export { CormoTypesString as String, CormoTypesNumber as Number, CormoTypesBoolean as Boolean, CormoTypesInteger as Integer, CormoTypesBigInteger as BigInteger, CormoTypesGeoPoint as GeoPoint, CormoTypesDate as Date, CormoTypesObject as Object, CormoTypesRecordID as RecordID, CormoTypesText as Text, _toCORMOType, };
export { CormoTypesString as String, CormoTypesNumber as Number, CormoTypesBoolean as Boolean, CormoTypesInteger as Integer, CormoTypesBigInteger as BigInteger, CormoTypesGeoPoint as GeoPoint, CormoTypesDate as Date, CormoTypesObject as Object, CormoTypesRecordID as RecordID, CormoTypesText as Text, CormoTypesBlob as Blob, _toCORMOType, };
/**
* A pseudo type represents a record's unique identifier.
*
Expand Down
11 changes: 10 additions & 1 deletion packages/cormo/lib/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @namespace cormo
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports._toCORMOType = exports.Text = exports.RecordID = exports.Object = exports.Date = exports.GeoPoint = exports.BigInteger = exports.Integer = exports.Boolean = exports.Number = exports.String = void 0;
exports._toCORMOType = exports.Blob = exports.Text = exports.RecordID = exports.Object = exports.Date = exports.GeoPoint = exports.BigInteger = exports.Integer = exports.Boolean = exports.Number = exports.String = void 0;
const CormoTypesString = function (length) {
if (!(this instanceof CormoTypesString)) {
return new CormoTypesString(length);
Expand Down Expand Up @@ -77,6 +77,13 @@ const CormoTypesText = function () {
this.toString = () => 'text';
};
exports.Text = CormoTypesText;
const CormoTypesBlob = function () {
if (!(this instanceof CormoTypesBlob)) {
return new CormoTypesBlob();
}
this.toString = () => 'blob';
};
exports.Blob = CormoTypesBlob;
/**
* Converts JavaScript built-in class to CORMO type
* @private
Expand Down Expand Up @@ -108,6 +115,8 @@ function _toCORMOType(type) {
return new CormoTypesRecordID();
case 'text':
return new CormoTypesText();
case 'blob':
return new CormoTypesBlob();
}
throw new Error(`unknown type: ${type}`);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/cormo/src/adapters/mongodb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,8 @@ export class MongoDBAdapter extends AdapterBase {
} else {
return value && _objectIdToString(value);
}
} else if (property.type_class === types.Blob) {
return value.read(0, value.length);
} else {
return value;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/cormo/src/adapters/mysql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ function _typeToSQL(property: ColumnPropertyInternal, support_fractional_seconds
return 'TEXT';
case types.Text:
return 'TEXT';
case types.Blob:
return 'BLOB';
}
}

Expand Down Expand Up @@ -1101,7 +1103,9 @@ export class MySQLAdapter extends SQLAdapterBase {
? new types.Date()
: /^text/i.test(column.Type)
? new types.Text()
: undefined;
: /^blob/i.test(column.Type)
? new types.Blob()
: undefined;
schema.columns[column.Field] = {
required: column.Null === 'NO',
type,
Expand Down
6 changes: 5 additions & 1 deletion packages/cormo/src/adapters/postgresql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ function _typeToSQL(property: ColumnPropertyInternal) {
return 'JSON';
case types.Text:
return 'TEXT';
case types.Blob:
return 'BYTEA';
}
}

Expand Down Expand Up @@ -793,7 +795,9 @@ export class PostgreSQLAdapter extends SQLAdapterBase {
? new types.Object()
: column.data_type === 'text'
? new types.Text()
: undefined;
: column.data_type === 'bytea'
? new types.Blob()
: undefined;
let adapter_type_string = column.data_type.toUpperCase();
if (column.data_type === 'character varying') {
adapter_type_string += `(${column.character_maximum_length || 255})`;
Expand Down
6 changes: 5 additions & 1 deletion packages/cormo/src/adapters/sqlite3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ function _typeToSQL(property: ColumnPropertyInternal) {
return 'TEXT';
case types.Text:
return 'TEXT';
case types.Blob:
return 'BLOB';
}
}

Expand Down Expand Up @@ -740,7 +742,9 @@ export class SQLite3Adapter extends SQLAdapterBase {
? new types.Date()
: /^text/i.test(column.type)
? new types.Text()
: undefined;
: /^blob/i.test(column.type)
? new types.Blob()
: undefined;
schema.columns[column.name] = {
required: column.notnull === 1,
type,
Expand Down
33 changes: 30 additions & 3 deletions packages/cormo/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,27 @@ const CormoTypesText: CormoTypesTextConstructor = function (this: CormoTypesText
this.toString = () => 'text';
} as CormoTypesTextConstructor;

/**
* Represents a blob, used in model schemas.
* @namespace types
* @class Blob
*/
export interface CormoTypesBlob {
_type: 'blob';
}

interface CormoTypesBlobConstructor {
new (): CormoTypesBlob;
(): CormoTypesBlob;
}

const CormoTypesBlob: CormoTypesBlobConstructor = function (this: CormoTypesBlob): void {
if (!(this instanceof CormoTypesBlob)) {
return new (CormoTypesBlob as any)();
}
this.toString = () => 'blob';
} as CormoTypesBlobConstructor;

export type ColumnTypeInternal =
| CormoTypesString
| CormoTypesNumber
Expand All @@ -231,7 +252,8 @@ export type ColumnTypeInternal =
| CormoTypesBigInteger
| CormoTypesGeoPoint
| CormoTypesRecordID
| CormoTypesText;
| CormoTypesText
| CormoTypesBlob;

export type ColumnTypeInternalConstructor =
| CormoTypesStringConstructor
Expand All @@ -243,7 +265,8 @@ export type ColumnTypeInternalConstructor =
| CormoTypesBigIntegerConstructor
| CormoTypesGeoPointConstructor
| CormoTypesRecordIDConstructor
| CormoTypesTextConstructor;
| CormoTypesTextConstructor
| CormoTypesBlobConstructor;

type ColumnTypeNativeConstructor =
| StringConstructor
Expand All @@ -262,7 +285,8 @@ type ColumnTypeString =
| 'biginteger'
| 'geopoint'
| 'recordid'
| 'text';
| 'text'
| 'blob';

export type ColumnType =
| ColumnTypeInternal
Expand Down Expand Up @@ -301,6 +325,8 @@ function _toCORMOType(type: ColumnType): ColumnTypeInternal {
return new CormoTypesRecordID();
case 'text':
return new CormoTypesText();
case 'blob':
return new CormoTypesBlob();
}
throw new Error(`unknown type: ${type}`);
} else if (type === String) {
Expand Down Expand Up @@ -331,6 +357,7 @@ export {
CormoTypesObject as Object,
CormoTypesRecordID as RecordID,
CormoTypesText as Text,
CormoTypesBlob as Blob,
_toCORMOType,
};

Expand Down
8 changes: 8 additions & 0 deletions packages/cormo/test/cases/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class Type extends cormo.BaseModel {
public recordid?: any;
public recordid_array?: any[];
public text?: string;
public blob?: Buffer;
}

export default function (models: { Type: typeof Type; connection: cormo.Connection | null }) {
Expand Down Expand Up @@ -268,4 +269,11 @@ export default function (models: { Type: typeof Type; connection: cormo.Connecti
expect(record.recordid_array).to.eql(type_ids.map((id) => (id ? String(id) : null)));
expect(record_lean.recordid_array).to.eql(type_ids.map((id) => (id ? String(id) : null)));
});

it('blob', async () => {
let type = await models.Type.create({ blob: Buffer.from([1, 2, 3, 4]) });
expect(type.blob).to.deep.equal(Buffer.from([1, 2, 3, 4]));
type = await models.Type.find(type.id);
expect(type.blob).to.deep.equal(Buffer.from([1, 2, 3, 4]));
});
}
4 changes: 4 additions & 0 deletions packages/cormo/test/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ _dbs.forEach((db) => {

@cormo.Column('text')
public text?: string;

@cormo.Column('blob')
public blob?: Buffer;
}
models.Type = Type;
} else {
Expand All @@ -71,6 +74,7 @@ _dbs.forEach((db) => {
recordid_array: [_g.cormo.types.RecordID],
string: String,
text: _g.cormo.types.Text,
blob: _g.cormo.types.Blob,
});
}

Expand Down

0 comments on commit 6fe4e5c

Please sign in to comment.