콘텐츠로 이동

Kysely and StudioCMS SDK

이 콘텐츠는 아직 번역되지 않았습니다.

The following packages are built-in to StudioCMS and provide the core database functionality used by StudioCMS. They are intended to be used internally by StudioCMS, but users can also use them directly in their projects for more advanced use cases.

Kysely^ is a type-safe SQL query builder for TypeScript. It provides a powerful and flexible way to interact with databases while ensuring type safety and reducing runtime errors. Kysely supports various SQL databases, including PostgreSQL, MySQL, SQLite, and more. It allows developers to construct SQL queries using a fluent API, making it easier to read and maintain database interactions in TypeScript applications.

Currently StudioCMS only supports libSQL(SQLite), MySQL, and PostgreSQL databases via Kysely. In the future, support for other database dialects can be added as needed or requested.

Want to have another database dialect supported? Check out the Kysely Dialects documentation^ and open an issue on the StudioCMS GitHub repository^.


@withstudiocms/kysely

A type-safe database client and migration system for StudioCMS, built on top of Kysely^. Provides a unified interface for working with libSQL, MySQL, and PostgreSQL databases with runtime schema management and migrations.

  • Type-Safe Database Operations - Full TypeScript support with Kysely’s type-safe query builder
  • Multi-Database Support - Works with libSQL (SQLite), MySQL, and PostgreSQL
  • Runtime Schema Management - Dynamic schema creation and validation
  • Error Handling - Custom error types for better debugging
  • TypeScript-Based Migrations - File-based migrations with automatic tracking
  • Schema Introspection - Inspect and validate database schemas at runtime
  • Effect-ts Integration - Functional programming patterns with Effect-ts
client-setup.ts
import {
const getDBClientLive: <Schema>(dialect: Dialect) => KyselyDBClientLive<Schema>

Factory that creates a live database client configured for the specified SQL dialect.

This exported helper forwards the provided dialect to an underlying makeDBClientLive implementation and returns the resulting database client instance typed to the supplied schema generic.

@paramdialect - The SQL dialect or driver configuration used to instantiate the client (e.g., PostgreSQL, MySQL, SQLite, etc.).

@returnsA fully configured, live database client instance typed to Schema.

@example // Create a client for the Chosen dialect: // const db = getDBClientLive(yourDriver);

getDBClientLive
, type
type StudioCMSDatabaseSchema = {
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}
const StudioCMSDatabaseSchema: Struct<{
StudioCMSUsersTable: Table<{
id: typeof String$;
url: NullishOr<typeof String$>;
name: typeof String$;
email: NullishOr<typeof String$>;
avatar: NullishOr<typeof String$>;
username: typeof String$;
password: NullishOr<typeof String$>;
updatedAt: Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof DateFromString, typeof String$, typeof String$>;
createdAt: Schema<ColumnType<Date, string | undefined, never>, ColumnType<string, string | undefined, never>, never> & ColumnTypes<...>;
emailVerified: transform<typeof Number$, typeof Boolean$>;
notifications: NullishOr<typeof String$>;
}>;
... 13 more ...;
StudioCMSDynamicConfigSettings: Table<{
id: typeof String$;
data: Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
}>;
}>

Complete StudioCMS Database Schema Definition

Type representing the StudioCMS Database Schema.

StudioCMSDatabaseSchema
} from '@withstudiocms/kysely';
import {
const libsqlDriver: Effect.Effect<LibsqlDialect, ConfigError, never>

Effect that builds and returns a LibsqlDialect configured from environment-backed configuration.

This generator reads the following configuration keys:

  • STUDIOCMS_LIBSQL_URL (required, redacted) — connection URL for the libsql instance.
  • STUDIOCMS_LIBSQL_AUTH_TOKEN (required, redacted) — authentication token for the libsql instance.
  • STUDIOCMS_LIBSQL_SYNC_INTERVAL (optional) — synchronization interval in milliseconds. If not set, no interval is configured.
  • STUDIOCMS_LIBSQL_SYNC_URL (optional, redacted) — optional sync URL. If not set, no sync URL is configured.

Secrets (URL, auth token, sync URL) are obtained via the redacted config helpers and passed to the dialect via Redacted.value to preserve redaction semantics.

The returned Effect yields a fully constructed LibsqlDialect instance:

  • url: string (from STUDIOCMS_LIBSQL_URL)
  • authToken: string (from STUDIOCMS_LIBSQL_AUTH_TOKEN)
  • syncInterval?: number (from STUDIOCMS_LIBSQL_SYNC_INTERVAL, or undefined)
  • syncUrl?: string (from STUDIOCMS_LIBSQL_SYNC_URL, or undefined)

@returnsAn Effect that, when executed, produces a configured LibsqlDialect instance.

@example // inside an Effect context: // const dialect = yield* libsqlDriver();

libsqlDriver
} from '@withstudiocms/kysely/drivers/libsql';
import {
import ConfigProvider
ConfigProvider
,
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
} from 'studiocms/effect';
export const
const getDbClient: Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, ConfigError, never>
getDbClient
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<LibsqlDialect, ConfigError, never>> | YieldWrap<Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, never, never>>, DBClientInterface<...>>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
// Setup the LibSQL driver with a database URL from config
const
const dialect: LibsqlDialect
dialect
= yield*
const libsqlDriver: Effect.Effect<LibsqlDialect, ConfigError, never>

Effect that builds and returns a LibsqlDialect configured from environment-backed configuration.

This generator reads the following configuration keys:

  • STUDIOCMS_LIBSQL_URL (required, redacted) — connection URL for the libsql instance.
  • STUDIOCMS_LIBSQL_AUTH_TOKEN (required, redacted) — authentication token for the libsql instance.
  • STUDIOCMS_LIBSQL_SYNC_INTERVAL (optional) — synchronization interval in milliseconds. If not set, no interval is configured.
  • STUDIOCMS_LIBSQL_SYNC_URL (optional, redacted) — optional sync URL. If not set, no sync URL is configured.

Secrets (URL, auth token, sync URL) are obtained via the redacted config helpers and passed to the dialect via Redacted.value to preserve redaction semantics.

The returned Effect yields a fully constructed LibsqlDialect instance:

  • url: string (from STUDIOCMS_LIBSQL_URL)
  • authToken: string (from STUDIOCMS_LIBSQL_AUTH_TOKEN)
  • syncInterval?: number (from STUDIOCMS_LIBSQL_SYNC_INTERVAL, or undefined)
  • syncUrl?: string (from STUDIOCMS_LIBSQL_SYNC_URL, or undefined)

@returnsAn Effect that, when executed, produces a configured LibsqlDialect instance.

@example // inside an Effect context: // const dialect = yield* libsqlDriver();

libsqlDriver
.
Pipeable.pipe<Effect.Effect<LibsqlDialect, ConfigError, never>, Effect.Effect<LibsqlDialect, ConfigError, never>>(this: Effect.Effect<LibsqlDialect, ConfigError, never>, ab: (_: Effect.Effect<LibsqlDialect, ConfigError, never>) => Effect.Effect<LibsqlDialect, ConfigError, never>): Effect.Effect<LibsqlDialect, ConfigError, never> (+21 overloads)
pipe
(
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const withConfigProvider: (provider: ConfigProvider.ConfigProvider) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R> (+1 overload)

Executes an effect using a specific configuration provider.

Details

This function lets you run an effect with a specified configuration provider. The custom provider will override the default configuration provider for the duration of the effect's execution.

When to Use

This is particularly useful when you need to use a different set of configuration values or sources for specific parts of your application.

Example

import { Config, ConfigProvider, Effect } from "effect"
const customProvider: ConfigProvider.ConfigProvider = ConfigProvider.fromMap(
new Map([["custom-key", "custom-value"]])
)
const program = Effect.withConfigProvider(customProvider)(
Effect.gen(function*() {
const value = yield* Config.string("custom-key")
console.log(`Config value: ${value}`)
})
)
Effect.runPromise(program)
// Output:
// Config value: custom-value

@since2.0.0

withConfigProvider
(
import ConfigProvider
ConfigProvider
.
const fromJson: (json: unknown) => ConfigProvider.ConfigProvider

Constructs a new ConfigProvider from a JSON object.

@since2.0.0

fromJson
({
type CMS_LIBSQL_URL: string
CMS_LIBSQL_URL
: 'file:./test.db',
})
)
);
// Return the Kysely DB client with Effect helpers
return yield*
getDBClientLive<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>(dialect: Dialect): KyselyDBClientLive<...>

