appwrite-cli 17.0.0 → 17.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +2 -2
  3. package/cli.ts +6 -0
  4. package/dist/bundle-win-arm64.mjs +489 -122
  5. package/dist/cli.cjs +489 -122
  6. package/dist/index.cjs +175 -85
  7. package/dist/index.js +175 -85
  8. package/dist/lib/commands/services/organizations.d.ts +3 -0
  9. package/dist/lib/commands/services/organizations.d.ts.map +1 -0
  10. package/dist/lib/commands/services/teams.d.ts.map +1 -1
  11. package/dist/lib/constants.d.ts +1 -1
  12. package/dist/lib/emulation/utils.d.ts.map +1 -1
  13. package/dist/lib/parser.d.ts.map +1 -1
  14. package/dist/lib/types.d.ts +1 -0
  15. package/dist/lib/types.d.ts.map +1 -1
  16. package/docs/examples/organizations/add-credit.md +5 -0
  17. package/docs/examples/organizations/cancel-downgrade.md +4 -0
  18. package/docs/examples/organizations/create-downgrade-feedback.md +8 -0
  19. package/docs/examples/organizations/create-invoice-payment.md +6 -0
  20. package/docs/examples/organizations/create-key.md +6 -0
  21. package/docs/examples/organizations/create.md +6 -0
  22. package/docs/examples/organizations/delete-backup-payment-method.md +4 -0
  23. package/docs/examples/organizations/delete-default-payment-method.md +4 -0
  24. package/docs/examples/organizations/delete-key.md +5 -0
  25. package/docs/examples/organizations/delete.md +4 -0
  26. package/docs/examples/organizations/estimation-create-organization.md +4 -0
  27. package/docs/examples/organizations/estimation-delete-organization.md +4 -0
  28. package/docs/examples/organizations/estimation-update-plan.md +5 -0
  29. package/docs/examples/organizations/get-aggregation.md +5 -0
  30. package/docs/examples/organizations/get-available-credits.md +4 -0
  31. package/docs/examples/organizations/get-credit.md +5 -0
  32. package/docs/examples/organizations/get-invoice-download.md +5 -0
  33. package/docs/examples/organizations/get-invoice-view.md +5 -0
  34. package/docs/examples/organizations/get-invoice.md +5 -0
  35. package/docs/examples/organizations/get-key.md +5 -0
  36. package/docs/examples/organizations/get-plan.md +4 -0
  37. package/docs/examples/organizations/get-scopes.md +4 -0
  38. package/docs/examples/organizations/get-usage.md +4 -0
  39. package/docs/examples/organizations/list-aggregations.md +4 -0
  40. package/docs/examples/organizations/list-credits.md +4 -0
  41. package/docs/examples/organizations/list-keys.md +4 -0
  42. package/docs/examples/organizations/list-regions.md +4 -0
  43. package/docs/examples/organizations/list.md +3 -0
  44. package/docs/examples/organizations/set-backup-payment-method.md +5 -0
  45. package/docs/examples/organizations/set-billing-address.md +5 -0
  46. package/docs/examples/organizations/set-billing-email.md +5 -0
  47. package/docs/examples/organizations/set-billing-tax-id.md +5 -0
  48. package/docs/examples/organizations/set-default-payment-method.md +5 -0
  49. package/docs/examples/organizations/update-budget.md +5 -0
  50. package/docs/examples/organizations/update-key.md +7 -0
  51. package/docs/examples/organizations/update-plan.md +5 -0
  52. package/docs/examples/organizations/validate-invoice.md +5 -0
  53. package/docs/examples/organizations/validate-payment.md +4 -0
  54. package/install.ps1 +2 -2
  55. package/install.sh +1 -1
  56. package/lib/commands/services/migrations.ts +2 -2
  57. package/lib/commands/services/organizations.ts +517 -0
  58. package/lib/commands/services/projects.ts +2 -2
  59. package/lib/commands/services/proxy.ts +2 -2
  60. package/lib/commands/services/teams.ts +10 -1
  61. package/lib/commands/services/vcs.ts +2 -2
  62. package/lib/constants.ts +1 -1
  63. package/lib/emulation/utils.ts +3 -2
  64. package/lib/parser.ts +149 -27
  65. package/lib/questions.ts +2 -2
  66. package/lib/sdks.ts +1 -0
  67. package/lib/types.ts +1 -0
  68. package/package.json +1 -1
  69. package/scoop/appwrite.config.json +3 -3
