appwrite-utils-cli 0.9.993 → 0.9.995
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/README.md +1 -2
- package/dist/collections/methods.js +6 -4
- package/dist/functions/deployments.d.ts +4 -0
- package/dist/functions/deployments.js +114 -0
- package/dist/functions/methods.d.ts +13 -8
- package/dist/functions/methods.js +74 -20
- package/dist/functions/templates/count-docs-in-collection/src/main.d.ts +21 -0
- package/dist/functions/templates/count-docs-in-collection/src/main.js +114 -0
- package/dist/functions/templates/count-docs-in-collection/src/request.d.ts +15 -0
- package/dist/functions/templates/count-docs-in-collection/src/request.js +6 -0
- package/dist/functions/templates/typescript-node/src/index.d.ts +11 -0
- package/dist/functions/templates/typescript-node/src/index.js +11 -0
- package/dist/interactiveCLI.d.ts +6 -0
- package/dist/interactiveCLI.js +437 -32
- package/dist/main.js +0 -0
- package/dist/migrations/appwriteToX.js +32 -1
- package/dist/migrations/schemaStrings.d.ts +1 -0
- package/dist/migrations/schemaStrings.js +74 -2
- package/dist/migrations/transfer.js +112 -123
- package/dist/utils/loadConfigs.d.ts +1 -0
- package/dist/utils/loadConfigs.js +19 -0
- package/dist/utils/schemaStrings.js +27 -0
- package/dist/utilsController.d.ts +5 -1
- package/dist/utilsController.js +54 -2
- package/package.json +57 -55
- package/src/collections/methods.ts +29 -10
- package/src/functions/deployments.ts +190 -0
- package/src/functions/methods.ts +295 -235
- package/src/functions/templates/count-docs-in-collection/README.md +54 -0
- package/src/functions/templates/count-docs-in-collection/src/main.ts +159 -0
- package/src/functions/templates/count-docs-in-collection/src/request.ts +9 -0
- package/src/functions/templates/poetry/README.md +30 -0
- package/src/functions/templates/poetry/pyproject.toml +16 -0
- package/src/functions/templates/poetry/src/__init__.py +0 -0
- package/src/functions/templates/poetry/src/index.py +16 -0
- package/src/functions/templates/typescript-node/README.md +32 -0
- package/src/functions/templates/typescript-node/src/index.ts +23 -0
- package/src/interactiveCLI.ts +606 -47
- package/src/migrations/appwriteToX.ts +44 -1
- package/src/migrations/schemaStrings.ts +83 -2
- package/src/migrations/transfer.ts +280 -207
- package/src/setupController.ts +41 -41
- package/src/utils/loadConfigs.ts +24 -0
- package/src/utils/schemaStrings.ts +27 -0
- package/src/utilsController.ts +63 -3
- package/tsconfig.json +8 -1
package/src/functions/methods.ts
CHANGED
@@ -1,235 +1,295 @@
|
|
1
|
-
import {
|
2
|
-
AppwriteException,
|
3
|
-
Client,
|
4
|
-
Functions,
|
5
|
-
Query,
|
6
|
-
Runtime,
|
7
|
-
|
8
|
-
} from "node
|
9
|
-
import
|
10
|
-
import {
|
11
|
-
import
|
12
|
-
import
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
);
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
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
|
+
```
|