not-manage 0.2.2 → 0.2.3
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.
- package/README.md +42 -6
- package/bin/not-manage.js +15 -2
- package/package.json +1 -1
- package/src/agent-input.js +101 -0
- package/src/cli-errors.js +109 -0
- package/src/cli.js +835 -64
- package/src/clio-api.js +108 -6
- package/src/commands-agent-context.js +119 -0
- package/src/commands-auth.js +336 -148
- package/src/commands-doctor.js +178 -0
- package/src/commands-request.js +144 -0
- package/src/compact-output.js +89 -0
- package/src/prompt.js +48 -0
- package/src/redaction.js +62 -25
- package/src/resource-command-runner.js +75 -4
- package/src/resource-handlers.js +15 -6
- package/src/resource-metadata.js +18 -0
- package/src/store.js +1 -1
|
@@ -3,7 +3,10 @@ const {
|
|
|
3
3
|
fetchResourcePage,
|
|
4
4
|
getValidAccessToken,
|
|
5
5
|
} = require("./clio-api");
|
|
6
|
+
const { readIdsInput } = require("./agent-input");
|
|
6
7
|
const { fetchPages } = require("./resource-utils");
|
|
8
|
+
const { maybeCompactPayload } = require("./compact-output");
|
|
9
|
+
const { UsageError } = require("./cli-errors");
|
|
7
10
|
const { maybeRedactData, maybeRedactPayload } = require("./redaction");
|
|
8
11
|
const { getConfig, getTokenSet } = require("./store");
|
|
9
12
|
|
|
@@ -44,6 +47,16 @@ async function fetchDefaultItemPayload({ accessToken, apiPath, config, id, query
|
|
|
44
47
|
return fetchResourceById(config, accessToken, apiPath, id, query);
|
|
45
48
|
}
|
|
46
49
|
|
|
50
|
+
function buildGetJsonEnvelope(items, requestedCount) {
|
|
51
|
+
return {
|
|
52
|
+
data: items,
|
|
53
|
+
meta: {
|
|
54
|
+
requested_count: requestedCount,
|
|
55
|
+
returned_count: items.length,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
47
60
|
function createListCommand(commandConfig) {
|
|
48
61
|
const {
|
|
49
62
|
apiPath,
|
|
@@ -69,7 +82,10 @@ function createListCommand(commandConfig) {
|
|
|
69
82
|
options,
|
|
70
83
|
query,
|
|
71
84
|
});
|
|
72
|
-
const data =
|
|
85
|
+
const data = maybeCompactPayload(
|
|
86
|
+
maybeRedactData(result.data, options, redactionResourceType),
|
|
87
|
+
options
|
|
88
|
+
);
|
|
73
89
|
|
|
74
90
|
if (options.json) {
|
|
75
91
|
const jsonMeta = buildJsonMeta ? buildJsonMeta({ data, options, result }) : {};
|
|
@@ -105,11 +121,62 @@ function createGetCommand(commandConfig) {
|
|
|
105
121
|
} = commandConfig;
|
|
106
122
|
|
|
107
123
|
return async function getCommand(options = {}) {
|
|
108
|
-
if (!options.id) {
|
|
109
|
-
throw new
|
|
124
|
+
if (!options.id && !options.idsFile) {
|
|
125
|
+
throw new UsageError(usage, {
|
|
126
|
+
code: "missing_resource_id",
|
|
127
|
+
hint: usage.replace(/^Usage:\s*/, ""),
|
|
128
|
+
details: { missing: ["id"] },
|
|
129
|
+
});
|
|
110
130
|
}
|
|
111
131
|
|
|
112
132
|
const { accessToken, config } = await getAuthContext();
|
|
133
|
+
|
|
134
|
+
if (options.idsFile) {
|
|
135
|
+
if (options.id) {
|
|
136
|
+
throw new UsageError("Pass either an ID argument or `--ids-file`, not both.", {
|
|
137
|
+
code: "conflicting_id_inputs",
|
|
138
|
+
hint: "Use `not-manage <resource> get <id>` or `not-manage <resource> get --ids-file ids.txt --json`.",
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (!options.json) {
|
|
142
|
+
throw new UsageError("Bulk `get` from `--ids-file` requires `--json`.", {
|
|
143
|
+
code: "json_required_for_bulk_get",
|
|
144
|
+
hint: "Re-run with `--json` or `--agent`.",
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const ids = await readIdsInput(options.idsFile);
|
|
149
|
+
if (ids.length === 0) {
|
|
150
|
+
throw new UsageError("Bulk `get` did not receive any IDs.", {
|
|
151
|
+
code: "missing_resource_id",
|
|
152
|
+
hint: "Provide one ID per line, a JSON array of IDs, or objects with an `id` field.",
|
|
153
|
+
details: { missing: ["id"] },
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const items = [];
|
|
158
|
+
for (const id of ids) {
|
|
159
|
+
const payload = await fetchItemPayload({
|
|
160
|
+
accessToken,
|
|
161
|
+
apiPath,
|
|
162
|
+
config,
|
|
163
|
+
id,
|
|
164
|
+
options,
|
|
165
|
+
query: {
|
|
166
|
+
fields: options.fields || defaultFields,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
const redactedPayload = maybeCompactPayload(
|
|
170
|
+
maybeRedactPayload(payload, options, redactionResourceType),
|
|
171
|
+
options
|
|
172
|
+
);
|
|
173
|
+
items.push(redactedPayload?.data ?? redactedPayload);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.log(JSON.stringify(buildGetJsonEnvelope(items, ids.length), null, options.compact ? 0 : 2));
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
113
180
|
const payload = await fetchItemPayload({
|
|
114
181
|
accessToken,
|
|
115
182
|
apiPath,
|
|
@@ -120,7 +187,10 @@ function createGetCommand(commandConfig) {
|
|
|
120
187
|
fields: options.fields || defaultFields,
|
|
121
188
|
},
|
|
122
189
|
});
|
|
123
|
-
const redactedPayload =
|
|
190
|
+
const redactedPayload = maybeCompactPayload(
|
|
191
|
+
maybeRedactPayload(payload, options, redactionResourceType),
|
|
192
|
+
options
|
|
193
|
+
);
|
|
124
194
|
|
|
125
195
|
if (options.json) {
|
|
126
196
|
console.log(JSON.stringify(redactedPayload, null, 2));
|
|
@@ -132,6 +202,7 @@ function createGetCommand(commandConfig) {
|
|
|
132
202
|
}
|
|
133
203
|
|
|
134
204
|
module.exports = {
|
|
205
|
+
buildGetJsonEnvelope,
|
|
135
206
|
buildListJsonEnvelope,
|
|
136
207
|
buildSummaryMessage,
|
|
137
208
|
createGetCommand,
|
package/src/resource-handlers.js
CHANGED
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
} = require("./resource-display");
|
|
7
7
|
const { buildListQueryFromResource } = require("./resource-query-builder");
|
|
8
8
|
const { createGetCommand, createListCommand } = require("./resource-command-runner");
|
|
9
|
+
const { getResourceMetadata } = require("./resource-metadata");
|
|
9
10
|
|
|
10
11
|
const RESOURCE_HANDLERS = {
|
|
11
12
|
activities: {
|
|
@@ -21,7 +22,7 @@ const RESOURCE_HANDLERS = {
|
|
|
21
22
|
const GENERIC_HANDLER_CACHE = new Map();
|
|
22
23
|
|
|
23
24
|
function createGenericHandlers(resourceMetadata) {
|
|
24
|
-
if (!resourceMetadata
|
|
25
|
+
if (!resourceMetadata) {
|
|
25
26
|
return null;
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -30,15 +31,23 @@ function createGenericHandlers(resourceMetadata) {
|
|
|
30
31
|
return cached;
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
const displayMetadata =
|
|
35
|
+
resourceMetadata.display
|
|
36
|
+
? resourceMetadata
|
|
37
|
+
: getResourceMetadata(resourceMetadata.handlerKey);
|
|
38
|
+
if (!displayMetadata?.display) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
const handlers = {};
|
|
34
43
|
|
|
35
|
-
if (resourceMetadata.capabilities.list.enabled &&
|
|
36
|
-
const printList = createListPrinter(
|
|
44
|
+
if (resourceMetadata.capabilities.list.enabled && displayMetadata.display.list) {
|
|
45
|
+
const printList = createListPrinter(displayMetadata.display.list);
|
|
37
46
|
handlers.list = createListCommand({
|
|
38
47
|
apiPath: resourceMetadata.apiPath,
|
|
39
48
|
buildQuery: (options) =>
|
|
40
49
|
buildListQueryFromResource(resourceMetadata, options, resourceMetadata.listQuery),
|
|
41
|
-
formatRow:
|
|
50
|
+
formatRow: displayMetadata.display.list.formatRow,
|
|
42
51
|
pluralLabel: resourceMetadata.summaryLabels.plural,
|
|
43
52
|
printList,
|
|
44
53
|
redactionResourceType: resourceMetadata.redaction.resourceType,
|
|
@@ -46,8 +55,8 @@ function createGenericHandlers(resourceMetadata) {
|
|
|
46
55
|
});
|
|
47
56
|
}
|
|
48
57
|
|
|
49
|
-
if (resourceMetadata.capabilities.get.enabled &&
|
|
50
|
-
const printItem = createDetailPrinter(
|
|
58
|
+
if (resourceMetadata.capabilities.get.enabled && displayMetadata.display.get) {
|
|
59
|
+
const printItem = createDetailPrinter(displayMetadata.display.get);
|
|
51
60
|
handlers.get = createGetCommand({
|
|
52
61
|
apiPath: resourceMetadata.apiPath,
|
|
53
62
|
defaultFields: resourceMetadata.defaultFields.get,
|
package/src/resource-metadata.js
CHANGED
|
@@ -2217,9 +2217,27 @@ function listRequiredOptionFlags(resourceMetadata, sub) {
|
|
|
2217
2217
|
});
|
|
2218
2218
|
}
|
|
2219
2219
|
|
|
2220
|
+
function findMissingRequiredOptions(resourceMetadata, sub, options = {}) {
|
|
2221
|
+
if (!resourceMetadata) {
|
|
2222
|
+
return [];
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
const requiredOptions = resourceMetadata.capabilities?.[sub]?.requiredOptions || [];
|
|
2226
|
+
return requiredOptions
|
|
2227
|
+
.filter((propertyName) => {
|
|
2228
|
+
const value = options[propertyName];
|
|
2229
|
+
return value === undefined || value === null || value === "";
|
|
2230
|
+
})
|
|
2231
|
+
.map((propertyName) => {
|
|
2232
|
+
const optionName = resourceMetadata.optionSchema?.[sub]?.[propertyName]?.option;
|
|
2233
|
+
return optionName ? `--${optionName}` : `--${propertyName}`;
|
|
2234
|
+
});
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2220
2237
|
module.exports = {
|
|
2221
2238
|
RESOURCE_METADATA,
|
|
2222
2239
|
RESOURCE_ORDER,
|
|
2240
|
+
findMissingRequiredOptions,
|
|
2223
2241
|
getResourceMetadata,
|
|
2224
2242
|
listResourceMetadata,
|
|
2225
2243
|
listRequiredOptionFlags,
|
package/src/store.js
CHANGED
|
@@ -153,7 +153,7 @@ async function getStoredTokenSet() {
|
|
|
153
153
|
};
|
|
154
154
|
} catch (_error) {
|
|
155
155
|
throw new Error(
|
|
156
|
-
"Stored token data is invalid. Run `not-manage auth revoke` then `not-manage auth login`."
|
|
156
|
+
"Stored token data is invalid. Run `not-manage auth revoke --yes` then `not-manage auth login`."
|
|
157
157
|
);
|
|
158
158
|
}
|
|
159
159
|
}
|