@vlandoss/vland 0.1.1 → 0.1.2-git-87ebfca.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/cli.usage.kdl +3 -1
- package/dist/run.mjs +42 -15
- package/package.json +3 -3
- package/src/actions/init.ts +29 -19
- package/src/program/commands/init.ts +7 -1
- package/src/services/ctx.ts +1 -3
package/dist/cli.usage.kdl
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @generated by @usage-spec/commander from Commander.js metadata
|
|
2
2
|
name vland
|
|
3
3
|
bin vland
|
|
4
|
-
version "0.1.
|
|
4
|
+
version "0.1.2-git-87ebfca.0"
|
|
5
5
|
usage "[options] [command]"
|
|
6
6
|
flag --usage help="print KDL spec for this CLI (https://kdl.dev)"
|
|
7
7
|
cmd completion help="print shell completion script 🐚 (usage)" {
|
|
@@ -25,7 +25,9 @@ cmd init help="init a new project 🚀 (giget)" {
|
|
|
25
25
|
choices npm pnpm yarn bun
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
flag --install help="install dependencies (skip prompt)"
|
|
28
29
|
flag --no-install help="skip dependency installation" negate=--install
|
|
30
|
+
flag --git help="initialise git repository (skip prompt)"
|
|
29
31
|
flag --no-git help="skip git init" negate=--git
|
|
30
32
|
flag "-f --force" help="overwrite existing directory"
|
|
31
33
|
arg "[name]" help="project name (also used as the target directory)" required=#false
|
package/dist/run.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { Argument, Command, Option, createCommand } from "commander";
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import { createLoggy } from "@vlandoss/loggy";
|
|
6
6
|
import { cp, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
7
|
-
import { cancel, intro, isCancel, log, outro, select, spinner, text as text$1 } from "@clack/prompts";
|
|
7
|
+
import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text as text$1 } from "@clack/prompts";
|
|
8
8
|
import { detectPackageManager, installDependencies } from "nypm";
|
|
9
9
|
import { downloadTemplate } from "giget";
|
|
10
10
|
import { generateToStdout } from "@usage-spec/commander";
|
|
@@ -19,7 +19,7 @@ async function createContext(binDir) {
|
|
|
19
19
|
const binPkg = await createPkg(binPath);
|
|
20
20
|
if (!binPkg) throw new Error("Could not find bin package.json");
|
|
21
21
|
debug("bin pkg info: %O", binPkg.info());
|
|
22
|
-
const shell = createShellService(
|
|
22
|
+
const shell = createShellService();
|
|
23
23
|
debug("shell service options: %O", shell.options);
|
|
24
24
|
return {
|
|
25
25
|
binPkg,
|
|
@@ -230,7 +230,15 @@ async function isDirEmpty(dir) {
|
|
|
230
230
|
}
|
|
231
231
|
async function readGitAuthor(shell) {
|
|
232
232
|
try {
|
|
233
|
-
const [name, email] = await Promise.all([shell
|
|
233
|
+
const [name, email] = await Promise.all([shell.runCaptured("git", [
|
|
234
|
+
"config",
|
|
235
|
+
"--get",
|
|
236
|
+
"user.name"
|
|
237
|
+
], { throwOnError: false }), shell.runCaptured("git", [
|
|
238
|
+
"config",
|
|
239
|
+
"--get",
|
|
240
|
+
"user.email"
|
|
241
|
+
], { throwOnError: false })]);
|
|
234
242
|
const trimmedName = name.stdout.trim();
|
|
235
243
|
const trimmedEmail = email.stdout.trim();
|
|
236
244
|
if (!trimmedName) return void 0;
|
|
@@ -246,7 +254,7 @@ function abort(message) {
|
|
|
246
254
|
async function runInit(ctx, options) {
|
|
247
255
|
const debug = logger.subdebug("init");
|
|
248
256
|
debug("options: %O", options);
|
|
249
|
-
const shell = ctx.shell
|
|
257
|
+
const shell = ctx.shell;
|
|
250
258
|
intro(`${palette.label(" vland init ")}`);
|
|
251
259
|
let template = options.template;
|
|
252
260
|
if (!template) {
|
|
@@ -311,7 +319,9 @@ async function runInit(ctx, options) {
|
|
|
311
319
|
});
|
|
312
320
|
await updateRootPackageName(dir, name);
|
|
313
321
|
placeholderSpin.stop("Placeholders applied");
|
|
314
|
-
|
|
322
|
+
const shouldInstall = await resolveYesNo(options.install, "Install dependencies?");
|
|
323
|
+
const shouldGit = await resolveYesNo(options.git, "Initialise a git repository?");
|
|
324
|
+
if (shouldInstall) {
|
|
315
325
|
const detected = options.pm ?? (await detectPackageManager(dir, { ignorePackageJSON: false }))?.name ?? "pnpm";
|
|
316
326
|
const installSpin = spinner();
|
|
317
327
|
installSpin.start(`Installing dependencies with ${palette.highlight(detected)}`);
|
|
@@ -329,36 +339,49 @@ async function runInit(ctx, options) {
|
|
|
329
339
|
log.warn("You can install manually later with `cd <dir> && <pm> install`.");
|
|
330
340
|
debug("install error: %O", error);
|
|
331
341
|
}
|
|
332
|
-
} else log.info(`Skipping ${palette.highlight("install")}
|
|
333
|
-
if (
|
|
342
|
+
} else log.info(`Skipping ${palette.highlight("install")}.`);
|
|
343
|
+
if (shouldGit) {
|
|
334
344
|
const gitSpin = spinner();
|
|
335
345
|
gitSpin.start("Initialising git repository");
|
|
336
346
|
try {
|
|
337
347
|
const gitShell = shell.at(dir).child({ env: {
|
|
338
|
-
...process.env,
|
|
339
348
|
GIT_AUTHOR_NAME: process.env.GIT_AUTHOR_NAME ?? "vland",
|
|
340
349
|
GIT_AUTHOR_EMAIL: process.env.GIT_AUTHOR_EMAIL ?? "noreply@variable.land",
|
|
341
350
|
GIT_COMMITTER_NAME: process.env.GIT_COMMITTER_NAME ?? "vland",
|
|
342
351
|
GIT_COMMITTER_EMAIL: process.env.GIT_COMMITTER_EMAIL ?? "noreply@variable.land"
|
|
343
352
|
} });
|
|
344
|
-
await gitShell
|
|
345
|
-
await gitShell
|
|
346
|
-
await gitShell
|
|
353
|
+
await gitShell.runCaptured("git", ["init"]);
|
|
354
|
+
await gitShell.runCaptured("git", ["add", "-A"]);
|
|
355
|
+
await gitShell.runCaptured("git", [
|
|
356
|
+
"commit",
|
|
357
|
+
"-m",
|
|
358
|
+
"chore: initial commit from vland"
|
|
359
|
+
]);
|
|
347
360
|
gitSpin.stop("Initialised git repository");
|
|
348
361
|
} catch (error) {
|
|
349
362
|
gitSpin.stop("Failed to initialise git", 1);
|
|
350
363
|
debug("git error: %O", error);
|
|
351
364
|
}
|
|
352
|
-
} else log.info(`Skipping ${palette.highlight("git init")}
|
|
365
|
+
} else log.info(`Skipping ${palette.highlight("git init")}.`);
|
|
353
366
|
const detectedPm = options.pm ?? (await detectPackageManager(dir, { ignorePackageJSON: false }))?.name ?? "pnpm";
|
|
354
367
|
outro([
|
|
355
368
|
palette.success("Done!"),
|
|
356
369
|
"",
|
|
357
370
|
palette.muted("Next steps:"),
|
|
358
371
|
` cd ${name}`,
|
|
359
|
-
|
|
372
|
+
shouldInstall ? ` ${detectedPm} dev` : ` ${detectedPm} install && ${detectedPm} dev`
|
|
360
373
|
].join("\n"));
|
|
361
374
|
}
|
|
375
|
+
async function resolveYesNo(explicit, message) {
|
|
376
|
+
if (typeof explicit === "boolean") return explicit;
|
|
377
|
+
if (!hasTTY) return true;
|
|
378
|
+
const value = await confirm({
|
|
379
|
+
message,
|
|
380
|
+
initialValue: true
|
|
381
|
+
});
|
|
382
|
+
if (isCancel(value)) abort("Cancelled.");
|
|
383
|
+
return value;
|
|
384
|
+
}
|
|
362
385
|
//#endregion
|
|
363
386
|
//#region src/program/commands/init.ts
|
|
364
387
|
function createInitCommand(ctx) {
|
|
@@ -367,11 +390,15 @@ function createInitCommand(ctx) {
|
|
|
367
390
|
"pnpm",
|
|
368
391
|
"yarn",
|
|
369
392
|
"bun"
|
|
370
|
-
])).addOption(new Option("--no-install", "skip dependency installation")).addOption(new Option("--no-git", "skip git init")).addOption(new Option("-f, --force", "overwrite existing directory").default(false)).action(async (name, options)
|
|
393
|
+
])).addOption(new Option("--install", "install dependencies (skip prompt)")).addOption(new Option("--no-install", "skip dependency installation")).addOption(new Option("--git", "initialise git repository (skip prompt)")).addOption(new Option("--no-git", "skip git init")).addOption(new Option("-f, --force", "overwrite existing directory").default(false)).action(async function(name, options) {
|
|
371
394
|
console.log(getBannerText(ctx.binPkg.version));
|
|
395
|
+
const installSource = this.getOptionValueSource("install");
|
|
396
|
+
const gitSource = this.getOptionValueSource("git");
|
|
372
397
|
await runInit(ctx, {
|
|
373
398
|
name,
|
|
374
|
-
...options
|
|
399
|
+
...options,
|
|
400
|
+
install: installSource === "cli" ? options.install : void 0,
|
|
401
|
+
git: gitSource === "cli" ? options.git : void 0
|
|
375
402
|
});
|
|
376
403
|
});
|
|
377
404
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vlandoss/vland",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2-git-87ebfca.0",
|
|
4
4
|
"description": "The CLI to init a new project in Variable Land",
|
|
5
5
|
"homepage": "https://github.com/variableland/dx/tree/main/packages/vland#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"commander": "14.0.3",
|
|
36
36
|
"giget": "2.0.0",
|
|
37
37
|
"nypm": "0.6.0",
|
|
38
|
-
"@vlandoss/
|
|
39
|
-
"@vlandoss/
|
|
38
|
+
"@vlandoss/loggy": "0.2.0",
|
|
39
|
+
"@vlandoss/clibuddy": "0.5.1-git-87ebfca.0"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public"
|
package/src/actions/init.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readdir } from "node:fs/promises";
|
|
2
2
|
import { isAbsolute, resolve } from "node:path";
|
|
3
|
-
import { cancel, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
|
|
3
|
+
import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text } from "@clack/prompts";
|
|
4
4
|
import { hasTTY, palette } from "@vlandoss/clibuddy";
|
|
5
5
|
import { detectPackageManager, installDependencies } from "nypm";
|
|
6
6
|
import type { Context } from "#src/services/ctx.ts";
|
|
@@ -13,8 +13,8 @@ export type InitOptions = {
|
|
|
13
13
|
template?: TemplateName;
|
|
14
14
|
dir?: string;
|
|
15
15
|
pm?: "npm" | "pnpm" | "yarn" | "bun";
|
|
16
|
-
install
|
|
17
|
-
git
|
|
16
|
+
install?: boolean;
|
|
17
|
+
git?: boolean;
|
|
18
18
|
force: boolean;
|
|
19
19
|
};
|
|
20
20
|
|
|
@@ -46,8 +46,8 @@ async function isDirEmpty(dir: string): Promise<boolean> {
|
|
|
46
46
|
async function readGitAuthor(shell: Context["shell"]): Promise<string | undefined> {
|
|
47
47
|
try {
|
|
48
48
|
const [name, email] = await Promise.all([
|
|
49
|
-
shell
|
|
50
|
-
shell
|
|
49
|
+
shell.runCaptured("git", ["config", "--get", "user.name"], { throwOnError: false }),
|
|
50
|
+
shell.runCaptured("git", ["config", "--get", "user.email"], { throwOnError: false }),
|
|
51
51
|
]);
|
|
52
52
|
const trimmedName = name.stdout.trim();
|
|
53
53
|
const trimmedEmail = email.stdout.trim();
|
|
@@ -67,8 +67,7 @@ export async function runInit(ctx: Context, options: InitOptions) {
|
|
|
67
67
|
const debug = logger.subdebug("init");
|
|
68
68
|
debug("options: %O", options);
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
const shell = ctx.shell.mute();
|
|
70
|
+
const shell = ctx.shell;
|
|
72
71
|
|
|
73
72
|
intro(`${palette.label(" vland init ")}`);
|
|
74
73
|
|
|
@@ -153,8 +152,12 @@ export async function runInit(ctx: Context, options: InitOptions) {
|
|
|
153
152
|
await updateRootPackageName(dir, name);
|
|
154
153
|
placeholderSpin.stop("Placeholders applied");
|
|
155
154
|
|
|
156
|
-
// 7.
|
|
157
|
-
|
|
155
|
+
// 7. Resolve install / git decisions (prompt with default-yes when not set on CLI)
|
|
156
|
+
const shouldInstall = await resolveYesNo(options.install, "Install dependencies?");
|
|
157
|
+
const shouldGit = await resolveYesNo(options.git, "Initialise a git repository?");
|
|
158
|
+
|
|
159
|
+
// 8. Install deps
|
|
160
|
+
if (shouldInstall) {
|
|
158
161
|
const detected = options.pm ?? (await detectPackageManager(dir, { ignorePackageJSON: false }))?.name ?? "pnpm";
|
|
159
162
|
const installSpin = spinner();
|
|
160
163
|
installSpin.start(`Installing dependencies with ${palette.highlight(detected)}`);
|
|
@@ -167,36 +170,35 @@ export async function runInit(ctx: Context, options: InitOptions) {
|
|
|
167
170
|
debug("install error: %O", error);
|
|
168
171
|
}
|
|
169
172
|
} else {
|
|
170
|
-
log.info(`Skipping ${palette.highlight("install")}
|
|
173
|
+
log.info(`Skipping ${palette.highlight("install")}.`);
|
|
171
174
|
}
|
|
172
175
|
|
|
173
|
-
//
|
|
174
|
-
if (
|
|
176
|
+
// 9. Git init
|
|
177
|
+
if (shouldGit) {
|
|
175
178
|
const gitSpin = spinner();
|
|
176
179
|
gitSpin.start("Initialising git repository");
|
|
177
180
|
try {
|
|
178
181
|
const gitShell = shell.at(dir).child({
|
|
179
182
|
env: {
|
|
180
|
-
...process.env,
|
|
181
183
|
GIT_AUTHOR_NAME: process.env.GIT_AUTHOR_NAME ?? "vland",
|
|
182
184
|
GIT_AUTHOR_EMAIL: process.env.GIT_AUTHOR_EMAIL ?? "noreply@variable.land",
|
|
183
185
|
GIT_COMMITTER_NAME: process.env.GIT_COMMITTER_NAME ?? "vland",
|
|
184
186
|
GIT_COMMITTER_EMAIL: process.env.GIT_COMMITTER_EMAIL ?? "noreply@variable.land",
|
|
185
187
|
},
|
|
186
188
|
});
|
|
187
|
-
await gitShell
|
|
188
|
-
await gitShell
|
|
189
|
-
await gitShell
|
|
189
|
+
await gitShell.runCaptured("git", ["init"]);
|
|
190
|
+
await gitShell.runCaptured("git", ["add", "-A"]);
|
|
191
|
+
await gitShell.runCaptured("git", ["commit", "-m", "chore: initial commit from vland"]);
|
|
190
192
|
gitSpin.stop("Initialised git repository");
|
|
191
193
|
} catch (error) {
|
|
192
194
|
gitSpin.stop("Failed to initialise git", 1);
|
|
193
195
|
debug("git error: %O", error);
|
|
194
196
|
}
|
|
195
197
|
} else {
|
|
196
|
-
log.info(`Skipping ${palette.highlight("git init")}
|
|
198
|
+
log.info(`Skipping ${palette.highlight("git init")}.`);
|
|
197
199
|
}
|
|
198
200
|
|
|
199
|
-
//
|
|
201
|
+
// 10. Outro with next steps
|
|
200
202
|
const detectedPm = options.pm ?? (await detectPackageManager(dir, { ignorePackageJSON: false }))?.name ?? "pnpm";
|
|
201
203
|
outro(
|
|
202
204
|
[
|
|
@@ -204,7 +206,15 @@ export async function runInit(ctx: Context, options: InitOptions) {
|
|
|
204
206
|
"",
|
|
205
207
|
palette.muted("Next steps:"),
|
|
206
208
|
` cd ${name}`,
|
|
207
|
-
|
|
209
|
+
shouldInstall ? ` ${detectedPm} dev` : ` ${detectedPm} install && ${detectedPm} dev`,
|
|
208
210
|
].join("\n"),
|
|
209
211
|
);
|
|
210
212
|
}
|
|
213
|
+
|
|
214
|
+
async function resolveYesNo(explicit: boolean | undefined, message: string): Promise<boolean> {
|
|
215
|
+
if (typeof explicit === "boolean") return explicit;
|
|
216
|
+
if (!hasTTY) return true;
|
|
217
|
+
const value = await confirm({ message, initialValue: true });
|
|
218
|
+
if (isCancel(value)) abort("Cancelled.");
|
|
219
|
+
return value as boolean;
|
|
220
|
+
}
|
|
@@ -21,14 +21,20 @@ export function createInitCommand(ctx: Context) {
|
|
|
21
21
|
.addOption(new Option("-t, --template <name>", "template to use").choices([...TEMPLATES]))
|
|
22
22
|
.addOption(new Option("-d, --dir <path>", "target directory (default: ./<name>)"))
|
|
23
23
|
.addOption(new Option("--pm <manager>", "package manager to use").choices(["npm", "pnpm", "yarn", "bun"]))
|
|
24
|
+
.addOption(new Option("--install", "install dependencies (skip prompt)"))
|
|
24
25
|
.addOption(new Option("--no-install", "skip dependency installation"))
|
|
26
|
+
.addOption(new Option("--git", "initialise git repository (skip prompt)"))
|
|
25
27
|
.addOption(new Option("--no-git", "skip git init"))
|
|
26
28
|
.addOption(new Option("-f, --force", "overwrite existing directory").default(false))
|
|
27
|
-
.action(async (name: string | undefined, options: InitOptions)
|
|
29
|
+
.action(async function (this: import("commander").Command, name: string | undefined, options: InitOptions) {
|
|
28
30
|
console.log(getBannerText(ctx.binPkg.version));
|
|
31
|
+
const installSource = this.getOptionValueSource("install");
|
|
32
|
+
const gitSource = this.getOptionValueSource("git");
|
|
29
33
|
await runInit(ctx, {
|
|
30
34
|
name,
|
|
31
35
|
...options,
|
|
36
|
+
install: installSource === "cli" ? options.install : undefined,
|
|
37
|
+
git: gitSource === "cli" ? options.git : undefined,
|
|
32
38
|
});
|
|
33
39
|
});
|
|
34
40
|
}
|
package/src/services/ctx.ts
CHANGED
|
@@ -22,9 +22,7 @@ export async function createContext(binDir: string): Promise<Context> {
|
|
|
22
22
|
|
|
23
23
|
debug("bin pkg info: %O", binPkg.info());
|
|
24
24
|
|
|
25
|
-
const shell = createShellService(
|
|
26
|
-
localBaseBinPath: [binDir],
|
|
27
|
-
});
|
|
25
|
+
const shell = createShellService();
|
|
28
26
|
|
|
29
27
|
debug("shell service options: %O", shell.options);
|
|
30
28
|
|