@0kmpo/openapi-clean-arch-generator 1.3.10

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.
Files changed (52) hide show
  1. package/.gitea/workflows/lint.yaml +41 -0
  2. package/.gitea/workflows/publish.yml +105 -0
  3. package/.openapi-generator-ignore +33 -0
  4. package/.prettierrc +7 -0
  5. package/LICENSE +21 -0
  6. package/README.md +333 -0
  7. package/dist/main.js +180 -0
  8. package/eslint.config.js +33 -0
  9. package/example-swagger.yaml +150 -0
  10. package/generation-config.json +24 -0
  11. package/main.ts +233 -0
  12. package/openapitools.json +23 -0
  13. package/package.json +70 -0
  14. package/src/generators/clean-arch.generator.ts +537 -0
  15. package/src/generators/dto.generator.ts +126 -0
  16. package/src/generators/lint.generator.ts +124 -0
  17. package/src/generators/report.generator.ts +80 -0
  18. package/src/swagger/analyzer.ts +32 -0
  19. package/src/types/cli.types.ts +36 -0
  20. package/src/types/generation.types.ts +50 -0
  21. package/src/types/index.ts +8 -0
  22. package/src/types/openapi.types.ts +126 -0
  23. package/src/types/swagger.types.ts +9 -0
  24. package/src/utils/config.ts +118 -0
  25. package/src/utils/environment-finder.ts +53 -0
  26. package/src/utils/filesystem.ts +31 -0
  27. package/src/utils/logger.ts +60 -0
  28. package/src/utils/mock-value-resolver.ts +70 -0
  29. package/src/utils/name-formatter.ts +12 -0
  30. package/src/utils/openapi-generator.ts +24 -0
  31. package/src/utils/prompt.ts +183 -0
  32. package/src/utils/type-mapper.ts +14 -0
  33. package/templates/api.repository.contract.mustache +34 -0
  34. package/templates/api.repository.impl.mock.mustache +21 -0
  35. package/templates/api.repository.impl.mustache +58 -0
  36. package/templates/api.repository.impl.spec.mustache +97 -0
  37. package/templates/api.use-cases.contract.mustache +34 -0
  38. package/templates/api.use-cases.impl.mustache +32 -0
  39. package/templates/api.use-cases.impl.spec.mustache +94 -0
  40. package/templates/api.use-cases.mock.mustache +21 -0
  41. package/templates/dto.mock.mustache +16 -0
  42. package/templates/mapper.mustache +28 -0
  43. package/templates/mapper.spec.mustache +39 -0
  44. package/templates/model-entity.mustache +24 -0
  45. package/templates/model-entity.spec.mustache +34 -0
  46. package/templates/model.mock.mustache +14 -0
  47. package/templates/model.mustache +20 -0
  48. package/templates/repository.provider.mock.mustache +20 -0
  49. package/templates/repository.provider.mustache +26 -0
  50. package/templates/use-cases.provider.mock.mustache +20 -0
  51. package/templates/use-cases.provider.mustache +26 -0
  52. package/tsconfig.json +17 -0
