Skip to content

Commit 1d31c8e

Browse files
committed
docs(admin users create): use primaryTenantId in help description and examples
サーバ実装 (`geolonia/geonicdb` の `src/api/admin/schemas/user.schemas.ts:48` `CreateUserInputSchema`) は `.strict()` で `primaryTenantId` のみを受理するが、CLI ヘルプの description と examples が旧フィールド名 `tenantId` のままだった。ヘルプ通りに書くと `400 Unrecognized key: "tenantId"` で必ず失敗する状態。 修正: - `src/commands/admin/users.ts`: - L86, L89 (description): `tenantId` → `primaryTenantId` - L107, L111 (`addExamples` payload): `"tenantId":"<tenant-id>"` → `"primaryTenantId":"<tenant-id>"` 回帰防止としてユニットテストを追加 (`tests/admin-users.test.ts`): - `users create` の description が `primaryTenantId` を含み、旧文言 `"tenantId":` / `tenantId is required` を含まないこと - `addExamples` に渡される example payload が role 別 (`tenant_admin` / `user`) で `primaryTenantId` を使い、旧 `"tenantId":` を含まないこと 実装側を変える前にテストを追加して red を確認 → 修正で green、というオーソドックスな TDD で進めた。lint / typecheck / 全 35 spec / 735 tests いずれも pass。 Closes #118
1 parent f80dbd4 commit 1d31c8e

3 files changed

Lines changed: 43 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77

88
## [Unreleased]
99

10+
### 2026-05-08
11+
- **Docs**: `admin users create` のヘルプ description / examples で旧フィールド名 `tenantId` を使っていた箇所を `primaryTenantId` に修正。サーバ側 `CreateUserInputSchema` (`.strict()`) は `primaryTenantId` のみを受理しており、ヘルプ通りに書くと `400 Unrecognized key: "tenantId"` で失敗していた。回帰防止としてヘルプ文字列・examples を `primaryTenantId` で検証するユニットテストを追加 (#118, #TBD)
12+
1013
## [0.15.0] - 2026-04-30
1114

1215
### 2026-04-30

src/commands/admin/users.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ export function registerUsersCommand(parent: Command): void {
8383
' "email": "user@example.com",\n' +
8484
' "password": "SecurePassword123!",\n' +
8585
' "role": "tenant_admin",\n' +
86-
' "tenantId": "<tenant-id>"\n' +
86+
' "primaryTenantId": "<tenant-id>"\n' +
8787
" }\n\n" +
8888
"Roles: super_admin, tenant_admin, user\n" +
89-
"tenantId is required for tenant_admin and user roles.",
89+
"primaryTenantId is required for tenant_admin and user roles.",
9090
)
9191
.action(
9292
withErrorHandler(async (json: unknown, _opts: unknown, cmd: Command) => {
@@ -104,11 +104,11 @@ export function registerUsersCommand(parent: Command): void {
104104
addExamples(create, [
105105
{
106106
description: "Create a tenant admin",
107-
command: `geonic admin users create '{"email":"admin@example.com","password":"SecurePass12345!","role":"tenant_admin","tenantId":"<tenant-id>"}'`,
107+
command: `geonic admin users create '{"email":"admin@example.com","password":"SecurePass12345!","role":"tenant_admin","primaryTenantId":"<tenant-id>"}'`,
108108
},
109109
{
110110
description: "Create a user for a tenant",
111-
command: `geonic admin users create '{"email":"user@example.com","password":"SecurePass12345!","role":"user","tenantId":"<tenant-id>"}'`,
111+
command: `geonic admin users create '{"email":"user@example.com","password":"SecurePass12345!","role":"user","primaryTenantId":"<tenant-id>"}'`,
112112
},
113113
{
114114
description: "Create from a JSON file",

tests/admin-users.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ vi.mock("../src/commands/help.js", () => ({
3838
addNotes: vi.fn(),
3939
}));
4040

41+
import type { Command } from "commander";
4142
import { createClient, getFormat, outputResponse } from "../src/helpers.js";
4243
import { parseJsonInput } from "../src/input.js";
4344
import { printSuccess } from "../src/output.js";
45+
import { addExamples } from "../src/commands/help.js";
4446
import { registerUsersCommand } from "../src/commands/admin/users.js";
4547

4648
describe("admin users commands", () => {
@@ -107,6 +109,40 @@ describe("admin users commands", () => {
107109
expect(outputResponse).toHaveBeenCalled();
108110
expect(printSuccess).toHaveBeenCalledWith("User created.");
109111
});
112+
113+
// #118: server schema accepts only `primaryTenantId`. Help and examples must reflect that.
114+
it("references primaryTenantId (not legacy tenantId) in description", () => {
115+
const program = makeProgram();
116+
const createCmd = program.commands
117+
.find((c) => c.name() === "admin")!
118+
.commands.find((c) => c.name() === "users")!
119+
.commands.find((c) => c.name() === "create")!;
120+
const desc = createCmd.description();
121+
expect(desc).toContain('"primaryTenantId":');
122+
expect(desc).toContain("primaryTenantId is required");
123+
expect(desc).not.toContain('"tenantId":');
124+
expect(desc).not.toContain("tenantId is required");
125+
});
126+
127+
it("uses primaryTenantId in registered example payloads", () => {
128+
makeProgram();
129+
const addExamplesMock = vi.mocked(addExamples);
130+
const createCalls = addExamplesMock.mock.calls.filter(
131+
([cmd]) => (cmd as Command).name() === "create",
132+
);
133+
expect(createCalls.length).toBeGreaterThan(0);
134+
const examples = createCalls.flatMap(
135+
([, exs]) => exs as ReadonlyArray<{ description: string; command: string }>,
136+
);
137+
const roleSpecificExamples = examples.filter(
138+
(e) => e.command.includes('"role":"tenant_admin"') || e.command.includes('"role":"user"'),
139+
);
140+
expect(roleSpecificExamples.length).toBeGreaterThan(0);
141+
for (const ex of roleSpecificExamples) {
142+
expect(ex.command).toContain('"primaryTenantId":');
143+
expect(ex.command).not.toContain('"tenantId":');
144+
}
145+
});
110146
});
111147

112148
describe("users update", () => {

0 commit comments

Comments
 (0)