schemantic 0.1.0
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/CHANGELOG.md +92 -0
- package/LICENSE +21 -0
- package/README.md +827 -0
- package/dist/__tests__/setup.d.ts +6 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +30 -0
- package/dist/__tests__/setup.js.map +1 -0
- package/dist/__tests__/test-config.d.ts +36 -0
- package/dist/__tests__/test-config.d.ts.map +1 -0
- package/dist/__tests__/test-config.js +563 -0
- package/dist/__tests__/test-config.js.map +1 -0
- package/dist/cli/index.d.ts +118 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +657 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +21 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/schemantic.d.ts +95 -0
- package/dist/core/schemantic.d.ts.map +1 -0
- package/dist/core/schemantic.js +543 -0
- package/dist/core/schemantic.js.map +1 -0
- package/dist/generators/api-client-generator.d.ts +145 -0
- package/dist/generators/api-client-generator.d.ts.map +1 -0
- package/dist/generators/api-client-generator.js +856 -0
- package/dist/generators/api-client-generator.js.map +1 -0
- package/dist/generators/base.d.ts +117 -0
- package/dist/generators/base.d.ts.map +1 -0
- package/dist/generators/base.js +232 -0
- package/dist/generators/base.js.map +1 -0
- package/dist/generators/enum-generator.d.ts +52 -0
- package/dist/generators/enum-generator.d.ts.map +1 -0
- package/dist/generators/enum-generator.js +178 -0
- package/dist/generators/enum-generator.js.map +1 -0
- package/dist/generators/factory.d.ts +59 -0
- package/dist/generators/factory.d.ts.map +1 -0
- package/dist/generators/factory.js +127 -0
- package/dist/generators/factory.js.map +1 -0
- package/dist/generators/hook-generator.d.ts +36 -0
- package/dist/generators/hook-generator.d.ts.map +1 -0
- package/dist/generators/hook-generator.js +495 -0
- package/dist/generators/hook-generator.js.map +1 -0
- package/dist/generators/index.d.ts +10 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +26 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/object-generator.d.ts +48 -0
- package/dist/generators/object-generator.d.ts.map +1 -0
- package/dist/generators/object-generator.js +280 -0
- package/dist/generators/object-generator.js.map +1 -0
- package/dist/generators/primitive-generator.d.ts +40 -0
- package/dist/generators/primitive-generator.d.ts.map +1 -0
- package/dist/generators/primitive-generator.js +150 -0
- package/dist/generators/primitive-generator.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/base.d.ts +101 -0
- package/dist/parsers/base.d.ts.map +1 -0
- package/dist/parsers/base.js +77 -0
- package/dist/parsers/base.js.map +1 -0
- package/dist/parsers/factory.d.ts +64 -0
- package/dist/parsers/factory.d.ts.map +1 -0
- package/dist/parsers/factory.js +116 -0
- package/dist/parsers/factory.js.map +1 -0
- package/dist/parsers/index.d.ts +7 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +23 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/openapi.d.ts +52 -0
- package/dist/parsers/openapi.d.ts.map +1 -0
- package/dist/parsers/openapi.js +396 -0
- package/dist/parsers/openapi.js.map +1 -0
- package/dist/plugins/branded-types.d.ts +28 -0
- package/dist/plugins/branded-types.d.ts.map +1 -0
- package/dist/plugins/branded-types.js +568 -0
- package/dist/plugins/branded-types.js.map +1 -0
- package/dist/plugins/builtin.d.ts +38 -0
- package/dist/plugins/builtin.d.ts.map +1 -0
- package/dist/plugins/builtin.js +283 -0
- package/dist/plugins/builtin.js.map +1 -0
- package/dist/plugins/index.d.ts +7 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +23 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/loader.d.ts +92 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +245 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/manager.d.ts +99 -0
- package/dist/plugins/manager.d.ts.map +1 -0
- package/dist/plugins/manager.js +233 -0
- package/dist/plugins/manager.js.map +1 -0
- package/dist/plugins/performance-monitoring.d.ts +98 -0
- package/dist/plugins/performance-monitoring.d.ts.map +1 -0
- package/dist/plugins/performance-monitoring.js +596 -0
- package/dist/plugins/performance-monitoring.js.map +1 -0
- package/dist/plugins/request-deduplication.d.ts +27 -0
- package/dist/plugins/request-deduplication.d.ts.map +1 -0
- package/dist/plugins/request-deduplication.js +650 -0
- package/dist/plugins/request-deduplication.js.map +1 -0
- package/dist/plugins/zod-validation.d.ts +63 -0
- package/dist/plugins/zod-validation.d.ts.map +1 -0
- package/dist/plugins/zod-validation.js +743 -0
- package/dist/plugins/zod-validation.js.map +1 -0
- package/dist/types/core.d.ts +203 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/core.js +24 -0
- package/dist/types/core.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +23 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/openapi.d.ts +250 -0
- package/dist/types/openapi.d.ts.map +1 -0
- package/dist/types/openapi.js +8 -0
- package/dist/types/openapi.js.map +1 -0
- package/dist/types/schema.d.ts +68 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +22 -0
- package/dist/types/schema.js.map +1 -0
- package/docs/ADVANCED_PLUGINS_IMPLEMENTATION.md +355 -0
- package/docs/ADVANCED_PLUGIN_DEVELOPMENT.md +309 -0
- package/docs/API.md +600 -0
- package/docs/CONFIGURATION.md +722 -0
- package/docs/FASTAPI_TUTORIAL.md +1497 -0
- package/docs/PLUGINS.md +683 -0
- package/docs/PLUGIN_DEVELOPMENT.md +720 -0
- package/package.json +90 -0
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* CLI interface for schemantic
|
|
5
|
+
* Provides command-line interface for generating TypeScript types and API clients
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.cli = exports.SchemanticCli = void 0;
|
|
42
|
+
const commander_1 = require("commander");
|
|
43
|
+
const core_1 = require("../types/core");
|
|
44
|
+
const schemantic_1 = require("../core/schemantic");
|
|
45
|
+
const plugins_1 = require("../plugins");
|
|
46
|
+
const builtin_1 = require("../plugins/builtin");
|
|
47
|
+
const readline = __importStar(require("readline"));
|
|
48
|
+
/**
|
|
49
|
+
* Main CLI class
|
|
50
|
+
*/
|
|
51
|
+
class SchemanticCli {
|
|
52
|
+
constructor() {
|
|
53
|
+
this.program = new commander_1.Command();
|
|
54
|
+
this.setupProgram();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Setup the CLI program
|
|
58
|
+
*/
|
|
59
|
+
setupProgram() {
|
|
60
|
+
this.program
|
|
61
|
+
.name("schemantic")
|
|
62
|
+
.description("Generate TypeScript types and API clients from OpenAPI schemas")
|
|
63
|
+
.version("1.0.0")
|
|
64
|
+
.option("-i, --interactive", "Run in interactive mode")
|
|
65
|
+
.option("-v, --verbose", "Verbose output")
|
|
66
|
+
.option("-q, --quiet", "Quiet output")
|
|
67
|
+
.option("--no-color", "Disable colored output");
|
|
68
|
+
// Add commands
|
|
69
|
+
this.addGenerateCommand();
|
|
70
|
+
this.addValidateCommand();
|
|
71
|
+
this.addPluginCommand();
|
|
72
|
+
this.addInitCommand();
|
|
73
|
+
this.addHelpCommand();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Add generate command
|
|
77
|
+
*/
|
|
78
|
+
addGenerateCommand() {
|
|
79
|
+
this.program
|
|
80
|
+
.command("generate [source]")
|
|
81
|
+
.alias("gen")
|
|
82
|
+
.description("Generate TypeScript types and API client from OpenAPI schema")
|
|
83
|
+
.option("-u, --url <url>", "OpenAPI schema URL")
|
|
84
|
+
.option("-f, --file <file>", "OpenAPI schema file path")
|
|
85
|
+
.option("-o, --output <dir>", "Output directory", "./src/generated")
|
|
86
|
+
.option("--types", "Generate types only")
|
|
87
|
+
.option("--client", "Generate API client only")
|
|
88
|
+
.option("--hooks", "Generate React hooks")
|
|
89
|
+
.option("--strict", "Use strict TypeScript types", true)
|
|
90
|
+
.option("--naming <convention>", "Naming convention (camelCase|snake_case|PascalCase)", "camelCase")
|
|
91
|
+
.option("--prefix <prefix>", "Type name prefix", "API")
|
|
92
|
+
.option("--suffix <suffix>", "Type name suffix", "")
|
|
93
|
+
.option("--exclude-paths <paths>", "Exclude paths (comma-separated)")
|
|
94
|
+
.option("--include-paths <paths>", "Include paths (comma-separated)")
|
|
95
|
+
.option("--exclude-schemas <schemas>", "Exclude schemas (comma-separated)")
|
|
96
|
+
.option("--include-schemas <schemas>", "Include schemas (comma-separated)")
|
|
97
|
+
.option("--plugins <plugins>", "Enable plugins (comma-separated)")
|
|
98
|
+
.option("-c, --config <file>", "Configuration file path")
|
|
99
|
+
.option("--watch", "Watch for changes and regenerate")
|
|
100
|
+
.action(async (source, options) => {
|
|
101
|
+
await this.handleGenerateCommand(source, options);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Add validate command
|
|
106
|
+
*/
|
|
107
|
+
addValidateCommand() {
|
|
108
|
+
this.program
|
|
109
|
+
.command("validate [source]")
|
|
110
|
+
.alias("check")
|
|
111
|
+
.description("Validate OpenAPI schema")
|
|
112
|
+
.option("-u, --url <url>", "OpenAPI schema URL")
|
|
113
|
+
.option("-f, --file <file>", "OpenAPI schema file path")
|
|
114
|
+
.option("--fix", "Attempt to fix common issues")
|
|
115
|
+
.action(async (source, options) => {
|
|
116
|
+
await this.handleValidateCommand(source, options);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Add plugin command
|
|
121
|
+
*/
|
|
122
|
+
addPluginCommand() {
|
|
123
|
+
const pluginCommand = this.program
|
|
124
|
+
.command("plugin")
|
|
125
|
+
.alias("plugins")
|
|
126
|
+
.description("Manage plugins");
|
|
127
|
+
pluginCommand
|
|
128
|
+
.command("list")
|
|
129
|
+
.alias("ls")
|
|
130
|
+
.description("List available plugins")
|
|
131
|
+
.action(async () => {
|
|
132
|
+
await this.handlePluginListCommand();
|
|
133
|
+
});
|
|
134
|
+
pluginCommand
|
|
135
|
+
.command("load <path>")
|
|
136
|
+
.description("Load plugin from file or package")
|
|
137
|
+
.action(async (path) => {
|
|
138
|
+
await this.handlePluginLoadCommand(path);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Add init command
|
|
143
|
+
*/
|
|
144
|
+
addInitCommand() {
|
|
145
|
+
this.program
|
|
146
|
+
.command("init [directory]")
|
|
147
|
+
.description("Initialize a new schemantic configuration")
|
|
148
|
+
.option("-t, --template <template>", "Configuration template", "default")
|
|
149
|
+
.option("--yes", "Skip interactive prompts")
|
|
150
|
+
.action(async (directory, options) => {
|
|
151
|
+
await this.handleInitCommand(directory, options);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Add help command
|
|
156
|
+
*/
|
|
157
|
+
addHelpCommand() {
|
|
158
|
+
this.program
|
|
159
|
+
.command("help [command]")
|
|
160
|
+
.description("Display help for a specific command")
|
|
161
|
+
.action((command) => {
|
|
162
|
+
this.handleHelpCommand(command);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Handle generate command
|
|
167
|
+
*/
|
|
168
|
+
async handleGenerateCommand(source, options = {}) {
|
|
169
|
+
try {
|
|
170
|
+
// Check for interactive mode
|
|
171
|
+
const globalOptions = this.program.opts();
|
|
172
|
+
if (globalOptions.interactive) {
|
|
173
|
+
await this.runInteractiveMode();
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
// Load configuration
|
|
177
|
+
const config = await this.loadConfiguration(source, options);
|
|
178
|
+
// Create Schemantic instance
|
|
179
|
+
const schemanticInstance = new schemantic_1.Schemantic(config);
|
|
180
|
+
// Load plugins
|
|
181
|
+
await this.loadPlugins(config, schemanticInstance);
|
|
182
|
+
// Generate types and client
|
|
183
|
+
const result = await schemanticInstance.generate();
|
|
184
|
+
// Output results
|
|
185
|
+
this.outputResults(result, options);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
this.handleError(error, options);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Handle validate command
|
|
193
|
+
*/
|
|
194
|
+
async handleValidateCommand(source, options = {}) {
|
|
195
|
+
try {
|
|
196
|
+
// Load configuration
|
|
197
|
+
const config = await this.loadConfiguration(source, options);
|
|
198
|
+
// Create Schemantic instance
|
|
199
|
+
const schemanticInstance = new schemantic_1.Schemantic(config);
|
|
200
|
+
// Validate schema
|
|
201
|
+
const result = await schemanticInstance.validate();
|
|
202
|
+
// Output validation results
|
|
203
|
+
this.outputValidationResults(result, options);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
this.handleError(error, options);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Handle init command
|
|
211
|
+
*/
|
|
212
|
+
async handleInitCommand(directory, options = {}) {
|
|
213
|
+
try {
|
|
214
|
+
const targetDir = directory || process.cwd();
|
|
215
|
+
if (options.yes) {
|
|
216
|
+
await this.createDefaultConfig(targetDir);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
await this.runInitInteractive(targetDir, options);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
this.handleError(error, options);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Handle plugin list command
|
|
228
|
+
*/
|
|
229
|
+
async handlePluginListCommand() {
|
|
230
|
+
try {
|
|
231
|
+
const builtinPlugins = (0, builtin_1.getBuiltinPlugins)();
|
|
232
|
+
console.log("Built-in plugins:");
|
|
233
|
+
for (const plugin of builtinPlugins) {
|
|
234
|
+
console.log(` ${plugin.name} (${plugin.version}) - ${plugin.description}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
this.handleError(error, {});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Handle plugin load command
|
|
243
|
+
*/
|
|
244
|
+
async handlePluginLoadCommand(path) {
|
|
245
|
+
try {
|
|
246
|
+
const loader = new plugins_1.PluginLoader();
|
|
247
|
+
const plugin = await loader.loadPluginFromFile(path);
|
|
248
|
+
console.log(`Loaded plugin: ${plugin.name} (${plugin.version})`);
|
|
249
|
+
console.log(`Description: ${plugin.description}`);
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
this.handleError(error, {});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Handle help command
|
|
257
|
+
*/
|
|
258
|
+
handleHelpCommand(command) {
|
|
259
|
+
if (command) {
|
|
260
|
+
// Show help for specific command
|
|
261
|
+
const subCommand = this.program.commands.find((cmd) => cmd.name() === command);
|
|
262
|
+
if (subCommand) {
|
|
263
|
+
subCommand.help();
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
console.log(`Unknown command: ${command}`);
|
|
267
|
+
console.log("Available commands:");
|
|
268
|
+
this.program.commands.forEach((cmd) => {
|
|
269
|
+
console.log(` ${cmd.name()} - ${cmd.description()}`);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
// Show general help with examples
|
|
275
|
+
console.log("š Schemantic CLI Examples:");
|
|
276
|
+
console.log("\nļæ½ Basic Usage:");
|
|
277
|
+
console.log(" # Generate from FastAPI server");
|
|
278
|
+
console.log(" npx schemantic generate --url http://localhost:8000/openapi.json");
|
|
279
|
+
console.log("\n # Generate from local file");
|
|
280
|
+
console.log(" npx schemantic generate --file ./openapi-schema.json");
|
|
281
|
+
console.log("\n # Custom output directory");
|
|
282
|
+
console.log(" npx schemantic generate --url http://localhost:8000/openapi.json --output ./src/api");
|
|
283
|
+
console.log("\nāļø React Integration:");
|
|
284
|
+
console.log(" # Generate with React hooks");
|
|
285
|
+
console.log(" npx schemantic generate --url http://localhost:8000/openapi.json --hooks");
|
|
286
|
+
console.log("\nšļø Interactive Mode:");
|
|
287
|
+
console.log(" npx schemantic generate --interactive");
|
|
288
|
+
console.log("\nāļø Configuration:");
|
|
289
|
+
console.log(" # Initialize configuration");
|
|
290
|
+
console.log(" npx schemantic init");
|
|
291
|
+
console.log("\n # Use configuration file");
|
|
292
|
+
console.log(" npx schemantic generate --config ./Schemantic.config.json");
|
|
293
|
+
console.log("\nā
Validation:");
|
|
294
|
+
console.log(" # Validate schema");
|
|
295
|
+
console.log(" npx schemantic validate --url http://localhost:8000/openapi.json");
|
|
296
|
+
console.log("\nļæ½ Advanced:");
|
|
297
|
+
console.log(" # Custom naming and filtering");
|
|
298
|
+
console.log(" npx schemantic generate --url http://localhost:8000/openapi.json \\");
|
|
299
|
+
console.log(" --naming PascalCase --prefix MyAPI --exclude-paths '/health,/docs'");
|
|
300
|
+
console.log("\nš For complete documentation:");
|
|
301
|
+
console.log(" https://github.com/Cstannahill/schemantic#readme");
|
|
302
|
+
console.log("\nš” Get help for specific commands:");
|
|
303
|
+
console.log(" npx schemantic help generate");
|
|
304
|
+
console.log(" npx schemantic generate --help");
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Load configuration from options
|
|
309
|
+
*/
|
|
310
|
+
async loadConfiguration(source, options = {}) {
|
|
311
|
+
let config = { ...core_1.DEFAULT_CONFIG };
|
|
312
|
+
// Load from config file if specified
|
|
313
|
+
if (options.config) {
|
|
314
|
+
const configFile = await this.loadConfigFile(options.config);
|
|
315
|
+
config = { ...config, ...configFile };
|
|
316
|
+
}
|
|
317
|
+
// Handle source parameter (URL or file path)
|
|
318
|
+
if (source) {
|
|
319
|
+
if (source.startsWith("http://") || source.startsWith("https://")) {
|
|
320
|
+
config.schemaUrl = source;
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
config.schemaFile = source;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
// Override with command line options
|
|
327
|
+
if (options.url) {
|
|
328
|
+
config.schemaUrl = options.url;
|
|
329
|
+
}
|
|
330
|
+
if (options.file) {
|
|
331
|
+
config.schemaFile = options.file;
|
|
332
|
+
}
|
|
333
|
+
if (options.output) {
|
|
334
|
+
config.outputDir = options.output;
|
|
335
|
+
}
|
|
336
|
+
if (options.types) {
|
|
337
|
+
config.generateTypes = true;
|
|
338
|
+
}
|
|
339
|
+
if (options.client) {
|
|
340
|
+
config.generateApiClient = true;
|
|
341
|
+
}
|
|
342
|
+
if (options.hooks) {
|
|
343
|
+
config.generateHooks = true;
|
|
344
|
+
}
|
|
345
|
+
if (options.strict !== undefined) {
|
|
346
|
+
config.useStrictTypes = options.strict;
|
|
347
|
+
}
|
|
348
|
+
if (options.naming) {
|
|
349
|
+
config.namingConvention = options.naming;
|
|
350
|
+
}
|
|
351
|
+
if (options.prefix) {
|
|
352
|
+
config.typePrefix = options.prefix;
|
|
353
|
+
}
|
|
354
|
+
if (options.suffix) {
|
|
355
|
+
config.typeSuffix = options.suffix;
|
|
356
|
+
}
|
|
357
|
+
if (options.excludePaths) {
|
|
358
|
+
config.excludePaths = options.excludePaths.split(",");
|
|
359
|
+
}
|
|
360
|
+
if (options.includePaths) {
|
|
361
|
+
config.includePaths = options.includePaths.split(",");
|
|
362
|
+
}
|
|
363
|
+
if (options.excludeSchemas) {
|
|
364
|
+
config.excludeSchemas = options.excludeSchemas.split(",");
|
|
365
|
+
}
|
|
366
|
+
if (options.includeSchemas) {
|
|
367
|
+
config.includeSchemas = options.includeSchemas.split(",");
|
|
368
|
+
}
|
|
369
|
+
if (options.plugins) {
|
|
370
|
+
config.plugins = options.plugins.split(",").map((name) => ({
|
|
371
|
+
name: name.trim(),
|
|
372
|
+
enabled: true,
|
|
373
|
+
}));
|
|
374
|
+
}
|
|
375
|
+
// Validate required fields
|
|
376
|
+
if (!config.schemaUrl && !config.schemaFile && !config.schemaData) {
|
|
377
|
+
throw new Error("Either source parameter, --url, --file, or schema data must be provided");
|
|
378
|
+
}
|
|
379
|
+
if (!config.outputDir) {
|
|
380
|
+
throw new Error("Output directory must be specified");
|
|
381
|
+
}
|
|
382
|
+
return config;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Load configuration file
|
|
386
|
+
*/
|
|
387
|
+
async loadConfigFile(filePath) {
|
|
388
|
+
try {
|
|
389
|
+
const fs = await Promise.resolve().then(() => __importStar(require("fs/promises")));
|
|
390
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
391
|
+
if (filePath.endsWith(".json")) {
|
|
392
|
+
return JSON.parse(content);
|
|
393
|
+
}
|
|
394
|
+
else if (filePath.endsWith(".js") || filePath.endsWith(".ts")) {
|
|
395
|
+
const module = await Promise.resolve(`${filePath}`).then(s => __importStar(require(s)));
|
|
396
|
+
return module.default || module;
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
throw new Error(`Unsupported configuration file format: ${filePath}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
throw new Error(`Failed to load configuration file ${filePath}: ${error}`);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Load plugins
|
|
408
|
+
*/
|
|
409
|
+
async loadPlugins(config, Schemantic) {
|
|
410
|
+
const pluginManager = Schemantic.getPluginManager();
|
|
411
|
+
// Load built-in plugins
|
|
412
|
+
const builtinPlugins = (0, builtin_1.getBuiltinPlugins)();
|
|
413
|
+
for (const plugin of builtinPlugins) {
|
|
414
|
+
pluginManager.registerPlugin(plugin);
|
|
415
|
+
}
|
|
416
|
+
// Load configured plugins
|
|
417
|
+
if (config.plugins) {
|
|
418
|
+
for (const pluginConfig of config.plugins) {
|
|
419
|
+
if (pluginConfig.enabled) {
|
|
420
|
+
pluginManager.enablePlugin(pluginConfig.name);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Output generation results
|
|
427
|
+
*/
|
|
428
|
+
outputResults(result, options) {
|
|
429
|
+
if (options.quiet) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
if (result.success) {
|
|
433
|
+
console.log("ā
Generation completed successfully!");
|
|
434
|
+
console.log(`š Generated ${result.generatedFiles.length} files`);
|
|
435
|
+
console.log(`š Statistics: ${result.statistics.totalTypes} types, ${result.statistics.totalEndpoints} endpoints`);
|
|
436
|
+
console.log(`ā±ļø Generation time: ${result.statistics.generationTime}ms`);
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
console.log("ā Generation failed!");
|
|
440
|
+
console.log(`šØ Errors: ${result.errors.length}`);
|
|
441
|
+
for (const error of result.errors) {
|
|
442
|
+
console.log(` - ${error.message}`);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Output validation results
|
|
448
|
+
*/
|
|
449
|
+
outputValidationResults(result, options) {
|
|
450
|
+
if (options.quiet) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
if (result.isValid) {
|
|
454
|
+
console.log("ā
Schema validation passed!");
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
console.log("ā Schema validation failed!");
|
|
458
|
+
console.log(`šØ Errors: ${result.errors.length}`);
|
|
459
|
+
for (const error of result.errors) {
|
|
460
|
+
console.log(` - ${error.message}${error.source ? ` (${error.source})` : ""}`);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
if (result.warnings.length > 0) {
|
|
464
|
+
console.log(`ā ļø Warnings: ${result.warnings.length}`);
|
|
465
|
+
for (const warning of result.warnings) {
|
|
466
|
+
console.log(` - ${warning.message}${warning.source ? ` (${warning.source})` : ""}`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Handle errors
|
|
472
|
+
*/
|
|
473
|
+
handleError(error, options) {
|
|
474
|
+
if (options.quiet) {
|
|
475
|
+
process.exit(1);
|
|
476
|
+
}
|
|
477
|
+
console.error("ā Error:", error);
|
|
478
|
+
process.exit(1);
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Run interactive mode
|
|
482
|
+
*/
|
|
483
|
+
async runInteractiveMode() {
|
|
484
|
+
console.log("š Schemantic Interactive Mode\n");
|
|
485
|
+
const rl = readline.createInterface({
|
|
486
|
+
input: process.stdin,
|
|
487
|
+
output: process.stdout,
|
|
488
|
+
});
|
|
489
|
+
try {
|
|
490
|
+
const config = { ...core_1.DEFAULT_CONFIG };
|
|
491
|
+
// Get schema source
|
|
492
|
+
const schemaSource = await this.askQuestion(rl, "Enter OpenAPI schema URL or file path: ");
|
|
493
|
+
if (schemaSource.startsWith("http")) {
|
|
494
|
+
config.schemaUrl = schemaSource;
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
config.schemaFile = schemaSource;
|
|
498
|
+
}
|
|
499
|
+
// Get output directory
|
|
500
|
+
const outputDir = await this.askQuestion(rl, "Output directory (default: ./src/generated): ");
|
|
501
|
+
config.outputDir = outputDir || "./src/generated";
|
|
502
|
+
// Get type prefix
|
|
503
|
+
const prefix = await this.askQuestion(rl, "Type prefix (default: API): ");
|
|
504
|
+
config.typePrefix = prefix || "API";
|
|
505
|
+
// Get generation options
|
|
506
|
+
const generateTypes = await this.askYesNo(rl, "Generate types? (Y/n): ");
|
|
507
|
+
config.generateTypes = generateTypes !== false;
|
|
508
|
+
const generateClient = await this.askYesNo(rl, "Generate API client? (Y/n): ");
|
|
509
|
+
config.generateApiClient = generateClient !== false;
|
|
510
|
+
const generateHooks = await this.askYesNo(rl, "Generate React hooks? (y/N): ");
|
|
511
|
+
config.generateHooks = generateHooks === true;
|
|
512
|
+
const strictTypes = await this.askYesNo(rl, "Use strict TypeScript types? (Y/n): ");
|
|
513
|
+
config.useStrictTypes = strictTypes !== false;
|
|
514
|
+
// Create Schemantic instance and generate
|
|
515
|
+
const schemanticInstance = new schemantic_1.Schemantic(config);
|
|
516
|
+
await this.loadPlugins(config, schemanticInstance);
|
|
517
|
+
console.log("\nāļø Generating types and API client...");
|
|
518
|
+
const result = await schemanticInstance.generate();
|
|
519
|
+
this.outputResults(result, {});
|
|
520
|
+
}
|
|
521
|
+
finally {
|
|
522
|
+
rl.close();
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Run init interactive mode
|
|
527
|
+
*/
|
|
528
|
+
async runInitInteractive(directory, _options) {
|
|
529
|
+
console.log("š Schemantic Configuration Initialization\n");
|
|
530
|
+
const rl = readline.createInterface({
|
|
531
|
+
input: process.stdin,
|
|
532
|
+
output: process.stdout,
|
|
533
|
+
});
|
|
534
|
+
try {
|
|
535
|
+
const config = { ...core_1.DEFAULT_CONFIG };
|
|
536
|
+
// Get schema source
|
|
537
|
+
const schemaSource = await this.askQuestion(rl, "Enter default OpenAPI schema URL or file path: ");
|
|
538
|
+
if (schemaSource.startsWith("http")) {
|
|
539
|
+
config.schemaUrl = schemaSource;
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
config.schemaFile = schemaSource;
|
|
543
|
+
}
|
|
544
|
+
// Get output directory
|
|
545
|
+
const outputDir = await this.askQuestion(rl, "Default output directory (default: ./src/generated): ");
|
|
546
|
+
config.outputDir = outputDir || "./src/generated";
|
|
547
|
+
// Get type prefix
|
|
548
|
+
const prefix = await this.askQuestion(rl, "Type prefix (default: API): ");
|
|
549
|
+
config.typePrefix = prefix || "API";
|
|
550
|
+
// Get naming convention
|
|
551
|
+
const naming = await this.askChoice(rl, "Naming convention (camelCase/snake_case/PascalCase): ", ["camelCase", "snake_case", "PascalCase"], "camelCase");
|
|
552
|
+
config.namingConvention = naming;
|
|
553
|
+
// Get generation options
|
|
554
|
+
const generateTypes = await this.askYesNo(rl, "Generate types by default? (Y/n): ");
|
|
555
|
+
config.generateTypes = generateTypes !== false;
|
|
556
|
+
const generateClient = await this.askYesNo(rl, "Generate API client by default? (Y/n): ");
|
|
557
|
+
config.generateApiClient = generateClient !== false;
|
|
558
|
+
const generateHooks = await this.askYesNo(rl, "Generate React hooks by default? (y/N): ");
|
|
559
|
+
config.generateHooks = generateHooks === true;
|
|
560
|
+
const strictTypes = await this.askYesNo(rl, "Use strict TypeScript types by default? (Y/n): ");
|
|
561
|
+
config.useStrictTypes = strictTypes !== false;
|
|
562
|
+
// Save configuration
|
|
563
|
+
await this.saveConfig(directory, config);
|
|
564
|
+
console.log("\nā
Configuration saved to Schemantic.config.json");
|
|
565
|
+
}
|
|
566
|
+
finally {
|
|
567
|
+
rl.close();
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Create default configuration
|
|
572
|
+
*/
|
|
573
|
+
async createDefaultConfig(directory) {
|
|
574
|
+
const config = {
|
|
575
|
+
...core_1.DEFAULT_CONFIG,
|
|
576
|
+
outputDir: "./src/generated",
|
|
577
|
+
typePrefix: "API",
|
|
578
|
+
generateTypes: true,
|
|
579
|
+
generateApiClient: true,
|
|
580
|
+
generateHooks: false,
|
|
581
|
+
useStrictTypes: true,
|
|
582
|
+
namingConvention: "camelCase",
|
|
583
|
+
typeSuffix: "",
|
|
584
|
+
generateBarrelExports: true,
|
|
585
|
+
useOptionalChaining: true,
|
|
586
|
+
useNullishCoalescing: true,
|
|
587
|
+
preserveComments: true,
|
|
588
|
+
generateIndexFile: true,
|
|
589
|
+
};
|
|
590
|
+
await this.saveConfig(directory, config);
|
|
591
|
+
console.log("ā
Default configuration created");
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* Save configuration to file
|
|
595
|
+
*/
|
|
596
|
+
async saveConfig(directory, config) {
|
|
597
|
+
const fs = await Promise.resolve().then(() => __importStar(require("fs/promises")));
|
|
598
|
+
const path = await Promise.resolve().then(() => __importStar(require("path")));
|
|
599
|
+
const configPath = path.join(directory, "Schemantic.config.json");
|
|
600
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Ask a question and return the answer
|
|
604
|
+
*/
|
|
605
|
+
askQuestion(rl, question) {
|
|
606
|
+
return new Promise((resolve) => {
|
|
607
|
+
rl.question(question, resolve);
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Ask a yes/no question and return boolean
|
|
612
|
+
*/
|
|
613
|
+
askYesNo(rl, question) {
|
|
614
|
+
return new Promise((resolve) => {
|
|
615
|
+
rl.question(question, (answer) => {
|
|
616
|
+
const normalized = answer.toLowerCase().trim();
|
|
617
|
+
if (normalized === "" || normalized === "y" || normalized === "yes") {
|
|
618
|
+
resolve(true);
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
resolve(false);
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Ask a choice question and return selected option
|
|
628
|
+
*/
|
|
629
|
+
askChoice(rl, question, choices, defaultChoice) {
|
|
630
|
+
return new Promise((resolve) => {
|
|
631
|
+
rl.question(question, (answer) => {
|
|
632
|
+
const normalized = answer.toLowerCase().trim();
|
|
633
|
+
if (normalized === "") {
|
|
634
|
+
resolve(defaultChoice);
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
const choice = choices.find((c) => c.toLowerCase() === normalized);
|
|
638
|
+
resolve(choice || defaultChoice);
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Run the CLI
|
|
645
|
+
*/
|
|
646
|
+
run() {
|
|
647
|
+
this.program.parse();
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
exports.SchemanticCli = SchemanticCli;
|
|
651
|
+
// Export CLI class and create instance
|
|
652
|
+
exports.cli = new SchemanticCli();
|
|
653
|
+
// Run CLI if this file is executed directly
|
|
654
|
+
if (require.main === module) {
|
|
655
|
+
exports.cli.run();
|
|
656
|
+
}
|
|
657
|
+
//# sourceMappingURL=index.js.map
|