@project-selene/create-mod 0.0.7 → 0.1.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/dist/main.mjs +12 -11
- package/package.json +1 -1
- package/template/.gitignore +3 -0
- package/src/main.mts +0 -182
- package/tsconfig.json +0 -45
package/dist/main.mjs
CHANGED
|
@@ -30,15 +30,15 @@ async function copyDir(src, dest) {
|
|
|
30
30
|
}
|
|
31
31
|
async function runNpmInstall(cwd) {
|
|
32
32
|
return new Promise((resolve, reject) => {
|
|
33
|
-
const
|
|
34
|
-
|
|
33
|
+
const child = spawn("npm install", { cwd, stdio: "inherit", shell: process.platform === "win32" });
|
|
34
|
+
child.on("error", reject);
|
|
35
35
|
child.on("close", (code) => code === 0 ? resolve() : reject(new Error("npm install failed")));
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
async function runGitInit(cwd) {
|
|
39
39
|
return new Promise((resolve, reject) => {
|
|
40
|
-
const
|
|
41
|
-
|
|
40
|
+
const child = spawn("git init", { cwd, stdio: "inherit", shell: process.platform === "win32" });
|
|
41
|
+
child.on("error", reject);
|
|
42
42
|
child.on("close", (code) => code === 0 ? resolve() : reject(new Error("git init failed")));
|
|
43
43
|
});
|
|
44
44
|
}
|
|
@@ -55,19 +55,19 @@ async function askPackageFields(providedBase) {
|
|
|
55
55
|
const result = Object.assign({}, providedBase);
|
|
56
56
|
const prompts = [];
|
|
57
57
|
if (!providedBase.name) {
|
|
58
|
-
prompts.push({ name: "name", message: descriptions.name, type: "input" });
|
|
58
|
+
prompts.push({ name: "name", message: descriptions.name + ":", type: "input" });
|
|
59
59
|
}
|
|
60
60
|
if (!providedBase.description) {
|
|
61
|
-
prompts.push({ name: "description", message: descriptions.description, type: "input" });
|
|
61
|
+
prompts.push({ name: "description", message: descriptions.description + ":", type: "input" });
|
|
62
62
|
}
|
|
63
63
|
if (!providedBase.author) {
|
|
64
|
-
prompts.push({ name: "author", message: descriptions.author, type: "input" });
|
|
64
|
+
prompts.push({ name: "author", message: descriptions.author + ":", type: "input" });
|
|
65
65
|
}
|
|
66
66
|
if (!providedBase.packageName) {
|
|
67
67
|
const defaultPackageName = providedBase.name ? providedBase.name.toLowerCase().replace(/\s+/g, "-") : void 0;
|
|
68
68
|
prompts.push({
|
|
69
69
|
name: "packageName",
|
|
70
|
-
message: descriptions.packageName,
|
|
70
|
+
message: descriptions.packageName + ":",
|
|
71
71
|
type: "input",
|
|
72
72
|
default: defaultPackageName,
|
|
73
73
|
validate: (input) => {
|
|
@@ -90,7 +90,6 @@ async function askPackageFields(providedBase) {
|
|
|
90
90
|
async function applyPackageFields(pkgPath, raw, provided) {
|
|
91
91
|
const replaced = raw.replace(/<package-name>/g, provided.packageName || "").replace(/<description>/g, provided.description || "").replace(/<author>/g, provided.author || "").replace(/<uuid>/g, uuidv4()).replace(/<name>/g, provided.name || "");
|
|
92
92
|
await fsp.writeFile(pkgPath, replaced, "utf8");
|
|
93
|
-
console.log("Replaced tokens in package.json.");
|
|
94
93
|
}
|
|
95
94
|
async function main() {
|
|
96
95
|
const program = new Command();
|
|
@@ -121,8 +120,8 @@ async function main() {
|
|
|
121
120
|
packageName: opts.packageName
|
|
122
121
|
};
|
|
123
122
|
const provided = await askPackageFields(providedBase);
|
|
123
|
+
console.log("Copying template to", destPath, "...");
|
|
124
124
|
await copyDir(templatePath, destPath);
|
|
125
|
-
console.log("Template copied to", destPath);
|
|
126
125
|
const pkgPath = path.join(destPath, "package.json");
|
|
127
126
|
const pkgExists = await fsp.stat(pkgPath).then(() => true).catch(() => false);
|
|
128
127
|
if (pkgExists) {
|
|
@@ -131,7 +130,9 @@ async function main() {
|
|
|
131
130
|
}
|
|
132
131
|
console.log("Installing dependencies...");
|
|
133
132
|
await runNpmInstall(destPath);
|
|
134
|
-
console.log("
|
|
133
|
+
console.log("Installing git repository...");
|
|
134
|
+
await runGitInit(destPath).catch(() => console.warn("Git initialization failed"));
|
|
135
|
+
console.log("Done.");
|
|
135
136
|
} catch (err) {
|
|
136
137
|
console.error("Error:", err.message || err);
|
|
137
138
|
process.exit(1);
|
package/package.json
CHANGED
package/src/main.mts
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { spawn } from 'child_process';
|
|
4
|
-
import { Command } from 'commander';
|
|
5
|
-
import { promises as fsp } from 'fs';
|
|
6
|
-
import inquirer, { type DistinctQuestion } from 'inquirer';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
import { v4 as uuidv4 } from "uuid";
|
|
9
|
-
|
|
10
|
-
const __templateDir = path.resolve(import.meta.url.substring('file:///'.length), '../../template');
|
|
11
|
-
|
|
12
|
-
interface Arguments {
|
|
13
|
-
packageName?: string;
|
|
14
|
-
name?: string;
|
|
15
|
-
description?: string;
|
|
16
|
-
author?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const descriptions = {
|
|
20
|
-
name: 'The name displayed to mod users',
|
|
21
|
-
packageName: 'The name used for the npm package (no spaces, lowercase)',
|
|
22
|
-
description: 'A short description of the mod',
|
|
23
|
-
author: 'The author of the mod'
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
async function copyDir(src: string, dest: string) {
|
|
27
|
-
await fsp.mkdir(dest, { recursive: true });
|
|
28
|
-
const entries = await fsp.readdir(src, { withFileTypes: true });
|
|
29
|
-
for (const ent of entries) {
|
|
30
|
-
const srcPath = path.join(src, ent.name);
|
|
31
|
-
const destPath = path.join(dest, ent.name);
|
|
32
|
-
if (ent.isDirectory()) {
|
|
33
|
-
await copyDir(srcPath, destPath);
|
|
34
|
-
} else if (ent.isSymbolicLink()) {
|
|
35
|
-
const link = await fsp.readlink(srcPath);
|
|
36
|
-
await fsp.symlink(link, destPath);
|
|
37
|
-
} else {
|
|
38
|
-
await fsp.copyFile(srcPath, destPath);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function runNpmInstall(cwd: string) {
|
|
44
|
-
return new Promise<void>((resolve, reject) => {
|
|
45
|
-
const cmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
46
|
-
const child = spawn(cmd, ['install'], { cwd, stdio: 'inherit' });
|
|
47
|
-
child.on('close', (code) => code === 0 ? resolve() : reject(new Error('npm install failed')));
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async function runGitInit(cwd: string) {
|
|
52
|
-
return new Promise<void>((resolve, reject) => {
|
|
53
|
-
const cmd = process.platform === 'win32' ? 'git.cmd' : 'git';
|
|
54
|
-
const child = spawn(cmd, ['init'], { cwd, stdio: 'inherit' });
|
|
55
|
-
child.on('close', (code) => code === 0 ? resolve() : reject(new Error('git init failed')));
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async function askDestName(): Promise<string> {
|
|
60
|
-
const ans = await inquirer.prompt([{ name: 'dest', message: 'Project folder name:', type: 'input' }]);
|
|
61
|
-
const dest = (ans.dest || '').trim();
|
|
62
|
-
if (!dest) {
|
|
63
|
-
console.error('No folder name provided. Exiting.');
|
|
64
|
-
process.exit(1);
|
|
65
|
-
}
|
|
66
|
-
return dest;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function askPackageFields(providedBase: Arguments): Promise<Arguments> {
|
|
70
|
-
const result = Object.assign({}, providedBase);
|
|
71
|
-
const prompts: DistinctQuestion[] = [];
|
|
72
|
-
|
|
73
|
-
if (!providedBase.name) {
|
|
74
|
-
prompts.push({ name: 'name', message: descriptions.name, type: 'input' });
|
|
75
|
-
}
|
|
76
|
-
if (!providedBase.description) {
|
|
77
|
-
prompts.push({ name: 'description', message: descriptions.description, type: 'input' });
|
|
78
|
-
}
|
|
79
|
-
if (!providedBase.author) {
|
|
80
|
-
prompts.push({ name: 'author', message: descriptions.author, type: 'input' });
|
|
81
|
-
}
|
|
82
|
-
if (!providedBase.packageName) {
|
|
83
|
-
const defaultPackageName = providedBase.name ? providedBase.name.toLowerCase().replace(/\s+/g, '-') : undefined;
|
|
84
|
-
prompts.push({
|
|
85
|
-
name: 'packageName',
|
|
86
|
-
message: descriptions.packageName,
|
|
87
|
-
type: 'input',
|
|
88
|
-
default: defaultPackageName,
|
|
89
|
-
validate: (input) => {
|
|
90
|
-
if (!input) return 'Package name cannot be empty';
|
|
91
|
-
if (/\s/.test(input)) return 'Package name cannot contain spaces';
|
|
92
|
-
if (input.toLowerCase() !== input) return 'Package name must be lowercase';
|
|
93
|
-
if (!/^(?:(?:@(?:[a-z0-9-*~][a-z0-9-*._~]*)?\/[a-z0-9-._~])|[a-z0-9-~])[a-z0-9-._~]*$/.test(input)) {
|
|
94
|
-
return 'Invalid npm package name. Refer to https://docs.npmjs.com/creating-a-package-json-file#required-name-and-version-fields for rules.';
|
|
95
|
-
}
|
|
96
|
-
return true;
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (prompts.length) {
|
|
102
|
-
const answers = await inquirer.prompt(prompts);
|
|
103
|
-
for (const k of Object.keys(answers) as Array<keyof Arguments>) result[k] = answers[k] || result[k];
|
|
104
|
-
}
|
|
105
|
-
return result;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
async function applyPackageFields(pkgPath: string, raw: string, provided: Arguments) {
|
|
109
|
-
const replaced = raw
|
|
110
|
-
.replace(/<package-name>/g, provided.packageName || '')
|
|
111
|
-
.replace(/<description>/g, provided.description || '')
|
|
112
|
-
.replace(/<author>/g, provided.author || '')
|
|
113
|
-
.replace(/<uuid>/g, uuidv4())
|
|
114
|
-
.replace(/<name>/g, provided.name || '')
|
|
115
|
-
await fsp.writeFile(pkgPath, replaced, 'utf8');
|
|
116
|
-
console.log('Replaced tokens in package.json.');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async function main() {
|
|
120
|
-
const program = new Command();
|
|
121
|
-
program
|
|
122
|
-
.argument('[dir]', 'destination folder name')
|
|
123
|
-
.option('-n, --name <name>', descriptions.name)
|
|
124
|
-
.option('-p, --package-name <name>', descriptions.packageName)
|
|
125
|
-
.option('-d, --description <description>', descriptions.description)
|
|
126
|
-
.option('-a, --author <author>', descriptions.author)
|
|
127
|
-
.parse(process.argv);
|
|
128
|
-
|
|
129
|
-
program.addHelpCommand();
|
|
130
|
-
|
|
131
|
-
const opts = program.opts();
|
|
132
|
-
const destName = opts.dir || await askDestName();
|
|
133
|
-
const cwd = process.cwd();
|
|
134
|
-
const templatePath = __templateDir;
|
|
135
|
-
|
|
136
|
-
const destPath = path.join(cwd, destName);
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
const stat = await fsp.stat(templatePath);
|
|
140
|
-
if (!stat.isDirectory()) throw new Error('template is not a directory');
|
|
141
|
-
} catch (err) {
|
|
142
|
-
console.error('Could not find template directory at', templatePath);
|
|
143
|
-
process.exit(1);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
const exists = await fsp.stat(destPath).then(() => true).catch(() => false);
|
|
148
|
-
if (exists) {
|
|
149
|
-
console.error(`Destination ${destPath} already exists. Aborting.`);
|
|
150
|
-
process.exit(1);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const providedBase: Arguments = {
|
|
154
|
-
name: opts.name,
|
|
155
|
-
description: opts.description || opts.desc,
|
|
156
|
-
author: opts.author,
|
|
157
|
-
packageName: opts.packageName,
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
const provided = await askPackageFields(providedBase);
|
|
161
|
-
|
|
162
|
-
await copyDir(templatePath, destPath);
|
|
163
|
-
console.log('Template copied to', destPath);
|
|
164
|
-
|
|
165
|
-
// After copy, apply the provided package fields to the destination package.json
|
|
166
|
-
const pkgPath = path.join(destPath, 'package.json');
|
|
167
|
-
const pkgExists = await fsp.stat(pkgPath).then(() => true).catch(() => false);
|
|
168
|
-
if (pkgExists) {
|
|
169
|
-
const raw = await fsp.readFile(pkgPath, 'utf8');
|
|
170
|
-
await applyPackageFields(pkgPath, raw, provided);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
console.log('Installing dependencies...');
|
|
174
|
-
await runNpmInstall(destPath);
|
|
175
|
-
console.log('Done. Project initialized at', destPath);
|
|
176
|
-
} catch (err: any) {
|
|
177
|
-
console.error('Error:', err.message || err);
|
|
178
|
-
process.exit(1);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
main();
|
package/tsconfig.json
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// Visit https://aka.ms/tsconfig to read more about this file
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
// File Layout
|
|
5
|
-
"rootDir": "./src",
|
|
6
|
-
"outDir": "./dist",
|
|
7
|
-
|
|
8
|
-
// Environment Settings
|
|
9
|
-
// See also https://aka.ms/tsconfig/module
|
|
10
|
-
"module": "nodenext",
|
|
11
|
-
"target": "esnext",
|
|
12
|
-
// "types": [],
|
|
13
|
-
// For nodejs:
|
|
14
|
-
"lib": ["esnext"],
|
|
15
|
-
"types": ["node", "inquirer"],
|
|
16
|
-
// and npm install -D @types/node
|
|
17
|
-
|
|
18
|
-
// Other Outputs
|
|
19
|
-
"sourceMap": true,
|
|
20
|
-
"declaration": true,
|
|
21
|
-
"declarationMap": true,
|
|
22
|
-
|
|
23
|
-
// Stricter Typechecking Options
|
|
24
|
-
"noUncheckedIndexedAccess": true,
|
|
25
|
-
"exactOptionalPropertyTypes": true,
|
|
26
|
-
|
|
27
|
-
// Style Options
|
|
28
|
-
// "noImplicitReturns": true,
|
|
29
|
-
// "noImplicitOverride": true,
|
|
30
|
-
// "noUnusedLocals": true,
|
|
31
|
-
// "noUnusedParameters": true,
|
|
32
|
-
// "noFallthroughCasesInSwitch": true,
|
|
33
|
-
// "noPropertyAccessFromIndexSignature": true,
|
|
34
|
-
|
|
35
|
-
// Recommended Options
|
|
36
|
-
"strict": true,
|
|
37
|
-
"jsx": "react-jsx",
|
|
38
|
-
"verbatimModuleSyntax": true,
|
|
39
|
-
"isolatedModules": true,
|
|
40
|
-
"noUncheckedSideEffectImports": true,
|
|
41
|
-
"moduleDetection": "force",
|
|
42
|
-
"skipLibCheck": true,
|
|
43
|
-
},
|
|
44
|
-
"exclude": ["template/**/*"]
|
|
45
|
-
}
|