@kosdev-code/kos-ui-cli 0.1.0-dev.5053

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 (47) hide show
  1. package/README.md +7 -0
  2. package/package.json +30 -0
  3. package/src/index.d.ts +2 -0
  4. package/src/index.d.ts.map +1 -0
  5. package/src/index.js +1 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/cli.mjs +803 -0
  8. package/src/lib/generators/cache/index.mjs +18 -0
  9. package/src/lib/generators/component/index.mjs +55 -0
  10. package/src/lib/generators/env/index.mjs +42 -0
  11. package/src/lib/generators/i18n/namespace.mjs +61 -0
  12. package/src/lib/generators/kab/index.mjs +82 -0
  13. package/src/lib/generators/metadata.json +341 -0
  14. package/src/lib/generators/model/add-future.mjs +96 -0
  15. package/src/lib/generators/model/companion.mjs +117 -0
  16. package/src/lib/generators/model/container.mjs +96 -0
  17. package/src/lib/generators/model/context.mjs +77 -0
  18. package/src/lib/generators/model/hook.mjs +77 -0
  19. package/src/lib/generators/model/model.mjs +79 -0
  20. package/src/lib/generators/plugin/index.mjs +195 -0
  21. package/src/lib/generators/project/app.mjs +39 -0
  22. package/src/lib/generators/project/content.mjs +41 -0
  23. package/src/lib/generators/project/i18n.mjs +38 -0
  24. package/src/lib/generators/project/plugin.mjs +38 -0
  25. package/src/lib/generators/project/splash.mjs +39 -0
  26. package/src/lib/generators/project/theme.mjs +38 -0
  27. package/src/lib/generators/serve/index.mjs +74 -0
  28. package/src/lib/generators/version/index.mjs +182 -0
  29. package/src/lib/generators/workspace/index.mjs +40 -0
  30. package/src/lib/generators/workspace/list-models.mjs +64 -0
  31. package/src/lib/generators/workspace/list-projects.mjs +167 -0
  32. package/src/lib/plopfile.mjs +67 -0
  33. package/src/lib/routing-plopfile.mjs +53 -0
  34. package/src/lib/scripts/generate-metadata.mjs +39 -0
  35. package/src/lib/utils/action-factory.mjs +9 -0
  36. package/src/lib/utils/cache.mjs +128 -0
  37. package/src/lib/utils/command-builder.mjs +94 -0
  38. package/src/lib/utils/exec.mjs +18 -0
  39. package/src/lib/utils/generator-loader.mjs +65 -0
  40. package/src/lib/utils/index.mjs +1 -0
  41. package/src/lib/utils/java-home.mjs +55 -0
  42. package/src/lib/utils/logger.mjs +0 -0
  43. package/src/lib/utils/nx-context.mjs +395 -0
  44. package/src/lib/utils/prompts.mjs +75 -0
  45. package/src/lib/utils/studio-home.mjs +12 -0
  46. package/src/lib/utils/utils.mjs +126 -0
  47. package/src/lib/utils/validators.mjs +10 -0
