ras-stack 1.1.1 → 2.0.1

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.
Files changed (45) hide show
  1. package/README.md +0 -2
  2. package/config/oxlint/domain.json +29 -0
  3. package/config/oxlint/layers.json +116 -0
  4. package/dist/auth/providers.js +1 -1
  5. package/dist/auth/providers.js.map +1 -1
  6. package/dist/email/index.d.ts +11 -0
  7. package/dist/email/index.js +16 -0
  8. package/dist/email/index.js.map +1 -1
  9. package/dist/policy/changesets.d.ts +1 -0
  10. package/dist/policy/changesets.js +37 -0
  11. package/dist/policy/changesets.js.map +1 -0
  12. package/dist/policy/cli.js +2 -1
  13. package/dist/policy/cli.js.map +1 -1
  14. package/dist/policy/index.js +5 -2
  15. package/dist/policy/index.js.map +1 -1
  16. package/dist/posthog/proxy.d.ts +1 -1
  17. package/dist/posthog/proxy.js +11 -5
  18. package/dist/posthog/proxy.js.map +1 -1
  19. package/dist/posthog/server.d.ts +6 -1
  20. package/dist/posthog/server.js +31 -0
  21. package/dist/posthog/server.js.map +1 -1
  22. package/dist/preview/dokploy.d.ts +1 -0
  23. package/dist/preview/dokploy.js +17 -0
  24. package/dist/preview/dokploy.js.map +1 -1
  25. package/dist/realtime/environment.d.ts +10 -0
  26. package/dist/realtime/environment.js +27 -0
  27. package/dist/realtime/environment.js.map +1 -0
  28. package/dist/realtime/index.d.ts +2 -0
  29. package/dist/realtime/index.js +1 -0
  30. package/dist/realtime/index.js.map +1 -1
  31. package/dist/realtime/publisher.d.ts +3 -1
  32. package/dist/realtime/publisher.js +19 -2
  33. package/dist/realtime/publisher.js.map +1 -1
  34. package/dist/runtime/index.d.ts +5 -0
  35. package/dist/runtime/index.js +15 -0
  36. package/dist/runtime/index.js.map +1 -1
  37. package/dist/server/index.d.ts +1 -1
  38. package/dist/server/index.js.map +1 -1
  39. package/dist/server/rpc.d.ts +2 -0
  40. package/dist/server/rpc.js +19 -14
  41. package/dist/server/rpc.js.map +1 -1
  42. package/dist/uploads/index.d.ts +7 -2
  43. package/dist/uploads/index.js +64 -33
  44. package/dist/uploads/index.js.map +1 -1
  45. package/package.json +6 -2
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\n\nexport { runRealtimeDev, type RealtimeDevOptions } from './dev.js'\n\nexport type RuntimeProcess = {\n name: string\n command: string\n args?: readonly string[]\n cwd?: string\n env?: NodeJS.ProcessEnv\n}\n\ntype SignalSource = Pick<NodeJS.Process, 'off' | 'once'>\ntype SpawnProcess = (process: RuntimeProcess) => ChildProcess\n\nexport type SupervisorOptions = {\n shutdownTimeoutMs?: number\n signalSource?: SignalSource\n spawn?: SpawnProcess\n}\n\nexport async function superviseProcesses(processes: readonly RuntimeProcess[], options: SupervisorOptions = {}) {\n return runSupervisor(processes, options)\n}\n\nasync function runSupervisor(processes: readonly RuntimeProcess[], options: SupervisorOptions, shutdownOrder?: readonly string[]) {\n if (processes.length === 0) throw new Error('at least one runtime process is required')\n const names = new Set<string>()\n for (const process of processes) {\n if (!process.name.trim()) throw new Error('runtime process names must not be empty')\n if (!process.command.trim()) throw new Error(`runtime process ${process.name} must have a command`)\n if (names.has(process.name)) throw new Error(`duplicate runtime process name: ${process.name}`)\n names.add(process.name)\n }\n\n const signalSource = options.signalSource ?? process\n const shutdownTimeoutMs = options.shutdownTimeoutMs ?? 10_000\n if (!Number.isSafeInteger(shutdownTimeoutMs) || shutdownTimeoutMs < 0) {\n throw new Error('shutdownTimeoutMs must be a non-negative integer')\n }\n const spawnProcess =\n options.spawn ??\n ((specification: RuntimeProcess) =>\n spawn(specification.command, [...(specification.args ?? [])], {\n cwd: specification.cwd,\n env: specification.env ?? process.env,\n stdio: 'inherit',\n }))\n const children = new Map<ChildProcess, string>()\n const exits = new Map<ChildProcess, Promise<void>>()\n let settled = false\n let phasedShutdown = false\n let expectedExit: ChildProcess | undefined\n let resolveResult!: (value: number) => void\n const result = new Promise<number>((resolve) => {\n resolveResult = resolve\n })\n\n const finishImmediately = async (status: number) => {\n if (settled) return\n settled = true\n signalSource.off('SIGINT', onSignal)\n signalSource.off('SIGTERM', onSignal)\n await stopChildren([...children.keys()], shutdownTimeoutMs)\n resolveResult(status)\n }\n const finishInPhases = async () => {\n if (settled || phasedShutdown) return\n phasedShutdown = true\n signalSource.off('SIGINT', onSignal)\n signalSource.off('SIGTERM', onSignal)\n const deadline = Date.now() + shutdownTimeoutMs\n for (const name of shutdownOrder ?? []) {\n if (settled) return\n const child = [...children].find(([, childName]) => childName === name)?.[0]\n if (!child || !running(child)) continue\n expectedExit = child\n child.kill('SIGTERM')\n // oxlint-disable-next-line no-await-in-loop -- Shutdown phases must remain dependency-ordered.\n const exited = await beforeDeadline(exits.get(child)!, Math.max(0, deadline - Date.now()))\n expectedExit = undefined\n if (settled) return\n if (!exited) {\n settled = true\n for (const runningChild of children.keys()) if (running(runningChild)) runningChild.kill('SIGKILL')\n resolveResult(0)\n return\n }\n }\n settled = true\n resolveResult(0)\n }\n const onSignal = () => {\n if (shutdownOrder) void finishInPhases()\n else void finishImmediately(0)\n }\n signalSource.once('SIGINT', onSignal)\n signalSource.once('SIGTERM', onSignal)\n\n try {\n for (const specification of processes) {\n const child = spawnProcess(specification)\n children.set(child, specification.name)\n let resolveExit!: () => void\n exits.set(\n child,\n new Promise<void>((resolve) => {\n resolveExit = resolve\n }),\n )\n child.once('error', () => void finishImmediately(1))\n child.once('exit', (code) => {\n resolveExit()\n if (!phasedShutdown || child !== expectedExit) void finishImmediately(code && code > 0 ? code : 1)\n })\n }\n } catch (error) {\n await finishImmediately(1)\n throw error\n }\n return result\n}\n\nasync function beforeDeadline(exited: Promise<void>, timeoutMs: number) {\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<false>((resolve) => {\n timer = setTimeout(() => resolve(false), timeoutMs)\n })\n const result = await Promise.race([exited.then(() => true as const), timeout])\n if (timer) clearTimeout(timer)\n return result\n}\n\nfunction running(child: ChildProcess) {\n return child.exitCode === null && child.signalCode === null\n}\n\nasync function stopChildren(children: ChildProcess[], timeoutMs: number) {\n const active = children.filter(running)\n if (active.length === 0) return\n const exited = Promise.all(active.map((child) => new Promise<void>((resolve) => child.once('exit', () => resolve())))).then(\n () => 'exited' as const,\n )\n for (const child of active) child.kill('SIGTERM')\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<'timeout'>((resolve) => {\n timer = setTimeout(() => resolve('timeout'), timeoutMs)\n })\n const outcome = await Promise.race([exited, timeout])\n if (timer) clearTimeout(timer)\n if (outcome === 'timeout') {\n for (const child of active) if (running(child)) child.kill('SIGKILL')\n }\n}\n\nexport type CentrifugoEnvironmentOptions = {\n apiKey: string\n clientTokenSecret?: string\n subscriptionTokenSecret?: string\n allowedOrigins?: string\n redisUrl?: string\n}\n\nexport type RealtimeStackOptions = {\n app: Omit<RuntimeProcess, 'name'>\n centrifugo: {\n command?: string\n configPath: string\n cwd?: string\n env?: NodeJS.ProcessEnv\n environment: CentrifugoEnvironmentOptions\n }\n caddy: {\n command?: string\n configPath: string\n cwd?: string\n env?: NodeJS.ProcessEnv\n proxy?: CaddyRealtimeProxyOptions\n runtime?: CaddyRuntimeEnvironmentOptions\n }\n supervisor?: SupervisorOptions\n}\n\nexport async function runRealtimeStack(options: RealtimeStackOptions) {\n const configPath = absolutePath(options.caddy.configPath, 'caddy.configPath')\n const centrifugoConfigPath = absolutePath(options.centrifugo.configPath, 'centrifugo.configPath')\n await mkdir(path.dirname(configPath), { recursive: true })\n await writeFile(configPath, caddyRealtimeProxy(options.caddy.proxy), 'utf8')\n return runSupervisor(\n [\n { name: 'app', ...options.app },\n {\n name: 'realtime',\n command: options.centrifugo.command ?? 'centrifugo',\n args: [`--config=${centrifugoConfigPath}`],\n ...(options.centrifugo.cwd ? { cwd: options.centrifugo.cwd } : {}),\n env: { ...options.centrifugo.env, ...centrifugoEnvironment(options.centrifugo.environment) },\n },\n {\n name: 'proxy',\n command: options.caddy.command ?? 'caddy',\n args: ['run', '--config', configPath, '--adapter', 'caddyfile'],\n ...(options.caddy.cwd ? { cwd: options.caddy.cwd } : {}),\n env: { ...options.caddy.env, ...caddyRuntimeEnvironment(options.caddy.runtime) },\n },\n ],\n options.supervisor ?? {},\n ['proxy', 'app', 'realtime'],\n )\n}\n\nexport function centrifugoEnvironment(options: CentrifugoEnvironmentOptions): NodeJS.ProcessEnv {\n const apiKey = requiredValue(options.apiKey, 'apiKey')\n const clientTokenSecret = options.clientTokenSecret?.trim()\n const subscriptionTokenSecret = options.subscriptionTokenSecret?.trim()\n return {\n CENTRIFUGO_HTTP_API_KEY: apiKey,\n CENTRIFUGO_CLIENT_ALLOWED_ORIGINS: options.allowedOrigins?.trim() || '*',\n CENTRIFUGO_HTTP_SERVER_ADDRESS: '127.0.0.1',\n CENTRIFUGO_HEALTH_ENABLED: 'true',\n ...(clientTokenSecret ? { CENTRIFUGO_CLIENT_TOKEN_HMAC_SECRET_KEY: clientTokenSecret } : {}),\n ...(subscriptionTokenSecret\n ? {\n CENTRIFUGO_CLIENT_SUBSCRIPTION_TOKEN_ENABLED: 'true',\n CENTRIFUGO_CLIENT_SUBSCRIPTION_TOKEN_HMAC_SECRET_KEY: subscriptionTokenSecret,\n }\n : {}),\n ...(options.redisUrl\n ? { CENTRIFUGO_ENGINE_TYPE: 'redis', CENTRIFUGO_ENGINE_REDIS_ADDRESS: requiredValue(options.redisUrl, 'redisUrl') }\n : {}),\n }\n}\n\nexport type CaddyRuntimeEnvironmentOptions = { configHome?: string; dataHome?: string }\n\nexport function caddyRuntimeEnvironment(options: CaddyRuntimeEnvironmentOptions = {}): NodeJS.ProcessEnv {\n const configHome = absolutePath(options.configHome ?? '/tmp/caddy-config', 'configHome')\n const dataHome = absolutePath(options.dataHome ?? '/tmp/caddy-data', 'dataHome')\n return { XDG_CONFIG_HOME: configHome, XDG_DATA_HOME: dataHome }\n}\n\nexport type CaddyRealtimeProxyOptions = {\n publicPort?: number\n appPort?: number\n realtimePort?: number\n websocketPath?: string\n /** Compress responses with zstd and gzip. On unless turned off: Caddy already skips upgrades and incompressible content. */\n encode?: boolean\n}\n\nexport function caddyRealtimeProxy(options: CaddyRealtimeProxyOptions = {}) {\n const publicPort = port(options.publicPort ?? 3000, 'publicPort')\n const appPort = port(options.appPort ?? 3001, 'appPort')\n const realtimePort = port(options.realtimePort ?? 8000, 'realtimePort')\n const websocketPath = options.websocketPath ?? '/connection/'\n if (!/^\\/[A-Za-z0-9._~/-]+\\/$/.test(websocketPath) || websocketPath.includes('//')) {\n throw new Error('websocketPath must be a normalized absolute directory path')\n }\n return `{\n\\tservers {\n\\t\\ttrusted_proxies static private_ranges\n\\t\\ttrusted_proxies_strict\n\\t}\n}\n\n:${publicPort} {\n${options.encode === false ? '' : '\\tencode zstd gzip\\n'}\\troute {\n\\t\\t@foreignWebSocketOrigin \\`{path}.startsWith('${websocketPath}') && {http.request.header.Origin} != '' && {http.request.header.Origin} != 'http://' + {http.request.hostport} && {http.request.header.Origin} != 'https://' + {http.request.hostport}\\`\n\\t\\trespond @foreignWebSocketOrigin 403\n\n\\t\\thandle ${websocketPath}* {\n\\t\\t\\treverse_proxy 127.0.0.1:${realtimePort}\n\\t\\t}\n\n\\t\\thandle {\n\\t\\t\\treverse_proxy 127.0.0.1:${appPort}\n\\t\\t}\n\\t}\n}\n`\n}\n\nfunction requiredValue(value: string, name: string) {\n const normalized = value.trim()\n if (!normalized) throw new Error(`${name} is required`)\n return normalized\n}\n\nfunction port(value: number, name: string) {\n if (!Number.isInteger(value) || value < 1 || value > 65_535) throw new Error(`${name} must be a valid TCP port`)\n return value\n}\n\nfunction absolutePath(value: string, name: string) {\n if (!path.isAbsolute(value)) throw new Error(`${name} must be an absolute path`)\n return value\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { persistedSecret } from '../auth/secret.js'\n\nexport { runRealtimeDev, type RealtimeDevOptions } from './dev.js'\n\nexport type RuntimeProcess = {\n name: string\n command: string\n args?: readonly string[]\n cwd?: string\n env?: NodeJS.ProcessEnv\n}\n\ntype SignalSource = Pick<NodeJS.Process, 'off' | 'once'>\ntype SpawnProcess = (process: RuntimeProcess) => ChildProcess\n\nexport type SupervisorOptions = {\n shutdownTimeoutMs?: number\n signalSource?: SignalSource\n spawn?: SpawnProcess\n}\n\nexport async function superviseProcesses(processes: readonly RuntimeProcess[], options: SupervisorOptions = {}) {\n return runSupervisor(processes, options)\n}\n\nasync function runSupervisor(processes: readonly RuntimeProcess[], options: SupervisorOptions, shutdownOrder?: readonly string[]) {\n if (processes.length === 0) throw new Error('at least one runtime process is required')\n const names = new Set<string>()\n for (const process of processes) {\n if (!process.name.trim()) throw new Error('runtime process names must not be empty')\n if (!process.command.trim()) throw new Error(`runtime process ${process.name} must have a command`)\n if (names.has(process.name)) throw new Error(`duplicate runtime process name: ${process.name}`)\n names.add(process.name)\n }\n\n const signalSource = options.signalSource ?? process\n const shutdownTimeoutMs = options.shutdownTimeoutMs ?? 10_000\n if (!Number.isSafeInteger(shutdownTimeoutMs) || shutdownTimeoutMs < 0) {\n throw new Error('shutdownTimeoutMs must be a non-negative integer')\n }\n const spawnProcess =\n options.spawn ??\n ((specification: RuntimeProcess) =>\n spawn(specification.command, [...(specification.args ?? [])], {\n cwd: specification.cwd,\n env: specification.env ?? process.env,\n stdio: 'inherit',\n }))\n const children = new Map<ChildProcess, string>()\n const exits = new Map<ChildProcess, Promise<void>>()\n let settled = false\n let phasedShutdown = false\n let expectedExit: ChildProcess | undefined\n let resolveResult!: (value: number) => void\n const result = new Promise<number>((resolve) => {\n resolveResult = resolve\n })\n\n const finishImmediately = async (status: number) => {\n if (settled) return\n settled = true\n signalSource.off('SIGINT', onSignal)\n signalSource.off('SIGTERM', onSignal)\n await stopChildren([...children.keys()], shutdownTimeoutMs)\n resolveResult(status)\n }\n const finishInPhases = async () => {\n if (settled || phasedShutdown) return\n phasedShutdown = true\n signalSource.off('SIGINT', onSignal)\n signalSource.off('SIGTERM', onSignal)\n const deadline = Date.now() + shutdownTimeoutMs\n for (const name of shutdownOrder ?? []) {\n if (settled) return\n const child = [...children].find(([, childName]) => childName === name)?.[0]\n if (!child || !running(child)) continue\n expectedExit = child\n child.kill('SIGTERM')\n // oxlint-disable-next-line no-await-in-loop -- Shutdown phases must remain dependency-ordered.\n const exited = await beforeDeadline(exits.get(child)!, Math.max(0, deadline - Date.now()))\n expectedExit = undefined\n if (settled) return\n if (!exited) {\n settled = true\n for (const runningChild of children.keys()) if (running(runningChild)) runningChild.kill('SIGKILL')\n resolveResult(0)\n return\n }\n }\n settled = true\n resolveResult(0)\n }\n const onSignal = () => {\n if (shutdownOrder) void finishInPhases()\n else void finishImmediately(0)\n }\n signalSource.once('SIGINT', onSignal)\n signalSource.once('SIGTERM', onSignal)\n\n try {\n for (const specification of processes) {\n const child = spawnProcess(specification)\n children.set(child, specification.name)\n let resolveExit!: () => void\n exits.set(\n child,\n new Promise<void>((resolve) => {\n resolveExit = resolve\n }),\n )\n child.once('error', () => void finishImmediately(1))\n child.once('exit', (code) => {\n resolveExit()\n if (!phasedShutdown || child !== expectedExit) void finishImmediately(code && code > 0 ? code : 1)\n })\n }\n } catch (error) {\n await finishImmediately(1)\n throw error\n }\n return result\n}\n\nasync function beforeDeadline(exited: Promise<void>, timeoutMs: number) {\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<false>((resolve) => {\n timer = setTimeout(() => resolve(false), timeoutMs)\n })\n const result = await Promise.race([exited.then(() => true as const), timeout])\n if (timer) clearTimeout(timer)\n return result\n}\n\nfunction running(child: ChildProcess) {\n return child.exitCode === null && child.signalCode === null\n}\n\nasync function stopChildren(children: ChildProcess[], timeoutMs: number) {\n const active = children.filter(running)\n if (active.length === 0) return\n const exited = Promise.all(active.map((child) => new Promise<void>((resolve) => child.once('exit', () => resolve())))).then(\n () => 'exited' as const,\n )\n for (const child of active) child.kill('SIGTERM')\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<'timeout'>((resolve) => {\n timer = setTimeout(() => resolve('timeout'), timeoutMs)\n })\n const outcome = await Promise.race([exited, timeout])\n if (timer) clearTimeout(timer)\n if (outcome === 'timeout') {\n for (const child of active) if (running(child)) child.kill('SIGKILL')\n }\n}\n\nexport type CentrifugoEnvironmentOptions = {\n apiKey: string\n clientTokenSecret?: string\n subscriptionTokenSecret?: string\n allowedOrigins?: string\n redisUrl?: string\n}\n\nexport type RealtimeStackOptions = {\n app: Omit<RuntimeProcess, 'name'>\n centrifugo: {\n command?: string\n configPath: string\n cwd?: string\n env?: NodeJS.ProcessEnv\n environment: CentrifugoEnvironmentOptions\n }\n caddy: {\n command?: string\n configPath: string\n cwd?: string\n env?: NodeJS.ProcessEnv\n proxy?: CaddyRealtimeProxyOptions\n runtime?: CaddyRuntimeEnvironmentOptions\n }\n supervisor?: SupervisorOptions\n}\n\nexport async function runRealtimeStack(options: RealtimeStackOptions) {\n const configPath = absolutePath(options.caddy.configPath, 'caddy.configPath')\n const centrifugoConfigPath = absolutePath(options.centrifugo.configPath, 'centrifugo.configPath')\n await mkdir(path.dirname(configPath), { recursive: true })\n await writeFile(configPath, caddyRealtimeProxy(options.caddy.proxy), 'utf8')\n return runSupervisor(\n [\n { name: 'app', ...options.app },\n {\n name: 'realtime',\n command: options.centrifugo.command ?? 'centrifugo',\n args: [`--config=${centrifugoConfigPath}`],\n ...(options.centrifugo.cwd ? { cwd: options.centrifugo.cwd } : {}),\n env: { ...options.centrifugo.env, ...centrifugoEnvironment(options.centrifugo.environment) },\n },\n {\n name: 'proxy',\n command: options.caddy.command ?? 'caddy',\n args: ['run', '--config', configPath, '--adapter', 'caddyfile'],\n ...(options.caddy.cwd ? { cwd: options.caddy.cwd } : {}),\n env: { ...options.caddy.env, ...caddyRuntimeEnvironment(options.caddy.runtime) },\n },\n ],\n options.supervisor ?? {},\n ['proxy', 'app', 'realtime'],\n )\n}\n\nexport function centrifugoEnvironment(options: CentrifugoEnvironmentOptions): NodeJS.ProcessEnv {\n const apiKey = requiredValue(options.apiKey, 'apiKey')\n const clientTokenSecret = options.clientTokenSecret?.trim()\n const subscriptionTokenSecret = options.subscriptionTokenSecret?.trim()\n return {\n CENTRIFUGO_HTTP_API_KEY: apiKey,\n CENTRIFUGO_CLIENT_ALLOWED_ORIGINS: options.allowedOrigins?.trim() || '*',\n CENTRIFUGO_HTTP_SERVER_ADDRESS: '127.0.0.1',\n CENTRIFUGO_HEALTH_ENABLED: 'true',\n ...(clientTokenSecret ? { CENTRIFUGO_CLIENT_TOKEN_HMAC_SECRET_KEY: clientTokenSecret } : {}),\n ...(subscriptionTokenSecret\n ? {\n CENTRIFUGO_CLIENT_SUBSCRIPTION_TOKEN_ENABLED: 'true',\n CENTRIFUGO_CLIENT_SUBSCRIPTION_TOKEN_HMAC_SECRET_KEY: subscriptionTokenSecret,\n }\n : {}),\n ...(options.redisUrl\n ? { CENTRIFUGO_ENGINE_TYPE: 'redis', CENTRIFUGO_ENGINE_REDIS_ADDRESS: requiredValue(options.redisUrl, 'redisUrl') }\n : {}),\n }\n}\n\nexport type CaddyRuntimeEnvironmentOptions = { configHome?: string; dataHome?: string }\n\nexport function caddyRuntimeEnvironment(options: CaddyRuntimeEnvironmentOptions = {}): NodeJS.ProcessEnv {\n const configHome = absolutePath(options.configHome ?? '/tmp/caddy-config', 'configHome')\n const dataHome = absolutePath(options.dataHome ?? '/tmp/caddy-data', 'dataHome')\n return { XDG_CONFIG_HOME: configHome, XDG_DATA_HOME: dataHome }\n}\n\nexport type CaddyRealtimeProxyOptions = {\n publicPort?: number\n appPort?: number\n realtimePort?: number\n websocketPath?: string\n /** Compress responses with zstd and gzip. On unless turned off: Caddy already skips upgrades and incompressible content. */\n encode?: boolean\n}\n\nexport function caddyRealtimeProxy(options: CaddyRealtimeProxyOptions = {}) {\n const publicPort = port(options.publicPort ?? 3000, 'publicPort')\n const appPort = port(options.appPort ?? 3001, 'appPort')\n const realtimePort = port(options.realtimePort ?? 8000, 'realtimePort')\n const websocketPath = options.websocketPath ?? '/connection/'\n if (!/^\\/[A-Za-z0-9._~/-]+\\/$/.test(websocketPath) || websocketPath.includes('//')) {\n throw new Error('websocketPath must be a normalized absolute directory path')\n }\n return `{\n\\tservers {\n\\t\\ttrusted_proxies static private_ranges\n\\t\\ttrusted_proxies_strict\n\\t}\n}\n\n:${publicPort} {\n${options.encode === false ? '' : '\\tencode zstd gzip\\n'}\\troute {\n\\t\\t@foreignWebSocketOrigin \\`{path}.startsWith('${websocketPath}') && {http.request.header.Origin} != '' && {http.request.header.Origin} != 'http://' + {http.request.hostport} && {http.request.header.Origin} != 'https://' + {http.request.hostport}\\`\n\\t\\trespond @foreignWebSocketOrigin 403\n\n\\t\\thandle ${websocketPath}* {\n\\t\\t\\treverse_proxy 127.0.0.1:${realtimePort}\n\\t\\t}\n\n\\t\\thandle {\n\\t\\t\\treverse_proxy 127.0.0.1:${appPort}\n\\t\\t}\n\\t}\n}\n`\n}\n\nfunction requiredValue(value: string, name: string) {\n const normalized = value.trim()\n if (!normalized) throw new Error(`${name} is required`)\n return normalized\n}\n\nfunction port(value: number, name: string) {\n if (!Number.isInteger(value) || value < 1 || value > 65_535) throw new Error(`${name} must be a valid TCP port`)\n return value\n}\n\nfunction absolutePath(value: string, name: string) {\n if (!path.isAbsolute(value)) throw new Error(`${name} must be an absolute path`)\n return value\n}\n\nexport type PersistedRealtimeSecretOptions = { prefix?: string; defaultFile?: string }\n\n// The secret lands back in the environment so the supervised application inherits the value Centrifugo was given.\nexport function persistedRealtimeSecret(environment: NodeJS.ProcessEnv = process.env, options: PersistedRealtimeSecretOptions = {}) {\n const prefix = options.prefix ?? ''\n const file = environment[`${prefix}REALTIME_SECRET_FILE`]?.trim() || options.defaultFile || '/data/realtime-secret'\n const secret = persistedSecret({\n directory: path.dirname(file),\n filename: path.basename(file),\n environment,\n environmentKey: `${prefix}REALTIME_SECRET`,\n bytes: 48,\n })\n environment[`${prefix}REALTIME_SECRET`] = secret\n return secret\n}\n"]}
@@ -7,5 +7,5 @@ export type { HealthResponseOptions } from './health.js';
7
7
  export { createRateLimit, forwardedClientAddress, memoryRateLimitStore, rateLimitTable } from './rate-limit.js';
8
8
  export type { RateLimitCounter, RateLimitDecision, RateLimitOptions, RateLimitStore } from './rate-limit.js';
9
9
  export { createRpc } from './rpc.js';
10
- export type { RpcErrorContext, RpcLogger, RpcOptions } from './rpc.js';
10
+ export type { RpcErrorContext, RpcLogger, RpcObserver, RpcOptions } from './rpc.js';
11
11
  export { clearGlobalSingleton, globalAsyncSingleton, globalSingleton, peekGlobalSingleton } from './singleton.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEvD,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAEzI,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEnE,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAE/G,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEpC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA","sourcesContent":["export { canonicalRedirect } from './canonical-host.js'\nexport type { CanonicalRedirectOptions } from './canonical-host.js'\nexport { errorHasCode, infrastructureDiagnostic, infrastructureFailure, InfrastructureError, safeInfrastructureError } from './errors.js'\nexport type { InfrastructureFailure } from './errors.js'\nexport { databaseHealthFailure, healthResponse } from './health.js'\nexport type { HealthResponseOptions } from './health.js'\nexport { createRateLimit, forwardedClientAddress, memoryRateLimitStore, rateLimitTable } from './rate-limit.js'\nexport type { RateLimitCounter, RateLimitDecision, RateLimitOptions, RateLimitStore } from './rate-limit.js'\nexport { createRpc } from './rpc.js'\nexport type { RpcErrorContext, RpcLogger, RpcOptions } from './rpc.js'\nexport { clearGlobalSingleton, globalAsyncSingleton, globalSingleton, peekGlobalSingleton } from './singleton.js'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEvD,OAAO,EAAE,YAAY,EAAE,wBAAwB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAEzI,OAAO,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEnE,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAE/G,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEpC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA","sourcesContent":["export { canonicalRedirect } from './canonical-host.js'\nexport type { CanonicalRedirectOptions } from './canonical-host.js'\nexport { errorHasCode, infrastructureDiagnostic, infrastructureFailure, InfrastructureError, safeInfrastructureError } from './errors.js'\nexport type { InfrastructureFailure } from './errors.js'\nexport { databaseHealthFailure, healthResponse } from './health.js'\nexport type { HealthResponseOptions } from './health.js'\nexport { createRateLimit, forwardedClientAddress, memoryRateLimitStore, rateLimitTable } from './rate-limit.js'\nexport type { RateLimitCounter, RateLimitDecision, RateLimitOptions, RateLimitStore } from './rate-limit.js'\nexport { createRpc } from './rpc.js'\nexport type { RpcErrorContext, RpcLogger, RpcObserver, RpcOptions } from './rpc.js'\nexport { clearGlobalSingleton, globalAsyncSingleton, globalSingleton, peekGlobalSingleton } from './singleton.js'\n"]}
@@ -3,10 +3,12 @@ export type RpcErrorContext = {
3
3
  path?: string;
4
4
  };
5
5
  export type RpcLogger = (error: unknown, context: RpcErrorContext, request?: Request) => void | Promise<void>;
6
+ export type RpcObserver = <T>(request: Request | undefined, work: () => Promise<T>) => Promise<T>;
6
7
  export type RpcOptions = {
7
8
  getRequest?: () => Request;
8
9
  requireMutation?: (request: Request) => void;
9
10
  logError?: RpcLogger;
11
+ observe?: RpcObserver;
10
12
  };
11
13
  export declare function createRpc(options?: RpcOptions): {
12
14
  rpc: <T>(work: () => Promise<T> | T) => Promise<T>;
@@ -1,26 +1,31 @@
1
1
  export function createRpc(options = {}) {
2
2
  async function rpc(work) {
3
- try {
4
- return await work();
5
- }
6
- catch (error) {
7
- if (error instanceof Response)
8
- throw new Error((await error.text()) || `request failed (${error.status})`, { cause: error });
9
- const request = resolveRequest(options.getRequest);
3
+ return run(work, resolveRequest(options.getRequest));
4
+ }
5
+ async function run(work, request) {
6
+ const execute = async () => {
10
7
  try {
11
- await options.logError?.(error, requestContext(request), request);
8
+ return await work();
9
+ }
10
+ catch (error) {
11
+ if (error instanceof Response)
12
+ throw new Error((await error.text()) || `request failed (${error.status})`, { cause: error });
13
+ try {
14
+ await options.logError?.(error, requestContext(request), request);
15
+ }
16
+ catch { }
17
+ throw error;
12
18
  }
13
- catch { }
14
- throw error;
15
- }
19
+ };
20
+ return options.observe ? options.observe(request, execute) : execute();
16
21
  }
17
- function mutationRpc(work, request = options.getRequest?.()) {
18
- return rpc(() => {
22
+ function mutationRpc(work, request = resolveRequest(options.getRequest)) {
23
+ return run(() => {
19
24
  if (!request)
20
25
  throw new Error('mutation request is unavailable');
21
26
  options.requireMutation?.(request);
22
27
  return work();
23
- });
28
+ }, request);
24
29
  }
25
30
  return { rpc, mutationRpc };
26
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/server/rpc.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,SAAS,CAAC,OAAO,GAAe,EAAE;IAChD,KAAK,UAAU,GAAG,CAAI,IAA0B;QAC9C,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,EAAE,CAAA;QACrB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,mBAAmB,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;YAC5H,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;YAClD,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAA;YACnE,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC;IAED,SAAS,WAAW,CAAI,IAA0B,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,EAAE;QAClF,OAAO,GAAG,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;YAChE,OAAO,CAAC,eAAe,EAAE,CAAC,OAAO,CAAC,CAAA;YAClC,OAAO,IAAI,EAAE,CAAA;QACf,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,CAAA;AAC7B,CAAC;AAED,SAAS,cAAc,CAAC,UAAuC;IAC7D,IAAI,CAAC;QACH,OAAO,UAAU,EAAE,EAAE,CAAA;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,OAA4B;IAClD,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AACvF,CAAC","sourcesContent":["export type RpcErrorContext = { method?: string; path?: string }\nexport type RpcLogger = (error: unknown, context: RpcErrorContext, request?: Request) => void | Promise<void>\n\nexport type RpcOptions = {\n getRequest?: () => Request\n requireMutation?: (request: Request) => void\n logError?: RpcLogger\n}\n\nexport function createRpc(options: RpcOptions = {}) {\n async function rpc<T>(work: () => Promise<T> | T): Promise<T> {\n try {\n return await work()\n } catch (error) {\n if (error instanceof Response) throw new Error((await error.text()) || `request failed (${error.status})`, { cause: error })\n const request = resolveRequest(options.getRequest)\n try {\n await options.logError?.(error, requestContext(request), request)\n } catch {}\n throw error\n }\n }\n\n function mutationRpc<T>(work: () => Promise<T> | T, request = options.getRequest?.()) {\n return rpc(() => {\n if (!request) throw new Error('mutation request is unavailable')\n options.requireMutation?.(request)\n return work()\n })\n }\n\n return { rpc, mutationRpc }\n}\n\nfunction resolveRequest(getRequest: (() => Request) | undefined) {\n try {\n return getRequest?.()\n } catch {\n return undefined\n }\n}\n\nfunction requestContext(request: Request | undefined): RpcErrorContext {\n return request ? { method: request.method, path: new URL(request.url).pathname } : {}\n}\n"]}
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/server/rpc.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,SAAS,CAAC,OAAO,GAAe,EAAE;IAChD,KAAK,UAAU,GAAG,CAAI,IAA0B;QAC9C,OAAO,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAA;IACtD,CAAC;IAED,KAAK,UAAU,GAAG,CAAI,IAA0B,EAAE,OAA4B;QAC5E,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;YACzB,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,EAAE,CAAA;YACrB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,QAAQ;oBAAE,MAAM,IAAI,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,mBAAmB,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;gBAC5H,IAAI,CAAC;oBACH,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAA;gBACnE,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;gBACV,MAAM,KAAK,CAAA;YACb,CAAC;QACH,CAAC,CAAA;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA;IACxE,CAAC;IAED,SAAS,WAAW,CAAI,IAA0B,EAAE,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC;QAC9F,OAAO,GAAG,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;YAChE,OAAO,CAAC,eAAe,EAAE,CAAC,OAAO,CAAC,CAAA;YAClC,OAAO,IAAI,EAAE,CAAA;QACf,CAAC,EAAE,OAAO,CAAC,CAAA;IACb,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,CAAA;AAC7B,CAAC;AAED,SAAS,cAAc,CAAC,UAAuC;IAC7D,IAAI,CAAC;QACH,OAAO,UAAU,EAAE,EAAE,CAAA;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,OAA4B;IAClD,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AACvF,CAAC","sourcesContent":["export type RpcErrorContext = { method?: string; path?: string }\nexport type RpcLogger = (error: unknown, context: RpcErrorContext, request?: Request) => void | Promise<void>\nexport type RpcObserver = <T>(request: Request | undefined, work: () => Promise<T>) => Promise<T>\n\nexport type RpcOptions = {\n getRequest?: () => Request\n requireMutation?: (request: Request) => void\n logError?: RpcLogger\n observe?: RpcObserver\n}\n\nexport function createRpc(options: RpcOptions = {}) {\n async function rpc<T>(work: () => Promise<T> | T): Promise<T> {\n return run(work, resolveRequest(options.getRequest))\n }\n\n async function run<T>(work: () => Promise<T> | T, request: Request | undefined): Promise<T> {\n const execute = async () => {\n try {\n return await work()\n } catch (error) {\n if (error instanceof Response) throw new Error((await error.text()) || `request failed (${error.status})`, { cause: error })\n try {\n await options.logError?.(error, requestContext(request), request)\n } catch {}\n throw error\n }\n }\n return options.observe ? options.observe(request, execute) : execute()\n }\n\n function mutationRpc<T>(work: () => Promise<T> | T, request = resolveRequest(options.getRequest)) {\n return run(() => {\n if (!request) throw new Error('mutation request is unavailable')\n options.requireMutation?.(request)\n return work()\n }, request)\n }\n\n return { rpc, mutationRpc }\n}\n\nfunction resolveRequest(getRequest: (() => Request) | undefined) {\n try {\n return getRequest?.()\n } catch {\n return undefined\n }\n}\n\nfunction requestContext(request: Request | undefined): RpcErrorContext {\n return request ? { method: request.method, path: new URL(request.url).pathname } : {}\n}\n"]}
@@ -20,9 +20,14 @@ export type TusUploadResult = {
20
20
  responseStatus: number | undefined;
21
21
  uploadUrl: string | null;
22
22
  };
23
+ export type TusUploadStartOptions = {
24
+ resume?: boolean;
25
+ signal?: AbortSignal;
26
+ terminateOnAbort?: boolean;
27
+ };
23
28
  export declare function createTusUpload(options: TusUploadOptions): Upload;
24
- export declare function startTusUpload(upload: Upload, resume?: boolean): Promise<TusUploadResult>;
25
- export declare function uploadWithTus(options: TusUploadOptions, resume?: boolean): Promise<TusUploadResult>;
29
+ export declare function startTusUpload(upload: Upload, options?: boolean | TusUploadStartOptions): Promise<TusUploadResult>;
30
+ export declare function uploadWithTus(options: TusUploadOptions, startOptions?: boolean | TusUploadStartOptions): Promise<TusUploadResult>;
26
31
  export declare function tusResponseMessage(error: unknown): string | undefined;
27
32
  export declare function tusResponse(error: unknown): {
28
33
  status: number | undefined;
@@ -16,41 +16,69 @@ export function createTusUpload(options) {
16
16
  onProgress: (sent, total) => options.onProgress?.({ sent, total, percent: total ? Math.round((sent / total) * 100) : 0 }),
17
17
  });
18
18
  }
19
- export async function startTusUpload(upload, resume = true) {
20
- if (resume) {
21
- const previous = await upload.findPreviousUploads();
22
- if (previous[0])
23
- upload.resumeFromPreviousUpload(previous[0]);
19
+ export async function startTusUpload(upload, options = true) {
20
+ const { resume = true, signal, terminateOnAbort = false } = typeof options === 'boolean' ? { resume: options } : options;
21
+ if (signal?.aborted)
22
+ throw tusAbortError();
23
+ let rejectAbort;
24
+ const aborted = signal
25
+ ? new Promise((_resolve, reject) => {
26
+ rejectAbort = reject;
27
+ })
28
+ : undefined;
29
+ const abort = () => {
30
+ rejectAbort?.(tusAbortError());
31
+ // Remote termination is best-effort after local cancellation has settled for the caller.
32
+ void Promise.resolve()
33
+ .then(() => upload.abort(terminateOnAbort))
34
+ .catch(() => undefined);
35
+ };
36
+ signal?.addEventListener('abort', abort, { once: true });
37
+ const run = async () => {
38
+ if (resume) {
39
+ const previous = await upload.findPreviousUploads();
40
+ if (signal?.aborted)
41
+ throw tusAbortError();
42
+ if (previous[0])
43
+ upload.resumeFromPreviousUpload(previous[0]);
44
+ }
45
+ return new Promise((resolve, reject) => {
46
+ const previousError = upload.options.onError;
47
+ const previousSuccess = upload.options.onSuccess;
48
+ upload.options.onError = (error) => {
49
+ try {
50
+ previousError?.(error);
51
+ }
52
+ finally {
53
+ reject(error);
54
+ }
55
+ };
56
+ upload.options.onSuccess = (event) => {
57
+ try {
58
+ previousSuccess?.(event);
59
+ resolve({
60
+ responseBody: event.lastResponse.getBody(),
61
+ responseStatus: event.lastResponse.getStatus(),
62
+ uploadUrl: upload.url,
63
+ });
64
+ }
65
+ catch (error) {
66
+ reject(error);
67
+ }
68
+ };
69
+ upload.start();
70
+ });
71
+ };
72
+ try {
73
+ const result = run();
74
+ return await (aborted ? Promise.race([result, aborted]) : result);
75
+ }
76
+ finally {
77
+ signal?.removeEventListener('abort', abort);
24
78
  }
25
- return new Promise((resolve, reject) => {
26
- const previousError = upload.options.onError;
27
- const previousSuccess = upload.options.onSuccess;
28
- upload.options.onError = (error) => {
29
- try {
30
- previousError?.(error);
31
- }
32
- finally {
33
- reject(error);
34
- }
35
- };
36
- upload.options.onSuccess = (event) => {
37
- try {
38
- previousSuccess?.(event);
39
- resolve({
40
- responseBody: event.lastResponse.getBody(),
41
- responseStatus: event.lastResponse.getStatus(),
42
- uploadUrl: upload.url,
43
- });
44
- }
45
- catch (error) {
46
- reject(error);
47
- }
48
- };
49
- upload.start();
50
- });
51
79
  }
52
- export function uploadWithTus(options, resume = true) {
53
- return startTusUpload(createTusUpload(options), resume);
80
+ export function uploadWithTus(options, startOptions = true) {
81
+ return startTusUpload(createTusUpload(options), startOptions);
54
82
  }
55
83
  export function tusResponseMessage(error) {
56
84
  const response = responseFromError(error);
@@ -74,4 +102,7 @@ function responseFromError(error) {
74
102
  const body = response.getBody();
75
103
  return { status: typeof status === 'number' ? status : undefined, body: typeof body === 'string' ? body : '' };
76
104
  }
105
+ function tusAbortError() {
106
+ return new DOMException('Upload cancelled', 'AbortError');
107
+ }
77
108
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/uploads/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { defaultOptions, Upload, type UploadOptions } from 'tus-js-client'\n\nexport type TusUploadProgress = { sent: number; total: number; percent: number }\n\nexport type TusUploadOptions = {\n endpoint: string\n file: File\n metadata: Record<string, string>\n chunkSize?: number\n retryDelays?: readonly number[]\n fingerprint?: UploadOptions['fingerprint']\n removeFingerprintOnSuccess?: boolean\n shouldRetry?: (status: number | undefined, retryAttempt: number) => boolean\n onProgress?: (progress: TusUploadProgress) => void\n}\n\nexport type TusUploadResult = {\n responseBody: string\n responseStatus: number | undefined\n uploadUrl: string | null\n}\n\nexport function createTusUpload(options: TusUploadOptions) {\n return new Upload(options.file, {\n endpoint: options.endpoint,\n metadata: options.metadata,\n retryDelays: [...(options.retryDelays ?? [0, 1_000, 3_000, 5_000])],\n ...(options.chunkSize === undefined ? {} : { chunkSize: options.chunkSize }),\n ...(options.fingerprint === undefined ? {} : { fingerprint: options.fingerprint }),\n ...(options.removeFingerprintOnSuccess === undefined ? {} : { removeFingerprintOnSuccess: options.removeFingerprintOnSuccess }),\n onShouldRetry: (error, retryAttempt, uploadOptions) => {\n const status = error.originalResponse?.getStatus()\n if (options.shouldRetry && !options.shouldRetry(status, retryAttempt)) return false\n return defaultOptions.onShouldRetry?.(error, retryAttempt, uploadOptions) === true\n },\n onProgress: (sent, total) => options.onProgress?.({ sent, total, percent: total ? Math.round((sent / total) * 100) : 0 }),\n })\n}\n\nexport async function startTusUpload(upload: Upload, resume = true): Promise<TusUploadResult> {\n if (resume) {\n const previous = await upload.findPreviousUploads()\n if (previous[0]) upload.resumeFromPreviousUpload(previous[0])\n }\n\n return new Promise((resolve, reject) => {\n const previousError = upload.options.onError\n const previousSuccess = upload.options.onSuccess\n upload.options.onError = (error) => {\n try {\n previousError?.(error)\n } finally {\n reject(error)\n }\n }\n upload.options.onSuccess = (event) => {\n try {\n previousSuccess?.(event)\n resolve({\n responseBody: event.lastResponse.getBody(),\n responseStatus: event.lastResponse.getStatus(),\n uploadUrl: upload.url,\n })\n } catch (error) {\n reject(error)\n }\n }\n upload.start()\n })\n}\n\nexport function uploadWithTus(options: TusUploadOptions, resume = true) {\n return startTusUpload(createTusUpload(options), resume)\n}\n\nexport function tusResponseMessage(error: unknown) {\n const response = responseFromError(error)\n if (response) return response.body\n const message = error instanceof Error ? error.message : undefined\n return message ? /response text: ([^,]+)/.exec(message)?.[1]?.trim() : undefined\n}\n\nexport function tusResponse(error: unknown) {\n return responseFromError(error)\n}\n\nfunction responseFromError(error: unknown) {\n if (!error || typeof error !== 'object' || !('originalResponse' in error)) return undefined\n const response = error.originalResponse\n if (!response || typeof response !== 'object' || !('getStatus' in response) || !('getBody' in response)) return undefined\n if (typeof response.getStatus !== 'function' || typeof response.getBody !== 'function') return undefined\n const status: unknown = response.getStatus()\n const body: unknown = response.getBody()\n return { status: typeof status === 'number' ? status : undefined, body: typeof body === 'string' ? body : '' }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/uploads/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { defaultOptions, Upload, type UploadOptions } from 'tus-js-client'\n\nexport type TusUploadProgress = { sent: number; total: number; percent: number }\n\nexport type TusUploadOptions = {\n endpoint: string\n file: File\n metadata: Record<string, string>\n chunkSize?: number\n retryDelays?: readonly number[]\n fingerprint?: UploadOptions['fingerprint']\n removeFingerprintOnSuccess?: boolean\n shouldRetry?: (status: number | undefined, retryAttempt: number) => boolean\n onProgress?: (progress: TusUploadProgress) => void\n}\n\nexport type TusUploadResult = {\n responseBody: string\n responseStatus: number | undefined\n uploadUrl: string | null\n}\n\nexport type TusUploadStartOptions = {\n resume?: boolean\n signal?: AbortSignal\n terminateOnAbort?: boolean\n}\n\nexport function createTusUpload(options: TusUploadOptions) {\n return new Upload(options.file, {\n endpoint: options.endpoint,\n metadata: options.metadata,\n retryDelays: [...(options.retryDelays ?? [0, 1_000, 3_000, 5_000])],\n ...(options.chunkSize === undefined ? {} : { chunkSize: options.chunkSize }),\n ...(options.fingerprint === undefined ? {} : { fingerprint: options.fingerprint }),\n ...(options.removeFingerprintOnSuccess === undefined ? {} : { removeFingerprintOnSuccess: options.removeFingerprintOnSuccess }),\n onShouldRetry: (error, retryAttempt, uploadOptions) => {\n const status = error.originalResponse?.getStatus()\n if (options.shouldRetry && !options.shouldRetry(status, retryAttempt)) return false\n return defaultOptions.onShouldRetry?.(error, retryAttempt, uploadOptions) === true\n },\n onProgress: (sent, total) => options.onProgress?.({ sent, total, percent: total ? Math.round((sent / total) * 100) : 0 }),\n })\n}\n\nexport async function startTusUpload(upload: Upload, options: boolean | TusUploadStartOptions = true): Promise<TusUploadResult> {\n const { resume = true, signal, terminateOnAbort = false } = typeof options === 'boolean' ? { resume: options } : options\n if (signal?.aborted) throw tusAbortError()\n let rejectAbort: ((reason: unknown) => void) | undefined\n const aborted = signal\n ? new Promise<never>((_resolve, reject) => {\n rejectAbort = reject\n })\n : undefined\n const abort = () => {\n rejectAbort?.(tusAbortError())\n // Remote termination is best-effort after local cancellation has settled for the caller.\n void Promise.resolve()\n .then(() => upload.abort(terminateOnAbort))\n .catch(() => undefined)\n }\n signal?.addEventListener('abort', abort, { once: true })\n\n const run = async () => {\n if (resume) {\n const previous = await upload.findPreviousUploads()\n if (signal?.aborted) throw tusAbortError()\n if (previous[0]) upload.resumeFromPreviousUpload(previous[0])\n }\n\n return new Promise<TusUploadResult>((resolve, reject) => {\n const previousError = upload.options.onError\n const previousSuccess = upload.options.onSuccess\n upload.options.onError = (error) => {\n try {\n previousError?.(error)\n } finally {\n reject(error)\n }\n }\n upload.options.onSuccess = (event) => {\n try {\n previousSuccess?.(event)\n resolve({\n responseBody: event.lastResponse.getBody(),\n responseStatus: event.lastResponse.getStatus(),\n uploadUrl: upload.url,\n })\n } catch (error) {\n reject(error)\n }\n }\n upload.start()\n })\n }\n\n try {\n const result = run()\n return await (aborted ? Promise.race([result, aborted]) : result)\n } finally {\n signal?.removeEventListener('abort', abort)\n }\n}\n\nexport function uploadWithTus(options: TusUploadOptions, startOptions: boolean | TusUploadStartOptions = true) {\n return startTusUpload(createTusUpload(options), startOptions)\n}\n\nexport function tusResponseMessage(error: unknown) {\n const response = responseFromError(error)\n if (response) return response.body\n const message = error instanceof Error ? error.message : undefined\n return message ? /response text: ([^,]+)/.exec(message)?.[1]?.trim() : undefined\n}\n\nexport function tusResponse(error: unknown) {\n return responseFromError(error)\n}\n\nfunction responseFromError(error: unknown) {\n if (!error || typeof error !== 'object' || !('originalResponse' in error)) return undefined\n const response = error.originalResponse\n if (!response || typeof response !== 'object' || !('getStatus' in response) || !('getBody' in response)) return undefined\n if (typeof response.getStatus !== 'function' || typeof response.getBody !== 'function') return undefined\n const status: unknown = response.getStatus()\n const body: unknown = response.getBody()\n return { status: typeof status === 'number' ? status : undefined, body: typeof body === 'string' ? body : '' }\n}\n\nfunction tusAbortError() {\n return new DOMException('Upload cancelled', 'AbortError')\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ras-stack",
3
- "version": "1.1.1",
3
+ "version": "2.0.1",
4
4
  "description": "Composable full-stack primitives shared across Richard Solomou's applications.",
5
5
  "keywords": [
6
6
  "authentication",
@@ -143,14 +143,18 @@
143
143
  "./config/typescript/bundler": "./config/typescript/bundler.json",
144
144
  "./config/typescript/library": "./config/typescript/library.json",
145
145
  "./config/typescript/node-bundler": "./config/typescript/node-bundler.json",
146
- "./config/typescript/tanstack": "./config/typescript/tanstack.json"
146
+ "./config/typescript/tanstack": "./config/typescript/tanstack.json",
147
+ "./config/oxlint/domain": "./config/oxlint/domain.json",
148
+ "./config/oxlint/layers": "./config/oxlint/layers.json"
147
149
  },
148
150
  "publishConfig": {
149
151
  "access": "public"
150
152
  },
151
153
  "dependencies": {
154
+ "@changesets/parse": "1.0.0",
152
155
  "@inquirer/confirm": "^6.1.1",
153
156
  "@inquirer/select": "^5.2.1",
157
+ "@manypkg/get-packages": "3.1.0",
154
158
  "yaml": "^2.8.2"
155
159
  },
156
160
  "devDependencies": {