Skip to content

Commit

Permalink
sqlite column to code converter
Browse files Browse the repository at this point in the history
  • Loading branch information
r1tsuu committed Dec 15, 2024
1 parent e79be1e commit 025e3ff
Show file tree
Hide file tree
Showing 10 changed files with 922 additions and 847 deletions.
6 changes: 6 additions & 0 deletions packages/db-postgres/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
updateVersion,
} from '@payloadcms/drizzle'
import {
columnToCodeConverter,
countDistinct,
createDatabase,
createExtensions,
Expand Down Expand Up @@ -108,7 +109,12 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>
},
fieldConstraints: {},
generateSchema: createSchemaGenerator({
columnToCodeConverter,
corePackageSuffix: 'pg-core',
defaultOutputFile: args.generateSchemaOutputFile,
enumImport: 'pgEnum',
schemaImport: 'pgSchema',
tableImport: 'pgTable',
}),
idType: postgresIDType,
initializing,
Expand Down
114 changes: 114 additions & 0 deletions packages/db-sqlite/src/columnToCodeConverter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import type { ColumnToCodeConverter } from '@payloadcms/drizzle/types'

export const columnToCodeConverter: ColumnToCodeConverter = ({
adapter,
addImport,
column,
locales,
}) => {
let columnBuilderFn: string = column.type

const columnBuilderArgsArray: string[] = []

let defaultStatement: null | string = null

switch (column.type) {
case 'boolean': {
columnBuilderFn = 'integer'
columnBuilderArgsArray.push("mode: 'boolean'")
break
}

case 'enum': {
let options: string[]
if ('isLocale' in column) {
options = locales
} else {
options = column.options
}

columnBuilderFn = 'text'
columnBuilderArgsArray.push(`enum: [${options.map((locale) => `'${locale}'`).join(', ')}]`)

break
}

case 'geometry':
case 'jsonb': {
columnBuilderFn = 'text'
columnBuilderArgsArray.push("mode: 'json'")
break
}

case 'serial': {
columnBuilderFn = 'integer'
break
}

case 'timestamp': {
columnBuilderFn = 'text'
defaultStatement = `default(sql\`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))\`)`
break
}

case 'uuid': {
columnBuilderFn = 'text'

if (column.defaultRandom) {
addImport('crypto', 'randomUUID')
defaultStatement = `defaultFn(() => randomUUID())`
}

break
}

case 'varchar': {
columnBuilderFn = 'text'
break
}

default: {
columnBuilderFn = column.type
}
}

addImport(`${adapter.packageName}/drizzle/sqlite-core`, columnBuilderFn)

let columnBuilderArgs = ''

if (columnBuilderArgsArray.length) {
columnBuilderArgs = `, {${columnBuilderArgsArray.join(',')}}`
}

let code = `${columnBuilderFn}('${column.name}'${columnBuilderArgs})`

if (column.notNull) {
code = `${code}.notNull()`
}

if (column.primaryKey) {
code = `${code}.primaryKey()`
}

if (defaultStatement) {
code = `${code}.${defaultStatement}`
} else if (typeof column.default !== 'undefined') {
let sanitizedDefault = column.default

if (column.type === 'jsonb' || column.type === 'geometry') {
sanitizedDefault = `'${JSON.stringify(column.default)}'`
} else if (typeof column.default === 'string' || column.type === 'numeric') {
sanitizedDefault = `'${column.default}'`
}

code = `${code}.default(${sanitizedDefault})`
}

if (column.reference) {
code = `${code}.references(() => ${column.reference.table}.${column.reference.name}, {
${column.reference.onDelete ? `onDelete: '${column.reference.onDelete}'` : ''}
})`
}

return code
}
4 changes: 4 additions & 0 deletions packages/db-sqlite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { fileURLToPath } from 'url'

import type { Args, SQLiteAdapter } from './types.js'

