cami-cli 1.0.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.
Files changed (2) hide show
  1. package/index.js +169 -0
  2. package/package.json +30 -0
package/index.js ADDED
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+
3
+ import * as p from "@clack/prompts";
4
+ import degit from "degit";
5
+ import { setTimeout as sleep } from "node:timers/promises";
6
+ import fs from "fs";
7
+ import { exec } from "node:child_process";
8
+ import { promisify } from "node:util";
9
+
10
+ const VISUAL_LINK = "https://github.com/Cellular-Automaton/VisualSkeleton"
11
+ const PLUGIN_LINK = "https://github.com/Cellular-Automaton/PluginSkeleton"
12
+
13
+
14
+ const execAsync = promisify(exec);
15
+
16
+ async function main() {
17
+ let flag = false;
18
+ let projectName;
19
+ console.clear();
20
+
21
+ await sleep(1000);
22
+ p.intro("Welcome to the CAMI cli!");
23
+
24
+ while (!flag) {
25
+ projectName = await p.text({
26
+ message: "How do you want to name your project?",
27
+ placeholder: "Type your project name here",
28
+ });
29
+
30
+ if (p.isCancel(projectName)) {
31
+ p.cancel("Operation cancelled. Goodbye!");
32
+ process.exit(0);
33
+ }
34
+
35
+ if (fs.existsSync(projectName)) {
36
+ p.note(`A folder named "${projectName}" already exists. Please choose a different name.`);
37
+ continue;
38
+ }
39
+
40
+ flag = true;
41
+ };
42
+
43
+ const type = await p.select({
44
+ message: "Select the type of project you want to create",
45
+ options: [
46
+ { label: "Plugin (A new system to extend functionality)", value: "plugin" },
47
+ { label: "Visual (A new system to visualize plugins)", value: "visual" },
48
+ ],
49
+ });
50
+
51
+ if (p.isCancel(type)) {
52
+ p.cancel("Operation cancelled. Goodbye!");
53
+ process.exit(0);
54
+ }
55
+
56
+ if (type === "plugin") {
57
+ await createPlugin(projectName);
58
+ } else if (type === "visual") {
59
+ await createVisual(projectName);
60
+ }
61
+
62
+ p.outro("Project setup complete! Happy coding!");
63
+ }
64
+
65
+ async function createVisual(projectName) {
66
+ const s = p.spinner();
67
+ const response = await p.select({
68
+ message: "Do you want a base project with a grid and PixiJS setup?",
69
+ options: [
70
+ { label: "Yes", value: true },
71
+ { label: "No", value: false },
72
+ ],
73
+ });
74
+
75
+ s.start("Creating your project...");
76
+
77
+ await degit(VISUAL_LINK, {
78
+ cache: false,
79
+ force: true,
80
+ verbose: true,
81
+ }).clone(projectName);
82
+
83
+ if (!response) {
84
+ await fs.promises.rm(`${projectName}/src/components/PixiRenderer.jsx`, { recursive: true, force: true });
85
+ await fs.promises.rm(`${projectName}/src/hooks/useGrid.js`, { recursive: true, force: true });
86
+ await fs.promises.rm(`${projectName}/src/App.jsx`, { recursive: true, force: true });
87
+ await fs.promises.appendFile(`${projectName}/src/App.jsx`,
88
+ `import React from 'react';\n\nfunction App() {\n return (\n <div className="flex w-full h-screen justify-center items-center bg-gray-950">\n <h1 className="text-3xl text-white/80">Welcome to your Visual Project!</h1>\n </div>\n );\n}\n\nexport default App;\n`
89
+ );
90
+ }
91
+
92
+ try {
93
+ await execAsync(`git init`, { cwd: projectName });
94
+ } catch (error) {
95
+ console.error("Error initializing git repository:", error);
96
+ }
97
+
98
+ s.stop("Project created successfully!");
99
+ }
100
+
101
+ async function createPlugin(projectName) {
102
+ const s = p.spinner();
103
+ s.start("Creating your plugin project...");
104
+
105
+ projectName = projectName.replace(/\s+/g, '-').toLowerCase();
106
+
107
+ try {
108
+ await degit(PLUGIN_LINK, {
109
+ cache: false,
110
+ force: true,
111
+ verbose: true,
112
+ }).clone(projectName);
113
+
114
+ await modifyName(projectName, projectName);
115
+ await execAsync(`git init`, { cwd: projectName });
116
+
117
+ } catch (error) {
118
+ console.error("Error initializing git repository:", error);
119
+ }
120
+ s.stop("Plugin project created successfully!");
121
+ }
122
+
123
+ /**
124
+ * Recursively traverses a directory and modifies files by replacing template placeholders with the project name.
125
+ *
126
+ * @async
127
+ * @param {string} path - The directory path to traverse
128
+ * @param {string} projectName - The project name to use for file modifications
129
+ * @returns {Promise<void>}
130
+ */
131
+ async function modifyName(path, projectName) {
132
+ const files = fs.readdirSync(path);
133
+
134
+ for (const file of files) {
135
+ if (fs.lstatSync(`${path}/${file}`).isDirectory()) {
136
+ await modifyName(`${path}/${file}`, projectName);
137
+ } else {
138
+ await modifyFile(`${path}/${file}`, projectName);
139
+ }
140
+ }
141
+ }
142
+
143
+
144
+ /**
145
+ * Modifies a file by replacing all occurrences of $NAME$ with the provided project name.
146
+ *
147
+ * @async
148
+ * @param {string} path - The file path to read and modify.
149
+ * @param {string} projectName - The project name to replace $NAME$ placeholders with.
150
+ * @returns {Promise<void>} A promise that resolves when the file has been modified and saved.
151
+ */
152
+ async function modifyFile(path, projectName) {
153
+ let content = fs.readFileSync(path, 'utf8');
154
+
155
+ // Replace all occurrences of $NAME$ with the project name in the file
156
+ content = content.replace(/\$NAME\$/g, projectName);
157
+ fs.writeFileSync(path, content, 'utf8');
158
+
159
+ // Replace all occurrences of $NAME$ in the filename
160
+ const newPath = path.replace(/\$NAME\$/g, projectName);
161
+ if (newPath !== path) {
162
+ fs.renameSync(path, newPath);
163
+ }
164
+ }
165
+
166
+ main().catch((err) => {
167
+ console.error(err);
168
+ process.exit(1);
169
+ });
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "dependencies": {
3
+ "@clack/core": "^0.5.0",
4
+ "@clack/prompts": "^0.11.0",
5
+ "degit": "^2.8.4"
6
+ },
7
+ "name": "cami-cli",
8
+ "version": "1.0.0",
9
+ "description": "",
10
+ "main": "index.js",
11
+ "scripts": {
12
+ "start": "node index.js",
13
+ "test": "echo \"No tests yet. Run: npm start\""
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/Cellular-Automaton/CAMI-CLI.git"
18
+ },
19
+ "bin": {
20
+ "cami": "./index.js"
21
+ },
22
+ "keywords": [],
23
+ "author": "",
24
+ "license": "ISC",
25
+ "type": "module",
26
+ "bugs": {
27
+ "url": "https://github.com/Cellular-Automaton/CAMI-CLI/issues"
28
+ },
29
+ "homepage": "https://github.com/Cellular-Automaton/CAMI-CLI#readme"
30
+ }