@crossdelta/infrastructure 0.1.41 → 0.2.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.
package/README.md CHANGED
@@ -21,7 +21,6 @@ npm install @crossdelta/infrastructure
21
21
  ```
22
22
 
23
23
  ## Quick Start
24
-
25
24
  ### 1. Create a service config
26
25
 
27
26
  ```typescript
@@ -42,7 +41,6 @@ export default config
42
41
 
43
42
  ```typescript
44
43
  // infra/index.ts
45
- import { join } from 'node:path'
46
44
  import {
47
45
  buildServices,
48
46
  buildIngressRules,
@@ -52,7 +50,7 @@ import {
52
50
  } from '@crossdelta/infrastructure'
53
51
  import { App } from '@pulumi/digitalocean'
54
52
 
55
- const serviceConfigs = discoverServices(join(__dirname, 'services'))
53
+ const serviceConfigs = discoverServices('services')
56
54
 
57
55
  const app = new App('my-app', {
58
56
  spec: {
@@ -104,7 +102,7 @@ const config: ServiceConfig = {
104
102
 
105
103
  ## CLI: generate-env
106
104
 
107
- Generate `.env.local` for local development from your Pulumi config and service definitions.
105
+ Generate `.env.local` and service-specific `env.ts` files for local development.
108
106
 
109
107
  ### Setup
110
108
 
@@ -113,16 +111,12 @@ Add a script to your workspace `package.json`:
113
111
  ```json
114
112
  {
115
113
  "scripts": {
116
- "generate-env": "npx tsx node_modules/@crossdelta/infrastructure/cli/commands/generate-env.ts"
114
+ "generate-env": "turbo run generate-env --ui=stream"
117
115
  }
118
116
  }
119
117
  ```
120
118
 
121
- Then run:
122
-
123
- ```bash
124
- npm run generate-env
125
- ```
119
+ Or use `pf dev` which runs `generate-env` automatically before starting services.
126
120
 
127
121
  ### What it does
128
122
 
@@ -130,7 +124,8 @@ npm run generate-env
130
124
  2. Discovers services from `infra/services/*.ts`
131
125
  3. Generates `SERVICE_URL` and `SERVICE_PORT` env vars for localhost
132
126
  4. Writes `.env.local` to your workspace root
133
- 5. Generates a `ServiceName` TypeScript type
127
+ 5. Generates `infra/env.ts` with type-safe `ServiceName` union type
128
+ 6. Generates `services/*/src/env.ts` for each service (Docker-compatible)
134
129
 
135
130
  ### Example output
136
131
 
@@ -145,17 +140,51 @@ API_GATEWAY_PORT=4000
145
140
  STOREFRONT_PORT=3000
146
141
  ```
147
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)
150
+ ```
151
+
152
+ ## Runtime Helpers
153
+
154
+ Use `@crossdelta/infrastructure/env` in your services to read environment configuration:
155
+
156
+ ```typescript
157
+ import { getServicePort, getServiceUrl } from '@crossdelta/infrastructure/env'
158
+
159
+ // Get port from ORDERS_PORT env var (fallback: 8080)
160
+ const port = getServicePort('orders', 8080)
161
+
162
+ // Get URL from ORDERS_URL env var
163
+ const url = getServiceUrl('orders')
164
+ ```
165
+
166
+ These helpers work both locally (via `.env.local`) and in production (via DO App Platform env injection).
167
+
148
168
  ## API
149
169
 
170
+ ### Main Export (`@crossdelta/infrastructure`)
171
+
150
172
  | Function | Description |
151
173
  |----------|-------------|
152
- | `discoverServices(dir)` | Auto-discover service configs from directory |
174
+ | `discoverServices(dir)` | Auto-discover service configs (relative to cwd or absolute) |
153
175
  | `buildServices(options)` | Build App Platform service specs |
154
176
  | `buildIngressRules(configs)` | Generate ingress rules |
155
177
  | `buildServiceUrlEnvs(configs)` | Create SERVICE_NAME_URL env vars |
156
178
  | `buildServicePortEnvs(configs)` | Create SERVICE_NAME_PORT env vars |
157
179
  | `buildLocalUrls(configs)` | Generate localhost URLs for local dev |
158
180
 
181
+ ### Env Export (`@crossdelta/infrastructure/env`)
182
+
183
+ | Function | Description |
184
+ |----------|-------------|
185
+ | `getServicePort(name, default)` | Read SERVICE_NAME_PORT from env |
186
+ | `getServiceUrl(name)` | Read SERVICE_NAME_URL from env |
187
+
159
188
  ## License
160
189
 
161
190
  MIT
package/dist/env.d.ts CHANGED
@@ -6,4 +6,3 @@
6
6
  * import { getServicePort, getServiceUrl } from '@crossdelta/infrastructure/env'
7
7
  */
8
8
  export * from './helpers/service-runtime';
9
- export type { ServiceName } from './types/service-names';
@@ -2,6 +2,17 @@ import type { ServiceConfig } from '../types';
2
2
  /**
3
3
  * Auto-discovers all service configurations from a directory.
4
4
  * Each .ts file (except index.ts) should export a ServiceConfig as default.
5
+ *
6
+ * @param servicesDir - Path to services directory (relative to cwd or absolute)
5
7
  * @throws Error if duplicate ports are detected
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * // Relative path (resolved from process.cwd())
12
+ * const configs = discoverServices('infra/services')
13
+ *
14
+ * // Absolute path
15
+ * const configs = discoverServices('/absolute/path/to/services')
16
+ * ```
6
17
  */