import { columnToCodeConverter } from './columnToCodeConverter.js'
import { connect } from './connect.js'
import { countDistinct } from './countDistinct.js'
import { convertPathToJSONTraversal } from './createJSONQuery/convertPathToJSONTraversal.js'
Expand Down Expand Up @@ -95,7 +96,10 @@ export function sqliteAdapter(args: Args): DatabaseAdapterObj<SQLiteAdapter> {
},
fieldConstraints: {},
generateSchema: createSchemaGenerator({
columnToCodeConverter,
corePackageSuffix: 'sqlite-core',
defaultOutputFile: args.generateSchemaOutputFile,
tableImport: 'sqliteTable',
}),
idType: postgresIDType,
initializing,
Expand Down
6 changes: 6 additions & 0 deletions packages/db-vercel-postgres/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
updateVersion,
} from '@payloadcms/drizzle'
import {
columnToCodeConverter,
countDistinct,
createDatabase,
createExtensions,
Expand Down Expand Up @@ -101,7 +102,12 @@ export function vercelPostgresAdapter(args: Args = {}): DatabaseAdapterObj<Verce
},
fieldConstraints: {},
generateSchema: createSchemaGenerator({
columnToCodeConverter,
corePackageSuffix: 'pg-core',
defaultOutputFile: args.generateSchemaOutputFile,
enumImport: 'pgEnum',
schemaImport: 'pgSchema',
tableImport: 'pgTable',
}),
idType: postgresIDType,
indexes: new Set<string>(),
Expand Down
1 change: 1 addition & 0 deletions packages/drizzle/src/exports/postgres.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { columnToCodeConverter } from '../postgres/columnToCodeConverter.js'
export { countDistinct } from '../postgres/countDistinct.js'
export { createDatabase } from '../postgres/createDatabase.js'
export { createExtensions } from '../postgres/createExtensions.js'
Expand Down
85 changes: 85 additions & 0 deletions packages/drizzle/src/postgres/columnToCodeConverter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import type { ColumnToCodeConverter } from '../types.js'

export const columnToCodeConverter: ColumnToCodeConverter = ({
adapter,
addEnum,
addImport,
column,
}) => {
let columnBuilderFn: string = column.type

if (column.type === 'geometry') {
columnBuilderFn = 'geometryColumn'
addImport(`@payloadcms/drizzle/postgres`, columnBuilderFn)
} else if (column.type === 'enum') {
if ('isLocale' in column) {
columnBuilderFn = `enum__locales`
} else {
addEnum(column.enumName, column.options)
columnBuilderFn = column.enumName
}
} else {
addImport(`${adapter.packageName}/drizzle/pg-core`, columnBuilderFn)
}

const columnBuilderArgsArray: string[] = []

if (column.type === 'timestamp') {
columnBuilderArgsArray.push(`mode: '${column.mode}'`)
if (column.withTimezone) {
columnBuilderArgsArray.push('withTimezone: true')
}

if (typeof column.precision === 'number') {
columnBuilderArgsArray.push(`precision: ${column.precision}`)
}
}

let columnBuilderArgs = ''

if (columnBuilderArgsArray.length) {
columnBuilderArgs = `, {${columnBuilderArgsArray.join(',')}}`
}

let code = `${columnBuilderFn}('${column.name}'${columnBuilderArgs})`

if (column.type === 'timestamp' && column.defaultNow) {
code = `${code}.defaultNow()`
}

if (column.type === 'uuid' && column.defaultRandom) {
code = `${code}.defaultRandom()`
}

if (column.notNull) {
code = `${code}.notNull()`
}

if (column.primaryKey) {
code = `${code}.primaryKey()`
}

if (typeof column.default !== 'undefined') {
let sanitizedDefault = column.default

if (column.type === 'geometry') {
sanitizedDefault = `sql\`${column.default}\``
} else if (column.type === 'jsonb') {
sanitizedDefault = `sql\`'${JSON.stringify(column.default)}'::jsonb\``
} else if (column.type === 'numeric') {
sanitizedDefault = `sql\`${column.default}\``
} else if (typeof column.default === 'string') {
sanitizedDefault = `'${column.default}'`
}

code = `${code}.default(${sanitizedDefault})`
}

if (column.reference) {
code = `${code}.references(() => ${column.reference.table}.${column.reference.name}, {
${column.reference.onDelete ? `onDelete: '${column.reference.onDelete}'` : ''}
})`
}

return code
}
8 changes: 8 additions & 0 deletions packages/drizzle/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ export type SetColumnID = (args: {
fields: FlattenedField[]
}) => IDType

export type ColumnToCodeConverter = (args: {
adapter: DrizzleAdapter
addEnum: (name: string, options: string[]) => void
addImport: (from: string, name: string) => void
column: RawColumn
locales?: string[]
}) => string

export type BuildDrizzleTable<T extends DrizzleAdapter = DrizzleAdapter> = (args: {
adapter: T
locales: string[]
Expand Down
Loading

0 comments on commit 025e3ff

Please sign in to comment.