Repository: JoshuaKGoldberg/create-typescript-app (ts)

Issue:
🚀 Feature: Infer access from package.json data
### Feature Request Checklist

- [x] I have pulled the latest `main` branch of the repository.
- [x] I have [searched for related issues](https://github.com/JoshuaKGoldberg/create-typescript-app/issues?q=is%3Aissue) and found none that matched my issue.

### Overview

Right now, the `access` option has a hardcoded default of `"public"`:

https://github.com/JoshuaKGoldberg/create-typescript-app/blob/20ab2419de4f1fdd78ff6270054793ebaa269c3e/src/base.ts#L260

That should be computed from `package.json` data on disk.

### Additional Info

Marking as blocked until #1973 -> #1985 is done, to avoid merge conflicts.

🎁 

Pull request description:
feat: infer access option from package.json
## PR Checklist

- [x] Addresses an existing open issue: fixes #1988
- [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

🎁 

Patch:
diff --git a/src/base.ts b/src/base.ts
index 7850a6a..cabfdc7 100644
--- a/src/base.ts
+++ b/src/base.ts
@@ -4,6 +4,7 @@ import { inputFromScript } from "input-from-script";
 import lazyValue from "lazy-value";
 import { z } from "zod";
 
+import { readAccess } from "./options/readAccess.js";
 import { readAllContributors } from "./options/readAllContributors.js";
 import { readAuthor } from "./options/readAuthor.js";
 import { readDescription } from "./options/readDescription.js";
@@ -167,6 +168,10 @@ export const base = createBase({
 			.describe("package version to publish as and store in `package.json`"),
 	},
 	prepare({ options, take }) {
+		const getAccess = lazyValue(
+			async () => await readAccess(getPackageDataFull),
+		);
+
 		const getAllContributors = lazyValue(
 			async () => await readAllContributors(take),
 		);
@@ -285,7 +290,7 @@ export const base = createBase({
 		);
 
 		return {
-			access: "public" as const,
+			access: getAccess,
 			author: getAuthor,
 			bin: getBin,
 			contributors: getAllContributors,
diff --git a/src/options/readAccess.ts b/src/options/readAccess.ts
new file mode 100644
index 0000000..bc60cd9
--- /dev/null
+++ b/src/options/readAccess.ts
@@ -0,0 +1,7 @@
+import { PartialPackageData } from "../types.js";
+
+export async function readAccess(
+	getPackageDataFull: () => Promise<PartialPackageData | undefined>,
+) {
+	return (await getPackageDataFull())?.publishConfig?.access ?? "public";
+}
diff --git a/src/types.ts b/src/types.ts
index 4dc2aed..b30d8ad 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -20,7 +20,12 @@ export interface PartialPackageData {
 	engines?: { node?: string };
 	name?: string;
 	packageManager?: string;
+	publishConfig?: PartialPublishConfig;
 	repository?: string | { type: string; url: string };
 	scripts?: Record<string, string>;
 	version?: string;
 }
+
+interface PartialPublishConfig {
+	access?: "public" | "restricted";
+}


Test patch:
diff --git a/src/options/readAccess.test.ts b/src/options/readAccess.test.ts
new file mode 100644
index 0000000..cc58d56
--- /dev/null
+++ b/src/options/readAccess.test.ts
@@ -0,0 +1,42 @@
+import { describe, expect, it, vi } from "vitest";
+
+import { readAccess } from "./readAccess.js";
+
+describe(readAccess, () => {
+	it("resolves with 'public' when package data does not exist", async () => {
+		const getDescription = vi.fn().mockResolvedValue(undefined);
+
+		const actual = await readAccess(getDescription);
+
+		expect(actual).toBe("public");
+	});
+
+	it("resolves with 'public' when package data does not have publishConfig", async () => {
+		const getDescription = vi.fn().mockResolvedValue({});
+
+		const actual = await readAccess(getDescription);
+
+		expect(actual).toBe("public");
+	});
+
+	it("resolves with 'public' when package data has an empty publishConfig", async () => {
+		const getDescription = vi.fn().mockResolvedValue({
+			publishConfig: {},
+		});
+
+		const actual = await readAccess(getDescription);
+
+		expect(actual).toBe("public");
+	});
+
+	it("resolves with the access when package data has a publishConfig with access", async () => {
+		const access = "restricted";
+		const getDescription = vi.fn().mockResolvedValue({
+			publishConfig: { access },
+		});
+
+		const actual = await readAccess(getDescription);
+
+		expect(actual).toBe(access);
+	});
+});