appwrite-utils-cli 0.9.993 → 0.9.994

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 (46) hide show
  1. package/README.md +1 -2
  2. package/dist/collections/methods.js +6 -4
  3. package/dist/functions/deployments.d.ts +4 -0
  4. package/dist/functions/deployments.js +114 -0
  5. package/dist/functions/methods.d.ts +13 -8
  6. package/dist/functions/methods.js +74 -20
  7. package/dist/functions/templates/count-docs-in-collection/src/main.d.ts +21 -0
  8. package/dist/functions/templates/count-docs-in-collection/src/main.js +114 -0
  9. package/dist/functions/templates/count-docs-in-collection/src/request.d.ts +15 -0
  10. package/dist/functions/templates/count-docs-in-collection/src/request.js +6 -0
  11. package/dist/functions/templates/typescript-node/src/index.d.ts +11 -0
  12. package/dist/functions/templates/typescript-node/src/index.js +11 -0
  13. package/dist/interactiveCLI.d.ts +6 -0
  14. package/dist/interactiveCLI.js +437 -32
  15. package/dist/main.js +0 -0
  16. package/dist/migrations/appwriteToX.js +32 -1
  17. package/dist/migrations/schemaStrings.d.ts +1 -0
  18. package/dist/migrations/schemaStrings.js +74 -2
  19. package/dist/migrations/transfer.js +112 -123
  20. package/dist/utils/loadConfigs.d.ts +1 -0
  21. package/dist/utils/loadConfigs.js +19 -0
  22. package/dist/utils/schemaStrings.js +27 -0
  23. package/dist/utilsController.d.ts +5 -1
  24. package/dist/utilsController.js +54 -2
  25. package/package.json +57 -55
  26. package/src/collections/methods.ts +29 -10
  27. package/src/functions/deployments.ts +190 -0
  28. package/src/functions/methods.ts +295 -235
  29. package/src/functions/templates/count-docs-in-collection/README.md +54 -0
  30. package/src/functions/templates/count-docs-in-collection/src/main.ts +159 -0
  31. package/src/functions/templates/count-docs-in-collection/src/request.ts +9 -0
  32. package/src/functions/templates/poetry/README.md +30 -0
  33. package/src/functions/templates/poetry/pyproject.toml +16 -0
  34. package/src/functions/templates/poetry/src/__init__.py +0 -0
  35. package/src/functions/templates/poetry/src/index.py +16 -0
  36. package/src/functions/templates/typescript-node/README.md +32 -0
  37. package/src/functions/templates/typescript-node/src/index.ts +23 -0
  38. package/src/interactiveCLI.ts +606 -47
  39. package/src/migrations/appwriteToX.ts +44 -1
  40. package/src/migrations/schemaStrings.ts +83 -2
  41. package/src/migrations/transfer.ts +280 -207
  42. package/src/setupController.ts +41 -41
  43. package/src/utils/loadConfigs.ts +24 -0
  44. package/src/utils/schemaStrings.ts +27 -0
  45. package/src/utilsController.ts +63 -3
  46. package/tsconfig.json +8 -1
