@better-media/framework 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +49 -0
- package/bin/media.mjs +3 -0
- package/dist/index.d.mts +225 -0
- package/dist/index.d.ts +225 -0
- package/dist/index.js +1118 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1044 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/lifecycle-engine.ts","../src/plugins/plugin-registry.ts","../src/index.ts","../src/core/file-loader.ts","../src/core/pipeline-executor.ts","../src/jobs/job-runner.ts","../src/db/postgres.ts"],"names":["TrustedMetadataSchema","HOOK_NAMES","resolveHookMode","stream","path","os","randomUUID","Readable","createWriteStream","markFileContentVerified","fs","syncTrustedToFile","createSecureContext","toCamelCase","toDbFieldName","schema","serializeData","deserializeData","getColumnType","isPgPoolLike","memoryJobAdapter"],"mappings":"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","file":"index.js","sourcesContent":["import {\n type PipelineContext,\n type PipelineContextWithVerified,\n type HookName,\n type ValidationResult,\n type JobAdapter,\n type PluginApi,\n type TrustedMetadata,\n type PluginManifest,\n TrustedMetadataSchema,\n} from \"@better-media/core\";\nimport type { HookRegistry } from \"../plugins/plugin.interface\";\n\nconst JOB_QUEUE_NAME = \"better-media:background\";\n\n/** Background job payload (serializable) */\nexport interface BackgroundJobPayload {\n recordId: string;\n metadata: Record<string, unknown>;\n file: PipelineContext[\"file\"];\n storageLocation: PipelineContext[\"storageLocation\"];\n processing: PipelineContext[\"processing\"];\n hookName: HookName;\n pluginName: string;\n manifest: PluginManifest;\n}\n\n/** Internal context with audit log (provenance uses PipelineContextWithVerified) */\ntype SecureAuditContext = PipelineContextWithVerified & {\n _auditLog?: Array<{\n timestamp: string;\n plugin: string;\n action: string;\n patch: TrustedMetadata;\n }>;\n};\n\n/**\n * Creates a Secure Context Proxy and Plugin API for a specific plugin.\n */\nexport function createSecureContext(\n context: PipelineContext,\n pluginName: string,\n namespace: string,\n trustLevel: string,\n capabilities: string[]\n): { proxy: PipelineContext; api: PluginApi } {\n // 1. Create the API implementation\n const api: PluginApi = {\n emitMetadata(patch: Record<string, unknown>) {\n if (!capabilities.includes(\"metadata.write.own\")) {\n console.warn(`[AUDIT] Denied metadata.write.own for plugin \"${pluginName}\"`);\n throw new Error(`Plugin \"${pluginName}\" lacks \"metadata.write.own\" capability`);\n }\n context.metadata[namespace] = {\n ...((context.metadata[namespace] as Record<string, unknown>) ?? {}),\n ...patch,\n };\n },\n emitProcessing(patch: Record<string, unknown>) {\n if (!capabilities.includes(\"processing.write.own\")) {\n console.warn(`[AUDIT] Denied processing.write.own for plugin \"${pluginName}\"`);\n throw new Error(`Plugin \"${pluginName}\" lacks \"processing.write.own\" capability`);\n }\n context.processing[namespace] = {\n ...((context.processing[namespace] as Record<string, unknown>) ?? {}),\n ...patch,\n };\n },\n proposeTrusted(patch: TrustedMetadata) {\n if (trustLevel !== \"trusted\" || !capabilities.includes(\"trusted.propose\")) {\n console.warn(\n `[AUDIT] Security Violation: Unauthorized trusted.propose from plugin \"${pluginName}\"`\n );\n throw new Error(`Plugin \"${pluginName}\" is not authorized to propose trusted metadata`);\n }\n\n // 1. Semantic Provenance Guard: Ensure plugin has verified data before proposing\n const secureContext = context as SecureAuditContext;\n const verified = secureContext._verifiedSources ?? new Set();\n if (!verified.has(\"file:content\") && (patch.file || patch.checksums || patch.media)) {\n console.warn(\n `[AUDIT] Provenance Failure: Plugin \"${pluginName}\" attempted to propose trusted metadata without independent verification (no file content read).`\n );\n throw new Error(\n `Plugin \"${pluginName}\" must verify file content before proposing trusted metadata`\n );\n }\n\n // 2. Strict Schema Validation\n TrustedMetadataSchema.parse(patch);\n\n // 2. Provenance Tracking (Internal audit log)\n const auditLog = (secureContext._auditLog ??= []);\n auditLog.push({\n timestamp: new Date().toISOString(),\n plugin: pluginName,\n action: \"proposeTrusted\",\n patch: JSON.parse(JSON.stringify(patch)), // Snapshot the patch\n });\n\n console.info(\n `[AUDIT] Accepted trusted proposal from plugin \"${pluginName}\" for file \"${context.file.key}\"`\n );\n\n // 2. Controlled Merge (Provenance-aware)\n context.trusted = {\n ...context.trusted,\n ...patch,\n file: { ...context.trusted.file, ...patch.file },\n checksums: { ...context.trusted.checksums, ...patch.checksums },\n media: { ...context.trusted.media, ...patch.media },\n };\n\n // 3. Authority Sync: Authoritative metadata is mirrored to context.file\n if (patch.file) {\n if (patch.file.mimeType != null) context.file.mimeType = patch.file.mimeType;\n if (patch.file.size != null) context.file.size = patch.file.size;\n if (patch.file.originalName != null) context.file.originalName = patch.file.originalName;\n if (patch.file.extension != null) context.file.extension = patch.file.extension;\n }\n if (patch.checksums) {\n context.file.checksums = { ...context.file.checksums, ...patch.checksums };\n }\n },\n };\n\n // 2. Create the Proxy to block direct mutation\n const proxy = new Proxy(context, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n\n // Wrap metadata, processing, and trusted in read-only proxies\n if (prop === \"metadata\" || prop === \"processing\" || prop === \"trusted\" || prop === \"file\") {\n return new Proxy(value as object, {\n set() {\n throw new Error(\n `Direct mutation of \"context.${String(prop)}\" is blocked. Use PluginApi instead. (Plugin: ${pluginName})`\n );\n },\n deleteProperty() {\n throw new Error(\n `Direct deletion of \"context.${String(prop)}\" properties is blocked. (Plugin: ${pluginName})`\n );\n },\n });\n }\n\n return value;\n },\n set(target, prop) {\n throw new Error(\n `Direct mutation of \"context.${String(prop)}\" is blocked. (Plugin: ${pluginName})`\n );\n },\n });\n\n return { proxy, api };\n}\n\n/**\n * Lifecycle engine: triggers hooks, runs sync handlers in series,\n * enqueues background handlers via JobAdapter.\n */\nexport class LifecycleEngine {\n constructor(\n private readonly registry: HookRegistry,\n private readonly jobAdapter: JobAdapter\n ) {}\n\n async trigger(hookName: HookName, context: PipelineContext): Promise<void | ValidationResult> {\n const handlers = this.registry.get(hookName) ?? [];\n const syncHandlers = handlers.filter((h) => h.mode === \"sync\");\n const backgroundHandlers = handlers.filter((h) => h.mode === \"background\");\n\n for (const { name, fn, manifest } of syncHandlers) {\n const { proxy, api } = createSecureContext(\n context,\n name,\n manifest.namespace,\n manifest.trustLevel,\n manifest.capabilities\n );\n\n const result = await fn(proxy, api);\n if (result !== undefined && typeof result === \"object\" && \"valid\" in result) {\n if (result.valid === false) return result;\n }\n }\n\n for (const { name, manifest } of backgroundHandlers) {\n // Deep clone to prevent shared references in memory-based adapters\n const payload: BackgroundJobPayload = {\n recordId: context.recordId,\n metadata: JSON.parse(JSON.stringify(context.metadata)),\n file: JSON.parse(JSON.stringify(context.file)),\n storageLocation: JSON.parse(JSON.stringify(context.storageLocation)),\n processing: JSON.parse(JSON.stringify(context.processing)),\n hookName,\n pluginName: name,\n manifest: JSON.parse(JSON.stringify(manifest)),\n };\n await this.jobAdapter.enqueue(JOB_QUEUE_NAME, payload as unknown as Record<string, unknown>);\n }\n }\n}\n","import {\n HOOK_NAMES,\n resolveHookMode,\n type MediaPlugin,\n type PipelinePlugin,\n type PipelineContext,\n type HookName,\n type HookContext,\n type MediaRuntime,\n type MediaRuntimeHook,\n type ValidationResult,\n type JobAdapter,\n type PluginManifest,\n type PluginApi,\n} from \"@better-media/core\";\nimport { LifecycleEngine } from \"../core/lifecycle-engine\";\nimport type { HookRegistry, TapInfo } from \"./plugin.interface\";\n\nfunction createEmptyRegistry(): HookRegistry {\n const reg = new Map<HookName, TapInfo[]>();\n for (const name of HOOK_NAMES) {\n reg.set(name, []);\n }\n return reg;\n}\n\nfunction clearRegistry(registry: HookRegistry): void {\n for (const [, list] of registry) {\n list.length = 0;\n }\n}\n\nfunction createHook(\n registry: HookRegistry,\n hookName: HookName,\n manifest: PluginManifest\n): MediaRuntimeHook {\n return {\n tap(\n name: string,\n fn: (ctx: PipelineContext, api: PluginApi) => Promise<void | ValidationResult>,\n options?: { mode?: \"sync\" | \"background\" }\n ) {\n const requested = options?.mode ?? \"sync\";\n const { effective, overridden } = resolveHookMode(hookName, requested);\n if (overridden) {\n console.warn(\n `[better-media] Hook '${hookName}' does not support mode '${requested}'. Overriding to '${effective}'. Plugin: ${name}`\n );\n }\n const list = registry.get(hookName)!;\n list.push({ name, fn, mode: effective, manifest });\n },\n };\n}\n\n/** Runtime with hooks that use plugin's intensive flag for default mode */\nfunction createPluginRuntime(registry: HookRegistry, plugin: PipelinePlugin): MediaRuntime {\n const hooks = {} as MediaRuntime[\"hooks\"];\n for (const name of HOOK_NAMES) {\n const baseTap = createHook(registry, name, plugin.runtimeManifest).tap;\n hooks[name] = {\n tap(\n handlerName: string,\n fn: (ctx: PipelineContext, api: PluginApi) => Promise<void | ValidationResult>,\n options?: { mode?: \"sync\" | \"background\" }\n ) {\n const mode = options?.mode ?? (plugin.intensive ? \"background\" : \"sync\");\n baseTap(handlerName, fn, { ...options, mode });\n },\n };\n }\n return { hooks };\n}\n\n/** Manifest for the global framework-level runtime */\nconst SYSTEM_MANIFEST: PluginManifest = {\n id: \"better-media-system\",\n version: \"1.0.0\",\n trustLevel: \"trusted\",\n capabilities: [\"file.read\", \"metadata.write.own\", \"processing.write.own\", \"trusted.propose\"],\n namespace: \"system\",\n};\n\n/**\n * Build MediaRuntime with hooks that plugins tap into.\n * Legacy plugins with only execute() are auto-tapped to process:run.\n */\nexport function createMediaRuntime(\n plugins: PipelinePlugin[],\n registry: HookRegistry\n): MediaRuntime {\n // Use a system manifest to initialize the global runtime, ensuring it's not \"empty\"\n const runtime = createPluginRuntime(registry, {\n name: \"system\",\n runtimeManifest: SYSTEM_MANIFEST,\n } as PipelinePlugin);\n\n for (const plugin of plugins) {\n // Every plugin (apply or execute) gets a dedicated runtime bound to its manifest\n const pluginRuntime = createPluginRuntime(registry, plugin);\n\n if (plugin.apply) {\n plugin.apply(pluginRuntime);\n } else if (plugin.execute) {\n const mode = plugin.executionMode ?? (plugin.intensive ? \"background\" : \"sync\");\n const wrappedExecute = (ctx: PipelineContext, _api: PluginApi) => plugin.execute!(ctx);\n\n pluginRuntime.hooks[\"process:run\"].tap(plugin.name, wrappedExecute, { mode });\n }\n }\n\n return runtime;\n}\n\n/**\n * Policy gate for explicitly authorizing trusted plugins.\n * Prevents unauthorized plugins from claiming \"trusted\" status.\n */\nexport interface TrustedPluginPolicy {\n isAuthorized(pluginId: string, namespace: string): boolean;\n}\n\n/** Default policy: allows only a hardcoded list of internal plugins to be trusted */\nconst DEFAULT_TRUSTED_POLICY: TrustedPluginPolicy = {\n isAuthorized(id) {\n // In a real app, this might check against a signed allowlist or config\n const allowed = [\"better-media-validation\"];\n return allowed.includes(id);\n },\n};\n\n/**\n * Build hook registry from plugins via apply pattern.\n */\nexport function buildPluginRegistry(\n plugins: PipelinePlugin[],\n policy: TrustedPluginPolicy = DEFAULT_TRUSTED_POLICY\n): {\n registry: HookRegistry;\n runtime: MediaRuntime;\n} {\n // 1. Validate all plugins first\n const seenIds = new Set<string>();\n const seenNamespaces = new Set<string>();\n\n for (const plugin of plugins) {\n validatePlugin(plugin);\n\n const { id, namespace, trustLevel } = plugin.runtimeManifest;\n\n // Policy Gate: Block unauthorized trusted plugins\n if (trustLevel === \"trusted\" && !policy.isAuthorized(id, namespace)) {\n throw new Error(\n `Security Violation: Plugin \"${plugin.name}\" (${id}) is not authorized for \"trusted\" status.`\n );\n }\n\n if (seenIds.has(id)) {\n throw new Error(`Duplicate plugin ID detected: ${id} (Plugin: ${plugin.name})`);\n }\n if (seenNamespaces.has(namespace)) {\n throw new Error(`Duplicate namespace detected: ${namespace} (Plugin: ${plugin.name})`);\n }\n seenIds.add(id);\n seenNamespaces.add(namespace);\n }\n\n const registry = createEmptyRegistry();\n const runtime = createMediaRuntime(plugins, registry);\n return { registry, runtime };\n}\n\nexport { HOOK_NAMES };\n\n/**\n * Validates that a plugin has required fields (name, apply or execute)\n * and a valid runtimeManifest.\n * @throws Error if plugin is invalid\n */\nexport function validatePlugin(plugin: PipelinePlugin): void {\n if (!plugin.name || typeof plugin.name !== \"string\") {\n throw new Error(\"Plugin must have a non-empty string name\");\n }\n if (!plugin.apply && !plugin.execute) {\n throw new Error(`Plugin \"${plugin.name}\" must define apply() or execute()`);\n }\n\n if (!plugin.runtimeManifest) {\n throw new Error(\n `Plugin \"${plugin.name}\" is missing runtimeManifest. V1 Secure Model requires manifests.`\n );\n }\n\n const { id, version, trustLevel, capabilities, namespace } = plugin.runtimeManifest;\n\n if (!id || !version || !namespace) {\n throw new Error(\n `Plugin \"${plugin.name}\" manifest is missing required fields (id, version, namespace)`\n );\n }\n\n if (![\"untrusted\", \"trusted\"].includes(trustLevel)) {\n throw new Error(`Plugin \"${plugin.name}\" has invalid trustLevel: ${trustLevel}`);\n }\n\n if (!Array.isArray(capabilities)) {\n throw new Error(`Plugin \"${plugin.name}\" capabilities must be an array`);\n }\n\n // Hard rule: untrusted plugins cannot have trusted.propose capability\n if (trustLevel === \"untrusted\" && capabilities.includes(\"trusted.propose\")) {\n throw new Error(\n `Untrusted plugin \"${plugin.name}\" cannot request \"trusted.propose\" capability`\n );\n }\n}\n\n/**\n * PluginRegistry: register plugins, maintain hook maps, execute hooks.\n * Allows dynamic registration and type-safe hook execution.\n *\n * @example\n * ```ts\n * const registry = new PluginRegistry(jobAdapter);\n * registry.register(validationPlugin());\n * registry.register(thumbnailPlugin({ mode: \"background\" }));\n *\n * await registry.executeHook(\"validation:run\", context);\n * ```\n */\nexport class PluginRegistry {\n private readonly plugins: MediaPlugin[] = [];\n private readonly registry: HookRegistry = createEmptyRegistry();\n private readonly engine: LifecycleEngine;\n\n constructor(jobAdapter: JobAdapter, initialPlugins: MediaPlugin[] = []) {\n this.engine = new LifecycleEngine(this.registry, jobAdapter);\n for (const plugin of initialPlugins) {\n this.register(plugin);\n }\n }\n\n /** Register a plugin and rebuild the hook map */\n register(plugin: MediaPlugin): void {\n validatePlugin(plugin);\n this.plugins.push(plugin);\n clearRegistry(this.registry);\n createMediaRuntime(this.plugins, this.registry);\n }\n\n /** Get all registered plugins (shallow copy) */\n getPlugins(): MediaPlugin[] {\n return [...this.plugins];\n }\n\n /**\n * Execute all handlers for a hook. Runs sync handlers in series.\n * Enqueues background handlers via JobAdapter.\n * @returns ValidationResult if validation phase aborts (valid: false)\n */\n async executeHook(hookName: HookName, context: HookContext): Promise<void | ValidationResult> {\n return this.engine.trigger(hookName, context);\n }\n\n /** Access the internal hook registry (for framework wiring) */\n getRegistry(): HookRegistry {\n return this.registry;\n }\n}\n\n/** Check if any handler in the registry is background mode */\nexport function hasBackgroundHandlers(registry: HookRegistry): boolean {\n for (const handlers of registry.values()) {\n if (handlers.some((h) => h.mode === \"background\")) return true;\n }\n return false;\n}\n","import fs from \"node:fs/promises\";\nimport { randomUUID } from \"node:crypto\";\nimport type { Readable } from \"node:stream\";\nimport type { JobAdapter } from \"@better-media/core\";\nimport { memoryJobAdapter } from \"@better-media/adapter-jobs\";\nimport type { BetterMediaConfig } from \"./config/config.interface\";\nimport type {\n BetterMediaRuntime,\n IngestInput,\n MediaMetadata,\n MediaResult,\n} from \"./runtime/runtime.interface\";\nimport { buildPluginRegistry, hasBackgroundHandlers } from \"./plugins/plugin-registry\";\nimport { LifecycleEngine } from \"./core/lifecycle-engine\";\nimport { PipelineExecutor } from \"./core/pipeline-executor\";\nimport { runBackgroundJob } from \"./jobs/job-runner\";\nimport type { BackgroundJobPayload } from \"./core/lifecycle-engine\";\nimport type { FileHandlingConfig } from \"./core/file-loader\";\nimport { toDatabaseAdapter } from \"./db/postgres\";\nimport type { PresignedUploadOptions } from \"@better-media/core\";\n\nfunction createNoopJobAdapter(): JobAdapter {\n return {\n async enqueue(_name: string, _payload: Record<string, unknown>) {\n // No-op when no job adapter configured\n },\n };\n}\n\ntype NormalizedFile = {\n /** File bytes ready for storage.put — always a Buffer. */\n data: Buffer;\n metadata: MediaMetadata;\n /** True when path-based ingest should unlink the source (default deleteAfterUpload). */\n shouldDeleteSource: boolean;\n sourcePath?: string;\n};\n\nasync function normalizeInput(\n input: IngestInput,\n fileHandling: FileHandlingConfig\n): Promise<NormalizedFile> {\n const { file, metadata = {}, deleteAfterUpload = true } = input;\n const maxBufferBytes = fileHandling.maxBufferBytes;\n let data: Buffer;\n let shouldDeleteSource = false;\n let sourcePath: string | undefined;\n\n if (\"buffer\" in file && file.buffer) {\n data = file.buffer;\n } else if (\"path\" in file && file.path) {\n if (maxBufferBytes != null) {\n const stat = await fs.stat(file.path);\n if (stat.size > maxBufferBytes) {\n throw new Error(\n `File at \"${file.path}\" is ${stat.size} bytes, which exceeds the configured ` +\n `maxBufferBytes limit of ${maxBufferBytes}. Use a storage adapter that supports ` +\n `streaming uploads, or increase maxBufferBytes.`\n );\n }\n }\n data = await fs.readFile(file.path);\n if (deleteAfterUpload) {\n shouldDeleteSource = true;\n sourcePath = file.path;\n }\n } else if (\"stream\" in file && file.stream) {\n const chunks: Buffer[] = [];\n let totalBytes = 0;\n for await (const chunk of file.stream) {\n const buf = Buffer.from(chunk);\n totalBytes += buf.length;\n if (maxBufferBytes != null && totalBytes > maxBufferBytes) {\n throw new Error(\n `Stream exceeded the configured maxBufferBytes limit of ${maxBufferBytes}. ` +\n `Use a storage adapter that supports streaming uploads, or increase maxBufferBytes.`\n );\n }\n chunks.push(buf);\n }\n data = Buffer.concat(chunks);\n } else if (\"url\" in file && file.url) {\n if (file.mode === \"reference\") {\n throw new Error(\"URL reference mode is not fully implemented yet.\");\n }\n const response = await fetch(file.url);\n if (!response.ok) throw new Error(`Failed to fetch URL: ${response.statusText}`);\n data = Buffer.from(await response.arrayBuffer());\n } else {\n throw new Error(\"Invalid MediaFileInput. Must provide buffer, stream, path, or url.\");\n }\n\n return { data, metadata, shouldDeleteSource, sourcePath };\n}\n\n/**\n * Create and initialize the Better Media runtime.\n *\n * @example\n * ```ts\n * const media = createBetterMedia({\n * storage: new S3StorageAdapter({\n * bucket: \"my-bucket\",\n * region: \"us-east-1\",\n * accessKeyId: \"...\",\n * secretAccessKey: \"...\"\n * }),\n * database: postgresAdapter(...),\n * jobs: redisJobAdapter(),\n * plugins: [\n * validationPlugin(),\n * virusScanPlugin(),\n * thumbnailPlugin({ mode: \"background\" }),\n * videoProcessingPlugin({ mode: \"background\" })\n * ]\n * });\n *\n * const result = await media.upload.ingest({\n * file: { buffer },\n * metadata: { filename: \"photo.jpg\", mimeType: \"image/jpeg\" },\n * });\n * ```\n */\nexport function createBetterMedia(config: BetterMediaConfig): BetterMediaRuntime {\n const { storage, plugins, trustedPolicy } = config;\n const database = toDatabaseAdapter(config.database);\n const { registry } = buildPluginRegistry(plugins, trustedPolicy);\n\n const fileHandling = config.fileHandling ?? {};\n const jobAdapter =\n config.jobs ??\n (hasBackgroundHandlers(registry)\n ? (() => {\n const adapter = memoryJobAdapter({\n processor: (p) =>\n runBackgroundJob(\n p as unknown as BackgroundJobPayload,\n registry,\n storage,\n database,\n adapter,\n fileHandling\n ),\n });\n return adapter;\n })()\n : createNoopJobAdapter());\n const engine = new LifecycleEngine(registry, jobAdapter);\n const executor = new PipelineExecutor(engine, storage, database, jobAdapter, fileHandling);\n\n const runPipeline = (\n recordId: string,\n fileKey: string,\n metadata: Record<string, unknown> = {},\n context: Record<string, unknown> = {}\n ) => executor.run(recordId, fileKey, metadata, context);\n\n return {\n upload: {\n async ingest(input: IngestInput): Promise<MediaResult> {\n const normalized = await normalizeInput(input, fileHandling);\n const recordId = randomUUID();\n const finalKey = input.key ?? normalized.metadata.filename ?? recordId;\n\n try {\n await storage.put(finalKey, normalized.data);\n // Pass metadata and context separately to the executor to persist once at the end\n await runPipeline(\n recordId,\n finalKey,\n normalized.metadata,\n (normalized.metadata.context as Record<string, unknown>) ?? {}\n );\n\n return {\n id: recordId,\n key: finalKey,\n status: \"processed\",\n metadata: normalized.metadata,\n };\n } finally {\n if (normalized.shouldDeleteSource && normalized.sourcePath) {\n await fs\n .unlink(normalized.sourcePath)\n .catch((err) => console.warn(\"Cleanup failed:\", err));\n }\n }\n },\n fromBuffer(buffer: Buffer, input?: Omit<IngestInput, \"file\">) {\n return this.ingest({ file: { buffer }, ...input });\n },\n fromStream(stream: Readable, input?: Omit<IngestInput, \"file\">) {\n return this.ingest({ file: { stream }, ...input });\n },\n fromPath(path: string, input?: Omit<IngestInput, \"file\">) {\n return this.ingest({ file: { path }, ...input });\n },\n fromUrl(url: string, input?: Omit<IngestInput, \"file\"> & { mode?: \"import\" | \"reference\" }) {\n return this.ingest({ file: { url, mode: input?.mode ?? \"import\" }, ...input });\n },\n async requestPresignedUpload(key: string, options: PresignedUploadOptions) {\n const fn = storage.createPresignedUpload;\n if (typeof fn !== \"function\") {\n throw new Error(\n \"Presigned upload not supported by this storage adapter. Use an S3/GCS adapter.\"\n );\n }\n return fn.call(storage, key, options);\n },\n async complete(key: string, metadata: MediaMetadata = {}) {\n const existing = await database.findOne({\n model: \"media\",\n where: [{ field: \"storageKey\", value: key }],\n });\n const recordId = (existing?.id as string) ?? randomUUID();\n\n await runPipeline(\n recordId,\n key,\n metadata,\n (metadata.context as Record<string, unknown>) ?? {}\n );\n return {\n id: recordId,\n key,\n status: \"processed\",\n metadata,\n };\n },\n },\n files: {\n get(id: string) {\n return database.findOne({ model: \"media\", where: [{ field: \"id\", value: id }] });\n },\n async delete(id: string) {\n const record = await this.get(id);\n const storageKey = (record?.storageKey as string) ?? id;\n await Promise.all([\n storage.delete(storageKey),\n database.delete({ model: \"media\", where: [{ field: \"id\", value: id }] }),\n ]);\n },\n async getUrl(id: string, options?: { expiresIn?: number }) {\n const record = await this.get(id);\n const storageKey = (record?.storageKey as string) ?? id;\n const fn = storage.getUrl;\n if (typeof fn !== \"function\") {\n throw new Error(\n \"URL generation not supported by this storage adapter. Use an S3/GCS adapter.\"\n );\n }\n return fn.call(storage, storageKey, options);\n },\n async reprocess(id: string, metadata: Record<string, unknown> = {}) {\n const record = await this.get(id);\n if (!record) throw new Error(`Media record not found: ${id}`);\n const storageKey = (record.storageKey as string) ?? id;\n return runPipeline(id, storageKey, metadata);\n },\n },\n async runBackgroundJob(payload: BackgroundJobPayload) {\n await runBackgroundJob(payload, registry, storage, database, jobAdapter, fileHandling);\n },\n };\n}\n\nexport { ValidationError } from \"./core/pipeline-executor\";\nexport {\n PluginRegistry,\n buildPluginRegistry,\n validatePlugin,\n hasBackgroundHandlers,\n HOOK_NAMES,\n} from \"./plugins/plugin-registry\";\nexport type { BackgroundJobPayload } from \"./core/lifecycle-engine\";\nexport type {\n BetterMediaRuntime,\n FileRecord,\n Metadata,\n IngestInput,\n MediaFileInput,\n MediaMetadata,\n MediaResult,\n} from \"./runtime/runtime.interface\";\nexport type {\n GetUrlOptions,\n PresignedUploadMethod,\n PresignedUploadOptions,\n PresignedUploadResult,\n} from \"@better-media/core\";\nexport type { FileHandlingConfig } from \"./core/file-loader\";\n\n// DB Architecture re-exports from core\nexport {\n schema,\n getMigrations,\n runMigrations,\n MigrationPlanner,\n compileMigrationOperationsSql,\n toCamelCase,\n toDbFieldName,\n applyOperationsToMetadata,\n isPgPoolLike,\n serializeData,\n deserializeData,\n runHooks,\n getColumnType,\n type SqlDialect,\n type TableMetadata,\n type MigrationOperation,\n type FieldDefinition,\n type FieldType,\n type BmSchema,\n type ModelDefinition,\n type IndexDefinition,\n type MigrationOptions,\n type DbHooks,\n type DatabaseHookContext,\n type HookContext,\n} from \"@better-media/core\";\n\n// Specific adapter implementations stay here\nexport * from \"./db/postgres\";\nexport { toDatabaseAdapter } from \"./db/postgres\";\n\n// CLI/Tooling utilities (moved to core)\nexport { getAdapter, type GetAdapterOptions } from \"@better-media/core\";\n","import fs from \"node:fs/promises\";\nimport { createWriteStream } from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { randomUUID } from \"node:crypto\";\nimport { Readable } from \"node:stream\";\nimport {\n type PipelineContext,\n type StorageAdapter,\n type DatabaseAdapter,\n TrustedMetadataSchema,\n type TrustedMetadata,\n markFileContentVerified,\n} from \"@better-media/core\";\n\n// const TRUSTED_DB_KEY_PREFIX = \"better-media:trusted:\";\n\nexport interface FileHandlingConfig {\n /** When set, files larger than this use streaming to temp file instead of loading into memory. */\n maxBufferBytes?: number;\n}\n\nexport async function loadTrustedFromDb(\n database: DatabaseAdapter,\n recordId: string\n): Promise<TrustedMetadata | null> {\n // Trusted metadata aligns with the central `media` model\n const record = await database.findOne({\n model: \"media\",\n where: [{ field: \"id\", value: recordId }],\n });\n\n if (!record || typeof record !== \"object\") return null;\n\n // Reconstruct TrustedMetadata shape from media record\n const rawTrusted = {\n file: {\n mimeType: record.mimeType ?? undefined,\n size: record.size ?? undefined,\n originalName: record.filename ?? undefined,\n },\n checksums: {\n sha256: record.checksum ?? undefined,\n },\n media: {\n width: record.width ?? undefined,\n height: record.height ?? undefined,\n duration: record.duration ?? undefined,\n },\n };\n\n // Strict runtime schema validation via Zod\n const result = TrustedMetadataSchema.safeParse(rawTrusted);\n\n if (!result.success) {\n console.error(`[QUARANTINE] Invalid TrustedMetadata mapped from media record \"${recordId}\"!`);\n console.error(`[QUARANTINE] Reason: ${JSON.stringify(result.error.format())}`);\n console.error(`[QUARANTINE] Data: ${JSON.stringify(rawTrusted)}`);\n return null;\n }\n\n const validated = result.data;\n return validated.file || validated.checksums || validated.media ? validated : null;\n}\n\nexport async function saveTrustedToDb(\n database: DatabaseAdapter,\n recordId: string,\n fileKey: string,\n trusted: TrustedMetadata,\n initialArgs?: {\n filename?: string;\n mimeType?: string;\n size?: number;\n context?: Record<string, unknown>;\n }\n): Promise<void> {\n // We map the trusted metadata back to the central media table, falling back to initial args.\n const updatePayload: Record<string, unknown> = {};\n\n if (trusted.file?.mimeType !== undefined) updatePayload.mimeType = trusted.file.mimeType;\n else if (initialArgs?.mimeType !== undefined) updatePayload.mimeType = initialArgs.mimeType;\n\n if (trusted.file?.size !== undefined) updatePayload.size = trusted.file.size;\n else if (initialArgs?.size !== undefined) updatePayload.size = initialArgs.size;\n\n if (trusted.file?.originalName !== undefined) updatePayload.filename = trusted.file.originalName;\n else if (initialArgs?.filename !== undefined) updatePayload.filename = initialArgs.filename;\n\n if (trusted.checksums?.sha256 !== undefined) updatePayload.checksum = trusted.checksums.sha256;\n if (trusted.media?.width !== undefined) updatePayload.width = trusted.media.width;\n if (trusted.media?.height !== undefined) updatePayload.height = trusted.media.height;\n if (trusted.media?.duration !== undefined) updatePayload.duration = trusted.media.duration;\n\n if (initialArgs?.context !== undefined) updatePayload.context = initialArgs.context;\n\n // Perform a single-shot Upsert\n const existing = await database.findOne({\n model: \"media\",\n where: [{ field: \"id\", value: recordId }],\n });\n\n updatePayload.storageKey = fileKey;\n\n if (existing) {\n if (Object.keys(updatePayload).length > 0) {\n await database.update({\n model: \"media\",\n where: [{ field: \"id\", value: recordId }],\n update: updatePayload,\n });\n }\n } else {\n // Record does not exist, initialize it\n updatePayload.id = recordId;\n updatePayload.status = \"PROCESSING\"; // Default standard\n updatePayload.createdAt = new Date();\n await database.create({\n model: \"media\",\n data: updatePayload,\n });\n }\n}\n\nasync function streamToTempFile(\n stream: ReadableStream<Uint8Array> | Readable | unknown,\n fileKey: string\n): Promise<string> {\n const ext = path.extname(fileKey) || \".bin\";\n const tmpPath = path.join(os.tmpdir(), `better-media-${randomUUID()}${ext}`);\n const nodeStream =\n stream instanceof Readable\n ? stream\n : Readable.fromWeb(stream as Parameters<typeof Readable.fromWeb>[0]);\n const writeStream = createWriteStream(tmpPath);\n await new Promise<void>((resolve, reject) => {\n nodeStream.pipe(writeStream);\n nodeStream.on(\"error\", reject);\n writeStream.on(\"error\", reject);\n writeStream.on(\"finish\", resolve);\n });\n return tmpPath;\n}\n\nexport async function loadFileIntoContext(\n context: PipelineContext,\n fileHandling: FileHandlingConfig\n): Promise<void> {\n const { file, storage } = context;\n const fileKey = file.key;\n const maxBufferBytes = fileHandling.maxBufferBytes;\n\n const storageWithExtras = storage as StorageAdapter & {\n getSize?: (key: string) => Promise<number | null>;\n getStream?: (key: string) => Promise<ReadableStream | null>;\n };\n\n if (!context.utilities) context.utilities = {};\n\n const fileContent: NonNullable<PipelineContext[\"utilities\"]>[\"fileContent\"] = {};\n\n let useStream = false;\n if (\n maxBufferBytes != null &&\n typeof storageWithExtras.getSize === \"function\" &&\n typeof storageWithExtras.getStream === \"function\"\n ) {\n const size = await storageWithExtras.getSize(fileKey);\n if (size != null && size > maxBufferBytes) {\n useStream = true;\n }\n }\n\n if (useStream && typeof storageWithExtras.getStream === \"function\") {\n const stream = await storageWithExtras.getStream(fileKey);\n if (stream != null) {\n const tmpPath = await streamToTempFile(stream, fileKey);\n fileContent.tempPath = tmpPath;\n } else {\n const buffer = await storage.get(fileKey);\n if (buffer != null) fileContent.buffer = buffer;\n }\n } else {\n const buffer = await storage.get(fileKey);\n if (buffer != null) fileContent.buffer = buffer;\n }\n\n context.utilities!.fileContent = fileContent;\n\n if (fileContent.buffer != null || fileContent.tempPath != null) {\n markFileContentVerified(context);\n }\n}\n\nexport async function getBufferFromContext(context: PipelineContext): Promise<Buffer | null> {\n const fileContent = context.utilities?.fileContent;\n if (!fileContent) return null;\n if (fileContent.buffer) {\n markFileContentVerified(context);\n return fileContent.buffer;\n }\n if (fileContent.tempPath) {\n markFileContentVerified(context);\n return fs.readFile(fileContent.tempPath);\n }\n return null;\n}\n\nexport async function cleanupTempFile(context: PipelineContext): Promise<void> {\n const tmpPath = context.utilities?.fileContent?.tempPath;\n if (tmpPath) {\n await fs.unlink(tmpPath).catch(() => {});\n if (context.utilities?.fileContent) {\n context.utilities.fileContent.tempPath = undefined;\n }\n }\n}\n","import path from \"node:path\";\nimport type {\n JobAdapter,\n PipelineContext,\n StorageAdapter,\n DatabaseAdapter,\n ValidationResult,\n} from \"@better-media/core\";\nimport { HOOK_NAMES } from \"../plugins/plugin-registry\";\nimport type { LifecycleEngine } from \"./lifecycle-engine\";\nimport {\n loadFileIntoContext,\n loadTrustedFromDb,\n saveTrustedToDb,\n cleanupTempFile,\n type FileHandlingConfig,\n} from \"./file-loader\";\n\nfunction buildFileInfo(\n fileKey: string,\n metadata: Record<string, unknown>\n): PipelineContext[\"file\"] {\n const mime = metadata.contentType ?? metadata.mimeType ?? metadata[\"content-type\"];\n const size = typeof metadata.size === \"number\" ? metadata.size : undefined;\n const originalName = (metadata.originalName as string) ?? (metadata.originalname as string);\n const ext = originalName\n ? path.extname(originalName).toLowerCase()\n : path.extname(fileKey).toLowerCase();\n\n return {\n key: fileKey,\n size,\n mimeType: typeof mime === \"string\" ? mime : undefined,\n originalName: typeof originalName === \"string\" ? originalName : undefined,\n extension: ext || undefined,\n checksums: undefined,\n };\n}\n\nfunction buildStorageLocation(fileKey: string): PipelineContext[\"storageLocation\"] {\n return {\n key: fileKey,\n bucket: undefined,\n region: undefined,\n url: undefined,\n };\n}\n\nfunction syncTrustedToFile(context: PipelineContext): void {\n const { trusted, file } = context;\n if (trusted.file?.mimeType != null) file.mimeType = trusted.file.mimeType;\n if (trusted.file?.size != null) file.size = trusted.file.size;\n if (trusted.file?.originalName != null) file.originalName = trusted.file.originalName;\n if (trusted.checksums) file.checksums = { ...file.checksums, ...trusted.checksums };\n}\n\n/** Error thrown when validation phase aborts the pipeline */\nexport class ValidationError extends Error {\n constructor(\n public readonly recordId: string,\n public readonly fileKey: string,\n public readonly result: ValidationResult\n ) {\n super(result.message ?? \"Validation failed\");\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Pipeline executor: runs phases in order (upload:init → validation → scan → process → upload:complete).\n */\nexport class PipelineExecutor {\n constructor(\n private readonly engine: LifecycleEngine,\n private readonly storage: StorageAdapter,\n private readonly database: DatabaseAdapter,\n private readonly jobs: JobAdapter,\n private readonly fileHandling: FileHandlingConfig = {}\n ) {}\n\n async run(\n recordId: string,\n fileKey: string,\n metadata: Record<string, unknown> = {},\n appContext: Record<string, unknown> = {}\n ): Promise<void> {\n const meta = { ...metadata };\n const trustedFromDb = await loadTrustedFromDb(this.database, recordId);\n\n const context: PipelineContext = {\n recordId,\n file: buildFileInfo(fileKey, meta),\n storageLocation: buildStorageLocation(fileKey),\n processing: {},\n metadata: { ...meta, ...appContext }, // Merge for plugins to read backwards-compatibly\n trusted: trustedFromDb ?? {},\n utilities: {},\n storage: this.storage,\n database: this.database,\n jobs: this.jobs,\n };\n\n if (trustedFromDb) {\n syncTrustedToFile(context);\n }\n\n try {\n await loadFileIntoContext(context, this.fileHandling);\n\n // Initialize the media record early to satisfy foreign key constraints\n // for any results (validation, scan) persisted by plugins during the pipeline.\n await saveTrustedToDb(this.database, recordId, fileKey, context.trusted, {\n filename: context.file.originalName,\n mimeType: context.file.mimeType,\n size: context.file.size,\n context: appContext,\n });\n\n for (const phase of HOOK_NAMES) {\n const result = await this.engine.trigger(phase, context);\n if (result !== undefined && typeof result === \"object\" && result.valid === false) {\n throw new ValidationError(recordId, fileKey, result);\n }\n }\n\n // Single-shot Upsert of initial data and trusted results\n await saveTrustedToDb(this.database, recordId, fileKey, context.trusted, {\n filename: context.file.originalName,\n mimeType: context.file.mimeType,\n size: context.file.size,\n context: appContext,\n });\n } finally {\n await cleanupTempFile(context);\n }\n }\n}\n","import path from \"node:path\";\nimport type {\n JobAdapter,\n PipelineContext,\n StorageAdapter,\n DatabaseAdapter,\n} from \"@better-media/core\";\nimport type { HookRegistry } from \"../plugins/plugin.interface\";\nimport type { BackgroundJobPayload } from \"../core/lifecycle-engine\";\nimport {\n loadFileIntoContext,\n loadTrustedFromDb,\n saveTrustedToDb,\n cleanupTempFile,\n type FileHandlingConfig,\n} from \"../core/file-loader\";\n\nfunction syncTrustedToFile(context: PipelineContext): void {\n const { trusted, file } = context;\n if (trusted.file?.mimeType != null) file.mimeType = trusted.file.mimeType;\n if (trusted.file?.size != null) file.size = trusted.file.size;\n if (trusted.file?.originalName != null) file.originalName = trusted.file.originalName;\n if (trusted.checksums) file.checksums = { ...file.checksums, ...trusted.checksums };\n}\n\n/**\n * Execute a background job: rebuild context, find handler, run it.\n * Call from worker process (Bull, SQS, Inngest, etc.).\n */\nexport async function runBackgroundJob(\n payload: BackgroundJobPayload,\n registry: HookRegistry,\n storage: StorageAdapter,\n database: DatabaseAdapter,\n jobs: JobAdapter,\n fileHandling: FileHandlingConfig = {}\n): Promise<void> {\n const {\n recordId: payloadRecordId,\n metadata = {},\n file: payloadFile,\n storageLocation: payloadStorage,\n processing: payloadProcessing,\n hookName,\n pluginName,\n } = payload;\n\n const meta = { ...metadata };\n\n // Backwards compat: legacy payloads may have fileKey instead of file\n const legacyKey = (payload as { fileKey?: string }).fileKey;\n if (!payloadFile && !legacyKey) {\n throw new Error(\"Background job payload must include file or fileKey\");\n }\n const file: PipelineContext[\"file\"] =\n payloadFile ??\n (legacyKey\n ? {\n key: legacyKey,\n size: typeof meta.size === \"number\" ? meta.size : undefined,\n mimeType:\n typeof (meta.contentType ?? meta.mimeType ?? meta[\"content-type\"]) === \"string\"\n ? ((meta.contentType ?? meta.mimeType ?? meta[\"content-type\"]) as string)\n : undefined,\n originalName:\n typeof (meta.originalName ?? meta.originalname) === \"string\"\n ? ((meta.originalName ?? meta.originalname) as string)\n : undefined,\n extension: path.extname(legacyKey).toLowerCase() || undefined,\n }\n : { key: \"\" });\n\n const recordId = payloadRecordId ?? file.key ?? \"unknown\";\n\n const storageLocation: PipelineContext[\"storageLocation\"] = payloadStorage ?? { key: file.key };\n\n const processing: PipelineContext[\"processing\"] = payloadProcessing ?? {};\n\n const trustedFromDb = await loadTrustedFromDb(database, recordId);\n\n const context: PipelineContext = {\n recordId,\n file,\n storageLocation,\n processing,\n metadata: meta,\n trusted: trustedFromDb ?? {},\n utilities: {},\n storage,\n database,\n jobs,\n };\n\n if (trustedFromDb) {\n syncTrustedToFile(context);\n }\n\n try {\n await loadFileIntoContext(context, fileHandling);\n\n const handlers = registry.get(hookName) ?? [];\n const handler = handlers.find((h) => h.name === pluginName);\n if (!handler) {\n throw new Error(`Handler not found: ${hookName}/${pluginName}`);\n }\n\n // Use the manifest from the registry exclusively to prevent trust escalation\n const manifest = handler.manifest;\n\n // TODO: Ideally createSecureContext should be in a shared utility.\n // For now, we'll implement it or use it if exported from LifecycleEngine.\n // Let's assume we need to implement it here for now or I should have exported it.\n // I will export it from LifecycleEngine.\n const { createSecureContext } = await import(\"../core/lifecycle-engine\");\n const { proxy, api } = createSecureContext(\n context,\n pluginName,\n manifest.namespace,\n manifest.trustLevel,\n manifest.capabilities\n );\n\n await handler.fn(proxy, api);\n\n if (context.trusted.file ?? context.trusted.checksums) {\n await saveTrustedToDb(database, recordId, file.key, context.trusted);\n }\n } finally {\n await cleanupTempFile(context);\n }\n}\n","import type {\n CountOptions,\n CreateOptions,\n DatabaseAdapter,\n DatabaseTransactionAdapter,\n DeleteOptions,\n FindOptions,\n UpdateOptions,\n WhereClause,\n FieldDefinition,\n MigrationOperation,\n SqlDialect,\n TableMetadata,\n} from \"@better-media/core\";\nimport {\n schema,\n deserializeData,\n serializeData,\n getColumnType,\n toCamelCase,\n toDbFieldName,\n isPgPoolLike,\n type PgPoolLike,\n type PgClientLike,\n type Queryable,\n type DatabaseHookContext,\n type QueryResultLike,\n} from \"@better-media/core\";\n\nexport type { PgPoolLike, PgClientLike, Queryable, QueryResultLike, DatabaseHookContext };\n\nfunction quote(name: string): string {\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\nfunction rowToAppKeys(row: Record<string, unknown>): Record<string, unknown> {\n const mapped: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) {\n mapped[toCamelCase(key)] = value;\n }\n return mapped;\n}\n\nfunction buildWhere(where?: WhereClause, startAt = 1): { sql: string; values: unknown[] } {\n if (!where?.length) return { sql: \"\", values: [] };\n const parts: string[] = [];\n const values: unknown[] = [];\n let idx = startAt;\n\n for (let i = 0; i < where.length; i++) {\n const condition = where[i];\n if (!condition) continue;\n\n const connector = i > 0 ? (where[i - 1]?.connector ?? \"AND\") : \"AND\";\n const field = quote(toDbFieldName(condition.field));\n const op = condition.operator ?? \"=\";\n\n if (i > 0) parts.push(connector);\n\n if (op === \"contains\" || op === \"starts_with\" || op === \"ends_with\") {\n const raw = String(condition.value ?? \"\");\n const value = op === \"contains\" ? `%${raw}%` : op === \"starts_with\" ? `${raw}%` : `%${raw}`;\n parts.push(`${field} LIKE $${idx}`);\n values.push(value);\n idx += 1;\n continue;\n }\n\n if (op === \"in\" || op === \"not_in\") {\n const list = Array.isArray(condition.value) ? condition.value : [condition.value];\n if (!list.length) {\n parts.push(op === \"in\" ? \"FALSE\" : \"TRUE\");\n continue;\n }\n const placeholders = list.map(() => `$${idx++}`).join(\", \");\n parts.push(`${field} ${op === \"in\" ? \"IN\" : \"NOT IN\"} (${placeholders})`);\n values.push(...list);\n continue;\n }\n\n if (condition.value === null && (op === \"=\" || op === \"!=\")) {\n parts.push(`${field} ${op === \"=\" ? \"IS\" : \"IS NOT\"} NULL`);\n continue;\n }\n\n const sqlOp = op === \"!=\" ? \"<>\" : op;\n parts.push(`${field} ${sqlOp} $${idx}`);\n values.push(condition.value);\n idx += 1;\n }\n\n if (!parts.length) return { sql: \"\", values: [] };\n return { sql: ` WHERE ${parts.join(\" \")}`, values };\n}\n\nclass PostgresDatabaseAdapter implements DatabaseAdapter {\n readonly id = \"postgres\";\n\n constructor(private readonly db: Queryable) {}\n\n private modelFields(model: string): Record<string, { type: FieldDefinition[\"type\"] }> {\n return schema[model]?.fields ?? {};\n }\n\n async create<T extends Record<string, unknown>>(options: CreateOptions<T>): Promise<T> {\n const fields = this.modelFields(options.model);\n const serialized = serializeData(fields, options.data as Record<string, unknown>);\n const keys = Object.keys(serialized);\n const columns = keys.map((k) => quote(toDbFieldName(k))).join(\", \");\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(\", \");\n const values = keys.map((k) => serialized[k]);\n const result = await this.db.query(\n `INSERT INTO ${quote(options.model)} (${columns}) VALUES (${placeholders}) RETURNING *`,\n values\n );\n return deserializeData(fields, rowToAppKeys(result.rows[0] ?? serialized)) as T;\n }\n\n async findOne<T extends Record<string, unknown>>(options: FindOptions<T>): Promise<T | null> {\n const rows = await this.findMany({ ...options, limit: 1 });\n return (rows[0] as T | undefined) ?? null;\n }\n\n async findMany<T extends Record<string, unknown>>(options: FindOptions<T>): Promise<T[]> {\n const fields = this.modelFields(options.model);\n const select =\n options.select && options.select.length > 0\n ? options.select.map((f) => `${quote(toDbFieldName(f))} AS ${quote(f)}`).join(\", \")\n : \"*\";\n let query = `SELECT ${select} FROM ${quote(options.model)}`;\n const where = buildWhere(options.where);\n query += where.sql;\n const values = [...where.values];\n\n if (options.sortBy) {\n query += ` ORDER BY ${quote(toDbFieldName(options.sortBy.field))} ${options.sortBy.direction.toUpperCase()}`;\n }\n if (typeof options.limit === \"number\") {\n query += ` LIMIT $${values.length + 1}`;\n values.push(options.limit);\n }\n if (typeof options.offset === \"number\") {\n query += ` OFFSET $${values.length + 1}`;\n values.push(options.offset);\n }\n\n const result = await this.db.query(query, values);\n return result.rows.map((r) => deserializeData(fields, rowToAppKeys(r)) as T);\n }\n\n async update<T extends Record<string, unknown>>(options: UpdateOptions<T>): Promise<T | null> {\n const updated = await this.updateMany(options);\n if (!updated) return null;\n return this.findOne({ model: options.model, where: options.where });\n }\n\n async updateMany<T extends Record<string, unknown>>(options: UpdateOptions<T>): Promise<number> {\n const fields = this.modelFields(options.model);\n const serialized = serializeData(fields, options.update as Record<string, unknown>);\n const entries = Object.entries(serialized);\n if (!entries.length) return 0;\n\n const setSql = entries.map(([key], i) => `${quote(toDbFieldName(key))} = $${i + 1}`).join(\", \");\n const setValues = entries.map(([, value]) => value);\n const where = buildWhere(options.where, setValues.length + 1);\n const query = `UPDATE ${quote(options.model)} SET ${setSql}${where.sql}`;\n const result = await this.db.query(query, [...setValues, ...where.values]);\n return Number(result.rowCount ?? 0);\n }\n\n async delete(options: DeleteOptions): Promise<void> {\n await this.deleteMany(options);\n }\n\n async deleteMany(options: DeleteOptions): Promise<number> {\n const where = buildWhere(options.where);\n const query = `DELETE FROM ${quote(options.model)}${where.sql}`;\n const result = await this.db.query(query, where.values);\n return Number(result.rowCount ?? 0);\n }\n\n async count(options: CountOptions): Promise<number> {\n const where = buildWhere(options.where);\n const result = await this.db.query(\n `SELECT COUNT(*)::int AS c FROM ${quote(options.model)}${where.sql}`,\n where.values\n );\n return Number(result.rows[0]?.c ?? 0);\n }\n\n async raw<T = unknown>(query: string, params?: unknown[]): Promise<T> {\n const result = await this.db.query(query, params);\n return result.rows as T;\n }\n\n async transaction<R>(callback: (trx: DatabaseTransactionAdapter) => Promise<R>): Promise<R> {\n const pool = this.db as PgPoolLike;\n if (typeof pool.connect !== \"function\") {\n throw new Error(\"[better-media] The provided Postgres client does not support transactions.\");\n }\n\n const client = await pool.connect();\n try {\n await client.query(\"BEGIN\");\n const trxAdapter = new PostgresDatabaseAdapter(client);\n const result = await callback(trxAdapter);\n await client.query(\"COMMIT\");\n return result;\n } catch (error) {\n await client.query(\"ROLLBACK\");\n throw error;\n } finally {\n client.release?.();\n }\n }\n\n __getDialect(): SqlDialect {\n return \"postgres\";\n }\n\n async __getMetadata(): Promise<TableMetadata[]> {\n const result = await this.db.query(\n `SELECT table_name AS \"tableName\", column_name AS \"columnName\", data_type AS \"dataType\", is_nullable AS \"isNullable\"\n FROM information_schema.columns\n WHERE table_schema = current_schema()\n ORDER BY table_name, ordinal_position`\n );\n\n const grouped = new Map<string, TableMetadata>();\n for (const row of result.rows as Array<Record<string, unknown>>) {\n const tableName = String(row.tableName);\n if (!grouped.has(tableName)) grouped.set(tableName, { name: tableName, columns: [] });\n grouped.get(tableName)!.columns.push({\n name: toCamelCase(String(row.columnName)),\n dataType: String(row.dataType),\n isNullable: String(row.isNullable).toUpperCase() === \"YES\",\n });\n }\n return [...grouped.values()];\n }\n\n async __executeMigration(operation: MigrationOperation): Promise<void> {\n if (operation.type === \"createTable\") {\n const columns = (Object.entries(operation.definition.fields) as [string, FieldDefinition][])\n .map(([name, field]) => {\n const parts = [quote(toDbFieldName(name)), getColumnType(field, \"postgres\")];\n if (field.primaryKey) parts.push(\"PRIMARY KEY\");\n if (field.required) parts.push(\"NOT NULL\");\n if (field.unique) parts.push(\"UNIQUE\");\n if (field.references) {\n parts.push(\n `REFERENCES ${quote(field.references.model)}(${quote(toDbFieldName(field.references.field))}) ON DELETE ${String(\n field.references.onDelete ?? \"CASCADE\"\n ).toUpperCase()}`\n );\n }\n return parts.join(\" \");\n })\n .join(\", \");\n\n await this.db.query(`CREATE TABLE IF NOT EXISTS ${quote(operation.table)} (${columns})`);\n\n for (const index of operation.definition.indexes ?? []) {\n const indexName = `idx_${operation.table}_${index.fields.map((f: string) => toDbFieldName(f)).join(\"_\")}`;\n await this.db.query(\n `CREATE ${index.unique ? \"UNIQUE \" : \"\"}INDEX IF NOT EXISTS ${quote(indexName)} ON ${quote(\n operation.table\n )} (${index.fields.map((f) => quote(toDbFieldName(f))).join(\", \")})`\n );\n }\n return;\n }\n\n if (operation.type === \"addColumn\") {\n const field = operation.definition;\n const parts = [\n quote(toDbFieldName(operation.field)),\n getColumnType(operation.definition as FieldDefinition, \"postgres\"),\n ];\n if (field.required) parts.push(\"NOT NULL\");\n if (field.unique) parts.push(\"UNIQUE\");\n if (field.references) {\n parts.push(\n `REFERENCES ${quote(field.references.model)}(${quote(toDbFieldName(field.references.field))}) ON DELETE ${String(\n field.references.onDelete ?? \"CASCADE\"\n ).toUpperCase()}`\n );\n }\n await this.db.query(\n `ALTER TABLE ${quote(operation.table)} ADD COLUMN IF NOT EXISTS ${parts.join(\" \")}`\n );\n return;\n }\n\n if (operation.type === \"createIndex\") {\n await this.db.query(\n `CREATE ${operation.unique ? \"UNIQUE \" : \"\"}INDEX IF NOT EXISTS ${quote(\n operation.name\n )} ON ${quote(operation.table)} (${operation.fields.map((f) => quote(toDbFieldName(f))).join(\", \")})`\n );\n }\n }\n}\n\nexport function postgresDatabase(pool: PgPoolLike): DatabaseAdapter {\n return new PostgresDatabaseAdapter(pool);\n}\n\nexport function toDatabaseAdapter(database: DatabaseAdapter | PgPoolLike): DatabaseAdapter {\n if (isPgPoolLike(database) && typeof (database as { create?: unknown }).create !== \"function\") {\n return postgresDatabase(database);\n }\n return database as DatabaseAdapter;\n}\n"]}
|