@tolinax/ayoune-cli 2026.2.4 → 2026.3.1
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/package.json +160 -158
- package/data/defaultActions.js +0 -9
- package/data/modelsAndRights.js +0 -3189
- package/data/modules.js +0 -111
- package/data/operations.js +0 -5
- package/data/services.js +0 -139
- package/index.js +0 -11
- package/lib/api/apiCallHandler.js +0 -68
- package/lib/api/apiClient.js +0 -100
- package/lib/api/auditCallHandler.js +0 -21
- package/lib/api/decodeToken.js +0 -4
- package/lib/api/handleAPIError.js +0 -59
- package/lib/api/login.js +0 -45
- package/lib/commands/createActionsCommand.js +0 -109
- package/lib/commands/createAiCommand.js +0 -188
- package/lib/commands/createAliasCommand.js +0 -106
- package/lib/commands/createAuditCommand.js +0 -49
- package/lib/commands/createBatchCommand.js +0 -304
- package/lib/commands/createCompletionsCommand.js +0 -169
- package/lib/commands/createConfigCommand.js +0 -208
- package/lib/commands/createCopyCommand.js +0 -39
- package/lib/commands/createCreateCommand.js +0 -50
- package/lib/commands/createDeleteCommand.js +0 -98
- package/lib/commands/createDeployCommand.js +0 -666
- package/lib/commands/createDescribeCommand.js +0 -42
- package/lib/commands/createEditCommand.js +0 -43
- package/lib/commands/createEventsCommand.js +0 -60
- package/lib/commands/createExecCommand.js +0 -182
- package/lib/commands/createExportCommand.js +0 -219
- package/lib/commands/createGetCommand.js +0 -47
- package/lib/commands/createJobsCommand.js +0 -168
- package/lib/commands/createListCommand.js +0 -49
- package/lib/commands/createLoginCommand.js +0 -18
- package/lib/commands/createLogoutCommand.js +0 -21
- package/lib/commands/createModulesCommand.js +0 -89
- package/lib/commands/createMonitorCommand.js +0 -283
- package/lib/commands/createPermissionsCommand.js +0 -241
- package/lib/commands/createProgram.js +0 -185
- package/lib/commands/createSearchCommand.js +0 -101
- package/lib/commands/createServicesCommand.js +0 -228
- package/lib/commands/createStorageCommand.js +0 -54
- package/lib/commands/createStreamCommand.js +0 -50
- package/lib/commands/createSyncCommand.js +0 -177
- package/lib/commands/createTemplateCommand.js +0 -238
- package/lib/commands/createUpdateCommand.js +0 -115
- package/lib/commands/createUsersCommand.js +0 -285
- package/lib/commands/createWebhooksCommand.js +0 -156
- package/lib/commands/createWhoAmICommand.js +0 -88
- package/lib/exitCodes.js +0 -6
- package/lib/helpers/addSpacesToCamelCase.js +0 -5
- package/lib/helpers/config.js +0 -6
- package/lib/helpers/configLoader.js +0 -60
- package/lib/helpers/formatDocument.js +0 -176
- package/lib/helpers/handleResponseFormatOptions.js +0 -85
- package/lib/helpers/initializeSettings.js +0 -14
- package/lib/helpers/localStorage.js +0 -4
- package/lib/helpers/makeRandomToken.js +0 -27
- package/lib/helpers/parseInt.js +0 -7
- package/lib/helpers/requireArg.js +0 -9
- package/lib/helpers/saveFile.js +0 -39
- package/lib/models/getCollections.js +0 -15
- package/lib/models/getModelsInModules.js +0 -13
- package/lib/models/getModuleFromCollection.js +0 -7
- package/lib/operations/handleAuditOperation.js +0 -22
- package/lib/operations/handleCollectionOperation.js +0 -91
- package/lib/operations/handleCopySingleOperation.js +0 -22
- package/lib/operations/handleCreateSingleOperation.js +0 -35
- package/lib/operations/handleDeleteSingleOperation.js +0 -14
- package/lib/operations/handleDescribeSingleOperation.js +0 -22
- package/lib/operations/handleEditOperation.js +0 -51
- package/lib/operations/handleEditRawOperation.js +0 -35
- package/lib/operations/handleGetOperation.js +0 -29
- package/lib/operations/handleGetSingleOperation.js +0 -20
- package/lib/operations/handleListOperation.js +0 -63
- package/lib/operations/handleSingleAuditOperation.js +0 -27
- package/lib/prompts/promptAudits.js +0 -15
- package/lib/prompts/promptCollection.js +0 -13
- package/lib/prompts/promptCollectionInModule.js +0 -13
- package/lib/prompts/promptCollectionWithModule.js +0 -15
- package/lib/prompts/promptConfirm.js +0 -12
- package/lib/prompts/promptDefaultAction.js +0 -13
- package/lib/prompts/promptEntry.js +0 -19
- package/lib/prompts/promptFileName.js +0 -12
- package/lib/prompts/promptFilePath.js +0 -18
- package/lib/prompts/promptModule.js +0 -19
- package/lib/prompts/promptName.js +0 -11
- package/lib/prompts/promptOperation.js +0 -13
- package/lib/socket/customerSocketClient.js +0 -13
- package/lib/socket/socketClient.js +0 -12
- package/lib/types.js +0 -1
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
2
|
-
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
3
|
-
import { saveFile } from "../helpers/saveFile.js";
|
|
4
|
-
import { spinner } from "../../index.js";
|
|
5
|
-
import { EXIT_GENERAL_ERROR } from "../exitCodes.js";
|
|
6
|
-
export function createTemplateCommand(program) {
|
|
7
|
-
const tmpl = program
|
|
8
|
-
.command("templates")
|
|
9
|
-
.alias("tmpl")
|
|
10
|
-
.description("Manage platform templates (email, notification, report, store)");
|
|
11
|
-
// ── EMAIL TEMPLATES ────────────────────────────────────
|
|
12
|
-
const email = tmpl
|
|
13
|
-
.command("email")
|
|
14
|
-
.description("Manage email templates");
|
|
15
|
-
// ay templates email list
|
|
16
|
-
email
|
|
17
|
-
.command("list")
|
|
18
|
-
.alias("ls")
|
|
19
|
-
.description("List email templates")
|
|
20
|
-
.option("--search <query>", "Search by name")
|
|
21
|
-
.option("-l, --limit <number>", "Limit results", parseInt, 50)
|
|
22
|
-
.option("-p, --page <number>", "Page number", parseInt, 1)
|
|
23
|
-
.action(async (options) => {
|
|
24
|
-
var _a, _b, _c;
|
|
25
|
-
try {
|
|
26
|
-
const opts = { ...program.opts(), ...options };
|
|
27
|
-
spinner.start({ text: "Fetching email templates...", color: "magenta" });
|
|
28
|
-
const params = {
|
|
29
|
-
page: opts.page,
|
|
30
|
-
limit: opts.limit,
|
|
31
|
-
responseFormat: opts.responseFormat,
|
|
32
|
-
verbosity: opts.verbosity,
|
|
33
|
-
};
|
|
34
|
-
if (opts.search)
|
|
35
|
-
params.q = opts.search;
|
|
36
|
-
const res = await apiCallHandler("marketing", "emailtemplates", "get", null, params);
|
|
37
|
-
handleResponseFormatOptions(opts, res);
|
|
38
|
-
const total = (_c = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.totalEntries) !== null && _c !== void 0 ? _c : 0;
|
|
39
|
-
spinner.success({ text: `Found ${total} email templates` });
|
|
40
|
-
spinner.stop();
|
|
41
|
-
if (opts.save)
|
|
42
|
-
await saveFile("email-templates", opts, res);
|
|
43
|
-
}
|
|
44
|
-
catch (e) {
|
|
45
|
-
spinner.error({ text: e.message || "Failed to list email templates" });
|
|
46
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
// ay templates email get <id>
|
|
50
|
-
email
|
|
51
|
-
.command("get <id>")
|
|
52
|
-
.description("Get email template details")
|
|
53
|
-
.action(async (id, options) => {
|
|
54
|
-
try {
|
|
55
|
-
const opts = { ...program.opts(), ...options };
|
|
56
|
-
spinner.start({ text: `Fetching email template ${id}...`, color: "magenta" });
|
|
57
|
-
const res = await apiCallHandler("marketing", `emailtemplates/${id}`, "get", null, {
|
|
58
|
-
responseFormat: opts.responseFormat,
|
|
59
|
-
verbosity: opts.verbosity,
|
|
60
|
-
});
|
|
61
|
-
handleResponseFormatOptions(opts, res);
|
|
62
|
-
spinner.success({ text: `Email template ${id} loaded` });
|
|
63
|
-
spinner.stop();
|
|
64
|
-
}
|
|
65
|
-
catch (e) {
|
|
66
|
-
spinner.error({ text: e.message || "Failed to get email template" });
|
|
67
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
// ── NOTIFICATION TEMPLATES ─────────────────────────────
|
|
71
|
-
const notify = tmpl
|
|
72
|
-
.command("notification")
|
|
73
|
-
.alias("notify")
|
|
74
|
-
.description("Manage notification templates");
|
|
75
|
-
// ay templates notification list
|
|
76
|
-
notify
|
|
77
|
-
.command("list")
|
|
78
|
-
.alias("ls")
|
|
79
|
-
.description("List notification templates")
|
|
80
|
-
.option("-l, --limit <number>", "Limit results", parseInt, 50)
|
|
81
|
-
.option("-p, --page <number>", "Page number", parseInt, 1)
|
|
82
|
-
.action(async (options) => {
|
|
83
|
-
var _a, _b, _c;
|
|
84
|
-
try {
|
|
85
|
-
const opts = { ...program.opts(), ...options };
|
|
86
|
-
spinner.start({ text: "Fetching notification templates...", color: "magenta" });
|
|
87
|
-
const res = await apiCallHandler("config", "notificationtemplates", "get", null, {
|
|
88
|
-
page: opts.page,
|
|
89
|
-
limit: opts.limit,
|
|
90
|
-
responseFormat: opts.responseFormat,
|
|
91
|
-
verbosity: opts.verbosity,
|
|
92
|
-
});
|
|
93
|
-
handleResponseFormatOptions(opts, res);
|
|
94
|
-
const total = (_c = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.totalEntries) !== null && _c !== void 0 ? _c : 0;
|
|
95
|
-
spinner.success({ text: `Found ${total} notification templates` });
|
|
96
|
-
spinner.stop();
|
|
97
|
-
if (opts.save)
|
|
98
|
-
await saveFile("notification-templates", opts, res);
|
|
99
|
-
}
|
|
100
|
-
catch (e) {
|
|
101
|
-
spinner.error({ text: e.message || "Failed to list notification templates" });
|
|
102
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
// ay templates notification get <id>
|
|
106
|
-
notify
|
|
107
|
-
.command("get <id>")
|
|
108
|
-
.description("Get notification template details")
|
|
109
|
-
.action(async (id, options) => {
|
|
110
|
-
try {
|
|
111
|
-
const opts = { ...program.opts(), ...options };
|
|
112
|
-
spinner.start({ text: `Fetching notification template ${id}...`, color: "magenta" });
|
|
113
|
-
const res = await apiCallHandler("config", `notificationtemplates/${id}`, "get", null, {
|
|
114
|
-
responseFormat: opts.responseFormat,
|
|
115
|
-
verbosity: opts.verbosity,
|
|
116
|
-
});
|
|
117
|
-
handleResponseFormatOptions(opts, res);
|
|
118
|
-
spinner.success({ text: `Notification template ${id} loaded` });
|
|
119
|
-
spinner.stop();
|
|
120
|
-
}
|
|
121
|
-
catch (e) {
|
|
122
|
-
spinner.error({ text: e.message || "Failed to get notification template" });
|
|
123
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
// ── REPORT TEMPLATES ───────────────────────────────────
|
|
127
|
-
const report = tmpl
|
|
128
|
-
.command("report")
|
|
129
|
-
.description("Manage report templates");
|
|
130
|
-
// ay templates report list
|
|
131
|
-
report
|
|
132
|
-
.command("list")
|
|
133
|
-
.alias("ls")
|
|
134
|
-
.description("List report templates")
|
|
135
|
-
.option("-l, --limit <number>", "Limit results", parseInt, 50)
|
|
136
|
-
.action(async (options) => {
|
|
137
|
-
var _a, _b, _c;
|
|
138
|
-
try {
|
|
139
|
-
const opts = { ...program.opts(), ...options };
|
|
140
|
-
spinner.start({ text: "Fetching report templates...", color: "magenta" });
|
|
141
|
-
const res = await apiCallHandler("reporting", "reporttemplates", "get", null, {
|
|
142
|
-
limit: opts.limit,
|
|
143
|
-
responseFormat: opts.responseFormat,
|
|
144
|
-
verbosity: opts.verbosity,
|
|
145
|
-
});
|
|
146
|
-
handleResponseFormatOptions(opts, res);
|
|
147
|
-
const total = (_c = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.totalEntries) !== null && _c !== void 0 ? _c : 0;
|
|
148
|
-
spinner.success({ text: `Found ${total} report templates` });
|
|
149
|
-
spinner.stop();
|
|
150
|
-
if (opts.save)
|
|
151
|
-
await saveFile("report-templates", opts, res);
|
|
152
|
-
}
|
|
153
|
-
catch (e) {
|
|
154
|
-
spinner.error({ text: e.message || "Failed to list report templates" });
|
|
155
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
// ── STORE TEMPLATES ────────────────────────────────────
|
|
159
|
-
const store = tmpl
|
|
160
|
-
.command("store")
|
|
161
|
-
.description("Browse template store / marketplace");
|
|
162
|
-
// ay templates store list
|
|
163
|
-
store
|
|
164
|
-
.command("list")
|
|
165
|
-
.alias("ls")
|
|
166
|
-
.description("List available store templates")
|
|
167
|
-
.option("--category <category>", "Filter by category")
|
|
168
|
-
.option("--search <query>", "Search templates")
|
|
169
|
-
.option("-l, --limit <number>", "Limit results", parseInt, 50)
|
|
170
|
-
.option("-p, --page <number>", "Page number", parseInt, 1)
|
|
171
|
-
.action(async (options) => {
|
|
172
|
-
var _a, _b, _c;
|
|
173
|
-
try {
|
|
174
|
-
const opts = { ...program.opts(), ...options };
|
|
175
|
-
spinner.start({ text: "Fetching store templates...", color: "magenta" });
|
|
176
|
-
const params = {
|
|
177
|
-
page: opts.page,
|
|
178
|
-
limit: opts.limit,
|
|
179
|
-
responseFormat: opts.responseFormat,
|
|
180
|
-
verbosity: opts.verbosity,
|
|
181
|
-
};
|
|
182
|
-
if (opts.category)
|
|
183
|
-
params.category = opts.category;
|
|
184
|
-
if (opts.search)
|
|
185
|
-
params.q = opts.search;
|
|
186
|
-
const res = await apiCallHandler("config", "templategroups", "get", null, params);
|
|
187
|
-
handleResponseFormatOptions(opts, res);
|
|
188
|
-
const total = (_c = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.totalEntries) !== null && _c !== void 0 ? _c : 0;
|
|
189
|
-
spinner.success({ text: `Found ${total} store templates` });
|
|
190
|
-
spinner.stop();
|
|
191
|
-
if (opts.save)
|
|
192
|
-
await saveFile("store-templates", opts, res);
|
|
193
|
-
}
|
|
194
|
-
catch (e) {
|
|
195
|
-
spinner.error({ text: e.message || "Failed to list store templates" });
|
|
196
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
// ay templates store get <id>
|
|
200
|
-
store
|
|
201
|
-
.command("get <id>")
|
|
202
|
-
.description("Get store template details")
|
|
203
|
-
.action(async (id, options) => {
|
|
204
|
-
try {
|
|
205
|
-
const opts = { ...program.opts(), ...options };
|
|
206
|
-
spinner.start({ text: `Fetching store template ${id}...`, color: "magenta" });
|
|
207
|
-
const res = await apiCallHandler("config", `templategroups/${id}`, "get", null, {
|
|
208
|
-
responseFormat: opts.responseFormat,
|
|
209
|
-
verbosity: opts.verbosity,
|
|
210
|
-
});
|
|
211
|
-
handleResponseFormatOptions(opts, res);
|
|
212
|
-
spinner.success({ text: `Store template ${id} loaded` });
|
|
213
|
-
spinner.stop();
|
|
214
|
-
}
|
|
215
|
-
catch (e) {
|
|
216
|
-
spinner.error({ text: e.message || "Failed to get store template" });
|
|
217
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
// ay templates store install <id>
|
|
221
|
-
store
|
|
222
|
-
.command("install <id>")
|
|
223
|
-
.description("Install a template from the store")
|
|
224
|
-
.action(async (id, options) => {
|
|
225
|
-
try {
|
|
226
|
-
const opts = { ...program.opts(), ...options };
|
|
227
|
-
spinner.start({ text: `Installing template ${id}...`, color: "magenta" });
|
|
228
|
-
const res = await apiCallHandler("config", `templategroups/${id}/install`, "post", null, { responseFormat: opts.responseFormat });
|
|
229
|
-
handleResponseFormatOptions(opts, res);
|
|
230
|
-
spinner.success({ text: `Template ${id} installed` });
|
|
231
|
-
spinner.stop();
|
|
232
|
-
}
|
|
233
|
-
catch (e) {
|
|
234
|
-
spinner.error({ text: e.message || "Failed to install template" });
|
|
235
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { Argument } from "commander";
|
|
2
|
-
import { getModuleFromCollection } from "../models/getModuleFromCollection.js";
|
|
3
|
-
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
4
|
-
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
5
|
-
import { saveFile } from "../helpers/saveFile.js";
|
|
6
|
-
import { localStorage } from "../helpers/localStorage.js";
|
|
7
|
-
import { spinner } from "../../index.js";
|
|
8
|
-
import { EXIT_GENERAL_ERROR, EXIT_MISUSE } from "../exitCodes.js";
|
|
9
|
-
export function createUpdateCommand(program) {
|
|
10
|
-
program
|
|
11
|
-
.command("update")
|
|
12
|
-
.alias("u")
|
|
13
|
-
.description("Update an entry non-interactively (for scripts and AI agents)")
|
|
14
|
-
.addHelpText("after", `
|
|
15
|
-
Unlike 'edit' (which opens an interactive editor), 'update' accepts changes
|
|
16
|
-
as JSON via --body, --body-file, or --body-stdin. Perfect for automation.
|
|
17
|
-
|
|
18
|
-
Examples:
|
|
19
|
-
ay update contacts 64a1b2c3 --body '{"firstName":"Jane"}'
|
|
20
|
-
ay update products 64a1b2c3 --body-file changes.json
|
|
21
|
-
echo '{"status":"active"}' | ay update contacts 64a1b2c3 --body-stdin
|
|
22
|
-
ay u tasks 64a1b2c3 --body '{"done":true}' --force`)
|
|
23
|
-
.addArgument(new Argument("[collection]", "The collection to use").default(localStorage.getItem("lastCollection"), `The last used collection (${localStorage.getItem("lastCollection")})`))
|
|
24
|
-
.addArgument(new Argument("[id]", "The ID of the entry to update").default(localStorage.getItem("lastId"), `The last used id (${localStorage.getItem("lastId")})`))
|
|
25
|
-
.option("--body <json>", "Update data as JSON string")
|
|
26
|
-
.option("--body-file <path>", "Read update data from JSON file")
|
|
27
|
-
.option("--body-stdin", "Read update data from stdin")
|
|
28
|
-
.option("--merge", "Merge with existing entry (GET + merge + PUT)", false)
|
|
29
|
-
.action(async (collection, id, options) => {
|
|
30
|
-
try {
|
|
31
|
-
if (!collection) {
|
|
32
|
-
spinner.error({ text: "Missing required argument: collection" });
|
|
33
|
-
process.exit(EXIT_MISUSE);
|
|
34
|
-
}
|
|
35
|
-
if (!id) {
|
|
36
|
-
spinner.error({ text: "Missing required argument: id" });
|
|
37
|
-
process.exit(EXIT_MISUSE);
|
|
38
|
-
}
|
|
39
|
-
const opts = { ...program.opts(), ...options };
|
|
40
|
-
const module = getModuleFromCollection(collection);
|
|
41
|
-
// Parse body from various sources
|
|
42
|
-
let body = null;
|
|
43
|
-
if (opts.body) {
|
|
44
|
-
try {
|
|
45
|
-
body = JSON.parse(opts.body);
|
|
46
|
-
}
|
|
47
|
-
catch (_a) {
|
|
48
|
-
spinner.error({ text: "Invalid JSON in --body" });
|
|
49
|
-
process.exit(EXIT_MISUSE);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (opts.bodyFile) {
|
|
53
|
-
const fs = await import("fs");
|
|
54
|
-
const content = fs.readFileSync(opts.bodyFile, "utf-8");
|
|
55
|
-
try {
|
|
56
|
-
body = JSON.parse(content);
|
|
57
|
-
}
|
|
58
|
-
catch (_b) {
|
|
59
|
-
spinner.error({ text: `Invalid JSON in file: ${opts.bodyFile}` });
|
|
60
|
-
process.exit(EXIT_MISUSE);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (opts.bodyStdin && !process.stdin.isTTY) {
|
|
64
|
-
const chunks = [];
|
|
65
|
-
for await (const chunk of process.stdin) {
|
|
66
|
-
chunks.push(chunk);
|
|
67
|
-
}
|
|
68
|
-
const stdinContent = Buffer.concat(chunks).toString("utf-8").trim();
|
|
69
|
-
if (stdinContent) {
|
|
70
|
-
try {
|
|
71
|
-
body = JSON.parse(stdinContent);
|
|
72
|
-
}
|
|
73
|
-
catch (_c) {
|
|
74
|
-
spinner.error({ text: "Invalid JSON from stdin" });
|
|
75
|
-
process.exit(EXIT_MISUSE);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (!body) {
|
|
80
|
-
spinner.error({ text: "No update data provided. Use --body, --body-file, or --body-stdin." });
|
|
81
|
-
process.exit(EXIT_MISUSE);
|
|
82
|
-
}
|
|
83
|
-
// Merge mode: GET existing → merge → PUT
|
|
84
|
-
if (opts.merge) {
|
|
85
|
-
spinner.start({ text: `Fetching ${id} from ${collection}...`, color: "magenta" });
|
|
86
|
-
const existing = await apiCallHandler(module.module, `${collection.toLowerCase()}/${id}`, "get", null, { responseFormat: "json" });
|
|
87
|
-
const existingData = (existing === null || existing === void 0 ? void 0 : existing.payload) || {};
|
|
88
|
-
body = { ...existingData, ...body };
|
|
89
|
-
spinner.update({ text: `Updating ${id} in ${collection} (merged)...` });
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
spinner.start({ text: `Updating ${id} in ${collection}...`, color: "magenta" });
|
|
93
|
-
}
|
|
94
|
-
// Ensure _id is set
|
|
95
|
-
body._id = id;
|
|
96
|
-
const res = await apiCallHandler(module.module, collection.toLowerCase(), "put", body, {
|
|
97
|
-
responseFormat: opts.responseFormat,
|
|
98
|
-
verbosity: opts.verbosity,
|
|
99
|
-
hideMeta: opts.hideMeta,
|
|
100
|
-
});
|
|
101
|
-
handleResponseFormatOptions(opts, res);
|
|
102
|
-
spinner.success({ text: `Updated entry ${id} in ${collection}` });
|
|
103
|
-
spinner.stop();
|
|
104
|
-
localStorage.setItem("lastModule", module.module);
|
|
105
|
-
localStorage.setItem("lastCollection", collection);
|
|
106
|
-
localStorage.setItem("lastId", id);
|
|
107
|
-
if (opts.save)
|
|
108
|
-
await saveFile("update", opts, res);
|
|
109
|
-
}
|
|
110
|
-
catch (e) {
|
|
111
|
-
spinner.error({ text: e.message || "An unexpected error occurred" });
|
|
112
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
}
|
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
import chalk from "chalk";
|
|
2
|
-
import { apiCallHandler } from "../api/apiCallHandler.js";
|
|
3
|
-
import { handleResponseFormatOptions } from "../helpers/handleResponseFormatOptions.js";
|
|
4
|
-
import { saveFile } from "../helpers/saveFile.js";
|
|
5
|
-
import { spinner } from "../../index.js";
|
|
6
|
-
import { EXIT_GENERAL_ERROR, EXIT_MISUSE } from "../exitCodes.js";
|
|
7
|
-
export function createUsersCommand(program) {
|
|
8
|
-
const users = program
|
|
9
|
-
.command("users")
|
|
10
|
-
.description("Manage users, teams, and roles");
|
|
11
|
-
// ── USERS ──────────────────────────────────────────────
|
|
12
|
-
// ay users list
|
|
13
|
-
users
|
|
14
|
-
.command("list")
|
|
15
|
-
.alias("ls")
|
|
16
|
-
.description("List users")
|
|
17
|
-
.option("--search <query>", "Search by name or email")
|
|
18
|
-
.option("--role <roleId>", "Filter by role ID")
|
|
19
|
-
.option("--active", "Show only active users")
|
|
20
|
-
.option("-l, --limit <number>", "Limit results", parseInt, 50)
|
|
21
|
-
.option("-p, --page <number>", "Page number", parseInt, 1)
|
|
22
|
-
.action(async (options) => {
|
|
23
|
-
var _a, _b, _c;
|
|
24
|
-
try {
|
|
25
|
-
const opts = { ...program.opts(), ...options };
|
|
26
|
-
spinner.start({ text: "Fetching users...", color: "magenta" });
|
|
27
|
-
const params = {
|
|
28
|
-
page: opts.page,
|
|
29
|
-
limit: opts.limit,
|
|
30
|
-
responseFormat: opts.responseFormat,
|
|
31
|
-
verbosity: opts.verbosity,
|
|
32
|
-
};
|
|
33
|
-
if (opts.search)
|
|
34
|
-
params.q = opts.search;
|
|
35
|
-
if (opts.role)
|
|
36
|
-
params.role = opts.role;
|
|
37
|
-
if (opts.active)
|
|
38
|
-
params.active = "true";
|
|
39
|
-
const res = await apiCallHandler("config", "users", "get", null, params);
|
|
40
|
-
handleResponseFormatOptions(opts, res);
|
|
41
|
-
const total = (_c = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.totalEntries) !== null && _c !== void 0 ? _c : 0;
|
|
42
|
-
spinner.success({ text: `Found ${total} users` });
|
|
43
|
-
spinner.stop();
|
|
44
|
-
if (opts.save)
|
|
45
|
-
await saveFile("users-list", opts, res);
|
|
46
|
-
}
|
|
47
|
-
catch (e) {
|
|
48
|
-
spinner.error({ text: e.message || "Failed to list users" });
|
|
49
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
// ay users get <id>
|
|
53
|
-
users
|
|
54
|
-
.command("get <id>")
|
|
55
|
-
.description("Get user details")
|
|
56
|
-
.action(async (id, options) => {
|
|
57
|
-
try {
|
|
58
|
-
const opts = { ...program.opts(), ...options };
|
|
59
|
-
spinner.start({ text: `Fetching user ${id}...`, color: "magenta" });
|
|
60
|
-
const res = await apiCallHandler("config", `users/${id}`, "get", null, {
|
|
61
|
-
responseFormat: opts.responseFormat,
|
|
62
|
-
verbosity: opts.verbosity,
|
|
63
|
-
});
|
|
64
|
-
handleResponseFormatOptions(opts, res);
|
|
65
|
-
spinner.success({ text: `User ${id} loaded` });
|
|
66
|
-
spinner.stop();
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
spinner.error({ text: e.message || "Failed to get user" });
|
|
70
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
// ay users invite --email <email> --role <roleId>
|
|
74
|
-
users
|
|
75
|
-
.command("invite")
|
|
76
|
-
.description("Invite a new user")
|
|
77
|
-
.requiredOption("--email <email>", "Email address of the user to invite")
|
|
78
|
-
.option("--role <roleId>", "Role ID to assign")
|
|
79
|
-
.option("--firstName <name>", "First name")
|
|
80
|
-
.option("--lastName <name>", "Last name")
|
|
81
|
-
.action(async (options) => {
|
|
82
|
-
try {
|
|
83
|
-
const opts = { ...program.opts(), ...options };
|
|
84
|
-
spinner.start({ text: `Inviting ${opts.email}...`, color: "magenta" });
|
|
85
|
-
const body = { email: opts.email };
|
|
86
|
-
if (opts.role)
|
|
87
|
-
body.role = opts.role;
|
|
88
|
-
if (opts.firstName)
|
|
89
|
-
body.firstName = opts.firstName;
|
|
90
|
-
if (opts.lastName)
|
|
91
|
-
body.lastName = opts.lastName;
|
|
92
|
-
const res = await apiCallHandler("config", "users", "post", body, {
|
|
93
|
-
responseFormat: opts.responseFormat,
|
|
94
|
-
});
|
|
95
|
-
handleResponseFormatOptions(opts, res);
|
|
96
|
-
spinner.success({ text: `Invitation sent to ${opts.email}` });
|
|
97
|
-
spinner.stop();
|
|
98
|
-
}
|
|
99
|
-
catch (e) {
|
|
100
|
-
spinner.error({ text: e.message || "Failed to invite user" });
|
|
101
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
// ay users deactivate <id>
|
|
105
|
-
users
|
|
106
|
-
.command("deactivate <id>")
|
|
107
|
-
.description("Deactivate a user account")
|
|
108
|
-
.action(async (id, options) => {
|
|
109
|
-
try {
|
|
110
|
-
const opts = { ...program.opts(), ...options };
|
|
111
|
-
if (!opts.force && process.stdin.isTTY) {
|
|
112
|
-
const inquirer = (await import("inquirer")).default;
|
|
113
|
-
const { confirmed } = await inquirer.prompt([
|
|
114
|
-
{ type: "confirm", name: "confirmed", message: `Deactivate user ${id}?`, default: false },
|
|
115
|
-
]);
|
|
116
|
-
if (!confirmed) {
|
|
117
|
-
console.error(chalk.yellow(" Aborted."));
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
spinner.start({ text: `Deactivating user ${id}...`, color: "magenta" });
|
|
122
|
-
const res = await apiCallHandler("config", "users", "put", { _id: id, active: false }, {
|
|
123
|
-
responseFormat: opts.responseFormat,
|
|
124
|
-
});
|
|
125
|
-
handleResponseFormatOptions(opts, res);
|
|
126
|
-
spinner.success({ text: `User ${id} deactivated` });
|
|
127
|
-
spinner.stop();
|
|
128
|
-
}
|
|
129
|
-
catch (e) {
|
|
130
|
-
spinner.error({ text: e.message || "Failed to deactivate user" });
|
|
131
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
// ── TEAMS ──────────────────────────────────────────────
|
|
135
|
-
const teams = users
|
|
136
|
-
.command("teams")
|
|
137
|
-
.description("Manage teams");
|
|
138
|
-
// ay users teams list
|
|
139
|
-
teams
|
|
140
|
-
.command("list")
|
|
141
|
-
.alias("ls")
|
|
142
|
-
.description("List teams")
|
|
143
|
-
.option("--search <query>", "Search teams by name")
|
|
144
|
-
.option("-l, --limit <number>", "Limit results", parseInt, 50)
|
|
145
|
-
.option("-p, --page <number>", "Page number", parseInt, 1)
|
|
146
|
-
.action(async (options) => {
|
|
147
|
-
var _a, _b, _c;
|
|
148
|
-
try {
|
|
149
|
-
const opts = { ...program.opts(), ...options };
|
|
150
|
-
spinner.start({ text: "Fetching teams...", color: "magenta" });
|
|
151
|
-
const params = {
|
|
152
|
-
page: opts.page,
|
|
153
|
-
limit: opts.limit,
|
|
154
|
-
responseFormat: opts.responseFormat,
|
|
155
|
-
verbosity: opts.verbosity,
|
|
156
|
-
};
|
|
157
|
-
if (opts.search)
|
|
158
|
-
params.q = opts.search;
|
|
159
|
-
const res = await apiCallHandler("config", "teams", "get", null, params);
|
|
160
|
-
handleResponseFormatOptions(opts, res);
|
|
161
|
-
const total = (_c = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.totalEntries) !== null && _c !== void 0 ? _c : 0;
|
|
162
|
-
spinner.success({ text: `Found ${total} teams` });
|
|
163
|
-
spinner.stop();
|
|
164
|
-
if (opts.save)
|
|
165
|
-
await saveFile("teams-list", opts, res);
|
|
166
|
-
}
|
|
167
|
-
catch (e) {
|
|
168
|
-
spinner.error({ text: e.message || "Failed to list teams" });
|
|
169
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
// ay users teams get <id>
|
|
173
|
-
teams
|
|
174
|
-
.command("get <id>")
|
|
175
|
-
.description("Get team details with members")
|
|
176
|
-
.action(async (id, options) => {
|
|
177
|
-
try {
|
|
178
|
-
const opts = { ...program.opts(), ...options };
|
|
179
|
-
spinner.start({ text: `Fetching team ${id}...`, color: "magenta" });
|
|
180
|
-
const res = await apiCallHandler("config", `teams/${id}`, "get", null, {
|
|
181
|
-
responseFormat: opts.responseFormat,
|
|
182
|
-
verbosity: opts.verbosity,
|
|
183
|
-
});
|
|
184
|
-
handleResponseFormatOptions(opts, res);
|
|
185
|
-
spinner.success({ text: `Team ${id} loaded` });
|
|
186
|
-
spinner.stop();
|
|
187
|
-
}
|
|
188
|
-
catch (e) {
|
|
189
|
-
spinner.error({ text: e.message || "Failed to get team" });
|
|
190
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
// ay users teams create --body '{...}'
|
|
194
|
-
teams
|
|
195
|
-
.command("create")
|
|
196
|
-
.description("Create a new team")
|
|
197
|
-
.option("--name <name>", "Team name")
|
|
198
|
-
.option("--body <json>", "Full team definition as JSON")
|
|
199
|
-
.action(async (options) => {
|
|
200
|
-
try {
|
|
201
|
-
const opts = { ...program.opts(), ...options };
|
|
202
|
-
let body = null;
|
|
203
|
-
if (opts.body) {
|
|
204
|
-
try {
|
|
205
|
-
body = JSON.parse(opts.body);
|
|
206
|
-
}
|
|
207
|
-
catch (_a) {
|
|
208
|
-
spinner.error({ text: "Invalid JSON in --body" });
|
|
209
|
-
process.exit(EXIT_MISUSE);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
else if (opts.name) {
|
|
213
|
-
body = { name: opts.name };
|
|
214
|
-
}
|
|
215
|
-
if (!body) {
|
|
216
|
-
spinner.error({ text: "Provide team definition via --name or --body" });
|
|
217
|
-
process.exit(EXIT_MISUSE);
|
|
218
|
-
}
|
|
219
|
-
spinner.start({ text: "Creating team...", color: "magenta" });
|
|
220
|
-
const res = await apiCallHandler("config", "teams", "post", body, {
|
|
221
|
-
responseFormat: opts.responseFormat,
|
|
222
|
-
});
|
|
223
|
-
handleResponseFormatOptions(opts, res);
|
|
224
|
-
spinner.success({ text: "Team created" });
|
|
225
|
-
spinner.stop();
|
|
226
|
-
}
|
|
227
|
-
catch (e) {
|
|
228
|
-
spinner.error({ text: e.message || "Failed to create team" });
|
|
229
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
// ── ROLES ──────────────────────────────────────────────
|
|
233
|
-
const roles = users
|
|
234
|
-
.command("roles")
|
|
235
|
-
.description("Manage roles");
|
|
236
|
-
// ay users roles list
|
|
237
|
-
roles
|
|
238
|
-
.command("list")
|
|
239
|
-
.alias("ls")
|
|
240
|
-
.description("List available roles")
|
|
241
|
-
.option("-l, --limit <number>", "Limit results", parseInt, 50)
|
|
242
|
-
.action(async (options) => {
|
|
243
|
-
var _a, _b, _c;
|
|
244
|
-
try {
|
|
245
|
-
const opts = { ...program.opts(), ...options };
|
|
246
|
-
spinner.start({ text: "Fetching roles...", color: "magenta" });
|
|
247
|
-
const res = await apiCallHandler("config", "roles", "get", null, {
|
|
248
|
-
limit: opts.limit,
|
|
249
|
-
responseFormat: opts.responseFormat,
|
|
250
|
-
verbosity: opts.verbosity,
|
|
251
|
-
});
|
|
252
|
-
handleResponseFormatOptions(opts, res);
|
|
253
|
-
const total = (_c = (_b = (_a = res.meta) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.totalEntries) !== null && _c !== void 0 ? _c : 0;
|
|
254
|
-
spinner.success({ text: `Found ${total} roles` });
|
|
255
|
-
spinner.stop();
|
|
256
|
-
if (opts.save)
|
|
257
|
-
await saveFile("roles-list", opts, res);
|
|
258
|
-
}
|
|
259
|
-
catch (e) {
|
|
260
|
-
spinner.error({ text: e.message || "Failed to list roles" });
|
|
261
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
// ay users roles get <id>
|
|
265
|
-
roles
|
|
266
|
-
.command("get <id>")
|
|
267
|
-
.description("Get role details with permissions")
|
|
268
|
-
.action(async (id, options) => {
|
|
269
|
-
try {
|
|
270
|
-
const opts = { ...program.opts(), ...options };
|
|
271
|
-
spinner.start({ text: `Fetching role ${id}...`, color: "magenta" });
|
|
272
|
-
const res = await apiCallHandler("config", `roles/${id}`, "get", null, {
|
|
273
|
-
responseFormat: opts.responseFormat,
|
|
274
|
-
verbosity: opts.verbosity,
|
|
275
|
-
});
|
|
276
|
-
handleResponseFormatOptions(opts, res);
|
|
277
|
-
spinner.success({ text: `Role ${id} loaded` });
|
|
278
|
-
spinner.stop();
|
|
279
|
-
}
|
|
280
|
-
catch (e) {
|
|
281
|
-
spinner.error({ text: e.message || "Failed to get role" });
|
|
282
|
-
process.exit(EXIT_GENERAL_ERROR);
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
}
|