@mrmtsu/mcms-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +184 -0
  3. package/README.md +185 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +143 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/api.d.ts +2 -0
  8. package/dist/commands/api.js +27 -0
  9. package/dist/commands/api.js.map +1 -0
  10. package/dist/commands/auth.d.ts +2 -0
  11. package/dist/commands/auth.js +238 -0
  12. package/dist/commands/auth.js.map +1 -0
  13. package/dist/commands/completion.d.ts +2 -0
  14. package/dist/commands/completion.js +390 -0
  15. package/dist/commands/completion.js.map +1 -0
  16. package/dist/commands/config.d.ts +2 -0
  17. package/dist/commands/config.js +63 -0
  18. package/dist/commands/config.js.map +1 -0
  19. package/dist/commands/content.d.ts +2 -0
  20. package/dist/commands/content.js +191 -0
  21. package/dist/commands/content.js.map +1 -0
  22. package/dist/commands/media.d.ts +2 -0
  23. package/dist/commands/media.js +47 -0
  24. package/dist/commands/media.js.map +1 -0
  25. package/dist/commands/schema.d.ts +2 -0
  26. package/dist/commands/schema.js +71 -0
  27. package/dist/commands/schema.js.map +1 -0
  28. package/dist/commands/types.d.ts +2 -0
  29. package/dist/commands/types.js +85 -0
  30. package/dist/commands/types.js.map +1 -0
  31. package/dist/commands/utils.d.ts +8 -0
  32. package/dist/commands/utils.js +56 -0
  33. package/dist/commands/utils.js.map +1 -0
  34. package/dist/commands/validate.d.ts +2 -0
  35. package/dist/commands/validate.js +38 -0
  36. package/dist/commands/validate.js.map +1 -0
  37. package/dist/core/auth-store.d.ts +11 -0
  38. package/dist/core/auth-store.js +83 -0
  39. package/dist/core/auth-store.js.map +1 -0
  40. package/dist/core/client.d.ts +33 -0
  41. package/dist/core/client.js +416 -0
  42. package/dist/core/client.js.map +1 -0
  43. package/dist/core/config.d.ts +11 -0
  44. package/dist/core/config.js +73 -0
  45. package/dist/core/config.js.map +1 -0
  46. package/dist/core/context.d.ts +39 -0
  47. package/dist/core/context.js +382 -0
  48. package/dist/core/context.js.map +1 -0
  49. package/dist/core/errors.d.ts +26 -0
  50. package/dist/core/errors.js +167 -0
  51. package/dist/core/errors.js.map +1 -0
  52. package/dist/core/exit-codes.d.ts +10 -0
  53. package/dist/core/exit-codes.js +10 -0
  54. package/dist/core/exit-codes.js.map +1 -0
  55. package/dist/core/http.d.ts +24 -0
  56. package/dist/core/http.js +237 -0
  57. package/dist/core/http.js.map +1 -0
  58. package/dist/core/io.d.ts +2 -0
  59. package/dist/core/io.js +39 -0
  60. package/dist/core/io.js.map +1 -0
  61. package/dist/core/output.d.ts +4 -0
  62. package/dist/core/output.js +182 -0
  63. package/dist/core/output.js.map +1 -0
  64. package/dist/core/schema.d.ts +23 -0
  65. package/dist/core/schema.js +319 -0
  66. package/dist/core/schema.js.map +1 -0
  67. package/dist/validation/payload.d.ts +6 -0
  68. package/dist/validation/payload.js +204 -0
  69. package/dist/validation/payload.js.map +1 -0
  70. package/package.json +39 -0