Factory that creates a live database client configured for the specified SQL dialect.

This exported helper forwards the provided dialect to an underlying makeDBClientLive implementation and returns the resulting database client instance typed to the supplied schema generic.

@paramdialect - The SQL dialect or driver configuration used to instantiate the client (e.g., PostgreSQL, MySQL, SQLite, etc.).

@returnsA fully configured, live database client instance typed to Schema.

@example // Create a client for the Chosen dialect: // const db = getDBClientLive(yourDriver);

getDBClientLive
<
type StudioCMSDatabaseSchema = {
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}

Complete StudioCMS Database Schema Definition

Type representing the StudioCMS Database Schema.

StudioCMSDatabaseSchema
>(
const dialect: LibsqlDialect
dialect
);
});
get-users.ts
import {
import Schema
Schema
} from 'studiocms/effect';
import {
const StudioCMSUsersTable: Table<{
id: typeof Schema.String;
url: Schema.NullishOr<typeof Schema.String>;
name: typeof Schema.String;
email: Schema.NullishOr<typeof Schema.String>;
avatar: Schema.NullishOr<typeof Schema.String>;
username: typeof Schema.String;
password: Schema.NullishOr<typeof Schema.String>;
updatedAt: Schema.Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof Schema.DateFromString, typeof Schema.String, typeof Schema.String>;
createdAt: Schema.Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
emailVerified: Schema.transform<typeof Schema.Number, typeof Schema.Boolean>;
notifications: Schema.NullishOr<typeof Schema.String>;
}>

StudioCMS Users Table Definition

StudioCMSUsersTable
} from '@withstudiocms/kysely';
export const
const getUsers: Effect.Effect<void, ConfigError | DBCallbackFailure | DatabaseError, never>
getUsers
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, ConfigError, never>> | YieldWrap<...>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const {
const withDecoder: <OEncoded, OType>({ decoder, callbackFn, }: {
decoder: Schema.Schema<OType, OEncoded, never>;
callbackFn: DBCallbackFn<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, undefined, OEncoded>;
}) => () => Effect.Effect<...>

Creates a function that decodes output data after executing a database operation.

withDecoder
} = yield*
const getDbClient: Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, ConfigError, never>
getDbClient
;
const
const getUsers: () => Effect.Effect<readonly {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}[], DBCallbackFailure | DatabaseError, never>
getUsers
=
const withDecoder: <readonly {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: string;
readonly createdAt: string;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
}[], readonly {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}[]>({ decoder, callbackFn, }: {
...;
}) => () => Effect.Effect<...>

Creates a function that decodes output data after executing a database operation.

withDecoder
({
decoder: Schema.Schema<readonly {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}[], readonly {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}[], never>
decoder
:
import Schema
Schema
.
Array<Schema.Struct<{
readonly id: Schema.Schema<string, string, never>;
readonly url: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly name: Schema.Schema<string, string, never>;
readonly email: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly avatar: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly username: Schema.Schema<string, string, never>;
readonly password: Schema.Schema<string | null | undefined, string | ... 1 more ... | undefined, never>;
readonly updatedAt: Schema.Schema<...>;
readonly createdAt: Schema.Schema<...>;
readonly emailVerified: Schema.Schema<...>;
readonly notifications: Schema.Schema<...>;
}>>(value: Schema.Struct<...>): Schema.Array$<...>
export Array

@since3.10.0

Array
(
const StudioCMSUsersTable: Table<{
id: typeof Schema.String;
url: Schema.NullishOr<typeof Schema.String>;
name: typeof Schema.String;
email: Schema.NullishOr<typeof Schema.String>;
avatar: Schema.NullishOr<typeof Schema.String>;
username: typeof Schema.String;
password: Schema.NullishOr<typeof Schema.String>;
updatedAt: Schema.Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof Schema.DateFromString, typeof Schema.String, typeof Schema.String>;
createdAt: Schema.Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
emailVerified: Schema.transform<typeof Schema.Number, typeof Schema.Boolean>;
notifications: Schema.NullishOr<typeof Schema.String>;
}>

StudioCMS Users Table Definition

StudioCMSUsersTable
.
type Select: Schema.Struct<{
readonly id: Schema.Schema<string, string, never>;
readonly url: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly name: Schema.Schema<string, string, never>;
readonly email: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly avatar: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly username: Schema.Schema<string, string, never>;
readonly password: Schema.Schema<string | null | undefined, string | ... 1 more ... | undefined, never>;
readonly updatedAt: Schema.Schema<...>;
readonly createdAt: Schema.Schema<...>;
readonly emailVerified: Schema.Schema<...>;
readonly notifications: Schema.Schema<...>;
}>

  • A mapping of column names to the types returned by SELECT queries. Typically these types represent the actual stored or computed values.

Select
),
callbackFn: DBCallbackFn<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, undefined, readonly {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}[]>
callbackFn
: (
db: DBCallback<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
db
) =>
db: <{
id: string;
url: string | null | undefined;
name: string;
email: string | null | undefined;
avatar: string | null | undefined;
username: string;
password: string | null | undefined;
updatedAt: string;
createdAt: string;
emailVerified: number;
notifications: string | null | undefined;
}[]>(fn: (db: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>) => Promise<...>) => Effect.Effect<out A, out E = never, out R = never>.AsEffect<...>
db
((
client: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
client
) =>
client: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
client
.
QueryCreator<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }>.selectFrom<"StudioCMSUsersTable">(from: "StudioCMSUsersTable"): SelectQueryBuilder<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable", {}>

Creates a select query builder for the given table or tables.

The tables passed to this method are built as the query's from clause.

Examples

Create a select query for one table:

db.selectFrom('person').selectAll()

The generated SQL (PostgreSQL):

select * from "person"

Create a select query for one table with an alias:

const persons = await db.selectFrom('person as p')
.select(['p.id', 'first_name'])
.execute()
console.log(persons[0].id)

The generated SQL (PostgreSQL):

select "p"."id", "first_name" from "person" as "p"

Create a select query from a subquery:

const persons = await db.selectFrom(
(eb) => eb.selectFrom('person').select('person.id as identifier').as('p')
)
.select('p.identifier')
.execute()
console.log(persons[0].identifier)

The generated SQL (PostgreSQL):

select "p"."identifier",
from (
select "person"."id" as "identifier" from "person"
) as p

Create a select query from raw sql:

importsql } from 'kysely'
const items = await db
.selectFrom(sql<{ one: number }>`(select 1 as one)`.as('q'))
.select('q.one')
.execute()
console.log(items[0].one)

The generated SQL (PostgreSQL):

select "q"."one",
from (
select 1 as one
) as q

When you use the sql tag you need to also provide the result type of the raw snippet / query so that Kysely can figure out what columns are available for the rest of the query.

The selectFrom method also accepts an array for multiple tables. All the above examples can also be used in an array.

importsql } from 'kysely'
const items = await db.selectFrom([
'person as p',
db.selectFrom('pet').select('pet.species').as('a'),
sql<{ one: number }>`(select 1 as one)`.as('q')
])
.select(['p.id', 'a.species', 'q.one'])
.execute()

The generated SQL (PostgreSQL):

select "p".id, "a"."species", "q"."one"
from
"person" as "p",
(select "pet"."species" from "pet") as a,
(select 1 as one) as "q"

selectFrom
('StudioCMSUsersTable').
SelectQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", {}>.selectAll(): SelectQueryBuilder<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable", {
...;
}> (+2 overloads)

Adds a select * or select table.* clause to the query.

