import { readFileSync } from 'node:fs' import { basename } from 'node:path' import { VaultFile, APIKeyAuthStrategy, DataTokenAuthStrategy, isVaultReference } from '@meistrari/vault-sdk' import type { AuthStrategy } from '@meistrari/vault-sdk' import { getApiBaseUrl, isApplicationToken, loadFreshApiKey } from './common.ts' export { isVaultReference } export type { VaultFile } // Application tokens must reach the gateway in the Authorization header, which is // what the API key strategy sends. function resolveAuthStrategy(token: string): AuthStrategy { const isJwt = token.split('.').length === 3 return isJwt && !isApplicationToken(token) ? new DataTokenAuthStrategy(token) : new APIKeyAuthStrategy(token) } async function getVaultConfig() { const token = await loadFreshApiKey() return { vaultUrl: `${getApiBaseUrl()}/_services/vault`, authStrategy: resolveAuthStrategy(token), } } /** * Upload a local file to Vault. Returns the vault:// reference. */ export async function uploadFile(filePath: string, opts?: { parentId?: string }): Promise { const config = await getVaultConfig() const content = new Blob([readFileSync(filePath)]) const name = basename(filePath) const file = await VaultFile.fromContent({ content, config, name, upload: true, parentId: opts?.parentId, }) return file.getVaultReference() } /** * Upload raw content to Vault. Returns the vault:// reference. */ export async function uploadContent(name: string, content: Blob | string, opts?: { mimeType?: string; parentId?: string }): Promise { const config = await getVaultConfig() const blob = typeof content === 'string' ? new Blob([content]) : content const file = await VaultFile.fromContent({ content: blob, config, name, mimeType: opts?.mimeType, upload: true, parentId: opts?.parentId, }) return file.getVaultReference() } /** * Download a file from Vault. Returns the file content as a Blob. */ export async function downloadFile(vaultRef: string): Promise { const config = await getVaultConfig() const file = await VaultFile.fromVaultReference({ reference: vaultRef, config, download: true }) return file.content! } /** * Get a pre-signed download URL for a Vault file. */ export async function downloadFileUrl(vaultRef: string): Promise { const config = await getVaultConfig() const file = await VaultFile.fromVaultReference({ reference: vaultRef, config }) const url = await file.getDownloadUrl() return url.toString() } /** * Delete a file from Vault. */ export async function deleteFile(vaultRef: string): Promise { const config = await getVaultConfig() const file = await VaultFile.fromVaultReference({ reference: vaultRef, config }) await file.delete() } /** * Get metadata for a Vault file. */ export async function getFileMetadata(vaultRef: string) { const config = await getVaultConfig() const file = await VaultFile.fromVaultReference({ reference: vaultRef, config }) return file.getFileMetadata() } /** * Create a public permalink for a Vault file. */ export async function createPermalink(vaultRef: string, opts?: { expiresIn?: number }) { const config = await getVaultConfig() const file = await VaultFile.fromVaultReference({ reference: vaultRef, config }) return file.createPermalink(opts) } /** * List all permalinks for a Vault file. */ export async function listPermalinks(vaultRef: string) { const config = await getVaultConfig() const file = await VaultFile.fromVaultReference({ reference: vaultRef, config }) return file.getPermalinks() } /** * Delete a permalink by ID. Requires the vault reference of the file that owns the permalink. */ export async function deletePermalink(vaultRef: string, permalinkId: string): Promise { const config = await getVaultConfig() const file = await VaultFile.fromVaultReference({ reference: vaultRef, config }) const permalinks = await file.getPermalinks() const permalink = permalinks.find(p => p.id === permalinkId) if (!permalink) { throw new Error(`Permalink ${permalinkId} not found for ${vaultRef}`) } await permalink.delete() } /** * Upload multiple files to Vault. Returns an array of vault:// references. */ export async function bulkUploadFiles(files: Array<{ name: string; content: Blob | string; mimeType?: string }>): Promise { const config = await getVaultConfig() const bulkInput = files.map(f => ({ content: typeof f.content === 'string' ? new Blob([f.content]) : f.content, name: f.name, mimeType: f.mimeType, })) const vaultFiles = await VaultFile.fromContentBulk({ files: bulkInput, config, upload: true }) return vaultFiles.map(f => f.getVaultReference()) } /** * Upload a file and return the vault:// reference string for use in test case variable values. */ export async function uploadFileForVariable(filePath: string): Promise { return uploadFile(filePath) }