@crossdelta/infrastructure 0.2.1 → 0.2.3

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
@@ -41,7 +41,6 @@ export default config
41
41
 
42
42
  ```typescript
43
43
  // infra/index.ts
44
- import { join } from 'node:path'
45
44
  import {
46
45
  buildServices,
47
46
  buildIngressRules,
@@ -51,7 +50,7 @@ import {
51
50
  } from '@crossdelta/infrastructure'
52
51
  import { App } from '@pulumi/digitalocean'
53
52
 
54
- const serviceConfigs = discoverServices(join(__dirname, 'services'))
53
+ const serviceConfigs = discoverServices('services')
55
54
 
56
55
  const app = new App('my-app', {
57
56
  spec: {
@@ -172,7 +171,7 @@ These helpers work both locally (via `.env.local`) and in production (via DO App
172
171
 
173
172
  | Function | Description |
174
173
  |----------|-------------|
175
- | `discoverServices(dir)` | Auto-discover service configs from directory |
174
+ | `discoverServices(dir)` | Auto-discover service configs (relative to cwd or absolute) |
176
175
  | `buildServices(options)` | Build App Platform service specs |
177
176
  | `buildIngressRules(configs)` | Generate ingress rules |
178
177
  | `buildServiceUrlEnvs(configs)` | Create SERVICE_NAME_URL env vars |
@@ -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[];
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Generate service-specific env.ts content.
3
+ *
4
+ * @param serviceName - The name of the service (e.g., 'orders', 'api-gateway')
5
+ * @returns The content for the service's src/env.ts file
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { generateServiceEnvFile } from '@crossdelta/infrastructure'
10
+ * import { writeFileSync } from 'node:fs'
11
+ *
12
+ * const content = generateServiceEnvFile('orders')
13
+ * writeFileSync('services/orders/src/env.ts', content)
14
+ * ```
15
+ */
16
+ export declare function generateServiceEnvFile(serviceName: string): string;
@@ -1,6 +1,7 @@
1
1
  export * from './config';
2
2
  export * from './discover-services';
3
3
  export * from './docker-hub-image';
4
+ export * from './generate-service-env';
4
5
  export * from './image';
5
6
  export * from './service-builder';
6
7
  export * from './service-runtime';
package/dist/index.cjs CHANGED
@@ -32,6 +32,7 @@ __export(exports_lib, {
32
32
  getServiceUrl: () => getServiceUrl,
33
33
  getServicePort: () => getServicePort2,
34
34
  getImage: () => getImage,
35
+ generateServiceEnvFile: () => generateServiceEnvFile,
35
36
  ensureDot: () => ensureDot,
36
37
  dockerHubImage: () => dockerHubImage,
37
38
  discoverServices: () => discoverServices,
@@ -105,9 +106,10 @@ ${conflicts.join(`
105
106
  }
106
107
  }
107
108
  function discoverServices(servicesDir) {
108
- const files = import_node_fs.readdirSync(servicesDir).filter((file) => file.endsWith(".ts") && file !== "index.ts");
109
+ const resolvedDir = import_node_path.isAbsolute(servicesDir) ? servicesDir : import_node_path.resolve(process.cwd(), servicesDir);
110
+ const files = import_node_fs.readdirSync(resolvedDir).filter((file) => file.endsWith(".ts") && file !== "index.ts");
109
111
  const configs = files.map((file) => {
110
- const module2 = require(import_node_path.join(servicesDir, file));
112
+ const module2 = require(import_node_path.join(resolvedDir, file));
111
113
  return module2.default;
112
114
  });
113
115
  validateNoDuplicatePorts(configs);
@@ -127,6 +129,39 @@ var dockerHubImage = (repository, tag, registry = "library") => ({
127
129
  repository,
128
130
  tag
129
131
  });
132
+ // lib/helpers/generate-service-env.ts
133
+ function generateServiceEnvFile(serviceName) {
134
+ const envKey = serviceName.toUpperCase().replace(/-/g, "_");
135
+ return `/**
136
+ * Service environment configuration.
137
+ * Auto-generated by: bun run generate-env
138
+ * DO NOT EDIT MANUALLY - changes will be overwritten!
139
+ */
140
+
141
+ import {
142
+ getServicePort as _getServicePort,
143
+ getServiceUrl as _getServiceUrl,
144
+ } from '@crossdelta/infrastructure/env'
145
+
146
+ /** This service's name */
147
+ export const SERVICE_NAME = '${serviceName}' as const
148
+ export type ServiceName = typeof SERVICE_NAME
149
+
150
+ /**
151
+ * Get the port for this service from environment variables.
152
+ * Reads from ${envKey}_PORT
153
+ */
154
+ export const getServicePort = (defaultPort = 8080): number =>
155
+ _getServicePort(SERVICE_NAME, defaultPort)
156
+
157
+ /**
158
+ * Get the URL for this service from environment variables.
159
+ * Reads from ${envKey}_URL
160
+ */
161
+ export const getServiceUrl = (): string | undefined =>
162
+ _getServiceUrl(SERVICE_NAME)
163
+ `;
164
+ }
130
165
  // lib/helpers/image.ts
131
166
  var scopeImageTagsRaw = process.env.SCOPE_IMAGE_TAGS ?? "";
132
167
  var scopeImageTags = (() => {
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);
@@ -79,6 +80,39 @@ var dockerHubImage = (repository, tag, registry = "library") => ({
79
80
  repository,
80
81
  tag
81
82
  });
83
+ // lib/helpers/generate-service-env.ts
84
+ function generateServiceEnvFile(serviceName) {
85
+ const envKey = serviceName.toUpperCase().replace(/-/g, "_");
86
+ return `/**
87
+ * Service environment configuration.
88
+ * Auto-generated by: bun run generate-env
89
+ * DO NOT EDIT MANUALLY - changes will be overwritten!
90
+ */
91
+
92
+ import {
93
+ getServicePort as _getServicePort,
94
+ getServiceUrl as _getServiceUrl,
95
+ } from '@crossdelta/infrastructure/env'
96
+
97
+ /** This service's name */
98
+ export const SERVICE_NAME = '${serviceName}' as const
99
+ export type ServiceName = typeof SERVICE_NAME
100
+
101
+ /**
102
+ * Get the port for this service from environment variables.
103
+ * Reads from ${envKey}_PORT
104
+ */
105
+ export const getServicePort = (defaultPort = 8080): number =>
106
+ _getServicePort(SERVICE_NAME, defaultPort)
107
+
108
+ /**
109
+ * Get the URL for this service from environment variables.
110
+ * Reads from ${envKey}_URL
111
+ */
112
+ export const getServiceUrl = (): string | undefined =>
113
+ _getServiceUrl(SERVICE_NAME)
114
+ `;
115
+ }
82
116
  // lib/helpers/image.ts
83
117
  var scopeImageTagsRaw = process.env.SCOPE_IMAGE_TAGS ?? "";
84
118
  var scopeImageTags = (() => {
@@ -214,6 +248,7 @@ export {
214
248
  getServiceUrl,
215
249
  getServicePort2 as getServicePort,
216
250
  getImage,
251
+ generateServiceEnvFile,
217
252
  ensureDot,
218
253
  dockerHubImage,
219
254
  discoverServices,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crossdelta/infrastructure",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "publishConfig": {