@vincentt-xr/cli 0.12.1 → 0.12.3
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/args.d.ts +19 -0
- package/dist/cli/args.js +24 -0
- package/dist/cli/index.js +29 -1
- package/dist/cli/usage-text.js +8 -2
- package/package.json +2 -2
package/dist/cli/args.d.ts
CHANGED
|
@@ -51,3 +51,22 @@ export declare function refusedFlag(args: string[]): string | undefined;
|
|
|
51
51
|
* the worst kind for an identifier that decides which project a folder points at.
|
|
52
52
|
*/
|
|
53
53
|
export declare function positionalArgs(args: string[]): string[];
|
|
54
|
+
/**
|
|
55
|
+
* Does this `create` invocation name a folder that `--dir` already points at?
|
|
56
|
+
*
|
|
57
|
+
* `--dir` says WHERE TO WORK; the positional says WHAT TO CREATE INSIDE it. They
|
|
58
|
+
* compose, so `--dir ~/apps/foo foo` writes `~/apps/foo/foo` — correct by the
|
|
59
|
+
* rules and almost never what was meant. The help said `--dir <path> (project
|
|
60
|
+
* dir)` under "Common options", which reads as *the project's own directory*
|
|
61
|
+
* rather than *the parent of it*, so an agent handed a folder path and a name
|
|
62
|
+
* passes both and gets a doubled path.
|
|
63
|
+
*
|
|
64
|
+
* Returns the resolved `--dir` when the collision is present, so the caller can
|
|
65
|
+
* name both correct forms; `undefined` otherwise.
|
|
66
|
+
*
|
|
67
|
+
* EXACT match on the last path segment only. A near miss (`foo-app` in `foo/`)
|
|
68
|
+
* is left alone: inferring intent from a similar name would refuse work that was
|
|
69
|
+
* never ambiguous. Trailing separators are normalised by `resolve` first, so
|
|
70
|
+
* `--dir ~/apps/foo/` behaves the same as without.
|
|
71
|
+
*/
|
|
72
|
+
export declare function createDirCollision(dirFlag: string | undefined, name: string, resolve: (p: string) => string, basename: (p: string) => string): string | undefined;
|
package/dist/cli/args.js
CHANGED
|
@@ -142,3 +142,27 @@ export function positionalArgs(args) {
|
|
|
142
142
|
}
|
|
143
143
|
return out;
|
|
144
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Does this `create` invocation name a folder that `--dir` already points at?
|
|
147
|
+
*
|
|
148
|
+
* `--dir` says WHERE TO WORK; the positional says WHAT TO CREATE INSIDE it. They
|
|
149
|
+
* compose, so `--dir ~/apps/foo foo` writes `~/apps/foo/foo` — correct by the
|
|
150
|
+
* rules and almost never what was meant. The help said `--dir <path> (project
|
|
151
|
+
* dir)` under "Common options", which reads as *the project's own directory*
|
|
152
|
+
* rather than *the parent of it*, so an agent handed a folder path and a name
|
|
153
|
+
* passes both and gets a doubled path.
|
|
154
|
+
*
|
|
155
|
+
* Returns the resolved `--dir` when the collision is present, so the caller can
|
|
156
|
+
* name both correct forms; `undefined` otherwise.
|
|
157
|
+
*
|
|
158
|
+
* EXACT match on the last path segment only. A near miss (`foo-app` in `foo/`)
|
|
159
|
+
* is left alone: inferring intent from a similar name would refuse work that was
|
|
160
|
+
* never ambiguous. Trailing separators are normalised by `resolve` first, so
|
|
161
|
+
* `--dir ~/apps/foo/` behaves the same as without.
|
|
162
|
+
*/
|
|
163
|
+
export function createDirCollision(dirFlag, name, resolve, basename) {
|
|
164
|
+
if (dirFlag === undefined)
|
|
165
|
+
return undefined;
|
|
166
|
+
const resolved = resolve(dirFlag);
|
|
167
|
+
return basename(resolved) === name ? resolved : undefined;
|
|
168
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -48,7 +48,7 @@ import { nudgeFor } from "../dx/nudge.js";
|
|
|
48
48
|
import { FETCH_TIMEOUT_MS, isFresh, updateNotice } from "../dx/updateCheck.js";
|
|
49
49
|
import { fetchLatest, loadCache, saveCache } from "../dx/updateCheckIo.js";
|
|
50
50
|
import { verbOf } from "../dx/skeleton.js";
|
|
51
|
-
import { createSourceFlagRefusal, fromFlagConflict, isHelpInvocation, isVersionInvocation, positionalArgs, refusedFlag, } from "./args.js";
|
|
51
|
+
import { createDirCollision, createSourceFlagRefusal, fromFlagConflict, isHelpInvocation, isVersionInvocation, positionalArgs, refusedFlag, } from "./args.js";
|
|
52
52
|
import { parseSourceRef } from "../lib/sourceRef.js";
|
|
53
53
|
import { printCreateSourceFlagRefusal, printFlagConflict, printSourceRefFailure, } from "../lib/sourceRefCopy.js";
|
|
54
54
|
import { registerAfterScaffold } from "../lib/initFrom.js";
|
|
@@ -291,6 +291,34 @@ async function create() {
|
|
|
291
291
|
process.exitCode = 1;
|
|
292
292
|
return;
|
|
293
293
|
}
|
|
294
|
+
// `--dir` says WHERE TO WORK; the positional says WHAT TO CREATE INSIDE it.
|
|
295
|
+
// They compose, so `--dir ~/apps/foo foo` writes `~/apps/foo/foo` — correct
|
|
296
|
+
// by the rules and almost never what was meant.
|
|
297
|
+
//
|
|
298
|
+
// Refused rather than silently resolved, because both readings are defensible
|
|
299
|
+
// and the CLI cannot tell them apart: someone who genuinely wants a nested
|
|
300
|
+
// `foo/foo` has a way to say so (below), and someone who does not gets the
|
|
301
|
+
// mistake at the moment it is cheap instead of after a scaffold and a
|
|
302
|
+
// registration.
|
|
303
|
+
//
|
|
304
|
+
// This fires on an EXACT match of the last path segment only. A near miss is
|
|
305
|
+
// left alone: guessing at intent from a similar name would refuse work that
|
|
306
|
+
// was never ambiguous.
|
|
307
|
+
const collided = createDirCollision(flag("--dir"), safe, path.resolve, path.basename);
|
|
308
|
+
if (collided !== undefined) {
|
|
309
|
+
const parent = path.dirname(collided);
|
|
310
|
+
print(`✗ That would create "${safe}" inside a folder already called "${safe}".`);
|
|
311
|
+
print("");
|
|
312
|
+
print(" --dir is where to work; the name is the folder to create inside it.");
|
|
313
|
+
print("");
|
|
314
|
+
print(` For ${path.join(parent, safe)}:`);
|
|
315
|
+
print(` vincentt create --dir ${parent} ${safe}`);
|
|
316
|
+
print("");
|
|
317
|
+
print(` For ${path.join(collided, safe)}, which is what this asked for:`);
|
|
318
|
+
print(` cd ${collided} && vincentt create ${safe}`);
|
|
319
|
+
process.exitCode = 1;
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
294
322
|
dir = safe;
|
|
295
323
|
}
|
|
296
324
|
const interactive = Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY);
|
package/dist/cli/usage-text.js
CHANGED
|
@@ -21,7 +21,12 @@ export const USAGE_TEXT = `Vincentt CLI — local-first AR dev loop\n\n` +
|
|
|
21
21
|
` [--from <owner>/<repo>@<tag>] Clone a gallery template\n` +
|
|
22
22
|
` and register it [--name <s>] [--slug <s>]\n` +
|
|
23
23
|
` create [name] Register a project and reserve its address; scaffolds first\n` +
|
|
24
|
-
` if the folder is empty
|
|
24
|
+
` if the folder is empty. The name is a NEW folder created\n` +
|
|
25
|
+
` inside the working dir, not the working dir itself:\n` +
|
|
26
|
+
` vincentt create my-app -> ./my-app\n` +
|
|
27
|
+
` vincentt create --dir ~/code my-app -> ~/code/my-app\n` +
|
|
28
|
+
` Omit the name to use the current folder as-is.\n` +
|
|
29
|
+
` [--name <s>] [--slug <s>]\n` +
|
|
25
30
|
` [--org <s>] [--preview] [--force] [--no-install]\n` +
|
|
26
31
|
` link <project-id> Link this folder to an existing project\n` +
|
|
27
32
|
` unlink Disconnect this folder from its project\n` +
|
|
@@ -93,5 +98,6 @@ export const USAGE_TEXT = `Vincentt CLI — local-first AR dev loop\n\n` +
|
|
|
93
98
|
` disable it, and is shown on \`vincentt dx\` and\n` +
|
|
94
99
|
` \`vincentt version\` while on.\n` +
|
|
95
100
|
` dx disable Turn that off again.\n\n` +
|
|
96
|
-
`Common options: --dir <path> (
|
|
101
|
+
`Common options: --dir <path> (where to work, default cwd — for \`create\` this is\n` +
|
|
102
|
+
` the PARENT of the new folder, not the folder itself)\n` +
|
|
97
103
|
` --allow-custom-api honor a binding's apiUrl override\n`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincentt-xr/cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "Vincentt CLI — the vincentt command-line dev loop (login, create, publish, preview, diagnostics, feedback, relay)",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"qrcode": "^1.5.4",
|
|
25
25
|
"ws": "^8.18.0",
|
|
26
26
|
"zod": "^3.23.8",
|
|
27
|
-
"@vincentt-xr/harness": "1.
|
|
27
|
+
"@vincentt-xr/harness": "1.4.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/qrcode": "^1.5.5",
|