Files
zpan/server/platform/node.ts
T
saltboandClaude Opus 4.7 bcb0b67872 feat(platform): add getBinding() for platform-native resources
Platform-native bindings (Cloudflare R2/D1/KV, Azure Storage contexts,
etc.) are not representable as strings, so getEnv() can't carry them.
Add a typed getBinding<T>() accessor: returns the binding on platforms
that support it, undefined on others.

Callers branch on the return — e.g. \`getBinding<R2Bucket>('PUBLIC_IMAGES')\`
will be defined on CF and undefined on Node/Docker, letting the same
code pick a runtime-appropriate path without platform-specific imports.

Used in the next commit to switch the public image upload flow to R2
binding on CF (zero-auth, zero-egress) while keeping the S3 fallback
for every other platform.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 22:56:35 -04:00

30 lines
977 B
TypeScript

import Database from 'better-sqlite3'
import { drizzle } from 'drizzle-orm/better-sqlite3'
import { migrate } from 'drizzle-orm/better-sqlite3/migrator'
import * as authSchema from '../db/auth-schema'
import * as schema from '../db/schema'
import type { Platform } from './interface'
export function createNodePlatform(): Platform {
const dbPath = process.env.DATABASE_URL || './zpan.db'
const migrationsFolder = process.env.MIGRATIONS_DIR || './migrations'
const sqlite = new Database(dbPath)
sqlite.pragma('journal_mode = WAL')
const db = drizzle(sqlite, { schema: { ...schema, ...authSchema } })
migrate(db, { migrationsFolder })
return {
db,
getEnv(key: string) {
return process.env[key]
},
// Node has no platform-native bindings — callers always fall back to
// whatever the non-binding path does (e.g. DB-configured S3 storage).
getBinding<T = unknown>(_key: string): T | undefined {
return undefined
},
}
}