@@ -1,235 +1,295 @@
1
- import {
2
- AppwriteException,
3
- Client,
4
- Functions,
5
- Query,
6
- Runtime,
7
- type Models,
8
- } from "node-appwrite";
9
- import { InputFile } from "node-appwrite/file";
10
- import { create as createTarball } from "tar";
11
- import { join } from "node:path";
12
- import fs from "node:fs";
13
- import { type Specification } from "appwrite-utils";
14
- import chalk from "chalk";
15
-
16
- export const listFunctions = async (
17
- client: Client,
18
- queries?: string[],
19
- search?: string
20
- ) => {
21
- const functions = new Functions(client);
22
- const functionsList = await functions.list(queries, search);
23
- return functionsList;
24
- };
25
-
26
- export const getFunction = async (client: Client, functionId: string) => {
27
- const functions = new Functions(client);
28
- const functionResponse = await functions.get(functionId);
29
- return functionResponse;
30
- };
31
-
32
- export const deleteFunction = async (client: Client, functionId: string) => {
33
- const functions = new Functions(client);
34
- const functionResponse = await functions.delete(functionId);
35
- return functionResponse;
36
- };
37
-
38
- export const createFunction = async (
39
- client: Client,
40
- functionId: string,
41
- name: string,
42
- runtime: Runtime,
43
- execute?: string[],
44
- events?: string[],
45
- schedule?: string,
46
- timeout?: number,
47
- enabled?: boolean,
48
- logging?: boolean,
49
- entrypoint?: string,
50
- commands?: string,
51
- scopes?: string[],
52
- installationId?: string,
53
- providerRepositoryId?: string,
54
- providerBranch?: string,
55
- providerSilentMode?: boolean,
56
- providerRootDirectory?: string,
57
- templateRepository?: string,
58
- templateOwner?: string,
59
- templateRootDirectory?: string,
60
- templateVersion?: string,
61
- specification?: string
62
- ) => {
63
- const functions = new Functions(client);
64
- const functionResponse = await functions.create(
65
- functionId,
66
- name,
67
- runtime,
68
- execute,
69
- events,
70
- schedule,
71
- timeout,
72
- enabled,
73
- logging,
74
- entrypoint,
75
- commands,
76
- scopes,
77
- installationId,
78
- providerRepositoryId,
79
- providerBranch,
80
- providerSilentMode,
81
- providerRootDirectory,
82
- templateRepository,
83
- templateOwner,
84
- templateRootDirectory,
85
- templateVersion,
86
- specification
87
- );
88
- return functionResponse;
89
- };
90
-
91
- export const updateFunctionSpecifications = async (
92
- client: Client,
93
- functionId: string,
94
- specification: Specification
95
- ) => {
96
- const curFunction = await listFunctions(client, [
97
- Query.equal("$id", functionId),
98
- ]);
99
- if (curFunction.functions.length === 0) {
100
- throw new Error("Function not found");
101
- }
102
- const functionFound = curFunction.functions[0];
103
- try {
104
- const functionResponse = await updateFunction(
105
- client,
106
- functionId,
107
- functionFound.name,
108
- functionFound.runtime as Runtime,
109
- functionFound.execute,
110
- functionFound.events,
111
- functionFound.schedule,
112
- functionFound.timeout,
113
- functionFound.enabled,
114
- functionFound.logging,
115
- functionFound.entrypoint,
116
- functionFound.commands,
117
- functionFound.scopes,
118
- functionFound.installationId,
119
- functionFound.providerRepositoryId,
120
- functionFound.providerBranch,
121
- functionFound.providerSilentMode,
122
- functionFound.providerRootDirectory,
123
- specification
124
- );
125
- return functionResponse;
126
- } catch (error) {
127
- if (
128
- error instanceof AppwriteException &&
129
- error.message.includes("Invalid `specification`")
130
- ) {
131
- console.error(
132
- chalk.red(
133
- "Error updating function specifications, please try setting the env variable `_FUNCTIONS_CPUS` and `_FUNCTIONS_RAM` to non-zero values"
134
- )
135
- );
136
- } else {
137
- console.error(chalk.red("Error updating function specifications."));
138
- throw error;
139
- }
140
- }
141
- };
142
-
143
- export const listSpecifications = async (client: Client) => {
144
- const functions = new Functions(client);
145
- const specifications = await functions.listSpecifications();
146
- return specifications;
147
- };
148
-
149
- export const updateFunction = async (
150
- client: Client,
151
- functionId: string,
152
- name: string,
153
- runtime?: Runtime,
154
- execute?: string[],
155
- events?: string[],
156
- schedule?: string,
157
- timeout?: number,
158
- enabled?: boolean,
159
- logging?: boolean,
160
- entrypoint?: string,
161
- commands?: string,
162
- scopes?: string[],
163
- installationId?: string,
164
- providerRepositoryId?: string,
165
- providerBranch?: string,
166
- providerSilentMode?: boolean,
167
- providerRootDirectory?: string,
168
- specification?: Specification
169
- ) => {
170
- const functions = new Functions(client);
171
- const functionResponse = await functions.update(
172
- functionId,
173
- name,
174
- runtime,
175
- execute,
176
- events,
177
- schedule,
178
- timeout,
179
- enabled,
180
- logging,
181
- entrypoint,
182
- commands,
183
- scopes,
184
- installationId,
185
- providerRepositoryId,
186
- providerBranch,
187
- providerSilentMode,
188
- providerRootDirectory,
189
- specification
190
- );
191
- return functionResponse;
192
- };
193
-
194
- export const deployFunction = async (
195
- client: Client,
196
- functionId: string,
197
- codePath: string,
198
- activate: boolean = true,
199
- entrypoint: string = "index.js",
200
- commands: string = "npm install"
201
- ) => {
202
- const functions = new Functions(client);
203
-
204
- // Create temporary tar.gz file
205
- const tarPath = join(process.cwd(), `function-${functionId}.tar.gz`);
206
- await createTarball(
207
- {
208
- gzip: true,
209
- file: tarPath,
210
- cwd: codePath,
211
- },
212
- ["."] // Include all files from codePath
213
- );
214
-
215
- // Read the tar.gz file and create a File object
216
- const fileBuffer = await fs.promises.readFile(tarPath);
217
- const fileObject = InputFile.fromBuffer(
218
- new Uint8Array(fileBuffer),
219
- `function-${functionId}.tar.gz`
220
- );
221
-
222
- // Create deployment with the File object
223
- const functionResponse = await functions.createDeployment(
224
- functionId,
225
- fileObject,
226
- activate,
227
- entrypoint,
228
- commands
229
- );
230
-
231
- // Clean up the temporary tar file
232
- await fs.promises.unlink(tarPath);
233
-
234
- return functionResponse;
235
- };
1
+ import {
2
+ AppwriteException,
3
+ Client,
4
+ Functions,
5
+ Query,
6
+ Runtime,
7
+ } from "node-appwrite";
8
+ import { join } from "node:path";
9
+ import fs from "node:fs";
10
+ import { type Specification } from "appwrite-utils";
11
+ import chalk from "chalk";
12
+ import { extract as extractTar } from "tar";
13
+
14
+ export const listFunctions = async (
15
+ client: Client,
16
+ queries?: string[],
17
+ search?: string
18
+ ) => {
19
+ const functions = new Functions(client);
20
+ const functionsList = await functions.list(queries, search);
21
+ return functionsList;
22
+ };
23
+
24
+ export const getFunction = async (client: Client, functionId: string) => {
25
+ const functions = new Functions(client);
26
+ const functionResponse = await functions.get(functionId);
27
+ return functionResponse;
28
+ };
29
+
30
+ export const downloadLatestFunctionDeployment = async (
31
+ client: Client,
32
+ functionId: string,
33
+ basePath: string = process.cwd()
34
+ ) => {
35
+ const functions = new Functions(client);
36
+ const functionInfo = await getFunction(client, functionId);
37
+ const functionDeployments = await functions.listDeployments(functionId, [
38
+ Query.orderDesc("$createdAt"),
39
+ ]);
40
+
41
+ if (functionDeployments.deployments.length === 0) {
42
+ throw new Error("No deployments found for function");
43
+ }
44
+
45
+ const latestDeployment = functionDeployments.deployments[0];
46
+ const deploymentData = await functions.getDeploymentDownload(
47
+ functionId,
48
+ latestDeployment.$id
49
+ );
50
+
51
+ // Create function directory using provided basePath
52
+ const functionDir = join(
53
+ basePath,
54
+ functionInfo.name.toLowerCase().replace(/\s+/g, "-")
55
+ );
56
+ await fs.promises.mkdir(functionDir, { recursive: true });
57
+
58
+ // Create temporary file for tar extraction
59
+ const tarPath = join(functionDir, "temp.tar.gz");
60
+ const uint8Array = new Uint8Array(deploymentData);
61
+ await fs.promises.writeFile(tarPath, uint8Array);
62
+
63
+ try {
64
+ // Extract tar file
65
+ extractTar({
66
+ C: functionDir,
67
+ file: tarPath,
68
+ sync: true,
69
+ });
70
+
71
+ return {
72
+ path: functionDir,
73
+ function: functionInfo,
74
+ deployment: latestDeployment,
75
+ };
76
+ } finally {
77
+ // Clean up tar file
78
+ await fs.promises.unlink(tarPath).catch(() => {});
79
+ }
80
+ };
81
+
82
+ export const deleteFunction = async (client: Client, functionId: string) => {
83
+ const functions = new Functions(client);
84
+ const functionResponse = await functions.delete(functionId);
85
+ return functionResponse;
86
+ };
87
+
88
+ export const createFunction = async (
89
+ client: Client,
90
+ functionId: string,
91
+ name: string,
92
+ runtime: Runtime,
93
+ execute?: string[],
94
+ events?: string[],
95
+ schedule?: string,
96
+ timeout?: number,
97
+ enabled?: boolean,
98
+ logging?: boolean,
99
+ entrypoint?: string,
100
+ commands?: string,
101
+ scopes?: string[],
102
+ installationId?: string,
103
+ providerRepositoryId?: string,
104
+ providerBranch?: string,
105
+ providerSilentMode?: boolean,
106
+ providerRootDirectory?: string,
107
+ templateRepository?: string,
108
+ templateOwner?: string,
109
+ templateRootDirectory?: string,
110
+ templateVersion?: string,
111
+ specification?: string
112
+ ) => {
113
+ const functions = new Functions(client);
114
+ const functionResponse = await functions.create(
115
+ functionId,
116
+ name,
117
+ runtime,
118
+ execute,
119
+ events,
120
+ schedule,
121
+ timeout,
122
+ enabled,
123
+ logging,
124
+ entrypoint,
125
+ commands,
126
+ scopes,
127
+ installationId,
128
+ providerRepositoryId,
129
+ providerBranch,
130
+ providerSilentMode,
131
+ providerRootDirectory,
132
+ templateRepository,
133
+ templateOwner,
134
+ templateRootDirectory,
135
+ templateVersion,
136
+ specification
137
+ );
138
+ return functionResponse;
139
+ };
140
+
141
+ export const updateFunctionSpecifications = async (
142
+ client: Client,
143
+ functionId: string,
144
+ specification: Specification
145
+ ) => {
146
+ const curFunction = await listFunctions(client, [
147
+ Query.equal("$id", functionId),
148
+ ]);
149
+ if (curFunction.functions.length === 0) {
150
+ throw new Error("Function not found");
151
+ }
152
+ const functionFound = curFunction.functions[0];
153
+ try {
154
+ const functionResponse = await updateFunction(
155
+ client,
156
+ functionId,
157
+ functionFound.name,
158
+ functionFound.runtime as Runtime,
159
+ functionFound.execute,
160
+ functionFound.events,
161
+ functionFound.schedule,
162
+ functionFound.timeout,
163
+ functionFound.enabled,
164
+ functionFound.logging,
165
+ functionFound.entrypoint,
166
+ functionFound.commands,
167
+ functionFound.scopes,
168
+ functionFound.installationId,
169
+ functionFound.providerRepositoryId,
170
+ functionFound.providerBranch,
171
+ functionFound.providerSilentMode,
172
+ functionFound.providerRootDirectory,
173
+ specification
174
+ );
175
+ return functionResponse;
176
+ } catch (error) {
177
+ if (
178
+ error instanceof AppwriteException &&
179
+ error.message.includes("Invalid `specification`")
180
+ ) {
181
+ console.error(
182
+ chalk.red(
183
+ "Error updating function specifications, please try setting the env variable `_FUNCTIONS_CPUS` and `_FUNCTIONS_RAM` to non-zero values"
184
+ )
185
+ );
186
+ } else {
187
+ console.error(chalk.red("Error updating function specifications."));
188
+ throw error;
189
+ }
190
+ }
191
+ };
192
+
193
+ export const listSpecifications = async (client: Client) => {
194
+ const functions = new Functions(client);
195
+ const specifications = await functions.listSpecifications();
196
+ return specifications;
197
+ };
198
+
199
+ export const updateFunction = async (
200
+ client: Client,
201
+ functionId: string,
202
+ name: string,
203
+ runtime?: Runtime,
204
+ execute?: string[],
205
+ events?: string[],
206
+ schedule?: string,
207
+ timeout?: number,
208
+ enabled?: boolean,
209
+ logging?: boolean,
210
+ entrypoint?: string,
211
+ commands?: string,
212
+ scopes?: string[],
213
+ installationId?: string,
214
+ providerRepositoryId?: string,
215
+ providerBranch?: string,
216
+ providerSilentMode?: boolean,
217
+ providerRootDirectory?: string,
218
+ specification?: Specification
219
+ ) => {
220
+ const functions = new Functions(client);
221
+ const functionResponse = await functions.update(
222
+ functionId,
223
+ name,
224
+ runtime,
225
+ execute,
226
+ events,
227
+ schedule,
228
+ timeout,
229
+ enabled,
230
+ logging,
231
+ entrypoint,
232
+ commands,
233
+ scopes,
234
+ installationId,
235
+ providerRepositoryId,
236
+ providerBranch,
237
+ providerSilentMode,
238
+ providerRootDirectory,
239
+ specification
240
+ );
241
+ return functionResponse;
242
+ };
243
+
244
+ export const createFunctionTemplate = async (
245
+ templateType: "typescript-node" | "poetry" | "count-docs-in-collection",
246
+ functionName: string,
247
+ basePath: string = "./functions"
248
+ ) => {
249
+ const functionPath = join(basePath, functionName);
250
+ const templatesPath = join(__dirname, "templates", templateType);
251
+
252
+ // Create function directory
253
+ await fs.promises.mkdir(functionPath, { recursive: true });
254
+
255
+ // Copy template files recursively
256
+ const copyTemplateFiles = async (sourcePath: string, targetPath: string) => {
257
+ const entries = await fs.promises.readdir(sourcePath, {
258
+ withFileTypes: true,
259
+ });
260
+
261
+ for (const entry of entries) {
262
+ const srcPath = join(sourcePath, entry.name);
263
+ const destPath = join(targetPath, entry.name);
264
+
265
+ if (entry.isDirectory()) {
266
+ await fs.promises.mkdir(destPath, { recursive: true });
267
+ await copyTemplateFiles(srcPath, destPath);
268
+ } else {
269
+ let content = await fs.promises.readFile(srcPath, "utf-8");
270
+
271
+ // Replace template variables
272
+ content = content
273
+ .replace(/\{\{functionName\}\}/g, functionName)
274
+ .replace(/\{\{databaseId\}\}/g, "{{databaseId}}")
275
+ .replace(/\{\{collectionId\}\}/g, "{{collectionId}}");
276
+
277
+ await fs.promises.writeFile(destPath, content);
278
+ }
279
+ }
280
+ };
281
+
282
+ try {
283
+ await copyTemplateFiles(templatesPath, functionPath);
284
+ console.log(
285
+ chalk.green(
286
+ `✨ Created ${templateType} function template at ${functionPath}`
287
+ )
288
+ );
289
+ } catch (error) {
290
+ console.error(chalk.red(`Failed to create function template: ${error}`));
291
+ throw error;
292
+ }
293
+
294
+ return functionPath;
295
+ };
@@ -0,0 +1,54 @@
1
+ # Count Documents in Collection Function
2
+
3
+ A utility function that accurately counts documents in an Appwrite collection, even when there are more than 5,000 documents.
4
+
5
+ ## Features
6
+ - Handles collections with any number of documents
7
+ - Supports filtering using Appwrite queries
8
+ - Uses efficient binary search algorithm for large collections
9
+ - Provides detailed logging during the counting process
10
+
11
+ ## Structure
12
+ - `src/main.ts`: Main function implementation with counting logic
13
+ - `src/request.ts`: Request validation schema using Zod
14
+
15
+ ## Usage
16
+ Send a POST request with:
17
+ ```json
18
+ {
19
+ "databaseId": "your-database-id",
20
+ "collectionId": "your-collection-id",
21
+ "queries": [Query.orderDesc("$createdAt"), Query.contains("name", "John")] // Or put the string array from after this, they are the same
22
+ }
23
+ ```
24
+
25
+ ## Response
26
+ ```json
27
+ {
28
+ "success": true,
29
+ "count": 12345
30
+ }
31
+ ```
32
+
33
+ ## Development
34
+ 1. Install dependencies: `npm|yarn|bun install`
35
+ 2. Build: `npm|yarn|bun run build`
36
+ 3. Deploy: Function will be built automatically during deployment
37
+
38
+ ## Deployment
39
+ Make sure it's inside `appwriteConfig.ts` functions array, and if you want to build it FIRST, before Appwrite (using your system), you can
40
+ add the `predeployCommands` to the function in `appwriteConfig.ts`.
41
+
42
+ ## Example Config
43
+ ```typescript
44
+ {
45
+ $id: 'count-docs',
46
+ name: 'Count Documents',
47
+ runtime: 'node-18.0',
48
+ path: 'functions/count-docs',
49
+ entrypoint: './main.js',
50
+ execute: ['any'],
51
+ predeployCommands: ['npm install', 'npm run build'],
52
+ deployDir: './dist'
53
+ }
54
+ ```