appwrite-cli 17.0.0 → 17.2.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/.github/workflows/ci.yml +1 -1
- package/.github/workflows/publish.yml +1 -1
- package/CHANGELOG.md +20 -0
- package/README.md +2 -2
- package/bun.lock +783 -0
- package/cli.ts +19 -1
- package/dist/bundle-win-arm64.mjs +1515 -744
- package/dist/cli.cjs +1515 -744
- package/dist/index.cjs +322 -118
- package/dist/index.js +322 -118
- package/dist/lib/client.d.ts +9 -0
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/commands/init.d.ts.map +1 -1
- package/dist/lib/commands/services/organizations.d.ts +3 -0
- package/dist/lib/commands/services/organizations.d.ts.map +1 -0
- package/dist/lib/commands/services/teams.d.ts.map +1 -1
- package/dist/lib/constants.d.ts +1 -1
- package/dist/lib/emulation/docker.d.ts.map +1 -1
- package/dist/lib/emulation/utils.d.ts.map +1 -1
- package/dist/lib/parser.d.ts.map +1 -1
- package/dist/lib/questions.d.ts.map +1 -1
- package/dist/lib/types.d.ts +3 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/utils.d.ts +12 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/docs/examples/organizations/add-credit.md +5 -0
- package/docs/examples/organizations/cancel-downgrade.md +4 -0
- package/docs/examples/organizations/create-downgrade-feedback.md +8 -0
- package/docs/examples/organizations/create-invoice-payment.md +6 -0
- package/docs/examples/organizations/create-key.md +6 -0
- package/docs/examples/organizations/create.md +6 -0
- package/docs/examples/organizations/delete-backup-payment-method.md +4 -0
- package/docs/examples/organizations/delete-default-payment-method.md +4 -0
- package/docs/examples/organizations/delete-key.md +5 -0
- package/docs/examples/organizations/delete.md +4 -0
- package/docs/examples/organizations/estimation-create-organization.md +4 -0
- package/docs/examples/organizations/estimation-delete-organization.md +4 -0
- package/docs/examples/organizations/estimation-update-plan.md +5 -0
- package/docs/examples/organizations/get-aggregation.md +5 -0
- package/docs/examples/organizations/get-available-credits.md +4 -0
- package/docs/examples/organizations/get-credit.md +5 -0
- package/docs/examples/organizations/get-invoice-download.md +5 -0
- package/docs/examples/organizations/get-invoice-view.md +5 -0
- package/docs/examples/organizations/get-invoice.md +5 -0
- package/docs/examples/organizations/get-key.md +5 -0
- package/docs/examples/organizations/get-plan.md +4 -0
- package/docs/examples/organizations/get-scopes.md +4 -0
- package/docs/examples/organizations/get-usage.md +4 -0
- package/docs/examples/organizations/list-aggregations.md +4 -0
- package/docs/examples/organizations/list-credits.md +4 -0
- package/docs/examples/organizations/list-keys.md +4 -0
- package/docs/examples/organizations/list-regions.md +4 -0
- package/docs/examples/organizations/list.md +3 -0
- package/docs/examples/organizations/set-backup-payment-method.md +5 -0
- package/docs/examples/organizations/set-billing-address.md +5 -0
- package/docs/examples/organizations/set-billing-email.md +5 -0
- package/docs/examples/organizations/set-billing-tax-id.md +5 -0
- package/docs/examples/organizations/set-default-payment-method.md +5 -0
- package/docs/examples/organizations/update-budget.md +5 -0
- package/docs/examples/organizations/update-key.md +7 -0
- package/docs/examples/organizations/update-plan.md +5 -0
- package/docs/examples/organizations/validate-invoice.md +5 -0
- package/docs/examples/organizations/validate-payment.md +4 -0
- package/install.ps1 +2 -2
- package/install.sh +1 -1
- package/lib/client.ts +12 -0
- package/lib/commands/init.ts +109 -2
- package/lib/commands/services/account.ts +110 -55
- package/lib/commands/services/activities.ts +4 -2
- package/lib/commands/services/backups.ts +24 -12
- package/lib/commands/services/databases.ts +150 -75
- package/lib/commands/services/functions.ts +60 -30
- package/lib/commands/services/graphql.ts +4 -2
- package/lib/commands/services/health.ts +46 -23
- package/lib/commands/services/locale.ts +16 -8
- package/lib/commands/services/messaging.ts +96 -48
- package/lib/commands/services/migrations.ts +30 -16
- package/lib/commands/services/organizations.ts +555 -0
- package/lib/commands/services/project.ts +12 -6
- package/lib/commands/services/projects.ts +105 -53
- package/lib/commands/services/proxy.ts +18 -10
- package/lib/commands/services/sites.ts +58 -29
- package/lib/commands/services/storage.ts +30 -15
- package/lib/commands/services/tables-db.ts +148 -74
- package/lib/commands/services/teams.ts +38 -15
- package/lib/commands/services/tokens.ts +10 -5
- package/lib/commands/services/users.ts +88 -44
- package/lib/commands/services/vcs.ts +22 -12
- package/lib/commands/services/webhooks.ts +12 -6
- package/lib/constants.ts +1 -1
- package/lib/emulation/docker.ts +1 -0
- package/lib/emulation/utils.ts +3 -2
- package/lib/parser.ts +356 -77
- package/lib/questions.ts +8 -3
- package/lib/types.ts +3 -0
- package/lib/utils.ts +234 -0
- package/package.json +1 -1
- package/scoop/appwrite.config.json +3 -3
package/lib/parser.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
// @ts-expect-error BigInt toJSON polyfill for JSON.stringify support
|
|
2
|
+
BigInt.prototype.toJSON = function () {
|
|
3
|
+
return this.toString();
|
|
4
|
+
};
|
|
5
|
+
|
|
1
6
|
import chalk from "chalk";
|
|
2
7
|
import { InvalidArgumentError } from "commander";
|
|
3
8
|
import Table from "cli-table3";
|
|
@@ -18,15 +23,33 @@ import {
|
|
|
18
23
|
const cliConfig: CliConfig = {
|
|
19
24
|
verbose: false,
|
|
20
25
|
json: false,
|
|
26
|
+
raw: false,
|
|
27
|
+
showSecrets: false,
|
|
21
28
|
force: false,
|
|
22
29
|
all: false,
|
|
23
30
|
ids: [],
|
|
24
31
|
report: false,
|
|
25
32
|
reportData: {},
|
|
33
|
+
displayFields: [],
|
|
26
34
|
};
|
|
27
35
|
|
|
28
36
|
type JsonObject = Record<string, unknown>;
|
|
29
37
|
|
|
38
|
+
const HIDDEN_VALUE = "[hidden]";
|
|
39
|
+
const SENSITIVE_KEYS = new Set([
|
|
40
|
+
"secret",
|
|
41
|
+
"apikey",
|
|
42
|
+
"accesstoken",
|
|
43
|
+
"refreshtoken",
|
|
44
|
+
"password",
|
|
45
|
+
"jwt",
|
|
46
|
+
"clientsecret",
|
|
47
|
+
"secretkey",
|
|
48
|
+
"sessionsecret",
|
|
49
|
+
]);
|
|
50
|
+
let renderDepth = 0;
|
|
51
|
+
let redactionApplied = false;
|
|
52
|
+
|
|
30
53
|
interface ReportDataPayload {
|
|
31
54
|
data?: {
|
|
32
55
|
args?: string[];
|
|
@@ -54,99 +77,355 @@ const extractReportCommandArgs = (value: unknown): string[] => {
|
|
|
54
77
|
return reportData.data.args;
|
|
55
78
|
};
|
|
56
79
|
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
return;
|
|
80
|
+
const beginRender = (): void => {
|
|
81
|
+
if (renderDepth === 0) {
|
|
82
|
+
redactionApplied = false;
|
|
61
83
|
}
|
|
62
84
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
console.log(`${chalk.yellow.bold(key)} : ${data[key]}`);
|
|
76
|
-
} else {
|
|
77
|
-
console.log(`${chalk.yellow.bold.underline(key)}`);
|
|
78
|
-
const tableRow = toJsonObject(data[key]) ?? {};
|
|
79
|
-
drawTable([tableRow]);
|
|
80
|
-
}
|
|
85
|
+
renderDepth++;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const endRender = (): void => {
|
|
89
|
+
renderDepth = Math.max(0, renderDepth - 1);
|
|
90
|
+
|
|
91
|
+
if (renderDepth === 0 && redactionApplied && !cliConfig.showSecrets) {
|
|
92
|
+
const message =
|
|
93
|
+
"Sensitive values were redacted. Pass --show-secrets to display them.";
|
|
94
|
+
|
|
95
|
+
if (cliConfig.json || cliConfig.raw) {
|
|
96
|
+
console.error(`${chalk.cyan.bold("♥ Hint:")} ${chalk.cyan(message)}`);
|
|
81
97
|
} else {
|
|
82
|
-
|
|
98
|
+
hint(message);
|
|
83
99
|
}
|
|
84
100
|
}
|
|
85
101
|
};
|
|
86
102
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
103
|
+
const withRender = <T>(callback: () => T): T => {
|
|
104
|
+
beginRender();
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
return callback();
|
|
108
|
+
} finally {
|
|
109
|
+
endRender();
|
|
91
110
|
}
|
|
111
|
+
};
|
|
92
112
|
|
|
93
|
-
|
|
113
|
+
const isSensitiveKey = (key: string): boolean => {
|
|
114
|
+
const normalizedKey = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
94
115
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
|
|
116
|
+
return SENSITIVE_KEYS.has(normalizedKey);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const maskSensitiveString = (value: string): string => {
|
|
120
|
+
if (value.length <= 16) {
|
|
121
|
+
return HIDDEN_VALUE;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const separatorIndex = value.indexOf("_");
|
|
125
|
+
if (separatorIndex > 0 && separatorIndex < value.length - 9) {
|
|
126
|
+
const prefix = value.slice(0, separatorIndex + 1);
|
|
127
|
+
const tail = value.slice(-4);
|
|
128
|
+
return `${prefix}${HIDDEN_VALUE}${tail}`;
|
|
102
129
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
130
|
+
|
|
131
|
+
return `${HIDDEN_VALUE}${value.slice(-4)}`;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const maskSensitiveData = (value: unknown, key?: string): unknown => {
|
|
135
|
+
if (key && isSensitiveKey(key) && !cliConfig.showSecrets) {
|
|
136
|
+
redactionApplied = true;
|
|
137
|
+
|
|
138
|
+
if (typeof value === "string") {
|
|
139
|
+
return maskSensitiveString(value);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (value == null) {
|
|
143
|
+
return value;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return HIDDEN_VALUE;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (Array.isArray(value)) {
|
|
150
|
+
return value.map((item) => maskSensitiveData(item));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (value && typeof value === "object") {
|
|
154
|
+
if (value?.constructor?.name === "BigNumber") {
|
|
155
|
+
return String(value);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const result: JsonObject = {};
|
|
159
|
+
for (const childKey of Object.keys(value as JsonObject)) {
|
|
160
|
+
const childValue = (value as JsonObject)[childKey];
|
|
161
|
+
if (typeof childValue === "function") continue;
|
|
162
|
+
result[childKey] = maskSensitiveData(childValue, childKey);
|
|
163
|
+
}
|
|
164
|
+
|
|
106
165
|
return result;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return value;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
const filterObject = (obj: JsonObject): JsonObject => {
|
|
172
|
+
const result: JsonObject = {};
|
|
173
|
+
for (const key of Object.keys(obj)) {
|
|
174
|
+
const value = obj[key];
|
|
175
|
+
if (typeof value === "function") continue;
|
|
176
|
+
if (value == null) continue;
|
|
177
|
+
if (value?.constructor?.name === "BigNumber") {
|
|
178
|
+
result[key] = String(value);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (typeof value === "object") continue;
|
|
182
|
+
if (typeof value === "string" && value.trim() === "") continue;
|
|
183
|
+
result[key] = value;
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const applyDisplayFilter = (rows: JsonObject[]): JsonObject[] => {
|
|
189
|
+
if (cliConfig.displayFields.length === 0) {
|
|
190
|
+
return rows;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return rows.map((row) => {
|
|
194
|
+
const filtered: JsonObject = {};
|
|
195
|
+
|
|
196
|
+
for (const key of cliConfig.displayFields) {
|
|
197
|
+
if (Object.prototype.hasOwnProperty.call(row, key)) {
|
|
198
|
+
filtered[key] = row[key];
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return Object.keys(filtered).length > 0 ? filtered : row;
|
|
132
203
|
});
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const filterData = (data: JsonObject): JsonObject => {
|
|
207
|
+
const result: JsonObject = {};
|
|
208
|
+
for (const key of Object.keys(data)) {
|
|
209
|
+
const value = data[key];
|
|
210
|
+
if (typeof value === "function") continue;
|
|
211
|
+
if (value == null) continue;
|
|
212
|
+
if (value?.constructor?.name === "BigNumber") {
|
|
213
|
+
result[key] = String(value);
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (Array.isArray(value)) {
|
|
217
|
+
result[key] = value.map((item) => {
|
|
218
|
+
if (item?.constructor?.name === "BigNumber") return String(item);
|
|
219
|
+
return item && typeof item === "object" && !Array.isArray(item)
|
|
220
|
+
? filterObject(item as JsonObject)
|
|
221
|
+
: item;
|
|
222
|
+
});
|
|
223
|
+
} else if (typeof value === "object") {
|
|
224
|
+
continue;
|
|
225
|
+
} else if (typeof value === "string" && value.trim() === "") {
|
|
226
|
+
continue;
|
|
227
|
+
} else {
|
|
228
|
+
result[key] = value;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return result;
|
|
232
|
+
};
|
|
133
233
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
234
|
+
export const parse = (data: JsonObject): void => {
|
|
235
|
+
withRender(() => {
|
|
236
|
+
const sanitizedData = maskSensitiveData(data) as JsonObject;
|
|
237
|
+
|
|
238
|
+
if (cliConfig.raw) {
|
|
239
|
+
drawJSON(sanitizedData);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (cliConfig.json) {
|
|
244
|
+
drawJSON(filterData(sanitizedData));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const keys = Object.keys(sanitizedData).filter(
|
|
249
|
+
(k) => typeof sanitizedData[k] !== "function",
|
|
250
|
+
);
|
|
251
|
+
let printedScalar = false;
|
|
252
|
+
|
|
253
|
+
for (const key of keys) {
|
|
254
|
+
const value = sanitizedData[key];
|
|
255
|
+
if (value == null) continue;
|
|
256
|
+
if (typeof value === "string" && value.trim() === "") continue;
|
|
257
|
+
if (Array.isArray(value)) {
|
|
258
|
+
if (value.length === 0) continue;
|
|
259
|
+
if (
|
|
260
|
+
value.every(
|
|
261
|
+
(item) =>
|
|
262
|
+
item &&
|
|
263
|
+
typeof item === "object" &&
|
|
264
|
+
!Array.isArray(item) &&
|
|
265
|
+
Object.keys(item).length === 0,
|
|
266
|
+
)
|
|
267
|
+
)
|
|
268
|
+
continue;
|
|
269
|
+
console.log();
|
|
270
|
+
console.log(`${chalk.yellow.bold.underline(key)}`);
|
|
271
|
+
if (typeof value[0] === "object") {
|
|
272
|
+
drawTable(value);
|
|
273
|
+
} else {
|
|
274
|
+
drawJSON(value);
|
|
275
|
+
}
|
|
276
|
+
console.log();
|
|
277
|
+
printedScalar = false;
|
|
278
|
+
} else if (typeof value === "object") {
|
|
279
|
+
if (value?.constructor?.name === "BigNumber") {
|
|
280
|
+
console.log(`${chalk.yellow.bold(key)} : ${value}`);
|
|
281
|
+
printedScalar = true;
|
|
282
|
+
} else {
|
|
283
|
+
const tableRow = toJsonObject(value) ?? {};
|
|
284
|
+
if (Object.keys(tableRow).length === 0) continue;
|
|
285
|
+
console.log();
|
|
286
|
+
console.log(`${chalk.yellow.bold.underline(key)}`);
|
|
287
|
+
drawTable([tableRow]);
|
|
288
|
+
console.log();
|
|
289
|
+
printedScalar = false;
|
|
290
|
+
}
|
|
143
291
|
} else {
|
|
144
|
-
|
|
292
|
+
console.log(`${chalk.yellow.bold(key)} : ${value}`);
|
|
293
|
+
printedScalar = true;
|
|
145
294
|
}
|
|
146
295
|
}
|
|
147
|
-
table.push(rowValues);
|
|
148
296
|
});
|
|
149
|
-
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const MAX_COL_WIDTH = 40;
|
|
300
|
+
|
|
301
|
+
const formatCellValue = (value: unknown): string => {
|
|
302
|
+
if (value == null) return "-";
|
|
303
|
+
if (Array.isArray(value)) {
|
|
304
|
+
if (value.length === 0) return "[]";
|
|
305
|
+
return `[${value.length} items]`;
|
|
306
|
+
}
|
|
307
|
+
if (typeof value === "object") {
|
|
308
|
+
if (value?.constructor?.name === "BigNumber") return String(value);
|
|
309
|
+
const keys = Object.keys(value as Record<string, unknown>);
|
|
310
|
+
if (keys.length === 0) return "{}";
|
|
311
|
+
return `{${keys.length} keys}`;
|
|
312
|
+
}
|
|
313
|
+
const str = String(value);
|
|
314
|
+
if (str.length > MAX_COL_WIDTH) {
|
|
315
|
+
return str.slice(0, MAX_COL_WIDTH - 1) + "…";
|
|
316
|
+
}
|
|
317
|
+
return str;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
export const drawTable = (data: Array<JsonObject | null | undefined>): void => {
|
|
321
|
+
withRender(() => {
|
|
322
|
+
if (data.length == 0) {
|
|
323
|
+
console.log("[]");
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const rows = applyDisplayFilter(
|
|
328
|
+
data.map((item): JsonObject => {
|
|
329
|
+
const maskedItem = maskSensitiveData(item);
|
|
330
|
+
return toJsonObject(maskedItem) ?? {};
|
|
331
|
+
}),
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
// Create an object with all the keys in it
|
|
335
|
+
const obj = rows.reduce((res, item) => ({ ...res, ...item }), {});
|
|
336
|
+
// Get those keys as an array
|
|
337
|
+
const allKeys = Object.keys(obj);
|
|
338
|
+
if (allKeys.length === 0) {
|
|
339
|
+
drawJSON(data);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// If too many columns, show condensed key-value output with only scalar, non-empty fields
|
|
344
|
+
const maxColumns = 6;
|
|
345
|
+
if (allKeys.length > maxColumns) {
|
|
346
|
+
// Collect visible entries per row to compute alignment
|
|
347
|
+
const rowEntries = rows.map((row) => {
|
|
348
|
+
const entries: Array<[string, string]> = [];
|
|
349
|
+
for (const key of Object.keys(row)) {
|
|
350
|
+
const value = row[key];
|
|
351
|
+
if (typeof value === "function") continue;
|
|
352
|
+
if (value == null) continue;
|
|
353
|
+
if (value?.constructor?.name === "BigNumber") {
|
|
354
|
+
entries.push([key, String(value)]);
|
|
355
|
+
continue;
|
|
356
|
+
}
|
|
357
|
+
if (typeof value === "object") continue;
|
|
358
|
+
if (typeof value === "string" && value.trim() === "") continue;
|
|
359
|
+
entries.push([key, String(value)]);
|
|
360
|
+
}
|
|
361
|
+
return entries;
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const flatEntries = rowEntries.flat();
|
|
365
|
+
if (flatEntries.length === 0) {
|
|
366
|
+
drawJSON(data);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const maxKeyLen = Math.max(...flatEntries.map(([key]) => key.length));
|
|
371
|
+
|
|
372
|
+
const separatorLen = Math.min(
|
|
373
|
+
maxKeyLen + 2 + MAX_COL_WIDTH,
|
|
374
|
+
process.stdout.columns || 80,
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
rowEntries.forEach((entries, idx) => {
|
|
378
|
+
if (idx > 0) console.log(chalk.cyan("─".repeat(separatorLen)));
|
|
379
|
+
for (const [key, value] of entries) {
|
|
380
|
+
const paddedKey = key.padEnd(maxKeyLen);
|
|
381
|
+
console.log(`${chalk.yellow.bold(paddedKey)} ${value}`);
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const columns = allKeys;
|
|
388
|
+
|
|
389
|
+
// Create an object with all keys set to the default value ''
|
|
390
|
+
const def = allKeys.reduce((result: Record<string, string>, key) => {
|
|
391
|
+
result[key] = "-";
|
|
392
|
+
return result;
|
|
393
|
+
}, {});
|
|
394
|
+
// Use object destructuring to replace all default values with the ones we have
|
|
395
|
+
const normalizedData = rows.map((item) => ({ ...def, ...item }));
|
|
396
|
+
|
|
397
|
+
const table = new Table({
|
|
398
|
+
head: columns.map((c) => chalk.cyan.italic.bold(c)),
|
|
399
|
+
colWidths: columns.map(() => null) as (number | null)[],
|
|
400
|
+
wordWrap: false,
|
|
401
|
+
chars: {
|
|
402
|
+
"top": " ",
|
|
403
|
+
"top-mid": " ",
|
|
404
|
+
"top-left": " ",
|
|
405
|
+
"top-right": " ",
|
|
406
|
+
"bottom": " ",
|
|
407
|
+
"bottom-mid": " ",
|
|
408
|
+
"bottom-left": " ",
|
|
409
|
+
"bottom-right": " ",
|
|
410
|
+
"left": " ",
|
|
411
|
+
"left-mid": " ",
|
|
412
|
+
"mid": chalk.cyan("─"),
|
|
413
|
+
"mid-mid": chalk.cyan("┼"),
|
|
414
|
+
"right": " ",
|
|
415
|
+
"right-mid": " ",
|
|
416
|
+
"middle": chalk.cyan("│"),
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
normalizedData.forEach((row) => {
|
|
421
|
+
const rowValues: string[] = [];
|
|
422
|
+
for (const key of columns) {
|
|
423
|
+
rowValues.push(formatCellValue(row[key]));
|
|
424
|
+
}
|
|
425
|
+
table.push(rowValues);
|
|
426
|
+
});
|
|
427
|
+
console.log(table.toString());
|
|
428
|
+
});
|
|
150
429
|
};
|
|
151
430
|
|
|
152
431
|
export const drawJSON = (data: unknown): void => {
|
|
@@ -281,7 +560,7 @@ export const commandDescriptions: Record<string, string> = {
|
|
|
281
560
|
avatars: `The avatars command aims to help you complete everyday tasks related to your app image, icons, and avatars.`,
|
|
282
561
|
databases: `(Legacy) The databases command allows you to create structured collections of documents and query and filter lists of documents.`,
|
|
283
562
|
"tables-db": `The tables-db command allows you to create structured tables of columns and query and filter lists of rows.`,
|
|
284
|
-
init: `The init command provides a convenient wrapper for creating and initializing projects, functions, collections, buckets, teams,
|
|
563
|
+
init: `The init command provides a convenient wrapper for creating and initializing projects, functions, collections, buckets, teams, messaging-topics, and agent skills in ${SDK_TITLE}.`,
|
|
285
564
|
push: `The push command provides a convenient wrapper for pushing your functions, collections, buckets, teams, and messaging-topics.`,
|
|
286
565
|
run: `The run command allows you to run the project locally to allow easy development and quick debugging.`,
|
|
287
566
|
functions: `The functions command allows you to view, create, and manage your Cloud Functions.`,
|
|
@@ -291,7 +570,7 @@ export const commandDescriptions: Record<string, string> = {
|
|
|
291
570
|
locale: `The locale command allows you to customize your app based on your users' location.`,
|
|
292
571
|
sites: `The sites command allows you to view, create and manage your Appwrite Sites.`,
|
|
293
572
|
storage: `The storage command allows you to manage your project files.`,
|
|
294
|
-
teams: `The teams command allows you to group users of your project to enable them to share read and write access to your project resources.`,
|
|
573
|
+
teams: `The teams command allows you to group users of your project to enable them to share read and write access to your project resources. Requires a linked project. To manage console-level teams, use the 'organizations' command instead.`,
|
|
295
574
|
update: `The update command allows you to update the ${SDK_TITLE} CLI to the latest version.`,
|
|
296
575
|
users: `The users command allows you to manage your project users.`,
|
|
297
576
|
projects: `The projects command allows you to manage your projects, add platforms, manage API keys, Dev Keys etc.`,
|
package/lib/questions.ts
CHANGED
|
@@ -227,14 +227,16 @@ export const questionsInitProject: Question[] = [
|
|
|
227
227
|
name: "project",
|
|
228
228
|
message: "What would you like to name your project?",
|
|
229
229
|
default: "My Awesome Project",
|
|
230
|
-
when: (answer: Answers) =>
|
|
230
|
+
when: (answer: Answers) =>
|
|
231
|
+
whenOverride(answer) && answer.start !== "existing",
|
|
231
232
|
},
|
|
232
233
|
{
|
|
233
234
|
type: "input",
|
|
234
235
|
name: "id",
|
|
235
236
|
message: "What ID would you like to have for your project?",
|
|
236
237
|
default: "unique()",
|
|
237
|
-
when: (answer: Answers) =>
|
|
238
|
+
when: (answer: Answers) =>
|
|
239
|
+
whenOverride(answer) && answer.start !== "existing",
|
|
238
240
|
},
|
|
239
241
|
{
|
|
240
242
|
type: "search-list",
|
|
@@ -251,7 +253,8 @@ export const questionsInitProject: Question[] = [
|
|
|
251
253
|
];
|
|
252
254
|
|
|
253
255
|
const { projects } = await paginate(
|
|
254
|
-
async (args) =>
|
|
256
|
+
async (args) =>
|
|
257
|
+
(await getProjectsService()).list(args.queries as string[]),
|
|
255
258
|
{ parseOutput: false },
|
|
256
259
|
100,
|
|
257
260
|
"projects",
|
|
@@ -301,6 +304,7 @@ export const questionsInitProject: Question[] = [
|
|
|
301
304
|
}));
|
|
302
305
|
},
|
|
303
306
|
when: (answer: Answers) => {
|
|
307
|
+
if (!whenOverride(answer)) return false;
|
|
304
308
|
if (answer.start === "existing") return false;
|
|
305
309
|
return isCloud();
|
|
306
310
|
},
|
|
@@ -900,6 +904,7 @@ export const questionsInitResources: Question[] = [
|
|
|
900
904
|
choices: [
|
|
901
905
|
{ name: "Function", value: "function" },
|
|
902
906
|
{ name: "Site", value: "site" },
|
|
907
|
+
{ name: "Skill", value: "skill" },
|
|
903
908
|
{ name: "Table", value: "table" },
|
|
904
909
|
{ name: "Bucket", value: "bucket" },
|
|
905
910
|
{ name: "Team", value: "team" },
|
package/lib/types.ts
CHANGED
|
@@ -52,11 +52,14 @@ export interface CommandDescription {
|
|
|
52
52
|
export interface CliConfig {
|
|
53
53
|
verbose: boolean;
|
|
54
54
|
json: boolean;
|
|
55
|
+
raw: boolean;
|
|
56
|
+
showSecrets: boolean;
|
|
55
57
|
force: boolean;
|
|
56
58
|
all: boolean;
|
|
57
59
|
ids: string[];
|
|
58
60
|
report: boolean;
|
|
59
61
|
reportData: Record<string, unknown>;
|
|
62
|
+
displayFields: string[];
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
export interface SessionData {
|