kopia lustrzana https://github.com/cloudflare/wildebeest
test neon
rodzic
2beb65f9e2
commit
575aecd33f
|
@ -2,7 +2,7 @@ name: Deploy
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- sven/neon
|
||||||
repository_dispatch:
|
repository_dispatch:
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
|
@ -273,6 +273,7 @@ jobs:
|
||||||
echo -e "DOMAIN=\"${{ vars.CF_DEPLOY_DOMAIN }}\"\n" >> consumer/wrangler.toml
|
echo -e "DOMAIN=\"${{ vars.CF_DEPLOY_DOMAIN }}\"\n" >> consumer/wrangler.toml
|
||||||
echo -e "ADMIN_EMAIL=\"${{ vars.ADMIN_EMAIL }}\"\n" >> consumer/wrangler.toml
|
echo -e "ADMIN_EMAIL=\"${{ vars.ADMIN_EMAIL }}\"\n" >> consumer/wrangler.toml
|
||||||
|
|
||||||
|
yarn
|
||||||
yarn --cwd consumer/
|
yarn --cwd consumer/
|
||||||
echo "******"
|
echo "******"
|
||||||
command: publish --config consumer/wrangler.toml
|
command: publish --config consumer/wrangler.toml
|
||||||
|
|
|
@ -24,7 +24,7 @@ export async function getAccount(domain: string, accountId: string, db: Database
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getRemoteAccount(handle: Handle, acct: string, db: D1Database): Promise<MastodonAccount | null> {
|
async function getRemoteAccount(handle: Handle, acct: string, db: Database): Promise<MastodonAccount | null> {
|
||||||
// TODO: using webfinger isn't the optimal implementation. We could cache
|
// TODO: using webfinger isn't the optimal implementation. We could cache
|
||||||
// the object in D1 and directly query the remote API, indicated by the actor's
|
// the object in D1 and directly query the remote API, indicated by the actor's
|
||||||
// url field. For now, let's keep it simple.
|
// url field. For now, let's keep it simple.
|
||||||
|
|
|
@ -9,13 +9,18 @@ export async function getPeers(db: Database): Promise<Array<String>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addPeer(db: Database, domain: string): Promise<void> {
|
export async function addPeer(db: Database, domain: string): Promise<void> {
|
||||||
const query = `
|
try {
|
||||||
INSERT OR IGNORE INTO peers (domain)
|
const query = `
|
||||||
VALUES (?)
|
INSERT INTO peers (domain)
|
||||||
`
|
VALUES (?)
|
||||||
|
`
|
||||||
|
|
||||||
const out = await db.prepare(query).bind(domain).run()
|
const out = await db.prepare(query).bind(domain).run()
|
||||||
if (!out.success) {
|
if (!out.success) {
|
||||||
throw new Error('SQL error: ' + out.error)
|
throw new Error('SQL error: ' + out.error)
|
||||||
|
}
|
||||||
|
} catch (err: any) {
|
||||||
|
console.warn(err.stack);
|
||||||
|
// handle peer already exists for psql
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,31 @@
|
||||||
import { type Database } from 'wildebeest/backend/src/database'
|
import { type Database, QueryBuilder } from 'wildebeest/backend/src/database'
|
||||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||||
|
|
||||||
export default function make(env: Env): Database {
|
const qb: QueryBuilder = {
|
||||||
return env.DATABASE
|
jsonExtract(obj: string, prop: string): string {
|
||||||
|
return `json_extract(${obj}, '$.${prop}')`
|
||||||
|
},
|
||||||
|
|
||||||
|
jsonExtractIsNull(obj: string, prop: string): string {
|
||||||
|
return `${qb.jsonExtract(obj, prop)} IS NULL`
|
||||||
|
},
|
||||||
|
|
||||||
|
set(array: string): string {
|
||||||
|
return `(SELECT value FROM json_each(${array}))`
|
||||||
|
},
|
||||||
|
|
||||||
|
psql(raw: string): string {
|
||||||
|
return ''
|
||||||
|
},
|
||||||
|
|
||||||
|
epoch(): string {
|
||||||
|
return '00-00-00 00:00:00'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function make(env: Env): Database {
|
||||||
|
const db = env.DATABASE as any
|
||||||
|
db.qb = qb
|
||||||
|
|
||||||
|
return db as Database
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import type { Env } from 'wildebeest/backend/src/types/env'
|
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||||
import d1 from './d1'
|
import d1 from './d1'
|
||||||
|
import neon from './neon'
|
||||||
|
|
||||||
export interface Result<T = unknown> {
|
export interface Result<T = unknown> {
|
||||||
results?: T[]
|
results?: T[]
|
||||||
|
@ -9,6 +10,7 @@ export interface Result<T = unknown> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Database {
|
export interface Database {
|
||||||
|
qb: QueryBuilder
|
||||||
prepare(query: string): PreparedStatement
|
prepare(query: string): PreparedStatement
|
||||||
dump(): Promise<ArrayBuffer>
|
dump(): Promise<ArrayBuffer>
|
||||||
batch<T = unknown>(statements: PreparedStatement[]): Promise<Result<T>[]>
|
batch<T = unknown>(statements: PreparedStatement[]): Promise<Result<T>[]>
|
||||||
|
@ -23,6 +25,20 @@ export interface PreparedStatement {
|
||||||
raw<T = unknown>(): Promise<T[]>
|
raw<T = unknown>(): Promise<T[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDatabase(env: Env): Database {
|
export interface QueryBuilder {
|
||||||
return d1(env)
|
jsonExtract(obj: string, prop: string): string
|
||||||
|
jsonExtractIsNull(obj: string, prop: string): string
|
||||||
|
set(array: string): string
|
||||||
|
psql(raw: string): string
|
||||||
|
epoch(): string
|
||||||
|
}
|
||||||
|
|
||||||
|
const isTesting = typeof jest !== 'undefined'
|
||||||
|
|
||||||
|
export async function getDatabase(env: Env): Promise<Database> {
|
||||||
|
if (isTesting) {
|
||||||
|
return d1(env)
|
||||||
|
} else {
|
||||||
|
return neon(env)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
import * as pg from 'pg'
|
||||||
|
import type { Database, Result } 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}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function make(env: Env): Database {
|
||||||
|
return {
|
||||||
|
prepare(query: string) {
|
||||||
|
return new PreparedStatement(env, query, [])
|
||||||
|
},
|
||||||
|
|
||||||
|
dump() {
|
||||||
|
throw new Error('not implemented')
|
||||||
|
},
|
||||||
|
|
||||||
|
async batch<T = unknown>(statements: PreparedStatement[]): Promise<Result<T>[]> {
|
||||||
|
console.log(statements)
|
||||||
|
throw new Error('not implemented')
|
||||||
|
},
|
||||||
|
|
||||||
|
async exec<T = unknown>(query: string): Promise<Result<T>> {
|
||||||
|
console.log(query)
|
||||||
|
throw new Error('not implemented')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PreparedStatement {
|
||||||
|
private env: Env
|
||||||
|
private query: string
|
||||||
|
private values: any[]
|
||||||
|
|
||||||
|
constructor(env: Env, query: string, values: any[]) {
|
||||||
|
this.env = env
|
||||||
|
this.query = query
|
||||||
|
this.values = values
|
||||||
|
}
|
||||||
|
|
||||||
|
bind(...values: any[]): PreparedStatement {
|
||||||
|
return new PreparedStatement(this.env, this.query, [...this.values, ...values])
|
||||||
|
}
|
||||||
|
|
||||||
|
private async connect() {
|
||||||
|
const s = 'postgres://postgres:postgres@127.0.0.1/postgres'
|
||||||
|
const client = new pg.Client(s)
|
||||||
|
await client.connect()
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
async first<T = unknown>(colName?: string): Promise<T> {
|
||||||
|
const conn = await this.connect()
|
||||||
|
try {
|
||||||
|
if (colName) {
|
||||||
|
throw new Error('not implemented')
|
||||||
|
}
|
||||||
|
const query = sqliteToPsql(this.query)
|
||||||
|
|
||||||
|
console.log(query, this.values)
|
||||||
|
const results = await conn.query(query, this.values)
|
||||||
|
console.log({ rowCount: results.rowCount })
|
||||||
|
if (results.rows.length !== 1) {
|
||||||
|
throw new Error(`expected a single row, returned ${results.rows.length} row(s)`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.rows[0] as T
|
||||||
|
} finally {
|
||||||
|
await conn.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async run<T = unknown>(): Promise<Result<T>> {
|
||||||
|
return this.all()
|
||||||
|
}
|
||||||
|
|
||||||
|
async all<T = unknown>(): Promise<Result<T>> {
|
||||||
|
const conn = await this.connect()
|
||||||
|
|
||||||
|
try {
|
||||||
|
const query = sqliteToPsql(this.query)
|
||||||
|
console.log(query, this.values)
|
||||||
|
const results = await conn.query(query, this.values)
|
||||||
|
console.log({ rowCount: results.rowCount })
|
||||||
|
|
||||||
|
return {
|
||||||
|
results: results.rows as T[],
|
||||||
|
success: true,
|
||||||
|
meta: {},
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await conn.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async raw<T = unknown>(): Promise<T[]> {
|
||||||
|
throw new Error('not implemented')
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
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}))`
|
||||||
|
},
|
||||||
|
|
||||||
|
psql(raw: string): string {
|
||||||
|
return raw
|
||||||
|
},
|
||||||
|
|
||||||
|
epoch(): string {
|
||||||
|
return 'epoch'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function make(env: Env): Promise<Database> {
|
||||||
|
const client = new neon.Client(env.NEON_DATABASE_URL!)
|
||||||
|
console.log(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>[]> {
|
||||||
|
console.log(statements)
|
||||||
|
throw new Error('not implemented')
|
||||||
|
},
|
||||||
|
|
||||||
|
async exec<T = unknown>(query: string): Promise<Result<T>> {
|
||||||
|
console.log(query)
|
||||||
|
throw new Error('not implemented')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PreparedStatement {
|
||||||
|
private env: Env
|
||||||
|
private client: neon.Client
|
||||||
|
private query: string
|
||||||
|
private values: any[]
|
||||||
|
|
||||||
|
constructor(env: Env, 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)
|
||||||
|
|
||||||
|
console.log(query, this.values)
|
||||||
|
const results = await this.client.query(query, this.values)
|
||||||
|
console.log({ results })
|
||||||
|
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)
|
||||||
|
console.log(query, this.values)
|
||||||
|
const results = await this.client.query(query, this.values)
|
||||||
|
console.log({ results })
|
||||||
|
|
||||||
|
return {
|
||||||
|
results: results.rows as T[],
|
||||||
|
success: true,
|
||||||
|
meta: {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async raw<T = unknown>(): Promise<T[]> {
|
||||||
|
throw new Error('not implemented')
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ export async function getHomeTimeline(domain: string, db: Database, actor: Actor
|
||||||
`
|
`
|
||||||
SELECT
|
SELECT
|
||||||
actor_following.target_actor_id as id,
|
actor_following.target_actor_id as id,
|
||||||
json_extract(actors.properties, '$.followers') as actorFollowersURL
|
${db.qb.jsonExtract('actors.properties', 'followers')} as actorFollowersURL
|
||||||
FROM actor_following
|
FROM actor_following
|
||||||
INNER JOIN actors ON actors.id = actor_following.target_actor_id
|
INNER JOIN actors ON actors.id = actor_following.target_actor_id
|
||||||
WHERE actor_id=? AND state='accepted'
|
WHERE actor_id=? AND state='accepted'
|
||||||
|
@ -60,10 +60,10 @@ INNER JOIN objects ON objects.id = outbox_objects.object_id
|
||||||
INNER JOIN actors ON actors.id = outbox_objects.actor_id
|
INNER JOIN actors ON actors.id = outbox_objects.actor_id
|
||||||
WHERE
|
WHERE
|
||||||
objects.type = 'Note'
|
objects.type = 'Note'
|
||||||
AND outbox_objects.actor_id IN (SELECT value FROM json_each(?2))
|
AND outbox_objects.actor_id IN ${db.qb.set('?2')}
|
||||||
AND json_extract(objects.properties, '$.inReplyTo') IS NULL
|
AND ${db.qb.jsonExtractIsNull('objects.properties', 'inReplyTo')}
|
||||||
AND (outbox_objects.target = '${PUBLIC_GROUP}' OR outbox_objects.target IN (SELECT value FROM json_each(?3)))
|
AND (outbox_objects.target = '${PUBLIC_GROUP}' OR outbox_objects.target IN ${db.qb.set('?3')})
|
||||||
GROUP BY objects.id
|
GROUP BY objects.id ${db.qb.psql(', actors.id, outbox_objects.actor_id, outbox_objects.published_date')}
|
||||||
ORDER by outbox_objects.published_date DESC
|
ORDER by outbox_objects.published_date DESC
|
||||||
LIMIT ?4
|
LIMIT ?4
|
||||||
`
|
`
|
||||||
|
@ -101,7 +101,7 @@ export enum LocalPreference {
|
||||||
function localPreferenceQuery(preference: LocalPreference): string {
|
function localPreferenceQuery(preference: LocalPreference): string {
|
||||||
switch (preference) {
|
switch (preference) {
|
||||||
case LocalPreference.NotSet:
|
case LocalPreference.NotSet:
|
||||||
return '1'
|
return 'true'
|
||||||
case LocalPreference.OnlyLocal:
|
case LocalPreference.OnlyLocal:
|
||||||
return 'objects.local = 1'
|
return 'objects.local = 1'
|
||||||
case LocalPreference.OnlyRemote:
|
case LocalPreference.OnlyRemote:
|
||||||
|
@ -136,10 +136,12 @@ INNER JOIN actors ON actors.id=outbox_objects.actor_id
|
||||||
LEFT JOIN note_hashtags ON objects.id=note_hashtags.object_id
|
LEFT JOIN note_hashtags ON objects.id=note_hashtags.object_id
|
||||||
WHERE objects.type='Note'
|
WHERE objects.type='Note'
|
||||||
AND ${localPreferenceQuery(localPreference)}
|
AND ${localPreferenceQuery(localPreference)}
|
||||||
AND json_extract(objects.properties, '$.inReplyTo') IS NULL
|
AND ${db.qb.jsonExtractIsNull('objects.properties', 'inReplyTo')}
|
||||||
AND outbox_objects.target = '${PUBLIC_GROUP}'
|
AND outbox_objects.target = '${PUBLIC_GROUP}'
|
||||||
${hashtagFilter}
|
${hashtagFilter}
|
||||||
GROUP BY objects.id
|
GROUP BY objects.id ${db.qb.psql(
|
||||||
|
', actors.id, actors.cdate, actors.properties, outbox_objects.actor_id, outbox_objects.published_date'
|
||||||
|
)}
|
||||||
ORDER by outbox_objects.published_date DESC
|
ORDER by outbox_objects.published_date DESC
|
||||||
LIMIT ?1 OFFSET ?2
|
LIMIT ?1 OFFSET ?2
|
||||||
`
|
`
|
||||||
|
|
|
@ -97,7 +97,7 @@ export async function main(context: EventContext<Env, any, any>) {
|
||||||
// configuration, which are used to verify the JWT.
|
// configuration, which are used to verify the JWT.
|
||||||
// TODO: since we don't load the instance configuration anymore, we
|
// TODO: since we don't load the instance configuration anymore, we
|
||||||
// don't need to load the user before anymore.
|
// don't need to load the user before anymore.
|
||||||
if (!(await loadContextData(getDatabase(context.env), clientId, payload.email, context))) {
|
if (!(await loadContextData(await getDatabase(context.env), clientId, payload.email, context))) {
|
||||||
return errors.notAuthorized('failed to load context data')
|
return errors.notAuthorized('failed to load context data')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,4 +25,12 @@ export interface Env {
|
||||||
SENTRY_DSN: string
|
SENTRY_DSN: string
|
||||||
SENTRY_ACCESS_CLIENT_ID: string
|
SENTRY_ACCESS_CLIENT_ID: string
|
||||||
SENTRY_ACCESS_CLIENT_SECRET: string
|
SENTRY_ACCESS_CLIENT_SECRET: string
|
||||||
|
|
||||||
|
NEON_DATABASE_URL?: string
|
||||||
|
|
||||||
|
PSQL_DATABASE_URL?: string
|
||||||
|
|
||||||
|
PSCALE_HOST?: string
|
||||||
|
PSCALE_USERNAME?: string
|
||||||
|
PSCALE_PASSWORD?: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import * as actors from '../activitypub/actors'
|
import * as actors from '../activitypub/actors'
|
||||||
|
import { type Database } from 'wildebeest/backend/src/database'
|
||||||
import type { Actor } from '../activitypub/actors'
|
import type { Actor } from '../activitypub/actors'
|
||||||
|
|
||||||
export type WebFingerResponse = {
|
export type WebFingerResponse = {
|
||||||
|
@ -11,7 +12,7 @@ const headers = {
|
||||||
accept: 'application/jrd+json',
|
accept: 'application/jrd+json',
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function queryAcct(domain: string, db: D1Database, acct: string): Promise<Actor | null> {
|
export async function queryAcct(domain: string, db: Database, acct: string): Promise<Actor | null> {
|
||||||
const url = await queryAcctLink(domain, acct)
|
const url = await queryAcctLink(domain, acct)
|
||||||
if (url === null) {
|
if (url === null) {
|
||||||
return null
|
return null
|
||||||
|
|
|
@ -76,12 +76,14 @@ describe('Mastodon APIs', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('GET /apps is bad request', async () => {
|
test('GET /apps is bad request', async () => {
|
||||||
|
const db = await makeDB()
|
||||||
const vapidKeys = await generateVAPIDKeys()
|
const vapidKeys = await generateVAPIDKeys()
|
||||||
const request = new Request('https://example.com')
|
const request = new Request('https://example.com')
|
||||||
const ctx: any = {
|
const ctx: any = {
|
||||||
next: () => new Response(),
|
next: () => new Response(),
|
||||||
data: null,
|
data: null,
|
||||||
env: {
|
env: {
|
||||||
|
DATABASE: db,
|
||||||
VAPID_JWK: JSON.stringify(vapidKeys),
|
VAPID_JWK: JSON.stringify(vapidKeys),
|
||||||
},
|
},
|
||||||
request,
|
request,
|
||||||
|
|
|
@ -81,7 +81,7 @@ describe('Mastodon APIs', () => {
|
||||||
.prepare(
|
.prepare(
|
||||||
`
|
`
|
||||||
SELECT
|
SELECT
|
||||||
json_extract(properties, '$.content') as content,
|
${db.qb.jsonExtract('properties', 'content')} as content,
|
||||||
original_actor_id,
|
original_actor_id,
|
||||||
original_object_id
|
original_object_id
|
||||||
FROM objects
|
FROM objects
|
||||||
|
@ -758,7 +758,7 @@ describe('Mastodon APIs', () => {
|
||||||
const row = await db
|
const row = await db
|
||||||
.prepare(
|
.prepare(
|
||||||
`
|
`
|
||||||
SELECT json_extract(properties, '$.inReplyTo') as inReplyTo
|
SELECT ${db.qb.jsonExtract('properties', 'inReplyTo')} as inReplyTo
|
||||||
FROM objects
|
FROM objects
|
||||||
WHERE mastodon_id=?
|
WHERE mastodon_id=?
|
||||||
`
|
`
|
||||||
|
|
|
@ -8,7 +8,8 @@ import { promises as fs } from 'fs'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import { BetaDatabase } from '@miniflare/d1'
|
import { BetaDatabase } from '@miniflare/d1'
|
||||||
import * as SQLiteDatabase from 'better-sqlite3'
|
import * as SQLiteDatabase from 'better-sqlite3'
|
||||||
import { type Database } from 'wildebeest/backend/src/database'
|
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
import d1 from 'wildebeest/backend/src/database/d1'
|
||||||
|
|
||||||
export function isUrlValid(s: string) {
|
export function isUrlValid(s: string) {
|
||||||
let url
|
let url
|
||||||
|
@ -32,7 +33,8 @@ export async function makeDB(): Promise<Database> {
|
||||||
db.exec(content)
|
db.exec(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
return db2 as unknown as Database
|
const env = { DATABASE: db2 } as any
|
||||||
|
return d1(env)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertCORS(response: Response) {
|
export function assertCORS(response: Response) {
|
||||||
|
|
|
@ -3,9 +3,14 @@
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/workers-types": "^4.20221111.1",
|
"@cloudflare/workers-types": "^4.20221111.1",
|
||||||
|
"@neondatabase/serverless": "^0.2.5",
|
||||||
"toucan-js": "^3.1.0",
|
"toucan-js": "^3.1.0",
|
||||||
"typescript": "^4.9.4",
|
"typescript": "^4.9.4",
|
||||||
"wrangler": "2.7.1"
|
"wrangler": "2.7.1"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@planetscale/database": "^1.5.0",
|
||||||
|
"pg": "^8.9.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ import { deliverToActor } from 'wildebeest/backend/src/activitypub/deliver'
|
||||||
|
|
||||||
export async function handleDeliverMessage(env: Env, actor: Actor, message: DeliverMessageBody) {
|
export async function handleDeliverMessage(env: Env, actor: Actor, message: DeliverMessageBody) {
|
||||||
const toActorId = new URL(message.toActorId)
|
const toActorId = new URL(message.toActorId)
|
||||||
const targetActor = await actors.getAndCache(toActorId, getDatabase(env as any))
|
const targetActor = await actors.getAndCache(toActorId, await getDatabase(env as any))
|
||||||
if (targetActor === null) {
|
if (targetActor === null) {
|
||||||
console.warn(`actor ${toActorId} not found`)
|
console.warn(`actor ${toActorId} not found`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const signingKey = await getSigningKey(message.userKEK, getDatabase(env as any), actor)
|
const signingKey = await getSigningKey(message.userKEK, await getDatabase(env as any), actor)
|
||||||
await deliverToActor(signingKey, actor, targetActor, message.activity, env.DOMAIN)
|
await deliverToActor(signingKey, actor, targetActor, message.activity, env.DOMAIN)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import type { Env } from './'
|
||||||
|
|
||||||
export async function handleInboxMessage(env: Env, actor: Actor, message: InboxMessageBody) {
|
export async function handleInboxMessage(env: Env, actor: Actor, message: InboxMessageBody) {
|
||||||
const domain = env.DOMAIN
|
const domain = env.DOMAIN
|
||||||
const db = getDatabase(env as any)
|
const db = await getDatabase(env as any)
|
||||||
const adminEmail = env.ADMIN_EMAIL
|
const adminEmail = env.ADMIN_EMAIL
|
||||||
const cache = cacheFromEnv(env)
|
const cache = cacheFromEnv(env)
|
||||||
const activity = message.activity
|
const activity = message.activity
|
||||||
|
|
|
@ -20,7 +20,7 @@ export type Env = {
|
||||||
export default {
|
export default {
|
||||||
async queue(batch: MessageBatch<MessageBody>, env: Env, ctx: ExecutionContext) {
|
async queue(batch: MessageBatch<MessageBody>, env: Env, ctx: ExecutionContext) {
|
||||||
const sentry = initSentryQueue(env, ctx)
|
const sentry = initSentryQueue(env, ctx)
|
||||||
const db = getDatabase(env as any)
|
const db = await getDatabase(env as any)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (const message of batch.messages) {
|
for (const message of batch.messages) {
|
||||||
|
|
1263
consumer/yarn.lock
1263
consumer/yarn.lock
Plik diff jest za duży
Load Diff
|
@ -8,12 +8,13 @@ import { Avatar } from '~/components/avatar'
|
||||||
import { getPersonByEmail } from 'wildebeest/backend/src/activitypub/actors'
|
import { getPersonByEmail } from 'wildebeest/backend/src/activitypub/actors'
|
||||||
import { getErrorHtml } from '~/utils/getErrorHtml/getErrorHtml'
|
import { getErrorHtml } from '~/utils/getErrorHtml/getErrorHtml'
|
||||||
import { buildRedirect } from 'wildebeest/functions/oauth/authorize'
|
import { buildRedirect } from 'wildebeest/functions/oauth/authorize'
|
||||||
|
import { getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const clientLoader = loader$<Promise<Client>, { DATABASE: D1Database }>(async ({ platform, query, html }) => {
|
export const clientLoader = loader$<Promise<Client>, { DATABASE: D1Database }>(async ({ platform, query, html }) => {
|
||||||
const client_id = query.get('client_id') || ''
|
const client_id = query.get('client_id') || ''
|
||||||
let client: Client | null = null
|
let client: Client | null = null
|
||||||
try {
|
try {
|
||||||
client = await getClientById(platform.DATABASE, client_id)
|
client = await getClientById(await getDatabase(platform as any), client_id)
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
const error = e as { stack: string; cause: string }
|
const error = e as { stack: string; cause: string }
|
||||||
console.warn(error.stack, error.cause)
|
console.warn(error.stack, error.cause)
|
||||||
|
@ -48,10 +49,10 @@ export const userLoader = loader$<
|
||||||
throw html(500, getErrorHtml("The Access JWT doesn't contain an email"))
|
throw html(500, getErrorHtml("The Access JWT doesn't contain an email"))
|
||||||
}
|
}
|
||||||
|
|
||||||
const person = await getPersonByEmail(platform.DATABASE, payload.email)
|
const person = await getPersonByEmail(await getDatabase(platform as any), payload.email)
|
||||||
if (person === null) {
|
if (person === null) {
|
||||||
const isFirstLogin = true
|
const isFirstLogin = true
|
||||||
const res = await buildRedirect(platform.DATABASE, request as Request, isFirstLogin, jwt.value)
|
const res = await buildRedirect(await getDatabase(platform as any), request as Request, isFirstLogin, jwt.value)
|
||||||
if (res.status === 302) {
|
if (res.status === 302) {
|
||||||
throw redirect(302, res.headers.get('location') || '')
|
throw redirect(302, res.headers.get('location') || '')
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { component$ } from '@builder.io/qwik'
|
import { component$ } from '@builder.io/qwik'
|
||||||
|
import { getDatabase } from 'wildebeest/backend/src/database'
|
||||||
import { MastodonStatus, StatusContext } from '~/types'
|
import { MastodonStatus, StatusContext } from '~/types'
|
||||||
import Status from '~/components/Status'
|
import Status from '~/components/Status'
|
||||||
import * as statusAPI from 'wildebeest/functions/api/v1/statuses/[id]'
|
import * as statusAPI from 'wildebeest/functions/api/v1/statuses/[id]'
|
||||||
|
@ -17,7 +18,12 @@ export const statusLoader = loader$<
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
let statusText = ''
|
let statusText = ''
|
||||||
try {
|
try {
|
||||||
const statusResponse = await statusAPI.handleRequestGet(platform.DATABASE, params.statusId, domain, {} as Person)
|
const statusResponse = await statusAPI.handleRequestGet(
|
||||||
|
await getDatabase(platform as any),
|
||||||
|
params.statusId,
|
||||||
|
domain,
|
||||||
|
{} as Person
|
||||||
|
)
|
||||||
statusText = await statusResponse.text()
|
statusText = await statusResponse.text()
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
const error = e as { stack: string; cause: string }
|
const error = e as { stack: string; cause: string }
|
||||||
|
@ -31,7 +37,7 @@ export const statusLoader = loader$<
|
||||||
const statusTextContent = await getTextContent(status.content)
|
const statusTextContent = await getTextContent(status.content)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const contextResponse = await contextAPI.handleRequest(domain, platform.DATABASE, params.statusId)
|
const contextResponse = await contextAPI.handleRequest(domain, await getDatabase(platform as any), params.statusId)
|
||||||
const contextText = await contextResponse.text()
|
const contextText = await contextResponse.text()
|
||||||
const context = JSON.parse(contextText ?? null) as StatusContext | null
|
const context = JSON.parse(contextText ?? null) as StatusContext | null
|
||||||
if (!context) {
|
if (!context) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { $, component$ } from '@builder.io/qwik'
|
import { $, component$ } from '@builder.io/qwik'
|
||||||
|
import { getDatabase } from 'wildebeest/backend/src/database'
|
||||||
import { loader$ } from '@builder.io/qwik-city'
|
import { loader$ } from '@builder.io/qwik-city'
|
||||||
import { getErrorHtml } from '~/utils/getErrorHtml/getErrorHtml'
|
import { getErrorHtml } from '~/utils/getErrorHtml/getErrorHtml'
|
||||||
import type { MastodonStatus } from '~/types'
|
import type { MastodonStatus } from '~/types'
|
||||||
|
@ -21,7 +22,7 @@ export const statusesLoader = loader$<
|
||||||
|
|
||||||
const handle = parseHandle(accountId)
|
const handle = parseHandle(accountId)
|
||||||
accountId = handle.localPart
|
accountId = handle.localPart
|
||||||
const response = await getLocalStatuses(request as Request, platform.DATABASE, handle, 0, false)
|
const response = await getLocalStatuses(request as Request, await getDatabase(platform as any), handle, 0, false)
|
||||||
statuses = await response.json<Array<MastodonStatus>>()
|
statuses = await response.json<Array<MastodonStatus>>()
|
||||||
} catch {
|
} catch {
|
||||||
throw html(
|
throw html(
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { component$, Slot, useStyles$ } from '@builder.io/qwik'
|
import { component$, Slot, useStyles$ } from '@builder.io/qwik'
|
||||||
|
import { getDatabase } from 'wildebeest/backend/src/database'
|
||||||
import { type DocumentHead, loader$, useLocation, Link } from '@builder.io/qwik-city'
|
import { type DocumentHead, loader$, useLocation, Link } from '@builder.io/qwik-city'
|
||||||
import { MastodonAccount } from 'wildebeest/backend/src/types'
|
import { MastodonAccount } from 'wildebeest/backend/src/types'
|
||||||
import StickyHeader from '~/components/StickyHeader/StickyHeader'
|
import StickyHeader from '~/components/StickyHeader/StickyHeader'
|
||||||
|
@ -24,14 +25,14 @@ export const accountPageLoader = loader$<
|
||||||
const accountId = url.pathname.split('/')[1]
|
const accountId = url.pathname.split('/')[1]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const statusResponse = await statusAPI.handleRequestGet(platform.DATABASE, params.statusId, domain)
|
const statusResponse = await statusAPI.handleRequestGet(await getDatabase(platform as any), params.statusId, domain)
|
||||||
const statusText = await statusResponse.text()
|
const statusText = await statusResponse.text()
|
||||||
isValidStatus = !!statusText
|
isValidStatus = !!statusText
|
||||||
} catch {
|
} catch {
|
||||||
isValidStatus = false
|
isValidStatus = false
|
||||||
}
|
}
|
||||||
|
|
||||||
account = await getAccount(domain, accountId, platform.DATABASE)
|
account = await getAccount(domain, accountId, await getDatabase(platform as any))
|
||||||
} catch {
|
} catch {
|
||||||
throw html(
|
throw html(
|
||||||
500,
|
500,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { $, component$, useStyles$ } from '@builder.io/qwik'
|
import { $, component$, useStyles$ } from '@builder.io/qwik'
|
||||||
|
import { getDatabase } from 'wildebeest/backend/src/database'
|
||||||
import { loader$ } from '@builder.io/qwik-city'
|
import { loader$ } from '@builder.io/qwik-city'
|
||||||
import styles from '../../../../utils/innerHtmlContent.scss?inline'
|
import styles from '../../../../utils/innerHtmlContent.scss?inline'
|
||||||
import { getErrorHtml } from '~/utils/getErrorHtml/getErrorHtml'
|
import { getErrorHtml } from '~/utils/getErrorHtml/getErrorHtml'
|
||||||
|
@ -22,7 +23,7 @@ export const statusesLoader = loader$<
|
||||||
|
|
||||||
const handle = parseHandle(accountId)
|
const handle = parseHandle(accountId)
|
||||||
accountId = handle.localPart
|
accountId = handle.localPart
|
||||||
const response = await getLocalStatuses(request as Request, platform.DATABASE, handle, 0, true)
|
const response = await getLocalStatuses(request as Request, await getDatabase(platform as any), handle, 0, true)
|
||||||
statuses = await response.json<Array<MastodonStatus>>()
|
statuses = await response.json<Array<MastodonStatus>>()
|
||||||
} catch {
|
} catch {
|
||||||
throw html(
|
throw html(
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { $, component$ } from '@builder.io/qwik'
|
import { $, component$ } from '@builder.io/qwik'
|
||||||
|
import { getDatabase } from 'wildebeest/backend/src/database'
|
||||||
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
||||||
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
||||||
import { StatusesPanel } from '~/components/StatusesPanel/StatusesPanel'
|
import { StatusesPanel } from '~/components/StatusesPanel/StatusesPanel'
|
||||||
|
@ -10,7 +11,7 @@ export const statusesLoader = loader$<Promise<MastodonStatus[]>, { DATABASE: D1D
|
||||||
async ({ platform, html }) => {
|
async ({ platform, html }) => {
|
||||||
try {
|
try {
|
||||||
// TODO: use the "trending" API endpoint here.
|
// TODO: use the "trending" API endpoint here.
|
||||||
const response = await timelines.handleRequest(platform.domain, platform.DATABASE)
|
const response = await timelines.handleRequest(platform.domain, await getDatabase(platform as any))
|
||||||
const results = await response.text()
|
const results = await response.text()
|
||||||
// Manually parse the JSON to ensure that Qwik finds the resulting objects serializable.
|
// Manually parse the JSON to ensure that Qwik finds the resulting objects serializable.
|
||||||
return JSON.parse(results) as MastodonStatus[]
|
return JSON.parse(results) as MastodonStatus[]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { $, component$ } from '@builder.io/qwik'
|
import { $, component$ } from '@builder.io/qwik'
|
||||||
|
import { getDatabase } from 'wildebeest/backend/src/database'
|
||||||
import { MastodonStatus } from '~/types'
|
import { MastodonStatus } from '~/types'
|
||||||
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
||||||
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
||||||
|
@ -11,7 +12,7 @@ export const statusesLoader = loader$<Promise<MastodonStatus[]>, { DATABASE: D1D
|
||||||
async ({ platform, html }) => {
|
async ({ platform, html }) => {
|
||||||
try {
|
try {
|
||||||
// TODO: use the "trending" API endpoint here.
|
// TODO: use the "trending" API endpoint here.
|
||||||
const response = await timelines.handleRequest(platform.domain, platform.DATABASE)
|
const response = await timelines.handleRequest(platform.domain, await getDatabase(platform as any))
|
||||||
const results = await response.text()
|
const results = await response.text()
|
||||||
// Manually parse the JSON to ensure that Qwik finds the resulting objects serializable.
|
// Manually parse the JSON to ensure that Qwik finds the resulting objects serializable.
|
||||||
return JSON.parse(results) as MastodonStatus[]
|
return JSON.parse(results) as MastodonStatus[]
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { $, component$ } from '@builder.io/qwik'
|
import { $, component$ } from '@builder.io/qwik'
|
||||||
|
import { getDatabase } from 'wildebeest/backend/src/database'
|
||||||
import { MastodonStatus } from '~/types'
|
import { MastodonStatus } from '~/types'
|
||||||
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
import * as timelines from 'wildebeest/functions/api/v1/timelines/public'
|
||||||
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
import { DocumentHead, loader$ } from '@builder.io/qwik-city'
|
||||||
|
@ -11,7 +12,7 @@ export const statusesLoader = loader$<Promise<MastodonStatus[]>, { DATABASE: D1D
|
||||||
async ({ platform, html }) => {
|
async ({ platform, html }) => {
|
||||||
try {
|
try {
|
||||||
// TODO: use the "trending" API endpoint here.
|
// TODO: use the "trending" API endpoint here.
|
||||||
const response = await timelines.handleRequest(platform.domain, platform.DATABASE, { local: true })
|
const response = await timelines.handleRequest(platform.domain, await getDatabase(platform as any), { local: true })
|
||||||
const results = await response.text()
|
const results = await response.text()
|
||||||
// Manually parse the JSON to ensure that Qwik finds the resulting objects serializable.
|
// Manually parse the JSON to ensure that Qwik finds the resulting objects serializable.
|
||||||
return JSON.parse(results) as MastodonStatus[]
|
return JSON.parse(results) as MastodonStatus[]
|
||||||
|
|
|
@ -7,7 +7,7 @@ import type { WebFingerResponse } from '../../backend/src/webfinger'
|
||||||
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any> = async ({ request, env }) => {
|
export const onRequest: PagesFunction<Env, any> = async ({ request, env }) => {
|
||||||
return handleRequest(request, getDatabase(env))
|
return handleRequest(request, await getDatabase(env))
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import * as objects from 'wildebeest/backend/src/activitypub/objects'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any> = async ({ params, request, env }) => {
|
export const onRequest: PagesFunction<Env, any> = async ({ params, request, env }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), params.id as string)
|
return handleRequest(domain, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import * as actors from 'wildebeest/backend/src/activitypub/actors'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any> = async ({ params, request, env }) => {
|
export const onRequest: PagesFunction<Env, any> = async ({ params, request, env }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), params.id as string)
|
return handleRequest(domain, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -11,7 +11,7 @@ const headers = {
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any> = async ({ params, request, env }) => {
|
export const onRequest: PagesFunction<Env, any> = async ({ params, request, env }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), params.id as string)
|
return handleRequest(domain, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(domain: string, db: Database, id: string): Promise<Response> {
|
export async function handleRequest(domain: string, db: Database, id: string): Promise<Response> {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import type { Env } from 'wildebeest/backend/src/types/env'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), params.id as string)
|
return handleRequest(domain, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -11,7 +11,7 @@ const headers = {
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any> = async ({ params, request, env }) => {
|
export const onRequest: PagesFunction<Env, any> = async ({ params, request, env }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), params.id as string)
|
return handleRequest(domain, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(domain: string, db: Database, id: string): Promise<Response> {
|
export async function handleRequest(domain: string, db: Database, id: string): Promise<Response> {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import type { Env } from 'wildebeest/backend/src/types/env'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), params.id as string)
|
return handleRequest(domain, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -41,7 +41,7 @@ export const onRequest: PagesFunction<Env, any> = async ({ params, request, env
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(
|
return handleRequest(
|
||||||
domain,
|
domain,
|
||||||
getDatabase(env),
|
await getDatabase(env),
|
||||||
params.id as string,
|
params.id as string,
|
||||||
activity,
|
activity,
|
||||||
env.QUEUE,
|
env.QUEUE,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import type { Env } from 'wildebeest/backend/src/types/env'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), params.id as string, env.userKEK)
|
return handleRequest(domain, await getDatabase(env), params.id as string, env.userKEK)
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { PUBLIC_GROUP } from 'wildebeest/backend/src/activitypub/activities'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), params.id as string)
|
return handleRequest(domain, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -13,7 +13,7 @@ const headers = {
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, params.id as string, getDatabase(env))
|
return handleRequest(domain, params.id as string, await getDatabase(env))
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(domain: string, id: string, db: Database): Promise<Response> {
|
export async function handleRequest(domain: string, id: string, db: Database): Promise<Response> {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import type { Relationship } from 'wildebeest/backend/src/types/account'
|
||||||
import { addFollowing } from 'wildebeest/backend/src/mastodon/follow'
|
import { addFollowing } from 'wildebeest/backend/src/mastodon/follow'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params, data }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params, data }) => {
|
||||||
return handleRequest(request, getDatabase(env), params.id as string, data.connectedActor, env.userKEK)
|
return handleRequest(request, await getDatabase(env), params.id as string, data.connectedActor, env.userKEK)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(
|
export async function handleRequest(
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { getFollowers, loadActors } from 'wildebeest/backend/src/activitypub/act
|
||||||
import * as localFollow from 'wildebeest/backend/src/mastodon/follow'
|
import * as localFollow from 'wildebeest/backend/src/mastodon/follow'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ params, request, env }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ params, request, env }) => {
|
||||||
return handleRequest(request, getDatabase(env), params.id as string)
|
return handleRequest(request, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(request: Request, db: Database, id: string): Promise<Response> {
|
export async function handleRequest(request: Request, db: Database, id: string): Promise<Response> {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import * as webfinger from 'wildebeest/backend/src/webfinger'
|
||||||
import { getFollowing, loadActors } from 'wildebeest/backend/src/activitypub/actors/follow'
|
import { getFollowing, loadActors } from 'wildebeest/backend/src/activitypub/actors/follow'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ params, request, env }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ params, request, env }) => {
|
||||||
return handleRequest(request, getDatabase(env), params.id as string)
|
return handleRequest(request, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(request: Request, db: Database, id: string): Promise<Response> {
|
export async function handleRequest(request: Request, db: Database, id: string): Promise<Response> {
|
||||||
|
|
|
@ -26,7 +26,7 @@ const headers = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
||||||
return handleRequest(request, getDatabase(env), params.id as string)
|
return handleRequest(request, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(request: Request, db: Database, id: string): Promise<Response> {
|
export async function handleRequest(request: Request, db: Database, id: string): Promise<Response> {
|
||||||
|
@ -140,10 +140,10 @@ FROM outbox_objects
|
||||||
INNER JOIN objects ON objects.id=outbox_objects.object_id
|
INNER JOIN objects ON objects.id=outbox_objects.object_id
|
||||||
INNER JOIN actors ON actors.id=outbox_objects.actor_id
|
INNER JOIN actors ON actors.id=outbox_objects.actor_id
|
||||||
WHERE objects.type='Note'
|
WHERE objects.type='Note'
|
||||||
${withReplies ? '' : "AND json_extract(objects.properties, '$.inReplyTo') IS NULL"}
|
${withReplies ? '' : 'AND ' + db.qb.jsonExtractIsNull('objects.properties', 'inReplyTo')}
|
||||||
AND outbox_objects.target = '${PUBLIC_GROUP}'
|
AND outbox_objects.target = '${PUBLIC_GROUP}'
|
||||||
AND outbox_objects.actor_id = ?1
|
AND outbox_objects.actor_id = ?1
|
||||||
AND outbox_objects.cdate > ?2
|
AND outbox_objects.cdate > ?2${db.qb.psql('::timestamp')}
|
||||||
ORDER by outbox_objects.published_date DESC
|
ORDER by outbox_objects.published_date DESC
|
||||||
LIMIT ?3 OFFSET ?4
|
LIMIT ?3 OFFSET ?4
|
||||||
`
|
`
|
||||||
|
@ -161,7 +161,7 @@ LIMIT ?3 OFFSET ?4
|
||||||
return new Response(JSON.stringify(out), { headers })
|
return new Response(JSON.stringify(out), { headers })
|
||||||
}
|
}
|
||||||
|
|
||||||
let afterCdate = '00-00-00 00:00:00'
|
let afterCdate = db.qb.epoch()
|
||||||
if (url.searchParams.has('max_id')) {
|
if (url.searchParams.has('max_id')) {
|
||||||
// Client asked to retrieve statuses after the max_id
|
// Client asked to retrieve statuses after the max_id
|
||||||
// As opposed to Mastodon we don't use incremental ID but UUID, we need
|
// As opposed to Mastodon we don't use incremental ID but UUID, we need
|
||||||
|
|
|
@ -12,7 +12,7 @@ import type { Relationship } from 'wildebeest/backend/src/types/account'
|
||||||
import { removeFollowing } from 'wildebeest/backend/src/mastodon/follow'
|
import { removeFollowing } from 'wildebeest/backend/src/mastodon/follow'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params, data }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params, data }) => {
|
||||||
return handleRequest(request, getDatabase(env), params.id as string, data.connectedActor, env.userKEK)
|
return handleRequest(request, await getDatabase(env), params.id as string, data.connectedActor, env.userKEK)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(
|
export async function handleRequest(
|
||||||
|
|
|
@ -8,7 +8,7 @@ import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||||
import { getFollowingAcct, getFollowingRequestedAcct } from 'wildebeest/backend/src/mastodon/follow'
|
import { getFollowingAcct, getFollowingRequestedAcct } from 'wildebeest/backend/src/mastodon/follow'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
||||||
return handleRequest(request, getDatabase(env), data.connectedActor)
|
return handleRequest(request, await getDatabase(env), data.connectedActor)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(req: Request, db: Database, connectedActor: Person): Promise<Response> {
|
export async function handleRequest(req: Request, db: Database, connectedActor: Person): Promise<Response> {
|
||||||
|
|
|
@ -22,7 +22,7 @@ const headers = {
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, data, env }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, data, env }) => {
|
||||||
return handleRequest(
|
return handleRequest(
|
||||||
getDatabase(env),
|
await getDatabase(env),
|
||||||
request,
|
request,
|
||||||
data.connectedActor,
|
data.connectedActor,
|
||||||
env.CF_ACCOUNT_ID,
|
env.CF_ACCOUNT_ID,
|
||||||
|
|
|
@ -12,7 +12,7 @@ export const onRequest: PagesFunction<Env, any, ContextData> = async ({ data, en
|
||||||
if (!data.connectedActor) {
|
if (!data.connectedActor) {
|
||||||
return errors.notAuthorized('no connected user')
|
return errors.notAuthorized('no connected user')
|
||||||
}
|
}
|
||||||
const user = await loadLocalMastodonAccount(getDatabase(env), data.connectedActor)
|
const user = await loadLocalMastodonAccount(await getDatabase(env), data.connectedActor)
|
||||||
|
|
||||||
const res: CredentialAccount = {
|
const res: CredentialAccount = {
|
||||||
...user,
|
...user,
|
||||||
|
|
|
@ -17,7 +17,7 @@ type AppsPost = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env }) => {
|
||||||
return handleRequest(getDatabase(env), request, getVAPIDKeys(env))
|
return handleRequest(await getDatabase(env), request, getVAPIDKeys(env))
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(db: Database, request: Request, vapidKeys: JWK) {
|
export async function handleRequest(db: Database, request: Request, vapidKeys: JWK) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// https://docs.joinmastodon.org/methods/apps/#verify_credentials
|
// https://docs.joinmastodon.org/methods/apps/#verify_credentials
|
||||||
|
|
||||||
|
import { type Database } from 'wildebeest/backend/src/database'
|
||||||
import { cors } from 'wildebeest/backend/src/utils/cors'
|
import { cors } from 'wildebeest/backend/src/utils/cors'
|
||||||
import { VAPIDPublicKey } from 'wildebeest/backend/src/mastodon/subscription'
|
import { VAPIDPublicKey } from 'wildebeest/backend/src/mastodon/subscription'
|
||||||
import { getVAPIDKeys } from 'wildebeest/backend/src/config'
|
import { getVAPIDKeys } from 'wildebeest/backend/src/config'
|
||||||
|
@ -24,7 +25,7 @@ export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request,
|
||||||
return handleRequest(env.DATABASE, request, getVAPIDKeys(env))
|
return handleRequest(env.DATABASE, request, getVAPIDKeys(env))
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(db: D1Database, request: Request, vapidKeys: JWK) {
|
export async function handleRequest(db: Database, request: Request, vapidKeys: JWK) {
|
||||||
if (request.method !== 'GET') {
|
if (request.method !== 'GET') {
|
||||||
return new Response('', { status: 400 })
|
return new Response('', { status: 400 })
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import type { Env } from 'wildebeest/backend/src/types/env'
|
||||||
import { getPeers } from 'wildebeest/backend/src/activitypub/peers'
|
import { getPeers } from 'wildebeest/backend/src/activitypub/peers'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any> = async ({ env }) => {
|
export const onRequest: PagesFunction<Env, any> = async ({ env }) => {
|
||||||
return handleRequest(getDatabase(env))
|
return handleRequest(await getDatabase(env))
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(db: Database): Promise<Response> {
|
export async function handleRequest(db: Database): Promise<Response> {
|
||||||
|
|
|
@ -15,7 +15,7 @@ const headers = {
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ data, request, env, params }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ data, request, env, params }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, params.id as string, getDatabase(env), data.connectedActor)
|
return handleRequest(domain, params.id as string, await getDatabase(env), data.connectedActor)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(
|
export async function handleRequest(
|
||||||
|
|
|
@ -12,11 +12,11 @@ import { VAPIDPublicKey } from 'wildebeest/backend/src/mastodon/subscription'
|
||||||
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
||||||
return handleGetRequest(getDatabase(env), request, data.connectedActor, data.clientId, getVAPIDKeys(env))
|
return handleGetRequest(await getDatabase(env), request, data.connectedActor, data.clientId, getVAPIDKeys(env))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
||||||
return handlePostRequest(getDatabase(env), request, data.connectedActor, data.clientId, getVAPIDKeys(env))
|
return handlePostRequest(await getDatabase(env), request, data.connectedActor, data.clientId, getVAPIDKeys(env))
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -39,7 +39,7 @@ type StatusCreate = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
||||||
return handleRequest(request, getDatabase(env), data.connectedActor, env.userKEK, env.QUEUE, cacheFromEnv(env))
|
return handleRequest(request, await getDatabase(env), data.connectedActor, env.userKEK, env.QUEUE, cacheFromEnv(env))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: add tests for delivery to followers and mentions to a specific Actor.
|
// FIXME: add tests for delivery to followers and mentions to a specific Actor.
|
||||||
|
|
|
@ -20,13 +20,13 @@ import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ params, env, request, data }) => {
|
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ params, env, request, data }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequestGet(getDatabase(env), params.id as UUID, domain, data.connectedActor)
|
return handleRequestGet(await getDatabase(env), params.id as UUID, domain, data.connectedActor)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const onRequestDelete: PagesFunction<Env, any, ContextData> = async ({ params, env, request, data }) => {
|
export const onRequestDelete: PagesFunction<Env, any, ContextData> = async ({ params, env, request, data }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequestDelete(
|
return handleRequestDelete(
|
||||||
getDatabase(env),
|
await getDatabase(env),
|
||||||
params.id as UUID,
|
params.id as UUID,
|
||||||
data.connectedActor,
|
data.connectedActor,
|
||||||
domain,
|
domain,
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), params.id as string)
|
return handleRequest(domain, await getDatabase(env), params.id as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ env, data, params, request }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ env, data, params, request }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(getDatabase(env), params.id as string, data.connectedActor, env.userKEK, domain)
|
return handleRequest(await getDatabase(env), params.id as string, data.connectedActor, env.userKEK, domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(
|
export async function handleRequest(
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ env, data, params, request }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ env, data, params, request }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(getDatabase(env), params.id as string, data.connectedActor, env.userKEK, env.QUEUE, domain)
|
return handleRequest(await getDatabase(env), params.id as string, data.connectedActor, env.userKEK, env.QUEUE, domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(
|
export async function handleRequest(
|
||||||
|
|
|
@ -14,7 +14,7 @@ const headers = {
|
||||||
|
|
||||||
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ params, env, request }) => {
|
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ params, env, request }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequestGet(getDatabase(env), domain, params.tag as string)
|
return handleRequestGet(await getDatabase(env), domain, params.tag as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequestGet(db: Database, domain: string, value: string): Promise<Response> {
|
export async function handleRequestGet(db: Database, domain: string, value: string): Promise<Response> {
|
||||||
|
|
|
@ -16,7 +16,7 @@ export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request,
|
||||||
const only_media = searchParams.get('only_media') === 'true'
|
const only_media = searchParams.get('only_media') === 'true'
|
||||||
const offset = Number.parseInt(searchParams.get('offset') ?? '0')
|
const offset = Number.parseInt(searchParams.get('offset') ?? '0')
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), { local, remote, only_media, offset })
|
return handleRequest(domain, await getDatabase(env), { local, remote, only_media, offset })
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(
|
export async function handleRequest(
|
||||||
|
|
|
@ -11,7 +11,7 @@ const headers = {
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
export const onRequest: PagesFunction<Env, any, ContextData> = async ({ request, env, params }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(getDatabase(env), request, domain, params.tag as string)
|
return handleRequest(await getDatabase(env), request, domain, params.tag as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(db: Database, request: Request, domain: string, tag: string): Promise<Response> {
|
export async function handleRequest(db: Database, request: Request, domain: string, tag: string): Promise<Response> {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any> = async ({ env, request }) => {
|
export const onRequest: PagesFunction<Env, any> = async ({ env, request }) => {
|
||||||
const domain = new URL(request.url).hostname
|
const domain = new URL(request.url).hostname
|
||||||
return handleRequest(domain, getDatabase(env), env)
|
return handleRequest(domain, await getDatabase(env), env)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(domain: string, db: Database, env: Env) {
|
export async function handleRequest(domain: string, db: Database, env: Env) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { mastodonIdSymbol } from 'wildebeest/backend/src/activitypub/objects'
|
||||||
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env, data }) => {
|
||||||
return handleRequestPost(request, getDatabase(env), data.connectedActor, env.CF_ACCOUNT_ID, env.CF_API_TOKEN)
|
return handleRequestPost(request, await getDatabase(env), data.connectedActor, env.CF_ACCOUNT_ID, env.CF_API_TOKEN)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequestPost(
|
export async function handleRequestPost(
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { updateObjectProperty } from 'wildebeest/backend/src/activitypub/objects
|
||||||
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequestPut: PagesFunction<Env, any, ContextData> = async ({ params, env, request }) => {
|
export const onRequestPut: PagesFunction<Env, any, ContextData> = async ({ params, env, request }) => {
|
||||||
return handleRequestPut(getDatabase(env), params.id as UUID, request)
|
return handleRequestPut(await getDatabase(env), params.id as UUID, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateMedia = {
|
type UpdateMedia = {
|
||||||
|
|
|
@ -22,7 +22,7 @@ type SearchResult = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any> = async ({ request, env }) => {
|
export const onRequest: PagesFunction<Env, any> = async ({ request, env }) => {
|
||||||
return handleRequest(getDatabase(env), request)
|
return handleRequest(await getDatabase(env), request)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(db: Database, request: Request): Promise<Response> {
|
export async function handleRequest(db: Database, request: Request): Promise<Response> {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import * as errors from 'wildebeest/backend/src/errors'
|
||||||
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ env, request, data }) => {
|
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ env, request, data }) => {
|
||||||
return handleRequestPost(getDatabase(env), request, data.connectedActor)
|
return handleRequestPost(await getDatabase(env), request, data.connectedActor)
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddAliasRequest = {
|
type AddAliasRequest = {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import * as access from 'wildebeest/backend/src/access'
|
||||||
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
|
||||||
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env }) => {
|
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env }) => {
|
||||||
return handlePostRequest(request, getDatabase(env), env.userKEK, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)
|
return handlePostRequest(request, await getDatabase(env), env.userKEK, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handlePostRequest(
|
export async function handlePostRequest(
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { type Database, getDatabase } from 'wildebeest/backend/src/database'
|
||||||
const extractJWTFromRequest = (request: Request) => request.headers.get('Cf-Access-Jwt-Assertion') || ''
|
const extractJWTFromRequest = (request: Request) => request.headers.get('Cf-Access-Jwt-Assertion') || ''
|
||||||
|
|
||||||
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env }) => {
|
export const onRequestPost: PagesFunction<Env, any, ContextData> = async ({ request, env }) => {
|
||||||
return handleRequestPost(request, getDatabase(env), env.userKEK, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)
|
return handleRequestPost(request, await getDatabase(env), env.userKEK, env.ACCESS_AUTH_DOMAIN, env.ACCESS_AUD)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function buildRedirect(
|
export async function buildRedirect(
|
||||||
|
|
|
@ -12,7 +12,7 @@ type Body = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const onRequest: PagesFunction<Env, any> = async ({ request, env }) => {
|
export const onRequest: PagesFunction<Env, any> = async ({ request, env }) => {
|
||||||
return handleRequest(getDatabase(env), request)
|
return handleRequest(await getDatabase(env), request)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function handleRequest(db: Database, request: Request): Promise<Response> {
|
export async function handleRequest(db: Database, request: Request): Promise<Response> {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import type { Env } from 'wildebeest/backend/src/types/env'
|
||||||
|
import { getDatabase } from 'wildebeest/backend/src/database'
|
||||||
|
import type { ContextData } from 'wildebeest/backend/src/types/context'
|
||||||
|
import * as neon from '@neondatabase/serverless'
|
||||||
|
|
||||||
|
export const onRequestGet: PagesFunction<Env, any, ContextData> = async ({ env }) => {
|
||||||
|
const client = new neon.Client(env.NEON_DATABASE_URL!)
|
||||||
|
console.log(env.NEON_DATABASE_URL!)
|
||||||
|
await client.connect()
|
||||||
|
|
||||||
|
const res = await client.query('select 2')
|
||||||
|
return new Response(JSON.stringify(res))
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
"@playwright/test": "^1.30.0",
|
"@playwright/test": "^1.30.0",
|
||||||
"@types/jest": "^29.2.4",
|
"@types/jest": "^29.2.4",
|
||||||
"@types/node": "^18.11.11",
|
"@types/node": "^18.11.11",
|
||||||
|
"@types/pg": "^8.6.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
||||||
"@typescript-eslint/parser": "^5.46.1",
|
"@typescript-eslint/parser": "^5.46.1",
|
||||||
"better-sqlite3": "8",
|
"better-sqlite3": "8",
|
||||||
|
@ -44,9 +45,12 @@
|
||||||
"deploy": "yarn build && yarn database:migrate && yarn pages publish frontend/dist --project-name=wildebeest"
|
"deploy": "yarn build && yarn database:migrate && yarn pages publish frontend/dist --project-name=wildebeest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@neondatabase/serverless": "^0.2.5",
|
||||||
|
"@planetscale/database": "^1.5.0",
|
||||||
"@types/cookie": "^0.5.1",
|
"@types/cookie": "^0.5.1",
|
||||||
"cookie": "^0.5.0",
|
"cookie": "^0.5.0",
|
||||||
"http-message-signatures": "^0.1.2",
|
"http-message-signatures": "^0.1.2",
|
||||||
|
"pg": "^8.9.0",
|
||||||
"toucan-js": "^3.1.0"
|
"toucan-js": "^3.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,165 @@
|
||||||
|
-- Migration number: 0000 2022-12-05T20:27:34.391Z
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS actors (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
email TEXT,
|
||||||
|
privkey bytea,
|
||||||
|
privkey_salt bytea,
|
||||||
|
pubkey TEXT,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now()),
|
||||||
|
properties TEXT NOT NULL DEFAULT ('{}')
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS actors_email ON actors(email);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS actor_following (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
actor_id TEXT NOT NULL,
|
||||||
|
target_actor_id TEXT NOT NULL,
|
||||||
|
target_actor_acct TEXT NOT NULL,
|
||||||
|
state TEXT NOT NULL DEFAULT 'pending',
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now())
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS actor_following_actor_id ON actor_following(actor_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS actor_following_target_actor_id ON actor_following(target_actor_id);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS objects (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
mastodon_id TEXT UNIQUE NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now()),
|
||||||
|
original_actor_id TEXT,
|
||||||
|
original_object_id TEXT UNIQUE,
|
||||||
|
reply_to_object_id TEXT,
|
||||||
|
properties TEXT NOT NULL DEFAULT ('{}'),
|
||||||
|
local INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS inbox_objects (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
actor_id TEXT NOT NULL,
|
||||||
|
object_id TEXT NOT NULL,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now())
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS outbox_objects (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
actor_id TEXT NOT NULL,
|
||||||
|
object_id TEXT NOT NULL,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now()),
|
||||||
|
published_date timestamp NOT NULL DEFAULT (now())
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS actor_notifications (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
actor_id TEXT NOT NULL,
|
||||||
|
from_actor_id TEXT NOT NULL,
|
||||||
|
object_id TEXT,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now())
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS actor_notifications_actor_id ON actor_notifications(actor_id);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS actor_favourites (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
actor_id TEXT NOT NULL,
|
||||||
|
object_id TEXT NOT NULL,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now())
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS actor_favourites_actor_id ON actor_favourites(actor_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS actor_favourites_object_id ON actor_favourites(object_id);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS actor_reblogs (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
actor_id TEXT NOT NULL,
|
||||||
|
object_id TEXT NOT NULL,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now())
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS actor_reblogs_actor_id ON actor_reblogs(actor_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS actor_reblogs_object_id ON actor_reblogs(object_id);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS clients (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
secret TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
redirect_uris TEXT NOT NULL,
|
||||||
|
website TEXT,
|
||||||
|
scopes TEXT,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now())
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS actor_replies (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
actor_id TEXT NOT NULL,
|
||||||
|
object_id TEXT NOT NULL,
|
||||||
|
in_reply_to_object_id TEXT NOT NULL,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now())
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS actor_replies_in_reply_to_object_id ON actor_replies(in_reply_to_object_id);
|
||||||
|
-- Migration number: 0001 2023-01-16T13:09:04.033Z
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX unique_actor_following ON actor_following (actor_id, target_actor_id);
|
||||||
|
-- Migration number: 0002 2023-01-16T13:46:54.975Z
|
||||||
|
|
||||||
|
ALTER TABLE outbox_objects
|
||||||
|
ADD target TEXT NOT NULL DEFAULT 'https://www.w3.org/ns/activitystreams#Public';
|
||||||
|
-- Migration number: 0003 2023-02-02T15:03:27.478Z
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS peers (
|
||||||
|
domain TEXT UNIQUE NOT NULL
|
||||||
|
);
|
||||||
|
-- Migration number: 0004 2023-02-03T17:17:19.099Z
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS outbox_objects_actor_id ON outbox_objects(actor_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS outbox_objects_target ON outbox_objects(target);
|
||||||
|
-- Migration number: 0005 2023-02-07T10:57:21.848Z
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS idempotency_keys (
|
||||||
|
key TEXT PRIMARY KEY,
|
||||||
|
object_id TEXT NOT NULL,
|
||||||
|
expires_at timestamp NOT NULL
|
||||||
|
|
||||||
|
);
|
||||||
|
-- Migration number: 0006 2023-02-13T11:18:03.485Z
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS note_hashtags (
|
||||||
|
value TEXT NOT NULL,
|
||||||
|
object_id TEXT NOT NULL,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now())
|
||||||
|
|
||||||
|
);
|
||||||
|
-- Migration number: 0007 2023-02-15T11:01:46.585Z
|
||||||
|
|
||||||
|
CREATE TABLE subscriptions (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
actor_id TEXT NOT NULL,
|
||||||
|
client_id TEXT NOT NULL,
|
||||||
|
endpoint TEXT NOT NULL,
|
||||||
|
key_p256dh TEXT NOT NULL,
|
||||||
|
key_auth TEXT NOT NULL,
|
||||||
|
alert_mention INTEGER NOT NULL,
|
||||||
|
alert_status INTEGER NOT NULL,
|
||||||
|
alert_reblog INTEGER NOT NULL,
|
||||||
|
alert_follow INTEGER NOT NULL,
|
||||||
|
alert_follow_request INTEGER NOT NULL,
|
||||||
|
alert_favourite INTEGER NOT NULL,
|
||||||
|
alert_poll INTEGER NOT NULL,
|
||||||
|
alert_update INTEGER NOT NULL,
|
||||||
|
alert_admin_sign_up INTEGER NOT NULL,
|
||||||
|
alert_admin_report INTEGER NOT NULL,
|
||||||
|
policy TEXT NOT NULL,
|
||||||
|
cdate timestamp NOT NULL DEFAULT (now()),
|
||||||
|
|
||||||
|
UNIQUE(actor_id, client_id)
|
||||||
|
);
|
|
@ -101,7 +101,7 @@ resource "random_password" "user_key" {
|
||||||
resource "cloudflare_pages_project" "wildebeest_pages_project" {
|
resource "cloudflare_pages_project" "wildebeest_pages_project" {
|
||||||
account_id = var.cloudflare_account_id
|
account_id = var.cloudflare_account_id
|
||||||
name = "wildebeest-${lower(var.name_suffix)}"
|
name = "wildebeest-${lower(var.name_suffix)}"
|
||||||
production_branch = "main"
|
production_branch = "sven/neon"
|
||||||
|
|
||||||
deployment_configs {
|
deployment_configs {
|
||||||
production {
|
production {
|
||||||
|
|
180
yarn.lock
180
yarn.lock
|
@ -316,12 +316,12 @@
|
||||||
|
|
||||||
"@databases/split-sql-query@1.0.3":
|
"@databases/split-sql-query@1.0.3":
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@databases/split-sql-query/-/split-sql-query-1.0.3.tgz#de2a14b16be14769b79de77e9b62f4a4aded13f9"
|
resolved "https://registry.npmjs.org/@databases/split-sql-query/-/split-sql-query-1.0.3.tgz"
|
||||||
integrity sha512-Q3UYX85e34yE9KXa095AJtJhBQ0NpLfC0kS9ydFKuNB25cto4YddY52RuXN81m2t0pS1Atg31ylNpKfNCnUPdA==
|
integrity sha512-Q3UYX85e34yE9KXa095AJtJhBQ0NpLfC0kS9ydFKuNB25cto4YddY52RuXN81m2t0pS1Atg31ylNpKfNCnUPdA==
|
||||||
|
|
||||||
"@databases/sql@3.2.0":
|
"@databases/sql@3.2.0":
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@databases/sql/-/sql-3.2.0.tgz#ac55ddaed5408c98e3891362ac5b70d06d7a89ff"
|
resolved "https://registry.npmjs.org/@databases/sql/-/sql-3.2.0.tgz"
|
||||||
integrity sha512-xQZzKIa0lvcdo0MYxnyFMVS1TRla9lpDSCYkobJl19vQEOJ9TqE4o8QBGRJNUfhSkbQIWyvMeBl3KBBbqyUVQQ==
|
integrity sha512-xQZzKIa0lvcdo0MYxnyFMVS1TRla9lpDSCYkobJl19vQEOJ9TqE4o8QBGRJNUfhSkbQIWyvMeBl3KBBbqyUVQQ==
|
||||||
|
|
||||||
"@esbuild-plugins/node-globals-polyfill@^0.1.1":
|
"@esbuild-plugins/node-globals-polyfill@^0.1.1":
|
||||||
|
@ -636,7 +636,7 @@
|
||||||
|
|
||||||
"@miniflare/cli-parser@2.11.0":
|
"@miniflare/cli-parser@2.11.0":
|
||||||
version "2.11.0"
|
version "2.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/@miniflare/cli-parser/-/cli-parser-2.11.0.tgz#47f517731791c9e652e9849d590fde3235737529"
|
resolved "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.11.0.tgz"
|
||||||
integrity sha512-JUmyRzEGAS6CouvXJwBh8p44onfw3KRpfq5JGXEuHModOGjTp6li7PQyCTNPV2Hv/7StAXWnTFGXeAqyDHuTig==
|
integrity sha512-JUmyRzEGAS6CouvXJwBh8p44onfw3KRpfq5JGXEuHModOGjTp6li7PQyCTNPV2Hv/7StAXWnTFGXeAqyDHuTig==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@miniflare/shared" "2.11.0"
|
"@miniflare/shared" "2.11.0"
|
||||||
|
@ -688,7 +688,7 @@
|
||||||
|
|
||||||
"@miniflare/http-server@2.11.0":
|
"@miniflare/http-server@2.11.0":
|
||||||
version "2.11.0"
|
version "2.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/@miniflare/http-server/-/http-server-2.11.0.tgz#76d2e2c6549528d965e5f48a8ddc3448c28d4569"
|
resolved "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.11.0.tgz"
|
||||||
integrity sha512-sMLcrDFzqqAvnQmAUH0hRTo8sBjW79VZYfnIH5FAGSGcKX6kdAGs9RStdYZ4CftQCBAEQScX0KBsMx5FwJRe9Q==
|
integrity sha512-sMLcrDFzqqAvnQmAUH0hRTo8sBjW79VZYfnIH5FAGSGcKX6kdAGs9RStdYZ4CftQCBAEQScX0KBsMx5FwJRe9Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@miniflare/core" "2.11.0"
|
"@miniflare/core" "2.11.0"
|
||||||
|
@ -731,7 +731,7 @@
|
||||||
|
|
||||||
"@miniflare/scheduler@2.11.0":
|
"@miniflare/scheduler@2.11.0":
|
||||||
version "2.11.0"
|
version "2.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/@miniflare/scheduler/-/scheduler-2.11.0.tgz#2568d44f571e73355369be6a6da4481aa4af25c8"
|
resolved "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.11.0.tgz"
|
||||||
integrity sha512-DPdzINhdWeS99eIicGoluMsD4pLTTAWNQbgCv3CTwgdKA3dxdvMSCkNqZzQLiALzvk9+rSfj46FlH++HE7o7/w==
|
integrity sha512-DPdzINhdWeS99eIicGoluMsD4pLTTAWNQbgCv3CTwgdKA3dxdvMSCkNqZzQLiALzvk9+rSfj46FlH++HE7o7/w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@miniflare/core" "2.11.0"
|
"@miniflare/core" "2.11.0"
|
||||||
|
@ -807,6 +807,11 @@
|
||||||
undici "5.9.1"
|
undici "5.9.1"
|
||||||
ws "^8.2.2"
|
ws "^8.2.2"
|
||||||
|
|
||||||
|
"@neondatabase/serverless@^0.2.5":
|
||||||
|
version "0.2.5"
|
||||||
|
resolved "https://registry.npmjs.org/@neondatabase/serverless/-/serverless-0.2.5.tgz"
|
||||||
|
integrity sha512-Qu/nNZftfoqw4ojVCXU/EgYlfII3mzLm82iXNOUljFumPhoZ/Wp8NJG5DgSAKCWC0zwTyJsojdPLQDj/UPs2vg==
|
||||||
|
|
||||||
"@nodelib/fs.scandir@2.1.5":
|
"@nodelib/fs.scandir@2.1.5":
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
|
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
|
||||||
|
@ -828,9 +833,14 @@
|
||||||
"@nodelib/fs.scandir" "2.1.5"
|
"@nodelib/fs.scandir" "2.1.5"
|
||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
|
"@planetscale/database@^1.5.0":
|
||||||
|
version "1.5.0"
|
||||||
|
resolved "https://registry.npmjs.org/@planetscale/database/-/database-1.5.0.tgz"
|
||||||
|
integrity sha512-Qwh7Or1W5dB5mZ9EQqDkgvkDKhBBmQe58KIVUy0SGocNtr5fP4JAWtvZ6EdLAV6C6hVpzNlCA2xIg9lKTswm1Q==
|
||||||
|
|
||||||
"@playwright/test@^1.30.0":
|
"@playwright/test@^1.30.0":
|
||||||
version "1.30.0"
|
version "1.30.0"
|
||||||
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.30.0.tgz#8c0c4930ff2c7be7b3ec3fd434b2a3b4465ed7cb"
|
resolved "https://registry.npmjs.org/@playwright/test/-/test-1.30.0.tgz"
|
||||||
integrity sha512-SVxkQw1xvn/Wk/EvBnqWIq6NLo1AppwbYOjNLmyU0R1RoQ3rLEBtmjTnElcnz8VEtn11fptj1ECxK0tgURhajw==
|
integrity sha512-SVxkQw1xvn/Wk/EvBnqWIq6NLo1AppwbYOjNLmyU0R1RoQ3rLEBtmjTnElcnz8VEtn11fptj1ECxK0tgURhajw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
@ -838,7 +848,7 @@
|
||||||
|
|
||||||
"@sentry/core@7.28.1":
|
"@sentry/core@7.28.1":
|
||||||
version "7.28.1"
|
version "7.28.1"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.28.1.tgz#c712ce17469b18b01606108817be24a99ed2116e"
|
resolved "https://registry.npmjs.org/@sentry/core/-/core-7.28.1.tgz"
|
||||||
integrity sha512-7wvnuvn/mrAfcugWoCG/3pqDIrUgH5t+HisMJMGw0h9Tc33KqrmqMDCQVvjlrr2pWrw/vuUCFdm8CbUHJ832oQ==
|
integrity sha512-7wvnuvn/mrAfcugWoCG/3pqDIrUgH5t+HisMJMGw0h9Tc33KqrmqMDCQVvjlrr2pWrw/vuUCFdm8CbUHJ832oQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sentry/types" "7.28.1"
|
"@sentry/types" "7.28.1"
|
||||||
|
@ -847,12 +857,12 @@
|
||||||
|
|
||||||
"@sentry/types@7.28.1":
|
"@sentry/types@7.28.1":
|
||||||
version "7.28.1"
|
version "7.28.1"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.28.1.tgz#9018b4c152b475de9bedd267237393d3c9b1253d"
|
resolved "https://registry.npmjs.org/@sentry/types/-/types-7.28.1.tgz"
|
||||||
integrity sha512-DvSplMVrVEmOzR2M161V5+B8Up3vR71xMqJOpWTzE9TqtFJRGPtqT/5OBsNJJw1+/j2ssMcnKwbEo9Q2EGeS6g==
|
integrity sha512-DvSplMVrVEmOzR2M161V5+B8Up3vR71xMqJOpWTzE9TqtFJRGPtqT/5OBsNJJw1+/j2ssMcnKwbEo9Q2EGeS6g==
|
||||||
|
|
||||||
"@sentry/utils@7.28.1":
|
"@sentry/utils@7.28.1":
|
||||||
version "7.28.1"
|
version "7.28.1"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.28.1.tgz#0a7b6aa4b09e91e4d1aded2a8c8dbaf818cee96e"
|
resolved "https://registry.npmjs.org/@sentry/utils/-/utils-7.28.1.tgz"
|
||||||
integrity sha512-75/jzLUO9HH09iC9TslNimGbxOP3jgn89P+q7uR+rp2fJfRExHVeKJZQdK0Ij4/SmE7TJ3Uh2r154N0INZEx1g==
|
integrity sha512-75/jzLUO9HH09iC9TslNimGbxOP3jgn89P+q7uR+rp2fJfRExHVeKJZQdK0Ij4/SmE7TJ3Uh2r154N0INZEx1g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sentry/types" "7.28.1"
|
"@sentry/types" "7.28.1"
|
||||||
|
@ -919,7 +929,7 @@
|
||||||
|
|
||||||
"@types/cookie@^0.5.1":
|
"@types/cookie@^0.5.1":
|
||||||
version "0.5.1"
|
version "0.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.5.1.tgz#b29aa1f91a59f35e29ff8f7cb24faf1a3a750554"
|
resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.1.tgz"
|
||||||
integrity sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==
|
integrity sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==
|
||||||
|
|
||||||
"@types/graceful-fs@^4.1.3":
|
"@types/graceful-fs@^4.1.3":
|
||||||
|
@ -966,6 +976,15 @@
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-18.11.11.tgz"
|
||||||
integrity sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g==
|
integrity sha512-KJ021B1nlQUBLopzZmPBVuGU9un7WJd/W4ya7Ih02B4Uwky5Nja0yGYav2EfYIk0RR2Q9oVhf60S2XR1BCWJ2g==
|
||||||
|
|
||||||
|
"@types/pg@^8.6.6":
|
||||||
|
version "8.6.6"
|
||||||
|
resolved "https://registry.npmjs.org/@types/pg/-/pg-8.6.6.tgz"
|
||||||
|
integrity sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
pg-protocol "*"
|
||||||
|
pg-types "^2.2.0"
|
||||||
|
|
||||||
"@types/prettier@^2.1.5":
|
"@types/prettier@^2.1.5":
|
||||||
version "2.7.1"
|
version "2.7.1"
|
||||||
resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz"
|
resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz"
|
||||||
|
@ -1159,7 +1178,7 @@ array-union@^2.1.0:
|
||||||
|
|
||||||
available-typed-arrays@^1.0.5:
|
available-typed-arrays@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz"
|
||||||
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
||||||
|
|
||||||
babel-jest@^29.3.1:
|
babel-jest@^29.3.1:
|
||||||
|
@ -1310,6 +1329,11 @@ buffer-from@^1.0.0:
|
||||||
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
|
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
|
||||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||||
|
|
||||||
|
buffer-writer@2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz"
|
||||||
|
integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==
|
||||||
|
|
||||||
buffer@^5.5.0:
|
buffer@^5.5.0:
|
||||||
version "5.7.1"
|
version "5.7.1"
|
||||||
resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz"
|
resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz"
|
||||||
|
@ -1334,7 +1358,7 @@ busboy@^1.6.0:
|
||||||
|
|
||||||
call-bind@^1.0.0, call-bind@^1.0.2:
|
call-bind@^1.0.0, call-bind@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz"
|
||||||
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
|
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
|
||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.1"
|
function-bind "^1.1.1"
|
||||||
|
@ -2520,21 +2544,21 @@ is-stream@^3.0.0:
|
||||||
|
|
||||||
is-string@^1.0.5, is-string@^1.0.7:
|
is-string@^1.0.5, is-string@^1.0.7:
|
||||||
version "1.0.7"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
|
resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz"
|
||||||
integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
|
integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
|
||||||
dependencies:
|
dependencies:
|
||||||
has-tostringtag "^1.0.0"
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
is-symbol@^1.0.2, is-symbol@^1.0.3:
|
is-symbol@^1.0.2, is-symbol@^1.0.3:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
|
resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz"
|
||||||
integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
|
integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
|
||||||
dependencies:
|
dependencies:
|
||||||
has-symbols "^1.0.2"
|
has-symbols "^1.0.2"
|
||||||
|
|
||||||
is-typed-array@^1.1.10, is-typed-array@^1.1.9:
|
is-typed-array@^1.1.10, is-typed-array@^1.1.9:
|
||||||
version "1.1.10"
|
version "1.1.10"
|
||||||
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f"
|
resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz"
|
||||||
integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==
|
integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==
|
||||||
dependencies:
|
dependencies:
|
||||||
available-typed-arrays "^1.0.5"
|
available-typed-arrays "^1.0.5"
|
||||||
|
@ -2545,7 +2569,7 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.9:
|
||||||
|
|
||||||
is-weakref@^1.0.2:
|
is-weakref@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
|
resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz"
|
||||||
integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
|
integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind "^1.0.2"
|
call-bind "^1.0.2"
|
||||||
|
@ -3173,7 +3197,7 @@ mimic-response@^3.1.0:
|
||||||
|
|
||||||
miniflare@2.11.0:
|
miniflare@2.11.0:
|
||||||
version "2.11.0"
|
version "2.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-2.11.0.tgz#36c575e1e75451c416f136d188b744896becc352"
|
resolved "https://registry.npmjs.org/miniflare/-/miniflare-2.11.0.tgz"
|
||||||
integrity sha512-QA18I1VQXdCo4nBtPJUcUDxW8c9xbc5ex5F61jwhkGVOISSnYdEheolESmjr8MYk28xwi0XD1ozS4rLaTONd+w==
|
integrity sha512-QA18I1VQXdCo4nBtPJUcUDxW8c9xbc5ex5F61jwhkGVOISSnYdEheolESmjr8MYk28xwi0XD1ozS4rLaTONd+w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@miniflare/cache" "2.11.0"
|
"@miniflare/cache" "2.11.0"
|
||||||
|
@ -3247,7 +3271,7 @@ natural-compare@^1.4.0:
|
||||||
|
|
||||||
nice-try@^1.0.4:
|
nice-try@^1.0.4:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz"
|
||||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||||
|
|
||||||
node-abi@^3.3.0:
|
node-abi@^3.3.0:
|
||||||
|
@ -3274,7 +3298,7 @@ node-releases@^2.0.6:
|
||||||
|
|
||||||
normalize-package-data@^2.3.2:
|
normalize-package-data@^2.3.2:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
|
resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz"
|
||||||
integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
|
integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
|
||||||
dependencies:
|
dependencies:
|
||||||
hosted-git-info "^2.1.4"
|
hosted-git-info "^2.1.4"
|
||||||
|
@ -3289,7 +3313,7 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||||
|
|
||||||
npm-run-all@^4.1.5:
|
npm-run-all@^4.1.5:
|
||||||
version "4.1.5"
|
version "4.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
|
resolved "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz"
|
||||||
integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
|
integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles "^3.2.1"
|
ansi-styles "^3.2.1"
|
||||||
|
@ -3328,17 +3352,17 @@ npx-import@^1.1.3:
|
||||||
|
|
||||||
object-inspect@^1.12.2, object-inspect@^1.9.0:
|
object-inspect@^1.12.2, object-inspect@^1.9.0:
|
||||||
version "1.12.2"
|
version "1.12.2"
|
||||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
|
resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz"
|
||||||
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
|
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
|
||||||
|
|
||||||
object-keys@^1.1.1:
|
object-keys@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz"
|
||||||
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
||||||
|
|
||||||
object.assign@^4.1.4:
|
object.assign@^4.1.4:
|
||||||
version "4.1.4"
|
version "4.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
|
resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz"
|
||||||
integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
|
integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind "^1.0.2"
|
call-bind "^1.0.2"
|
||||||
|
@ -3412,6 +3436,11 @@ p-try@^2.0.0:
|
||||||
resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz"
|
resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz"
|
||||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||||
|
|
||||||
|
packet-reader@1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz"
|
||||||
|
integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==
|
||||||
|
|
||||||
parent-module@^1.0.0:
|
parent-module@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
|
||||||
|
@ -3421,7 +3450,7 @@ parent-module@^1.0.0:
|
||||||
|
|
||||||
parse-json@^4.0.0:
|
parse-json@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
|
resolved "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz"
|
||||||
integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==
|
integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==
|
||||||
dependencies:
|
dependencies:
|
||||||
error-ex "^1.3.1"
|
error-ex "^1.3.1"
|
||||||
|
@ -3489,6 +3518,57 @@ path-type@^4.0.0:
|
||||||
resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
|
resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
|
||||||
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
|
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
|
||||||
|
|
||||||
|
pg-connection-string@^2.5.0:
|
||||||
|
version "2.5.0"
|
||||||
|
resolved "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz"
|
||||||
|
integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==
|
||||||
|
|
||||||
|
pg-int8@1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz"
|
||||||
|
integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==
|
||||||
|
|
||||||
|
pg-pool@^3.5.2:
|
||||||
|
version "3.5.2"
|
||||||
|
resolved "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz"
|
||||||
|
integrity sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==
|
||||||
|
|
||||||
|
pg-protocol@*, pg-protocol@^1.6.0:
|
||||||
|
version "1.6.0"
|
||||||
|
resolved "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz"
|
||||||
|
integrity sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==
|
||||||
|
|
||||||
|
pg-types@^2.1.0, pg-types@^2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz"
|
||||||
|
integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==
|
||||||
|
dependencies:
|
||||||
|
pg-int8 "1.0.1"
|
||||||
|
postgres-array "~2.0.0"
|
||||||
|
postgres-bytea "~1.0.0"
|
||||||
|
postgres-date "~1.0.4"
|
||||||
|
postgres-interval "^1.1.0"
|
||||||
|
|
||||||
|
pg@^8.9.0:
|
||||||
|
version "8.9.0"
|
||||||
|
resolved "https://registry.npmjs.org/pg/-/pg-8.9.0.tgz"
|
||||||
|
integrity sha512-ZJM+qkEbtOHRuXjmvBtOgNOXOtLSbxiMiUVMgE4rV6Zwocy03RicCVvDXgx8l4Biwo8/qORUnEqn2fdQzV7KCg==
|
||||||
|
dependencies:
|
||||||
|
buffer-writer "2.0.0"
|
||||||
|
packet-reader "1.0.0"
|
||||||
|
pg-connection-string "^2.5.0"
|
||||||
|
pg-pool "^3.5.2"
|
||||||
|
pg-protocol "^1.6.0"
|
||||||
|
pg-types "^2.1.0"
|
||||||
|
pgpass "1.x"
|
||||||
|
|
||||||
|
pgpass@1.x:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz"
|
||||||
|
integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==
|
||||||
|
dependencies:
|
||||||
|
split2 "^4.1.0"
|
||||||
|
|
||||||
picocolors@^1.0.0:
|
picocolors@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz"
|
||||||
|
@ -3526,6 +3606,28 @@ playwright-core@1.30.0:
|
||||||
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.30.0.tgz#de987cea2e86669e3b85732d230c277771873285"
|
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.30.0.tgz#de987cea2e86669e3b85732d230c277771873285"
|
||||||
integrity sha512-7AnRmTCf+GVYhHbLJsGUtskWTE33SwMZkybJ0v6rqR1boxq2x36U7p1vDRV7HO2IwTZgmycracLxPEJI49wu4g==
|
integrity sha512-7AnRmTCf+GVYhHbLJsGUtskWTE33SwMZkybJ0v6rqR1boxq2x36U7p1vDRV7HO2IwTZgmycracLxPEJI49wu4g==
|
||||||
|
|
||||||
|
postgres-array@~2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz"
|
||||||
|
integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==
|
||||||
|
|
||||||
|
postgres-bytea@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz"
|
||||||
|
integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==
|
||||||
|
|
||||||
|
postgres-date@~1.0.4:
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz"
|
||||||
|
integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==
|
||||||
|
|
||||||
|
postgres-interval@^1.1.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz"
|
||||||
|
integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==
|
||||||
|
dependencies:
|
||||||
|
xtend "^4.0.0"
|
||||||
|
|
||||||
prebuild-install@^7.1.0:
|
prebuild-install@^7.1.0:
|
||||||
version "7.1.1"
|
version "7.1.1"
|
||||||
resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz"
|
resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz"
|
||||||
|
@ -3905,6 +4007,11 @@ spdx-license-ids@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779"
|
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779"
|
||||||
integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==
|
integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==
|
||||||
|
|
||||||
|
split2@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz"
|
||||||
|
integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==
|
||||||
|
|
||||||
sprintf-js@~1.0.2:
|
sprintf-js@~1.0.2:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
|
resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
|
||||||
|
@ -4095,7 +4202,7 @@ to-regex-range@^5.0.1:
|
||||||
|
|
||||||
toucan-js@^3.1.0:
|
toucan-js@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/toucan-js/-/toucan-js-3.1.0.tgz#412cf43c259e702f46427e465adb2f588b7eea85"
|
resolved "https://registry.npmjs.org/toucan-js/-/toucan-js-3.1.0.tgz"
|
||||||
integrity sha512-bRbq/HB+aSfwbsSoCNI6qyPXx2bhsscxSYxnAY63xXv9lIeOLUYfvYdOIBWfAVj9QHNST+X83GQ0lj/llvHpVg==
|
integrity sha512-bRbq/HB+aSfwbsSoCNI6qyPXx2bhsscxSYxnAY63xXv9lIeOLUYfvYdOIBWfAVj9QHNST+X83GQ0lj/llvHpVg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@sentry/core" "7.28.1"
|
"@sentry/core" "7.28.1"
|
||||||
|
@ -4104,7 +4211,7 @@ toucan-js@^3.1.0:
|
||||||
|
|
||||||
tree-kill@^1.2.2:
|
tree-kill@^1.2.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz"
|
||||||
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
||||||
|
|
||||||
ts-jest@^29.0.3:
|
ts-jest@^29.0.3:
|
||||||
|
@ -4128,7 +4235,7 @@ tslib@^1.8.1, tslib@^1.9.3:
|
||||||
|
|
||||||
tslib@^2.1.0:
|
tslib@^2.1.0:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
|
resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz"
|
||||||
integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
|
integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
|
||||||
|
|
||||||
tsutils@^3.21.0:
|
tsutils@^3.21.0:
|
||||||
|
@ -4169,7 +4276,7 @@ type-fest@^0.21.3:
|
||||||
|
|
||||||
typed-array-length@^1.0.4:
|
typed-array-length@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb"
|
resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz"
|
||||||
integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==
|
integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind "^1.0.2"
|
call-bind "^1.0.2"
|
||||||
|
@ -4183,7 +4290,7 @@ typescript@^4.9.4:
|
||||||
|
|
||||||
unbox-primitive@^1.0.2:
|
unbox-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
|
resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz"
|
||||||
integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
|
integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind "^1.0.2"
|
call-bind "^1.0.2"
|
||||||
|
@ -4232,7 +4339,7 @@ v8-to-istanbul@^9.0.1:
|
||||||
|
|
||||||
validate-npm-package-license@^3.0.1:
|
validate-npm-package-license@^3.0.1:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
|
resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz"
|
||||||
integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
|
integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
|
||||||
dependencies:
|
dependencies:
|
||||||
spdx-correct "^3.0.0"
|
spdx-correct "^3.0.0"
|
||||||
|
@ -4254,7 +4361,7 @@ walker@^1.0.8:
|
||||||
|
|
||||||
which-boxed-primitive@^1.0.2:
|
which-boxed-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz"
|
||||||
integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
|
integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
|
||||||
dependencies:
|
dependencies:
|
||||||
is-bigint "^1.0.1"
|
is-bigint "^1.0.1"
|
||||||
|
@ -4265,7 +4372,7 @@ which-boxed-primitive@^1.0.2:
|
||||||
|
|
||||||
which-typed-array@^1.1.9:
|
which-typed-array@^1.1.9:
|
||||||
version "1.1.9"
|
version "1.1.9"
|
||||||
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6"
|
resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz"
|
||||||
integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==
|
integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==
|
||||||
dependencies:
|
dependencies:
|
||||||
available-typed-arrays "^1.0.5"
|
available-typed-arrays "^1.0.5"
|
||||||
|
@ -4277,7 +4384,7 @@ which-typed-array@^1.1.9:
|
||||||
|
|
||||||
which@^1.2.9:
|
which@^1.2.9:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz"
|
||||||
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
|
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
@ -4296,7 +4403,7 @@ word-wrap@^1.2.3:
|
||||||
|
|
||||||
wrangler@2.7.1:
|
wrangler@2.7.1:
|
||||||
version "2.7.1"
|
version "2.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-2.7.1.tgz#adb9d06c0dde3fc434e4a85a286c1da3f485cade"
|
resolved "https://registry.npmjs.org/wrangler/-/wrangler-2.7.1.tgz"
|
||||||
integrity sha512-SKoe+UTOCX0J+RfEDE6MEdnNy1lDSnB1BfpAEblgvDHjmEunPFu0w6GxcyOYAl/fTl3/VjXZO3p+Ybm9zenzWg==
|
integrity sha512-SKoe+UTOCX0J+RfEDE6MEdnNy1lDSnB1BfpAEblgvDHjmEunPFu0w6GxcyOYAl/fTl3/VjXZO3p+Ybm9zenzWg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@cloudflare/kv-asset-handler" "^0.2.0"
|
"@cloudflare/kv-asset-handler" "^0.2.0"
|
||||||
|
@ -4344,6 +4451,11 @@ ws@^8.2.2:
|
||||||
resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz"
|
resolved "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz"
|
||||||
integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
|
integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
|
||||||
|
|
||||||
|
xtend@^4.0.0:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz"
|
||||||
|
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||||
|
|
||||||
xxhash-wasm@^1.0.1:
|
xxhash-wasm@^1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.2.tgz"
|
||||||
|
|
Ładowanie…
Reference in New Issue