appwrite-cli 13.6.0 → 13.6.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/CHANGELOG.md +4 -0
- package/README.md +2 -2
- package/cli.ts +3 -3
- package/dist/bundle-win-arm64.mjs +336 -212
- package/dist/cli.cjs +336 -212
- package/dist/index.cjs +156 -104
- package/dist/index.js +156 -104
- package/dist/lib/commands/config-validations.d.ts +1 -1
- package/dist/lib/commands/config-validations.d.ts.map +1 -1
- package/dist/lib/commands/errors.d.ts +4 -4
- package/dist/lib/commands/errors.d.ts.map +1 -1
- package/dist/lib/commands/generate.d.ts.map +1 -1
- package/dist/lib/commands/generators/base.d.ts +5 -0
- package/dist/lib/commands/generators/base.d.ts.map +1 -1
- package/dist/lib/commands/generic.d.ts.map +1 -1
- package/dist/lib/commands/init.d.ts.map +1 -1
- package/dist/lib/commands/run.d.ts.map +1 -1
- package/dist/lib/commands/types.d.ts.map +1 -1
- package/dist/lib/commands/update.d.ts.map +1 -1
- package/dist/lib/commands/utils/change-approval.d.ts +3 -3
- package/dist/lib/commands/utils/change-approval.d.ts.map +1 -1
- package/dist/lib/commands/utils/database-sync.d.ts.map +1 -1
- package/dist/lib/commands/utils/deployment.d.ts +16 -4
- package/dist/lib/commands/utils/deployment.d.ts.map +1 -1
- package/dist/lib/commands/utils/pools.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/json.d.ts +1 -1
- package/dist/lib/json.d.ts.map +1 -1
- package/dist/lib/paginate.d.ts +5 -6
- package/dist/lib/paginate.d.ts.map +1 -1
- package/dist/lib/parser.d.ts +5 -4
- package/dist/lib/parser.d.ts.map +1 -1
- package/dist/lib/spinner.d.ts +1 -1
- package/dist/lib/spinner.d.ts.map +1 -1
- package/dist/lib/utils.d.ts +6 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/validations.d.ts +1 -1
- package/dist/lib/validations.d.ts.map +1 -1
- package/eslint.config.js +45 -0
- package/install.ps1 +2 -2
- package/install.sh +1 -1
- package/lib/client.ts +3 -3
- package/lib/commands/config-validations.ts +1 -1
- package/lib/commands/config.ts +2 -2
- package/lib/commands/errors.ts +2 -2
- package/lib/commands/generate.ts +8 -6
- package/lib/commands/generators/base.ts +6 -0
- package/lib/commands/generators/typescript/databases.ts +9 -9
- package/lib/commands/generators/typescript/templates/databases.ts.hbs +16 -16
- package/lib/commands/generic.ts +21 -16
- package/lib/commands/init.ts +147 -61
- package/lib/commands/pull.ts +1 -1
- package/lib/commands/push.ts +19 -19
- package/lib/commands/run.ts +15 -9
- package/lib/commands/types.ts +18 -8
- package/lib/commands/update.ts +24 -16
- package/lib/commands/utils/attributes.ts +6 -6
- package/lib/commands/utils/change-approval.ts +26 -19
- package/lib/commands/utils/database-sync.ts +58 -18
- package/lib/commands/utils/deployment.ts +22 -5
- package/lib/commands/utils/pools.ts +11 -5
- package/lib/config.ts +1 -1
- package/lib/constants.ts +1 -1
- package/lib/emulation/docker.ts +5 -6
- package/lib/emulation/utils.ts +2 -2
- package/lib/json.ts +15 -7
- package/lib/paginate.ts +30 -20
- package/lib/parser.ts +46 -15
- package/lib/questions.ts +38 -38
- package/lib/spinner.ts +5 -1
- package/lib/utils.ts +15 -3
- package/lib/validations.ts +1 -1
- package/package.json +7 -1
- package/scoop/appwrite.config.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
+
import { AppwriteException } from "@appwrite.io/console";
|
|
2
3
|
import { localConfig } from "../../config.js";
|
|
3
4
|
import { log, success, error, drawTable } from "../../parser.js";
|
|
4
5
|
import { paginate } from "../../paginate.js";
|
|
@@ -10,6 +11,39 @@ export interface TablesDBChangesResult {
|
|
|
10
11
|
resyncNeeded: boolean;
|
|
11
12
|
}
|
|
12
13
|
|
|
14
|
+
interface TablesDBResource {
|
|
15
|
+
$id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const isTablesDBResource = (value: unknown): value is TablesDBResource => {
|
|
21
|
+
if (!value || typeof value !== "object") {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
"$id" in value &&
|
|
27
|
+
typeof value.$id === "string" &&
|
|
28
|
+
"name" in value &&
|
|
29
|
+
typeof value.name === "string" &&
|
|
30
|
+
"enabled" in value &&
|
|
31
|
+
typeof value.enabled === "boolean"
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const getSyncErrorMessage = (err: unknown): string => {
|
|
36
|
+
if (err instanceof AppwriteException) {
|
|
37
|
+
return err.message;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (err instanceof Error) {
|
|
41
|
+
return err.message;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return String(err);
|
|
45
|
+
};
|
|
46
|
+
|
|
13
47
|
/**
|
|
14
48
|
* Check for and apply changes to tablesDB (databases)
|
|
15
49
|
* Handles creation, update, and deletion of databases
|
|
@@ -18,29 +52,37 @@ export const checkAndApplyTablesDBChanges =
|
|
|
18
52
|
async (): Promise<TablesDBChangesResult> => {
|
|
19
53
|
log("Checking for tablesDB changes ...");
|
|
20
54
|
|
|
21
|
-
const localTablesDBs = localConfig.getTablesDBs();
|
|
22
|
-
const
|
|
23
|
-
async (args
|
|
55
|
+
const localTablesDBs: TablesDBResource[] = localConfig.getTablesDBs();
|
|
56
|
+
const paginatedResult = await paginate(
|
|
57
|
+
async (args) => {
|
|
24
58
|
const tablesDBService = await getTablesDBService();
|
|
25
|
-
|
|
59
|
+
const queries = Array.isArray(args.queries)
|
|
60
|
+
? args.queries.filter(
|
|
61
|
+
(query): query is string => typeof query === "string",
|
|
62
|
+
)
|
|
63
|
+
: [];
|
|
64
|
+
return await tablesDBService.list(queries);
|
|
26
65
|
},
|
|
27
66
|
{},
|
|
28
67
|
100,
|
|
29
68
|
"databases",
|
|
30
69
|
);
|
|
70
|
+
const remoteTablesDBs = Array.isArray(paginatedResult.databases)
|
|
71
|
+
? paginatedResult.databases.filter(isTablesDBResource)
|
|
72
|
+
: [];
|
|
31
73
|
|
|
32
74
|
if (localTablesDBs.length === 0 && remoteTablesDBs.length === 0) {
|
|
33
75
|
return { applied: false, resyncNeeded: false };
|
|
34
76
|
}
|
|
35
77
|
|
|
36
|
-
const changes:
|
|
37
|
-
const toCreate:
|
|
38
|
-
const toUpdate:
|
|
39
|
-
const toDelete:
|
|
78
|
+
const changes: Array<Record<string, unknown>> = [];
|
|
79
|
+
const toCreate: TablesDBResource[] = [];
|
|
80
|
+
const toUpdate: TablesDBResource[] = [];
|
|
81
|
+
const toDelete: TablesDBResource[] = [];
|
|
40
82
|
|
|
41
83
|
// Check for deletions - remote DBs that aren't in local config
|
|
42
84
|
for (const remoteDB of remoteTablesDBs) {
|
|
43
|
-
const localDB = localTablesDBs.find((db
|
|
85
|
+
const localDB = localTablesDBs.find((db) => db.$id === remoteDB.$id);
|
|
44
86
|
if (!localDB) {
|
|
45
87
|
toDelete.push(remoteDB);
|
|
46
88
|
changes.push({
|
|
@@ -55,9 +97,7 @@ export const checkAndApplyTablesDBChanges =
|
|
|
55
97
|
|
|
56
98
|
// Check for additions and updates
|
|
57
99
|
for (const localDB of localTablesDBs) {
|
|
58
|
-
const remoteDB = remoteTablesDBs.find(
|
|
59
|
-
(db: any) => db.$id === localDB.$id,
|
|
60
|
-
);
|
|
100
|
+
const remoteDB = remoteTablesDBs.find((db) => db.$id === localDB.$id);
|
|
61
101
|
|
|
62
102
|
if (!remoteDB) {
|
|
63
103
|
toCreate.push(localDB);
|
|
@@ -132,9 +172,9 @@ export const checkAndApplyTablesDBChanges =
|
|
|
132
172
|
await tablesDBService.delete(db.$id);
|
|
133
173
|
success(`Deleted ${db.name} ( ${db.$id} )`);
|
|
134
174
|
needsResync = true;
|
|
135
|
-
} catch (e:
|
|
175
|
+
} catch (e: unknown) {
|
|
136
176
|
error(
|
|
137
|
-
`Failed to delete database ${db.name} ( ${db.$id} ): ${e
|
|
177
|
+
`Failed to delete database ${db.name} ( ${db.$id} ): ${getSyncErrorMessage(e)}`,
|
|
138
178
|
);
|
|
139
179
|
throw new Error(
|
|
140
180
|
`Database sync failed during deletion of ${db.$id}. Some changes may have been applied.`,
|
|
@@ -149,9 +189,9 @@ export const checkAndApplyTablesDBChanges =
|
|
|
149
189
|
const tablesDBService = await getTablesDBService();
|
|
150
190
|
await tablesDBService.create(db.$id, db.name, db.enabled);
|
|
151
191
|
success(`Created ${db.name} ( ${db.$id} )`);
|
|
152
|
-
} catch (e:
|
|
192
|
+
} catch (e: unknown) {
|
|
153
193
|
error(
|
|
154
|
-
`Failed to create database ${db.name} ( ${db.$id} ): ${e
|
|
194
|
+
`Failed to create database ${db.name} ( ${db.$id} ): ${getSyncErrorMessage(e)}`,
|
|
155
195
|
);
|
|
156
196
|
throw new Error(
|
|
157
197
|
`Database sync failed during creation of ${db.$id}. Some changes may have been applied.`,
|
|
@@ -166,9 +206,9 @@ export const checkAndApplyTablesDBChanges =
|
|
|
166
206
|
const tablesDBService = await getTablesDBService();
|
|
167
207
|
await tablesDBService.update(db.$id, db.name, db.enabled);
|
|
168
208
|
success(`Updated ${db.name} ( ${db.$id} )`);
|
|
169
|
-
} catch (e:
|
|
209
|
+
} catch (e: unknown) {
|
|
170
210
|
error(
|
|
171
|
-
`Failed to update database ${db.name} ( ${db.$id} ): ${e
|
|
211
|
+
`Failed to update database ${db.name} ( ${db.$id} ): ${getSyncErrorMessage(e)}`,
|
|
172
212
|
);
|
|
173
213
|
throw new Error(
|
|
174
214
|
`Database sync failed during update of ${db.$id}. Some changes may have been applied.`,
|
|
@@ -6,6 +6,19 @@ import { error } from "../../parser.js";
|
|
|
6
6
|
|
|
7
7
|
const POLL_DEBOUNCE = 2000; // Milliseconds
|
|
8
8
|
|
|
9
|
+
interface DeploymentListResult {
|
|
10
|
+
total: number;
|
|
11
|
+
deployments: Array<{
|
|
12
|
+
$id: string;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface DeploymentDetails {
|
|
17
|
+
$id: string;
|
|
18
|
+
status: string;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
9
22
|
/**
|
|
10
23
|
* Package a directory into a tar.gz File object for deployment
|
|
11
24
|
* @private - Only used internally by pushDeployment
|
|
@@ -38,7 +51,7 @@ export async function downloadDeploymentCode(params: {
|
|
|
38
51
|
resourcePath: string;
|
|
39
52
|
holdingVars: { key: string; value: string }[];
|
|
40
53
|
withVariables?: boolean;
|
|
41
|
-
listDeployments: () => Promise<
|
|
54
|
+
listDeployments: () => Promise<DeploymentListResult>;
|
|
42
55
|
getDownloadUrl: (deploymentId: string) => string;
|
|
43
56
|
projectClient: Client;
|
|
44
57
|
}): Promise<void> {
|
|
@@ -85,8 +98,12 @@ export async function downloadDeploymentCode(params: {
|
|
|
85
98
|
"arrayBuffer",
|
|
86
99
|
);
|
|
87
100
|
|
|
101
|
+
if (!(downloadBuffer instanceof ArrayBuffer)) {
|
|
102
|
+
throw new Error("Failed to download deployment archive as ArrayBuffer.");
|
|
103
|
+
}
|
|
104
|
+
|
|
88
105
|
try {
|
|
89
|
-
fs.writeFileSync(compressedFileName, Buffer.from(downloadBuffer
|
|
106
|
+
fs.writeFileSync(compressedFileName, Buffer.from(downloadBuffer));
|
|
90
107
|
} catch (err) {
|
|
91
108
|
const message = err instanceof Error ? err.message : String(err);
|
|
92
109
|
throw new Error(
|
|
@@ -118,14 +135,14 @@ export async function downloadDeploymentCode(params: {
|
|
|
118
135
|
|
|
119
136
|
export interface PushDeploymentParams {
|
|
120
137
|
resourcePath: string;
|
|
121
|
-
createDeployment: (codeFile: File) => Promise<
|
|
122
|
-
getDeployment?: (deploymentId: string) => Promise<
|
|
138
|
+
createDeployment: (codeFile: File) => Promise<DeploymentDetails>;
|
|
139
|
+
getDeployment?: (deploymentId: string) => Promise<DeploymentDetails>;
|
|
123
140
|
pollForStatus?: boolean;
|
|
124
141
|
onStatusUpdate?: (status: string) => void;
|
|
125
142
|
}
|
|
126
143
|
|
|
127
144
|
export interface PushDeploymentResult {
|
|
128
|
-
deployment:
|
|
145
|
+
deployment: DeploymentDetails;
|
|
129
146
|
wasPolled: boolean;
|
|
130
147
|
finalStatus?: string;
|
|
131
148
|
}
|
|
@@ -39,7 +39,7 @@ export class Pools {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
if (this.pollMaxDebounces === this.POLL_DEFAULT_VALUE) {
|
|
42
|
-
|
|
42
|
+
const steps = Math.max(1, Math.ceil(Number(total) / this.STEP_SIZE));
|
|
43
43
|
if (steps > 1 && iteration === 1) {
|
|
44
44
|
this.pollMaxDebounces *= steps;
|
|
45
45
|
|
|
@@ -78,7 +78,7 @@ export class Pools {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
if (this.pollMaxDebounces === this.POLL_DEFAULT_VALUE) {
|
|
81
|
-
|
|
81
|
+
const steps = Math.max(1, Math.ceil(Number(total) / this.STEP_SIZE));
|
|
82
82
|
if (steps > 1 && iteration === 1) {
|
|
83
83
|
this.pollMaxDebounces *= steps;
|
|
84
84
|
|
|
@@ -106,7 +106,10 @@ export class Pools {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
if (this.pollMaxDebounces === this.POLL_DEFAULT_VALUE) {
|
|
109
|
-
|
|
109
|
+
const steps = Math.max(
|
|
110
|
+
1,
|
|
111
|
+
Math.ceil(attributeKeys.length / this.STEP_SIZE),
|
|
112
|
+
);
|
|
110
113
|
if (steps > 1 && iteration === 1) {
|
|
111
114
|
this.pollMaxDebounces *= steps;
|
|
112
115
|
|
|
@@ -164,7 +167,10 @@ export class Pools {
|
|
|
164
167
|
}
|
|
165
168
|
|
|
166
169
|
if (this.pollMaxDebounces === this.POLL_DEFAULT_VALUE) {
|
|
167
|
-
|
|
170
|
+
const steps = Math.max(
|
|
171
|
+
1,
|
|
172
|
+
Math.ceil(attributeKeys.length / this.STEP_SIZE),
|
|
173
|
+
);
|
|
168
174
|
if (steps > 1 && iteration === 1) {
|
|
169
175
|
this.pollMaxDebounces *= steps;
|
|
170
176
|
|
|
@@ -232,7 +238,7 @@ export class Pools {
|
|
|
232
238
|
}
|
|
233
239
|
|
|
234
240
|
if (this.pollMaxDebounces === this.POLL_DEFAULT_VALUE) {
|
|
235
|
-
|
|
241
|
+
const steps = Math.max(1, Math.ceil(indexKeys.length / this.STEP_SIZE));
|
|
236
242
|
if (steps > 1 && iteration === 1) {
|
|
237
243
|
this.pollMaxDebounces *= steps;
|
|
238
244
|
|
package/lib/config.ts
CHANGED
package/lib/constants.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SDK
|
|
2
2
|
export const SDK_TITLE = 'Appwrite';
|
|
3
3
|
export const SDK_TITLE_LOWER = 'appwrite';
|
|
4
|
-
export const SDK_VERSION = '13.6.
|
|
4
|
+
export const SDK_VERSION = '13.6.1';
|
|
5
5
|
export const SDK_NAME = 'Command Line';
|
|
6
6
|
export const SDK_PLATFORM = 'console';
|
|
7
7
|
export const SDK_LANGUAGE = 'cli';
|
package/lib/emulation/docker.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import ignoreModule from "ignore";
|
|
2
2
|
const ignore: typeof ignoreModule =
|
|
3
|
-
(ignoreModule as
|
|
3
|
+
(ignoreModule as unknown as { default?: typeof ignoreModule }).default ??
|
|
4
|
+
ignoreModule;
|
|
4
5
|
import net from "net";
|
|
5
6
|
import chalk from "chalk";
|
|
6
7
|
import childProcess from "child_process";
|
|
@@ -256,11 +257,9 @@ export async function dockerStart(
|
|
|
256
257
|
|
|
257
258
|
try {
|
|
258
259
|
await waitUntilPortOpen(port);
|
|
259
|
-
} catch (err:
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
(err.message ? err.message : err.toString()),
|
|
263
|
-
);
|
|
260
|
+
} catch (err: unknown) {
|
|
261
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
262
|
+
error(`Failed to start function with error: ${message}`);
|
|
264
263
|
return;
|
|
265
264
|
}
|
|
266
265
|
|
package/lib/emulation/utils.ts
CHANGED
|
@@ -142,14 +142,14 @@ export const JwtManager = {
|
|
|
142
142
|
await usersClient.get({
|
|
143
143
|
userId,
|
|
144
144
|
});
|
|
145
|
-
const userResponse
|
|
145
|
+
const userResponse = await usersClient.createJWT({
|
|
146
146
|
userId,
|
|
147
147
|
duration: 60 * 60,
|
|
148
148
|
});
|
|
149
149
|
this.userJwt = userResponse.jwt;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
const functionResponse
|
|
152
|
+
const functionResponse = await projectsClient.createJWT({
|
|
153
153
|
projectId: localConfig.getProject().projectId!,
|
|
154
154
|
scopes: projectScopes,
|
|
155
155
|
duration: 60 * 60,
|
package/lib/json.ts
CHANGED
|
@@ -8,18 +8,25 @@ const MIN_SAFE = BigInt(Number.MIN_SAFE_INTEGER);
|
|
|
8
8
|
const MAX_INT64 = BigInt("9223372036854775807");
|
|
9
9
|
const MIN_INT64 = BigInt("-9223372036854775808");
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
interface BigNumberLike {
|
|
12
|
+
_isBigNumber: boolean;
|
|
13
|
+
isInteger: () => boolean;
|
|
14
|
+
toFixed: () => string;
|
|
15
|
+
toNumber: () => number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isBigNumber(value: unknown): value is BigNumberLike {
|
|
12
19
|
return (
|
|
13
20
|
value !== null &&
|
|
14
21
|
typeof value === "object" &&
|
|
15
|
-
value._isBigNumber === true &&
|
|
16
|
-
typeof value.isInteger === "function" &&
|
|
17
|
-
typeof value.toFixed === "function" &&
|
|
18
|
-
typeof value.toNumber === "function"
|
|
22
|
+
(value as BigNumberLike)._isBigNumber === true &&
|
|
23
|
+
typeof (value as BigNumberLike).isInteger === "function" &&
|
|
24
|
+
typeof (value as BigNumberLike).toFixed === "function" &&
|
|
25
|
+
typeof (value as BigNumberLike).toNumber === "function"
|
|
19
26
|
);
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
function reviver(_key: string, value:
|
|
29
|
+
function reviver(_key: string, value: unknown): unknown {
|
|
23
30
|
if (isBigNumber(value)) {
|
|
24
31
|
if (value.isInteger()) {
|
|
25
32
|
const str = value.toFixed();
|
|
@@ -38,6 +45,7 @@ function reviver(_key: string, value: any): any {
|
|
|
38
45
|
}
|
|
39
46
|
|
|
40
47
|
export const JSONBig = {
|
|
41
|
-
parse: (text: string) =>
|
|
48
|
+
parse: <T = unknown>(text: string): T =>
|
|
49
|
+
JSONbigParser.parse(text, reviver) as T,
|
|
42
50
|
stringify: JSONbigSerializer.stringify,
|
|
43
51
|
};
|
package/lib/paginate.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
type PaginateArgs = Record<string, unknown>;
|
|
2
|
+
|
|
3
|
+
type WrappedPaginateResponse<T, K extends string = string> = Record<K, T[]> & {
|
|
4
|
+
total: number;
|
|
5
|
+
};
|
|
4
6
|
|
|
5
7
|
// Overload for when wrapper is empty string - returns array
|
|
6
|
-
export function paginate<T =
|
|
7
|
-
action: (args: PaginateArgs) => Promise<
|
|
8
|
+
export function paginate<T = unknown>(
|
|
9
|
+
action: (args: PaginateArgs) => Promise<T[]>,
|
|
8
10
|
args: PaginateArgs,
|
|
9
11
|
limit: number,
|
|
10
12
|
wrapper: "",
|
|
@@ -12,22 +14,24 @@ export function paginate<T = any>(
|
|
|
12
14
|
): Promise<T[]>;
|
|
13
15
|
|
|
14
16
|
// Overload for when wrapper is specified - returns object with that key
|
|
15
|
-
export function paginate<T =
|
|
16
|
-
action: (args: PaginateArgs) => Promise<
|
|
17
|
+
export function paginate<T = unknown, K extends string = string>(
|
|
18
|
+
action: (args: PaginateArgs) => Promise<WrappedPaginateResponse<T, K>>,
|
|
17
19
|
args: PaginateArgs,
|
|
18
20
|
limit: number,
|
|
19
21
|
wrapper: K,
|
|
20
22
|
queries?: string[],
|
|
21
|
-
): Promise<
|
|
23
|
+
): Promise<WrappedPaginateResponse<T, K>>;
|
|
22
24
|
|
|
23
25
|
// Implementation
|
|
24
|
-
export async function paginate<T =
|
|
25
|
-
action: (
|
|
26
|
+
export async function paginate<T = unknown>(
|
|
27
|
+
action: (
|
|
28
|
+
args: PaginateArgs,
|
|
29
|
+
) => Promise<T[] | WrappedPaginateResponse<T, string>>,
|
|
26
30
|
args: PaginateArgs = {},
|
|
27
31
|
limit: number = 100,
|
|
28
32
|
wrapper: string = "",
|
|
29
33
|
queries: string[] = [],
|
|
30
|
-
): Promise<T[] |
|
|
34
|
+
): Promise<T[] | WrappedPaginateResponse<T, string>> {
|
|
31
35
|
let pageNumber = 0;
|
|
32
36
|
let results: T[] = [];
|
|
33
37
|
let total = 0;
|
|
@@ -46,21 +50,27 @@ export async function paginate<T = any>(
|
|
|
46
50
|
});
|
|
47
51
|
|
|
48
52
|
if (wrapper === "") {
|
|
49
|
-
|
|
53
|
+
const listResponse = response as T[];
|
|
54
|
+
|
|
55
|
+
if (listResponse.length === 0) {
|
|
50
56
|
break;
|
|
51
57
|
}
|
|
52
|
-
|
|
58
|
+
|
|
59
|
+
results = results.concat(listResponse);
|
|
53
60
|
} else {
|
|
54
|
-
|
|
61
|
+
const wrappedResponse = response as WrappedPaginateResponse<T, string>;
|
|
62
|
+
const wrappedResults = wrappedResponse[wrapper] ?? [];
|
|
63
|
+
|
|
64
|
+
if (wrappedResults.length === 0) {
|
|
55
65
|
break;
|
|
56
66
|
}
|
|
57
|
-
results = results.concat(response[wrapper]);
|
|
58
|
-
}
|
|
59
67
|
|
|
60
|
-
|
|
68
|
+
results = results.concat(wrappedResults);
|
|
69
|
+
total = wrappedResponse.total;
|
|
61
70
|
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
if (results.length >= total) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
64
74
|
}
|
|
65
75
|
|
|
66
76
|
pageNumber++;
|
|
@@ -73,5 +83,5 @@ export async function paginate<T = any>(
|
|
|
73
83
|
return {
|
|
74
84
|
[wrapper]: results,
|
|
75
85
|
total,
|
|
76
|
-
} as
|
|
86
|
+
} as WrappedPaginateResponse<T, string>;
|
|
77
87
|
}
|
package/lib/parser.ts
CHANGED
|
@@ -25,7 +25,36 @@ const cliConfig: CliConfig = {
|
|
|
25
25
|
reportData: {},
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
type JsonObject = Record<string, unknown>;
|
|
29
|
+
|
|
30
|
+
interface ReportDataPayload {
|
|
31
|
+
data?: {
|
|
32
|
+
args?: string[];
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const toJsonObject = (value: unknown): JsonObject | null => {
|
|
37
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
38
|
+
return value as JsonObject;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return null;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const extractReportCommandArgs = (value: unknown): string[] => {
|
|
45
|
+
if (!value || typeof value !== "object") {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const reportData = value as ReportDataPayload;
|
|
50
|
+
if (!Array.isArray(reportData.data?.args)) {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return reportData.data.args;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const parse = (data: JsonObject): void => {
|
|
29
58
|
if (cliConfig.json) {
|
|
30
59
|
drawJSON(data);
|
|
31
60
|
return;
|
|
@@ -46,7 +75,8 @@ export const parse = (data: Record<string, any>): void => {
|
|
|
46
75
|
console.log(`${chalk.yellow.bold(key)} : ${data[key]}`);
|
|
47
76
|
} else {
|
|
48
77
|
console.log(`${chalk.yellow.bold.underline(key)}`);
|
|
49
|
-
|
|
78
|
+
const tableRow = toJsonObject(data[key]) ?? {};
|
|
79
|
+
drawTable([tableRow]);
|
|
50
80
|
}
|
|
51
81
|
} else {
|
|
52
82
|
console.log(`${chalk.yellow.bold(key)} : ${data[key]}`);
|
|
@@ -54,17 +84,13 @@ export const parse = (data: Record<string, any>): void => {
|
|
|
54
84
|
}
|
|
55
85
|
};
|
|
56
86
|
|
|
57
|
-
export const drawTable = (
|
|
58
|
-
data: Array<Record<string, any> | null | undefined>,
|
|
59
|
-
): void => {
|
|
87
|
+
export const drawTable = (data: Array<JsonObject | null | undefined>): void => {
|
|
60
88
|
if (data.length == 0) {
|
|
61
89
|
console.log("[]");
|
|
62
90
|
return;
|
|
63
91
|
}
|
|
64
92
|
|
|
65
|
-
const rows = data.map((item) =>
|
|
66
|
-
item && typeof item === "object" && !Array.isArray(item) ? item : {},
|
|
67
|
-
);
|
|
93
|
+
const rows = data.map((item): JsonObject => toJsonObject(item) ?? {});
|
|
68
94
|
|
|
69
95
|
// Create an object with all the keys in it
|
|
70
96
|
const obj = rows.reduce((res, item) => ({ ...res, ...item }), {});
|
|
@@ -106,7 +132,7 @@ export const drawTable = (
|
|
|
106
132
|
});
|
|
107
133
|
|
|
108
134
|
normalizedData.forEach((row) => {
|
|
109
|
-
const rowValues:
|
|
135
|
+
const rowValues: string[] = [];
|
|
110
136
|
for (const key of columns) {
|
|
111
137
|
if (row[key] == null) {
|
|
112
138
|
rowValues.push("-");
|
|
@@ -115,7 +141,7 @@ export const drawTable = (
|
|
|
115
141
|
} else if (typeof row[key] === "object") {
|
|
116
142
|
rowValues.push(JSON.stringify(row[key]));
|
|
117
143
|
} else {
|
|
118
|
-
rowValues.push(row[key]);
|
|
144
|
+
rowValues.push(String(row[key]));
|
|
119
145
|
}
|
|
120
146
|
}
|
|
121
147
|
table.push(rowValues);
|
|
@@ -123,13 +149,13 @@ export const drawTable = (
|
|
|
123
149
|
console.log(table.toString());
|
|
124
150
|
};
|
|
125
151
|
|
|
126
|
-
export const drawJSON = (data:
|
|
152
|
+
export const drawJSON = (data: unknown): void => {
|
|
127
153
|
console.log(JSON.stringify(data, null, 2));
|
|
128
154
|
};
|
|
129
155
|
|
|
130
156
|
export const parseError = (err: Error): void => {
|
|
131
157
|
if (cliConfig.report) {
|
|
132
|
-
(async () => {
|
|
158
|
+
void (async () => {
|
|
133
159
|
let appwriteVersion = "unknown";
|
|
134
160
|
const endpoint = globalConfig.getEndpoint();
|
|
135
161
|
|
|
@@ -145,7 +171,8 @@ export const parseError = (err: Error): void => {
|
|
|
145
171
|
}
|
|
146
172
|
|
|
147
173
|
const version = SDK_VERSION;
|
|
148
|
-
const
|
|
174
|
+
const commandArgs = extractReportCommandArgs(cliConfig.reportData);
|
|
175
|
+
const stepsToReproduce = `Running \`${EXECUTABLE_NAME} ${commandArgs.join(" ")}\``;
|
|
149
176
|
const yourEnvironment = `CLI version: ${version}\nOperation System: ${os.type()}\nAppwrite version: ${appwriteVersion}\nIs Cloud: ${isCloud()}`;
|
|
150
177
|
|
|
151
178
|
const stack = "```\n" + (err.stack || err.message) + "\n```";
|
|
@@ -188,7 +215,9 @@ export const parseError = (err: Error): void => {
|
|
|
188
215
|
}
|
|
189
216
|
};
|
|
190
217
|
|
|
191
|
-
export const actionRunner = <
|
|
218
|
+
export const actionRunner = <
|
|
219
|
+
T extends (...args: unknown[]) => Promise<unknown>,
|
|
220
|
+
>(
|
|
192
221
|
fn: T,
|
|
193
222
|
): ((...args: Parameters<T>) => Promise<void>) => {
|
|
194
223
|
return (...args: Parameters<T>) => {
|
|
@@ -200,7 +229,9 @@ export const actionRunner = <T extends (...args: any[]) => Promise<any>>(
|
|
|
200
229
|
error(`The '--all' and '--id' flags cannot be used together.`);
|
|
201
230
|
process.exit(1);
|
|
202
231
|
}
|
|
203
|
-
return fn(...args)
|
|
232
|
+
return fn(...args)
|
|
233
|
+
.then(() => undefined)
|
|
234
|
+
.catch(parseError);
|
|
204
235
|
};
|
|
205
236
|
};
|
|
206
237
|
|