@alienplatform/testing 1.14.0 → 1.14.1-dev.e74fae6cd01b61e77a285276f264b5480977f41a
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/README.md +1 -1
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
- package/LICENSE.md +0 -105
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
5
5
|
import { promisify } from "node:util";
|
|
6
6
|
import { AlienError } from "@alienplatform/core";
|
|
7
7
|
import getPort from "get-port";
|
|
8
|
-
import { CommandsClient } from "@alienplatform/
|
|
8
|
+
import { CommandsClient } from "@alienplatform/commands";
|
|
9
9
|
//#region src/deployment.ts
|
|
10
10
|
/**
|
|
11
11
|
* Deployment — handle to a deployed application for testing
|
|
@@ -47,16 +47,24 @@ var Deployment = class {
|
|
|
47
47
|
this.apiKey = params.apiKey;
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* Invoke a command on the deployment
|
|
50
|
+
* Invoke a command on the deployment.
|
|
51
|
+
*
|
|
52
|
+
* Pass `options.target` to route the command to a specific command-capable
|
|
53
|
+
* resource by id. This is required when more than one resource (e.g. a Worker
|
|
54
|
+
* and a Daemon) registers a handler under the same command name — the target
|
|
55
|
+
* disambiguates which one runs. When omitted, the server routes by its default
|
|
56
|
+
* rules.
|
|
51
57
|
*/
|
|
52
|
-
async invokeCommand(name, params) {
|
|
58
|
+
async invokeCommand(name, params, options) {
|
|
53
59
|
const token = this.apiKey ?? "";
|
|
54
|
-
|
|
60
|
+
const arc = new CommandsClient({
|
|
55
61
|
managerUrl: this.commandsUrl,
|
|
56
62
|
deploymentId: this.id,
|
|
57
63
|
token,
|
|
58
64
|
allowLocalStorage: this.platform === "local"
|
|
59
|
-
})
|
|
65
|
+
});
|
|
66
|
+
if (options?.target) return arc.target(options.target).invoke(name, params);
|
|
67
|
+
return arc.invoke(name, params);
|
|
60
68
|
}
|
|
61
69
|
/**
|
|
62
70
|
* Set an external secret using platform-native tools
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["execFileAsync","signalProcessTree"],"sources":["../src/deployment.ts","../src/deploy.ts"],"sourcesContent":["/**\n * Deployment — handle to a deployed application for testing\n *\n * Supports two deployment modes:\n * - Dev mode: manages a child `alien dev` process (local platform)\n * - API mode: manages a deployment via platform API (cloud platforms)\n */\n\nimport { execFile } from \"node:child_process\"\nimport type { ChildProcess } from \"node:child_process\"\nimport { readFileSync } from \"node:fs\"\nimport { resolve } from \"node:path\"\nimport { promisify } from \"node:util\"\nimport { CommandsClient } from \"@alienplatform/sdk/commands\"\nimport type { DeploymentInit, Platform, UpgradeOptions } from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\nfunction signalProcessTree(proc: ChildProcess, signal: NodeJS.Signals): void {\n if (proc.pid && process.platform !== \"win32\") {\n try {\n process.kill(-proc.pid, signal)\n return\n } catch {\n // Fall back to signaling only the direct child.\n }\n }\n\n proc.kill(signal)\n}\n\nexport class Deployment {\n readonly id: string\n readonly name: string\n /** Public URL of the app. Undefined for stacks with no URL-exposing resource (e.g. daemon-only). */\n readonly url: string | undefined\n readonly platform: Platform\n\n /** Whether the deployment has been destroyed */\n destroyed = false\n\n private process?: ChildProcess\n private commandsUrl: string\n private appPath: string\n\n // API mode fields\n private apiUrl?: string\n private apiKey?: string\n\n constructor(params: DeploymentInit) {\n this.id = params.id\n this.name = params.name\n this.url = params.url\n this.platform = params.platform\n this.commandsUrl = params.commandsUrl\n this.process = params.process\n this.appPath = params.appPath\n this.apiUrl = params.apiUrl\n this.apiKey = params.apiKey\n }\n\n /**\n * Invoke a command on the deployment\n */\n async invokeCommand(name: string, params: any): Promise<any> {\n const token = this.apiKey ?? \"\"\n const arc = new CommandsClient({\n managerUrl: this.commandsUrl,\n deploymentId: this.id,\n token,\n allowLocalStorage: this.platform === \"local\",\n })\n\n return arc.invoke(name, params)\n }\n\n /**\n * Set an external secret using platform-native tools\n */\n async setExternalSecret(\n vaultName: string,\n secretKey: string,\n secretValue: string,\n ): Promise<void> {\n const { setExternalSecret } = await import(\"./external-secrets.js\")\n const stateDir = this.appPath ? `${this.appPath}/.alien` : undefined\n await setExternalSecret(\n this.platform,\n this.name, // resourcePrefix (cloud: naming prefix, local: unused)\n vaultName,\n secretKey,\n secretValue,\n undefined, // namespace\n stateDir,\n this.id, // deploymentId (local: used for vault path)\n )\n }\n\n /**\n * Upgrade the deployment by creating a new release and updating the deployment.\n * Only works for API-mode deployments (cloud platforms).\n */\n async upgrade(options: UpgradeOptions = {}): Promise<void> {\n if (!this.apiUrl || !this.apiKey) {\n throw new Error(\"upgrade() requires a cloud deployment (not local dev mode)\")\n }\n\n const headers = {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n }\n\n // Build new artifacts\n const cliPath = this.resolveCliPath()\n const buildArgs = [\"build\", \"--platform\", this.platform]\n await execFileAsync(cliPath, buildArgs, { cwd: this.appPath })\n\n // Read the built stack\n const stackPath = resolve(this.appPath, \".alien\", \"stack.json\")\n const stack = JSON.parse(readFileSync(stackPath, \"utf-8\"))\n\n // Create a new release\n const releaseResp = await fetch(`${this.apiUrl}/v1/releases`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ stack }),\n })\n\n if (!releaseResp.ok) {\n const body = await releaseResp.text()\n throw new Error(`Failed to create release for upgrade: ${releaseResp.status} ${body}`)\n }\n\n const release = (await releaseResp.json()) as { id: string }\n\n // Update the deployment with the new release and optional env vars\n const patchBody: Record<string, unknown> = { releaseId: release.id }\n if (options.environmentVariables?.length) {\n patchBody.environmentVariables = options.environmentVariables\n }\n\n const patchResp = await fetch(`${this.apiUrl}/v1/deployments/${this.id}`, {\n method: \"PATCH\",\n headers,\n body: JSON.stringify(patchBody),\n })\n\n if (!patchResp.ok) {\n const body = await patchResp.text()\n throw new Error(`Failed to update deployment for upgrade: ${patchResp.status} ${body}`)\n }\n\n // Wait for deployment to pick up the new release\n const timeout = 300_000 // 5 minutes\n const start = Date.now()\n while (Date.now() - start < timeout) {\n const resp = await fetch(`${this.apiUrl}/v1/deployments/${this.id}`, {\n headers: { Authorization: `Bearer ${this.apiKey}` },\n })\n if (resp.ok) {\n const data = (await resp.json()) as { status: string; releaseId: string }\n if (data.releaseId === release.id && data.status === \"running\") {\n return\n }\n if (data.status === \"error\" || data.status.includes(\"failed\")) {\n throw new Error(`Deployment failed during upgrade with status: ${data.status}`)\n }\n }\n await new Promise(r => setTimeout(r, 5000))\n }\n\n throw new Error(\"Timeout waiting for deployment to pick up upgrade\")\n }\n\n /**\n * Destroy the deployment.\n *\n * For dev mode: kills the `alien dev` process.\n * For API mode: calls DELETE on platform API.\n */\n async destroy(): Promise<void> {\n if (this.destroyed) return\n\n // Dev mode — kill the process\n if (this.process) {\n if (!this.process.killed) {\n signalProcessTree(this.process, \"SIGTERM\")\n\n await new Promise<void>(resolve => {\n const timeout = setTimeout(() => {\n if (!this.process!.killed) {\n signalProcessTree(this.process!, \"SIGKILL\")\n }\n resolve()\n }, 5000)\n\n this.process!.once(\"exit\", () => {\n clearTimeout(timeout)\n resolve()\n })\n })\n }\n this.destroyed = true\n return\n }\n\n // API mode — delete via platform API\n if (this.apiUrl && this.apiKey) {\n const headers = { Authorization: `Bearer ${this.apiKey}` }\n\n // Delete via platform API\n const resp = await fetch(`${this.apiUrl}/v1/deployments/${this.id}`, {\n method: \"DELETE\",\n headers,\n })\n\n if (!resp.ok && resp.status !== 404) {\n const body = await resp.text()\n throw new Error(`Failed to destroy deployment: ${resp.status} ${body}`)\n }\n\n // Poll until deployment is gone or destroyed\n const timeout = 300_000 // 5 minutes\n const start = Date.now()\n while (Date.now() - start < timeout) {\n const checkResp = await fetch(`${this.apiUrl}/v1/deployments/${this.id}`, { headers })\n if (checkResp.status === 404) break\n if (checkResp.ok) {\n const data = (await checkResp.json()) as { status: string }\n if (data.status === \"destroyed\" || data.status === \"deleted\") break\n }\n await new Promise(r => setTimeout(r, 5000))\n }\n }\n\n this.destroyed = true\n }\n\n private resolveCliPath(): string {\n const raw = process.env.ALIEN_CLI_PATH?.trim()\n if (raw) {\n return raw.includes(\"/\") || raw.includes(\"\\\\\") ? resolve(raw) : raw\n }\n return \"alien\"\n }\n}\n","/**\n * deploy() — single entry point for deploying an Alien application for testing\n *\n * Auto-detects the deployment method based on the target platform:\n * - local (default): spawns `alien dev` and watches its status file contract\n * - aws / gcp / azure: builds + creates release/deployment via platform API — reads ALIEN_API_KEY from env\n */\n\nimport { execFile, spawn } from \"node:child_process\"\nimport { existsSync, readFileSync, rmSync } from \"node:fs\"\nimport { dirname, join, resolve } from \"node:path\"\nimport { promisify } from \"node:util\"\nimport { AlienError } from \"@alienplatform/core\"\nimport type { DevStatus } from \"@alienplatform/core\"\nimport getPort from \"get-port\"\nimport { Deployment } from \"./deployment.js\"\nimport { TestingOperationFailedError, withTestingContext } from \"./errors.js\"\nimport type { DeployOptions } from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\ntype DevStatusAgent = DevStatus[\"agents\"][string] & {\n commandsUrl?: string | null\n}\n\n/**\n * Get the alien CLI path with fallback discovery.\n *\n * Resolution order:\n * 1. ALIEN_CLI_PATH (if set)\n * 2. nearest ../target/debug/alien (or alien.exe) walking upward from app path\n * 3. \"alien\" from PATH\n */\nfunction getAlienCliPath(appPath: string): string {\n const raw = process.env.ALIEN_CLI_PATH?.trim()\n if (raw) {\n if (raw.includes(\"/\") || raw.includes(\"\\\\\")) {\n return resolve(raw)\n }\n return raw\n }\n\n let current = resolve(appPath)\n while (true) {\n const unixCandidate = join(current, \"target\", \"debug\", \"alien\")\n if (existsSync(unixCandidate)) {\n return unixCandidate\n }\n const windowsCandidate = `${unixCandidate}.exe`\n if (existsSync(windowsCandidate)) {\n return windowsCandidate\n }\n\n const parent = dirname(current)\n if (parent === current) {\n break\n }\n current = parent\n }\n\n return \"alien\"\n}\n\n/**\n * Deploy an Alien application for testing.\n *\n * Uses local dev mode by default. Set `platform` to a cloud provider\n * to deploy via the platform API (requires ALIEN_API_KEY env var).\n */\nexport async function deploy(options: DeployOptions): Promise<Deployment> {\n const platform = options.platform ?? \"local\"\n\n if (platform === \"local\") {\n return deployViaDev(options)\n }\n\n // Cloud platforms: aws, gcp, azure\n return deployViaApi(options)\n}\n\n// ---------------------------------------------------------------------------\n// Method: dev — spawns `alien dev` as a child process\n// ---------------------------------------------------------------------------\n\nasync function deployViaDev(options: DeployOptions): Promise<Deployment> {\n const verbose = options.verbose ?? process.env.VERBOSE === \"true\"\n const port = await getPort()\n const cliPath = getAlienCliPath(options.app)\n const statusFile = join(options.app, \".alien\", \"testing-dev-status.json\")\n\n const args = [\"dev\", \"--port\", String(port), \"--status-file\", statusFile]\n\n if (options.config) {\n args.push(\"--config\", options.config)\n }\n\n for (const ev of options.environmentVariables ?? []) {\n const flag = ev.type === \"secret\" ? \"--secret\" : \"--env\"\n const targets = ev.targetResources?.length ? `:${ev.targetResources.join(\",\")}` : \"\"\n args.push(flag, `${ev.name}=${ev.value}${targets}`)\n }\n\n if (verbose) {\n console.log(`[testing] Spawning: ${cliPath} ${args.join(\" \")}`)\n }\n\n // Clean .alien state directory to ensure fresh deployment state.\n const alienStateDir = join(options.app, \".alien\")\n rmSync(alienStateDir, { recursive: true, force: true })\n\n const childEnv: Record<string, string> = {\n ...(process.env as Record<string, string>),\n }\n\n const proc = spawn(cliPath, args, {\n cwd: options.app,\n env: childEnv,\n detached: process.platform !== \"win32\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n })\n\n let stdout = \"\"\n let stderr = \"\"\n\n proc.stdout?.on(\"data\", (data: Buffer) => {\n stdout += data.toString()\n if (verbose) {\n process.stdout.write(data)\n }\n })\n\n proc.stderr?.on(\"data\", (data: Buffer) => {\n stderr += data.toString()\n if (verbose) {\n process.stderr.write(data)\n }\n })\n\n let exited = false\n let exitCode: number | null = null\n proc.on(\"exit\", code => {\n exited = true\n exitCode = code\n })\n proc.on(\"error\", err => {\n exited = true\n exitCode = 1\n stderr += `\\nFailed to spawn alien CLI: ${err.message}`\n })\n\n try {\n const status = await waitForDevStatusReady(\n statusFile,\n () => exited,\n () => exitCode,\n () => stderr,\n )\n\n const agent = findPrimaryAgent(status)\n\n // A stack with no URL-exposing resource (e.g. daemon-only) has no public URL;\n // commands are still reachable through commandsUrl.\n const publicUrl = findPublicUrl(agent.resources)\n\n if (verbose) {\n console.log(`[testing] Public URL: ${publicUrl ?? \"(none)\"}`)\n if (agent.commandsUrl) {\n console.log(`[testing] Commands URL: ${agent.commandsUrl}`)\n }\n }\n\n if (!agent.commandsUrl) {\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"resolve-commands-url\",\n message: \"alien dev status file did not include a commands URL\",\n details: { agent },\n }),\n )\n }\n\n return new Deployment({\n id: agent.id,\n name: agent.name,\n url: publicUrl,\n platform: options.platform ?? \"local\",\n commandsUrl: agent.commandsUrl,\n process: proc,\n appPath: options.app,\n })\n } catch (error) {\n signalProcessTree(proc, \"SIGTERM\")\n throw await withTestingContext(\n error,\n \"deploy\",\n \"Failed while waiting for alien dev to become ready\",\n { statusFile, appPath: options.app, platform: options.platform ?? \"local\" },\n )\n }\n}\n\nfunction signalProcessTree(\n proc: import(\"node:child_process\").ChildProcess,\n signal: NodeJS.Signals,\n): void {\n if (proc.pid && process.platform !== \"win32\") {\n try {\n process.kill(-proc.pid, signal)\n return\n } catch {\n // Fall back to signaling only the direct child.\n }\n }\n\n proc.kill(signal)\n}\n\n// ---------------------------------------------------------------------------\n// Method: api — direct platform API calls (reads ALIEN_API_KEY from env)\n// ---------------------------------------------------------------------------\n\ninterface PlatformDeploymentResponse {\n id: string\n name: string\n status: string\n releaseId: string\n url?: string\n commandsUrl?: string\n}\n\ninterface PlatformReleaseResponse {\n id: string\n version: number\n}\n\nasync function deployViaApi(options: DeployOptions): Promise<Deployment> {\n const platform = options.platform ?? \"local\"\n const verbose = options.verbose ?? process.env.VERBOSE === \"true\"\n\n const apiKey = process.env.ALIEN_API_KEY\n if (!apiKey) {\n throw new Error(\n `Cloud deployment (platform: '${platform}') requires the ALIEN_API_KEY environment variable to be set`,\n )\n }\n\n const apiUrl = process.env.ALIEN_API_URL ?? \"https://api.alien.dev\"\n\n const headers = {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n }\n\n // 1. Build the application\n if (verbose) console.log(\"[testing:api] Building application...\")\n const cliPath = getAlienCliPath(options.app)\n const buildArgs = [\"build\", \"--platform\", platform]\n if (options.config) {\n buildArgs.push(\"--config\", options.config)\n }\n await execFileAsync(cliPath, buildArgs, { cwd: options.app })\n\n // 2. Read the built stack\n const stackPath = resolve(options.app, \".alien\", \"stack.json\")\n if (!existsSync(stackPath)) {\n throw new Error(`Build did not produce stack.json at ${stackPath}`)\n }\n const stack = JSON.parse(readFileSync(stackPath, \"utf-8\"))\n\n // 3. Create a release\n if (verbose) console.log(\"[testing:api] Creating release...\")\n const releaseResp = await fetch(`${apiUrl}/v1/releases`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ stack }),\n })\n\n if (!releaseResp.ok) {\n const body = await releaseResp.text()\n throw new Error(`Failed to create release: ${releaseResp.status} ${body}`)\n }\n\n const release = (await releaseResp.json()) as PlatformReleaseResponse\n\n // 4. Create a deployment\n if (verbose) console.log(\"[testing:api] Creating deployment...\")\n const deploymentName = `e2e-${Date.now()}`\n const deployBody: Record<string, unknown> = {\n releaseId: release.id,\n platform,\n name: deploymentName,\n }\n\n if (options.environmentVariables?.length) {\n deployBody.environmentVariables = options.environmentVariables\n }\n\n const deployResp = await fetch(`${apiUrl}/v1/deployments`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(deployBody),\n })\n\n if (!deployResp.ok) {\n const body = await deployResp.text()\n throw new Error(`Failed to create deployment: ${deployResp.status} ${body}`)\n }\n\n const deployment = (await deployResp.json()) as PlatformDeploymentResponse\n\n // 5. Poll until running\n if (verbose) console.log(`[testing:api] Waiting for deployment ${deployment.id} to be running...`)\n const running = await waitForPlatformDeploymentRunning(apiUrl, apiKey, deployment.id, verbose)\n\n return new Deployment({\n id: running.id,\n name: running.name,\n url: running.url,\n platform,\n commandsUrl: running.commandsUrl!,\n appPath: options.app,\n apiUrl,\n apiKey,\n })\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Wait for `alien dev` to report a ready local session via its status file.\n */\nasync function waitForDevStatusReady(\n statusFile: string,\n hasExited: () => boolean,\n getExitCode: () => number | null,\n getStderr: () => string,\n): Promise<DevStatus> {\n const timeout = 900_000\n const pollInterval = 500\n const start = Date.now()\n\n while (Date.now() - start < timeout) {\n if (hasExited()) {\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"wait-for-ready\",\n message: \"alien dev exited before the local session became ready\",\n details: {\n exitCode: getExitCode(),\n stderrTail: getStderr().slice(-1000),\n },\n }),\n )\n }\n\n if (!existsSync(statusFile)) {\n await new Promise(r => setTimeout(r, pollInterval))\n continue\n }\n\n try {\n const status = JSON.parse(readFileSync(statusFile, \"utf-8\")) as DevStatus\n if (status.status === \"error\") {\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"wait-for-ready\",\n message: \"alien dev reported an error status\",\n details: { status },\n }),\n )\n }\n\n if (status.status === \"ready\" && Object.keys(status.agents ?? {}).length > 0) {\n return status\n }\n } catch (error) {\n if (error instanceof AlienError && error.code === \"TESTING_OPERATION_FAILED\") {\n throw error\n }\n // Status file may be mid-write; retry.\n }\n\n await new Promise(r => setTimeout(r, pollInterval))\n }\n\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"wait-for-ready\",\n message: `Timeout waiting for alien dev to report readiness (${timeout / 1000}s)`,\n details: { statusFile, timeoutMs: timeout },\n }),\n )\n}\n\nfunction findPrimaryAgent(status: DevStatus): DevStatusAgent {\n const agent = Object.values(status.agents ?? {})[0] as DevStatusAgent | undefined\n if (!agent) {\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"resolve-agent\",\n message: \"alien dev reported readiness but no agents were present in the status file\",\n details: { status },\n }),\n )\n }\n\n return agent\n}\n\n/**\n * Wait for a platform API deployment to reach \"running\" status.\n */\nasync function waitForPlatformDeploymentRunning(\n apiUrl: string,\n apiKey: string,\n deploymentId: string,\n verbose: boolean,\n): Promise<PlatformDeploymentResponse> {\n const timeout = 900_000 // 15 minutes\n const pollInterval = 5000\n const start = Date.now()\n const headers = { Authorization: `Bearer ${apiKey}` }\n\n while (Date.now() - start < timeout) {\n try {\n const resp = await fetch(`${apiUrl}/v1/deployments/${deploymentId}`, {\n headers,\n signal: AbortSignal.timeout(10000),\n })\n\n if (resp.ok) {\n const data = (await resp.json()) as PlatformDeploymentResponse\n if (verbose) {\n console.log(`[testing] Deployment ${deploymentId} status: ${data.status}`)\n }\n\n // A running deployment may have no URL (e.g. daemon-only stacks) — url stays optional.\n if (data.status === \"running\") {\n return data\n }\n\n if (data.status === \"error\" || data.status.includes(\"failed\")) {\n throw new Error(`Deployment failed with status: ${data.status}`)\n }\n }\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"failed with status\")) {\n throw error\n }\n // Network errors expected during provisioning\n }\n\n await new Promise(r => setTimeout(r, pollInterval))\n }\n\n throw new Error(\n `Timeout waiting for deployment ${deploymentId} to reach running status (${timeout / 1000}s)`,\n )\n}\n\n/**\n * Find the public URL from deployment resources\n */\nfunction findPublicUrl(\n resources: Record<string, { url: string; resourceType?: string | null }>,\n): string | undefined {\n for (const [name, resource] of Object.entries(resources)) {\n if (\n resource.url &&\n (name.includes(\"router\") || name.includes(\"gateway\") || name.includes(\"proxy\"))\n ) {\n return resource.url\n }\n }\n\n const publicResources = Object.entries(resources).filter(\n ([_, r]) => (r.resourceType === \"container\" || r.resourceType === \"worker\") && r.url,\n )\n if (publicResources.length > 0) {\n return publicResources[publicResources.length - 1]![1].url\n }\n\n return undefined\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["execFileAsync","signalProcessTree"],"sources":["../src/deployment.ts","../src/deploy.ts"],"sourcesContent":["/**\n * Deployment — handle to a deployed application for testing\n *\n * Supports two deployment modes:\n * - Dev mode: manages a child `alien dev` process (local platform)\n * - API mode: manages a deployment via platform API (cloud platforms)\n */\n\nimport { execFile } from \"node:child_process\"\nimport type { ChildProcess } from \"node:child_process\"\nimport { readFileSync } from \"node:fs\"\nimport { resolve } from \"node:path\"\nimport { promisify } from \"node:util\"\nimport { CommandsClient } from \"@alienplatform/commands\"\nimport type { DeploymentInit, Platform, UpgradeOptions } from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\nfunction signalProcessTree(proc: ChildProcess, signal: NodeJS.Signals): void {\n if (proc.pid && process.platform !== \"win32\") {\n try {\n process.kill(-proc.pid, signal)\n return\n } catch {\n // Fall back to signaling only the direct child.\n }\n }\n\n proc.kill(signal)\n}\n\nexport class Deployment {\n readonly id: string\n readonly name: string\n /** Public URL of the app. Undefined for stacks with no URL-exposing resource (e.g. daemon-only). */\n readonly url: string | undefined\n readonly platform: Platform\n\n /** Whether the deployment has been destroyed */\n destroyed = false\n\n private process?: ChildProcess\n private commandsUrl: string\n private appPath: string\n\n // API mode fields\n private apiUrl?: string\n private apiKey?: string\n\n constructor(params: DeploymentInit) {\n this.id = params.id\n this.name = params.name\n this.url = params.url\n this.platform = params.platform\n this.commandsUrl = params.commandsUrl\n this.process = params.process\n this.appPath = params.appPath\n this.apiUrl = params.apiUrl\n this.apiKey = params.apiKey\n }\n\n /**\n * Invoke a command on the deployment.\n *\n * Pass `options.target` to route the command to a specific command-capable\n * resource by id. This is required when more than one resource (e.g. a Worker\n * and a Daemon) registers a handler under the same command name — the target\n * disambiguates which one runs. When omitted, the server routes by its default\n * rules.\n */\n async invokeCommand<T = unknown>(\n name: string,\n params: unknown,\n options?: { target?: string },\n ): Promise<T> {\n const token = this.apiKey ?? \"\"\n const arc = new CommandsClient({\n managerUrl: this.commandsUrl,\n deploymentId: this.id,\n token,\n allowLocalStorage: this.platform === \"local\",\n })\n\n if (options?.target) {\n return arc.target(options.target).invoke<T>(name, params)\n }\n return arc.invoke<T>(name, params)\n }\n\n /**\n * Set an external secret using platform-native tools\n */\n async setExternalSecret(\n vaultName: string,\n secretKey: string,\n secretValue: string,\n ): Promise<void> {\n const { setExternalSecret } = await import(\"./external-secrets.js\")\n const stateDir = this.appPath ? `${this.appPath}/.alien` : undefined\n await setExternalSecret(\n this.platform,\n this.name, // resourcePrefix (cloud: naming prefix, local: unused)\n vaultName,\n secretKey,\n secretValue,\n undefined, // namespace\n stateDir,\n this.id, // deploymentId (local: used for vault path)\n )\n }\n\n /**\n * Upgrade the deployment by creating a new release and updating the deployment.\n * Only works for API-mode deployments (cloud platforms).\n */\n async upgrade(options: UpgradeOptions = {}): Promise<void> {\n if (!this.apiUrl || !this.apiKey) {\n throw new Error(\"upgrade() requires a cloud deployment (not local dev mode)\")\n }\n\n const headers = {\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Type\": \"application/json\",\n }\n\n // Build new artifacts\n const cliPath = this.resolveCliPath()\n const buildArgs = [\"build\", \"--platform\", this.platform]\n await execFileAsync(cliPath, buildArgs, { cwd: this.appPath })\n\n // Read the built stack\n const stackPath = resolve(this.appPath, \".alien\", \"stack.json\")\n const stack = JSON.parse(readFileSync(stackPath, \"utf-8\"))\n\n // Create a new release\n const releaseResp = await fetch(`${this.apiUrl}/v1/releases`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ stack }),\n })\n\n if (!releaseResp.ok) {\n const body = await releaseResp.text()\n throw new Error(`Failed to create release for upgrade: ${releaseResp.status} ${body}`)\n }\n\n const release = (await releaseResp.json()) as { id: string }\n\n // Update the deployment with the new release and optional env vars\n const patchBody: Record<string, unknown> = { releaseId: release.id }\n if (options.environmentVariables?.length) {\n patchBody.environmentVariables = options.environmentVariables\n }\n\n const patchResp = await fetch(`${this.apiUrl}/v1/deployments/${this.id}`, {\n method: \"PATCH\",\n headers,\n body: JSON.stringify(patchBody),\n })\n\n if (!patchResp.ok) {\n const body = await patchResp.text()\n throw new Error(`Failed to update deployment for upgrade: ${patchResp.status} ${body}`)\n }\n\n // Wait for deployment to pick up the new release\n const timeout = 300_000 // 5 minutes\n const start = Date.now()\n while (Date.now() - start < timeout) {\n const resp = await fetch(`${this.apiUrl}/v1/deployments/${this.id}`, {\n headers: { Authorization: `Bearer ${this.apiKey}` },\n })\n if (resp.ok) {\n const data = (await resp.json()) as { status: string; releaseId: string }\n if (data.releaseId === release.id && data.status === \"running\") {\n return\n }\n if (data.status === \"error\" || data.status.includes(\"failed\")) {\n throw new Error(`Deployment failed during upgrade with status: ${data.status}`)\n }\n }\n await new Promise(r => setTimeout(r, 5000))\n }\n\n throw new Error(\"Timeout waiting for deployment to pick up upgrade\")\n }\n\n /**\n * Destroy the deployment.\n *\n * For dev mode: kills the `alien dev` process.\n * For API mode: calls DELETE on platform API.\n */\n async destroy(): Promise<void> {\n if (this.destroyed) return\n\n // Dev mode — kill the process\n if (this.process) {\n if (!this.process.killed) {\n signalProcessTree(this.process, \"SIGTERM\")\n\n await new Promise<void>(resolve => {\n const timeout = setTimeout(() => {\n if (!this.process!.killed) {\n signalProcessTree(this.process!, \"SIGKILL\")\n }\n resolve()\n }, 5000)\n\n this.process!.once(\"exit\", () => {\n clearTimeout(timeout)\n resolve()\n })\n })\n }\n this.destroyed = true\n return\n }\n\n // API mode — delete via platform API\n if (this.apiUrl && this.apiKey) {\n const headers = { Authorization: `Bearer ${this.apiKey}` }\n\n // Delete via platform API\n const resp = await fetch(`${this.apiUrl}/v1/deployments/${this.id}`, {\n method: \"DELETE\",\n headers,\n })\n\n if (!resp.ok && resp.status !== 404) {\n const body = await resp.text()\n throw new Error(`Failed to destroy deployment: ${resp.status} ${body}`)\n }\n\n // Poll until deployment is gone or destroyed\n const timeout = 300_000 // 5 minutes\n const start = Date.now()\n while (Date.now() - start < timeout) {\n const checkResp = await fetch(`${this.apiUrl}/v1/deployments/${this.id}`, { headers })\n if (checkResp.status === 404) break\n if (checkResp.ok) {\n const data = (await checkResp.json()) as { status: string }\n if (data.status === \"destroyed\" || data.status === \"deleted\") break\n }\n await new Promise(r => setTimeout(r, 5000))\n }\n }\n\n this.destroyed = true\n }\n\n private resolveCliPath(): string {\n const raw = process.env.ALIEN_CLI_PATH?.trim()\n if (raw) {\n return raw.includes(\"/\") || raw.includes(\"\\\\\") ? resolve(raw) : raw\n }\n return \"alien\"\n }\n}\n","/**\n * deploy() — single entry point for deploying an Alien application for testing\n *\n * Auto-detects the deployment method based on the target platform:\n * - local (default): spawns `alien dev` and watches its status file contract\n * - aws / gcp / azure: builds + creates release/deployment via platform API — reads ALIEN_API_KEY from env\n */\n\nimport { execFile, spawn } from \"node:child_process\"\nimport { existsSync, readFileSync, rmSync } from \"node:fs\"\nimport { dirname, join, resolve } from \"node:path\"\nimport { promisify } from \"node:util\"\nimport { AlienError } from \"@alienplatform/core\"\nimport type { DevStatus } from \"@alienplatform/core\"\nimport getPort from \"get-port\"\nimport { Deployment } from \"./deployment.js\"\nimport { TestingOperationFailedError, withTestingContext } from \"./errors.js\"\nimport type { DeployOptions } from \"./types.js\"\n\nconst execFileAsync = promisify(execFile)\n\ntype DevStatusAgent = DevStatus[\"agents\"][string] & {\n commandsUrl?: string | null\n}\n\n/**\n * Get the alien CLI path with fallback discovery.\n *\n * Resolution order:\n * 1. ALIEN_CLI_PATH (if set)\n * 2. nearest ../target/debug/alien (or alien.exe) walking upward from app path\n * 3. \"alien\" from PATH\n */\nfunction getAlienCliPath(appPath: string): string {\n const raw = process.env.ALIEN_CLI_PATH?.trim()\n if (raw) {\n if (raw.includes(\"/\") || raw.includes(\"\\\\\")) {\n return resolve(raw)\n }\n return raw\n }\n\n let current = resolve(appPath)\n while (true) {\n const unixCandidate = join(current, \"target\", \"debug\", \"alien\")\n if (existsSync(unixCandidate)) {\n return unixCandidate\n }\n const windowsCandidate = `${unixCandidate}.exe`\n if (existsSync(windowsCandidate)) {\n return windowsCandidate\n }\n\n const parent = dirname(current)\n if (parent === current) {\n break\n }\n current = parent\n }\n\n return \"alien\"\n}\n\n/**\n * Deploy an Alien application for testing.\n *\n * Uses local dev mode by default. Set `platform` to a cloud provider\n * to deploy via the platform API (requires ALIEN_API_KEY env var).\n */\nexport async function deploy(options: DeployOptions): Promise<Deployment> {\n const platform = options.platform ?? \"local\"\n\n if (platform === \"local\") {\n return deployViaDev(options)\n }\n\n // Cloud platforms: aws, gcp, azure\n return deployViaApi(options)\n}\n\n// ---------------------------------------------------------------------------\n// Method: dev — spawns `alien dev` as a child process\n// ---------------------------------------------------------------------------\n\nasync function deployViaDev(options: DeployOptions): Promise<Deployment> {\n const verbose = options.verbose ?? process.env.VERBOSE === \"true\"\n const port = await getPort()\n const cliPath = getAlienCliPath(options.app)\n const statusFile = join(options.app, \".alien\", \"testing-dev-status.json\")\n\n const args = [\"dev\", \"--port\", String(port), \"--status-file\", statusFile]\n\n if (options.config) {\n args.push(\"--config\", options.config)\n }\n\n for (const ev of options.environmentVariables ?? []) {\n const flag = ev.type === \"secret\" ? \"--secret\" : \"--env\"\n const targets = ev.targetResources?.length ? `:${ev.targetResources.join(\",\")}` : \"\"\n args.push(flag, `${ev.name}=${ev.value}${targets}`)\n }\n\n if (verbose) {\n console.log(`[testing] Spawning: ${cliPath} ${args.join(\" \")}`)\n }\n\n // Clean .alien state directory to ensure fresh deployment state.\n const alienStateDir = join(options.app, \".alien\")\n rmSync(alienStateDir, { recursive: true, force: true })\n\n const childEnv: Record<string, string> = {\n ...(process.env as Record<string, string>),\n }\n\n const proc = spawn(cliPath, args, {\n cwd: options.app,\n env: childEnv,\n detached: process.platform !== \"win32\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n })\n\n let stdout = \"\"\n let stderr = \"\"\n\n proc.stdout?.on(\"data\", (data: Buffer) => {\n stdout += data.toString()\n if (verbose) {\n process.stdout.write(data)\n }\n })\n\n proc.stderr?.on(\"data\", (data: Buffer) => {\n stderr += data.toString()\n if (verbose) {\n process.stderr.write(data)\n }\n })\n\n let exited = false\n let exitCode: number | null = null\n proc.on(\"exit\", code => {\n exited = true\n exitCode = code\n })\n proc.on(\"error\", err => {\n exited = true\n exitCode = 1\n stderr += `\\nFailed to spawn alien CLI: ${err.message}`\n })\n\n try {\n const status = await waitForDevStatusReady(\n statusFile,\n () => exited,\n () => exitCode,\n () => stderr,\n )\n\n const agent = findPrimaryAgent(status)\n\n // A stack with no URL-exposing resource (e.g. daemon-only) has no public URL;\n // commands are still reachable through commandsUrl.\n const publicUrl = findPublicUrl(agent.resources)\n\n if (verbose) {\n console.log(`[testing] Public URL: ${publicUrl ?? \"(none)\"}`)\n if (agent.commandsUrl) {\n console.log(`[testing] Commands URL: ${agent.commandsUrl}`)\n }\n }\n\n if (!agent.commandsUrl) {\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"resolve-commands-url\",\n message: \"alien dev status file did not include a commands URL\",\n details: { agent },\n }),\n )\n }\n\n return new Deployment({\n id: agent.id,\n name: agent.name,\n url: publicUrl,\n platform: options.platform ?? \"local\",\n commandsUrl: agent.commandsUrl,\n process: proc,\n appPath: options.app,\n })\n } catch (error) {\n signalProcessTree(proc, \"SIGTERM\")\n throw await withTestingContext(\n error,\n \"deploy\",\n \"Failed while waiting for alien dev to become ready\",\n { statusFile, appPath: options.app, platform: options.platform ?? \"local\" },\n )\n }\n}\n\nfunction signalProcessTree(\n proc: import(\"node:child_process\").ChildProcess,\n signal: NodeJS.Signals,\n): void {\n if (proc.pid && process.platform !== \"win32\") {\n try {\n process.kill(-proc.pid, signal)\n return\n } catch {\n // Fall back to signaling only the direct child.\n }\n }\n\n proc.kill(signal)\n}\n\n// ---------------------------------------------------------------------------\n// Method: api — direct platform API calls (reads ALIEN_API_KEY from env)\n// ---------------------------------------------------------------------------\n\ninterface PlatformDeploymentResponse {\n id: string\n name: string\n status: string\n releaseId: string\n url?: string\n commandsUrl?: string\n}\n\ninterface PlatformReleaseResponse {\n id: string\n version: number\n}\n\nasync function deployViaApi(options: DeployOptions): Promise<Deployment> {\n const platform = options.platform ?? \"local\"\n const verbose = options.verbose ?? process.env.VERBOSE === \"true\"\n\n const apiKey = process.env.ALIEN_API_KEY\n if (!apiKey) {\n throw new Error(\n `Cloud deployment (platform: '${platform}') requires the ALIEN_API_KEY environment variable to be set`,\n )\n }\n\n const apiUrl = process.env.ALIEN_API_URL ?? \"https://api.alien.dev\"\n\n const headers = {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n }\n\n // 1. Build the application\n if (verbose) console.log(\"[testing:api] Building application...\")\n const cliPath = getAlienCliPath(options.app)\n const buildArgs = [\"build\", \"--platform\", platform]\n if (options.config) {\n buildArgs.push(\"--config\", options.config)\n }\n await execFileAsync(cliPath, buildArgs, { cwd: options.app })\n\n // 2. Read the built stack\n const stackPath = resolve(options.app, \".alien\", \"stack.json\")\n if (!existsSync(stackPath)) {\n throw new Error(`Build did not produce stack.json at ${stackPath}`)\n }\n const stack = JSON.parse(readFileSync(stackPath, \"utf-8\"))\n\n // 3. Create a release\n if (verbose) console.log(\"[testing:api] Creating release...\")\n const releaseResp = await fetch(`${apiUrl}/v1/releases`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ stack }),\n })\n\n if (!releaseResp.ok) {\n const body = await releaseResp.text()\n throw new Error(`Failed to create release: ${releaseResp.status} ${body}`)\n }\n\n const release = (await releaseResp.json()) as PlatformReleaseResponse\n\n // 4. Create a deployment\n if (verbose) console.log(\"[testing:api] Creating deployment...\")\n const deploymentName = `e2e-${Date.now()}`\n const deployBody: Record<string, unknown> = {\n releaseId: release.id,\n platform,\n name: deploymentName,\n }\n\n if (options.environmentVariables?.length) {\n deployBody.environmentVariables = options.environmentVariables\n }\n\n const deployResp = await fetch(`${apiUrl}/v1/deployments`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(deployBody),\n })\n\n if (!deployResp.ok) {\n const body = await deployResp.text()\n throw new Error(`Failed to create deployment: ${deployResp.status} ${body}`)\n }\n\n const deployment = (await deployResp.json()) as PlatformDeploymentResponse\n\n // 5. Poll until running\n if (verbose) console.log(`[testing:api] Waiting for deployment ${deployment.id} to be running...`)\n const running = await waitForPlatformDeploymentRunning(apiUrl, apiKey, deployment.id, verbose)\n\n return new Deployment({\n id: running.id,\n name: running.name,\n url: running.url,\n platform,\n commandsUrl: running.commandsUrl!,\n appPath: options.app,\n apiUrl,\n apiKey,\n })\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Wait for `alien dev` to report a ready local session via its status file.\n */\nasync function waitForDevStatusReady(\n statusFile: string,\n hasExited: () => boolean,\n getExitCode: () => number | null,\n getStderr: () => string,\n): Promise<DevStatus> {\n const timeout = 900_000\n const pollInterval = 500\n const start = Date.now()\n\n while (Date.now() - start < timeout) {\n if (hasExited()) {\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"wait-for-ready\",\n message: \"alien dev exited before the local session became ready\",\n details: {\n exitCode: getExitCode(),\n stderrTail: getStderr().slice(-1000),\n },\n }),\n )\n }\n\n if (!existsSync(statusFile)) {\n await new Promise(r => setTimeout(r, pollInterval))\n continue\n }\n\n try {\n const status = JSON.parse(readFileSync(statusFile, \"utf-8\")) as DevStatus\n if (status.status === \"error\") {\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"wait-for-ready\",\n message: \"alien dev reported an error status\",\n details: { status },\n }),\n )\n }\n\n if (status.status === \"ready\" && Object.keys(status.agents ?? {}).length > 0) {\n return status\n }\n } catch (error) {\n if (error instanceof AlienError && error.code === \"TESTING_OPERATION_FAILED\") {\n throw error\n }\n // Status file may be mid-write; retry.\n }\n\n await new Promise(r => setTimeout(r, pollInterval))\n }\n\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"wait-for-ready\",\n message: `Timeout waiting for alien dev to report readiness (${timeout / 1000}s)`,\n details: { statusFile, timeoutMs: timeout },\n }),\n )\n}\n\nfunction findPrimaryAgent(status: DevStatus): DevStatusAgent {\n const agent = Object.values(status.agents ?? {})[0] as DevStatusAgent | undefined\n if (!agent) {\n throw new AlienError(\n TestingOperationFailedError.create({\n operation: \"resolve-agent\",\n message: \"alien dev reported readiness but no agents were present in the status file\",\n details: { status },\n }),\n )\n }\n\n return agent\n}\n\n/**\n * Wait for a platform API deployment to reach \"running\" status.\n */\nasync function waitForPlatformDeploymentRunning(\n apiUrl: string,\n apiKey: string,\n deploymentId: string,\n verbose: boolean,\n): Promise<PlatformDeploymentResponse> {\n const timeout = 900_000 // 15 minutes\n const pollInterval = 5000\n const start = Date.now()\n const headers = { Authorization: `Bearer ${apiKey}` }\n\n while (Date.now() - start < timeout) {\n try {\n const resp = await fetch(`${apiUrl}/v1/deployments/${deploymentId}`, {\n headers,\n signal: AbortSignal.timeout(10000),\n })\n\n if (resp.ok) {\n const data = (await resp.json()) as PlatformDeploymentResponse\n if (verbose) {\n console.log(`[testing] Deployment ${deploymentId} status: ${data.status}`)\n }\n\n // A running deployment may have no URL (e.g. daemon-only stacks) — url stays optional.\n if (data.status === \"running\") {\n return data\n }\n\n if (data.status === \"error\" || data.status.includes(\"failed\")) {\n throw new Error(`Deployment failed with status: ${data.status}`)\n }\n }\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"failed with status\")) {\n throw error\n }\n // Network errors expected during provisioning\n }\n\n await new Promise(r => setTimeout(r, pollInterval))\n }\n\n throw new Error(\n `Timeout waiting for deployment ${deploymentId} to reach running status (${timeout / 1000}s)`,\n )\n}\n\n/**\n * Find the public URL from deployment resources\n */\nfunction findPublicUrl(\n resources: Record<string, { url: string; resourceType?: string | null }>,\n): string | undefined {\n for (const [name, resource] of Object.entries(resources)) {\n if (\n resource.url &&\n (name.includes(\"router\") || name.includes(\"gateway\") || name.includes(\"proxy\"))\n ) {\n return resource.url\n }\n }\n\n const publicResources = Object.entries(resources).filter(\n ([_, r]) => (r.resourceType === \"container\" || r.resourceType === \"worker\") && r.url,\n )\n if (publicResources.length > 0) {\n return publicResources[publicResources.length - 1]![1].url\n }\n\n return undefined\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alienplatform/testing",
|
|
3
|
-
"version": "1.14.
|
|
3
|
+
"version": "1.14.1-dev.e74fae6cd01b61e77a285276f264b5480977f41a",
|
|
4
4
|
"description": "Testing framework for Alien applications",
|
|
5
5
|
"author": "Alien Software, Inc. <hi@alien.dev>",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|
|
@@ -25,11 +25,18 @@
|
|
|
25
25
|
"publishConfig": {
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsdown",
|
|
30
|
+
"dev": "tsdown --watch --no-clean",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:watch": "vitest",
|
|
33
|
+
"test:ts": "tsc --noEmit"
|
|
34
|
+
},
|
|
28
35
|
"dependencies": {
|
|
36
|
+
"@alienplatform/commands": "1.14.1-dev.e74fae6cd01b61e77a285276f264b5480977f41a",
|
|
37
|
+
"@alienplatform/core": "1.14.1-dev.e74fae6cd01b61e77a285276f264b5480977f41a",
|
|
29
38
|
"get-port": "^7.1.0",
|
|
30
|
-
"zod": "4.3.2"
|
|
31
|
-
"@alienplatform/sdk": "1.14.0",
|
|
32
|
-
"@alienplatform/core": "1.14.0"
|
|
39
|
+
"zod": "4.3.2"
|
|
33
40
|
},
|
|
34
41
|
"peerDependencies": {
|
|
35
42
|
"@aws-sdk/client-ssm": "^3.0.0",
|
|
@@ -52,6 +59,7 @@
|
|
|
52
59
|
}
|
|
53
60
|
},
|
|
54
61
|
"devDependencies": {
|
|
62
|
+
"@alienplatform/typescript-config": "workspace:^",
|
|
55
63
|
"@aws-sdk/client-ssm": "^3.0.0",
|
|
56
64
|
"@azure/identity": "^4.0.0",
|
|
57
65
|
"@azure/keyvault-secrets": "^4.0.0",
|
|
@@ -59,14 +67,6 @@
|
|
|
59
67
|
"@types/node": "^24.0.15",
|
|
60
68
|
"tsdown": "^0.13.0",
|
|
61
69
|
"typescript": "^5.8.3",
|
|
62
|
-
"vitest": "^3.1.4"
|
|
63
|
-
"@alienplatform/typescript-config": "^1.0.0"
|
|
64
|
-
},
|
|
65
|
-
"scripts": {
|
|
66
|
-
"build": "tsdown",
|
|
67
|
-
"dev": "tsdown --watch --no-clean",
|
|
68
|
-
"test": "vitest run",
|
|
69
|
-
"test:watch": "vitest",
|
|
70
|
-
"test:ts": "tsc --noEmit"
|
|
70
|
+
"vitest": "^3.1.4"
|
|
71
71
|
}
|
|
72
|
-
}
|
|
72
|
+
}
|
package/LICENSE.md
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
# Functional Source License, Version 1.1, Apache 2.0 Future License
|
|
2
|
-
|
|
3
|
-
## Abbreviation
|
|
4
|
-
|
|
5
|
-
FSL-1.1-Apache-2.0
|
|
6
|
-
|
|
7
|
-
## Notice
|
|
8
|
-
|
|
9
|
-
Copyright 2026 Alien Software, Inc.
|
|
10
|
-
|
|
11
|
-
## Terms and Conditions
|
|
12
|
-
|
|
13
|
-
### Licensor ("We")
|
|
14
|
-
|
|
15
|
-
The party offering the Software under these Terms and Conditions.
|
|
16
|
-
|
|
17
|
-
### The Software
|
|
18
|
-
|
|
19
|
-
The "Software" is each version of the software that we make available under
|
|
20
|
-
these Terms and Conditions, as indicated by our inclusion of these Terms and
|
|
21
|
-
Conditions with the Software.
|
|
22
|
-
|
|
23
|
-
### License Grant
|
|
24
|
-
|
|
25
|
-
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
-
Redistribution and Trademark clauses below, we hereby grant you the right to
|
|
27
|
-
use, copy, modify, create derivative works, publicly perform, publicly display
|
|
28
|
-
and redistribute the Software for any Permitted Purpose identified below.
|
|
29
|
-
|
|
30
|
-
### Permitted Purpose
|
|
31
|
-
|
|
32
|
-
A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
|
|
33
|
-
means making the Software available to others in a commercial product or
|
|
34
|
-
service that:
|
|
35
|
-
|
|
36
|
-
1. substitutes for the Software;
|
|
37
|
-
|
|
38
|
-
2. substitutes for any other product or service we offer using the Software
|
|
39
|
-
that exists as of the date we make the Software available; or
|
|
40
|
-
|
|
41
|
-
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
-
|
|
43
|
-
Permitted Purposes specifically include using the Software:
|
|
44
|
-
|
|
45
|
-
1. for your internal use and access;
|
|
46
|
-
|
|
47
|
-
2. for non-commercial education;
|
|
48
|
-
|
|
49
|
-
3. for non-commercial research; and
|
|
50
|
-
|
|
51
|
-
4. in connection with professional services that you provide to a licensee
|
|
52
|
-
using the Software in accordance with these Terms and Conditions.
|
|
53
|
-
|
|
54
|
-
### Patents
|
|
55
|
-
|
|
56
|
-
To the extent your use for a Permitted Purpose would necessarily infringe our
|
|
57
|
-
patents, the license grant above includes a license under our patents. If you
|
|
58
|
-
make a claim against any party that the Software infringes or contributes to
|
|
59
|
-
the infringement of any patent, then your patent license to the Software ends
|
|
60
|
-
immediately.
|
|
61
|
-
|
|
62
|
-
### Redistribution
|
|
63
|
-
|
|
64
|
-
The Terms and Conditions apply to all copies, modifications and derivatives of
|
|
65
|
-
the Software.
|
|
66
|
-
|
|
67
|
-
If you redistribute any copies, modifications or derivatives of the Software,
|
|
68
|
-
you must include a copy of or a link to these Terms and Conditions and not
|
|
69
|
-
remove any copyright notices provided in or with the Software.
|
|
70
|
-
|
|
71
|
-
### Disclaimer
|
|
72
|
-
|
|
73
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
|
|
74
|
-
IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
|
|
75
|
-
PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
|
|
76
|
-
|
|
77
|
-
IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
|
|
78
|
-
SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
|
|
79
|
-
EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
|
|
80
|
-
|
|
81
|
-
### Trademarks
|
|
82
|
-
|
|
83
|
-
Except for displaying the License Details and identifying us as the origin of
|
|
84
|
-
the Software, you have no right under these Terms and Conditions to use our
|
|
85
|
-
trademarks, trade names, service marks or product names.
|
|
86
|
-
|
|
87
|
-
## Grant of Future License
|
|
88
|
-
|
|
89
|
-
We hereby irrevocably grant you an additional license to use the Software under
|
|
90
|
-
the Apache License, Version 2.0 that is effective on the second anniversary of
|
|
91
|
-
the date we make the Software available. On or after that date, you may use the
|
|
92
|
-
Software under the Apache License, Version 2.0, in which case the following
|
|
93
|
-
will apply:
|
|
94
|
-
|
|
95
|
-
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
96
|
-
this file except in compliance with the License.
|
|
97
|
-
|
|
98
|
-
You may obtain a copy of the License at
|
|
99
|
-
|
|
100
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
101
|
-
|
|
102
|
-
Unless required by applicable law or agreed to in writing, software distributed
|
|
103
|
-
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
104
|
-
CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
105
|
-
specific language governing permissions and limitations under the License.
|