├── .github
└── workflows
│ ├── preview.yml
│ └── test.yml
├── .gitignore
├── .node-version
├── .nvmrc
├── .prettierignore
├── .prettierrc.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── FUNDING.md
├── LICENSE
├── README.md
├── assets
└── demo.gif
├── deno.check.d.ts
├── deno.check.json
├── docker-compose.yml
├── docs
└── index.html
├── example
├── .env
├── .gitignore
├── .prettierrc.json
├── README.md
├── package-lock.json
├── package.json
├── src
│ ├── app.ts
│ ├── authentication
│ │ ├── auth-token.service.ts
│ │ ├── auth-token.ts
│ │ ├── authentication.service.ts
│ │ ├── refresh-token.repository.ts
│ │ ├── refresh-token.table.ts
│ │ └── refresh-token.ts
│ ├── config.ts
│ ├── context.ts
│ ├── database.ts
│ ├── migrate-to-latest.ts
│ ├── migrations
│ │ ├── 2021_09_18_06_54_59_create_user.ts
│ │ ├── 2021_09_18_14_05_20_create_refresh_token.ts
│ │ └── 2021_09_18_18_22_45_create_sign_in_method.ts
│ ├── router.ts
│ ├── user
│ │ ├── sign-in-method
│ │ │ ├── password-sign-in-method.table.ts
│ │ │ ├── sign-in-method.controller.ts
│ │ │ ├── sign-in-method.repository.ts
│ │ │ ├── sign-in-method.service.ts
│ │ │ ├── sign-in-method.table.ts
│ │ │ └── sign-in-method.ts
│ │ ├── signed-in-user.ts
│ │ ├── user.controller.ts
│ │ ├── user.repository.ts
│ │ ├── user.service.ts
│ │ ├── user.table.ts
│ │ └── user.ts
│ └── util
│ │ ├── ajv.ts
│ │ ├── errors.ts
│ │ └── object.ts
├── test
│ ├── test-config.ts
│ ├── test-context.ts
│ └── user
│ │ └── user.test.ts
└── tsconfig.json
├── outdated-typescript.d.ts
├── package-lock.json
├── package.json
├── scripts
├── add-deno-type-references.js
├── align-site-version.js
├── check-esm-imports.js
├── check-exports.js
├── copy-interface-documentation.js
├── exclude-test-files-for-backwards-compat.mts
├── generate-site-examples.js
├── module-fixup.js
├── tsconfig.json
└── util
│ └── for-each-file.js
├── site
├── .gitignore
├── babel.config.js
├── docs
│ ├── dialects.md
│ ├── examples
│ │ ├── _category_.json
│ │ ├── cte
│ │ │ ├── 0010-simple-selects.js
│ │ │ ├── 0010-simple-selects.mdx
│ │ │ ├── 0020-inserts-updates-and-deletions.js
│ │ │ ├── 0020-inserts-updates-and-deletions.mdx
│ │ │ └── _category_.json
│ │ ├── delete
│ │ │ ├── 0010-single-row.js
│ │ │ ├── 0010-single-row.mdx
│ │ │ └── _category_.json
│ │ ├── insert
│ │ │ ├── 0010-single-row.js
│ │ │ ├── 0010-single-row.mdx
│ │ │ ├── 0020-multiple-rows.js
│ │ │ ├── 0020-multiple-rows.mdx
│ │ │ ├── 0030-returning-data.js
│ │ │ ├── 0030-returning-data.mdx
│ │ │ ├── 0040-complex-values.js
│ │ │ ├── 0040-complex-values.mdx
│ │ │ ├── 0050-insert-subquery.js
│ │ │ ├── 0050-insert-subquery.mdx
│ │ │ └── _category_.json
│ │ ├── join
│ │ │ ├── 0010-simple-inner-join.js
│ │ │ ├── 0010-simple-inner-join.mdx
│ │ │ ├── 0020-aliased-inner-join.js
│ │ │ ├── 0020-aliased-inner-join.mdx
│ │ │ ├── 0030-complex-join.js
│ │ │ ├── 0030-complex-join.mdx
│ │ │ ├── 0040-subquery-join.js
│ │ │ ├── 0040-subquery-join.mdx
│ │ │ └── _category_.json
│ │ ├── merge
│ │ │ ├── 0010-source-row-existence.js
│ │ │ ├── 0010-source-row-existence.mdx
│ │ │ ├── 0020-temporary-changes-table.js
│ │ │ ├── 0020-temporary-changes-table.mdx
│ │ │ └── _category_.json
│ │ ├── select
│ │ │ ├── 0010-a-single-column.js
│ │ │ ├── 0010-a-single-column.mdx
│ │ │ ├── 0020-column-with-a-table.js
│ │ │ ├── 0020-column-with-a-table.mdx
│ │ │ ├── 0030-multiple-columns.js
│ │ │ ├── 0030-multiple-columns.mdx
│ │ │ ├── 0040-aliases.js
│ │ │ ├── 0040-aliases.mdx
│ │ │ ├── 0050-complex-selections.js
│ │ │ ├── 0050-complex-selections.mdx
│ │ │ ├── 0051-not-null.js
│ │ │ ├── 0051-not-null.mdx
│ │ │ ├── 0060-function-calls.js
│ │ │ ├── 0060-function-calls.mdx
│ │ │ ├── 0070-distinct.js
│ │ │ ├── 0070-distinct.mdx
│ │ │ ├── 0080-distinct-on.js
│ │ │ ├── 0080-distinct-on.mdx
│ │ │ ├── 0090-all-columns.js
│ │ │ ├── 0090-all-columns.mdx
│ │ │ ├── 0100-all-columns-of-a-table.js
│ │ │ ├── 0100-all-columns-of-a-table.mdx
│ │ │ ├── 0110-nested-array.js
│ │ │ ├── 0110-nested-array.mdx
│ │ │ ├── 0120-nested-object.js
│ │ │ ├── 0120-nested-object.mdx
│ │ │ ├── 0130-generic-find-query.js
│ │ │ ├── 0130-generic-find-query.mdx
│ │ │ └── _category_.json
│ │ ├── transactions
│ │ │ ├── 0010-simple-transaction.js
│ │ │ ├── 0010-simple-transaction.mdx
│ │ │ ├── 0011-controlled-transaction.js
│ │ │ ├── 0011-controlled-transaction.mdx
│ │ │ ├── 0012-controlled-transaction-w-savepoints.js
│ │ │ ├── 0012-controlled-transaction-w-savepoints.mdx
│ │ │ └── _category_.json
│ │ ├── update
│ │ │ ├── 0010-single-row.js
│ │ │ ├── 0010-single-row.mdx
│ │ │ ├── 0020-complex-values.js
│ │ │ ├── 0020-complex-values.mdx
│ │ │ ├── 0030-my-sql-joins.js
│ │ │ ├── 0030-my-sql-joins.mdx
│ │ │ └── _category_.json
│ │ └── where
│ │ │ ├── 0010-simple-where-clause.js
│ │ │ ├── 0010-simple-where-clause.mdx
│ │ │ ├── 0020-where-in.js
│ │ │ ├── 0020-where-in.mdx
│ │ │ ├── 0030-object-filter.js
│ │ │ ├── 0030-object-filter.mdx
│ │ │ ├── 0040-or-where.js
│ │ │ ├── 0040-or-where.mdx
│ │ │ ├── 0050-conditional-where-calls.js
│ │ │ ├── 0050-conditional-where-calls.mdx
│ │ │ ├── 0060-complex-where-clause.js
│ │ │ ├── 0060-complex-where-clause.mdx
│ │ │ └── _category_.json
│ ├── generating-types.md
│ ├── getting-started.mdx
│ ├── getting-started
│ │ ├── Dialects.tsx
│ │ ├── IUseADifferentDatabase.tsx
│ │ ├── IUseADifferentPackageManager.tsx
│ │ ├── Installation.tsx
│ │ ├── Instantiation.tsx
│ │ ├── Querying.tsx
│ │ ├── Summary.tsx
│ │ ├── _prerequisites.mdx
│ │ ├── _types.mdx
│ │ └── shared.tsx
│ ├── intro.mdx
│ ├── migrations.mdx
│ ├── playground.mdx
│ ├── plugins.md
│ ├── recipes
│ │ ├── 0001-relations.md
│ │ ├── 0001-reusable-helpers.md
│ │ ├── 0002-data-types.md
│ │ ├── 0003-raw-sql.md
│ │ ├── 0004-splitting-query-building-and-execution.md
│ │ ├── 0005-conditional-selects.md
│ │ ├── 0006-expressions.md
│ │ ├── 0007-schemas.md
│ │ ├── 0008-deduplicate-joins.md
│ │ ├── 0009-excessively-deep-types.md
│ │ ├── 0010-extending-kysely.md
│ │ ├── 0011-introspecting-relation-metadata.md
│ │ ├── 0012-logging.md
│ │ └── _category_.json
│ └── runtimes
│ │ ├── _category_.json
│ │ ├── browser.md
│ │ └── deno.mdx
├── docusaurus.config.ts
├── package-lock.json
├── package.json
├── sidebars.js
├── src
│ ├── components
│ │ ├── DemoVideo.module.css
│ │ ├── DemoVideo.tsx
│ │ ├── Playground.module.css
│ │ ├── Playground.tsx
│ │ ├── SectionFeatures
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ │ ├── SectionQuotes
│ │ │ ├── Quote.tsx
│ │ │ ├── index.tsx
│ │ │ ├── quotes.ts
│ │ │ ├── reddit.module.css
│ │ │ └── styles.module.css
│ │ └── playground-example-types.ts
│ ├── css
│ │ └── custom.css
│ └── pages
│ │ ├── index.module.css
│ │ └── index.tsx
├── static
│ ├── .nojekyll
│ ├── demo.mp4
│ └── img
│ │ ├── avatars
│ │ ├── alberto.jpeg
│ │ ├── alexanderson.jpeg
│ │ ├── bekacru.png
│ │ ├── benholmes.jpeg
│ │ ├── capaj.png
│ │ ├── catalin.png
│ │ ├── daxraad.jpeg
│ │ ├── gal.jpeg
│ │ ├── gannon.jpeg
│ │ ├── gudmundur.png
│ │ ├── guga.png
│ │ ├── harminder.png
│ │ ├── johan.jpeg
│ │ ├── julius.jpeg
│ │ ├── leerob.jpeg
│ │ ├── marvin.png
│ │ ├── marvinh.jpeg
│ │ ├── mehul.jpeg
│ │ ├── nexxel.jpeg
│ │ ├── nicholas.jpeg
│ │ ├── niels.png
│ │ ├── orta.jpeg
│ │ ├── pilcrowonpaper.jpeg
│ │ ├── ross.jpeg
│ │ ├── samcook.jpeg
│ │ ├── sommelier.jpeg
│ │ ├── tgriesser.jpeg
│ │ ├── theo.jpeg
│ │ └── yusuke.jpeg
│ │ ├── docusaurus.png
│ │ ├── favicon.ico
│ │ ├── logo.svg
│ │ ├── powered-by-vercel.svg
│ │ ├── undraw_docusaurus_mountain.svg
│ │ ├── undraw_docusaurus_react.svg
│ │ └── undraw_docusaurus_tree.svg
└── tsconfig.json
├── src
├── dialect
│ ├── database-introspector.ts
│ ├── dialect-adapter-base.ts
│ ├── dialect-adapter.ts
│ ├── dialect.ts
│ ├── mssql
│ │ ├── mssql-adapter.ts
│ │ ├── mssql-dialect-config.ts
│ │ ├── mssql-dialect.ts
│ │ ├── mssql-driver.ts
│ │ ├── mssql-introspector.ts
│ │ └── mssql-query-compiler.ts
│ ├── mysql
│ │ ├── mysql-adapter.ts
│ │ ├── mysql-dialect-config.ts
│ │ ├── mysql-dialect.ts
│ │ ├── mysql-driver.ts
│ │ ├── mysql-introspector.ts
│ │ └── mysql-query-compiler.ts
│ ├── postgres
│ │ ├── postgres-adapter.ts
│ │ ├── postgres-dialect-config.ts
│ │ ├── postgres-dialect.ts
│ │ ├── postgres-driver.ts
│ │ ├── postgres-introspector.ts
│ │ └── postgres-query-compiler.ts
│ └── sqlite
│ │ ├── sqlite-adapter.ts
│ │ ├── sqlite-dialect-config.ts
│ │ ├── sqlite-dialect.ts
│ │ ├── sqlite-driver.ts
│ │ ├── sqlite-introspector.ts
│ │ └── sqlite-query-compiler.ts
├── driver
│ ├── connection-provider.ts
│ ├── database-connection.ts
│ ├── default-connection-provider.ts
│ ├── driver.ts
│ ├── dummy-driver.ts
│ ├── runtime-driver.ts
│ └── single-connection-provider.ts
├── dynamic
│ ├── dynamic-reference-builder.ts
│ ├── dynamic-table-builder.ts
│ └── dynamic.ts
├── expression
│ ├── expression-builder.ts
│ ├── expression-wrapper.ts
│ └── expression.ts
├── helpers
│ ├── mssql.ts
│ ├── mysql.ts
│ ├── postgres.ts
│ └── sqlite.ts
├── index.ts
├── kysely.ts
├── migration
│ ├── file-migration-provider.ts
│ └── migrator.ts
├── operation-node
│ ├── add-column-node.ts
│ ├── add-constraint-node.ts
│ ├── add-index-node.ts
│ ├── aggregate-function-node.ts
│ ├── alias-node.ts
│ ├── alter-column-node.ts
│ ├── alter-table-node.ts
│ ├── and-node.ts
│ ├── binary-operation-node.ts
│ ├── case-node.ts
│ ├── cast-node.ts
│ ├── check-constraint-node.ts
│ ├── collate-node.ts
│ ├── column-definition-node.ts
│ ├── column-node.ts
│ ├── column-update-node.ts
│ ├── common-table-expression-name-node.ts
│ ├── common-table-expression-node.ts
│ ├── constraint-node.ts
│ ├── create-index-node.ts
│ ├── create-schema-node.ts
│ ├── create-table-node.ts
│ ├── create-type-node.ts
│ ├── create-view-node.ts
│ ├── data-type-node.ts
│ ├── default-insert-value-node.ts
│ ├── default-value-node.ts
│ ├── delete-query-node.ts
│ ├── drop-column-node.ts
│ ├── drop-constraint-node.ts
│ ├── drop-index-node.ts
│ ├── drop-schema-node.ts
│ ├── drop-table-node.ts
│ ├── drop-type-node.ts
│ ├── drop-view-node.ts
│ ├── explain-node.ts
│ ├── fetch-node.ts
│ ├── foreign-key-constraint-node.ts
│ ├── from-node.ts
│ ├── function-node.ts
│ ├── generated-node.ts
│ ├── group-by-item-node.ts
│ ├── group-by-node.ts
│ ├── having-node.ts
│ ├── identifier-node.ts
│ ├── insert-query-node.ts
│ ├── join-node.ts
│ ├── json-operator-chain-node.ts
│ ├── json-path-leg-node.ts
│ ├── json-path-node.ts
│ ├── json-reference-node.ts
│ ├── limit-node.ts
│ ├── list-node.ts
│ ├── matched-node.ts
│ ├── merge-query-node.ts
│ ├── modify-column-node.ts
│ ├── offset-node.ts
│ ├── on-conflict-node.ts
│ ├── on-duplicate-key-node.ts
│ ├── on-node.ts
│ ├── operation-node-source.ts
│ ├── operation-node-transformer.ts
│ ├── operation-node-visitor.ts
│ ├── operation-node.ts
│ ├── operator-node.ts
│ ├── or-action-node.ts
│ ├── or-node.ts
│ ├── order-by-item-node.ts
│ ├── order-by-node.ts
│ ├── output-node.ts
│ ├── over-node.ts
│ ├── parens-node.ts
│ ├── partition-by-item-node.ts
│ ├── partition-by-node.ts
│ ├── primary-key-constraint-node.ts
│ ├── primitive-value-list-node.ts
│ ├── query-node.ts
│ ├── raw-node.ts
│ ├── reference-node.ts
│ ├── references-node.ts
│ ├── refresh-materialized-view-node.ts
│ ├── rename-column-node.ts
│ ├── rename-constraint-node.ts
│ ├── returning-node.ts
│ ├── schemable-identifier-node.ts
│ ├── select-all-node.ts
│ ├── select-modifier-node.ts
│ ├── select-query-node.ts
│ ├── selection-node.ts
│ ├── set-operation-node.ts
│ ├── simple-reference-expression-node.ts
│ ├── table-node.ts
│ ├── top-node.ts
│ ├── tuple-node.ts
│ ├── unary-operation-node.ts
│ ├── unique-constraint-node.ts
│ ├── update-query-node.ts
│ ├── using-node.ts
│ ├── value-list-node.ts
│ ├── value-node.ts
│ ├── values-node.ts
│ ├── when-node.ts
│ ├── where-node.ts
│ └── with-node.ts
├── parser
│ ├── binary-operation-parser.ts
│ ├── coalesce-parser.ts
│ ├── collate-parser.ts
│ ├── data-type-parser.ts
│ ├── default-value-parser.ts
│ ├── delete-from-parser.ts
│ ├── expression-parser.ts
│ ├── fetch-parser.ts
│ ├── group-by-parser.ts
│ ├── identifier-parser.ts
│ ├── insert-values-parser.ts
│ ├── join-parser.ts
│ ├── merge-into-parser.ts
│ ├── merge-parser.ts
│ ├── on-commit-action-parse.ts
│ ├── on-modify-action-parser.ts
│ ├── order-by-parser.ts
│ ├── parse-utils.ts
│ ├── partition-by-parser.ts
│ ├── reference-parser.ts
│ ├── returning-parser.ts
│ ├── savepoint-parser.ts
│ ├── select-from-parser.ts
│ ├── select-parser.ts
│ ├── set-operation-parser.ts
│ ├── table-parser.ts
│ ├── top-parser.ts
│ ├── tuple-parser.ts
│ ├── unary-operation-parser.ts
│ ├── update-parser.ts
│ ├── update-set-parser.ts
│ ├── value-parser.ts
│ └── with-parser.ts
├── plugin
│ ├── camel-case
│ │ ├── camel-case-plugin.ts
│ │ ├── camel-case-transformer.ts
│ │ └── camel-case.ts
│ ├── deduplicate-joins
│ │ ├── deduplicate-joins-plugin.ts
│ │ └── deduplicate-joins-transformer.ts
│ ├── handle-empty-in-lists
│ │ ├── handle-empty-in-lists-plugin.ts
│ │ ├── handle-empty-in-lists-transformer.ts
│ │ └── handle-empty-in-lists.ts
│ ├── immediate-value
│ │ ├── immediate-value-plugin.ts
│ │ └── immediate-value-transformer.ts
│ ├── kysely-plugin.ts
│ ├── noop-plugin.ts
│ ├── parse-json-results
│ │ └── parse-json-results-plugin.ts
│ └── with-schema
│ │ ├── with-schema-plugin.ts
│ │ └── with-schema-transformer.ts
├── query-builder
│ ├── aggregate-function-builder.ts
│ ├── case-builder.ts
│ ├── cte-builder.ts
│ ├── delete-query-builder.ts
│ ├── delete-result.ts
│ ├── function-module.ts
│ ├── having-interface.ts
│ ├── insert-query-builder.ts
│ ├── insert-result.ts
│ ├── join-builder.ts
│ ├── json-path-builder.ts
│ ├── merge-query-builder.ts
│ ├── merge-result.ts
│ ├── no-result-error.ts
│ ├── on-conflict-builder.ts
│ ├── order-by-interface.ts
│ ├── order-by-item-builder.ts
│ ├── output-interface.ts
│ ├── over-builder.ts
│ ├── returning-interface.ts
│ ├── select-query-builder-expression.ts
│ ├── select-query-builder.ts
│ ├── update-query-builder.ts
│ ├── update-result.ts
│ └── where-interface.ts
├── query-compiler
│ ├── compiled-query.ts
│ ├── default-query-compiler.ts
│ └── query-compiler.ts
├── query-creator.ts
├── query-executor
│ ├── default-query-executor.ts
│ ├── noop-query-executor.ts
│ ├── query-executor-base.ts
│ ├── query-executor-provider.ts
│ └── query-executor.ts
├── raw-builder
│ ├── raw-builder.ts
│ └── sql.ts
├── schema
│ ├── alter-column-builder.ts
│ ├── alter-table-add-foreign-key-constraint-builder.ts
│ ├── alter-table-add-index-builder.ts
│ ├── alter-table-builder.ts
│ ├── alter-table-drop-constraint-builder.ts
│ ├── alter-table-executor.ts
│ ├── check-constraint-builder.ts
│ ├── column-definition-builder.ts
│ ├── create-index-builder.ts
│ ├── create-schema-builder.ts
│ ├── create-table-builder.ts
│ ├── create-type-builder.ts
│ ├── create-view-builder.ts
│ ├── drop-index-builder.ts
│ ├── drop-schema-builder.ts
│ ├── drop-table-builder.ts
│ ├── drop-type-builder.ts
│ ├── drop-view-builder.ts
│ ├── foreign-key-constraint-builder.ts
│ ├── primary-key-constraint-builder.ts
│ ├── refresh-materialized-view-builder.ts
│ ├── schema.ts
│ └── unique-constraint-builder.ts
└── util
│ ├── assert.ts
│ ├── column-type.ts
│ ├── compilable.ts
│ ├── deferred.ts
│ ├── explainable.ts
│ ├── infer-result.ts
│ ├── json-object-args.ts
│ ├── log-once.ts
│ ├── log.ts
│ ├── object-utils.ts
│ ├── performance-now.ts
│ ├── provide-controlled-connection.ts
│ ├── query-id.ts
│ ├── random-string.ts
│ ├── require-all-props.ts
│ ├── stack-trace-utils.ts
│ ├── streamable.ts
│ ├── type-error.ts
│ └── type-utils.ts
├── test
├── browser
│ ├── index.html
│ ├── main.ts
│ └── test.js
├── bun
│ ├── bun.lockb
│ ├── bun.test.ts
│ └── package.json
├── cloudflare-workers
│ ├── .dev.vars
│ ├── api.ts
│ ├── package-lock.json
│ ├── package.json
│ └── test.ts
├── deno
│ ├── cdn.test.ts
│ ├── deno.json
│ ├── deno.lock
│ └── local.test.ts
├── node
│ ├── src
│ │ ├── aggregate-function.test.ts
│ │ ├── array.test.ts
│ │ ├── async-dispose.test.ts
│ │ ├── camel-case.test.ts
│ │ ├── case.test.ts
│ │ ├── clear.test.ts
│ │ ├── coalesce.test.ts
│ │ ├── controlled-transaction.test.ts
│ │ ├── deduplicate-joins.test.ts
│ │ ├── delete.test.ts
│ │ ├── disconnects.test.ts
│ │ ├── error-stack.test.ts
│ │ ├── execute.test.ts
│ │ ├── explain.test.ts
│ │ ├── expression.test.ts
│ │ ├── group-by.test.ts
│ │ ├── handle-empty-in-lists-plugin.test.ts
│ │ ├── having.test.ts
│ │ ├── immediate-value-plugin.test.ts
│ │ ├── insert.test.ts
│ │ ├── introspect.test.ts
│ │ ├── join.test.ts
│ │ ├── json-traversal.test.ts
│ │ ├── json.test.ts
│ │ ├── log-once.test.ts
│ │ ├── logging.test.ts
│ │ ├── merge.test.ts
│ │ ├── migration.test.ts
│ │ ├── object-util.test.ts
│ │ ├── order-by.test.ts
│ │ ├── parse-json-results-plugin.test.ts
│ │ ├── performance.test.ts
│ │ ├── query-id.test.ts
│ │ ├── raw-query.test.ts
│ │ ├── raw-sql.test.ts
│ │ ├── replace.test.ts
│ │ ├── sanitize-identifiers.test.ts
│ │ ├── schema.test.ts
│ │ ├── select.test.ts
│ │ ├── set-operation.test.ts
│ │ ├── sql-injection.test.ts
│ │ ├── stream.test.ts
│ │ ├── test-migrations
│ │ │ ├── migration1.ts
│ │ │ └── migration2.ts
│ │ ├── test-setup.ts
│ │ ├── transaction.test.ts
│ │ ├── update.test.ts
│ │ ├── where.test.ts
│ │ ├── with-schema.test.ts
│ │ └── with.test.ts
│ └── tsconfig.json
├── outdated-ts
│ ├── outdated-ts.test.ts
│ ├── package-lock.json
│ ├── package.json
│ └── tsconfig.json
├── scripts
│ └── mysql-init.sql
├── ts-benchmarks
│ ├── index.ts
│ ├── order-by.bench.ts
│ ├── package.json
│ ├── select-from.bench.ts
│ └── tsconfig.json
└── typings
│ ├── index.d.ts
│ ├── package.json
│ ├── shared.d.ts
│ ├── test-d
│ ├── aggregate-function.test-d.ts
│ ├── alter-table.test-d.ts
│ ├── assert-type.test-d.ts
│ ├── case.test-d.ts
│ ├── clear.test-d.ts
│ ├── coalesce.test-d.ts
│ ├── create-table.test-d.ts
│ ├── delete-query-builder.test-d.ts
│ ├── expression.test-d.ts
│ ├── generic.test-d.ts
│ ├── huge-db.test-d.ts
│ ├── if.test-d.ts
│ ├── index.test-d.ts
│ ├── infer-result.test-d.ts
│ ├── insert.test-d.ts
│ ├── join.test-d.ts
│ ├── json-traversal.test-d.ts
│ ├── kysely-any.test-d.ts
│ ├── merge.test-d.ts
│ ├── postgres-json.test-d.ts
│ ├── select-from.test-d.ts
│ ├── select-no-from.test-d.ts
│ ├── select.test-d.ts
│ ├── set-operation.test-d.ts
│ ├── update.test-d.ts
│ ├── where.test-d.ts
│ └── with.test-d.ts
│ └── tsconfig.json
├── tsconfig-base.json
├── tsconfig-cjs.json
└── tsconfig.json
/.github/workflows/preview.yml:
--------------------------------------------------------------------------------
1 | name: preview
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | paths-ignore:
9 | - '.github/workflows/test.yml'
10 | - 'assets/**'
11 | - 'docs/**'
12 | - 'example/**'
13 | - 'site/**'
14 | - 'test/**'
15 | - '.npmignore'
16 | - '.prettierignore'
17 | - '.prettierrc'
18 | - '.renovaterc.json'
19 | - '*.md'
20 | - 'LICENSE'
21 |
22 | jobs:
23 | release:
24 | name: Release preview build
25 | runs-on: ubuntu-latest
26 |
27 | steps:
28 | - uses: actions/checkout@v4
29 |
30 | - name: Use Node.js
31 | uses: actions/setup-node@v4
32 | with:
33 | cache: 'npm'
34 | node-version: lts/*
35 |
36 | - name: Install dependencies
37 | run: npm ci
38 |
39 | - name: Build
40 | run: npm run build
41 |
42 | - name: Release preview version
43 | run: npx pkg-pr-new@0.0.50 publish --template './example'
44 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | /helpers
3 | /test/browser/bundle.js
4 | node_modules
5 | .vscode
6 | .idea
7 |
--------------------------------------------------------------------------------
/.node-version:
--------------------------------------------------------------------------------
1 | 22
2 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | lts/*
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | *.md
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true,
4 | "trailingComma": "all"
5 | }
6 |
--------------------------------------------------------------------------------
/FUNDING.md:
--------------------------------------------------------------------------------
1 | # Funding
2 |
3 | Kysely is an MIT-licensed open-source project and is completely free to use - and will remain so.
4 |
5 | Kysely is a labor of love. We do this in our free time.
6 |
7 | We do not accept donations.
8 |
9 | - Getting paid for open-source won't make us put more time and effort into open-source.
10 | We have family, friends, and other hobbies and interests.
11 |
12 | - We work in the tech industry, full-time, as software developers. We are comfortable as-is.
13 |
14 | - We don't believe in freelance open-source as a stable source of income for the long term.
15 | We have mouths to feed, and careers to maintain.
16 |
17 | - Sponsored projects tend to be affected by big sponsors. We want to keep Kysely away
18 | from companies' and VCs' opinions and business needs.
19 |
20 | - Kysely is escapism for us. We don't want it to feel like another job.
21 |
22 |
23 | Instead of donating to us, we encourage you to support meaningful causes or other open-source projects in need of funding.
24 |
25 | Thank you for supporting Kysely through your usage, contributions, and feedback.
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2022 Sami Koskimäki
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/assets/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/assets/demo.gif
--------------------------------------------------------------------------------
/deno.check.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://deno.land/x/deno/cli/schemas/config-file.v1.json",
3 | "compilerOptions": {
4 | "types": ["./deno.check.d.ts"]
5 | },
6 | "imports": {
7 | "better-sqlite3": "npm:better-sqlite3",
8 | "kysely": "./dist/esm",
9 | "kysely/helpers/mssql": "./dist/esm/helpers/mssql.js",
10 | "kysely/helpers/mysql": "./dist/esm/helpers/mysql.js",
11 | "kysely/helpers/postgres": "./dist/esm/helpers/postgres.js",
12 | "kysely/helpers/sqlite": "./dist/esm/helpers/sqlite.js",
13 | "lodash/snakeCase": "npm:lodash/snakeCase",
14 | "mysql2": "npm:mysql2",
15 | "pg": "npm:pg",
16 | "pg-cursor": "npm:pg-cursor",
17 | "tarn": "npm:tarn",
18 | "tedious": "npm:tedious",
19 | "type-editor": "./deno.check.d.ts"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/.env:
--------------------------------------------------------------------------------
1 | # IMPORTANT!
2 | #
3 | # Normally you'd never ever include the .env file in the repo, but for simplicity
4 | # of this example project we do.
5 | #
6 | # Let me say this again: DO NOT INCLUDE THIS FILE IN THE REPO OF ANY REAL PROJECT.
7 |
8 | PORT=3000
9 | AUTH_TOKEN_SECRET=50a7d98cb1f35f2cf746b7be83b36395463b76647c7fca8c86
10 | AUTH_TOKEN_EXIRY_DURATION=2h
11 | DATABASE_HOST=localhost
12 | DATABASE_USER=postgres
13 | DATABASE=kysely_koa_example
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | lib
2 | node_modules
3 | .vscode
4 |
--------------------------------------------------------------------------------
/example/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "singleQuote": true
4 | }
--------------------------------------------------------------------------------
/example/src/authentication/auth-token.ts:
--------------------------------------------------------------------------------
1 | export interface AuthToken {
2 | authToken: string
3 | }
4 |
--------------------------------------------------------------------------------
/example/src/authentication/refresh-token.table.ts:
--------------------------------------------------------------------------------
1 | import { Generated, Insertable, Selectable, Updateable } from 'kysely'
2 |
3 | export interface RefreshTokenTable {
4 | refresh_token_id: Generated
5 | user_id: string
6 | last_refreshed_at: Date
7 | created_at: Generated
8 | }
9 |
10 | export type RefreshTokenRow = Selectable
11 | export type InsertableRefreshTokenRow = Insertable
12 | export type UpdateableRefreshTokenRow = Updateable
13 |
--------------------------------------------------------------------------------
/example/src/authentication/refresh-token.ts:
--------------------------------------------------------------------------------
1 | import { ajv } from '../util/ajv'
2 |
3 | export interface RefreshToken {
4 | refreshToken: string
5 | }
6 |
7 | export const validateRefreshToken = ajv.compile({
8 | type: 'object',
9 | required: ['refreshToken'],
10 | properties: {
11 | refreshToken: {
12 | type: 'string',
13 | },
14 | },
15 | })
16 |
--------------------------------------------------------------------------------
/example/src/config.ts:
--------------------------------------------------------------------------------
1 | import * as dotenv from 'dotenv'
2 | import { ConnectionConfig } from 'pg'
3 |
4 | dotenv.config()
5 |
6 | export interface Config {
7 | readonly port: number
8 | readonly authTokenSecret: string
9 | readonly authTokenExpiryDuration: string
10 | readonly database: ConnectionConfig
11 | }
12 |
13 | export const config: Config = Object.freeze({
14 | port: parseInt(getEnvVariable('PORT'), 10),
15 | authTokenSecret: getEnvVariable('AUTH_TOKEN_SECRET'),
16 | authTokenExpiryDuration: getEnvVariable('AUTH_TOKEN_EXIRY_DURATION'),
17 | database: Object.freeze({
18 | database: getEnvVariable('DATABASE'),
19 | host: getEnvVariable('DATABASE_HOST'),
20 | user: getEnvVariable('DATABASE_USER'),
21 | }),
22 | })
23 |
24 | function getEnvVariable(name: string): string {
25 | if (!process.env[name]) {
26 | throw new Error(`environment variable ${name} not found`)
27 | }
28 |
29 | return process.env[name]!
30 | }
31 |
--------------------------------------------------------------------------------
/example/src/context.ts:
--------------------------------------------------------------------------------
1 | import * as Koa from 'koa'
2 | import * as KoaRouter from 'koa-router'
3 |
4 | import { Kysely } from 'kysely'
5 | import { Database } from './database'
6 |
7 | export interface ContextExtension {
8 | db: Kysely
9 | }
10 |
11 | export type Context = Koa.ParameterizedContext<
12 | any,
13 | ContextExtension & KoaRouter.IRouterParamContext,
14 | any
15 | >
16 |
--------------------------------------------------------------------------------
/example/src/database.ts:
--------------------------------------------------------------------------------
1 | import { RefreshTokenTable } from './authentication/refresh-token.table'
2 | import { PasswordSignInMethodTable } from './user/sign-in-method/password-sign-in-method.table'
3 | import { SignInMethodTable } from './user/sign-in-method/sign-in-method.table'
4 | import { UserTable } from './user/user.table'
5 |
6 | export interface Database {
7 | user: UserTable
8 | refresh_token: RefreshTokenTable
9 | sign_in_method: SignInMethodTable
10 | password_sign_in_method: PasswordSignInMethodTable
11 | }
12 |
--------------------------------------------------------------------------------
/example/src/migrations/2021_09_18_06_54_59_create_user.ts:
--------------------------------------------------------------------------------
1 | import { Kysely, sql } from 'kysely'
2 |
3 | export async function up(db: Kysely): Promise {
4 | await db.schema
5 | .createTable('user')
6 | .addColumn('user_id', 'uuid', (col) =>
7 | col.primaryKey().defaultTo(sql`gen_random_uuid()`)
8 | )
9 | .addColumn('first_name', 'text')
10 | .addColumn('last_name', 'text')
11 | .addColumn('email', 'text', (col) => col.unique())
12 | .addColumn('created_at', 'timestamp', (col) => col.defaultTo(sql`NOW()`))
13 | .execute()
14 | }
15 |
16 | export async function down(db: Kysely): Promise {
17 | await db.schema.dropTable('user').execute()
18 | }
19 |
--------------------------------------------------------------------------------
/example/src/migrations/2021_09_18_14_05_20_create_refresh_token.ts:
--------------------------------------------------------------------------------
1 | import { Kysely, sql } from 'kysely'
2 |
3 | export async function up(db: Kysely): Promise {
4 | await db.schema
5 | .createTable('refresh_token')
6 | .addColumn('refresh_token_id', 'uuid', (col) =>
7 | col.primaryKey().defaultTo(sql`gen_random_uuid()`)
8 | )
9 | .addColumn('user_id', 'uuid', (col) =>
10 | col.references('user.user_id').notNull().onDelete('cascade')
11 | )
12 | .addColumn('last_refreshed_at', 'timestamp', (col) => col.notNull())
13 | .addColumn('created_at', 'timestamp', (col) =>
14 | col.notNull().defaultTo(sql`NOW()`)
15 | )
16 | .execute()
17 |
18 | await db.schema
19 | .createIndex('refresh_token_user_id_index')
20 | .on('refresh_token')
21 | .column('user_id')
22 | .execute()
23 | }
24 |
25 | export async function down(db: Kysely): Promise {
26 | await db.schema.dropTable('refresh_token').execute()
27 | }
28 |
--------------------------------------------------------------------------------
/example/src/router.ts:
--------------------------------------------------------------------------------
1 | import * as KoaRouter from 'koa-router'
2 |
3 | import { ContextExtension } from './context'
4 |
5 | export class Router extends KoaRouter {}
6 |
--------------------------------------------------------------------------------
/example/src/user/sign-in-method/password-sign-in-method.table.ts:
--------------------------------------------------------------------------------
1 | import { Insertable, Selectable, Updateable } from 'kysely'
2 |
3 | export interface PasswordSignInMethodTable {
4 | user_id: string
5 | password_hash: string
6 | }
7 |
8 | export type PasswordSignInMethodRow = Selectable
9 |
10 | export type InsertablePasswordSignInMethodRow =
11 | Insertable
12 |
13 | export type UpdateablePasswordSignInMethodRow =
14 | Updateable
15 |
--------------------------------------------------------------------------------
/example/src/user/sign-in-method/sign-in-method.repository.ts:
--------------------------------------------------------------------------------
1 | import { Kysely } from 'kysely'
2 | import { Database } from '../../database'
3 | import {
4 | InsertablePasswordSignInMethodRow,
5 | PasswordSignInMethodRow,
6 | } from './password-sign-in-method.table'
7 |
8 | export async function findPasswordSignInMethod(
9 | db: Kysely,
10 | userId: string
11 | ): Promise {
12 | const method = await db
13 | .selectFrom('sign_in_method as sim')
14 | .innerJoin('password_sign_in_method as psim', 'psim.user_id', 'sim.user_id')
15 | .selectAll('psim')
16 | .where('sim.type', '=', 'password')
17 | .where('sim.user_id', '=', userId)
18 | .executeTakeFirst()
19 |
20 | return method
21 | }
22 |
23 | export async function insertPasswordSignInMethod(
24 | db: Kysely,
25 | method: InsertablePasswordSignInMethodRow
26 | ): Promise {
27 | await db
28 | .with('sim', (db) =>
29 | db
30 | .insertInto('sign_in_method')
31 | .values({ user_id: method.user_id, type: 'password' })
32 | )
33 | .insertInto('password_sign_in_method')
34 | .values(method)
35 | .execute()
36 |
37 | return method
38 | }
39 |
--------------------------------------------------------------------------------
/example/src/user/sign-in-method/sign-in-method.table.ts:
--------------------------------------------------------------------------------
1 | import { Insertable, Selectable, Updateable } from 'kysely'
2 |
3 | export interface SignInMethodTable {
4 | user_id: string
5 | type: 'password'
6 | }
7 |
8 | export type SignInMethodRow = Selectable
9 | export type InsertableSignInMethodRow = Insertable
10 | export type UpdateableSignInMethodRow = Updateable
11 |
--------------------------------------------------------------------------------
/example/src/user/sign-in-method/sign-in-method.ts:
--------------------------------------------------------------------------------
1 | import { ajv } from '../../util/ajv'
2 |
3 | export type SignInMethod = PasswordSignInMethod
4 |
5 | export interface PasswordSignInMethod {
6 | email: string
7 | password: string
8 | }
9 |
10 | export const validatePasswordSignInMethod = ajv.compile({
11 | type: 'object',
12 | required: ['email', 'password'],
13 | properties: {
14 | email: {
15 | type: 'string',
16 | },
17 | password: {
18 | type: 'string',
19 | },
20 | },
21 | })
22 |
--------------------------------------------------------------------------------
/example/src/user/signed-in-user.ts:
--------------------------------------------------------------------------------
1 | import { AuthToken } from '../authentication/auth-token'
2 | import { RefreshToken } from '../authentication/refresh-token'
3 | import { User } from './user'
4 |
5 | export interface SignedInUser {
6 | refreshToken: RefreshToken
7 | authToken: AuthToken
8 | user: User
9 | }
10 |
--------------------------------------------------------------------------------
/example/src/user/user.table.ts:
--------------------------------------------------------------------------------
1 | import { Generated, Insertable, Selectable, Updateable } from 'kysely'
2 |
3 | export interface UserTable {
4 | user_id: Generated
5 | first_name: string | null
6 | last_name: string | null
7 | email: string | null
8 | created_at: Generated
9 | }
10 |
11 | export type UserRow = Selectable
12 | export type InsertableUserRow = Insertable
13 | export type UpdateableUserRow = Updateable
14 |
--------------------------------------------------------------------------------
/example/src/user/user.ts:
--------------------------------------------------------------------------------
1 | import { ajv } from '../util/ajv'
2 |
3 | export interface User {
4 | id: string
5 | firstName: string | null
6 | lastName: string | null
7 | email: string | null
8 | }
9 |
10 | export interface CreateAnonymousUserRequest {
11 | firstName?: string
12 | lastName?: string
13 | }
14 |
15 | export const validateCreateAnonymousUserRequest =
16 | ajv.compile({
17 | type: 'object',
18 | properties: {
19 | firstName: {
20 | type: 'string',
21 | },
22 | lastName: {
23 | type: 'string',
24 | },
25 | },
26 | })
27 |
--------------------------------------------------------------------------------
/example/src/util/ajv.ts:
--------------------------------------------------------------------------------
1 | import Ajv from 'ajv'
2 |
3 | export const ajv = new Ajv()
4 |
--------------------------------------------------------------------------------
/example/src/util/object.ts:
--------------------------------------------------------------------------------
1 | export function isObject(value: unknown): value is Record {
2 | return typeof value === 'object' && value !== null
3 | }
4 |
--------------------------------------------------------------------------------
/example/test/test-config.ts:
--------------------------------------------------------------------------------
1 | import { ConnectionConfig } from 'pg'
2 | import { Config } from '../src/config'
3 |
4 | export interface TestConfig extends Config {
5 | readonly adminDatabase: ConnectionConfig
6 | }
7 |
8 | export const testConfig: TestConfig = {
9 | port: 3001,
10 | authTokenSecret: 'a498a5cf13a8194a2477f9284df34af3954fad3dc8459e343a',
11 | authTokenExpiryDuration: '2h',
12 | database: {
13 | host: 'localhost',
14 | database: 'kysely_koa_example_test',
15 | user: 'postgres',
16 | },
17 | adminDatabase: {
18 | host: 'localhost',
19 | database: 'postgres',
20 | user: 'postgres',
21 | },
22 | }
23 |
--------------------------------------------------------------------------------
/example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "ESNext",
5 | "declaration": true,
6 | "outDir": "./dist",
7 | "strict": true,
8 | "noImplicitAny": true,
9 | },
10 | "include": ["src/**/*"],
11 | }
12 |
--------------------------------------------------------------------------------
/outdated-typescript.d.ts:
--------------------------------------------------------------------------------
1 | import type { KyselyTypeError } from './dist/cjs/util/type-error'
2 |
3 | declare const Kysely: KyselyTypeError<'The installed TypeScript version is outdated and cannot guarantee type-safety with Kysely. Please upgrade to version 4.6 or newer.'>
4 | declare const RawBuilder: KyselyTypeError<'The installed TypeScript version is outdated and cannot guarantee type-safety with Kysely. Please upgrade to version 4.6 or newer.'>
5 | declare const sql: KyselyTypeError<'The installed TypeScript version is outdated and cannot guarantee type-safety with Kysely. Please upgrade to version 4.6 or newer.'>
6 |
--------------------------------------------------------------------------------
/scripts/add-deno-type-references.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This scripts adds a `/// ` directive
3 | * at the beginning of each ESM JavaScript file so that they work with
4 | * deno.
5 | */
6 |
7 | const fs = require('fs')
8 | const path = require('path')
9 | const forEachFile = require('./util/for-each-file')
10 |
11 | const ESM_DIST_PATH = path.join(__dirname, '..', 'dist', 'esm')
12 |
13 | forEachFile(ESM_DIST_PATH, (filePath) => {
14 | if (filePath.endsWith('.js')) {
15 | const dTsFile = path.basename(filePath).replace(/\.js$/, '.d.ts')
16 | const content = fs.readFileSync(filePath, { encoding: 'utf-8' })
17 |
18 | fs.writeFileSync(
19 | filePath,
20 | `/// \n${content}`
21 | )
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/scripts/align-site-version.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This script aligns docusaurus package.json & package-lock.json versions with
3 | * Kysely's version so we use only the latest published version in the docs.
4 | */
5 |
6 | const { version } = require('../package.json')
7 | const sitePackageJson = require('../site/package.json')
8 | const sitePackageLockJson = require('../site/package-lock.json')
9 | const { writeFileSync } = require('fs')
10 | const { join } = require('path')
11 |
12 | const sitePath = join(__dirname, '..', 'site')
13 |
14 | writeFileSync(
15 | join(sitePath, 'package.json'),
16 | JSON.stringify({ ...sitePackageJson, version }, null, 2) + '\n'
17 | )
18 | writeFileSync(
19 | join(sitePath, 'package-lock.json'),
20 | JSON.stringify({ ...sitePackageLockJson, version }, null, 2) + '\n'
21 | )
22 |
--------------------------------------------------------------------------------
/scripts/check-exports.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This script ensures all files in a path are exported in the index.ts file.
3 | * For now it only checks the operation-node folder, as we've had issues with
4 | * missing exports there.
5 | */
6 |
7 | const fs = require('node:fs')
8 | const path = require('node:path')
9 | const forEachFile = require('./util/for-each-file')
10 |
11 | let errorsFound = false
12 |
13 | function checkExports(dir) {
14 | const indexFileContents = fs.readFileSync(
15 | path.join(__dirname, '..', 'src/index.ts'),
16 | 'utf-8',
17 | )
18 |
19 | forEachFile(dir, (filePath) => {
20 | if (filePath.endsWith('.ts')) {
21 | const expectedExportPath = filePath.replace(
22 | /^.+\/src\/(.+)\.ts$/,
23 | "'./$1.js'",
24 | )
25 |
26 | if (!indexFileContents.includes(expectedExportPath)) {
27 | console.log(`Missing export: ${expectedExportPath}`)
28 | errorsFound = true
29 | }
30 | }
31 | })
32 | }
33 |
34 | checkExports(path.join(__dirname, '..', 'src/operation-node'))
35 |
36 | if (errorsFound) {
37 | console.log(' ')
38 | console.log('check-exports.js failed!')
39 | process.exit(1)
40 | }
41 |
--------------------------------------------------------------------------------
/scripts/exclude-test-files-for-backwards-compat.mts:
--------------------------------------------------------------------------------
1 | import { writeFile } from 'node:fs/promises'
2 | import { dirname, resolve } from 'pathe'
3 | import { lt } from 'semver'
4 | import { devDependencies } from '../package.json'
5 |
6 | const typescriptVersion = devDependencies.typescript.replace('^', '')
7 | const testTsConfigRelativePath = '../test/node/tsconfig.json'
8 |
9 | if (lt(typescriptVersion, '5.0.0')) {
10 | const tsconfig = await import('../test/node/tsconfig.json')
11 |
12 | await writeFile(
13 | resolve(
14 | dirname(new URL(import.meta.url).pathname),
15 | testTsConfigRelativePath,
16 | ),
17 | JSON.stringify({
18 | ...tsconfig,
19 | exclude: [...(tsconfig.exclude || []), 'src/async-dispose.test.ts'],
20 | }),
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/scripts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig-base.json",
3 | "compilerOptions": {
4 | "module": "ESNext",
5 | "resolveJsonModule": true
6 | },
7 | "include": ["./"]
8 | }
9 |
--------------------------------------------------------------------------------
/scripts/util/for-each-file.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 |
4 | function forEachFile(dir, callback) {
5 | const files = fs.readdirSync(dir).filter((it) => it !== '.' && it !== '..')
6 |
7 | for (const file of files) {
8 | const filePath = path.join(dir, file)
9 |
10 | if (isDir(filePath)) {
11 | forEachFile(filePath, callback)
12 | } else {
13 | callback(filePath)
14 | }
15 | }
16 | }
17 |
18 | function isDir(file) {
19 | return fs.lstatSync(file).isDirectory()
20 | }
21 |
22 | module.exports = forEachFile
23 |
--------------------------------------------------------------------------------
/site/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | /node_modules
3 |
4 | # Production
5 | /build
6 |
7 | # Generated files
8 | .docusaurus
9 | .cache-loader
10 |
11 | # Misc
12 | .DS_Store
13 | .env.local
14 | .env.development.local
15 | .env.test.local
16 | .env.production.local
17 |
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 |
22 | .vercel
23 |
--------------------------------------------------------------------------------
/site/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
3 | };
4 |
--------------------------------------------------------------------------------
/site/docs/examples/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Examples",
3 | "position": 5,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Short and simple examples of how to use Kysely to achieve common tasks."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/examples/cte/0010-simple-selects.js:
--------------------------------------------------------------------------------
1 | export const simpleSelects = `const result = await db
2 | // Create a CTE called \`jennifers\` that selects all
3 | // persons named 'Jennifer'.
4 | .with('jennifers', (db) => db
5 | .selectFrom('person')
6 | .where('first_name', '=', 'Jennifer')
7 | .select(['id', 'age'])
8 | )
9 | // Select all rows from the \`jennifers\` CTE and
10 | // further filter it.
11 | .with('adult_jennifers', (db) => db
12 | .selectFrom('jennifers')
13 | .where('age', '>', 18)
14 | .select(['id', 'age'])
15 | )
16 | // Finally select all adult jennifers that are
17 | // also younger than 60.
18 | .selectFrom('adult_jennifers')
19 | .where('age', '<', 60)
20 | .selectAll()
21 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/cte/0010-simple-selects.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Simple selects'
3 | ---
4 |
5 | # Simple selects
6 |
7 | Common table expressions (CTE) are a great way to modularize complex queries.
8 | Essentially they allow you to run multiple separate queries within a
9 | single roundtrip to the DB.
10 |
11 | Since CTEs are a part of the main query, query optimizers inside DB
12 | engines are able to optimize the overall query. For example, postgres
13 | is able to inline the CTEs inside the using queries if it decides it's
14 | faster.
15 |
16 | import { Playground } from '../../../src/components/Playground'
17 |
18 | import {
19 | simpleSelects
20 | } from './0010-simple-selects'
21 |
22 |
25 |
--------------------------------------------------------------------------------
/site/docs/examples/cte/0020-inserts-updates-and-deletions.js:
--------------------------------------------------------------------------------
1 | export const insertsUpdatesAndDeletions = `const result = await db
2 | .with('new_person', (db) => db
3 | .insertInto('person')
4 | .values({
5 | first_name: 'Jennifer',
6 | age: 35,
7 | })
8 | .returning('id')
9 | )
10 | .with('new_pet', (db) => db
11 | .insertInto('pet')
12 | .values({
13 | name: 'Doggo',
14 | species: 'dog',
15 | is_favorite: true,
16 | // Use the id of the person we just inserted.
17 | owner_id: db
18 | .selectFrom('new_person')
19 | .select('id')
20 | })
21 | .returning('id')
22 | )
23 | .selectFrom(['new_person', 'new_pet'])
24 | .select([
25 | 'new_person.id as person_id',
26 | 'new_pet.id as pet_id'
27 | ])
28 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/cte/0020-inserts-updates-and-deletions.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Inserts, updates and deletions'
3 | ---
4 |
5 | # Inserts, updates and deletions
6 |
7 | Some databases like postgres also allow you to run other queries than selects
8 | in CTEs. On these databases CTEs are extremely powerful:
9 |
10 | import { Playground } from '../../../src/components/Playground'
11 |
12 | import {
13 | insertsUpdatesAndDeletions
14 | } from './0020-inserts-updates-and-deletions'
15 |
16 |
19 |
--------------------------------------------------------------------------------
/site/docs/examples/cte/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "CTE",
3 | "position": 9,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Short and simple examples of how to use Common Table Expressions (CTE) in queries."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/examples/delete/0010-single-row.js:
--------------------------------------------------------------------------------
1 | export const singleRow = `const result = await db
2 | .deleteFrom('person')
3 | .where('person.id', '=', 1)
4 | .executeTakeFirst()
5 |
6 | console.log(result.numDeletedRows)`
--------------------------------------------------------------------------------
/site/docs/examples/delete/0010-single-row.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Single row'
3 | ---
4 |
5 | # Single row
6 |
7 | Delete a single row:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | singleRow
13 | } from './0010-single-row'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [deleteFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#deleteFrom)
26 | - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/DeleteQueryBuilder.html#returning)
27 | :::
28 |
--------------------------------------------------------------------------------
/site/docs/examples/delete/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "DELETE",
3 | "position": 6,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Short and simple examples of how to write DELETE queries."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/examples/insert/0010-single-row.js:
--------------------------------------------------------------------------------
1 | export const singleRow = `const result = await db
2 | .insertInto('person')
3 | .values({
4 | first_name: 'Jennifer',
5 | last_name: 'Aniston',
6 | age: 40
7 | })
8 | .executeTakeFirst()
9 |
10 | // \`insertId\` is only available on dialects that
11 | // automatically return the id of the inserted row
12 | // such as MySQL and SQLite. On PostgreSQL, for example,
13 | // you need to add a \`returning\` clause to the query to
14 | // get anything out. See the "returning data" example.
15 | console.log(result.insertId)`
--------------------------------------------------------------------------------
/site/docs/examples/insert/0010-single-row.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Single row'
3 | ---
4 |
5 | # Single row
6 |
7 | Insert a single row:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | singleRow
13 | } from './0010-single-row'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [values method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#values)
26 | - [onConflict method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#onConflict)
27 | - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/InsertQueryBuilder.html#returning)
28 | - [insertInto method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#insertInto)
29 | :::
30 |
--------------------------------------------------------------------------------
/site/docs/examples/insert/0020-multiple-rows.js:
--------------------------------------------------------------------------------
1 | export const multipleRows = `await db
2 | .insertInto('person')
3 | .values([{
4 | first_name: 'Jennifer',
5 | last_name: 'Aniston',
6 | age: 40,
7 | }, {
8 | first_name: 'Arnold',
9 | last_name: 'Schwarzenegger',
10 | age: 70,
11 | }])
12 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/insert/0030-returning-data.js:
--------------------------------------------------------------------------------
1 | export const returningData = `const result = await db
2 | .insertInto('person')
3 | .values({
4 | first_name: 'Jennifer',
5 | last_name: 'Aniston',
6 | age: 40,
7 | })
8 | .returning(['id', 'first_name as name'])
9 | .executeTakeFirstOrThrow()`
--------------------------------------------------------------------------------
/site/docs/examples/insert/0040-complex-values.js:
--------------------------------------------------------------------------------
1 | export const complexValues = `import { sql } from 'kysely'
2 |
3 | const ani = "Ani"
4 | const ston = "ston"
5 |
6 | const result = await db
7 | .insertInto('person')
8 | .values(({ ref, selectFrom, fn }) => ({
9 | first_name: 'Jennifer',
10 | last_name: sql\`concat(\${ani}, \${ston})\`,
11 | middle_name: ref('first_name'),
12 | age: selectFrom('person')
13 | .select(fn.avg('age').as('avg_age')),
14 | }))
15 | .executeTakeFirst()`
--------------------------------------------------------------------------------
/site/docs/examples/insert/0050-insert-subquery.js:
--------------------------------------------------------------------------------
1 | export const insertSubquery = `const result = await db.insertInto('person')
2 | .columns(['first_name', 'last_name', 'age'])
3 | .expression((eb) => eb
4 | .selectFrom('pet')
5 | .select((eb) => [
6 | 'pet.name',
7 | eb.val('Petson').as('last_name'),
8 | eb.lit(7).as('age'),
9 | ])
10 | )
11 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/insert/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "INSERT",
3 | "position": 4,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Short and simple examples of how to write INSERT queries."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/examples/join/0010-simple-inner-join.js:
--------------------------------------------------------------------------------
1 | export const simpleInnerJoin = `const result = await db
2 | .selectFrom('person')
3 | .innerJoin('pet', 'pet.owner_id', 'person.id')
4 | // \`select\` needs to come after the call to \`innerJoin\` so
5 | // that you can select from the joined table.
6 | .select(['person.id', 'pet.name as pet_name'])
7 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/join/0020-aliased-inner-join.js:
--------------------------------------------------------------------------------
1 | export const aliasedInnerJoin = `await db.selectFrom('person')
2 | .innerJoin('pet as p', 'p.owner_id', 'person.id')
3 | .where('p.name', '=', 'Doggo')
4 | .selectAll()
5 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/join/0030-complex-join.js:
--------------------------------------------------------------------------------
1 | export const complexJoin = `await db.selectFrom('person')
2 | .innerJoin(
3 | 'pet',
4 | (join) => join
5 | .onRef('pet.owner_id', '=', 'person.id')
6 | .on('pet.name', '=', 'Doggo')
7 | .on((eb) => eb.or([
8 | eb('person.age', '>', 18),
9 | eb('person.age', '<', 100)
10 | ]))
11 | )
12 | .selectAll()
13 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/join/0040-subquery-join.js:
--------------------------------------------------------------------------------
1 | export const subqueryJoin = `const result = await db.selectFrom('person')
2 | .innerJoin(
3 | (eb) => eb
4 | .selectFrom('pet')
5 | .select(['owner_id as owner', 'name'])
6 | .where('name', '=', 'Doggo')
7 | .as('doggos'),
8 | (join) => join
9 | .onRef('doggos.owner', '=', 'person.id'),
10 | )
11 | .selectAll('doggos')
12 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/join/0040-subquery-join.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Subquery join'
3 | ---
4 |
5 | # Subquery join
6 |
7 | You can join a subquery by providing two callbacks:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | subqueryJoin
13 | } from './0040-subquery-join'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [innerJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#innerJoin)
26 | - [leftJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#leftJoin)
27 | - [rightJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#rightJoin)
28 | - [fullJoin method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#fullJoin)
29 | :::
30 |
--------------------------------------------------------------------------------
/site/docs/examples/join/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "JOIN",
3 | "position": 3,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Examples of queries that use JOINs."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/examples/merge/0010-source-row-existence.js:
--------------------------------------------------------------------------------
1 | export const sourceRowExistence = `const result = await db
2 | .mergeInto('person as target')
3 | .using('pet as source', 'source.owner_id', 'target.id')
4 | .whenMatchedAnd('target.has_pets', '!=', 'Y')
5 | .thenUpdateSet({ has_pets: 'Y' })
6 | .whenNotMatchedBySourceAnd('target.has_pets', '=', 'Y')
7 | .thenUpdateSet({ has_pets: 'N' })
8 | .executeTakeFirstOrThrow()
9 |
10 | console.log(result.numChangedRows)`
--------------------------------------------------------------------------------
/site/docs/examples/merge/0020-temporary-changes-table.js:
--------------------------------------------------------------------------------
1 | export const temporaryChangesTable = `const result = await db
2 | .mergeInto('wine as target')
3 | .using(
4 | 'wine_stock_change as source',
5 | 'source.wine_name',
6 | 'target.name',
7 | )
8 | .whenNotMatchedAnd('source.stock_delta', '>', 0)
9 | .thenInsertValues(({ ref }) => ({
10 | name: ref('source.wine_name'),
11 | stock: ref('source.stock_delta'),
12 | }))
13 | .whenMatchedAnd(
14 | (eb) => eb('target.stock', '+', eb.ref('source.stock_delta')),
15 | '>',
16 | 0,
17 | )
18 | .thenUpdateSet('stock', (eb) =>
19 | eb('target.stock', '+', eb.ref('source.stock_delta')),
20 | )
21 | .whenMatched()
22 | .thenDelete()
23 | .executeTakeFirstOrThrow()`
--------------------------------------------------------------------------------
/site/docs/examples/merge/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "MERGE",
3 | "position": 7,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Short and simple examples of how to write MERGE queries."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/examples/select/0010-a-single-column.js:
--------------------------------------------------------------------------------
1 | export const aSingleColumn = `const persons = await db
2 | .selectFrom('person')
3 | .select('id')
4 | .where('first_name', '=', 'Arnold')
5 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0010-a-single-column.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'A single column'
3 | ---
4 |
5 | # A single column
6 |
7 | Select a single column:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | aSingleColumn
13 | } from './0010-a-single-column'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)
26 | - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)
27 | - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)
28 | :::
29 |
--------------------------------------------------------------------------------
/site/docs/examples/select/0020-column-with-a-table.js:
--------------------------------------------------------------------------------
1 | export const columnWithATable = `const persons = await db
2 | .selectFrom(['person', 'pet'])
3 | .select('person.id')
4 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0020-column-with-a-table.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Column with a table'
3 | ---
4 |
5 | # Column with a table
6 |
7 | Select a single column and specify a table:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | columnWithATable
13 | } from './0020-column-with-a-table'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)
26 | - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)
27 | - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)
28 | :::
29 |
--------------------------------------------------------------------------------
/site/docs/examples/select/0030-multiple-columns.js:
--------------------------------------------------------------------------------
1 | export const multipleColumns = `const persons = await db
2 | .selectFrom('person')
3 | .select(['person.id', 'first_name'])
4 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0030-multiple-columns.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Multiple columns'
3 | ---
4 |
5 | # Multiple columns
6 |
7 | Select multiple columns:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | multipleColumns
13 | } from './0030-multiple-columns'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)
26 | - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)
27 | - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)
28 | :::
29 |
--------------------------------------------------------------------------------
/site/docs/examples/select/0040-aliases.js:
--------------------------------------------------------------------------------
1 | export const aliases = `const persons = await db
2 | .selectFrom('person as p')
3 | .select([
4 | 'first_name as fn',
5 | 'p.last_name as ln'
6 | ])
7 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0040-aliases.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Aliases'
3 | ---
4 |
5 | # Aliases
6 |
7 | You can give an alias for selections and tables by appending `as the_alias` to the name:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | aliases
13 | } from './0040-aliases'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)
26 | - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)
27 | - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)
28 | :::
29 |
--------------------------------------------------------------------------------
/site/docs/examples/select/0050-complex-selections.js:
--------------------------------------------------------------------------------
1 | export const complexSelections = `import { sql } from 'kysely'
2 |
3 | const persons = await db.selectFrom('person')
4 | .select(({ eb, selectFrom, or, val, lit }) => [
5 | // Select a correlated subquery
6 | selectFrom('pet')
7 | .whereRef('person.id', '=', 'pet.owner_id')
8 | .select('pet.name')
9 | .orderBy('pet.name')
10 | .limit(1)
11 | .as('first_pet_name'),
12 |
13 | // Build and select an expression using
14 | // the expression builder
15 | or([
16 | eb('first_name', '=', 'Jennifer'),
17 | eb('first_name', '=', 'Arnold')
18 | ]).as('is_jennifer_or_arnold'),
19 |
20 | // Select a raw sql expression
21 | sql\`concat(first_name, ' ', last_name)\`.as('full_name'),
22 |
23 | // Select a static string value
24 | val('Some value').as('string_value'),
25 |
26 | // Select a literal value
27 | lit(42).as('literal_value'),
28 | ])
29 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0051-not-null.js:
--------------------------------------------------------------------------------
1 | export const notNull = `import { NotNull } from 'kysely'
2 | import { jsonObjectFrom } from 'kysely/helpers/postgres'
3 |
4 | const persons = db
5 | .selectFrom('person')
6 | .select((eb) => [
7 | 'last_name',
8 | // Let's assume we know the person has at least one
9 | // pet. We can use the \`.$notNull()\` method to make
10 | // the expression not null. You could just as well
11 | // add \`pet\` to the \`$narrowType\` call below.
12 | jsonObjectFrom(
13 | eb.selectFrom('pet')
14 | .selectAll()
15 | .limit(1)
16 | .whereRef('person.id', '=', 'pet.owner_id')
17 | ).$notNull().as('pet')
18 | ])
19 | .where('last_name', 'is not', null)
20 | // $narrowType can be used to narrow the output type.
21 | // The special \`NotNull\` type can be used to make a
22 | // selection not null. You could add \`pet: NotNull\`
23 | // here and omit the \`$notNull()\` call on it.
24 | // Use whichever way you prefer.
25 | .$narrowType<{ last_name: NotNull }>()
26 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0070-distinct.js:
--------------------------------------------------------------------------------
1 | export const distinct = `const persons = await db.selectFrom('person')
2 | .select('first_name')
3 | .distinct()
4 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0070-distinct.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Distinct'
3 | ---
4 |
5 | # Distinct
6 |
7 | import { Playground } from '../../../src/components/Playground'
8 |
9 | import {
10 | distinct
11 | } from './0070-distinct'
12 |
13 |
16 |
17 | :::info[More examples]
18 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
19 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
20 | just one hover away!
21 |
22 | For example, check out these sections:
23 | - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)
24 | - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)
25 | - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)
26 | :::
27 |
--------------------------------------------------------------------------------
/site/docs/examples/select/0080-distinct-on.js:
--------------------------------------------------------------------------------
1 | export const distinctOn = `const persons = await db.selectFrom('person')
2 | .innerJoin('pet', 'pet.owner_id', 'person.id')
3 | .where('pet.name', '=', 'Doggo')
4 | .distinctOn('person.id')
5 | .selectAll('person')
6 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0080-distinct-on.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Distinct on'
3 | ---
4 |
5 | # Distinct on
6 |
7 | import { Playground } from '../../../src/components/Playground'
8 |
9 | import {
10 | distinctOn
11 | } from './0080-distinct-on'
12 |
13 |
16 |
17 | :::info[More examples]
18 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
19 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
20 | just one hover away!
21 |
22 | For example, check out these sections:
23 | - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)
24 | - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)
25 | - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)
26 | :::
27 |
--------------------------------------------------------------------------------
/site/docs/examples/select/0090-all-columns.js:
--------------------------------------------------------------------------------
1 | export const allColumns = `const persons = await db
2 | .selectFrom('person')
3 | .selectAll()
4 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0090-all-columns.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'All columns'
3 | ---
4 |
5 | # All columns
6 |
7 | The `selectAll` method generates `SELECT *`:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | allColumns
13 | } from './0090-all-columns'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)
26 | - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)
27 | - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)
28 | :::
29 |
--------------------------------------------------------------------------------
/site/docs/examples/select/0100-all-columns-of-a-table.js:
--------------------------------------------------------------------------------
1 | export const allColumnsOfATable = `const persons = await db
2 | .selectFrom('person')
3 | .selectAll('person')
4 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0100-all-columns-of-a-table.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'All columns of a table'
3 | ---
4 |
5 | # All columns of a table
6 |
7 | Select all columns of a table:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | allColumnsOfATable
13 | } from './0100-all-columns-of-a-table'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)
26 | - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)
27 | - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)
28 | :::
29 |
--------------------------------------------------------------------------------
/site/docs/examples/select/0110-nested-array.js:
--------------------------------------------------------------------------------
1 | export const nestedArray = `import { jsonArrayFrom } from 'kysely/helpers/postgres'
2 |
3 | const result = await db
4 | .selectFrom('person')
5 | .select((eb) => [
6 | 'id',
7 | jsonArrayFrom(
8 | eb.selectFrom('pet')
9 | .select(['pet.id as pet_id', 'pet.name'])
10 | .whereRef('pet.owner_id', '=', 'person.id')
11 | .orderBy('pet.name')
12 | ).as('pets')
13 | ])
14 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0120-nested-object.js:
--------------------------------------------------------------------------------
1 | export const nestedObject = `import { jsonObjectFrom } from 'kysely/helpers/postgres'
2 |
3 | const result = await db
4 | .selectFrom('person')
5 | .select((eb) => [
6 | 'id',
7 | jsonObjectFrom(
8 | eb.selectFrom('pet')
9 | .select(['pet.id as pet_id', 'pet.name'])
10 | .whereRef('pet.owner_id', '=', 'person.id')
11 | .where('pet.is_favorite', '=', true)
12 | ).as('favorite_pet')
13 | ])
14 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/select/0130-generic-find-query.js:
--------------------------------------------------------------------------------
1 | export const genericFindQuery = `import { SelectType } from 'kysely'
2 | import { Database } from 'type-editor'
3 |
4 | async function getRowByColumn<
5 | T extends keyof Database,
6 | C extends keyof Database[T] & string,
7 | V extends SelectType,
8 | >(t: T, c: C, v: V) {
9 | // We need to use the dynamic module since the table name
10 | // is not known at compile time.
11 | const { table, ref } = db.dynamic
12 |
13 | return await db
14 | .selectFrom(table(t).as('t'))
15 | .selectAll()
16 | .where(ref(c), '=', v)
17 | .orderBy('t.id')
18 | .executeTakeFirstOrThrow()
19 | }
20 |
21 | const person = await getRowByColumn('person', 'first_name', 'Arnold')`
--------------------------------------------------------------------------------
/site/docs/examples/select/0130-generic-find-query.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Generic find query'
3 | ---
4 |
5 | # Generic find query
6 |
7 | A generic type-safe helper function for finding a row by a column value:
8 |
9 | import {
10 | Playground,
11 | exampleSetup,
12 | } from '../../../src/components/Playground'
13 |
14 | import {
15 | genericFindQuery
16 | } from './0130-generic-find-query'
17 |
18 |
21 |
22 | :::info[More examples]
23 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
24 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
25 | just one hover away!
26 |
27 | For example, check out these sections:
28 | - [select method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#select)
29 | - [selectAll method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#selectAll)
30 | - [selectFrom method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#selectFrom)
31 | :::
32 |
--------------------------------------------------------------------------------
/site/docs/examples/select/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "SELECT",
3 | "position": 1,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Short and simple examples of using the SELECT methods."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/examples/transactions/0010-simple-transaction.js:
--------------------------------------------------------------------------------
1 | export const simpleTransaction = `const catto = await db.transaction().execute(async (trx) => {
2 | const jennifer = await trx.insertInto('person')
3 | .values({
4 | first_name: 'Jennifer',
5 | last_name: 'Aniston',
6 | age: 40,
7 | })
8 | .returning('id')
9 | .executeTakeFirstOrThrow()
10 |
11 | return await trx.insertInto('pet')
12 | .values({
13 | owner_id: jennifer.id,
14 | name: 'Catto',
15 | species: 'cat',
16 | is_favorite: false,
17 | })
18 | .returningAll()
19 | .executeTakeFirst()
20 | })`
--------------------------------------------------------------------------------
/site/docs/examples/transactions/0010-simple-transaction.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Simple transaction'
3 | ---
4 |
5 | # Simple transaction
6 |
7 | This example inserts two rows in a transaction. If an exception is thrown inside
8 | the callback passed to the `execute` method,
9 | 1. the exception is caught,
10 | 2. the transaction is rolled back, and
11 | 3. the exception is thrown again.
12 | Otherwise the transaction is committed.
13 |
14 | import { Playground } from '../../../src/components/Playground'
15 |
16 | import {
17 | simpleTransaction
18 | } from './0010-simple-transaction'
19 |
20 |
23 |
24 | :::info[More examples]
25 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
26 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
27 | just one hover away!
28 |
29 | For example, check out these sections:
30 | - [transaction method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#transaction)
31 | :::
32 |
--------------------------------------------------------------------------------
/site/docs/examples/transactions/0011-controlled-transaction.js:
--------------------------------------------------------------------------------
1 | export const controlledTransaction = `const trx = await db.startTransaction().execute()
2 |
3 | try {
4 | const jennifer = await trx.insertInto('person')
5 | .values({
6 | first_name: 'Jennifer',
7 | last_name: 'Aniston',
8 | age: 40,
9 | })
10 | .returning('id')
11 | .executeTakeFirstOrThrow()
12 |
13 | const catto = await trx.insertInto('pet')
14 | .values({
15 | owner_id: jennifer.id,
16 | name: 'Catto',
17 | species: 'cat',
18 | is_favorite: false,
19 | })
20 | .returningAll()
21 | .executeTakeFirstOrThrow()
22 |
23 | await trx.commit().execute()
24 |
25 | // ...
26 | } catch (error) {
27 | await trx.rollback().execute()
28 | }`
--------------------------------------------------------------------------------
/site/docs/examples/transactions/0011-controlled-transaction.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Controlled transaction'
3 | ---
4 |
5 | # Controlled transaction
6 |
7 | A controlled transaction allows you to commit and rollback manually, execute
8 | savepoint commands, and queries in general.
9 |
10 | In this example we start a transaction, use it to insert two rows and then commit
11 | the transaction. If an error is thrown, we catch it and rollback the transaction.
12 |
13 | import { Playground } from '../../../src/components/Playground'
14 |
15 | import {
16 | controlledTransaction
17 | } from './0011-controlled-transaction'
18 |
19 |
22 |
23 | :::info[More examples]
24 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
25 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
26 | just one hover away!
27 |
28 | For example, check out these sections:
29 | - [transaction method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#transaction)
30 | :::
31 |
--------------------------------------------------------------------------------
/site/docs/examples/transactions/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Transactions",
3 | "position": 8,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Short and simple examples of how to use transactions."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/examples/update/0010-single-row.js:
--------------------------------------------------------------------------------
1 | export const singleRow = `const result = await db
2 | .updateTable('person')
3 | .set({
4 | first_name: 'Jennifer',
5 | last_name: 'Aniston'
6 | })
7 | .where('id', '=', 1)
8 | .executeTakeFirst()`
--------------------------------------------------------------------------------
/site/docs/examples/update/0010-single-row.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Single row'
3 | ---
4 |
5 | # Single row
6 |
7 | Update a row in `person` table:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | singleRow
13 | } from './0010-single-row'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [set method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#set)
26 | - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#returning)
27 | - [updateTable method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#updateTable)
28 | :::
29 |
--------------------------------------------------------------------------------
/site/docs/examples/update/0020-complex-values.js:
--------------------------------------------------------------------------------
1 | export const complexValues = `const result = await db
2 | .updateTable('person')
3 | .set((eb) => ({
4 | age: eb('age', '+', 1),
5 | first_name: eb.selectFrom('pet').select('name').limit(1),
6 | last_name: 'updated',
7 | }))
8 | .where('id', '=', 1)
9 | .executeTakeFirst()`
--------------------------------------------------------------------------------
/site/docs/examples/update/0020-complex-values.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Complex values'
3 | ---
4 |
5 | # Complex values
6 |
7 | As always, you can provide a callback to the `set` method to get access
8 | to an expression builder:
9 |
10 | import { Playground } from '../../../src/components/Playground'
11 |
12 | import {
13 | complexValues
14 | } from './0020-complex-values'
15 |
16 |
19 |
20 | :::info[More examples]
21 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
22 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
23 | just one hover away!
24 |
25 | For example, check out these sections:
26 | - [set method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#set)
27 | - [returning method](https://kysely-org.github.io/kysely-apidoc/classes/UpdateQueryBuilder.html#returning)
28 | - [updateTable method](https://kysely-org.github.io/kysely-apidoc/classes/Kysely.html#updateTable)
29 | :::
30 |
--------------------------------------------------------------------------------
/site/docs/examples/update/0030-my-sql-joins.js:
--------------------------------------------------------------------------------
1 | export const mySqlJoins = `const result = await db
2 | .updateTable(['person', 'pet'])
3 | .set('person.first_name', 'Updated person')
4 | .set('pet.name', 'Updated doggo')
5 | .whereRef('person.id', '=', 'pet.owner_id')
6 | .where('person.id', '=', 1)
7 | .executeTakeFirst()`
--------------------------------------------------------------------------------
/site/docs/examples/update/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "UPDATE",
3 | "position": 5,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Short and simple examples of how to write UPDATE queries."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/examples/where/0010-simple-where-clause.js:
--------------------------------------------------------------------------------
1 | export const simpleWhereClause = `const person = await db
2 | .selectFrom('person')
3 | .selectAll()
4 | .where('first_name', '=', 'Jennifer')
5 | .where('age', '>', 40)
6 | .executeTakeFirst()`
--------------------------------------------------------------------------------
/site/docs/examples/where/0010-simple-where-clause.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Simple where clause'
3 | ---
4 |
5 | # Simple where clause
6 |
7 | `where` method calls are combined with `AND`:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | simpleWhereClause
13 | } from './0010-simple-where-clause'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)
26 | - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)
27 | :::
28 |
--------------------------------------------------------------------------------
/site/docs/examples/where/0020-where-in.js:
--------------------------------------------------------------------------------
1 | export const whereIn = `const persons = await db
2 | .selectFrom('person')
3 | .selectAll()
4 | .where('id', 'in', [1, 2, 3])
5 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/where/0020-where-in.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Where in'
3 | ---
4 |
5 | # Where in
6 |
7 | Find multiple items using a list of identifiers:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | whereIn
13 | } from './0020-where-in'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)
26 | - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)
27 | :::
28 |
--------------------------------------------------------------------------------
/site/docs/examples/where/0030-object-filter.js:
--------------------------------------------------------------------------------
1 | export const objectFilter = `const persons = await db
2 | .selectFrom('person')
3 | .selectAll()
4 | .where((eb) => eb.and({
5 | first_name: 'Jennifer',
6 | last_name: eb.ref('first_name')
7 | }))
8 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/where/0030-object-filter.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Object filter'
3 | ---
4 |
5 | # Object filter
6 |
7 | You can use the `and` function to create a simple equality
8 | filter using an object
9 |
10 | import { Playground } from '../../../src/components/Playground'
11 |
12 | import {
13 | objectFilter
14 | } from './0030-object-filter'
15 |
16 |
19 |
20 | :::info[More examples]
21 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
22 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
23 | just one hover away!
24 |
25 | For example, check out these sections:
26 | - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)
27 | - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)
28 | :::
29 |
--------------------------------------------------------------------------------
/site/docs/examples/where/0040-or-where.js:
--------------------------------------------------------------------------------
1 | export const orWhere = `const persons = await db
2 | .selectFrom('person')
3 | .selectAll()
4 | // 1. Using the \`or\` method on the expression builder:
5 | .where((eb) => eb.or([
6 | eb('first_name', '=', 'Jennifer'),
7 | eb('first_name', '=', 'Sylvester')
8 | ]))
9 | // 2. Chaining expressions using the \`or\` method on the
10 | // created expressions:
11 | .where((eb) =>
12 | eb('last_name', '=', 'Aniston').or('last_name', '=', 'Stallone')
13 | )
14 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/where/0040-or-where.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'OR where'
3 | ---
4 |
5 | # OR where
6 |
7 | To combine conditions using `OR`, you can use the expression builder.
8 | There are two ways to create `OR` expressions. Both are shown in this
9 | example:
10 |
11 | import { Playground } from '../../../src/components/Playground'
12 |
13 | import {
14 | orWhere
15 | } from './0040-or-where'
16 |
17 |
20 |
21 | :::info[More examples]
22 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
23 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
24 | just one hover away!
25 |
26 | For example, check out these sections:
27 | - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)
28 | - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)
29 | :::
30 |
--------------------------------------------------------------------------------
/site/docs/examples/where/0050-conditional-where-calls.js:
--------------------------------------------------------------------------------
1 | export const conditionalWhereCalls = `import { Expression, SqlBool } from 'kysely'
2 |
3 | const firstName: string | undefined = 'Jennifer'
4 | const lastName: string | undefined = 'Aniston'
5 | const under18 = true
6 | const over60 = true
7 |
8 | let query = db
9 | .selectFrom('person')
10 | .selectAll()
11 |
12 | if (firstName) {
13 | // The query builder is immutable. Remember to reassign
14 | // the result back to the query variable.
15 | query = query.where('first_name', '=', firstName)
16 | }
17 |
18 | if (lastName) {
19 | query = query.where('last_name', '=', lastName)
20 | }
21 |
22 | if (under18 || over60) {
23 | // Conditional OR expressions can be added like this.
24 | query = query.where((eb) => {
25 | const ors: Expression[] = []
26 |
27 | if (under18) {
28 | ors.push(eb('age', '<', 18))
29 | }
30 |
31 | if (over60) {
32 | ors.push(eb('age', '>', 60))
33 | }
34 |
35 | return eb.or(ors)
36 | })
37 | }
38 |
39 | const persons = await query.execute()`
--------------------------------------------------------------------------------
/site/docs/examples/where/0050-conditional-where-calls.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Conditional where calls'
3 | ---
4 |
5 | # Conditional where calls
6 |
7 | You can add expressions conditionally like this:
8 |
9 | import { Playground } from '../../../src/components/Playground'
10 |
11 | import {
12 | conditionalWhereCalls
13 | } from './0050-conditional-where-calls'
14 |
15 |
18 |
19 | :::info[More examples]
20 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
21 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
22 | just one hover away!
23 |
24 | For example, check out these sections:
25 | - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)
26 | - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)
27 | :::
28 |
--------------------------------------------------------------------------------
/site/docs/examples/where/0060-complex-where-clause.js:
--------------------------------------------------------------------------------
1 | export const complexWhereClause = `const firstName = 'Jennifer'
2 | const maxAge = 60
3 |
4 | const persons = await db
5 | .selectFrom('person')
6 | .selectAll('person')
7 | .where(({ eb, or, and, not, exists, selectFrom }) => and([
8 | or([
9 | eb('first_name', '=', firstName),
10 | eb('age', '<', maxAge)
11 | ]),
12 | not(exists(
13 | selectFrom('pet')
14 | .select('pet.id')
15 | .whereRef('pet.owner_id', '=', 'person.id')
16 | ))
17 | ]))
18 | .execute()`
--------------------------------------------------------------------------------
/site/docs/examples/where/0060-complex-where-clause.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Complex where clause'
3 | ---
4 |
5 | # Complex where clause
6 |
7 | For complex `where` expressions you can pass in a single callback and
8 | use the `ExpressionBuilder` to build your expression:
9 |
10 | import { Playground } from '../../../src/components/Playground'
11 |
12 | import {
13 | complexWhereClause
14 | } from './0060-complex-where-clause'
15 |
16 |
19 |
20 | :::info[More examples]
21 | The API documentation is packed with examples. The API docs are hosted [here](https://kysely-org.github.io/kysely-apidoc/),
22 | but you can access the same documentation by hovering over functions/methods/classes in your IDE. The examples are always
23 | just one hover away!
24 |
25 | For example, check out these sections:
26 | - [where method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#where)
27 | - [whereRef method](https://kysely-org.github.io/kysely-apidoc/interfaces/SelectQueryBuilder.html#whereRef)
28 | :::
29 |
--------------------------------------------------------------------------------
/site/docs/examples/where/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "WHERE",
3 | "position": 2,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Short and simple examples of how to use the where method to add a WHERE statement. While most of the examples show a SELECT query, the where method works exactly the same in UPDATE and DELETE queries too."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/getting-started/IUseADifferentDatabase.tsx:
--------------------------------------------------------------------------------
1 | import Link from '@docusaurus/Link'
2 | import { PRETTY_DIALECT_NAMES, type PropsWithDialect } from './shared'
3 |
4 | export function IUseADifferentDatabase(props: PropsWithDialect) {
5 | const dialectName = PRETTY_DIALECT_NAMES[props.dialect || 'postgresql']
6 |
7 | return (
8 |
9 |
10 | I use a different database (not {dialectName})
11 |
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/site/docs/getting-started/IUseADifferentPackageManager.tsx:
--------------------------------------------------------------------------------
1 | import Link from '@docusaurus/Link'
2 | import { PRETTY_PACKAGE_MANAGER_NAMES, type PackageManager } from './shared'
3 |
4 | export interface IUseADifferentPackageManagerProps {
5 | packageManager: PackageManager | undefined
6 | packageManagersURL: string
7 | }
8 |
9 | export function IUseADifferentPackageManager(
10 | props: IUseADifferentPackageManagerProps,
11 | ) {
12 | const packageManagerName =
13 | PRETTY_PACKAGE_MANAGER_NAMES[props.packageManager || 'npm']
14 |
15 | return (
16 |
17 |
18 | I use a different package manager (not {packageManagerName})
19 |
20 |
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/site/docs/getting-started/_prerequisites.mdx:
--------------------------------------------------------------------------------
1 | - [TypeScript](https://www.typescriptlang.org/) version 4.6 or later is supported for type-safety. For better autocompletion experience and compilation performance use version 5.3 or later.
2 |
3 | - You must enable `strict` mode in your `tsconfig.json` file's `compilerOptions`.
4 |
5 | ```ts title="tsconfig.json"
6 | {
7 | // ...
8 | "compilerOptions": {
9 | // ...
10 | "strict": true
11 | // ...
12 | }
13 | // ...
14 | }
15 | ```
16 |
--------------------------------------------------------------------------------
/site/docs/playground.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | sidebar_position: 3
3 | ---
4 |
5 | # Playground
6 |
7 | [@wirekang](https://github.com/wirekang) has created a [playground for Kysely](https://kyse.link). You can use it to quickly test stuff out and for creating code examples for your issues, PRs and Discord messages.
8 |
9 | import { Playground } from '../src/components/Playground'
10 |
11 |
19 |
20 | ## Codesandbox
21 |
22 | We also have a minimal [code sandbox example](https://codesandbox.io/s/kysely-demo-9l099t?file=/src/index.tsx:0-36).
23 |
--------------------------------------------------------------------------------
/site/docs/plugins.md:
--------------------------------------------------------------------------------
1 | # Plugin system
2 |
3 | Plugins are classes that implement [KyselyPlugin](https://kysely-org.github.io/kysely-apidoc/interfaces/KyselyPlugin.html). Plugins are then added to the `Kysely` instance as follows:
4 |
5 | ```ts
6 | const db = new Kysely({
7 | dialect: new PostgresDialect({
8 | database: 'kysely_test',
9 | host: 'localhost',
10 | }),
11 | plugins: [new CamelCasePlugin()],
12 | })
13 | ```
14 |
15 | ## Built-in plugins
16 |
17 | ### Camel case plugin
18 |
19 | A plugin that converts snake_case identifiers in the database into camelCase in the JavaScript side. [Learn more](https://kysely-org.github.io/kysely-apidoc/classes/CamelCasePlugin.html).
20 |
21 | ### Deduplicate joins plugin
22 |
23 | A plugin that removes duplicate joins from queries. You can read more about it in the [examples](/docs/recipes/deduplicate-joins) section or check the [API docs](https://kysely-org.github.io/kysely-apidoc/classes/DeduplicateJoinsPlugin.html).
24 |
25 | ### Handle `in ()` and `not in ()` plugin
26 |
27 | A plugin that allows handling `in ()` and `not in ()` with a chosen strategy. [Learn more](https://kysely-org.github.io/kysely-apidoc/classes/HandleEmptyInListsPlugin.html).
28 |
--------------------------------------------------------------------------------
/site/docs/recipes/0003-raw-sql.md:
--------------------------------------------------------------------------------
1 | # Raw SQL
2 |
3 | You can execute raw SQL strings and pass raw SQL snippets to pretty much any method or function
4 | using the [sql template tag](https://kysely-org.github.io/kysely-apidoc/interfaces/Sql.html).
5 |
--------------------------------------------------------------------------------
/site/docs/recipes/0011-introspecting-relation-metadata.md:
--------------------------------------------------------------------------------
1 | # Introspecting relation metadata
2 |
3 | Extracting metadata about tables and views from your database schema in runtime is possible using the methods in the `instrospection` property of a `Kysely` instance.
4 |
5 | The example below uses a PostgreSQL connection to print information about all tables and views found in the database schema:
6 |
7 | ```ts
8 | import { Kysely, PostgresDialect } from 'kysely'
9 | import pg from 'pg'
10 | const { Pool } = pg
11 |
12 | async function logDatabaseSchema() {
13 | const db = new Kysely({
14 | dialect: new PostgresDialect({
15 | pool: new Pool({
16 | connectionString: process.env.DATABASE_URL,
17 | }),
18 | }),
19 | })
20 |
21 | const tables = await db.introspection.getTables()
22 | // ^? TableMetadata[]
23 |
24 | console.log({ tables })
25 | }
26 |
27 | logDatabaseSchema()
28 | ```
29 |
30 | For more information check the docs for details on the interfaces [DatabaseIntrospector](https://kysely-org.github.io/kysely-apidoc/interfaces/DatabaseIntrospector.html) and [TableMetadata](https://kysely-org.github.io/kysely-apidoc/interfaces/TableMetadata.html).
31 |
--------------------------------------------------------------------------------
/site/docs/recipes/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Recipes",
3 | "position": 6,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "A list of guides or recipes explaning how to use various features of the library. These are more advanced topics, make sure you familiriaze yourself with the examples first."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/runtimes/_category_.json:
--------------------------------------------------------------------------------
1 | {
2 | "label": "Other runtimes",
3 | "position": 10,
4 | "link": {
5 | "type": "generated-index",
6 | "description": "Kysely works on the browser, Node.js and Deno. Here are some examples of how to use it."
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/site/docs/runtimes/browser.md:
--------------------------------------------------------------------------------
1 | # Browser
2 |
3 | Kysely also runs in the browser. Here's a minimal example:
4 |
5 | ```ts
6 | import {
7 | Kysely,
8 | Generated,
9 | DummyDriver,
10 | SqliteAdapter,
11 | SqliteIntrospector,
12 | SqliteQueryCompiler,
13 | } from 'kysely'
14 |
15 | interface Person {
16 | id: Generated
17 | first_name: string
18 | last_name: string | null
19 | }
20 |
21 | interface Database {
22 | person: Person
23 | }
24 |
25 | const db = new Kysely({
26 | dialect: {
27 | createAdapter() {
28 | return new SqliteAdapter()
29 | },
30 | createDriver() {
31 | return new DummyDriver()
32 | },
33 | createIntrospector(db: Kysely) {
34 | return new SqliteIntrospector(db)
35 | },
36 | createQueryCompiler() {
37 | return new SqliteQueryCompiler()
38 | },
39 | },
40 | })
41 |
42 | window.addEventListener('load', () => {
43 | const sql = db.selectFrom('person').select('id').compile()
44 |
45 | const result = document.createElement('span')
46 | result.id = 'result'
47 | result.innerHTML = sql.sql
48 |
49 | document.body.appendChild(result)
50 | })
51 | ```
52 |
--------------------------------------------------------------------------------
/site/sidebars.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Creating a sidebar enables you to:
3 | - create an ordered group of docs
4 | - render a sidebar for each doc of that group
5 | - provide next/previous navigation
6 |
7 | The sidebars can be generated from the filesystem, or explicitly defined here.
8 |
9 | Create as many sidebars as you want.
10 | */
11 |
12 | // @ts-check
13 |
14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
15 | const sidebars = {
16 | // By default, Docusaurus generates a sidebar from the docs folder structure
17 | tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }],
18 |
19 | // But you can create a sidebar manually
20 | /*
21 | tutorialSidebar: [
22 | 'intro',
23 | 'hello',
24 | {
25 | type: 'category',
26 | label: 'Tutorial',
27 | items: ['tutorial-basics/create-a-document'],
28 | },
29 | ],
30 | */
31 | }
32 |
33 | module.exports = sidebars
34 |
--------------------------------------------------------------------------------
/site/src/components/DemoVideo.module.css:
--------------------------------------------------------------------------------
1 | .videoContainer {
2 | width: 100%;
3 | max-width: 832px;
4 | height: 0;
5 | padding-bottom: 55.59%;
6 | position: relative;
7 | overflow: hidden;
8 | }
9 |
10 | .videoContainer video {
11 | position: absolute;
12 | top: 0;
13 | width: fit-content;
14 | height: 100%;
15 | background: #1d1d1d;
16 | left: 50%;
17 | transform: translateX(-50%);
18 | max-height: 610px;
19 | border-radius: 12px;
20 | box-shadow: var(--shadow-elevation-medium);
21 | }
22 |
--------------------------------------------------------------------------------
/site/src/components/DemoVideo.tsx:
--------------------------------------------------------------------------------
1 | import styles from './DemoVideo.module.css'
2 |
3 | export function DemoVideo() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/site/src/components/Playground.module.css:
--------------------------------------------------------------------------------
1 | .playground {
2 | border: 1px solid var(--gray3);
3 | border-radius: 7px;
4 | min-height: 600px;
5 | width: 100%;
6 | }
7 |
--------------------------------------------------------------------------------
/site/src/components/SectionFeatures/styles.module.css:
--------------------------------------------------------------------------------
1 | .features {
2 | display: flex;
3 | align-items: center;
4 | width: 100%;
5 | position: relative;
6 | min-height: 80vh;
7 | padding: 64px 0;
8 | }
9 |
10 | [data-theme='dark'] .features {
11 | background-color: var(--gray12);
12 | }
13 |
14 | .featureTitle {
15 | align-items: center;
16 | color: var(--gray12);
17 | display: inline-flex;
18 | gap: 8px;
19 | }
20 |
21 | [data-theme='dark'] .featureTitle {
22 | color: var(--gray4);
23 | }
24 |
25 | .tickContainer {
26 | background-color: var(--sky7);
27 | border: 1px solid var(--sky10);
28 | border-radius: 100%;
29 | display: grid;
30 | font-size: 12px;
31 | height: 20px;
32 | place-items: center;
33 | width: 20px;
34 | }
35 |
36 | .tickIcon {
37 | height: 12px;
38 | fill: var(--sky12);
39 | width: 12px;
40 | }
41 |
42 | .featureDescription {
43 | color: var(--gray11);
44 | }
45 |
46 | [data-theme='dark'] .featureDescription {
47 | color: var(--gray8);
48 | }
49 |
--------------------------------------------------------------------------------
/site/src/components/SectionQuotes/index.tsx:
--------------------------------------------------------------------------------
1 | import clsx from 'clsx'
2 |
3 | import { Quote } from './Quote'
4 | import { quotes } from './quotes'
5 | import styles from './styles.module.css'
6 |
7 | export function SectionQuotes() {
8 | return (
9 |
10 |
11 |
What the internet is saying
12 |
Developers are loving Kysely for its simplicity and power.
13 |
14 | {quotes.map((quote, index) => (
15 |
16 | ))}
17 |
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/site/src/components/SectionQuotes/reddit.module.css:
--------------------------------------------------------------------------------
1 | .snoo1 {
2 | fill: url(#snoo-radial-gragient) white;
3 | }
4 |
5 | .snoo1,
6 | .snoo2,
7 | .snoo3,
8 | .snoo4,
9 | .snoo5,
10 | .snoo6,
11 | .snoo7,
12 | .snoo8,
13 | .snoo9,
14 | .snoo10,
15 | .snoo11 {
16 | stroke-width: 0px;
17 | }
18 |
19 | .snoo2 {
20 | fill: url(#snoo-radial-gragient-2) white;
21 | }
22 |
23 | .snoo3 {
24 | fill: url(#snoo-radial-gragient-3) white;
25 | }
26 |
27 | .snoo4 {
28 | fill: url(#snoo-radial-gragient-4) #fc4301;
29 | }
30 |
31 | .snoo5 {
32 | fill: url(#snoo-radial-gragient-6) black;
33 | }
34 |
35 | .snoo6 {
36 | fill: url(#snoo-radial-gragient-8) black;
37 | }
38 |
39 | .snoo7 {
40 | fill: url(#snoo-radial-gragient-5) #fc4301;
41 | }
42 |
43 | .snoo8 {
44 | fill: url(#snoo-radial-gragient-7) white;
45 | }
46 |
47 | .snoo9 {
48 | fill: #842123;
49 | }
50 |
51 | .snoo10 {
52 | fill: #ff4500;
53 | }
54 |
55 | .snoo11 {
56 | fill: #ffc49c;
57 | }
58 |
--------------------------------------------------------------------------------
/site/static/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/.nojekyll
--------------------------------------------------------------------------------
/site/static/demo.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/demo.mp4
--------------------------------------------------------------------------------
/site/static/img/avatars/alberto.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/alberto.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/alexanderson.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/alexanderson.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/bekacru.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/bekacru.png
--------------------------------------------------------------------------------
/site/static/img/avatars/benholmes.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/benholmes.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/capaj.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/capaj.png
--------------------------------------------------------------------------------
/site/static/img/avatars/catalin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/catalin.png
--------------------------------------------------------------------------------
/site/static/img/avatars/daxraad.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/daxraad.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/gal.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/gal.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/gannon.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/gannon.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/gudmundur.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/gudmundur.png
--------------------------------------------------------------------------------
/site/static/img/avatars/guga.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/guga.png
--------------------------------------------------------------------------------
/site/static/img/avatars/harminder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/harminder.png
--------------------------------------------------------------------------------
/site/static/img/avatars/johan.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/johan.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/julius.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/julius.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/leerob.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/leerob.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/marvin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/marvin.png
--------------------------------------------------------------------------------
/site/static/img/avatars/marvinh.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/marvinh.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/mehul.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/mehul.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/nexxel.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/nexxel.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/nicholas.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/nicholas.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/niels.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/niels.png
--------------------------------------------------------------------------------
/site/static/img/avatars/orta.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/orta.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/pilcrowonpaper.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/pilcrowonpaper.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/ross.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/ross.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/samcook.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/samcook.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/sommelier.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/sommelier.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/tgriesser.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/tgriesser.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/theo.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/theo.jpeg
--------------------------------------------------------------------------------
/site/static/img/avatars/yusuke.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/avatars/yusuke.jpeg
--------------------------------------------------------------------------------
/site/static/img/docusaurus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/docusaurus.png
--------------------------------------------------------------------------------
/site/static/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/site/static/img/favicon.ico
--------------------------------------------------------------------------------
/site/static/img/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/site/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // This file is not used in compilation. It is here just for a nice editor experience.
3 | "extends": "@docusaurus/tsconfig",
4 | "compilerOptions": {
5 | "baseUrl": ".",
6 | "resolveJsonModule": true
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/dialect/dialect-adapter-base.ts:
--------------------------------------------------------------------------------
1 | import { Kysely } from '../kysely.js'
2 | import { DialectAdapter, MigrationLockOptions } from './dialect-adapter.js'
3 |
4 | /**
5 | * A basic implementation of `DialectAdapter` with sensible default values.
6 | * Third-party dialects can extend this instead of implementing the `DialectAdapter`
7 | * interface from scratch. That way all new settings will get default values when
8 | * they are added and there will be less breaking changes.
9 | */
10 | export abstract class DialectAdapterBase implements DialectAdapter {
11 | get supportsCreateIfNotExists(): boolean {
12 | return true
13 | }
14 |
15 | get supportsTransactionalDdl(): boolean {
16 | return false
17 | }
18 |
19 | get supportsReturning(): boolean {
20 | return false
21 | }
22 |
23 | get supportsOutput(): boolean {
24 | return false
25 | }
26 |
27 | abstract acquireMigrationLock(
28 | db: Kysely,
29 | options: MigrationLockOptions,
30 | ): Promise
31 |
32 | abstract releaseMigrationLock(
33 | db: Kysely,
34 | options: MigrationLockOptions,
35 | ): Promise
36 | }
37 |
--------------------------------------------------------------------------------
/src/dialect/postgres/postgres-query-compiler.ts:
--------------------------------------------------------------------------------
1 | import { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js'
2 |
3 | const ID_WRAP_REGEX = /"/g
4 |
5 | export class PostgresQueryCompiler extends DefaultQueryCompiler {
6 | protected override sanitizeIdentifier(identifier: string): string {
7 | return identifier.replace(ID_WRAP_REGEX, '""')
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/dialect/sqlite/sqlite-adapter.ts:
--------------------------------------------------------------------------------
1 | import { Kysely } from '../../kysely.js'
2 | import { DialectAdapterBase } from '../dialect-adapter-base.js'
3 | import { MigrationLockOptions } from '../dialect-adapter.js'
4 |
5 | export class SqliteAdapter extends DialectAdapterBase {
6 | override get supportsTransactionalDdl(): boolean {
7 | return false
8 | }
9 |
10 | override get supportsReturning(): boolean {
11 | return true
12 | }
13 |
14 | override async acquireMigrationLock(
15 | _db: Kysely,
16 | _opt: MigrationLockOptions,
17 | ): Promise {
18 | // SQLite only has one connection that's reserved by the migration system
19 | // for the whole time between acquireMigrationLock and releaseMigrationLock.
20 | // We don't need to do anything here.
21 | }
22 |
23 | override async releaseMigrationLock(
24 | _db: Kysely,
25 | _opt: MigrationLockOptions,
26 | ): Promise {
27 | // SQLite only has one connection that's reserved by the migration system
28 | // for the whole time between acquireMigrationLock and releaseMigrationLock.
29 | // We don't need to do anything here.
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/driver/connection-provider.ts:
--------------------------------------------------------------------------------
1 | import { DatabaseConnection } from './database-connection.js'
2 |
3 | export interface ConnectionProvider {
4 | /**
5 | * Provides a connection for the callback and takes care of disposing
6 | * the connection after the callback has been run.
7 | */
8 | provideConnection(
9 | consumer: (connection: DatabaseConnection) => Promise,
10 | ): Promise
11 | }
12 |
--------------------------------------------------------------------------------
/src/driver/default-connection-provider.ts:
--------------------------------------------------------------------------------
1 | import { DatabaseConnection } from './database-connection.js'
2 | import { ConnectionProvider } from './connection-provider.js'
3 | import { Driver } from './driver.js'
4 |
5 | export class DefaultConnectionProvider implements ConnectionProvider {
6 | readonly #driver: Driver
7 |
8 | constructor(driver: Driver) {
9 | this.#driver = driver
10 | }
11 |
12 | async provideConnection(
13 | consumer: (connection: DatabaseConnection) => Promise,
14 | ): Promise {
15 | const connection = await this.#driver.acquireConnection()
16 |
17 | try {
18 | return await consumer(connection)
19 | } finally {
20 | await this.#driver.releaseConnection(connection)
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/operation-node/add-column-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { ColumnDefinitionNode } from './column-definition-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export interface AddColumnNode extends OperationNode {
6 | readonly kind: 'AddColumnNode'
7 | readonly column: ColumnDefinitionNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const AddColumnNode = freeze({
14 | is(node: OperationNode): node is AddColumnNode {
15 | return node.kind === 'AddColumnNode'
16 | },
17 |
18 | create(column: ColumnDefinitionNode): AddColumnNode {
19 | return freeze({
20 | kind: 'AddColumnNode',
21 | column,
22 | })
23 | },
24 | })
25 |
--------------------------------------------------------------------------------
/src/operation-node/add-constraint-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 | import { ConstraintNode } from './constraint-node.js'
4 |
5 | export interface AddConstraintNode extends OperationNode {
6 | readonly kind: 'AddConstraintNode'
7 | readonly constraint: ConstraintNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const AddConstraintNode = freeze({
14 | is(node: OperationNode): node is AddConstraintNode {
15 | return node.kind === 'AddConstraintNode'
16 | },
17 |
18 | create(constraint: ConstraintNode): AddConstraintNode {
19 | return freeze({
20 | kind: 'AddConstraintNode',
21 | constraint,
22 | })
23 | },
24 | })
25 |
--------------------------------------------------------------------------------
/src/operation-node/alias-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface AliasNode extends OperationNode {
5 | readonly kind: 'AliasNode'
6 | readonly node: OperationNode
7 | readonly alias: OperationNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const AliasNode = freeze({
14 | is(node: OperationNode): node is AliasNode {
15 | return node.kind === 'AliasNode'
16 | },
17 |
18 | create(node: OperationNode, alias: OperationNode): AliasNode {
19 | return freeze({
20 | kind: 'AliasNode',
21 | node,
22 | alias,
23 | })
24 | },
25 | })
26 |
--------------------------------------------------------------------------------
/src/operation-node/alter-column-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 | import { ColumnNode } from './column-node.js'
4 | import { RawNode } from './raw-node.js'
5 |
6 | export type AlterColumnNodeProps = Omit
7 |
8 | export interface AlterColumnNode extends OperationNode {
9 | readonly kind: 'AlterColumnNode'
10 | readonly column: ColumnNode
11 | readonly dataType?: OperationNode
12 | readonly dataTypeExpression?: RawNode
13 | readonly setDefault?: OperationNode
14 | readonly dropDefault?: true
15 | readonly setNotNull?: true
16 | readonly dropNotNull?: true
17 | }
18 |
19 | /**
20 | * @internal
21 | */
22 | export const AlterColumnNode = freeze({
23 | is(node: OperationNode): node is AlterColumnNode {
24 | return node.kind === 'AlterColumnNode'
25 | },
26 |
27 | create(
28 | column: string,
29 | prop: T,
30 | value: Required[T],
31 | ): AlterColumnNode {
32 | return freeze({
33 | kind: 'AlterColumnNode',
34 | column: ColumnNode.create(column),
35 | [prop]: value,
36 | })
37 | },
38 | })
39 |
--------------------------------------------------------------------------------
/src/operation-node/and-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 |
4 | export interface AndNode extends OperationNode {
5 | readonly kind: 'AndNode'
6 | readonly left: OperationNode
7 | readonly right: OperationNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const AndNode = freeze({
14 | is(node: OperationNode): node is AndNode {
15 | return node.kind === 'AndNode'
16 | },
17 |
18 | create(left: OperationNode, right: OperationNode): AndNode {
19 | return freeze({
20 | kind: 'AndNode',
21 | left,
22 | right,
23 | })
24 | },
25 | })
26 |
--------------------------------------------------------------------------------
/src/operation-node/binary-operation-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface BinaryOperationNode extends OperationNode {
5 | readonly kind: 'BinaryOperationNode'
6 | readonly leftOperand: OperationNode
7 | readonly operator: OperationNode
8 | readonly rightOperand: OperationNode
9 | }
10 |
11 | /**
12 | * @internal
13 | */
14 | export const BinaryOperationNode = freeze({
15 | is(node: OperationNode): node is BinaryOperationNode {
16 | return node.kind === 'BinaryOperationNode'
17 | },
18 |
19 | create(
20 | leftOperand: OperationNode,
21 | operator: OperationNode,
22 | rightOperand: OperationNode,
23 | ): BinaryOperationNode {
24 | return freeze({
25 | kind: 'BinaryOperationNode',
26 | leftOperand,
27 | operator,
28 | rightOperand,
29 | })
30 | },
31 | })
32 |
--------------------------------------------------------------------------------
/src/operation-node/cast-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 |
4 | export interface CastNode extends OperationNode {
5 | readonly kind: 'CastNode'
6 | readonly expression: OperationNode
7 | readonly dataType: OperationNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const CastNode = freeze({
14 | is(node: OperationNode): node is CastNode {
15 | return node.kind === 'CastNode'
16 | },
17 |
18 | create(expression: OperationNode, dataType: OperationNode): CastNode {
19 | return freeze({
20 | kind: 'CastNode',
21 | expression,
22 | dataType,
23 | })
24 | },
25 | })
26 |
--------------------------------------------------------------------------------
/src/operation-node/check-constraint-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 | import { IdentifierNode } from './identifier-node.js'
4 |
5 | export interface CheckConstraintNode extends OperationNode {
6 | readonly kind: 'CheckConstraintNode'
7 | readonly expression: OperationNode
8 | readonly name?: IdentifierNode
9 | }
10 |
11 | /**
12 | * @internal
13 | */
14 | export const CheckConstraintNode = freeze({
15 | is(node: OperationNode): node is CheckConstraintNode {
16 | return node.kind === 'CheckConstraintNode'
17 | },
18 |
19 | create(
20 | expression: OperationNode,
21 | constraintName?: string,
22 | ): CheckConstraintNode {
23 | return freeze({
24 | kind: 'CheckConstraintNode',
25 | expression,
26 | name: constraintName ? IdentifierNode.create(constraintName) : undefined,
27 | })
28 | },
29 | })
30 |
--------------------------------------------------------------------------------
/src/operation-node/collate-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { IdentifierNode } from './identifier-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export interface CollateNode extends OperationNode {
6 | readonly kind: 'CollateNode'
7 | readonly collation: IdentifierNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const CollateNode = {
14 | is(node: OperationNode): node is CollateNode {
15 | return node.kind === 'CollateNode'
16 | },
17 |
18 | create(collation: string): CollateNode {
19 | return freeze({
20 | kind: 'CollateNode',
21 | collation: IdentifierNode.create(collation),
22 | })
23 | },
24 | }
25 |
--------------------------------------------------------------------------------
/src/operation-node/column-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { IdentifierNode } from './identifier-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export interface ColumnNode extends OperationNode {
6 | readonly kind: 'ColumnNode'
7 | readonly column: IdentifierNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const ColumnNode = freeze({
14 | is(node: OperationNode): node is ColumnNode {
15 | return node.kind === 'ColumnNode'
16 | },
17 |
18 | create(column: string): ColumnNode {
19 | return freeze({
20 | kind: 'ColumnNode',
21 | column: IdentifierNode.create(column),
22 | })
23 | },
24 | })
25 |
--------------------------------------------------------------------------------
/src/operation-node/column-update-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface ColumnUpdateNode extends OperationNode {
5 | readonly kind: 'ColumnUpdateNode'
6 | readonly column: OperationNode
7 | readonly value: OperationNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const ColumnUpdateNode = freeze({
14 | is(node: OperationNode): node is ColumnUpdateNode {
15 | return node.kind === 'ColumnUpdateNode'
16 | },
17 |
18 | create(column: OperationNode, value: OperationNode): ColumnUpdateNode {
19 | return freeze({
20 | kind: 'ColumnUpdateNode',
21 | column,
22 | value,
23 | })
24 | },
25 | })
26 |
--------------------------------------------------------------------------------
/src/operation-node/common-table-expression-name-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { ColumnNode } from './column-node.js'
3 | import { OperationNode } from './operation-node.js'
4 | import { TableNode } from './table-node.js'
5 |
6 | export interface CommonTableExpressionNameNode extends OperationNode {
7 | readonly kind: 'CommonTableExpressionNameNode'
8 | readonly table: TableNode
9 | readonly columns?: ReadonlyArray
10 | }
11 |
12 | /**
13 | * @internal
14 | */
15 | export const CommonTableExpressionNameNode = freeze({
16 | is(node: OperationNode): node is CommonTableExpressionNameNode {
17 | return node.kind === 'CommonTableExpressionNameNode'
18 | },
19 |
20 | create(
21 | tableName: string,
22 | columnNames?: ReadonlyArray,
23 | ): CommonTableExpressionNameNode {
24 | return freeze({
25 | kind: 'CommonTableExpressionNameNode',
26 | table: TableNode.create(tableName),
27 | columns: columnNames
28 | ? freeze(columnNames.map(ColumnNode.create))
29 | : undefined,
30 | })
31 | },
32 | })
33 |
--------------------------------------------------------------------------------
/src/operation-node/constraint-node.ts:
--------------------------------------------------------------------------------
1 | import { CheckConstraintNode } from './check-constraint-node.js'
2 | import { ForeignKeyConstraintNode } from './foreign-key-constraint-node.js'
3 | import { PrimaryKeyConstraintNode } from './primary-key-constraint-node.js'
4 | import { UniqueConstraintNode } from './unique-constraint-node.js'
5 |
6 | export type ConstraintNode =
7 | | PrimaryKeyConstraintNode
8 | | UniqueConstraintNode
9 | | CheckConstraintNode
10 | | ForeignKeyConstraintNode
11 |
--------------------------------------------------------------------------------
/src/operation-node/create-schema-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { IdentifierNode } from './identifier-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export type CreateSchemaNodeParams = Omit<
6 | Partial,
7 | 'kind' | 'schema'
8 | >
9 |
10 | export interface CreateSchemaNode extends OperationNode {
11 | readonly kind: 'CreateSchemaNode'
12 | readonly schema: IdentifierNode
13 | readonly ifNotExists?: boolean
14 | }
15 |
16 | /**
17 | * @internal
18 | */
19 | export const CreateSchemaNode = freeze({
20 | is(node: OperationNode): node is CreateSchemaNode {
21 | return node.kind === 'CreateSchemaNode'
22 | },
23 |
24 | create(schema: string, params?: CreateSchemaNodeParams): CreateSchemaNode {
25 | return freeze({
26 | kind: 'CreateSchemaNode',
27 | schema: IdentifierNode.create(schema),
28 | ...params,
29 | })
30 | },
31 |
32 | cloneWith(
33 | createSchema: CreateSchemaNode,
34 | params: CreateSchemaNodeParams,
35 | ): CreateSchemaNode {
36 | return freeze({
37 | ...createSchema,
38 | ...params,
39 | })
40 | },
41 | })
42 |
--------------------------------------------------------------------------------
/src/operation-node/create-type-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { SchemableIdentifierNode } from './schemable-identifier-node.js'
4 | import { ValueListNode } from './value-list-node.js'
5 | import { ValueNode } from './value-node.js'
6 |
7 | export type CreateTypeNodeParams = Omit, 'kind'>
8 |
9 | export interface CreateTypeNode extends OperationNode {
10 | readonly kind: 'CreateTypeNode'
11 | readonly name: SchemableIdentifierNode
12 | readonly enum?: ValueListNode
13 | }
14 |
15 | /**
16 | * @internal
17 | */
18 | export const CreateTypeNode = freeze({
19 | is(node: OperationNode): node is CreateTypeNode {
20 | return node.kind === 'CreateTypeNode'
21 | },
22 |
23 | create(name: SchemableIdentifierNode): CreateTypeNode {
24 | return freeze({
25 | kind: 'CreateTypeNode',
26 | name,
27 | })
28 | },
29 |
30 | cloneWithEnum(
31 | createType: CreateTypeNode,
32 | values: readonly string[],
33 | ): CreateTypeNode {
34 | return freeze({
35 | ...createType,
36 | enum: ValueListNode.create(values.map(ValueNode.createImmediate)),
37 | })
38 | },
39 | })
40 |
--------------------------------------------------------------------------------
/src/operation-node/default-insert-value-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface DefaultInsertValueNode extends OperationNode {
5 | readonly kind: 'DefaultInsertValueNode'
6 | }
7 |
8 | /**
9 | * @internal
10 | */
11 | export const DefaultInsertValueNode = freeze({
12 | is(node: OperationNode): node is DefaultInsertValueNode {
13 | return node.kind === 'DefaultInsertValueNode'
14 | },
15 |
16 | create(): DefaultInsertValueNode {
17 | return freeze({
18 | kind: 'DefaultInsertValueNode',
19 | })
20 | },
21 | })
22 |
--------------------------------------------------------------------------------
/src/operation-node/default-value-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface DefaultValueNode extends OperationNode {
5 | readonly kind: 'DefaultValueNode'
6 | readonly defaultValue: OperationNode
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const DefaultValueNode = freeze({
13 | is(node: OperationNode): node is DefaultValueNode {
14 | return node.kind === 'DefaultValueNode'
15 | },
16 |
17 | create(defaultValue: OperationNode): DefaultValueNode {
18 | return freeze({
19 | kind: 'DefaultValueNode',
20 | defaultValue,
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/drop-column-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 | import { ColumnNode } from './column-node.js'
4 |
5 | export interface DropColumnNode extends OperationNode {
6 | readonly kind: 'DropColumnNode'
7 | readonly column: ColumnNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const DropColumnNode = freeze({
14 | is(node: OperationNode): node is DropColumnNode {
15 | return node.kind === 'DropColumnNode'
16 | },
17 |
18 | create(column: string): DropColumnNode {
19 | return freeze({
20 | kind: 'DropColumnNode',
21 | column: ColumnNode.create(column),
22 | })
23 | },
24 | })
25 |
--------------------------------------------------------------------------------
/src/operation-node/drop-constraint-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 | import { IdentifierNode } from './identifier-node.js'
4 |
5 | export type DropConstraintNodeProps = Omit<
6 | DropConstraintNode,
7 | 'kind' | 'constraintName'
8 | >
9 |
10 | export interface DropConstraintNode extends OperationNode {
11 | readonly kind: 'DropConstraintNode'
12 | readonly constraintName: IdentifierNode
13 | readonly ifExists?: boolean
14 | readonly modifier?: 'cascade' | 'restrict'
15 | }
16 |
17 | /**
18 | * @internal
19 | */
20 | export const DropConstraintNode = freeze({
21 | is(node: OperationNode): node is DropConstraintNode {
22 | return node.kind === 'DropConstraintNode'
23 | },
24 |
25 | create(constraintName: string): DropConstraintNode {
26 | return freeze({
27 | kind: 'DropConstraintNode',
28 | constraintName: IdentifierNode.create(constraintName),
29 | })
30 | },
31 |
32 | cloneWith(
33 | dropConstraint: DropConstraintNode,
34 | props: DropConstraintNodeProps,
35 | ): DropConstraintNode {
36 | return freeze({
37 | ...dropConstraint,
38 | ...props,
39 | })
40 | },
41 | })
42 |
--------------------------------------------------------------------------------
/src/operation-node/drop-schema-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { IdentifierNode } from './identifier-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export type DropSchemaNodeParams = Omit<
6 | Partial,
7 | 'kind' | 'schema'
8 | >
9 |
10 | export interface DropSchemaNode extends OperationNode {
11 | readonly kind: 'DropSchemaNode'
12 | readonly schema: IdentifierNode
13 | readonly ifExists?: boolean
14 | readonly cascade?: boolean
15 | }
16 |
17 | /**
18 | * @internal
19 | */
20 | export const DropSchemaNode = freeze({
21 | is(node: OperationNode): node is DropSchemaNode {
22 | return node.kind === 'DropSchemaNode'
23 | },
24 |
25 | create(schema: string, params?: DropSchemaNodeParams): DropSchemaNode {
26 | return freeze({
27 | kind: 'DropSchemaNode',
28 | schema: IdentifierNode.create(schema),
29 | ...params,
30 | })
31 | },
32 |
33 | cloneWith(
34 | dropSchema: DropSchemaNode,
35 | params: DropSchemaNodeParams,
36 | ): DropSchemaNode {
37 | return freeze({
38 | ...dropSchema,
39 | ...params,
40 | })
41 | },
42 | })
43 |
--------------------------------------------------------------------------------
/src/operation-node/drop-table-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { TableNode } from './table-node.js'
4 |
5 | export type DropTablexNodeParams = Omit<
6 | Partial,
7 | 'kind' | 'table'
8 | >
9 | export interface DropTableNode extends OperationNode {
10 | readonly kind: 'DropTableNode'
11 | readonly table: TableNode
12 | readonly ifExists?: boolean
13 | readonly cascade?: boolean
14 | }
15 |
16 | /**
17 | * @internal
18 | */
19 | export const DropTableNode = freeze({
20 | is(node: OperationNode): node is DropTableNode {
21 | return node.kind === 'DropTableNode'
22 | },
23 |
24 | create(table: TableNode, params?: DropTablexNodeParams): DropTableNode {
25 | return freeze({
26 | kind: 'DropTableNode',
27 | table,
28 | ...params,
29 | })
30 | },
31 |
32 | cloneWith(
33 | dropIndex: DropTableNode,
34 | params: DropTablexNodeParams,
35 | ): DropTableNode {
36 | return freeze({
37 | ...dropIndex,
38 | ...params,
39 | })
40 | },
41 | })
42 |
--------------------------------------------------------------------------------
/src/operation-node/drop-type-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { SchemableIdentifierNode } from './schemable-identifier-node.js'
4 |
5 | export type DropTypeNodeParams = Omit, 'kind' | 'name'>
6 |
7 | export interface DropTypeNode extends OperationNode {
8 | readonly kind: 'DropTypeNode'
9 | readonly name: SchemableIdentifierNode
10 | readonly ifExists?: boolean
11 | }
12 |
13 | /**
14 | * @internal
15 | */
16 | export const DropTypeNode = freeze({
17 | is(node: OperationNode): node is DropTypeNode {
18 | return node.kind === 'DropTypeNode'
19 | },
20 |
21 | create(name: SchemableIdentifierNode): DropTypeNode {
22 | return freeze({
23 | kind: 'DropTypeNode',
24 | name,
25 | })
26 | },
27 |
28 | cloneWith(dropType: DropTypeNode, params: DropTypeNodeParams): DropTypeNode {
29 | return freeze({
30 | ...dropType,
31 | ...params,
32 | })
33 | },
34 | })
35 |
--------------------------------------------------------------------------------
/src/operation-node/drop-view-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { SchemableIdentifierNode } from './schemable-identifier-node.js'
4 |
5 | export type DropViewNodeParams = Omit, 'kind' | 'name'>
6 |
7 | export interface DropViewNode extends OperationNode {
8 | readonly kind: 'DropViewNode'
9 | readonly name: SchemableIdentifierNode
10 | readonly ifExists?: boolean
11 | readonly materialized?: boolean
12 | readonly cascade?: boolean
13 | }
14 |
15 | /**
16 | * @internal
17 | */
18 | export const DropViewNode = freeze({
19 | is(node: OperationNode): node is DropViewNode {
20 | return node.kind === 'DropViewNode'
21 | },
22 |
23 | create(name: string): DropViewNode {
24 | return freeze({
25 | kind: 'DropViewNode',
26 | name: SchemableIdentifierNode.create(name),
27 | })
28 | },
29 |
30 | cloneWith(dropView: DropViewNode, params: DropViewNodeParams): DropViewNode {
31 | return freeze({
32 | ...dropView,
33 | ...params,
34 | })
35 | },
36 | })
37 |
--------------------------------------------------------------------------------
/src/operation-node/explain-node.ts:
--------------------------------------------------------------------------------
1 | import { ExplainFormat } from '../util/explainable.js'
2 | import { freeze } from '../util/object-utils.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export interface ExplainNode extends OperationNode {
6 | readonly kind: 'ExplainNode'
7 | readonly format?: ExplainFormat
8 | readonly options?: OperationNode
9 | }
10 |
11 | /**
12 | * @internal
13 | */
14 | export const ExplainNode = freeze({
15 | is(node: OperationNode): node is ExplainNode {
16 | return node.kind === 'ExplainNode'
17 | },
18 |
19 | create(format?: ExplainFormat, options?: OperationNode): ExplainNode {
20 | return freeze({
21 | kind: 'ExplainNode',
22 | format,
23 | options,
24 | })
25 | },
26 | })
27 |
--------------------------------------------------------------------------------
/src/operation-node/fetch-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { ValueNode } from './value-node.js'
3 |
4 | export type FetchModifier = 'only' | 'with ties'
5 |
6 | export interface FetchNode extends OperationNode {
7 | readonly kind: 'FetchNode'
8 | readonly rowCount: ValueNode
9 | readonly modifier: FetchModifier
10 | }
11 |
12 | /**
13 | * @internal
14 | */
15 | export const FetchNode = {
16 | is(node: OperationNode): node is FetchNode {
17 | return node.kind === 'FetchNode'
18 | },
19 |
20 | create(rowCount: number | bigint, modifier: FetchModifier): FetchNode {
21 | return {
22 | kind: 'FetchNode',
23 | rowCount: ValueNode.create(rowCount),
24 | modifier,
25 | }
26 | },
27 | }
28 |
--------------------------------------------------------------------------------
/src/operation-node/from-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface FromNode extends OperationNode {
5 | readonly kind: 'FromNode'
6 | readonly froms: ReadonlyArray
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const FromNode = freeze({
13 | is(node: OperationNode): node is FromNode {
14 | return node.kind === 'FromNode'
15 | },
16 |
17 | create(froms: ReadonlyArray): FromNode {
18 | return freeze({
19 | kind: 'FromNode',
20 | froms: freeze(froms),
21 | })
22 | },
23 |
24 | cloneWithFroms(
25 | from: FromNode,
26 | froms: ReadonlyArray,
27 | ): FromNode {
28 | return freeze({
29 | ...from,
30 | froms: freeze([...from.froms, ...froms]),
31 | })
32 | },
33 | })
34 |
--------------------------------------------------------------------------------
/src/operation-node/function-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface FunctionNode extends OperationNode {
5 | readonly kind: 'FunctionNode'
6 | readonly func: string
7 | readonly arguments: ReadonlyArray
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const FunctionNode = freeze({
14 | is(node: OperationNode): node is FunctionNode {
15 | return node.kind === 'FunctionNode'
16 | },
17 |
18 | create(func: string, args: ReadonlyArray): FunctionNode {
19 | return freeze({
20 | kind: 'FunctionNode',
21 | func,
22 | arguments: args,
23 | })
24 | },
25 | })
26 |
--------------------------------------------------------------------------------
/src/operation-node/group-by-item-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface GroupByItemNode extends OperationNode {
5 | readonly kind: 'GroupByItemNode'
6 | readonly groupBy: OperationNode
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const GroupByItemNode = freeze({
13 | is(node: OperationNode): node is GroupByItemNode {
14 | return node.kind === 'GroupByItemNode'
15 | },
16 |
17 | create(groupBy: OperationNode): GroupByItemNode {
18 | return freeze({
19 | kind: 'GroupByItemNode',
20 | groupBy,
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/group-by-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { GroupByItemNode } from './group-by-item-node.js'
4 |
5 | export interface GroupByNode extends OperationNode {
6 | readonly kind: 'GroupByNode'
7 | readonly items: ReadonlyArray
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const GroupByNode = freeze({
14 | is(node: OperationNode): node is GroupByNode {
15 | return node.kind === 'GroupByNode'
16 | },
17 |
18 | create(items: ReadonlyArray): GroupByNode {
19 | return freeze({
20 | kind: 'GroupByNode',
21 | items: freeze(items),
22 | })
23 | },
24 |
25 | cloneWithItems(
26 | groupBy: GroupByNode,
27 | items: ReadonlyArray,
28 | ): GroupByNode {
29 | return freeze({
30 | ...groupBy,
31 | items: freeze([...groupBy.items, ...items]),
32 | })
33 | },
34 | })
35 |
--------------------------------------------------------------------------------
/src/operation-node/having-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { AndNode } from './and-node.js'
3 | import { OperationNode } from './operation-node.js'
4 | import { OrNode } from './or-node.js'
5 |
6 | export interface HavingNode extends OperationNode {
7 | readonly kind: 'HavingNode'
8 | readonly having: OperationNode
9 | }
10 |
11 | /**
12 | * @internal
13 | */
14 | export const HavingNode = freeze({
15 | is(node: OperationNode): node is HavingNode {
16 | return node.kind === 'HavingNode'
17 | },
18 |
19 | create(filter: OperationNode): HavingNode {
20 | return freeze({
21 | kind: 'HavingNode',
22 | having: filter,
23 | })
24 | },
25 |
26 | cloneWithOperation(
27 | havingNode: HavingNode,
28 | operator: 'And' | 'Or',
29 | operation: OperationNode,
30 | ): HavingNode {
31 | return freeze({
32 | ...havingNode,
33 | having:
34 | operator === 'And'
35 | ? AndNode.create(havingNode.having, operation)
36 | : OrNode.create(havingNode.having, operation),
37 | })
38 | },
39 | })
40 |
--------------------------------------------------------------------------------
/src/operation-node/identifier-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface IdentifierNode extends OperationNode {
5 | readonly kind: 'IdentifierNode'
6 | readonly name: string
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const IdentifierNode = freeze({
13 | is(node: OperationNode): node is IdentifierNode {
14 | return node.kind === 'IdentifierNode'
15 | },
16 |
17 | create(name: string): IdentifierNode {
18 | return freeze({
19 | kind: 'IdentifierNode',
20 | name,
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/json-operator-chain-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { OperatorNode } from './operator-node.js'
4 | import { ValueNode } from './value-node.js'
5 |
6 | export interface JSONOperatorChainNode extends OperationNode {
7 | readonly kind: 'JSONOperatorChainNode'
8 | readonly operator: OperatorNode
9 | readonly values: readonly ValueNode[]
10 | }
11 |
12 | /**
13 | * @internal
14 | */
15 | export const JSONOperatorChainNode = freeze({
16 | is(node: OperationNode): node is JSONOperatorChainNode {
17 | return node.kind === 'JSONOperatorChainNode'
18 | },
19 |
20 | create(operator: OperatorNode): JSONOperatorChainNode {
21 | return freeze({
22 | kind: 'JSONOperatorChainNode',
23 | operator,
24 | values: freeze([]),
25 | })
26 | },
27 |
28 | cloneWithValue(
29 | node: JSONOperatorChainNode,
30 | value: ValueNode,
31 | ): JSONOperatorChainNode {
32 | return freeze({
33 | ...node,
34 | values: freeze([...node.values, value]),
35 | })
36 | },
37 | })
38 |
--------------------------------------------------------------------------------
/src/operation-node/json-path-leg-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export type JSONPathLegType = 'Member' | 'ArrayLocation'
5 |
6 | export interface JSONPathLegNode extends OperationNode {
7 | readonly kind: 'JSONPathLegNode'
8 | readonly type: JSONPathLegType
9 | readonly value: string | number
10 | }
11 |
12 | /**
13 | * @internal
14 | */
15 | export const JSONPathLegNode = freeze({
16 | is(node: OperationNode): node is JSONPathLegNode {
17 | return node.kind === 'JSONPathLegNode'
18 | },
19 |
20 | create(type: JSONPathLegType, value: string | number): JSONPathLegNode {
21 | return freeze({
22 | kind: 'JSONPathLegNode',
23 | type,
24 | value,
25 | })
26 | },
27 | })
28 |
--------------------------------------------------------------------------------
/src/operation-node/json-path-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { JSONPathLegNode } from './json-path-leg-node.js'
3 | import { OperationNode } from './operation-node.js'
4 | import { OperatorNode } from './operator-node.js'
5 |
6 | export interface JSONPathNode extends OperationNode {
7 | readonly kind: 'JSONPathNode'
8 | readonly inOperator?: OperatorNode
9 | readonly pathLegs: ReadonlyArray
10 | }
11 |
12 | /**
13 | * @internal
14 | */
15 | export const JSONPathNode = freeze({
16 | is(node: OperationNode): node is JSONPathNode {
17 | return node.kind === 'JSONPathNode'
18 | },
19 |
20 | create(inOperator?: OperatorNode): JSONPathNode {
21 | return freeze({
22 | kind: 'JSONPathNode',
23 | inOperator,
24 | pathLegs: freeze([]),
25 | })
26 | },
27 |
28 | cloneWithLeg(
29 | jsonPathNode: JSONPathNode,
30 | pathLeg: JSONPathLegNode,
31 | ): JSONPathNode {
32 | return freeze({
33 | ...jsonPathNode,
34 | pathLegs: freeze([...jsonPathNode.pathLegs, pathLeg]),
35 | })
36 | },
37 | })
38 |
--------------------------------------------------------------------------------
/src/operation-node/limit-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface LimitNode extends OperationNode {
5 | readonly kind: 'LimitNode'
6 | readonly limit: OperationNode
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const LimitNode = freeze({
13 | is(node: OperationNode): node is LimitNode {
14 | return node.kind === 'LimitNode'
15 | },
16 |
17 | create(limit: OperationNode): LimitNode {
18 | return freeze({
19 | kind: 'LimitNode',
20 | limit,
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/list-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface ListNode extends OperationNode {
5 | readonly kind: 'ListNode'
6 | readonly items: ReadonlyArray
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const ListNode = freeze({
13 | is(node: OperationNode): node is ListNode {
14 | return node.kind === 'ListNode'
15 | },
16 |
17 | create(items: ReadonlyArray): ListNode {
18 | return freeze({
19 | kind: 'ListNode',
20 | items: freeze(items),
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/matched-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface MatchedNode extends OperationNode {
5 | readonly kind: 'MatchedNode'
6 | readonly not: boolean
7 | readonly bySource: boolean
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const MatchedNode = freeze({
14 | is(node: OperationNode): node is MatchedNode {
15 | return node.kind === 'MatchedNode'
16 | },
17 |
18 | create(not: boolean, bySource: boolean = false): MatchedNode {
19 | return freeze({
20 | kind: 'MatchedNode',
21 | not,
22 | bySource,
23 | })
24 | },
25 | })
26 |
--------------------------------------------------------------------------------
/src/operation-node/modify-column-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { ColumnDefinitionNode } from './column-definition-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export interface ModifyColumnNode extends OperationNode {
6 | readonly kind: 'ModifyColumnNode'
7 | readonly column: ColumnDefinitionNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const ModifyColumnNode = freeze({
14 | is(node: OperationNode): node is ModifyColumnNode {
15 | return node.kind === 'ModifyColumnNode'
16 | },
17 |
18 | create(column: ColumnDefinitionNode): ModifyColumnNode {
19 | return freeze({
20 | kind: 'ModifyColumnNode',
21 | column,
22 | })
23 | },
24 | })
25 |
--------------------------------------------------------------------------------
/src/operation-node/offset-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface OffsetNode extends OperationNode {
5 | readonly kind: 'OffsetNode'
6 | readonly offset: OperationNode
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const OffsetNode = freeze({
13 | is(node: OperationNode): node is OffsetNode {
14 | return node.kind === 'OffsetNode'
15 | },
16 |
17 | create(offset: OperationNode): OffsetNode {
18 | return freeze({
19 | kind: 'OffsetNode',
20 | offset,
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/on-duplicate-key-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { ColumnUpdateNode } from './column-update-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export type OnDuplicateKeyNodeProps = Omit
6 |
7 | export interface OnDuplicateKeyNode extends OperationNode {
8 | readonly kind: 'OnDuplicateKeyNode'
9 | readonly updates: ReadonlyArray
10 | }
11 |
12 | /**
13 | * @internal
14 | */
15 | export const OnDuplicateKeyNode = freeze({
16 | is(node: OperationNode): node is OnDuplicateKeyNode {
17 | return node.kind === 'OnDuplicateKeyNode'
18 | },
19 |
20 | create(updates: ReadonlyArray): OnDuplicateKeyNode {
21 | return freeze({
22 | kind: 'OnDuplicateKeyNode',
23 | updates,
24 | })
25 | },
26 | })
27 |
--------------------------------------------------------------------------------
/src/operation-node/on-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { AndNode } from './and-node.js'
3 | import { OperationNode } from './operation-node.js'
4 | import { OrNode } from './or-node.js'
5 |
6 | export interface OnNode extends OperationNode {
7 | readonly kind: 'OnNode'
8 | readonly on: OperationNode
9 | }
10 |
11 | /**
12 | * @internal
13 | */
14 | export const OnNode = freeze({
15 | is(node: OperationNode): node is OnNode {
16 | return node.kind === 'OnNode'
17 | },
18 |
19 | create(filter: OperationNode): OnNode {
20 | return freeze({
21 | kind: 'OnNode',
22 | on: filter,
23 | })
24 | },
25 |
26 | cloneWithOperation(
27 | onNode: OnNode,
28 | operator: 'And' | 'Or',
29 | operation: OperationNode,
30 | ): OnNode {
31 | return freeze({
32 | ...onNode,
33 | on:
34 | operator === 'And'
35 | ? AndNode.create(onNode.on, operation)
36 | : OrNode.create(onNode.on, operation),
37 | })
38 | },
39 | })
40 |
--------------------------------------------------------------------------------
/src/operation-node/operation-node-source.ts:
--------------------------------------------------------------------------------
1 | import { isFunction, isObject } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface OperationNodeSource {
5 | toOperationNode(): OperationNode
6 | }
7 |
8 | export function isOperationNodeSource(
9 | obj: unknown,
10 | ): obj is OperationNodeSource {
11 | return isObject(obj) && isFunction(obj.toOperationNode)
12 | }
13 |
--------------------------------------------------------------------------------
/src/operation-node/or-action-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface OrActionNode extends OperationNode {
5 | readonly kind: 'OrActionNode'
6 | readonly action: string
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const OrActionNode = freeze({
13 | is(node: OperationNode): node is OrActionNode {
14 | return node.kind === 'OrActionNode'
15 | },
16 |
17 | create(action: string): OrActionNode {
18 | return freeze({
19 | kind: 'OrActionNode',
20 | action,
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/or-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface OrNode extends OperationNode {
5 | readonly kind: 'OrNode'
6 | readonly left: OperationNode
7 | readonly right: OperationNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const OrNode = freeze({
14 | is(node: OperationNode): node is OrNode {
15 | return node.kind === 'OrNode'
16 | },
17 |
18 | create(left: OperationNode, right: OperationNode): OrNode {
19 | return freeze({
20 | kind: 'OrNode',
21 | left,
22 | right,
23 | })
24 | },
25 | })
26 |
--------------------------------------------------------------------------------
/src/operation-node/order-by-item-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { CollateNode } from './collate-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export type OrderByItemNodeProps = Omit
6 |
7 | export interface OrderByItemNode extends OperationNode {
8 | readonly kind: 'OrderByItemNode'
9 | readonly orderBy: OperationNode
10 | readonly direction?: OperationNode
11 | readonly nulls?: 'first' | 'last'
12 | readonly collation?: CollateNode
13 | }
14 |
15 | /**
16 | * @internal
17 | */
18 | export const OrderByItemNode = freeze({
19 | is(node: OperationNode): node is OrderByItemNode {
20 | return node.kind === 'OrderByItemNode'
21 | },
22 |
23 | create(orderBy: OperationNode, direction?: OperationNode): OrderByItemNode {
24 | return freeze({
25 | kind: 'OrderByItemNode',
26 | orderBy,
27 | direction,
28 | })
29 | },
30 |
31 | cloneWith(
32 | node: OrderByItemNode,
33 | props: OrderByItemNodeProps,
34 | ): OrderByItemNode {
35 | return freeze({
36 | ...node,
37 | ...props,
38 | })
39 | },
40 | })
41 |
--------------------------------------------------------------------------------
/src/operation-node/order-by-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { OrderByItemNode } from './order-by-item-node.js'
4 |
5 | export interface OrderByNode extends OperationNode {
6 | readonly kind: 'OrderByNode'
7 | readonly items: ReadonlyArray
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const OrderByNode = freeze({
14 | is(node: OperationNode): node is OrderByNode {
15 | return node.kind === 'OrderByNode'
16 | },
17 |
18 | create(items: ReadonlyArray): OrderByNode {
19 | return freeze({
20 | kind: 'OrderByNode',
21 | items: freeze([...items]),
22 | })
23 | },
24 |
25 | cloneWithItems(
26 | orderBy: OrderByNode,
27 | items: ReadonlyArray,
28 | ): OrderByNode {
29 | return freeze({
30 | ...orderBy,
31 | items: freeze([...orderBy.items, ...items]),
32 | })
33 | },
34 | })
35 |
--------------------------------------------------------------------------------
/src/operation-node/output-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface OutputNode extends OperationNode {
5 | readonly kind: 'OutputNode'
6 | readonly selections: ReadonlyArray
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const OutputNode = freeze({
13 | is(node: OperationNode): node is OutputNode {
14 | return node.kind === 'OutputNode'
15 | },
16 |
17 | create(selections: ReadonlyArray): OutputNode {
18 | return freeze({
19 | kind: 'OutputNode',
20 | selections: freeze(selections),
21 | })
22 | },
23 |
24 | cloneWithSelections(
25 | output: OutputNode,
26 | selections: ReadonlyArray,
27 | ): OutputNode {
28 | return freeze({
29 | ...output,
30 | selections: output.selections
31 | ? freeze([...output.selections, ...selections])
32 | : freeze(selections),
33 | })
34 | },
35 | })
36 |
--------------------------------------------------------------------------------
/src/operation-node/parens-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 |
4 | export interface ParensNode extends OperationNode {
5 | readonly kind: 'ParensNode'
6 | readonly node: OperationNode
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const ParensNode = freeze({
13 | is(node: OperationNode): node is ParensNode {
14 | return node.kind === 'ParensNode'
15 | },
16 |
17 | create(node: OperationNode): ParensNode {
18 | return freeze({
19 | kind: 'ParensNode',
20 | node,
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/partition-by-item-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { SimpleReferenceExpressionNode } from './simple-reference-expression-node.js'
4 |
5 | export interface PartitionByItemNode extends OperationNode {
6 | readonly kind: 'PartitionByItemNode'
7 | readonly partitionBy: SimpleReferenceExpressionNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const PartitionByItemNode = freeze({
14 | is(node: OperationNode): node is PartitionByItemNode {
15 | return node.kind === 'PartitionByItemNode'
16 | },
17 |
18 | create(partitionBy: SimpleReferenceExpressionNode): PartitionByItemNode {
19 | return freeze({
20 | kind: 'PartitionByItemNode',
21 | partitionBy,
22 | })
23 | },
24 | })
25 |
--------------------------------------------------------------------------------
/src/operation-node/partition-by-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { PartitionByItemNode } from './partition-by-item-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export interface PartitionByNode extends OperationNode {
6 | readonly kind: 'PartitionByNode'
7 | readonly items: ReadonlyArray
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const PartitionByNode = freeze({
14 | is(node: OperationNode): node is PartitionByNode {
15 | return node.kind === 'PartitionByNode'
16 | },
17 |
18 | create(items: ReadonlyArray): PartitionByNode {
19 | return freeze({
20 | kind: 'PartitionByNode',
21 | items: freeze(items),
22 | })
23 | },
24 |
25 | cloneWithItems(
26 | partitionBy: PartitionByNode,
27 | items: ReadonlyArray,
28 | ): PartitionByNode {
29 | return freeze({
30 | ...partitionBy,
31 | items: freeze([...partitionBy.items, ...items]),
32 | })
33 | },
34 | })
35 |
--------------------------------------------------------------------------------
/src/operation-node/primitive-value-list-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | /**
5 | * This node is basically just a performance optimization over the normal ValueListNode.
6 | * The queries often contain large arrays of primitive values (for example in a `where in` list)
7 | * and we don't want to create a ValueNode for each item in those lists.
8 | */
9 | export interface PrimitiveValueListNode extends OperationNode {
10 | readonly kind: 'PrimitiveValueListNode'
11 | readonly values: ReadonlyArray
12 | }
13 |
14 | /**
15 | * @internal
16 | */
17 | export const PrimitiveValueListNode = freeze({
18 | is(node: OperationNode): node is PrimitiveValueListNode {
19 | return node.kind === 'PrimitiveValueListNode'
20 | },
21 |
22 | create(values: ReadonlyArray): PrimitiveValueListNode {
23 | return freeze({
24 | kind: 'PrimitiveValueListNode',
25 | values: freeze([...values]),
26 | })
27 | },
28 | })
29 |
--------------------------------------------------------------------------------
/src/operation-node/raw-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface RawNode extends OperationNode {
5 | readonly kind: 'RawNode'
6 | readonly sqlFragments: ReadonlyArray
7 | readonly parameters: ReadonlyArray
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const RawNode = freeze({
14 | is(node: OperationNode): node is RawNode {
15 | return node.kind === 'RawNode'
16 | },
17 |
18 | create(
19 | sqlFragments: ReadonlyArray,
20 | parameters: ReadonlyArray,
21 | ): RawNode {
22 | return freeze({
23 | kind: 'RawNode',
24 | sqlFragments: freeze(sqlFragments),
25 | parameters: freeze(parameters),
26 | })
27 | },
28 |
29 | createWithSql(sql: string): RawNode {
30 | return RawNode.create([sql], [])
31 | },
32 |
33 | createWithChild(child: OperationNode): RawNode {
34 | return RawNode.create(['', ''], [child])
35 | },
36 |
37 | createWithChildren(children: ReadonlyArray): RawNode {
38 | return RawNode.create(new Array(children.length + 1).fill(''), children)
39 | },
40 | })
41 |
--------------------------------------------------------------------------------
/src/operation-node/reference-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { ColumnNode } from './column-node.js'
3 | import { TableNode } from './table-node.js'
4 | import { SelectAllNode } from './select-all-node.js'
5 | import { freeze } from '../util/object-utils.js'
6 |
7 | export interface ReferenceNode extends OperationNode {
8 | readonly kind: 'ReferenceNode'
9 | readonly column: ColumnNode | SelectAllNode
10 | readonly table?: TableNode
11 | }
12 |
13 | /**
14 | * @internal
15 | */
16 | export const ReferenceNode = freeze({
17 | is(node: OperationNode): node is ReferenceNode {
18 | return node.kind === 'ReferenceNode'
19 | },
20 |
21 | create(column: ColumnNode, table?: TableNode): ReferenceNode {
22 | return freeze({
23 | kind: 'ReferenceNode',
24 | table,
25 | column,
26 | })
27 | },
28 |
29 | createSelectAll(table: TableNode): ReferenceNode {
30 | return freeze({
31 | kind: 'ReferenceNode',
32 | table,
33 | column: SelectAllNode.create(),
34 | })
35 | },
36 | })
37 |
--------------------------------------------------------------------------------
/src/operation-node/rename-column-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 | import { ColumnNode } from './column-node.js'
4 |
5 | export interface RenameColumnNode extends OperationNode {
6 | readonly kind: 'RenameColumnNode'
7 | readonly column: ColumnNode
8 | readonly renameTo: ColumnNode
9 | }
10 |
11 | /**
12 | * @internal
13 | */
14 | export const RenameColumnNode = freeze({
15 | is(node: OperationNode): node is RenameColumnNode {
16 | return node.kind === 'RenameColumnNode'
17 | },
18 |
19 | create(column: string, newColumn: string): RenameColumnNode {
20 | return freeze({
21 | kind: 'RenameColumnNode',
22 | column: ColumnNode.create(column),
23 | renameTo: ColumnNode.create(newColumn),
24 | })
25 | },
26 | })
27 |
--------------------------------------------------------------------------------
/src/operation-node/rename-constraint-node.ts:
--------------------------------------------------------------------------------
1 | import { OperationNode } from './operation-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 | import { IdentifierNode } from './identifier-node.js'
4 |
5 | export interface RenameConstraintNode extends OperationNode {
6 | readonly kind: 'RenameConstraintNode'
7 | readonly oldName: IdentifierNode
8 | readonly newName: IdentifierNode
9 | }
10 |
11 | /**
12 | * @internal
13 | */
14 | export const RenameConstraintNode = freeze({
15 | is(node: OperationNode): node is RenameConstraintNode {
16 | return node.kind === 'RenameConstraintNode'
17 | },
18 |
19 | create(oldName: string, newName: string): RenameConstraintNode {
20 | return freeze({
21 | kind: 'RenameConstraintNode',
22 | oldName: IdentifierNode.create(oldName),
23 | newName: IdentifierNode.create(newName),
24 | })
25 | },
26 | })
27 |
--------------------------------------------------------------------------------
/src/operation-node/returning-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { SelectionNode } from './selection-node.js'
4 |
5 | export interface ReturningNode extends OperationNode {
6 | readonly kind: 'ReturningNode'
7 | readonly selections: ReadonlyArray
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const ReturningNode = freeze({
14 | is(node: OperationNode): node is ReturningNode {
15 | return node.kind === 'ReturningNode'
16 | },
17 |
18 | create(selections: ReadonlyArray): ReturningNode {
19 | return freeze({
20 | kind: 'ReturningNode',
21 | selections: freeze(selections),
22 | })
23 | },
24 |
25 | cloneWithSelections(
26 | returning: ReturningNode,
27 | selections: ReadonlyArray,
28 | ): ReturningNode {
29 | return freeze({
30 | ...returning,
31 | selections: returning.selections
32 | ? freeze([...returning.selections, ...selections])
33 | : freeze(selections),
34 | })
35 | },
36 | })
37 |
--------------------------------------------------------------------------------
/src/operation-node/schemable-identifier-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { IdentifierNode } from './identifier-node.js'
3 | import { OperationNode } from './operation-node.js'
4 |
5 | export interface SchemableIdentifierNode extends OperationNode {
6 | readonly kind: 'SchemableIdentifierNode'
7 | readonly schema?: IdentifierNode
8 | readonly identifier: IdentifierNode
9 | }
10 |
11 | /**
12 | * @internal
13 | */
14 | export const SchemableIdentifierNode = freeze({
15 | is(node: OperationNode): node is SchemableIdentifierNode {
16 | return node.kind === 'SchemableIdentifierNode'
17 | },
18 |
19 | create(identifier: string): SchemableIdentifierNode {
20 | return freeze({
21 | kind: 'SchemableIdentifierNode',
22 | identifier: IdentifierNode.create(identifier),
23 | })
24 | },
25 |
26 | createWithSchema(
27 | schema: string,
28 | identifier: string,
29 | ): SchemableIdentifierNode {
30 | return freeze({
31 | kind: 'SchemableIdentifierNode',
32 | schema: IdentifierNode.create(schema),
33 | identifier: IdentifierNode.create(identifier),
34 | })
35 | },
36 | })
37 |
--------------------------------------------------------------------------------
/src/operation-node/select-all-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface SelectAllNode extends OperationNode {
5 | readonly kind: 'SelectAllNode'
6 | }
7 |
8 | /**
9 | * @internal
10 | */
11 | export const SelectAllNode = freeze({
12 | is(node: OperationNode): node is SelectAllNode {
13 | return node.kind === 'SelectAllNode'
14 | },
15 |
16 | create(): SelectAllNode {
17 | return freeze({
18 | kind: 'SelectAllNode',
19 | })
20 | },
21 | })
22 |
--------------------------------------------------------------------------------
/src/operation-node/set-operation-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export type SetOperator = 'union' | 'intersect' | 'except'
5 |
6 | export interface SetOperationNode extends OperationNode {
7 | kind: 'SetOperationNode'
8 | operator: SetOperator
9 | expression: OperationNode
10 | all: boolean
11 | }
12 |
13 | /**
14 | * @internal
15 | */
16 | export const SetOperationNode = freeze({
17 | is(node: OperationNode): node is SetOperationNode {
18 | return node.kind === 'SetOperationNode'
19 | },
20 |
21 | create(
22 | operator: SetOperator,
23 | expression: OperationNode,
24 | all: boolean,
25 | ): SetOperationNode {
26 | return freeze({
27 | kind: 'SetOperationNode',
28 | operator,
29 | expression,
30 | all,
31 | })
32 | },
33 | })
34 |
--------------------------------------------------------------------------------
/src/operation-node/simple-reference-expression-node.ts:
--------------------------------------------------------------------------------
1 | import { ColumnNode } from './column-node.js'
2 | import { ReferenceNode } from './reference-node.js'
3 |
4 | export type SimpleReferenceExpressionNode = ColumnNode | ReferenceNode
5 |
--------------------------------------------------------------------------------
/src/operation-node/table-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { SchemableIdentifierNode } from './schemable-identifier-node.js'
4 |
5 | export interface TableNode extends OperationNode {
6 | readonly kind: 'TableNode'
7 | readonly table: SchemableIdentifierNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const TableNode = freeze({
14 | is(node: OperationNode): node is TableNode {
15 | return node.kind === 'TableNode'
16 | },
17 |
18 | create(table: string): TableNode {
19 | return freeze({
20 | kind: 'TableNode',
21 | table: SchemableIdentifierNode.create(table),
22 | })
23 | },
24 |
25 | createWithSchema(schema: string, table: string): TableNode {
26 | return freeze({
27 | kind: 'TableNode',
28 | table: SchemableIdentifierNode.createWithSchema(schema, table),
29 | })
30 | },
31 | })
32 |
--------------------------------------------------------------------------------
/src/operation-node/top-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export type TopModifier = 'percent' | 'with ties' | 'percent with ties'
5 |
6 | export interface TopNode extends OperationNode {
7 | readonly kind: 'TopNode'
8 | readonly expression: number | bigint
9 | readonly modifiers?: TopModifier
10 | }
11 |
12 | /**
13 | * @internal
14 | */
15 | export const TopNode = freeze({
16 | is(node: OperationNode): node is TopNode {
17 | return node.kind === 'TopNode'
18 | },
19 |
20 | create(expression: number | bigint, modifiers?: TopModifier): TopNode {
21 | return freeze({
22 | kind: 'TopNode',
23 | expression,
24 | modifiers,
25 | })
26 | },
27 | })
28 |
--------------------------------------------------------------------------------
/src/operation-node/tuple-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface TupleNode extends OperationNode {
5 | readonly kind: 'TupleNode'
6 | readonly values: ReadonlyArray
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const TupleNode = freeze({
13 | is(node: OperationNode): node is TupleNode {
14 | return node.kind === 'TupleNode'
15 | },
16 |
17 | create(values: ReadonlyArray): TupleNode {
18 | return freeze({
19 | kind: 'TupleNode',
20 | values: freeze(values),
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/unary-operation-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface UnaryOperationNode extends OperationNode {
5 | readonly kind: 'UnaryOperationNode'
6 | readonly operator: OperationNode
7 | readonly operand: OperationNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const UnaryOperationNode = freeze({
14 | is(node: OperationNode): node is UnaryOperationNode {
15 | return node.kind === 'UnaryOperationNode'
16 | },
17 |
18 | create(operator: OperationNode, operand: OperationNode): UnaryOperationNode {
19 | return freeze({
20 | kind: 'UnaryOperationNode',
21 | operator,
22 | operand,
23 | })
24 | },
25 | })
26 |
--------------------------------------------------------------------------------
/src/operation-node/using-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface UsingNode extends OperationNode {
5 | readonly kind: 'UsingNode'
6 | readonly tables: ReadonlyArray
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const UsingNode = freeze({
13 | is(node: OperationNode): node is UsingNode {
14 | return node.kind === 'UsingNode'
15 | },
16 |
17 | create(tables: ReadonlyArray): UsingNode {
18 | return freeze({
19 | kind: 'UsingNode',
20 | tables: freeze(tables),
21 | })
22 | },
23 |
24 | cloneWithTables(
25 | using: UsingNode,
26 | tables: ReadonlyArray,
27 | ): UsingNode {
28 | return freeze({
29 | ...using,
30 | tables: freeze([...using.tables, ...tables]),
31 | })
32 | },
33 | })
34 |
--------------------------------------------------------------------------------
/src/operation-node/value-list-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface ValueListNode extends OperationNode {
5 | readonly kind: 'ValueListNode'
6 | readonly values: ReadonlyArray
7 | }
8 |
9 | /**
10 | * @internal
11 | */
12 | export const ValueListNode = freeze({
13 | is(node: OperationNode): node is ValueListNode {
14 | return node.kind === 'ValueListNode'
15 | },
16 |
17 | create(values: ReadonlyArray): ValueListNode {
18 | return freeze({
19 | kind: 'ValueListNode',
20 | values: freeze(values),
21 | })
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/src/operation-node/value-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface ValueNode extends OperationNode {
5 | readonly kind: 'ValueNode'
6 | readonly value: unknown
7 | readonly immediate?: boolean
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const ValueNode = freeze({
14 | is(node: OperationNode): node is ValueNode {
15 | return node.kind === 'ValueNode'
16 | },
17 |
18 | create(value: unknown): ValueNode {
19 | return freeze({
20 | kind: 'ValueNode',
21 | value,
22 | })
23 | },
24 |
25 | createImmediate(value: unknown): ValueNode {
26 | return freeze({
27 | kind: 'ValueNode',
28 | value,
29 | immediate: true,
30 | })
31 | },
32 | })
33 |
--------------------------------------------------------------------------------
/src/operation-node/values-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { PrimitiveValueListNode } from './primitive-value-list-node.js'
4 | import { ValueListNode } from './value-list-node.js'
5 |
6 | export type ValuesItemNode = ValueListNode | PrimitiveValueListNode
7 |
8 | export interface ValuesNode extends OperationNode {
9 | readonly kind: 'ValuesNode'
10 | readonly values: ReadonlyArray
11 | }
12 |
13 | /**
14 | * @internal
15 | */
16 | export const ValuesNode = freeze({
17 | is(node: OperationNode): node is ValuesNode {
18 | return node.kind === 'ValuesNode'
19 | },
20 |
21 | create(values: ReadonlyArray): ValuesNode {
22 | return freeze({
23 | kind: 'ValuesNode',
24 | values: freeze(values),
25 | })
26 | },
27 | })
28 |
--------------------------------------------------------------------------------
/src/operation-node/when-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 |
4 | export interface WhenNode extends OperationNode {
5 | readonly kind: 'WhenNode'
6 | readonly condition: OperationNode
7 | readonly result?: OperationNode
8 | }
9 |
10 | /**
11 | * @internal
12 | */
13 | export const WhenNode = freeze({
14 | is(node: OperationNode): node is WhenNode {
15 | return node.kind === 'WhenNode'
16 | },
17 |
18 | create(condition: OperationNode): WhenNode {
19 | return freeze({
20 | kind: 'WhenNode',
21 | condition,
22 | })
23 | },
24 |
25 | cloneWithResult(whenNode: WhenNode, result: OperationNode): WhenNode {
26 | return freeze({
27 | ...whenNode,
28 | result,
29 | })
30 | },
31 | })
32 |
--------------------------------------------------------------------------------
/src/operation-node/where-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { AndNode } from './and-node.js'
3 | import { OperationNode } from './operation-node.js'
4 | import { OrNode } from './or-node.js'
5 |
6 | export interface WhereNode extends OperationNode {
7 | readonly kind: 'WhereNode'
8 | readonly where: OperationNode
9 | }
10 |
11 | /**
12 | * @internal
13 | */
14 | export const WhereNode = freeze({
15 | is(node: OperationNode): node is WhereNode {
16 | return node.kind === 'WhereNode'
17 | },
18 |
19 | create(filter: OperationNode): WhereNode {
20 | return freeze({
21 | kind: 'WhereNode',
22 | where: filter,
23 | })
24 | },
25 |
26 | cloneWithOperation(
27 | whereNode: WhereNode,
28 | operator: 'And' | 'Or',
29 | operation: OperationNode,
30 | ): WhereNode {
31 | return freeze({
32 | ...whereNode,
33 | where:
34 | operator === 'And'
35 | ? AndNode.create(whereNode.where, operation)
36 | : OrNode.create(whereNode.where, operation),
37 | })
38 | },
39 | })
40 |
--------------------------------------------------------------------------------
/src/operation-node/with-node.ts:
--------------------------------------------------------------------------------
1 | import { freeze } from '../util/object-utils.js'
2 | import { OperationNode } from './operation-node.js'
3 | import { CommonTableExpressionNode } from './common-table-expression-node.js'
4 |
5 | export type WithNodeParams = Omit
6 |
7 | export interface WithNode extends OperationNode {
8 | readonly kind: 'WithNode'
9 | readonly expressions: ReadonlyArray
10 | readonly recursive?: boolean
11 | }
12 |
13 | /**
14 | * @internal
15 | */
16 | export const WithNode = freeze({
17 | is(node: OperationNode): node is WithNode {
18 | return node.kind === 'WithNode'
19 | },
20 |
21 | create(
22 | expression: CommonTableExpressionNode,
23 | params?: WithNodeParams,
24 | ): WithNode {
25 | return freeze({
26 | kind: 'WithNode',
27 | expressions: freeze([expression]),
28 | ...params,
29 | })
30 | },
31 |
32 | cloneWithExpression(
33 | withNode: WithNode,
34 | expression: CommonTableExpressionNode,
35 | ): WithNode {
36 | return freeze({
37 | ...withNode,
38 | expressions: freeze([...withNode.expressions, expression]),
39 | })
40 | },
41 | })
42 |
--------------------------------------------------------------------------------
/src/parser/collate-parser.ts:
--------------------------------------------------------------------------------
1 | export type Collation =
2 | // anything super common or simple should be added here.
3 | // https://sqlite.org/datatype3.html#collating_sequences
4 | | 'nocase'
5 | | 'binary'
6 | | 'rtrim'
7 | // otherwise, allow any string, while still providing autocompletion.
8 | | (string & {})
9 |
--------------------------------------------------------------------------------
/src/parser/data-type-parser.ts:
--------------------------------------------------------------------------------
1 | import { Expression } from '../expression/expression.js'
2 | import {
3 | ColumnDataType,
4 | DataTypeNode,
5 | isColumnDataType,
6 | } from '../operation-node/data-type-node.js'
7 | import { isOperationNodeSource } from '../operation-node/operation-node-source.js'
8 | import { OperationNode } from '../operation-node/operation-node.js'
9 |
10 | export type DataTypeExpression = ColumnDataType | Expression
11 |
12 | export function parseDataTypeExpression(
13 | dataType: DataTypeExpression,
14 | ): OperationNode {
15 | if (isOperationNodeSource(dataType)) {
16 | return dataType.toOperationNode()
17 | }
18 |
19 | if (isColumnDataType(dataType)) {
20 | return DataTypeNode.create(dataType)
21 | }
22 |
23 | throw new Error(`invalid column data type ${JSON.stringify(dataType)}`)
24 | }
25 |
--------------------------------------------------------------------------------
/src/parser/default-value-parser.ts:
--------------------------------------------------------------------------------
1 | import { Expression } from '../expression/expression.js'
2 | import { isOperationNodeSource } from '../operation-node/operation-node-source.js'
3 | import { OperationNode } from '../operation-node/operation-node.js'
4 | import { ValueNode } from '../operation-node/value-node.js'
5 |
6 | export type DefaultValueExpression = unknown | Expression
7 |
8 | export function parseDefaultValueExpression(
9 | value: DefaultValueExpression,
10 | ): OperationNode {
11 | return isOperationNodeSource(value)
12 | ? value.toOperationNode()
13 | : ValueNode.createImmediate(value)
14 | }
15 |
--------------------------------------------------------------------------------
/src/parser/fetch-parser.ts:
--------------------------------------------------------------------------------
1 | import { FetchModifier, FetchNode } from '../operation-node/fetch-node.js'
2 | import { isBigInt, isNumber } from '../util/object-utils.js'
3 |
4 | export function parseFetch(
5 | rowCount: number | bigint,
6 | modifier: FetchModifier,
7 | ): FetchNode {
8 | if (!isNumber(rowCount) && !isBigInt(rowCount)) {
9 | throw new Error(`Invalid fetch row count: ${rowCount}`)
10 | }
11 |
12 | if (!isFetchModifier(modifier)) {
13 | throw new Error(`Invalid fetch modifier: ${modifier}`)
14 | }
15 |
16 | return FetchNode.create(rowCount, modifier)
17 | }
18 |
19 | function isFetchModifier(value: any): value is FetchModifier {
20 | return value === 'only' || value === 'with ties'
21 | }
22 |
--------------------------------------------------------------------------------
/src/parser/group-by-parser.ts:
--------------------------------------------------------------------------------
1 | import { GroupByItemNode } from '../operation-node/group-by-item-node.js'
2 | import {
3 | expressionBuilder,
4 | ExpressionBuilder,
5 | } from '../expression/expression-builder.js'
6 | import { isFunction } from '../util/object-utils.js'
7 | import {
8 | parseReferenceExpressionOrList,
9 | ReferenceExpression,
10 | } from './reference-parser.js'
11 |
12 | export type GroupByExpression =
13 | | ReferenceExpression
14 | | (keyof O & string)
15 |
16 | export type GroupByArg =
17 | | GroupByExpression
18 | | ReadonlyArray>
19 | | ((
20 | eb: ExpressionBuilder,
21 | ) => ReadonlyArray>)
22 |
23 | export function parseGroupBy(
24 | groupBy: GroupByArg,
25 | ): GroupByItemNode[] {
26 | groupBy = isFunction(groupBy) ? groupBy(expressionBuilder()) : groupBy
27 | return parseReferenceExpressionOrList(groupBy).map(GroupByItemNode.create)
28 | }
29 |
--------------------------------------------------------------------------------
/src/parser/identifier-parser.ts:
--------------------------------------------------------------------------------
1 | import { SchemableIdentifierNode } from '../operation-node/schemable-identifier-node.js'
2 |
3 | export function parseSchemableIdentifier(id: string): SchemableIdentifierNode {
4 | const SCHEMA_SEPARATOR = '.'
5 |
6 | if (id.includes(SCHEMA_SEPARATOR)) {
7 | const parts = id.split(SCHEMA_SEPARATOR).map(trim)
8 |
9 | if (parts.length === 2) {
10 | return SchemableIdentifierNode.createWithSchema(parts[0], parts[1])
11 | } else {
12 | throw new Error(`invalid schemable identifier ${id}`)
13 | }
14 | } else {
15 | return SchemableIdentifierNode.create(id)
16 | }
17 | }
18 |
19 | function trim(str: string): string {
20 | return str.trim()
21 | }
22 |
--------------------------------------------------------------------------------
/src/parser/merge-into-parser.ts:
--------------------------------------------------------------------------------
1 | import type { MergeQueryBuilder } from '../query-builder/merge-query-builder.js'
2 | import type { MergeResult } from '../query-builder/merge-result.js'
3 | import type { ShallowRecord } from '../util/type-utils.js'
4 | import type { ExtractTableAlias, SimpleTableReference } from './table-parser.js'
5 |
6 | export type MergeInto<
7 | DB,
8 | TE extends SimpleTableReference,
9 | > = TE extends keyof DB & string
10 | ? MergeQueryBuilder, MergeResult>
11 | : TE extends `${infer T} as ${infer A}`
12 | ? T extends keyof DB
13 | ? MergeQueryBuilder, A, MergeResult>
14 | : never
15 | : never
16 |
--------------------------------------------------------------------------------
/src/parser/on-commit-action-parse.ts:
--------------------------------------------------------------------------------
1 | import {
2 | OnCommitAction,
3 | ON_COMMIT_ACTIONS,
4 | } from '../operation-node/create-table-node.js'
5 |
6 | export function parseOnCommitAction(action: OnCommitAction): OnCommitAction {
7 | if (ON_COMMIT_ACTIONS.includes(action)) {
8 | return action
9 | }
10 |
11 | throw new Error(`invalid OnCommitAction ${action}`)
12 | }
13 |
--------------------------------------------------------------------------------
/src/parser/on-modify-action-parser.ts:
--------------------------------------------------------------------------------
1 | import {
2 | OnModifyForeignAction,
3 | ON_MODIFY_FOREIGN_ACTIONS,
4 | } from '../operation-node/references-node.js'
5 |
6 | export function parseOnModifyForeignAction(
7 | action: OnModifyForeignAction,
8 | ): OnModifyForeignAction {
9 | if (ON_MODIFY_FOREIGN_ACTIONS.includes(action)) {
10 | return action
11 | }
12 |
13 | throw new Error(`invalid OnModifyForeignAction ${action}`)
14 | }
15 |
--------------------------------------------------------------------------------
/src/parser/partition-by-parser.ts:
--------------------------------------------------------------------------------
1 | import { DynamicReferenceBuilder } from '../dynamic/dynamic-reference-builder.js'
2 | import { PartitionByItemNode } from '../operation-node/partition-by-item-node.js'
3 | import { SimpleReferenceExpressionNode } from '../operation-node/simple-reference-expression-node.js'
4 | import {
5 | parseReferenceExpressionOrList,
6 | StringReference,
7 | } from './reference-parser.js'
8 |
9 | export type PartitionByExpression =
10 | | StringReference
11 | | DynamicReferenceBuilder
12 |
13 | export type PartitionByExpressionOrList =
14 | | ReadonlyArray>
15 | | PartitionByExpression
16 |
17 | export function parsePartitionBy(
18 | partitionBy: PartitionByExpressionOrList,
19 | ): PartitionByItemNode[] {
20 | return (
21 | parseReferenceExpressionOrList(
22 | partitionBy,
23 | ) as SimpleReferenceExpressionNode[]
24 | ).map(PartitionByItemNode.create)
25 | }
26 |
--------------------------------------------------------------------------------
/src/parser/returning-parser.ts:
--------------------------------------------------------------------------------
1 | import { DeleteResult } from '../query-builder/delete-result.js'
2 | import { InsertResult } from '../query-builder/insert-result.js'
3 | import { MergeResult } from '../query-builder/merge-result.js'
4 | import { UpdateResult } from '../query-builder/update-result.js'
5 | import { Selection, AllSelection, CallbackSelection } from './select-parser.js'
6 |
7 | export type ReturningRow = O extends
8 | | InsertResult
9 | | DeleteResult
10 | | UpdateResult
11 | | MergeResult
12 | ? Selection
13 | : O & Selection
14 |
15 | export type ReturningCallbackRow = O extends
16 | | InsertResult
17 | | DeleteResult
18 | | UpdateResult
19 | | MergeResult
20 | ? CallbackSelection
21 | : O & CallbackSelection
22 |
23 | export type ReturningAllRow = O extends
24 | | InsertResult
25 | | DeleteResult
26 | | UpdateResult
27 | | MergeResult
28 | ? AllSelection
29 | : O & AllSelection
30 |
--------------------------------------------------------------------------------
/src/parser/savepoint-parser.ts:
--------------------------------------------------------------------------------
1 | import { IdentifierNode } from '../operation-node/identifier-node.js'
2 | import { RawNode } from '../operation-node/raw-node.js'
3 |
4 | export type RollbackToSavepoint<
5 | S extends string[],
6 | SN extends S[number],
7 | > = S extends [...infer L, infer R]
8 | ? R extends SN
9 | ? S
10 | : RollbackToSavepoint
11 | : never
12 |
13 | export type ReleaseSavepoint<
14 | S extends string[],
15 | SN extends S[number],
16 | > = S extends [...infer L, infer R]
17 | ? R extends SN
18 | ? L
19 | : ReleaseSavepoint
20 | : never
21 |
22 | export function parseSavepointCommand(
23 | command: string,
24 | savepointName: string,
25 | ): RawNode {
26 | return RawNode.createWithChildren([
27 | RawNode.createWithSql(`${command} `),
28 | IdentifierNode.create(savepointName), // ensures savepointName gets sanitized
29 | ])
30 | }
31 |
--------------------------------------------------------------------------------
/src/parser/set-operation-parser.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ExpressionBuilder,
3 | createExpressionBuilder,
4 | } from '../expression/expression-builder.js'
5 | import { Expression } from '../expression/expression.js'
6 | import {
7 | SetOperator,
8 | SetOperationNode,
9 | } from '../operation-node/set-operation-node.js'
10 | import { isFunction, isReadonlyArray } from '../util/object-utils.js'
11 | import { parseExpression } from './expression-parser.js'
12 |
13 | export type SetOperandExpression =
14 | | Expression
15 | | ReadonlyArray>
16 | | ((
17 | eb: ExpressionBuilder,
18 | ) => Expression | ReadonlyArray>)
19 |
20 | export function parseSetOperations(
21 | operator: SetOperator,
22 | expression: SetOperandExpression,
23 | all: boolean,
24 | ) {
25 | if (isFunction(expression)) {
26 | expression = expression(createExpressionBuilder())
27 | }
28 |
29 | if (!isReadonlyArray(expression)) {
30 | expression = [expression]
31 | }
32 |
33 | return expression.map((expr) =>
34 | SetOperationNode.create(operator, parseExpression(expr), all),
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/src/parser/top-parser.ts:
--------------------------------------------------------------------------------
1 | import { TopModifier, TopNode } from '../operation-node/top-node.js'
2 | import { isBigInt, isNumber, isUndefined } from '../util/object-utils.js'
3 |
4 | export function parseTop(
5 | expression: number | bigint,
6 | modifiers?: TopModifier,
7 | ): TopNode {
8 | if (!isNumber(expression) && !isBigInt(expression)) {
9 | throw new Error(`Invalid top expression: ${expression}`)
10 | }
11 |
12 | if (!isUndefined(modifiers) && !isTopModifiers(modifiers)) {
13 | throw new Error(`Invalid top modifiers: ${modifiers}`)
14 | }
15 |
16 | return TopNode.create(expression, modifiers)
17 | }
18 |
19 | function isTopModifiers(modifiers: string): modifiers is TopModifier {
20 | return (
21 | modifiers === 'percent' ||
22 | modifiers === 'with ties' ||
23 | modifiers === 'percent with ties'
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/src/parser/unary-operation-parser.ts:
--------------------------------------------------------------------------------
1 | import { OperatorNode, UnaryOperator } from '../operation-node/operator-node.js'
2 | import { UnaryOperationNode } from '../operation-node/unary-operation-node.js'
3 | import { ExpressionOrFactory } from './expression-parser.js'
4 | import {
5 | parseReferenceExpression,
6 | ReferenceExpression,
7 | } from './reference-parser.js'
8 |
9 | export type ExistsExpression = ExpressionOrFactory<
10 | DB,
11 | TB,
12 | any
13 | >
14 |
15 | export function parseExists(
16 | operand: ExistsExpression,
17 | ): UnaryOperationNode {
18 | return parseUnaryOperation('exists', operand)
19 | }
20 |
21 | export function parseNotExists(
22 | operand: ExistsExpression,
23 | ): UnaryOperationNode {
24 | return parseUnaryOperation('not exists', operand)
25 | }
26 |
27 | export function parseUnaryOperation(
28 | operator: UnaryOperator,
29 | operand: ReferenceExpression,
30 | ): UnaryOperationNode {
31 | return UnaryOperationNode.create(
32 | OperatorNode.create(operator),
33 | parseReferenceExpression(operand),
34 | )
35 | }
36 |
--------------------------------------------------------------------------------
/src/plugin/camel-case/camel-case-transformer.ts:
--------------------------------------------------------------------------------
1 | import { IdentifierNode } from '../../operation-node/identifier-node.js'
2 | import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js'
3 | import { QueryId } from '../../util/query-id.js'
4 | import { StringMapper } from './camel-case.js'
5 |
6 | export class SnakeCaseTransformer extends OperationNodeTransformer {
7 | readonly #snakeCase: StringMapper
8 |
9 | constructor(snakeCase: StringMapper) {
10 | super()
11 | this.#snakeCase = snakeCase
12 | }
13 |
14 | protected override transformIdentifier(
15 | node: IdentifierNode,
16 | queryId: QueryId,
17 | ): IdentifierNode {
18 | node = super.transformIdentifier(node, queryId)
19 |
20 | return {
21 | ...node,
22 | name: this.#snakeCase(node.name),
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/plugin/deduplicate-joins/deduplicate-joins-plugin.ts:
--------------------------------------------------------------------------------
1 | import { QueryResult } from '../../driver/database-connection.js'
2 | import { RootOperationNode } from '../../query-compiler/query-compiler.js'
3 | import { UnknownRow } from '../../util/type-utils.js'
4 | import {
5 | KyselyPlugin,
6 | PluginTransformQueryArgs,
7 | PluginTransformResultArgs,
8 | } from '../kysely-plugin.js'
9 | import { DeduplicateJoinsTransformer } from './deduplicate-joins-transformer.js'
10 |
11 | /**
12 | * Plugin that removes duplicate joins from queries.
13 | *
14 | * See [this recipe](https://github.com/kysely-org/kysely/blob/master/site/docs/recipes/0008-deduplicate-joins.md)
15 | */
16 | export class DeduplicateJoinsPlugin implements KyselyPlugin {
17 | readonly #transformer = new DeduplicateJoinsTransformer()
18 |
19 | transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
20 | return this.#transformer.transformNode(args.node, args.queryId)
21 | }
22 |
23 | transformResult(
24 | args: PluginTransformResultArgs,
25 | ): Promise> {
26 | return Promise.resolve(args.result)
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/plugin/immediate-value/immediate-value-plugin.ts:
--------------------------------------------------------------------------------
1 | import { QueryResult } from '../../driver/database-connection.js'
2 | import { RootOperationNode } from '../../query-compiler/query-compiler.js'
3 | import { UnknownRow } from '../../util/type-utils.js'
4 | import {
5 | KyselyPlugin,
6 | PluginTransformQueryArgs,
7 | PluginTransformResultArgs,
8 | } from '../kysely-plugin.js'
9 | import { ImmediateValueTransformer } from './immediate-value-transformer.js'
10 |
11 | /**
12 | * Transforms all ValueNodes to immediate.
13 | *
14 | * WARNING! This should never be part of the public API. Users should never use this.
15 | * This is an internal helper.
16 | *
17 | * @internal
18 | */
19 | export class ImmediateValuePlugin implements KyselyPlugin {
20 | readonly #transformer = new ImmediateValueTransformer()
21 |
22 | transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
23 | return this.#transformer.transformNode(args.node, args.queryId)
24 | }
25 |
26 | transformResult(
27 | args: PluginTransformResultArgs,
28 | ): Promise> {
29 | return Promise.resolve(args.result)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/plugin/immediate-value/immediate-value-transformer.ts:
--------------------------------------------------------------------------------
1 | import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js'
2 | import { PrimitiveValueListNode } from '../../operation-node/primitive-value-list-node.js'
3 | import { ValueListNode } from '../../operation-node/value-list-node.js'
4 | import { ValueNode } from '../../operation-node/value-node.js'
5 |
6 | /**
7 | * Transforms all ValueNodes to immediate.
8 | *
9 | * WARNING! This should never be part of the public API. Users should never use this.
10 | * This is an internal helper.
11 | *
12 | * @internal
13 | */
14 | export class ImmediateValueTransformer extends OperationNodeTransformer {
15 | override transformPrimitiveValueList(
16 | node: PrimitiveValueListNode,
17 | ): PrimitiveValueListNode {
18 | return ValueListNode.create(
19 | node.values.map(ValueNode.createImmediate),
20 | ) as any
21 | }
22 |
23 | override transformValue(node: ValueNode): ValueNode {
24 | return ValueNode.createImmediate(node.value)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/plugin/noop-plugin.ts:
--------------------------------------------------------------------------------
1 | import { QueryResult } from '../driver/database-connection.js'
2 | import { RootOperationNode } from '../query-compiler/query-compiler.js'
3 | import { UnknownRow } from '../util/type-utils.js'
4 | import {
5 | KyselyPlugin,
6 | PluginTransformQueryArgs,
7 | PluginTransformResultArgs,
8 | } from './kysely-plugin.js'
9 |
10 | export class NoopPlugin implements KyselyPlugin {
11 | transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
12 | return args.node
13 | }
14 |
15 | async transformResult(
16 | args: PluginTransformResultArgs,
17 | ): Promise> {
18 | return args.result
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/plugin/with-schema/with-schema-plugin.ts:
--------------------------------------------------------------------------------
1 | import { QueryResult } from '../../driver/database-connection.js'
2 | import { RootOperationNode } from '../../query-compiler/query-compiler.js'
3 | import { WithSchemaTransformer } from './with-schema-transformer.js'
4 | import {
5 | KyselyPlugin,
6 | PluginTransformQueryArgs,
7 | PluginTransformResultArgs,
8 | } from '../kysely-plugin.js'
9 | import { UnknownRow } from '../../util/type-utils.js'
10 |
11 | export class WithSchemaPlugin implements KyselyPlugin {
12 | readonly #transformer: WithSchemaTransformer
13 |
14 | constructor(schema: string) {
15 | this.#transformer = new WithSchemaTransformer(schema)
16 | }
17 |
18 | transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
19 | return this.#transformer.transformNode(args.node, args.queryId)
20 | }
21 |
22 | async transformResult(
23 | args: PluginTransformResultArgs,
24 | ): Promise> {
25 | return args.result
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/query-builder/delete-result.ts:
--------------------------------------------------------------------------------
1 | export class DeleteResult {
2 | readonly numDeletedRows: bigint
3 |
4 | constructor(numDeletedRows: bigint) {
5 | this.numDeletedRows = numDeletedRows
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/query-builder/merge-result.ts:
--------------------------------------------------------------------------------
1 | export class MergeResult {
2 | readonly numChangedRows: bigint | undefined
3 |
4 | constructor(numChangedRows: bigint | undefined) {
5 | this.numChangedRows = numChangedRows
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/query-builder/no-result-error.ts:
--------------------------------------------------------------------------------
1 | import { QueryNode } from '../operation-node/query-node.js'
2 |
3 | export type NoResultErrorConstructor = new (node: QueryNode) => Error
4 |
5 | export class NoResultError extends Error {
6 | /**
7 | * The operation node tree of the query that was executed.
8 | */
9 | readonly node: QueryNode
10 |
11 | constructor(node: QueryNode) {
12 | super('no result')
13 | this.node = node
14 | }
15 | }
16 |
17 | export function isNoResultErrorConstructor(
18 | fn: NoResultErrorConstructor | ((node: QueryNode) => Error),
19 | ): fn is NoResultErrorConstructor {
20 | return Object.prototype.hasOwnProperty.call(fn, 'prototype')
21 | }
22 |
--------------------------------------------------------------------------------
/src/query-builder/select-query-builder-expression.ts:
--------------------------------------------------------------------------------
1 | import { AliasableExpression } from '../expression/expression.js'
2 | import { SelectQueryNode } from '../operation-node/select-query-node.js'
3 |
4 | export interface SelectQueryBuilderExpression
5 | extends AliasableExpression {
6 | get isSelectQueryBuilder(): true
7 | toOperationNode(): SelectQueryNode
8 | }
9 |
--------------------------------------------------------------------------------
/src/query-builder/update-result.ts:
--------------------------------------------------------------------------------
1 | export class UpdateResult {
2 | /**
3 | * The number of rows the update query updated (even if not changed).
4 | */
5 | readonly numUpdatedRows: bigint
6 |
7 | /**
8 | * The number of rows the update query changed.
9 | *
10 | * This is **optional** and only supported in dialects such as MySQL.
11 | * You would probably use {@link numUpdatedRows} in most cases.
12 | */
13 | readonly numChangedRows?: bigint
14 |
15 | constructor(numUpdatedRows: bigint, numChangedRows: bigint | undefined) {
16 | this.numUpdatedRows = numUpdatedRows
17 | this.numChangedRows = numChangedRows
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/query-compiler/compiled-query.ts:
--------------------------------------------------------------------------------
1 | import { RawNode } from '../operation-node/raw-node.js'
2 | import { freeze } from '../util/object-utils.js'
3 | import { createQueryId, QueryId } from '../util/query-id.js'
4 | import { RootOperationNode } from './query-compiler.js'
5 |
6 | export interface CompiledQuery {
7 | readonly query: RootOperationNode
8 | readonly queryId: QueryId
9 | readonly sql: string
10 | readonly parameters: ReadonlyArray
11 | }
12 |
13 | export const CompiledQuery = freeze({
14 | raw(sql: string, parameters: unknown[] = []): CompiledQuery {
15 | return freeze({
16 | sql,
17 | query: RawNode.createWithSql(sql),
18 | parameters: freeze(parameters),
19 | queryId: createQueryId(),
20 | })
21 | },
22 | })
23 |
--------------------------------------------------------------------------------
/src/query-executor/query-executor-provider.ts:
--------------------------------------------------------------------------------
1 | import { QueryExecutor } from './query-executor.js'
2 |
3 | /**
4 | * @internal
5 | * @private
6 | */
7 | export interface QueryExecutorProvider {
8 | getExecutor(): QueryExecutor
9 | }
10 |
--------------------------------------------------------------------------------
/src/schema/check-constraint-builder.ts:
--------------------------------------------------------------------------------
1 | import { OperationNodeSource } from '../operation-node/operation-node-source.js'
2 | import { CheckConstraintNode } from '../operation-node/check-constraint-node.js'
3 |
4 | export class CheckConstraintBuilder implements OperationNodeSource {
5 | readonly #node: CheckConstraintNode
6 |
7 | constructor(node: CheckConstraintNode) {
8 | this.#node = node
9 | }
10 |
11 | /**
12 | * Simply calls the provided function passing `this` as the only argument. `$call` returns
13 | * what the provided function returns.
14 | */
15 | $call(func: (qb: this) => T): T {
16 | return func(this)
17 | }
18 |
19 | toOperationNode(): CheckConstraintNode {
20 | return this.#node
21 | }
22 | }
23 |
24 | export type CheckConstraintBuilderCallback = (
25 | builder: CheckConstraintBuilder,
26 | ) => CheckConstraintBuilder
27 |
--------------------------------------------------------------------------------
/src/util/assert.ts:
--------------------------------------------------------------------------------
1 | export function assertNotNullOrUndefined(
2 | value: T,
3 | ): asserts value is NonNullable {
4 | if (value === null || value === undefined) {
5 | throw new Error(`${value} must not be null or undefined`)
6 | }
7 | }
8 |
9 | export function assertIsString(value: any): asserts value is string {
10 | if (typeof value !== 'string') {
11 | throw new Error(`${value} must be a string`)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/util/compilable.ts:
--------------------------------------------------------------------------------
1 | import { CompiledQuery } from '../query-compiler/compiled-query.js'
2 | import { isFunction, isObject } from './object-utils.js'
3 |
4 | export interface Compilable {
5 | compile(): CompiledQuery
6 | }
7 |
8 | export function isCompilable(value: unknown): value is Compilable {
9 | return isObject(value) && isFunction(value.compile)
10 | }
11 |
--------------------------------------------------------------------------------
/src/util/deferred.ts:
--------------------------------------------------------------------------------
1 | export class Deferred {
2 | readonly #promise: Promise
3 |
4 | #resolve?: (value: T | PromiseLike) => void
5 | #reject?: (reason?: any) => void
6 |
7 | constructor() {
8 | this.#promise = new Promise((resolve, reject) => {
9 | this.#reject = reject
10 | this.#resolve = resolve
11 | })
12 | }
13 |
14 | get promise(): Promise {
15 | return this.#promise
16 | }
17 |
18 | resolve = (value: T | PromiseLike): void => {
19 | if (this.#resolve) {
20 | this.#resolve(value)
21 | }
22 | }
23 |
24 | reject = (reason?: any): void => {
25 | if (this.#reject) {
26 | this.#reject(reason)
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/util/log-once.ts:
--------------------------------------------------------------------------------
1 | const LOGGED_MESSAGES: Set = new Set()
2 |
3 | /**
4 | * Use for system-level logging, such as deprecation messages.
5 | * Logs a message and ensures it won't be logged again.
6 | */
7 | export function logOnce(message: string): void {
8 | if (LOGGED_MESSAGES.has(message)) {
9 | return
10 | }
11 |
12 | LOGGED_MESSAGES.add(message)
13 | console.log(message)
14 | }
15 |
--------------------------------------------------------------------------------
/src/util/performance-now.ts:
--------------------------------------------------------------------------------
1 | import { isFunction } from './object-utils.js'
2 |
3 | export function performanceNow() {
4 | if (typeof performance !== 'undefined' && isFunction(performance.now)) {
5 | return performance.now()
6 | } else {
7 | return Date.now()
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/util/query-id.ts:
--------------------------------------------------------------------------------
1 | import { randomString } from './random-string.js'
2 |
3 | export interface QueryId {
4 | readonly queryId: string
5 | }
6 |
7 | export function createQueryId(): QueryId {
8 | return new LazyQueryId()
9 | }
10 |
11 | class LazyQueryId implements QueryId {
12 | #queryId: string | undefined
13 |
14 | get queryId(): string {
15 | if (this.#queryId === undefined) {
16 | this.#queryId = randomString(8)
17 | }
18 |
19 | return this.#queryId
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/util/random-string.ts:
--------------------------------------------------------------------------------
1 | const CHARS = [
2 | 'A',
3 | 'B',
4 | 'C',
5 | 'D',
6 | 'E',
7 | 'F',
8 | 'G',
9 | 'H',
10 | 'I',
11 | 'J',
12 | 'K',
13 | 'L',
14 | 'M',
15 | 'N',
16 | 'O',
17 | 'P',
18 | 'Q',
19 | 'R',
20 | 'S',
21 | 'T',
22 | 'U',
23 | 'V',
24 | 'W',
25 | 'X',
26 | 'Y',
27 | 'Z',
28 | 'a',
29 | 'b',
30 | 'c',
31 | 'd',
32 | 'e',
33 | 'f',
34 | 'g',
35 | 'h',
36 | 'i',
37 | 'j',
38 | 'k',
39 | 'l',
40 | 'm',
41 | 'n',
42 | 'o',
43 | 'p',
44 | 'q',
45 | 'r',
46 | 's',
47 | 't',
48 | 'u',
49 | 'v',
50 | 'w',
51 | 'x',
52 | 'y',
53 | 'z',
54 | '0',
55 | '1',
56 | '2',
57 | '3',
58 | '4',
59 | '5',
60 | '6',
61 | '7',
62 | '8',
63 | '9',
64 | ]
65 |
66 | export function randomString(length: number): string {
67 | let chars = ''
68 |
69 | for (let i = 0; i < length; ++i) {
70 | chars += randomChar()
71 | }
72 |
73 | return chars
74 | }
75 |
76 | function randomChar() {
77 | return CHARS[~~(Math.random() * CHARS.length)]
78 | }
79 |
--------------------------------------------------------------------------------
/src/util/stack-trace-utils.ts:
--------------------------------------------------------------------------------
1 | import { isObject, isString } from './object-utils.js'
2 |
3 | export function extendStackTrace(err: unknown, stackError: Error): unknown {
4 | if (isStackHolder(err) && stackError.stack) {
5 | // Remove the first line that just says `Error`.
6 | const stackExtension = stackError.stack.split('\n').slice(1).join('\n')
7 |
8 | err.stack += `\n${stackExtension}`
9 | return err
10 | }
11 |
12 | return err
13 | }
14 |
15 | interface StackHolder {
16 | stack: string
17 | }
18 |
19 | function isStackHolder(obj: unknown): obj is StackHolder {
20 | return isObject(obj) && isString(obj.stack)
21 | }
22 |
--------------------------------------------------------------------------------
/src/util/streamable.ts:
--------------------------------------------------------------------------------
1 | export interface Streamable {
2 | /**
3 | * Executes the query and streams the rows.
4 | *
5 | * The optional argument `chunkSize` defines how many rows to fetch from the database
6 | * at a time. It only affects some dialects like PostgreSQL that support it.
7 | *
8 | * ### Examples
9 | *
10 | * ```ts
11 | * const stream = db
12 | * .selectFrom('person')
13 | * .select(['first_name', 'last_name'])
14 | * .where('gender', '=', 'other')
15 | * .stream()
16 | *
17 | * for await (const person of stream) {
18 | * console.log(person.first_name)
19 | *
20 | * if (person.last_name === 'Something') {
21 | * // Breaking or returning before the stream has ended will release
22 | * // the database connection and invalidate the stream.
23 | * break
24 | * }
25 | * }
26 | * ```
27 | */
28 | stream(chunkSize?: number): AsyncIterableIterator
29 | }
30 |
--------------------------------------------------------------------------------
/src/util/type-error.ts:
--------------------------------------------------------------------------------
1 | export interface KyselyTypeError {
2 | readonly __kyselyTypeError__: E
3 | }
4 |
--------------------------------------------------------------------------------
/test/browser/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Kysely browser test
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/browser/main.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Kysely,
3 | Generated,
4 | DummyDriver,
5 | SqliteAdapter,
6 | SqliteIntrospector,
7 | SqliteQueryCompiler,
8 | } from '../..'
9 |
10 | interface Person {
11 | id: Generated
12 | first_name: string
13 | last_name: string | null
14 | }
15 |
16 | interface Database {
17 | person: Person
18 | }
19 |
20 | const db = new Kysely({
21 | dialect: {
22 | createAdapter() {
23 | return new SqliteAdapter()
24 | },
25 | createDriver() {
26 | return new DummyDriver()
27 | },
28 | createIntrospector(db: Kysely) {
29 | return new SqliteIntrospector(db)
30 | },
31 | createQueryCompiler() {
32 | return new SqliteQueryCompiler()
33 | },
34 | },
35 | })
36 |
37 | window.addEventListener('load', () => {
38 | const sql = db.selectFrom('person').select('id').compile()
39 |
40 | const result = document.createElement('span')
41 | result.id = 'result'
42 | result.innerHTML = sql.sql
43 |
44 | document.body.appendChild(result)
45 | })
46 |
--------------------------------------------------------------------------------
/test/browser/test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Super simple smoke test that just opens an empty web page
3 | * and runs the `main.ts` script in it (bundled with esbuild).
4 | * The script builds a query and writes the result to a span
5 | * in the browser.
6 | */
7 |
8 | const path = require('path')
9 | const { chromium } = require('playwright')
10 |
11 | const EXPECTED_SQL = 'select "id" from "person"'
12 |
13 | ;(async () => {
14 | let browser
15 |
16 | try {
17 | browser = await chromium.launch({ headless: true })
18 | const page = await browser.newPage()
19 |
20 | await page.goto('file://' + path.join(__dirname, 'index.html'))
21 | // Wait until the main.ts script has finished and the result
22 | // span exists in the body.
23 | await page.waitForSelector('#result', { timeout: 5000 })
24 | const sql = await page.$eval('#result', (el) => el.innerHTML)
25 |
26 | if (sql !== EXPECTED_SQL) {
27 | throw new Error(`failed to build a query`)
28 | }
29 | } catch (error) {
30 | console.error(error)
31 | process.exit(1)
32 | } finally {
33 | await browser?.close()
34 | }
35 |
36 | console.log('browser test passed')
37 | })()
38 |
--------------------------------------------------------------------------------
/test/bun/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/test/bun/bun.lockb
--------------------------------------------------------------------------------
/test/bun/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kysely-bun-test",
3 | "private": true,
4 | "scripts": {
5 | "test": "bun bun.test.ts"
6 | },
7 | "dependencies": {
8 | "kysely": "link:kysely",
9 | "mysql2": "^3.11.0",
10 | "pg": "^8.12.0",
11 | "tarn": "^3.0.2",
12 | "tedious": "^19.0.0"
13 | },
14 | "devDependencies": {
15 | "@types/bun": "^1.1.8",
16 | "typescript": "^5.5.4"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/test/cloudflare-workers/.dev.vars:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kysely-org/kysely/6333aeee019dd8ba4cc8f077d6a40203f54d9ae2/test/cloudflare-workers/.dev.vars
--------------------------------------------------------------------------------
/test/cloudflare-workers/api.ts:
--------------------------------------------------------------------------------
1 | import { Pool } from 'pg'
2 | import { Hono } from 'hono'
3 | import { Generated, Kysely, PostgresDialect, sql } from '../../'
4 |
5 | interface Person {
6 | id: Generated
7 | first_name: string
8 | last_name: string | null
9 | }
10 |
11 | interface Database {
12 | person: Person
13 | }
14 |
15 | const db = new Kysely({
16 | dialect: new PostgresDialect({
17 | pool: new Pool({
18 | database: 'kysely_test',
19 | host: 'localhost',
20 | user: 'kysely',
21 | port: 5434,
22 | }),
23 | }),
24 | })
25 |
26 | const app = new Hono()
27 |
28 | app.get('/', async (c) => {
29 | if (
30 | db.selectFrom('person').selectAll().compile().sql !==
31 | 'select * from "person"'
32 | ) {
33 | throw new Error('Unexpected SQL')
34 | }
35 |
36 | const {
37 | rows: [row],
38 | } = await sql`select 1 as ok`.execute(db)
39 |
40 | return c.json(row as object)
41 | })
42 |
43 | export default app
44 |
--------------------------------------------------------------------------------
/test/cloudflare-workers/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kysely-cloudflare-workers-test",
3 | "type": "module",
4 | "private": true,
5 | "scripts": {
6 | "test": "node --experimental-strip-types test.ts"
7 | },
8 | "devDependencies": {
9 | "hono": "^4.5.8",
10 | "tsx": "^4.18.0",
11 | "wrangler": "^3.72.2"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/test/cloudflare-workers/test.ts:
--------------------------------------------------------------------------------
1 | import { unstable_dev } from 'wrangler'
2 | ;(async () => {
3 | const worker = await unstable_dev('./api.ts', {
4 | experimental: { disableExperimentalWarning: true },
5 | local: true,
6 | nodeCompat: true,
7 | })
8 |
9 | let exitCode = 0
10 |
11 | try {
12 | const response = await worker.fetch('/')
13 |
14 | if (!response.ok) {
15 | throw new Error(`Unexpected response: ${response.status}`)
16 | }
17 |
18 | console.log('test successful!')
19 | } catch (error) {
20 | exitCode = 1
21 | } finally {
22 | await worker.stop()
23 | process.exit(exitCode)
24 | }
25 | })()
26 |
--------------------------------------------------------------------------------
/test/deno/deno.json:
--------------------------------------------------------------------------------
1 | {
2 | "imports": {
3 | "kysely": "npm:kysely@^0.27.4",
4 | "mysql2": "npm:mysql2@^3.11.0",
5 | "pg": "npm:pg@^8.12.0",
6 | "pg-pool": "npm:pg-pool@^3.6.2"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/test/node/src/log-once.test.ts:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai'
2 | import { createSandbox, SinonSpy } from 'sinon'
3 | import { logOnce } from '../../..'
4 |
5 | describe('logOnce', () => {
6 | let logSpy: SinonSpy
7 | const sandbox = createSandbox()
8 |
9 | before(() => {
10 | logSpy = sandbox.stub(console, 'log')
11 | })
12 |
13 | after(() => {
14 | sandbox.restore()
15 | })
16 |
17 | it('should log each message once.', () => {
18 | const message = 'Kysely is awesome!'
19 | const message2 = 'Type-safety is everything!'
20 |
21 | logOnce(message)
22 | logOnce(message)
23 | logOnce(message2)
24 | logOnce(message2)
25 | logOnce(message)
26 |
27 | expect(logSpy.calledTwice).to.be.true
28 | expect(logSpy.getCall(0).args[0]).to.equal(message)
29 | expect(logSpy.getCall(1).args[0]).to.equal(message2)
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/test/node/src/object-util.test.ts:
--------------------------------------------------------------------------------
1 | import { isPlainObject } from '../../../dist/cjs/util/object-utils'
2 |
3 | import { expect } from './test-setup.js'
4 |
5 | describe('object util', () => {
6 | it('isPlainObject', async () => {
7 | class SomeClass {}
8 |
9 | for (const obj of [{ foo: 'bar' }, Object.create(null)]) {
10 | expect(isPlainObject(obj)).to.equal(true)
11 | }
12 |
13 | for (const obj of [
14 | [],
15 | new Date(),
16 | Buffer.allocUnsafe(10),
17 | new ArrayBuffer(10),
18 | new Int32Array(10),
19 | new Float64Array(10),
20 | '',
21 | 42,
22 | false,
23 | null,
24 | undefined,
25 | new SomeClass(),
26 | ]) {
27 | expect(isPlainObject(obj)).to.equal(false)
28 | }
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/test/node/src/parse-json-results-plugin.test.ts:
--------------------------------------------------------------------------------
1 | import { ParseJSONResultsPlugin } from '../../..'
2 | import { createQueryId } from '../../../dist/cjs/util/query-id.js'
3 |
4 | describe('ParseJSONResultsPlugin', () => {
5 | describe("when `objectStrategy` is 'create'", () => {
6 | let plugin: ParseJSONResultsPlugin
7 |
8 | beforeEach(() => {
9 | plugin = new ParseJSONResultsPlugin({ objectStrategy: 'create' })
10 | })
11 |
12 | it('should parse JSON results that contain readonly arrays/objects', async () => {
13 | await plugin.transformResult({
14 | queryId: createQueryId(),
15 | result: {
16 | rows: [
17 | Object.freeze({
18 | id: 1,
19 | carIds: Object.freeze([1, 2, 3]),
20 | metadata: JSON.stringify({ foo: 'bar' }),
21 | }),
22 | ],
23 | },
24 | })
25 | })
26 | })
27 | })
28 |
--------------------------------------------------------------------------------
/test/node/src/test-migrations/migration1.ts:
--------------------------------------------------------------------------------
1 | import { Kysely } from '../../../../'
2 |
3 | export async function up(db: Kysely): Promise {
4 | await db.schema
5 | .createTable('test1')
6 | .addColumn('id', 'integer', (col) => col.primaryKey())
7 | .execute()
8 | }
9 |
10 | export async function down(db: Kysely): Promise {
11 | await db.schema.dropTable('test1').execute()
12 | }
13 |
--------------------------------------------------------------------------------
/test/node/src/test-migrations/migration2.ts:
--------------------------------------------------------------------------------
1 | import { Kysely } from '../../../../'
2 |
3 | export async function up(db: Kysely): Promise {
4 | await db.schema
5 | .createTable('test2')
6 | .addColumn('id', 'integer', (col) => col.primaryKey())
7 | .addColumn('test1_id', 'integer', (col) => col.references('test1.id'))
8 | .execute()
9 | }
10 |
11 | // Down migration is missing on purpose. It's optional.
12 |
--------------------------------------------------------------------------------
/test/node/tsconfig.json:
--------------------------------------------------------------------------------
1 | {"compilerOptions":{"target":"ES2022","lib":["ESNext"],"module":"CommonJS","outDir":"dist","skipLibCheck":true},"default":{"compilerOptions":{"target":"ES2022","lib":["ESNext"],"module":"CommonJS","outDir":"dist","skipLibCheck":true},"default":{"compilerOptions":{"target":"ES2022","lib":["ESNext"],"module":"CommonJS","outDir":"dist","skipLibCheck":true},"default":{"extends":"../../tsconfig-base.json","include":["src/**/*"],"compilerOptions":{"target":"ES2022","lib":["ESNext"],"module":"CommonJS","outDir":"dist","skipLibCheck":true}},"extends":"../../tsconfig-base.json","include":["src/**/*"],"exclude":["src/async-dispose.test.ts"]},"exclude":["src/async-dispose.test.ts"],"extends":"../../tsconfig-base.json","include":["src/**/*"]},"exclude":["src/async-dispose.test.ts","src/async-dispose.test.ts"],"extends":"../../tsconfig-base.json","include":["src/**/*"]}
--------------------------------------------------------------------------------
/test/outdated-ts/outdated-ts.test.ts:
--------------------------------------------------------------------------------
1 | import { Kysely, RawBuilder, sql } from 'kysely'
2 | import { KyselyTypeError } from '../../src/util/type-error'
3 |
4 | function expectOutdatedTSError(
5 | _: KyselyTypeError<'The installed TypeScript version is outdated and cannot guarantee type-safety with Kysely. Please upgrade to version 4.6 or newer.'>,
6 | ): void {}
7 |
8 | expectOutdatedTSError(Kysely)
9 | expectOutdatedTSError(RawBuilder)
10 | expectOutdatedTSError(sql)
11 |
--------------------------------------------------------------------------------
/test/outdated-ts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "outdated-ts",
3 | "private": true,
4 | "version": "1.0.0",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "tsc --noEmit"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "description": "",
13 | "dependencies": {
14 | "kysely": "file:../../"
15 | },
16 | "devDependencies": {
17 | "typescript": "4.5.x"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test/outdated-ts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig-base.json",
3 | "include": ["./**/*"],
4 | "compilerOptions": {
5 | "skipLibCheck": true
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/test/scripts/mysql-init.sql:
--------------------------------------------------------------------------------
1 | CREATE USER 'kysely'@'%' IDENTIFIED WITH mysql_native_password BY 'kysely';
2 | GRANT ALL ON *.* TO 'kysely'@'%';
3 | CREATE DATABASE kysely_test;
--------------------------------------------------------------------------------
/test/ts-benchmarks/index.ts:
--------------------------------------------------------------------------------
1 | import './select-from.bench.ts'
2 | import './order-by.bench.ts'
3 |
--------------------------------------------------------------------------------
/test/ts-benchmarks/package.json:
--------------------------------------------------------------------------------
1 | { "type": "module" }
2 |
--------------------------------------------------------------------------------
/test/ts-benchmarks/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig-base.json",
3 | "include": ["**/*.ts"],
4 | }
5 |
--------------------------------------------------------------------------------
/test/typings/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from '../../'
2 | export * from '../../helpers/postgres'
3 |
--------------------------------------------------------------------------------
/test/typings/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "types": "index.d.ts"
3 | }
4 |
--------------------------------------------------------------------------------
/test/typings/test-d/select-no-from.test-d.ts:
--------------------------------------------------------------------------------
1 | import { Kysely, SqlBool, sql } from '..'
2 | import { Database } from '../shared'
3 | import { expectType } from 'tsd'
4 |
5 | async function testSelectNoFrom(db: Kysely) {
6 | const r1 = await db
7 | .selectNoFrom(sql<'bar'>`select 'bar'`.as('foo'))
8 | .executeTakeFirstOrThrow()
9 | expectType<{ foo: 'bar' }>(r1)
10 |
11 | const r2 = await db
12 | .selectNoFrom((eb) => eb(eb.val(1), '=', 1).as('very_useful'))
13 | .executeTakeFirstOrThrow()
14 | expectType<{ very_useful: SqlBool }>(r2)
15 |
16 | const r3 = await db
17 | .selectNoFrom([
18 | sql<'bar'>`select 'bar'`.as('foo'),
19 | db.selectFrom('pet').select('id').limit(1).as('pet_id'),
20 | ])
21 | .executeTakeFirstOrThrow()
22 | expectType<{ foo: 'bar'; pet_id: string | null }>(r3)
23 |
24 | const r4 = await db
25 | .selectNoFrom((eb) => [
26 | eb(eb.val(1), '=', 1).as('very_useful'),
27 | eb.selectFrom('pet').select('id').limit(1).as('pet_id'),
28 | ])
29 | .executeTakeFirstOrThrow()
30 | expectType<{ very_useful: SqlBool; pet_id: string | null }>(r4)
31 | }
32 |
--------------------------------------------------------------------------------
/test/typings/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig-base.json",
3 | "include": ["./**/*"],
4 | "compilerOptions": {
5 | "exactOptionalPropertyTypes": true,
6 | "module": "CommonJS"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tsconfig-base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "moduleResolution": "Node",
4 | "target": "ESNext",
5 | "declaration": true,
6 | "strict": true,
7 | "noImplicitAny": true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tsconfig-cjs.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig-base.json",
3 | "include": ["src/**/*"],
4 | "compilerOptions": {
5 | "module": "CommonJS",
6 | "outDir": "dist/cjs"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig-base.json",
3 | "include": ["src/**/*"],
4 | "compilerOptions": {
5 | "module": "ESNext",
6 | "outDir": "dist/esm"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------