Skip to content

Commit

Permalink
fix: deno 2 experimental support
Browse files Browse the repository at this point in the history
  • Loading branch information
fenos committed Oct 16, 2024
1 parent 689d255 commit 0cc7a1c
Show file tree
Hide file tree
Showing 28 changed files with 106 additions and 61 deletions.
13 changes: 13 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"tasks": {
"dev": "deno run --watch main.ts"
},
"imports": {
"@std/assert": "jsr:@std/assert@1",
"@internal/": "./src/internal/",
"@storage/": "./src/storage/",
"postgres-migrations/": "npm:postgres-migrations/",
"postgres-migrations/dist/": "npm:postgres-migrations/dist/",
"ajv": "npm:ajv"
}
}
6 changes: 3 additions & 3 deletions src/http/error-handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FastifyInstance } from 'fastify'
import { FastifyError } from '@fastify/error'
import { DatabaseError } from 'pg'
import pg from 'pg'
import { ErrorCode, isRenderableError } from '@internal/errors'

/**
Expand All @@ -17,15 +17,15 @@ export const setErrorHandler = (app: FastifyInstance) => {

// database error
if (
error instanceof DatabaseError &&
error instanceof pg.DatabaseError &&
[
'Authentication error', // supavisor specific
'Max client connections reached',
'remaining connection slots are reserved for non-replication superuser connections',
'no more connections allowed',
'sorry, too many clients already',
'server login has been failing, try again later',
].some((msg) => (error as DatabaseError).message.includes(msg))
].some((msg) => (error as pg.DatabaseError).message.includes(msg))
) {
return reply.status(429).send({
statusCode: `429`,
Expand Down
3 changes: 1 addition & 2 deletions src/http/plugins/log-request.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import fastifyPlugin from 'fastify-plugin'
import { logSchema, redactQueryParamFromRequest } from '@internal/monitoring'
import { trace } from '@opentelemetry/api'
import { FastifyRequest } from 'fastify/types/request'
import { FastifyReply } from 'fastify/types/reply'
import { FastifyRequest, FastifyReply } from 'fastify'

interface RequestLoggerOptions {
excludeUrls?: string[]
Expand Down
2 changes: 1 addition & 1 deletion src/http/plugins/tracing.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fastifyPlugin from 'fastify-plugin'
import { isIP } from 'net'
import { isIP } from 'node:net'
import { getTenantConfig } from '@internal/database'

import { getConfig } from '../../config'
Expand Down
2 changes: 1 addition & 1 deletion src/http/routes/object/getObject.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
import { FromSchema } from 'json-schema-to-ts'
import { IncomingMessage, Server, ServerResponse } from 'http'
import { IncomingMessage, Server, ServerResponse } from 'node:http'
import { getConfig } from '../../../config'
import { AuthenticatedRangeRequest } from '../../types'
import { ROUTE_OPERATIONS } from '../operations'
Expand Down
2 changes: 1 addition & 1 deletion src/http/routes/object/getObjectInfo.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
import { FromSchema } from 'json-schema-to-ts'
import { IncomingMessage, Server, ServerResponse } from 'http'
import { IncomingMessage, Server, ServerResponse } from 'node:http'
import { getConfig } from '../../../config'
import { AuthenticatedRangeRequest } from '../../types'
import { Obj } from '@storage/schemas'
Expand Down
9 changes: 4 additions & 5 deletions src/http/routes/s3/error-handler.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { FastifyError } from '@fastify/error'
import { FastifyRequest } from 'fastify/types/request'
import { FastifyReply } from 'fastify/types/reply'
import { FastifyReply, FastifyRequest } from 'fastify'
import { S3ServiceException } from '@aws-sdk/client-s3'
import { DatabaseError } from 'pg'
import pg from 'pg'
import { ErrorCode, StorageBackendError } from '@internal/errors'

export const s3ErrorHandler = (
Expand Down Expand Up @@ -41,14 +40,14 @@ export const s3ErrorHandler = (

// database error
if (
error instanceof DatabaseError &&
error instanceof pg.DatabaseError &&
[
'Max client connections reached',
'remaining connection slots are reserved for non-replication superuser connections',
'no more connections allowed',
'sorry, too many clients already',
'server login has been failing, try again later',
].some((msg) => (error as DatabaseError).message.includes(msg))
].some((msg) => (error as pg.DatabaseError).message.includes(msg))
) {
return reply.status(429).send({
Error: {
Expand Down
2 changes: 1 addition & 1 deletion src/http/routes/tus/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FastifyBaseLogger, FastifyInstance } from 'fastify'
import fastifyPlugin from 'fastify-plugin'
import * as http from 'http'
import * as http from 'node:http'
import { ServerOptions, DataStore } from '@tus/server'
import { getFileSizeLimit } from '@storage/limits'
import { Storage } from '@storage/storage'
Expand Down
4 changes: 2 additions & 2 deletions src/http/routes/tus/lifecycle.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import http from 'http'
import http from 'node:http'
import { BaseLogger } from 'pino'
import { Upload } from '@tus/server'
import { randomUUID } from 'crypto'
import { randomUUID } from 'node:crypto'
import { TenantConnection } from '@internal/database'
import { ERRORS, isRenderableError } from '@internal/errors'
import { Storage } from '@storage/storage'
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
import './start/server'
import './start/server.ts'
54 changes: 43 additions & 11 deletions src/internal/auth/crypto.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,53 @@
import AES from 'crypto-js/aes'
import Utf8 from 'crypto-js/enc-utf8'
import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto'
import { getConfig } from '../../config'

const { encryptionKey } = getConfig()

/**
* Decrypts a text with the configured encryption key via ENCRYPTION_KEY env
* @param ciphertext
*/
* Generate CryptoJs.AES key from passphrase
* https://github.com/brix/crypto-js/issues/468
* */
function convertPassphraseToAesKeyBuffer(key: string, salt: Buffer): Buffer {
const password = Buffer.concat([Buffer.from(key, 'binary'), salt])
const hash: Buffer[] = []
let digest = password
for (let i = 0; i < 3; i++) {
hash[i] = createHash('md5').update(digest).digest()
digest = Buffer.concat([hash[i]!, password])
}
return Buffer.concat(hash)
}

