drizzle-orm 1.0.0-beta.1-bd417c1 → 1.0.0-beta.1-03aea0b
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/gel-core/columns/common.cjs +8 -0
- package/gel-core/columns/common.cjs.map +1 -1
- package/gel-core/columns/common.d.cts +2 -0
- package/gel-core/columns/common.d.ts +2 -0
- package/gel-core/columns/common.js +8 -0
- package/gel-core/columns/common.js.map +1 -1
- package/gel-core/columns/custom.cjs +12 -0
- package/gel-core/columns/custom.cjs.map +1 -1
- package/gel-core/columns/custom.d.cts +116 -4
- package/gel-core/columns/custom.d.ts +116 -4
- package/gel-core/columns/custom.js +12 -0
- package/gel-core/columns/custom.js.map +1 -1
- package/gel-core/dialect.cjs +21 -2
- package/gel-core/dialect.cjs.map +1 -1
- package/gel-core/dialect.js +22 -3
- package/gel-core/dialect.js.map +1 -1
- package/mysql-core/columns/custom.cjs +28 -0
- package/mysql-core/columns/custom.cjs.map +1 -1
- package/mysql-core/columns/custom.d.cts +119 -4
- package/mysql-core/columns/custom.d.ts +119 -4
- package/mysql-core/columns/custom.js +28 -0
- package/mysql-core/columns/custom.js.map +1 -1
- package/mysql-core/dialect.cjs +3 -0
- package/mysql-core/dialect.cjs.map +1 -1
- package/mysql-core/dialect.js +3 -0
- package/mysql-core/dialect.js.map +1 -1
- package/package.json +37 -37
- package/pg-core/columns/common.cjs +8 -0
- package/pg-core/columns/common.cjs.map +1 -1
- package/pg-core/columns/common.d.cts +1 -0
- package/pg-core/columns/common.d.ts +1 -0
- package/pg-core/columns/common.js +8 -0
- package/pg-core/columns/common.js.map +1 -1
- package/pg-core/columns/custom.cjs +27 -0
- package/pg-core/columns/custom.cjs.map +1 -1
- package/pg-core/columns/custom.d.cts +118 -4
- package/pg-core/columns/custom.d.ts +118 -4
- package/pg-core/columns/custom.js +27 -0
- package/pg-core/columns/custom.js.map +1 -1
- package/pg-core/dialect.cjs +7 -3
- package/pg-core/dialect.cjs.map +1 -1
- package/pg-core/dialect.js +7 -3
- package/pg-core/dialect.js.map +1 -1
- package/relations.cjs +1 -1
- package/relations.cjs.map +1 -1
- package/relations.js +1 -1
- package/relations.js.map +1 -1
- package/singlestore-core/columns/custom.cjs +28 -0
- package/singlestore-core/columns/custom.cjs.map +1 -1
- package/singlestore-core/columns/custom.d.cts +119 -4
- package/singlestore-core/columns/custom.d.ts +119 -4
- package/singlestore-core/columns/custom.js +28 -0
- package/singlestore-core/columns/custom.js.map +1 -1
- package/sql/sql.cjs.map +1 -1
- package/sql/sql.d.cts +1 -0
- package/sql/sql.d.ts +1 -0
- package/sql/sql.js.map +1 -1
- package/sqlite-core/columns/custom.cjs +27 -0
- package/sqlite-core/columns/custom.cjs.map +1 -1
- package/sqlite-core/columns/custom.d.cts +119 -4
- package/sqlite-core/columns/custom.d.ts +119 -4
- package/sqlite-core/columns/custom.js +27 -0
- package/sqlite-core/columns/custom.js.map +1 -1
- package/sqlite-core/dialect.cjs +3 -0
- package/sqlite-core/dialect.cjs.map +1 -1
- package/sqlite-core/dialect.js +3 -0
- package/sqlite-core/dialect.js.map +1 -1
- package/version.cjs +1 -1
- package/version.d.cts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
|
@@ -197,6 +197,14 @@ class GelArray extends GelColumn {
|
|
|
197
197
|
}
|
|
198
198
|
size;
|
|
199
199
|
static [import_entity.entityKind] = "GelArray";
|
|
200
|
+
mapFromDriverValue(value) {
|
|
201
|
+
return value.map((v) => this.baseColumn.mapFromDriverValue(v));
|
|
202
|
+
}
|
|
203
|
+
// Needed for arrays of custom types
|
|
204
|
+
mapFromJsonValue(value) {
|
|
205
|
+
const base = this.baseColumn;
|
|
206
|
+
return "mapFromJsonValue" in base ? value.map((v) => base.mapFromJsonValue(v)) : value.map((v) => base.mapFromDriverValue(v));
|
|
207
|
+
}
|
|
200
208
|
getSQLType() {
|
|
201
209
|
return `${this.baseColumn.getSQLType()}[${typeof this.size === "number" ? this.size : ""}]`;
|
|
202
210
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/gel-core/columns/common.ts"],"sourcesContent":["import type {\n\tColumnBuilderBase,\n\tColumnBuilderBaseConfig,\n\tColumnBuilderExtraConfig,\n\tColumnBuilderRuntimeConfig,\n\tColumnDataType,\n\tHasGenerated,\n\tMakeColumnConfig,\n} from '~/column-builder.ts';\nimport { ColumnBuilder } from '~/column-builder.ts';\nimport type { ColumnBaseConfig } from '~/column.ts';\nimport { Column } from '~/column.ts';\nimport { entityKind } from '~/entity.ts';\nimport type { Simplify, Update } from '~/utils.ts';\n\nimport type { ForeignKey, UpdateDeleteAction } from '~/gel-core/foreign-keys.ts';\nimport { ForeignKeyBuilder } from '~/gel-core/foreign-keys.ts';\nimport type { AnyGelTable, GelTable } from '~/gel-core/table.ts';\nimport type { SQL } from '~/sql/sql.ts';\nimport { iife } from '~/tracing-utils.ts';\nimport type { GelIndexOpClass } from '../indexes.ts';\nimport { uniqueKeyName } from '../unique-constraint.ts';\n\nexport interface ReferenceConfig {\n\tref: () => GelColumn;\n\tactions: {\n\t\tonUpdate?: UpdateDeleteAction;\n\t\tonDelete?: UpdateDeleteAction;\n\t};\n}\n\nexport interface GelColumnBuilderBase<\n\tT extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>,\n\tTTypeConfig extends object = object,\n> extends ColumnBuilderBase<T, TTypeConfig & { dialect: 'gel' }> {}\n\nexport abstract class GelColumnBuilder<\n\tT extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>,\n\tTRuntimeConfig extends object = object,\n\tTTypeConfig extends object = object,\n\tTExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig,\n> extends ColumnBuilder<T, TRuntimeConfig, TTypeConfig & { dialect: 'gel' }, TExtraConfig>\n\timplements GelColumnBuilderBase<T, TTypeConfig>\n{\n\tprivate foreignKeyConfigs: ReferenceConfig[] = [];\n\n\tstatic override readonly [entityKind]: string = 'GelColumnBuilder';\n\n\tarray<TSize extends number | undefined = undefined>(size?: TSize): GelArrayBuilder<\n\t\t& {\n\t\t\tname: T['name'];\n\t\t\tdataType: 'array';\n\t\t\tcolumnType: 'GelArray';\n\t\t\tdata: T['data'][];\n\t\t\tdriverParam: T['driverParam'][] | string;\n\t\t\tenumValues: T['enumValues'];\n\t\t\tsize: TSize;\n\t\t\tbaseBuilder: T;\n\t\t}\n\t\t& (T extends { notNull: true } ? { notNull: true } : {})\n\t\t& (T extends { hasDefault: true } ? { hasDefault: true } : {}),\n\t\tT\n\t> {\n\t\treturn new GelArrayBuilder(this.config.name, this as GelColumnBuilder<any, any>, size as any);\n\t}\n\n\treferences(\n\t\tref: ReferenceConfig['ref'],\n\t\tactions: ReferenceConfig['actions'] = {},\n\t): this {\n\t\tthis.foreignKeyConfigs.push({ ref, actions });\n\t\treturn this;\n\t}\n\n\tunique(\n\t\tname?: string,\n\t\tconfig?: { nulls: 'distinct' | 'not distinct' },\n\t): this {\n\t\tthis.config.isUnique = true;\n\t\tthis.config.uniqueName = name;\n\t\tthis.config.uniqueType = config?.nulls;\n\t\treturn this;\n\t}\n\n\tgeneratedAlwaysAs(as: SQL | T['data'] | (() => SQL)): HasGenerated<this, {\n\t\ttype: 'always';\n\t}> {\n\t\tthis.config.generated = {\n\t\t\tas,\n\t\t\ttype: 'always',\n\t\t\tmode: 'stored',\n\t\t};\n\t\treturn this as HasGenerated<this, {\n\t\t\ttype: 'always';\n\t\t}>;\n\t}\n\n\t/** @internal */\n\tbuildForeignKeys(column: GelColumn, table: GelTable): ForeignKey[] {\n\t\treturn this.foreignKeyConfigs.map(({ ref, actions }) => {\n\t\t\treturn iife(\n\t\t\t\t(ref, actions) => {\n\t\t\t\t\tconst builder = new ForeignKeyBuilder(() => {\n\t\t\t\t\t\tconst foreignColumn = ref();\n\t\t\t\t\t\treturn { columns: [column], foreignColumns: [foreignColumn] };\n\t\t\t\t\t});\n\t\t\t\t\tif (actions.onUpdate) {\n\t\t\t\t\t\tbuilder.onUpdate(actions.onUpdate);\n\t\t\t\t\t}\n\t\t\t\t\tif (actions.onDelete) {\n\t\t\t\t\t\tbuilder.onDelete(actions.onDelete);\n\t\t\t\t\t}\n\t\t\t\t\treturn builder.build(table);\n\t\t\t\t},\n\t\t\t\tref,\n\t\t\t\tactions,\n\t\t\t);\n\t\t});\n\t}\n\n\t/** @internal */\n\tabstract build<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelColumn<MakeColumnConfig<T, TTableName>>;\n\n\t/** @internal */\n\tbuildExtraConfigColumn<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelExtraConfigColumn {\n\t\treturn new GelExtraConfigColumn(table, this.config);\n\t}\n}\n\n// To understand how to use `GelColumn` and `GelColumn`, see `Column` and `AnyColumn` documentation.\nexport abstract class GelColumn<\n\tT extends ColumnBaseConfig<ColumnDataType, string> = ColumnBaseConfig<ColumnDataType, string>,\n\tTRuntimeConfig extends object = {},\n\tTTypeConfig extends object = {},\n> extends Column<T, TRuntimeConfig, TTypeConfig & { dialect: 'gel' }> {\n\tstatic override readonly [entityKind]: string = 'GelColumn';\n\n\tconstructor(\n\t\toverride readonly table: GelTable,\n\t\tconfig: ColumnBuilderRuntimeConfig<T['data'], TRuntimeConfig>,\n\t) {\n\t\tif (!config.uniqueName) {\n\t\t\tconfig.uniqueName = uniqueKeyName(table, [config.name]);\n\t\t}\n\t\tsuper(table, config);\n\t}\n}\n\nexport type IndexedExtraConfigType = { order?: 'asc' | 'desc'; nulls?: 'first' | 'last'; opClass?: string };\n\nexport class GelExtraConfigColumn<\n\tT extends ColumnBaseConfig<ColumnDataType, string> = ColumnBaseConfig<ColumnDataType, string>,\n> extends GelColumn<T, IndexedExtraConfigType> {\n\tstatic override readonly [entityKind]: string = 'GelExtraConfigColumn';\n\n\toverride getSQLType(): string {\n\t\treturn this.getSQLType();\n\t}\n\n\tindexConfig: IndexedExtraConfigType = {\n\t\torder: this.config.order ?? 'asc',\n\t\tnulls: this.config.nulls ?? 'last',\n\t\topClass: this.config.opClass,\n\t};\n\tdefaultConfig: IndexedExtraConfigType = {\n\t\torder: 'asc',\n\t\tnulls: 'last',\n\t\topClass: undefined,\n\t};\n\n\tasc(): Omit<this, 'asc' | 'desc'> {\n\t\tthis.indexConfig.order = 'asc';\n\t\treturn this;\n\t}\n\n\tdesc(): Omit<this, 'asc' | 'desc'> {\n\t\tthis.indexConfig.order = 'desc';\n\t\treturn this;\n\t}\n\n\tnullsFirst(): Omit<this, 'nullsFirst' | 'nullsLast'> {\n\t\tthis.indexConfig.nulls = 'first';\n\t\treturn this;\n\t}\n\n\tnullsLast(): Omit<this, 'nullsFirst' | 'nullsLast'> {\n\t\tthis.indexConfig.nulls = 'last';\n\t\treturn this;\n\t}\n\n\t/**\n\t * ### PostgreSQL documentation quote\n\t *\n\t * > An operator class with optional parameters can be specified for each column of an index.\n\t * The operator class identifies the operators to be used by the index for that column.\n\t * For example, a B-tree index on four-byte integers would use the int4_ops class;\n\t * this operator class includes comparison functions for four-byte integers.\n\t * In practice the default operator class for the column's data type is usually sufficient.\n\t * The main point of having operator classes is that for some data types, there could be more than one meaningful ordering.\n\t * For example, we might want to sort a complex-number data type either by absolute value or by real part.\n\t * We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index.\n\t * More information about operator classes check:\n\t *\n\t * ### Useful links\n\t * https://www.postgresql.org/docs/current/sql-createindex.html\n\t *\n\t * https://www.postgresql.org/docs/current/indexes-opclass.html\n\t *\n\t * https://www.postgresql.org/docs/current/xindex.html\n\t *\n\t * ### Additional types\n\t * If you have the `Gel_vector` extension installed in your database, you can use the\n\t * `vector_l2_ops`, `vector_ip_ops`, `vector_cosine_ops`, `vector_l1_ops`, `bit_hamming_ops`, `bit_jaccard_ops`, `halfvec_l2_ops`, `sparsevec_l2_ops` options, which are predefined types.\n\t *\n\t * **You can always specify any string you want in the operator class, in case Drizzle doesn't have it natively in its types**\n\t *\n\t * @param opClass\n\t * @returns\n\t */\n\top(opClass: GelIndexOpClass): Omit<this, 'op'> {\n\t\tthis.indexConfig.opClass = opClass;\n\t\treturn this;\n\t}\n}\n\nexport class IndexedColumn {\n\tstatic readonly [entityKind]: string = 'IndexedColumn';\n\tconstructor(\n\t\tname: string | undefined,\n\t\tkeyAsName: boolean,\n\t\ttype: string,\n\t\tindexConfig: IndexedExtraConfigType,\n\t) {\n\t\tthis.name = name;\n\t\tthis.keyAsName = keyAsName;\n\t\tthis.type = type;\n\t\tthis.indexConfig = indexConfig;\n\t}\n\n\tname: string | undefined;\n\tkeyAsName: boolean;\n\ttype: string;\n\tindexConfig: IndexedExtraConfigType;\n}\n\nexport type AnyGelColumn<TPartial extends Partial<ColumnBaseConfig<ColumnDataType, string>> = {}> = GelColumn<\n\tRequired<Update<ColumnBaseConfig<ColumnDataType, string>, TPartial>>\n>;\n\nexport type GelArrayColumnBuilderBaseConfig = ColumnBuilderBaseConfig<'array', 'GelArray'> & {\n\tsize: number | undefined;\n\tbaseBuilder: ColumnBuilderBaseConfig<ColumnDataType, string>;\n};\n\nexport class GelArrayBuilder<\n\tT extends GelArrayColumnBuilderBaseConfig,\n\tTBase extends ColumnBuilderBaseConfig<ColumnDataType, string> | GelArrayColumnBuilderBaseConfig,\n> extends GelColumnBuilder<\n\tT,\n\t{\n\t\tbaseBuilder: TBase extends GelArrayColumnBuilderBaseConfig ? GelArrayBuilder<\n\t\t\t\tTBase,\n\t\t\t\tTBase extends { baseBuilder: infer TBaseBuilder extends ColumnBuilderBaseConfig<any, any> } ? TBaseBuilder\n\t\t\t\t\t: never\n\t\t\t>\n\t\t\t: GelColumnBuilder<TBase, {}, Simplify<Omit<TBase, keyof ColumnBuilderBaseConfig<any, any>>>>;\n\t\tsize: T['size'];\n\t},\n\t{\n\t\tbaseBuilder: TBase extends GelArrayColumnBuilderBaseConfig ? GelArrayBuilder<\n\t\t\t\tTBase,\n\t\t\t\tTBase extends { baseBuilder: infer TBaseBuilder extends ColumnBuilderBaseConfig<any, any> } ? TBaseBuilder\n\t\t\t\t\t: never\n\t\t\t>\n\t\t\t: GelColumnBuilder<TBase, {}, Simplify<Omit<TBase, keyof ColumnBuilderBaseConfig<any, any>>>>;\n\t\tsize: T['size'];\n\t}\n> {\n\tstatic override readonly [entityKind] = 'GelArrayBuilder';\n\n\tconstructor(\n\t\tname: string,\n\t\tbaseBuilder: GelArrayBuilder<T, TBase>['config']['baseBuilder'],\n\t\tsize: T['size'],\n\t) {\n\t\tsuper(name, 'array', 'GelArray');\n\t\tthis.config.baseBuilder = baseBuilder;\n\t\tthis.config.size = size;\n\t}\n\n\t/** @internal */\n\toverride build<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelArray<MakeColumnConfig<T, TTableName> & { size: T['size']; baseBuilder: T['baseBuilder'] }, TBase> {\n\t\tconst baseColumn = this.config.baseBuilder.build(table);\n\t\treturn new GelArray<MakeColumnConfig<T, TTableName> & { size: T['size']; baseBuilder: T['baseBuilder'] }, TBase>(\n\t\t\ttable as AnyGelTable<{ name: MakeColumnConfig<T, TTableName>['tableName'] }>,\n\t\t\tthis.config as ColumnBuilderRuntimeConfig<any, any>,\n\t\t\tbaseColumn,\n\t\t);\n\t}\n}\n\nexport class GelArray<\n\tT extends ColumnBaseConfig<'array', 'GelArray'> & {\n\t\tsize: number | undefined;\n\t\tbaseBuilder: ColumnBuilderBaseConfig<ColumnDataType, string>;\n\t},\n\tTBase extends ColumnBuilderBaseConfig<ColumnDataType, string>,\n> extends GelColumn<T, {}, { size: T['size']; baseBuilder: T['baseBuilder'] }> {\n\treadonly size: T['size'];\n\n\tstatic override readonly [entityKind]: string = 'GelArray';\n\n\tconstructor(\n\t\ttable: AnyGelTable<{ name: T['tableName'] }>,\n\t\tconfig: GelArrayBuilder<T, TBase>['config'],\n\t\treadonly baseColumn: GelColumn,\n\t\treadonly range?: [number | undefined, number | undefined],\n\t) {\n\t\tsuper(table, config);\n\t\tthis.size = config.size;\n\t}\n\n\tgetSQLType(): string {\n\t\treturn `${this.baseColumn.getSQLType()}[${typeof this.size === 'number' ? this.size : ''}]`;\n\t}\n}\n"],"mappings":"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","names":["ref","actions"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/gel-core/columns/common.ts"],"sourcesContent":["import type {\n\tColumnBuilderBase,\n\tColumnBuilderBaseConfig,\n\tColumnBuilderExtraConfig,\n\tColumnBuilderRuntimeConfig,\n\tColumnDataType,\n\tHasGenerated,\n\tMakeColumnConfig,\n} from '~/column-builder.ts';\nimport { ColumnBuilder } from '~/column-builder.ts';\nimport type { ColumnBaseConfig } from '~/column.ts';\nimport { Column } from '~/column.ts';\nimport { entityKind } from '~/entity.ts';\nimport type { Simplify, Update } from '~/utils.ts';\n\nimport type { ForeignKey, UpdateDeleteAction } from '~/gel-core/foreign-keys.ts';\nimport { ForeignKeyBuilder } from '~/gel-core/foreign-keys.ts';\nimport type { AnyGelTable, GelTable } from '~/gel-core/table.ts';\nimport type { SQL } from '~/sql/sql.ts';\nimport { iife } from '~/tracing-utils.ts';\nimport type { GelIndexOpClass } from '../indexes.ts';\nimport { uniqueKeyName } from '../unique-constraint.ts';\n\nexport interface ReferenceConfig {\n\tref: () => GelColumn;\n\tactions: {\n\t\tonUpdate?: UpdateDeleteAction;\n\t\tonDelete?: UpdateDeleteAction;\n\t};\n}\n\nexport interface GelColumnBuilderBase<\n\tT extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>,\n\tTTypeConfig extends object = object,\n> extends ColumnBuilderBase<T, TTypeConfig & { dialect: 'gel' }> {}\n\nexport abstract class GelColumnBuilder<\n\tT extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>,\n\tTRuntimeConfig extends object = object,\n\tTTypeConfig extends object = object,\n\tTExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig,\n> extends ColumnBuilder<T, TRuntimeConfig, TTypeConfig & { dialect: 'gel' }, TExtraConfig>\n\timplements GelColumnBuilderBase<T, TTypeConfig>\n{\n\tprivate foreignKeyConfigs: ReferenceConfig[] = [];\n\n\tstatic override readonly [entityKind]: string = 'GelColumnBuilder';\n\n\tarray<TSize extends number | undefined = undefined>(size?: TSize): GelArrayBuilder<\n\t\t& {\n\t\t\tname: T['name'];\n\t\t\tdataType: 'array';\n\t\t\tcolumnType: 'GelArray';\n\t\t\tdata: T['data'][];\n\t\t\tdriverParam: T['driverParam'][] | string;\n\t\t\tenumValues: T['enumValues'];\n\t\t\tsize: TSize;\n\t\t\tbaseBuilder: T;\n\t\t}\n\t\t& (T extends { notNull: true } ? { notNull: true } : {})\n\t\t& (T extends { hasDefault: true } ? { hasDefault: true } : {}),\n\t\tT\n\t> {\n\t\treturn new GelArrayBuilder(this.config.name, this as GelColumnBuilder<any, any>, size as any);\n\t}\n\n\treferences(\n\t\tref: ReferenceConfig['ref'],\n\t\tactions: ReferenceConfig['actions'] = {},\n\t): this {\n\t\tthis.foreignKeyConfigs.push({ ref, actions });\n\t\treturn this;\n\t}\n\n\tunique(\n\t\tname?: string,\n\t\tconfig?: { nulls: 'distinct' | 'not distinct' },\n\t): this {\n\t\tthis.config.isUnique = true;\n\t\tthis.config.uniqueName = name;\n\t\tthis.config.uniqueType = config?.nulls;\n\t\treturn this;\n\t}\n\n\tgeneratedAlwaysAs(as: SQL | T['data'] | (() => SQL)): HasGenerated<this, {\n\t\ttype: 'always';\n\t}> {\n\t\tthis.config.generated = {\n\t\t\tas,\n\t\t\ttype: 'always',\n\t\t\tmode: 'stored',\n\t\t};\n\t\treturn this as HasGenerated<this, {\n\t\t\ttype: 'always';\n\t\t}>;\n\t}\n\n\t/** @internal */\n\tbuildForeignKeys(column: GelColumn, table: GelTable): ForeignKey[] {\n\t\treturn this.foreignKeyConfigs.map(({ ref, actions }) => {\n\t\t\treturn iife(\n\t\t\t\t(ref, actions) => {\n\t\t\t\t\tconst builder = new ForeignKeyBuilder(() => {\n\t\t\t\t\t\tconst foreignColumn = ref();\n\t\t\t\t\t\treturn { columns: [column], foreignColumns: [foreignColumn] };\n\t\t\t\t\t});\n\t\t\t\t\tif (actions.onUpdate) {\n\t\t\t\t\t\tbuilder.onUpdate(actions.onUpdate);\n\t\t\t\t\t}\n\t\t\t\t\tif (actions.onDelete) {\n\t\t\t\t\t\tbuilder.onDelete(actions.onDelete);\n\t\t\t\t\t}\n\t\t\t\t\treturn builder.build(table);\n\t\t\t\t},\n\t\t\t\tref,\n\t\t\t\tactions,\n\t\t\t);\n\t\t});\n\t}\n\n\t/** @internal */\n\tabstract build<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelColumn<MakeColumnConfig<T, TTableName>>;\n\n\t/** @internal */\n\tbuildExtraConfigColumn<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelExtraConfigColumn {\n\t\treturn new GelExtraConfigColumn(table, this.config);\n\t}\n}\n\n// To understand how to use `GelColumn` and `GelColumn`, see `Column` and `AnyColumn` documentation.\nexport abstract class GelColumn<\n\tT extends ColumnBaseConfig<ColumnDataType, string> = ColumnBaseConfig<ColumnDataType, string>,\n\tTRuntimeConfig extends object = {},\n\tTTypeConfig extends object = {},\n> extends Column<T, TRuntimeConfig, TTypeConfig & { dialect: 'gel' }> {\n\tstatic override readonly [entityKind]: string = 'GelColumn';\n\n\tconstructor(\n\t\toverride readonly table: GelTable,\n\t\tconfig: ColumnBuilderRuntimeConfig<T['data'], TRuntimeConfig>,\n\t) {\n\t\tif (!config.uniqueName) {\n\t\t\tconfig.uniqueName = uniqueKeyName(table, [config.name]);\n\t\t}\n\t\tsuper(table, config);\n\t}\n}\n\nexport type IndexedExtraConfigType = { order?: 'asc' | 'desc'; nulls?: 'first' | 'last'; opClass?: string };\n\nexport class GelExtraConfigColumn<\n\tT extends ColumnBaseConfig<ColumnDataType, string> = ColumnBaseConfig<ColumnDataType, string>,\n> extends GelColumn<T, IndexedExtraConfigType> {\n\tstatic override readonly [entityKind]: string = 'GelExtraConfigColumn';\n\n\toverride getSQLType(): string {\n\t\treturn this.getSQLType();\n\t}\n\n\tindexConfig: IndexedExtraConfigType = {\n\t\torder: this.config.order ?? 'asc',\n\t\tnulls: this.config.nulls ?? 'last',\n\t\topClass: this.config.opClass,\n\t};\n\tdefaultConfig: IndexedExtraConfigType = {\n\t\torder: 'asc',\n\t\tnulls: 'last',\n\t\topClass: undefined,\n\t};\n\n\tasc(): Omit<this, 'asc' | 'desc'> {\n\t\tthis.indexConfig.order = 'asc';\n\t\treturn this;\n\t}\n\n\tdesc(): Omit<this, 'asc' | 'desc'> {\n\t\tthis.indexConfig.order = 'desc';\n\t\treturn this;\n\t}\n\n\tnullsFirst(): Omit<this, 'nullsFirst' | 'nullsLast'> {\n\t\tthis.indexConfig.nulls = 'first';\n\t\treturn this;\n\t}\n\n\tnullsLast(): Omit<this, 'nullsFirst' | 'nullsLast'> {\n\t\tthis.indexConfig.nulls = 'last';\n\t\treturn this;\n\t}\n\n\t/**\n\t * ### PostgreSQL documentation quote\n\t *\n\t * > An operator class with optional parameters can be specified for each column of an index.\n\t * The operator class identifies the operators to be used by the index for that column.\n\t * For example, a B-tree index on four-byte integers would use the int4_ops class;\n\t * this operator class includes comparison functions for four-byte integers.\n\t * In practice the default operator class for the column's data type is usually sufficient.\n\t * The main point of having operator classes is that for some data types, there could be more than one meaningful ordering.\n\t * For example, we might want to sort a complex-number data type either by absolute value or by real part.\n\t * We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index.\n\t * More information about operator classes check:\n\t *\n\t * ### Useful links\n\t * https://www.postgresql.org/docs/current/sql-createindex.html\n\t *\n\t * https://www.postgresql.org/docs/current/indexes-opclass.html\n\t *\n\t * https://www.postgresql.org/docs/current/xindex.html\n\t *\n\t * ### Additional types\n\t * If you have the `Gel_vector` extension installed in your database, you can use the\n\t * `vector_l2_ops`, `vector_ip_ops`, `vector_cosine_ops`, `vector_l1_ops`, `bit_hamming_ops`, `bit_jaccard_ops`, `halfvec_l2_ops`, `sparsevec_l2_ops` options, which are predefined types.\n\t *\n\t * **You can always specify any string you want in the operator class, in case Drizzle doesn't have it natively in its types**\n\t *\n\t * @param opClass\n\t * @returns\n\t */\n\top(opClass: GelIndexOpClass): Omit<this, 'op'> {\n\t\tthis.indexConfig.opClass = opClass;\n\t\treturn this;\n\t}\n}\n\nexport class IndexedColumn {\n\tstatic readonly [entityKind]: string = 'IndexedColumn';\n\tconstructor(\n\t\tname: string | undefined,\n\t\tkeyAsName: boolean,\n\t\ttype: string,\n\t\tindexConfig: IndexedExtraConfigType,\n\t) {\n\t\tthis.name = name;\n\t\tthis.keyAsName = keyAsName;\n\t\tthis.type = type;\n\t\tthis.indexConfig = indexConfig;\n\t}\n\n\tname: string | undefined;\n\tkeyAsName: boolean;\n\ttype: string;\n\tindexConfig: IndexedExtraConfigType;\n}\n\nexport type AnyGelColumn<TPartial extends Partial<ColumnBaseConfig<ColumnDataType, string>> = {}> = GelColumn<\n\tRequired<Update<ColumnBaseConfig<ColumnDataType, string>, TPartial>>\n>;\n\nexport type GelArrayColumnBuilderBaseConfig = ColumnBuilderBaseConfig<'array', 'GelArray'> & {\n\tsize: number | undefined;\n\tbaseBuilder: ColumnBuilderBaseConfig<ColumnDataType, string>;\n};\n\nexport class GelArrayBuilder<\n\tT extends GelArrayColumnBuilderBaseConfig,\n\tTBase extends ColumnBuilderBaseConfig<ColumnDataType, string> | GelArrayColumnBuilderBaseConfig,\n> extends GelColumnBuilder<\n\tT,\n\t{\n\t\tbaseBuilder: TBase extends GelArrayColumnBuilderBaseConfig ? GelArrayBuilder<\n\t\t\t\tTBase,\n\t\t\t\tTBase extends { baseBuilder: infer TBaseBuilder extends ColumnBuilderBaseConfig<any, any> } ? TBaseBuilder\n\t\t\t\t\t: never\n\t\t\t>\n\t\t\t: GelColumnBuilder<TBase, {}, Simplify<Omit<TBase, keyof ColumnBuilderBaseConfig<any, any>>>>;\n\t\tsize: T['size'];\n\t},\n\t{\n\t\tbaseBuilder: TBase extends GelArrayColumnBuilderBaseConfig ? GelArrayBuilder<\n\t\t\t\tTBase,\n\t\t\t\tTBase extends { baseBuilder: infer TBaseBuilder extends ColumnBuilderBaseConfig<any, any> } ? TBaseBuilder\n\t\t\t\t\t: never\n\t\t\t>\n\t\t\t: GelColumnBuilder<TBase, {}, Simplify<Omit<TBase, keyof ColumnBuilderBaseConfig<any, any>>>>;\n\t\tsize: T['size'];\n\t}\n> {\n\tstatic override readonly [entityKind] = 'GelArrayBuilder';\n\n\tconstructor(\n\t\tname: string,\n\t\tbaseBuilder: GelArrayBuilder<T, TBase>['config']['baseBuilder'],\n\t\tsize: T['size'],\n\t) {\n\t\tsuper(name, 'array', 'GelArray');\n\t\tthis.config.baseBuilder = baseBuilder;\n\t\tthis.config.size = size;\n\t}\n\n\t/** @internal */\n\toverride build<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelArray<MakeColumnConfig<T, TTableName> & { size: T['size']; baseBuilder: T['baseBuilder'] }, TBase> {\n\t\tconst baseColumn = this.config.baseBuilder.build(table);\n\t\treturn new GelArray<MakeColumnConfig<T, TTableName> & { size: T['size']; baseBuilder: T['baseBuilder'] }, TBase>(\n\t\t\ttable as AnyGelTable<{ name: MakeColumnConfig<T, TTableName>['tableName'] }>,\n\t\t\tthis.config as ColumnBuilderRuntimeConfig<any, any>,\n\t\t\tbaseColumn,\n\t\t);\n\t}\n}\n\nexport class GelArray<\n\tT extends ColumnBaseConfig<'array', 'GelArray'> & {\n\t\tsize: number | undefined;\n\t\tbaseBuilder: ColumnBuilderBaseConfig<ColumnDataType, string>;\n\t},\n\tTBase extends ColumnBuilderBaseConfig<ColumnDataType, string>,\n> extends GelColumn<T, {}, { size: T['size']; baseBuilder: T['baseBuilder'] }> {\n\treadonly size: T['size'];\n\n\tstatic override readonly [entityKind]: string = 'GelArray';\n\n\tconstructor(\n\t\ttable: AnyGelTable<{ name: T['tableName'] }>,\n\t\tconfig: GelArrayBuilder<T, TBase>['config'],\n\t\treadonly baseColumn: GelColumn,\n\t\treadonly range?: [number | undefined, number | undefined],\n\t) {\n\t\tsuper(table, config);\n\t\tthis.size = config.size;\n\t}\n\n\toverride mapFromDriverValue(value: unknown[]): T['data'] {\n\t\treturn value.map((v) => this.baseColumn.mapFromDriverValue(v));\n\t}\n\n\t// Needed for arrays of custom types\n\tmapFromJsonValue(value: unknown[]): T['data'] {\n\t\tconst base = this.baseColumn;\n\n\t\treturn 'mapFromJsonValue' in base\n\t\t\t? value.map((v) => (<(value: unknown) => unknown> base.mapFromJsonValue)(v))\n\t\t\t: value.map((v) => base.mapFromDriverValue(v));\n\t}\n\n\tgetSQLType(): string {\n\t\treturn `${this.baseColumn.getSQLType()}[${typeof this.size === 'number' ? this.size : ''}]`;\n\t}\n}\n"],"mappings":"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","names":["ref","actions"]}
|
|
@@ -143,5 +143,7 @@ export declare class GelArray<T extends ColumnBaseConfig<'array', 'GelArray'> &
|
|
|
143
143
|
constructor(table: AnyGelTable<{
|
|
144
144
|
name: T['tableName'];
|
|
145
145
|
}>, config: GelArrayBuilder<T, TBase>['config'], baseColumn: GelColumn, range?: [number | undefined, number | undefined] | undefined);
|
|
146
|
+
mapFromDriverValue(value: unknown[]): T['data'];
|
|
147
|
+
mapFromJsonValue(value: unknown[]): T['data'];
|
|
146
148
|
getSQLType(): string;
|
|
147
149
|
}
|
|
@@ -143,5 +143,7 @@ export declare class GelArray<T extends ColumnBaseConfig<'array', 'GelArray'> &
|
|
|
143
143
|
constructor(table: AnyGelTable<{
|
|
144
144
|
name: T['tableName'];
|
|
145
145
|
}>, config: GelArrayBuilder<T, TBase>['config'], baseColumn: GelColumn, range?: [number | undefined, number | undefined] | undefined);
|
|
146
|
+
mapFromDriverValue(value: unknown[]): T['data'];
|
|
147
|
+
mapFromJsonValue(value: unknown[]): T['data'];
|
|
146
148
|
getSQLType(): string;
|
|
147
149
|
}
|
|
@@ -169,6 +169,14 @@ class GelArray extends GelColumn {
|
|
|
169
169
|
}
|
|
170
170
|
size;
|
|
171
171
|
static [entityKind] = "GelArray";
|
|
172
|
+
mapFromDriverValue(value) {
|
|
173
|
+
return value.map((v) => this.baseColumn.mapFromDriverValue(v));
|
|
174
|
+
}
|
|
175
|
+
// Needed for arrays of custom types
|
|
176
|
+
mapFromJsonValue(value) {
|
|
177
|
+
const base = this.baseColumn;
|
|
178
|
+
return "mapFromJsonValue" in base ? value.map((v) => base.mapFromJsonValue(v)) : value.map((v) => base.mapFromDriverValue(v));
|
|
179
|
+
}
|
|
172
180
|
getSQLType() {
|
|
173
181
|
return `${this.baseColumn.getSQLType()}[${typeof this.size === "number" ? this.size : ""}]`;
|
|
174
182
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/gel-core/columns/common.ts"],"sourcesContent":["import type {\n\tColumnBuilderBase,\n\tColumnBuilderBaseConfig,\n\tColumnBuilderExtraConfig,\n\tColumnBuilderRuntimeConfig,\n\tColumnDataType,\n\tHasGenerated,\n\tMakeColumnConfig,\n} from '~/column-builder.ts';\nimport { ColumnBuilder } from '~/column-builder.ts';\nimport type { ColumnBaseConfig } from '~/column.ts';\nimport { Column } from '~/column.ts';\nimport { entityKind } from '~/entity.ts';\nimport type { Simplify, Update } from '~/utils.ts';\n\nimport type { ForeignKey, UpdateDeleteAction } from '~/gel-core/foreign-keys.ts';\nimport { ForeignKeyBuilder } from '~/gel-core/foreign-keys.ts';\nimport type { AnyGelTable, GelTable } from '~/gel-core/table.ts';\nimport type { SQL } from '~/sql/sql.ts';\nimport { iife } from '~/tracing-utils.ts';\nimport type { GelIndexOpClass } from '../indexes.ts';\nimport { uniqueKeyName } from '../unique-constraint.ts';\n\nexport interface ReferenceConfig {\n\tref: () => GelColumn;\n\tactions: {\n\t\tonUpdate?: UpdateDeleteAction;\n\t\tonDelete?: UpdateDeleteAction;\n\t};\n}\n\nexport interface GelColumnBuilderBase<\n\tT extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>,\n\tTTypeConfig extends object = object,\n> extends ColumnBuilderBase<T, TTypeConfig & { dialect: 'gel' }> {}\n\nexport abstract class GelColumnBuilder<\n\tT extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>,\n\tTRuntimeConfig extends object = object,\n\tTTypeConfig extends object = object,\n\tTExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig,\n> extends ColumnBuilder<T, TRuntimeConfig, TTypeConfig & { dialect: 'gel' }, TExtraConfig>\n\timplements GelColumnBuilderBase<T, TTypeConfig>\n{\n\tprivate foreignKeyConfigs: ReferenceConfig[] = [];\n\n\tstatic override readonly [entityKind]: string = 'GelColumnBuilder';\n\n\tarray<TSize extends number | undefined = undefined>(size?: TSize): GelArrayBuilder<\n\t\t& {\n\t\t\tname: T['name'];\n\t\t\tdataType: 'array';\n\t\t\tcolumnType: 'GelArray';\n\t\t\tdata: T['data'][];\n\t\t\tdriverParam: T['driverParam'][] | string;\n\t\t\tenumValues: T['enumValues'];\n\t\t\tsize: TSize;\n\t\t\tbaseBuilder: T;\n\t\t}\n\t\t& (T extends { notNull: true } ? { notNull: true } : {})\n\t\t& (T extends { hasDefault: true } ? { hasDefault: true } : {}),\n\t\tT\n\t> {\n\t\treturn new GelArrayBuilder(this.config.name, this as GelColumnBuilder<any, any>, size as any);\n\t}\n\n\treferences(\n\t\tref: ReferenceConfig['ref'],\n\t\tactions: ReferenceConfig['actions'] = {},\n\t): this {\n\t\tthis.foreignKeyConfigs.push({ ref, actions });\n\t\treturn this;\n\t}\n\n\tunique(\n\t\tname?: string,\n\t\tconfig?: { nulls: 'distinct' | 'not distinct' },\n\t): this {\n\t\tthis.config.isUnique = true;\n\t\tthis.config.uniqueName = name;\n\t\tthis.config.uniqueType = config?.nulls;\n\t\treturn this;\n\t}\n\n\tgeneratedAlwaysAs(as: SQL | T['data'] | (() => SQL)): HasGenerated<this, {\n\t\ttype: 'always';\n\t}> {\n\t\tthis.config.generated = {\n\t\t\tas,\n\t\t\ttype: 'always',\n\t\t\tmode: 'stored',\n\t\t};\n\t\treturn this as HasGenerated<this, {\n\t\t\ttype: 'always';\n\t\t}>;\n\t}\n\n\t/** @internal */\n\tbuildForeignKeys(column: GelColumn, table: GelTable): ForeignKey[] {\n\t\treturn this.foreignKeyConfigs.map(({ ref, actions }) => {\n\t\t\treturn iife(\n\t\t\t\t(ref, actions) => {\n\t\t\t\t\tconst builder = new ForeignKeyBuilder(() => {\n\t\t\t\t\t\tconst foreignColumn = ref();\n\t\t\t\t\t\treturn { columns: [column], foreignColumns: [foreignColumn] };\n\t\t\t\t\t});\n\t\t\t\t\tif (actions.onUpdate) {\n\t\t\t\t\t\tbuilder.onUpdate(actions.onUpdate);\n\t\t\t\t\t}\n\t\t\t\t\tif (actions.onDelete) {\n\t\t\t\t\t\tbuilder.onDelete(actions.onDelete);\n\t\t\t\t\t}\n\t\t\t\t\treturn builder.build(table);\n\t\t\t\t},\n\t\t\t\tref,\n\t\t\t\tactions,\n\t\t\t);\n\t\t});\n\t}\n\n\t/** @internal */\n\tabstract build<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelColumn<MakeColumnConfig<T, TTableName>>;\n\n\t/** @internal */\n\tbuildExtraConfigColumn<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelExtraConfigColumn {\n\t\treturn new GelExtraConfigColumn(table, this.config);\n\t}\n}\n\n// To understand how to use `GelColumn` and `GelColumn`, see `Column` and `AnyColumn` documentation.\nexport abstract class GelColumn<\n\tT extends ColumnBaseConfig<ColumnDataType, string> = ColumnBaseConfig<ColumnDataType, string>,\n\tTRuntimeConfig extends object = {},\n\tTTypeConfig extends object = {},\n> extends Column<T, TRuntimeConfig, TTypeConfig & { dialect: 'gel' }> {\n\tstatic override readonly [entityKind]: string = 'GelColumn';\n\n\tconstructor(\n\t\toverride readonly table: GelTable,\n\t\tconfig: ColumnBuilderRuntimeConfig<T['data'], TRuntimeConfig>,\n\t) {\n\t\tif (!config.uniqueName) {\n\t\t\tconfig.uniqueName = uniqueKeyName(table, [config.name]);\n\t\t}\n\t\tsuper(table, config);\n\t}\n}\n\nexport type IndexedExtraConfigType = { order?: 'asc' | 'desc'; nulls?: 'first' | 'last'; opClass?: string };\n\nexport class GelExtraConfigColumn<\n\tT extends ColumnBaseConfig<ColumnDataType, string> = ColumnBaseConfig<ColumnDataType, string>,\n> extends GelColumn<T, IndexedExtraConfigType> {\n\tstatic override readonly [entityKind]: string = 'GelExtraConfigColumn';\n\n\toverride getSQLType(): string {\n\t\treturn this.getSQLType();\n\t}\n\n\tindexConfig: IndexedExtraConfigType = {\n\t\torder: this.config.order ?? 'asc',\n\t\tnulls: this.config.nulls ?? 'last',\n\t\topClass: this.config.opClass,\n\t};\n\tdefaultConfig: IndexedExtraConfigType = {\n\t\torder: 'asc',\n\t\tnulls: 'last',\n\t\topClass: undefined,\n\t};\n\n\tasc(): Omit<this, 'asc' | 'desc'> {\n\t\tthis.indexConfig.order = 'asc';\n\t\treturn this;\n\t}\n\n\tdesc(): Omit<this, 'asc' | 'desc'> {\n\t\tthis.indexConfig.order = 'desc';\n\t\treturn this;\n\t}\n\n\tnullsFirst(): Omit<this, 'nullsFirst' | 'nullsLast'> {\n\t\tthis.indexConfig.nulls = 'first';\n\t\treturn this;\n\t}\n\n\tnullsLast(): Omit<this, 'nullsFirst' | 'nullsLast'> {\n\t\tthis.indexConfig.nulls = 'last';\n\t\treturn this;\n\t}\n\n\t/**\n\t * ### PostgreSQL documentation quote\n\t *\n\t * > An operator class with optional parameters can be specified for each column of an index.\n\t * The operator class identifies the operators to be used by the index for that column.\n\t * For example, a B-tree index on four-byte integers would use the int4_ops class;\n\t * this operator class includes comparison functions for four-byte integers.\n\t * In practice the default operator class for the column's data type is usually sufficient.\n\t * The main point of having operator classes is that for some data types, there could be more than one meaningful ordering.\n\t * For example, we might want to sort a complex-number data type either by absolute value or by real part.\n\t * We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index.\n\t * More information about operator classes check:\n\t *\n\t * ### Useful links\n\t * https://www.postgresql.org/docs/current/sql-createindex.html\n\t *\n\t * https://www.postgresql.org/docs/current/indexes-opclass.html\n\t *\n\t * https://www.postgresql.org/docs/current/xindex.html\n\t *\n\t * ### Additional types\n\t * If you have the `Gel_vector` extension installed in your database, you can use the\n\t * `vector_l2_ops`, `vector_ip_ops`, `vector_cosine_ops`, `vector_l1_ops`, `bit_hamming_ops`, `bit_jaccard_ops`, `halfvec_l2_ops`, `sparsevec_l2_ops` options, which are predefined types.\n\t *\n\t * **You can always specify any string you want in the operator class, in case Drizzle doesn't have it natively in its types**\n\t *\n\t * @param opClass\n\t * @returns\n\t */\n\top(opClass: GelIndexOpClass): Omit<this, 'op'> {\n\t\tthis.indexConfig.opClass = opClass;\n\t\treturn this;\n\t}\n}\n\nexport class IndexedColumn {\n\tstatic readonly [entityKind]: string = 'IndexedColumn';\n\tconstructor(\n\t\tname: string | undefined,\n\t\tkeyAsName: boolean,\n\t\ttype: string,\n\t\tindexConfig: IndexedExtraConfigType,\n\t) {\n\t\tthis.name = name;\n\t\tthis.keyAsName = keyAsName;\n\t\tthis.type = type;\n\t\tthis.indexConfig = indexConfig;\n\t}\n\n\tname: string | undefined;\n\tkeyAsName: boolean;\n\ttype: string;\n\tindexConfig: IndexedExtraConfigType;\n}\n\nexport type AnyGelColumn<TPartial extends Partial<ColumnBaseConfig<ColumnDataType, string>> = {}> = GelColumn<\n\tRequired<Update<ColumnBaseConfig<ColumnDataType, string>, TPartial>>\n>;\n\nexport type GelArrayColumnBuilderBaseConfig = ColumnBuilderBaseConfig<'array', 'GelArray'> & {\n\tsize: number | undefined;\n\tbaseBuilder: ColumnBuilderBaseConfig<ColumnDataType, string>;\n};\n\nexport class GelArrayBuilder<\n\tT extends GelArrayColumnBuilderBaseConfig,\n\tTBase extends ColumnBuilderBaseConfig<ColumnDataType, string> | GelArrayColumnBuilderBaseConfig,\n> extends GelColumnBuilder<\n\tT,\n\t{\n\t\tbaseBuilder: TBase extends GelArrayColumnBuilderBaseConfig ? GelArrayBuilder<\n\t\t\t\tTBase,\n\t\t\t\tTBase extends { baseBuilder: infer TBaseBuilder extends ColumnBuilderBaseConfig<any, any> } ? TBaseBuilder\n\t\t\t\t\t: never\n\t\t\t>\n\t\t\t: GelColumnBuilder<TBase, {}, Simplify<Omit<TBase, keyof ColumnBuilderBaseConfig<any, any>>>>;\n\t\tsize: T['size'];\n\t},\n\t{\n\t\tbaseBuilder: TBase extends GelArrayColumnBuilderBaseConfig ? GelArrayBuilder<\n\t\t\t\tTBase,\n\t\t\t\tTBase extends { baseBuilder: infer TBaseBuilder extends ColumnBuilderBaseConfig<any, any> } ? TBaseBuilder\n\t\t\t\t\t: never\n\t\t\t>\n\t\t\t: GelColumnBuilder<TBase, {}, Simplify<Omit<TBase, keyof ColumnBuilderBaseConfig<any, any>>>>;\n\t\tsize: T['size'];\n\t}\n> {\n\tstatic override readonly [entityKind] = 'GelArrayBuilder';\n\n\tconstructor(\n\t\tname: string,\n\t\tbaseBuilder: GelArrayBuilder<T, TBase>['config']['baseBuilder'],\n\t\tsize: T['size'],\n\t) {\n\t\tsuper(name, 'array', 'GelArray');\n\t\tthis.config.baseBuilder = baseBuilder;\n\t\tthis.config.size = size;\n\t}\n\n\t/** @internal */\n\toverride build<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelArray<MakeColumnConfig<T, TTableName> & { size: T['size']; baseBuilder: T['baseBuilder'] }, TBase> {\n\t\tconst baseColumn = this.config.baseBuilder.build(table);\n\t\treturn new GelArray<MakeColumnConfig<T, TTableName> & { size: T['size']; baseBuilder: T['baseBuilder'] }, TBase>(\n\t\t\ttable as AnyGelTable<{ name: MakeColumnConfig<T, TTableName>['tableName'] }>,\n\t\t\tthis.config as ColumnBuilderRuntimeConfig<any, any>,\n\t\t\tbaseColumn,\n\t\t);\n\t}\n}\n\nexport class GelArray<\n\tT extends ColumnBaseConfig<'array', 'GelArray'> & {\n\t\tsize: number | undefined;\n\t\tbaseBuilder: ColumnBuilderBaseConfig<ColumnDataType, string>;\n\t},\n\tTBase extends ColumnBuilderBaseConfig<ColumnDataType, string>,\n> extends GelColumn<T, {}, { size: T['size']; baseBuilder: T['baseBuilder'] }> {\n\treadonly size: T['size'];\n\n\tstatic override readonly [entityKind]: string = 'GelArray';\n\n\tconstructor(\n\t\ttable: AnyGelTable<{ name: T['tableName'] }>,\n\t\tconfig: GelArrayBuilder<T, TBase>['config'],\n\t\treadonly baseColumn: GelColumn,\n\t\treadonly range?: [number | undefined, number | undefined],\n\t) {\n\t\tsuper(table, config);\n\t\tthis.size = config.size;\n\t}\n\n\tgetSQLType(): string {\n\t\treturn `${this.baseColumn.getSQLType()}[${typeof this.size === 'number' ? this.size : ''}]`;\n\t}\n}\n"],"mappings":"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","names":["ref","actions"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/gel-core/columns/common.ts"],"sourcesContent":["import type {\n\tColumnBuilderBase,\n\tColumnBuilderBaseConfig,\n\tColumnBuilderExtraConfig,\n\tColumnBuilderRuntimeConfig,\n\tColumnDataType,\n\tHasGenerated,\n\tMakeColumnConfig,\n} from '~/column-builder.ts';\nimport { ColumnBuilder } from '~/column-builder.ts';\nimport type { ColumnBaseConfig } from '~/column.ts';\nimport { Column } from '~/column.ts';\nimport { entityKind } from '~/entity.ts';\nimport type { Simplify, Update } from '~/utils.ts';\n\nimport type { ForeignKey, UpdateDeleteAction } from '~/gel-core/foreign-keys.ts';\nimport { ForeignKeyBuilder } from '~/gel-core/foreign-keys.ts';\nimport type { AnyGelTable, GelTable } from '~/gel-core/table.ts';\nimport type { SQL } from '~/sql/sql.ts';\nimport { iife } from '~/tracing-utils.ts';\nimport type { GelIndexOpClass } from '../indexes.ts';\nimport { uniqueKeyName } from '../unique-constraint.ts';\n\nexport interface ReferenceConfig {\n\tref: () => GelColumn;\n\tactions: {\n\t\tonUpdate?: UpdateDeleteAction;\n\t\tonDelete?: UpdateDeleteAction;\n\t};\n}\n\nexport interface GelColumnBuilderBase<\n\tT extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>,\n\tTTypeConfig extends object = object,\n> extends ColumnBuilderBase<T, TTypeConfig & { dialect: 'gel' }> {}\n\nexport abstract class GelColumnBuilder<\n\tT extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>,\n\tTRuntimeConfig extends object = object,\n\tTTypeConfig extends object = object,\n\tTExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig,\n> extends ColumnBuilder<T, TRuntimeConfig, TTypeConfig & { dialect: 'gel' }, TExtraConfig>\n\timplements GelColumnBuilderBase<T, TTypeConfig>\n{\n\tprivate foreignKeyConfigs: ReferenceConfig[] = [];\n\n\tstatic override readonly [entityKind]: string = 'GelColumnBuilder';\n\n\tarray<TSize extends number | undefined = undefined>(size?: TSize): GelArrayBuilder<\n\t\t& {\n\t\t\tname: T['name'];\n\t\t\tdataType: 'array';\n\t\t\tcolumnType: 'GelArray';\n\t\t\tdata: T['data'][];\n\t\t\tdriverParam: T['driverParam'][] | string;\n\t\t\tenumValues: T['enumValues'];\n\t\t\tsize: TSize;\n\t\t\tbaseBuilder: T;\n\t\t}\n\t\t& (T extends { notNull: true } ? { notNull: true } : {})\n\t\t& (T extends { hasDefault: true } ? { hasDefault: true } : {}),\n\t\tT\n\t> {\n\t\treturn new GelArrayBuilder(this.config.name, this as GelColumnBuilder<any, any>, size as any);\n\t}\n\n\treferences(\n\t\tref: ReferenceConfig['ref'],\n\t\tactions: ReferenceConfig['actions'] = {},\n\t): this {\n\t\tthis.foreignKeyConfigs.push({ ref, actions });\n\t\treturn this;\n\t}\n\n\tunique(\n\t\tname?: string,\n\t\tconfig?: { nulls: 'distinct' | 'not distinct' },\n\t): this {\n\t\tthis.config.isUnique = true;\n\t\tthis.config.uniqueName = name;\n\t\tthis.config.uniqueType = config?.nulls;\n\t\treturn this;\n\t}\n\n\tgeneratedAlwaysAs(as: SQL | T['data'] | (() => SQL)): HasGenerated<this, {\n\t\ttype: 'always';\n\t}> {\n\t\tthis.config.generated = {\n\t\t\tas,\n\t\t\ttype: 'always',\n\t\t\tmode: 'stored',\n\t\t};\n\t\treturn this as HasGenerated<this, {\n\t\t\ttype: 'always';\n\t\t}>;\n\t}\n\n\t/** @internal */\n\tbuildForeignKeys(column: GelColumn, table: GelTable): ForeignKey[] {\n\t\treturn this.foreignKeyConfigs.map(({ ref, actions }) => {\n\t\t\treturn iife(\n\t\t\t\t(ref, actions) => {\n\t\t\t\t\tconst builder = new ForeignKeyBuilder(() => {\n\t\t\t\t\t\tconst foreignColumn = ref();\n\t\t\t\t\t\treturn { columns: [column], foreignColumns: [foreignColumn] };\n\t\t\t\t\t});\n\t\t\t\t\tif (actions.onUpdate) {\n\t\t\t\t\t\tbuilder.onUpdate(actions.onUpdate);\n\t\t\t\t\t}\n\t\t\t\t\tif (actions.onDelete) {\n\t\t\t\t\t\tbuilder.onDelete(actions.onDelete);\n\t\t\t\t\t}\n\t\t\t\t\treturn builder.build(table);\n\t\t\t\t},\n\t\t\t\tref,\n\t\t\t\tactions,\n\t\t\t);\n\t\t});\n\t}\n\n\t/** @internal */\n\tabstract build<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelColumn<MakeColumnConfig<T, TTableName>>;\n\n\t/** @internal */\n\tbuildExtraConfigColumn<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelExtraConfigColumn {\n\t\treturn new GelExtraConfigColumn(table, this.config);\n\t}\n}\n\n// To understand how to use `GelColumn` and `GelColumn`, see `Column` and `AnyColumn` documentation.\nexport abstract class GelColumn<\n\tT extends ColumnBaseConfig<ColumnDataType, string> = ColumnBaseConfig<ColumnDataType, string>,\n\tTRuntimeConfig extends object = {},\n\tTTypeConfig extends object = {},\n> extends Column<T, TRuntimeConfig, TTypeConfig & { dialect: 'gel' }> {\n\tstatic override readonly [entityKind]: string = 'GelColumn';\n\n\tconstructor(\n\t\toverride readonly table: GelTable,\n\t\tconfig: ColumnBuilderRuntimeConfig<T['data'], TRuntimeConfig>,\n\t) {\n\t\tif (!config.uniqueName) {\n\t\t\tconfig.uniqueName = uniqueKeyName(table, [config.name]);\n\t\t}\n\t\tsuper(table, config);\n\t}\n}\n\nexport type IndexedExtraConfigType = { order?: 'asc' | 'desc'; nulls?: 'first' | 'last'; opClass?: string };\n\nexport class GelExtraConfigColumn<\n\tT extends ColumnBaseConfig<ColumnDataType, string> = ColumnBaseConfig<ColumnDataType, string>,\n> extends GelColumn<T, IndexedExtraConfigType> {\n\tstatic override readonly [entityKind]: string = 'GelExtraConfigColumn';\n\n\toverride getSQLType(): string {\n\t\treturn this.getSQLType();\n\t}\n\n\tindexConfig: IndexedExtraConfigType = {\n\t\torder: this.config.order ?? 'asc',\n\t\tnulls: this.config.nulls ?? 'last',\n\t\topClass: this.config.opClass,\n\t};\n\tdefaultConfig: IndexedExtraConfigType = {\n\t\torder: 'asc',\n\t\tnulls: 'last',\n\t\topClass: undefined,\n\t};\n\n\tasc(): Omit<this, 'asc' | 'desc'> {\n\t\tthis.indexConfig.order = 'asc';\n\t\treturn this;\n\t}\n\n\tdesc(): Omit<this, 'asc' | 'desc'> {\n\t\tthis.indexConfig.order = 'desc';\n\t\treturn this;\n\t}\n\n\tnullsFirst(): Omit<this, 'nullsFirst' | 'nullsLast'> {\n\t\tthis.indexConfig.nulls = 'first';\n\t\treturn this;\n\t}\n\n\tnullsLast(): Omit<this, 'nullsFirst' | 'nullsLast'> {\n\t\tthis.indexConfig.nulls = 'last';\n\t\treturn this;\n\t}\n\n\t/**\n\t * ### PostgreSQL documentation quote\n\t *\n\t * > An operator class with optional parameters can be specified for each column of an index.\n\t * The operator class identifies the operators to be used by the index for that column.\n\t * For example, a B-tree index on four-byte integers would use the int4_ops class;\n\t * this operator class includes comparison functions for four-byte integers.\n\t * In practice the default operator class for the column's data type is usually sufficient.\n\t * The main point of having operator classes is that for some data types, there could be more than one meaningful ordering.\n\t * For example, we might want to sort a complex-number data type either by absolute value or by real part.\n\t * We could do this by defining two operator classes for the data type and then selecting the proper class when creating an index.\n\t * More information about operator classes check:\n\t *\n\t * ### Useful links\n\t * https://www.postgresql.org/docs/current/sql-createindex.html\n\t *\n\t * https://www.postgresql.org/docs/current/indexes-opclass.html\n\t *\n\t * https://www.postgresql.org/docs/current/xindex.html\n\t *\n\t * ### Additional types\n\t * If you have the `Gel_vector` extension installed in your database, you can use the\n\t * `vector_l2_ops`, `vector_ip_ops`, `vector_cosine_ops`, `vector_l1_ops`, `bit_hamming_ops`, `bit_jaccard_ops`, `halfvec_l2_ops`, `sparsevec_l2_ops` options, which are predefined types.\n\t *\n\t * **You can always specify any string you want in the operator class, in case Drizzle doesn't have it natively in its types**\n\t *\n\t * @param opClass\n\t * @returns\n\t */\n\top(opClass: GelIndexOpClass): Omit<this, 'op'> {\n\t\tthis.indexConfig.opClass = opClass;\n\t\treturn this;\n\t}\n}\n\nexport class IndexedColumn {\n\tstatic readonly [entityKind]: string = 'IndexedColumn';\n\tconstructor(\n\t\tname: string | undefined,\n\t\tkeyAsName: boolean,\n\t\ttype: string,\n\t\tindexConfig: IndexedExtraConfigType,\n\t) {\n\t\tthis.name = name;\n\t\tthis.keyAsName = keyAsName;\n\t\tthis.type = type;\n\t\tthis.indexConfig = indexConfig;\n\t}\n\n\tname: string | undefined;\n\tkeyAsName: boolean;\n\ttype: string;\n\tindexConfig: IndexedExtraConfigType;\n}\n\nexport type AnyGelColumn<TPartial extends Partial<ColumnBaseConfig<ColumnDataType, string>> = {}> = GelColumn<\n\tRequired<Update<ColumnBaseConfig<ColumnDataType, string>, TPartial>>\n>;\n\nexport type GelArrayColumnBuilderBaseConfig = ColumnBuilderBaseConfig<'array', 'GelArray'> & {\n\tsize: number | undefined;\n\tbaseBuilder: ColumnBuilderBaseConfig<ColumnDataType, string>;\n};\n\nexport class GelArrayBuilder<\n\tT extends GelArrayColumnBuilderBaseConfig,\n\tTBase extends ColumnBuilderBaseConfig<ColumnDataType, string> | GelArrayColumnBuilderBaseConfig,\n> extends GelColumnBuilder<\n\tT,\n\t{\n\t\tbaseBuilder: TBase extends GelArrayColumnBuilderBaseConfig ? GelArrayBuilder<\n\t\t\t\tTBase,\n\t\t\t\tTBase extends { baseBuilder: infer TBaseBuilder extends ColumnBuilderBaseConfig<any, any> } ? TBaseBuilder\n\t\t\t\t\t: never\n\t\t\t>\n\t\t\t: GelColumnBuilder<TBase, {}, Simplify<Omit<TBase, keyof ColumnBuilderBaseConfig<any, any>>>>;\n\t\tsize: T['size'];\n\t},\n\t{\n\t\tbaseBuilder: TBase extends GelArrayColumnBuilderBaseConfig ? GelArrayBuilder<\n\t\t\t\tTBase,\n\t\t\t\tTBase extends { baseBuilder: infer TBaseBuilder extends ColumnBuilderBaseConfig<any, any> } ? TBaseBuilder\n\t\t\t\t\t: never\n\t\t\t>\n\t\t\t: GelColumnBuilder<TBase, {}, Simplify<Omit<TBase, keyof ColumnBuilderBaseConfig<any, any>>>>;\n\t\tsize: T['size'];\n\t}\n> {\n\tstatic override readonly [entityKind] = 'GelArrayBuilder';\n\n\tconstructor(\n\t\tname: string,\n\t\tbaseBuilder: GelArrayBuilder<T, TBase>['config']['baseBuilder'],\n\t\tsize: T['size'],\n\t) {\n\t\tsuper(name, 'array', 'GelArray');\n\t\tthis.config.baseBuilder = baseBuilder;\n\t\tthis.config.size = size;\n\t}\n\n\t/** @internal */\n\toverride build<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelArray<MakeColumnConfig<T, TTableName> & { size: T['size']; baseBuilder: T['baseBuilder'] }, TBase> {\n\t\tconst baseColumn = this.config.baseBuilder.build(table);\n\t\treturn new GelArray<MakeColumnConfig<T, TTableName> & { size: T['size']; baseBuilder: T['baseBuilder'] }, TBase>(\n\t\t\ttable as AnyGelTable<{ name: MakeColumnConfig<T, TTableName>['tableName'] }>,\n\t\t\tthis.config as ColumnBuilderRuntimeConfig<any, any>,\n\t\t\tbaseColumn,\n\t\t);\n\t}\n}\n\nexport class GelArray<\n\tT extends ColumnBaseConfig<'array', 'GelArray'> & {\n\t\tsize: number | undefined;\n\t\tbaseBuilder: ColumnBuilderBaseConfig<ColumnDataType, string>;\n\t},\n\tTBase extends ColumnBuilderBaseConfig<ColumnDataType, string>,\n> extends GelColumn<T, {}, { size: T['size']; baseBuilder: T['baseBuilder'] }> {\n\treadonly size: T['size'];\n\n\tstatic override readonly [entityKind]: string = 'GelArray';\n\n\tconstructor(\n\t\ttable: AnyGelTable<{ name: T['tableName'] }>,\n\t\tconfig: GelArrayBuilder<T, TBase>['config'],\n\t\treadonly baseColumn: GelColumn,\n\t\treadonly range?: [number | undefined, number | undefined],\n\t) {\n\t\tsuper(table, config);\n\t\tthis.size = config.size;\n\t}\n\n\toverride mapFromDriverValue(value: unknown[]): T['data'] {\n\t\treturn value.map((v) => this.baseColumn.mapFromDriverValue(v));\n\t}\n\n\t// Needed for arrays of custom types\n\tmapFromJsonValue(value: unknown[]): T['data'] {\n\t\tconst base = this.baseColumn;\n\n\t\treturn 'mapFromJsonValue' in base\n\t\t\t? value.map((v) => (<(value: unknown) => unknown> base.mapFromJsonValue)(v))\n\t\t\t: value.map((v) => base.mapFromDriverValue(v));\n\t}\n\n\tgetSQLType(): string {\n\t\treturn `${this.baseColumn.getSQLType()}[${typeof this.size === 'number' ? this.size : ''}]`;\n\t}\n}\n"],"mappings":"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","names":["ref","actions"]}
|
|
@@ -46,11 +46,15 @@ class GelCustomColumn extends import_common.GelColumn {
|
|
|
46
46
|
sqlName;
|
|
47
47
|
mapTo;
|
|
48
48
|
mapFrom;
|
|
49
|
+
mapJson;
|
|
50
|
+
forJsonSelect;
|
|
49
51
|
constructor(table, config) {
|
|
50
52
|
super(table, config);
|
|
51
53
|
this.sqlName = config.customTypeParams.dataType(config.fieldConfig);
|
|
52
54
|
this.mapTo = config.customTypeParams.toDriver;
|
|
53
55
|
this.mapFrom = config.customTypeParams.fromDriver;
|
|
56
|
+
this.mapJson = config.customTypeParams.fromJson;
|
|
57
|
+
this.forJsonSelect = config.customTypeParams.forJsonSelect;
|
|
54
58
|
}
|
|
55
59
|
getSQLType() {
|
|
56
60
|
return this.sqlName;
|
|
@@ -58,6 +62,14 @@ class GelCustomColumn extends import_common.GelColumn {
|
|
|
58
62
|
mapFromDriverValue(value) {
|
|
59
63
|
return typeof this.mapFrom === "function" ? this.mapFrom(value) : value;
|
|
60
64
|
}
|
|
65
|
+
mapFromJsonValue(value) {
|
|
66
|
+
return typeof this.mapJson === "function" ? this.mapJson(value) : this.mapFromDriverValue(value);
|
|
67
|
+
}
|
|
68
|
+
jsonSelectIdentifier(identifier, sql, arrayDimensions) {
|
|
69
|
+
if (typeof this.forJsonSelect === "function")
|
|
70
|
+
return this.forJsonSelect(identifier, sql, arrayDimensions);
|
|
71
|
+
return identifier;
|
|
72
|
+
}
|
|
61
73
|
mapToDriverValue(value) {
|
|
62
74
|
return typeof this.mapTo === "function" ? this.mapTo(value) : value;
|
|
63
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/gel-core/columns/custom.ts"],"sourcesContent":["import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts';\nimport type { ColumnBaseConfig } from '~/column.ts';\nimport { entityKind } from '~/entity.ts';\nimport type { AnyGelTable } from '~/gel-core/table.ts';\nimport type { SQL } from '~/sql/sql.ts';\nimport { type Equal, getColumnNameAndConfig } from '~/utils.ts';\nimport { GelColumn, GelColumnBuilder } from './common.ts';\n\nexport type ConvertCustomConfig<TName extends string, T extends Partial<CustomTypeValues>> =\n\t& {\n\t\tname: TName;\n\t\tdataType: 'custom';\n\t\tcolumnType: 'GelCustomColumn';\n\t\tdata: T['data'];\n\t\tdriverParam: T['driverData'];\n\t\tenumValues: undefined;\n\t}\n\t& (T['notNull'] extends true ? { notNull: true } : {})\n\t& (T['default'] extends true ? { hasDefault: true } : {});\n\nexport interface GelCustomColumnInnerConfig {\n\tcustomTypeValues: CustomTypeValues;\n}\n\nexport class GelCustomColumnBuilder<T extends ColumnBuilderBaseConfig<'custom', 'GelCustomColumn'>>\n\textends GelColumnBuilder<\n\t\tT,\n\t\t{\n\t\t\tfieldConfig: CustomTypeValues['config'];\n\t\t\tcustomTypeParams: CustomTypeParams<any>;\n\t\t},\n\t\t{\n\t\t\tgelColumnBuilderBrand: 'GelCustomColumnBuilderBrand';\n\t\t}\n\t>\n{\n\tstatic override readonly [entityKind]: string = 'GelCustomColumnBuilder';\n\n\tconstructor(\n\t\tname: T['name'],\n\t\tfieldConfig: CustomTypeValues['config'],\n\t\tcustomTypeParams: CustomTypeParams<any>,\n\t) {\n\t\tsuper(name, 'custom', 'GelCustomColumn');\n\t\tthis.config.fieldConfig = fieldConfig;\n\t\tthis.config.customTypeParams = customTypeParams;\n\t}\n\n\t/** @internal */\n\tbuild<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelCustomColumn<MakeColumnConfig<T, TTableName>> {\n\t\treturn new GelCustomColumn<MakeColumnConfig<T, TTableName>>(\n\t\t\ttable,\n\t\t\tthis.config as ColumnBuilderRuntimeConfig<any, any>,\n\t\t);\n\t}\n}\n\nexport class GelCustomColumn<T extends ColumnBaseConfig<'custom', 'GelCustomColumn'>> extends GelColumn<T> {\n\tstatic override readonly [entityKind]: string = 'GelCustomColumn';\n\n\tprivate sqlName: string;\n\tprivate mapTo?: (value: T['data']) => T['driverParam'];\n\tprivate mapFrom?: (value: T['driverParam']) => T['data'];\n\n\tconstructor(\n\t\ttable: AnyGelTable<{ name: T['tableName'] }>,\n\t\tconfig: GelCustomColumnBuilder<T>['config'],\n\t) {\n\t\tsuper(table, config);\n\t\tthis.sqlName = config.customTypeParams.dataType(config.fieldConfig);\n\t\tthis.mapTo = config.customTypeParams.toDriver;\n\t\tthis.mapFrom = config.customTypeParams.fromDriver;\n\t}\n\n\tgetSQLType(): string {\n\t\treturn this.sqlName;\n\t}\n\n\toverride mapFromDriverValue(value: T['driverParam']): T['data'] {\n\t\treturn typeof this.mapFrom === 'function' ? this.mapFrom(value) : value as T['data'];\n\t}\n\n\toverride mapToDriverValue(value: T['data']): T['driverParam'] {\n\t\treturn typeof this.mapTo === 'function' ? this.mapTo(value) : value as T['data'];\n\t}\n}\n\nexport type CustomTypeValues = {\n\t/**\n\t * Required type for custom column, that will infer proper type model\n\t *\n\t * Examples:\n\t *\n\t * If you want your column to be `string` type after selecting/or on inserting - use `data: string`. Like `text`, `varchar`\n\t *\n\t * If you want your column to be `number` type after selecting/or on inserting - use `data: number`. Like `integer`\n\t */\n\tdata: unknown;\n\n\t/**\n\t * Type helper, that represents what type database driver is accepting for specific database data type\n\t */\n\tdriverData?: unknown;\n\n\t/**\n\t * What config type should be used for {@link CustomTypeParams} `dataType` generation\n\t */\n\tconfig?: Record<string, any>;\n\n\t/**\n\t * Whether the config argument should be required or not\n\t * @default false\n\t */\n\tconfigRequired?: boolean;\n\n\t/**\n\t * If your custom data type should be notNull by default you can use `notNull: true`\n\t *\n\t * @example\n\t * const customSerial = customType<{ data: number, notNull: true, default: true }>({\n\t * \t dataType() {\n\t * \t return 'serial';\n\t * },\n\t * });\n\t */\n\tnotNull?: boolean;\n\n\t/**\n\t * If your custom data type has default you can use `default: true`\n\t *\n\t * @example\n\t * const customSerial = customType<{ data: number, notNull: true, default: true }>({\n\t * \t dataType() {\n\t * \t return 'serial';\n\t * },\n\t * });\n\t */\n\tdefault?: boolean;\n};\n\nexport interface CustomTypeParams<T extends CustomTypeValues> {\n\t/**\n\t * Database data type string representation, that is used for migrations\n\t * @example\n\t * ```\n\t * `jsonb`, `text`\n\t * ```\n\t *\n\t * If database data type needs additional params you can use them from `config` param\n\t * @example\n\t * ```\n\t * `varchar(256)`, `numeric(2,3)`\n\t * ```\n\t *\n\t * To make `config` be of specific type please use config generic in {@link CustomTypeValues}\n\t *\n\t * @example\n\t * Usage example\n\t * ```\n\t * dataType() {\n\t * return 'boolean';\n\t * },\n\t * ```\n\t * Or\n\t * ```\n\t * dataType(config) {\n\t * \t return typeof config.length !== 'undefined' ? `varchar(${config.length})` : `varchar`;\n\t * \t }\n\t * ```\n\t */\n\tdataType: (config: T['config'] | (Equal<T['configRequired'], true> extends true ? never : undefined)) => string;\n\n\t/**\n\t * Optional mapping function, between user input and driver\n\t * @example\n\t * For example, when using jsonb we need to map JS/TS object to string before writing to database\n\t * ```\n\t * toDriver(value: TData): string {\n\t * \t return JSON.stringify(value);\n\t * }\n\t * ```\n\t */\n\ttoDriver?: (value: T['data']) => T['driverData'] | SQL;\n\n\t/**\n\t * Optional mapping function, that is responsible for data mapping from database to JS/TS code\n\t * @example\n\t * For example, when using timestamp we need to map string Date representation to JS Date\n\t * ```\n\t * fromDriver(value: string): Date {\n\t * \treturn new Date(value);\n\t * },\n\t * ```\n\t */\n\tfromDriver?: (value: T['driverData']) => T['data'];\n}\n\n/**\n * Custom gel database data type generator\n */\nexport function customType<T extends CustomTypeValues = CustomTypeValues>(\n\tcustomTypeParams: CustomTypeParams<T>,\n): Equal<T['configRequired'], true> extends true ? {\n\t\t<TConfig extends Record<string, any> & T['config']>(\n\t\t\tfieldConfig: TConfig,\n\t\t): GelCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TName extends string>(\n\t\t\tdbName: TName,\n\t\t\tfieldConfig: T['config'],\n\t\t): GelCustomColumnBuilder<ConvertCustomConfig<TName, T>>;\n\t}\n\t: {\n\t\t(): GelCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TConfig extends Record<string, any> & T['config']>(\n\t\t\tfieldConfig?: TConfig,\n\t\t): GelCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TName extends string>(\n\t\t\tdbName: TName,\n\t\t\tfieldConfig?: T['config'],\n\t\t): GelCustomColumnBuilder<ConvertCustomConfig<TName, T>>;\n\t}\n{\n\treturn <TName extends string>(\n\t\ta?: TName | T['config'],\n\t\tb?: T['config'],\n\t): GelCustomColumnBuilder<ConvertCustomConfig<TName, T>> => {\n\t\tconst { name, config } = getColumnNameAndConfig<T['config']>(a, b);\n\t\treturn new GelCustomColumnBuilder(name as ConvertCustomConfig<TName, T>['name'], config, customTypeParams);\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAA2B;AAG3B,mBAAmD;AACnD,oBAA4C;AAkBrC,MAAM,+BACJ,+BAUT;AAAA,EACC,QAA0B,wBAAU,IAAY;AAAA,EAEhD,YACC,MACA,aACA,kBACC;AACD,UAAM,MAAM,UAAU,iBAAiB;AACvC,SAAK,OAAO,cAAc;AAC1B,SAAK,OAAO,mBAAmB;AAAA,EAChC;AAAA;AAAA,EAGA,MACC,OACmD;AACnD,WAAO,IAAI;AAAA,MACV;AAAA,MACA,KAAK;AAAA,IACN;AAAA,EACD;AACD;AAEO,MAAM,wBAAiF,wBAAa;AAAA,EAC1G,QAA0B,wBAAU,IAAY;AAAA,EAExC;AAAA,EACA;AAAA,EACA;AAAA,EAER,YACC,OACA,QACC;AACD,UAAM,OAAO,MAAM;AACnB,SAAK,UAAU,OAAO,iBAAiB,SAAS,OAAO,WAAW;AAClE,SAAK,QAAQ,OAAO,iBAAiB;AACrC,SAAK,UAAU,OAAO,iBAAiB;AAAA,EACxC;AAAA,EAEA,aAAqB;AACpB,WAAO,KAAK;AAAA,EACb;AAAA,EAES,mBAAmB,OAAoC;AAC/D,WAAO,OAAO,KAAK,YAAY,aAAa,KAAK,QAAQ,KAAK,IAAI;AAAA,EACnE;AAAA,EAES,iBAAiB,OAAoC;AAC7D,WAAO,OAAO,KAAK,UAAU,aAAa,KAAK,MAAM,KAAK,IAAI;AAAA,EAC/D;AACD;AAmHO,SAAS,WACf,kBAoBD;AACC,SAAO,CACN,GACA,MAC2D;AAC3D,UAAM,EAAE,MAAM,OAAO,QAAI,qCAAoC,GAAG,CAAC;AACjE,WAAO,IAAI,uBAAuB,MAA+C,QAAQ,gBAAgB;AAAA,EAC1G;AACD;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/gel-core/columns/custom.ts"],"sourcesContent":["import type { ColumnBuilderBaseConfig, ColumnBuilderRuntimeConfig, MakeColumnConfig } from '~/column-builder.ts';\nimport type { ColumnBaseConfig } from '~/column.ts';\nimport { entityKind } from '~/entity.ts';\nimport type { AnyGelTable } from '~/gel-core/table.ts';\nimport type { SQL, SQLGenerator } from '~/sql/sql.ts';\nimport { type Equal, getColumnNameAndConfig } from '~/utils.ts';\nimport { GelColumn, GelColumnBuilder } from './common.ts';\n\nexport type ConvertCustomConfig<TName extends string, T extends Partial<CustomTypeValues>> =\n\t& {\n\t\tname: TName;\n\t\tdataType: 'custom';\n\t\tcolumnType: 'GelCustomColumn';\n\t\tdata: T['data'];\n\t\tdriverParam: T['driverData'];\n\t\tenumValues: undefined;\n\t}\n\t& (T['notNull'] extends true ? { notNull: true } : {})\n\t& (T['default'] extends true ? { hasDefault: true } : {});\n\nexport interface GelCustomColumnInnerConfig {\n\tcustomTypeValues: CustomTypeValues;\n}\n\nexport class GelCustomColumnBuilder<T extends ColumnBuilderBaseConfig<'custom', 'GelCustomColumn'>>\n\textends GelColumnBuilder<\n\t\tT,\n\t\t{\n\t\t\tfieldConfig: CustomTypeValues['config'];\n\t\t\tcustomTypeParams: CustomTypeParams<any>;\n\t\t},\n\t\t{\n\t\t\tgelColumnBuilderBrand: 'GelCustomColumnBuilderBrand';\n\t\t}\n\t>\n{\n\tstatic override readonly [entityKind]: string = 'GelCustomColumnBuilder';\n\n\tconstructor(\n\t\tname: T['name'],\n\t\tfieldConfig: CustomTypeValues['config'],\n\t\tcustomTypeParams: CustomTypeParams<any>,\n\t) {\n\t\tsuper(name, 'custom', 'GelCustomColumn');\n\t\tthis.config.fieldConfig = fieldConfig;\n\t\tthis.config.customTypeParams = customTypeParams;\n\t}\n\n\t/** @internal */\n\tbuild<TTableName extends string>(\n\t\ttable: AnyGelTable<{ name: TTableName }>,\n\t): GelCustomColumn<MakeColumnConfig<T, TTableName>> {\n\t\treturn new GelCustomColumn<MakeColumnConfig<T, TTableName>>(\n\t\t\ttable,\n\t\t\tthis.config as ColumnBuilderRuntimeConfig<any, any>,\n\t\t);\n\t}\n}\n\nexport class GelCustomColumn<T extends ColumnBaseConfig<'custom', 'GelCustomColumn'>> extends GelColumn<T> {\n\tstatic override readonly [entityKind]: string = 'GelCustomColumn';\n\n\tprivate sqlName: string;\n\tprivate mapTo?: (value: T['data']) => T['driverParam'];\n\tprivate mapFrom?: (value: T['driverParam']) => T['data'];\n\tprivate mapJson?: (value: unknown) => T['data'];\n\tprivate forJsonSelect?: (name: SQL, sql: SQLGenerator, arrayDimensions?: number) => SQL;\n\n\tconstructor(\n\t\ttable: AnyGelTable<{ name: T['tableName'] }>,\n\t\tconfig: GelCustomColumnBuilder<T>['config'],\n\t) {\n\t\tsuper(table, config);\n\t\tthis.sqlName = config.customTypeParams.dataType(config.fieldConfig);\n\t\tthis.mapTo = config.customTypeParams.toDriver;\n\t\tthis.mapFrom = config.customTypeParams.fromDriver;\n\t\tthis.mapJson = config.customTypeParams.fromJson;\n\t\tthis.forJsonSelect = config.customTypeParams.forJsonSelect;\n\t}\n\n\tgetSQLType(): string {\n\t\treturn this.sqlName;\n\t}\n\n\toverride mapFromDriverValue(value: T['driverParam']): T['data'] {\n\t\treturn typeof this.mapFrom === 'function' ? this.mapFrom(value) : value as T['data'];\n\t}\n\n\tmapFromJsonValue(value: unknown): T['data'] {\n\t\treturn typeof this.mapJson === 'function' ? this.mapJson(value) : this.mapFromDriverValue(value) as T['data'];\n\t}\n\n\tjsonSelectIdentifier(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL {\n\t\tif (typeof this.forJsonSelect === 'function') return this.forJsonSelect(identifier, sql, arrayDimensions);\n\n\t\treturn identifier;\n\t}\n\n\toverride mapToDriverValue(value: T['data']): T['driverParam'] {\n\t\treturn typeof this.mapTo === 'function' ? this.mapTo(value) : value as T['data'];\n\t}\n}\n\nexport type CustomTypeValues = {\n\t/**\n\t * Required type for custom column, that will infer proper type model\n\t *\n\t * Examples:\n\t *\n\t * If you want your column to be `string` type after selecting/or on inserting - use `data: string`. Like `text`, `varchar`\n\t *\n\t * If you want your column to be `number` type after selecting/or on inserting - use `data: number`. Like `integer`\n\t */\n\tdata: unknown;\n\n\t/**\n\t * Type helper, that represents what type database driver is returning for specific database data type\n\t *\n\t * Needed only in case driver's output and input for type differ\n\t *\n\t * @default\n\t * Defaults to `driverData`\n\t */\n\tdriverOutput?: unknown;\n\n\t/**\n\t * Type helper, that represents what type database driver is accepting for specific database data type\n\t */\n\tdriverData?: unknown;\n\n\t/**\n\t * Type helper, that represents what type field returns after being aggregated to JSON\n\t */\n\tjsonData?: unknown;\n\n\t/**\n\t * What config type should be used for {@link CustomTypeParams} `dataType` generation\n\t */\n\tconfig?: Record<string, any>;\n\n\t/**\n\t * Whether the config argument should be required or not\n\t * @default false\n\t */\n\tconfigRequired?: boolean;\n\n\t/**\n\t * If your custom data type should be notNull by default you can use `notNull: true`\n\t *\n\t * @example\n\t * const customSerial = customType<{ data: number, notNull: true, default: true }>({\n\t * \t dataType() {\n\t * \t return 'serial';\n\t * },\n\t * });\n\t */\n\tnotNull?: boolean;\n\n\t/**\n\t * If your custom data type has default you can use `default: true`\n\t *\n\t * @example\n\t * const customSerial = customType<{ data: number, notNull: true, default: true }>({\n\t * \t dataType() {\n\t * \t return 'serial';\n\t * },\n\t * });\n\t */\n\tdefault?: boolean;\n};\n\nexport interface CustomTypeParams<T extends CustomTypeValues> {\n\t/**\n\t * Database data type string representation, that is used for migrations\n\t * @example\n\t * ```\n\t * `jsonb`, `text`\n\t * ```\n\t *\n\t * If database data type needs additional params you can use them from `config` param\n\t * @example\n\t * ```\n\t * `varchar(256)`, `numeric(2,3)`\n\t * ```\n\t *\n\t * To make `config` be of specific type please use config generic in {@link CustomTypeValues}\n\t *\n\t * @example\n\t * Usage example\n\t * ```\n\t * dataType() {\n\t * return 'boolean';\n\t * },\n\t * ```\n\t * Or\n\t * ```\n\t * dataType(config) {\n\t * \t return typeof config.length !== 'undefined' ? `varchar(${config.length})` : `varchar`;\n\t * \t }\n\t * ```\n\t */\n\tdataType: (config: T['config'] | (Equal<T['configRequired'], true> extends true ? never : undefined)) => string;\n\n\t/**\n\t * Optional mapping function, that is used to transform inputs from desired to be used in code format to one suitable for driver\n\t * @example\n\t * For example, when using jsonb we need to map JS/TS object to string before writing to database\n\t * ```\n\t * toDriver(value: TData): string {\n\t * \t return JSON.stringify(value);\n\t * }\n\t * ```\n\t */\n\ttoDriver?: (value: T['data']) => T['driverData'] | SQL;\n\n\t/**\n\t * Optional mapping function, that is used for transforming data returned by driver to desired column's output format\n\t * @example\n\t * For example, when using timestamp we need to map string Date representation to JS Date\n\t * ```\n\t * fromDriver(value: string): Date {\n\t * \treturn new Date(value);\n\t * }\n\t * ```\n\t *\n\t * It'll cause the returned data to change from:\n\t * ```\n\t * {\n\t * \tcustomField: \"2025-04-07T03:25:16.635Z\";\n\t * }\n\t * ```\n\t * to:\n\t * ```\n\t * {\n\t * \tcustomField: new Date(\"2025-04-07T03:25:16.635Z\");\n\t * }\n\t * ```\n\t */\n\tfromDriver?: (value: 'driverOutput' extends keyof T ? T['driverOutput'] : T['driverData']) => T['data'];\n\n\t/**\n\t * Optional mapping function, that is used for transforming data returned by transofmed to JSON in database data to desired format\n\t *\n\t * Used by relational queries\n\t * @example\n\t * For example, when querying bigint column via RQB or JSON funcitons, the result field will be returned as it's string representation, as opposed to bigint from regular query\n\t * To handle that, we need a separate function to handle such field's mapping:\n\t * ```\n\t * fromJson(value: string): bigint {\n\t * \treturn BigInt(value);\n\t * },\n\t * ```\n\t *\n\t * It'll cause the returned data to change from:\n\t * ```\n\t * {\n\t * \tcustomField: \"5044565289845416380\";\n\t * }\n\t * ```\n\t * to:\n\t * ```\n\t * {\n\t * \tcustomField: 5044565289845416380n;\n\t * }\n\t * ```\n\t * @default\n\t * Defaults to {@link fromDriver} function\n\t */\n\tfromJson?: (value: T['jsonData']) => T['data'];\n\n\t/**\n\t * Optional selection modifier function, that is used for modifying selection of column inside JSON functions\n\t *\n\t * Additional mapping that could be required for such scenarios can be handled using {@link fromJson} function\n\t *\n\t * Used by relational queries\n\t * @example\n\t * For example, when using bigint we need to cast field to text to preserve data integrity\n\t * ```\n\t * forJsonSelect(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL {\n\t * \treturn sql`${identifier}::text`\n\t * },\n\t * ```\n\t *\n\t * This will change query from:\n\t * ```\n\t * SELECT\n\t * \trow_to_json(\"t\".*)\n\t * \tFROM\n\t * \t(\n\t * \t\tSELECT\n\t * \t\t\"table\".\"custom_bigint\" AS \"bigint\"\n\t * \t\tFROM\n\t * \t\t\"table\"\n\t * \t) AS \"t\"\n\t * ```\n\t * to:\n\t * ```\n\t * SELECT\n\t * \trow_to_json(\"t\".*)\n\t * \tFROM\n\t * \t(\n\t * \t\tSELECT\n\t * \t\t\"table\".\"custom_bigint\"::text AS \"bigint\"\n\t * \t\tFROM\n\t * \t\t\"table\"\n\t * \t) AS \"t\"\n\t * ```\n\t *\n\t * Returned by query object will change from:\n\t * ```\n\t * {\n\t * \tbigint: 5044565289845416000; // Partial data loss due to direct conversion to JSON format\n\t * }\n\t * ```\n\t * to:\n\t * ```\n\t * {\n\t * \tbigint: \"5044565289845416380\"; // Data is preserved due to conversion of field to text before JSON-ification\n\t * }\n\t * ```\n\t */\n\tforJsonSelect?: (identifier: SQL, sql: SQLGenerator, arrayDimensions?: number) => SQL;\n}\n\n/**\n * Custom gel database data type generator\n */\nexport function customType<T extends CustomTypeValues = CustomTypeValues>(\n\tcustomTypeParams: CustomTypeParams<T>,\n): Equal<T['configRequired'], true> extends true ? {\n\t\t<TConfig extends Record<string, any> & T['config']>(\n\t\t\tfieldConfig: TConfig,\n\t\t): GelCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TName extends string>(\n\t\t\tdbName: TName,\n\t\t\tfieldConfig: T['config'],\n\t\t): GelCustomColumnBuilder<ConvertCustomConfig<TName, T>>;\n\t}\n\t: {\n\t\t(): GelCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TConfig extends Record<string, any> & T['config']>(\n\t\t\tfieldConfig?: TConfig,\n\t\t): GelCustomColumnBuilder<ConvertCustomConfig<'', T>>;\n\t\t<TName extends string>(\n\t\t\tdbName: TName,\n\t\t\tfieldConfig?: T['config'],\n\t\t): GelCustomColumnBuilder<ConvertCustomConfig<TName, T>>;\n\t}\n{\n\treturn <TName extends string>(\n\t\ta?: TName | T['config'],\n\t\tb?: T['config'],\n\t): GelCustomColumnBuilder<ConvertCustomConfig<TName, T>> => {\n\t\tconst { name, config } = getColumnNameAndConfig<T['config']>(a, b);\n\t\treturn new GelCustomColumnBuilder(name as ConvertCustomConfig<TName, T>['name'], config, customTypeParams);\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAA2B;AAG3B,mBAAmD;AACnD,oBAA4C;AAkBrC,MAAM,+BACJ,+BAUT;AAAA,EACC,QAA0B,wBAAU,IAAY;AAAA,EAEhD,YACC,MACA,aACA,kBACC;AACD,UAAM,MAAM,UAAU,iBAAiB;AACvC,SAAK,OAAO,cAAc;AAC1B,SAAK,OAAO,mBAAmB;AAAA,EAChC;AAAA;AAAA,EAGA,MACC,OACmD;AACnD,WAAO,IAAI;AAAA,MACV;AAAA,MACA,KAAK;AAAA,IACN;AAAA,EACD;AACD;AAEO,MAAM,wBAAiF,wBAAa;AAAA,EAC1G,QAA0B,wBAAU,IAAY;AAAA,EAExC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YACC,OACA,QACC;AACD,UAAM,OAAO,MAAM;AACnB,SAAK,UAAU,OAAO,iBAAiB,SAAS,OAAO,WAAW;AAClE,SAAK,QAAQ,OAAO,iBAAiB;AACrC,SAAK,UAAU,OAAO,iBAAiB;AACvC,SAAK,UAAU,OAAO,iBAAiB;AACvC,SAAK,gBAAgB,OAAO,iBAAiB;AAAA,EAC9C;AAAA,EAEA,aAAqB;AACpB,WAAO,KAAK;AAAA,EACb;AAAA,EAES,mBAAmB,OAAoC;AAC/D,WAAO,OAAO,KAAK,YAAY,aAAa,KAAK,QAAQ,KAAK,IAAI;AAAA,EACnE;AAAA,EAEA,iBAAiB,OAA2B;AAC3C,WAAO,OAAO,KAAK,YAAY,aAAa,KAAK,QAAQ,KAAK,IAAI,KAAK,mBAAmB,KAAK;AAAA,EAChG;AAAA,EAEA,qBAAqB,YAAiB,KAAmB,iBAA+B;AACvF,QAAI,OAAO,KAAK,kBAAkB;AAAY,aAAO,KAAK,cAAc,YAAY,KAAK,eAAe;AAExG,WAAO;AAAA,EACR;AAAA,EAES,iBAAiB,OAAoC;AAC7D,WAAO,OAAO,KAAK,UAAU,aAAa,KAAK,MAAM,KAAK,IAAI;AAAA,EAC/D;AACD;AAmOO,SAAS,WACf,kBAoBD;AACC,SAAO,CACN,GACA,MAC2D;AAC3D,UAAM,EAAE,MAAM,OAAO,QAAI,qCAAoC,GAAG,CAAC;AACjE,WAAO,IAAI,uBAAuB,MAA+C,QAAQ,gBAAgB;AAAA,EAC1G;AACD;","names":[]}
|
|
@@ -2,7 +2,7 @@ import type { ColumnBuilderBaseConfig } from "../../column-builder.cjs";
|
|
|
2
2
|
import type { ColumnBaseConfig } from "../../column.cjs";
|
|
3
3
|
import { entityKind } from "../../entity.cjs";
|
|
4
4
|
import type { AnyGelTable } from "../table.cjs";
|
|
5
|
-
import type { SQL } from "../../sql/sql.cjs";
|
|
5
|
+
import type { SQL, SQLGenerator } from "../../sql/sql.cjs";
|
|
6
6
|
import { type Equal } from "../../utils.cjs";
|
|
7
7
|
import { GelColumn, GelColumnBuilder } from "./common.cjs";
|
|
8
8
|
export type ConvertCustomConfig<TName extends string, T extends Partial<CustomTypeValues>> = {
|
|
@@ -34,11 +34,15 @@ export declare class GelCustomColumn<T extends ColumnBaseConfig<'custom', 'GelCu
|
|
|
34
34
|
private sqlName;
|
|
35
35
|
private mapTo?;
|
|
36
36
|
private mapFrom?;
|
|
37
|
+
private mapJson?;
|
|
38
|
+
private forJsonSelect?;
|
|
37
39
|
constructor(table: AnyGelTable<{
|
|
38
40
|
name: T['tableName'];
|
|
39
41
|
}>, config: GelCustomColumnBuilder<T>['config']);
|
|
40
42
|
getSQLType(): string;
|
|
41
43
|
mapFromDriverValue(value: T['driverParam']): T['data'];
|
|
44
|
+
mapFromJsonValue(value: unknown): T['data'];
|
|
45
|
+
jsonSelectIdentifier(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL;
|
|
42
46
|
mapToDriverValue(value: T['data']): T['driverParam'];
|
|
43
47
|
}
|
|
44
48
|
export type CustomTypeValues = {
|
|
@@ -52,10 +56,23 @@ export type CustomTypeValues = {
|
|
|
52
56
|
* If you want your column to be `number` type after selecting/or on inserting - use `data: number`. Like `integer`
|
|
53
57
|
*/
|
|
54
58
|
data: unknown;
|
|
59
|
+
/**
|
|
60
|
+
* Type helper, that represents what type database driver is returning for specific database data type
|
|
61
|
+
*
|
|
62
|
+
* Needed only in case driver's output and input for type differ
|
|
63
|
+
*
|
|
64
|
+
* @default
|
|
65
|
+
* Defaults to `driverData`
|
|
66
|
+
*/
|
|
67
|
+
driverOutput?: unknown;
|
|
55
68
|
/**
|
|
56
69
|
* Type helper, that represents what type database driver is accepting for specific database data type
|
|
57
70
|
*/
|
|
58
71
|
driverData?: unknown;
|
|
72
|
+
/**
|
|
73
|
+
* Type helper, that represents what type field returns after being aggregated to JSON
|
|
74
|
+
*/
|
|
75
|
+
jsonData?: unknown;
|
|
59
76
|
/**
|
|
60
77
|
* What config type should be used for {@link CustomTypeParams} `dataType` generation
|
|
61
78
|
*/
|
|
@@ -120,7 +137,7 @@ export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
|
120
137
|
*/
|
|
121
138
|
dataType: (config: T['config'] | (Equal<T['configRequired'], true> extends true ? never : undefined)) => string;
|
|
122
139
|
/**
|
|
123
|
-
* Optional mapping function,
|
|
140
|
+
* Optional mapping function, that is used to transform inputs from desired to be used in code format to one suitable for driver
|
|
124
141
|
* @example
|
|
125
142
|
* For example, when using jsonb we need to map JS/TS object to string before writing to database
|
|
126
143
|
* ```
|
|
@@ -131,16 +148,111 @@ export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
|
131
148
|
*/
|
|
132
149
|
toDriver?: (value: T['data']) => T['driverData'] | SQL;
|
|
133
150
|
/**
|
|
134
|
-
* Optional mapping function, that is
|
|
151
|
+
* Optional mapping function, that is used for transforming data returned by driver to desired column's output format
|
|
135
152
|
* @example
|
|
136
153
|
* For example, when using timestamp we need to map string Date representation to JS Date
|
|
137
154
|
* ```
|
|
138
155
|
* fromDriver(value: string): Date {
|
|
139
156
|
* return new Date(value);
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* It'll cause the returned data to change from:
|
|
161
|
+
* ```
|
|
162
|
+
* {
|
|
163
|
+
* customField: "2025-04-07T03:25:16.635Z";
|
|
164
|
+
* }
|
|
165
|
+
* ```
|
|
166
|
+
* to:
|
|
167
|
+
* ```
|
|
168
|
+
* {
|
|
169
|
+
* customField: new Date("2025-04-07T03:25:16.635Z");
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
fromDriver?: (value: 'driverOutput' extends keyof T ? T['driverOutput'] : T['driverData']) => T['data'];
|
|
174
|
+
/**
|
|
175
|
+
* Optional mapping function, that is used for transforming data returned by transofmed to JSON in database data to desired format
|
|
176
|
+
*
|
|
177
|
+
* Used by relational queries
|
|
178
|
+
* @example
|
|
179
|
+
* For example, when querying bigint column via RQB or JSON funcitons, the result field will be returned as it's string representation, as opposed to bigint from regular query
|
|
180
|
+
* To handle that, we need a separate function to handle such field's mapping:
|
|
181
|
+
* ```
|
|
182
|
+
* fromJson(value: string): bigint {
|
|
183
|
+
* return BigInt(value);
|
|
140
184
|
* },
|
|
141
185
|
* ```
|
|
186
|
+
*
|
|
187
|
+
* It'll cause the returned data to change from:
|
|
188
|
+
* ```
|
|
189
|
+
* {
|
|
190
|
+
* customField: "5044565289845416380";
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
* to:
|
|
194
|
+
* ```
|
|
195
|
+
* {
|
|
196
|
+
* customField: 5044565289845416380n;
|
|
197
|
+
* }
|
|
198
|
+
* ```
|
|
199
|
+
* @default
|
|
200
|
+
* Defaults to {@link fromDriver} function
|
|
201
|
+
*/
|
|
202
|
+
fromJson?: (value: T['jsonData']) => T['data'];
|
|
203
|
+
/**
|
|
204
|
+
* Optional selection modifier function, that is used for modifying selection of column inside JSON functions
|
|
205
|
+
*
|
|
206
|
+
* Additional mapping that could be required for such scenarios can be handled using {@link fromJson} function
|
|
207
|
+
*
|
|
208
|
+
* Used by relational queries
|
|
209
|
+
* @example
|
|
210
|
+
* For example, when using bigint we need to cast field to text to preserve data integrity
|
|
211
|
+
* ```
|
|
212
|
+
* forJsonSelect(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL {
|
|
213
|
+
* return sql`${identifier}::text`
|
|
214
|
+
* },
|
|
215
|
+
* ```
|
|
216
|
+
*
|
|
217
|
+
* This will change query from:
|
|
218
|
+
* ```
|
|
219
|
+
* SELECT
|
|
220
|
+
* row_to_json("t".*)
|
|
221
|
+
* FROM
|
|
222
|
+
* (
|
|
223
|
+
* SELECT
|
|
224
|
+
* "table"."custom_bigint" AS "bigint"
|
|
225
|
+
* FROM
|
|
226
|
+
* "table"
|
|
227
|
+
* ) AS "t"
|
|
228
|
+
* ```
|
|
229
|
+
* to:
|
|
230
|
+
* ```
|
|
231
|
+
* SELECT
|
|
232
|
+
* row_to_json("t".*)
|
|
233
|
+
* FROM
|
|
234
|
+
* (
|
|
235
|
+
* SELECT
|
|
236
|
+
* "table"."custom_bigint"::text AS "bigint"
|
|
237
|
+
* FROM
|
|
238
|
+
* "table"
|
|
239
|
+
* ) AS "t"
|
|
240
|
+
* ```
|
|
241
|
+
*
|
|
242
|
+
* Returned by query object will change from:
|
|
243
|
+
* ```
|
|
244
|
+
* {
|
|
245
|
+
* bigint: 5044565289845416000; // Partial data loss due to direct conversion to JSON format
|
|
246
|
+
* }
|
|
247
|
+
* ```
|
|
248
|
+
* to:
|
|
249
|
+
* ```
|
|
250
|
+
* {
|
|
251
|
+
* bigint: "5044565289845416380"; // Data is preserved due to conversion of field to text before JSON-ification
|
|
252
|
+
* }
|
|
253
|
+
* ```
|
|
142
254
|
*/
|
|
143
|
-
|
|
255
|
+
forJsonSelect?: (identifier: SQL, sql: SQLGenerator, arrayDimensions?: number) => SQL;
|
|
144
256
|
}
|
|
145
257
|
/**
|
|
146
258
|
* Custom gel database data type generator
|
|
@@ -2,7 +2,7 @@ import type { ColumnBuilderBaseConfig } from "../../column-builder.js";
|
|
|
2
2
|
import type { ColumnBaseConfig } from "../../column.js";
|
|
3
3
|
import { entityKind } from "../../entity.js";
|
|
4
4
|
import type { AnyGelTable } from "../table.js";
|
|
5
|
-
import type { SQL } from "../../sql/sql.js";
|
|
5
|
+
import type { SQL, SQLGenerator } from "../../sql/sql.js";
|
|
6
6
|
import { type Equal } from "../../utils.js";
|
|
7
7
|
import { GelColumn, GelColumnBuilder } from "./common.js";
|
|
8
8
|
export type ConvertCustomConfig<TName extends string, T extends Partial<CustomTypeValues>> = {
|
|
@@ -34,11 +34,15 @@ export declare class GelCustomColumn<T extends ColumnBaseConfig<'custom', 'GelCu
|
|
|
34
34
|
private sqlName;
|
|
35
35
|
private mapTo?;
|
|
36
36
|
private mapFrom?;
|
|
37
|
+
private mapJson?;
|
|
38
|
+
private forJsonSelect?;
|
|
37
39
|
constructor(table: AnyGelTable<{
|
|
38
40
|
name: T['tableName'];
|
|
39
41
|
}>, config: GelCustomColumnBuilder<T>['config']);
|
|
40
42
|
getSQLType(): string;
|
|
41
43
|
mapFromDriverValue(value: T['driverParam']): T['data'];
|
|
44
|
+
mapFromJsonValue(value: unknown): T['data'];
|
|
45
|
+
jsonSelectIdentifier(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL;
|
|
42
46
|
mapToDriverValue(value: T['data']): T['driverParam'];
|
|
43
47
|
}
|
|
44
48
|
export type CustomTypeValues = {
|
|
@@ -52,10 +56,23 @@ export type CustomTypeValues = {
|
|
|
52
56
|
* If you want your column to be `number` type after selecting/or on inserting - use `data: number`. Like `integer`
|
|
53
57
|
*/
|
|
54
58
|
data: unknown;
|
|
59
|
+
/**
|
|
60
|
+
* Type helper, that represents what type database driver is returning for specific database data type
|
|
61
|
+
*
|
|
62
|
+
* Needed only in case driver's output and input for type differ
|
|
63
|
+
*
|
|
64
|
+
* @default
|
|
65
|
+
* Defaults to `driverData`
|
|
66
|
+
*/
|
|
67
|
+
driverOutput?: unknown;
|
|
55
68
|
/**
|
|
56
69
|
* Type helper, that represents what type database driver is accepting for specific database data type
|
|
57
70
|
*/
|
|
58
71
|
driverData?: unknown;
|
|
72
|
+
/**
|
|
73
|
+
* Type helper, that represents what type field returns after being aggregated to JSON
|
|
74
|
+
*/
|
|
75
|
+
jsonData?: unknown;
|
|
59
76
|
/**
|
|
60
77
|
* What config type should be used for {@link CustomTypeParams} `dataType` generation
|
|
61
78
|
*/
|
|
@@ -120,7 +137,7 @@ export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
|
120
137
|
*/
|
|
121
138
|
dataType: (config: T['config'] | (Equal<T['configRequired'], true> extends true ? never : undefined)) => string;
|
|
122
139
|
/**
|
|
123
|
-
* Optional mapping function,
|
|
140
|
+
* Optional mapping function, that is used to transform inputs from desired to be used in code format to one suitable for driver
|
|
124
141
|
* @example
|
|
125
142
|
* For example, when using jsonb we need to map JS/TS object to string before writing to database
|
|
126
143
|
* ```
|
|
@@ -131,16 +148,111 @@ export interface CustomTypeParams<T extends CustomTypeValues> {
|
|
|
131
148
|
*/
|
|
132
149
|
toDriver?: (value: T['data']) => T['driverData'] | SQL;
|
|
133
150
|
/**
|
|
134
|
-
* Optional mapping function, that is
|
|
151
|
+
* Optional mapping function, that is used for transforming data returned by driver to desired column's output format
|
|
135
152
|
* @example
|
|
136
153
|
* For example, when using timestamp we need to map string Date representation to JS Date
|
|
137
154
|
* ```
|
|
138
155
|
* fromDriver(value: string): Date {
|
|
139
156
|
* return new Date(value);
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* It'll cause the returned data to change from:
|
|
161
|
+
* ```
|
|
162
|
+
* {
|
|
163
|
+
* customField: "2025-04-07T03:25:16.635Z";
|
|
164
|
+
* }
|
|
165
|
+
* ```
|
|
166
|
+
* to:
|
|
167
|
+
* ```
|
|
168
|
+
* {
|
|
169
|
+
* customField: new Date("2025-04-07T03:25:16.635Z");
|
|
170
|
+
* }
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
fromDriver?: (value: 'driverOutput' extends keyof T ? T['driverOutput'] : T['driverData']) => T['data'];
|
|
174
|
+
/**
|
|
175
|
+
* Optional mapping function, that is used for transforming data returned by transofmed to JSON in database data to desired format
|
|
176
|
+
*
|
|
177
|
+
* Used by relational queries
|
|
178
|
+
* @example
|
|
179
|
+
* For example, when querying bigint column via RQB or JSON funcitons, the result field will be returned as it's string representation, as opposed to bigint from regular query
|
|
180
|
+
* To handle that, we need a separate function to handle such field's mapping:
|
|
181
|
+
* ```
|
|
182
|
+
* fromJson(value: string): bigint {
|
|
183
|
+
* return BigInt(value);
|
|
140
184
|
* },
|
|
141
185
|
* ```
|
|
186
|
+
*
|
|
187
|
+
* It'll cause the returned data to change from:
|
|
188
|
+
* ```
|
|
189
|
+
* {
|
|
190
|
+
* customField: "5044565289845416380";
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
* to:
|
|
194
|
+
* ```
|
|
195
|
+
* {
|
|
196
|
+
* customField: 5044565289845416380n;
|
|
197
|
+
* }
|
|
198
|
+
* ```
|
|
199
|
+
* @default
|
|
200
|
+
* Defaults to {@link fromDriver} function
|
|
201
|
+
*/
|
|
202
|
+
fromJson?: (value: T['jsonData']) => T['data'];
|
|
203
|
+
/**
|
|
204
|
+
* Optional selection modifier function, that is used for modifying selection of column inside JSON functions
|
|
205
|
+
*
|
|
206
|
+
* Additional mapping that could be required for such scenarios can be handled using {@link fromJson} function
|
|
207
|
+
*
|
|
208
|
+
* Used by relational queries
|
|
209
|
+
* @example
|
|
210
|
+
* For example, when using bigint we need to cast field to text to preserve data integrity
|
|
211
|
+
* ```
|
|
212
|
+
* forJsonSelect(identifier: SQL, sql: SQLGenerator, arrayDimensions?: number): SQL {
|
|
213
|
+
* return sql`${identifier}::text`
|
|
214
|
+
* },
|
|
215
|
+
* ```
|
|
216
|
+
*
|
|
217
|
+
* This will change query from:
|
|
218
|
+
* ```
|
|
219
|
+
* SELECT
|
|
220
|
+
* row_to_json("t".*)
|
|
221
|
+
* FROM
|
|
222
|
+
* (
|
|
223
|
+
* SELECT
|
|
224
|
+
* "table"."custom_bigint" AS "bigint"
|
|
225
|
+
* FROM
|
|
226
|
+
* "table"
|
|
227
|
+
* ) AS "t"
|
|
228
|
+
* ```
|
|
229
|
+
* to:
|
|
230
|
+
* ```
|
|
231
|
+
* SELECT
|
|
232
|
+
* row_to_json("t".*)
|
|
233
|
+
* FROM
|
|
234
|
+
* (
|
|
235
|
+
* SELECT
|
|
236
|
+
* "table"."custom_bigint"::text AS "bigint"
|
|
237
|
+
* FROM
|
|
238
|
+
* "table"
|
|
239
|
+
* ) AS "t"
|
|
240
|
+
* ```
|
|
241
|
+
*
|
|
242
|
+
* Returned by query object will change from:
|
|
243
|
+
* ```
|
|
244
|
+
* {
|
|
245
|
+
* bigint: 5044565289845416000; // Partial data loss due to direct conversion to JSON format
|
|
246
|
+
* }
|
|
247
|
+
* ```
|
|
248
|
+
* to:
|
|
249
|
+
* ```
|
|
250
|
+
* {
|
|
251
|
+
* bigint: "5044565289845416380"; // Data is preserved due to conversion of field to text before JSON-ification
|
|
252
|
+
* }
|
|
253
|
+
* ```
|
|
142
254
|
*/
|
|
143
|
-
|
|
255
|
+
forJsonSelect?: (identifier: SQL, sql: SQLGenerator, arrayDimensions?: number) => SQL;
|
|
144
256
|
}
|
|
145
257
|
/**
|
|
146
258
|
* Custom gel database data type generator
|