Examples

The selectAll method generates SELECT *:

const persons = await db
.selectFrom('person')
.selectAll()
.execute()

The generated SQL (PostgreSQL):

select * from "person"

Select all columns of a table:

const persons = await db
.selectFrom('person')
.selectAll('person')
.execute()

The generated SQL (PostgreSQL):

select "person".* from "person"

Select all columns of multiple tables:

const personsPets = await db
.selectFrom(['person', 'pet'])
.selectAll(['person', 'pet'])
.execute()

The generated SQL (PostgreSQL):

select "person".*, "pet".* from "person", "pet"

selectAll
().
SelectQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", { ...; }>.execute(): Promise<{
id: string;
url: string | null | undefined;
name: string;
email: string | null | undefined;
avatar: string | null | undefined;
username: string;
password: string | null | undefined;
updatedAt: string;
createdAt: string;
emailVerified: number;
notifications: string | null | undefined;
}[]>

Executes the query and returns an array of rows.

Also see the

executeTakeFirst

and

executeTakeFirstOrThrow

methods.

execute
()),
});
const
const users: readonly {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}[]
users
= yield*
const getUsers: () => Effect.Effect<readonly {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}[], DBCallbackFailure | DatabaseError, never>
getUsers
();
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
('Users:',
const users: readonly {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}[]
users
);
/*
type of 'users' is:
const users: readonly {
readonly url: string | null | undefined;
readonly id: string;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}[]
*/
});
insert-user.ts
import {
import Schema
Schema
} from 'studiocms/effect';
import {
const StudioCMSUsersTable: Table<{
id: typeof Schema.String;
url: Schema.NullishOr<typeof Schema.String>;
name: typeof Schema.String;
email: Schema.NullishOr<typeof Schema.String>;
avatar: Schema.NullishOr<typeof Schema.String>;
username: typeof Schema.String;
password: Schema.NullishOr<typeof Schema.String>;
updatedAt: Schema.Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof Schema.DateFromString, typeof Schema.String, typeof Schema.String>;
createdAt: Schema.Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
emailVerified: Schema.transform<typeof Schema.Number, typeof Schema.Boolean>;
notifications: Schema.NullishOr<typeof Schema.String>;
}>

StudioCMS Users Table Definition

StudioCMSUsersTable
} from '@withstudiocms/kysely';
export const
const insertUser: Effect.Effect<void, ConfigError | DBCallbackFailure | DatabaseError, never>
insertUser
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, ConfigError, never>> | YieldWrap<...>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const {
const withEncoder: <IEncoded, IType, O, CIType = OmitNever<{ [K in keyof IType as HasNullOrUndefined<IType[K]> extends true ? K : never]?: IType[K] extends object ? IType[K] extends any[] ? IType[K] : OmitNever<{ [K in keyof IType[K] as HasNullOrUndefined<IType[K][K]> extends true ? K : never]?: IType[K][K] extends object ? IType[K][K] extends any[] ? IType[K][K] : OmitNever<{ [K in keyof IType[K][K] as HasNullOrUndefined<IType[K][K][K]> extends true ? K : never]?: IType[K][K][K] extends object ? IType[K][K][K] extends any[] ? IType[K][K][K] : OmitNever<...> : IType[K][K][K]; } & { [K in keyof IType[K][K] as HasNullOrUndefined<...> extends true ? never : K]: IType[K][K][K] extends object ? IType[K][K][K] extends any[] ? IType[K][K][K] : OmitNever<...> : IType[K][K][K]; }> : IType[K][K]; } & { [K in keyof IType[K] as HasNullOrUndefined<...> extends true ? never : K]: IType[K][K] extends object ? IType[K][K] extends any[] ? IType[K][K] : OmitNever<...> : IType[K][K]; }> : IType[K]; } & { [K in keyof IType as HasNullOrUndefined<...> extends true ? never : K]: IType[K] extends object ? IType[K] extends any[] ? IType[K] : OmitNever<...> : IType[K]; }>>({ callbackFn, encoder, }: {
...;
}) => (input: CIType) => Effect.Effect<...>

Creates a function that encodes input data before executing a database operation.

withEncoder
} = yield*
const getDbClient: Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, ConfigError, never>
getDbClient
;
const
const insertUser: (input: OmitNever<{
readonly url?: string | null | undefined;
readonly email?: string | null | undefined;
readonly avatar?: string | null | undefined;
readonly password?: string | null | undefined;
readonly createdAt?: string | undefined;
readonly notifications?: string | null | undefined;
} & {
readonly id: string;
readonly name: string;
readonly username: string;
readonly updatedAt: string;
readonly emailVerified: boolean;
}>) => Effect.Effect<InsertResult, DBCallbackFailure | DatabaseError, never>
insertUser
=
const withEncoder: <{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: string;
readonly createdAt: string | undefined;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
}, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}, InsertResult, OmitNever<...>>({ callbackFn, encoder, }: {
...;
}) => (input: OmitNever<...>) => Effect.Effect<...>

Creates a function that encodes input data before executing a database operation.

withEncoder
({
encoder: Schema.Schema<{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: string;
readonly createdAt: string | undefined;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}, never>
encoder
:
const StudioCMSUsersTable: Table<{
id: typeof Schema.String;
url: Schema.NullishOr<typeof Schema.String>;
name: typeof Schema.String;
email: Schema.NullishOr<typeof Schema.String>;
avatar: Schema.NullishOr<typeof Schema.String>;
username: typeof Schema.String;
password: Schema.NullishOr<typeof Schema.String>;
updatedAt: Schema.Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof Schema.DateFromString, typeof Schema.String, typeof Schema.String>;
createdAt: Schema.Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
emailVerified: Schema.transform<typeof Schema.Number, typeof Schema.Boolean>;
notifications: Schema.NullishOr<typeof Schema.String>;
}>

StudioCMS Users Table Definition

StudioCMSUsersTable
.
type Insert: Schema.Struct<{
readonly id: Schema.Schema<string, string, never>;
readonly url: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly name: Schema.Schema<string, string, never>;
readonly email: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly avatar: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly username: Schema.Schema<string, string, never>;
readonly password: Schema.Schema<string | null | undefined, string | ... 1 more ... | undefined, never>;
readonly updatedAt: Schema.Schema<...>;
readonly createdAt: Schema.Schema<...>;
readonly emailVerified: Schema.Schema<...>;
readonly notifications: Schema.Schema<...>;
}>

  • A mapping of column names to the types accepted by INSERT operations. Insert types may allow undefined/optional values for columns with defaults or auto-generated values.

Insert
,
callbackFn: DBCallbackFn<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}, InsertResult>
callbackFn
: (
db: DBCallback<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
db
,
newUser: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}
newUser
) =>
db: <InsertResult>(fn: (db: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>) => Promise<...>) => Effect.Effect<out A, out E = never, out R = never>.AsEffect<...>
db
((
client: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
client
) =>
client: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
client
.
QueryCreator<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }>.insertInto<"StudioCMSUsersTable">(table: "StudioCMSUsersTable"): InsertQueryBuilder<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable", InsertResult>

Creates an insert query.

The return value of this query is an instance of

InsertResult

.

InsertResult

has the

InsertResult.insertId insertId

field that holds the auto incremented id of the inserted row if the db returned one.

See the

InsertQueryBuilder.values values

method for more info and examples. Also see the

ReturningInterface.returning returning

method for a way to return columns on supported databases like PostgreSQL.

Examples

const result = await db
.insertInto('person')
.values({
first_name: 'Jennifer',
last_name: 'Aniston'
})
.executeTakeFirst()
console.log(result.insertId)

Some databases like PostgreSQL support the returning method:

const { id } = await db
.insertInto('person')
.values({
first_name: 'Jennifer',
last_name: 'Aniston'
})
.returning('id')
.executeTakeFirstOrThrow()

insertInto
('StudioCMSUsersTable').
InsertQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", InsertResult>.values(insert: InsertExpression<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable">): InsertQueryBuilder<...>