/**
* Replicate CryptoJs.AES.decrypt method
* */
export function decrypt(ciphertext: string): string {
return AES.decrypt(ciphertext, encryptionKey).toString(Utf8)
try {
const cipherBuffer = Buffer.from(ciphertext, 'base64')
const salt = cipherBuffer.subarray(8, 16)
const keyDerivation = convertPassphraseToAesKeyBuffer(encryptionKey, salt)
const [key, iv] = [keyDerivation.subarray(0, 32), keyDerivation.subarray(32)]
const contents = cipherBuffer.subarray(16)
const decipher = createDecipheriv('aes-256-cbc', key, iv)
const decrypted = Buffer.concat([decipher.update(contents), decipher.final()])
return decrypted.toString('utf8')
} catch (e) {
throw e
}
}

/**
* Encrypts a text with the configured encryption key via ENCRYPTION_KEY env
* @param plaintext
*/
* Replicate CryptoJs.AES.encrypt method
* */
export function encrypt(plaintext: string): string {
return AES.encrypt(plaintext, encryptionKey).toString()
try {
const salt = randomBytes(8)
const keyDerivation = convertPassphraseToAesKeyBuffer(encryptionKey, salt)
const [key, iv] = [keyDerivation.subarray(0, 32), keyDerivation.subarray(32)]
const cipher = createCipheriv('aes-256-cbc', key, iv)
const contents = Buffer.concat([cipher.update(plaintext), cipher.final()])
const encrypted = Buffer.concat([Buffer.from('Salted__', 'utf8'), salt, contents])
return encrypted.toString('base64')
} catch (e) {
throw e
}
}
2 changes: 1 addition & 1 deletion src/internal/concurrency/stream.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Transform, TransformCallback } from 'stream'
import { Transform, TransformCallback } from 'node:stream'