@@ -0,0 +1,63 @@
1
+ import { canUseKeychain } from "../core/auth-store.js";
2
+ import { getConfigPath, readConfig } from "../core/config.js";
3
+ import { printSuccess } from "../core/output.js";
4
+ import { contextFromCommand, getActionCommand } from "./utils.js";
5
+ export function registerConfigCommands(program) {
6
+ const config = program.command("config").description("Inspect local CLI config");
7
+ config
8
+ .command("doctor")
9
+ .description("Show resolved auth/config sources and common risks")
10
+ .action(async (...actionArgs) => {
11
+ const command = getActionCommand(actionArgs);
12
+ const ctx = await contextFromCommand(command);
13
+ const keychainAvailable = await canUseKeychain();
14
+ const savedConfig = await readConfig();
15
+ const warnings = [];
16
+ const recommendations = [];
17
+ if (!ctx.serviceDomain) {
18
+ warnings.push("Service domain is not resolved.");
19
+ recommendations.push("Set --service-domain, MICROCMS_SERVICE_DOMAIN, or configure a profile.");
20
+ }
21
+ if (!ctx.apiKey) {
22
+ warnings.push("API key is not resolved.");
23
+ recommendations.push("Use auth login, MICROCMS_API_KEY, --api-key-stdin, or --prompt.");
24
+ }
25
+ if (ctx.apiKeySourceDetail === "option") {
26
+ warnings.push("API key was passed via --api-key and may leak via shell history/process list.");
27
+ recommendations.push("Prefer --api-key-stdin or auth login --prompt.");
28
+ }
29
+ if (!keychainAvailable) {
30
+ warnings.push("OS keychain is unavailable (keytar optional dependency). Stored keys fallback may not work.");
31
+ recommendations.push("Install optional keytar dependency for secure local key storage.");
32
+ }
33
+ printSuccess(ctx, {
34
+ resolved: {
35
+ profile: {
36
+ value: ctx.profile ?? null,
37
+ source: ctx.profileSource
38
+ },
39
+ serviceDomain: {
40
+ value: ctx.serviceDomain ?? null,
41
+ source: ctx.serviceDomainSource
42
+ },
43
+ apiKey: {
44
+ available: Boolean(ctx.apiKey),
45
+ source: ctx.apiKeySource,
46
+ sourceDetail: ctx.apiKeySourceDetail
47
+ }
48
+ },
49
+ keychain: {
50
+ available: keychainAvailable
51
+ },
52
+ config: {
53
+ path: getConfigPath(),
54
+ defaultProfile: savedConfig.defaultProfile ?? null,
55
+ profileCount: Object.keys(savedConfig.profiles ?? {}).length,
56
+ hasLegacyServiceDomain: Boolean(savedConfig.serviceDomain)
57
+ },
58
+ warnings,
59
+ recommendations
60
+ });
61
+ });
62
+ }
63
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC;IAEjF,MAAM;SACH,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,oDAAoD,CAAC;SACjE,MAAM,CAAC,KAAK,EAAE,GAAG,UAAqB,EAAE,EAAE;QACzC,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,iBAAiB,GAAG,MAAM,cAAc,EAAE,CAAC;QACjD,MAAM,WAAW,GAAG,MAAM,UAAU,EAAE,CAAC;QAEvC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,eAAe,GAAa,EAAE,CAAC;QAErC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;YACjD,eAAe,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;QACjG,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC;YAChB,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;YAC1C,eAAe,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;QAC1F,CAAC;QAED,IAAI,GAAG,CAAC,kBAAkB,KAAK,QAAQ,EAAE,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;YAC/F,eAAe,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC,6FAA6F,CAAC,CAAC;YAC7G,eAAe,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QAC3F,CAAC;QAED,YAAY,CAAC,GAAG,EAAE;YAChB,QAAQ,EAAE;gBACR,OAAO,EAAE;oBACP,KAAK,EAAE,GAAG,CAAC,OAAO,IAAI,IAAI;oBAC1B,MAAM,EAAE,GAAG,CAAC,aAAa;iBAC1B;gBACD,aAAa,EAAE;oBACb,KAAK,EAAE,GAAG,CAAC,aAAa,IAAI,IAAI;oBAChC,MAAM,EAAE,GAAG,CAAC,mBAAmB;iBAChC;gBACD,MAAM,EAAE;oBACN,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;oBAC9B,MAAM,EAAE,GAAG,CAAC,YAAY;oBACxB,YAAY,EAAE,GAAG,CAAC,kBAAkB;iBACrC;aACF;YACD,QAAQ,EAAE;gBACR,SAAS,EAAE,iBAAiB;aAC7B;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,aAAa,EAAE;gBACrB,cAAc,EAAE,WAAW,CAAC,cAAc,IAAI,IAAI;gBAClD,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,MAAM;gBAC5D,sBAAsB,EAAE,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC;aAC3D;YACD,QAAQ;YACR,eAAe;SAChB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerContentCommands(program: Command): void;
@@ -0,0 +1,191 @@
1
+ import { createContent, deleteContent, getContent, listContent, updateContent } from "../core/client.js";
2
+ import { CliError } from "../core/errors.js";
3
+ import { EXIT_CODE } from "../core/exit-codes.js";
4
+ import { assertObjectPayload, readJsonFile } from "../core/io.js";
5
+ import { printSuccess } from "../core/output.js";
6
+ import { contextFromCommand, getActionCommand, parseIntegerOption } from "./utils.js";
7
+ export function registerContentCommands(program) {
8
+ const content = program.command("content").description("Content API operations");
9
+ content
10
+ .command("list")
11
+ .argument("<endpoint>", "API endpoint")
12
+ .option("--limit <limit>")
13
+ .option("--offset <offset>")
14
+ .option("--orders <orders>")
15
+ .option("--q <q>")
16
+ .option("--filters <filters>")
17
+ .option("--fields <fields>")
18
+ .option("--ids <ids>")
19
+ .option("--depth <depth>")
20
+ .option("--draft-key <draftKey>")
21
+ .option("--all", "fetch all pages")
22
+ .action(async (...actionArgs) => {
23
+ const endpoint = actionArgs[0];
24
+ const options = actionArgs[1];
25
+ const command = getActionCommand(actionArgs);
26
+ const ctx = await contextFromCommand(command);
27
+ const queries = compactObject({
28
+ limit: parseIntegerOption("limit", options.limit, { min: 1, max: 100 }),
29
+ offset: parseIntegerOption("offset", options.offset, { min: 0, max: 100000 }),
30
+ orders: options.orders,
31
+ q: options.q,
32
+ filters: options.filters,
33
+ fields: options.fields,
34
+ ids: options.ids,
35
+ depth: parseIntegerOption("depth", options.depth, { min: 0, max: 3 }),
36
+ draftKey: options.draftKey
37
+ });
38
+ const result = options.all
39
+ ? await listContentAll(ctx, endpoint, queries)
40
+ : await listContent(ctx, endpoint, queries);
41
+ printSuccess(ctx, result.data, result.requestId);
42
+ });
43
+ content
44
+ .command("get")
45
+ .argument("<endpoint>", "API endpoint")
46
+ .argument("<id>", "Content ID")
47
+ .option("--draft-key <draftKey>")
48
+ .action(async (...actionArgs) => {
49
+ const endpoint = actionArgs[0];
50
+ const id = actionArgs[1];
51
+ const options = actionArgs[2];
52
+ const command = getActionCommand(actionArgs);
53
+ const ctx = await contextFromCommand(command);
54
+ const result = await getContent(ctx, endpoint, id, compactObject({ draftKey: options.draftKey }));
55
+ printSuccess(ctx, result.data, result.requestId);
56
+ });
57
+ content
58
+ .command("create")
59
+ .argument("<endpoint>", "API endpoint")
60
+ .requiredOption("--file <path>", "Payload JSON file")
61
+ .option("--dry-run", "show operation without sending request")
62
+ .action(async (...actionArgs) => {
63
+ const endpoint = actionArgs[0];
64
+ const options = actionArgs[1];
65
+ const command = getActionCommand(actionArgs);
66
+ const ctx = await contextFromCommand(command);
67
+ const payload = assertObjectPayload(await readJsonFile(options.file));
68
+ if (options.dryRun) {
69
+ printSuccess(ctx, {
70
+ dryRun: true,
71
+ operation: "content.create",
72
+ endpoint,
73
+ payload
74
+ });
75
+ return;
76
+ }
77
+ const result = await createContent(ctx, endpoint, payload);
78
+ printSuccess(ctx, result.data, result.requestId);
79
+ });
80
+ content
81
+ .command("update")
82
+ .argument("<endpoint>", "API endpoint")
83
+ .argument("<id>", "Content ID")
84
+ .requiredOption("--file <path>", "Payload JSON file")
85
+ .option("--dry-run", "show operation without sending request")
86
+ .action(async (...actionArgs) => {
87
+ const endpoint = actionArgs[0];
88
+ const id = actionArgs[1];
89
+ const options = actionArgs[2];
90
+ const command = getActionCommand(actionArgs);
91
+ const ctx = await contextFromCommand(command);
92
+ const payload = assertObjectPayload(await readJsonFile(options.file));
93
+ if (options.dryRun) {
94
+ printSuccess(ctx, {
95
+ dryRun: true,
96
+ operation: "content.update",
97
+ endpoint,
98
+ id,
99
+ payload
100
+ });
101
+ return;
102
+ }
103
+ const result = await updateContent(ctx, endpoint, id, payload);
104
+ printSuccess(ctx, result.data, result.requestId);
105
+ });
106
+ content
107
+ .command("delete")
108
+ .argument("<endpoint>", "API endpoint")
109
+ .argument("<id>", "Content ID")
110
+ .option("--dry-run", "show operation without sending request")
111
+ .action(async (...actionArgs) => {
112
+ const endpoint = actionArgs[0];
113
+ const id = actionArgs[1];
114
+ const options = actionArgs[2];
115
+ const command = getActionCommand(actionArgs);
116
+ const ctx = await contextFromCommand(command);
117
+ if (options.dryRun) {
118
+ printSuccess(ctx, {
119
+ dryRun: true,
120
+ operation: "content.delete",
121
+ endpoint,
122
+ id
123
+ });
124
+ return;
125
+ }
126
+ const result = await deleteContent(ctx, endpoint, id);
127
+ const data = typeof result.data === "object" && result.data !== null
128
+ ? result.data
129
+ : {
130
+ id,
131
+ deleted: true
132
+ };
133
+ printSuccess(ctx, data, result.requestId);
134
+ });
135
+ }
136
+ function compactObject(value) {
137
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
138
+ }
139
+ async function listContentAll(ctx, endpoint, queries) {
140
+ const pageSize = queries.limit ?? 100;
141
+ let offset = queries.offset ?? 0;
142
+ const startOffset = offset;
143
+ const mergedContents = [];
144
+ let requestId = null;
145
+ let totalCount;
146
+ for (let i = 0; i < 10_000; i += 1) {
147
+ const result = await listContent(ctx, endpoint, {
148
+ ...queries,
149
+ limit: pageSize,
150
+ offset
151
+ });
152
+ requestId = result.requestId;
153
+ const page = parseListShape(result.data);
154
+ if (!page) {
155
+ throw new CliError({
156
+ code: "API_ERROR",
157
+ message: "--all requires a list response containing `contents` and `totalCount`.",
158
+ exitCode: EXIT_CODE.UNKNOWN
159
+ });
160
+ }
161
+ totalCount = page.totalCount;
162
+ mergedContents.push(...page.contents);
163
+ if (mergedContents.length >= totalCount || page.contents.length === 0) {
164
+ break;
165
+ }
166
+ offset += page.contents.length;
167
+ }
168
+ return {
169
+ data: {
170
+ contents: mergedContents,
171
+ totalCount: totalCount ?? mergedContents.length,
172
+ offset: startOffset,
173
+ limit: pageSize
174
+ },
175
+ requestId
176
+ };
177
+ }
178
+ function parseListShape(data) {
179
+ if (typeof data !== "object" || data === null) {
180
+ return null;
181
+ }
182
+ const candidate = data;
183
+ if (!Array.isArray(candidate.contents) || typeof candidate.totalCount !== "number") {
184
+ return null;
185
+ }
186
+ return {
187
+ contents: candidate.contents,
188
+ totalCount: candidate.totalCount
189
+ };
190
+ }
191
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/commands/content.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerMediaCommands(program: Command): void;
@@ -0,0 +1,47 @@
1
+ import { stat } from "node:fs/promises";
2
+ import { uploadMedia } from "../core/client.js";
3
+ import { CliError } from "../core/errors.js";
4
+ import { EXIT_CODE } from "../core/exit-codes.js";
5
+ import { printSuccess } from "../core/output.js";
6
+ import { contextFromCommand, getActionCommand } from "./utils.js";
7
+ export function registerMediaCommands(program) {
8
+ const media = program.command("media").description("Media operations");
9
+ media
10
+ .command("upload")
11
+ .argument("<path>", "Path to media file")
12
+ .option("--dry-run", "show operation without sending request")
13
+ .action(async (...actionArgs) => {
14
+ const path = actionArgs[0];
15
+ const options = actionArgs[1];
16
+ const command = getActionCommand(actionArgs);
17
+ const ctx = await contextFromCommand(command);
18
+ if (options.dryRun) {
19
+ const file = await stat(path).catch(() => {
20
+ throw new CliError({
21
+ code: "INVALID_INPUT",
22
+ message: `Could not read file: ${path}`,
23
+ details: { path },
24
+ exitCode: EXIT_CODE.INVALID_INPUT
25
+ });
26
+ });
27
+ if (!file.isFile()) {
28
+ throw new CliError({
29
+ code: "INVALID_INPUT",
30
+ message: `Path is not a file: ${path}`,
31
+ details: { path },
32
+ exitCode: EXIT_CODE.INVALID_INPUT
33
+ });
34
+ }
35
+ printSuccess(ctx, {
36
+ dryRun: true,
37
+ operation: "media.upload",
38
+ path,
39
+ size: file.size
40
+ });
41
+ return;
42
+ }
43
+ const result = await uploadMedia(ctx, path);
44
+ printSuccess(ctx, result.data, result.requestId);
45
+ });
46
+ }
47
+ //# sourceMappingURL=media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/commands/media.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAEvE,KAAK;SACF,OAAO,CAAC,QAAQ,CAAC;SACjB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;SACxC,MAAM,CAAC,WAAW,EAAE,wCAAwC,CAAC;SAC7D,MAAM,CAAC,KAAK,EAAE,GAAG,UAAqB,EAAE,EAAE;QACzC,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAW,CAAC;QACrC,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAyB,CAAC;QACtD,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAE9C,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBACvC,MAAM,IAAI,QAAQ,CAAC;oBACjB,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE,wBAAwB,IAAI,EAAE;oBACvC,OAAO,EAAE,EAAE,IAAI,EAAE;oBACjB,QAAQ,EAAE,SAAS,CAAC,aAAa;iBAClC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnB,MAAM,IAAI,QAAQ,CAAC;oBACjB,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE,uBAAuB,IAAI,EAAE;oBACtC,OAAO,EAAE,EAAE,IAAI,EAAE;oBACjB,QAAQ,EAAE,SAAS,CAAC,aAAa;iBAClC,CAAC,CAAC;YACL,CAAC;YAED,YAAY,CAAC,GAAG,EAAE;gBAChB,MAAM,EAAE,IAAI;gBACZ,SAAS,EAAE,cAAc;gBACzB,IAAI;gBACJ,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC5C,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerSchemaCommands(program: Command): void;
@@ -0,0 +1,71 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import { getApiInfo, listApis } from "../core/client.js";
4
+ import { buildSchemaBundle, extractApiEndpoints } from "../core/schema.js";
5
+ import { CliError } from "../core/errors.js";
6
+ import { EXIT_CODE } from "../core/exit-codes.js";
7
+ import { printSuccess } from "../core/output.js";
8
+ import { contextFromCommand, getActionCommand } from "./utils.js";
9
+ export function registerSchemaCommands(program) {
10
+ const schema = program.command("schema").description("Schema operations");
11
+ schema
12
+ .command("pull")
13
+ .description("Fetch API schema metadata and save to file")
14
+ .option("--out <path>", "output JSON file", "microcms-schema.json")
15
+ .option("--endpoints <list>", "comma-separated endpoints to pull")
16
+ .action(async (...actionArgs) => {
17
+ const options = actionArgs[0];
18
+ const command = getActionCommand(actionArgs);
19
+ const ctx = await contextFromCommand(command);
20
+ const selectedEndpoints = parseEndpointsOption(options.endpoints);
21
+ let requestId = null;
22
+ let endpoints;
23
+ if (selectedEndpoints.length > 0) {
24
+ endpoints = selectedEndpoints;
25
+ }
26
+ else {
27
+ const listed = await listApis(ctx);
28
+ requestId = listed.requestId;
29
+ endpoints = extractApiEndpoints(listed.data);
30
+ }
31
+ if (endpoints.length === 0) {
32
+ throw new CliError({
33
+ code: "INVALID_INPUT",
34
+ message: "No endpoints were found. Specify --endpoints or check API permissions.",
35
+ exitCode: EXIT_CODE.INVALID_INPUT
36
+ });
37
+ }
38
+ const pulled = [];
39
+ for (const endpoint of endpoints) {
40
+ const info = await getApiInfo(ctx, endpoint);
41
+ requestId = info.requestId ?? requestId;
42
+ pulled.push({
43
+ endpoint,
44
+ api: info.data
45
+ });
46
+ }
47
+ const bundle = buildSchemaBundle({
48
+ serviceDomain: ctx.serviceDomain,
49
+ apis: pulled
50
+ });
51
+ const outPath = options.out ?? "microcms-schema.json";
52
+ await mkdir(dirname(outPath), { recursive: true });
53
+ await writeFile(outPath, JSON.stringify(bundle, null, 2), "utf8");
54
+ printSuccess(ctx, {
55
+ out: outPath,
56
+ endpointCount: pulled.length,
57
+ endpoints: pulled.map((item) => item.endpoint)
58
+ }, requestId);
59
+ });
60
+ }
61
+ function parseEndpointsOption(value) {
62
+ if (!value) {
63
+ return [];
64
+ }
65
+ const endpoints = value
66
+ .split(",")
67
+ .map((endpoint) => endpoint.trim())
68
+ .filter((endpoint) => endpoint.length > 0);
69
+ return [...new Set(endpoints)];
70
+ }
71
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/commands/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAOlE,MAAM,UAAU,sBAAsB,CAAC,OAAgB;IACrD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;IAE1E,MAAM;SACH,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,4CAA4C,CAAC;SACzD,MAAM,CAAC,cAAc,EAAE,kBAAkB,EAAE,sBAAsB,CAAC;SAClE,MAAM,CAAC,oBAAoB,EAAE,mCAAmC,CAAC;SACjE,MAAM,CAAC,KAAK,EAAE,GAAG,UAAqB,EAAE,EAAE;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAgB,CAAC;QAC7C,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAE9C,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClE,IAAI,SAAS,GAAkB,IAAI,CAAC;QACpC,IAAI,SAAmB,CAAC;QAExB,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,SAAS,GAAG,iBAAiB,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;YACnC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YAC7B,SAAS,GAAG,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC/C,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,QAAQ,CAAC;gBACjB,IAAI,EAAE,eAAe;gBACrB,OAAO,EAAE,wEAAwE;gBACjF,QAAQ,EAAE,SAAS,CAAC,aAAa;aAClC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,MAAM,GAA8C,EAAE,CAAC;QAC7D,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC7C,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC;gBACV,QAAQ;gBACR,GAAG,EAAE,IAAI,CAAC,IAAI;aACf,CAAC,CAAC;QACL,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,CAAC;YAC/B,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,IAAI,sBAAsB,CAAC;QACtD,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAElE,YAAY,CACV,GAAG,EACH;YACE,GAAG,EAAE,OAAO;YACZ,aAAa,EAAE,MAAM,CAAC,MAAM;YAC5B,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;SAC/C,EACD,SAAS,CACV,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAyB;IACrD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAG,KAAK;SACpB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;SAClC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE7C,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerTypesCommands(program: Command): void;
@@ -0,0 +1,85 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ import { getApiInfo, listApis } from "../core/client.js";
4
+ import { readJsonFile } from "../core/io.js";
5
+ import { buildSchemaBundle, extractApiEndpoints, generateTypesFromSchema } from "../core/schema.js";
6
+ import { CliError } from "../core/errors.js";
7
+ import { EXIT_CODE } from "../core/exit-codes.js";
8
+ import { printSuccess } from "../core/output.js";
9
+ import { contextFromCommand, getActionCommand } from "./utils.js";
10
+ export function registerTypesCommands(program) {
11
+ const types = program.command("types").description("Type generation operations");
12
+ types
13
+ .command("generate")
14
+ .description("Generate TypeScript type definitions from microCMS API schema")
15
+ .option("--schema <path>", "use local schema JSON file")
16
+ .option("--out <path>", "output declaration file", "microcms-types.d.ts")
17
+ .option("--endpoints <list>", "comma-separated endpoints to fetch (when --schema is not used)")
18
+ .action(async (...actionArgs) => {
19
+ const options = actionArgs[0];
20
+ const command = getActionCommand(actionArgs);
21
+ const ctx = await contextFromCommand(command);
22
+ let source;
23
+ let requestId = null;
24
+ if (options.schema) {
25
+ source = await readJsonFile(options.schema);
26
+ }
27
+ else {
28
+ const selectedEndpoints = parseEndpointsOption(options.endpoints);
29
+ let endpoints;
30
+ if (selectedEndpoints.length > 0) {
31
+ endpoints = selectedEndpoints;
32
+ }
33
+ else {
34
+ const listed = await listApis(ctx);
35
+ requestId = listed.requestId;
36
+ endpoints = extractApiEndpoints(listed.data);
37
+ }
38
+ if (endpoints.length === 0) {
39
+ throw new CliError({
40
+ code: "INVALID_INPUT",
41
+ message: "No endpoints were found. Specify --endpoints or provide --schema.",
42
+ exitCode: EXIT_CODE.INVALID_INPUT
43
+ });
44
+ }
45
+ const apis = [];
46
+ for (const endpoint of endpoints) {
47
+ const info = await getApiInfo(ctx, endpoint);
48
+ requestId = info.requestId ?? requestId;
49
+ apis.push({ endpoint, api: info.data });
50
+ }
51
+ source = buildSchemaBundle({
52
+ serviceDomain: ctx.serviceDomain,
53
+ apis
54
+ });
55
+ }
56
+ const generated = generateTypesFromSchema(source);
57
+ if (generated.endpointCount === 0) {
58
+ throw new CliError({
59
+ code: "INVALID_INPUT",
60
+ message: "No schema entries were found to generate types.",
61
+ exitCode: EXIT_CODE.INVALID_INPUT
62
+ });
63
+ }
64
+ const outPath = options.out ?? "microcms-types.d.ts";
65
+ await mkdir(dirname(outPath), { recursive: true });
66
+ await writeFile(outPath, generated.code, "utf8");
67
+ printSuccess(ctx, {
68
+ out: outPath,
69
+ endpointCount: generated.endpointCount,
70
+ warnings: generated.warnings,
71
+ source: options.schema ? "schema_file" : "management_api"
72
+ }, requestId);
73
+ });
74
+ }
75
+ function parseEndpointsOption(value) {
76
+ if (!value) {
77
+ return [];
78
+ }
79
+ const endpoints = value
80
+ .split(",")
81
+ .map((endpoint) => endpoint.trim())
82
+ .filter((endpoint) => endpoint.length > 0);
83
+ return [...new Set(endpoints)];
84
+ }
85
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/commands/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Command } from "commander";
2
+ import { type RuntimeContext } from "../core/context.js";
3
+ export declare function contextFromCommand(command: Command): Promise<RuntimeContext>;
4
+ export declare function getActionCommand(args: unknown[]): Command;
5
+ export declare function parseIntegerOption(name: string, value: string | undefined, range?: {
6
+ min?: number;
7
+ max?: number;
8
+ }): number | undefined;
@@ -0,0 +1,56 @@
1
+ import { createRuntimeContext } from "../core/context.js";
2
+ import { CliError } from "../core/errors.js";
3
+ import { EXIT_CODE } from "../core/exit-codes.js";
4
+ export async function contextFromCommand(command) {
5
+ const options = command.optsWithGlobals();
6
+ return createRuntimeContext(options);
7
+ }
8
+ export function getActionCommand(args) {
9
+ const command = args.at(-1);
10
+ if (command &&
11
+ typeof command === "object" &&
12
+ "optsWithGlobals" in command &&
13
+ typeof command.optsWithGlobals === "function") {
14
+ return command;
15
+ }
16
+ throw new Error("Command context is unavailable");
17
+ }
18
+ export function parseIntegerOption(name, value, range) {
19
+ if (!value) {
20
+ return undefined;
21
+ }
22
+ if (!/^\d+$/.test(value.trim())) {
23
+ throw invalidInteger(name, value, describeRange(range));
24
+ }
25
+ const parsed = Number.parseInt(value, 10);
26
+ if (!Number.isFinite(parsed)) {
27
+ throw invalidInteger(name, value, describeRange(range));
28
+ }
29
+ if (range?.min !== undefined && parsed < range.min) {
30
+ throw invalidInteger(name, value, describeRange(range));
31
+ }
32
+ if (range?.max !== undefined && parsed > range.max) {
33
+ throw invalidInteger(name, value, describeRange(range));
34
+ }
35
+ return parsed;
36
+ }
37
+ function invalidInteger(name, value, expected) {
38
+ return new CliError({
39
+ code: "INVALID_INPUT",
40
+ message: `Invalid ${name}: ${value}. Expected ${expected}.`,
41
+ exitCode: EXIT_CODE.INVALID_INPUT
42
+ });
43
+ }
44
+ function describeRange(range) {
45
+ if (!range || (range.min === undefined && range.max === undefined)) {
46
+ return "integer";
47
+ }
48
+ if (range.min !== undefined && range.max !== undefined) {
49
+ return `integer in range ${range.min}-${range.max}`;
50
+ }
51
+ if (range.min !== undefined) {
52
+ return `integer >= ${range.min}`;
53
+ }
54
+ return `integer <= ${range.max}`;
55
+ }
56
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/commands/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from "commander";
2
+ export declare function registerValidateCommand(program: Command): void;
@@ -0,0 +1,38 @@
1
+ import { getApiInfo } from "../core/client.js";
2
+ import { CliError } from "../core/errors.js";
3
+ import { EXIT_CODE } from "../core/exit-codes.js";
4
+ import { assertObjectPayload, readJsonFile } from "../core/io.js";
5
+ import { printSuccess } from "../core/output.js";
6
+ import { validatePayload } from "../validation/payload.js";
7
+ import { contextFromCommand } from "./utils.js";
8
+ export function registerValidateCommand(program) {
9
+ program
10
+ .command("validate")
11
+ .argument("<endpoint>", "API endpoint")
12
+ .requiredOption("--file <path>", "Payload JSON file")
13
+ .option("--strict-warnings", "treat warnings as validation errors")
14
+ .description("Run lightweight payload precheck before create/update")
15
+ .action(async (endpoint, options, command) => {
16
+ const ctx = await contextFromCommand(command);
17
+ const payload = assertObjectPayload(await readJsonFile(options.file));
18
+ const apiInfo = await getApiInfo(ctx, endpoint);
19
+ const result = validatePayload(payload, apiInfo.data);
20
+ const hasStrictWarningFailure = Boolean(options.strictWarnings && result.warnings.length > 0);
21
+ if (!result.valid || hasStrictWarningFailure) {
22
+ throw new CliError({
23
+ code: "INVALID_INPUT",
24
+ message: "Payload validation failed",
25
+ details: {
26
+ ...result,
27
+ strictWarnings: Boolean(options.strictWarnings)
28
+ },
29
+ exitCode: EXIT_CODE.INVALID_INPUT
30
+ });
31
+ }
32
+ printSuccess(ctx, {
33
+ endpoint,
34
+ ...result
35
+ }, apiInfo.requestId);
36
+ });
37
+ }
38
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,UAAU,uBAAuB,CAAC,OAAgB;IACtD,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC;SACtC,cAAc,CAAC,eAAe,EAAE,mBAAmB,CAAC;SACpD,MAAM,CAAC,mBAAmB,EAAE,qCAAqC,CAAC;SAClE,WAAW,CAAC,uDAAuD,CAAC;SACpE,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,OAAmD,EAAE,OAAgB,EAAE,EAAE;QACxG,MAAM,GAAG,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,uBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAE9F,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,uBAAuB,EAAE,CAAC;YAC7C,MAAM,IAAI,QAAQ,CAAC;gBACjB,IAAI,EAAE,eAAe;gBACrB,OAAO,EAAE,2BAA2B;gBACpC,OAAO,EAAE;oBACP,GAAG,MAAM;oBACT,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC;iBAChD;gBACD,QAAQ,EAAE,SAAS,CAAC,aAAa;aAClC,CAAC,CAAC;QACL,CAAC;QAED,YAAY,CACV,GAAG,EACH;YACE,QAAQ;YACR,GAAG,MAAM;SACV,EACD,OAAO,CAAC,SAAS,CAClB,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC"}