@hstm-labs/forge-services-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 ADDED
@@ -0,0 +1,38 @@
1
+ # @hstm-labs/forge-services-generator
2
+
3
+ Services layer generation stage for Forge — produces API (delivery), Application (use cases, DTOs), Domain (entities, value objects), and Infrastructure artifacts from architecture output. Emits artifacts under the four-layer pattern: Api/, Application/, Domain/, Infrastructure/.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @hstm-labs/forge-services-generator
9
+ ```
10
+
11
+ ## Public API
12
+
13
+ ### Types
14
+
15
+ - `ApiArtifact` — complete API layer output
16
+ - `ApiEndpoint` — route definition with method, path, parameters
17
+ - `ApiHandler` — request handler implementation
18
+ - `ApiTypeDefinition` — shared type/interface definitions
19
+ - `ApiContract` — API contract (OpenAPI-style) metadata
20
+
21
+ ### Classes
22
+
23
+ - `ServicesGenerateStage` — pipeline stage implementing `PipelineStage` interface
24
+ - `ApiOutputValidator` — validates LLM-produced API output
25
+
26
+ ## Usage
27
+
28
+ ```typescript
29
+ import { ServicesGenerateStage } from '@hstm-labs/forge-services-generator';
30
+
31
+ const stage = new ServicesGenerateStage();
32
+ const result = await stage.execute(input);
33
+ // result.data contains ApiArtifact
34
+ ```
35
+
36
+ ## License
37
+
38
+ [MIT](../../LICENSE)
@@ -0,0 +1,56 @@
1
+ /**
2
+ * API generation pipeline stage.
3
+ *
4
+ * Produces routes/resolvers, handlers, type definitions, and a contract
5
+ * artifact (OpenAPI/GraphQL schema) from specification, architecture, and
6
+ * profile. Follows the same stage implementation pattern established by
7
+ * {@link ArchitectStage} in Task 5.1.
8
+ *
9
+ * In API mode, renders prompt templates, calls the LLM via
10
+ * {@link ApiStageExecutor}, validates the output, unpacks individual
11
+ * files, and returns the parsed {@link ApiArtifact} in the stage output data.
12
+ *
13
+ * In agent mode, the pipeline runner intercepts before calling
14
+ * `execute()` and exports a prompt via {@link AgentStageExecutor}.
15
+ */
16
+ import type { StageName } from '@hstm-labs/forge-common';
17
+ import type { PipelineStage, PipelineStageInput, PipelineStageOutput, PipelineContext, AgentPromptContext } from '@hstm-labs/forge-core';
18
+ /**
19
+ * Pipeline stage that generates the API layer.
20
+ *
21
+ * Produces an {@link ApiArtifact} containing endpoint definitions, handler
22
+ * source files, type definitions, and a contract artifact. Each handler
23
+ * and type definition is written as a separate file artifact.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const stage = new ApiGenerateStage();
28
+ * const output = await stage.execute(input, context);
29
+ * const api = output.data?.api as ApiArtifact;
30
+ * ```
31
+ */
32
+ export declare class ApiGenerateStage implements PipelineStage {
33
+ readonly name: StageName;
34
+ readonly dependsOn: StageName[];
35
+ readonly requiresLLM = true;
36
+ /**
37
+ * Return rendered agent-mode prompt context using `api-generate-agent.hbs`.
38
+ *
39
+ * @param input - Input from prior stages
40
+ * @param context - Pipeline context with config, workspace, and runId
41
+ * @returns Agent prompt context with rendered template and output schema
42
+ */
43
+ getAgentContext(input: PipelineStageInput, context: PipelineContext): AgentPromptContext;
44
+ /**
45
+ * Execute the API generation stage.
46
+ *
47
+ * @param input - Input from prior stages (expects validate + architect output)
48
+ * @param context - Pipeline context with config, workspace, and adapter
49
+ * @returns Stage output with API artifacts and parsed ApiArtifact in data
50
+ * @throws {ForgeError} FORGE-PIPE-003 if dependency stage output is missing
51
+ * @throws {ForgeError} FORGE-PIPE-001 if adapter is missing
52
+ * @throws {ForgeError} FORGE-GEN-003 if max retries exhausted
53
+ */
54
+ execute(input: PipelineStageInput, context: PipelineContext): Promise<PipelineStageOutput>;
55
+ }
56
+ //# sourceMappingURL=api-generate-stage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-generate-stage.d.ts","sourceRoot":"","sources":["../src/api-generate-stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;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;AAW/B;;;;;;;;;;;;;GAaG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IACpD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAkB;IAC1C,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;IA2CrB;;;;;;;;;OASG;IACG,OAAO,CACX,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,mBAAmB,CAAC;CAmKhC"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * API generation pipeline stage.
3
+ *
4
+ * Produces routes/resolvers, handlers, type definitions, and a contract
5
+ * artifact (OpenAPI/GraphQL schema) from specification, architecture, and
6
+ * profile. Follows the same stage implementation pattern established by
7
+ * {@link ArchitectStage} in Task 5.1.
8
+ *
9
+ * In API mode, renders prompt templates, calls the LLM via
10
+ * {@link ApiStageExecutor}, validates the output, unpacks individual
11
+ * files, and returns the parsed {@link ApiArtifact} in the stage output data.
12
+ *
13
+ * In agent mode, the pipeline runner intercepts before calling
14
+ * `execute()` and exports a prompt via {@link AgentStageExecutor}.
15
+ */
16
+ import { join } from 'node:path';
17
+ import { writeFileSync, mkdirSync } from 'node:fs';
18
+ import { ForgeError, ErrorCodes, hashContent } from '@hstm-labs/forge-common';
19
+ import { ApiStageExecutor } from '@hstm-labs/forge-core';
20
+ import { resolveApiStyle } from '@hstm-labs/forge-architect';
21
+ import { loadProfile } from '@hstm-labs/forge-profiles';
22
+ import { loadTemplate, renderTemplate } from '@hstm-labs/forge-templates';
23
+ import { ApiOutputValidator } from './validator.js';
24
+ /**
25
+ * Pipeline stage that generates the API layer.
26
+ *
27
+ * Produces an {@link ApiArtifact} containing endpoint definitions, handler
28
+ * source files, type definitions, and a contract artifact. Each handler
29
+ * and type definition is written as a separate file artifact.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * const stage = new ApiGenerateStage();
34
+ * const output = await stage.execute(input, context);
35
+ * const api = output.data?.api as ApiArtifact;
36
+ * ```
37
+ */
38
+ export class ApiGenerateStage {
39
+ name = 'api-generate';
40
+ dependsOn = ['architect'];
41
+ requiresLLM = true;
42
+ /**
43
+ * Return rendered agent-mode prompt context using `api-generate-agent.hbs`.
44
+ *
45
+ * @param input - Input from prior stages
46
+ * @param context - Pipeline context with config, workspace, and runId
47
+ * @returns Agent prompt context with rendered template and output schema
48
+ */
49
+ getAgentContext(input, context) {
50
+ const parsedSpec = input['validate']?.data?.['parsedSpec'];
51
+ const architecture = input['architect']?.data?.['architecture'];
52
+ const profile = loadProfile(context.config.profileName, context.workspace.rootDir);
53
+ const resolvedApiStyle = parsedSpec
54
+ ? resolveApiStyle(parsedSpec, profile)
55
+ : 'graphql';
56
+ const outputDir = join(context.workspace.forgeDir, 'runs', context.runId, 'stages', 'api-generate', 'artifacts');
57
+ const agentTemplate = loadTemplate('api-generate-agent', context.workspace.rootDir);
58
+ const rendered = renderTemplate(agentTemplate, {
59
+ spec: (parsedSpec ?? {}),
60
+ profile: profile,
61
+ architecture: (architecture ?? {}),
62
+ stage: { resolvedApiStyle, outputDir },
63
+ });
64
+ return {
65
+ prompt: rendered.content,
66
+ outputSchema: { format: 'json' },
67
+ };
68
+ }
69
+ /**
70
+ * Execute the API generation stage.
71
+ *
72
+ * @param input - Input from prior stages (expects validate + architect output)
73
+ * @param context - Pipeline context with config, workspace, and adapter
74
+ * @returns Stage output with API artifacts and parsed ApiArtifact in data
75
+ * @throws {ForgeError} FORGE-PIPE-003 if dependency stage output is missing
76
+ * @throws {ForgeError} FORGE-PIPE-001 if adapter is missing
77
+ * @throws {ForgeError} FORGE-GEN-003 if max retries exhausted
78
+ */
79
+ async execute(input, context) {
80
+ // 1. Get parsed spec from validate stage output
81
+ const validateOutput = input['validate'];
82
+ if (validateOutput === undefined) {
83
+ throw new ForgeError(ErrorCodes.PIPE.DEPENDENCY_UNMET, "API generate stage requires 'validate' stage output, but it was not found. " +
84
+ 'Ensure the validate stage runs before the api-generate stage.');
85
+ }
86
+ const parsedSpec = validateOutput.data?.['parsedSpec'];
87
+ if (parsedSpec === undefined) {
88
+ throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Validate stage did not produce a parsed specification in its output data. ' +
89
+ 'Ensure the validate stage includes parsedSpec in its data output.');
90
+ }
91
+ // 2. Get architecture from architect stage output
92
+ const architectOutput = input['architect'];
93
+ if (architectOutput === undefined) {
94
+ throw new ForgeError(ErrorCodes.PIPE.DEPENDENCY_UNMET, "API generate stage requires 'architect' stage output, but it was not found. " +
95
+ 'Ensure the architect stage runs before the api-generate stage.');
96
+ }
97
+ const architecture = architectOutput.data?.['architecture'];
98
+ if (architecture === undefined) {
99
+ throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Architect stage did not produce an architecture in its output data. ' +
100
+ 'Ensure the architect stage includes architecture in its data output.');
101
+ }
102
+ // 3. Load profile, resolve API style
103
+ const profile = loadProfile(context.config.profileName, context.workspace.rootDir);
104
+ const resolvedApiStyle = resolveApiStyle(parsedSpec, profile);
105
+ // 4. Compute output directory
106
+ const outputDir = join(context.workspace.forgeDir, 'runs', context.runId, 'stages', 'api-generate', 'artifacts');
107
+ // 5. Load and render templates
108
+ const systemTemplate = loadTemplate('api-generate-system', context.workspace.rootDir);
109
+ const userTemplate = loadTemplate('api-generate-user', context.workspace.rootDir);
110
+ const templateContext = {
111
+ spec: parsedSpec,
112
+ profile: profile,
113
+ architecture: architecture,
114
+ stage: {
115
+ resolvedApiStyle,
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, 'API 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 ApiOutputValidator(architecture.dataModel);
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: 'api-generate',
140
+ outputDir,
141
+ runId: context.runId,
142
+ mode: 'api',
143
+ outputSchema: { format: 'json' },
144
+ });
145
+ // 7. Parse ApiArtifact from LLM output
146
+ const rawContent = result.artifacts[0]?.content ?? '';
147
+ const apiArtifact = JSON.parse(rawContent);
148
+ // 8. Write individual files to artifacts directory
149
+ mkdirSync(outputDir, { recursive: true });
150
+ const artifacts = [];
151
+ // Write handler files
152
+ for (const handler of apiArtifact.handlers) {
153
+ const filePath = handler.fileName;
154
+ writeFileSync(join(outputDir, filePath), handler.content, 'utf-8');
155
+ artifacts.push({
156
+ filePath,
157
+ content: handler.content,
158
+ contentHash: hashContent(handler.content),
159
+ sizeBytes: Buffer.byteLength(handler.content, 'utf-8'),
160
+ });
161
+ }
162
+ // Write type definition files
163
+ for (const typeDef of apiArtifact.types) {
164
+ const filePath = typeDef.fileName;
165
+ writeFileSync(join(outputDir, filePath), typeDef.content, 'utf-8');
166
+ artifacts.push({
167
+ filePath,
168
+ content: typeDef.content,
169
+ contentHash: hashContent(typeDef.content),
170
+ sizeBytes: Buffer.byteLength(typeDef.content, 'utf-8'),
171
+ });
172
+ }
173
+ // Write contract artifact
174
+ const contractPath = apiArtifact.contract.fileName;
175
+ writeFileSync(join(outputDir, contractPath), apiArtifact.contract.content, 'utf-8');
176
+ artifacts.push({
177
+ filePath: contractPath,
178
+ content: apiArtifact.contract.content,
179
+ contentHash: hashContent(apiArtifact.contract.content),
180
+ sizeBytes: Buffer.byteLength(apiArtifact.contract.content, 'utf-8'),
181
+ });
182
+ // 9. Return PipelineStageOutput with all artifacts and data
183
+ return {
184
+ artifacts,
185
+ data: {
186
+ api: apiArtifact,
187
+ },
188
+ };
189
+ }
190
+ }
191
+ //# sourceMappingURL=api-generate-stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-generate-stage.js","sourceRoot":"","sources":["../src/api-generate-stage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type { ApiArtifact, ApiEndpoint, ApiHandler, ApiTypeDefinition, ApiContract, } from './types.js';
2
+ export { ServicesGenerateStage } from './services-generate-stage.js';
3
+ export { ApiOutputValidator } 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":"AAEA,YAAY,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ // @hstm-labs/forge-services-generator public API
2
+ export { ServicesGenerateStage } from './services-generate-stage.js';
3
+ export { ApiOutputValidator } from './validator.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iDAAiD;AAUjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Services generation pipeline stage.
3
+ *
4
+ * Produces routes/resolvers, handlers, type definitions, and a contract
5
+ * artifact (OpenAPI/GraphQL schema) from specification, architecture, and
6
+ * profile. Emits artifacts under Api/, Application/, Domain/, Infrastructure/
7
+ * (four-layer pattern). Follows the same stage implementation pattern as
8
+ * {@link ArchitectStage}.
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 ApiArtifact} in the stage output data.
13
+ *
14
+ * In agent mode, the pipeline runner intercepts before calling
15
+ * `execute()` and exports a prompt via {@link AgentStageExecutor}.
16
+ */
17
+ import type { StageName } from '@hstm-labs/forge-common';
18
+ import type { PipelineStage, PipelineStageInput, PipelineStageOutput, PipelineContext, AgentPromptContext } from '@hstm-labs/forge-core';
19
+ /**
20
+ * Pipeline stage that generates the API layer.
21
+ *
22
+ * Produces an {@link ApiArtifact} containing endpoint definitions, handler
23
+ * source files, type definitions, and a contract artifact. Each handler
24
+ * and type definition is written as a separate file artifact.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * const stage = new ServicesGenerateStage();
29
+ * const output = await stage.execute(input, context);
30
+ * const api = output.data?.api as ApiArtifact;
31
+ * ```
32
+ */
33
+ export declare class ServicesGenerateStage implements PipelineStage {
34
+ readonly name: StageName;
35
+ readonly dependsOn: StageName[];
36
+ readonly requiresLLM = true;
37
+ /**
38
+ * Return rendered agent-mode prompt context using `services-generate-agent.hbs`.
39
+ *
40
+ * @param input - Input from prior stages
41
+ * @param context - Pipeline context with config, workspace, and runId
42
+ * @returns Agent prompt context with rendered template and output schema
43
+ */
44
+ getAgentContext(input: PipelineStageInput, context: PipelineContext): AgentPromptContext;
45
+ /**
46
+ * Execute the API generation stage.
47
+ *
48
+ * @param input - Input from prior stages (expects validate + architect output)
49
+ * @param context - Pipeline context with config, workspace, and adapter
50
+ * @returns Stage output with API artifacts and parsed ApiArtifact in data
51
+ * @throws {ForgeError} FORGE-PIPE-003 if dependency stage output is missing
52
+ * @throws {ForgeError} FORGE-PIPE-001 if adapter is missing
53
+ * @throws {ForgeError} FORGE-GEN-003 if max retries exhausted
54
+ */
55
+ execute(input: PipelineStageInput, context: PipelineContext): Promise<PipelineStageOutput>;
56
+ }
57
+ //# sourceMappingURL=services-generate-stage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services-generate-stage.d.ts","sourceRoot":"","sources":["../src/services-generate-stage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;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;AAW/B;;;;;;;;;;;;;GAaG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IACzD,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAuB;IAC/C,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;IA2CrB;;;;;;;;;OASG;IACG,OAAO,CACX,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,mBAAmB,CAAC;CAmKhC"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Services generation pipeline stage.
3
+ *
4
+ * Produces routes/resolvers, handlers, type definitions, and a contract
5
+ * artifact (OpenAPI/GraphQL schema) from specification, architecture, and
6
+ * profile. Emits artifacts under Api/, Application/, Domain/, Infrastructure/
7
+ * (four-layer pattern). Follows the same stage implementation pattern as
8
+ * {@link ArchitectStage}.
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 ApiArtifact} in the stage output data.
13
+ *
14
+ * In agent mode, the pipeline runner intercepts before calling
15
+ * `execute()` and exports a prompt via {@link AgentStageExecutor}.
16
+ */
17
+ import { join } from 'node:path';
18
+ import { writeFileSync, mkdirSync } from 'node:fs';
19
+ import { ForgeError, ErrorCodes, hashContent } from '@hstm-labs/forge-common';
20
+ import { ApiStageExecutor } from '@hstm-labs/forge-core';
21
+ import { resolveApiStyle } from '@hstm-labs/forge-architect';
22
+ import { loadProfile } from '@hstm-labs/forge-profiles';
23
+ import { loadTemplate, renderTemplate } from '@hstm-labs/forge-templates';
24
+ import { ApiOutputValidator } from './validator.js';
25
+ /**
26
+ * Pipeline stage that generates the API layer.
27
+ *
28
+ * Produces an {@link ApiArtifact} containing endpoint definitions, handler
29
+ * source files, type definitions, and a contract artifact. Each handler
30
+ * and type definition is written as a separate file artifact.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * const stage = new ServicesGenerateStage();
35
+ * const output = await stage.execute(input, context);
36
+ * const api = output.data?.api as ApiArtifact;
37
+ * ```
38
+ */
39
+ export class ServicesGenerateStage {
40
+ name = 'services-generate';
41
+ dependsOn = ['architect'];
42
+ requiresLLM = true;
43
+ /**
44
+ * Return rendered agent-mode prompt context using `services-generate-agent.hbs`.
45
+ *
46
+ * @param input - Input from prior stages
47
+ * @param context - Pipeline context with config, workspace, and runId
48
+ * @returns Agent prompt context with rendered template and output schema
49
+ */
50
+ getAgentContext(input, context) {
51
+ const parsedSpec = input['validate']?.data?.['parsedSpec'];
52
+ const architecture = input['architect']?.data?.['architecture'];
53
+ const profile = loadProfile(context.config.profileName, context.workspace.rootDir);
54
+ const resolvedApiStyle = parsedSpec
55
+ ? resolveApiStyle(parsedSpec, profile)
56
+ : 'graphql';
57
+ const outputDir = join(context.workspace.forgeDir, 'runs', context.runId, 'stages', 'services-generate', 'artifacts');
58
+ const agentTemplate = loadTemplate('services-generate-agent', context.workspace.rootDir);
59
+ const rendered = renderTemplate(agentTemplate, {
60
+ spec: (parsedSpec ?? {}),
61
+ profile: profile,
62
+ architecture: (architecture ?? {}),
63
+ stage: { resolvedApiStyle, outputDir },
64
+ });
65
+ return {
66
+ prompt: rendered.content,
67
+ outputSchema: { format: 'json' },
68
+ };
69
+ }
70
+ /**
71
+ * Execute the API generation stage.
72
+ *
73
+ * @param input - Input from prior stages (expects validate + architect output)
74
+ * @param context - Pipeline context with config, workspace, and adapter
75
+ * @returns Stage output with API artifacts and parsed ApiArtifact in data
76
+ * @throws {ForgeError} FORGE-PIPE-003 if dependency stage output is missing
77
+ * @throws {ForgeError} FORGE-PIPE-001 if adapter is missing
78
+ * @throws {ForgeError} FORGE-GEN-003 if max retries exhausted
79
+ */
80
+ async execute(input, context) {
81
+ // 1. Get parsed spec from validate stage output
82
+ const validateOutput = input['validate'];
83
+ if (validateOutput === undefined) {
84
+ throw new ForgeError(ErrorCodes.PIPE.DEPENDENCY_UNMET, "Services generate stage requires 'validate' stage output, but it was not found. " +
85
+ 'Ensure the validate stage runs before the services-generate stage.');
86
+ }
87
+ const parsedSpec = validateOutput.data?.['parsedSpec'];
88
+ if (parsedSpec === undefined) {
89
+ throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Validate stage did not produce a parsed specification in its output data. ' +
90
+ 'Ensure the validate stage includes parsedSpec in its data output.');
91
+ }
92
+ // 2. Get architecture from architect stage output
93
+ const architectOutput = input['architect'];
94
+ if (architectOutput === undefined) {
95
+ throw new ForgeError(ErrorCodes.PIPE.DEPENDENCY_UNMET, "Services generate stage requires 'architect' stage output, but it was not found. " +
96
+ 'Ensure the architect stage runs before the services-generate stage.');
97
+ }
98
+ const architecture = architectOutput.data?.['architecture'];
99
+ if (architecture === undefined) {
100
+ throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Architect stage did not produce an architecture in its output data. ' +
101
+ 'Ensure the architect stage includes architecture in its data output.');
102
+ }
103
+ // 3. Load profile, resolve API style
104
+ const profile = loadProfile(context.config.profileName, context.workspace.rootDir);
105
+ const resolvedApiStyle = resolveApiStyle(parsedSpec, profile);
106
+ // 4. Compute output directory
107
+ const outputDir = join(context.workspace.forgeDir, 'runs', context.runId, 'stages', 'services-generate', 'artifacts');
108
+ // 5. Load and render templates
109
+ const systemTemplate = loadTemplate('services-generate-system', context.workspace.rootDir);
110
+ const userTemplate = loadTemplate('services-generate-user', context.workspace.rootDir);
111
+ const templateContext = {
112
+ spec: parsedSpec,
113
+ profile: profile,
114
+ architecture: architecture,
115
+ stage: {
116
+ resolvedApiStyle,
117
+ outputDir,
118
+ },
119
+ };
120
+ const systemPrompt = renderTemplate(systemTemplate, templateContext);
121
+ const userPrompt = renderTemplate(userTemplate, templateContext);
122
+ // 6. Execute via API mode StageExecutor
123
+ if (context.adapter === undefined) {
124
+ throw new ForgeError(ErrorCodes.PIPE.STAGE_FAILURE, 'Services generate stage requires an LLM adapter in API mode, but none was provided. ' +
125
+ 'Configure an LLM provider in forge.config.json or use agent mode.');
126
+ }
127
+ const validator = new ApiOutputValidator(architecture.dataModel);
128
+ const executor = new ApiStageExecutor({
129
+ adapter: context.adapter,
130
+ validator,
131
+ retryPolicy: {
132
+ maxRetries: 3,
133
+ backoffMs: 1000,
134
+ includeErrorInRetry: true,
135
+ },
136
+ });
137
+ const result = await executor.execute({
138
+ prompt: userPrompt.content,
139
+ systemPrompt: systemPrompt.content,
140
+ stageName: 'services-generate',
141
+ outputDir,
142
+ runId: context.runId,
143
+ mode: 'api',
144
+ outputSchema: { format: 'json' },
145
+ });
146
+ // 7. Parse ApiArtifact from LLM output
147
+ const rawContent = result.artifacts[0]?.content ?? '';
148
+ const apiArtifact = JSON.parse(rawContent);
149
+ // 8. Write individual files to artifacts directory
150
+ mkdirSync(outputDir, { recursive: true });
151
+ const artifacts = [];
152
+ // Write handler files
153
+ for (const handler of apiArtifact.handlers) {
154
+ const filePath = handler.fileName;
155
+ writeFileSync(join(outputDir, filePath), handler.content, 'utf-8');
156
+ artifacts.push({
157
+ filePath,
158
+ content: handler.content,
159
+ contentHash: hashContent(handler.content),
160
+ sizeBytes: Buffer.byteLength(handler.content, 'utf-8'),
161
+ });
162
+ }
163
+ // Write type definition files
164
+ for (const typeDef of apiArtifact.types) {
165
+ const filePath = typeDef.fileName;
166
+ writeFileSync(join(outputDir, filePath), typeDef.content, 'utf-8');
167
+ artifacts.push({
168
+ filePath,
169
+ content: typeDef.content,
170
+ contentHash: hashContent(typeDef.content),
171
+ sizeBytes: Buffer.byteLength(typeDef.content, 'utf-8'),
172
+ });
173
+ }
174
+ // Write contract artifact
175
+ const contractPath = apiArtifact.contract.fileName;
176
+ writeFileSync(join(outputDir, contractPath), apiArtifact.contract.content, 'utf-8');
177
+ artifacts.push({
178
+ filePath: contractPath,
179
+ content: apiArtifact.contract.content,
180
+ contentHash: hashContent(apiArtifact.contract.content),
181
+ sizeBytes: Buffer.byteLength(apiArtifact.contract.content, 'utf-8'),
182
+ });
183
+ // 9. Return PipelineStageOutput with all artifacts and data
184
+ return {
185
+ artifacts,
186
+ data: {
187
+ api: apiArtifact,
188
+ },
189
+ };
190
+ }
191
+ }
192
+ //# sourceMappingURL=services-generate-stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"services-generate-stage.js","sourceRoot":"","sources":["../src/services-generate-stage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * API artifact type definitions for the Forge API generation stage.
3
+ *
4
+ * Defines the output schema produced by the API generation stage,
5
+ * including endpoints, handlers, type definitions, and the contract
6
+ * artifact (OpenAPI or GraphQL schema).
7
+ */
8
+ /** Complete API layer output produced by the services-generate stage. */
9
+ export interface ApiArtifact {
10
+ /** Resolved API style for this generation. */
11
+ apiStyle: 'rest' | 'graphql' | 'grpc';
12
+ /** Generated route/resolver definitions. */
13
+ endpoints: ApiEndpoint[];
14
+ /** Generated handler implementations (source code). */
15
+ handlers: ApiHandler[];
16
+ /** Type/schema definitions. */
17
+ types: ApiTypeDefinition[];
18
+ /** Contract artifact content. */
19
+ contract: ApiContract;
20
+ }
21
+ /** A single API endpoint or resolver definition. */
22
+ export interface ApiEndpoint {
23
+ /** Entity or resource this endpoint covers. */
24
+ entity: string;
25
+ /** HTTP method (REST) or operation type (GraphQL: query/mutation). */
26
+ method: string;
27
+ /** Route path (REST: /api/pets) or field name (GraphQL: pets). */
28
+ path: string;
29
+ /** Handler function name. */
30
+ handler: string;
31
+ /** Description. */
32
+ description: string;
33
+ }
34
+ /** A generated handler source file. */
35
+ export interface ApiHandler {
36
+ /** File name (e.g., "pet-router.ts", "pet-resolver.ts"). */
37
+ fileName: string;
38
+ /** File content (source code). */
39
+ content: string;
40
+ /** Entity this handler covers. */
41
+ entity: string;
42
+ }
43
+ /** A generated TypeScript type/interface definition file. */
44
+ export interface ApiTypeDefinition {
45
+ /** Type name. */
46
+ name: string;
47
+ /** File name. */
48
+ fileName: string;
49
+ /** File content. */
50
+ content: string;
51
+ }
52
+ /** The API contract artifact (OpenAPI spec or GraphQL schema). */
53
+ export interface ApiContract {
54
+ /** Contract format. */
55
+ format: 'openapi' | 'graphql';
56
+ /** File name (openapi.json or schema.graphql). */
57
+ fileName: string;
58
+ /** Contract content (JSON string or GraphQL SDL). */
59
+ content: string;
60
+ }
61
+ //# 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,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;IACtC,4CAA4C;IAC5C,SAAS,EAAE,WAAW,EAAE,CAAC;IACzB,uDAAuD;IACvD,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,+BAA+B;IAC/B,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,iCAAiC;IACjC,QAAQ,EAAE,WAAW,CAAC;CACvB;AAMD,oDAAoD;AACpD,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAMD,uCAAuC;AACvC,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,uBAAuB;IACvB,MAAM,EAAE,SAAS,GAAG,SAAS,CAAC;IAC9B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC;CACjB"}
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * API artifact type definitions for the Forge API generation stage.
3
+ *
4
+ * Defines the output schema produced by the API generation stage,
5
+ * including endpoints, handlers, type definitions, and the contract
6
+ * artifact (OpenAPI or GraphQL schema).
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,42 @@
1
+ /**
2
+ * API output validator for the Forge API generation stage.
3
+ *
4
+ * Validates LLM-generated API output against the
5
+ * {@link ApiArtifact} schema with structural and semantic checks.
6
+ */
7
+ import type { OutputValidator, OutputSchema, ValidationResult } from '@hstm-labs/forge-core';
8
+ import type { DataModelEntity } from '@hstm-labs/forge-architect';
9
+ /**
10
+ * Validator for API generation stage output.
11
+ *
12
+ * Performs the following checks:
13
+ * 1. JSON parse validation
14
+ * 2. Required top-level keys
15
+ * 3. Non-empty endpoints with required fields
16
+ * 4. Entity coverage (every data model entity has endpoints)
17
+ * 5. Contract presence with valid format, fileName, and content
18
+ * 6. Contract format matches apiStyle
19
+ * 7. Non-empty handlers with fileName and content
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const validator = new ApiOutputValidator(dataModelEntities);
24
+ * const result = validator.validate(llmOutput, { format: 'json' });
25
+ * ```
26
+ */
27
+ export declare class ApiOutputValidator implements OutputValidator {
28
+ private readonly dataModelEntities;
29
+ /**
30
+ * @param dataModelEntities - Data model entities to verify endpoint coverage
31
+ */
32
+ constructor(dataModelEntities: DataModelEntity[]);
33
+ /**
34
+ * Validate API output against the ApiArtifact schema.
35
+ *
36
+ * @param output - Raw LLM output text
37
+ * @param _schema - Output schema (format expected to be 'json')
38
+ * @returns Validation result with descriptive errors
39
+ */
40
+ validate(output: string, _schema: OutputSchema): ValidationResult;
41
+ }
42
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EAEjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAuBlE;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,kBAAmB,YAAW,eAAe;IACxD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAoB;IAEtD;;OAEG;gBACS,iBAAiB,EAAE,eAAe,EAAE;IAIhD;;;;;;OAMG;IAEH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,gBAAgB;CAiMlE"}
@@ -0,0 +1,236 @@
1
+ /**
2
+ * API output validator for the Forge API generation stage.
3
+ *
4
+ * Validates LLM-generated API output against the
5
+ * {@link ApiArtifact} schema with structural and semantic checks.
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // Contract format mapping
9
+ // ---------------------------------------------------------------------------
10
+ const API_STYLE_TO_CONTRACT_FORMAT = {
11
+ rest: 'openapi',
12
+ graphql: 'graphql',
13
+ };
14
+ const REQUIRED_TOP_LEVEL_KEYS = [
15
+ 'apiStyle',
16
+ 'endpoints',
17
+ 'handlers',
18
+ 'types',
19
+ 'contract',
20
+ ];
21
+ // ---------------------------------------------------------------------------
22
+ // Implementation
23
+ // ---------------------------------------------------------------------------
24
+ /**
25
+ * Validator for API generation stage output.
26
+ *
27
+ * Performs the following checks:
28
+ * 1. JSON parse validation
29
+ * 2. Required top-level keys
30
+ * 3. Non-empty endpoints with required fields
31
+ * 4. Entity coverage (every data model entity has endpoints)
32
+ * 5. Contract presence with valid format, fileName, and content
33
+ * 6. Contract format matches apiStyle
34
+ * 7. Non-empty handlers with fileName and content
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * const validator = new ApiOutputValidator(dataModelEntities);
39
+ * const result = validator.validate(llmOutput, { format: 'json' });
40
+ * ```
41
+ */
42
+ export class ApiOutputValidator {
43
+ dataModelEntities;
44
+ /**
45
+ * @param dataModelEntities - Data model entities to verify endpoint coverage
46
+ */
47
+ constructor(dataModelEntities) {
48
+ this.dataModelEntities = dataModelEntities;
49
+ }
50
+ /**
51
+ * Validate API output against the ApiArtifact schema.
52
+ *
53
+ * @param output - Raw LLM output text
54
+ * @param _schema - Output schema (format expected to be 'json')
55
+ * @returns Validation result with descriptive errors
56
+ */
57
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
58
+ validate(output, _schema) {
59
+ const errors = [];
60
+ // 1. Parse as JSON
61
+ let parsed;
62
+ try {
63
+ parsed = JSON.parse(output);
64
+ }
65
+ catch {
66
+ errors.push({
67
+ message: 'API output is not valid JSON. Ensure the LLM produces only raw JSON without markdown fences or explanatory text.',
68
+ severity: 'error',
69
+ });
70
+ return { valid: false, errors };
71
+ }
72
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
73
+ errors.push({
74
+ message: 'API output must be a JSON object, not an array or primitive.',
75
+ severity: 'error',
76
+ });
77
+ return { valid: false, errors };
78
+ }
79
+ const obj = parsed;
80
+ // 2. Verify required top-level keys
81
+ for (const key of REQUIRED_TOP_LEVEL_KEYS) {
82
+ if (!(key in obj)) {
83
+ errors.push({
84
+ message: `Missing required top-level key: '${key}'.`,
85
+ path: key,
86
+ severity: 'error',
87
+ });
88
+ }
89
+ }
90
+ if (errors.length > 0) {
91
+ return { valid: false, errors };
92
+ }
93
+ // 3. Verify endpoints is non-empty array with required fields
94
+ const endpoints = obj['endpoints'];
95
+ if (!Array.isArray(endpoints) || endpoints.length === 0) {
96
+ errors.push({
97
+ message: "Key 'endpoints' must be a non-empty array of endpoint definitions.",
98
+ path: 'endpoints',
99
+ severity: 'error',
100
+ });
101
+ }
102
+ else {
103
+ for (let i = 0; i < endpoints.length; i++) {
104
+ const ep = endpoints[i];
105
+ if (ep === undefined || typeof ep !== 'object' || ep === null) {
106
+ errors.push({
107
+ message: `endpoints[${String(i)}] is not a valid object.`,
108
+ path: `endpoints[${String(i)}]`,
109
+ severity: 'error',
110
+ });
111
+ continue;
112
+ }
113
+ if (typeof ep['entity'] !== 'string' || ep['entity'].length === 0) {
114
+ errors.push({
115
+ message: `endpoints[${String(i)}] is missing required field 'entity'.`,
116
+ path: `endpoints[${String(i)}].entity`,
117
+ severity: 'error',
118
+ });
119
+ }
120
+ if (typeof ep['method'] !== 'string' || ep['method'].length === 0) {
121
+ errors.push({
122
+ message: `endpoints[${String(i)}] is missing required field 'method'.`,
123
+ path: `endpoints[${String(i)}].method`,
124
+ severity: 'error',
125
+ });
126
+ }
127
+ if (typeof ep['path'] !== 'string' || ep['path'].length === 0) {
128
+ errors.push({
129
+ message: `endpoints[${String(i)}] is missing required field 'path'.`,
130
+ path: `endpoints[${String(i)}].path`,
131
+ severity: 'error',
132
+ });
133
+ }
134
+ }
135
+ }
136
+ // 4. Entity coverage — every data model entity has at least one endpoint
137
+ if (Array.isArray(endpoints) && endpoints.length > 0) {
138
+ const endpointEntities = new Set(endpoints
139
+ .filter((ep) => typeof ep['entity'] === 'string')
140
+ .map((ep) => ep['entity'].toLowerCase()));
141
+ for (const entity of this.dataModelEntities) {
142
+ if (!endpointEntities.has(entity.name.toLowerCase())) {
143
+ errors.push({
144
+ message: `Data model entity '${entity.name}' has no corresponding endpoints. Every entity must have API coverage.`,
145
+ path: 'endpoints',
146
+ severity: 'error',
147
+ });
148
+ }
149
+ }
150
+ }
151
+ // 5. Verify contract has valid format, fileName, and non-empty content
152
+ const contract = obj['contract'];
153
+ if (typeof contract !== 'object' || contract === null || Array.isArray(contract)) {
154
+ errors.push({
155
+ message: "Key 'contract' must be an object with format, fileName, and content.",
156
+ path: 'contract',
157
+ severity: 'error',
158
+ });
159
+ }
160
+ else {
161
+ const c = contract;
162
+ if (typeof c['format'] !== 'string' || c['format'].length === 0) {
163
+ errors.push({
164
+ message: "Contract is missing required field 'format'.",
165
+ path: 'contract.format',
166
+ severity: 'error',
167
+ });
168
+ }
169
+ if (typeof c['fileName'] !== 'string' || c['fileName'].length === 0) {
170
+ errors.push({
171
+ message: "Contract is missing required field 'fileName'.",
172
+ path: 'contract.fileName',
173
+ severity: 'error',
174
+ });
175
+ }
176
+ if (typeof c['content'] !== 'string' || c['content'].length === 0) {
177
+ errors.push({
178
+ message: "Contract is missing required field 'content' (must be non-empty).",
179
+ path: 'contract.content',
180
+ severity: 'error',
181
+ });
182
+ }
183
+ // 6. Verify contract format matches apiStyle
184
+ const apiStyle = obj['apiStyle'];
185
+ if (typeof apiStyle === 'string' &&
186
+ typeof c['format'] === 'string') {
187
+ const expectedFormat = API_STYLE_TO_CONTRACT_FORMAT[apiStyle];
188
+ if (expectedFormat !== undefined && c['format'] !== expectedFormat) {
189
+ errors.push({
190
+ message: `Contract format '${c['format']}' does not match API style '${apiStyle}'. Expected '${expectedFormat}'.`,
191
+ path: 'contract.format',
192
+ severity: 'error',
193
+ });
194
+ }
195
+ }
196
+ }
197
+ // 7. Verify handlers is non-empty array with fileName and content
198
+ const handlers = obj['handlers'];
199
+ if (!Array.isArray(handlers) || handlers.length === 0) {
200
+ errors.push({
201
+ message: "Key 'handlers' must be a non-empty array of handler definitions.",
202
+ path: 'handlers',
203
+ severity: 'error',
204
+ });
205
+ }
206
+ else {
207
+ for (let i = 0; i < handlers.length; i++) {
208
+ const h = handlers[i];
209
+ if (h === undefined || typeof h !== 'object' || h === null) {
210
+ errors.push({
211
+ message: `handlers[${String(i)}] is not a valid object.`,
212
+ path: `handlers[${String(i)}]`,
213
+ severity: 'error',
214
+ });
215
+ continue;
216
+ }
217
+ if (typeof h['fileName'] !== 'string' || h['fileName'].length === 0) {
218
+ errors.push({
219
+ message: `handlers[${String(i)}] is missing required field 'fileName'.`,
220
+ path: `handlers[${String(i)}].fileName`,
221
+ severity: 'error',
222
+ });
223
+ }
224
+ if (typeof h['content'] !== 'string' || h['content'].length === 0) {
225
+ errors.push({
226
+ message: `handlers[${String(i)}] is missing required field 'content'.`,
227
+ path: `handlers[${String(i)}].content`,
228
+ severity: 'error',
229
+ });
230
+ }
231
+ }
232
+ }
233
+ return { valid: errors.length === 0, errors };
234
+ }
235
+ }
236
+ //# 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-services-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
+ }