Sets the values to insert for an

Kysely.insertInto insert

query.

This method takes an object whose keys are column names and values are values to insert. In addition to the column's type, the values can be raw

sql

snippets or select queries.

You must provide all fields you haven't explicitly marked as nullable or optional using

Generated

or

ColumnType

.

The return value of an insert query is an instance of

InsertResult

. The

InsertResult.insertId insertId

field holds the auto incremented primary key if the database returned one.

On PostgreSQL and some other dialects, you need to call returning to get something out of the query.

Also see the

expression

method for inserting the result of a select query or any other expression.

Examples

Insert a single row:

const result = await db
.insertInto('person')
.values({
first_name: 'Jennifer',
last_name: 'Aniston',
age: 40
})
.executeTakeFirst()
// `insertId` is only available on dialects that
// automatically return the id of the inserted row
// such as MySQL and SQLite. On PostgreSQL, for example,
// you need to add a `returning` clause to the query to
// get anything out. See the "returning data" example.
console.log(result.insertId)

The generated SQL (MySQL):

insert into `person` (`first_name`, `last_name`, `age`) values (?, ?, ?)

On dialects that support it (for example PostgreSQL) you can insert multiple rows by providing an array. Note that the return value is once again very dialect-specific. Some databases may only return the id of the last inserted row and some return nothing at all unless you call returning.

await db
.insertInto('person')
.values([{
first_name: 'Jennifer',
last_name: 'Aniston',
age: 40,
}, {
first_name: 'Arnold',
last_name: 'Schwarzenegger',
age: 70,
}])
.execute()

The generated SQL (PostgreSQL):

insert into "person" ("first_name", "last_name", "age") values (($1, $2, $3), ($4, $5, $6))

On supported dialects like PostgreSQL you need to chain returning to the query to get the inserted row's columns (or any other expression) as the return value. returning works just like select. Refer to select method's examples and documentation for more info.

const result = await db
.insertInto('person')
.values({
first_name: 'Jennifer',
last_name: 'Aniston',
age: 40,
})
.returning(['id', 'first_name as name'])
.executeTakeFirstOrThrow()

The generated SQL (PostgreSQL):

insert into "person" ("first_name", "last_name", "age") values ($1, $2, $3) returning "id", "first_name" as "name"

In addition to primitives, the values can also be arbitrary expressions. You can build the expressions by using a callback and calling the methods on the expression builder passed to it:

import { sql } from 'kysely'
const ani = "Ani"
const ston = "ston"
const result = await db
.insertInto('person')
.values(({ ref, selectFrom, fn }) => ({
first_name: 'Jennifer',
last_name: sql<string>`concat(${ani}, ${ston})`,
middle_name: ref('first_name'),
age: selectFrom('person')
.select(fn.avg<number>('age').as('avg_age')),
}))
.executeTakeFirst()

The generated SQL (PostgreSQL):

insert into "person" (
"first_name",
"last_name",
"middle_name",
"age"
)
values (
$1,
concat($2, $3),
"first_name",
(select avg("age") as "avg_age" from "person")
)

You can also use the callback version of subqueries or raw expressions:

await db.with('jennifer', (db) => db
.selectFrom('person')
.where('first_name', '=', 'Jennifer')
.select(['id', 'first_name', 'gender'])
.limit(1)
).insertInto('pet').values((eb) => ({
owner_id: eb.selectFrom('jennifer').select('id'),
name: eb.selectFrom('jennifer').select('first_name'),
species: 'cat',
}))
.execute()

The generated SQL (PostgreSQL):

with "jennifer" as (
select "id", "first_name", "gender"
from "person"
where "first_name" = $1
limit $2
)
insert into "pet" ("owner_id", "name", "species")
values (
(select "id" from "jennifer"),
(select "first_name" from "jennifer"),
$3
)

values
(
newUser: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}
newUser
).
InsertQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", InsertResult>.executeTakeFirst(): Promise<InsertResult>

Executes the query and returns the first result or undefined if the query returned no result.

executeTakeFirst
()),
});
const
const newUser: InsertResult
newUser
= yield*
const insertUser: (input: OmitNever<{
readonly url?: string | null | undefined;
readonly email?: string | null | undefined;
readonly avatar?: string | null | undefined;
readonly password?: string | null | undefined;
readonly createdAt?: string | undefined;
readonly notifications?: string | null | undefined;
} & {
readonly id: string;
readonly name: string;
readonly username: string;
readonly updatedAt: string;
readonly emailVerified: boolean;
}>) => Effect.Effect<InsertResult, DBCallbackFailure | DatabaseError, never>
insertUser
({
username: string
username
: 'new_user',
email?: string | null | undefined
email
: 'new_user@example.com',
password?: string | null | undefined
password
: null,
avatar?: string | null | undefined
avatar
: null,
emailVerified: boolean
emailVerified
: false,
name: string
name
: 'user',
notifications?: string | null | undefined
notifications
: '',
url?: string | null | undefined
url
: null,
id: string
id
:
var crypto: webcrypto.Crypto
crypto
.
webcrypto.Crypto.randomUUID(): UUID

Generates a random

https://www.rfc-editor.org/rfc/rfc4122.txt RFC 4122

version 4 UUID. The UUID is generated using a cryptographic pseudorandom number generator.

@sincev16.7.0

randomUUID
(),
updatedAt: string
updatedAt
: new
var Date: DateConstructor
new () => Date (+3 overloads)
Date
().
Date.toISOString(): string

Returns a date as a string value in ISO format.

toISOString
(),
});
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
('Inserted new user:',
const newUser: InsertResult
newUser
); // withEncoder returns a 'InsertResult'
/*
type of 'newUser' is:
const newUser: InsertResult
*/
});
insert-user.ts
import {
import Schema
Schema
} from 'studiocms/effect';
import {
const StudioCMSUsersTable: Table<{
id: typeof Schema.String;
url: Schema.NullishOr<typeof Schema.String>;
name: typeof Schema.String;
email: Schema.NullishOr<typeof Schema.String>;
avatar: Schema.NullishOr<typeof Schema.String>;
username: typeof Schema.String;
password: Schema.NullishOr<typeof Schema.String>;
updatedAt: Schema.Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof Schema.DateFromString, typeof Schema.String, typeof Schema.String>;
createdAt: Schema.Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
emailVerified: Schema.transform<typeof Schema.Number, typeof Schema.Boolean>;
notifications: Schema.NullishOr<typeof Schema.String>;
}>

StudioCMS Users Table Definition

StudioCMSUsersTable
} from '@withstudiocms/kysely';
export const
const insertUser: Effect.Effect<void, ConfigError | DBCallbackFailure | DatabaseError, never>
insertUser
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, ConfigError, never>> | YieldWrap<...>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const {
const withCodec: <IEncoded, IType, OEncoded, OType, CIType = OmitNever<{ [K in keyof IType as HasNullOrUndefined<IType[K]> extends true ? K : never]?: IType[K] extends object ? IType[K] extends any[] ? IType[K] : OmitNever<{ [K in keyof IType[K] as HasNullOrUndefined<IType[K][K]> extends true ? K : never]?: IType[K][K] extends object ? IType[K][K] extends any[] ? IType[K][K] : OmitNever<{ [K in keyof IType[K][K] as HasNullOrUndefined<IType[K][K][K]> extends true ? K : never]?: IType[K][K][K] extends object ? IType[K][K][K] extends any[] ? IType[K][K][K] : OmitNever<...> : IType[K][K][K]; } & { [K in keyof IType[K][K] as HasNullOrUndefined<...> extends true ? never : K]: IType[K][K][K] extends object ? IType[K][K][K] extends any[] ? IType[K][K][K] : OmitNever<...> : IType[K][K][K]; }> : IType[K][K]; } & { [K in keyof IType[K] as HasNullOrUndefined<...> extends true ? never : K]: IType[K][K] extends object ? IType[K][K] extends any[] ? IType[K][K] : OmitNever<...> : IType[K][K]; }> : IType[K]; } & { [K in keyof IType as HasNullOrUndefined<...> extends true ? never : K]: IType[K] extends object ? IType[K] extends any[] ? IType[K] : OmitNever<...> : IType[K]; }>>({ encoder, decoder, callbackFn, }: {
...;
}) => (input: CIType) => Effect.Effect<...>

Creates a function that both encodes input data and decodes output data around a database operation.

withCodec
} = yield*
const getDbClient: Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, ConfigError, never>
getDbClient
;
const
const insertNewUser: (input: OmitNever<{
readonly url?: string | null | undefined;
readonly email?: string | null | undefined;
readonly avatar?: string | null | undefined;
readonly password?: string | null | undefined;
readonly createdAt?: string | undefined;
readonly notifications?: string | null | undefined;
} & {
readonly id: string;
readonly name: string;
readonly username: string;
readonly updatedAt: string;
readonly emailVerified: boolean;
}>) => Effect.Effect<{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
... 6 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}, DBCallbackFailure | DatabaseError, never>
insertNewUser
=
const withCodec: <{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: string;
readonly createdAt: string | undefined;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
}, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}, {
...;
}, {
...;
}, OmitNever<...>>({ encoder, decoder, callbackFn, }: {
...;
}) => (input: OmitNever<...>) => Effect.Effect<...>

