@hstm-labs/forge-infra-generator 0.1.11
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 +40 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/infra-generate-stage.d.ts +59 -0
- package/dist/infra-generate-stage.d.ts.map +1 -0
- package/dist/infra-generate-stage.js +195 -0
- package/dist/infra-generate-stage.js.map +1 -0
- package/dist/types.d.ts +83 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/validator.d.ts +49 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +233 -0
- package/dist/validator.js.map +1 -0
- package/package.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# @hstm-labs/forge-infra-generator
|
|
2
|
+
|
|
3
|
+
Infrastructure configuration generation stage for Forge — produces Dockerfiles, compose configs, CI pipelines, database scripts, environment files, and configuration from architecture output.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @hstm-labs/forge-infra-generator
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Public API
|
|
12
|
+
|
|
13
|
+
### Types
|
|
14
|
+
|
|
15
|
+
- `InfraArtifact` — complete infrastructure output
|
|
16
|
+
- `InfraContainer` — Dockerfile definition
|
|
17
|
+
- `InfraComposeConfig` — Docker Compose configuration
|
|
18
|
+
- `InfraCiPipeline` — CI/CD pipeline definition
|
|
19
|
+
- `InfraDatabaseScript` — database migration/init scripts
|
|
20
|
+
- `InfraEnvFile` — environment variable file
|
|
21
|
+
- `InfraConfigFile` — application config file
|
|
22
|
+
|
|
23
|
+
### Classes
|
|
24
|
+
|
|
25
|
+
- `InfraGenerateStage` — pipeline stage implementing `PipelineStage` interface
|
|
26
|
+
- `InfraOutputValidator` — validates LLM-produced infrastructure output
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { InfraGenerateStage } from '@hstm-labs/forge-infra-generator';
|
|
32
|
+
|
|
33
|
+
const stage = new InfraGenerateStage();
|
|
34
|
+
const result = await stage.execute(input);
|
|
35
|
+
// result.data contains InfraArtifact
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## License
|
|
39
|
+
|
|
40
|
+
[MIT](../../LICENSE)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { InfraArtifact, InfraContainer, InfraComposeConfig, InfraCiPipeline, InfraDatabaseScript, InfraEnvFile, InfraConfigFile, } from './types.js';
|
|
2
|
+
export { InfraGenerateStage } from './infra-generate-stage.js';
|
|
3
|
+
export { InfraOutputValidator } from './validator.js';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,aAAa,EACb,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure generation pipeline stage.
|
|
3
|
+
*
|
|
4
|
+
* Produces Dockerfiles, compose configs, CI/CD pipeline definitions,
|
|
5
|
+
* database scripts, environment files, and additional config files
|
|
6
|
+
* from architecture, profile, and specification. Follows the stage
|
|
7
|
+
* implementation pattern established by {@link ArchitectStage} and
|
|
8
|
+
* {@link ServicesGenerateStage}.
|
|
9
|
+
*
|
|
10
|
+
* In API mode, renders prompt templates, calls the LLM via
|
|
11
|
+
* {@link ApiStageExecutor}, validates the output, unpacks individual
|
|
12
|
+
* files, and returns the parsed {@link InfraArtifact} in the stage
|
|
13
|
+
* output data.
|
|
14
|
+
*
|
|
15
|
+
* In agent mode, the pipeline runner intercepts before calling
|
|
16
|
+
* `execute()` and exports a prompt via {@link AgentStageExecutor}.
|
|
17
|
+
*/
|
|
18
|
+
import type { StageName } from '@hstm-labs/forge-common';
|
|
19
|
+
import type { PipelineStage, PipelineStageInput, PipelineStageOutput, PipelineContext, AgentPromptContext } from '@hstm-labs/forge-core';
|
|
20
|
+
/**
|
|
21
|
+
* Pipeline stage that generates infrastructure configuration.
|
|
22
|
+
*
|
|
23
|
+
* Produces an {@link InfraArtifact} containing Dockerfiles, compose
|
|
24
|
+
* configuration, CI/CD pipeline, database scripts, environment files,
|
|
25
|
+
* and additional config files. Each element is written as a separate
|
|
26
|
+
* file artifact, preserving directory structure from file names.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* const stage = new InfraGenerateStage();
|
|
31
|
+
* const output = await stage.execute(input, context);
|
|
32
|
+
* const infra = output.data?.infra as InfraArtifact;
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class InfraGenerateStage implements PipelineStage {
|
|
36
|
+
readonly name: StageName;
|
|
37
|
+
readonly dependsOn: StageName[];
|
|
38
|
+
readonly requiresLLM = true;
|
|
39
|
+
/**
|
|
40
|
+
* Return rendered agent-mode prompt context using `infra-generate-agent.hbs`.
|
|
41
|
+
*
|
|
42
|
+
* @param input - Input from prior stages
|
|
43
|
+
* @param context - Pipeline context with config, workspace, and runId
|
|
44
|
+
* @returns Agent prompt context with rendered template and output schema
|
|
45
|
+
*/
|
|
46
|
+
getAgentContext(input: PipelineStageInput, context: PipelineContext): AgentPromptContext;
|
|
47
|
+
/**
|
|
48
|
+
* Execute the infrastructure generation stage.
|
|
49
|
+
*
|
|
50
|
+
* @param input - Input from prior stages (expects validate + architect output)
|
|
51
|
+
* @param context - Pipeline context with config, workspace, and adapter
|
|
52
|
+
* @returns Stage output with infra artifacts and parsed InfraArtifact in data
|
|
53
|
+
* @throws {ForgeError} FORGE-PIPE-003 if dependency stage output is missing
|
|
54
|
+
* @throws {ForgeError} FORGE-PIPE-001 if adapter is missing
|
|
55
|
+
* @throws {ForgeError} FORGE-GEN-003 if max retries exhausted
|
|
56
|
+
*/
|
|
57
|
+
execute(input: PipelineStageInput, context: PipelineContext): Promise<PipelineStageOutput>;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=infra-generate-stage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"infra-generate-stage.d.ts","sourceRoot":"","sources":["../src/infra-generate-stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EAEf,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAU/B;;;;;;;;;;;;;;GAcG;AACH,qBAAa,kBAAmB,YAAW,aAAa;IACtD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAoB;IAC5C,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,CAAiB;IAChD,QAAQ,CAAC,WAAW,QAAQ;IAE5B;;;;;;OAMG;IACH,eAAe,CACb,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,eAAe,GACvB,kBAAkB;IAwCrB;;;;;;;;;OASG;IACG,OAAO,CACX,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,mBAAmB,CAAC;CA6KhC"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure generation pipeline stage.
|
|
3
|
+
*
|
|
4
|
+
* Produces Dockerfiles, compose configs, CI/CD pipeline definitions,
|
|
5
|
+
* database scripts, environment files, and additional config files
|
|
6
|
+
* from architecture, profile, and specification. Follows the stage
|
|
7
|
+
* implementation pattern established by {@link ArchitectStage} and
|
|
8
|
+
* {@link ServicesGenerateStage}.
|
|
9
|
+
*
|
|
10
|
+
* In API mode, renders prompt templates, calls the LLM via
|
|
11
|
+
* {@link ApiStageExecutor}, validates the output, unpacks individual
|
|
12
|
+
* files, and returns the parsed {@link InfraArtifact} in the stage
|
|
13
|
+
* output data.
|
|
14
|
+
*
|
|
15
|
+
* In agent mode, the pipeline runner intercepts before calling
|
|
16
|
+
* `execute()` and exports a prompt via {@link AgentStageExecutor}.
|
|
17
|
+
*/
|
|
18
|
+
import { join, dirname } from 'node:path';
|
|
19
|
+
import { writeFileSync, mkdirSync } from 'node:fs';
|
|
20
|
+
import { ForgeError, ErrorCodes, hashContent } from '@hstm-labs/forge-common';
|
|
21
|
+
import { ApiStageExecutor } from '@hstm-labs/forge-core';
|
|
22
|
+
import { loadProfile } from '@hstm-labs/forge-profiles';
|
|
23
|
+
import { loadTemplate, renderTemplate } from '@hstm-labs/forge-templates';
|
|
24
|
+
import { InfraOutputValidator } from './validator.js';
|
|
25
|
+
/**
|
|
26
|
+
* Pipeline stage that generates infrastructure configuration.
|
|
27
|
+
*
|
|
28
|
+
* Produces an {@link InfraArtifact} containing Dockerfiles, compose
|
|
29
|
+
* configuration, CI/CD pipeline, database scripts, environment files,
|
|
30
|
+
* and additional config files. Each element is written as a separate
|
|
31
|
+
* file artifact, preserving directory structure from file names.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* const stage = new InfraGenerateStage();
|
|
36
|
+
* const output = await stage.execute(input, context);
|
|
37
|
+
* const infra = output.data?.infra as InfraArtifact;
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export class InfraGenerateStage {
|
|
41
|
+
name = 'infra-generate';
|
|
42
|
+
dependsOn = ['architect'];
|
|
43
|
+
requiresLLM = true;
|
|
44
|
+
/**
|
|
45
|
+
* Return rendered agent-mode prompt context using `infra-generate-agent.hbs`.
|
|
46
|
+
*
|
|
47
|
+
* @param input - Input from prior stages
|
|
48
|
+
* @param context - Pipeline context with config, workspace, and runId
|
|
49
|
+
* @returns Agent prompt context with rendered template and output schema
|
|
50
|
+
*/
|
|
51
|
+
getAgentContext(input, context) {
|
|
52
|
+
const parsedSpec = input['validate']?.data?.['parsedSpec'];
|
|
53
|
+
const architecture = input['architect']?.data?.['architecture'];
|
|
54
|
+
const profile = loadProfile(context.config.profileName, context.workspace.rootDir);
|
|
55
|
+
const outputDir = join(context.workspace.forgeDir, 'runs', context.runId, 'stages', 'infra-generate', 'artifacts');
|
|
56
|
+
const agentTemplate = loadTemplate('infra-generate-agent', context.workspace.rootDir);
|
|
57
|
+
const rendered = renderTemplate(agentTemplate, {
|
|
58
|
+
spec: (parsedSpec ?? {}),
|
|
59
|
+
profile: profile,
|
|
60
|
+
architecture: (architecture ?? {}),
|
|
61
|
+
stage: { outputDir },
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
prompt: rendered.content,
|
|
65
|
+
outputSchema: { format: 'json' },
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Execute the infrastructure generation stage.
|
|
70
|
+
*
|
|
71
|
+
* @param input - Input from prior stages (expects validate + architect output)
|
|
72
|
+
* @param context - Pipeline context with config, workspace, and adapter
|
|
73
|
+
* @returns Stage output with infra artifacts and parsed InfraArtifact in data
|
|
74
|
+
* @throws {ForgeError} FORGE-PIPE-003 if dependency stage output is missing
|
|
75
|
+
* @throws {ForgeError} FORGE-PIPE-001 if adapter is missing
|
|
76
|
+
* @throws {ForgeError} FORGE-GEN-003 if max retries exhausted
|
|
77
|
+
*/
|
|
78
|
+
async execute(input, context) {
|
|
79
|
+
// 1. Get parsed spec from validate stage output
|
|
80
|
+
const validateOutput = input['validate'];
|
|
81
|
+
if (validateOutput === undefined) {
|
|
82
|
+
throw new ForgeError(ErrorCodes.PIPE.DEPENDENCY_UNMET, "Infra generate stage requires 'validate' stage output, but it was not found. " +
|
|
83
|
+
'Ensure the validate stage runs before the infra-generate stage.');
|
|
84
|
+
}
|
|
85
|
+
const parsedSpec = validateOutput.data?.['parsedSpec'];
|
|
86
|
+
if (parsedSpec === undefined) {
|
|
87
|
+
throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Validate stage did not produce a parsed specification in its output data. ' +
|
|
88
|
+
'Ensure the validate stage includes parsedSpec in its data output.');
|
|
89
|
+
}
|
|
90
|
+
// 2. Get architecture from architect stage output
|
|
91
|
+
const architectOutput = input['architect'];
|
|
92
|
+
if (architectOutput === undefined) {
|
|
93
|
+
throw new ForgeError(ErrorCodes.PIPE.DEPENDENCY_UNMET, "Infra generate stage requires 'architect' stage output, but it was not found. " +
|
|
94
|
+
'Ensure the architect stage runs before the infra-generate stage.');
|
|
95
|
+
}
|
|
96
|
+
const architecture = architectOutput.data?.['architecture'];
|
|
97
|
+
if (architecture === undefined) {
|
|
98
|
+
throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Architect stage did not produce an architecture in its output data. ' +
|
|
99
|
+
'Ensure the architect stage includes architecture in its data output.');
|
|
100
|
+
}
|
|
101
|
+
// 3. Load profile, determine infra flags
|
|
102
|
+
const profile = loadProfile(context.config.profileName, context.workspace.rootDir);
|
|
103
|
+
const infraSection = profile['infrastructure'] ?? {};
|
|
104
|
+
const hasOrchestration = typeof infraSection['orchestration'] === 'string' && infraSection['orchestration'].length > 0;
|
|
105
|
+
const hasCi = typeof infraSection['ci'] === 'string' && infraSection['ci'].length > 0;
|
|
106
|
+
// 4. Compute output directory
|
|
107
|
+
const outputDir = join(context.workspace.forgeDir, 'runs', context.runId, 'stages', 'infra-generate', 'artifacts');
|
|
108
|
+
// 5. Load and render templates
|
|
109
|
+
const systemTemplate = loadTemplate('infra-generate-system', context.workspace.rootDir);
|
|
110
|
+
const userTemplate = loadTemplate('infra-generate-user', context.workspace.rootDir);
|
|
111
|
+
const templateContext = {
|
|
112
|
+
spec: parsedSpec,
|
|
113
|
+
profile: profile,
|
|
114
|
+
architecture: architecture,
|
|
115
|
+
stage: {
|
|
116
|
+
outputDir,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
const systemPrompt = renderTemplate(systemTemplate, templateContext);
|
|
120
|
+
const userPrompt = renderTemplate(userTemplate, templateContext);
|
|
121
|
+
// 6. Execute via API mode StageExecutor
|
|
122
|
+
if (context.adapter === undefined) {
|
|
123
|
+
throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Infra generate stage requires an LLM adapter in API mode, but none was provided. ' +
|
|
124
|
+
'Configure an LLM provider in forge.config.json or use agent mode.');
|
|
125
|
+
}
|
|
126
|
+
const validator = new InfraOutputValidator(hasOrchestration, hasCi);
|
|
127
|
+
const executor = new ApiStageExecutor({
|
|
128
|
+
adapter: context.adapter,
|
|
129
|
+
validator,
|
|
130
|
+
retryPolicy: {
|
|
131
|
+
maxRetries: 3,
|
|
132
|
+
backoffMs: 1000,
|
|
133
|
+
includeErrorInRetry: true,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
const result = await executor.execute({
|
|
137
|
+
prompt: userPrompt.content,
|
|
138
|
+
systemPrompt: systemPrompt.content,
|
|
139
|
+
stageName: 'infra-generate',
|
|
140
|
+
outputDir,
|
|
141
|
+
runId: context.runId,
|
|
142
|
+
mode: 'api',
|
|
143
|
+
outputSchema: { format: 'json' },
|
|
144
|
+
});
|
|
145
|
+
// 7. Parse InfraArtifact from LLM output
|
|
146
|
+
const rawContent = result.artifacts[0]?.content ?? '';
|
|
147
|
+
const infraArtifact = JSON.parse(rawContent);
|
|
148
|
+
// 8. Write individual files to artifacts directory
|
|
149
|
+
const artifacts = [];
|
|
150
|
+
// Helper to write a file, creating intermediate directories as needed
|
|
151
|
+
const writeArtifact = (filePath, content) => {
|
|
152
|
+
const fullPath = join(outputDir, filePath);
|
|
153
|
+
mkdirSync(dirname(fullPath), { recursive: true });
|
|
154
|
+
writeFileSync(fullPath, content, 'utf-8');
|
|
155
|
+
artifacts.push({
|
|
156
|
+
filePath,
|
|
157
|
+
content,
|
|
158
|
+
contentHash: hashContent(content),
|
|
159
|
+
sizeBytes: Buffer.byteLength(content, 'utf-8'),
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
// Containers (Dockerfiles)
|
|
163
|
+
for (const container of infraArtifact.containers) {
|
|
164
|
+
writeArtifact(container.fileName, container.content);
|
|
165
|
+
}
|
|
166
|
+
// Compose config
|
|
167
|
+
if (infraArtifact.compose !== undefined && infraArtifact.compose !== null) {
|
|
168
|
+
writeArtifact(infraArtifact.compose.fileName, infraArtifact.compose.content);
|
|
169
|
+
}
|
|
170
|
+
// CI pipeline
|
|
171
|
+
if (infraArtifact.ciPipeline !== undefined && infraArtifact.ciPipeline !== null) {
|
|
172
|
+
writeArtifact(infraArtifact.ciPipeline.fileName, infraArtifact.ciPipeline.content);
|
|
173
|
+
}
|
|
174
|
+
// Database scripts
|
|
175
|
+
for (const script of infraArtifact.databaseScripts) {
|
|
176
|
+
writeArtifact(script.fileName, script.content);
|
|
177
|
+
}
|
|
178
|
+
// Environment files
|
|
179
|
+
for (const envFile of infraArtifact.envFiles) {
|
|
180
|
+
writeArtifact(envFile.fileName, envFile.content);
|
|
181
|
+
}
|
|
182
|
+
// Additional config files
|
|
183
|
+
for (const configFile of infraArtifact.configFiles) {
|
|
184
|
+
writeArtifact(configFile.fileName, configFile.content);
|
|
185
|
+
}
|
|
186
|
+
// 9. Return PipelineStageOutput with all artifacts and data
|
|
187
|
+
return {
|
|
188
|
+
artifacts,
|
|
189
|
+
data: {
|
|
190
|
+
infra: infraArtifact,
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=infra-generate-stage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"infra-generate-stage.js","sourceRoot":"","sources":["../src/infra-generate-stage.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure artifact type definitions for the Forge infrastructure generation stage.
|
|
3
|
+
*
|
|
4
|
+
* Defines the output schema produced by the infra generation stage,
|
|
5
|
+
* including containers, compose config, CI/CD pipelines, database
|
|
6
|
+
* scripts, environment files, and additional config files.
|
|
7
|
+
*/
|
|
8
|
+
/** Complete infrastructure output produced by the infra-generate stage. */
|
|
9
|
+
export interface InfraArtifact {
|
|
10
|
+
/** Container definitions (Dockerfiles). */
|
|
11
|
+
containers: InfraContainer[];
|
|
12
|
+
/** Compose/orchestration configuration. */
|
|
13
|
+
compose: InfraComposeConfig | undefined;
|
|
14
|
+
/** CI/CD pipeline definition. */
|
|
15
|
+
ciPipeline: InfraCiPipeline | undefined;
|
|
16
|
+
/** Database migration or initialization scripts. */
|
|
17
|
+
databaseScripts: InfraDatabaseScript[];
|
|
18
|
+
/** Environment configuration files. */
|
|
19
|
+
envFiles: InfraEnvFile[];
|
|
20
|
+
/** Additional config files (nginx, etc.). */
|
|
21
|
+
configFiles: InfraConfigFile[];
|
|
22
|
+
}
|
|
23
|
+
/** A Dockerfile definition for a service. */
|
|
24
|
+
export interface InfraContainer {
|
|
25
|
+
/** Service name (e.g., "backend", "frontend", "database"). */
|
|
26
|
+
service: string;
|
|
27
|
+
/** Dockerfile file name (e.g., "Dockerfile.backend"). */
|
|
28
|
+
fileName: string;
|
|
29
|
+
/** Dockerfile content. */
|
|
30
|
+
content: string;
|
|
31
|
+
/** Base image. */
|
|
32
|
+
baseImage: string;
|
|
33
|
+
/** Exposed ports. */
|
|
34
|
+
ports: number[];
|
|
35
|
+
}
|
|
36
|
+
/** Docker Compose or orchestration configuration. */
|
|
37
|
+
export interface InfraComposeConfig {
|
|
38
|
+
/** File name (e.g., "docker-compose.yml"). */
|
|
39
|
+
fileName: string;
|
|
40
|
+
/** File content (YAML). */
|
|
41
|
+
content: string;
|
|
42
|
+
/** Service names defined in the compose file. */
|
|
43
|
+
services: string[];
|
|
44
|
+
}
|
|
45
|
+
/** CI/CD pipeline definition. */
|
|
46
|
+
export interface InfraCiPipeline {
|
|
47
|
+
/** CI platform (e.g., "GitHub Actions", "GitLab CI"). */
|
|
48
|
+
platform: string;
|
|
49
|
+
/** File name (e.g., ".github/workflows/ci.yml"). */
|
|
50
|
+
fileName: string;
|
|
51
|
+
/** File content (YAML). */
|
|
52
|
+
content: string;
|
|
53
|
+
/** Pipeline stages defined. */
|
|
54
|
+
stages: string[];
|
|
55
|
+
}
|
|
56
|
+
/** A database initialization or migration script. */
|
|
57
|
+
export interface InfraDatabaseScript {
|
|
58
|
+
/** Script purpose (e.g., "init", "migration", "seed-schema"). */
|
|
59
|
+
purpose: string;
|
|
60
|
+
/** File name. */
|
|
61
|
+
fileName: string;
|
|
62
|
+
/** File content (SQL or migration script). */
|
|
63
|
+
content: string;
|
|
64
|
+
}
|
|
65
|
+
/** An environment configuration file. */
|
|
66
|
+
export interface InfraEnvFile {
|
|
67
|
+
/** Environment name (e.g., "development", "production", "test"). */
|
|
68
|
+
environment: string;
|
|
69
|
+
/** File name (e.g., ".env.example", ".env.development"). */
|
|
70
|
+
fileName: string;
|
|
71
|
+
/** File content (KEY=value pairs with placeholder secrets). */
|
|
72
|
+
content: string;
|
|
73
|
+
}
|
|
74
|
+
/** An additional configuration file (nginx, eslint, prettier, etc.). */
|
|
75
|
+
export interface InfraConfigFile {
|
|
76
|
+
/** Config purpose (e.g., "nginx", "eslint", "prettier"). */
|
|
77
|
+
purpose: string;
|
|
78
|
+
/** File name. */
|
|
79
|
+
fileName: string;
|
|
80
|
+
/** File content. */
|
|
81
|
+
content: string;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B,2CAA2C;IAC3C,OAAO,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,iCAAiC;IACjC,UAAU,EAAE,eAAe,GAAG,SAAS,CAAC;IACxC,oDAAoD;IACpD,eAAe,EAAE,mBAAmB,EAAE,CAAC;IACvC,uCAAuC;IACvC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,6CAA6C;IAC7C,WAAW,EAAE,eAAe,EAAE,CAAC;CAChC;AAMD,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAMD,qDAAqD;AACrD,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAMD,iCAAiC;AACjC,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAMD,qDAAqD;AACrD,MAAM,WAAW,mBAAmB;IAClC,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,yCAAyC;AACzC,MAAM,WAAW,YAAY;IAC3B,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure artifact type definitions for the Forge infrastructure generation stage.
|
|
3
|
+
*
|
|
4
|
+
* Defines the output schema produced by the infra generation stage,
|
|
5
|
+
* including containers, compose config, CI/CD pipelines, database
|
|
6
|
+
* scripts, environment files, and additional config files.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure output validator for the Forge infra generation stage.
|
|
3
|
+
*
|
|
4
|
+
* Validates LLM-generated infrastructure output against the
|
|
5
|
+
* {@link InfraArtifact} schema with structural, semantic, and
|
|
6
|
+
* security checks.
|
|
7
|
+
*/
|
|
8
|
+
import type { OutputValidator, OutputSchema, ValidationResult } from '@hstm-labs/forge-core';
|
|
9
|
+
/**
|
|
10
|
+
* Validator for infrastructure generation stage output.
|
|
11
|
+
*
|
|
12
|
+
* Performs the following checks:
|
|
13
|
+
* 1. JSON parse validation
|
|
14
|
+
* 2. Required top-level keys
|
|
15
|
+
* 3. Non-empty containers with required fields
|
|
16
|
+
* 4. Non-empty envFiles (at least one)
|
|
17
|
+
* 5. Security: scan content for hardcoded secrets (best-effort)
|
|
18
|
+
* 6. Compose validation (when present)
|
|
19
|
+
* 7. CI pipeline validation (when present)
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const validator = new InfraOutputValidator(true, true);
|
|
24
|
+
* const result = validator.validate(llmOutput, { format: 'json' });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class InfraOutputValidator implements OutputValidator {
|
|
28
|
+
private readonly hasOrchestration;
|
|
29
|
+
private readonly hasCi;
|
|
30
|
+
/**
|
|
31
|
+
* @param hasOrchestration - Whether the profile specifies orchestration
|
|
32
|
+
* @param hasCi - Whether the profile specifies CI
|
|
33
|
+
*/
|
|
34
|
+
constructor(hasOrchestration: boolean, hasCi: boolean);
|
|
35
|
+
/**
|
|
36
|
+
* Validate infrastructure output against the InfraArtifact schema.
|
|
37
|
+
*
|
|
38
|
+
* @param output - Raw LLM output text
|
|
39
|
+
* @param _schema - Output schema (format expected to be 'json')
|
|
40
|
+
* @returns Validation result with descriptive errors
|
|
41
|
+
*/
|
|
42
|
+
validate(output: string, _schema: OutputSchema): ValidationResult;
|
|
43
|
+
/**
|
|
44
|
+
* Recursively scan all string fields for hardcoded secret patterns.
|
|
45
|
+
* This is a best-effort check, not exhaustive.
|
|
46
|
+
*/
|
|
47
|
+
private scanForSecrets;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EAEjB,MAAM,uBAAuB,CAAC;AA4B/B;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,oBAAqB,YAAW,eAAe;IAC1D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;IAEhC;;;OAGG;gBACS,gBAAgB,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO;IAKrD;;;;;;OAMG;IAEH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,gBAAgB;IAmJjE;;;OAGG;IACH,OAAO,CAAC,cAAc;CA2BvB"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Infrastructure output validator for the Forge infra generation stage.
|
|
3
|
+
*
|
|
4
|
+
* Validates LLM-generated infrastructure output against the
|
|
5
|
+
* {@link InfraArtifact} schema with structural, semantic, and
|
|
6
|
+
* security checks.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Constants
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
const REQUIRED_TOP_LEVEL_KEYS = [
|
|
12
|
+
'containers',
|
|
13
|
+
'compose',
|
|
14
|
+
'ciPipeline',
|
|
15
|
+
'databaseScripts',
|
|
16
|
+
'envFiles',
|
|
17
|
+
'configFiles',
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* Best-effort regex patterns to detect hardcoded secrets in content.
|
|
21
|
+
* Matches values that look like real credentials rather than placeholders.
|
|
22
|
+
*/
|
|
23
|
+
const HARDCODED_SECRET_PATTERNS = [
|
|
24
|
+
// password=<non-placeholder> (not ${...} or <...> or CHANGEME etc.)
|
|
25
|
+
/(?:password|passwd|secret|api_key|apikey|token|auth)\s*[=:]\s*["']?(?!(\$\{|<|CHANGEME|changeme|placeholder|your_|TODO|xxx))[A-Za-z0-9!@#$%^&*]{8,}["']?/i,
|
|
26
|
+
];
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Implementation
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
/**
|
|
31
|
+
* Validator for infrastructure generation stage output.
|
|
32
|
+
*
|
|
33
|
+
* Performs the following checks:
|
|
34
|
+
* 1. JSON parse validation
|
|
35
|
+
* 2. Required top-level keys
|
|
36
|
+
* 3. Non-empty containers with required fields
|
|
37
|
+
* 4. Non-empty envFiles (at least one)
|
|
38
|
+
* 5. Security: scan content for hardcoded secrets (best-effort)
|
|
39
|
+
* 6. Compose validation (when present)
|
|
40
|
+
* 7. CI pipeline validation (when present)
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const validator = new InfraOutputValidator(true, true);
|
|
45
|
+
* const result = validator.validate(llmOutput, { format: 'json' });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export class InfraOutputValidator {
|
|
49
|
+
hasOrchestration;
|
|
50
|
+
hasCi;
|
|
51
|
+
/**
|
|
52
|
+
* @param hasOrchestration - Whether the profile specifies orchestration
|
|
53
|
+
* @param hasCi - Whether the profile specifies CI
|
|
54
|
+
*/
|
|
55
|
+
constructor(hasOrchestration, hasCi) {
|
|
56
|
+
this.hasOrchestration = hasOrchestration;
|
|
57
|
+
this.hasCi = hasCi;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Validate infrastructure output against the InfraArtifact schema.
|
|
61
|
+
*
|
|
62
|
+
* @param output - Raw LLM output text
|
|
63
|
+
* @param _schema - Output schema (format expected to be 'json')
|
|
64
|
+
* @returns Validation result with descriptive errors
|
|
65
|
+
*/
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
67
|
+
validate(output, _schema) {
|
|
68
|
+
const errors = [];
|
|
69
|
+
// 1. Parse as JSON
|
|
70
|
+
let parsed;
|
|
71
|
+
try {
|
|
72
|
+
parsed = JSON.parse(output);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
errors.push({
|
|
76
|
+
message: 'Infrastructure output is not valid JSON. Ensure the LLM produces only raw JSON without markdown fences or explanatory text.',
|
|
77
|
+
severity: 'error',
|
|
78
|
+
});
|
|
79
|
+
return { valid: false, errors };
|
|
80
|
+
}
|
|
81
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
82
|
+
errors.push({
|
|
83
|
+
message: 'Infrastructure output must be a JSON object, not an array or primitive.',
|
|
84
|
+
severity: 'error',
|
|
85
|
+
});
|
|
86
|
+
return { valid: false, errors };
|
|
87
|
+
}
|
|
88
|
+
const obj = parsed;
|
|
89
|
+
// 2. Verify required top-level keys
|
|
90
|
+
for (const key of REQUIRED_TOP_LEVEL_KEYS) {
|
|
91
|
+
if (!(key in obj)) {
|
|
92
|
+
errors.push({
|
|
93
|
+
message: `Missing required top-level key: '${key}'.`,
|
|
94
|
+
path: key,
|
|
95
|
+
severity: 'error',
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (errors.length > 0) {
|
|
100
|
+
return { valid: false, errors };
|
|
101
|
+
}
|
|
102
|
+
// 3. Verify containers is non-empty array with required fields
|
|
103
|
+
const containers = obj['containers'];
|
|
104
|
+
if (!Array.isArray(containers) || containers.length === 0) {
|
|
105
|
+
errors.push({
|
|
106
|
+
message: "Key 'containers' must be a non-empty array of container definitions.",
|
|
107
|
+
path: 'containers',
|
|
108
|
+
severity: 'error',
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
for (let i = 0; i < containers.length; i++) {
|
|
113
|
+
const c = containers[i];
|
|
114
|
+
if (c === undefined || typeof c !== 'object' || c === null) {
|
|
115
|
+
errors.push({
|
|
116
|
+
message: `containers[${String(i)}] is not a valid object.`,
|
|
117
|
+
path: `containers[${String(i)}]`,
|
|
118
|
+
severity: 'error',
|
|
119
|
+
});
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
for (const field of ['service', 'fileName', 'content', 'baseImage']) {
|
|
123
|
+
if (typeof c[field] !== 'string' || c[field].length === 0) {
|
|
124
|
+
errors.push({
|
|
125
|
+
message: `containers[${String(i)}] is missing required field '${field}'.`,
|
|
126
|
+
path: `containers[${String(i)}].${field}`,
|
|
127
|
+
severity: 'error',
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// 4. Verify envFiles is non-empty
|
|
134
|
+
const envFiles = obj['envFiles'];
|
|
135
|
+
if (!Array.isArray(envFiles) || envFiles.length === 0) {
|
|
136
|
+
errors.push({
|
|
137
|
+
message: "Key 'envFiles' must be a non-empty array — at least one environment file (.env.example) is required.",
|
|
138
|
+
path: 'envFiles',
|
|
139
|
+
severity: 'error',
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
// 5. Security check: scan all content fields for hardcoded secrets
|
|
143
|
+
this.scanForSecrets(obj, errors);
|
|
144
|
+
// 6. Compose validation (when present and non-null)
|
|
145
|
+
const compose = obj['compose'];
|
|
146
|
+
if (compose !== null && compose !== undefined) {
|
|
147
|
+
if (typeof compose !== 'object' || Array.isArray(compose)) {
|
|
148
|
+
errors.push({
|
|
149
|
+
message: "Key 'compose' must be an object or null.",
|
|
150
|
+
path: 'compose',
|
|
151
|
+
severity: 'error',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
const c = compose;
|
|
156
|
+
if (typeof c['content'] !== 'string' || c['content'].length === 0) {
|
|
157
|
+
errors.push({
|
|
158
|
+
message: "Compose config is missing required field 'content'.",
|
|
159
|
+
path: 'compose.content',
|
|
160
|
+
severity: 'error',
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
if (!Array.isArray(c['services']) || c['services'].length === 0) {
|
|
164
|
+
errors.push({
|
|
165
|
+
message: "Compose config 'services' must be a non-empty array.",
|
|
166
|
+
path: 'compose.services',
|
|
167
|
+
severity: 'error',
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// 7. CI pipeline validation (when present and non-null)
|
|
173
|
+
const ciPipeline = obj['ciPipeline'];
|
|
174
|
+
if (ciPipeline !== null && ciPipeline !== undefined) {
|
|
175
|
+
if (typeof ciPipeline !== 'object' || Array.isArray(ciPipeline)) {
|
|
176
|
+
errors.push({
|
|
177
|
+
message: "Key 'ciPipeline' must be an object or null.",
|
|
178
|
+
path: 'ciPipeline',
|
|
179
|
+
severity: 'error',
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
const ci = ciPipeline;
|
|
184
|
+
if (typeof ci['content'] !== 'string' || ci['content'].length === 0) {
|
|
185
|
+
errors.push({
|
|
186
|
+
message: "CI pipeline is missing required field 'content'.",
|
|
187
|
+
path: 'ciPipeline.content',
|
|
188
|
+
severity: 'error',
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
if (!Array.isArray(ci['stages']) || ci['stages'].length === 0) {
|
|
192
|
+
errors.push({
|
|
193
|
+
message: "CI pipeline 'stages' must be a non-empty array.",
|
|
194
|
+
path: 'ciPipeline.stages',
|
|
195
|
+
severity: 'error',
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return { valid: errors.length === 0, errors };
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Recursively scan all string fields for hardcoded secret patterns.
|
|
204
|
+
* This is a best-effort check, not exhaustive.
|
|
205
|
+
*/
|
|
206
|
+
scanForSecrets(obj, errors) {
|
|
207
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
208
|
+
if (typeof value === 'string') {
|
|
209
|
+
for (const pattern of HARDCODED_SECRET_PATTERNS) {
|
|
210
|
+
if (pattern.test(value)) {
|
|
211
|
+
errors.push({
|
|
212
|
+
message: `Potential hardcoded secret detected in field '${key}'. Use environment variable placeholders instead.`,
|
|
213
|
+
path: key,
|
|
214
|
+
severity: 'error',
|
|
215
|
+
});
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
else if (Array.isArray(value)) {
|
|
221
|
+
for (const item of value) {
|
|
222
|
+
if (typeof item === 'object' && item !== null && !Array.isArray(item)) {
|
|
223
|
+
this.scanForSecrets(item, errors);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else if (typeof value === 'object' && value !== null) {
|
|
228
|
+
this.scanForSecrets(value, errors);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hstm-labs/forge-infra-generator",
|
|
3
|
+
"version": "0.1.11",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"prepublishOnly": "npm run build"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@hstm-labs/forge-common": "0.1.11",
|
|
20
|
+
"@hstm-labs/forge-core": "0.1.11",
|
|
21
|
+
"@hstm-labs/forge-architect": "0.1.11",
|
|
22
|
+
"@hstm-labs/forge-spec-parser": "0.1.11",
|
|
23
|
+
"@hstm-labs/forge-profiles": "0.1.11",
|
|
24
|
+
"@hstm-labs/forge-templates": "0.1.11"
|
|
25
|
+
}
|
|
26
|
+
}
|