@c7-digital/ledger 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/BUILD.md +125 -0
  2. package/LICENSE +17 -0
  3. package/README.md +97 -0
  4. package/lib/scripts/build.d.ts +9 -0
  5. package/lib/scripts/build.js +366 -0
  6. package/lib/scripts/enhance-types.d.ts +3 -0
  7. package/lib/scripts/enhance-types.js +174 -0
  8. package/lib/scripts/generate-asyncapi-types.d.ts +9 -0
  9. package/lib/scripts/generate-asyncapi-types.js +129 -0
  10. package/lib/scripts/generate-schema-modules.d.ts +3 -0
  11. package/lib/scripts/generate-schema-modules.js +33 -0
  12. package/lib/src/TemplateEmitterMap.d.ts +40 -0
  13. package/lib/src/TemplateEmitterMap.js +57 -0
  14. package/lib/src/client.d.ts +55 -0
  15. package/lib/src/client.js +62 -0
  16. package/lib/src/generated/api.d.ts +7147 -0
  17. package/lib/src/generated/api.js +1 -0
  18. package/lib/src/generated/async-api.d.ts +1665 -0
  19. package/lib/src/generated/async-api.js +1 -0
  20. package/lib/src/generated/asyncapi-schema.d.ts +1 -0
  21. package/lib/src/generated/asyncapi-schema.js +2233 -0
  22. package/lib/src/generated/openapi-schema.d.ts +1 -0
  23. package/lib/src/generated/openapi-schema.js +7321 -0
  24. package/lib/src/generated/sdk-version.d.ts +1 -0
  25. package/lib/src/generated/sdk-version.js +3 -0
  26. package/lib/src/index.d.ts +8 -0
  27. package/lib/src/index.js +8 -0
  28. package/lib/src/ledger.d.ts +188 -0
  29. package/lib/src/ledger.js +849 -0
  30. package/lib/src/ledger.test.d.ts +1 -0
  31. package/lib/src/ledger.test.js +23 -0
  32. package/lib/src/logger.d.ts +41 -0
  33. package/lib/src/logger.js +56 -0
  34. package/lib/src/multistream.d.ts +47 -0
  35. package/lib/src/multistream.js +123 -0
  36. package/lib/src/translate.d.ts +5 -0
  37. package/lib/src/translate.js +30 -0
  38. package/lib/src/types.d.ts +201 -0
  39. package/lib/src/types.js +1 -0
  40. package/lib/src/util.d.ts +3 -0
  41. package/lib/src/util.js +7 -0
  42. package/lib/src/validation.d.ts +27 -0
  43. package/lib/src/validation.js +182 -0
  44. package/lib/src/valueTypes.d.ts +34 -0
  45. package/lib/src/valueTypes.js +76 -0
  46. package/lib/src/websocket.d.ts +69 -0
  47. package/lib/src/websocket.js +125 -0
  48. package/lib/tsconfig.tsbuildinfo +1 -0
  49. package/lib-lite/scripts/build.d.ts +9 -0
  50. package/lib-lite/scripts/build.js +366 -0
  51. package/lib-lite/scripts/enhance-types.d.ts +3 -0
  52. package/lib-lite/scripts/enhance-types.js +174 -0
  53. package/lib-lite/scripts/generate-asyncapi-types.d.ts +9 -0
  54. package/lib-lite/scripts/generate-asyncapi-types.js +129 -0
  55. package/lib-lite/scripts/generate-schema-modules.d.ts +3 -0
  56. package/lib-lite/scripts/generate-schema-modules.js +33 -0
  57. package/lib-lite/src/TemplateEmitterMap.d.ts +40 -0
  58. package/lib-lite/src/TemplateEmitterMap.js +57 -0
  59. package/lib-lite/src/client.d.ts +55 -0
  60. package/lib-lite/src/client.js +62 -0
  61. package/lib-lite/src/generated/api.d.ts +7147 -0
  62. package/lib-lite/src/generated/api.js +1 -0
  63. package/lib-lite/src/generated/async-api.d.ts +1665 -0
  64. package/lib-lite/src/generated/async-api.js +1 -0
  65. package/lib-lite/src/generated/asyncapi-schema.d.ts +1 -0
  66. package/lib-lite/src/generated/asyncapi-schema.js +2 -0
  67. package/lib-lite/src/generated/openapi-schema.d.ts +1 -0
  68. package/lib-lite/src/generated/openapi-schema.js +2 -0
  69. package/lib-lite/src/generated/sdk-version.d.ts +1 -0
  70. package/lib-lite/src/generated/sdk-version.js +3 -0
  71. package/lib-lite/src/index.d.ts +8 -0
  72. package/lib-lite/src/index.js +8 -0
  73. package/lib-lite/src/ledger.d.ts +188 -0
  74. package/lib-lite/src/ledger.js +849 -0
  75. package/lib-lite/src/ledger.test.d.ts +1 -0
  76. package/lib-lite/src/ledger.test.js +23 -0
  77. package/lib-lite/src/logger.d.ts +41 -0
  78. package/lib-lite/src/logger.js +56 -0
  79. package/lib-lite/src/multistream.d.ts +47 -0
  80. package/lib-lite/src/multistream.js +123 -0
  81. package/lib-lite/src/translate.d.ts +5 -0
  82. package/lib-lite/src/translate.js +30 -0
  83. package/lib-lite/src/types.d.ts +201 -0
  84. package/lib-lite/src/types.js +1 -0
  85. package/lib-lite/src/util.d.ts +3 -0
  86. package/lib-lite/src/util.js +7 -0
  87. package/lib-lite/src/validation.d.ts +14 -0
  88. package/lib-lite/src/validation.js +31 -0
  89. package/lib-lite/src/valueTypes.d.ts +34 -0
  90. package/lib-lite/src/valueTypes.js +76 -0
  91. package/lib-lite/src/websocket.d.ts +69 -0
  92. package/lib-lite/src/websocket.js +125 -0
  93. package/lib-lite/tsconfig.temp.tsbuildinfo +1 -0
  94. package/package.json +72 -0
  95. package/scripts/build.ts +456 -0
  96. package/scripts/enhance-types.ts +223 -0
  97. package/scripts/generate-asyncapi-types.ts +158 -0
  98. package/scripts/generate-schema-modules.ts +52 -0
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+ // Script to automatically brand OpenAPI generated types with value.proto constraints
3
+ // Ideally the spec would provide this, but this is sufficient for now.
4
+
5
+ import { readFileSync, writeFileSync, unlinkSync } from "fs";
6
+ import { join, dirname } from "path";
7
+
8
+ interface ValueProtoPattern {
9
+ // The JSDoc comment pattern to match
10
+ commentPattern: string;
11
+ // The target type to replace with (for string fields)
12
+ targetType: string;
13
+ }
14
+
15
+ // Patterns to find fields with value.proto references based on JSDoc comments
16
+ // Each entry automatically handles both string and string[] cases
17
+ const VALUE_PROTO_PATTERNS: ValueProtoPattern[] = [
18
+ // LedgerString patterns
19
+ {
20
+ commentPattern: "Must be a valid LedgerString",
21
+ targetType: "LedgerString",
22
+ },
23
+
24
+ // PartyIdString patterns
25
+ {
26
+ commentPattern: "Must be a valid PartyIdString",
27
+ targetType: "PartyIdString",
28
+ },
29
+
30
+ // UserIdString patterns
31
+ {
32
+ commentPattern: "Must be a valid UserIdString",
33
+ targetType: "UserIdString",
34
+ },
35
+
36
+ // NameString patterns
37
+ {
38
+ commentPattern: "Must be a valid NameString",
39
+ targetType: "NameString",
40
+ },
41
+
42
+ // PackageIdString patterns
43
+ {
44
+ commentPattern: "Must be a valid PackageIdString",
45
+ targetType: "PackageIdString",
46
+ },
47
+ {
48
+ commentPattern: "The identifier uses the package-id reference format",
49
+ targetType: "PackageIdString",
50
+ },
51
+ ];
52
+
53
+ function brandApiTypes(inputPath: string, outputPath: string, label: string): number {
54
+ console.log(`๐Ÿ”„ Branding ${label} types with value.proto constraints...`);
55
+ const content = readFileSync(inputPath, "utf-8");
56
+ let brandedContent = content;
57
+
58
+ // Add imports at the top if not already present
59
+ if (!content.includes('from "../valueTypes.js"')) {
60
+ const importStatement = `import { LedgerString, PartyIdString, UserIdString, NameString, PackageIdString } from "../valueTypes.js";\n\n`;
61
+ brandedContent = importStatement + brandedContent;
62
+ }
63
+
64
+ let replacementCount = 0;
65
+
66
+ // Track usage of each comment pattern
67
+ const patternUsage = new Map<string, { count: number; examples: string[] }>();
68
+
69
+ // This regex captures JSDoc comments followed by field declarations
70
+ // We're looking for: /** JSDoc comment */ fieldName?: fieldType;
71
+ //
72
+ // Regex breakdown:
73
+ // /\/\*\* - Match opening /** (literal forward slash, asterisk, asterisk)
74
+ // ([^*]|[\r\n]|(\*+([^*/]|[\r\n])))* - Match JSDoc content (non-greedy):
75
+ // [^*] - Any character except asterisk
76
+ // |[\r\n] - OR newline characters (carriage return or line feed)
77
+ // |(\*+([^*/]|[\r\n])) - OR one or more asterisks followed by non-closing chars
78
+ // \*+\/ - Match closing */ (one or more asterisks + forward slash)
79
+ // \s* - Match optional whitespace after JSDoc
80
+ // (\w+) - Capture group 4: field name (word characters)
81
+ // (\?)? - Capture group 5: optional question mark for optional fields
82
+ // \s*:\s* - Match colon with optional whitespace around it
83
+ // ([^;,\}\n]+) - Capture group 6: field type (everything except semicolon, comma, closing brace, newline)
84
+ //
85
+ // The regex handles multi-line JSDoc with @description tags and indented fields within object types
86
+ const fieldRegex =
87
+ /\/\*\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/\s*(\w+)(\?)?\s*:\s*([^;,\}\n]+)/g;
88
+
89
+ // Use a more compatible approach for regex matching
90
+ const matches: RegExpExecArray[] = [];
91
+ let match: RegExpExecArray | null;
92
+ while ((match = fieldRegex.exec(content)) !== null) {
93
+ matches.push(match);
94
+ }
95
+
96
+
97
+ // Process each match
98
+ for (const match of matches) {
99
+ if (match.length < 6) continue;
100
+
101
+ const fullMatch = match[0];
102
+ const jsDocComment = match[0].substring(3, match[0].indexOf("*/")); // Extract JSDoc content
103
+ const fieldName = match[4]; // Field name
104
+ const isOptional = match[5] === "?"; // Optional marker
105
+ const fieldType = match[6]; // Field type (could be anything)
106
+
107
+
108
+ // Skip if we don't have the necessary data
109
+ if (!fullMatch || !fieldName || !fieldType) continue;
110
+
111
+ // Check if this is a string-related type that we care about
112
+ const trimmedFieldType = fieldType.trim();
113
+ if (trimmedFieldType === "string" || trimmedFieldType === "string[]") {
114
+ // Check if the JSDoc comment matches any of our patterns
115
+ for (const { commentPattern, targetType } of VALUE_PROTO_PATTERNS) {
116
+ // Check if JSDoc contains the pattern
117
+ if (jsDocComment.includes(commentPattern)) {
118
+ // Extra validation: ensure this is actually a value.proto constraint comment
119
+ if (
120
+ commentPattern.includes("Must be a valid") ||
121
+ commentPattern.includes("package-id reference format")
122
+ ) {
123
+ // Determine the correct target type based on whether it's an array
124
+ const finalTargetType =
125
+ trimmedFieldType === "string[]" ? `${targetType}[]` : targetType;
126
+
127
+ // Create the branded declaration
128
+ const brandedDeclaration = fullMatch.replace(trimmedFieldType, finalTargetType);
129
+
130
+ // Replace in the content
131
+ brandedContent = brandedContent.replace(fullMatch, brandedDeclaration);
132
+ replacementCount++;
133
+
134
+ // Track pattern usage
135
+ const fieldExample = `${fieldName}${isOptional ? "?" : ""}: ${trimmedFieldType} โ†’ ${finalTargetType}`;
136
+ if (!patternUsage.has(commentPattern)) {
137
+ patternUsage.set(commentPattern, { count: 0, examples: [] });
138
+ }
139
+ const usage = patternUsage.get(commentPattern)!;
140
+ usage.count++;
141
+ if (usage.examples.length < 3) {
142
+ // Keep up to 3 examples per pattern
143
+ usage.examples.push(fieldExample);
144
+ }
145
+
146
+ // Log the branding with field name
147
+ const optionalMarker = isOptional ? "?" : "";
148
+ console.log(
149
+ `โœ… Branded ${fieldName}${optionalMarker}: ${trimmedFieldType} โ†’ ${finalTargetType}`
150
+ );
151
+ // console.log(`JSDoc: ${jsDocComment}`);
152
+ // console.log(`Pattern: ${commentPattern}`);
153
+ // console.log(`---------------------------------`);
154
+ break; // Stop checking patterns once we've found a match
155
+ }
156
+ }
157
+ }
158
+ }
159
+ }
160
+
161
+ // Write branded content directly to the output file
162
+ console.log(`๐Ÿ“ Writing branded types to ${outputPath}...`);
163
+ writeFileSync(outputPath, brandedContent);
164
+
165
+ console.log(`๐ŸŽ‰ Branded ${replacementCount} field declarations with value.proto constraints`);
166
+
167
+ // Report pattern usage summary
168
+ if (patternUsage.size > 0) {
169
+ console.log(`\n๐Ÿ“Š Pattern Usage Summary:`);
170
+ console.log(`โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`);
171
+
172
+ // Sort patterns by usage count (descending)
173
+ const sortedPatterns = Array.from(patternUsage.entries()).sort(
174
+ ([, a], [, b]) => b.count - a.count
175
+ );
176
+
177
+ for (const [pattern, { count, examples }] of sortedPatterns) {
178
+ console.log(`\n๐Ÿ”– "${pattern}"`);
179
+ console.log(` Used ${count} time${count === 1 ? "" : "s"}`);
180
+ console.log(` Examples:`);
181
+ for (const example of examples) {
182
+ console.log(` โ€ข ${example}`);
183
+ }
184
+ if (count > examples.length) {
185
+ console.log(` ... and ${count - examples.length} more`);
186
+ }
187
+ }
188
+ console.log(`\nโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•`);
189
+ }
190
+
191
+ return replacementCount;
192
+ }
193
+
194
+ function brandTypes(inputPath: string, outputPath: string, label: string = "API"): void {
195
+ brandApiTypes(inputPath, outputPath, label);
196
+ }
197
+
198
+ // Export the function for use in other scripts
199
+ export { brandTypes };
200
+
201
+ // Check if this script is being run directly
202
+ // For ES modules, we check if the import.meta.url matches the process.argv[1]
203
+ const isMainModule =
204
+ process.argv[1] &&
205
+ (process.argv[1].endsWith("brand-types.ts") || process.argv[1].endsWith("enhance-types.ts"));
206
+ if (isMainModule) {
207
+ const args = process.argv.slice(2);
208
+
209
+ if (args.length < 2) {
210
+ console.error("Usage: brand-types.ts <input-file> <output-file> [label]");
211
+ process.exit(1);
212
+ }
213
+
214
+ if (!args[0] || !args[1]) {
215
+ console.error("Input and output files must be specified.");
216
+ process.exit(1);
217
+ }
218
+ const inputPath = args[0];
219
+ const outputPath = args[1];
220
+ const label = args[2] || "API";
221
+
222
+ brandTypes(inputPath, outputPath, label);
223
+ }
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Generate TypeScript types from AsyncAPI specification by converting to OpenAPI format
5
+ *
6
+ * This script converts the AsyncAPI YAML to OpenAPI format and uses the existing
7
+ * openapi-typescript generator to create types. Much simpler than custom schema parsing.
8
+ */
9
+
10
+ import * as fs from "fs";
11
+ import * as path from "path";
12
+ import * as yaml from "yaml";
13
+ import { exec } from "child_process";
14
+ import { promisify } from "util";
15
+
16
+ const execAsync = promisify(exec);
17
+ const __dirname = process.cwd();
18
+
19
+ async function generateAsyncApiTypes(specPath?: string): Promise<void> {
20
+ try {
21
+ // Get spec path from parameter or command line argument
22
+ const asyncApiSpecPath = specPath || process.argv[2];
23
+ if (!asyncApiSpecPath) {
24
+ console.error("Usage: node generate-asyncapi-types.ts <path-to-asyncapi-spec>");
25
+ process.exit(1);
26
+ }
27
+
28
+ // Read the AsyncAPI specification
29
+ const asyncApiPath = path.resolve(asyncApiSpecPath);
30
+ const asyncApiContent = fs.readFileSync(asyncApiPath, "utf8");
31
+ const asyncApiSpec = yaml.parse(asyncApiContent);
32
+
33
+ // Convert AsyncAPI to OpenAPI format by changing the header
34
+ const openApiSpec = {
35
+ ...asyncApiSpec,
36
+ openapi: "3.0.3",
37
+ info: asyncApiSpec.info,
38
+ components: asyncApiSpec.components,
39
+ // Remove AsyncAPI-specific fields
40
+ asyncapi: undefined,
41
+ channels: undefined,
42
+ operations: undefined,
43
+ // Add empty paths since OpenAPI requires it
44
+ paths: {},
45
+ };
46
+
47
+ // Clean up undefined properties
48
+ delete openApiSpec.asyncapi;
49
+ delete openApiSpec.channels;
50
+ delete openApiSpec.operations;
51
+
52
+ // Create temporary OpenAPI file
53
+ const tempOpenApiPath = path.join(__dirname, "temp-asyncapi-as-openapi.yaml");
54
+ fs.writeFileSync(tempOpenApiPath, yaml.stringify(openApiSpec));
55
+
56
+ console.log(`๐Ÿ“ Created temporary OpenAPI file: ${tempOpenApiPath}`);
57
+ console.log(`๐Ÿ”„ Generating types using openapi-typescript...`);
58
+
59
+ // Use the existing openapi-typescript generator
60
+ const outputPath = path.join(__dirname, "src", "generated", "async-api.ts");
61
+ const generateCommand = `pnpm exec openapi-typescript "${tempOpenApiPath}" --output "${outputPath}"`;
62
+
63
+ const { stdout, stderr } = await execAsync(generateCommand);
64
+
65
+ if (stderr && !stderr.includes("Warning")) {
66
+ console.warn("openapi-typescript warnings:", stderr);
67
+ }
68
+
69
+ if (stdout) {
70
+ console.log("openapi-typescript output:", stdout);
71
+ }
72
+
73
+ // Now add channels interface for WebSocket connections
74
+ console.log(`๐Ÿ”„ Adding channels interface for WebSocket connections...`);
75
+
76
+ // Parse the original AsyncAPI spec to extract channels
77
+ let channelsInterface = "\nexport interface channels {\n";
78
+
79
+ if (asyncApiSpec.channels) {
80
+ for (const [channelPath, channelData] of Object.entries(asyncApiSpec.channels)) {
81
+ const channel = channelData as any;
82
+ channelsInterface += ` "${channelPath}": {\n`;
83
+
84
+ // Add description if available
85
+ if (channel.description) {
86
+ channelsInterface += ` /** @description ${channel.description} */\n`;
87
+ }
88
+
89
+ // Add operations (publish/subscribe)
90
+ if (channel.publish) {
91
+ channelsInterface += ` publish: {\n`;
92
+ if (channel.publish.description) {
93
+ channelsInterface += ` /** @description ${channel.publish.description} */\n`;
94
+ }
95
+ if (channel.publish.message) {
96
+ const messageRef = channel.publish.message.$ref || channel.publish.message;
97
+ const messageName =
98
+ typeof messageRef === "string" && messageRef.includes("#/")
99
+ ? messageRef.replace("#/components/messages/", "")
100
+ : messageRef;
101
+ channelsInterface += ` message: components["schemas"]["${messageName}"];\n`;
102
+ }
103
+ channelsInterface += ` };\n`;
104
+ }
105
+
106
+ if (channel.subscribe) {
107
+ channelsInterface += ` subscribe: {\n`;
108
+ if (channel.subscribe.description) {
109
+ channelsInterface += ` /** @description ${channel.subscribe.description} */\n`;
110
+ }
111
+ if (channel.subscribe.message) {
112
+ const messageRef = channel.subscribe.message.$ref || channel.subscribe.message;
113
+ const messageName =
114
+ typeof messageRef === "string" && messageRef.includes("#/")
115
+ ? messageRef.replace("#/components/messages/", "")
116
+ : messageRef;
117
+ channelsInterface += ` message: components["schemas"]["${messageName}"];\n`;
118
+ }
119
+ channelsInterface += ` };\n`;
120
+ }
121
+
122
+ channelsInterface += ` };\n`;
123
+ }
124
+ }
125
+
126
+ channelsInterface += "}\n";
127
+
128
+ // Append channels interface to the generated file
129
+ const generatedContent = fs.readFileSync(outputPath, "utf8");
130
+ const brandedContent = generatedContent + channelsInterface;
131
+ fs.writeFileSync(outputPath, brandedContent);
132
+
133
+ // Clean up temporary file
134
+ fs.unlinkSync(tempOpenApiPath);
135
+ console.log(`๐Ÿงน Cleaned up temporary file`);
136
+
137
+ console.log(`โœ… Generated AsyncAPI types with channels interface: ${outputPath}`);
138
+ } catch (error) {
139
+ console.error("โŒ Error generating AsyncAPI types:", (error as Error).message);
140
+
141
+ // Clean up temporary file on error
142
+ const tempOpenApiPath = path.join(__dirname, "temp-asyncapi-as-openapi.yaml");
143
+ if (fs.existsSync(tempOpenApiPath)) {
144
+ fs.unlinkSync(tempOpenApiPath);
145
+ console.log(`๐Ÿงน Cleaned up temporary file after error`);
146
+ }
147
+
148
+ process.exit(1);
149
+ }
150
+ }
151
+
152
+ // Export the function for use in other scripts
153
+ export { generateAsyncApiTypes };
154
+
155
+ // Only run directly if this file is executed as main module
156
+ if (import.meta.url === `file://${process.argv[1]}`) {
157
+ generateAsyncApiTypes();
158
+ }
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env tsx
2
+
3
+ import { readFileSync, writeFileSync } from "fs";
4
+ import { join, dirname } from "path";
5
+ import { fileURLToPath } from "url";
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+
10
+ function generateSchemaModule(yamlPath: string, outputPath: string, exportName: string) {
11
+ const yamlContent = readFileSync(yamlPath, "utf-8");
12
+
13
+ // Escape the YAML content for TypeScript string literal
14
+ const escapedContent = yamlContent
15
+ .replace(/\\/g, "\\\\")
16
+ .replace(/`/g, "\\`")
17
+ .replace(/\$\{/g, "\\${");
18
+
19
+ const tsContent = `// Auto-generated file - do not edit manually
20
+ // Generated from ${yamlPath}
21
+
22
+ export const ${exportName} = \`${escapedContent}\`;
23
+ `;
24
+
25
+ writeFileSync(outputPath, tsContent, "utf-8");
26
+ console.log(`โœ… Generated ${outputPath} from ${yamlPath}`);
27
+ }
28
+
29
+ // Export the function for use in other scripts
30
+ export { generateSchemaModule };
31
+
32
+ // Only run directly if this file is executed as main module
33
+ if (import.meta.url === `file://${process.argv[1]}`) {
34
+ const projectRoot = join(__dirname, "..");
35
+ const specsDir = join(projectRoot, "specs");
36
+ const outputDir = join(projectRoot, "src", "generated");
37
+
38
+ // Generate modules for both schemas
39
+ generateSchemaModule(
40
+ join(specsDir, "openapi_2025-08-31.yaml"),
41
+ join(outputDir, "openapi-schema.ts"),
42
+ "OPENAPI_SCHEMA"
43
+ );
44
+
45
+ generateSchemaModule(
46
+ join(specsDir, "asyncapi_2025-08-31.yaml"),
47
+ join(outputDir, "asyncapi-schema.ts"),
48
+ "ASYNCAPI_SCHEMA"
49
+ );
50
+
51
+ console.log("๐ŸŽ‰ All schema modules generated successfully!");
52
+ }