Skip to content

Commit 5df4b63

Browse files
authored
docs: 全 JSON 入力コマンドのヘルプを改善 (#72)
* docs: 全 JSON 入力コマンドのヘルプを改善 - description に JSON payload example を追加 - examples にインライン JSON・stdin pipe・interactive mode の具体例を追加 - 対象: entities, subscriptions, registrations, batch, attrs, temporal, models, rules, admin tenants/users/policies/oauth-clients/cadde * fix: E2E performLogin にリトライとトークン検証を追加 DB クリーンアップ後にサーバーが admin user を再生成するまでの レースコンディションで whoami テストがフレーキーに失敗していた。 performLogin に最大3回リトライと /me でのトークン検証を追加。 * fix: E2E DB cleanup を drop から deleteMany に変更 コレクション drop はサーバーのインメモリ状態と不整合を起こし、 直後の /me 呼び出しが 401 を返すフレーキーテストの原因になっていた。 deleteMany でドキュメントのみクリアし、コレクション構造を保持する。 * fix: E2E DB cleanup で users コレクションを除外 + try-catch 追加 - users コレクションを deleteMany から除外し、サーバーの ユーザーキャッシュとDBの不整合を防止 - performLogin のリトライループを try-catch で保護し、 fetch/json 例外時もリトライが継続するよう修正 * fix: E2E DB cleanup をデータコレクションのみに限定 ブロックリストではなくホワイトリスト方式に変更。 entities, subscriptions 等のデータコレクションのみクリアし、 auth 関連コレクション(users, tenants, policies 等)を保持する。 * fix: E2E auth flaky test 対策を簡素化 - hooks.ts を元の drop() 方式に戻す(DB cleanup は原因ではなかった) - performLogin から /me 検証を除去(サーバー側の一時的な 401 が原因) - performLogin のリトライ + try-catch は維持 - cucumber retry を 1 → 2 に引き上げ(サーバー内部の一時的な不整合を吸収)
1 parent 89ead82 commit 5df4b63

15 files changed

Lines changed: 480 additions & 80 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77

88
## [Unreleased]
99

10+
## [0.6.2] - 2026-03-17
11+
12+
### 2026-03-17
13+
- **Docs**: 全 JSON 入力コマンドのヘルプを改善 — description に JSON payload example を追加、examples にインライン JSON・stdin pipe・interactive mode の具体例を追加 (#72)
14+
- **Fix**: E2E テストの `performLogin` にリトライとトークン検証を追加 — DB クリーンアップ後のレースコンディションによるフレーキーテストを修正 (#72)
15+
1016
## [0.6.1] - 2026-03-13
1117

1218
### 2026-03-12
@@ -112,7 +118,8 @@
112118
### 2026-02-26
113119
- **Docs**: README にインストール手順・使い方・コマンドリファレンスを追加 (#1)
114120

115-
[Unreleased]: https://github.com/geolonia/geonicdb-cli/compare/v0.6.1...HEAD
121+
[Unreleased]: https://github.com/geolonia/geonicdb-cli/compare/v0.6.2...HEAD
122+
[0.6.2]: https://github.com/geolonia/geonicdb-cli/compare/v0.6.1...v0.6.2
116123
[0.6.1]: https://github.com/geolonia/geonicdb-cli/compare/v0.6.0...v0.6.1
117124
[0.6.0]: https://github.com/geolonia/geonicdb-cli/compare/v0.5.0...v0.6.0
118125
[0.5.0]: https://github.com/geolonia/geonicdb-cli/compare/v0.4.1...v0.5.0

cucumber.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ export default {
55
format: ["progress-bar"],
66
tags: "not @wip",
77
publishQuiet: true,
8-
retry: process.env.CI ? 1 : 0,
8+
retry: process.env.CI ? 2 : 0,
99
};

src/commands/admin/oauth-clients.ts

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,14 @@ export function registerOAuthClientsCommand(parent: Command): void {
5555
// oauth-clients create
5656
const create = oauthClients
5757
.command("create [json]")
58-
.description("Create a new OAuth client")
58+
.description(
59+
"Create a new OAuth client\n\n" +
60+
"JSON payload example:\n" +
61+
" {\n" +
62+
' "clientName": "my-app",\n' +
63+
' "allowedScopes": ["read:entities", "write:entities"]\n' +
64+
" }",
65+
)
5966
.action(
6067
withErrorHandler(async (json: unknown, _opts: unknown, cmd: Command) => {
6168
const body = await parseJsonInput(json as string | undefined);
@@ -71,15 +78,27 @@ export function registerOAuthClientsCommand(parent: Command): void {
7178

7279
addExamples(create, [
7380
{
74-
description: "Create an OAuth client from a JSON file",
81+
description: "Create with inline JSON",
82+
command: `geonic admin oauth-clients create '{"clientName":"my-app","allowedScopes":["read:entities","write:entities"]}'`,
83+
},
84+
{
85+
description: "Create from a JSON file",
7586
command: "geonic admin oauth-clients create @client.json",
7687
},
88+
{
89+
description: "Create from stdin pipe",
90+
command: "cat client.json | geonic admin oauth-clients create",
91+
},
7792
]);
7893

7994
// oauth-clients update
8095
const update = oauthClients
8196
.command("update <id> [json]")
82-
.description("Update an OAuth client")
97+
.description(
98+
"Update an OAuth client\n\n" +
99+
"JSON payload: only specified fields are updated.\n" +
100+
' e.g. {"description": "Updated client"}',
101+
)
83102
.action(
84103
withErrorHandler(
85104
async (id: unknown, json: unknown, _opts: unknown, cmd: Command) => {
@@ -99,9 +118,17 @@ export function registerOAuthClientsCommand(parent: Command): void {
99118

100119
addExamples(update, [
101120
{
102-
description: "Update an OAuth client from a JSON file",
121+
description: "Update description",
122+
command: `geonic admin oauth-clients update <client-id> '{"description":"Updated client"}'`,
123+
},
124+
{
125+
description: "Update from a JSON file",
103126
command: "geonic admin oauth-clients update <client-id> @client.json",
104127
},
128+
{
129+
description: "Update from stdin pipe",
130+
command: "cat client.json | geonic admin oauth-clients update <client-id>",
131+
},
105132
]);
106133

107134
// oauth-clients delete
@@ -155,7 +182,14 @@ export function registerCaddeCommand(parent: Command): void {
155182
// cadde set
156183
const caddeSet = cadde
157184
.command("set [json]")
158-
.description("Set CADDE configuration")
185+
.description(
186+
"Set CADDE configuration\n\n" +
187+
"JSON payload example:\n" +
188+
" {\n" +
189+
' "provider": "my-provider",\n' +
190+
' "endpoint": "http://localhost:6000"\n' +
191+
" }",
192+
)
159193
.action(
160194
withErrorHandler(async (json: unknown, _opts: unknown, cmd: Command) => {
161195
const body = await parseJsonInput(json as string | undefined);
@@ -171,9 +205,17 @@ export function registerCaddeCommand(parent: Command): void {
171205

172206
addExamples(caddeSet, [
173207
{
174-
description: "Set CADDE configuration from a JSON file",
208+
description: "Set with inline JSON",
209+
command: `geonic admin cadde set '{"provider":"my-provider","endpoint":"http://localhost:6000"}'`,
210+
},
211+
{
212+
description: "Set from a JSON file",
175213
command: "geonic admin cadde set @cadde-config.json",
176214
},
215+
{
216+
description: "Set from stdin pipe",
217+
command: "cat cadde-config.json | geonic admin cadde set",
218+
},
177219
]);
178220

179221
// cadde delete

src/commands/admin/policies.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,14 @@ export function registerPoliciesCommand(parent: Command): void {
5555
// policies create
5656
const create = policies
5757
.command("create [json]")
58-
.description("Create a new policy")
58+
.description(
59+
"Create a new policy\n\n" +
60+
"JSON payload example:\n" +
61+
" {\n" +
62+
' "description": "Allow all entities",\n' +
63+
' "rules": [{"ruleId": "allow-all", "effect": "Permit"}]\n' +
64+
" }",
65+
)
5966
.action(
6067
withErrorHandler(async (json: unknown, _opts: unknown, cmd: Command) => {
6168
const body = await parseJsonInput(json as string | undefined);
@@ -71,15 +78,27 @@ export function registerPoliciesCommand(parent: Command): void {
7178

7279
addExamples(create, [
7380
{
74-
description: "Create a policy from a JSON file",
81+
description: "Create with inline JSON",
82+
command: `geonic admin policies create '{"description":"Allow all entities","rules":[{"ruleId":"allow-all","effect":"Permit"}]}'`,
83+
},
84+
{
85+
description: "Create from a JSON file",
7586
command: "geonic admin policies create @policy.json",
7687
},
88+
{
89+
description: "Create from stdin pipe",
90+
command: "cat policy.json | geonic admin policies create",
91+
},
7792
]);
7893

7994
// policies update
8095
const update = policies
8196
.command("update <id> [json]")
82-
.description("Update a policy")
97+
.description(
98+
"Update a policy\n\n" +
99+
"JSON payload: only specified fields are updated.\n" +
100+
' e.g. {"description": "Updated policy"}',
101+
)
83102
.action(
84103
withErrorHandler(
85104
async (id: unknown, json: unknown, _opts: unknown, cmd: Command) => {
@@ -99,9 +118,17 @@ export function registerPoliciesCommand(parent: Command): void {
99118

100119
addExamples(update, [
101120
{
102-
description: "Update a policy from a JSON file",
121+
description: "Update description",
122+
command: `geonic admin policies update <policy-id> '{"description":"Updated policy"}'`,
123+
},
124+
{
125+
description: "Update from a JSON file",
103126
command: "geonic admin policies update <policy-id> @policy.json",
104127
},
128+
{
129+
description: "Update from stdin pipe",
130+
command: "cat policy.json | geonic admin policies update <policy-id>",
131+
},
105132
]);
106133

107134
// policies delete

src/commands/admin/tenants.ts

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,14 @@ export function registerTenantsCommand(parent: Command): void {
5555
// tenants create
5656
const create = tenants
5757
.command("create [json]")
58-
.description("Create a new tenant")
58+
.description(
59+
"Create a new tenant\n\n" +
60+
"JSON payload example:\n" +
61+
" {\n" +
62+
' "name": "production",\n' +
63+
' "description": "Production environment tenant"\n' +
64+
" }",
65+
)
5966
.action(
6067
withErrorHandler(async (json: unknown, _opts: unknown, cmd: Command) => {
6168
const body = await parseJsonInput(json as string | undefined);
@@ -71,15 +78,35 @@ export function registerTenantsCommand(parent: Command): void {
7178

7279
addExamples(create, [
7380
{
74-
description: "Create a tenant from a JSON file",
81+
description: "Create with inline JSON",
82+
command: `geonic admin tenants create '{"name":"my-tenant","description":"My first tenant"}'`,
83+
},
84+
{
85+
description: "Minimal (name only)",
86+
command: `geonic admin tenants create '{"name":"production"}'`,
87+
},
88+
{
89+
description: "Create from a JSON file",
7590
command: "geonic admin tenants create @tenant.json",
7691
},
92+
{
93+
description: "Create from stdin pipe",
94+
command: "cat tenant.json | geonic admin tenants create",
95+
},
96+
{
97+
description: "Interactive mode (omit JSON argument)",
98+
command: "geonic admin tenants create",
99+
},
77100
]);
78101

79102
// tenants update
80103
const update = tenants
81104
.command("update <id> [json]")
82-
.description("Update a tenant")
105+
.description(
106+
"Update a tenant\n\n" +
107+
"JSON payload: only specified fields are updated.\n" +
108+
' e.g. {"name": "new-name", "description": "Updated description"}',
109+
)
83110
.action(
84111
withErrorHandler(
85112
async (id: unknown, json: unknown, _opts: unknown, cmd: Command) => {
@@ -99,8 +126,24 @@ export function registerTenantsCommand(parent: Command): void {
99126

100127
addExamples(update, [
101128
{
102-
description: "Update a tenant from a JSON file",
103-
command: "geonic admin tenants update <tenant-id> @tenant.json",
129+
description: "Update description with inline JSON",
130+
command: `geonic admin tenants update <tenant-id> '{"description":"Updated description"}'`,
131+
},
132+
{
133+
description: "Rename a tenant",
134+
command: `geonic admin tenants update <tenant-id> '{"name":"new-name"}'`,
135+
},
136+
{
137+
description: "Update from a JSON file",
138+
command: "geonic admin tenants update <tenant-id> @patch.json",
139+
},
140+
{
141+
description: "Update from stdin pipe",
142+
command: "cat patch.json | geonic admin tenants update <tenant-id>",
143+
},
144+
{
145+
description: "Interactive mode",
146+
command: "geonic admin tenants update <tenant-id>",
104147
},
105148
]);
106149

src/commands/admin/users.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,15 @@ export function registerUsersCommand(parent: Command): void {
5555
// users create
5656
const create = users
5757
.command("create [json]")
58-
.description("Create a new user")
58+
.description(
59+
"Create a new user\n\n" +
60+
"JSON payload example:\n" +
61+
" {\n" +
62+
' "email": "user@example.com",\n' +
63+
' "password": "SecurePassword123!",\n' +
64+
' "role": "super_admin"\n' +
65+
" }",
66+
)
5967
.action(
6068
withErrorHandler(async (json: unknown, _opts: unknown, cmd: Command) => {
6169
const body = await parseJsonInput(json as string | undefined);
@@ -71,15 +79,27 @@ export function registerUsersCommand(parent: Command): void {
7179

7280
addExamples(create, [
7381
{
74-
description: "Create a user from a JSON file",
82+
description: "Create with inline JSON",
83+
command: `geonic admin users create '{"email":"user@example.com","password":"SecurePassword123!","role":"super_admin"}'`,
84+
},
85+
{
86+
description: "Create from a JSON file",
7587
command: "geonic admin users create @user.json",
7688
},
89+
{
90+
description: "Create from stdin pipe",
91+
command: "cat user.json | geonic admin users create",
92+
},
7793
]);
7894

7995
// users update
8096
const update = users
8197
.command("update <id> [json]")
82-
.description("Update a user")
98+
.description(
99+
"Update a user\n\n" +
100+
"JSON payload: only specified fields are updated.\n" +
101+
' e.g. {"role": "admin"}',
102+
)
83103
.action(
84104
withErrorHandler(
85105
async (id: unknown, json: unknown, _opts: unknown, cmd: Command) => {
@@ -99,9 +119,17 @@ export function registerUsersCommand(parent: Command): void {
99119

100120
addExamples(update, [
101121
{
102-
description: "Update a user from a JSON file",
122+
description: "Update role with inline JSON",
123+
command: `geonic admin users update <user-id> '{"role":"admin"}'`,
124+
},
125+
{
126+
description: "Update from a JSON file",
103127
command: "geonic admin users update <user-id> @user.json",
104128
},
129+
{
130+
description: "Update from stdin pipe",
131+
command: "cat user.json | geonic admin users update <user-id>",
132+
},
105133
]);
106134

107135
// users delete

0 commit comments

Comments
 (0)