7
18
  export declare function discoverServices(servicesDir: string): ServiceConfig[];
@@ -3,37 +3,20 @@
3
3
  * These functions read from environment variables set by generate-env (local)
4
4
  * or injected by DO App Platform (production).
5
5
  */
6
- import type { ServiceName } from '../types';
7
6
  /**
8
7
  * Get the port for a service from environment variables.
9
- * Reads from <SERVICE_NAME>_PORT (e.g., ORDERS_PORT, API_GATEWAY_PORT)
8
+ * Reads from SERVICE_NAME_PORT (e.g., ORDERS_PORT, API_GATEWAY_PORT)
10
9
  *
11
10
  * @param serviceName - The service name (e.g., 'orders', 'api-gateway')
12
11
  * @param defaultPort - Fallback port if env var is not set (default: 8080)
13
12
  * @returns The configured port number
14
- *
15
- * @example
16
- * ```typescript
17
- * import { getServicePort } from '@crossdelta/infrastructure/env'
18
- *
19
- * const port = getServicePort('orders', 3001)
20
- * // Reads process.env.ORDERS_PORT, falls back to 3001
21
- * ```
22
13
  */
23
- export declare function getServicePort(serviceName: ServiceName, defaultPort?: number): number;
14
+ export declare function getServicePort(serviceName: string, defaultPort?: number): number;
24
15
  /**
25
16
  * Get the URL for a service from environment variables.
26
- * Reads from <SERVICE_NAME>_URL (e.g., ORDERS_URL, API_GATEWAY_URL)
17
+ * Reads from SERVICE_NAME_URL (e.g., ORDERS_URL, API_GATEWAY_URL)
27
18
  *
28
19
  * @param serviceName - The service name (e.g., 'orders', 'api-gateway')
29
20
  * @returns The service URL or undefined if not set
30
- *
31
- * @example
32
- * ```typescript
33
- * import { getServiceUrl } from '@crossdelta/infrastructure/env'
34
- *
35
- * const ordersUrl = getServiceUrl('orders')
36
- * // Returns process.env.ORDERS_URL
37
- * ```
38
21
  */
39
- export declare function getServiceUrl(serviceName: ServiceName): string | undefined;
22
+ export declare function getServiceUrl(serviceName: string): string | undefined;
package/dist/index.cjs CHANGED
@@ -105,9 +105,10 @@ ${conflicts.join(`
105
105
  }
106
106
  }
107
107
  function discoverServices(servicesDir) {
108
- const files = import_node_fs.readdirSync(servicesDir).filter((file) => file.endsWith(".ts") && file !== "index.ts");
108
+ const resolvedDir = import_node_path.isAbsolute(servicesDir) ? servicesDir : import_node_path.resolve(process.cwd(), servicesDir);
109
+ const files = import_node_fs.readdirSync(resolvedDir).filter((file) => file.endsWith(".ts") && file !== "index.ts");
109
110
  const configs = files.map((file) => {
110
- const module2 = require(import_node_path.join(servicesDir, file));
111
+ const module2 = require(import_node_path.join(resolvedDir, file));
111
112
  return module2.default;
112
113
  });
113
114
  validateNoDuplicatePorts(configs);
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ var defaultHealthCheck = {
32
32
  };
33
33
  // lib/helpers/discover-services.ts
34
34
  import { readdirSync } from "node:fs";
35
- import { join } from "node:path";
35
+ import { isAbsolute, join, resolve } from "node:path";
36
36
  function getServicePort(config) {
37
37
  if (config.httpPort)
38
38
  return config.httpPort;
@@ -57,9 +57,10 @@ ${conflicts.join(`
57
57
  }
58
58
  }
59
59
  function discoverServices(servicesDir) {
60
- const files = readdirSync(servicesDir).filter((file) => file.endsWith(".ts") && file !== "index.ts");
60
+ const resolvedDir = isAbsolute(servicesDir) ? servicesDir : resolve(process.cwd(), servicesDir);
61
+ const files = readdirSync(resolvedDir).filter((file) => file.endsWith(".ts") && file !== "index.ts");
61
62
  const configs = files.map((file) => {
62
- const module = __require(join(servicesDir, file));
63
+ const module = __require(join(resolvedDir, file));
63
64
  return module.default;
64
65
  });
65
66
  validateNoDuplicatePorts(configs);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crossdelta/infrastructure",
3
- "version": "0.1.41",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {