diff --git a/drizzle-orm/.madgerc b/drizzle-orm/.madgerc new file mode 100644 index 000000000..66f0c66c6 --- /dev/null +++ b/drizzle-orm/.madgerc @@ -0,0 +1,7 @@ +{ + "detectiveOptions": { + "ts": { + "skipTypeImports": true + } + } +} diff --git a/drizzle-orm/src/alias.ts b/drizzle-orm/src/alias.ts index f55c9f6db..c83b30633 100644 --- a/drizzle-orm/src/alias.ts +++ b/drizzle-orm/src/alias.ts @@ -1,6 +1,6 @@ import type { AnyColumn } from './column'; import { Column } from './column'; -import { type Relation } from './relations'; +import type { Relation } from './relations'; import { SQL, sql } from './sql'; import { Table } from './table'; import { type View, ViewBaseConfig } from './view'; diff --git a/drizzle-orm/src/aws-data-api/common/index.ts b/drizzle-orm/src/aws-data-api/common/index.ts index bae9bdfbe..fcbc9ba78 100644 --- a/drizzle-orm/src/aws-data-api/common/index.ts +++ b/drizzle-orm/src/aws-data-api/common/index.ts @@ -2,23 +2,23 @@ import type { Field } from '@aws-sdk/client-rds-data'; import { TypeHint } from '@aws-sdk/client-rds-data'; import type { QueryTypingsValue } from '~/sql'; -export function getValueFromDataApi(row: Field) { - if (row.stringValue !== undefined) { - return row.stringValue; - } else if (row.booleanValue !== undefined) { - return row.booleanValue; - } else if (row.doubleValue !== undefined) { - return row.doubleValue; - } else if (row.isNull !== undefined) { +export function getValueFromDataApi(field: Field) { + if (field.stringValue !== undefined) { + return field.stringValue; + } else if (field.booleanValue !== undefined) { + return field.booleanValue; + } else if (field.doubleValue !== undefined) { + return field.doubleValue; + } else if (field.isNull !== undefined) { return null; - } else if (row.longValue !== undefined) { - return row.longValue; - } else if (row.blobValue !== undefined) { - return row.blobValue; + } else if (field.longValue !== undefined) { + return field.longValue; + } else if (field.blobValue !== undefined) { + return field.blobValue; // eslint-disable-next-line unicorn/no-negated-condition - } else if (row.arrayValue !== undefined) { - if (row.arrayValue.stringValues !== undefined) { - return row.arrayValue.stringValues; + } else if (field.arrayValue !== undefined) { + if (field.arrayValue.stringValues !== undefined) { + return field.arrayValue.stringValues; } throw new Error('Unknown array type'); } else { diff --git a/drizzle-orm/src/aws-data-api/pg/session.ts b/drizzle-orm/src/aws-data-api/pg/session.ts index 74dace747..70ca4d0a9 100644 --- a/drizzle-orm/src/aws-data-api/pg/session.ts +++ b/drizzle-orm/src/aws-data-api/pg/session.ts @@ -1,4 +1,4 @@ -import type { ExecuteStatementCommandOutput, RDSDataClient } from '@aws-sdk/client-rds-data'; +import type { ExecuteStatementCommandOutput, Field, RDSDataClient } from '@aws-sdk/client-rds-data'; import { BeginTransactionCommand, CommitTransactionCommand, @@ -35,7 +35,7 @@ export class AwsDataApiPreparedQuery extends Prep private fields: SelectedFieldsOrdered | undefined, /** @internal */ readonly transactionId: string | undefined, - private customResultMapper?: (rows: unknown[][]) => T['execute'], + private customResultMapper?: (rows: unknown[][], mapColumnValue: (value: unknown) => unknown) => T['execute'], ) { super(); this.rawQuery = new ExecuteStatementCommand({ @@ -56,7 +56,7 @@ export class AwsDataApiPreparedQuery extends Prep return rows as T['execute']; } return customResultMapper - ? customResultMapper(rows) + ? customResultMapper(rows, (field) => getValueFromDataApi(field as Field)) : rows.map((row) => mapResultRow(fields!, row, joinsNotNullableMap)); } @@ -82,8 +82,8 @@ export class AwsDataApiPreparedQuery extends Prep const result = await client.send(rawQuery); - return result.records?.map((result: any) => { - return result.map((res: any) => getValueFromDataApi(res)); + return result.records?.map((row: any) => { + return row.map((field: Field) => getValueFromDataApi(field)); }); } } @@ -129,7 +129,7 @@ export class AwsDataApiSession< query: Query, fields: SelectedFieldsOrdered | undefined, transactionId?: string, - customResultMapper?: (rows: unknown[][]) => T['execute'], + customResultMapper?: (rows: unknown[][], mapColumnValue: (value: unknown) => unknown) => T['execute'], ): PreparedQuery { return new AwsDataApiPreparedQuery( this.client, diff --git a/drizzle-orm/src/pg-core/query-builders/query.ts b/drizzle-orm/src/pg-core/query-builders/query.ts index 12663d68d..969970146 100644 --- a/drizzle-orm/src/pg-core/query-builders/query.ts +++ b/drizzle-orm/src/pg-core/query-builders/query.ts @@ -6,11 +6,11 @@ import { type TableRelationalConfig, type TablesRelationalConfig, } from '~/relations'; -import { type SQL } from '~/sql'; +import type { SQL } from '~/sql'; import { tracer } from '~/tracing'; -import { type KnownKeysOnly } from '~/utils'; -import { type PgDialect } from '../dialect'; -import { type PgSession, type PreparedQuery, type PreparedQueryConfig } from '../session'; +import type { KnownKeysOnly } from '~/utils'; +import type { PgDialect } from '../dialect'; +import type { PgSession, PreparedQuery, PreparedQueryConfig } from '../session'; import { type AnyPgTable } from '../table'; export class RelationalQueryBuilder { @@ -93,8 +93,10 @@ export class PgRelationalQuery extends QueryPromise { builtQuery, undefined, name, - (rawRows) => { - const rows = rawRows.map((row) => mapRelationalRow(this.schema, this.tableConfig, row, query.selection)); + (rawRows, mapColumnValue) => { + const rows = rawRows.map((row) => + mapRelationalRow(this.schema, this.tableConfig, row, query.selection, mapColumnValue) + ); if (this.mode === 'first') { return rows[0] as TResult; } diff --git a/drizzle-orm/src/pg-core/session.ts b/drizzle-orm/src/pg-core/session.ts index 78fc69f11..268a71140 100644 --- a/drizzle-orm/src/pg-core/session.ts +++ b/drizzle-orm/src/pg-core/session.ts @@ -39,7 +39,7 @@ export abstract class PgSession< query: Query, fields: SelectedFieldsOrdered | undefined, name: string | undefined, - customResultMapper?: (rows: unknown[][]) => T['execute'], + customResultMapper?: (rows: unknown[][], mapColumnValue?: (value: unknown) => unknown) => T['execute'], ): PreparedQuery; execute(query: SQL): Promise { diff --git a/drizzle-orm/src/pg-core/table.ts b/drizzle-orm/src/pg-core/table.ts index a65b1c343..0fc5fc3f5 100644 --- a/drizzle-orm/src/pg-core/table.ts +++ b/drizzle-orm/src/pg-core/table.ts @@ -1,11 +1,11 @@ import type { BuildColumns } from '~/column-builder'; import { type AnyTableHKT, Table, type TableConfig as TableConfigBase, type UpdateTableConfig } from '~/table'; -import { type Assume } from '~/utils'; -import { type CheckBuilder } from './checks'; +import type { Assume } from '~/utils'; +import type { CheckBuilder } from './checks'; import type { AnyPgColumn, AnyPgColumnBuilder } from './columns/common'; import type { ForeignKey, ForeignKeyBuilder } from './foreign-keys'; -import { type AnyIndexBuilder } from './indexes'; -import { type PrimaryKeyBuilder } from './primary-keys'; +import type { AnyIndexBuilder } from './indexes'; +import type { PrimaryKeyBuilder } from './primary-keys'; export type PgTableExtraConfig = Record< string, diff --git a/drizzle-orm/src/relations.ts b/drizzle-orm/src/relations.ts index 8eff11791..38a39fbc8 100644 --- a/drizzle-orm/src/relations.ts +++ b/drizzle-orm/src/relations.ts @@ -494,7 +494,6 @@ export function mapRelationalRow( tableConfig: TableRelationalConfig, row: unknown[], buildQueryResultSelection: BuildRelationalQueryResult['selection'], - jsonParseRelationalFields = false, mapColumnValue: (value: unknown) => unknown = (value) => value, ): Record { const result: Record = {}; @@ -502,10 +501,8 @@ export function mapRelationalRow( for (const [selectionItemIndex, selectionItem] of buildQueryResultSelection.entries()) { if (selectionItem.isJson) { const relation = tableConfig.relations[selectionItem.tsKey]!; - let subRows = row[selectionItemIndex] as unknown[][]; - if (jsonParseRelationalFields) { - subRows = JSON.parse(subRows as unknown as string); - } + const rawSubRows = row[selectionItemIndex] as unknown[][] | string; + const subRows = typeof rawSubRows === 'string' ? JSON.parse(rawSubRows) as unknown[][] : rawSubRows; if (relation instanceof One) { result[selectionItem.tsKey] = subRows[0] ? mapRelationalRow( @@ -513,6 +510,7 @@ export function mapRelationalRow( tablesConfig[selectionItem.tableTsKey!]!, subRows[0], selectionItem.selection, + mapColumnValue, ) : null; } else { @@ -522,6 +520,7 @@ export function mapRelationalRow( tablesConfig[selectionItem.tableTsKey!]!, subRow as unknown[], selectionItem.selection, + mapColumnValue, ) ); } diff --git a/drizzle-orm/src/sqlite-core/query-builders/query.ts b/drizzle-orm/src/sqlite-core/query-builders/query.ts index 72787c5c1..ec457d447 100644 --- a/drizzle-orm/src/sqlite-core/query-builders/query.ts +++ b/drizzle-orm/src/sqlite-core/query-builders/query.ts @@ -176,7 +176,7 @@ export class SQLiteRelationalQuery { const rows = rawRows.map((row) => - mapRelationalRow(this.schema, this.tableConfig, row, query.selection, true, mapColumnValue) + mapRelationalRow(this.schema, this.tableConfig, row, query.selection, mapColumnValue) ); if (this.mode === 'first') { return rows[0] as TResult; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 712bdf02b..b86a1076c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,8 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false patchedDependencies: typescript@5.0.3: @@ -143,10 +147,10 @@ importers: version: 3.12.7 vite-tsconfig-paths: specifier: ^4.2.0 - version: 4.2.0(typescript@5.0.3)(vite@4.3.9) + version: 4.2.0(typescript@5.0.3) vitest: specifier: ^0.31.1 - version: 0.31.1(@vitest/ui@0.31.1) + version: 0.31.1 zod: specifier: ^3.20.2 version: 3.21.4 @@ -1574,7 +1578,7 @@ packages: resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} dependencies: '@gar/promisify': 1.1.3 - semver: 7.3.8 + semver: 7.5.1 optional: true /@npmcli/move-file@1.1.2: @@ -4451,7 +4455,7 @@ packages: dependencies: foreground-child: 3.1.1 jackspeak: 2.1.0 - minimatch: 9.0.0 + minimatch: 9.0.1 minipass: 5.0.0 path-scurry: 1.7.0 dev: true @@ -5338,8 +5342,8 @@ packages: brace-expansion: 2.0.1 dev: true - /minimatch@9.0.0: - resolution: {integrity: sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==} + /minimatch@9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 @@ -6164,7 +6168,7 @@ packages: resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} engines: {node: '>= 10.13.0'} dependencies: - resolve: 1.22.1 + resolve: 1.22.2 dev: true /regexp-tree@0.1.25: @@ -7190,6 +7194,22 @@ packages: - supports-color - terser + /vite-tsconfig-paths@4.2.0(typescript@5.0.3): + resolution: {integrity: sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw==} + peerDependencies: + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + debug: 4.3.4 + globrex: 0.1.2 + tsconfck: 2.1.1(typescript@5.0.3) + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /vite-tsconfig-paths@4.2.0(typescript@5.0.3)(vite@4.3.9): resolution: {integrity: sha512-jGpus0eUy5qbbMVGiTxCL1iB9ZGN6Bd37VGLJU39kTDD6ZfULTTb1bcc5IeTWqWJKiWV5YihCaibeASPiGi8kw==} peerDependencies: @@ -7239,6 +7259,71 @@ packages: optionalDependencies: fsevents: 2.3.2 + /vitest@0.31.1: + resolution: {integrity: sha512-/dOoOgzoFk/5pTvg1E65WVaobknWREN15+HF+0ucudo3dDG/vCZoXTQrjIfEaWvQXmqScwkRodrTbM/ScMpRcQ==} + engines: {node: '>=v14.18.0'} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@vitest/browser': '*' + '@vitest/ui': '*' + happy-dom: '*' + jsdom: '*' + playwright: '*' + safaridriver: '*' + webdriverio: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true + dependencies: + '@types/chai': 4.3.5 + '@types/chai-subset': 1.3.3 + '@types/node': 20.2.5 + '@vitest/expect': 0.31.1 + '@vitest/runner': 0.31.1 + '@vitest/snapshot': 0.31.1 + '@vitest/spy': 0.31.1 + '@vitest/utils': 0.31.1 + acorn: 8.8.2 + acorn-walk: 8.2.0 + cac: 6.7.14 + chai: 4.3.7 + concordance: 5.0.4 + debug: 4.3.4 + local-pkg: 0.4.3 + magic-string: 0.30.0 + pathe: 1.1.0 + picocolors: 1.0.0 + std-env: 3.3.3 + strip-literal: 1.0.1 + tinybench: 2.5.0 + tinypool: 0.5.0 + vite: 4.3.9(@types/node@20.2.5) + vite-node: 0.31.1(@types/node@20.2.5) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vitest@0.31.1(@vitest/ui@0.31.1): resolution: {integrity: sha512-/dOoOgzoFk/5pTvg1E65WVaobknWREN15+HF+0ucudo3dDG/vCZoXTQrjIfEaWvQXmqScwkRodrTbM/ScMpRcQ==} engines: {node: '>=v14.18.0'}