Kanel (type generation)
The files in the types directory are generated by running pnpm --filter db make-kysely-types, which connects to the database specified by the DATABASE_URL var, introspects the schema, and then writes updated types to your local filesystem. These types are committed to the repo and must be updated alongside any migration. Since we are currently still using Prisma to manage our schema, this means you should always generate these types from your local database after creating and running a new migration.
We use Kanel to generate these types, which can be configured via .kanelrc.js. Configuration options can be found in the Kanel docs .
Generating the types
Make sure the database is running on localhost:54322 and the user is postgres.
The default way of doing this is by following the instruction in core/README.md.
Or, if you don’t have it run there, create an .env.local file with the following content:
DATABASE_URL="your postgres url"To generate just the types, run
pnpm --filter db make-kysely-typesIf you want to regenerate the types after updating core/prisma/schema.prisma, run
pnpm --filter core migrate-devYou might need to run pnpm --filter db migrate-dev twice to get the types to update properly.
Generating types for JSON fields
It is possible to generate more specific types for JSON fields defined.
This is done in the Prisma schema, by adding an annotation to the field which will add a comment to the database.
model ApiAccessPermission {
id String @id @default(dbgenerated("gen_random_uuid()"))
apiAccessTokenId String
apiAccessToken ApiAccessToken @relation(fields: [apiAccessTokenId], references: [id], onDelete: Cascade)
scope ApiAccessScope
accessType ApiAccessType
constraints Json? /// @type(ApiAccessPermissionConstraints, '../types', true, false, true)
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
// this ensures that only one permission per token and scope and access type exists
@@index([apiAccessTokenId, scope, accessType], name: "api_access_permissions_idx")
@@map(name: "api_access_permissions")
}Adding a /// will add the string as a comment to that column in the database using a custom generator defined here
generator comments {
provider = "pnpm exec tsx prisma/scripts/comment-generator.mts"
}This will lead to the following migration:
-- Model api_access_permissions comments
COMMENT ON COLUMN "api_access_permissions"."constraints" IS '@type(ApiAccessPermissionConstraints, ''../types'', true, false, true)';This comment then gets picked up by Kanel and turned into a type definition for the field.
The syntax (largely undocumented, except for here https://github.com/kristiandupont/kanel/issues/429#issuecomment-1636126264 ), is:
@type(name, path, isAbsolute, isDefault, importAsType)So
config Json? /// @type(RuleConfigs, '~/actions/types', true, false, true)will generate the following type:
import type { RuleConfigs } from "~/actions/types";
// ...
config: RuleConfigs | null;
// ...Alernatively, you can also specify a type directly:
config Json? /// @type:stringor use global types
config Json? /// @type:DBTypes.RuleConfigand then specify those types in some file like globals.ts:
declare global {
namespace DBTypes {
type RuleConfig = {
// ...
};
}
}
// necessary to make `declare global` work with or without using `import`s
export {};It is also possible to use these comments to provide nicer documentation for other elements, such as enums.
/// @property generic - For most use-cases. This will just authenticate you with a regular session.
/// @property passwordReset - For resetting your password only
/// @property signup - For signing up, but also when you're invited to a community
/// @property verifyEmail - For verifying your email address
enum AuthTokenType {
generic
passwordReset
signup
verifyEmail
}This will generate the following enum
/**
* Represents the enum public.AuthTokenType
* @property generic - For most use-cases. This will just authenticate you with a regular session.
* @property passwordReset - For resetting your password only
* @property signup - For signing up, but also when you're invited to a community
* @property verifyEmail - For verifying your email address
*/
export enum AuthTokenType {
generic = "generic",
passwordReset = "passwordReset",
signup = "signup",
verifyEmail = "verifyEmail",
}Adding a table
If you have added a new table, make sure to add
export * from "./tableName";to /packages/db/src/public.ts, otherwise it won’t be properly exported.
Special hooks
Because kanel is a bit messy, we have a few special hooks to make it easier to work with.
See packages/db/src/kanel for more details.
Adding extra types you want to use
You can add/export extra types in src/types. This can be useful if you want to augment the default types that kanel generates, for instance for
JSON columns.