ras-stack 0.42.0 → 0.42.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.
package/dist/preview/dokploy.js
CHANGED
|
@@ -88,9 +88,9 @@ export class DokployClient {
|
|
|
88
88
|
return (await this.applications()).find((application) => application.name === name);
|
|
89
89
|
}
|
|
90
90
|
async generatedDomain(appName, serverId, existing = []) {
|
|
91
|
-
const serverIp =
|
|
92
|
-
query: { serverId
|
|
93
|
-
|
|
91
|
+
const serverIp = serverId
|
|
92
|
+
? await this.api('domain.canGenerateTraefikMeDomains', { query: { serverId } })
|
|
93
|
+
: await this.api('settings.getIp');
|
|
94
94
|
const publicIp = previewServerIp(serverIp);
|
|
95
95
|
const current = existing.find((host) => isCurrentGeneratedPreviewHostname(host, appName, publicIp));
|
|
96
96
|
if (current)
|
|
@@ -129,14 +129,12 @@ export class DokployPreviewManager {
|
|
|
129
129
|
throw new Error(`Dokploy did not report ${name} after creating it`);
|
|
130
130
|
}
|
|
131
131
|
const applicationId = application.applicationId;
|
|
132
|
-
const details = await this.options.client.api('application.one', {
|
|
133
|
-
query: { applicationId },
|
|
134
|
-
});
|
|
132
|
+
const details = await this.options.client.api('application.one', { query: { applicationId } });
|
|
135
133
|
const generated = !this.options.hostname;
|
|
136
134
|
const managedDomains = details?.domains?.filter((domain) => isGeneratedPreviewHostname(domain.host, generatedPreviewName)) ?? [];
|
|
137
135
|
const host = previewHostname(this.options.hostname
|
|
138
136
|
? this.options.hostname(prNumber)
|
|
139
|
-
: await this.options.client.generatedDomain(generatedPreviewName, application.serverId ?? undefined, managedDomains.map((domain) => domain.host)));
|
|
137
|
+
: await this.options.client.generatedDomain(generatedPreviewName, details?.serverId ?? application.serverId ?? undefined, managedDomains.map((domain) => domain.host)));
|
|
140
138
|
const url = `${generated ? 'http' : 'https'}://${host}`;
|
|
141
139
|
if (!details?.domains?.some((domain) => domain.host === host)) {
|
|
142
140
|
await this.options.client.api('domain.create', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dokploy.js","sourceRoot":"","sources":["../../src/preview/dokploy.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync } from 'node:fs'\nimport { BlockList, isIP } from 'node:net'\n\nexport type DokployApplication = { applicationId: string; name: string; serverId?: string | null }\n\nexport function dokployPreviewFromEnvironment(environment: NodeJS.ProcessEnv = process.env) {\n const githubOutput = optionalEnvironment(environment, 'GITHUB_OUTPUT')\n const username = optionalEnvironment(environment, 'PREVIEW_REGISTRY_USERNAME')\n const password = optionalEnvironment(environment, 'PREVIEW_REGISTRY_PASSWORD')\n if (Boolean(username) !== Boolean(password)) throw new Error('preview registry username and password must be configured together')\n const port = Number(requiredEnvironment(environment, 'PREVIEW_PORT'))\n if (!Number.isInteger(port) || port < 1 || port > 65_535) throw new Error('PREVIEW_PORT must be a valid port')\n const applicationPrefix = requiredEnvironment(environment, 'PREVIEW_APPLICATION_PREFIX')\n if (!/^[a-z\\d](?:[a-z\\d-]*[a-z\\d])?$/.test(applicationPrefix)) throw new Error('PREVIEW_APPLICATION_PREFIX must be a slug')\n const domain = optionalEnvironment(environment, 'PREVIEW_DOMAIN')\n if (domain) previewHostname(`pr-1.${domain}`)\n const config = {\n url: requiredEnvironment(environment, 'DOKPLOY_URL'),\n apiKey: requiredEnvironment(environment, 'DOKPLOY_API_KEY'),\n environmentId: requiredEnvironment(environment, 'DOKPLOY_ENVIRONMENT_ID'),\n applicationPrefix,\n domain,\n port,\n healthPath: optionalEnvironment(environment, 'PREVIEW_HEALTH_PATH'),\n ...(username && password ? { registry: { username, password } } : {}),\n }\n const client = new DokployClient(config)\n return {\n config,\n manager: new DokployPreviewManager({\n client,\n applicationName: (prNumber) => `${applicationPrefix}-pr-${prNumber}`,\n ...(domain ? { hostname: (prNumber: string) => `pr-${prNumber}.${domain}` } : {}),\n port,\n ...(config.healthPath ? { healthPath: config.healthPath } : {}),\n ...(githubOutput ? { onResolved: ({ url }: { url: string }) => appendFileSync(githubOutput, `preview-url=${url}\\n`) } : {}),\n }),\n }\n}\n\nexport type DokployClientOptions = {\n url: string\n apiKey: string\n environmentId: string\n fetch?: typeof fetch\n log?: (message: string) => void\n}\n\nexport class DokployClient {\n private readonly request: typeof fetch\n private readonly log: (message: string) => void\n\n constructor(private readonly options: DokployClientOptions) {\n this.request = options.fetch ?? fetch\n this.log = options.log ?? console.log\n }\n\n get environmentId() {\n return this.options.environmentId\n }\n\n async api<T = unknown>(\n procedure: string,\n options: { query?: Record<string, string>; body?: unknown; signal?: AbortSignal } = {},\n ): Promise<T> {\n const url = new URL(`${this.options.url.replace(/\\/$/, '')}/api/${procedure}`)\n for (const [key, value] of Object.entries(options.query ?? {})) url.searchParams.set(key, value)\n this.log(`→ ${procedure}`)\n const response = await this.request(url, {\n method: options.body === undefined ? 'GET' : 'POST',\n headers: {\n 'x-api-key': this.options.apiKey,\n ...(options.body === undefined ? {} : { 'content-type': 'application/json' }),\n },\n ...(options.signal ? { signal: options.signal } : {}),\n ...(options.body === undefined ? {} : { body: JSON.stringify(options.body) }),\n })\n const text = await response.text()\n if (!response.ok) throw new Error(`${procedure} failed with ${response.status}: ${text.slice(0, 500)}`)\n if (!text) return undefined as T\n try {\n return JSON.parse(text) as T\n } catch {\n throw new Error(`${procedure} returned ${response.status} with a non-JSON body: ${text.slice(0, 200)}`)\n }\n }\n\n async applications() {\n const environment = await this.api<{ applications?: DokployApplication[] } | undefined>('environment.one', {\n query: { environmentId: this.options.environmentId },\n })\n if (!environment) throw new Error('environment.one returned an empty response')\n return environment.applications ?? []\n }\n\n async application(name: string) {\n return (await this.applications()).find((application) => application.name === name)\n }\n\n async generatedDomain(appName: string, serverId?: string, existing: string[] = []) {\n const serverIp = await this.api('domain.canGenerateTraefikMeDomains', {\n query: { serverId: serverId ?? '' },\n })\n const publicIp = previewServerIp(serverIp)\n const current = existing.find((host) => isCurrentGeneratedPreviewHostname(host, appName, publicIp))\n if (current) return current\n const generated = await this.api('domain.generateDomain', {\n body: { appName, ...(serverId ? { serverId } : {}) },\n })\n if (typeof generated !== 'string') throw new Error('domain.generateDomain returned an invalid hostname')\n return generatedPreviewHostname(generated, publicIp, appName)\n }\n}\n\nexport type DokployPreviewOptions = {\n client: DokployClient\n applicationName: (prNumber: string) => string\n hostname?: (prNumber: string) => string\n port: number\n healthPath?: string\n deploymentTimeoutMs?: number\n healthTimeoutMs?: number\n pollIntervalMs?: number\n fetch?: typeof fetch\n sleep?: (milliseconds: number) => Promise<void>\n now?: () => number\n log?: (message: string) => void\n onResolved?: (context: { host: string; url: string }) => void | Promise<void>\n}\n\nexport type DeployPreviewOptions = {\n prNumber: string\n image: string\n environment: string | ((context: { host: string; url: string }) => string)\n registry?: { username: string; password: string }\n configure?: (context: { applicationId: string; client: DokployClient; host: string; url: string }) => void | Promise<void>\n}\n\nexport class DokployPreviewManager {\n private readonly request: typeof fetch\n private readonly pause: (milliseconds: number) => Promise<void>\n private readonly log: (message: string) => void\n private readonly now: () => number\n\n constructor(private readonly options: DokployPreviewOptions) {\n this.request = options.fetch ?? fetch\n this.pause = options.sleep ?? ((milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)))\n this.log = options.log ?? console.log\n this.now = options.now ?? Date.now\n }\n\n async deploy(options: DeployPreviewOptions) {\n const prNumber = pullRequestNumber(options.prNumber)\n const name = this.options.applicationName(prNumber)\n let application = await this.options.client.application(name)\n if (!application) {\n await this.options.client.api('application.create', {\n body: { name, appName: name, environmentId: this.options.client.environmentId },\n })\n application = await this.options.client.application(name)\n if (!application) throw new Error(`Dokploy did not report ${name} after creating it`)\n }\n const applicationId = application.applicationId\n const details = await this.options.client.api<{ domains?: { domainId?: string; host: string }[] } | undefined>('application.one', {\n query: { applicationId },\n })\n const generated = !this.options.hostname\n const managedDomains = details?.domains?.filter((domain) => isGeneratedPreviewHostname(domain.host, generatedPreviewName)) ?? []\n const host = previewHostname(\n this.options.hostname\n ? this.options.hostname(prNumber)\n : await this.options.client.generatedDomain(\n generatedPreviewName,\n application.serverId ?? undefined,\n managedDomains.map((domain) => domain.host),\n ),\n )\n const url = `${generated ? 'http' : 'https'}://${host}`\n if (!details?.domains?.some((domain) => domain.host === host)) {\n await this.options.client.api('domain.create', {\n body: {\n applicationId,\n host,\n path: '/',\n port: this.options.port,\n https: !generated,\n certificateType: generated ? 'none' : 'letsencrypt',\n domainType: 'application',\n },\n })\n }\n await this.options.onResolved?.({ host, url })\n await options.configure?.({ applicationId, client: this.options.client, host, url })\n await this.options.client.api('application.saveDockerProvider', {\n body: {\n applicationId,\n dockerImage: options.image,\n username: options.registry?.username ?? null,\n password: options.registry?.password ?? null,\n registryUrl: options.registry ? options.image.split('/')[0] : null,\n },\n })\n await this.options.client.api('application.saveEnvironment', {\n body: {\n applicationId,\n env: typeof options.environment === 'function' ? options.environment({ host, url }) : options.environment,\n buildArgs: null,\n buildSecrets: null,\n createEnvFile: false,\n },\n })\n await this.options.client.api('application.deploy', { body: { applicationId } })\n await this.waitForDeployment(applicationId)\n await this.waitForHealth(new URL(this.options.healthPath ?? '/api/health', url).toString())\n for (const domain of managedDomains.filter((candidate) => candidate.host !== host)) {\n if (!domain.domainId) throw new Error(`Dokploy did not report an ID for generated domain ${domain.host}`)\n // oxlint-disable-next-line no-await-in-loop\n await this.options.client.api('domain.delete', { body: { domainId: domain.domainId } })\n }\n this.log(`Preview ready at ${url}`)\n return { applicationId, host, url }\n }\n\n async delete(prNumber: string, beforeDelete?: (application: DokployApplication | undefined) => void | Promise<void>) {\n const name = this.options.applicationName(pullRequestNumber(prNumber))\n const application = await this.options.client.application(name)\n await beforeDelete?.(application)\n if (!application) return false\n await this.options.client.api('application.delete', { body: { applicationId: application.applicationId } })\n return true\n }\n\n async prune(\n openPullRequests: ReadonlySet<string>,\n beforeDelete?: (prNumber: string, application: DokployApplication) => void | Promise<void>,\n ) {\n const deleted: string[] = []\n for (const application of await this.options.client.applications()) {\n const prNumber = previewApplicationPrNumber(application.name, this.options.applicationName)\n if (!prNumber || openPullRequests.has(prNumber)) continue\n // Dokploy mutations are intentionally ordered to avoid overwhelming one environment.\n // oxlint-disable-next-line no-await-in-loop\n await beforeDelete?.(prNumber, application)\n // oxlint-disable-next-line no-await-in-loop\n await this.options.client.api('application.delete', { body: { applicationId: application.applicationId } })\n deleted.push(prNumber)\n }\n return deleted\n }\n\n private async waitForDeployment(applicationId: string) {\n const deadline = this.now() + (this.options.deploymentTimeoutMs ?? 600_000)\n while (this.now() < deadline) {\n // Polling is intentionally sequential; each response determines whether another request is needed.\n // oxlint-disable-next-line no-await-in-loop\n await this.pause(this.options.pollIntervalMs ?? 5_000)\n let applicationStatus: string\n try {\n // Polling is intentionally sequential; each response determines whether another request is needed.\n // oxlint-disable-next-line no-await-in-loop\n const details = await this.options.client.api<{ applicationStatus: string }>('application.one', {\n query: { applicationId },\n signal: AbortSignal.timeout(Math.max(1, deadline - this.now())),\n })\n applicationStatus = details.applicationStatus\n } catch (error) {\n if (error instanceof DOMException && error.name === 'TimeoutError') break\n throw error\n }\n if (applicationStatus === 'done') return\n if (applicationStatus === 'error') throw new Error('Dokploy reported a failed deployment')\n }\n throw new Error('Timed out waiting for the Dokploy deployment to finish')\n }\n\n private async waitForHealth(url: string) {\n const deadline = this.now() + (this.options.healthTimeoutMs ?? 300_000)\n let lastFailure = 'no response'\n while (this.now() < deadline) {\n try {\n // Polling is intentionally sequential; each response determines whether another request is needed.\n // oxlint-disable-next-line no-await-in-loop\n const response = await this.request(url, { signal: AbortSignal.timeout(Math.max(1, deadline - this.now())) })\n if (response.status === 200) return\n lastFailure = `status ${response.status}`\n } catch (error) {\n lastFailure = error instanceof Error ? error.message : String(error)\n }\n // oxlint-disable-next-line no-await-in-loop\n await this.pause(this.options.pollIntervalMs ?? 5_000)\n }\n throw new Error(`Timed out waiting for ${url} (${lastFailure})`)\n }\n}\n\nexport function pullRequestNumber(value: string) {\n if (!/^\\d+$/.test(value)) throw new Error('pull request number must contain only digits')\n return value\n}\n\nexport function previewHostname(value: string) {\n const parsed = new URL(`https://${value}`)\n if (parsed.hostname !== value || parsed.port || parsed.username || parsed.password || parsed.pathname !== '/') {\n throw new Error('preview hostname must be a bare hostname')\n }\n return value\n}\n\nfunction generatedPreviewHostname(value: string, serverIp: string, appName: string) {\n const host = previewHostname(value)\n if (!isCurrentGeneratedPreviewHostname(host, appName, serverIp))\n throw new Error('domain.generateDomain did not return an sslip.io hostname for the Dokploy server')\n return host\n}\n\nfunction isGeneratedPreviewHostname(host: string, appName: string) {\n return new RegExp(`^${regularExpressionLiteral(appName.slice(0, 40))}-[a-f\\\\d]{6}-[a-f\\\\d-]+\\\\.sslip\\\\.io$`).test(host)\n}\n\nfunction isCurrentGeneratedPreviewHostname(host: string, appName: string, serverIp: string) {\n return new RegExp(\n `^${regularExpressionLiteral(appName.slice(0, 40))}-[a-f\\\\d]{6}-${regularExpressionLiteral(encodedIp(serverIp))}\\\\.sslip\\\\.io$`,\n ).test(host)\n}\n\nfunction regularExpressionLiteral(value: string) {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction encodedIp(address: string) {\n return address.replaceAll('.', '-').replaceAll(':', '-')\n}\n\nconst generatedPreviewName = 'ras-preview'\n\nconst blockedPreviewAddresses = new BlockList()\nfor (const [address, prefix, family] of [\n ['0.0.0.0', 8, 'ipv4'],\n ['10.0.0.0', 8, 'ipv4'],\n ['100.64.0.0', 10, 'ipv4'],\n ['127.0.0.0', 8, 'ipv4'],\n ['169.254.0.0', 16, 'ipv4'],\n ['172.16.0.0', 12, 'ipv4'],\n ['192.0.0.0', 24, 'ipv4'],\n ['192.0.2.0', 24, 'ipv4'],\n ['192.88.99.0', 24, 'ipv4'],\n ['192.168.0.0', 16, 'ipv4'],\n ['198.18.0.0', 15, 'ipv4'],\n ['198.51.100.0', 24, 'ipv4'],\n ['203.0.113.0', 24, 'ipv4'],\n ['224.0.0.0', 4, 'ipv4'],\n ['240.0.0.0', 4, 'ipv4'],\n ['::', 128, 'ipv6'],\n ['::1', 128, 'ipv6'],\n ['64:ff9b:1::', 48, 'ipv6'],\n ['100::', 64, 'ipv6'],\n ['100:0:0:1::', 64, 'ipv6'],\n ['2001::', 23, 'ipv6'],\n ['2001:db8::', 32, 'ipv6'],\n ['2002::', 16, 'ipv6'],\n ['3fff::', 20, 'ipv6'],\n ['5f00::', 16, 'ipv6'],\n ['fc00::', 7, 'ipv6'],\n ['fe80::', 10, 'ipv6'],\n ['ff00::', 8, 'ipv6'],\n] as const) {\n blockedPreviewAddresses.addSubnet(address, prefix, family)\n}\n\nfunction previewServerIp(value: unknown) {\n if (typeof value !== 'string') throw new Error('Dokploy requires a public server IP before it can generate preview domains')\n const address = value.trim().toLowerCase()\n const version = isIP(address)\n const family = version === 4 ? 'ipv4' : version === 6 ? 'ipv6' : undefined\n if (!family || address.startsWith('::ffff:') || blockedPreviewAddresses.check(address, family)) {\n throw new Error('Dokploy requires a public server IP before it can generate preview domains')\n }\n return address\n}\n\nfunction previewApplicationPrNumber(name: string, applicationName: (prNumber: string) => string) {\n const match = /^(\\d+)$/.exec(name.match(/(\\d+)$/)?.[1] ?? '')\n const prNumber = match?.[1]\n return prNumber && applicationName(prNumber) === name ? prNumber : undefined\n}\n\nfunction requiredEnvironment(environment: NodeJS.ProcessEnv, name: string) {\n const value = optionalEnvironment(environment, name)\n if (!value) throw new Error(`${name} is required`)\n return value\n}\n\nfunction optionalEnvironment(environment: NodeJS.ProcessEnv, name: string) {\n return environment[name]?.trim() || undefined\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dokploy.js","sourceRoot":"","sources":["../../src/preview/dokploy.ts"],"names":[],"mappings":"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","sourcesContent":["import { appendFileSync } from 'node:fs'\nimport { BlockList, isIP } from 'node:net'\n\nexport type DokployApplication = { applicationId: string; name: string; serverId?: string | null }\n\nexport function dokployPreviewFromEnvironment(environment: NodeJS.ProcessEnv = process.env) {\n const githubOutput = optionalEnvironment(environment, 'GITHUB_OUTPUT')\n const username = optionalEnvironment(environment, 'PREVIEW_REGISTRY_USERNAME')\n const password = optionalEnvironment(environment, 'PREVIEW_REGISTRY_PASSWORD')\n if (Boolean(username) !== Boolean(password)) throw new Error('preview registry username and password must be configured together')\n const port = Number(requiredEnvironment(environment, 'PREVIEW_PORT'))\n if (!Number.isInteger(port) || port < 1 || port > 65_535) throw new Error('PREVIEW_PORT must be a valid port')\n const applicationPrefix = requiredEnvironment(environment, 'PREVIEW_APPLICATION_PREFIX')\n if (!/^[a-z\\d](?:[a-z\\d-]*[a-z\\d])?$/.test(applicationPrefix)) throw new Error('PREVIEW_APPLICATION_PREFIX must be a slug')\n const domain = optionalEnvironment(environment, 'PREVIEW_DOMAIN')\n if (domain) previewHostname(`pr-1.${domain}`)\n const config = {\n url: requiredEnvironment(environment, 'DOKPLOY_URL'),\n apiKey: requiredEnvironment(environment, 'DOKPLOY_API_KEY'),\n environmentId: requiredEnvironment(environment, 'DOKPLOY_ENVIRONMENT_ID'),\n applicationPrefix,\n domain,\n port,\n healthPath: optionalEnvironment(environment, 'PREVIEW_HEALTH_PATH'),\n ...(username && password ? { registry: { username, password } } : {}),\n }\n const client = new DokployClient(config)\n return {\n config,\n manager: new DokployPreviewManager({\n client,\n applicationName: (prNumber) => `${applicationPrefix}-pr-${prNumber}`,\n ...(domain ? { hostname: (prNumber: string) => `pr-${prNumber}.${domain}` } : {}),\n port,\n ...(config.healthPath ? { healthPath: config.healthPath } : {}),\n ...(githubOutput ? { onResolved: ({ url }: { url: string }) => appendFileSync(githubOutput, `preview-url=${url}\\n`) } : {}),\n }),\n }\n}\n\nexport type DokployClientOptions = {\n url: string\n apiKey: string\n environmentId: string\n fetch?: typeof fetch\n log?: (message: string) => void\n}\n\nexport class DokployClient {\n private readonly request: typeof fetch\n private readonly log: (message: string) => void\n\n constructor(private readonly options: DokployClientOptions) {\n this.request = options.fetch ?? fetch\n this.log = options.log ?? console.log\n }\n\n get environmentId() {\n return this.options.environmentId\n }\n\n async api<T = unknown>(\n procedure: string,\n options: { query?: Record<string, string>; body?: unknown; signal?: AbortSignal } = {},\n ): Promise<T> {\n const url = new URL(`${this.options.url.replace(/\\/$/, '')}/api/${procedure}`)\n for (const [key, value] of Object.entries(options.query ?? {})) url.searchParams.set(key, value)\n this.log(`→ ${procedure}`)\n const response = await this.request(url, {\n method: options.body === undefined ? 'GET' : 'POST',\n headers: {\n 'x-api-key': this.options.apiKey,\n ...(options.body === undefined ? {} : { 'content-type': 'application/json' }),\n },\n ...(options.signal ? { signal: options.signal } : {}),\n ...(options.body === undefined ? {} : { body: JSON.stringify(options.body) }),\n })\n const text = await response.text()\n if (!response.ok) throw new Error(`${procedure} failed with ${response.status}: ${text.slice(0, 500)}`)\n if (!text) return undefined as T\n try {\n return JSON.parse(text) as T\n } catch {\n throw new Error(`${procedure} returned ${response.status} with a non-JSON body: ${text.slice(0, 200)}`)\n }\n }\n\n async applications() {\n const environment = await this.api<{ applications?: DokployApplication[] } | undefined>('environment.one', {\n query: { environmentId: this.options.environmentId },\n })\n if (!environment) throw new Error('environment.one returned an empty response')\n return environment.applications ?? []\n }\n\n async application(name: string) {\n return (await this.applications()).find((application) => application.name === name)\n }\n\n async generatedDomain(appName: string, serverId?: string, existing: string[] = []) {\n const serverIp = serverId\n ? await this.api('domain.canGenerateTraefikMeDomains', { query: { serverId } })\n : await this.api('settings.getIp')\n const publicIp = previewServerIp(serverIp)\n const current = existing.find((host) => isCurrentGeneratedPreviewHostname(host, appName, publicIp))\n if (current) return current\n const generated = await this.api('domain.generateDomain', {\n body: { appName, ...(serverId ? { serverId } : {}) },\n })\n if (typeof generated !== 'string') throw new Error('domain.generateDomain returned an invalid hostname')\n return generatedPreviewHostname(generated, publicIp, appName)\n }\n}\n\nexport type DokployPreviewOptions = {\n client: DokployClient\n applicationName: (prNumber: string) => string\n hostname?: (prNumber: string) => string\n port: number\n healthPath?: string\n deploymentTimeoutMs?: number\n healthTimeoutMs?: number\n pollIntervalMs?: number\n fetch?: typeof fetch\n sleep?: (milliseconds: number) => Promise<void>\n now?: () => number\n log?: (message: string) => void\n onResolved?: (context: { host: string; url: string }) => void | Promise<void>\n}\n\nexport type DeployPreviewOptions = {\n prNumber: string\n image: string\n environment: string | ((context: { host: string; url: string }) => string)\n registry?: { username: string; password: string }\n configure?: (context: { applicationId: string; client: DokployClient; host: string; url: string }) => void | Promise<void>\n}\n\nexport class DokployPreviewManager {\n private readonly request: typeof fetch\n private readonly pause: (milliseconds: number) => Promise<void>\n private readonly log: (message: string) => void\n private readonly now: () => number\n\n constructor(private readonly options: DokployPreviewOptions) {\n this.request = options.fetch ?? fetch\n this.pause = options.sleep ?? ((milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)))\n this.log = options.log ?? console.log\n this.now = options.now ?? Date.now\n }\n\n async deploy(options: DeployPreviewOptions) {\n const prNumber = pullRequestNumber(options.prNumber)\n const name = this.options.applicationName(prNumber)\n let application = await this.options.client.application(name)\n if (!application) {\n await this.options.client.api('application.create', {\n body: { name, appName: name, environmentId: this.options.client.environmentId },\n })\n application = await this.options.client.application(name)\n if (!application) throw new Error(`Dokploy did not report ${name} after creating it`)\n }\n const applicationId = application.applicationId\n const details = await this.options.client.api<\n { domains?: { domainId?: string; host: string }[]; serverId?: string | null } | undefined\n >('application.one', { query: { applicationId } })\n const generated = !this.options.hostname\n const managedDomains = details?.domains?.filter((domain) => isGeneratedPreviewHostname(domain.host, generatedPreviewName)) ?? []\n const host = previewHostname(\n this.options.hostname\n ? this.options.hostname(prNumber)\n : await this.options.client.generatedDomain(\n generatedPreviewName,\n details?.serverId ?? application.serverId ?? undefined,\n managedDomains.map((domain) => domain.host),\n ),\n )\n const url = `${generated ? 'http' : 'https'}://${host}`\n if (!details?.domains?.some((domain) => domain.host === host)) {\n await this.options.client.api('domain.create', {\n body: {\n applicationId,\n host,\n path: '/',\n port: this.options.port,\n https: !generated,\n certificateType: generated ? 'none' : 'letsencrypt',\n domainType: 'application',\n },\n })\n }\n await this.options.onResolved?.({ host, url })\n await options.configure?.({ applicationId, client: this.options.client, host, url })\n await this.options.client.api('application.saveDockerProvider', {\n body: {\n applicationId,\n dockerImage: options.image,\n username: options.registry?.username ?? null,\n password: options.registry?.password ?? null,\n registryUrl: options.registry ? options.image.split('/')[0] : null,\n },\n })\n await this.options.client.api('application.saveEnvironment', {\n body: {\n applicationId,\n env: typeof options.environment === 'function' ? options.environment({ host, url }) : options.environment,\n buildArgs: null,\n buildSecrets: null,\n createEnvFile: false,\n },\n })\n await this.options.client.api('application.deploy', { body: { applicationId } })\n await this.waitForDeployment(applicationId)\n await this.waitForHealth(new URL(this.options.healthPath ?? '/api/health', url).toString())\n for (const domain of managedDomains.filter((candidate) => candidate.host !== host)) {\n if (!domain.domainId) throw new Error(`Dokploy did not report an ID for generated domain ${domain.host}`)\n // oxlint-disable-next-line no-await-in-loop\n await this.options.client.api('domain.delete', { body: { domainId: domain.domainId } })\n }\n this.log(`Preview ready at ${url}`)\n return { applicationId, host, url }\n }\n\n async delete(prNumber: string, beforeDelete?: (application: DokployApplication | undefined) => void | Promise<void>) {\n const name = this.options.applicationName(pullRequestNumber(prNumber))\n const application = await this.options.client.application(name)\n await beforeDelete?.(application)\n if (!application) return false\n await this.options.client.api('application.delete', { body: { applicationId: application.applicationId } })\n return true\n }\n\n async prune(\n openPullRequests: ReadonlySet<string>,\n beforeDelete?: (prNumber: string, application: DokployApplication) => void | Promise<void>,\n ) {\n const deleted: string[] = []\n for (const application of await this.options.client.applications()) {\n const prNumber = previewApplicationPrNumber(application.name, this.options.applicationName)\n if (!prNumber || openPullRequests.has(prNumber)) continue\n // Dokploy mutations are intentionally ordered to avoid overwhelming one environment.\n // oxlint-disable-next-line no-await-in-loop\n await beforeDelete?.(prNumber, application)\n // oxlint-disable-next-line no-await-in-loop\n await this.options.client.api('application.delete', { body: { applicationId: application.applicationId } })\n deleted.push(prNumber)\n }\n return deleted\n }\n\n private async waitForDeployment(applicationId: string) {\n const deadline = this.now() + (this.options.deploymentTimeoutMs ?? 600_000)\n while (this.now() < deadline) {\n // Polling is intentionally sequential; each response determines whether another request is needed.\n // oxlint-disable-next-line no-await-in-loop\n await this.pause(this.options.pollIntervalMs ?? 5_000)\n let applicationStatus: string\n try {\n // Polling is intentionally sequential; each response determines whether another request is needed.\n // oxlint-disable-next-line no-await-in-loop\n const details = await this.options.client.api<{ applicationStatus: string }>('application.one', {\n query: { applicationId },\n signal: AbortSignal.timeout(Math.max(1, deadline - this.now())),\n })\n applicationStatus = details.applicationStatus\n } catch (error) {\n if (error instanceof DOMException && error.name === 'TimeoutError') break\n throw error\n }\n if (applicationStatus === 'done') return\n if (applicationStatus === 'error') throw new Error('Dokploy reported a failed deployment')\n }\n throw new Error('Timed out waiting for the Dokploy deployment to finish')\n }\n\n private async waitForHealth(url: string) {\n const deadline = this.now() + (this.options.healthTimeoutMs ?? 300_000)\n let lastFailure = 'no response'\n while (this.now() < deadline) {\n try {\n // Polling is intentionally sequential; each response determines whether another request is needed.\n // oxlint-disable-next-line no-await-in-loop\n const response = await this.request(url, { signal: AbortSignal.timeout(Math.max(1, deadline - this.now())) })\n if (response.status === 200) return\n lastFailure = `status ${response.status}`\n } catch (error) {\n lastFailure = error instanceof Error ? error.message : String(error)\n }\n // oxlint-disable-next-line no-await-in-loop\n await this.pause(this.options.pollIntervalMs ?? 5_000)\n }\n throw new Error(`Timed out waiting for ${url} (${lastFailure})`)\n }\n}\n\nexport function pullRequestNumber(value: string) {\n if (!/^\\d+$/.test(value)) throw new Error('pull request number must contain only digits')\n return value\n}\n\nexport function previewHostname(value: string) {\n const parsed = new URL(`https://${value}`)\n if (parsed.hostname !== value || parsed.port || parsed.username || parsed.password || parsed.pathname !== '/') {\n throw new Error('preview hostname must be a bare hostname')\n }\n return value\n}\n\nfunction generatedPreviewHostname(value: string, serverIp: string, appName: string) {\n const host = previewHostname(value)\n if (!isCurrentGeneratedPreviewHostname(host, appName, serverIp))\n throw new Error('domain.generateDomain did not return an sslip.io hostname for the Dokploy server')\n return host\n}\n\nfunction isGeneratedPreviewHostname(host: string, appName: string) {\n return new RegExp(`^${regularExpressionLiteral(appName.slice(0, 40))}-[a-f\\\\d]{6}-[a-f\\\\d-]+\\\\.sslip\\\\.io$`).test(host)\n}\n\nfunction isCurrentGeneratedPreviewHostname(host: string, appName: string, serverIp: string) {\n return new RegExp(\n `^${regularExpressionLiteral(appName.slice(0, 40))}-[a-f\\\\d]{6}-${regularExpressionLiteral(encodedIp(serverIp))}\\\\.sslip\\\\.io$`,\n ).test(host)\n}\n\nfunction regularExpressionLiteral(value: string) {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\nfunction encodedIp(address: string) {\n return address.replaceAll('.', '-').replaceAll(':', '-')\n}\n\nconst generatedPreviewName = 'ras-preview'\n\nconst blockedPreviewAddresses = new BlockList()\nfor (const [address, prefix, family] of [\n ['0.0.0.0', 8, 'ipv4'],\n ['10.0.0.0', 8, 'ipv4'],\n ['100.64.0.0', 10, 'ipv4'],\n ['127.0.0.0', 8, 'ipv4'],\n ['169.254.0.0', 16, 'ipv4'],\n ['172.16.0.0', 12, 'ipv4'],\n ['192.0.0.0', 24, 'ipv4'],\n ['192.0.2.0', 24, 'ipv4'],\n ['192.88.99.0', 24, 'ipv4'],\n ['192.168.0.0', 16, 'ipv4'],\n ['198.18.0.0', 15, 'ipv4'],\n ['198.51.100.0', 24, 'ipv4'],\n ['203.0.113.0', 24, 'ipv4'],\n ['224.0.0.0', 4, 'ipv4'],\n ['240.0.0.0', 4, 'ipv4'],\n ['::', 128, 'ipv6'],\n ['::1', 128, 'ipv6'],\n ['64:ff9b:1::', 48, 'ipv6'],\n ['100::', 64, 'ipv6'],\n ['100:0:0:1::', 64, 'ipv6'],\n ['2001::', 23, 'ipv6'],\n ['2001:db8::', 32, 'ipv6'],\n ['2002::', 16, 'ipv6'],\n ['3fff::', 20, 'ipv6'],\n ['5f00::', 16, 'ipv6'],\n ['fc00::', 7, 'ipv6'],\n ['fe80::', 10, 'ipv6'],\n ['ff00::', 8, 'ipv6'],\n] as const) {\n blockedPreviewAddresses.addSubnet(address, prefix, family)\n}\n\nfunction previewServerIp(value: unknown) {\n if (typeof value !== 'string') throw new Error('Dokploy requires a public server IP before it can generate preview domains')\n const address = value.trim().toLowerCase()\n const version = isIP(address)\n const family = version === 4 ? 'ipv4' : version === 6 ? 'ipv6' : undefined\n if (!family || address.startsWith('::ffff:') || blockedPreviewAddresses.check(address, family)) {\n throw new Error('Dokploy requires a public server IP before it can generate preview domains')\n }\n return address\n}\n\nfunction previewApplicationPrNumber(name: string, applicationName: (prNumber: string) => string) {\n const match = /^(\\d+)$/.exec(name.match(/(\\d+)$/)?.[1] ?? '')\n const prNumber = match?.[1]\n return prNumber && applicationName(prNumber) === name ? prNumber : undefined\n}\n\nfunction requiredEnvironment(environment: NodeJS.ProcessEnv, name: string) {\n const value = optionalEnvironment(environment, name)\n if (!value) throw new Error(`${name} is required`)\n return value\n}\n\nfunction optionalEnvironment(environment: NodeJS.ProcessEnv, name: string) {\n return environment[name]?.trim() || undefined\n}\n"]}
|