Creates a function that both encodes input data and decodes output data around a database operation.

withCodec
({
encoder: Schema.Schema<{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: string;
readonly createdAt: string | undefined;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}, never>
encoder
:
const StudioCMSUsersTable: Table<{
id: typeof Schema.String;
url: Schema.NullishOr<typeof Schema.String>;
name: typeof Schema.String;
email: Schema.NullishOr<typeof Schema.String>;
avatar: Schema.NullishOr<typeof Schema.String>;
username: typeof Schema.String;
password: Schema.NullishOr<typeof Schema.String>;
updatedAt: Schema.Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof Schema.DateFromString, typeof Schema.String, typeof Schema.String>;
createdAt: Schema.Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
emailVerified: Schema.transform<typeof Schema.Number, typeof Schema.Boolean>;
notifications: Schema.NullishOr<typeof Schema.String>;
}>

StudioCMS Users Table Definition

StudioCMSUsersTable
.
type Insert: Schema.Struct<{
readonly id: Schema.Schema<string, string, never>;
readonly url: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly name: Schema.Schema<string, string, never>;
readonly email: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly avatar: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly username: Schema.Schema<string, string, never>;
readonly password: Schema.Schema<string | null | undefined, string | ... 1 more ... | undefined, never>;
readonly updatedAt: Schema.Schema<...>;
readonly createdAt: Schema.Schema<...>;
readonly emailVerified: Schema.Schema<...>;
readonly notifications: Schema.Schema<...>;
}>

  • A mapping of column names to the types accepted by INSERT operations. Insert types may allow undefined/optional values for columns with defaults or auto-generated values.

Insert
,
decoder: Schema.Schema<{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}, never>
decoder
:
const StudioCMSUsersTable: Table<{
id: typeof Schema.String;
url: Schema.NullishOr<typeof Schema.String>;
name: typeof Schema.String;
email: Schema.NullishOr<typeof Schema.String>;
avatar: Schema.NullishOr<typeof Schema.String>;
username: typeof Schema.String;
password: Schema.NullishOr<typeof Schema.String>;
updatedAt: Schema.Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof Schema.DateFromString, typeof Schema.String, typeof Schema.String>;
createdAt: Schema.Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
emailVerified: Schema.transform<typeof Schema.Number, typeof Schema.Boolean>;
notifications: Schema.NullishOr<typeof Schema.String>;
}>

StudioCMS Users Table Definition

StudioCMSUsersTable
.
type Select: Schema.Struct<{
readonly id: Schema.Schema<string, string, never>;
readonly url: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly name: Schema.Schema<string, string, never>;
readonly email: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly avatar: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly username: Schema.Schema<string, string, never>;
readonly password: Schema.Schema<string | null | undefined, string | ... 1 more ... | undefined, never>;
readonly updatedAt: Schema.Schema<...>;
readonly createdAt: Schema.Schema<...>;
readonly emailVerified: Schema.Schema<...>;
readonly notifications: Schema.Schema<...>;
}>

  • A mapping of column names to the types returned by SELECT queries. Typically these types represent the actual stored or computed values.

Select
,
callbackFn: DBCallbackFn<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}>
callbackFn
: (
db: DBCallback<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
db
,
newUser: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}
newUser
) =>
db: <{
id: string;
url: string | null | undefined;
name: string;
email: string | null | undefined;
avatar: string | null | undefined;
username: string;
password: string | null | undefined;
updatedAt: string;
createdAt: string;
emailVerified: number;
notifications: string | null | undefined;
}>(fn: (db: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>) => Promise<...>) => Effect.Effect<out A, out E = never, out R = never>.AsEffect<...>
db
((
client: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
client
) =>
client: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
client
.
QueryCreator<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }>.insertInto<"StudioCMSUsersTable">(table: "StudioCMSUsersTable"): InsertQueryBuilder<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable", InsertResult>

Creates an insert query.

The return value of this query is an instance of

InsertResult

.

InsertResult

has the

InsertResult.insertId insertId

field that holds the auto incremented id of the inserted row if the db returned one.

See the

InsertQueryBuilder.values values

method for more info and examples. Also see the

ReturningInterface.returning returning

method for a way to return columns on supported databases like PostgreSQL.

Examples

const result = await db
.insertInto('person')
.values({
first_name: 'Jennifer',
last_name: 'Aniston'
})
.executeTakeFirst()
console.log(result.insertId)

Some databases like PostgreSQL support the returning method:

const { id } = await db
.insertInto('person')
.values({
first_name: 'Jennifer',
last_name: 'Aniston'
})
.returning('id')
.executeTakeFirstOrThrow()

insertInto
('StudioCMSUsersTable')
.
InsertQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", InsertResult>.values(insert: InsertExpression<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable">): InsertQueryBuilder<...>

Sets the values to insert for an

Kysely.insertInto insert

query.

This method takes an object whose keys are column names and values are values to insert. In addition to the column's type, the values can be raw

sql

snippets or select queries.

You must provide all fields you haven't explicitly marked as nullable or optional using

Generated

or

ColumnType

.

The return value of an insert query is an instance of

InsertResult

. The

InsertResult.insertId insertId

field holds the auto incremented primary key if the database returned one.

On PostgreSQL and some other dialects, you need to call returning to get something out of the query.

Also see the

expression

method for inserting the result of a select query or any other expression.

Examples

Insert a single row:

const result = await db
.insertInto('person')
.values({
first_name: 'Jennifer',
last_name: 'Aniston',
age: 40
})
.executeTakeFirst()
// `insertId` is only available on dialects that
// automatically return the id of the inserted row
// such as MySQL and SQLite. On PostgreSQL, for example,
// you need to add a `returning` clause to the query to
// get anything out. See the "returning data" example.
console.log(result.insertId)

The generated SQL (MySQL):

insert into `person` (`first_name`, `last_name`, `age`) values (?, ?, ?)

On dialects that support it (for example PostgreSQL) you can insert multiple rows by providing an array. Note that the return value is once again very dialect-specific. Some databases may only return the id of the last inserted row and some return nothing at all unless you call returning.

await db
.insertInto('person')
.values([{
first_name: 'Jennifer',
last_name: 'Aniston',
age: 40,
}, {
first_name: 'Arnold',
last_name: 'Schwarzenegger',
age: 70,
}])
.execute()

The generated SQL (PostgreSQL):

insert into "person" ("first_name", "last_name", "age") values (($1, $2, $3), ($4, $5, $6))

On supported dialects like PostgreSQL you need to chain returning to the query to get the inserted row's columns (or any other expression) as the return value. returning works just like select. Refer to select method's examples and documentation for more info.

const result = await db
.insertInto('person')
.values({
first_name: 'Jennifer',
last_name: 'Aniston',
age: 40,
})
.returning(['id', 'first_name as name'])
.executeTakeFirstOrThrow()

