@ankhorage/infra 7.1.6 → 7.1.7

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @ankhorage/infra
2
2
 
3
+ ## 7.1.7
4
+
5
+ ### Patch Changes
6
+
7
+ - e844b0a: Document Infra usage from a runnable public example, keep Renovate configuration out of package documentation, and align the runtime dependency graph with current Contracts collection semantics.
8
+ - 91c1d71: Update Ankhorage dependencies: `@ankhorage/local`, `@ankhorage/minikube`, `@ankhorage/paradox`, `@ankhorage/supabase-vault`, `@ankhorage/supabase`, `@ankhorage/utility`.
9
+
3
10
  ## 7.1.6
4
11
 
5
12
  ### Patch Changes
package/README.md CHANGED
@@ -3,42 +3,62 @@
3
3
 
4
4
  # INFRA
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v7.1.6](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v7.1.7](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![paradox: canonical](././paradox/badges/docs.svg)
7
7
 
8
8
  Executable infra provider and standalone CLI for Ankhorage project workflows.
9
9
 
10
10
  ## Usage
11
11
 
12
- ### Provider-neutral infrastructure lifecycle
12
+ ### CLI
13
13
 
14
- `@ankhorage/infra` resolves only the compute, runtime, and service adapter packages selected by
15
- an environment-aware Infra manifest. Its typed use cases own orchestration, dependency ordering,
16
- safe outputs, deterministic artifacts, and environment-scoped ownership state. Provider packages
17
- own all technology-specific implementation.
14
+ Ankhorage packages expose their command-line interface through `ankh`. Use `ankh --help` to discover available package commands, or run a package command with `--help` for package-specific usage.
18
15
 
19
- The standalone CLI and `ankh infra` expose the same lifecycle:
16
+ ```zsh
17
+ # Install the Ankhorage CLI
18
+ bun add --global @ankhorage/ankh
20
19
 
21
- - `validate`
22
- - `plan`
23
- - `generate`
24
- - `up`
25
- - `status`
26
- - `outputs`
27
- - `down`
28
- - `destroy`
20
+ # Show usage information for infra
21
+ ankh infra --help
22
+ ```
23
+
24
+ ### Explore Infra commands
25
+
26
+ Inspect the commands exposed by the standalone Infra provider.
27
+
28
+ The provider owns the validation, planning, generation, and lifecycle command surface. Select
29
+ an environment explicitly before destructive operations.
30
+
31
+ ```ts
32
+ import { createInfraRuntimeProvider } from '@ankhorage/infra/cli';
33
+ ```
29
34
 
30
- `local` is the only default environment. Destruction always requires an explicit environment and
31
- exact `<project>:<environment>` confirmation. Persistent resources remain retained unless each
32
- exact owned resource is separately authorized with `--delete-resource <adapter>:<resourceId>`.
33
- Environment-style outputs print only explicitly public values with an environment-variable name;
34
- secret outputs remain references.
35
+ ## Configuration
35
36
 
36
- Source: `src/readme-usage.ts`
37
+ ### Example
37
38
 
38
39
  ```ts
39
- import { runInfraCliAsync } from './cli/runInfraCliAsync.js';
40
+ import { defineParadoxConfig } from '@ankhorage/paradox';
41
+
42
+ export default defineParadoxConfig({
43
+ mode: 'write',
44
+
45
+ docs: {
46
+ title: 'INFRA',
47
+ description: 'Executable infra provider and standalone CLI for Ankhorage project workflows.',
48
+ usage: {
49
+ entrypoints: ['examples/basic-usage/main.ts'],
50
+ },
51
+ },
52
+
53
+ package: {
54
+ root: '.',
55
+ entrypoints: ['src/index.ts'],
56
+ },
40
57
 
41
- await runInfraCliAsync(['--help']);
58
+ output: {
59
+ dir: './paradox',
60
+ },
61
+ });
42
62
  ```
43
63
 
44
64
  ## Generated documentation
@@ -52,7 +52,7 @@ export async function prepareInfraOperationAsync(request, operation, dependencie
52
52
  targets: compute.value.targets.length > 0
53
53
  ? compute.value.targets
54
54
  : (request.previous?.targets ?? compute.value.targets),
55
- workloads: [...(environment.value.desired.workloads ?? []), ...workloads.value],
55
+ workloads: [...Object.values(environment.value.desired.workloads ?? {}), ...workloads.value],
56
56
  availableOutputs: mergeOutputs(request.previous?.outputs ?? [], compute.value.outputs),
57
57
  };
58
58
  if (runtimeDesired.targets.length === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"prepareInfraOperationAsync.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/prepareInfraOperationAsync.ts"],"names":[],"mappings":"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","sourcesContent":["import type { InfraDiagnostic, InfraResult } from '@ankhorage/contracts/infra';\n\nimport type {\n InfraOperationRequest,\n InfraOrchestrationDependencies,\n PreparedInfraOperation,\n} from '../../../../types/infraOrchestration.js';\nimport { resolveInfraEnvironment } from '../../domain/resolveInfraEnvironment.js';\nimport { appendInfraFailure } from '../../utils/appendInfraFailure.js';\nimport { createInfraExecutionContext } from '../../utils/createInfraExecutionContext.js';\nimport { collectInfraWorkloadsAsync } from './collectInfraWorkloadsAsync.js';\nimport { resolveInfraAdaptersAsync } from './resolveInfraAdaptersAsync.js';\nimport { validateInfraAdaptersAsync } from './validateInfraAdaptersAsync.js';\n\n/*** Resolve and validate one operation without creating, updating or deleting infrastructure. */\nexport async function prepareInfraOperationAsync(\n request: InfraOperationRequest,\n operation: 'validate' | 'plan' | 'generate' | 'status' | 'outputs' | 'down' | 'destroy',\n dependencies: InfraOrchestrationDependencies,\n): Promise<InfraResult<PreparedInfraOperation>> {\n const diagnostics: InfraDiagnostic[] = [];\n const environment = resolveInfraEnvironment({\n manifest: request.manifest,\n environment: request.environment,\n operation,\n });\n if (!environment.ok) return environment;\n diagnostics.push(...environment.diagnostics);\n if (\n request.previous !== undefined &&\n request.previousDesired !== undefined &&\n !hasSameProviderSelection(request.previousDesired, environment.value.desired)\n ) {\n return {\n ok: false,\n diagnostics: [\n ...diagnostics,\n {\n severity: 'error',\n code: 'infra-provider-selection-changed',\n message:\n 'Stored Infra resources use another provider selection. Destroy that environment before applying the new selection.',\n },\n ],\n };\n }\n const adapters = await resolveInfraAdaptersAsync(\n environment.value.desired,\n dependencies.adapterResolver,\n );\n if (!adapters.ok) return appendInfraFailure(diagnostics, adapters);\n diagnostics.push(...adapters.diagnostics);\n const context = createInfraExecutionContext(request, environment.value, dependencies);\n const validation = await validateInfraAdaptersAsync(context, adapters.value);\n if (!validation.ok) return appendInfraFailure(diagnostics, validation);\n diagnostics.push(...validation.diagnostics);\n const workloads = await collectInfraWorkloadsAsync(context, adapters.value.services);\n if (!workloads.ok) return appendInfraFailure(diagnostics, workloads);\n diagnostics.push(...workloads.diagnostics);\n const compute = await adapters.value.compute.inspectAsync(\n context,\n environment.value.desired.deployment.compute,\n );\n if (!compute.ok) return appendInfraFailure(diagnostics, compute);\n diagnostics.push(...compute.diagnostics);\n const runtimeDesired = {\n selection: environment.value.desired.deployment.runtime,\n targets:\n compute.value.targets.length > 0\n ? compute.value.targets\n : (request.previous?.targets ?? compute.value.targets),\n workloads: [...(environment.value.desired.workloads ?? []), ...workloads.value],\n availableOutputs: mergeOutputs(request.previous?.outputs ?? [], compute.value.outputs),\n };\n if (runtimeDesired.targets.length === 0) {\n diagnostics.push({\n severity: 'info',\n code: 'infra-runtime-target-deferred',\n message: 'Runtime validation is deferred until compute exposes a portable target.',\n });\n } else {\n const runtime = await adapters.value.runtime.validateAsync(context, runtimeDesired);\n if (!runtime.ok) return appendInfraFailure(diagnostics, runtime);\n diagnostics.push(...runtime.diagnostics);\n }\n return {\n ok: true,\n value: {\n environment: environment.value,\n context,\n adapters: adapters.value,\n compute: compute.value,\n runtimeDesired,\n },\n diagnostics,\n };\n}\n\n/*** Compare provider identity only; configuration changes remain normal in-place reconciliation. */\nfunction hasSameProviderSelection(\n previous: PreparedInfraOperation['environment']['desired'],\n current: PreparedInfraOperation['environment']['desired'],\n): boolean {\n return providerSelection(previous).join('\\0') === providerSelection(current).join('\\0');\n}\n\n/*** Read the closed provider slots in stable capability order. */\nfunction providerSelection(\n desired: PreparedInfraOperation['environment']['desired'],\n): readonly (string | undefined)[] {\n return [\n desired.deployment.compute.provider,\n desired.deployment.runtime.provider,\n desired.database?.provider,\n desired.objectStorage?.provider,\n desired.auth?.provider,\n desired.authz?.provider,\n desired.secretStore?.provider,\n ];\n}\n\n/*** Prefer freshly inspected outputs while preserving unrelated safe prior values. */\nfunction mergeOutputs(\n previous: PreparedInfraOperation['runtimeDesired']['availableOutputs'],\n current: PreparedInfraOperation['runtimeDesired']['availableOutputs'],\n): PreparedInfraOperation['runtimeDesired']['availableOutputs'] {\n const currentKeys = new Set(current.map(outputKey));\n return [...previous.filter((output) => !currentKeys.has(outputKey(output))), ...current];\n}\n\n/*** Create one stable public-or-secret output identity without reading its value. */\nfunction outputKey(\n output: PreparedInfraOperation['runtimeDesired']['availableOutputs'][number],\n): string {\n const { owner } = output;\n return `${owner.projectId}\\0${owner.environment}\\0${owner.adapter}\\0${owner.resourceId}\\0${output.name}`;\n}\n"]}
