@kosdev-code/kos-ui-cli 2.0.43 → 2.0.45

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.
@@ -0,0 +1,139 @@
1
+ import { compareApiVersions } from "./lib/compare-api.mjs";
2
+
3
+ /**
4
+ * Registers the api:compare generator with Plop for comparing OpenAPI versions
5
+ * and detecting breaking changes between API type definitions.
6
+ *
7
+ * This generator analyzes two generated API type definition files to identify
8
+ * compatibility issues such as removed endpoints, changed parameters, and
9
+ * breaking changes. Essential for safe API upgrades and release planning.
10
+ *
11
+ * @param {import('plop').NodePlopAPI} plop - The Plop API instance
12
+ * @returns {Promise<void>} Resolves when generator is registered
13
+ *
14
+ * @example
15
+ * ```javascript
16
+ * // In plopfile.mjs
17
+ * import registerApiCompare from './generators/api/compare.mjs';
18
+ * await registerApiCompare(plop);
19
+ * ```
20
+ */
21
+ export default async function register(plop) {
22
+ plop.setGenerator("api:compare", {
23
+ description: "Compare OpenAPI versions for compatibility analysis",
24
+ prompts: [
25
+ {
26
+ type: "input",
27
+ name: "project",
28
+ message: "Project name containing generated API types",
29
+ validate: (input) => {
30
+ if (!input || input.trim() === "") {
31
+ return "Project name is required";
32
+ }
33
+ return true;
34
+ },
35
+ },
36
+ {
37
+ type: "input",
38
+ name: "app",
39
+ message: "App namespace to compare (kos, dispense, freestyle, etc.)",
40
+ validate: (input) => {
41
+ if (!input || input.trim() === "") {
42
+ return "App namespace is required";
43
+ }
44
+ return true;
45
+ },
46
+ },
47
+ {
48
+ type: "input",
49
+ name: "baseVersion",
50
+ message: "Base version to compare from",
51
+ validate: (input) => {
52
+ if (!input || input.trim() === "") {
53
+ return "Base version is required";
54
+ }
55
+ return true;
56
+ },
57
+ },
58
+ {
59
+ type: "input",
60
+ name: "targetVersion",
61
+ message: "Target version to compare to",
62
+ validate: (input) => {
63
+ if (!input || input.trim() === "") {
64
+ return "Target version is required";
65
+ }
66
+ return true;
67
+ },
68
+ },
69
+ {
70
+ type: "list",
71
+ name: "format",
72
+ message: "Output format",
73
+ choices: ["console", "json", "markdown"],
74
+ default: "console",
75
+ },
76
+ {
77
+ type: "input",
78
+ name: "outputFile",
79
+ message: "Output file path (optional, leave empty for stdout)",
80
+ default: "",
81
+ },
82
+ ],
83
+ actions: function (answers) {
84
+ return [
85
+ async function compareApi() {
86
+ try {
87
+ const options = {
88
+ project: answers.project,
89
+ app: answers.app,
90
+ apps: answers.apps, // Support multi-app comparison
91
+ baseVersion: answers.baseVersion,
92
+ targetVersion: answers.targetVersion,
93
+ format: answers.format,
94
+ outputFile: answers.outputFile || undefined,
95
+ };
96
+
97
+ const result = await compareApiVersions(options);
98
+
99
+ if (answers.outputFile) {
100
+ return `[ok] Comparison written to ${answers.outputFile}`;
101
+ } else {
102
+ return `[ok] Comparison complete`;
103
+ }
104
+ } catch (error) {
105
+ console.error("Error comparing API versions:", error);
106
+ throw new Error(`Failed to compare API versions: ${error.message}`);
107
+ }
108
+ },
109
+ ];
110
+ },
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Metadata for CLI integration describing the api:compare command.
116
+ *
117
+ * Provides command key, description, and argument mappings for the CLI
118
+ * help system and command-line argument parsing.
119
+ *
120
+ * @type {Object}
121
+ * @property {string} key - Command identifier used in CLI
122
+ * @property {string} name - Human-readable command name
123
+ * @property {string} description - Command description for help text
124
+ * @property {Object} namedArguments - Maps CLI argument names to prompt property names
125
+ */
126
+ export const metadata = {
127
+ key: "api:compare",
128
+ name: "Compare API Versions",
129
+ description: "Analyze compatibility between OpenAPI versions and detect breaking changes",
130
+ namedArguments: {
131
+ project: "project",
132
+ app: "app",
133
+ apps: "apps", // For multi-app comparison
134
+ base: "baseVersion",
135
+ target: "targetVersion",
136
+ format: "format",
137
+ output: "outputFile",
138
+ },
139
+ };
@@ -0,0 +1,105 @@
1
+ import { generateApiTypes } from "./lib/generate-api.mjs";
2
+
3
+ /**
4
+ * Generator for creating OpenAPI service types
5
+ */
6
+ export default async function register(plop) {
7
+ plop.setGenerator("api:generate", {
8
+ description: "Generate OpenAPI service types for a project",
9
+ prompts: [
10
+ {
11
+ type: "input",
12
+ name: "project",
13
+ message: "Project name",
14
+ validate: (input) => {
15
+ if (!input || input.trim() === "") {
16
+ return "Project name is required";
17
+ }
18
+ return true;
19
+ },
20
+ },
21
+ {
22
+ type: "input",
23
+ name: "host",
24
+ message: "API host URL (or 'inherit' to use project.json)",
25
+ default: "inherit",
26
+ },
27
+ {
28
+ type: "input",
29
+ name: "apps",
30
+ message: "Apps to include (comma-separated, leave empty for all)",
31
+ default: "",
32
+ filter: (input) => {
33
+ if (!input || input.trim() === "") {
34
+ return [];
35
+ }
36
+ return input.split(",").map((s) => s.trim()).filter(Boolean);
37
+ },
38
+ },
39
+ {
40
+ type: "input",
41
+ name: "outputPath",
42
+ message: "Output path (or 'inherit' to use project.json)",
43
+ default: "inherit",
44
+ },
45
+ {
46
+ type: "input",
47
+ name: "defaultVersion",
48
+ message: "Default version (or 'inherit' to use project.json)",
49
+ default: "inherit",
50
+ },
51
+ {
52
+ type: "input",
53
+ name: "allAppsVersion",
54
+ message: "Override all apps to specific version (leave empty to use individual versions)",
55
+ default: "",
56
+ },
57
+ ],
58
+ actions: function (answers) {
59
+ return [
60
+ async function generateApi() {
61
+ try {
62
+ const options = {
63
+ project: answers.project,
64
+ host: answers.host === "inherit" ? undefined : answers.host,
65
+ studio: false, // Third-party projects don't use Studio endpoints
66
+ apps: answers.apps,
67
+ excludeCore: true, // Always exclude core services (already in published SDKs)
68
+ outputPath: answers.outputPath === "inherit" ? undefined : (answers.outputPath || undefined),
69
+ defaultVersion: answers.defaultVersion === "inherit" ? undefined : answers.defaultVersion,
70
+ allAppsVersion: answers.allAppsVersion || undefined,
71
+ // Pass CLI overrides if provided (they'll be merged with project.json in generate-api.mjs)
72
+ appVersions: answers.appVersions,
73
+ serviceExportAliases: answers.serviceExportAliases,
74
+ };
75
+
76
+ const result = await generateApiTypes(options);
77
+
78
+ return `[ok] Generated ${result.filesGenerated} files for ${result.apps.length} apps: ${result.apps.join(", ")}`;
79
+ } catch (error) {
80
+ console.error("Error generating API types:", error);
81
+ throw new Error(`Failed to generate API types: ${error.message}`);
82
+ }
83
+ },
84
+ ];
85
+ },
86
+ });
87
+ }
88
+
89
+ // Export metadata for CLI integration
90
+ export const metadata = {
91
+ key: "api:generate",
92
+ name: "Generate OpenAPI service types",
93
+ description: "Generate typed service helpers from OpenAPI specifications",
94
+ namedArguments: {
95
+ project: "project",
96
+ host: "host",
97
+ apps: "apps",
98
+ output: "outputPath",
99
+ "default-version": "defaultVersion",
100
+ "all-apps-version": "allAppsVersion",
101
+ // Advanced options that can be passed as JSON strings or key=value pairs
102
+ alias: "serviceExportAliases",
103
+ "app-version": "appVersions",
104
+ },
105
+ };