@crossdelta/infrastructure 0.2.27 → 0.3.0-beta.2

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.
@@ -37,8 +37,7 @@ const resolveNumber = (value: string, fileContent: string): number | undefined =
37
37
  }
38
38
 
39
39
  const extract = {
40
- string: (content: string, pattern: RegExp): string | undefined =>
41
- content.match(pattern)?.[1],
40
+ string: (content: string, pattern: RegExp): string | undefined => content.match(pattern)?.[1],
42
41
 
43
42
  number: (content: string, pattern: RegExp): number | undefined => {
44
43
  const match = content.match(pattern)?.[1]
@@ -72,7 +71,7 @@ const loadPulumiConfig = async (infraDir: string, stack: string): Promise<string
72
71
  try {
73
72
  const result = Bun.spawnSync(['pulumi', 'config', '--show-secrets', '--json', '--stack', stack, '--cwd', infraDir])
74
73
  if (result.exitCode !== 0) return []
75
-
74
+
76
75
  const config = JSON.parse(result.stdout.toString()) as Record<string, PulumiConfigEntry>
77
76
 
78
77
  return Object.entries(config)
@@ -89,10 +88,8 @@ const loadPulumiConfig = async (infraDir: string, stack: string): Promise<string
89
88
 
90
89
  const discoverServices = (servicesDir: string): MinimalServiceConfig[] => {
91
90
  if (!existsSync(servicesDir)) return []
92
-
93
- const files = readdirSync(servicesDir).filter(
94
- (file) => file.endsWith('.ts') && file !== 'index.ts'
95
- )
91
+
92
+ const files = readdirSync(servicesDir).filter((file) => file.endsWith('.ts') && file !== 'index.ts')
96
93
 
97
94
  return files.map((file) => {
98
95
  const content = readFileSync(join(servicesDir, file), 'utf-8')
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Compatibility helpers for migrating from old port models to unified port config.
3
+ *
4
+ * These helpers allow gradual migration from the inconsistent
5
+ * httpPort/internalPorts/containerPort model to the unified ServicePorts model.
6
+ */
7
+ import type { ServicePorts } from './types';
8
+ /**
9
+ * Legacy port configuration (App Platform style).
10
+ */
11
+ export interface LegacyAppPlatformPorts {
12
+ /** Public HTTP port */
13
+ httpPort?: number;
14
+ /** Internal-only ports */
15
+ internalPorts?: number[];
16
+ }
17
+ /**
18
+ * Legacy port configuration (Kubernetes style).
19
+ */
20
+ export interface LegacyK8sPorts {
21
+ /** Container port */
22
+ containerPort: number;
23
+ /** Additional ports */
24
+ additionalPorts?: Array<{
25
+ name: string;
26
+ port: number;
27
+ targetPort?: number;
28
+ protocol?: 'TCP' | 'UDP';
29
+ }>;
30
+ }
31
+ /**
32
+ * Convert legacy App Platform port config to unified model.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * // Old style
37
+ * { httpPort: 3000 }
38
+ *
39
+ * // Converts to
40
+ * { primary: { port: 3000, name: 'http', public: true } }
41
+ * ```
42
+ */
43
+ export declare function fromAppPlatformPorts(config: LegacyAppPlatformPorts): ServicePorts;
44
+ /**
45
+ * Convert legacy Kubernetes port config to unified model.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * // Old style
50
+ * { containerPort: 4001 }
51
+ *
52
+ * // Converts to
53
+ * { primary: { port: 4001, name: 'http' } }
54
+ * ```
55
+ */
56
+ export declare function fromK8sPorts(config: LegacyK8sPorts): ServicePorts;
57
+ /**
58
+ * Extract primary port number from ServicePorts (for backward compatibility).
59
+ */
60
+ export declare function getPrimaryPort(ports: ServicePorts): number;
61
+ /**
62
+ * Get all port numbers from ServicePorts.
63
+ */
64
+ export declare function getAllPorts(ports: ServicePorts): number[];
65
+ /**
66
+ * Get public ports from ServicePorts.
67
+ */
68
+ export declare function getPublicPorts(ports: ServicePorts): number[];
69
+ /**
70
+ * Check if any port is public.
71
+ */
72
+ export declare function hasPublicPort(ports: ServicePorts): boolean;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Core provider-agnostic infrastructure types and utilities.
3
+ *
4
+ * This module provides the foundation for multi-cloud infrastructure management.
5
+ */
6
+ export * from './compat';
7
+ export * from './runtime';
8
+ export * from './types';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Runtime detection utilities
3
+ *
4
+ * Separate from main runtime.ts to avoid Pulumi imports in tests
5
+ */
6
+ /**
7
+ * Detect runtime from environment or configuration.
8
+ *
9
+ * Priority:
10
+ * 1. INFRASTRUCTURE_PROVIDER env var
11
+ * 2. Default to 'doks'
12
+ *
13
+ * Note: Pulumi config detection is handled in the main runtime.ts file
14
+ */
15
+ export declare function detectRuntimeProvider(): string;
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Runtime adapter interfaces for provider-agnostic infrastructure management.
3
+ *
4
+ * Each cloud provider (DOKS, EKS, AKS, GKE) implements these interfaces
5
+ * to provide a consistent API across different platforms.
6
+ */
7
+ import * as pulumi from '@pulumi/pulumi';
8
+ import type { ClusterDeploymentResult, CoreClusterConfig, CoreNetworkConfig, CoreServiceConfig, ServiceDeploymentResult } from './types';
9
+ /**
10
+ * Runtime adapter for a specific cloud provider.
11
+ *
12
+ * Each provider implements this interface to translate core configurations
13
+ * into provider-specific resources.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Create DOKS adapter
18
+ * const runtime = createDOKSRuntime()
19
+ *
20
+ * // Deploy cluster
21
+ * const cluster = await runtime.createCluster(clusterConfig)
22
+ *
23
+ * // Deploy services
24
+ * const service = await runtime.deployService(serviceConfig, cluster.provider)
25
+ * ```
26
+ */
27
+ export interface RuntimeAdapter {
28
+ /** Provider identifier */
29
+ readonly provider: string;
30
+ /**
31
+ * Create a VPC/network.
32
+ */
33
+ createNetwork(config: CoreNetworkConfig): Promise<NetworkResult>;
34
+ /**
35
+ * Create a Kubernetes cluster.
36
+ */
37
+ createCluster(config: CoreClusterConfig, networkId?: pulumi.Input<string>): Promise<ClusterResult>;
38
+ /**
39
+ * Deploy a service to the cluster.
40
+ */
41
+ deployService(config: CoreServiceConfig, options: DeployServiceOptions): Promise<ServiceDeploymentResult>;
42
+ /**
43
+ * Deploy multiple services to the cluster.
44
+ */
45
+ deployServices(configs: CoreServiceConfig[], options: DeployServicesOptions): Promise<ServiceDeploymentResult[]>;
46
+ /**
47
+ * Configure ingress controller for the cluster.
48
+ */
49
+ configureIngress?(options: ConfigureIngressOptions): Promise<IngressResult>;
50
+ /**
51
+ * Configure certificate management (e.g., cert-manager, AWS ACM).
52
+ */
53
+ configureCertManager?(options: ConfigureCertManagerOptions): Promise<void>;
54
+ }
55
+ /**
56
+ * Network creation result.
57
+ */
58
+ export interface NetworkResult {
59
+ /** Network ID */
60
+ id: pulumi.Output<string>;
61
+ /** Network name */
62
+ name: string;
63
+ /** CIDR block */
64
+ cidrBlock?: pulumi.Output<string>;
65
+ }
66
+ /**
67
+ * Cluster creation result.
68
+ */
69
+ export interface ClusterResult extends ClusterDeploymentResult {
70
+ /** Cluster ID */
71
+ id: pulumi.Output<string>;
72
+ /** Kubernetes provider (for deploying resources) */
73
+ provider: any;
74
+ /** VPC/Network ID */
75
+ networkId?: pulumi.Output<string>;
76
+ }
77
+ /**
78
+ * Ingress controller result.
79
+ */
80
+ export interface IngressResult {
81
+ /** Ingress controller name */
82
+ name: string;
83
+ /** Public IP/hostname */
84
+ endpoint?: pulumi.Output<string>;
85
+ }
86
+ /**
87
+ * Options for deploying a single service.
88
+ */
89
+ export interface DeployServiceOptions {
90
+ /** Kubernetes provider */
91
+ provider: any;
92
+ /** Namespace to deploy to */
93
+ namespace: string;
94
+ /** Image pull secret name */
95
+ imagePullSecretName?: string;
96
+ /** Additional environment variables to inject */
97
+ additionalEnv?: Record<string, pulumi.Input<string>>;
98
+ }
99
+ /**
100
+ * Options for deploying multiple services.
101
+ */
102
+ export interface DeployServicesOptions extends DeployServiceOptions {
103
+ /** Filter services by name (regex) */
104
+ filter?: RegExp;
105
+ }
106
+ /**
107
+ * Options for configuring ingress.
108
+ */
109
+ export interface ConfigureIngressOptions {
110
+ /** Kubernetes provider */
111
+ provider: any;
112
+ /** Namespace */
113
+ namespace: string;
114
+ /** Ingress class name */
115
+ ingressClassName?: string;
116
+ /** Load balancer IP (optional, for static IP) */
117
+ loadBalancerIp?: string;
118
+ }
119
+ /**
120
+ * Options for configuring cert manager.
121
+ */
122
+ export interface ConfigureCertManagerOptions {
123
+ /** Kubernetes provider */
124
+ provider: any;
125
+ /** Namespace */
126
+ namespace?: string;
127
+ /** Email for Let's Encrypt notifications */
128
+ email: string;
129
+ /** Staging mode (for testing) */
130
+ staging?: boolean;
131
+ }
132
+ /**
133
+ * Runtime factory function signature.
134
+ */
135
+ export type RuntimeFactory = () => RuntimeAdapter;
136
+ /**
137
+ * Register a runtime adapter for a provider.
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * registerRuntime('doks', createDOKSRuntime)
142
+ * ```
143
+ */
144
+ export declare function registerRuntime(provider: string, factory: RuntimeFactory): void;
145
+ /**
146
+ * Get a runtime adapter for a provider.
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * const runtime = getRuntime('doks')
151
+ * ```
152
+ */
153
+ export declare function getRuntime(provider: string): RuntimeAdapter;
154
+ /**
155
+ * Detect runtime from environment or configuration.
156
+ *
157
+ * Priority:
158
+ * 1. INFRASTRUCTURE_PROVIDER env var
159
+ * 2. Pulumi config (infrastructure:provider)
160
+ * 3. Default to 'doks'
161
+ */
162
+ export declare function detectRuntime(): string;
163
+ /**
164
+ * Runtime component configuration
165
+ *
166
+ * Configures which runtime components to deploy and their settings.
167
+ */
168
+ export interface RuntimeDeploymentConfig {
169
+ /** NATS configuration */
170
+ nats?: {
171
+ enabled: boolean;
172
+ config?: any;
173
+ };
174
+ /** Ingress configuration */
175
+ ingress?: {
176
+ enabled: boolean;
177
+ config?: any;
178
+ };
179
+ /** Certificate manager configuration */
180
+ certManager?: {
181
+ enabled: boolean;
182
+ config?: any;
183
+ };
184
+ }
185
+ /**
186
+ * Runtime deployment result
187
+ */
188
+ export interface RuntimeDeploymentResult {
189
+ /** NATS internal URL */
190
+ natsUrl?: pulumi.Output<string>;
191
+ /** LoadBalancer IP (if ingress enabled) */
192
+ loadBalancerIp?: pulumi.Output<string>;
193
+ /** Cert manager ready */
194
+ certManagerReady?: boolean;
195
+ }
196
+ /**
197
+ * Deploy runtime components using the detected or specified runtime adapter.
198
+ *
199
+ * This is a convenience function that:
200
+ * 1. Detects or uses the specified runtime provider
201
+ * 2. Deploys optional runtime components (NATS, Ingress, Cert-Manager)
202
+ * 3. Returns URLs and metadata for the deployed components
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * const runtime = deployRuntime(provider, 'default', {
207
+ * nats: {
208
+ * enabled: true,
209
+ * config: { jetstream: { enabled: true, storageSize: '1Gi' } }
210
+ * },
211
+ * ingress: {
212
+ * enabled: true,
213
+ * config: { replicas: 1 }
214
+ * }
215
+ * })
216
+ *
217
+ * console.log('NATS URL:', runtime.natsUrl)
218
+ * console.log('LoadBalancer IP:', runtime.loadBalancerIp)
219
+ * ```
220
+ */
221
+ export declare function deployRuntime(provider: any, namespace: string, config: RuntimeDeploymentConfig, runtimeProvider?: string): RuntimeDeploymentResult;