Skip to content

Commit 21c8529

Browse files
feat: add --bin option (#1068)
## PR Checklist - [x] Addresses an existing open issue: fixes #938 - [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/create-typescript-app/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22) - [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/create-typescript-app/blob/main/.github/CONTRIBUTING.md) were taken ## Overview Adds the `--bin` option with auto-detection from existing `package.json` contents. Doesn't do anything about investigating whether to adjust `pnpm build` before `pnpm lint` & similar. That can be a followup.
1 parent c980e54 commit 21c8529

File tree

10 files changed

+37
-0
lines changed

10 files changed

+37
-0
lines changed

docs/Options.md

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ The setup scripts also allow for optional overrides of the following inputs whos
5353

5454
- `--access` _(`"public" | "restricted"`)_: Which [`npm publish --access`](https://docs.npmjs.com/cli/commands/npm-publish#access) to release npm packages with (by default, `"public"`)
5555
- `--author` _(`string`)_: Username on npm to publish packages under (by default, an existing npm author, or the currently logged in npm user, or `owner.toLowerCase()`)
56+
- `--bin` _(`string`)_: `package.json` bin value to include for npx-style running.
5657
- `--directory` _(`string`)_: Directory to create the repository in (by default, the same name as the repository)
5758
- `--email` _(`string`)_: Email address to be listed as the point of contact in docs and packages (e.g. `[email protected]`)
5859
- Optionally, `--email-github` _(`string`)_ and/or `--email-npm` _(`string`)_ may be provided to use different emails in `.md` files and `package.json`, respectively

src/bin/help.test.ts

+4
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ describe("logHelpText", () => {
120120
"
121121
--auto: Whether to infer all options from files on disk.",
122122
],
123+
[
124+
"
125+
--bin (string): package.json bin value to include for npx-style running.",
126+
],
123127
[
124128
"
125129
--directory (string): Directory to create the repository in (by default, the same

src/shared/options/args.ts

+5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ export const allArgOptions = {
3131
docsSection: "core",
3232
type: "string",
3333
},
34+
bin: {
35+
description: `package.json bin value to include for npx-style running.`,
36+
docsSection: "optional",
37+
type: "string",
38+
},
3439
"create-repository": {
3540
description: `Whether to create a corresponding repository on github.com
3641
(if it doesn't yet exist)`,

src/shared/options/createOptionDefaults/index.test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,26 @@ vi.mock("../../packages.js", () => ({
3535
}));
3636

3737
describe("createOptionDefaults", () => {
38+
describe("bin", () => {
39+
it("returns undefined when package data does not have a bin", async () => {
40+
mockReadPackageData.mockResolvedValue({});
41+
42+
const actual = await createOptionDefaults().bin();
43+
44+
expect(actual).toBeUndefined();
45+
});
46+
47+
it("returns the bin when package data has a bin", async () => {
48+
const bin = "./lib/index.js";
49+
50+
mockReadPackageData.mockResolvedValue({ bin });
51+
52+
const actual = await createOptionDefaults().bin();
53+
54+
expect(actual).toBe(bin);
55+
});
56+
});
57+
3858
describe("email", () => {
3959
it("returns the npm whoami email from npm when only an npm exists", async () => {
4060
mock$.mockImplementation(([command]: string[]) =>

src/shared/options/createOptionDefaults/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export function createOptionDefaults(promptedOptions?: PromptedOptions) {
3030

3131
return {
3232
author: async () => (await packageAuthor()).author ?? npmDefaults.name,
33+
bin: async () => (await packageData()).bin,
3334
description: async () => (await packageData()).description,
3435
email: async () => {
3536
const gitEmail = await tryCatchAsync(

src/shared/options/optionsSchema.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const optionsSchemaShape = {
1212
z.literal("prompt"),
1313
])
1414
.optional(),
15+
bin: z.string().optional(),
1516
description: z.string().optional(),
1617
directory: z.string().optional(),
1718
email: z

src/shared/options/readOptions.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const emptyOptions = {
1010
author: undefined,
1111
auto: false,
1212
base: undefined,
13+
bin: undefined,
1314
description: undefined,
1415
directory: undefined,
1516
email: undefined,

src/shared/options/readOptions.ts

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export async function readOptions(
5555
author: values.author,
5656
auto: !!values.auto,
5757
base: values.base,
58+
bin: values.bin,
5859
description: values.description,
5960
directory: values.directory,
6061
email:

src/shared/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface AllContributorsData {
1313

1414
export interface PartialPackageData {
1515
author?: { email: string; name: string } | string;
16+
bin?: string;
1617
dependencies?: Record<string, string>;
1718
description?: string;
1819
devDependencies?: Record<string, string>;
@@ -48,6 +49,7 @@ export interface Options {
4849
access: OptionsAccess;
4950
author?: string;
5051
base?: OptionsBase;
52+
bin?: string;
5153
description: string;
5254
directory: string;
5355
email: OptionsEmail;

src/steps/writing/creation/writePackageJson.ts

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export async function writePackageJson(options: Options) {
4141
...existingPackageJson,
4242

4343
author: { email: options.email.npm, name: options.author },
44+
bin: options.bin,
4445
description: options.description,
4546
keywords: options.keywords?.length
4647
? options.keywords.flatMap((keyword) => keyword.split(/ /))

0 commit comments

Comments
 (0)