The generated SQL (PostgreSQL):

insert into "person" ("first_name", "last_name", "age") values ($1, $2, $3) returning "id", "first_name" as "name"

In addition to primitives, the values can also be arbitrary expressions. You can build the expressions by using a callback and calling the methods on the expression builder passed to it:

import { sql } from 'kysely'
const ani = "Ani"
const ston = "ston"
const result = await db
.insertInto('person')
.values(({ ref, selectFrom, fn }) => ({
first_name: 'Jennifer',
last_name: sql<string>`concat(${ani}, ${ston})`,
middle_name: ref('first_name'),
age: selectFrom('person')
.select(fn.avg<number>('age').as('avg_age')),
}))
.executeTakeFirst()

The generated SQL (PostgreSQL):

insert into "person" (
"first_name",
"last_name",
"middle_name",
"age"
)
values (
$1,
concat($2, $3),
"first_name",
(select avg("age") as "avg_age" from "person")
)

You can also use the callback version of subqueries or raw expressions:

await db.with('jennifer', (db) => db
.selectFrom('person')
.where('first_name', '=', 'Jennifer')
.select(['id', 'first_name', 'gender'])
.limit(1)
).insertInto('pet').values((eb) => ({
owner_id: eb.selectFrom('jennifer').select('id'),
name: eb.selectFrom('jennifer').select('first_name'),
species: 'cat',
}))
.execute()

The generated SQL (PostgreSQL):

with "jennifer" as (
select "id", "first_name", "gender"
from "person"
where "first_name" = $1
limit $2
)
insert into "pet" ("owner_id", "name", "species")
values (
(select "id" from "jennifer"),
(select "first_name" from "jennifer"),
$3
)

values
(
newUser: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}
newUser
)
.
InsertQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", InsertResult>.returningAll(): InsertQueryBuilder<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable", {
...;
}>

Adds a returning * to an insert/update/delete/merge query on databases that support returning such as PostgreSQL.

Also see the

returning

method.

returningAll
()
.
InsertQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", { ...; }>.executeTakeFirstOrThrow(errorConstructor?: NoResultErrorConstructor | ((node: QueryNode) => Error)): Promise<{
id: string;
url: string | null | undefined;
name: string;
email: string | null | undefined;
avatar: string | null | undefined;
username: string;
password: string | null | undefined;
updatedAt: string;
createdAt: string;
emailVerified: number;
notifications: string | null | undefined;
}>

Executes the query and returns the first result or throws if the query returned no result.

By default an instance of

NoResultError

is thrown, but you can provide a custom error class, or callback as the only argument to throw a different error.

executeTakeFirstOrThrow
()
),
});
const
const insertedUser: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}
insertedUser
= yield*
const insertNewUser: (input: OmitNever<{
readonly url?: string | null | undefined;
readonly email?: string | null | undefined;
readonly avatar?: string | null | undefined;
readonly password?: string | null | undefined;
readonly createdAt?: string | undefined;
readonly notifications?: string | null | undefined;
} & {
readonly id: string;
readonly name: string;
readonly username: string;
readonly updatedAt: string;
readonly emailVerified: boolean;
}>) => Effect.Effect<{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
... 6 more ...;
readonly notifications: string | ... 1 more ... | undefined;
}, DBCallbackFailure | DatabaseError, never>
insertNewUser
({
username: string
username
: 'codec_user',
email?: string | null | undefined
email
: 'codec_user@example.com',
password?: string | null | undefined
password
: null,
avatar?: string | null | undefined
avatar
: null,
emailVerified: boolean
emailVerified
: false,
name: string
name
: 'user',
notifications?: string | null | undefined
notifications
: '',
url?: string | null | undefined
url
: null,
id: string
id
:
var crypto: webcrypto.Crypto
crypto
.
webcrypto.Crypto.randomUUID(): UUID

Generates a random

https://www.rfc-editor.org/rfc/rfc4122.txt RFC 4122

version 4 UUID. The UUID is generated using a cryptographic pseudorandom number generator.

@sincev16.7.0

randomUUID
(),
updatedAt: string
updatedAt
: new
var Date: DateConstructor
new () => Date (+3 overloads)
Date
().
Date.toISOString(): string

Returns a date as a string value in ISO format.

toISOString
(),
});
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
('Inserted user with codec:',
const insertedUser: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}
insertedUser
); // withCodec returns decoded results
/*
type of 'insertedUser' is:
const user: {
readonly url: string | null | undefined;
readonly id: string;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
}
*/
});
get-user.ts
import {
import Schema
Schema
} from 'studiocms/effect';
import {
const StudioCMSUsersTable: Table<{
id: typeof Schema.String;
url: Schema.NullishOr<typeof Schema.String>;
name: typeof Schema.String;
email: Schema.NullishOr<typeof Schema.String>;
avatar: Schema.NullishOr<typeof Schema.String>;
username: typeof Schema.String;
password: Schema.NullishOr<typeof Schema.String>;
updatedAt: Schema.Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof Schema.DateFromString, typeof Schema.String, typeof Schema.String>;
createdAt: Schema.Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
emailVerified: Schema.transform<typeof Schema.Number, typeof Schema.Boolean>;
notifications: Schema.NullishOr<typeof Schema.String>;
}>

StudioCMS Users Table Definition

StudioCMSUsersTable
} from '@withstudiocms/kysely';
export const
const insertUser: Effect.Effect<void, ConfigError | DBCallbackFailure | DatabaseError, never>
insertUser
=
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const gen: <YieldWrap<Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, ConfigError, never>> | YieldWrap<...>, void>(f: (resume: Effect.Adapter) => Generator<...>) => Effect.Effect<...> (+1 overload)

Provides a way to write effectful code using generator functions, simplifying control flow and error handling.

When to Use

Effect.gen allows you to write code that looks and behaves like synchronous code, but it can handle asynchronous tasks, errors, and complex control flow (like loops and conditions). It helps make asynchronous code more readable and easier to manage.

The generator functions work similarly to async/await but with more explicit control over the execution of effects. You can yield* values from effects and return the final result at the end.

Example

import { Effect } from "effect"
const addServiceCharge = (amount: number) => amount + 1
const applyDiscount = (
total: number,
discountRate: number
): Effect.Effect<number, Error> =>
discountRate === 0
? Effect.fail(new Error("Discount rate cannot be zero"))
: Effect.succeed(total - (total * discountRate) / 100)
const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
export const program = Effect.gen(function* () {
const transactionAmount = yield* fetchTransactionAmount
const discountRate = yield* fetchDiscountRate
const discountedAmount = yield* applyDiscount(
transactionAmount,
discountRate
)
const finalAmount = addServiceCharge(discountedAmount)
return `Final amount to charge: ${finalAmount}`
})

@since2.0.0

gen
(function* () {
const {
const withCodec: <IEncoded, IType, OEncoded, OType, CIType = OmitNever<{ [K in keyof IType as HasNullOrUndefined<IType[K]> extends true ? K : never]?: IType[K] extends object ? IType[K] extends any[] ? IType[K] : OmitNever<{ [K in keyof IType[K] as HasNullOrUndefined<IType[K][K]> extends true ? K : never]?: IType[K][K] extends object ? IType[K][K] extends any[] ? IType[K][K] : OmitNever<{ [K in keyof IType[K][K] as HasNullOrUndefined<IType[K][K][K]> extends true ? K : never]?: IType[K][K][K] extends object ? IType[K][K][K] extends any[] ? IType[K][K][K] : OmitNever<...> : IType[K][K][K]; } & { [K in keyof IType[K][K] as HasNullOrUndefined<...> extends true ? never : K]: IType[K][K][K] extends object ? IType[K][K][K] extends any[] ? IType[K][K][K] : OmitNever<...> : IType[K][K][K]; }> : IType[K][K]; } & { [K in keyof IType[K] as HasNullOrUndefined<...> extends true ? never : K]: IType[K][K] extends object ? IType[K][K] extends any[] ? IType[K][K] : OmitNever<...> : IType[K][K]; }> : IType[K]; } & { [K in keyof IType as HasNullOrUndefined<...> extends true ? never : K]: IType[K] extends object ? IType[K] extends any[] ? IType[K] : OmitNever<...> : IType[K]; }>>({ encoder, decoder, callbackFn, }: {
...;
}) => (input: CIType) => Effect.Effect<...>

Creates a function that both encodes input data and decodes output data around a database operation.

withCodec
} = yield*
const getDbClient: Effect.Effect<DBClientInterface<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>, ConfigError, never>
getDbClient
;
const
const getUserById: (input: string) => Effect.Effect<{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
} | undefined, DBCallbackFailure | DatabaseError, never>
getUserById
=
const withCodec: <string, string, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: string;
readonly createdAt: string;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
} | undefined, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | ... 1 more ... | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
} | undefined, string>({ encoder, decoder, callbackFn, }: {
...;
}) => (input: string) => Effect.Effect<...>

