Skip to content

Commit c4f1b64

Browse files
authored
fix(dlx): handle scoped create commands (#4627)
1 parent 23c410a commit c4f1b64

File tree

4 files changed

+95
-28
lines changed

4 files changed

+95
-28
lines changed

.yarn/versions/93ce6177.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
releases:
2+
"@yarnpkg/cli": patch
3+
"@yarnpkg/plugin-dlx": patch
4+
5+
declined:
6+
- "@yarnpkg/plugin-compat"
7+
- "@yarnpkg/plugin-constraints"
8+
- "@yarnpkg/plugin-essentials"
9+
- "@yarnpkg/plugin-init"
10+
- "@yarnpkg/plugin-interactive-tools"
11+
- "@yarnpkg/plugin-nm"
12+
- "@yarnpkg/plugin-npm-cli"
13+
- "@yarnpkg/plugin-pack"
14+
- "@yarnpkg/plugin-patch"
15+
- "@yarnpkg/plugin-pnp"
16+
- "@yarnpkg/plugin-pnpm"
17+
- "@yarnpkg/plugin-stage"
18+
- "@yarnpkg/plugin-typescript"
19+
- "@yarnpkg/plugin-version"
20+
- "@yarnpkg/plugin-workspace-tools"
21+
- "@yarnpkg/builder"
22+
- "@yarnpkg/core"
23+
- "@yarnpkg/doctor"

packages/acceptance-tests/pkg-tests-specs/sources/commands/create.test.js

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import {xfs, ppath, Filename} from '@yarnpkg/fslib';
2+
3+
describe(`Commands`, () => {
4+
describe(`create`, () => {
5+
test(
6+
`it should generate \`hello.txt\` correctly using a starter-kit-package`,
7+
makeTemporaryEnv({}, async ({path, run, source}) => {
8+
await run(`create`, `-q`, `test-app`);
9+
expect(xfs.readFileSync(ppath.join(path, `hello.txt` as Filename), `utf8`)).toEqual(`Hello World`);
10+
}),
11+
);
12+
13+
test(
14+
`it should generate \`hello.txt\` correctly using a scoped starter-kit-package`,
15+
makeTemporaryEnv({}, async ({path, run, source}) => {
16+
await run(`create`, `-q`, `@scoped/test-app`);
17+
expect(xfs.readFileSync(ppath.join(path, `hello.txt` as Filename), `utf8`)).toEqual(`Hello World`);
18+
}),
19+
);
20+
21+
test(
22+
`it should treat '@scope' as '@scope/create'`,
23+
makeTemporaryEnv({}, async ({path, run, source}) => {
24+
await expect(run(`create`, `@404-scope`)).rejects.toMatchObject({
25+
code: 1,
26+
stdout: expect.stringContaining(`@404-scope/create@unknown`),
27+
});
28+
}),
29+
);
30+
31+
test(
32+
`it should treat '@scope@next' as '@scope/create@next'`,
33+
makeTemporaryEnv({}, async ({path, run, source}) => {
34+
await expect(run(`create`, `@404-scope@next`)).rejects.toMatchObject({
35+
code: 1,
36+
stdout: expect.stringContaining(`@404-scope/create@npm:next`),
37+
});
38+
}),
39+
);
40+
41+
test(
42+
`it should treat '@scope/app' as '@scope/create-app'`,
43+
makeTemporaryEnv({}, async ({path, run, source}) => {
44+
await expect(run(`create`, `@404-scope/app`)).rejects.toMatchObject({
45+
code: 1,
46+
stdout: expect.stringContaining(`@404-scope/create-app@unknown`),
47+
});
48+
}),
49+
);
50+
});
51+
});

packages/plugin-dlx/sources/commands/create.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import {BaseCommand} from '@yarnpkg/cli';
2-
import {structUtils} from '@yarnpkg/core';
3-
import {Option} from 'clipanion';
1+
import {BaseCommand} from '@yarnpkg/cli';
2+
import {Ident, structUtils} from '@yarnpkg/core';
3+
import {Option} from 'clipanion';
44

55
// eslint-disable-next-line arca/no-default-export
66
export default class CreateCommand extends BaseCommand {
@@ -26,9 +26,24 @@ export default class CreateCommand extends BaseCommand {
2626
if (this.quiet)
2727
flags.push(`--quiet`);
2828

29-
const ident = structUtils.parseIdent(this.command);
30-
const modified = structUtils.makeIdent(ident.scope, `create-${ident.name}`);
29+
const descriptor = structUtils.parseDescriptor(this.command);
3130

32-
return this.cli.run([`dlx`, ...flags, structUtils.stringifyIdent(modified), ...this.args]);
31+
let modifiedIdent: Ident;
32+
33+
if (descriptor.scope)
34+
// @foo/app -> @foo/create-app
35+
modifiedIdent = structUtils.makeIdent(descriptor.scope, `create-${descriptor.name}`);
36+
else if (descriptor.name.startsWith(`@`))
37+
// @foo -> @foo/create
38+
modifiedIdent = structUtils.makeIdent(descriptor.name.substring(1), `create`);
39+
else
40+
// foo -> create-foo
41+
modifiedIdent = structUtils.makeIdent(null, `create-${descriptor.name}`);
42+
43+
let finalDescriptorString = structUtils.stringifyIdent(modifiedIdent);
44+
if (descriptor.range !== `unknown`)
45+
finalDescriptorString += `@${descriptor.range}`;
46+
47+
return this.cli.run([`dlx`, ...flags, finalDescriptorString, ...this.args]);
3348
}
3449
}

0 commit comments

Comments
 (0)