@@ -0,0 +1,126 @@
1
+ import { execSync } from 'child_process';
2
+ import fs from 'fs-extra';
3
+ import path from 'path';
4
+ import { logStep, logSuccess, logError, logDetail } from '../utils/logger';
5
+
6
+ /** Invokes `openapi-generator-cli` to generate DTOs into a temporary directory. */
7
+ export function generateCode(swaggerFile: string, templatesDir: string): string {
8
+ logStep('Generating code from OpenAPI spec...');
9
+
10
+ const tempDir = path.join(process.cwd(), '.temp-generated');
11
+
12
+ if (fs.existsSync(tempDir)) {
13
+ fs.removeSync(tempDir);
14
+ }
15
+
16
+ try {
17
+ const command = `openapi-generator-cli generate \
18
+ -i "${swaggerFile}" \
19
+ -g typescript-angular \
20
+ --global-property models \
21
+ -t "${templatesDir}" \
22
+ -o "${tempDir}" \
23
+ --additional-properties=ngVersion=17.0.0,modelFileSuffix=.dto,modelNameSuffix=Dto`;
24
+
25
+ execSync(command, { stdio: 'pipe' });
26
+ logSuccess('Code generated successfully');
27
+
28
+ return tempDir;
29
+ } catch (_error) {
30
+ logError('Error generating code');
31
+ if (fs.existsSync(tempDir)) {
32
+ fs.removeSync(tempDir);
33
+ }
34
+ process.exit(1);
35
+ }
36
+ }
37
+
38
+ /** Copies the generated DTOs from the temporary directory to the output directory. */
39
+ export function organizeFiles(tempDir: string, outputDir: string): void {
40
+ logStep('Organising generated DTO files...');
41
+
42
+ const sourceDir = path.join(tempDir, 'model');
43
+ const destDir = path.join(outputDir, 'data/dtos');
44
+ let filesMoved = 0;
45
+
46
+ if (fs.existsSync(sourceDir)) {
47
+ fs.ensureDirSync(destDir);
48
+
49
+ const files = fs.readdirSync(sourceDir).filter((file) => file.endsWith('.dto.ts'));
50
+
51
+ files.forEach((file) => {
52
+ const sourcePath = path.join(sourceDir, file);
53
+ const destPath = path.join(destDir, file);
54
+ fs.copySync(sourcePath, destPath);
55
+ filesMoved++;
56
+ logDetail('dto', `${file} → ${path.relative(process.cwd(), destPath)}`);
57
+ });
58
+ }
59
+
60
+ logSuccess(`${filesMoved} DTOs moved successfully`);
61
+ }
62
+
63
+ /** Post-processes the generated DTOs: adds cross-DTO imports and normalises Array<T> → T[]. */
64
+ export function addDtoImports(outputDir: string): void {
65
+ logStep('Post-processing generated DTOs...');
66
+
67
+ const dtosDir = path.join(outputDir, 'data/dtos');
68
+
69
+ if (!fs.existsSync(dtosDir)) return;
70
+
71
+ const files = fs.readdirSync(dtosDir).filter((f) => f.endsWith('.dto.ts'));
72
+
73
+ // Build a map of DTO classname → file base name (without .ts)
74
+ const dtoMap: Record<string, string> = {};
75
+ files.forEach((file) => {
76
+ const content = fs.readFileSync(path.join(dtosDir, file), 'utf8');
77
+ const match = content.match(/export interface (\w+)/);
78
+ if (match) {
79
+ dtoMap[match[1]] = file.replace('.ts', '');
80
+ }
81
+ });
82
+
83
+ let filesProcessed = 0;
84
+
85
+ files.forEach((file) => {
86
+ const filePath = path.join(dtosDir, file);
87
+ const originalContent = fs.readFileSync(filePath, 'utf8');
88
+ let content = originalContent;
89
+
90
+ const selfMatch = content.match(/export interface (\w+)/);
91
+ const selfName = selfMatch ? selfMatch[1] : '';
92
+
93
+ // Normalize Array<T> → T[] (openapi-generator-cli always outputs Array<T>)
94
+ content = content.replace(/Array<(\w+)>/g, '$1[]');
95
+
96
+ // Find all Dto type references in the file body (excluding the interface name itself)
97
+ const references = new Set<string>();
98
+ const typeRegex = /\b(\w+Dto)\b/g;
99
+ let match;
100
+ while ((match = typeRegex.exec(content)) !== null) {
101
+ if (match[1] !== selfName) {
102
+ references.add(match[1]);
103
+ }
104
+ }
105
+
106
+ // Build import lines for each referenced type that exists in the dtoMap
107
+ const imports: string[] = [];
108
+ references.forEach((ref) => {
109
+ if (dtoMap[ref]) {
110
+ imports.push(`import { ${ref} } from './${dtoMap[ref]}';`);
111
+ }
112
+ });
113
+
114
+ if (imports.length > 0) {
115
+ content = imports.join('\n') + '\n' + content;
116
+ }
117
+
118
+ if (content !== originalContent) {
119
+ fs.writeFileSync(filePath, content);
120
+ filesProcessed++;
121
+ logDetail('dto', `Post-processed ${file} (added ${imports.length} import(s))`);
122
+ }
123
+ });
124
+
125
+ logSuccess(`${filesProcessed} DTOs post-processed`);
126
+ }
@@ -0,0 +1,124 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { spawnSync } from 'child_process';
4
+ import { logStep, logSuccess, logWarning, logDetail } from '../utils/logger';
5
+ import type { LintResult } from '../types';
6
+
7
+ /**
8
+ * Walks up the directory tree from `startDir` to find the nearest
9
+ * directory containing a `package.json` (i.e. the project root).
10
+ * Returns `null` if none is found before reaching the filesystem root.
11
+ */
12
+ function findProjectRoot(startDir: string): string | null {
13
+ let current = path.resolve(startDir);
14
+ while (true) {
15
+ if (fs.existsSync(path.join(current, 'package.json'))) return current;
16
+ const parent = path.dirname(current);
17
+ if (parent === current) return null;
18
+ current = parent;
19
+ }
20
+ }
21
+
22
+ /**
23
+ * Collects all `.ts` files recursively inside a directory.
24
+ */
25
+ function collectTsFiles(dir: string): string[] {
26
+ if (!fs.existsSync(dir)) return [];
27
+ const results: string[] = [];
28
+ fs.readdirSync(dir).forEach((entry) => {
29
+ const full = path.join(dir, entry);
30
+ if (fs.statSync(full).isDirectory()) {
31
+ results.push(...collectTsFiles(full));
32
+ } else if (entry.endsWith('.ts')) {
33
+ results.push(full);
34
+ }
35
+ });
36
+ return results;
37
+ }
38
+
39
+ /**
40
+ * Runs a command synchronously. Only prints to console on fatal failure (exit >= 2).
41
+ * Exit code 1 from ESLint means "warnings remain after --fix" — not a fatal error.
42
+ * Returns captured output for logging to file.
43
+ */
44
+ function run(cmd: string, args: string[], cwd: string): { success: boolean; output: string } {
45
+ const result = spawnSync(cmd, args, { cwd, encoding: 'utf8', shell: true });
46
+ const output = [result.stdout, result.stderr].filter(Boolean).join('\n').trim();
47
+ const fatalError = result.status === null || result.status >= 2;
48
+ if (fatalError) {
49
+ if (result.stderr) process.stderr.write(result.stderr);
50
+ if (result.stdout) process.stdout.write(result.stdout);
51
+ }
52
+ return { success: !fatalError, output };
53
+ }
54
+
55
+ /**
56
+ * Runs Prettier and ESLint (--fix) on all generated `.ts` files inside `outputDir`.
57
+ * Both tools are looked up via `npx` in the nearest project root so that the
58
+ * target Angular project's own configuration and plugins are used.
59
+ *
60
+ * - Prettier: always attempted; logs a warning if not found.
61
+ * - ESLint: optional; silently skipped if no config is found in the project root.
62
+ *
63
+ * Returns a `LintResult` with the outcome of each tool for inclusion in the report.
64
+ */
65
+ export function lintGeneratedFiles(outputDir: string): LintResult {
66
+ logStep('Linting generated files...');
67
+
68
+ const result: LintResult = {
69
+ prettier: { ran: false, filesFormatted: 0 },
70
+ eslint: { ran: false, filesFixed: 0 }
71
+ };
72
+
73
+ const projectRoot = findProjectRoot(outputDir);
74
+ if (!projectRoot) {
75
+ logWarning('Could not locate a project root (package.json). Skipping lint.');
76
+ return result;
77
+ }
78
+
79
+ const files = collectTsFiles(outputDir);
80
+ if (files.length === 0) {
81
+ logWarning('No TypeScript files found in output directory. Skipping lint.');
82
+ return result;
83
+ }
84
+
85
+ logDetail('lint', `Project root: ${projectRoot}`);
86
+ logDetail('lint', `Files to process: ${files.length}`);
87
+
88
+ const relativePaths = files.map((f) => path.relative(projectRoot, f));
89
+
90
+ // --- Prettier ---
91
+ const prettier = run('npx', ['prettier', '--write', ...relativePaths], projectRoot);
92
+ if (prettier.output) logDetail('prettier', prettier.output);
93
+ if (prettier.success) {
94
+ result.prettier = { ran: true, filesFormatted: files.length };
95
+ logSuccess(`Prettier formatted ${files.length} files`);
96
+ } else {
97
+ logWarning('Prettier not available or encountered errors. Skipping formatting.');
98
+ }
99
+
100
+ // --- ESLint (only if a config exists in the project root) ---
101
+ const hasEslintConfig =
102
+ fs.existsSync(path.join(projectRoot, 'eslint.config.js')) ||
103
+ fs.existsSync(path.join(projectRoot, 'eslint.config.mjs')) ||
104
+ fs.existsSync(path.join(projectRoot, '.eslintrc.js')) ||
105
+ fs.existsSync(path.join(projectRoot, '.eslintrc.json')) ||
106
+ fs.existsSync(path.join(projectRoot, '.eslintrc.yml')) ||
107
+ fs.existsSync(path.join(projectRoot, '.eslintrc.yaml'));
108
+
109
+ if (!hasEslintConfig) {
110
+ logWarning('No ESLint config found in project root. Skipping ESLint fix.');
111
+ return result;
112
+ }
113
+
114
+ const eslint = run('npx', ['eslint', '--fix', ...relativePaths], projectRoot);
115
+ if (eslint.output) logDetail('eslint', eslint.output);
116
+ if (eslint.success) {
117
+ result.eslint = { ran: true, filesFixed: files.length };
118
+ logSuccess(`ESLint fixed ${files.length} files`);
119
+ } else {
120
+ logWarning('ESLint reported errors that could not be auto-fixed. Review the output above.');
121
+ }
122
+
123
+ return result;
124
+ }
@@ -0,0 +1,80 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { logStep, logSuccess } from '../utils/logger';
4
+ import type { SwaggerAnalysis, GenerationReport, LintResult } from '../types';
5
+
6
+ /** Counts files ending with `.mock.ts` in a directory (returns 0 if directory does not exist). */
7
+ function countMockFiles(dir: string): number {
8
+ try {
9
+ return fs.readdirSync(dir).filter((f) => f.endsWith('.mock.ts')).length;
10
+ } catch {
11
+ return 0;
12
+ }
13
+ }
14
+
15
+ /** Counts files ending with `.spec.ts` in a directory (returns 0 if directory does not exist). */
16
+ function countSpecFiles(dir: string): number {
17
+ try {
18
+ return fs.readdirSync(dir).filter((f) => f.endsWith('.spec.ts')).length;
19
+ } catch {
20
+ return 0;
21
+ }
22
+ }
23
+
24
+ /** Generates and persists the `generation-report.json` file with process statistics. */
25
+ export function generateReport(
26
+ outputDir: string,
27
+ analysis: SwaggerAnalysis,
28
+ lintResult: LintResult
29
+ ): GenerationReport {
30
+ logStep('Generating report...');
31
+
32
+ const tags = Array.isArray(analysis.tags) ? analysis.tags : [];
33
+ const tagDetails = tags.map((tag: unknown) => {
34
+ const t = tag as { name: string; description?: string };
35
+ const endpointCount = Object.values(analysis.paths).filter((pathObj) =>
36
+ Object.values(pathObj as Record<string, unknown>).some((op) => {
37
+ const operation = op as { tags?: string[] };
38
+ return operation.tags?.includes(t.name);
39
+ })
40
+ ).length;
41
+ return { name: t.name, description: t.description || '', endpoints: endpointCount };
42
+ });
43
+
44
+ const report: GenerationReport = {
45
+ timestamp: new Date().toISOString(),
46
+ tags: analysis.tags.length,
47
+ endpoints: Object.keys(analysis.paths).length,
48
+ tagDetails,
49
+ outputDirectory: outputDir,
50
+ linting: lintResult,
51
+ structure: {
52
+ dtos: fs.readdirSync(path.join(outputDir, 'data/dtos')).length,
53
+ repositories: fs.readdirSync(path.join(outputDir, 'data/repositories')).length,
54
+ mappers: fs.readdirSync(path.join(outputDir, 'data/mappers')).length,
55
+ useCases: fs.readdirSync(path.join(outputDir, 'domain/use-cases')).length,
56
+ providers:
57
+ fs.readdirSync(path.join(outputDir, 'di/repositories')).length +
58
+ fs.readdirSync(path.join(outputDir, 'di/use-cases')).length,
59
+ mocks:
60
+ countMockFiles(path.join(outputDir, 'data/dtos')) +
61
+ countMockFiles(path.join(outputDir, 'data/repositories')) +
62
+ countMockFiles(path.join(outputDir, 'di/repositories')) +
63
+ countMockFiles(path.join(outputDir, 'di/use-cases')) +
64
+ countMockFiles(path.join(outputDir, 'domain/use-cases')) +
65
+ countMockFiles(path.join(outputDir, 'entities/models')),
66
+ specs:
67
+ countSpecFiles(path.join(outputDir, 'entities/models')) +
68
+ countSpecFiles(path.join(outputDir, 'data/mappers')) +
69
+ countSpecFiles(path.join(outputDir, 'data/repositories')) +
70
+ countSpecFiles(path.join(outputDir, 'domain/use-cases'))
71
+ }
72
+ };
73
+
74
+ const reportPath = path.join(process.cwd(), 'generation-report.json');
75
+ fs.writeJsonSync(reportPath, report, { spaces: 2 });
76
+
77
+ logSuccess(`Report saved to: ${reportPath}`);
78
+
79
+ return report;
80
+ }
@@ -0,0 +1,32 @@
1
+ import fs from 'fs-extra';
2
+ import yaml from 'js-yaml';
3
+ import { logStep, logSuccess, logError, logDetail } from '../utils/logger';
4
+ import type { SwaggerAnalysis } from '../types';
5
+
6
+ /** Parses an OpenAPI/Swagger file and extracts tags, paths and the full document. */
7
+ export function analyzeSwagger(swaggerFile: string): SwaggerAnalysis {
8
+ logStep('Analysing OpenAPI file...');
9
+
10
+ try {
11
+ const fileContent = fs.readFileSync(swaggerFile, 'utf8');
12
+ const swagger = yaml.load(fileContent) as Record<string, unknown>;
13
+
14
+ const tags = Array.isArray(swagger.tags) ? swagger.tags : [];
15
+ const paths = (swagger.paths as Record<string, unknown>) || {};
16
+
17
+ logDetail('analyze', `Input: ${swaggerFile}`);
18
+ logDetail('analyze', `Found ${tags.length} tags, ${Object.keys(paths).length} endpoints`);
19
+ tags.forEach((tag: unknown) => {
20
+ const t = tag as { name: string; description?: string };
21
+ logDetail('analyze', ` - ${t.name}: ${t.description || 'No description'}`);
22
+ });
23
+
24
+ logSuccess(`${tags.length} tags, ${Object.keys(paths).length} endpoints found`);
25
+
26
+ return { tags, paths, swagger };
27
+ } catch (error: unknown) {
28
+ const err = error as Error;
29
+ logError(`Error reading the Swagger file: ${err.message}`);
30
+ process.exit(1);
31
+ }
32
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Options received from the command line (Commander).
3
+ * Decoupled from the CLI framework to allow use from a backend or other entry points.
4
+ */
5
+ export interface CliOptions {
6
+ input: string;
7
+ output: string;
8
+ templates: string;
9
+ skipInstall?: boolean;
10
+ dryRun?: boolean;
11
+ selectEndpoints?: boolean;
12
+ skipLint?: boolean;
13
+ config?: string;
14
+ initConfig?: string | boolean;
15
+ }
16
+
17
+ /**
18
+ * Per-tag configuration inside the generation config file.
19
+ */
20
+ export interface TagConfig {
21
+ baseUrl: string;
22
+ endpoints: string[];
23
+ }
24
+
25
+ /**
26
+ * JSON configuration file schema.
27
+ * Allows full non-interactive control of the generation process.
28
+ */
29
+ export interface GenerationConfig {
30
+ input: string;
31
+ output: string;
32
+ templates?: string;
33
+ skipInstall?: boolean;
34
+ skipLint?: boolean;
35
+ tags: Record<string, TagConfig>;
36
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Cumulative counters of artifacts generated during the process.
3
+ */
4
+ export interface GeneratedCount {
5
+ models: number;
6
+ repositories: number;
7
+ mappers: number;
8
+ useCases: number;
9
+ providers: number;
10
+ mocks: number;
11
+ specs: number;
12
+ }
13
+
14
+ /**
15
+ * Result returned by the lint/format step.
16
+ */
17
+ export interface LintResult {
18
+ prettier: { ran: boolean; filesFormatted: number };
19
+ eslint: { ran: boolean; filesFixed: number };
20
+ }
21
+
22
+ /**
23
+ * Per-tag summary included in the generation report.
24
+ */
25
+ export interface TagDetail {
26
+ name: string;
27
+ description: string;
28
+ endpoints: number;
29
+ }
30
+
31
+ /**
32
+ * Final generation report persisted as `generation-report.json`.
33
+ */
34
+ export interface GenerationReport {
35
+ timestamp: string;
36
+ tags: number;
37
+ endpoints: number;
38
+ tagDetails: TagDetail[];
39
+ outputDirectory: string;
40
+ linting: LintResult;
41
+ structure: {
42
+ dtos: number;
43
+ repositories: number;
44
+ mappers: number;
45
+ useCases: number;
46
+ providers: number;
47
+ mocks: number;
48
+ specs: number;
49
+ };
50
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @module types
3
+ * @description Barrel that re-exports all shared types and interfaces for the project.
4
+ */
5
+ export * from './cli.types';
6
+ export * from './swagger.types';
7
+ export * from './openapi.types';
8
+ export * from './generation.types';
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Summary of a single endpoint for display on the interactive selection screen.
3
+ */
4
+ export interface OperationSummary {
5
+ nickname: string;
6
+ method: string;
7
+ path: string;
8
+ summary: string;
9
+ }
10
+
11
+ /**
12
+ * Tag with its summarised endpoints, used on the interactive selection screen.
13
+ */
14
+ export interface TagSummary {
15
+ tag: string;
16
+ operations: OperationSummary[];
17
+ }
18
+
19
+ /**
20
+ * Selection filter map: tag → array of selected operation nicknames.
21
+ */
22
+ export type SelectionFilter = Record<string, string[]>;
23
+
24
+ /**
25
+ * Simplified representation of an OpenAPI component schema.
26
+ * Used to generate domain models (entities) and mappers.
27
+ */
28
+ export interface OpenApiSchema {
29
+ properties?: Record<
30
+ string,
31
+ {
32
+ type?: string;
33
+ format?: string;
34
+ description?: string;
35
+ example?: unknown;
36
+ enum?: unknown[];
37
+ $ref?: string;
38
+ items?: { $ref?: string; type?: string };
39
+ }
40
+ >;
41
+ required?: string[];
42
+ description?: string;
43
+ }
44
+
45
+ /**
46
+ * Representation of an OpenAPI operation (GET, POST, etc.) within a path.
47
+ * Contains the information needed to generate repositories and use cases.
48
+ */
49
+ export interface OpenApiOperation {
50
+ tags?: string[];
51
+ operationId?: string;
52
+ summary?: string;
53
+ description?: string;
54
+ parameters?: Array<{
55
+ name: string;
56
+ in: string;
57
+ required: boolean;
58
+ description?: string;
59
+ schema?: { type?: string };
60
+ }>;
61
+ requestBody?: {
62
+ description?: string;
63
+ content?: Record<
64
+ string,
65
+ {
66
+ schema?: {
67
+ $ref?: string;
68
+ type?: string;
69
+ };
70
+ }
71
+ >;
72
+ };
73
+ responses?: Record<
74
+ string,
75
+ {
76
+ content?: Record<
77
+ string,
78
+ {
79
+ schema?: {
80
+ $ref?: string;
81
+ type?: string;
82
+ items?: { $ref?: string };
83
+ };
84
+ }
85
+ >;
86
+ }
87
+ >;
88
+ }
89
+
90
+ /**
91
+ * A single parameter of a normalised API operation, ready for Mustache template consumption.
92
+ */
93
+ export interface TagOperationParam {
94
+ paramName: string;
95
+ dataType: string;
96
+ description: string;
97
+ required: boolean;
98
+ '-last': boolean;
99
+ testValue?: string;
100
+ }
101
+
102
+ /**
103
+ * Normalised operation ready to be consumed by Mustache templates.
104
+ * Each instance represents an endpoint grouped under an API tag.
105
+ */
106
+ export interface TagOperation {
107
+ nickname: string;
108
+ summary: string;
109
+ notes: string;
110
+ httpMethod: string;
111
+ uppercaseHttpMethod: string;
112
+ path: string;
113
+ allParams: TagOperationParam[];
114
+ hasQueryParams: boolean;
115
+ queryParams: unknown[];
116
+ hasBodyParam: boolean;
117
+ bodyParam: string;
118
+ hasOptions: boolean;
119
+ hasBothParamsAndBody: boolean;
120
+ returnType: string | boolean;
121
+ returnBaseType: string | boolean;
122
+ returnTypeVarName: string | boolean;
123
+ returnBaseTypeVarName: string | boolean;
124
+ isListContainer: boolean;
125
+ vendorExtensions: Record<string, unknown>;
126
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Result of parsing an OpenAPI/Swagger file.
3
+ * Contains the raw structures extracted from the spec for further processing.
4
+ */
5
+ export interface SwaggerAnalysis {
6
+ tags: unknown[];
7
+ paths: Record<string, unknown>;
8
+ swagger: unknown;
9
+ }