@kosdev-code/kos-ui-cli 2.1.39 → 3.0.1

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.
@@ -1,61 +1,1123 @@
1
- // generators/model/context.mjs
2
- import { actionFactory } from "../../utils/action-factory.mjs";
3
- import { execute } from "../../utils/exec.mjs";
4
- import { getAllModels, getAllProjects } from "../../utils/nx-context.mjs";
5
- export const metadata = {
1
+ // ../kos-codegen-core/src/lib/codegen-filesystem.ts
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ var TrackingFileSystem = class {
5
+ inner;
6
+ _writtenPaths = [];
7
+ constructor(inner) {
8
+ this.inner = inner;
9
+ }
10
+ get root() {
11
+ return this.inner.root;
12
+ }
13
+ get writtenPaths() {
14
+ return [...this._writtenPaths];
15
+ }
16
+ read(filePath) {
17
+ return this.inner.read(filePath);
18
+ }
19
+ write(filePath, content) {
20
+ this.inner.write(filePath, content);
21
+ this._writtenPaths.push(
22
+ path.isAbsolute(filePath) ? filePath : path.join(this.inner.root, filePath)
23
+ );
24
+ }
25
+ exists(filePath) {
26
+ return this.inner.exists(filePath);
27
+ }
28
+ delete(filePath) {
29
+ this.inner.delete(filePath);
30
+ }
31
+ listFiles(dirPath) {
32
+ return this.inner.listFiles(dirPath);
33
+ }
34
+ };
35
+ var DirectFileSystem = class {
36
+ root;
37
+ constructor(workspaceRoot) {
38
+ this.root = path.resolve(workspaceRoot);
39
+ }
40
+ read(filePath) {
41
+ const abs = this.resolve(filePath);
42
+ try {
43
+ return fs.readFileSync(abs, "utf-8");
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+ write(filePath, content) {
49
+ const abs = this.resolve(filePath);
50
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
51
+ fs.writeFileSync(abs, content, "utf-8");
52
+ }
53
+ exists(filePath) {
54
+ return fs.existsSync(this.resolve(filePath));
55
+ }
56
+ delete(filePath) {
57
+ const abs = this.resolve(filePath);
58
+ try {
59
+ fs.unlinkSync(abs);
60
+ } catch {
61
+ }
62
+ }
63
+ listFiles(dirPath) {
64
+ const abs = this.resolve(dirPath);
65
+ if (!fs.existsSync(abs)) {
66
+ return [];
67
+ }
68
+ return this.walkDir(abs).map((file) => path.relative(this.root, file));
69
+ }
70
+ resolve(filePath) {
71
+ if (path.isAbsolute(filePath)) {
72
+ return filePath;
73
+ }
74
+ return path.join(this.root, filePath);
75
+ }
76
+ walkDir(dir) {
77
+ const results = [];
78
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
79
+ for (const entry of entries) {
80
+ const full = path.join(dir, entry.name);
81
+ if (entry.isDirectory()) {
82
+ results.push(...this.walkDir(full));
83
+ } else {
84
+ results.push(full);
85
+ }
86
+ }
87
+ return results;
88
+ }
89
+ };
90
+
91
+ // ../kos-codegen-core/src/lib/generate-files.ts
92
+ import * as fs2 from "fs";
93
+ import * as path2 from "path";
94
+ import * as ejs from "ejs";
95
+
96
+ // ../kos-codegen-core/src/lib/logger.ts
97
+ var noopLogger = {
98
+ debug: () => {
99
+ },
100
+ info: () => {
101
+ },
102
+ warn: () => {
103
+ },
104
+ error: () => {
105
+ }
106
+ };
107
+ var activeLogger = noopLogger;
108
+ function getCodegenLogger() {
109
+ return activeLogger;
110
+ }
111
+
112
+ // ../kos-codegen-core/src/lib/generate-files.ts
113
+ function generateFilesFromTemplates(codegenFs, srcFolder, destFolder, substitutions) {
114
+ const logger = getCodegenLogger();
115
+ const templateFiles = walkTemplateDir(srcFolder);
116
+ for (const templateFile of templateFiles) {
117
+ const relPath = path2.relative(srcFolder, templateFile);
118
+ let destRelPath = interpolateFilename(relPath, substitutions);
119
+ if (destRelPath.endsWith(".template")) {
120
+ destRelPath = destRelPath.slice(0, -".template".length);
121
+ }
122
+ const destPath = path2.join(destFolder, destRelPath);
123
+ const rawContent = fs2.readFileSync(templateFile, "utf-8");
124
+ const rendered = ejs.render(rawContent, substitutions, {
125
+ filename: templateFile
126
+ // for EJS error messages and includes
127
+ });
128
+ logger.debug(`Generating ${destPath}`);
129
+ codegenFs.write(destPath, rendered);
130
+ }
131
+ }
132
+ function interpolateFilename(filePath, substitutions) {
133
+ return filePath.replace(/__([^_]+)__/g, (match, key) => {
134
+ if (key in substitutions) {
135
+ return String(substitutions[key]);
136
+ }
137
+ return match;
138
+ });
139
+ }
140
+ function walkTemplateDir(dir) {
141
+ const results = [];
142
+ const entries = fs2.readdirSync(dir, { withFileTypes: true });
143
+ for (const entry of entries) {
144
+ const full = path2.join(dir, entry.name);
145
+ if (entry.isDirectory()) {
146
+ results.push(...walkTemplateDir(full));
147
+ } else {
148
+ results.push(full);
149
+ }
150
+ }
151
+ return results;
152
+ }
153
+
154
+ // ../kos-codegen-core/src/lib/project-discovery.ts
155
+ import * as fs3 from "fs";
156
+ import * as path3 from "path";
157
+ import fg from "fast-glob";
158
+ function discoverProjects(workspaceRoot) {
159
+ const logger = getCodegenLogger();
160
+ const projects = /* @__PURE__ */ new Map();
161
+ const projectJsonPaths = fg.sync("**/project.json", {
162
+ cwd: workspaceRoot,
163
+ ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"],
164
+ absolute: false
165
+ });
166
+ for (const relPath of projectJsonPaths) {
167
+ const absPath = path3.join(workspaceRoot, relPath);
168
+ try {
169
+ const raw = fs3.readFileSync(absPath, "utf-8");
170
+ const json = JSON.parse(raw);
171
+ const projectRoot = path3.dirname(relPath);
172
+ const name = json.name ?? path3.basename(projectRoot);
173
+ const config = {
174
+ name,
175
+ root: projectRoot,
176
+ sourceRoot: json.sourceRoot ?? path3.join(projectRoot, "src"),
177
+ projectType: json.projectType,
178
+ targets: json.targets,
179
+ tags: json.tags
180
+ };
181
+ projects.set(name, config);
182
+ logger.debug(`Discovered project: ${name} at ${projectRoot}`);
183
+ } catch (err) {
184
+ logger.warn(`Failed to parse ${absPath}: ${err}`);
185
+ }
186
+ }
187
+ logger.info(`Discovered ${projects.size} projects`);
188
+ return projects;
189
+ }
190
+ function findProjectByName(workspaceRoot, projectName, projects) {
191
+ const map = projects ?? discoverProjects(workspaceRoot);
192
+ return map.get(projectName);
193
+ }
194
+ function findProjectForPath(workspaceRoot, filePath) {
195
+ const resolved = path3.resolve(workspaceRoot);
196
+ let dir = path3.dirname(path3.resolve(filePath));
197
+ while (dir.startsWith(resolved) && dir !== resolved) {
198
+ const projectJsonPath = path3.join(dir, "project.json");
199
+ if (fs3.existsSync(projectJsonPath)) {
200
+ try {
201
+ const raw = fs3.readFileSync(projectJsonPath, "utf-8");
202
+ const json = JSON.parse(raw);
203
+ const projectRoot = path3.relative(resolved, dir);
204
+ const name = json.name ?? path3.basename(dir);
205
+ return {
206
+ name,
207
+ root: projectRoot,
208
+ sourceRoot: json.sourceRoot ?? path3.join(projectRoot, "src"),
209
+ projectType: json.projectType,
210
+ targets: json.targets,
211
+ tags: json.tags
212
+ };
213
+ } catch {
214
+ return void 0;
215
+ }
216
+ }
217
+ dir = path3.dirname(dir);
218
+ }
219
+ return void 0;
220
+ }
221
+
222
+ // ../kos-codegen-core/src/lib/json-utils.ts
223
+ function readJson(codegenFs, filePath) {
224
+ const content = codegenFs.read(filePath);
225
+ if (content === null) {
226
+ throw new Error(`File not found: ${filePath}`);
227
+ }
228
+ return JSON.parse(content);
229
+ }
230
+
231
+ // ../kos-codegen-core/src/lib/format-files.ts
232
+ import * as fs4 from "fs";
233
+ import * as path4 from "path";
234
+ import prettier from "prettier";
235
+ var FORMATTABLE_EXTENSIONS = /* @__PURE__ */ new Set([
236
+ ".ts",
237
+ ".tsx",
238
+ ".js",
239
+ ".jsx",
240
+ ".json",
241
+ ".css",
242
+ ".scss",
243
+ ".md",
244
+ ".yaml",
245
+ ".yml",
246
+ ".html"
247
+ ]);
248
+ async function formatFiles(workspaceRoot, filePaths) {
249
+ const logger = getCodegenLogger();
250
+ for (const filePath of filePaths) {
251
+ const ext = path4.extname(filePath);
252
+ if (!FORMATTABLE_EXTENSIONS.has(ext)) {
253
+ continue;
254
+ }
255
+ try {
256
+ const content = fs4.readFileSync(filePath, "utf-8");
257
+ const options = await prettier.resolveConfig(filePath, {
258
+ editorconfig: true
259
+ });
260
+ const formatted = await prettier.format(content, {
261
+ ...options,
262
+ filepath: filePath
263
+ });
264
+ fs4.writeFileSync(filePath, formatted, "utf-8");
265
+ logger.debug(`Formatted ${path4.relative(workspaceRoot, filePath)}`);
266
+ } catch (err) {
267
+ logger.warn(`Failed to format ${filePath}: ${err}`);
268
+ }
269
+ }
270
+ }
271
+
272
+ // ../kos-codegen-core/src/lib/name-utils.ts
273
+ function dashCase(input) {
274
+ return input.replace(/\s+/g, "-").replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
275
+ }
276
+ function camelCase(input) {
277
+ if (input.length === 0)
278
+ return "";
279
+ const words = input.split(/-|\s+/);
280
+ if (words.length > 0 && words[0].length > 0) {
281
+ words[0] = words[0].charAt(0).toLowerCase() + words[0].slice(1);
282
+ }
283
+ for (let i = 1; i < words.length; i++) {
284
+ words[i] = words[i].charAt(0).toUpperCase() + words[i].slice(1);
285
+ }
286
+ return words.join("");
287
+ }
288
+ function pascalCase(input) {
289
+ if (input.length === 0)
290
+ return "";
291
+ const cc = camelCase(input);
292
+ return cc[0].toUpperCase() + cc.slice(1);
293
+ }
294
+ function properCase(input) {
295
+ const words = input.toLowerCase().replaceAll("-", " ").split(" ").filter(Boolean);
296
+ for (let i = 0; i < words.length; i++) {
297
+ words[i] = words[i][0].toUpperCase() + words[i].slice(1);
298
+ }
299
+ return words.join("");
300
+ }
301
+ function constantCase(input) {
302
+ if (input.length === 0)
303
+ return "";
304
+ return input.toUpperCase().split(/[\s-]+/).filter(Boolean).join("_");
305
+ }
306
+
307
+ // ../kos-codegen-core/src/lib/normalize-values.ts
308
+ var normalizeValue = (optionsName, value) => ({
309
+ [`${camelCase(optionsName)}CamelCase`]: camelCase(value),
310
+ [`${camelCase(optionsName)}ConstantCase`]: constantCase(value),
311
+ [`${camelCase(optionsName)}DashCase`]: dashCase(value),
312
+ [`${camelCase(optionsName)}PascalCase`]: pascalCase(value),
313
+ [`${camelCase(optionsName)}ProperCase`]: properCase(value),
314
+ [`${camelCase(optionsName)}LowerCase`]: value.toLowerCase(),
315
+ [`${optionsName}`]: value
316
+ });
317
+ var normalizeAllValues = (options) => {
318
+ let normalizedValues = {};
319
+ for (const key in options) {
320
+ if (Object.prototype.hasOwnProperty.call(options, key)) {
321
+ const element = options[key];
322
+ const newOptions = typeof element !== "string" || element === "" ? { [key]: element } : normalizeValue(key, element);
323
+ normalizedValues = {
324
+ ...normalizedValues,
325
+ ...newOptions
326
+ };
327
+ }
328
+ }
329
+ return normalizedValues;
330
+ };
331
+
332
+ // ../kos-codegen-core/src/lib/kos-config.ts
333
+ import * as path5 from "path";
334
+ function getCurrentDirectoryName(cwd) {
335
+ return cwd.split("/").pop();
336
+ }
337
+ function getProject(codegenFs, cwd) {
338
+ return findProjectForPath(codegenFs.root, cwd);
339
+ }
340
+ function getKosProjectConfiguration(codegenFs, projectName, projects) {
341
+ const project = findProjectByName(codegenFs.root, projectName, projects);
342
+ if (!project)
343
+ return void 0;
344
+ const configPath = path5.join(project.root, ".kos.json");
345
+ if (!codegenFs.exists(configPath)) {
346
+ const defaultConfig = {
347
+ name: `${dashCase(projectName)}-model`,
348
+ type: "kos.model",
349
+ version: "0.1.0",
350
+ models: {},
351
+ generator: { defaults: { model: { folder: "" } } }
352
+ };
353
+ codegenFs.write(configPath, JSON.stringify(defaultConfig, null, 2));
354
+ }
355
+ const content = codegenFs.read(configPath);
356
+ return content ? JSON.parse(content) : void 0;
357
+ }
358
+ function getKosModelConfiguration(codegenFs, projectName, modelName, projects) {
359
+ const kosConfig = getKosProjectConfiguration(
360
+ codegenFs,
361
+ projectName,
362
+ projects
363
+ );
364
+ return kosConfig?.models?.[modelName];
365
+ }
366
+ function getKosModelConfigProp(params) {
367
+ const config = getKosModelConfiguration(
368
+ params.codegenFs,
369
+ params.project,
370
+ params.modelName,
371
+ params.projects
372
+ );
373
+ return config ? config[params.prop] : void 0;
374
+ }
375
+
376
+ // ../kos-codegen-core/src/lib/template-resolver.ts
377
+ import * as path6 from "path";
378
+ import * as fs5 from "fs";
379
+ function findPackageRoot() {
380
+ if (process.env.KOS_TEMPLATE_BASE_DIR) {
381
+ return process.env.KOS_TEMPLATE_BASE_DIR;
382
+ }
383
+ let dir = __dirname;
384
+ while (dir !== path6.dirname(dir)) {
385
+ const pkgPath = path6.join(dir, "package.json");
386
+ if (fs5.existsSync(pkgPath)) {
387
+ try {
388
+ const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
389
+ if (pkg.name === "@kosdev-code/kos-codegen-core") {
390
+ return dir;
391
+ }
392
+ } catch {
393
+ }
394
+ }
395
+ dir = path6.dirname(dir);
396
+ }
397
+ return path6.resolve(__dirname, "..", "..");
398
+ }
399
+ function getTemplateDir(generatorName) {
400
+ return path6.join(findPackageRoot(), "templates", generatorName);
401
+ }
402
+
403
+ // ../kos-codegen-core/src/lib/generators/normalize-options.ts
404
+ import * as path7 from "path";
405
+ function normalizeOptions(codegenFs, options, projects) {
406
+ const toNormalize = {
407
+ name: options.name
408
+ };
409
+ if (options.modelName) {
410
+ toNormalize.modelName = options.modelName;
411
+ }
412
+ if (options.companionModel) {
413
+ toNormalize.companionModel = options.companionModel;
414
+ }
415
+ const normalizedValues = normalizeAllValues(toNormalize);
416
+ const modelProject = options.modelProject;
417
+ const registrationProject = options.registrationProject || "";
418
+ const useModelProject = modelProject !== "__NONE__";
419
+ let importPath = "";
420
+ if (useModelProject) {
421
+ const modelProjectConfig = findProjectByName(
422
+ codegenFs.root,
423
+ modelProject,
424
+ projects
425
+ );
426
+ if (modelProjectConfig) {
427
+ const pkgJsonPath = path7.join(modelProjectConfig.root, "package.json");
428
+ try {
429
+ const pkgJson = readJson(codegenFs, pkgJsonPath);
430
+ importPath = pkgJson.name || "";
431
+ } catch {
432
+ importPath = "";
433
+ }
434
+ }
435
+ }
436
+ const booleanDefaults = {
437
+ companion: false,
438
+ skipRegistration: false
439
+ };
440
+ return {
441
+ ...booleanDefaults,
442
+ ...options,
443
+ ...normalizedValues,
444
+ modelProject,
445
+ importPath,
446
+ registrationProject,
447
+ template: ""
448
+ };
449
+ }
450
+
451
+ // ../kos-codegen-core/src/lib/generators/barrel-utils.ts
452
+ function appendBarrelExport(codegenFs, indexPath, exportPath) {
453
+ const exportLine = `export * from '${exportPath}'`;
454
+ const content = codegenFs.read(indexPath) ?? "";
455
+ const lines = content.split("\n");
456
+ if (lines.some((line) => line.includes(exportLine))) {
457
+ return;
458
+ }
459
+ lines.push(exportLine);
460
+ codegenFs.write(indexPath, lines.join("\n"));
461
+ }
462
+
463
+ // ../kos-codegen-core/src/lib/generators/update-model-index.ts
464
+ import * as ts from "typescript";
465
+
466
+ // ../kos-codegen-core/src/lib/generators/generate-context.ts
467
+ import * as path8 from "path";
468
+ function generateContext(codegenFs, templateDir, options, cwd, projects) {
469
+ if (!options.appProject) {
470
+ throw new Error("No app project specified");
471
+ }
472
+ const currentProject = getProject(codegenFs, cwd);
473
+ const modelProjectName = options.modelProject || currentProject?.name;
474
+ if (!modelProjectName) {
475
+ throw new Error(
476
+ "No model project found. Please specify a model project with --modelProject."
477
+ );
478
+ }
479
+ const modelName = options.name || getCurrentDirectoryName(cwd);
480
+ if (!modelName) {
481
+ throw new Error(
482
+ "No model name found. Please specify a model name with --name."
483
+ );
484
+ }
485
+ const singletonProp = getKosModelConfigProp({
486
+ codegenFs,
487
+ project: modelProjectName,
488
+ modelName,
489
+ prop: "singleton",
490
+ projects
491
+ });
492
+ options.singleton = !!singletonProp;
493
+ options.name = modelName;
494
+ options.modelProject = modelProjectName;
495
+ const normalized = normalizeOptions(codegenFs, options, projects);
496
+ const appProject = findProjectByName(
497
+ codegenFs.root,
498
+ normalized.appProject,
499
+ projects
500
+ );
501
+ if (!appProject) {
502
+ throw new Error(`App project '${normalized.appProject}' not found`);
503
+ }
504
+ const projectRoot = appProject.sourceRoot;
505
+ if (projectRoot) {
506
+ const dir = appProject.projectType === "application" || options.internal ? options.appDirectory : options.appDirectory ?? "lib";
507
+ generateFilesFromTemplates(
508
+ codegenFs,
509
+ templateDir,
510
+ path8.join(projectRoot, dir, "contexts", normalized.nameDashCase),
511
+ normalized
512
+ );
513
+ appendBarrelExport(
514
+ codegenFs,
515
+ path8.join(projectRoot, dir, "contexts", "index.ts"),
516
+ `./${normalized.nameDashCase}`
517
+ );
518
+ }
519
+ }
520
+
521
+ // ../kos-codegen-core/src/lib/generators/component/types.ts
522
+ var PLUGIN_TYPES = {
523
+ CUI: "cui",
524
+ UTILITY: "utility",
525
+ TROUBLE_ACTION: "troubleAction",
526
+ SETUP: "setup",
527
+ SETTING: "setting",
528
+ NAV: "nav",
529
+ CONTROL_POUR: "controlPour",
530
+ CUSTOM: "custom"
531
+ };
532
+ var CONTRIBUTION_TYPE_MAP = {
533
+ [PLUGIN_TYPES.SETUP]: "setup",
534
+ [PLUGIN_TYPES.CUI]: "cui",
535
+ [PLUGIN_TYPES.UTILITY]: "utility",
536
+ [PLUGIN_TYPES.SETTING]: "setting",
537
+ [PLUGIN_TYPES.NAV]: "nav",
538
+ [PLUGIN_TYPES.TROUBLE_ACTION]: "trouble-action",
539
+ [PLUGIN_TYPES.CONTROL_POUR]: "control-pour",
540
+ [PLUGIN_TYPES.CUSTOM]: "custom"
541
+ };
542
+ var LOCALIZED_PLUGIN_TYPES = /* @__PURE__ */ new Set([
543
+ PLUGIN_TYPES.CUI,
544
+ PLUGIN_TYPES.UTILITY,
545
+ PLUGIN_TYPES.SETUP,
546
+ PLUGIN_TYPES.SETTING,
547
+ PLUGIN_TYPES.NAV,
548
+ PLUGIN_TYPES.CONTROL_POUR,
549
+ PLUGIN_TYPES.TROUBLE_ACTION,
550
+ PLUGIN_TYPES.CUSTOM
551
+ ]);
552
+
553
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/base.ts
554
+ var BasePluginHandler = class {
555
+ getContributionKey() {
556
+ return this.contributionKey;
557
+ }
558
+ requiresLocalization() {
559
+ return this.requiresI18n;
560
+ }
561
+ getTemplatePath() {
562
+ return this.contributionKey;
563
+ }
564
+ /**
565
+ * Helper to create experience configuration
566
+ */
567
+ createExperience(options, experienceId) {
568
+ const compPath = this.getComponentPath(options);
569
+ return {
570
+ id: experienceId,
571
+ component: options.namePascalCase,
572
+ location: `./src/${compPath}`
573
+ };
574
+ }
575
+ /**
576
+ * Helper to get component path
577
+ */
578
+ getComponentPath(options) {
579
+ return `${options.appDirectory}/${this.contributionKey}/${options.nameDashCase}/${options.nameDashCase}.tsx`;
580
+ }
581
+ /**
582
+ * Helper to create config prefix
583
+ */
584
+ getConfigPrefix(options) {
585
+ return `${options.appProject}.${options.nameCamelCase}`;
586
+ }
587
+ };
588
+
589
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/control-pour-handler.ts
590
+ var ControlPourPluginHandler = class extends BasePluginHandler {
591
+ pluginType = PLUGIN_TYPES.CONTROL_POUR;
592
+ contributionKey = "control-pour";
593
+ requiresI18n = true;
594
+ createConfiguration(options) {
595
+ const configPrefix = this.getConfigPrefix(options);
596
+ const experienceId = `${configPrefix}.controlPour.experience`;
597
+ const contribution = {
598
+ id: `${configPrefix}.controlPour`,
599
+ title: `${configPrefix}.controlPour.title`,
600
+ namespace: options.appProject,
601
+ experienceId
602
+ };
603
+ const experience = this.createExperience(options, experienceId);
604
+ return {
605
+ contributions: {
606
+ controlPour: [contribution]
607
+ },
608
+ experiences: {
609
+ [experienceId]: experience
610
+ }
611
+ };
612
+ }
613
+ };
614
+
615
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/cui-handler.ts
616
+ var CuiPluginHandler = class extends BasePluginHandler {
617
+ pluginType = PLUGIN_TYPES.CUI;
618
+ contributionKey = "cui";
619
+ requiresI18n = true;
620
+ createConfiguration(options) {
621
+ const configPrefix = this.getConfigPrefix(options);
622
+ const experienceId = `${configPrefix}.cui.experience`;
623
+ const contribution = {
624
+ id: configPrefix,
625
+ title: `${configPrefix}.cui.title`,
626
+ namespace: options.appProject,
627
+ experienceId
628
+ };
629
+ const experience = this.createExperience(options, experienceId);
630
+ return {
631
+ contributions: {
632
+ cui: [contribution]
633
+ },
634
+ experiences: {
635
+ [experienceId]: experience
636
+ }
637
+ };
638
+ }
639
+ };
640
+
641
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/custom-handler.ts
642
+ var CustomPluginHandler = class extends BasePluginHandler {
643
+ pluginType = PLUGIN_TYPES.CUSTOM;
644
+ contributionKey = "custom";
645
+ requiresI18n = true;
646
+ createConfiguration(options) {
647
+ const configPrefix = this.getConfigPrefix(options);
648
+ const experienceId = `${configPrefix}.${options.contributionKey || "custom"}.experience`;
649
+ const userContributionKey = options.contributionKey || "custom";
650
+ const contribution = {
651
+ id: configPrefix,
652
+ title: `${configPrefix}.${userContributionKey}.title`,
653
+ namespace: options.appProject,
654
+ experienceId
655
+ // TODO: Add additional fields as required by the plugin-explorer specification
656
+ // Refer to the plugin-explorer documentation for your specific contribution type
657
+ };
658
+ const experience = this.createExperience(options, experienceId);
659
+ return {
660
+ contributions: {
661
+ [userContributionKey]: [contribution]
662
+ },
663
+ experiences: {
664
+ [experienceId]: experience
665
+ }
666
+ };
667
+ }
668
+ getTemplatePath() {
669
+ return this.contributionKey || "custom";
670
+ }
671
+ getComponentPath(options) {
672
+ const pathKey = options.contributionKey || "custom";
673
+ return `${options.appDirectory}/${pathKey}/${options.nameDashCase}/${options.nameDashCase}.tsx`;
674
+ }
675
+ };
676
+
677
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/default-handler.ts
678
+ var DefaultComponentHandler = class extends BasePluginHandler {
679
+ pluginType = "component";
680
+ contributionKey = "components";
681
+ requiresI18n = false;
682
+ createConfiguration(options) {
683
+ const compPath = this.getComponentPath(options);
684
+ const viewConfig = {
685
+ id: `${options.appProject}.${options.nameCamelCase}`,
686
+ title: "ddk.ncui.config.title",
687
+ namespace: options.appProject,
688
+ component: options.namePascalCase,
689
+ location: `./src/${compPath}`
690
+ };
691
+ return {
692
+ contributions: {},
693
+ experiences: {},
694
+ views: {
695
+ [this.getTabViewKey()]: [viewConfig]
696
+ }
697
+ };
698
+ }
699
+ getTabViewKey() {
700
+ return "ddk.ncui.settings.tabView";
701
+ }
702
+ getTemplatePath() {
703
+ return "files";
704
+ }
705
+ };
706
+
707
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/nav-handler.ts
708
+ var NavPluginHandler = class extends BasePluginHandler {
709
+ pluginType = PLUGIN_TYPES.NAV;
710
+ contributionKey = "nav";
711
+ requiresI18n = true;
712
+ createConfiguration(options) {
713
+ const configPrefix = this.getConfigPrefix(options);
714
+ const experienceId = `${configPrefix}.nav.experience`;
715
+ const contribution = {
716
+ id: `${configPrefix}.nav`,
717
+ title: `${configPrefix}.nav.title`,
718
+ namespace: options.appProject,
719
+ navDescriptor: options.nameLowerCase,
720
+ experienceId
721
+ };
722
+ const experience = this.createExperience(options, experienceId);
723
+ return {
724
+ contributions: {
725
+ navViews: [contribution]
726
+ },
727
+ experiences: {
728
+ [experienceId]: experience
729
+ }
730
+ };
731
+ }
732
+ };
733
+
734
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/setting-handler.ts
735
+ var SettingPluginHandler = class extends BasePluginHandler {
736
+ pluginType = PLUGIN_TYPES.SETTING;
737
+ contributionKey = "setting";
738
+ requiresI18n = true;
739
+ createConfiguration(options) {
740
+ const configPrefix = this.getConfigPrefix(options);
741
+ const experienceId = `${configPrefix}.settings.experience`;
742
+ const contribution = {
743
+ id: `${configPrefix}.setting`,
744
+ title: `${configPrefix}.setting.title`,
745
+ namespace: options.appProject,
746
+ settingsGroup: options.group || "general",
747
+ experienceId
748
+ };
749
+ const experience = this.createExperience(options, experienceId);
750
+ return {
751
+ contributions: {
752
+ settings: [contribution]
753
+ },
754
+ experiences: {
755
+ [experienceId]: experience
756
+ }
757
+ };
758
+ }
759
+ };
760
+
761
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/setup-handler.ts
762
+ var SetupPluginHandler = class extends BasePluginHandler {
763
+ pluginType = PLUGIN_TYPES.SETUP;
764
+ contributionKey = "setup";
765
+ requiresI18n = true;
766
+ createConfiguration(options) {
767
+ const configPrefix = this.getConfigPrefix(options);
768
+ const experienceId = `${configPrefix}.setup.experience`;
769
+ const contribution = {
770
+ id: `${configPrefix}.setup`,
771
+ title: `${configPrefix}.setup.title`,
772
+ namespace: options.appProject,
773
+ setupDescriptor: options.nameCamelCase,
774
+ experienceId
775
+ };
776
+ const experience = this.createExperience(options, experienceId);
777
+ return {
778
+ contributions: {
779
+ setupStep: [contribution]
780
+ },
781
+ experiences: {
782
+ [experienceId]: experience
783
+ }
784
+ };
785
+ }
786
+ };
787
+
788
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/trouble-action-handler.ts
789
+ var TroubleActionPluginHandler = class extends BasePluginHandler {
790
+ pluginType = PLUGIN_TYPES.TROUBLE_ACTION;
791
+ contributionKey = "trouble-action";
792
+ requiresI18n = true;
793
+ createConfiguration(options) {
794
+ const configPrefix = this.getConfigPrefix(options);
795
+ const experienceId = `${configPrefix}.troubleAction.experience`;
796
+ const contribution = {
797
+ id: `${configPrefix}.troubleAction`,
798
+ title: `${configPrefix}.troubleAction.title`,
799
+ namespace: options.appProject,
800
+ troubleType: options.nameCamelCase,
801
+ experienceId
802
+ };
803
+ const experience = this.createExperience(options, experienceId);
804
+ return {
805
+ contributions: {
806
+ troubleActions: [contribution]
807
+ },
808
+ experiences: {
809
+ [experienceId]: experience
810
+ }
811
+ };
812
+ }
813
+ };
814
+
815
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/utility-handler.ts
816
+ var UtilityPluginHandler = class extends BasePluginHandler {
817
+ pluginType = PLUGIN_TYPES.UTILITY;
818
+ contributionKey = "utility";
819
+ requiresI18n = true;
820
+ createConfiguration(options) {
821
+ const configPrefix = this.getConfigPrefix(options);
822
+ const experienceId = `${configPrefix}.util.experience`;
823
+ const contribution = {
824
+ id: `${configPrefix}.util`,
825
+ title: `${configPrefix}.utility.title`,
826
+ namespace: options.appProject,
827
+ utilDescriptor: options.nameCamelCase,
828
+ experienceId
829
+ };
830
+ const experience = this.createExperience(options, experienceId);
831
+ return {
832
+ contributions: {
833
+ utilities: [contribution]
834
+ },
835
+ experiences: {
836
+ [experienceId]: experience
837
+ }
838
+ };
839
+ }
840
+ };
841
+
842
+ // ../kos-codegen-core/src/lib/generators/component/plugin-handlers/factory.ts
843
+ var PluginHandlerFactory = class {
844
+ static handlers = /* @__PURE__ */ new Map([
845
+ [PLUGIN_TYPES.CUI, CuiPluginHandler],
846
+ [PLUGIN_TYPES.UTILITY, UtilityPluginHandler],
847
+ [PLUGIN_TYPES.SETTING, SettingPluginHandler],
848
+ [PLUGIN_TYPES.SETUP, SetupPluginHandler],
849
+ [PLUGIN_TYPES.NAV, NavPluginHandler],
850
+ [PLUGIN_TYPES.CONTROL_POUR, ControlPourPluginHandler],
851
+ [PLUGIN_TYPES.TROUBLE_ACTION, TroubleActionPluginHandler],
852
+ [PLUGIN_TYPES.CUSTOM, CustomPluginHandler]
853
+ ]);
854
+ static createHandler(pluginType) {
855
+ if (!pluginType) {
856
+ return new DefaultComponentHandler();
857
+ }
858
+ const HandlerClass = this.handlers.get(pluginType);
859
+ if (!HandlerClass) {
860
+ console.warn(
861
+ `No handler found for plugin type: ${pluginType}. Using default handler.`
862
+ );
863
+ return new DefaultComponentHandler();
864
+ }
865
+ return new HandlerClass();
866
+ }
867
+ static isValidPluginType(type) {
868
+ return this.handlers.has(type);
869
+ }
870
+ };
871
+
872
+ // src/lib/utils/action-factory.mjs
873
+ var actionFactory = (action, metadata2) => {
874
+ return () => {
875
+ const _actions = [{ type: action }];
876
+ if (metadata2.invalidateCache) {
877
+ _actions.push({ type: "clearCache" });
878
+ }
879
+ return _actions;
880
+ };
881
+ };
882
+
883
+ // src/lib/utils/nx-context.mjs
884
+ import { existsSync as existsSync4, readFileSync as readFileSync6, readdirSync as readdirSync3, statSync } from "fs";
885
+ import path10 from "path";
886
+ import { fileURLToPath } from "url";
887
+
888
+ // src/lib/utils/cache.mjs
889
+ import fs6 from "fs";
890
+ import path9 from "path";
891
+ var CACHE_PATH = path9.resolve(".nx/cli-cache.json");
892
+ var CACHE_TTL = 600 * 1e3;
893
+ var ARGS = process.argv;
894
+ var DISABLE_CACHE = process.env.DISABLE_CACHE === "true" || process.env.REFRESH === "true";
895
+ var _cache = {};
896
+ var _loaded = false;
897
+ function ensureCacheDir() {
898
+ const dir = path9.dirname(CACHE_PATH);
899
+ if (!fs6.existsSync(dir))
900
+ fs6.mkdirSync(dir, { recursive: true });
901
+ }
902
+ function loadCacheFromDisk() {
903
+ if (_loaded)
904
+ return;
905
+ _loaded = true;
906
+ try {
907
+ if (fs6.existsSync(CACHE_PATH)) {
908
+ const data = fs6.readFileSync(CACHE_PATH, "utf-8");
909
+ _cache = JSON.parse(data);
910
+ }
911
+ } catch (err) {
912
+ console.warn("Failed to load CLI cache:", err);
913
+ _cache = {};
914
+ }
915
+ }
916
+ function saveCacheToDisk() {
917
+ try {
918
+ ensureCacheDir();
919
+ fs6.writeFileSync(CACHE_PATH, JSON.stringify(_cache, null, 2));
920
+ } catch (err) {
921
+ console.warn("Failed to save CLI cache:", err);
922
+ }
923
+ }
924
+ function isFresh(entry, ttl = CACHE_TTL) {
925
+ if (!entry || !entry.timestamp)
926
+ return false;
927
+ return Date.now() - entry.timestamp < ttl;
928
+ }
929
+ function getCached(key, ttl = CACHE_TTL) {
930
+ if (DISABLE_CACHE)
931
+ return null;
932
+ loadCacheFromDisk();
933
+ const entry = _cache[key];
934
+ if (isFresh(entry, ttl))
935
+ return entry.data;
936
+ return null;
937
+ }
938
+ function setCached(key, data) {
939
+ loadCacheFromDisk();
940
+ _cache[key] = {
941
+ data,
942
+ timestamp: Date.now()
943
+ };
944
+ saveCacheToDisk();
945
+ }
946
+
947
+ // src/lib/utils/nx-context.mjs
948
+ var __dirname2 = path10.dirname(fileURLToPath(import.meta.url));
949
+ function findKosJsonFiles(dir = process.cwd(), files = []) {
950
+ try {
951
+ const entries = readdirSync3(dir);
952
+ for (const entry of entries) {
953
+ if (entry === "node_modules" || entry === ".git" || entry === ".nx" || entry === "dist" || entry === "coverage" || entry === ".vscode" || entry === ".idea" || entry.startsWith(".") && entry !== ".kos.json") {
954
+ continue;
955
+ }
956
+ const fullPath = path10.join(dir, entry);
957
+ try {
958
+ const stat = statSync(fullPath);
959
+ if (stat.isFile() && entry === ".kos.json") {
960
+ files.push(fullPath);
961
+ } else if (stat.isDirectory()) {
962
+ if (entry !== "tmp" && entry !== "temp" && entry !== "build") {
963
+ findKosJsonFiles(fullPath, files);
964
+ }
965
+ }
966
+ } catch (error) {
967
+ continue;
968
+ }
969
+ }
970
+ } catch (error) {
971
+ }
972
+ return files;
973
+ }
974
+ async function getAllProjects() {
975
+ const cached = getCached("allProjects");
976
+ if (cached)
977
+ return cached;
978
+ const projectMap = discoverProjects(process.cwd());
979
+ const projects = Array.from(projectMap.keys());
980
+ setCached("allProjects", projects);
981
+ return projects;
982
+ }
983
+ async function getAllKosProjects() {
984
+ const cached = getCached("allKosProjects");
985
+ if (cached)
986
+ return cached;
987
+ if (process.env.KOS_CLI_QUIET !== "true") {
988
+ console.warn(`[kos-cli] Discovering KOS projects by scanning .kos.json files...`);
989
+ }
990
+ const projectDirs = ["apps", "libs", "packages"];
991
+ const kosJsonFiles = [];
992
+ const workspaceRoot = process.cwd();
993
+ for (const dir of projectDirs) {
994
+ const dirPath = path10.join(workspaceRoot, dir);
995
+ if (existsSync4(dirPath)) {
996
+ findKosJsonFiles(dirPath, kosJsonFiles);
997
+ }
998
+ }
999
+ const rootKosJson = path10.join(workspaceRoot, ".kos.json");
1000
+ if (existsSync4(rootKosJson)) {
1001
+ kosJsonFiles.push(rootKosJson);
1002
+ }
1003
+ if (kosJsonFiles.length === 0) {
1004
+ if (process.env.KOS_CLI_QUIET !== "true") {
1005
+ console.warn(`[kos-cli] No .kos.json files found in common directories, performing full workspace scan...`);
1006
+ }
1007
+ findKosJsonFiles(workspaceRoot, kosJsonFiles);
1008
+ }
1009
+ const kosProjects = [];
1010
+ for (const kosJsonPath of kosJsonFiles) {
1011
+ try {
1012
+ const kosConfig = JSON.parse(readFileSync6(kosJsonPath, "utf-8"));
1013
+ const projectDir = path10.dirname(kosJsonPath);
1014
+ let projectName = null;
1015
+ const projectJsonPath = path10.join(projectDir, "project.json");
1016
+ if (existsSync4(projectJsonPath)) {
1017
+ try {
1018
+ const projectJson = JSON.parse(readFileSync6(projectJsonPath, "utf-8"));
1019
+ projectName = projectJson.name;
1020
+ } catch (error) {
1021
+ projectName = path10.basename(projectDir);
1022
+ }
1023
+ } else {
1024
+ projectName = path10.basename(projectDir);
1025
+ }
1026
+ if (kosConfig.type === "root") {
1027
+ continue;
1028
+ }
1029
+ kosProjects.push({
1030
+ name: projectName,
1031
+ path: projectDir,
1032
+ kosJsonPath,
1033
+ config: kosConfig,
1034
+ projectType: kosConfig.generator?.projectType
1035
+ });
1036
+ } catch (error) {
1037
+ console.warn(`[kos-cli] Error reading ${kosJsonPath}: ${error.message}`);
1038
+ }
1039
+ }
1040
+ setCached("allKosProjects", kosProjects);
1041
+ return kosProjects;
1042
+ }
1043
+ async function getAllModels() {
1044
+ const cached = getCached("allModels");
1045
+ if (cached)
1046
+ return cached;
1047
+ if (process.env.KOS_CLI_QUIET !== "true") {
1048
+ console.warn(`[kos-cli] Scanning for models in KOS projects...`);
1049
+ }
1050
+ const allKosProjects = await getAllKosProjects();
1051
+ const models = [];
1052
+ for (const kosProject of allKosProjects) {
1053
+ if (kosProject.config.models) {
1054
+ Object.keys(kosProject.config.models).forEach((model) => {
1055
+ models.push({ model, project: kosProject.name });
1056
+ });
1057
+ }
1058
+ }
1059
+ models.sort((a, b) => {
1060
+ if (a.project === b.project) {
1061
+ return a.model.localeCompare(b.model);
1062
+ } else {
1063
+ return a.project.localeCompare(b.project);
1064
+ }
1065
+ });
1066
+ setCached("allModels", models);
1067
+ return models;
1068
+ }
1069
+
1070
+ // src/lib/generators/model/context.mjs
1071
+ var metadata = {
6
1072
  key: "context",
7
1073
  name: "KOS Model React Context",
8
1074
  namedArguments: {
9
1075
  modelName: "modelName",
10
1076
  componentProject: "componentProject",
11
- project: "componentProject",
12
- },
1077
+ project: "componentProject"
1078
+ }
13
1079
  };
14
-
15
- export default async function (plop) {
1080
+ async function context_default(plop) {
16
1081
  const allProjects = await getAllProjects();
17
-
18
- // Check if we're in interactive mode by looking at process args
19
- const isInteractive = process.argv.includes('-i') || process.argv.includes('--interactive');
20
-
21
- // For interactive mode, use lazy loading. For non-interactive, load immediately.
1082
+ const isInteractive = process.argv.includes("-i") || process.argv.includes("--interactive");
22
1083
  let modelChoices;
23
1084
  if (isInteractive) {
24
1085
  modelChoices = async () => {
25
1086
  const allModels = await getAllModels();
26
1087
  return allModels.map((m) => ({
27
1088
  name: `${m.model} (${m.project})`,
28
- value: m.model,
1089
+ value: m.model
29
1090
  }));
30
1091
  };
31
1092
  } else {
32
1093
  const allModels = await getAllModels();
33
1094
  modelChoices = allModels.map((m) => ({
34
1095
  name: `${m.model} (${m.project})`,
35
- value: m.model,
1096
+ value: m.model
36
1097
  }));
37
1098
  }
38
-
39
- plop.setActionType("createContext", async function (answers) {
1099
+ plop.setActionType("createContext", async function(answers) {
1100
+ const cwd = process.cwd();
1101
+ const codegenFs = new TrackingFileSystem(new DirectFileSystem(cwd));
40
1102
  const allModels = await getAllModels();
41
1103
  const modelProject = allModels.find(
42
1104
  (m) => m.model === answers.modelName
43
1105
  )?.project;
44
- const command = `npx nx generate @kosdev-code/kos-nx-plugin:kos-context \
45
- --appProject=${answers.componentProject} \
46
- --modelProject=${modelProject} \
47
- --name=${answers.modelName} \
48
- --no-interactive ${answers.dryRun ? "--dryRun" : ""}`;
49
-
50
- try {
51
- await execute(command);
52
- } catch (error) {
53
- throw new Error(error);
54
- }
55
-
1106
+ generateContext(
1107
+ codegenFs,
1108
+ getTemplateDir("kos-context"),
1109
+ {
1110
+ name: answers.modelName,
1111
+ appProject: answers.componentProject,
1112
+ modelProject,
1113
+ modelDirectory: "",
1114
+ appDirectory: ""
1115
+ },
1116
+ cwd
1117
+ );
1118
+ await formatFiles(codegenFs.root, codegenFs.writtenPaths);
56
1119
  return `Context created for ${answers.modelName} in ${answers.componentProject}`;
57
1120
  });
58
-
59
1121
  plop.setGenerator("context", {
60
1122
  description: "Create a context for a KOS Model",
61
1123
  prompts: [
@@ -63,15 +1125,20 @@ export default async function (plop) {
63
1125
  type: "list",
64
1126
  name: "modelName",
65
1127
  message: "Which model to use?",
66
- choices: modelChoices,
1128
+ choices: modelChoices
67
1129
  },
68
1130
  {
69
1131
  type: "list",
70
1132
  name: "componentProject",
71
1133
  message: "Which project should the context be created in?",
72
- choices: allProjects,
73
- },
1134
+ choices: allProjects
1135
+ }
74
1136
  ],
75
- actions: actionFactory("createContext", metadata),
1137
+ actions: actionFactory("createContext", metadata)
76
1138
  });
77
1139
  }
1140
+ export {
1141
+ context_default as default,
1142
+ metadata
1143
+ };
1144
+ //# sourceMappingURL=context.mjs.map