package/lib/parser.ts CHANGED
@@ -1,3 +1,6 @@
1
+ // @ts-expect-error BigInt toJSON polyfill for JSON.stringify support
2
+ BigInt.prototype.toJSON = function () { return this.toString(); };
3
+
1
4
  import chalk from "chalk";
2
5
  import { InvalidArgumentError } from "commander";
3
6
  import Table from "cli-table3";
@@ -18,6 +21,7 @@ import {
18
21
  const cliConfig: CliConfig = {
19
22
  verbose: false,
20
23
  json: false,
24
+ raw: false,
21
25
  force: false,
22
26
  all: false,
23
27
  ids: [],
@@ -54,36 +58,118 @@ const extractReportCommandArgs = (value: unknown): string[] => {
54
58
  return reportData.data.args;
55
59
  };
56
60
 
61
+ const filterObject = (obj: JsonObject): JsonObject => {
62
+ const result: JsonObject = {};
63
+ for (const key of Object.keys(obj)) {
64
+ const value = obj[key];
65
+ if (typeof value === "function") continue;
66
+ if (value == null) continue;
67
+ if (value?.constructor?.name === "BigNumber") {
68
+ result[key] = String(value);
69
+ continue;
70
+ }
71
+ if (typeof value === "object") continue;
72
+ if (typeof value === "string" && value.trim() === "") continue;
73
+ result[key] = value;
74
+ }
75
+ return result;
76
+ };
77
+
78
+ const filterData = (data: JsonObject): JsonObject => {
79
+ const result: JsonObject = {};
80
+ for (const key of Object.keys(data)) {
81
+ const value = data[key];
82
+ if (typeof value === "function") continue;
83
+ if (value == null) continue;
84
+ if (value?.constructor?.name === "BigNumber") {
85
+ result[key] = String(value);
86
+ continue;
87
+ }
88
+ if (Array.isArray(value)) {
89
+ result[key] = value.map((item) => {
90
+ if (item?.constructor?.name === "BigNumber") return String(item);
91
+ return item && typeof item === "object" && !Array.isArray(item)
92
+ ? filterObject(item as JsonObject)
93
+ : item;
94
+ });
95
+ } else if (typeof value === "object") {
96
+ continue;
97
+ } else if (typeof value === "string" && value.trim() === "") {
98
+ continue;
99
+ } else {
100
+ result[key] = value;
101
+ }
102
+ }
103
+ return result;
104
+ };
105
+
57
106
  export const parse = (data: JsonObject): void => {
58
- if (cliConfig.json) {
107
+ if (cliConfig.raw) {
59
108
  drawJSON(data);
60
109
  return;
61
110
  }
62
111
 
63
- for (const key in data) {
64
- if (data[key] === null) {
112
+ if (cliConfig.json) {
113
+ drawJSON(filterData(data));
114
+ return;
115
+ }
116
+
117
+ const keys = Object.keys(data).filter((k) => typeof data[k] !== "function");
118
+ let printedScalar = false;
119
+
120
+ for (const key of keys) {
121
+ const value = data[key];
122
+ if (value === null) {
65
123
  console.log(`${chalk.yellow.bold(key)} : null`);
66
- } else if (Array.isArray(data[key])) {
124
+ printedScalar = true;
125
+ } else if (Array.isArray(value)) {
126
+ if (printedScalar) console.log("");
67
127
  console.log(`${chalk.yellow.bold.underline(key)}`);
68
- if (typeof data[key][0] === "object") {
69
- drawTable(data[key]);
128
+ if (typeof value[0] === "object") {
129
+ drawTable(value);
70
130
  } else {
71
- drawJSON(data[key]);
131
+ drawJSON(value);
72
132
  }
73
- } else if (typeof data[key] === "object") {
74
- if (data[key]?.constructor?.name === "BigNumber") {
75
- console.log(`${chalk.yellow.bold(key)} : ${data[key]}`);
133
+ printedScalar = false;
134
+ } else if (typeof value === "object") {
135
+ if (printedScalar) console.log("");
136
+ if (value?.constructor?.name === "BigNumber") {
137
+ console.log(`${chalk.yellow.bold(key)} : ${value}`);
138
+ printedScalar = true;
76
139
  } else {
77
140
  console.log(`${chalk.yellow.bold.underline(key)}`);
78
- const tableRow = toJsonObject(data[key]) ?? {};
141
+ const tableRow = toJsonObject(value) ?? {};
79
142
  drawTable([tableRow]);
143
+ printedScalar = false;
80
144
  }
81
145
  } else {
82
- console.log(`${chalk.yellow.bold(key)} : ${data[key]}`);
146
+ console.log(`${chalk.yellow.bold(key)} : ${value}`);
147
+ printedScalar = true;
83
148
  }
84
149
  }
85
150
  };
86
151
 
152
+ const MAX_COL_WIDTH = 40;
153
+
154
+ const formatCellValue = (value: unknown): string => {
155
+ if (value == null) return "-";
156
+ if (Array.isArray(value)) {
157
+ if (value.length === 0) return "[]";
158
+ return `[${value.length} items]`;
159
+ }
160
+ if (typeof value === "object") {
161
+ if (value?.constructor?.name === "BigNumber") return String(value);
162
+ const keys = Object.keys(value as Record<string, unknown>);
163
+ if (keys.length === 0) return "{}";
164
+ return `{${keys.length} keys}`;
165
+ }
166
+ const str = String(value);
167
+ if (str.length > MAX_COL_WIDTH) {
168
+ return str.slice(0, MAX_COL_WIDTH - 1) + "…";
169
+ }
170
+ return str;
171
+ };
172
+
87
173
  export const drawTable = (data: Array<JsonObject | null | undefined>): void => {
88
174
  if (data.length == 0) {
89
175
  console.log("[]");
@@ -95,23 +181,67 @@ export const drawTable = (data: Array<JsonObject | null | undefined>): void => {
95
181
  // Create an object with all the keys in it
96
182
  const obj = rows.reduce((res, item) => ({ ...res, ...item }), {});
97
183
  // Get those keys as an array
98
- const keys = Object.keys(obj);
99
- if (keys.length === 0) {
184
+ const allKeys = Object.keys(obj);
185
+ if (allKeys.length === 0) {
100
186
  drawJSON(data);
101
187
  return;
102
188
  }
189
+
190
+ // If too many columns, show condensed key-value output with only scalar, non-empty fields
191
+ const maxColumns = 6;
192
+ if (allKeys.length > maxColumns) {
193
+ // Collect visible entries per row to compute alignment
194
+ const rowEntries = rows.map((row) => {
195
+ const entries: Array<[string, string]> = [];
196
+ for (const key of Object.keys(row)) {
197
+ const value = row[key];
198
+ if (typeof value === "function") continue;
199
+ if (value == null) continue;
200
+ if (value?.constructor?.name === "BigNumber") {
201
+ entries.push([key, String(value)]);
202
+ continue;
203
+ }
204
+ if (typeof value === "object") continue;
205
+ if (typeof value === "string" && value.trim() === "") continue;
206
+ entries.push([key, String(value)]);
207
+ }
208
+ return entries;
209
+ });
210
+
211
+ const flatEntries = rowEntries.flat();
212
+ if (flatEntries.length === 0) {
213
+ drawJSON(data);
214
+ return;
215
+ }
216
+
217
+ const maxKeyLen = Math.max(...flatEntries.map(([key]) => key.length));
218
+
219
+ const separatorLen = Math.min(maxKeyLen + 2 + MAX_COL_WIDTH, process.stdout.columns || 80);
220
+
221
+ rowEntries.forEach((entries, idx) => {
222
+ if (idx > 0) console.log(chalk.cyan("─".repeat(separatorLen)));
223
+ for (const [key, value] of entries) {
224
+ const paddedKey = key.padEnd(maxKeyLen);
225
+ console.log(`${chalk.yellow.bold(paddedKey)} ${value}`);
226
+ }
227
+ });
228
+ return;
229
+ }
230
+
231
+ const columns = allKeys;
232
+
103
233
  // Create an object with all keys set to the default value ''
104
- const def = keys.reduce((result: Record<string, string>, key) => {
234
+ const def = allKeys.reduce((result: Record<string, string>, key) => {
105
235
  result[key] = "-";
106
236
  return result;
107
237
  }, {});
108
238
  // Use object destructuring to replace all default values with the ones we have
109
239
  const normalizedData = rows.map((item) => ({ ...def, ...item }));
110
240
 
111
- const columns = Object.keys(normalizedData[0]);
112
-
113
241
  const table = new Table({
114
242
  head: columns.map((c) => chalk.cyan.italic.bold(c)),
243
+ colWidths: columns.map(() => null) as (number | null)[],
244
+ wordWrap: false,
115
245
  chars: {
116
246
  top: " ",
117
247
  "top-mid": " ",
@@ -134,15 +264,7 @@ export const drawTable = (data: Array<JsonObject | null | undefined>): void => {
134
264
  normalizedData.forEach((row) => {
135
265
  const rowValues: string[] = [];
136
266
  for (const key of columns) {
137
- if (row[key] == null) {
138
- rowValues.push("-");
139
- } else if (Array.isArray(row[key])) {
140
- rowValues.push(JSON.stringify(row[key]));
141
- } else if (typeof row[key] === "object") {
142
- rowValues.push(JSON.stringify(row[key]));
143
- } else {
144
- rowValues.push(String(row[key]));
145
- }
267
+ rowValues.push(formatCellValue(row[key]));
146
268
  }
147
269
  table.push(rowValues);
148
270
  });
@@ -291,7 +413,7 @@ export const commandDescriptions: Record<string, string> = {
291
413
  locale: `The locale command allows you to customize your app based on your users' location.`,
292
414
  sites: `The sites command allows you to view, create and manage your Appwrite Sites.`,
293
415
  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.`,
416
+ 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
417
  update: `The update command allows you to update the ${SDK_TITLE} CLI to the latest version.`,
296
418
  users: `The users command allows you to manage your project users.`,
297
419
  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,14 @@ 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) => answer.start !== "existing",
230
+ when: (answer: Answers) => whenOverride(answer) && answer.start !== "existing",
231
231
  },
232
232
  {
233
233
  type: "input",
234
234
  name: "id",
235
235
  message: "What ID would you like to have for your project?",
236
236
  default: "unique()",
237
- when: (answer: Answers) => answer.start !== "existing",
237
+ when: (answer: Answers) => whenOverride(answer) && answer.start !== "existing",
238
238
  },
239
239
  {
240
240
  type: "search-list",
package/lib/sdks.ts CHANGED
@@ -88,3 +88,4 @@ export const sdkForProject = async (): Promise<Client> => {
88
88
  `Session not found. Please run \`${EXECUTABLE_NAME} login\` to create a session.`,
89
89
  );
90
90
  };
91
+
package/lib/types.ts CHANGED
@@ -52,6 +52,7 @@ export interface CommandDescription {
52
52
  export interface CliConfig {
53
53
  verbose: boolean;
54
54
  json: boolean;
55
+ raw: boolean;
55
56
  force: boolean;
56
57
  all: boolean;
57
58
  ids: string[];
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "type": "module",
4
4
  "homepage": "https://appwrite.io/support",
5
5
  "description": "Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API",
6
- "version": "17.0.0",
6
+ "version": "17.1.0",
7
7
  "license": "BSD-3-Clause",
8
8
  "main": "dist/index.cjs",
9
9
  "module": "dist/index.js",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/schema.json",
3
- "version": "17.0.0",
3
+ "version": "17.1.0",
4
4
  "description": "The Appwrite CLI is a command-line application that allows you to interact with Appwrite and perform server-side tasks using your terminal.",
5
5
  "homepage": "https://github.com/appwrite/sdk-for-cli",
6
6
  "license": "BSD-3-Clause",
7
7
  "architecture": {
8
8
  "64bit": {
9
- "url": "https://github.com/appwrite/sdk-for-cli/releases/download/17.0.0/appwrite-cli-win-x64.exe",
9
+ "url": "https://github.com/appwrite/sdk-for-cli/releases/download/17.1.0/appwrite-cli-win-x64.exe",
10
10
  "bin": [
11
11
  [
12
12
  "appwrite-cli-win-x64.exe",
@@ -15,7 +15,7 @@
15
15
  ]
16
16
  },
17
17
  "arm64": {
18
- "url": "https://github.com/appwrite/sdk-for-cli/releases/download/17.0.0/appwrite-cli-win-arm64.exe",
18
+ "url": "https://github.com/appwrite/sdk-for-cli/releases/download/17.1.0/appwrite-cli-win-arm64.exe",
19
19
  "bin": [
20
20
  [
21
21
  "appwrite-cli-win-arm64.exe",