@kosdev-code/kos-ui-cli 1.6.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/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # sdk-kos-ui-cli
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Building
6
+
7
+ Run `nx build sdk-kos-ui-cli` to build the library.
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@kosdev-code/kos-ui-cli",
3
+ "version": "1.6.0",
4
+ "bin": {
5
+ "kosui": "./src/lib/cli.mjs"
6
+ },
7
+ "files": [
8
+ "src"
9
+ ],
10
+ "type": "module",
11
+ "dependencies": {
12
+ "prettier": "^2.6.2",
13
+ "rimraf": "^5.0.1",
14
+ "plop": "^3.1.2",
15
+ "inquirer-directory": "^2.2.0",
16
+ "figlet": "^1.6.0",
17
+ "create-nx-workspace": "18.0.3"
18
+ },
19
+ "module": "./src/index.js",
20
+ "main": "./src/index.js",
21
+ "kos": {
22
+ "build": {
23
+ "gitHash": "9a0e8bf2281366d70b509e1ba964955806ce6c69"
24
+ }
25
+ },
26
+ "publishConfig": {
27
+ "registry": "https://registry.npmjs.org/"
28
+ }
29
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/sdk/kos-ui-cli/src/index.js"],"names":[],"mappings":""}
package/src/index.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/sdk/kos-ui-cli/src/index.js"],"names":[],"mappings":""}
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+ import figlet from "figlet";
3
+ import minimist from "minimist";
4
+ import path, { dirname } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { Plop, run } from "plop";
7
+
8
+ const args = process.argv.slice(2);
9
+ const argv = minimist(args);
10
+
11
+ const __dirname = dirname(fileURLToPath(import.meta.url));
12
+ figlet("kOS CLI", function (err, data) {
13
+ if (err) {
14
+ console.log("Something went wrong...");
15
+ console.dir(err);
16
+ return;
17
+ }
18
+
19
+ const command = args.length > 0 ? args[0] : "help";
20
+
21
+ switch (command) {
22
+ case "workspace":
23
+ case "component":
24
+ case "pluginComponent":
25
+ case "plugin:cui":
26
+ case "plugin:utility":
27
+ case "plugin:setup":
28
+ case "plugin:setting":
29
+ case "plugin:nav":
30
+ case "plugin:troubleAction":
31
+ case "project":
32
+ case "project:splash":
33
+ case "theme":
34
+ case "plugin":
35
+ case "i18n":
36
+ case "i18n:namespace":
37
+ case "model": {
38
+ Plop.prepare(
39
+ {
40
+ cwd: argv.cwd,
41
+ configPath: path.join(__dirname, "plopfile.mjs"),
42
+ preload: argv.preload || [],
43
+ completion: argv.completion,
44
+ },
45
+ (env) =>
46
+ Plop.execute(env, (env) => {
47
+ const options = {
48
+ ...env,
49
+ dest: process.cwd(), // this will make the destination path to be based on the cwd when calling the wrapper
50
+ };
51
+ return run(options, undefined, true);
52
+ })
53
+ );
54
+
55
+ break;
56
+ }
57
+ case "hook":
58
+ case "container":
59
+ case "context":
60
+ case "model:companion": {
61
+ console.warn(`--- Create a new kOS Model - ${args[0]} ---`);
62
+ Plop.prepare(
63
+ {
64
+ cwd: argv.cwd,
65
+ configPath: path.join(__dirname, "model-aware-plopfile.mjs"),
66
+ preload: argv.preload || [],
67
+ completion: argv.completion,
68
+ },
69
+ (env) =>
70
+ Plop.execute(env, (env) => {
71
+ const options = {
72
+ ...env,
73
+ dest: process.cwd(), // this will make the destination path to be based on the cwd when calling the wrapper
74
+ };
75
+ return run(options, undefined, true);
76
+ })
77
+ );
78
+
79
+ break;
80
+ }
81
+ case "env": {
82
+ console.warn("--- Discover Studio Environment Variables ---");
83
+ console.warn("The following will discover Studio Environment Variables.");
84
+ Plop.prepare(
85
+ {
86
+ cwd: argv.cwd,
87
+ configPath: path.join(__dirname, "env-plopfile.mjs"),
88
+ preload: argv.preload || [],
89
+ completion: argv.completion,
90
+ },
91
+ (env) =>
92
+ Plop.execute(env, (env) => {
93
+ const options = {
94
+ ...env,
95
+ dest: process.cwd(), // this will make the destination path to be based on the cwd when calling the wrapper
96
+ };
97
+ return run(options, undefined, true);
98
+ })
99
+ );
100
+
101
+ break;
102
+ }
103
+ default: {
104
+ console.warn("--- kOS CLI Help ---");
105
+ Plop.prepare(
106
+ {
107
+ cwd: argv.cwd,
108
+ configPath: path.join(__dirname, "routing-plopfile.mjs"),
109
+ preload: argv.preload || [],
110
+ completion: argv.completion,
111
+ },
112
+ (env) =>
113
+ Plop.execute(env, (env) => {
114
+ const options = {
115
+ ...env,
116
+ dest: process.cwd(), // this will make the destination path to be based on the cwd when calling the wrapper
117
+ };
118
+ return run(options, undefined, true);
119
+ })
120
+ );
121
+
122
+ break;
123
+ }
124
+ }
125
+ });
@@ -0,0 +1,33 @@
1
+ import fs from "fs";
2
+ import directoryPrompt from "inquirer-directory";
3
+ import { findJavaExecutable } from "./utils/java-home.mjs";
4
+ import { findStudioHome } from "./utils/studio-home.mjs";
5
+ import { detectWorkspace } from "./utils/utils.mjs";
6
+
7
+ export default async function (plop) {
8
+ plop.setPrompt("directory", directoryPrompt);
9
+ const isWorkspace = await detectWorkspace();
10
+
11
+ plop.setActionType("findEnv", async function (answers, config, plop) {
12
+ const studioHome = findStudioHome();
13
+ const javaHome = findJavaExecutable();
14
+
15
+ fs.writeFileSync(
16
+ ".env.local",
17
+ `# Path to the Java binary\nJAVA_CMD='${javaHome}'\n\n# Path to the kos installation\nKOS_INSTALL_PATH='${studioHome}'\n`
18
+ );
19
+
20
+ return `Studio Home: ${studioHome}\nJava Home: ${javaHome}`;
21
+ });
22
+
23
+ plop.setGenerator("env", {
24
+ description: "Discover Studio Environment Variables",
25
+ prompts: [],
26
+ actions: function (data) {
27
+ const action = {
28
+ type: "findEnv",
29
+ };
30
+ return [action];
31
+ },
32
+ });
33
+ }
@@ -0,0 +1,274 @@
1
+ import directoryPrompt from "inquirer-directory";
2
+ import {
3
+ detectWorkspace,
4
+ execute,
5
+ getAllModels,
6
+ getAllProjects,
7
+ getLibraryProjects,
8
+ getProjectDetails,
9
+ required,
10
+ } from "./utils/utils.mjs";
11
+
12
+ const DEFAULT_PROMPTS = [
13
+ {
14
+ type: "confirm",
15
+ name: "interactive",
16
+ message: "Do you want to use the interactive mode?",
17
+ default: false,
18
+ when: false,
19
+ },
20
+ {
21
+ type: "confirm",
22
+ name: "dryRun",
23
+ message: "Show the output of the command without running it?",
24
+ default: false,
25
+ when: false,
26
+ },
27
+ ];
28
+
29
+ const MODEL_PROMPTS = [
30
+ {
31
+ type: "confirm",
32
+ name: "container",
33
+ default: false,
34
+ message: "Does this model require a container model?",
35
+ },
36
+ {
37
+ type: "confirm",
38
+ name: "parentAware",
39
+ when: (answers) => {
40
+ console.log(answers);
41
+ return !!answers.container;
42
+ },
43
+ default: false,
44
+ message: "Should the model be aware of it's parent container?",
45
+ },
46
+ {
47
+ type: "confirm",
48
+ name: "singleton",
49
+ default: false,
50
+ message: "Is this model a singleton?",
51
+ },
52
+
53
+ {
54
+ type: "confirm",
55
+ name: "dataServices",
56
+ default: true,
57
+ message: "Create data services for model?",
58
+ },
59
+ ];
60
+ export default async function (plop) {
61
+ plop.setPrompt("directory", directoryPrompt);
62
+ const isWorkspace = await detectWorkspace();
63
+
64
+ const allProjects = isWorkspace ? await getAllProjects() : [];
65
+ const libraryProjects = isWorkspace ? await getLibraryProjects() : [];
66
+ const allModels = isWorkspace ? await getAllModels() : [];
67
+ const workspaceModels = allModels.map((model) => {
68
+ return { name: `${model.model} (${model.project})`, value: model.model };
69
+ });
70
+
71
+ plop.setActionType("createContainer", async function (answers, config, plop) {
72
+ const modelProjectName = allModels.find(
73
+ (model) => model.model === answers.modelName
74
+ )?.project;
75
+ const modelProject = await getProjectDetails(modelProjectName);
76
+
77
+ try {
78
+ await execute(
79
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-container-model --modelName=${
80
+ answers.modelName
81
+ } --modelProject=${
82
+ modelProject.name
83
+ } --skipRegistration=true --dataServices=${!!answers.dataServices} --singleton=${!!answers.singleton} --no-interactive ${
84
+ answers.dryRun ? "--dryRun" : ""
85
+ } --verbose`
86
+ );
87
+ } catch (error) {
88
+ throw new Error(error);
89
+ }
90
+ return `model ${answers.modelName} created in ${answers.modelProject}`;
91
+ });
92
+
93
+ plop.setActionType("createHook", async function (answers, config, plop) {
94
+ const modelProject = allModels.find(
95
+ (model) => model.model === answers.modelName
96
+ )?.project;
97
+
98
+ try {
99
+ await execute(
100
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-hook --appProject=${
101
+ answers.componentProject
102
+ } --modelProject=${modelProject} --name=${
103
+ answers.modelName
104
+ } --no-interactive ${answers.dryRun ? "--dryRun" : ""}`
105
+ );
106
+ } catch (error) {
107
+ throw new Error(error);
108
+ }
109
+
110
+ return `hook created for ${answers.modelName} in ${answers.componentProject}`;
111
+ });
112
+
113
+ plop.setActionType("createContext", async function (answers, config, plop) {
114
+ const modelProject = allModels.find(
115
+ (model) => model.model === answers.modelName
116
+ )?.project;
117
+
118
+ try {
119
+ await execute(
120
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-context --appProject=${
121
+ answers.componentProject
122
+ } --modelProject=${modelProject} --name=${
123
+ answers.modelName
124
+ } --no-interactive ${answers.dryRun ? "--dryRun" : ""}`
125
+ );
126
+ } catch (error) {
127
+ throw new Error(error);
128
+ }
129
+
130
+ return `context created for ${answers.modelName} in ${answers.componentProject}`;
131
+ });
132
+
133
+ plop.setActionType(
134
+ "createCompanionModel",
135
+ async function (answers, config, plop) {
136
+ console.log(JSON.stringify(answers, null, 2));
137
+ const modelProject = await getProjectDetails(answers.modelProject);
138
+
139
+ const companionParentProjectName = allModels.find(
140
+ (model) => model.model === answers.companionParent
141
+ )?.project;
142
+ try {
143
+ await execute(
144
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-model --name=${
145
+ answers.modelName
146
+ } --modelProject=${
147
+ modelProject.name
148
+ } --skipRegistration=true --container=${!!answers.container} --dataServices=${!!answers.dataServices} --singleton=${!!answers.singleton} --parentAware=${!!answers.parentAware} --companion=true --companionModel=${
149
+ answers.companionParent
150
+ } --companionModelProject=${companionParentProjectName} --no-interactive ${
151
+ answers.dryRun ? "--dryRun" : ""
152
+ } --verbose`
153
+ );
154
+ } catch (error) {
155
+ throw new Error(error);
156
+ }
157
+ }
158
+ );
159
+
160
+ plop.setGenerator("container", {
161
+ description: "Create a new kOS Container Model",
162
+ prompts: [
163
+ ...DEFAULT_PROMPTS,
164
+ {
165
+ type: "list",
166
+ name: "modelName",
167
+ message: "Which model to use?",
168
+ choices: workspaceModels,
169
+ },
170
+ {
171
+ type: "list",
172
+ name: "registrationProject",
173
+ message: "Which project should the model be registered in?",
174
+ validate: required,
175
+ choices: allProjects,
176
+ },
177
+ ...MODEL_PROMPTS,
178
+ ],
179
+ actions: function (data) {
180
+ const action = {
181
+ type: "createContainer",
182
+ };
183
+ return [action];
184
+ },
185
+ });
186
+
187
+ plop.setGenerator("hook", {
188
+ description: "Create a hook for a kOS Model",
189
+ prompts: [
190
+ {
191
+ type: "list",
192
+ name: "modelName",
193
+ message: "Which model to use?",
194
+
195
+ choices: workspaceModels,
196
+ },
197
+
198
+ {
199
+ type: "list",
200
+ name: "componentProject",
201
+ message: "Which project should the hook be created in?",
202
+ when: (answers) => {
203
+ return !answers.componentProject;
204
+ },
205
+ choices: allProjects,
206
+ },
207
+ ],
208
+ actions: function (data) {
209
+ const action = {
210
+ type: "createHook",
211
+ };
212
+ return [action];
213
+ },
214
+ });
215
+
216
+ plop.setGenerator("context", {
217
+ description: "Create a context for a kOS Model",
218
+ prompts: [
219
+ {
220
+ type: "list",
221
+ name: "modelName",
222
+ message: "Which model to use?",
223
+ choices: workspaceModels,
224
+ },
225
+
226
+ {
227
+ type: "list",
228
+ name: "componentProject",
229
+ message: "Which project should the context be created in?",
230
+ choices: getAllProjects,
231
+ },
232
+ ],
233
+ actions: function (data) {
234
+ const action = {
235
+ type: "createContext",
236
+ };
237
+ return [action];
238
+ },
239
+ });
240
+
241
+ plop.setGenerator("model:companion", {
242
+ description: "Create a new kOS Companion Model",
243
+ prompts: [
244
+ ...DEFAULT_PROMPTS,
245
+ {
246
+ type: "input",
247
+ name: "modelName",
248
+ message: "Enter the name of the model",
249
+ validate: required,
250
+ },
251
+ {
252
+ type: "list",
253
+ name: "modelProject",
254
+ message: "Which model project to use?",
255
+ validate: required,
256
+ choices: libraryProjects,
257
+ },
258
+ {
259
+ type: "list",
260
+ name: "companionParent",
261
+ message: "Select the companion parent model?",
262
+ choices: workspaceModels,
263
+ },
264
+
265
+ ...MODEL_PROMPTS,
266
+ ],
267
+ actions: function (data) {
268
+ const action = {
269
+ type: "createCompanionModel",
270
+ };
271
+ return [action];
272
+ },
273
+ });
274
+ }
@@ -0,0 +1,586 @@
1
+ import { spawn } from "child_process";
2
+ import { createWorkspace } from "create-nx-workspace";
3
+ import fs from "fs";
4
+ import directoryPrompt from "inquirer-directory";
5
+ import path from "path";
6
+ import {
7
+ detectWorkspace,
8
+ execute,
9
+ getAllProjects,
10
+ getLibraryProjects,
11
+ getPluginProjects,
12
+ getProjectDetails,
13
+ required,
14
+ } from "./utils/utils.mjs";
15
+
16
+ const DEFAULT_PROMPTS = [
17
+ {
18
+ type: "confirm",
19
+ name: "interactive",
20
+ message: "Do you want to use the interactive mode?",
21
+ default: false,
22
+ when: false,
23
+ },
24
+ {
25
+ type: "confirm",
26
+ name: "dryRun",
27
+ message: "Show the output of the command without running it?",
28
+ default: false,
29
+ when: false,
30
+ },
31
+ ];
32
+
33
+ const MODEL_PROMPTS = [
34
+ {
35
+ type: "confirm",
36
+ name: "container",
37
+ default: false,
38
+ message: "Does this model require a container model?",
39
+ },
40
+ {
41
+ type: "confirm",
42
+ name: "parentAware",
43
+ when: (answers) => {
44
+ return !!answers.container;
45
+ },
46
+ default: false,
47
+ message: "Should the model be aware of it's parent container?",
48
+ },
49
+ {
50
+ type: "confirm",
51
+ name: "singleton",
52
+ default: false,
53
+ message: "Is this model a singleton?",
54
+ },
55
+
56
+ {
57
+ type: "confirm",
58
+ name: "dataServices",
59
+ default: true,
60
+ message: "Create data services for model?",
61
+ },
62
+ ];
63
+ export default async function (plop) {
64
+ plop.setPrompt("directory", directoryPrompt);
65
+ const isWorkspace = await detectWorkspace();
66
+ const libraryProjects = isWorkspace ? await getLibraryProjects() : [];
67
+ const allProjects = isWorkspace ? await getAllProjects() : [];
68
+
69
+ plop.setActionType("createWorkspace", async function (answers, config, plop) {
70
+ await createWorkspace("@kosdev-code/kos-nx-plugin", {
71
+ nxCloud: "skip",
72
+ name: answers.workspaceName,
73
+ });
74
+ return `workspace ${answers.workspaceName} created`;
75
+ });
76
+
77
+ plop.setActionType("createModel", async function (answers, config, plop) {
78
+ const modelProject = await getProjectDetails(answers.modelProject);
79
+
80
+ try {
81
+ await execute(
82
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-model --name=${
83
+ answers.modelName
84
+ } --modelProject=${
85
+ modelProject.name
86
+ } --skipRegistration=true --container=${!!answers.container} --dataServices=${!!answers.dataServices} --singleton=${!!answers.singleton} --parentAware=${!!answers.parentAware} --no-interactive ${
87
+ answers.dryRun ? "--dryRun" : ""
88
+ } --verbose`
89
+ );
90
+ } catch (error) {
91
+ throw new Error(error);
92
+ }
93
+
94
+ return `*******************************************************
95
+ model ${answers.modelName} created in ${answers.modelProject}
96
+
97
+ Please register the model in your app registration file
98
+ *******************************************************`;
99
+ });
100
+
101
+ plop.setActionType("addNamespace", async function (answers, config, plop) {
102
+ const i18nProject = await getProjectDetails(answers.project);
103
+ const locale = answers.locale;
104
+ const src = i18nProject.sourceRoot;
105
+ const namespaceDirPath = path.join(src, "assets", "locales", locale);
106
+
107
+ const namespacePath = path.join(namespaceDirPath, `${answers.name}.json`);
108
+
109
+ const defaultData = {
110
+ name: answers.name,
111
+ };
112
+
113
+ fs.mkdirSync(namespaceDirPath, { recursive: true });
114
+ fs.writeFileSync(namespacePath, JSON.stringify(defaultData, null, 2));
115
+ });
116
+
117
+ plop.setActionType("createSplashProject", function (answers, config, plop) {
118
+ return new Promise((resolve, reject) => {
119
+ const command =
120
+ `nx generate @kosdev-code/kos-nx-plugin:kos-splash-project --name=${answers.name} --no-interactive`.split(
121
+ " "
122
+ );
123
+
124
+ const child = spawn("npx", command, { shell: true });
125
+ child.stdout.on("data", (data) => {
126
+ console.log(`${data}`);
127
+ });
128
+
129
+ child.stderr.on("data", (data) => {
130
+ console.error(`ERROR:${data}`);
131
+ });
132
+ child.on("exit", function (code, signal) {
133
+ if (code === 0) {
134
+ resolve(`Splash page project ${answers.name} created`);
135
+ } else {
136
+ reject(`Splash page project ${answers.name} failed`);
137
+ }
138
+ });
139
+ });
140
+ });
141
+ plop.setActionType("createComponent", function (answers, config, plop) {
142
+ return new Promise((resolve, reject) => {
143
+ const command =
144
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-component --name=${answers.componentName} --appProject=${answers.componentProject} --type=components --no-interactive`.split(
145
+ " "
146
+ );
147
+ const child = spawn("npx", command, { shell: true });
148
+ child.stdout.on("data", (data) => {
149
+ console.log(`${data}`);
150
+ });
151
+
152
+ child.stderr.on("data", (data) => {
153
+ console.error(`ERROR:${data}`);
154
+ });
155
+ child.on("exit", function (code, signal) {
156
+ if (code === 0) {
157
+ resolve(`UI project ${answers.name} created`);
158
+ } else {
159
+ reject(`UI project ${answers.name} failed`);
160
+ }
161
+ });
162
+ });
163
+ });
164
+ plop.setActionType("createPluginComponent", function (answers, config, plop) {
165
+ return new Promise((resolve, reject) => {
166
+ const pluginType = answers.extensionPoint;
167
+ const command =
168
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-component --name=${answers.componentName} --group=${answers.group} --appProject=${answers.componentProject} --pluginType=${pluginType} --type=components --no-interactive`.split(
169
+ " "
170
+ );
171
+ const child = spawn("npx", command, { shell: true });
172
+ child.stdout.on("data", (data) => {
173
+ console.log(`${data}`);
174
+ });
175
+
176
+ child.stderr.on("data", (data) => {
177
+ console.error(`ERROR:${data}`);
178
+ });
179
+ child.on("exit", function (code, signal) {
180
+ if (code === 0) {
181
+ resolve(`UI project ${answers.name} created`);
182
+ } else {
183
+ reject(`UI project ${answers.name} failed`);
184
+ }
185
+ });
186
+ });
187
+ });
188
+ plop.setActionType("createUiProject", function (answers, config, plop) {
189
+ return new Promise((resolve, reject) => {
190
+ const command =
191
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-ui-project --name=${answers.name} --no-interactive`.split(
192
+ " "
193
+ );
194
+ const child = spawn("npx", command, { shell: true });
195
+ child.stdout.on("data", (data) => {
196
+ console.log(`${data}`);
197
+ });
198
+
199
+ child.stderr.on("data", (data) => {
200
+ console.error(`ERROR:${data}`);
201
+ });
202
+ child.on("exit", function (code, signal) {
203
+ if (code === 0) {
204
+ resolve(`UI project ${answers.name} created`);
205
+ } else {
206
+ reject(`UI project ${answers.name} failed`);
207
+ }
208
+ });
209
+ });
210
+ });
211
+
212
+ plop.setActionType("createI18nProject", function (answers, config, plop) {
213
+ return new Promise((resolve, reject) => {
214
+ const command =
215
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-i18n-project --name=${answers.name} --no-interactive`.split(
216
+ " "
217
+ );
218
+ const child = spawn("npx", command, { shell: true });
219
+ child.stdout.on("data", (data) => {
220
+ console.log(`${data}`);
221
+ });
222
+
223
+ child.stderr.on("data", (data) => {
224
+ console.error(`ERROR:${data}`);
225
+ });
226
+ child.on("exit", function (code, signal) {
227
+ if (code === 0) {
228
+ resolve(`i18n project ${answers.name} created`);
229
+ } else {
230
+ reject(`i18n project ${answers.name} failed`);
231
+ }
232
+ });
233
+ });
234
+ });
235
+ plop.setActionType("createThemeProject", function (answers, config, plop) {
236
+ return new Promise((resolve, reject) => {
237
+ const command =
238
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-theme-project --name=${answers.name} --no-interactive`.split(
239
+ " "
240
+ );
241
+ const child = spawn("npx", command, { shell: true });
242
+ child.stdout.on("data", (data) => {
243
+ console.log(`${data}`);
244
+ });
245
+
246
+ child.stderr.on("data", (data) => {
247
+ console.error(`ERROR:${data}`);
248
+ });
249
+ child.on("exit", function (code, signal) {
250
+ if (code === 0) {
251
+ resolve(`theme project ${answers.name} created`);
252
+ } else {
253
+ reject(`theme project ${answers.name} failed`);
254
+ }
255
+ });
256
+ });
257
+ });
258
+
259
+ plop.setActionType("createPluginProject", function (answers, config, plop) {
260
+ return new Promise((resolve, reject) => {
261
+ const command =
262
+ `npx nx generate @kosdev-code/kos-nx-plugin:kos-plugin-project --name=${answers.name} --no-interactive`.split(
263
+ " "
264
+ );
265
+ const child = spawn("npx", command, { shell: true });
266
+ child.stdout.on("data", (data) => {
267
+ console.log(`${data}`);
268
+ });
269
+
270
+ child.stderr.on("data", (data) => {
271
+ console.error(`ERROR:${data}`);
272
+ });
273
+ child.on("exit", function (code, signal) {
274
+ if (code === 0) {
275
+ resolve(`plugin project ${answers.name} created`);
276
+ } else {
277
+ reject(`plugin project ${answers.name} failed`);
278
+ }
279
+ });
280
+ });
281
+ });
282
+
283
+ plop.setGenerator("component", {
284
+ description: "Create a new kOS Component",
285
+ prompts: [
286
+ {
287
+ type: "input",
288
+ name: "componentName",
289
+ message: "Enter the name of the component",
290
+ validate: required,
291
+ },
292
+ {
293
+ type: "list",
294
+ name: "componentProject",
295
+ message: "Which project should the component be created in?",
296
+ choices: allProjects,
297
+ },
298
+ ],
299
+ actions: function (data) {
300
+ const action = {
301
+ type: "createComponent",
302
+ };
303
+ return [action];
304
+ },
305
+ });
306
+
307
+ const pluginPrompts = [
308
+ {
309
+ type: "input",
310
+ name: "componentName",
311
+ message: "Enter the name of the component",
312
+ validate: required,
313
+ },
314
+ {
315
+ type: "list",
316
+ name: "componentProject",
317
+ message: "Which project should the component be created in?",
318
+ choices: getPluginProjects,
319
+ },
320
+ ];
321
+ plop.setGenerator("pluginComponent", {
322
+ description: "Create a new kOS Plugin Component",
323
+ prompts: [
324
+ ...pluginPrompts,
325
+ {
326
+ type: "list",
327
+ name: "extensionPoint",
328
+ message: "What type of extension point is the plugin supporting?",
329
+ choices: ["cui", "setup", "utility", "setting", "troubleAction"],
330
+ },
331
+ ],
332
+ actions: function (data) {
333
+ const action = {
334
+ type: "createPluginComponent",
335
+ };
336
+ return [action];
337
+ },
338
+ });
339
+
340
+ plop.setGenerator("plugin:cui", {
341
+ description: "Create a new kOS CUI Configuration Plugin Component",
342
+ prompts: [...pluginPrompts],
343
+ actions: function (data) {
344
+ data.extensionPoint = "cui";
345
+ const action = {
346
+ type: "createPluginComponent",
347
+ extensionPoint: "cui",
348
+ };
349
+ return [action];
350
+ },
351
+ });
352
+ plop.setGenerator("plugin:utility", {
353
+ description: "Create a new kOS Utility Plugin Component",
354
+ prompts: [...pluginPrompts],
355
+ actions: function (data) {
356
+ data.extensionPoint = "utility";
357
+ const action = {
358
+ type: "createPluginComponent",
359
+ extensionPoint: "utility",
360
+ };
361
+ return [action];
362
+ },
363
+ });
364
+
365
+ plop.setGenerator("plugin:troubleAction", {
366
+ description: "Create a new kOS Trouble Action Plugin Component",
367
+ prompts: [...pluginPrompts],
368
+ actions: function (data) {
369
+ data.extensionPoint = "troubleAction";
370
+ const action = {
371
+ type: "createPluginComponent",
372
+ extensionPoint: "troubleAction",
373
+ };
374
+ return [action];
375
+ },
376
+ });
377
+
378
+ plop.setGenerator("plugin:setup", {
379
+ description: "Create a new kOS Setup Step Plugin Component",
380
+ prompts: [...pluginPrompts],
381
+ actions: function (data) {
382
+ data.extensionPoint = "setup";
383
+ const action = {
384
+ type: "createPluginComponent",
385
+ extensionPoint: "setup",
386
+ };
387
+ return [action];
388
+ },
389
+ });
390
+
391
+ plop.setGenerator("plugin:setting", {
392
+ description: "Create a new kOS Settings Plugin Component",
393
+ prompts: [
394
+ ...pluginPrompts,
395
+ {
396
+ type: "input",
397
+ name: "group",
398
+ message: "Which settings group should the setting be located?",
399
+ },
400
+ ],
401
+ actions: function (data) {
402
+ data.extensionPoint = "setting";
403
+ const action = {
404
+ type: "createPluginComponent",
405
+ extensionPoint: "setting",
406
+ };
407
+ return [action];
408
+ },
409
+ });
410
+ plop.setGenerator("plugin:nav", {
411
+ description: "Create a new kOS Navigation View Plugin Component",
412
+ prompts: [...pluginPrompts],
413
+ actions: function (data) {
414
+ data.extensionPoint = "nav";
415
+ const action = {
416
+ type: "createPluginComponent",
417
+ extensionPoint: "nav",
418
+ };
419
+ return [action];
420
+ },
421
+ });
422
+ plop.setGenerator("workspace", {
423
+ description: "kOS UI Workspace Setup",
424
+ prompts: [
425
+ {
426
+ type: "input",
427
+ name: "workspaceName",
428
+ message: "kOS UI Workspace Name",
429
+ validate: required,
430
+ },
431
+ ],
432
+ actions: function (data) {
433
+ const action = {
434
+ type: "createWorkspace",
435
+ };
436
+ return [action];
437
+ },
438
+ });
439
+
440
+ plop.setGenerator("model", {
441
+ description: "Create a new kOS Model",
442
+ prompts: [
443
+ ...DEFAULT_PROMPTS,
444
+ {
445
+ type: "input",
446
+ name: "modelName",
447
+ message: "Enter the name of the model",
448
+ validate: required,
449
+ },
450
+ {
451
+ type: "list",
452
+ name: "modelProject",
453
+ message: "Which model project to use?",
454
+ validate: required,
455
+ choices: libraryProjects,
456
+ },
457
+ ...MODEL_PROMPTS,
458
+ ],
459
+ actions: function (data) {
460
+ const action = {
461
+ type: "createModel",
462
+ };
463
+ return [action];
464
+ },
465
+ });
466
+
467
+ plop.setGenerator("theme", {
468
+ description: "Create a new kos UI Theme project",
469
+ prompts: [
470
+ {
471
+ type: "input",
472
+ name: "name",
473
+ message: "What is the name of the theme project?",
474
+ validate: required,
475
+ },
476
+ ],
477
+ actions: function (data) {
478
+ const action = {
479
+ type: "createThemeProject",
480
+ };
481
+ return [action];
482
+ },
483
+ });
484
+
485
+ plop.setGenerator("project", {
486
+ description: "Create a new kos UI App project",
487
+ prompts: [
488
+ {
489
+ type: "input",
490
+ name: "name",
491
+ message: "What is the name of the app project?",
492
+ validate: required,
493
+ },
494
+ ],
495
+ actions: function (data) {
496
+ const action = {
497
+ type: "createUiProject",
498
+ };
499
+ return [action];
500
+ },
501
+ });
502
+
503
+ plop.setGenerator("plugin", {
504
+ description: "Create a new kos UI Plugin project",
505
+ prompts: [
506
+ {
507
+ type: "input",
508
+ name: "name",
509
+ message: "What is the name of the plugin project?",
510
+ validate: required,
511
+ },
512
+ ],
513
+ actions: function (data) {
514
+ const action = {
515
+ type: "createPluginProject",
516
+ };
517
+ return [action];
518
+ },
519
+ });
520
+
521
+ plop.setGenerator("project:splash", {
522
+ description: "Create a new kos splash page project",
523
+ prompts: [
524
+ {
525
+ type: "input",
526
+ name: "name",
527
+ message: "What is the name of the splash project?",
528
+ validate: required,
529
+ },
530
+ ],
531
+ actions: function (data) {
532
+ const action = {
533
+ type: "createSplashProject",
534
+ };
535
+ return [action];
536
+ },
537
+ });
538
+
539
+ plop.setGenerator("i18n", {
540
+ description: "Create a new kos UI i18n project",
541
+ prompts: [
542
+ {
543
+ type: "input",
544
+ name: "name",
545
+ message: "What is the name of the i18n project?",
546
+ validate: required,
547
+ },
548
+ ],
549
+ actions: function (data) {
550
+ const action = {
551
+ type: "createI18nProject",
552
+ };
553
+ return [action];
554
+ },
555
+ });
556
+
557
+ plop.setGenerator("i18n:namespace", {
558
+ description: "Create a new kos UI i18n namespace",
559
+ prompts: [
560
+ {
561
+ type: "input",
562
+ name: "name",
563
+ message: "What is the name of the i18n namespace?",
564
+ validate: required,
565
+ },
566
+ {
567
+ type: "input",
568
+ name: "locale",
569
+ message: "What is the locale of the i18n namespace?",
570
+ validate: required,
571
+ },
572
+ {
573
+ type: "list",
574
+ name: "project",
575
+ message: "Which project should the namespace be created in?",
576
+ choices: getAllProjects,
577
+ },
578
+ ],
579
+ actions: function (data) {
580
+ const action = {
581
+ type: "addNamespace",
582
+ };
583
+ return [action];
584
+ },
585
+ });
586
+ }
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ import minimist from "minimist";
3
+ import { dirname } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const args = process.argv.slice(2);
7
+ const argv = minimist(args);
8
+
9
+ const __dirname = dirname(fileURLToPath(import.meta.url));
10
+ export default async function (plop) {
11
+ const generators = {
12
+ model: { name: "kOS Model", path: "plopfile.mjs" },
13
+ "model:companion": {
14
+ name: "kOS Companion Model",
15
+ path: "model-aware-plopfile.mjs",
16
+ },
17
+ hook: { name: "kOS Model Hook and HoC", path: "model-aware-plopfile.mjs" },
18
+ context: { name: "kOS Model Context", path: "model-aware-plopfile.mjs" },
19
+ container: {
20
+ name: "kOS Model Container",
21
+ path: "model-aware-plopfile.mjs",
22
+ },
23
+
24
+ workspace: {
25
+ name: "kOS Development Workspace",
26
+ path: "plopfile.mjs",
27
+ },
28
+ project: { name: "kOS UI App Project", path: "model-aware-plopfile.mjs" },
29
+ plugin: { name: "kOS UI Plugin Project", path: "plopfile.mjs" },
30
+ "plugin:utility": { name: "kOS UI Plugin Utility", path: "plopfile.mjs" },
31
+ "plugin:setup": { name: "kOS UI Plugin Setup Step", path: "plopfile.mjs" },
32
+ "plugin:cui": {
33
+ name: "kOS UI Plugin CUI Configuration",
34
+ path: "plopfile.mjs",
35
+ },
36
+ "plugin:setup": { name: "kOS UI Plugin Setup Step", path: "plopfile.mjs" },
37
+ "plugin:nav": {
38
+ name: "kOS UI Plugin Page Navigation",
39
+ path: "plopfile.mjs",
40
+ },
41
+ component: { name: "kOS UI Component", path: "plopfile.mjs" },
42
+ pluginComponent: { name: "kOS UI Plugin Component", path: "plopfile.mjs" },
43
+ i18n: {
44
+ name: "kOS Localization Project",
45
+ path: "plopfile.mjs",
46
+ },
47
+ "i18n:namespace": {
48
+ name: "kOS Localization Namespace",
49
+ path: "plopfile.mjs",
50
+ },
51
+ theme: { name: "kOS Theme Project", path: "plopfile.mjs" },
52
+ env: {
53
+ name: "Discover and Set Studio Environment Variables",
54
+ path: "env-plopfile.mjs",
55
+ },
56
+ };
57
+ plop.setActionType("execute", async (answers, config) => {
58
+ const template = answers.template;
59
+ argv._ = [template];
60
+ const pathName = generators[template].path;
61
+
62
+ console.warn(`--------- Please run kosui ${template} ---------`);
63
+ });
64
+
65
+ plop.setGenerator("help", {
66
+ description: "Select a task to run",
67
+ prompts: [
68
+ {
69
+ type: "list",
70
+ name: "template",
71
+ message: "Choose a task to run:",
72
+ choices: Object.keys(generators).map((key) => ({
73
+ name: generators[key].name,
74
+ value: key,
75
+ })),
76
+ },
77
+ ],
78
+ actions: function (data) {
79
+ const action = {
80
+ type: "execute",
81
+ };
82
+ return [action];
83
+ },
84
+ });
85
+ }
@@ -0,0 +1 @@
1
+ export * from "./utils.mjs";
@@ -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
+ }
@@ -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
+ }