@tolinax/ayoune-cli 2026.3.0 → 2026.4.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.
- package/data/contextSlots.js +189 -0
- package/data/modelsAndRights.js +56 -0
- package/data/modules.js +16 -0
- package/lib/api/apiCallHandler.js +6 -2
- package/lib/api/apiClient.js +9 -1
- package/lib/api/auditCallHandler.js +2 -2
- package/lib/api/handleAPIError.js +20 -18
- package/lib/api/login.js +3 -3
- package/lib/api/searchClient.js +119 -0
- package/lib/commands/createAccessCommand.js +126 -0
- package/lib/commands/createActionsCommand.js +40 -9
- package/lib/commands/createAiCommand.js +17 -17
- package/lib/commands/createAliasCommand.js +4 -6
- package/lib/commands/createAuditCommand.js +5 -9
- package/lib/commands/createBatchCommand.js +15 -28
- package/lib/commands/createCompletionsCommand.js +6 -3
- package/lib/commands/createConfigCommand.js +8 -14
- package/lib/commands/createContextCommand.js +163 -0
- package/lib/commands/createCopyCommand.js +4 -7
- package/lib/commands/createCreateCommand.js +4 -7
- package/lib/commands/createDeleteCommand.js +4 -6
- package/lib/commands/createDeployCommand.js +31 -55
- package/lib/commands/createDescribeCommand.js +12 -10
- package/lib/commands/createEditCommand.js +13 -8
- package/lib/commands/createEventsCommand.js +4 -4
- package/lib/commands/createExecCommand.js +65 -35
- package/lib/commands/createExportCommand.js +21 -24
- package/lib/commands/createGetCommand.js +13 -14
- package/lib/commands/createJobsCommand.js +8 -13
- package/lib/commands/createListCommand.js +13 -14
- package/lib/commands/createLoginCommand.js +16 -4
- package/lib/commands/createLogoutCommand.js +2 -2
- package/lib/commands/createModulesCommand.js +16 -19
- package/lib/commands/createMonitorCommand.js +9 -16
- package/lib/commands/createPermissionsCommand.js +10 -18
- package/lib/commands/createProgram.js +47 -21
- package/lib/commands/createSearchCommand.js +219 -69
- package/lib/commands/createSelfHostUpdateCommand.js +166 -0
- package/lib/commands/createServicesCommand.js +5 -8
- package/lib/commands/createSetupCommand.js +305 -0
- package/lib/commands/createStatusCommand.js +147 -0
- package/lib/commands/createStorageCommand.js +2 -3
- package/lib/commands/createStreamCommand.js +4 -4
- package/lib/commands/createSyncCommand.js +5 -8
- package/lib/commands/createTemplateCommand.js +9 -16
- package/lib/commands/createUpdateCommand.js +12 -15
- package/lib/commands/createUsersCommand.js +21 -31
- package/lib/commands/createWebhooksCommand.js +15 -22
- package/lib/commands/createWhoAmICommand.js +8 -6
- package/lib/helpers/cliError.js +24 -0
- package/lib/helpers/config.js +1 -0
- package/lib/helpers/configLoader.js +6 -0
- package/lib/helpers/contextInjector.js +65 -0
- package/lib/helpers/contextResolver.js +70 -0
- package/lib/helpers/contextStore.js +46 -0
- package/lib/helpers/handleResponseFormatOptions.js +59 -10
- package/lib/helpers/logo.js +48 -0
- package/lib/helpers/resolveCollectionArgs.js +36 -0
- package/lib/helpers/sanitizeFields.js +18 -0
- package/lib/helpers/secureStorage.js +72 -0
- package/lib/helpers/tokenPayload.js +21 -0
- package/lib/helpers/updateNotifier.js +49 -0
- package/lib/models/getModuleFromCollection.js +4 -1
- package/lib/operations/handleCopySingleOperation.js +10 -2
- package/lib/operations/handleCreateSingleOperation.js +3 -0
- package/lib/operations/handleDescribeSingleOperation.js +23 -0
- package/lib/operations/handleGetOperation.js +9 -3
- package/lib/operations/handleListOperation.js +14 -10
- package/lib/prompts/promptModule.js +9 -6
- package/package.json +163 -158
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Option } from "commander";
|
|
2
|
-
import {
|
|
2
|
+
import { secureStorage } from "../helpers/secureStorage.js";
|
|
3
3
|
import { decodeToken } from "../api/decodeToken.js";
|
|
4
4
|
import { customerSocket } from "../socket/customerSocketClient.js";
|
|
5
5
|
import { spinner } from "../../index.js";
|
|
6
6
|
import yaml from "js-yaml";
|
|
7
7
|
import { EXIT_GENERAL_ERROR } from "../exitCodes.js";
|
|
8
|
+
import { cliError } from "../helpers/cliError.js";
|
|
8
9
|
export function createEventsCommand(program) {
|
|
9
10
|
program
|
|
10
11
|
.command("events")
|
|
@@ -24,7 +25,7 @@ Examples:
|
|
|
24
25
|
.addOption(new Option("-V, --value <value>", "Set the value to listen").default("*"))
|
|
25
26
|
.action(async (options) => {
|
|
26
27
|
try {
|
|
27
|
-
const tokenPayload = decodeToken(
|
|
28
|
+
const tokenPayload = decodeToken(secureStorage.getItem("token"));
|
|
28
29
|
const user = tokenPayload.payload;
|
|
29
30
|
spinner.start({ text: `Starting stream with [${user._customerID}]` });
|
|
30
31
|
const socket = customerSocket(user);
|
|
@@ -53,8 +54,7 @@ Examples:
|
|
|
53
54
|
});
|
|
54
55
|
}
|
|
55
56
|
catch (e) {
|
|
56
|
-
|
|
57
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
57
|
+
cliError(e.message || "An unexpected error occurred", EXIT_GENERAL_ERROR);
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
}
|
|
@@ -1,35 +1,67 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import { api } from "../api/apiClient.js";
|
|
3
|
-
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
2
|
+
import { api, getModuleBaseUrl } from "../api/apiClient.js";
|
|
4
3
|
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
5
4
|
import { saveFile } from "../helpers/saveFile.js";
|
|
6
|
-
import {
|
|
5
|
+
import { secureStorage } from "../helpers/secureStorage.js";
|
|
7
6
|
import { spinner } from "../../index.js";
|
|
8
|
-
import { EXIT_GENERAL_ERROR, EXIT_MISUSE } from "../exitCodes.js";
|
|
7
|
+
import { EXIT_GENERAL_ERROR, EXIT_MISUSE, EXIT_PERMISSION_DENIED } from "../exitCodes.js";
|
|
8
|
+
import { cliError } from "../helpers/cliError.js";
|
|
9
9
|
async function resolveAction(searchTerm) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
var _a, _b;
|
|
11
|
+
// Try su module first (full access), fall back to config module (limited access)
|
|
12
|
+
const modules = ["su", "config"];
|
|
13
|
+
let permissionDenied = false;
|
|
14
|
+
for (const mod of modules) {
|
|
15
|
+
try {
|
|
16
|
+
const token = secureStorage.getItem("token") || "";
|
|
17
|
+
const response = await api({
|
|
18
|
+
baseURL: getModuleBaseUrl(mod),
|
|
19
|
+
method: "get",
|
|
20
|
+
url: "ayouneapiactions",
|
|
21
|
+
params: { q: searchTerm, limit: 50, responseFormat: "json" },
|
|
22
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
23
|
+
});
|
|
24
|
+
const res = response.data;
|
|
25
|
+
if (!(res === null || res === void 0 ? void 0 : res.payload) || !Array.isArray(res.payload) || res.payload.length === 0) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const actions = res.payload.filter((a) => !a.deprecated);
|
|
29
|
+
// Exact operationId match
|
|
30
|
+
const exact = actions.find((a) => a.operationId === searchTerm);
|
|
31
|
+
if (exact)
|
|
32
|
+
return mapAction(exact);
|
|
33
|
+
// Partial operationId match
|
|
34
|
+
const partial = actions.find((a) => { var _a; return (_a = a.operationId) === null || _a === void 0 ? void 0 : _a.includes(searchTerm); });
|
|
35
|
+
if (partial)
|
|
36
|
+
return mapAction(partial);
|
|
37
|
+
// If multiple results, return first match
|
|
38
|
+
if (actions.length > 0)
|
|
39
|
+
return mapAction(actions[0]);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
// On 401/403 permission denied, try next module
|
|
43
|
+
if (((_a = e.response) === null || _a === void 0 ? void 0 : _a.status) === 403 || ((_b = e.response) === null || _b === void 0 ? void 0 : _b.status) === 401) {
|
|
44
|
+
permissionDenied = true;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// For other errors (network, 500, etc.), only throw on last module
|
|
48
|
+
if (mod === modules[modules.length - 1])
|
|
49
|
+
throw e;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Distinguish between "not found" and "permission denied on all modules"
|
|
53
|
+
if (permissionDenied) {
|
|
54
|
+
throw new PermissionError("Permission denied: you do not have access to query API actions. Contact your administrator for the required rights.");
|
|
18
55
|
}
|
|
19
|
-
const actions = res.payload.filter((a) => !a.deprecated);
|
|
20
|
-
// Exact operationId match
|
|
21
|
-
const exact = actions.find((a) => a.operationId === searchTerm);
|
|
22
|
-
if (exact)
|
|
23
|
-
return mapAction(exact);
|
|
24
|
-
// Partial operationId match
|
|
25
|
-
const partial = actions.find((a) => { var _a; return (_a = a.operationId) === null || _a === void 0 ? void 0 : _a.includes(searchTerm); });
|
|
26
|
-
if (partial)
|
|
27
|
-
return mapAction(partial);
|
|
28
|
-
// If multiple results, return first match
|
|
29
|
-
if (actions.length > 0)
|
|
30
|
-
return mapAction(actions[0]);
|
|
31
56
|
return null;
|
|
32
57
|
}
|
|
58
|
+
class PermissionError extends Error {
|
|
59
|
+
constructor(message) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.isPermissionError = true;
|
|
62
|
+
this.name = "PermissionError";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
33
65
|
function mapAction(a) {
|
|
34
66
|
return {
|
|
35
67
|
host: a.host || "",
|
|
@@ -73,8 +105,7 @@ Examples:
|
|
|
73
105
|
spinner.start({ text: `Resolving action: ${operationId}`, color: "magenta" });
|
|
74
106
|
const action = await resolveAction(operationId);
|
|
75
107
|
if (!action) {
|
|
76
|
-
|
|
77
|
-
process.exit(EXIT_MISUSE);
|
|
108
|
+
cliError(`No API action found for: ${operationId}`, EXIT_MISUSE);
|
|
78
109
|
}
|
|
79
110
|
spinner.update({ text: `Executing: ${action.method} https://${action.host}${action.endpoint}` });
|
|
80
111
|
// Parse path params
|
|
@@ -105,8 +136,7 @@ Examples:
|
|
|
105
136
|
body = JSON.parse(opts.body);
|
|
106
137
|
}
|
|
107
138
|
catch (_a) {
|
|
108
|
-
|
|
109
|
-
process.exit(EXIT_MISUSE);
|
|
139
|
+
cliError("Invalid JSON in --body", EXIT_MISUSE);
|
|
110
140
|
}
|
|
111
141
|
}
|
|
112
142
|
if (opts.bodyFile) {
|
|
@@ -116,8 +146,7 @@ Examples:
|
|
|
116
146
|
body = JSON.parse(content);
|
|
117
147
|
}
|
|
118
148
|
catch (_b) {
|
|
119
|
-
|
|
120
|
-
process.exit(EXIT_MISUSE);
|
|
149
|
+
cliError(`Invalid JSON in file: ${opts.bodyFile}`, EXIT_MISUSE);
|
|
121
150
|
}
|
|
122
151
|
}
|
|
123
152
|
if (opts.bodyStdin && !process.stdin.isTTY) {
|
|
@@ -131,8 +160,7 @@ Examples:
|
|
|
131
160
|
body = JSON.parse(stdinContent);
|
|
132
161
|
}
|
|
133
162
|
catch (_c) {
|
|
134
|
-
|
|
135
|
-
process.exit(EXIT_MISUSE);
|
|
163
|
+
cliError("Invalid JSON from stdin", EXIT_MISUSE);
|
|
136
164
|
}
|
|
137
165
|
}
|
|
138
166
|
}
|
|
@@ -160,7 +188,7 @@ Examples:
|
|
|
160
188
|
data: body,
|
|
161
189
|
params: queryParams,
|
|
162
190
|
headers: {
|
|
163
|
-
Authorization: `Bearer ${
|
|
191
|
+
Authorization: `Bearer ${secureStorage.getItem("token")}`,
|
|
164
192
|
},
|
|
165
193
|
});
|
|
166
194
|
const res = response.data;
|
|
@@ -175,8 +203,10 @@ Examples:
|
|
|
175
203
|
}
|
|
176
204
|
}
|
|
177
205
|
catch (e) {
|
|
178
|
-
|
|
179
|
-
|
|
206
|
+
if (e instanceof PermissionError) {
|
|
207
|
+
cliError(e.message, EXIT_PERMISSION_DENIED);
|
|
208
|
+
}
|
|
209
|
+
cliError(e.message || "Failed to execute API action", EXIT_GENERAL_ERROR);
|
|
180
210
|
}
|
|
181
211
|
});
|
|
182
212
|
}
|
|
@@ -4,6 +4,8 @@ import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOpti
|
|
|
4
4
|
import { saveFile } from "../helpers/saveFile.js";
|
|
5
5
|
import { spinner } from "../../index.js";
|
|
6
6
|
import { EXIT_GENERAL_ERROR } from "../exitCodes.js";
|
|
7
|
+
import { cliError } from "../helpers/cliError.js";
|
|
8
|
+
import { sanitizeFields } from "../helpers/sanitizeFields.js";
|
|
7
9
|
export function createExportCommand(program) {
|
|
8
10
|
const exp = program
|
|
9
11
|
.command("export")
|
|
@@ -25,7 +27,7 @@ Examples:
|
|
|
25
27
|
.option("-l, --limit <number>", "Limit results (0 = all)", parseInt, 0)
|
|
26
28
|
.option("-p, --page <number>", "Page number", parseInt, 1)
|
|
27
29
|
.action(async (collection, options) => {
|
|
28
|
-
var _a, _b, _c, _d, _e
|
|
30
|
+
var _a, _b, _c, _d, _e;
|
|
29
31
|
try {
|
|
30
32
|
const opts = { ...program.opts(), ...options };
|
|
31
33
|
const module = getModuleFromCollection(collection);
|
|
@@ -39,7 +41,7 @@ Examples:
|
|
|
39
41
|
if (opts.limit > 0)
|
|
40
42
|
params.limit = opts.limit;
|
|
41
43
|
if (opts.fields)
|
|
42
|
-
params.fields = opts.fields;
|
|
44
|
+
params.fields = sanitizeFields(opts.fields).join(",");
|
|
43
45
|
// Parse filters
|
|
44
46
|
if (opts.filter) {
|
|
45
47
|
const filters = opts.filter.split(",");
|
|
@@ -96,8 +98,8 @@ Examples:
|
|
|
96
98
|
else {
|
|
97
99
|
const res = await apiCallHandler(module.module, collection.toLowerCase(), "get", null, params);
|
|
98
100
|
opts.responseFormat = opts.format;
|
|
99
|
-
handleResponseFormatOptions(opts, res);
|
|
100
|
-
const total = (
|
|
101
|
+
const { result: expResult, meta: expMeta } = handleResponseFormatOptions(opts, res);
|
|
102
|
+
const total = (_e = (_d = expMeta === null || expMeta === void 0 ? void 0 : expMeta.pageInfo) === null || _d === void 0 ? void 0 : _d.totalEntries) !== null && _e !== void 0 ? _e : (Array.isArray(expResult) ? expResult.length : 0);
|
|
101
103
|
spinner.success({ text: `Exported ${total} entries from ${collection}` });
|
|
102
104
|
spinner.stop();
|
|
103
105
|
if (opts.save)
|
|
@@ -105,8 +107,7 @@ Examples:
|
|
|
105
107
|
}
|
|
106
108
|
}
|
|
107
109
|
catch (e) {
|
|
108
|
-
|
|
109
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
110
|
+
cliError(e.message || "Export failed", EXIT_GENERAL_ERROR);
|
|
110
111
|
}
|
|
111
112
|
});
|
|
112
113
|
// ay export list
|
|
@@ -117,7 +118,7 @@ Examples:
|
|
|
117
118
|
.option("-l, --limit <number>", "Limit results", parseInt, 25)
|
|
118
119
|
.option("-p, --page <number>", "Page number", parseInt, 1)
|
|
119
120
|
.action(async (options) => {
|
|
120
|
-
var _a, _b
|
|
121
|
+
var _a, _b;
|
|
121
122
|
try {
|
|
122
123
|
const opts = { ...program.opts(), ...options };
|
|
123
124
|
spinner.start({ text: "Fetching exports...", color: "magenta" });
|
|
@@ -127,16 +128,15 @@ Examples:
|
|
|
127
128
|
responseFormat: opts.responseFormat,
|
|
128
129
|
verbosity: opts.verbosity,
|
|
129
130
|
});
|
|
130
|
-
handleResponseFormatOptions(opts, res);
|
|
131
|
-
const total = (
|
|
131
|
+
const { result: listResult, meta: listMeta } = handleResponseFormatOptions(opts, res);
|
|
132
|
+
const total = (_b = (_a = listMeta === null || listMeta === void 0 ? void 0 : listMeta.pageInfo) === null || _a === void 0 ? void 0 : _a.totalEntries) !== null && _b !== void 0 ? _b : (Array.isArray(listResult) ? listResult.length : 0);
|
|
132
133
|
spinner.success({ text: `Found ${total} exports` });
|
|
133
134
|
spinner.stop();
|
|
134
135
|
if (opts.save)
|
|
135
136
|
await saveFile("exports-list", opts, res);
|
|
136
137
|
}
|
|
137
138
|
catch (e) {
|
|
138
|
-
|
|
139
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
139
|
+
cliError(e.message || "Failed to list exports", EXIT_GENERAL_ERROR);
|
|
140
140
|
}
|
|
141
141
|
});
|
|
142
142
|
// ay export get <id>
|
|
@@ -156,8 +156,7 @@ Examples:
|
|
|
156
156
|
spinner.stop();
|
|
157
157
|
}
|
|
158
158
|
catch (e) {
|
|
159
|
-
|
|
160
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
159
|
+
cliError(e.message || "Failed to get export", EXIT_GENERAL_ERROR);
|
|
161
160
|
}
|
|
162
161
|
});
|
|
163
162
|
// ay export configs
|
|
@@ -166,7 +165,7 @@ Examples:
|
|
|
166
165
|
.description("List export configurations")
|
|
167
166
|
.option("-l, --limit <number>", "Limit results", parseInt, 50)
|
|
168
167
|
.action(async (options) => {
|
|
169
|
-
var _a, _b
|
|
168
|
+
var _a, _b;
|
|
170
169
|
try {
|
|
171
170
|
const opts = { ...program.opts(), ...options };
|
|
172
171
|
spinner.start({ text: "Fetching export configs...", color: "magenta" });
|
|
@@ -175,16 +174,15 @@ Examples:
|
|
|
175
174
|
responseFormat: opts.responseFormat,
|
|
176
175
|
verbosity: opts.verbosity,
|
|
177
176
|
});
|
|
178
|
-
handleResponseFormatOptions(opts, res);
|
|
179
|
-
const total = (
|
|
177
|
+
const { result: cfgResult, meta: cfgMeta } = handleResponseFormatOptions(opts, res);
|
|
178
|
+
const total = (_b = (_a = cfgMeta === null || cfgMeta === void 0 ? void 0 : cfgMeta.pageInfo) === null || _a === void 0 ? void 0 : _a.totalEntries) !== null && _b !== void 0 ? _b : (Array.isArray(cfgResult) ? cfgResult.length : 0);
|
|
180
179
|
spinner.success({ text: `Found ${total} export configurations` });
|
|
181
180
|
spinner.stop();
|
|
182
181
|
if (opts.save)
|
|
183
182
|
await saveFile("export-configs", opts, res);
|
|
184
183
|
}
|
|
185
184
|
catch (e) {
|
|
186
|
-
|
|
187
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
185
|
+
cliError(e.message || "Failed to list export configs", EXIT_GENERAL_ERROR);
|
|
188
186
|
}
|
|
189
187
|
});
|
|
190
188
|
// ay export logs
|
|
@@ -194,26 +192,25 @@ Examples:
|
|
|
194
192
|
.option("-l, --limit <number>", "Limit results", parseInt, 25)
|
|
195
193
|
.option("-p, --page <number>", "Page number", parseInt, 1)
|
|
196
194
|
.action(async (options) => {
|
|
197
|
-
var _a, _b
|
|
195
|
+
var _a, _b;
|
|
198
196
|
try {
|
|
199
197
|
const opts = { ...program.opts(), ...options };
|
|
200
198
|
spinner.start({ text: "Fetching export logs...", color: "magenta" });
|
|
201
|
-
const res = await apiCallHandler("
|
|
199
|
+
const res = await apiCallHandler("export", "exportlogs", "get", null, {
|
|
202
200
|
page: opts.page,
|
|
203
201
|
limit: opts.limit,
|
|
204
202
|
responseFormat: opts.responseFormat,
|
|
205
203
|
verbosity: opts.verbosity,
|
|
206
204
|
});
|
|
207
|
-
handleResponseFormatOptions(opts, res);
|
|
208
|
-
const total = (
|
|
205
|
+
const { result: logResult, meta: logMeta } = handleResponseFormatOptions(opts, res);
|
|
206
|
+
const total = (_b = (_a = logMeta === null || logMeta === void 0 ? void 0 : logMeta.pageInfo) === null || _a === void 0 ? void 0 : _a.totalEntries) !== null && _b !== void 0 ? _b : (Array.isArray(logResult) ? logResult.length : 0);
|
|
209
207
|
spinner.success({ text: `Found ${total} export log entries` });
|
|
210
208
|
spinner.stop();
|
|
211
209
|
if (opts.save)
|
|
212
210
|
await saveFile("export-logs", opts, res);
|
|
213
211
|
}
|
|
214
212
|
catch (e) {
|
|
215
|
-
|
|
216
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
213
|
+
cliError(e.message || "Failed to list export logs", EXIT_GENERAL_ERROR);
|
|
217
214
|
}
|
|
218
215
|
});
|
|
219
216
|
}
|
|
@@ -1,47 +1,46 @@
|
|
|
1
1
|
import { parseInteger } from "../helpers/parseInt.js";
|
|
2
2
|
import { promptCollectionWithModule } from "../prompts/promptCollectionWithModule.js";
|
|
3
|
-
import {
|
|
3
|
+
import { resolveCollectionArgs } from "../helpers/resolveCollectionArgs.js";
|
|
4
4
|
import { saveFile } from "../helpers/saveFile.js";
|
|
5
5
|
import { handleGetOperation } from "../operations/handleGetOperation.js";
|
|
6
6
|
import { localStorage } from "../helpers/localStorage.js";
|
|
7
|
-
import { spinner } from "../../index.js";
|
|
8
7
|
import { EXIT_GENERAL_ERROR, EXIT_MISUSE } from "../exitCodes.js";
|
|
8
|
+
import { cliError } from "../helpers/cliError.js";
|
|
9
9
|
export function createGetCommand(program) {
|
|
10
10
|
program
|
|
11
|
-
.command("get [collection]")
|
|
11
|
+
.command("get [collectionOrModule] [collection]")
|
|
12
12
|
.alias("g")
|
|
13
13
|
.description("Retrieve entries from a collection with field selection")
|
|
14
14
|
.addHelpText("after", `
|
|
15
15
|
Examples:
|
|
16
16
|
ay get contacts Get contacts with default fields
|
|
17
|
+
ay get crm consumers Get consumers (explicit module)
|
|
17
18
|
ay get products -i name price Get only name and price fields
|
|
18
19
|
ay get orders -p 3 -l 10 -r csv Get orders page 3, 10 per page, as CSV`)
|
|
19
20
|
.option("-p, --page <number>", "Page", parseInteger, 1)
|
|
20
21
|
.option("-l, --limit <number>", "Limit", parseInteger, 20)
|
|
21
22
|
.option("-f, --from <date>", "From date")
|
|
22
23
|
.option("-i, --fields <fields...>", "Fields to get")
|
|
23
|
-
.action(async (collection, options) => {
|
|
24
|
+
.action(async (collectionOrModule, collection, options) => {
|
|
24
25
|
try {
|
|
25
26
|
const opts = { ...program.opts(), ...options };
|
|
26
|
-
if (!
|
|
27
|
+
if (!collectionOrModule) {
|
|
27
28
|
if (!process.stdin.isTTY) {
|
|
28
|
-
|
|
29
|
-
process.exit(EXIT_MISUSE);
|
|
29
|
+
cliError("Missing required argument: collection", EXIT_MISUSE);
|
|
30
30
|
}
|
|
31
|
-
|
|
31
|
+
collectionOrModule = await promptCollectionWithModule();
|
|
32
32
|
}
|
|
33
|
-
const
|
|
34
|
-
localStorage.setItem("lastModule",
|
|
35
|
-
localStorage.setItem("lastCollection", collection);
|
|
33
|
+
const resolved = resolveCollectionArgs(collectionOrModule, collection);
|
|
34
|
+
localStorage.setItem("lastModule", resolved.module);
|
|
35
|
+
localStorage.setItem("lastCollection", resolved.collection);
|
|
36
36
|
let result = {};
|
|
37
|
-
result = await handleGetOperation(
|
|
37
|
+
result = await handleGetOperation(resolved.module, resolved.collection, opts);
|
|
38
38
|
if (opts.save) {
|
|
39
39
|
await saveFile("get", opts, result);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
catch (e) {
|
|
43
|
-
|
|
44
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
43
|
+
cliError(e.message || "An unexpected error occurred", EXIT_GENERAL_ERROR);
|
|
45
44
|
}
|
|
46
45
|
});
|
|
47
46
|
}
|
|
@@ -3,6 +3,7 @@ import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOpti
|
|
|
3
3
|
import { saveFile } from "../helpers/saveFile.js";
|
|
4
4
|
import { spinner } from "../../index.js";
|
|
5
5
|
import { EXIT_GENERAL_ERROR } from "../exitCodes.js";
|
|
6
|
+
import { cliError } from "../helpers/cliError.js";
|
|
6
7
|
export function createJobsCommand(program) {
|
|
7
8
|
const jobs = program
|
|
8
9
|
.command("jobs")
|
|
@@ -38,8 +39,7 @@ export function createJobsCommand(program) {
|
|
|
38
39
|
await saveFile("jobs-list", opts, res);
|
|
39
40
|
}
|
|
40
41
|
catch (e) {
|
|
41
|
-
|
|
42
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
42
|
+
cliError(e.message || "Failed to list jobs", EXIT_GENERAL_ERROR);
|
|
43
43
|
}
|
|
44
44
|
});
|
|
45
45
|
// ay jobs triggers
|
|
@@ -67,8 +67,7 @@ export function createJobsCommand(program) {
|
|
|
67
67
|
await saveFile("jobs-triggers", opts, res);
|
|
68
68
|
}
|
|
69
69
|
catch (e) {
|
|
70
|
-
|
|
71
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
70
|
+
cliError(e.message || "Failed to list triggers", EXIT_GENERAL_ERROR);
|
|
72
71
|
}
|
|
73
72
|
});
|
|
74
73
|
// ay jobs automations
|
|
@@ -101,8 +100,7 @@ export function createJobsCommand(program) {
|
|
|
101
100
|
await saveFile("jobs-automations", opts, res);
|
|
102
101
|
}
|
|
103
102
|
catch (e) {
|
|
104
|
-
|
|
105
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
103
|
+
cliError(e.message || "Failed to list automations", EXIT_GENERAL_ERROR);
|
|
106
104
|
}
|
|
107
105
|
});
|
|
108
106
|
// ay jobs execute <automationId>
|
|
@@ -121,8 +119,7 @@ export function createJobsCommand(program) {
|
|
|
121
119
|
body = JSON.parse(opts.body);
|
|
122
120
|
}
|
|
123
121
|
catch (_a) {
|
|
124
|
-
|
|
125
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
122
|
+
cliError("Invalid JSON in --body", EXIT_GENERAL_ERROR);
|
|
126
123
|
}
|
|
127
124
|
}
|
|
128
125
|
const res = await apiCallHandler("automation", `automations/${automationId}/execute`, "post", body, { responseFormat: opts.responseFormat });
|
|
@@ -131,8 +128,7 @@ export function createJobsCommand(program) {
|
|
|
131
128
|
spinner.stop();
|
|
132
129
|
}
|
|
133
130
|
catch (e) {
|
|
134
|
-
|
|
135
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
131
|
+
cliError(e.message || "Failed to execute automation", EXIT_GENERAL_ERROR);
|
|
136
132
|
}
|
|
137
133
|
});
|
|
138
134
|
// ay jobs notifications
|
|
@@ -147,7 +143,7 @@ export function createJobsCommand(program) {
|
|
|
147
143
|
try {
|
|
148
144
|
const opts = { ...program.opts(), ...options };
|
|
149
145
|
spinner.start({ text: "Fetching notifications...", color: "magenta" });
|
|
150
|
-
const res = await apiCallHandler("
|
|
146
|
+
const res = await apiCallHandler("crm", "notifications", "get", null, {
|
|
151
147
|
page: opts.page,
|
|
152
148
|
limit: opts.limit,
|
|
153
149
|
responseFormat: opts.responseFormat,
|
|
@@ -161,8 +157,7 @@ export function createJobsCommand(program) {
|
|
|
161
157
|
await saveFile("jobs-notifications", opts, res);
|
|
162
158
|
}
|
|
163
159
|
catch (e) {
|
|
164
|
-
|
|
165
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
160
|
+
cliError(e.message || "Failed to list notifications", EXIT_GENERAL_ERROR);
|
|
166
161
|
}
|
|
167
162
|
});
|
|
168
163
|
}
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { parseInteger } from "../helpers/parseInt.js";
|
|
2
2
|
import { promptCollectionWithModule } from "../prompts/promptCollectionWithModule.js";
|
|
3
|
-
import {
|
|
3
|
+
import { resolveCollectionArgs } from "../helpers/resolveCollectionArgs.js";
|
|
4
4
|
import { handleListOperation } from "../operations/handleListOperation.js";
|
|
5
5
|
import { saveFile } from "../helpers/saveFile.js";
|
|
6
6
|
import { localStorage } from "../helpers/localStorage.js";
|
|
7
|
-
import { spinner } from "../../index.js";
|
|
8
7
|
import { EXIT_GENERAL_ERROR, EXIT_MISUSE } from "../exitCodes.js";
|
|
8
|
+
import { cliError } from "../helpers/cliError.js";
|
|
9
9
|
export function createListCommand(program) {
|
|
10
10
|
program
|
|
11
|
-
.command("list [collection]")
|
|
11
|
+
.command("list [collectionOrModule] [collection]")
|
|
12
12
|
.alias("l")
|
|
13
13
|
.description("List entries in a collection with pagination support")
|
|
14
14
|
.addHelpText("after", `
|
|
15
15
|
Examples:
|
|
16
16
|
ay list contacts List contacts (page 1, limit 20)
|
|
17
|
+
ay list crm consumers List consumers (explicit module)
|
|
17
18
|
ay list products -p 2 -l 50 List products page 2, 50 per page
|
|
18
19
|
ay list orders -r yaml -s List orders as YAML and save to file
|
|
19
20
|
ay list contacts --all Fetch all pages
|
|
@@ -22,28 +23,26 @@ Examples:
|
|
|
22
23
|
.option("-l, --limit <number>", "Limit", parseInteger, 20)
|
|
23
24
|
.option("-f, --from <date>", "From date")
|
|
24
25
|
.option("-a, --all", "Fetch all pages automatically")
|
|
25
|
-
.action(async (collection, options) => {
|
|
26
|
+
.action(async (collectionOrModule, collection, options) => {
|
|
26
27
|
try {
|
|
27
28
|
const opts = { ...program.opts(), ...options };
|
|
28
|
-
if (!
|
|
29
|
+
if (!collectionOrModule) {
|
|
29
30
|
if (!process.stdin.isTTY) {
|
|
30
|
-
|
|
31
|
-
process.exit(EXIT_MISUSE);
|
|
31
|
+
cliError("Missing required argument: collection", EXIT_MISUSE);
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
collectionOrModule = await promptCollectionWithModule();
|
|
34
34
|
}
|
|
35
|
-
const
|
|
36
|
-
localStorage.setItem("lastModule",
|
|
37
|
-
localStorage.setItem("lastCollection", collection);
|
|
35
|
+
const resolved = resolveCollectionArgs(collectionOrModule, collection);
|
|
36
|
+
localStorage.setItem("lastModule", resolved.module);
|
|
37
|
+
localStorage.setItem("lastCollection", resolved.collection);
|
|
38
38
|
let result = {};
|
|
39
|
-
result = await handleListOperation(
|
|
39
|
+
result = await handleListOperation(resolved.module, resolved.collection, opts);
|
|
40
40
|
if (opts.save) {
|
|
41
41
|
await saveFile("list", opts, result);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
catch (e) {
|
|
45
|
-
|
|
46
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
45
|
+
cliError(e.message || "An unexpected error occurred", EXIT_GENERAL_ERROR);
|
|
47
46
|
}
|
|
48
47
|
});
|
|
49
48
|
}
|
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
import { login } from "../api/login.js";
|
|
2
2
|
import { spinner } from "../../index.js";
|
|
3
3
|
import { EXIT_AUTH_REQUIRED } from "../exitCodes.js";
|
|
4
|
+
import { cliError } from "../helpers/cliError.js";
|
|
5
|
+
import { decodeToken } from "../api/decodeToken.js";
|
|
6
|
+
import chalk from "chalk";
|
|
4
7
|
export function createLoginCommand(program) {
|
|
5
8
|
program
|
|
6
9
|
.command("login")
|
|
7
10
|
.alias("auth")
|
|
8
|
-
.description("Authenticate with your aYOUne account via browser")
|
|
9
|
-
.action(async () => {
|
|
11
|
+
.description("Authenticate with your aYOUne account via browser or JWT token")
|
|
12
|
+
.action(async (_options, cmd) => {
|
|
13
|
+
var _a, _b, _c, _d;
|
|
10
14
|
try {
|
|
15
|
+
// --token is a global option, check it from the parent program
|
|
16
|
+
const globalToken = (_b = (_a = cmd.parent) === null || _a === void 0 ? void 0 : _a.opts()) === null || _b === void 0 ? void 0 : _b.token;
|
|
17
|
+
if (globalToken) {
|
|
18
|
+
// Token was already stored by preAction hook, just confirm
|
|
19
|
+
const decoded = decodeToken(globalToken);
|
|
20
|
+
const username = ((_c = decoded === null || decoded === void 0 ? void 0 : decoded.payload) === null || _c === void 0 ? void 0 : _c.username) || ((_d = decoded === null || decoded === void 0 ? void 0 : decoded.payload) === null || _d === void 0 ? void 0 : _d._id) || "unknown";
|
|
21
|
+
spinner.success({ text: `Authenticated as ${chalk.cyan(username)} via token` });
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
11
24
|
await login();
|
|
12
25
|
}
|
|
13
26
|
catch (e) {
|
|
14
|
-
|
|
15
|
-
process.exit(EXIT_AUTH_REQUIRED);
|
|
27
|
+
cliError(e.message || "An unexpected error occurred", EXIT_AUTH_REQUIRED);
|
|
16
28
|
}
|
|
17
29
|
});
|
|
18
30
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { localStorage } from "../helpers/localStorage.js";
|
|
2
2
|
import { spinner } from "../../index.js";
|
|
3
3
|
import { EXIT_GENERAL_ERROR } from "../exitCodes.js";
|
|
4
|
+
import { cliError } from "../helpers/cliError.js";
|
|
4
5
|
export function createLogoutCommand(program) {
|
|
5
6
|
program
|
|
6
7
|
.command("logout")
|
|
@@ -14,8 +15,7 @@ export function createLogoutCommand(program) {
|
|
|
14
15
|
spinner.success({ text: "Credentials cleared" });
|
|
15
16
|
}
|
|
16
17
|
catch (e) {
|
|
17
|
-
|
|
18
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
18
|
+
cliError(e.message || "An unexpected error occurred", EXIT_GENERAL_ERROR);
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
}
|