export const createByteCounterStream = () => {
let bytes = 0
Expand Down
7 changes: 4 additions & 3 deletions src/internal/database/connection.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pg, { DatabaseError } from 'pg'
import { Knex, knex } from 'knex'
import pg from 'pg'
import { Knex } from 'knex'
import knex from 'knex'
import { JwtPayload } from 'jsonwebtoken'
import retry from 'async-retry'
import TTLCache from '@isaacs/ttlcache'
Expand Down Expand Up @@ -163,7 +164,7 @@ export class TenantConnection {
return await pool.transaction()
} catch (e) {
if (
e instanceof DatabaseError &&
e instanceof pg.DatabaseError &&
e.code === '08P01' &&
e.message.includes('no more connections allowed')
) {
Expand Down
16 changes: 8 additions & 8 deletions src/internal/database/migrations/migrate.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Client, ClientConfig } from 'pg'
import pg from 'pg'
import SQL from 'sql-template-strings'
import { loadMigrationFiles, MigrationError } from 'postgres-migrations'
import { getConfig, MultitenantMigrationStrategy } from '../../../config'
import { logger, logSchema } from '../../monitoring'
import { BasicPgClient, Migration } from 'postgres-migrations/dist/types'
import { validateMigrationHashes } from 'postgres-migrations/dist/validation'
import { runMigration } from 'postgres-migrations/dist/run-migration'
import type { BasicPgClient, Migration } from 'postgres-migrations/dist/types'
import { validateMigrationHashes } from 'postgres-migrations/dist/validation.js'
import { runMigration } from 'postgres-migrations/dist/run-migration.js'
import { searchPath } from '../connection'
import { getTenantConfig, listTenantsToMigrate } from '../tenant'
import { multitenantKnex } from '../multitenant-db'
Expand Down Expand Up @@ -179,7 +179,7 @@ export async function runMigrationsOnTenant(
tenantId?: string,
waitForLock = true
): Promise<void> {
let ssl: ClientConfig['ssl'] | undefined = undefined
let ssl: pg.ClientConfig['ssl'] | undefined = undefined

if (databaseSSLRootCert) {
ssl = { ca: databaseSSLRootCert }
Expand All @@ -202,7 +202,7 @@ export async function runMigrationsOnTenant(
async function connectAndMigrate(options: {
databaseUrl: string | undefined
migrationsDirectory: string
ssl?: ClientConfig['ssl']
ssl?: pg.ClientConfig['ssl']
shouldCreateStorageSchema?: boolean
tenantId?: string
waitForLock?: boolean
Expand All @@ -216,14 +216,14 @@ async function connectAndMigrate(options: {
waitForLock,
} = options

const dbConfig: ClientConfig = {
const dbConfig: pg.ClientConfig = {
connectionString: databaseUrl,
connectionTimeoutMillis: 60_000,
options: `-c search_path=${searchPath}`,
ssl,
}

const client = new Client(dbConfig)
const client = new pg.Client(dbConfig)
client.on('error', (err) => {
logSchema.error(logger, 'Error on database connection', {
type: 'error',
Expand Down
2 changes: 1 addition & 1 deletion src/internal/queue/database.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Db } from 'pg-boss'
import EventEmitter from 'events'
import EventEmitter from 'node:events'
import pg from 'pg'
import { ERRORS } from '@internal/errors'

Expand Down
2 changes: 1 addition & 1 deletion src/start/shutdown.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { logger, logSchema } from '@internal/monitoring'
import { AsyncAbortController } from '@internal/concurrency'
import { multitenantKnex, TenantConnection } from '@internal/database'
import http from 'http'
import http from 'node:http'

/**
* Binds shutdown handlers to the process
Expand Down
2 changes: 1 addition & 1 deletion src/storage/backend/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Readable } from 'stream'
import { Readable } from 'node:stream'
import { getConfig } from '../../config'

/**
Expand Down
8 changes: 4 additions & 4 deletions src/storage/backend/file.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as xattr from 'fs-xattr'
import fs from 'fs-extra'
import path from 'path'
import path from 'node:path'
import fileChecksum from 'md5-file'
import { promisify } from 'util'
import stream from 'stream'
import { promisify } from 'node:util'
import stream from 'node:stream'
import MultiStream from 'multistream'
import { getConfig } from '../../config'
import {
Expand All @@ -15,7 +15,7 @@ import {
UploadPart,
} from './adapter'
import { ERRORS, StorageBackendError } from '@internal/errors'
import { randomUUID } from 'crypto'
import { randomUUID } from 'node:crypto'
import fsExtra from 'fs-extra'
const pipeline = promisify(stream.pipeline)

Expand Down
1 change: 1 addition & 0 deletions src/storage/backend/s3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ export class S3Backend implements StorageBackendAdapter {
const params: S3ClientConfig = {
region: options.region,
runtime: 'node',
cacheMiddleware: true,
requestHandler: new NodeHttpHandler({
httpAgent: options.httpAgent?.httpAgent,
httpsAgent: options.httpAgent?.httpsAgent,
Expand Down
2 changes: 1 addition & 1 deletion src/storage/protocols/s3/byte-limit-stream.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Transform, TransformCallback } from 'stream'
import { Transform, TransformCallback } from 'node:stream'
import { ERRORS } from '@internal/errors'

export class ByteLimitTransformStream extends Transform {
Expand Down
4 changes: 2 additions & 2 deletions src/storage/protocols/s3/s3-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import {
UploadPartCommandInput,
UploadPartCopyCommandInput,
} from '@aws-sdk/client-s3'
import { PassThrough, Readable } from 'stream'
import stream from 'stream/promises'
import { PassThrough, Readable } from 'node:stream'
import stream from 'node:stream/promises'
import { getFileSizeLimit, mustBeValidBucketName, mustBeValidKey } from '../../limits'
import { ERRORS } from '@internal/errors'
import { S3MultipartUpload, Obj } from '../../schemas'
Expand Down
2 changes: 1 addition & 1 deletion src/storage/protocols/s3/signature-v4.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import crypto from 'crypto'
import crypto from 'node:crypto'
import { ERRORS } from '@internal/errors'

interface SignatureV4Options {
Expand Down
2 changes: 1 addition & 1 deletion src/storage/protocols/tus/als-memory-kv.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncLocalStorage } from 'async_hooks'
import { AsyncLocalStorage } from 'node:async_hooks'
import { KvStore } from '@tus/server'
import { MetadataValue } from '@tus/s3-store'

Expand Down
2 changes: 1 addition & 1 deletion src/storage/protocols/tus/file-store.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FileStore as TusFileStore } from '@tus/file-store'
import { Upload } from '@tus/server'
import fsExtra from 'fs-extra'
import path from 'path'
import path from 'node:path'
import { Configstore } from '@tus/file-store'
import { FileBackend } from '../../backend'

Expand Down
10 changes: 5 additions & 5 deletions src/storage/protocols/tus/postgres-locker.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Lock, Locker, RequestRelease } from '@tus/server'
import { clearTimeout } from 'timers'
import EventEmitter from 'events'
import { Database, DBError } from '../../database'
import { clearTimeout } from 'node:timers'
import EventEmitter from 'node:events'
import { Database } from '../../database'
import { PubSubAdapter } from '@internal/pubsub'
import { UploadId } from './upload-id'
import { ERRORS } from '@internal/errors'
import { ErrorCode, ERRORS, StorageBackendError } from '@internal/errors'

const REQUEST_LOCK_RELEASE_MESSAGE = 'REQUEST_LOCK_RELEASE'

Expand Down Expand Up @@ -94,7 +94,7 @@ export class PgLock implements Lock {
await db.mustLockObject(uploadId.bucket, uploadId.objectName, uploadId.version)
return true
} catch (e) {
if (e instanceof DBError && e.message === 'resource_locked') {
if (e instanceof StorageBackendError && e.code === ErrorCode.ResourceLocked) {
await this.notifier.release(id)
await new Promise((resolve) => {
setTimeout(resolve, 500)
Expand Down
2 changes: 1 addition & 1 deletion src/storage/renderer/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { FastifyRequest } from 'fastify'
import { Renderer, RenderOptions } from './renderer'
import axiosRetry from 'axios-retry'
import { ERRORS } from '@internal/errors'
import { Stream } from 'stream'
import { Stream } from 'node:stream'
import Agent from 'agentkeepalive'

/**
Expand Down
2 changes: 1 addition & 1 deletion src/storage/renderer/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FastifyReply, FastifyRequest } from 'fastify'
import { ObjectMetadata } from '../backend'
import { Readable } from 'stream'
import { Readable } from 'node:stream'
import { getConfig } from '../../config'
import { Obj } from '../schemas'

Expand Down
2 changes: 1 addition & 1 deletion src/storage/uploader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { randomUUID } from 'crypto'
import { randomUUID } from 'node:crypto'
import { FastifyRequest } from 'fastify'

import { ERRORS } from '@internal/errors'
Expand Down

0 comments on commit 0cc7a1c

Please sign in to comment.