Creates a function that both encodes input data and decodes output data around a database operation.

withCodec
({
encoder: Schema.Schema<string, string, never>
encoder
:
import Schema
Schema
.
class String
export String

@since3.10.0

String
,
decoder: Schema.Schema<{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
} | undefined, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | ... 1 more ... | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
} | undefined, never>
decoder
:
import Schema
Schema
.
const UndefinedOr: <Schema.Struct<{
readonly id: Schema.Schema<string, string, never>;
readonly url: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly name: Schema.Schema<string, string, never>;
readonly email: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly avatar: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly username: Schema.Schema<string, string, never>;
readonly password: Schema.Schema<string | null | undefined, string | ... 1 more ... | undefined, never>;
readonly updatedAt: Schema.Schema<...>;
readonly createdAt: Schema.Schema<...>;
readonly emailVerified: Schema.Schema<...>;
readonly notifications: Schema.Schema<...>;
}>>(self: Schema.Struct<...>) => Schema.UndefinedOr<...>

@since3.10.0

UndefinedOr
(
const StudioCMSUsersTable: Table<{
id: typeof Schema.String;
url: Schema.NullishOr<typeof Schema.String>;
name: typeof Schema.String;
email: Schema.NullishOr<typeof Schema.String>;
avatar: Schema.NullishOr<typeof Schema.String>;
username: typeof Schema.String;
password: Schema.NullishOr<typeof Schema.String>;
updatedAt: Schema.Schema<ColumnType<Date, string, string>, ColumnType<string, string, string>, never> & ColumnTypes<typeof Schema.DateFromString, typeof Schema.String, typeof Schema.String>;
createdAt: Schema.Schema<ColumnType<...>, ColumnType<...>, never> & ColumnTypes<...>;
emailVerified: Schema.transform<typeof Schema.Number, typeof Schema.Boolean>;
notifications: Schema.NullishOr<typeof Schema.String>;
}>

StudioCMS Users Table Definition

StudioCMSUsersTable
.
type Select: Schema.Struct<{
readonly id: Schema.Schema<string, string, never>;
readonly url: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly name: Schema.Schema<string, string, never>;
readonly email: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly avatar: Schema.Schema<string | null | undefined, string | null | undefined, never>;
readonly username: Schema.Schema<string, string, never>;
readonly password: Schema.Schema<string | null | undefined, string | ... 1 more ... | undefined, never>;
readonly updatedAt: Schema.Schema<...>;
readonly createdAt: Schema.Schema<...>;
readonly emailVerified: Schema.Schema<...>;
readonly notifications: Schema.Schema<...>;
}>

  • A mapping of column names to the types returned by SELECT queries. Typically these types represent the actual stored or computed values.

Select
),
callbackFn: DBCallbackFn<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, string, {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | ... 1 more ... | undefined;
... 5 more ...;
readonly notifications: string | ... 1 more ... | undefined;
} | undefined>
callbackFn
: (
db: DBCallback<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
db
,
id: string
id
) =>
db: <{
id: string;
url: string | null | undefined;
name: string;
email: string | null | undefined;
avatar: string | null | undefined;
username: string;
password: string | null | undefined;
updatedAt: string;
createdAt: string;
emailVerified: number;
notifications: string | null | undefined;
} | undefined>(fn: (db: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>) => Promise<...>) => Effect.Effect<out A, out E = never, out R = never>.AsEffect<...>
db
((
client: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
client
) =>
client: Kysely<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}>
client
.
QueryCreator<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }>.selectFrom<"StudioCMSUsersTable">(from: "StudioCMSUsersTable"): SelectQueryBuilder<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable", {}>

Creates a select query builder for the given table or tables.

The tables passed to this method are built as the query's from clause.

Examples

Create a select query for one table:

db.selectFrom('person').selectAll()

The generated SQL (PostgreSQL):

select * from "person"

Create a select query for one table with an alias:

const persons = await db.selectFrom('person as p')
.select(['p.id', 'first_name'])
.execute()
console.log(persons[0].id)

The generated SQL (PostgreSQL):

select "p"."id", "first_name" from "person" as "p"

Create a select query from a subquery:

const persons = await db.selectFrom(
(eb) => eb.selectFrom('person').select('person.id as identifier').as('p')
)
.select('p.identifier')
.execute()
console.log(persons[0].identifier)

The generated SQL (PostgreSQL):

select "p"."identifier",
from (
select "person"."id" as "identifier" from "person"
) as p

Create a select query from raw sql:

importsql } from 'kysely'
const items = await db
.selectFrom(sql<{ one: number }>`(select 1 as one)`.as('q'))
.select('q.one')
.execute()
console.log(items[0].one)

The generated SQL (PostgreSQL):

select "q"."one",
from (
select 1 as one
) as q

When you use the sql tag you need to also provide the result type of the raw snippet / query so that Kysely can figure out what columns are available for the rest of the query.

The selectFrom method also accepts an array for multiple tables. All the above examples can also be used in an array.

importsql } from 'kysely'
const items = await db.selectFrom([
'person as p',
db.selectFrom('pet').select('pet.species').as('a'),
sql<{ one: number }>`(select 1 as one)`.as('q')
])
.select(['p.id', 'a.species', 'q.one'])
.execute()

The generated SQL (PostgreSQL):

select "p".id, "a"."species", "q"."one"
from
"person" as "p",
(select "pet"."species" from "pet") as a,
(select 1 as one) as "q"

selectFrom
('StudioCMSUsersTable').
SelectQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", {}>.selectAll(): SelectQueryBuilder<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable", {
...;
}> (+2 overloads)

Adds a select * or select table.* clause to the query.

Examples

The selectAll method generates SELECT *:

const persons = await db
.selectFrom('person')
.selectAll()
.execute()

The generated SQL (PostgreSQL):

select * from "person"

Select all columns of a table:

const persons = await db
.selectFrom('person')
.selectAll('person')
.execute()

The generated SQL (PostgreSQL):

select "person".* from "person"

Select all columns of multiple tables:

const personsPets = await db
.selectFrom(['person', 'pet'])
.selectAll(['person', 'pet'])
.execute()

The generated SQL (PostgreSQL):

select "person".*, "pet".* from "person", "pet"

selectAll
().
SelectQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", { ...; }>.where<"id", string>(lhs: "id", op: ComparisonOperatorExpression, rhs: string): SelectQueryBuilder<{
readonly StudioCMSUsersTable: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: ColumnType<string, string, string>;
readonly createdAt: ColumnType<string, string | undefined, never>;
readonly emailVerified: number;
readonly notifications: string | null | undefined;
};
... 13 more ...;
readonly StudioCMSDynamicConfigSettings: {
readonly id: string;
readonly data: ColumnType<...>;
};
}, "StudioCMSUsersTable", {
...;
}> (+1 overload)

Adds a where expression to the query.

Calling this method multiple times will combine the expressions using and.

Also see

whereRef

Examples

where method calls are combined with AND:

