@crossdelta/infrastructure 0.2.11 → 0.2.13
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 +294 -41
- package/dist/helpers/droplet-builder.d.ts +38 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/index.cjs +311692 -1
- package/dist/index.js +311680 -1
- package/dist/types/index.d.ts +70 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,15 +3,55 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@crossdelta/infrastructure)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
Infrastructure-as-Code helpers for deploying microservices to DigitalOcean
|
|
6
|
+
Infrastructure-as-Code helpers for deploying microservices to DigitalOcean with Pulumi.
|
|
7
|
+
|
|
8
|
+
> **Note**: This is an MVP architecture optimized for simplicity and cost-efficiency.
|
|
9
|
+
> For production with SLAs, consider managed services or HA clustering.
|
|
10
|
+
|
|
11
|
+
## Architecture Overview
|
|
12
|
+
|
|
13
|
+
```mermaid
|
|
14
|
+
graph TB
|
|
15
|
+
subgraph DO[DigitalOcean]
|
|
16
|
+
subgraph APP[App Platform]
|
|
17
|
+
FE[frontend :3000]
|
|
18
|
+
API[api :4000]
|
|
19
|
+
WRK[worker :4001]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
subgraph DROP[Droplet]
|
|
23
|
+
NATS[NATS + JetStream]
|
|
24
|
+
VOL[(Volume /data)]
|
|
25
|
+
NATS --> VOL
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
APP -->|VPC| DROP
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
style APP fill:#e1f5fe
|
|
32
|
+
style DROP fill:#fff3e0
|
|
33
|
+
style VOL fill:#f5f5f5
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Platform Strategy
|
|
37
|
+
|
|
38
|
+
| Platform | Use Case | Pros | Cons |
|
|
39
|
+
|----------|----------|------|------|
|
|
40
|
+
| **App Platform** | Stateless services (APIs, frontends) | Auto-scaling, zero-ops, built-in networking | No persistent volumes |
|
|
41
|
+
| **Droplet** | Stateful services (NATS, databases) | Persistent volumes, full control | Manual management |
|
|
42
|
+
|
|
43
|
+
**Why this split?** DigitalOcean App Platform doesn't support persistent volumes.
|
|
44
|
+
Services like NATS with JetStream need persistent storage for message durability.
|
|
7
45
|
|
|
8
46
|
## Features
|
|
9
47
|
|
|
48
|
+
- **Dual Platform Support** - Deploy to App Platform or Droplets from the same config
|
|
10
49
|
- **Service Discovery** - Auto-discover service configs from `infra/services/*.ts`
|
|
11
50
|
- **Type-safe Config** - Full TypeScript support with `ServiceConfig` type
|
|
12
51
|
- **Smart Routing** - Automatic ingress rules for public services
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
52
|
+
- **VPC Networking** - Secure private communication between platforms
|
|
53
|
+
- **Persistent Volumes** - Automatic volume creation and mounting for Droplets
|
|
54
|
+
- **Config File Mounting** - Share config files between local dev and production
|
|
15
55
|
- **URL Generation** - Auto-generate service URLs and port env vars
|
|
16
56
|
|
|
17
57
|
## Installation
|
|
@@ -21,17 +61,44 @@ npm install @crossdelta/infrastructure
|
|
|
21
61
|
```
|
|
22
62
|
|
|
23
63
|
## Quick Start
|
|
24
|
-
|
|
64
|
+
|
|
65
|
+
### 1. Create service configs
|
|
25
66
|
|
|
26
67
|
```typescript
|
|
27
|
-
// infra/services/api
|
|
68
|
+
// infra/services/api.ts - App Platform (stateless)
|
|
28
69
|
import type { ServiceConfig } from '@crossdelta/infrastructure'
|
|
29
70
|
|
|
30
71
|
const config: ServiceConfig = {
|
|
31
|
-
name: 'api
|
|
32
|
-
instanceSizeSlug: 'apps-s-1vcpu-0.5gb',
|
|
72
|
+
name: 'api',
|
|
33
73
|
httpPort: 4000,
|
|
34
74
|
ingressPrefix: '/api',
|
|
75
|
+
instanceSizeSlug: 'apps-s-1vcpu-0.5gb',
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default config
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// infra/services/nats.ts - Droplet (stateful with persistence)
|
|
83
|
+
import { dockerHubImage, type ServiceConfig } from '@crossdelta/infrastructure'
|
|
84
|
+
import { readFileSync } from 'node:fs'
|
|
85
|
+
|
|
86
|
+
const config: ServiceConfig = {
|
|
87
|
+
name: 'nats',
|
|
88
|
+
platform: 'droplet',
|
|
89
|
+
internalPorts: [4222, 8222],
|
|
90
|
+
internalUrl: 'nats://nats:4222',
|
|
91
|
+
image: dockerHubImage('nats', '2.10-alpine'),
|
|
92
|
+
runCommand: '-c /etc/nats/nats.conf',
|
|
93
|
+
droplet: {
|
|
94
|
+
size: 's-1vcpu-1gb',
|
|
95
|
+
volumes: [{ name: 'nats-data', mountPath: '/data', sizeGb: 10 }],
|
|
96
|
+
vpcPorts: [4222, 8222],
|
|
97
|
+
configFile: {
|
|
98
|
+
containerPath: '/etc/nats/nats.conf',
|
|
99
|
+
content: readFileSync('path/to/nats.conf', 'utf-8'),
|
|
100
|
+
},
|
|
101
|
+
},
|
|
35
102
|
}
|
|
36
103
|
|
|
37
104
|
export default config
|
|
@@ -46,60 +113,215 @@ import {
|
|
|
46
113
|
buildIngressRules,
|
|
47
114
|
buildServiceUrlEnvs,
|
|
48
115
|
buildServicePortEnvs,
|
|
116
|
+
buildDropletServices,
|
|
117
|
+
filterByPlatform,
|
|
49
118
|
discoverServices,
|
|
50
119
|
} from '@crossdelta/infrastructure'
|
|
51
|
-
import { App } from '@pulumi/digitalocean'
|
|
120
|
+
import { App, Vpc } from '@pulumi/digitalocean'
|
|
52
121
|
|
|
122
|
+
const region = 'fra1'
|
|
53
123
|
const serviceConfigs = discoverServices('services')
|
|
54
124
|
|
|
125
|
+
// Split services by platform
|
|
126
|
+
const { appPlatformServices, dropletServices } = filterByPlatform(serviceConfigs)
|
|
127
|
+
|
|
128
|
+
// Create VPC for private networking
|
|
129
|
+
const vpc = new Vpc('platform-vpc', {
|
|
130
|
+
name: 'platform-vpc',
|
|
131
|
+
region,
|
|
132
|
+
ipRange: '10.10.10.0/24',
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
// Deploy Droplet services (stateful)
|
|
136
|
+
const dropletResources = buildDropletServices({
|
|
137
|
+
serviceConfigs: dropletServices,
|
|
138
|
+
region,
|
|
139
|
+
vpcUuid: vpc.id,
|
|
140
|
+
projectName: 'my-platform',
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
// Get env vars for Droplet service URLs
|
|
144
|
+
const dropletServiceEnvs = dropletResources.flatMap(r => [
|
|
145
|
+
{ key: `${r.serviceName.toUpperCase()}_URL`, value: r.internalUrl },
|
|
146
|
+
{ key: `${r.serviceName.toUpperCase()}_HOST`, value: r.privateIp },
|
|
147
|
+
])
|
|
148
|
+
|
|
149
|
+
// Deploy App Platform services (stateless)
|
|
55
150
|
const app = new App('my-app', {
|
|
56
151
|
spec: {
|
|
57
152
|
name: 'my-platform',
|
|
58
|
-
region: 'fra'
|
|
153
|
+
region: region.replace(/\d+$/, ''), // 'fra1' -> 'fra'
|
|
59
154
|
envs: [
|
|
60
|
-
...buildServiceUrlEnvs(
|
|
61
|
-
...buildServicePortEnvs(
|
|
155
|
+
...buildServiceUrlEnvs(appPlatformServices),
|
|
156
|
+
...buildServicePortEnvs(appPlatformServices),
|
|
157
|
+
...dropletServiceEnvs,
|
|
62
158
|
],
|
|
63
|
-
services: buildServices({ serviceConfigs }),
|
|
64
|
-
ingress: { rules: buildIngressRules(
|
|
159
|
+
services: buildServices({ serviceConfigs: appPlatformServices }),
|
|
160
|
+
ingress: { rules: buildIngressRules(appPlatformServices) },
|
|
65
161
|
},
|
|
66
162
|
})
|
|
67
163
|
```
|
|
68
164
|
|
|
165
|
+
## ServiceConfig API
|
|
166
|
+
|
|
167
|
+
The `ServiceConfig` type is the central configuration for all services:
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
type ServiceConfig = {
|
|
171
|
+
/** Unique name of the service (required) */
|
|
172
|
+
name: string
|
|
173
|
+
|
|
174
|
+
/** Deployment platform: 'app-platform' (default) or 'droplet' */
|
|
175
|
+
platform?: 'app-platform' | 'droplet'
|
|
176
|
+
|
|
177
|
+
/** Public HTTP port with ingress routing (requires ingressPrefix) */
|
|
178
|
+
httpPort?: number
|
|
179
|
+
|
|
180
|
+
/** Internal-only ports, not publicly accessible */
|
|
181
|
+
internalPorts?: number[]
|
|
182
|
+
|
|
183
|
+
/** Ingress path prefix for public routing (e.g., '/api') */
|
|
184
|
+
ingressPrefix?: string
|
|
185
|
+
|
|
186
|
+
/** Override internal URL (e.g., 'nats://nats:4222' for non-HTTP) */
|
|
187
|
+
internalUrl?: string
|
|
188
|
+
|
|
189
|
+
/** Exclude from deployment */
|
|
190
|
+
skip?: boolean
|
|
191
|
+
|
|
192
|
+
/** Custom image configuration */
|
|
193
|
+
image?: {
|
|
194
|
+
registryType: 'DOCKER_HUB' | 'GHCR' | 'DOCR'
|
|
195
|
+
registry: string // e.g., 'library', 'myorg'
|
|
196
|
+
repository: string // e.g., 'nats', 'platform/api'
|
|
197
|
+
tag: string // e.g., '2.10-alpine', 'latest'
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Command to run in the container */
|
|
201
|
+
runCommand?: string
|
|
202
|
+
|
|
203
|
+
/** App Platform: instance size (e.g., 'apps-s-1vcpu-0.5gb') */
|
|
204
|
+
instanceSizeSlug?: string
|
|
205
|
+
|
|
206
|
+
/** Droplet-specific configuration */
|
|
207
|
+
droplet?: {
|
|
208
|
+
/** Droplet size (e.g., 's-1vcpu-1gb') */
|
|
209
|
+
size: string
|
|
210
|
+
|
|
211
|
+
/** Persistent volumes */
|
|
212
|
+
volumes?: Array<{
|
|
213
|
+
name: string // Volume name (unique)
|
|
214
|
+
mountPath: string // Path in container (e.g., '/data')
|
|
215
|
+
sizeGb: number // Size in GB
|
|
216
|
+
}>
|
|
217
|
+
|
|
218
|
+
/** Ports to open in VPC firewall */
|
|
219
|
+
vpcPorts?: number[]
|
|
220
|
+
|
|
221
|
+
/** Additional Docker run arguments */
|
|
222
|
+
dockerArgs?: string
|
|
223
|
+
|
|
224
|
+
/** Config file to mount into container */
|
|
225
|
+
configFile?: {
|
|
226
|
+
containerPath: string // Path in container
|
|
227
|
+
content: string // File content
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
69
233
|
## Service Configuration Examples
|
|
70
234
|
|
|
71
|
-
### Public Service
|
|
235
|
+
### Public Service (App Platform)
|
|
72
236
|
|
|
73
237
|
```typescript
|
|
74
238
|
const config: ServiceConfig = {
|
|
75
|
-
name: '
|
|
239
|
+
name: 'frontend',
|
|
76
240
|
httpPort: 3000,
|
|
77
241
|
ingressPrefix: '/',
|
|
78
242
|
instanceSizeSlug: 'apps-s-1vcpu-1gb',
|
|
79
243
|
}
|
|
80
244
|
```
|
|
81
245
|
|
|
82
|
-
### Internal Service
|
|
246
|
+
### Internal Service (App Platform)
|
|
83
247
|
|
|
84
248
|
```typescript
|
|
85
249
|
const config: ServiceConfig = {
|
|
86
|
-
name: '
|
|
250
|
+
name: 'worker',
|
|
87
251
|
internalPorts: [4001],
|
|
88
252
|
instanceSizeSlug: 'apps-s-1vcpu-0.5gb',
|
|
89
253
|
}
|
|
90
254
|
```
|
|
91
255
|
|
|
92
|
-
###
|
|
256
|
+
### Stateful Service with Persistence (Droplet)
|
|
93
257
|
|
|
94
258
|
```typescript
|
|
259
|
+
import { dockerHubImage, type ServiceConfig } from '@crossdelta/infrastructure'
|
|
260
|
+
|
|
95
261
|
const config: ServiceConfig = {
|
|
96
262
|
name: 'nats',
|
|
263
|
+
platform: 'droplet',
|
|
97
264
|
internalPorts: [4222, 8222],
|
|
98
265
|
internalUrl: 'nats://nats:4222',
|
|
99
|
-
|
|
266
|
+
image: dockerHubImage('nats', '2.10-alpine'),
|
|
267
|
+
runCommand: '-c /etc/nats/nats.conf',
|
|
268
|
+
droplet: {
|
|
269
|
+
size: 's-1vcpu-1gb',
|
|
270
|
+
volumes: [{ name: 'nats-data', mountPath: '/data', sizeGb: 10 }],
|
|
271
|
+
vpcPorts: [4222, 8222],
|
|
272
|
+
configFile: {
|
|
273
|
+
containerPath: '/etc/nats/nats.conf',
|
|
274
|
+
content: readFileSync('services/nats/nats.conf', 'utf-8'),
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Config File Sharing (Local + Production)
|
|
281
|
+
|
|
282
|
+
One of the key features is sharing configuration between local development and production:
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
services/nats/
|
|
286
|
+
├── nats.conf # Shared config (used by both)
|
|
287
|
+
└── scripts/
|
|
288
|
+
└── start-dev.sh # Local dev script
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**nats.conf** (shared):
|
|
292
|
+
```conf
|
|
293
|
+
server_name: my-nats-server
|
|
294
|
+
listen: 0.0.0.0:4222
|
|
295
|
+
http: 0.0.0.0:8222
|
|
296
|
+
|
|
297
|
+
jetstream {
|
|
298
|
+
store_dir: /data
|
|
299
|
+
max_mem: 1G
|
|
300
|
+
max_file: 10G
|
|
100
301
|
}
|
|
101
302
|
```
|
|
102
303
|
|
|
304
|
+
**start-dev.sh** (local):
|
|
305
|
+
```bash
|
|
306
|
+
docker run -d --name nats \
|
|
307
|
+
-v "$(pwd)/nats.conf:/etc/nats/nats.conf:ro" \
|
|
308
|
+
-v "$(pwd)/.nats-data:/data" \
|
|
309
|
+
-p 4222:4222 -p 8222:8222 \
|
|
310
|
+
nats:2.10-alpine -c /etc/nats/nats.conf
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**infra/services/nats.ts** (production):
|
|
314
|
+
```typescript
|
|
315
|
+
droplet: {
|
|
316
|
+
configFile: {
|
|
317
|
+
containerPath: '/etc/nats/nats.conf',
|
|
318
|
+
content: readFileSync('services/nats/nats.conf', 'utf-8'),
|
|
319
|
+
},
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
→ Same config file, same behavior, different environments.
|
|
324
|
+
|
|
103
325
|
## CLI: generate-env
|
|
104
326
|
|
|
105
327
|
Generate `.env.local` and service-specific `env.ts` files for local development.
|
|
@@ -116,8 +338,6 @@ Add a script to your workspace `package.json`:
|
|
|
116
338
|
}
|
|
117
339
|
```
|
|
118
340
|
|
|
119
|
-
Or use `pf dev` which runs `generate-env` automatically before starting services.
|
|
120
|
-
|
|
121
341
|
### What it does
|
|
122
342
|
|
|
123
343
|
1. Loads secrets from Pulumi config (dev stack)
|
|
@@ -132,21 +352,13 @@ Or use `pf dev` which runs `generate-env` automatically before starting services
|
|
|
132
352
|
`.env.local`:
|
|
133
353
|
```bash
|
|
134
354
|
# Service URLs (localhost for local development)
|
|
135
|
-
|
|
136
|
-
|
|
355
|
+
API_URL=http://localhost:4000
|
|
356
|
+
FRONTEND_URL=http://localhost:3000
|
|
357
|
+
NATS_URL=nats://localhost:4222
|
|
137
358
|
|
|
138
359
|
# Service Ports
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
`services/orders/src/env.ts`:
|
|
144
|
-
```typescript
|
|
145
|
-
import { getServicePort, getServiceUrl } from '@crossdelta/infrastructure/env'
|
|
146
|
-
|
|
147
|
-
export const SERVICE_NAME = 'orders' as const
|
|
148
|
-
export const getServicePort = (defaultPort = 8080) => _getServicePort(SERVICE_NAME, defaultPort)
|
|
149
|
-
export const getServiceUrl = () => _getServiceUrl(SERVICE_NAME)
|
|
360
|
+
API_PORT=4000
|
|
361
|
+
FRONTEND_PORT=3000
|
|
150
362
|
```
|
|
151
363
|
|
|
152
364
|
## Runtime Helpers
|
|
@@ -156,27 +368,51 @@ Use `@crossdelta/infrastructure/env` in your services to read environment config
|
|
|
156
368
|
```typescript
|
|
157
369
|
import { getServicePort, getServiceUrl } from '@crossdelta/infrastructure/env'
|
|
158
370
|
|
|
159
|
-
// Get port from
|
|
160
|
-
const port = getServicePort('
|
|
371
|
+
// Get port from WORKER_PORT env var (fallback: 8080)
|
|
372
|
+
const port = getServicePort('worker', 8080)
|
|
161
373
|
|
|
162
|
-
// Get URL from
|
|
163
|
-
const url = getServiceUrl('
|
|
374
|
+
// Get URL from WORKER_URL env var
|
|
375
|
+
const url = getServiceUrl('worker')
|
|
164
376
|
```
|
|
165
377
|
|
|
166
378
|
These helpers work both locally (via `.env.local`) and in production (via DO App Platform env injection).
|
|
167
379
|
|
|
168
|
-
## API
|
|
380
|
+
## API Reference
|
|
169
381
|
|
|
170
382
|
### Main Export (`@crossdelta/infrastructure`)
|
|
171
383
|
|
|
172
384
|
| Function | Description |
|
|
173
385
|
|----------|-------------|
|
|
174
|
-
| `discoverServices(dir)` | Auto-discover service configs
|
|
386
|
+
| `discoverServices(dir)` | Auto-discover service configs from directory |
|
|
175
387
|
| `buildServices(options)` | Build App Platform service specs |
|
|
176
|
-
| `buildIngressRules(configs)` | Generate ingress rules |
|
|
388
|
+
| `buildIngressRules(configs)` | Generate ingress rules for public services |
|
|
177
389
|
| `buildServiceUrlEnvs(configs)` | Create SERVICE_NAME_URL env vars |
|
|
178
390
|
| `buildServicePortEnvs(configs)` | Create SERVICE_NAME_PORT env vars |
|
|
179
391
|
| `buildLocalUrls(configs)` | Generate localhost URLs for local dev |
|
|
392
|
+
| `filterByPlatform(configs)` | Split configs into App Platform and Droplet services |
|
|
393
|
+
| `buildDropletServices(options)` | Create Droplet resources with volumes and firewall |
|
|
394
|
+
| `dockerHubImage(repo, tag, registry?)` | Create Docker Hub image config (defaults to `library`) |
|
|
395
|
+
|
|
396
|
+
### Droplet Builder Options
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
buildDropletServices({
|
|
400
|
+
serviceConfigs: ServiceConfig[] // Services with platform: 'droplet'
|
|
401
|
+
region: string // DO region (e.g., 'fra1')
|
|
402
|
+
vpcUuid: pulumi.Output<string> // VPC ID for private networking
|
|
403
|
+
projectName: string // Prefix for resource names
|
|
404
|
+
})
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Returns an array of:
|
|
408
|
+
```typescript
|
|
409
|
+
{
|
|
410
|
+
serviceName: string // Service name
|
|
411
|
+
droplet: digitalocean.Droplet // Created Droplet resource
|
|
412
|
+
privateIp: pulumi.Output<string> // Private IP in VPC
|
|
413
|
+
internalUrl: string // URL for service discovery
|
|
414
|
+
}
|
|
415
|
+
```
|
|
180
416
|
|
|
181
417
|
### Env Export (`@crossdelta/infrastructure/env`)
|
|
182
418
|
|
|
@@ -185,6 +421,23 @@ These helpers work both locally (via `.env.local`) and in production (via DO App
|
|
|
185
421
|
| `getServicePort(name, default)` | Read SERVICE_NAME_PORT from env |
|
|
186
422
|
| `getServiceUrl(name)` | Read SERVICE_NAME_URL from env |
|
|
187
423
|
|
|
424
|
+
## MVP Limitations & Future Improvements
|
|
425
|
+
|
|
426
|
+
This architecture is designed for MVP/Beta deployments:
|
|
427
|
+
|
|
428
|
+
| Current (MVP) | Future (Production) |
|
|
429
|
+
|---------------|---------------------|
|
|
430
|
+
| Single NATS Droplet | NATS Cluster (3 nodes) or Synadia Cloud |
|
|
431
|
+
| No auto-healing | Kubernetes or managed service |
|
|
432
|
+
| Manual scaling | Auto-scaling policies |
|
|
433
|
+
| Basic monitoring | Prometheus/Grafana stack |
|
|
434
|
+
|
|
435
|
+
**Cost estimate (MVP)**:
|
|
436
|
+
- App Platform: ~$12-24/month (depending on instance sizes)
|
|
437
|
+
- NATS Droplet: ~$6/month (s-1vcpu-1gb)
|
|
438
|
+
- Volume: ~$1/month (10GB)
|
|
439
|
+
- **Total**: ~$19-31/month
|
|
440
|
+
|
|
188
441
|
## License
|
|
189
442
|
|
|
190
443
|
MIT
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as digitalocean from '@pulumi/digitalocean';
|
|
2
|
+
import * as pulumi from '@pulumi/pulumi';
|
|
3
|
+
import type { ServiceConfig } from '../types';
|
|
4
|
+
export interface DropletServiceResources {
|
|
5
|
+
droplet: digitalocean.Droplet;
|
|
6
|
+
volume?: digitalocean.Volume;
|
|
7
|
+
volumeAttachment?: digitalocean.VolumeAttachment;
|
|
8
|
+
firewall?: digitalocean.Firewall;
|
|
9
|
+
/** Private IP for VPC communication */
|
|
10
|
+
privateIp: pulumi.Output<string>;
|
|
11
|
+
}
|
|
12
|
+
export interface BuildDropletServicesOptions {
|
|
13
|
+
/** Service configs with platform: 'droplet' */
|
|
14
|
+
serviceConfigs: ServiceConfig[];
|
|
15
|
+
/** DigitalOcean region (e.g., 'fra1') */
|
|
16
|
+
region: string;
|
|
17
|
+
/** VPC UUID for private networking */
|
|
18
|
+
vpcUuid: pulumi.Input<string>;
|
|
19
|
+
/** SSH key IDs for Droplet access (optional) */
|
|
20
|
+
sshKeyIds?: pulumi.Input<pulumi.Input<string>[]>;
|
|
21
|
+
/** Registry credentials for private images (optional) */
|
|
22
|
+
registryCredentials?: pulumi.Output<string>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Builds Droplet resources for services with platform: 'droplet'.
|
|
26
|
+
*
|
|
27
|
+
* Creates:
|
|
28
|
+
* - Droplet with Docker and cloud-init script
|
|
29
|
+
* - Volume(s) for persistent storage (if configured)
|
|
30
|
+
* - Firewall rules for VPC access
|
|
31
|
+
*
|
|
32
|
+
* @returns Map of service name to created resources
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildDropletServices(options: BuildDropletServicesOptions): Map<string, DropletServiceResources>;
|
|
35
|
+
/**
|
|
36
|
+
* Filters service configs by platform type.
|
|
37
|
+
*/
|
|
38
|
+
export declare function filterByPlatform(configs: ServiceConfig[], platform: 'app-platform' | 'droplet'): ServiceConfig[];
|
package/dist/helpers/index.d.ts
CHANGED