create-vimp-game 0.2.1 → 0.3.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.
- package/package.json +1 -1
- package/src/cli.js +7 -0
- package/src/generator.js +55 -0
- package/src/prompts.js +4 -1
- package/src/versions.generated.json +1 -1
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -26,6 +26,8 @@ export const USAGE = `Usage: create-vimp-game <directory> [options]
|
|
|
26
26
|
--title <title> human-readable title
|
|
27
27
|
--package <name> npm package name (default: @vimp-games/<id>)
|
|
28
28
|
--author <name>
|
|
29
|
+
--repository <url> project repository (URL or user/repo) — the engine links
|
|
30
|
+
to it from the game's entry form
|
|
29
31
|
--yes, -y accept all defaults, no prompts
|
|
30
32
|
--force allow a non-empty target directory
|
|
31
33
|
--no-git skip \`git init\`
|
|
@@ -39,6 +41,7 @@ const VALUE_OPTIONS = new Map([
|
|
|
39
41
|
['--title', 'title'],
|
|
40
42
|
['--package', 'packageName'],
|
|
41
43
|
['--author', 'author'],
|
|
44
|
+
['--repository', 'repository'],
|
|
42
45
|
['--engine-path', 'enginePath'],
|
|
43
46
|
['--core-path', 'corePath'],
|
|
44
47
|
]);
|
|
@@ -114,6 +117,9 @@ export function buildDefaults(args) {
|
|
|
114
117
|
title: args.title ?? defaultTitle(id),
|
|
115
118
|
packageName: args.packageName ?? defaultPackageName(id),
|
|
116
119
|
author: args.author ?? '',
|
|
120
|
+
// репозиторий не выводится из author: тот — имя человека, а не логин на
|
|
121
|
+
// хостинге, и угаданный URL уехал бы битой ссылкой в футер к игрокам
|
|
122
|
+
repository: args.repository ?? '',
|
|
117
123
|
};
|
|
118
124
|
}
|
|
119
125
|
|
|
@@ -200,6 +206,7 @@ export async function main(argv) {
|
|
|
200
206
|
force: args.force === true,
|
|
201
207
|
enginePath: args.enginePath,
|
|
202
208
|
corePath: args.corePath,
|
|
209
|
+
repository: answers.repository,
|
|
203
210
|
});
|
|
204
211
|
|
|
205
212
|
if (args.git) {
|
package/src/generator.js
CHANGED
|
@@ -144,6 +144,53 @@ async function applyEnginePath(targetDir, enginePath) {
|
|
|
144
144
|
await writeFile(file, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
// Приводит введённое человеком к голому https-адресу проекта, из которого
|
|
148
|
+
// собираются оба поля. Разбираются все формы, которые реально вводят руками:
|
|
149
|
+
// шорткат `user/repo`, строка из кнопки "Code → HTTPS" (хвост `.git`),
|
|
150
|
+
// scp-форма `git@host:a/b`, `git+`/`ssh://`/`git://`, `#readme` и слэш.
|
|
151
|
+
//
|
|
152
|
+
// Движковый resolveProjectUrl сюда не импортируется: у пакета нулевые
|
|
153
|
+
// рантайм-зависимости (см. prompts.js), а vimp-engine ему даже не
|
|
154
|
+
// зависимость. Формы держать согласованными с packages/engine/src/lib/
|
|
155
|
+
// packageLink.js — их читает та же ссылка в футере.
|
|
156
|
+
function normalizeRepositoryUrl(raw) {
|
|
157
|
+
let url = raw.trim().replace(/^git\+/, '');
|
|
158
|
+
|
|
159
|
+
if (/^[\w.-]+\/[\w.-]+$/.test(url)) {
|
|
160
|
+
return `https://github.com/${url}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// scp-форма git@host:user/repo — двоеточие здесь разделитель, не порт
|
|
164
|
+
const scp = /^git@([^:/]+):(.+)$/.exec(url);
|
|
165
|
+
|
|
166
|
+
if (scp) {
|
|
167
|
+
url = `https://${scp[1]}/${scp[2]}`;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return url
|
|
171
|
+
.replace(/^ssh:\/\/(git@)?/, 'https://')
|
|
172
|
+
.replace(/^git:\/\//, 'https://')
|
|
173
|
+
.replace(/#readme$/, '')
|
|
174
|
+
.replace(/\.git(?=$|[#?])/, '')
|
|
175
|
+
.replace(/\/+$/, '');
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Адрес проекта в package.json: движок берёт из него ссылку в футере формы
|
|
179
|
+
// входа (docs/en/client.md), а правило контракта A7 предупреждает, когда поля
|
|
180
|
+
// нет. Пишется только по явно заданному значению — угаданный URL уехал бы
|
|
181
|
+
// битой ссылкой к игрокам.
|
|
182
|
+
async function applyRepository(targetDir, repository) {
|
|
183
|
+
const url = normalizeRepositoryUrl(repository);
|
|
184
|
+
|
|
185
|
+
const file = path.join(targetDir, 'package.json');
|
|
186
|
+
const manifest = JSON.parse(await readFile(file, 'utf8'));
|
|
187
|
+
|
|
188
|
+
manifest.repository = { type: 'git', url: `git+${url}.git` };
|
|
189
|
+
manifest.homepage = `${url}#readme`;
|
|
190
|
+
|
|
191
|
+
await writeFile(file, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
|
|
192
|
+
}
|
|
193
|
+
|
|
147
194
|
async function applyCorePath(targetDir, corePath) {
|
|
148
195
|
const file = path.join(targetDir, 'Cargo.toml');
|
|
149
196
|
const patch =
|
|
@@ -171,6 +218,7 @@ export async function generate({
|
|
|
171
218
|
force = false,
|
|
172
219
|
enginePath,
|
|
173
220
|
corePath,
|
|
221
|
+
repository = '',
|
|
174
222
|
}) {
|
|
175
223
|
await ensureTargetDir(targetDir, { force });
|
|
176
224
|
|
|
@@ -185,6 +233,13 @@ export async function generate({
|
|
|
185
233
|
await applyEnginePath(targetDir, enginePath);
|
|
186
234
|
}
|
|
187
235
|
|
|
236
|
+
if (
|
|
237
|
+
(repository ?? '').trim() !== '' &&
|
|
238
|
+
(await exists(path.join(targetDir, 'package.json')))
|
|
239
|
+
) {
|
|
240
|
+
await applyRepository(targetDir, repository);
|
|
241
|
+
}
|
|
242
|
+
|
|
188
243
|
if (
|
|
189
244
|
corePath !== undefined &&
|
|
190
245
|
(await exists(path.join(targetDir, 'Cargo.toml')))
|
package/src/prompts.js
CHANGED
|
@@ -29,7 +29,7 @@ export async function ask(question, fallback = '') {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// переспрос на месте: без него невалидный id всплывал бы TokenError-ом уже
|
|
32
|
-
// после всех
|
|
32
|
+
// после всех шести вопросов, и вводить пришлось бы заново
|
|
33
33
|
export async function askValid(question, fallback, isValid, hint) {
|
|
34
34
|
for (;;) {
|
|
35
35
|
const answer = await ask(question, fallback);
|
|
@@ -72,6 +72,9 @@ export async function askAnswers(defaults, { interactive = true, derive } = {})
|
|
|
72
72
|
'expected an npm package name, e.g. @vimp-games/space-arena',
|
|
73
73
|
),
|
|
74
74
|
author: await ask('Author', defaults.author),
|
|
75
|
+
// пустой ответ допустим: поля repository тогда не будет вовсе, о чём
|
|
76
|
+
// скажет правило контракта A7
|
|
77
|
+
repository: await ask('Repository (URL or user/repo)', defaults.repository),
|
|
75
78
|
};
|
|
76
79
|
} finally {
|
|
77
80
|
closePrompts();
|