1
+ {"version":3,"file":"prepareInfraOperationAsync.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/prepareInfraOperationAsync.ts"],"names":[],"mappings":"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","sourcesContent":["import type { InfraDiagnostic, InfraResult } from '@ankhorage/contracts/infra';\n\nimport type {\n InfraOperationRequest,\n InfraOrchestrationDependencies,\n PreparedInfraOperation,\n} from '../../../../types/infraOrchestration.js';\nimport { resolveInfraEnvironment } from '../../domain/resolveInfraEnvironment.js';\nimport { appendInfraFailure } from '../../utils/appendInfraFailure.js';\nimport { createInfraExecutionContext } from '../../utils/createInfraExecutionContext.js';\nimport { collectInfraWorkloadsAsync } from './collectInfraWorkloadsAsync.js';\nimport { resolveInfraAdaptersAsync } from './resolveInfraAdaptersAsync.js';\nimport { validateInfraAdaptersAsync } from './validateInfraAdaptersAsync.js';\n\n/*** Resolve and validate one operation without creating, updating or deleting infrastructure. */\nexport async function prepareInfraOperationAsync(\n request: InfraOperationRequest,\n operation: 'validate' | 'plan' | 'generate' | 'status' | 'outputs' | 'down' | 'destroy',\n dependencies: InfraOrchestrationDependencies,\n): Promise<InfraResult<PreparedInfraOperation>> {\n const diagnostics: InfraDiagnostic[] = [];\n const environment = resolveInfraEnvironment({\n manifest: request.manifest,\n environment: request.environment,\n operation,\n });\n if (!environment.ok) return environment;\n diagnostics.push(...environment.diagnostics);\n if (\n request.previous !== undefined &&\n request.previousDesired !== undefined &&\n !hasSameProviderSelection(request.previousDesired, environment.value.desired)\n ) {\n return {\n ok: false,\n diagnostics: [\n ...diagnostics,\n {\n severity: 'error',\n code: 'infra-provider-selection-changed',\n message:\n 'Stored Infra resources use another provider selection. Destroy that environment before applying the new selection.',\n },\n ],\n };\n }\n const adapters = await resolveInfraAdaptersAsync(\n environment.value.desired,\n dependencies.adapterResolver,\n );\n if (!adapters.ok) return appendInfraFailure(diagnostics, adapters);\n diagnostics.push(...adapters.diagnostics);\n const context = createInfraExecutionContext(request, environment.value, dependencies);\n const validation = await validateInfraAdaptersAsync(context, adapters.value);\n if (!validation.ok) return appendInfraFailure(diagnostics, validation);\n diagnostics.push(...validation.diagnostics);\n const workloads = await collectInfraWorkloadsAsync(context, adapters.value.services);\n if (!workloads.ok) return appendInfraFailure(diagnostics, workloads);\n diagnostics.push(...workloads.diagnostics);\n const compute = await adapters.value.compute.inspectAsync(\n context,\n environment.value.desired.deployment.compute,\n );\n if (!compute.ok) return appendInfraFailure(diagnostics, compute);\n diagnostics.push(...compute.diagnostics);\n const runtimeDesired = {\n selection: environment.value.desired.deployment.runtime,\n targets:\n compute.value.targets.length > 0\n ? compute.value.targets\n : (request.previous?.targets ?? compute.value.targets),\n workloads: [...Object.values(environment.value.desired.workloads ?? {}), ...workloads.value],\n availableOutputs: mergeOutputs(request.previous?.outputs ?? [], compute.value.outputs),\n };\n if (runtimeDesired.targets.length === 0) {\n diagnostics.push({\n severity: 'info',\n code: 'infra-runtime-target-deferred',\n message: 'Runtime validation is deferred until compute exposes a portable target.',\n });\n } else {\n const runtime = await adapters.value.runtime.validateAsync(context, runtimeDesired);\n if (!runtime.ok) return appendInfraFailure(diagnostics, runtime);\n diagnostics.push(...runtime.diagnostics);\n }\n return {\n ok: true,\n value: {\n environment: environment.value,\n context,\n adapters: adapters.value,\n compute: compute.value,\n runtimeDesired,\n },\n diagnostics,\n };\n}\n\n/*** Compare provider identity only; configuration changes remain normal in-place reconciliation. */\nfunction hasSameProviderSelection(\n previous: PreparedInfraOperation['environment']['desired'],\n current: PreparedInfraOperation['environment']['desired'],\n): boolean {\n return providerSelection(previous).join('\\0') === providerSelection(current).join('\\0');\n}\n\n/*** Read the closed provider slots in stable capability order. */\nfunction providerSelection(\n desired: PreparedInfraOperation['environment']['desired'],\n): readonly (string | undefined)[] {\n return [\n desired.deployment.compute.provider,\n desired.deployment.runtime.provider,\n desired.database?.provider,\n desired.objectStorage?.provider,\n desired.auth?.provider,\n desired.authz?.provider,\n desired.secretStore?.provider,\n ];\n}\n\n/*** Prefer freshly inspected outputs while preserving unrelated safe prior values. */\nfunction mergeOutputs(\n previous: PreparedInfraOperation['runtimeDesired']['availableOutputs'],\n current: PreparedInfraOperation['runtimeDesired']['availableOutputs'],\n): PreparedInfraOperation['runtimeDesired']['availableOutputs'] {\n const currentKeys = new Set(current.map(outputKey));\n return [...previous.filter((output) => !currentKeys.has(outputKey(output))), ...current];\n}\n\n/*** Create one stable public-or-secret output identity without reading its value. */\nfunction outputKey(\n output: PreparedInfraOperation['runtimeDesired']['availableOutputs'][number],\n): string {\n const { owner } = output;\n return `${owner.projectId}\\0${owner.environment}\\0${owner.adapter}\\0${owner.resourceId}\\0${output.name}`;\n}\n"]}
@@ -41,7 +41,7 @@ export async function upInfraEnvironmentAsync(request, dependencies) {
41
41
  const runtimeDesired = {
42
42
  selection: environment.value.desired.deployment.runtime,
43
43
  targets: compute.value.targets,
44
- workloads: [...(environment.value.desired.workloads ?? []), ...workloads.value],
44
+ workloads: [...Object.values(environment.value.desired.workloads ?? {}), ...workloads.value],
45
45
  availableOutputs: mergeInfraOutputs(request.previous?.outputs ?? [], compute.value.outputs),
46
46
  };
47
47
  const runtimeValidation = await adapters.value.runtime.validateAsync(context, runtimeDesired);
@@ -1 +1 @@
1
- {"version":3,"file":"upInfraEnvironmentAsync.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n InfraDiagnostic,\n InfraExecutionContext,\n InfraOutput,\n InfraOwnedResource,\n InfraResult,\n InfraServiceAdapter,\n} from '@ankhorage/contracts/infra';\n\nimport type {\n InfraOrchestrationDependencies,\n InfraUpOperationResult,\n InfraUpRequest,\n} from '../../../../types/infraOrchestration.js';\nimport { resolveInfraEnvironment } from '../../domain/resolveInfraEnvironment.js';\nimport { appendInfraFailure } from '../../utils/appendInfraFailure.js';\nimport { createInfraExecutionContext } from '../../utils/createInfraExecutionContext.js';\nimport { createInfraLedger } from '../../utils/createInfraLedger.js';\nimport { mergeInfraOutputs } from '../../utils/mergeInfraOutputs.js';\nimport { collectInfraWorkloadsAsync } from './collectInfraWorkloadsAsync.js';\nimport { prepareInfraServicesAsync } from './prepareInfraServicesAsync.js';\nimport { resolveInfraAdaptersAsync } from './resolveInfraAdaptersAsync.js';\nimport { validateInfraAdaptersAsync } from './validateInfraAdaptersAsync.js';\n\n/*** Validate and reconcile compute, service preparation, workloads, runtime and services in order. */\nexport async function upInfraEnvironmentAsync(\n request: InfraUpRequest,\n dependencies: InfraOrchestrationDependencies,\n): Promise<InfraUpOperationResult> {\n const environment = resolveInfraEnvironment({\n manifest: request.manifest,\n environment: request.environment,\n operation: 'up',\n });\n if (!environment.ok) return environment;\n const diagnostics: InfraDiagnostic[] = [...environment.diagnostics];\n const adapters = await resolveInfraAdaptersAsync(\n environment.value.desired,\n dependencies.adapterResolver,\n );\n if (!adapters.ok) return appendInfraFailure(diagnostics, adapters);\n diagnostics.push(...adapters.diagnostics);\n const context = createInfraExecutionContext(request, environment.value, dependencies);\n const validation = await validateInfraAdaptersAsync(context, adapters.value);\n if (!validation.ok) return appendInfraFailure(diagnostics, validation);\n diagnostics.push(...validation.diagnostics);\n const compute = await adapters.value.compute.ensureAsync(\n context,\n environment.value.desired.deployment.compute,\n );\n if (!compute.ok) return appendInfraFailure(diagnostics, compute);\n diagnostics.push(...compute.diagnostics);\n const preparation = await prepareInfraServicesAsync(context, adapters.value.services);\n if (!preparation.ok) return appendInfraFailure(diagnostics, preparation);\n diagnostics.push(...preparation.diagnostics);\n const workloads = await collectInfraWorkloadsAsync(context, adapters.value.services);\n if (!workloads.ok) return appendInfraFailure(diagnostics, workloads);\n diagnostics.push(...workloads.diagnostics);\n const runtimeDesired = {\n selection: environment.value.desired.deployment.runtime,\n targets: compute.value.targets,\n workloads: [...(environment.value.desired.workloads ?? []), ...workloads.value],\n availableOutputs: mergeInfraOutputs(request.previous?.outputs ?? [], compute.value.outputs),\n };\n const runtimeValidation = await adapters.value.runtime.validateAsync(context, runtimeDesired);\n if (!runtimeValidation.ok) return appendInfraFailure(diagnostics, runtimeValidation);\n diagnostics.push(...runtimeValidation.diagnostics);\n const runtime = await adapters.value.runtime.ensureAsync(context, runtimeDesired);\n if (!runtime.ok) return appendInfraFailure(diagnostics, runtime);\n diagnostics.push(...runtime.diagnostics);\n const services = await reconcileServicesAsync(context, adapters.value.services, [\n ...compute.value.outputs,\n ...runtime.value.outputs,\n ]);\n if (!services.ok) return appendInfraFailure(diagnostics, services);\n diagnostics.push(...services.diagnostics);\n const resources = [\n ...compute.value.resources,\n ...runtime.value.resources,\n ...services.value.resources,\n ];\n const outputs = mergeInfraOutputs(\n compute.value.outputs,\n runtime.value.outputs,\n services.value.outputs,\n );\n const ledger = createInfraLedger({\n projectId: request.projectId,\n environment: environment.value.id,\n targets: compute.value.targets,\n resources,\n outputs,\n previous: request.previous,\n });\n return {\n ok: true,\n value: {\n environment: environment.value.id,\n targets: compute.value.targets,\n resources,\n outputs,\n ledger,\n },\n diagnostics,\n };\n}\n\n/*** Reconcile service-owned external state after its runtime workloads expose outputs. */\nasync function reconcileServicesAsync(\n context: InfraExecutionContext,\n services: readonly InfraServiceAdapter[],\n runtimeOutputs: readonly InfraOutput[],\n): Promise<\n InfraResult<{\n readonly resources: readonly InfraOwnedResource[];\n readonly outputs: readonly InfraOutput[];\n }>\n> {\n const resources: InfraOwnedResource[] = [];\n const outputs: InfraOutput[] = [];\n const diagnostics: InfraDiagnostic[] = [];\n for (const service of services) {\n const result = await service.reconcileAsync(context, runtimeOutputs);\n if (!result.ok) return appendInfraFailure(diagnostics, result);\n resources.push(...result.value.resources);\n outputs.push(...result.value.outputs);\n diagnostics.push(...result.diagnostics);\n }\n return { ok: true, value: { resources, outputs }, diagnostics };\n}\n"]}
1
+ {"version":3,"file":"upInfraEnvironmentAsync.js","sourceRoot":"","sources":["../../../../../src/features/environment-lifecycle/application/use-cases/upInfraEnvironmentAsync.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n InfraDiagnostic,\n InfraExecutionContext,\n InfraOutput,\n InfraOwnedResource,\n InfraResult,\n InfraServiceAdapter,\n} from '@ankhorage/contracts/infra';\n\nimport type {\n InfraOrchestrationDependencies,\n InfraUpOperationResult,\n InfraUpRequest,\n} from '../../../../types/infraOrchestration.js';\nimport { resolveInfraEnvironment } from '../../domain/resolveInfraEnvironment.js';\nimport { appendInfraFailure } from '../../utils/appendInfraFailure.js';\nimport { createInfraExecutionContext } from '../../utils/createInfraExecutionContext.js';\nimport { createInfraLedger } from '../../utils/createInfraLedger.js';\nimport { mergeInfraOutputs } from '../../utils/mergeInfraOutputs.js';\nimport { collectInfraWorkloadsAsync } from './collectInfraWorkloadsAsync.js';\nimport { prepareInfraServicesAsync } from './prepareInfraServicesAsync.js';\nimport { resolveInfraAdaptersAsync } from './resolveInfraAdaptersAsync.js';\nimport { validateInfraAdaptersAsync } from './validateInfraAdaptersAsync.js';\n\n/*** Validate and reconcile compute, service preparation, workloads, runtime and services in order. */\nexport async function upInfraEnvironmentAsync(\n request: InfraUpRequest,\n dependencies: InfraOrchestrationDependencies,\n): Promise<InfraUpOperationResult> {\n const environment = resolveInfraEnvironment({\n manifest: request.manifest,\n environment: request.environment,\n operation: 'up',\n });\n if (!environment.ok) return environment;\n const diagnostics: InfraDiagnostic[] = [...environment.diagnostics];\n const adapters = await resolveInfraAdaptersAsync(\n environment.value.desired,\n dependencies.adapterResolver,\n );\n if (!adapters.ok) return appendInfraFailure(diagnostics, adapters);\n diagnostics.push(...adapters.diagnostics);\n const context = createInfraExecutionContext(request, environment.value, dependencies);\n const validation = await validateInfraAdaptersAsync(context, adapters.value);\n if (!validation.ok) return appendInfraFailure(diagnostics, validation);\n diagnostics.push(...validation.diagnostics);\n const compute = await adapters.value.compute.ensureAsync(\n context,\n environment.value.desired.deployment.compute,\n );\n if (!compute.ok) return appendInfraFailure(diagnostics, compute);\n diagnostics.push(...compute.diagnostics);\n const preparation = await prepareInfraServicesAsync(context, adapters.value.services);\n if (!preparation.ok) return appendInfraFailure(diagnostics, preparation);\n diagnostics.push(...preparation.diagnostics);\n const workloads = await collectInfraWorkloadsAsync(context, adapters.value.services);\n if (!workloads.ok) return appendInfraFailure(diagnostics, workloads);\n diagnostics.push(...workloads.diagnostics);\n const runtimeDesired = {\n selection: environment.value.desired.deployment.runtime,\n targets: compute.value.targets,\n workloads: [...Object.values(environment.value.desired.workloads ?? {}), ...workloads.value],\n availableOutputs: mergeInfraOutputs(request.previous?.outputs ?? [], compute.value.outputs),\n };\n const runtimeValidation = await adapters.value.runtime.validateAsync(context, runtimeDesired);\n if (!runtimeValidation.ok) return appendInfraFailure(diagnostics, runtimeValidation);\n diagnostics.push(...runtimeValidation.diagnostics);\n const runtime = await adapters.value.runtime.ensureAsync(context, runtimeDesired);\n if (!runtime.ok) return appendInfraFailure(diagnostics, runtime);\n diagnostics.push(...runtime.diagnostics);\n const services = await reconcileServicesAsync(context, adapters.value.services, [\n ...compute.value.outputs,\n ...runtime.value.outputs,\n ]);\n if (!services.ok) return appendInfraFailure(diagnostics, services);\n diagnostics.push(...services.diagnostics);\n const resources = [\n ...compute.value.resources,\n ...runtime.value.resources,\n ...services.value.resources,\n ];\n const outputs = mergeInfraOutputs(\n compute.value.outputs,\n runtime.value.outputs,\n services.value.outputs,\n );\n const ledger = createInfraLedger({\n projectId: request.projectId,\n environment: environment.value.id,\n targets: compute.value.targets,\n resources,\n outputs,\n previous: request.previous,\n });\n return {\n ok: true,\n value: {\n environment: environment.value.id,\n targets: compute.value.targets,\n resources,\n outputs,\n ledger,\n },\n diagnostics,\n };\n}\n\n/*** Reconcile service-owned external state after its runtime workloads expose outputs. */\nasync function reconcileServicesAsync(\n context: InfraExecutionContext,\n services: readonly InfraServiceAdapter[],\n runtimeOutputs: readonly InfraOutput[],\n): Promise<\n InfraResult<{\n readonly resources: readonly InfraOwnedResource[];\n readonly outputs: readonly InfraOutput[];\n }>\n> {\n const resources: InfraOwnedResource[] = [];\n const outputs: InfraOutput[] = [];\n const diagnostics: InfraDiagnostic[] = [];\n for (const service of services) {\n const result = await service.reconcileAsync(context, runtimeOutputs);\n if (!result.ok) return appendInfraFailure(diagnostics, result);\n resources.push(...result.value.resources);\n outputs.push(...result.value.outputs);\n diagnostics.push(...result.diagnostics);\n }\n return { ok: true, value: { resources, outputs }, diagnostics };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"testSupport.d.ts","sourceRoot":"","sources":["../src/testSupport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,SAAU,GAChB,sBAAsB,CAmBxB;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,GAAE;IACJ,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CACxB,GACL,OAAO,CAAC;IACT,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC,CA6BD;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,WAAW,CAAC,OAAO,CAUzB,GACA,WAAW,CAwBb"}
1
+ {"version":3,"file":"testSupport.d.ts","sourceRoot":"","sources":["../src/testSupport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAKxD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,SAAU,GAChB,sBAAsB,CAmBxB;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,GAAE;IACJ,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CACxB,GACL,OAAO,CAAC;IACT,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B,CAAC,CA6BD;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,WAAW,CAAC,OAAO,CAUzB,GACA,WAAW,CA+Bb"}
@@ -49,7 +49,7 @@ export function createAppManifest(projectId, infra = {
49
49
  },
50
50
  },
51
51
  },
52
- modules: [],
52
+ modules: {},
53
53
  }) {
54
54
  return {
55
55
  metadata: {
@@ -59,7 +59,14 @@ export function createAppManifest(projectId, infra = {
59
59
  category: 'developer_tools',
60
60
  themeId: 'default',
61
61
  },
62
- themes: [],
62
+ themes: {
63
+ default: {
64
+ id: 'default',
65
+ name: 'Default',
66
+ light: { primaryColor: '#3366ff', harmony: 'analogous' },
67
+ dark: { primaryColor: '#6699ff', harmony: 'analogous' },
68
+ },
69
+ },
63
70
  activeThemeId: 'default',
64
71
  infra,
65
72
  navigator: {
@@ -1 +1 @@
1
- {"version":3,"file":"testSupport.js","sourceRoot":"","sources":["../src/testSupport.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppManifest } from '@ankhorage/contracts';\nimport { promises as fs } from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport type { InfraCommandContext } from './types/infraCli.js';\n\nexport interface CapturedCommandContext {\n readonly context: InfraCommandContext;\n readonly stderr: { value: string };\n readonly stdout: { value: string };\n}\n\nexport function createCapturedCommandContext(\n cwd: string,\n version = '0.2.1',\n): CapturedCommandContext {\n const stdout = { value: '' };\n const stderr = { value: '' };\n\n return {\n stdout,\n stderr,\n context: {\n cwd,\n env: process.env,\n version,\n writeStdout(text: string) {\n stdout.value += text;\n },\n writeStderr(text: string) {\n stderr.value += text;\n },\n },\n };\n}\n\nexport async function createWorkspaceFixture(\n args: {\n readonly manifest?: AppManifest;\n readonly manifestFile?: 'invalid-json' | 'missing';\n readonly projectId?: string;\n } = {},\n): Promise<{\n readonly appsRoot: string;\n readonly projectId: string;\n readonly projectPath: string;\n readonly rootPath: string;\n}> {\n const rootPath = await fs.mkdtemp(path.join(os.tmpdir(), 'ankhorage-infra-'));\n const appsRoot = path.join(rootPath, 'apps');\n const projectId = args.projectId ?? 'shop';\n const projectPath = path.join(appsRoot, projectId);\n\n await fs.mkdir(projectPath, { recursive: true });\n await fs.writeFile(\n path.join(projectPath, 'package.json'),\n JSON.stringify({ name: projectId, version: '1.0.0' }, null, 2),\n 'utf8',\n );\n\n if (args.manifestFile === 'invalid-json') {\n await fs.writeFile(path.join(projectPath, 'ankh.config.json'), '{invalid', 'utf8');\n } else if (args.manifestFile !== 'missing') {\n await fs.writeFile(\n path.join(projectPath, 'ankh.config.json'),\n `${JSON.stringify(args.manifest ?? createAppManifest(projectId), null, 2)}\\n`,\n 'utf8',\n );\n }\n\n return {\n appsRoot,\n projectId,\n projectPath,\n rootPath,\n };\n}\n\nexport function createAppManifest(\n projectId: string,\n infra: AppManifest['infra'] = {\n environments: {\n local: {\n deployment: {\n compute: { provider: 'local' },\n runtime: { provider: 'docker-compose' },\n },\n },\n },\n modules: [],\n },\n): AppManifest {\n return {\n metadata: {\n name: projectId,\n slug: projectId,\n version: '1.0.0',\n category: 'developer_tools',\n themeId: 'default',\n },\n themes: [],\n activeThemeId: 'default',\n infra,\n navigator: {\n type: 'stack',\n routes: [{ name: 'index', screenId: 'index' }],\n },\n screens: {},\n settings: {\n localization: {\n defaultLocale: 'en',\n locales: ['en'],\n },\n },\n };\n}\n"]}
1
+ {"version":3,"file":"testSupport.js","sourceRoot":"","sources":["../src/testSupport.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppManifest } from '@ankhorage/contracts';\nimport { promises as fs } from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport type { InfraCommandContext } from './types/infraCli.js';\n\nexport interface CapturedCommandContext {\n readonly context: InfraCommandContext;\n readonly stderr: { value: string };\n readonly stdout: { value: string };\n}\n\nexport function createCapturedCommandContext(\n cwd: string,\n version = '0.2.1',\n): CapturedCommandContext {\n const stdout = { value: '' };\n const stderr = { value: '' };\n\n return {\n stdout,\n stderr,\n context: {\n cwd,\n env: process.env,\n version,\n writeStdout(text: string) {\n stdout.value += text;\n },\n writeStderr(text: string) {\n stderr.value += text;\n },\n },\n };\n}\n\nexport async function createWorkspaceFixture(\n args: {\n readonly manifest?: AppManifest;\n readonly manifestFile?: 'invalid-json' | 'missing';\n readonly projectId?: string;\n } = {},\n): Promise<{\n readonly appsRoot: string;\n readonly projectId: string;\n readonly projectPath: string;\n readonly rootPath: string;\n}> {\n const rootPath = await fs.mkdtemp(path.join(os.tmpdir(), 'ankhorage-infra-'));\n const appsRoot = path.join(rootPath, 'apps');\n const projectId = args.projectId ?? 'shop';\n const projectPath = path.join(appsRoot, projectId);\n\n await fs.mkdir(projectPath, { recursive: true });\n await fs.writeFile(\n path.join(projectPath, 'package.json'),\n JSON.stringify({ name: projectId, version: '1.0.0' }, null, 2),\n 'utf8',\n );\n\n if (args.manifestFile === 'invalid-json') {\n await fs.writeFile(path.join(projectPath, 'ankh.config.json'), '{invalid', 'utf8');\n } else if (args.manifestFile !== 'missing') {\n await fs.writeFile(\n path.join(projectPath, 'ankh.config.json'),\n `${JSON.stringify(args.manifest ?? createAppManifest(projectId), null, 2)}\\n`,\n 'utf8',\n );\n }\n\n return {\n appsRoot,\n projectId,\n projectPath,\n rootPath,\n };\n}\n\nexport function createAppManifest(\n projectId: string,\n infra: AppManifest['infra'] = {\n environments: {\n local: {\n deployment: {\n compute: { provider: 'local' },\n runtime: { provider: 'docker-compose' },\n },\n },\n },\n modules: {},\n },\n): AppManifest {\n return {\n metadata: {\n name: projectId,\n slug: projectId,\n version: '1.0.0',\n category: 'developer_tools',\n themeId: 'default',\n },\n themes: {\n default: {\n id: 'default',\n name: 'Default',\n light: { primaryColor: '#3366ff', harmony: 'analogous' },\n dark: { primaryColor: '#6699ff', harmony: 'analogous' },\n },\n },\n activeThemeId: 'default',\n infra,\n navigator: {\n type: 'stack',\n routes: [{ name: 'index', screenId: 'index' }],\n },\n screens: {},\n settings: {\n localization: {\n defaultLocale: 'en',\n locales: ['en'],\n },\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/infra",
3
3
  "type": "module",
4
- "version": "7.1.6",
4
+ "version": "7.1.7",
5
5
  "description": "Project-aware infrastructure generation library and executable Ankh provider for Ankhorage.",
6
6
  "homepage": "https://github.com/ankhorage/infra#readme",
7
7
  "bugs": {
@@ -36,8 +36,8 @@
36
36
  ],
37
37
  "dependencies": {
38
38
  "@ankhorage/ankh": "^0.10.4",
39
- "@ankhorage/contracts": "^21.0.0",
40
- "@ankhorage/utility": "^1.2.0"
39
+ "@ankhorage/contracts": "^22.8.2",
40
+ "@ankhorage/utility": "^1.9.0"
41
41
  },
42
42
  "files": [
43
43
  "dist",
@@ -113,16 +113,16 @@
113
113
  },
114
114
  "devDependencies": {
115
115
  "@ankhorage/cerbos": "^0.2.0",
116
- "@ankhorage/devtools": "^1.17.2",
116
+ "@ankhorage/devtools": "^1.21.3",
117
117
  "@ankhorage/docker-compose": "^0.5.3",
118
118
  "@ankhorage/hetzner": "^0.3.0",
119
119
  "@ankhorage/k3s": "^0.4.1",
120
- "@ankhorage/local": "^0.3.0",
121
- "@ankhorage/minikube": "^0.4.4",
122
- "@ankhorage/paradox": "^0.1.26",
120
+ "@ankhorage/local": "^0.3.2",
121
+ "@ankhorage/minikube": "^0.4.16",
122
+ "@ankhorage/paradox": "^0.2.8",
123
123
  "@ankhorage/r2": "^0.2.0",
124
- "@ankhorage/supabase": "^0.5.13",
125
- "@ankhorage/supabase-vault": "^0.3.4",
124
+ "@ankhorage/supabase": "^0.5.14",
125
+ "@ankhorage/supabase-vault": "^0.3.12",
126
126
  "@types/bun": "^1.4.1",
127
127
  "@types/node": "^25.6.0",
128
128
  "typescript": "^5.9.3"
@@ -69,7 +69,7 @@ export async function prepareInfraOperationAsync(
69
69
  compute.value.targets.length > 0
70
70
  ? compute.value.targets
71
71
  : (request.previous?.targets ?? compute.value.targets),
72
- workloads: [...(environment.value.desired.workloads ?? []), ...workloads.value],
72
+ workloads: [...Object.values(environment.value.desired.workloads ?? {}), ...workloads.value],
73
73
  availableOutputs: mergeOutputs(request.previous?.outputs ?? [], compute.value.outputs),
74
74
  };
75
75
  if (runtimeDesired.targets.length === 0) {
@@ -59,7 +59,7 @@ export async function upInfraEnvironmentAsync(
59
59
  const runtimeDesired = {
60
60
  selection: environment.value.desired.deployment.runtime,
61
61
  targets: compute.value.targets,
62
- workloads: [...(environment.value.desired.workloads ?? []), ...workloads.value],
62
+ workloads: [...Object.values(environment.value.desired.workloads ?? {}), ...workloads.value],
63
63
  availableOutputs: mergeInfraOutputs(request.previous?.outputs ?? [], compute.value.outputs),
64
64
  };
65
65
  const runtimeValidation = await adapters.value.runtime.validateAsync(context, runtimeDesired);
@@ -58,11 +58,11 @@ const manifest = {
58
58
  },
59
59
  database: { provider: 'supabase', tier: 'dev' },
60
60
  auth: { provider: 'supabase' },
61
- objectStorage: { provider: 'supabase', buckets: [bucket] },
61
+ objectStorage: { provider: 'supabase', buckets: { [bucket]: true } },
62
62
  networking: { publicBaseUrl },
63
63
  },
64
64
  },
65
- modules: [],
65
+ modules: {},
66
66
  } as const satisfies InfraManifest;
67
67
 
68
68
  test('runs local k3s and Supabase through the portable compute lifecycle', async () => {
@@ -40,11 +40,11 @@ const manifest = {
40
40
  },
41
41
  database: { provider: 'supabase', tier: 'dev' },
42
42
  auth: { provider: 'supabase' },
43
- objectStorage: { provider: 'supabase', buckets: [bucket] },
43
+ objectStorage: { provider: 'supabase', buckets: { [bucket]: true } },
44
44
  networking: { publicBaseUrl: baseUrl },
45
45
  },
46
46
  },
47
- modules: [],
47
+ modules: {},
48
48
  } as const satisfies InfraManifest;
49
49
 
50
50
  test.skipIf(process.env.ANKH_INFRA_MINIKUBE_SUPABASE_E2E !== '1')(
@@ -1,4 +1,7 @@
1
1
  import { createHmac } from 'node:crypto';
2
+ import { mkdtemp, rm } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
2
5
 
3
6
  import type {
4
7
  InfraControlPlaneCredentialRef,
@@ -21,10 +24,8 @@ const namespace = `${projectId}-local`;
21
24
  const baseUrl = 'http://127.0.0.1:54322';
22
25
  const logicalBucket = 'phase10-objects';
23
26
  const physicalBucket = 'phase10-persistence';
24
- const minioContainer = 'infra145-minio-recovery';
25
27
  const minioHostEndpoint = 'http://127.0.0.1:19000';
26
28
  const minioPodEndpoint = 'http://host.minikube.internal:19000';
27
- const minioImage = 'quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z';
28
29
  const s3AccessKey = 'phase10-access';
29
30
  const s3SecretKey = 'phase10-secret-key';
30
31
  const databaseMarker = 'database-survived-from-s3-backup';
@@ -59,20 +60,19 @@ const manifest = {
59
60
  auth: { provider: 'supabase' },
60
61
  objectStorage: {
61
62
  provider: 'supabase',
62
- buckets: [logicalBucket],
63
+ buckets: { [logicalBucket]: true },
63
64
  backend: persistenceTarget,
64
65
  },
65
66
  networking: { publicBaseUrl: baseUrl },
66
67
  },
67
68
  },
68
- modules: [],
69
+ modules: {},
69
70
  } as const satisfies InfraManifest;
70
71
 
71
72
  test.skipIf(process.env.ANKH_INFRA_MINIKUBE_SUPABASE_RECOVERY_E2E !== '1')(
72
73
  'recovers a fresh Minikube Supabase database while S3-backed Storage remains off-cluster',
73
74
  async () => {
74
- await stopMinioAsync();
75
- await startMinioAsync();
75
+ const minio = await startMinioAsync();
76
76
  try {
77
77
  const dependencies = createDependencies();
78
78
  const firstUp = requireSuccess(
@@ -110,56 +110,59 @@ test.skipIf(process.env.ANKH_INFRA_MINIKUBE_SUPABASE_RECOVERY_E2E !== '1')(
110
110
  throw new Error(`${message}\nRecovery diagnostics: ${diagnostics}`, { cause: error });
111
111
  } finally {
112
112
  await runAllowFailureAsync(['minikube', 'delete', '-p', profile]);
113
- await stopMinioAsync();
113
+ await stopMinioAsync(minio);
114
114
  }
115
115
  },
116
116
  1_200_000,
117
117
  );
118
118
 
119
- async function startMinioAsync(): Promise<void> {
120
- await runAsync(
121
- [
122
- 'docker',
123
- 'run',
124
- '--detach',
125
- '--rm',
126
- '--name',
127
- minioContainer,
128
- '--publish',
129
- '19000:9000',
130
- '--env',
131
- `MINIO_ROOT_USER=${s3AccessKey}`,
132
- '--env',
133
- `MINIO_ROOT_PASSWORD=${s3SecretKey}`,
134
- minioImage,
135
- 'server',
136
- '/data',
137
- '--address',
138
- ':9000',
139
- ],
140
- 'start MinIO',
141
- );
142
- await waitForMinioAsync();
143
- await runAsync(
144
- [
145
- 'curl',
146
- '--fail',
147
- '--silent',
148
- '--show-error',
149
- '--request',
150
- 'PUT',
151
- '--aws-sigv4',
152
- 'aws:amz:us-east-1:s3',
153
- '--user',
154
- `${s3AccessKey}:${s3SecretKey}`,
155
- `${minioHostEndpoint}/${physicalBucket}`,
156
- ],
157
- 'create MinIO bucket',
158
- );
119
+ interface MinioServer {
120
+ readonly subprocess: ReturnType<typeof Bun.spawn>;
121
+ readonly dataDirectory: string;
122
+ }
123
+
124
+ async function startMinioAsync(): Promise<MinioServer> {
125
+ const dataDirectory = await mkdtemp(join(tmpdir(), 'infra145-minio-'));
126
+ const subprocess = Bun.spawn(['minio', 'server', dataDirectory, '--address', ':19000'], {
127
+ env: {
128
+ ...process.env,
129
+ MINIO_ROOT_USER: s3AccessKey,
130
+ MINIO_ROOT_PASSWORD: s3SecretKey,
131
+ },
132
+ stdout: 'inherit',
133
+ stderr: 'inherit',
134
+ });
135
+ const server = { subprocess, dataDirectory };
136
+ try {
137
+ await waitForMinioAsync(subprocess);
138
+ await runAsync(
139
+ [
140
+ 'curl',
141
+ '--fail',
142
+ '--silent',
143
+ '--show-error',
144
+ '--request',
145
+ 'PUT',
146
+ '--aws-sigv4',
147
+ 'aws:amz:us-east-1:s3',
148
+ '--user',
149
+ `${s3AccessKey}:${s3SecretKey}`,
150
+ `${minioHostEndpoint}/${physicalBucket}`,
151
+ ],
152
+ 'create MinIO bucket',
153
+ );
154
+ return server;
155
+ } catch (error) {
156
+ await stopMinioAsync(server);
157
+ throw error;
158
+ }
159
159
  }
160
160
 
161
- async function waitForMinioAsync(): Promise<void> {
161
+ async function waitForMinioAsync(subprocess: MinioServer['subprocess']): Promise<void> {
162
162
  for (const _attempt of Array.from({ length: 60 }, (_, index) => index)) {
163
+ if (subprocess.exitCode !== null) {
164
+ throw new Error(`MinIO exited before becoming ready with code ${subprocess.exitCode}.`);
165
+ }
163
166
  const response = await fetch(`${minioHostEndpoint}/minio/health/live`).catch(() => undefined);
164
167
  if (response?.ok === true) return;
165
168
  await Bun.sleep(500);
@@ -167,8 +170,10 @@ async function waitForMinioAsync(): Promise<void> {
167
170
  throw new Error('MinIO did not become ready.');
168
171
  }
169
172
 
170
- async function stopMinioAsync(): Promise<void> {
171
- await runAllowFailureAsync(['docker', 'rm', '--force', minioContainer]);
173
+ async function stopMinioAsync(server: MinioServer): Promise<void> {
174
+ if (server.subprocess.exitCode === null) server.subprocess.kill();
175
+ await server.subprocess.exited;
176
+ await rm(server.dataDirectory, { recursive: true, force: true });
172
177
  }
173
178
 
174
179
  async function writeDatabaseMarkerAsync(): Promise<void> {
@@ -88,7 +88,7 @@ export function createAppManifest(
88
88
  },
89
89
  },
90
90
  },
91
- modules: [],
91
+ modules: {},
92
92
  },
93
93
  ): AppManifest {
94
94
  return {
@@ -99,7 +99,14 @@ export function createAppManifest(
99
99
  category: 'developer_tools',
100
100
  themeId: 'default',
101
101
  },
102
- themes: [],
102
+ themes: {
103
+ default: {
104
+ id: 'default',
105
+ name: 'Default',
106
+ light: { primaryColor: '#3366ff', harmony: 'analogous' },
107
+ dark: { primaryColor: '#6699ff', harmony: 'analogous' },
108
+ },
109
+ },
103
110
  activeThemeId: 'default',
104
111
  infra,
105
112
  navigator: {
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=readme-usage.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"readme-usage.d.ts","sourceRoot":"","sources":["../src/readme-usage.ts"],"names":[],"mappings":""}
@@ -1,30 +0,0 @@
1
- import { runInfraCliAsync } from './cli/runInfraCliAsync.js';
2
- /***
3
- * Provider-neutral infrastructure lifecycle
4
- *
5
- * `@ankhorage/infra` resolves only the compute, runtime, and service adapter packages selected by
6
- * an environment-aware Infra manifest. Its typed use cases own orchestration, dependency ordering,
7
- * safe outputs, deterministic artifacts, and environment-scoped ownership state. Provider packages
8
- * own all technology-specific implementation.
9
- *
10
- * The standalone CLI and `ankh infra` expose the same lifecycle:
11
- *
12
- * - `validate`
13
- * - `plan`
14
- * - `generate`
15
- * - `up`
16
- * - `status`
17
- * - `outputs`
18
- * - `down`
19
- * - `destroy`
20
- *
21
- * `local` is the only default environment. Destruction always requires an explicit environment and
22
- * exact `<project>:<environment>` confirmation. Persistent resources remain retained unless each
23
- * exact owned resource is separately authorized with `--delete-resource <adapter>:<resourceId>`.
24
- * Environment-style outputs print only explicitly public values with an environment-variable name;
25
- * secret outputs remain references.
26
- *
27
- * @usage
28
- */
29
- await runInfraCliAsync(['--help']);
30
- //# sourceMappingURL=readme-usage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"readme-usage.js","sourceRoot":"","sources":["../src/readme-usage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,gBAAgB,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC","sourcesContent":["import { runInfraCliAsync } from './cli/runInfraCliAsync.js';\n\n/***\n * Provider-neutral infrastructure lifecycle\n *\n * `@ankhorage/infra` resolves only the compute, runtime, and service adapter packages selected by\n * an environment-aware Infra manifest. Its typed use cases own orchestration, dependency ordering,\n * safe outputs, deterministic artifacts, and environment-scoped ownership state. Provider packages\n * own all technology-specific implementation.\n *\n * The standalone CLI and `ankh infra` expose the same lifecycle:\n *\n * - `validate`\n * - `plan`\n * - `generate`\n * - `up`\n * - `status`\n * - `outputs`\n * - `down`\n * - `destroy`\n *\n * `local` is the only default environment. Destruction always requires an explicit environment and\n * exact `<project>:<environment>` confirmation. Persistent resources remain retained unless each\n * exact owned resource is separately authorized with `--delete-resource <adapter>:<resourceId>`.\n * Environment-style outputs print only explicitly public values with an environment-variable name;\n * secret outputs remain references.\n *\n * @usage\n */\nawait runInfraCliAsync(['--help']);\n"]}
@@ -1,30 +0,0 @@
1
- import { runInfraCliAsync } from './cli/runInfraCliAsync.js';
2
-
3
- /***
4
- * Provider-neutral infrastructure lifecycle
5
- *
6
- * `@ankhorage/infra` resolves only the compute, runtime, and service adapter packages selected by
7
- * an environment-aware Infra manifest. Its typed use cases own orchestration, dependency ordering,
8
- * safe outputs, deterministic artifacts, and environment-scoped ownership state. Provider packages
9
- * own all technology-specific implementation.
10
- *
11
- * The standalone CLI and `ankh infra` expose the same lifecycle:
12
- *
13
- * - `validate`
14
- * - `plan`
15
- * - `generate`
16
- * - `up`
17
- * - `status`
18
- * - `outputs`
19
- * - `down`
20
- * - `destroy`
21
- *
22
- * `local` is the only default environment. Destruction always requires an explicit environment and
23
- * exact `<project>:<environment>` confirmation. Persistent resources remain retained unless each
24
- * exact owned resource is separately authorized with `--delete-resource <adapter>:<resourceId>`.
25
- * Environment-style outputs print only explicitly public values with an environment-variable name;
26
- * secret outputs remain references.
27
- *
28
- * @usage
29
- */
30
- await runInfraCliAsync(['--help']);