const person = await db
.selectFrom('person')
.selectAll()
.where('first_name', '=', 'Jennifer')
.where('age', '>', 40)
.executeTakeFirst()

The generated SQL (PostgreSQL):

select * from "person" where "first_name" = $1 and "age" > $2

Operator can be any supported operator or if the typings don't support it you can always use:

import { sql } from 'kysely'
sql`your operator`

Find multiple items using a list of identifiers:

const persons = await db
.selectFrom('person')
.selectAll()
.where('id', 'in', [1, 2, 3])
.execute()

The generated SQL (PostgreSQL):

select * from "person" where "id" in ($1, $2, $3)

You can use the and function to create a simple equality filter using an object

const persons = await db
.selectFrom('person')
.selectAll()
.where((eb) => eb.and({
first_name: 'Jennifer',
last_name: eb.ref('first_name')
}))
.execute()

The generated SQL (PostgreSQL):

select *
from "person"
where (
"first_name" = $1
and "last_name" = "first_name"
)

To combine conditions using OR, you can use the expression builder. There are two ways to create OR expressions. Both are shown in this example:

const persons = await db
.selectFrom('person')
.selectAll()
// 1. Using the `or` method on the expression builder:
.where((eb) => eb.or([
eb('first_name', '=', 'Jennifer'),
eb('first_name', '=', 'Sylvester')
]))
// 2. Chaining expressions using the `or` method on the
// created expressions:
.where((eb) =>
eb('last_name', '=', 'Aniston').or('last_name', '=', 'Stallone')
)
.execute()

The generated SQL (PostgreSQL):

select *
from "person"
where (
("first_name" = $1 or "first_name" = $2)
and
("last_name" = $3 or "last_name" = $4)
)

You can add expressions conditionally like this:

import { Expression, SqlBool } from 'kysely'
const firstName: string | undefined = 'Jennifer'
const lastName: string | undefined = 'Aniston'
const under18 = true
const over60 = true
let query = db
.selectFrom('person')
.selectAll()
if (firstName) {
// The query builder is immutable. Remember to reassign
// the result back to the query variable.
query = query.where('first_name', '=', firstName)
}
if (lastName) {
query = query.where('last_name', '=', lastName)
}
if (under18 || over60) {
// Conditional OR expressions can be added like this.
query = query.where((eb) => {
const ors: Expression<SqlBool>[] = []
if (under18) {
ors.push(eb('age', '<', 18))
}
if (over60) {
ors.push(eb('age', '>', 60))
}
return eb.or(ors)
})
}
const persons = await query.execute()

Both the first and third argument can also be arbitrary expressions like subqueries. An expression can defined by passing a function and calling the methods of the

ExpressionBuilder

passed to the callback:

const persons = await db
.selectFrom('person')
.selectAll()
.where(
(qb) => qb.selectFrom('pet')
.select('pet.name')
.whereRef('pet.owner_id', '=', 'person.id')
.limit(1),
'=',
'Fluffy'
)
.execute()

The generated SQL (PostgreSQL):

select *
from "person"
where (
select "pet"."name"
from "pet"
where "pet"."owner_id" = "person"."id"
limit $1
) = $2

A where in query can be built by using the in operator and an array of values. The values in the array can also be expressions:

const persons = await db
.selectFrom('person')
.selectAll()
.where('person.id', 'in', [100, 200, 300])
.execute()

The generated SQL (PostgreSQL):

select * from "person" where "id" in ($1, $2, $3)

For complex where expressions you can pass in a single callback and use the ExpressionBuilder to build your expression:

const firstName = 'Jennifer'
const maxAge = 60
const persons = await db
.selectFrom('person')
.selectAll('person')
.where(({ eb, or, and, not, exists, selectFrom }) => and([
or([
eb('first_name', '=', firstName),
eb('age', '<', maxAge)
]),
not(exists(
selectFrom('pet')
.select('pet.id')
.whereRef('pet.owner_id', '=', 'person.id')
))
]))
.execute()

The generated SQL (PostgreSQL):

select "person".*
from "person"
where (
(
"first_name" = $1
or "age" < $2
)
and not exists (
select "pet"."id" from "pet" where "pet"."owner_id" = "person"."id"
)
)

If everything else fails, you can always use the

sql

tag as any of the arguments, including the operator:

importsql } from 'kysely'
const persons = await db
.selectFrom('person')
.selectAll()
.where(
sql<string>`coalesce(first_name, last_name)`,
'like',
'%' + name + '%',
)
.execute()

The generated SQL (PostgreSQL):

select * from "person"
where coalesce(first_name, last_name) like $1

In all examples above the columns were known at compile time (except for the raw

sql

expressions). By default kysely only allows you to refer to columns that exist in the database and can be referred to in the current query and context.

Sometimes you may want to refer to columns that come from the user input and thus are not available at compile time.

You have two options, the

sql

tag or db.dynamic. The example below uses both:

importsql } from 'kysely'
const { ref } = db.dynamic
const columnFromUserInput: string = 'id'
const persons = await db
.selectFrom('person')
.selectAll()
.where(ref(columnFromUserInput), '=', 1)
.where(sql.id(columnFromUserInput), '=', 2)
.execute()

where
('id', '=',
id: string
id
).
SelectQueryBuilder<{ readonly StudioCMSUsersTable: { readonly id: string; readonly url: string | null | undefined; readonly name: string; readonly email: string | null | undefined; readonly avatar: string | null | undefined; readonly username: string; readonly password: string | null | undefined; readonly updatedAt: ColumnType<string, string, string>; readonly createdAt: ColumnType<string, string | undefined, never>; readonly emailVerified: number; readonly notifications: string | null | undefined; }; ... 13 more ...; readonly StudioCMSDynamicConfigSettings: { readonly id: string; readonly data: ColumnType<...>; }; }, "StudioCMSUsersTable", { ...; }>.executeTakeFirst(): Promise<{
id: string;
url: string | null | undefined;
name: string;
email: string | null | undefined;
avatar: string | null | undefined;
username: string;
password: string | null | undefined;
updatedAt: string;
createdAt: string;
emailVerified: number;
notifications: string | null | undefined;
} | undefined>

Executes the query and returns the first result or undefined if the query returned no result.

executeTakeFirst
()
),
});
const
const user: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
} | undefined
user
= yield*
const getUserById: (input: string) => Effect.Effect<{
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
} | undefined, DBCallbackFailure | DatabaseError, never>
getUserById
('some-user-id');
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err

@seesource

console
.
Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100

log
('User by ID:',
const user: {
readonly id: string;
readonly url: string | null | undefined;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
} | undefined
user
);
/*
type of 'user' is:
const user: {
readonly url: string | null | undefined;
readonly id: string;
readonly name: string;
readonly email: string | null | undefined;
readonly avatar: string | null | undefined;
readonly username: string;
readonly password: string | null | undefined;
readonly updatedAt: Date;
readonly createdAt: Date;
readonly emailVerified: boolean;
readonly notifications: string | null | undefined;
} | undefined
*/
});

@withstudiocms/sdk

A comprehensive Software Development Kit for StudioCMS, providing a unified API for interacting with the CMS core functionality. Built with TypeScript and Effect-ts for type-safety and functional programming patterns, with Kysely DB (@withstudiocms/kysely) for dynamic database storage.

  • Authentication Module - User authentication and session management
  • Configuration Management - Type-safe configuration handling with validation
  • Database Operations - CRUD operations with Effect-ts error handling
  • Plugin System - Utilities for plugin development and integration
  • Caching Layer - Built-in caching with query memoization and invalidation
  • Middleware Utilities - Request handling and middleware composition
  • Diff Tracking - Track changes and modifications
  • REST API Helpers - Utilities for building REST endpoints
  • Notification Settings - User notification preference management
  • Token Bucket - Rate limiting and token management

For a code example of how to use the StudioCMS SDK manually in your project, check how it’s implemented in StudioCMS on GitHub^

Interested in the live SDK already available in StudioCMS? Check out The SDK documentation to learn how to use it in your StudioCMS project!