@@ -0,0 +1,55 @@
1
+ import { execSync } from "child_process";
2
+ import { platform } from "os";
3
+ import { join } from "path";
4
+
5
+ export function findJavaHome() {
6
+ const os = platform();
7
+
8
+ if (os === "win32") {
9
+ return findJavaHomeWindows();
10
+ } else if (os === "darwin" || os === "linux") {
11
+ return findJavaHomeUnix();
12
+ } else {
13
+ throw new Error("Unsupported operating system: " + os);
14
+ }
15
+ }
16
+
17
+ function findJavaHomeWindows() {
18
+ try {
19
+ const output = execSync(
20
+ 'reg query "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JDK" /s /v JavaHome'
21
+ );
22
+ const match = /JavaHome\s+REG_SZ\s+(.*)/i.exec(output.toString());
23
+ if (match && match[1]) {
24
+ return match[1].trim();
25
+ }
26
+ } catch (error) {
27
+ console.error("Unable to find Java home directory:", error);
28
+ }
29
+
30
+ return undefined;
31
+ }
32
+
33
+ function findJavaHomeUnix() {
34
+ try {
35
+ const output = execSync(
36
+ "echo $(dirname $(dirname $(readlink -f $(which javac))))"
37
+ );
38
+ if (output) {
39
+ return output.toString().trim();
40
+ }
41
+ } catch (error) {
42
+ console.error("Unable to find Java home directory:", error);
43
+ }
44
+
45
+ return undefined;
46
+ }
47
+
48
+ export function findJavaExecutable() {
49
+ const javaHome = findJavaHome();
50
+ const javaExecutable =
51
+ platform() === "darwin"
52
+ ? join(javaHome || "", "bin", "java")
53
+ : join(javaHome || "", "bin", "java.exe");
54
+ return javaExecutable;
55
+ }
File without changes
@@ -0,0 +1,395 @@
1
+ // utils/nx-context.mjs
2
+ import { execSync } from "child_process";
3
+ import { existsSync, readFileSync, readdirSync, statSync } from "fs";
4
+ import path from "path";
5
+ import { fileURLToPath } from "url";
6
+ import { getCached, setCached } from "./cache.mjs";
7
+
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+
10
+ function execJson(cmd) {
11
+ const output = execSync(cmd, { encoding: "utf-8" });
12
+ return JSON.parse(output);
13
+ }
14
+
15
+ function findKosJsonFiles(dir = process.cwd(), files = []) {
16
+ try {
17
+ const entries = readdirSync(dir);
18
+
19
+ for (const entry of entries) {
20
+ // Skip common directories that won't have .kos.json files
21
+ // BUT don't skip .kos.json files themselves!
22
+ if (entry === 'node_modules' || entry === '.git' || entry === '.nx' ||
23
+ entry === 'dist' || entry === 'coverage' || entry === '.vscode' ||
24
+ entry === '.idea' || (entry.startsWith('.') && entry !== '.kos.json')) {
25
+ continue;
26
+ }
27
+
28
+ const fullPath = path.join(dir, entry);
29
+
30
+ try {
31
+ const stat = statSync(fullPath);
32
+
33
+ if (stat.isFile() && entry === '.kos.json') {
34
+ files.push(fullPath);
35
+ } else if (stat.isDirectory()) {
36
+ // Only recurse into directories that might contain projects
37
+ // Skip common build/temp directories
38
+ if (entry !== 'tmp' && entry !== 'temp' && entry !== 'build') {
39
+ findKosJsonFiles(fullPath, files);
40
+ }
41
+ }
42
+ } catch (error) {
43
+ // Skip files/directories we can't access
44
+ continue;
45
+ }
46
+ }
47
+ } catch (error) {
48
+ // Skip directories we can't read
49
+ }
50
+
51
+ return files;
52
+ }
53
+
54
+ let _workspaceDetected;
55
+
56
+ export async function detectWorkspace(startDir = process.cwd()) {
57
+ if (_workspaceDetected !== undefined) return _workspaceDetected;
58
+
59
+ let dir = startDir;
60
+ while (dir !== path.dirname(dir)) {
61
+ if (existsSync(path.join(dir, "nx.json"))) {
62
+ _workspaceDetected = true;
63
+ return true;
64
+ }
65
+ dir = path.dirname(dir);
66
+ }
67
+
68
+ _workspaceDetected = false;
69
+ return false;
70
+ }
71
+ export async function getAllProjects() {
72
+ const cached = getCached("allProjects");
73
+ if (cached) return cached;
74
+
75
+ const projects = execJson("npx nx show projects --all --json").map((p) => p);
76
+ setCached("allProjects", projects);
77
+ return projects;
78
+ }
79
+
80
+ export async function getLibraryProjects() {
81
+ const cached = getCached("libraryProjects");
82
+ if (cached) return cached;
83
+
84
+ const projects = execJson("npx nx show projects --type=lib --json").map(
85
+ (p) => p
86
+ );
87
+ setCached("libraryProjects", projects);
88
+ return projects;
89
+ }
90
+
91
+ export async function getPluginProjects() {
92
+ const cached = getCached("pluginProjects");
93
+ if (cached) return cached;
94
+
95
+ const all = await getAllProjects();
96
+ const filtered = all.filter(
97
+ (p) => p.includes("plugin") || p.includes("extension")
98
+ );
99
+ setCached("pluginProjects", filtered);
100
+ return filtered;
101
+ }
102
+
103
+ export async function getAllKosProjects() {
104
+ const cached = getCached("allKosProjects");
105
+ if (cached) return cached;
106
+
107
+ if (process.env.KOS_CLI_QUIET !== "true") {
108
+ console.warn(`[kos-cli] Discovering KOS projects by scanning .kos.json files...`);
109
+ }
110
+
111
+ // In an NX workspace, focus on common project directories first
112
+ const projectDirs = ['apps', 'libs', 'packages'];
113
+ const kosJsonFiles = [];
114
+ const workspaceRoot = process.cwd();
115
+
116
+ // First scan common project directories
117
+ for (const dir of projectDirs) {
118
+ const dirPath = path.join(workspaceRoot, dir);
119
+ if (existsSync(dirPath)) {
120
+ findKosJsonFiles(dirPath, kosJsonFiles);
121
+ }
122
+ }
123
+
124
+ // Also check the workspace root for any .kos.json files
125
+ const rootKosJson = path.join(workspaceRoot, '.kos.json');
126
+ if (existsSync(rootKosJson)) {
127
+ kosJsonFiles.push(rootKosJson);
128
+ }
129
+
130
+ // If we didn't find any in the common directories, fall back to full scan
131
+ if (kosJsonFiles.length === 0) {
132
+ if (process.env.KOS_CLI_QUIET !== "true") {
133
+ console.warn(`[kos-cli] No .kos.json files found in common directories, performing full workspace scan...`);
134
+ }
135
+ findKosJsonFiles(workspaceRoot, kosJsonFiles);
136
+ }
137
+
138
+ const kosProjects = [];
139
+
140
+ for (const kosJsonPath of kosJsonFiles) {
141
+ try {
142
+ const kosConfig = JSON.parse(readFileSync(kosJsonPath, "utf-8"));
143
+ const projectDir = path.dirname(kosJsonPath);
144
+
145
+ // Try to determine the project name by looking for project.json
146
+ let projectName = null;
147
+ const projectJsonPath = path.join(projectDir, 'project.json');
148
+
149
+ if (existsSync(projectJsonPath)) {
150
+ try {
151
+ const projectJson = JSON.parse(readFileSync(projectJsonPath, "utf-8"));
152
+ projectName = projectJson.name;
153
+ } catch (error) {
154
+ // If we can't read project.json, use directory name as fallback
155
+ projectName = path.basename(projectDir);
156
+ }
157
+ } else {
158
+ // Use directory name as fallback
159
+ projectName = path.basename(projectDir);
160
+ }
161
+
162
+ // Skip root-type configurations as they are not projects
163
+ if (kosConfig.type === 'root') {
164
+ continue;
165
+ }
166
+
167
+ kosProjects.push({
168
+ name: projectName,
169
+ path: projectDir,
170
+ kosJsonPath,
171
+ config: kosConfig,
172
+ projectType: kosConfig.generator?.projectType
173
+ });
174
+ } catch (error) {
175
+ console.warn(`[kos-cli] Error reading ${kosJsonPath}: ${error.message}`);
176
+ }
177
+ }
178
+
179
+ setCached("allKosProjects", kosProjects);
180
+ return kosProjects;
181
+ }
182
+
183
+ export async function getProjectsByType(targetType) {
184
+ const cacheKey = `projectsByType:${targetType}`;
185
+ const cached = getCached(cacheKey);
186
+ if (cached) return cached;
187
+
188
+ if (process.env.KOS_CLI_QUIET !== "true") {
189
+ console.warn(`[kos-cli] Filtering projects for ${targetType} projectType...`);
190
+ }
191
+ const allKosProjects = await getAllKosProjects();
192
+ const filteredProjects = [];
193
+
194
+ for (const kosProject of allKosProjects) {
195
+ const projectType = kosProject.projectType;
196
+
197
+ // Handle both string and array formats for projectType
198
+ const hasTargetType = Array.isArray(projectType)
199
+ ? projectType.includes(targetType)
200
+ : projectType === targetType;
201
+
202
+ if (hasTargetType) {
203
+ filteredProjects.push(kosProject.name);
204
+ }
205
+ }
206
+
207
+ setCached(cacheKey, filteredProjects);
208
+ return filteredProjects;
209
+ }
210
+
211
+ export async function getModelProjects() {
212
+ return await getProjectsByType("model");
213
+ }
214
+
215
+ export async function getUIProjects() {
216
+ return await getProjectsByType("ui");
217
+ }
218
+
219
+ export async function getModelComponentProjects() {
220
+ return await getProjectsByType("model-component");
221
+ }
222
+
223
+ export async function getI18nProjects() {
224
+ return await getProjectsByType("i18n");
225
+ }
226
+
227
+
228
+ export async function getProjectsByTypeWithFallback(targetType, fallbackFunction = getLibraryProjects) {
229
+ const filteredProjects = await getProjectsByType(targetType);
230
+
231
+ if (filteredProjects.length > 0) {
232
+ if (process.env.KOS_CLI_QUIET !== "true") {
233
+ console.warn(`[kos-cli] Found ${filteredProjects.length} ${targetType} projects`);
234
+ }
235
+ return filteredProjects;
236
+ } else {
237
+ if (process.env.KOS_CLI_QUIET !== "true") {
238
+ console.warn(`[kos-cli] No ${targetType} projects found, showing fallback projects`);
239
+ }
240
+ return await fallbackFunction();
241
+ }
242
+ }
243
+
244
+ export async function getModelProjectsWithFallback() {
245
+ return await getProjectsByTypeWithFallback("model", getLibraryProjects);
246
+ }
247
+
248
+ export async function getModelComponentProjectsWithFallback() {
249
+ return await getProjectsByTypeWithFallback("model-component", getAllProjects);
250
+ }
251
+
252
+ export async function getProjectsByMultipleTypes(targetTypes) {
253
+ const cacheKey = `projectsByMultipleTypes:${targetTypes.join(',')}`;
254
+ const cached = getCached(cacheKey);
255
+ if (cached) return cached;
256
+
257
+ console.warn(`[kos-cli] Filtering projects for projectTypes: ${targetTypes.join(', ')}...`);
258
+ const allKosProjects = await getAllKosProjects();
259
+ const filteredProjects = [];
260
+
261
+ for (const kosProject of allKosProjects) {
262
+ const projectType = kosProject.projectType;
263
+
264
+ // Handle both string and array formats for projectType
265
+ const hasAnyTargetType = targetTypes.some(targetType => {
266
+ return Array.isArray(projectType)
267
+ ? projectType.includes(targetType)
268
+ : projectType === targetType;
269
+ });
270
+
271
+ if (hasAnyTargetType) {
272
+ filteredProjects.push(kosProject.name);
273
+ }
274
+ }
275
+
276
+ setCached(cacheKey, filteredProjects);
277
+ return filteredProjects;
278
+ }
279
+
280
+ export async function getComponentCompatibleProjects() {
281
+ return await getProjectsByMultipleTypes(["ui", "splash", "model-component"]);
282
+ }
283
+
284
+ export async function getComponentCompatibleProjectsWithFallback() {
285
+ const componentProjects = await getComponentCompatibleProjects();
286
+
287
+ if (componentProjects.length > 0) {
288
+ if (process.env.KOS_CLI_QUIET !== "true") {
289
+ console.warn(`[kos-cli] Found ${componentProjects.length} component-compatible projects`);
290
+ }
291
+ return componentProjects;
292
+ } else {
293
+ if (process.env.KOS_CLI_QUIET !== "true") {
294
+ console.warn(`[kos-cli] No component-compatible projects found, showing all projects`);
295
+ }
296
+ return await getAllProjects();
297
+ }
298
+ }
299
+
300
+ export async function getI18nProjectsWithFallback() {
301
+ return await getProjectsByTypeWithFallback("i18n", getAllProjects);
302
+ }
303
+
304
+ export async function getPluginProjectsWithFallback() {
305
+ // First try type-based filtering
306
+ const pluginProjectsByType = await getProjectsByType("plugin");
307
+ if (pluginProjectsByType.length > 0) {
308
+ if (process.env.KOS_CLI_QUIET !== "true") {
309
+ console.warn(`[kos-cli] Found ${pluginProjectsByType.length} plugin projects by type`);
310
+ }
311
+ return pluginProjectsByType;
312
+ }
313
+
314
+ // Fall back to existing name-based filtering
315
+ const pluginProjectsByName = await getPluginProjects();
316
+ if (pluginProjectsByName.length > 0) {
317
+ if (process.env.KOS_CLI_QUIET !== "true") {
318
+ console.warn(`[kos-cli] Found ${pluginProjectsByName.length} plugin projects by name`);
319
+ }
320
+ return pluginProjectsByName;
321
+ }
322
+
323
+ // Final fallback to all projects
324
+ console.warn(`[kos-cli] No plugin projects found, showing all projects`);
325
+ return await getAllProjects();
326
+ }
327
+
328
+ export async function getAllModels() {
329
+ const cached = getCached("allModels");
330
+ if (cached) return cached;
331
+
332
+ if (process.env.KOS_CLI_QUIET !== "true") {
333
+ console.warn(`[kos-cli] Scanning for models in KOS projects...`);
334
+ }
335
+ const allKosProjects = await getAllKosProjects();
336
+ const models = [];
337
+
338
+ for (const kosProject of allKosProjects) {
339
+ if (kosProject.config.models) {
340
+ Object.keys(kosProject.config.models).forEach((model) => {
341
+ models.push({ model: model, project: kosProject.name });
342
+ });
343
+ }
344
+ }
345
+
346
+ // Sort models by project name first, then by model name
347
+ models.sort((a, b) => {
348
+ if (a.project === b.project) {
349
+ return a.model.localeCompare(b.model);
350
+ } else {
351
+ return a.project.localeCompare(b.project);
352
+ }
353
+ });
354
+
355
+ setCached("allModels", models);
356
+ return models;
357
+ }
358
+
359
+ export async function getWorkspaceDefaults() {
360
+ const cached = getCached("workspaceDefaults");
361
+ if (cached) return cached;
362
+
363
+ const workspaceRoot = process.cwd();
364
+ const rootKosJsonPath = path.join(workspaceRoot, '.kos.json');
365
+
366
+ if (existsSync(rootKosJsonPath)) {
367
+ try {
368
+ const rootConfig = JSON.parse(readFileSync(rootKosJsonPath, "utf-8"));
369
+ if (rootConfig.type === 'root' && rootConfig.generator?.defaults) {
370
+ setCached("workspaceDefaults", rootConfig.generator.defaults);
371
+ return rootConfig.generator.defaults;
372
+ }
373
+ } catch (error) {
374
+ console.warn(`[kos-cli] Error reading workspace defaults: ${error.message}`);
375
+ }
376
+ }
377
+
378
+ setCached("workspaceDefaults", {});
379
+ return {};
380
+ }
381
+
382
+ export async function getDefaultProjectForType(projectType) {
383
+ const defaults = await getWorkspaceDefaults();
384
+ return defaults[projectType] || null;
385
+ }
386
+
387
+ export async function getProjectDetails(projectName) {
388
+ const cacheKey = `projectDetails:${projectName}`;
389
+ const cached = getCached(cacheKey);
390
+ if (cached) return cached;
391
+
392
+ const details = execJson(`npx nx show project ${projectName} --json`);
393
+ setCached(cacheKey, details);
394
+ return details;
395
+ }
@@ -0,0 +1,75 @@
1
+ // utils/prompts.mjs
2
+
3
+ export const DEFAULT_PROMPTS = [
4
+ {
5
+ type: "confirm",
6
+ name: "interactive",
7
+ message: "Use interactive mode?",
8
+ default: false,
9
+ when: false,
10
+ },
11
+ {
12
+ type: "confirm",
13
+ name: "dryRun",
14
+ message: "Dry run the command?",
15
+ default: false,
16
+ when: false,
17
+ },
18
+ ];
19
+
20
+ export const MODEL_PROMPTS = [
21
+ {
22
+ type: "confirm",
23
+ name: "container",
24
+ message: "Requires container model?",
25
+ default: false,
26
+ },
27
+ {
28
+ type: "confirm",
29
+ name: "parentAware",
30
+ message: "Aware of parent container?",
31
+ default: false,
32
+ },
33
+ {
34
+ type: "confirm",
35
+ name: "singleton",
36
+ message: "Is singleton?",
37
+ default: false,
38
+ },
39
+ {
40
+ type: "confirm",
41
+ name: "dataServices",
42
+ message: "Create data services?",
43
+ default: true,
44
+ },
45
+ {
46
+ type: "list",
47
+ name: "futureAware",
48
+ message: "Include Future-aware capabilities?",
49
+ choices: [
50
+ { name: "No Future support", value: "none" },
51
+ { name: "Minimal (external access only)", value: "minimal" },
52
+ { name: "Complete (internal + external access)", value: "complete" },
53
+ ],
54
+ default: "none",
55
+ },
56
+ ];
57
+
58
+ export const COMPANION_PROMPTS = [
59
+ {
60
+ type: "list",
61
+ name: "companionPattern",
62
+ message: "Which companion pattern to use?",
63
+ choices: [
64
+ {
65
+ name: "Composition (recommended) - explicit parent access via this.parent",
66
+ value: "composition",
67
+ },
68
+ {
69
+ name: "Decorator - transparent parent access, drop-in replacement",
70
+ value: "decorator",
71
+ },
72
+ ],
73
+ default: "composition",
74
+ },
75
+ ];
@@ -0,0 +1,12 @@
1
+ import os from "os";
2
+ import { join } from "path";
3
+ export const findStudioHome = () => {
4
+ const homeDir = os.homedir();
5
+
6
+ const installDir =
7
+ os.platform() === "darwin"
8
+ ? join(homeDir, "Applications", "kosStudio.app")
9
+ : join(homeDir, "AppData", "Local", "kosStudio");
10
+
11
+ return installDir;
12
+ };
@@ -0,0 +1,126 @@
1
+ import { exec, execSync, spawn } from "child_process";
2
+ import { readFile, readdir } from "fs/promises";
3
+ import path from "path";
4
+
5
+ export async function getAllModels() {
6
+ console.log(`parsing projects for models...`);
7
+ const allProjects = await getAllProjects();
8
+ const models = await allProjects.reduce(async (acc, curr) => {
9
+ const project = await getProjectDetails(curr);
10
+ const list = await acc;
11
+
12
+ const config = await readdir(project.root, { withFileTypes: true });
13
+ if (config.find((dirent) => dirent.name === ".kos.json")) {
14
+ const kosConfig = JSON.parse(
15
+ await readFile(path.join(project.root, ".kos.json"), "utf-8")
16
+ );
17
+ if (kosConfig.models) {
18
+ Object.keys(kosConfig.models).forEach((model) => {
19
+ list.push({ model: model, project: project.name });
20
+ });
21
+ }
22
+ }
23
+ return list.sort((a, b) => {
24
+ if (a.project === b.project) {
25
+ return a.model.localeCompare(b.model);
26
+ } else {
27
+ return a.project.localeCompare(b.project);
28
+ }
29
+ });
30
+ }, []);
31
+ return models;
32
+ }
33
+ export async function getAllProjects() {
34
+ return new Promise((resolve, reject) => {
35
+ exec("npx nx show projects --json", (error, stdout, stderr) => {
36
+ if (error) {
37
+ reject(error);
38
+ }
39
+ if (stderr) {
40
+ reject(stderr);
41
+ }
42
+ resolve(JSON.parse(stdout).sort((a, b) => a.localeCompare(b)));
43
+ });
44
+ });
45
+ }
46
+
47
+ export function getLibraryProjects() {
48
+ const projects = execSync("npx nx show projects --type lib --json");
49
+ return JSON.parse(projects).sort((a, b) => a.localeCompare(b));
50
+ }
51
+
52
+ export function getPluginProjects() {
53
+ const internal = !!process.env.INTERNAL;
54
+ const filter = internal ? "*plugin*" : "plugins/*";
55
+ const projects = execSync(
56
+ `npx nx show projects --projects "${filter}" --json`
57
+ );
58
+ return JSON.parse(projects);
59
+ }
60
+
61
+ export async function getProjectDetails(project) {
62
+ return new Promise((resolve, reject) => {
63
+ exec(`npx nx show project ${project} --json`, (error, stdout, stderr) => {
64
+ if (error) {
65
+ reject(error);
66
+ }
67
+ if (stderr) {
68
+ reject(stderr);
69
+ }
70
+ resolve(JSON.parse(stdout));
71
+ });
72
+ });
73
+ }
74
+
75
+ export function interactive(answers) {
76
+ return answers.interactive;
77
+ }
78
+
79
+ export function required(value) {
80
+ if (/.+/.test(value)) {
81
+ return true;
82
+ }
83
+ return false;
84
+ }
85
+
86
+ export async function execute(commandString) {
87
+ return new Promise((resolve, reject) => {
88
+ const [command, ...commandArguments] = commandString.split(" ");
89
+ const child = spawn(command, commandArguments, {
90
+ shell: true,
91
+ });
92
+
93
+ child.on("message", (message) => {
94
+ console.log(message);
95
+ });
96
+
97
+ child.stdout.on("data", (data) => {
98
+ console.log(`${data}`);
99
+ });
100
+
101
+ child.stderr.on("data", (data) => {
102
+ // console.info(`ERROR:${data}`);
103
+ });
104
+ child.on("exit", function (code, signal) {
105
+ console.log(`process exited with code ${code}`);
106
+ if (code === 0) {
107
+ resolve("success");
108
+ } else {
109
+ reject("failure");
110
+ }
111
+ });
112
+ });
113
+ }
114
+
115
+ export async function workspaceModels() {
116
+ const allModels = await getAllModels();
117
+ const workspaceModels = allModels.map((model) => {
118
+ return model.model;
119
+ });
120
+ return workspaceModels;
121
+ }
122
+
123
+ export async function detectWorkspace() {
124
+ const files = await readdir(process.cwd(), { withFileTypes: true });
125
+ return files.find((file) => file.name === "nx.json");
126
+ }
@@ -0,0 +1,10 @@
1
+ // utils/validators.mjs
2
+
3
+ /**
4
+ * Validator that ensures a value is not empty.
5
+ * @param {string} value
6
+ * @returns {true|string}
7
+ */
8
+ export function required(value) {
9
+ return value && value.trim() !== "" ? true : "This field is required.";
10
+ }