Skip to content

Commit

Permalink
call the new type Json instead, to not introduce a breaking change.
Browse files Browse the repository at this point in the history
  • Loading branch information
igalklebanov committed Oct 3, 2024
1 parent 4883c88 commit 9b746b8
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 38 deletions.
12 changes: 5 additions & 7 deletions site/docs/getting-started/_types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
ColumnType,
Generated,
Insertable,
JSONColumnType,
Json,
Selectable,
Updateable,
} from 'kysely'
Expand Down Expand Up @@ -45,12 +45,10 @@ export interface PersonTable {
// can never be updated:
created_at: ColumnType<Date, string | undefined, never>

// You can specify JSON columns using the `JSONColumnType` wrapper.
// It is a shorthand for `ColumnType<T, string, string>`, where T
// is the type of the JSON object/array retrieved from the database,
// and the insert and update types are always `string` since you're
// always stringifying insert/update values.
metadata: JSONColumnType<{
// You can specify JSON columns using the `Json` wrapper.
// When inserting/updating values of such columns, you're required to wrap the
// values with `eb.valJson` or `sql.valJson`.
metadata: Json<{
login_at: string
ip: string | null
agent: string | null
Expand Down
10 changes: 5 additions & 5 deletions src/expression/expression-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,22 +516,22 @@ export interface ExpressionBuilder<DB, TB extends keyof DB> {
* Returns a value expression that will be serialized before being passed to the database.
*
* This can be used to pass in an object/array value when inserting/updating a
* value to a column defined with `JSONColumnType`.
* value to a column defined with `Json`.
*
* Default serializer function is `JSON.stringify`.
*
* ### Example
*
* ```ts
* import { GeneratedAlways, JSONColumnType } from 'kysely'
* import { GeneratedAlways, Json } from 'kysely'
*
* interface Database {
* person: {
* id: GeneratedAlways<number>
* name: string
* experience: JSONColumnType<{ title: string; company: string }[]>
* preferences: JSONColumnType<{ locale: string; timezone: string }>
* profile: JSONColumnType<{ email_verified: boolean }>
* experience: Json<{ title: string; company: string }[]>
* preferences: Json<{ locale: string; timezone: string }>
* profile: Json<{ email_verified: boolean }>
* }
* }
*
Expand Down
30 changes: 23 additions & 7 deletions src/util/column-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,18 @@ export type Generated<S> = ColumnType<S, S | undefined, S>
export type GeneratedAlways<S> = ColumnType<S, never, never>

/**
* A shortcut for defining type-safe JSON columns.
* A shortcut for defining type-safe JSON columns. Inserts/updates require passing
* values that are wrapped with `eb.valJson` or `sql.valJson` instead of `JSON.stringify`.
*/
export type JSONColumnType<SelectType extends object | null> = ColumnType<
SelectType,
Serialized<SelectType> | Extract<null, SelectType>,
Serialized<SelectType> | Extract<null, SelectType>
>
export type Json<
SelectType extends object | null,
InsertType extends Serialized<SelectType> | Extract<null, SelectType> =
| Serialized<SelectType>
| Extract<null, SelectType>,
UpdateType extends Serialized<SelectType> | Extract<null, SelectType> =
| Serialized<SelectType>
| Extract<null, SelectType>,
> = ColumnType<SelectType, InsertType, UpdateType>

/**
* A symbol that is used to brand serialized objects/arrays.
Expand All @@ -86,9 +91,20 @@ declare const SerializedBrand: unique symbol
* A type that is used to brand serialized objects/arrays.
*/
export type Serialized<O extends object | null> = O & {
[SerializedBrand]: '⚠️ When you insert into or update columns of type `JSONColumnType` (or similar), you should wrap your JSON value with `eb.valJson` or `sql.valJson`, instead of `JSON.stringify`. ⚠️'
readonly [SerializedBrand]: '⚠️ When you insert into or update columns of type `Json` (or similar), you should wrap your JSON value with `eb.valJson` or `sql.valJson`, instead of `JSON.stringify`. ⚠️'
}

/**
* A shortcut for defining JSON columns, which are by default inserted/updated
* as stringified JSON strings.
* @deprecated Use {@link Json} instead.
*/
export type JSONColumnType<
SelectType extends object | null,
InsertType = string,
UpdateType = string,
> = ColumnType<SelectType, InsertType, UpdateType>

/**
* Evaluates to `K` if `T` can be `null` or `undefined`.
*/
Expand Down
12 changes: 6 additions & 6 deletions test/node/src/json-traversal.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
ColumnDefinitionBuilder,
JSONColumnType,
Json,
ParseJSONResultsPlugin,
SqlBool,
sql,
Expand Down Expand Up @@ -732,9 +732,9 @@ async function initJSONTest<D extends BuiltInDialect>(
let db = testContext.db.withTables<{
person_metadata: {
person_id: number
website: JSONColumnType<{ url: string }>
nicknames: JSONColumnType<string[]>
profile: JSONColumnType<{
website: Json<{ url: string }>
nicknames: Json<string[]>
profile: Json<{
auth: {
roles: string[]
last_login?: { device: string }
Expand All @@ -744,12 +744,12 @@ async function initJSONTest<D extends BuiltInDialect>(
avatar: string | null
tags: string[]
}>
experience: JSONColumnType<
experience: Json<
{
establishment: string
}[]
>
schedule: JSONColumnType<{ name: string; time: string }[][][]>
schedule: Json<{ name: string; time: string }[][][]>
}
}>()

Expand Down
21 changes: 8 additions & 13 deletions test/typings/shared.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
ColumnType,
Generated,
GeneratedAlways,
JSONColumnType,
} from '../../dist/cjs'
import { ColumnType, Generated, GeneratedAlways, Json } from '../../dist/cjs'

export interface Pet {
id: Generated<string>
Expand Down Expand Up @@ -71,21 +66,21 @@ export interface Person {
export interface PersonMetadata {
id: Generated<number>
person_id: number
website: JSONColumnType<{ url: string }>
nicknames: JSONColumnType<string[]>
profile: JSONColumnType<{
website: Json<{ url: string }>
nicknames: Json<string[]>
profile: Json<{
auth: {
roles: string[]
last_login?: { device: string }
}
tags: string[]
}>
experience: JSONColumnType<
experience: Json<
{
establishment: string
}[]
>
schedule: JSONColumnType<{ name: string; time: string }[][][]>
record: JSONColumnType<Record<string, string>>
array: JSONColumnType<Array<string> | null>
schedule: Json<{ name: string; time: string }[][][]>
record: Json<Record<string, string>>
array: Json<Array<string> | null>
}

0 comments on commit 9b746b8

Please sign in to comment.