@geekmidas/cli 1.2.2 → 1.2.3
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 +6 -0
- package/dist/index.cjs +88 -161
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +89 -162
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-BZ4Qik9w.mjs → openapi-NthphEWK.mjs} +2 -2
- package/dist/{openapi-BZ4Qik9w.mjs.map → openapi-NthphEWK.mjs.map} +1 -1
- package/dist/{openapi-CzfnHlhG.cjs → openapi-ZhO7wwya.cjs} +1 -7
- package/dist/{openapi-CzfnHlhG.cjs.map → openapi-ZhO7wwya.cjs.map} +1 -1
- package/dist/openapi.cjs +1 -1
- package/dist/openapi.mjs +1 -1
- package/package.json +2 -2
- package/src/dev/index.ts +69 -106
- package/src/workspace/__tests__/client-generator.spec.ts +330 -301
- package/src/workspace/client-generator.ts +139 -199
package/dist/openapi.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
2
|
require('./workspace-BMJE18LV.cjs');
|
|
3
3
|
require('./config-Bayob8pB.cjs');
|
|
4
|
-
const require_openapi = require('./openapi-
|
|
4
|
+
const require_openapi = require('./openapi-ZhO7wwya.cjs');
|
|
5
5
|
|
|
6
6
|
exports.OPENAPI_OUTPUT_PATH = require_openapi.OPENAPI_OUTPUT_PATH;
|
|
7
7
|
exports.generateOpenApi = require_openapi.generateOpenApi;
|
package/dist/openapi.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
2
|
import "./workspace-CASoZOjs.mjs";
|
|
3
3
|
import "./config-BQ4a36Rq.mjs";
|
|
4
|
-
import { OPENAPI_OUTPUT_PATH, generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi-
|
|
4
|
+
import { OPENAPI_OUTPUT_PATH, generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi-NthphEWK.mjs";
|
|
5
5
|
|
|
6
6
|
export { OPENAPI_OUTPUT_PATH, generateOpenApi, openapiCommand, resolveOpenApiConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
"prompts": "~2.4.2",
|
|
55
55
|
"tsx": "~4.20.3",
|
|
56
56
|
"@geekmidas/constructs": "~1.0.0",
|
|
57
|
-
"@geekmidas/errors": "~1.0.0",
|
|
58
57
|
"@geekmidas/envkit": "~1.0.0",
|
|
58
|
+
"@geekmidas/errors": "~1.0.0",
|
|
59
59
|
"@geekmidas/logger": "~1.0.0",
|
|
60
60
|
"@geekmidas/schema": "~1.0.0"
|
|
61
61
|
},
|
package/src/dev/index.ts
CHANGED
|
@@ -46,10 +46,9 @@ import type {
|
|
|
46
46
|
TelescopeConfig,
|
|
47
47
|
} from '../types';
|
|
48
48
|
import {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
normalizeRoutes,
|
|
49
|
+
copyAllClients,
|
|
50
|
+
copyClientToFrontends,
|
|
51
|
+
getBackendOpenApiPath,
|
|
53
52
|
} from '../workspace/client-generator.js';
|
|
54
53
|
import {
|
|
55
54
|
getAppBuildOrder,
|
|
@@ -964,12 +963,12 @@ async function workspaceDevCommand(
|
|
|
964
963
|
logger.log('✅ Frontend apps validated');
|
|
965
964
|
}
|
|
966
965
|
|
|
967
|
-
//
|
|
968
|
-
if (frontendApps.length > 0) {
|
|
969
|
-
const clientResults = await
|
|
970
|
-
const
|
|
971
|
-
if (
|
|
972
|
-
logger.log(`\n📦
|
|
966
|
+
// Copy initial clients from backends to frontends
|
|
967
|
+
if (frontendApps.length > 0 && backendApps.length > 0) {
|
|
968
|
+
const clientResults = await copyAllClients(workspace);
|
|
969
|
+
const copiedCount = clientResults.filter((r) => r.success).length;
|
|
970
|
+
if (copiedCount > 0) {
|
|
971
|
+
logger.log(`\n📦 Copied ${copiedCount} API client(s)`);
|
|
973
972
|
}
|
|
974
973
|
}
|
|
975
974
|
|
|
@@ -1058,117 +1057,81 @@ async function workspaceDevCommand(
|
|
|
1058
1057
|
env: turboEnv,
|
|
1059
1058
|
});
|
|
1060
1059
|
|
|
1061
|
-
// Set up file watcher for backend
|
|
1062
|
-
let
|
|
1060
|
+
// Set up file watcher for backend .gkm/openapi.ts changes (auto-copy to frontends)
|
|
1061
|
+
let openApiWatcher: ReturnType<typeof chokidar.watch> | null = null;
|
|
1063
1062
|
|
|
1064
1063
|
if (frontendApps.length > 0 && backendApps.length > 0) {
|
|
1065
|
-
// Collect all backend
|
|
1066
|
-
const
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
const fullPattern = join(workspace.root, app.path, routePattern);
|
|
1073
|
-
watchPatterns.push(fullPattern);
|
|
1074
|
-
|
|
1075
|
-
// Map pattern to app name for change detection
|
|
1076
|
-
const patternKey = join(app.path, routePattern);
|
|
1077
|
-
const existing = backendRouteMap.get(patternKey) || [];
|
|
1078
|
-
backendRouteMap.set(patternKey, [...existing, appName]);
|
|
1064
|
+
// Collect all backend openapi.ts file paths to watch
|
|
1065
|
+
const openApiPaths: { path: string; appName: string }[] = [];
|
|
1066
|
+
|
|
1067
|
+
for (const [appName] of backendApps) {
|
|
1068
|
+
const openApiPath = getBackendOpenApiPath(workspace, appName);
|
|
1069
|
+
if (openApiPath) {
|
|
1070
|
+
openApiPaths.push({ path: openApiPath, appName });
|
|
1079
1071
|
}
|
|
1080
1072
|
}
|
|
1081
1073
|
|
|
1082
|
-
if (
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
absolute: true,
|
|
1087
|
-
onlyFiles: true,
|
|
1088
|
-
});
|
|
1074
|
+
if (openApiPaths.length > 0) {
|
|
1075
|
+
logger.log(
|
|
1076
|
+
`\n👀 Watching ${openApiPaths.length} backend OpenAPI spec(s) for changes`,
|
|
1077
|
+
);
|
|
1089
1078
|
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
`\n👀 Watching ${resolvedFiles.length} endpoint file(s) for schema changes`,
|
|
1093
|
-
);
|
|
1079
|
+
// Create a map for quick lookup of app name from path
|
|
1080
|
+
const pathToApp = new Map(openApiPaths.map((p) => [p.path, p.appName]));
|
|
1094
1081
|
|
|
1095
|
-
|
|
1096
|
-
|
|
1082
|
+
openApiWatcher = chokidar.watch(
|
|
1083
|
+
openApiPaths.map((p) => p.path),
|
|
1084
|
+
{
|
|
1097
1085
|
persistent: true,
|
|
1098
1086
|
ignoreInitial: true,
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1087
|
+
// Watch parent directory too since file may not exist yet
|
|
1088
|
+
depth: 0,
|
|
1089
|
+
},
|
|
1090
|
+
);
|
|
1102
1091
|
|
|
1103
|
-
|
|
1104
|
-
// Debounce regeneration
|
|
1105
|
-
if (regenerateTimeout) {
|
|
1106
|
-
clearTimeout(regenerateTimeout);
|
|
1107
|
-
}
|
|
1092
|
+
let copyTimeout: NodeJS.Timeout | null = null;
|
|
1108
1093
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
const routePatterns = normalizeRoutes(app.routes);
|
|
1115
|
-
for (const routePattern of routePatterns) {
|
|
1116
|
-
const routesDir = join(
|
|
1117
|
-
workspace.root,
|
|
1118
|
-
app.path,
|
|
1119
|
-
routePattern.split('*')[0] || '',
|
|
1120
|
-
);
|
|
1121
|
-
if (changedPath.startsWith(routesDir.replace(/\/$/, ''))) {
|
|
1122
|
-
changedBackends.push(appName);
|
|
1123
|
-
break; // Found a match, no need to check other patterns
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
if (changedBackends.length === 0) {
|
|
1129
|
-
return;
|
|
1130
|
-
}
|
|
1094
|
+
const handleChange = async (changedPath: string) => {
|
|
1095
|
+
// Debounce to handle rapid changes
|
|
1096
|
+
if (copyTimeout) {
|
|
1097
|
+
clearTimeout(copyTimeout);
|
|
1098
|
+
}
|
|
1131
1099
|
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
affectedFrontends.add(frontend);
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1100
|
+
copyTimeout = setTimeout(async () => {
|
|
1101
|
+
const backendAppName = pathToApp.get(changedPath);
|
|
1102
|
+
if (!backendAppName) {
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1140
1105
|
|
|
1141
|
-
|
|
1142
|
-
return;
|
|
1143
|
-
}
|
|
1106
|
+
logger.log(`\n🔄 OpenAPI spec changed for ${backendAppName}`);
|
|
1144
1107
|
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1108
|
+
try {
|
|
1109
|
+
const results = await copyClientToFrontends(
|
|
1110
|
+
workspace,
|
|
1111
|
+
backendAppName,
|
|
1112
|
+
{ silent: true },
|
|
1148
1113
|
);
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
workspace,
|
|
1154
|
-
frontend,
|
|
1114
|
+
for (const result of results) {
|
|
1115
|
+
if (result.success) {
|
|
1116
|
+
logger.log(
|
|
1117
|
+
` 📦 Copied client to ${result.frontendApp} (${result.endpointCount} endpoints)`,
|
|
1155
1118
|
);
|
|
1156
|
-
|
|
1157
|
-
if (result.generated) {
|
|
1158
|
-
logger.log(
|
|
1159
|
-
` 📦 Regenerated client for ${result.frontendApp} (${result.endpointCount} endpoints)`,
|
|
1160
|
-
);
|
|
1161
|
-
}
|
|
1162
|
-
}
|
|
1163
|
-
} catch (error) {
|
|
1119
|
+
} else if (result.error) {
|
|
1164
1120
|
logger.error(
|
|
1165
|
-
` ❌ Failed to
|
|
1121
|
+
` ❌ Failed to copy client to ${result.frontendApp}: ${result.error}`,
|
|
1166
1122
|
);
|
|
1167
1123
|
}
|
|
1168
1124
|
}
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
|
|
1125
|
+
} catch (error) {
|
|
1126
|
+
logger.error(
|
|
1127
|
+
` ❌ Failed to copy clients: ${(error as Error).message}`,
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
}, 200); // 200ms debounce
|
|
1131
|
+
};
|
|
1132
|
+
|
|
1133
|
+
openApiWatcher.on('change', handleChange);
|
|
1134
|
+
openApiWatcher.on('add', handleChange);
|
|
1172
1135
|
}
|
|
1173
1136
|
}
|
|
1174
1137
|
|
|
@@ -1180,9 +1143,9 @@ async function workspaceDevCommand(
|
|
|
1180
1143
|
|
|
1181
1144
|
logger.log('\n🛑 Shutting down workspace...');
|
|
1182
1145
|
|
|
1183
|
-
// Close
|
|
1184
|
-
if (
|
|
1185
|
-
|
|
1146
|
+
// Close OpenAPI watcher
|
|
1147
|
+
if (openApiWatcher) {
|
|
1148
|
+
openApiWatcher.close().catch(() => {});
|
|
1186
1149
|
}
|
|
1187
1150
|
|
|
1188
1151
|
// Kill turbo process
|
|
@@ -1214,8 +1177,8 @@ async function workspaceDevCommand(
|
|
|
1214
1177
|
|
|
1215
1178
|
turboProcess.on('exit', (code) => {
|
|
1216
1179
|
// Close watcher on exit
|
|
1217
|
-
if (
|
|
1218
|
-
|
|
1180
|
+
if (openApiWatcher) {
|
|
1181
|
+
openApiWatcher.close().catch(() => {});
|
|
1219
1182
|
}
|
|
1220
1183
|
|
|
1221
1184
|
if (code !== null && code !== 0) {
|