mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
Merge pull request #14070 from supabase/thor/kysely-postgres-example
feat: add kysely postgres example
This commit is contained in:
9 files changed
+560
-11
No files matched your search
@@ -6,6 +6,12 @@ const examples = [
|
||||
description: 'Use the Supabase client inside your Edge Function.',
|
||||
href: 'https://github.com/supabase/supabase/blob/master/examples/edge-functions/supabase/functions/select-from-table-with-auth-rls/index.ts',
|
||||
},
|
||||
{
|
||||
name: 'Type-Safe SQL with Kysely',
|
||||
description:
|
||||
'Combining Kysely with Deno Postgres gives you a convenient developer experience for interacting directly with your Postgres database.',
|
||||
href: '/guides/functions/kysely-postgres',
|
||||
},
|
||||
{
|
||||
name: 'With CORS headers',
|
||||
description: 'Send CORS headers for invoking from the browser.',
|
||||
|
||||
@@ -591,6 +591,7 @@ export const functions = {
|
||||
{ name: 'Browserless.io', url: '/guides/functions/examples/screenshots' },
|
||||
{ name: 'OpenAI API', url: '/guides/functions/examples/openai' },
|
||||
{ name: 'Upstash Redis', url: '/guides/functions/examples/upstash-redis' },
|
||||
{ name: 'Type-Safe SQL with Kysely', url: '/guides/functions/kysely-postgres' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -45,6 +45,12 @@ export const examples = [
|
||||
description: 'Use the Supabase client inside your Edge Function.',
|
||||
href: '/guides/functions/auth',
|
||||
},
|
||||
{
|
||||
name: 'Type-Safe SQL with Kysely',
|
||||
description:
|
||||
'Combining Kysely with Deno Postgres gives you a convenient developer experience for interacting directly with your Postgres database.',
|
||||
href: '/guides/functions/kysely-postgres',
|
||||
},
|
||||
{
|
||||
name: 'With CORS headers',
|
||||
description: 'Send CORS headers for invoking from the browser.',
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
import Layout from '~/layouts/DefaultGuideLayout'
|
||||
|
||||
export const meta = {
|
||||
id: 'kysely-postgres',
|
||||
title: 'Type-Safe SQL with Kysely',
|
||||
description:
|
||||
'Combining Kysely with Deno Postgres gives you a convenient developer experience for interacting directly with your Postgres database.',
|
||||
}
|
||||
|
||||
<div class="video-container">
|
||||
<iframe
|
||||
src="https://www.youtube-nocookie.com/embed/zd9a_Lk3jAc"
|
||||
frameBorder="1"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
|
||||
Supabase Edge Functions can [connect directly to your Postgres database](/guides/functions/connect-to-postgres) to execute SQL queries. [Kysely](https://github.com/kysely-org/kysely#kysely) is a type-safe and autocompletion-friendly typescript SQL query builder.
|
||||
|
||||
Combining Kysely with Deno Postgres gives you a convenient developer experience for interacting directly with your Postgres database.
|
||||
|
||||
## Code
|
||||
|
||||
Find the example on [GitHub](https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/kysely-postgres)
|
||||
|
||||
Get your database connection credentials from your [Supabase Dashboard](https://app.supabase.com/project/_/settings/database) and store them in an `.env` file:
|
||||
|
||||
```txt .env
|
||||
DB_HOSTNAME=
|
||||
DB_PASSWORD=
|
||||
DB_SSL_CERT="-----BEGIN CERTIFICATE-----
|
||||
GET YOUR CERT FROM YOUR PROJECT DASHBOARD
|
||||
-----END CERTIFICATE-----"
|
||||
```
|
||||
|
||||
Create a `DenoPostgresDriver.ts` file to manage the connection to Postgres via [deno-postgres](https://deno-postgres.com/):
|
||||
|
||||
```ts DenoPostgresDriver.ts
|
||||
import {
|
||||
CompiledQuery,
|
||||
DatabaseConnection,
|
||||
Driver,
|
||||
PostgresCursorConstructor,
|
||||
QueryResult,
|
||||
TransactionSettings,
|
||||
} from 'https://esm.sh/kysely@0.23.4'
|
||||
import { freeze, isFunction } from 'https://esm.sh/kysely@0.23.4/dist/esm/util/object-utils.js'
|
||||
import { extendStackTrace } from 'https://esm.sh/kysely@0.23.4/dist/esm/util/stack-trace-utils.js'
|
||||
import { Pool, PoolClient } from 'https://deno.land/x/postgres@v0.17.0/mod.ts'
|
||||
|
||||
export interface PostgresDialectConfig {
|
||||
pool: Pool | (() => Promise<Pool>)
|
||||
cursor?: PostgresCursorConstructor
|
||||
onCreateConnection?: (connection: DatabaseConnection) => Promise<void>
|
||||
}
|
||||
|
||||
const PRIVATE_RELEASE_METHOD = Symbol()
|
||||
|
||||
export class PostgresDriver implements Driver {
|
||||
readonly #config: PostgresDialectConfig
|
||||
readonly #connections = new WeakMap<PoolClient, DatabaseConnection>()
|
||||
#pool?: Pool
|
||||
|
||||
constructor(config: PostgresDialectConfig) {
|
||||
this.#config = freeze({ ...config })
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
this.#pool = isFunction(this.#config.pool) ? await this.#config.pool() : this.#config.pool
|
||||
}
|
||||
|
||||
async acquireConnection(): Promise<DatabaseConnection> {
|
||||
const client = await this.#pool!.connect()
|
||||
let connection = this.#connections.get(client)
|
||||
|
||||
if (!connection) {
|
||||
connection = new PostgresConnection(client, {
|
||||
cursor: this.#config.cursor ?? null,
|
||||
})
|
||||
this.#connections.set(client, connection)
|
||||
|
||||
// The driver must take care of calling `onCreateConnection` when a new
|
||||
// connection is created. The `pg` module doesn't provide an async hook
|
||||
// for the connection creation. We need to call the method explicitly.
|
||||
if (this.#config?.onCreateConnection) {
|
||||
await this.#config.onCreateConnection(connection)
|
||||
}
|
||||
}
|
||||
|
||||
return connection
|
||||
}
|
||||
|
||||
async beginTransaction(
|
||||
connection: DatabaseConnection,
|
||||
settings: TransactionSettings
|
||||
): Promise<void> {
|
||||
if (settings.isolationLevel) {
|
||||
await connection.executeQuery(
|
||||
CompiledQuery.raw(`start transaction isolation level ${settings.isolationLevel}`)
|
||||
)
|
||||
} else {
|
||||
await connection.executeQuery(CompiledQuery.raw('begin'))
|
||||
}
|
||||
}
|
||||
|
||||
async commitTransaction(connection: DatabaseConnection): Promise<void> {
|
||||
await connection.executeQuery(CompiledQuery.raw('commit'))
|
||||
}
|
||||
|
||||
async rollbackTransaction(connection: DatabaseConnection): Promise<void> {
|
||||
await connection.executeQuery(CompiledQuery.raw('rollback'))
|
||||
}
|
||||
|
||||
async releaseConnection(connection: PostgresConnection): Promise<void> {
|
||||
connection[PRIVATE_RELEASE_METHOD]()
|
||||
}
|
||||
|
||||
async destroy(): Promise<void> {
|
||||
if (this.#pool) {
|
||||
const pool = this.#pool
|
||||
this.#pool = undefined
|
||||
await pool.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface PostgresConnectionOptions {
|
||||
cursor: PostgresCursorConstructor | null
|
||||
}
|
||||
|
||||
class PostgresConnection implements DatabaseConnection {
|
||||
#client: PoolClient
|
||||
#options: PostgresConnectionOptions
|
||||
|
||||
constructor(client: PoolClient, options: PostgresConnectionOptions) {
|
||||
this.#client = client
|
||||
this.#options = options
|
||||
}
|
||||
|
||||
async executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {
|
||||
try {
|
||||
const result = await this.#client.queryObject<O>(compiledQuery.sql, [
|
||||
...compiledQuery.parameters,
|
||||
])
|
||||
|
||||
if (
|
||||
result.command === 'INSERT' ||
|
||||
result.command === 'UPDATE' ||
|
||||
result.command === 'DELETE'
|
||||
) {
|
||||
const numAffectedRows = BigInt(result.rowCount || 0)
|
||||
|
||||
return {
|
||||
numUpdatedOrDeletedRows: numAffectedRows,
|
||||
numAffectedRows,
|
||||
rows: result.rows ?? [],
|
||||
} as any
|
||||
}
|
||||
|
||||
return {
|
||||
rows: result.rows ?? [],
|
||||
}
|
||||
} catch (err) {
|
||||
throw extendStackTrace(err, new Error())
|
||||
}
|
||||
}
|
||||
|
||||
async *streamQuery<O>(
|
||||
_compiledQuery: CompiledQuery,
|
||||
chunkSize: number
|
||||
): AsyncIterableIterator<QueryResult<O>> {
|
||||
if (!this.#options.cursor) {
|
||||
throw new Error(
|
||||
"'cursor' is not present in your postgres dialect config. It's required to make streaming work in postgres."
|
||||
)
|
||||
}
|
||||
|
||||
if (!Number.isInteger(chunkSize) || chunkSize <= 0) {
|
||||
throw new Error('chunkSize must be a positive integer')
|
||||
}
|
||||
|
||||
// stream not available
|
||||
return null
|
||||
}
|
||||
|
||||
[PRIVATE_RELEASE_METHOD](): void {
|
||||
this.#client.release()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Create an `index.ts` file to execute a query on incoming requests:
|
||||
|
||||
```ts index.ts
|
||||
import { serve } from 'https://deno.land/std@0.175.0/http/server.ts'
|
||||
import { Pool } from 'https://deno.land/x/postgres@v0.17.0/mod.ts'
|
||||
import {
|
||||
Kysely,
|
||||
Generated,
|
||||
PostgresAdapter,
|
||||
PostgresIntrospector,
|
||||
PostgresQueryCompiler,
|
||||
} from 'https://esm.sh/kysely@0.23.4'
|
||||
import { PostgresDriver } from './DenoPostgresDriver.ts'
|
||||
|
||||
console.log(`Function "kysely-postgres" up and running!`)
|
||||
|
||||
interface AnimalTable {
|
||||
id: Generated<bigint>
|
||||
animal: string
|
||||
created_at: Date
|
||||
}
|
||||
|
||||
// Keys of this interface are table names.
|
||||
interface Database {
|
||||
animals: AnimalTable
|
||||
}
|
||||
|
||||
// Create a database pool with one connection.
|
||||
const pool = new Pool(
|
||||
{
|
||||
tls: { caCertificates: [Deno.env.get('DB_SSL_CERT')!] },
|
||||
database: 'postgres',
|
||||
hostname: Deno.env.get('DB_HOSTNAME'),
|
||||
user: 'postgres',
|
||||
port: 5432,
|
||||
password: Deno.env.get('DB_PASSWORD'),
|
||||
},
|
||||
1
|
||||
)
|
||||
|
||||
// You'd create one of these when you start your app.
|
||||
const db = new Kysely<Database>({
|
||||
dialect: {
|
||||
createAdapter() {
|
||||
return new PostgresAdapter()
|
||||
},
|
||||
createDriver() {
|
||||
return new PostgresDriver({ pool })
|
||||
},
|
||||
createIntrospector(db: Kysely<unknown>) {
|
||||
return new PostgresIntrospector(db)
|
||||
},
|
||||
createQueryCompiler() {
|
||||
return new PostgresQueryCompiler()
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
serve(async (_req) => {
|
||||
try {
|
||||
// Run a query
|
||||
const animals = await db.selectFrom('animals').select(['id', 'animal', 'created_at']).execute()
|
||||
|
||||
// Neat, it's properly typed \o/
|
||||
console.log(animals[0].created_at.getFullYear())
|
||||
|
||||
// Encode the result as pretty printed JSON
|
||||
const body = JSON.stringify(
|
||||
animals,
|
||||
(key, value) => (typeof value === 'bigint' ? value.toString() : value),
|
||||
2
|
||||
)
|
||||
|
||||
// Return the response with the correct content type header
|
||||
return new Response(body, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return new Response(String(err?.message ?? err), { status: 500 })
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
export const Page = ({ children }) => <Layout meta={meta} children={children} />
|
||||
|
||||
export default Page
|
||||
@@ -10,8 +10,13 @@ IPINFO_TOKEN="your https://ipinfo.io token"
|
||||
# openai
|
||||
OPENAI_API_KEY="<YOUR API KEY HERE>"
|
||||
|
||||
# postgres-on-the-edge
|
||||
DATABASE_URL=
|
||||
# postgres-on-the-edge & kysely-postgres
|
||||
DB_HOSTNAME=
|
||||
DB_PASSWORD=
|
||||
DB_SSL_CERT="-----BEGIN CERTIFICATE-----
|
||||
GET YOUR CERT FROM YOUR PROJECT DASHBOARD
|
||||
https://app.supabase.com/project/_/settings/database
|
||||
-----END CERTIFICATE-----"
|
||||
|
||||
# puppeteer
|
||||
PUPPETEER_BROWSERLESS_IO_TOKEN=
|
||||
|
||||
@@ -11,10 +11,11 @@
|
||||
"stripe": "https://esm.sh/stripe@11.1.0?target=deno",
|
||||
"sift": "https://deno.land/x/sift@0.6.0/mod.ts",
|
||||
"@supabase/supabase-js": "https://esm.sh/@supabase/supabase-js@2.7.1",
|
||||
"postgres": "https://deno.land/x/postgres@v0.14.2/mod.ts",
|
||||
"postgres": "https://deno.land/x/postgres@v0.17.0/mod.ts",
|
||||
"puppeteer": "https://deno.land/x/puppeteer@16.2.0/mod.ts",
|
||||
"React": "https://esm.sh/react@18.2.0?deno-std=0.177.0",
|
||||
"upstash_redis": "https://deno.land/x/upstash_redis@v1.19.3/mod.ts",
|
||||
"xhr_polyfill": "https://deno.land/x/xhr@0.3.0/mod.ts"
|
||||
"xhr_polyfill": "https://deno.land/x/xhr@0.3.0/mod.ts",
|
||||
"kysely": "https://esm.sh/kysely@0.23.4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
import {
|
||||
CompiledQuery,
|
||||
DatabaseConnection,
|
||||
Driver,
|
||||
PostgresCursorConstructor,
|
||||
QueryResult,
|
||||
TransactionSettings,
|
||||
} from 'https://esm.sh/kysely@0.23.4'
|
||||
import { freeze, isFunction } from 'https://esm.sh/kysely@0.23.4/dist/esm/util/object-utils.js'
|
||||
import { extendStackTrace } from 'https://esm.sh/kysely@0.23.4/dist/esm/util/stack-trace-utils.js'
|
||||
import { Pool, PoolClient } from 'https://deno.land/x/postgres@v0.17.0/mod.ts'
|
||||
|
||||
export interface PostgresDialectConfig {
|
||||
pool: Pool | (() => Promise<Pool>)
|
||||
cursor?: PostgresCursorConstructor
|
||||
onCreateConnection?: (connection: DatabaseConnection) => Promise<void>
|
||||
}
|
||||
|
||||
const PRIVATE_RELEASE_METHOD = Symbol()
|
||||
|
||||
export class PostgresDriver implements Driver {
|
||||
readonly #config: PostgresDialectConfig
|
||||
readonly #connections = new WeakMap<PoolClient, DatabaseConnection>()
|
||||
#pool?: Pool
|
||||
|
||||
constructor(config: PostgresDialectConfig) {
|
||||
this.#config = freeze({ ...config })
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
this.#pool = isFunction(this.#config.pool) ? await this.#config.pool() : this.#config.pool
|
||||
}
|
||||
|
||||
async acquireConnection(): Promise<DatabaseConnection> {
|
||||
const client = await this.#pool!.connect()
|
||||
let connection = this.#connections.get(client)
|
||||
|
||||
if (!connection) {
|
||||
connection = new PostgresConnection(client, {
|
||||
cursor: this.#config.cursor ?? null,
|
||||
})
|
||||
this.#connections.set(client, connection)
|
||||
|
||||
// The driver must take care of calling `onCreateConnection` when a new
|
||||
// connection is created. The `pg` module doesn't provide an async hook
|
||||
// for the connection creation. We need to call the method explicitly.
|
||||
if (this.#config?.onCreateConnection) {
|
||||
await this.#config.onCreateConnection(connection)
|
||||
}
|
||||
}
|
||||
|
||||
return connection
|
||||
}
|
||||
|
||||
async beginTransaction(
|
||||
connection: DatabaseConnection,
|
||||
settings: TransactionSettings
|
||||
): Promise<void> {
|
||||
if (settings.isolationLevel) {
|
||||
await connection.executeQuery(
|
||||
CompiledQuery.raw(`start transaction isolation level ${settings.isolationLevel}`)
|
||||
)
|
||||
} else {
|
||||
await connection.executeQuery(CompiledQuery.raw('begin'))
|
||||
}
|
||||
}
|
||||
|
||||
async commitTransaction(connection: DatabaseConnection): Promise<void> {
|
||||
await connection.executeQuery(CompiledQuery.raw('commit'))
|
||||
}
|
||||
|
||||
async rollbackTransaction(connection: DatabaseConnection): Promise<void> {
|
||||
await connection.executeQuery(CompiledQuery.raw('rollback'))
|
||||
}
|
||||
|
||||
async releaseConnection(connection: PostgresConnection): Promise<void> {
|
||||
connection[PRIVATE_RELEASE_METHOD]()
|
||||
}
|
||||
|
||||
async destroy(): Promise<void> {
|
||||
if (this.#pool) {
|
||||
const pool = this.#pool
|
||||
this.#pool = undefined
|
||||
await pool.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface PostgresConnectionOptions {
|
||||
cursor: PostgresCursorConstructor | null
|
||||
}
|
||||
|
||||
class PostgresConnection implements DatabaseConnection {
|
||||
#client: PoolClient
|
||||
#options: PostgresConnectionOptions
|
||||
|
||||
constructor(client: PoolClient, options: PostgresConnectionOptions) {
|
||||
this.#client = client
|
||||
this.#options = options
|
||||
}
|
||||
|
||||
async executeQuery<O>(compiledQuery: CompiledQuery): Promise<QueryResult<O>> {
|
||||
try {
|
||||
const result = await this.#client.queryObject<O>(compiledQuery.sql, [
|
||||
...compiledQuery.parameters,
|
||||
])
|
||||
|
||||
if (
|
||||
result.command === 'INSERT' ||
|
||||
result.command === 'UPDATE' ||
|
||||
result.command === 'DELETE'
|
||||
) {
|
||||
const numAffectedRows = BigInt(result.rowCount || 0)
|
||||
|
||||
return {
|
||||
// TODO: remove.
|
||||
numUpdatedOrDeletedRows: numAffectedRows,
|
||||
numAffectedRows,
|
||||
rows: result.rows ?? [],
|
||||
} as any
|
||||
}
|
||||
|
||||
return {
|
||||
rows: result.rows ?? [],
|
||||
}
|
||||
} catch (err) {
|
||||
throw extendStackTrace(err, new Error())
|
||||
}
|
||||
}
|
||||
|
||||
async *streamQuery<O>(
|
||||
_compiledQuery: CompiledQuery,
|
||||
chunkSize: number
|
||||
): AsyncIterableIterator<QueryResult<O>> {
|
||||
if (!this.#options.cursor) {
|
||||
throw new Error(
|
||||
"'cursor' is not present in your postgres dialect config. It's required to make streaming work in postgres."
|
||||
)
|
||||
}
|
||||
|
||||
if (!Number.isInteger(chunkSize) || chunkSize <= 0) {
|
||||
throw new Error('chunkSize must be a positive integer')
|
||||
}
|
||||
|
||||
// stream not available
|
||||
return null
|
||||
}
|
||||
|
||||
[PRIVATE_RELEASE_METHOD](): void {
|
||||
this.#client.release()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// Follow this setup guide to integrate the Deno language server with your editor:
|
||||
// https://deno.land/manual/getting_started/setup_your_environment
|
||||
// This enables autocomplete, go to definition, etc.
|
||||
|
||||
import { serve } from 'std/server'
|
||||
import { Pool } from 'postgres'
|
||||
import {
|
||||
Kysely,
|
||||
Generated,
|
||||
PostgresAdapter,
|
||||
PostgresIntrospector,
|
||||
PostgresQueryCompiler,
|
||||
} from 'kysely'
|
||||
import { PostgresDriver } from './DenoPostgresDriver.ts'
|
||||
|
||||
console.log(`Function "kysely-postgres" up and running!`)
|
||||
|
||||
interface AnimalTable {
|
||||
id: Generated<bigint>
|
||||
animal: string
|
||||
created_at: Date
|
||||
}
|
||||
|
||||
// Keys of this interface are table names.
|
||||
interface Database {
|
||||
animals: AnimalTable
|
||||
}
|
||||
|
||||
// Create a database pool with one connection.
|
||||
const pool = new Pool(
|
||||
{
|
||||
tls: { caCertificates: [Deno.env.get('DB_SSL_CERT')!] },
|
||||
database: 'postgres',
|
||||
hostname: Deno.env.get('DB_HOSTNAME'),
|
||||
user: 'postgres',
|
||||
port: 5432,
|
||||
password: Deno.env.get('DB_PASSWORD'),
|
||||
},
|
||||
1
|
||||
)
|
||||
|
||||
// You'd create one of these when you start your app.
|
||||
const db = new Kysely<Database>({
|
||||
dialect: {
|
||||
createAdapter() {
|
||||
return new PostgresAdapter()
|
||||
},
|
||||
createDriver() {
|
||||
// You need a driver to be able to execute queries. In this example
|
||||
// we use the dummy driver that never does anything.
|
||||
return new PostgresDriver({ pool })
|
||||
},
|
||||
createIntrospector(db: Kysely<unknown>) {
|
||||
return new PostgresIntrospector(db)
|
||||
},
|
||||
createQueryCompiler() {
|
||||
return new PostgresQueryCompiler()
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
serve(async (_req) => {
|
||||
try {
|
||||
// Run a query
|
||||
const animals = await db.selectFrom('animals').select(['id', 'animal', 'created_at']).execute()
|
||||
|
||||
// Neat, it's properly typed \o/
|
||||
console.log(animals[0].created_at.getFullYear())
|
||||
|
||||
// Encode the result as pretty printed JSON
|
||||
const body = JSON.stringify(
|
||||
animals,
|
||||
(key, value) => (typeof value === 'bigint' ? value.toString() : value),
|
||||
2
|
||||
)
|
||||
|
||||
// Return the response with the correct content type header
|
||||
return new Response(body, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
},
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return new Response(String(err?.message ?? err), { status: 500 })
|
||||
}
|
||||
})
|
||||
|
||||
// To invoke: navigate to http://localhost:54321/functions/v1/kysely-postgres
|
||||
@@ -1,11 +1,18 @@
|
||||
import * as postgres from 'postgres'
|
||||
import { Pool } from 'postgres'
|
||||
import { serve } from 'std/server'
|
||||
|
||||
// Get the connection string from the environment variable "DATABASE_URL"
|
||||
const databaseUrl = Deno.env.get('DATABASE_URL')!
|
||||
|
||||
// Create a database pool with three connections that are lazily established
|
||||
const pool = new postgres.Pool(databaseUrl, 3, true)
|
||||
// Create a database pool with one connection.
|
||||
const pool = new Pool(
|
||||
{
|
||||
tls: { enabled: false },
|
||||
database: 'postgres',
|
||||
hostname: Deno.env.get('DB_HOSTNAME'),
|
||||
user: 'postgres',
|
||||
port: 5432,
|
||||
password: Deno.env.get('DB_PASSWORD'),
|
||||
},
|
||||
1
|
||||
)
|
||||
|
||||
serve(async (_req) => {
|
||||
try {
|
||||
@@ -16,7 +23,6 @@ serve(async (_req) => {
|
||||
// Run a query
|
||||
const result = await connection.queryObject`SELECT * FROM animals`
|
||||
const animals = result.rows // [{ id: 1, name: "Lion" }, ...]
|
||||
console.log(animals)
|
||||
|
||||
// Encode the result as pretty printed JSON
|
||||
const body = JSON.stringify(
|
||||
|
||||
Reference in new issue
Block a user