add neon client

pull/355/head
Sven Sauleau 2023-03-01 09:30:35 +00:00
rodzic 1b830d8df2
commit c3fb612d21
6 zmienionych plików z 126 dodań i 1 usunięć

Wyświetl plik

@ -273,6 +273,7 @@ jobs:
echo -e "DOMAIN=\"${{ vars.CF_DEPLOY_DOMAIN }}\"\n" >> consumer/wrangler.toml
echo -e "ADMIN_EMAIL=\"${{ vars.ADMIN_EMAIL }}\"\n" >> consumer/wrangler.toml
yarn
yarn --cwd consumer/
echo "******"
command: publish --config consumer/wrangler.toml

Wyświetl plik

@ -1,5 +1,6 @@
import type { Env } from 'wildebeest/backend/src/types/env'
import d1 from './d1'
import neon from './neon'
export interface Result<T = unknown> {
results?: T[]
@ -32,6 +33,10 @@ export interface QueryBuilder {
insertOrIgnore(q: string): string
}
export async function getDatabase(env: Pick<Env, 'DATABASE'>): Promise<Database> {
export async function getDatabase(env: Pick<Env, 'DATABASE' | 'NEON_DATABASE_URL'>): Promise<Database> {
if (env.NEON_DATABASE_URL !== undefined) {
return neon(env)
}
return d1(env)
}

Wyświetl plik

@ -0,0 +1,111 @@
import * as neon from '@neondatabase/serverless'
import type { Database, Result, QueryBuilder } from 'wildebeest/backend/src/database'
import type { Env } from 'wildebeest/backend/src/types/env'
function sqliteToPsql(query: string): string {
let c = 0
return query.replaceAll(/\?([0-9])?/g, (match: string, p1: string) => {
c += 1
return `$${p1 || c}`
})
}
const qb: QueryBuilder = {
jsonExtract(obj: string, prop: string): string {
return `json_extract_path(${obj}::json, '${prop}')::text`
},
jsonExtractIsNull(obj: string, prop: string): string {
return `${qb.jsonExtract(obj, prop)} = 'null'`
},
set(array: string): string {
return `(SELECT value::text FROM json_array_elements_text(${array}))`
},
epoch(): string {
return 'epoch'
},
insertOrIgnore(q: string): string {
return `INSERT ${q} ON CONFLICT DO NOTHING`
},
}
export default async function make(env: Pick<Env, 'NEON_DATABASE_URL'>): Promise<Database> {
const client = new neon.Client(env.NEON_DATABASE_URL)
await client.connect()
return {
qb,
prepare(query: string) {
return new PreparedStatement(env, query, [], client)
},
dump() {
throw new Error('not implemented')
},
async batch<T = unknown>(statements: PreparedStatement[]): Promise<Result<T>[]> {
throw new Error('not implemented')
console.log(statements)
},
async exec<T = unknown>(query: string): Promise<Result<T>> {
throw new Error('not implemented')
console.log(query)
},
}
}
export class PreparedStatement {
private env: Pick<Env, 'NEON_DATABASE_URL'>
private client: neon.Client
private query: string
private values: any[]
constructor(env: Pick<Env, 'NEON_DATABASE_URL'>, query: string, values: any[], client: neon.Client) {
this.env = env
this.query = query
this.values = values
this.client = client
}
bind(...values: any[]): PreparedStatement {
return new PreparedStatement(this.env, this.query, [...this.values, ...values], this.client)
}
async first<T = unknown>(colName?: string): Promise<T> {
if (colName) {
throw new Error('not implemented')
}
const query = sqliteToPsql(this.query)
const results = await this.client.query(query, this.values)
if (results.rows.length !== 1) {
throw new Error(`expected a single row, returned ${results.rows.length} row(s)`)
}
return results.rows[0] as T
}
async run<T = unknown>(): Promise<Result<T>> {
return this.all()
}
async all<T = unknown>(): Promise<Result<T>> {
const query = sqliteToPsql(this.query)
const results = await this.client.query(query, this.values)
return {
results: results.rows as T[],
success: true,
meta: {},
}
}
async raw<T = unknown>(): Promise<T[]> {
throw new Error('not implemented')
}
}

Wyświetl plik

@ -25,4 +25,6 @@ export interface Env {
SENTRY_DSN: string
SENTRY_ACCESS_CLIENT_ID: string
SENTRY_ACCESS_CLIENT_SECRET: string
NEON_DATABASE_URL?: string
}

Wyświetl plik

@ -44,6 +44,7 @@
"deploy": "yarn build && yarn database:migrate && yarn pages publish frontend/dist --project-name=wildebeest"
},
"dependencies": {
"@neondatabase/serverless": "^0.2.5",
"@types/cookie": "^0.5.1",
"cookie": "^0.5.0",
"http-message-signatures": "^0.1.2",

Wyświetl plik

@ -807,6 +807,11 @@
undici "5.9.1"
ws "^8.2.2"
"@neondatabase/serverless@^0.2.5":
version "0.2.5"
resolved "https://registry.yarnpkg.com/@neondatabase/serverless/-/serverless-0.2.5.tgz#78bd4a905f50d087d06f16c02711fdd05b2a851d"
integrity sha512-Qu/nNZftfoqw4ojVCXU/EgYlfII3mzLm82iXNOUljFumPhoZ/Wp8NJG5DgSAKCWC0zwTyJsojdPLQDj/UPs2vg==
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"