appwrite-utils-cli 0.0.4 → 0.0.6

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 CHANGED
@@ -77,4 +77,9 @@ This setup ensures that developers have robust tools at their fingertips to mana
77
77
 
78
78
  - Syncing configuration
79
79
  - Better file format for config (potentially)
80
- - Separation of collections and import configuration from main config
80
+ - Separation of collections and import configuration from main config
81
+
82
+ ### Changelog
83
+
84
+ - 0.0.6: Added `setTargetFieldFromOtherCollectionDocumentsByMatchingField` for the below, but setting a different field than the field you matched. The names are long, but at least you know what's going on lmao.
85
+ - 0.0.5: Added `setFieldFromOtherCollectionDocuments` to set an array of ID's for instance from another collection as a `postImportAction`
@@ -7,6 +7,12 @@ export declare const afterImportActions: {
7
7
  updateCreatedDocument: (config: AppwriteConfig, dbId: string, collId: string, docId: string, data: any) => Promise<void>;
8
8
  checkAndUpdateFieldInDocument: (config: AppwriteConfig, dbId: string, collId: string, docId: string, fieldName: string, oldFieldValue: any, newFieldValue: any) => Promise<void>;
9
9
  setFieldFromOtherCollectionDocument: (config: AppwriteConfig, dbId: string, collIdOrName: string, docId: string, fieldName: string, otherCollIdOrName: string, otherDocId: string, otherFieldName: string) => Promise<void>;
10
+ /**
11
+ * Updates a field in a document by setting it with document IDs from another collection
12
+ * based on a matching field value.
13
+ */
14
+ setFieldFromOtherCollectionDocuments: (config: AppwriteConfig, dbId: string, collIdOrName: string, docId: string, fieldName: string, otherCollIdOrName: string, matchingFieldName: string, matchingFieldValue: any, fieldToSet?: string) => Promise<void>;
15
+ setTargetFieldFromOtherCollectionDocumentsByMatchingField: (config: AppwriteConfig, dbId: string, collIdOrName: string, docId: string, fieldName: string, otherCollIdOrName: string, matchingFieldName: string, matchingFieldValue: any, targetField: string) => Promise<void>;
10
16
  createOrGetBucket: (config: AppwriteConfig, bucketName: string, bucketId?: string, permissions?: string[], fileSecurity?: boolean, enabled?: boolean, maxFileSize?: number, allowedExtensions?: string[], compression?: string, encryption?: boolean, antivirus?: boolean) => Promise<Models.Bucket | undefined>;
11
17
  createFileAndUpdateField: (config: AppwriteConfig, dbId: string, collId: string, docId: string, fieldName: string, bucketId: string, filePath: string, fileName: string) => Promise<void>;
12
18
  };
@@ -79,6 +79,121 @@ export const afterImportActions = {
79
79
  console.error("Error setting field from other collection document: ", error);
80
80
  }
81
81
  },
82
+ /**
83
+ * Updates a field in a document by setting it with document IDs from another collection
84
+ * based on a matching field value.
85
+ */
86
+ setFieldFromOtherCollectionDocuments: async (config, dbId, collIdOrName, docId, fieldName, otherCollIdOrName, matchingFieldName, matchingFieldValue, fieldToSet) => {
87
+ const db = getDatabaseFromConfig(config);
88
+ // Helper function to find a collection ID by name or return the ID if given
89
+ const findCollectionId = async (collectionIdentifier) => {
90
+ const collections = await db.listCollections(dbId, [
91
+ Query.equal("name", collectionIdentifier),
92
+ Query.limit(1),
93
+ ]);
94
+ return collections.total > 0
95
+ ? collections.collections[0].$id
96
+ : collectionIdentifier;
97
+ };
98
+ // Function to check if the target field is an array
99
+ const isTargetFieldArray = async (collectionId, fieldName) => {
100
+ const collection = await db.getCollection(dbId, collectionId);
101
+ const attribute = collection.attributes.find((attr) => attr.key === fieldName);
102
+ // @ts-ignore
103
+ return attribute?.array === true;
104
+ };
105
+ try {
106
+ const targetCollectionId = await findCollectionId(collIdOrName);
107
+ const otherCollectionId = await findCollectionId(otherCollIdOrName);
108
+ const targetFieldIsArray = await isTargetFieldArray(targetCollectionId, fieldName);
109
+ // Function to recursively fetch all matching documents from the other collection
110
+ const fetchAllMatchingDocuments = async (cursor) => {
111
+ const docLimit = 100;
112
+ const queries = targetFieldIsArray
113
+ ? // @ts-ignore
114
+ [Query.contains(matchingFieldName, [matchingFieldValue])]
115
+ : [Query.equal(matchingFieldName, matchingFieldValue)];
116
+ if (cursor) {
117
+ queries.push(Query.cursorAfter(cursor));
118
+ }
119
+ queries.push(Query.limit(docLimit));
120
+ const response = await db.listDocuments(dbId, otherCollectionId, queries);
121
+ const documents = response.documents;
122
+ if (documents.length === 0 || documents.length < docLimit) {
123
+ return documents;
124
+ }
125
+ const nextCursor = documents[documents.length - 1].$id;
126
+ const nextBatch = await fetchAllMatchingDocuments(nextCursor);
127
+ return documents.concat(nextBatch);
128
+ };
129
+ const matchingDocuments = await fetchAllMatchingDocuments();
130
+ const documentIds = matchingDocuments.map((doc) => doc.$id);
131
+ if (documentIds.length > 0) {
132
+ const updatePayload = targetFieldIsArray
133
+ ? { [fieldName]: documentIds }
134
+ : { [fieldName]: documentIds[0] };
135
+ await db.updateDocument(dbId, targetCollectionId, docId, updatePayload);
136
+ console.log(`Field ${fieldName} updated successfully in document ${docId} with ${documentIds.length} document IDs.`);
137
+ }
138
+ }
139
+ catch (error) {
140
+ console.error("Error setting field from other collection documents: ", error);
141
+ }
142
+ },
143
+ setTargetFieldFromOtherCollectionDocumentsByMatchingField: async (config, dbId, collIdOrName, docId, fieldName, otherCollIdOrName, matchingFieldName, matchingFieldValue, targetField) => {
144
+ const db = getDatabaseFromConfig(config);
145
+ const findCollectionId = async (collectionIdentifier) => {
146
+ const collections = await db.listCollections(dbId, [
147
+ Query.equal("name", collectionIdentifier),
148
+ Query.limit(1),
149
+ ]);
150
+ return collections.total > 0
151
+ ? collections.collections[0].$id
152
+ : collectionIdentifier;
153
+ };
154
+ const isTargetFieldArray = async (collectionId, fieldName) => {
155
+ const collection = await db.getCollection(dbId, collectionId);
156
+ const attribute = collection.attributes.find((attr) => attr.key === fieldName);
157
+ // @ts-ignore
158
+ return attribute?.array === true;
159
+ };
160
+ try {
161
+ const targetCollectionId = await findCollectionId(collIdOrName);
162
+ const otherCollectionId = await findCollectionId(otherCollIdOrName);
163
+ const targetFieldIsArray = await isTargetFieldArray(targetCollectionId, fieldName);
164
+ const fetchAllMatchingDocuments = async (cursor) => {
165
+ const docLimit = 100;
166
+ const queries = [
167
+ Query.equal(matchingFieldName, matchingFieldValue),
168
+ Query.limit(docLimit),
169
+ ];
170
+ if (cursor) {
171
+ queries.push(Query.cursorAfter(cursor));
172
+ }
173
+ const response = await db.listDocuments(dbId, otherCollectionId, queries);
174
+ const documents = response.documents;
175
+ if (documents.length === 0 || documents.length < docLimit) {
176
+ return documents;
177
+ }
178
+ const nextCursor = documents[documents.length - 1].$id;
179
+ const nextBatch = await fetchAllMatchingDocuments(nextCursor);
180
+ return documents.concat(nextBatch);
181
+ };
182
+ const matchingDocuments = await fetchAllMatchingDocuments();
183
+ // Map the values from the targetField instead of the document IDs
184
+ const targetFieldValues = matchingDocuments.map((doc) => doc[targetField]);
185
+ if (targetFieldValues.length > 0) {
186
+ const updatePayload = targetFieldIsArray
187
+ ? { [fieldName]: targetFieldValues }
188
+ : { [fieldName]: targetFieldValues[0] };
189
+ await db.updateDocument(dbId, targetCollectionId, docId, updatePayload);
190
+ console.log(`Field ${fieldName} updated successfully in document ${docId} with values from field ${targetField}.`);
191
+ }
192
+ }
193
+ catch (error) {
194
+ console.error("Error setting field from other collection documents: ", error);
195
+ }
196
+ },
82
197
  createOrGetBucket: async (config, bucketName, bucketId, permissions, fileSecurity, enabled, maxFileSize, allowedExtensions, compression, encryption, antivirus) => {
83
198
  try {
84
199
  const storage = getStorageFromConfig(config);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "appwrite-utils-cli",
3
3
  "description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
4
- "version": "0.0.4",
4
+ "version": "0.0.6",
5
5
  "main": "src/main.ts",
6
6
  "type": "module",
7
7
  "repository": {
@@ -128,6 +128,193 @@ export const afterImportActions = {
128
128
  );
129
129
  }
130
130
  },
131
+ /**
132
+ * Updates a field in a document by setting it with document IDs from another collection
133
+ * based on a matching field value.
134
+ */
135
+ setFieldFromOtherCollectionDocuments: async (
136
+ config: AppwriteConfig,
137
+ dbId: string,
138
+ collIdOrName: string,
139
+ docId: string,
140
+ fieldName: string,
141
+ otherCollIdOrName: string,
142
+ matchingFieldName: string,
143
+ matchingFieldValue: any,
144
+ fieldToSet?: string
145
+ ): Promise<void> => {
146
+ const db = getDatabaseFromConfig(config);
147
+
148
+ // Helper function to find a collection ID by name or return the ID if given
149
+ const findCollectionId = async (collectionIdentifier: string) => {
150
+ const collections = await db.listCollections(dbId, [
151
+ Query.equal("name", collectionIdentifier),
152
+ Query.limit(1),
153
+ ]);
154
+ return collections.total > 0
155
+ ? collections.collections[0].$id
156
+ : collectionIdentifier;
157
+ };
158
+
159
+ // Function to check if the target field is an array
160
+ const isTargetFieldArray = async (
161
+ collectionId: string,
162
+ fieldName: string
163
+ ) => {
164
+ const collection = await db.getCollection(dbId, collectionId);
165
+ const attribute = collection.attributes.find(
166
+ (attr: any) => attr.key === fieldName
167
+ );
168
+ // @ts-ignore
169
+ return attribute?.array === true;
170
+ };
171
+
172
+ try {
173
+ const targetCollectionId = await findCollectionId(collIdOrName);
174
+ const otherCollectionId = await findCollectionId(otherCollIdOrName);
175
+ const targetFieldIsArray = await isTargetFieldArray(
176
+ targetCollectionId,
177
+ fieldName
178
+ );
179
+
180
+ // Function to recursively fetch all matching documents from the other collection
181
+ const fetchAllMatchingDocuments = async (
182
+ cursor?: string
183
+ ): Promise<Models.Document[]> => {
184
+ const docLimit = 100;
185
+ const queries = targetFieldIsArray
186
+ ? // @ts-ignore
187
+ [Query.contains(matchingFieldName, [matchingFieldValue])]
188
+ : [Query.equal(matchingFieldName, matchingFieldValue)];
189
+ if (cursor) {
190
+ queries.push(Query.cursorAfter(cursor));
191
+ }
192
+ queries.push(Query.limit(docLimit));
193
+ const response = await db.listDocuments(
194
+ dbId,
195
+ otherCollectionId,
196
+ queries
197
+ );
198
+ const documents = response.documents;
199
+ if (documents.length === 0 || documents.length < docLimit) {
200
+ return documents;
201
+ }
202
+ const nextCursor = documents[documents.length - 1].$id;
203
+ const nextBatch = await fetchAllMatchingDocuments(nextCursor);
204
+ return documents.concat(nextBatch);
205
+ };
206
+
207
+ const matchingDocuments = await fetchAllMatchingDocuments();
208
+ const documentIds = matchingDocuments.map((doc) => doc.$id);
209
+
210
+ if (documentIds.length > 0) {
211
+ const updatePayload = targetFieldIsArray
212
+ ? { [fieldName]: documentIds }
213
+ : { [fieldName]: documentIds[0] };
214
+ await db.updateDocument(dbId, targetCollectionId, docId, updatePayload);
215
+
216
+ console.log(
217
+ `Field ${fieldName} updated successfully in document ${docId} with ${documentIds.length} document IDs.`
218
+ );
219
+ }
220
+ } catch (error) {
221
+ console.error(
222
+ "Error setting field from other collection documents: ",
223
+ error
224
+ );
225
+ }
226
+ },
227
+ setTargetFieldFromOtherCollectionDocumentsByMatchingField: async (
228
+ config: AppwriteConfig,
229
+ dbId: string,
230
+ collIdOrName: string,
231
+ docId: string,
232
+ fieldName: string,
233
+ otherCollIdOrName: string,
234
+ matchingFieldName: string,
235
+ matchingFieldValue: any,
236
+ targetField: string
237
+ ): Promise<void> => {
238
+ const db = getDatabaseFromConfig(config);
239
+
240
+ const findCollectionId = async (collectionIdentifier: string) => {
241
+ const collections = await db.listCollections(dbId, [
242
+ Query.equal("name", collectionIdentifier),
243
+ Query.limit(1),
244
+ ]);
245
+ return collections.total > 0
246
+ ? collections.collections[0].$id
247
+ : collectionIdentifier;
248
+ };
249
+
250
+ const isTargetFieldArray = async (
251
+ collectionId: string,
252
+ fieldName: string
253
+ ) => {
254
+ const collection = await db.getCollection(dbId, collectionId);
255
+ const attribute = collection.attributes.find(
256
+ (attr: any) => attr.key === fieldName
257
+ );
258
+ // @ts-ignore
259
+ return attribute?.array === true;
260
+ };
261
+
262
+ try {
263
+ const targetCollectionId = await findCollectionId(collIdOrName);
264
+ const otherCollectionId = await findCollectionId(otherCollIdOrName);
265
+ const targetFieldIsArray = await isTargetFieldArray(
266
+ targetCollectionId,
267
+ fieldName
268
+ );
269
+
270
+ const fetchAllMatchingDocuments = async (
271
+ cursor?: string
272
+ ): Promise<Models.Document[]> => {
273
+ const docLimit = 100;
274
+ const queries = [
275
+ Query.equal(matchingFieldName, matchingFieldValue),
276
+ Query.limit(docLimit),
277
+ ];
278
+ if (cursor) {
279
+ queries.push(Query.cursorAfter(cursor));
280
+ }
281
+ const response = await db.listDocuments(
282
+ dbId,
283
+ otherCollectionId,
284
+ queries
285
+ );
286
+ const documents = response.documents;
287
+ if (documents.length === 0 || documents.length < docLimit) {
288
+ return documents;
289
+ }
290
+ const nextCursor = documents[documents.length - 1].$id;
291
+ const nextBatch = await fetchAllMatchingDocuments(nextCursor);
292
+ return documents.concat(nextBatch);
293
+ };
294
+
295
+ const matchingDocuments = await fetchAllMatchingDocuments();
296
+ // Map the values from the targetField instead of the document IDs
297
+ const targetFieldValues = matchingDocuments.map(
298
+ (doc) => doc[targetField as keyof typeof doc]
299
+ );
300
+
301
+ if (targetFieldValues.length > 0) {
302
+ const updatePayload = targetFieldIsArray
303
+ ? { [fieldName]: targetFieldValues }
304
+ : { [fieldName]: targetFieldValues[0] };
305
+ await db.updateDocument(dbId, targetCollectionId, docId, updatePayload);
306
+
307
+ console.log(
308
+ `Field ${fieldName} updated successfully in document ${docId} with values from field ${targetField}.`
309
+ );
310
+ }
311
+ } catch (error) {
312
+ console.error(
313
+ "Error setting field from other collection documents: ",
314
+ error
315
+ );
316
+ }
317
+ },
131
318
  createOrGetBucket: async (
132
319
  config: AppwriteConfig,
133
320
  bucketName: string,
@@ -1,667 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "type": "object",
4
- "properties": {
5
- "appwriteEndpoint": {
6
- "type": "string",
7
- "default": "https://cloud.appwrite.io/v1"
8
- },
9
- "appwriteProject": {
10
- "type": "string"
11
- },
12
- "appwriteKey": {
13
- "type": "string"
14
- },
15
- "appwriteClient": {
16
- "type": [
17
- "object",
18
- "null"
19
- ],
20
- "default": null
21
- },
22
- "enableDevDatabase": {
23
- "type": "boolean",
24
- "default": true,
25
- "description": "Enable development database alongside production database"
26
- },
27
- "enableBackups": {
28
- "type": "boolean",
29
- "default": true,
30
- "description": "Enable backups"
31
- },
32
- "backupInterval": {
33
- "type": "number",
34
- "default": 3600,
35
- "description": "Backup interval in seconds"
36
- },
37
- "backupRetention": {
38
- "type": "number",
39
- "default": 30,
40
- "description": "Backup retention in days"
41
- },
42
- "enableBackupCleanup": {
43
- "type": "boolean",
44
- "default": true,
45
- "description": "Enable backup cleanup"
46
- },
47
- "enableLocalImport": {
48
- "type": "boolean",
49
- "default": false,
50
- "description": "Enable local import"
51
- },
52
- "enableMockData": {
53
- "type": "boolean",
54
- "default": false,
55
- "description": "Enable mock data"
56
- },
57
- "enableWipeOtherDatabases": {
58
- "type": "boolean",
59
- "default": true,
60
- "description": "Enable wiping other databases"
61
- },
62
- "databases": {
63
- "type": "array",
64
- "items": {
65
- "type": "object",
66
- "properties": {
67
- "$id": {
68
- "type": "string"
69
- },
70
- "name": {
71
- "type": "string"
72
- }
73
- },
74
- "required": [
75
- "$id",
76
- "name"
77
- ]
78
- },
79
- "default": [
80
- {
81
- "$id": "dev",
82
- "name": "Development"
83
- },
84
- {
85
- "$id": "main",
86
- "name": "Main"
87
- },
88
- {
89
- "$id": "migrations",
90
- "name": "Migrations"
91
- }
92
- ],
93
- "description": "Databases to create, $id is the id of the database"
94
- },
95
- "collections": {
96
- "type": "array",
97
- "items": {
98
- "type": "object",
99
- "properties": {
100
- "name": {
101
- "type": "string"
102
- },
103
- "attributes": {
104
- "type": "array",
105
- "items": {
106
- "oneOf": [
107
- {
108
- "type": "object",
109
- "properties": {
110
- "key": {
111
- "type": "string"
112
- },
113
- "type": {
114
- "type": "string",
115
- "enum": [
116
- "string"
117
- ]
118
- },
119
- "required": {
120
- "type": "boolean",
121
- "default": false
122
- },
123
- "array": {
124
- "type": "boolean",
125
- "default": false
126
- },
127
- "size": {
128
- "type": "number",
129
- "default": 50
130
- },
131
- "xdefault": {
132
- "type": [
133
- "string",
134
- "null"
135
- ]
136
- },
137
- "encrypted": {
138
- "type": "boolean",
139
- "default": false
140
- }
141
- },
142
- "required": [
143
- "key",
144
- "type"
145
- ]
146
- },
147
- {
148
- "type": "object",
149
- "properties": {
150
- "key": {
151
- "type": "string"
152
- },
153
- "type": {
154
- "type": "string",
155
- "enum": [
156
- "integer"
157
- ]
158
- },
159
- "required": {
160
- "type": "boolean",
161
- "default": false
162
- },
163
- "array": {
164
- "type": "boolean",
165
- "default": false
166
- },
167
- "min": {
168
- "type": "number"
169
- },
170
- "max": {
171
- "type": "number"
172
- },
173
- "xdefault": {
174
- "type": [
175
- "number",
176
- "null"
177
- ]
178
- }
179
- },
180
- "required": [
181
- "key",
182
- "type"
183
- ]
184
- },
185
- {
186
- "type": "object",
187
- "properties": {
188
- "key": {
189
- "type": "string"
190
- },
191
- "type": {
192
- "type": "string",
193
- "enum": [
194
- "float"
195
- ]
196
- },
197
- "required": {
198
- "type": "boolean",
199
- "default": false
200
- },
201
- "array": {
202
- "type": "boolean",
203
- "default": false
204
- },
205
- "min": {
206
- "type": "number"
207
- },
208
- "max": {
209
- "type": "number"
210
- },
211
- "xdefault": {
212
- "type": [
213
- "number",
214
- "null"
215
- ]
216
- }
217
- },
218
- "required": [
219
- "key",
220
- "type"
221
- ]
222
- },
223
- {
224
- "type": "object",
225
- "properties": {
226
- "key": {
227
- "type": "string"
228
- },
229
- "type": {
230
- "type": "string",
231
- "enum": [
232
- "boolean"
233
- ]
234
- },
235
- "required": {
236
- "type": "boolean",
237
- "default": false
238
- },
239
- "array": {
240
- "type": "boolean",
241
- "default": false
242
- },
243
- "xdefault": {
244
- "type": [
245
- "boolean",
246
- "null"
247
- ]
248
- }
249
- },
250
- "required": [
251
- "key",
252
- "type"
253
- ]
254
- },
255
- {
256
- "type": "object",
257
- "properties": {
258
- "key": {
259
- "type": "string"
260
- },
261
- "type": {
262
- "type": "string",
263
- "enum": [
264
- "datetime"
265
- ]
266
- },
267
- "required": {
268
- "type": "boolean",
269
- "default": false
270
- },
271
- "array": {
272
- "type": "boolean",
273
- "default": false
274
- },
275
- "xdefault": {
276
- "type": [
277
- "string",
278
- "null"
279
- ]
280
- }
281
- },
282
- "required": [
283
- "key",
284
- "type"
285
- ]
286
- },
287
- {
288
- "type": "object",
289
- "properties": {
290
- "key": {
291
- "type": "string"
292
- },
293
- "type": {
294
- "type": "string",
295
- "enum": [
296
- "email"
297
- ]
298
- },
299
- "required": {
300
- "type": "boolean",
301
- "default": false
302
- },
303
- "array": {
304
- "type": "boolean",
305
- "default": false
306
- },
307
- "xdefault": {
308
- "type": [
309
- "string",
310
- "null"
311
- ]
312
- }
313
- },
314
- "required": [
315
- "key",
316
- "type"
317
- ]
318
- },
319
- {
320
- "type": "object",
321
- "properties": {
322
- "key": {
323
- "type": "string"
324
- },
325
- "type": {
326
- "type": "string",
327
- "enum": [
328
- "ip"
329
- ]
330
- },
331
- "required": {
332
- "type": "boolean",
333
- "default": false
334
- },
335
- "array": {
336
- "type": "boolean",
337
- "default": false
338
- },
339
- "xdefault": {
340
- "type": [
341
- "string",
342
- "null"
343
- ]
344
- }
345
- },
346
- "required": [
347
- "key",
348
- "type"
349
- ]
350
- },
351
- {
352
- "type": "object",
353
- "properties": {
354
- "key": {
355
- "type": "string"
356
- },
357
- "type": {
358
- "type": "string",
359
- "enum": [
360
- "url"
361
- ]
362
- },
363
- "required": {
364
- "type": "boolean",
365
- "default": false
366
- },
367
- "array": {
368
- "type": "boolean",
369
- "default": false
370
- },
371
- "xdefault": {
372
- "type": [
373
- "string",
374
- "null"
375
- ]
376
- }
377
- },
378
- "required": [
379
- "key",
380
- "type"
381
- ]
382
- },
383
- {
384
- "type": "object",
385
- "properties": {
386
- "key": {
387
- "type": "string"
388
- },
389
- "type": {
390
- "type": "string",
391
- "enum": [
392
- "enum"
393
- ]
394
- },
395
- "required": {
396
- "type": "boolean",
397
- "default": false
398
- },
399
- "array": {
400
- "type": "boolean",
401
- "default": false
402
- },
403
- "values": {
404
- "type": "array",
405
- "items": {
406
- "type": "string"
407
- }
408
- },
409
- "xdefault": {
410
- "type": [
411
- "string",
412
- "null"
413
- ]
414
- }
415
- },
416
- "required": [
417
- "key",
418
- "type",
419
- "values"
420
- ]
421
- },
422
- {
423
- "type": "object",
424
- "properties": {
425
- "key": {
426
- "type": "string"
427
- },
428
- "type": {
429
- "type": "string",
430
- "enum": [
431
- "relationship"
432
- ]
433
- },
434
- "required": {
435
- "type": "boolean",
436
- "default": false
437
- },
438
- "array": {
439
- "type": "boolean",
440
- "default": false
441
- },
442
- "relatedCollection": {
443
- "type": "string"
444
- },
445
- "relationType": {
446
- "type": "string",
447
- "enum": [
448
- "oneToOne",
449
- "oneToMany",
450
- "manyToOne",
451
- "manyToMany"
452
- ]
453
- },
454
- "twoWay": {
455
- "type": "boolean",
456
- "default": false
457
- },
458
- "twoWayKey": {
459
- "type": "string",
460
- "nullable": true
461
- },
462
- "onDelete": {
463
- "type": "string",
464
- "enum": [
465
- "cascade",
466
- "setNull",
467
- "restrict"
468
- ],
469
- "default": "restrict"
470
- },
471
- "side": {
472
- "type": "string",
473
- "enum": [
474
- "parent",
475
- "child"
476
- ],
477
- "nullable": true
478
- },
479
- "importMapping": {
480
- "type": "object",
481
- "nullable": true,
482
- "properties": {
483
- "originalIdField": {
484
- "type": "string",
485
- "description": "The field in the import data representing the original ID to match"
486
- },
487
- "targetField": {
488
- "type": "string",
489
- "description": "The field in the target collection that matches the original ID. Optional, defaults to the same as originalIdField if not provided",
490
- "default": ""
491
- }
492
- },
493
- "required": [
494
- "originalIdField"
495
- ],
496
- "description": "Configuration for mapping and resolving relationships during data import"
497
- }
498
- },
499
- "required": [
500
- "key",
501
- "type",
502
- "relatedCollection",
503
- "relationType"
504
- ]
505
- }
506
- ]
507
- },
508
- "default": []
509
- },
510
- "indexes": {
511
- "type": "array",
512
- "items": {
513
- "type": "object",
514
- "properties": {
515
- "key": {
516
- "type": "string"
517
- },
518
- "type": {
519
- "type": "string",
520
- "enum": [
521
- "key",
522
- "unique",
523
- "fulltext"
524
- ],
525
- "default": "key"
526
- },
527
- "status": {
528
- "type": "string"
529
- },
530
- "error": {
531
- "type": "string",
532
- "nullable": true
533
- },
534
- "attributes": {
535
- "type": "array",
536
- "items": {
537
- "type": "string"
538
- }
539
- },
540
- "orders": {
541
- "type": "array",
542
- "items": {
543
- "type": "string"
544
- },
545
- "nullable": true
546
- }
547
- },
548
- "required": [
549
- "key",
550
- "type",
551
- "attributes"
552
- ]
553
- }
554
- }
555
- },
556
- "required": [
557
- "name",
558
- "attributes"
559
- ]
560
- },
561
- "default": [],
562
- "description": "Collections to create, $id is the id of the collection, it'll always check by collection name and $id for existing before creating another"
563
- },
564
- "importDefs": {
565
- "type": "array",
566
- "items": {
567
- "type": "object",
568
- "properties": {
569
- "filePath": {
570
- "type": "string",
571
- "description": "The file path of the data to import"
572
- },
573
- "basePath": {
574
- "type": "string",
575
- "description": "The base path of the import e.g. if you have JSON, and the array is in the RECORDS object, then this would be RECORDS"
576
- },
577
- "attributeMappings": {
578
- "type": "array",
579
- "items": {
580
- "type": "object",
581
- "properties": {
582
- "oldKey": {
583
- "type": "string",
584
- "description": "The key of the attribute in the old document"
585
- },
586
- "targetKey": {
587
- "type": "string",
588
- "description": "The key of the attribute in the new document"
589
- },
590
- "converters": {
591
- "type": "array",
592
- "items": {
593
- "type": "string"
594
- },
595
- "description": "The converters to use for the import",
596
- "default": []
597
- },
598
- "validationActions": {
599
- "type": "array",
600
- "items": {
601
- "type": "object",
602
- "properties": {
603
- "action": {
604
- "type": "string"
605
- },
606
- "params": {
607
- "type": "array",
608
- "items": {
609
- "type": "string",
610
- "pattern": "^\\{.*\\}$"
611
- }
612
- }
613
- },
614
- "required": [
615
- "action",
616
- "params"
617
- ]
618
- },
619
- "description": "The after import actions and parameter placeholders (they'll be replaced with the actual data) to use for the import",
620
- "default": []
621
- },
622
- "postImportActions": {
623
- "type": "array",
624
- "items": {
625
- "type": "object",
626
- "properties": {
627
- "action": {
628
- "type": "string"
629
- },
630
- "params": {
631
- "type": "array",
632
- "items": {
633
- "type": "string",
634
- "pattern": "^\\{.*\\}$"
635
- }
636
- }
637
- },
638
- "required": [
639
- "action",
640
- "params"
641
- ]
642
- },
643
- "description": "The after import actions and parameter placeholders (they'll be replaced with the actual data) to use for the import",
644
- "default": []
645
- }
646
- },
647
- "required": [
648
- "oldKey",
649
- "targetKey"
650
- ]
651
- }
652
- }
653
- },
654
- "required": [
655
- "filePath",
656
- "basePath",
657
- "attributeMappings"
658
- ]
659
- }
660
- }
661
- },
662
- "required": [
663
- "appwriteEndpoint",
664
- "appwriteProject",
665
- "appwriteKey"
666
- ]
667
- }
@@ -1,11 +0,0 @@
1
- import type { ConverterFunctions, ValidationRules, AfterImportActions } from "appwrite-utils";
2
-
3
- export const customConverterFunctions: ConverterFunctions = {
4
- // Add your custom converter functions here
5
- }
6
- export const customValidationRules: ValidationRules = {
7
- // Add your custom validation rules here
8
- }
9
- export const customAfterImportActions: AfterImportActions = {
10
- // Add your custom after import actions here
11
- }
@@ -1,76 +0,0 @@
1
- {
2
- "RECORDS": [
3
- {
4
- "id": "1",
5
- "name": "Charlie",
6
- "breed": "Golden Retriever",
7
- "age": 2,
8
- "ownerId": "123",
9
- "vetRecords": {
10
- "1": {
11
- "id": 1,
12
- "visitDate": "2022-01-01",
13
- "vetName": "Dr. Smith"
14
- },
15
- "2": {
16
- "id": 2,
17
- "visitDate": "2022-02-01",
18
- "vetName": "Dr. Johnson"
19
- },
20
- "3": {
21
- "id": 3,
22
- "visitDate": "2022-03-01",
23
- "vetName": "Dr. Williams"
24
- }
25
- }
26
- },
27
- {
28
- "id": "2",
29
- "name": "Buddy",
30
- "breed": "Labrador",
31
- "age": 3,
32
- "ownerId": "123",
33
- "vetRecords": {
34
- "4": {
35
- "id": 4,
36
- "visitDate": "2022-01-02",
37
- "vetName": "Dr. Smith"
38
- },
39
- "5": {
40
- "id": 5,
41
- "visitDate": "2022-02-02",
42
- "vetName": "Dr. Johnson"
43
- },
44
- "6": {
45
- "id": 6,
46
- "visitDate": "2022-03-02",
47
- "vetName": "Dr. Williams"
48
- }
49
- }
50
- },
51
- {
52
- "id": "3",
53
- "name": "Max",
54
- "breed": "Poodle",
55
- "age": 1,
56
- "ownerId": "456",
57
- "vetRecords": {
58
- "7": {
59
- "id": 7,
60
- "visitDate": "2022-01-03",
61
- "vetName": "Dr. Smith"
62
- },
63
- "8": {
64
- "id": 8,
65
- "visitDate": "2022-02-03",
66
- "vetName": "Dr. Johnson"
67
- },
68
- "9": {
69
- "id": 9,
70
- "visitDate": "2022-03-03",
71
- "vetName": "Dr. Williams"
72
- }
73
- }
74
- }
75
- ]
76
- }
@@ -1,16 +0,0 @@
1
- {
2
- "RECORDS": [
3
- {
4
- "id": 123,
5
- "name": "John Doe",
6
- "email": "john@doe.com",
7
- "photoUrl": "https://picsum.photos/200/300"
8
- },
9
- {
10
- "id": 456,
11
- "name": "Jane Doe",
12
- "email": "jane@doe.com",
13
- "photoUrl": "https://picsum.photos/200/300"
14
- }
15
- ]
16
- }
@@ -1,27 +0,0 @@
1
- import { z } from "zod";
2
- import { MembersSchema, type Members } from "./members";
3
-
4
-
5
- export const DogsSchemaBase = z.object({
6
- $id: z.string().optional(),
7
- $createdAt: z.date().or(z.string()).optional(),
8
- $updatedAt: z.date().or(z.string()).optional(),
9
- name: z.string().max(255, "Maximum length of 255 characters exceeded"),
10
- breed: z.string().max(255, "Maximum length of 255 characters exceeded").nullish(),
11
- age: z.number().int().min(0, "Minimum value of 0 not met").max(100, "Maximum value of 100 exceeded").nullish(),
12
- idOrig: z.string().max(20, "Maximum length of 20 characters exceeded").nullish(),
13
- ownerIdOrig: z.string().max(255, "Maximum length of 255 characters exceeded").nullish(),
14
- vetRecords: z.string().max(255, "Maximum length of 255 characters exceeded").nullish(),
15
- vetRecordIds: z.array(z.string().max(255, "Maximum length of 255 characters exceeded")).nullish(),
16
- });
17
-
18
- export type DogsBase = z.infer<typeof DogsSchemaBase> & {
19
- owner?: Members | null;
20
- };
21
-
22
- export const DogsSchema: z.ZodType<DogsBase> = DogsSchemaBase.extend({
23
- owner: z.lazy(() => MembersSchema.nullish()),
24
- });
25
-
26
- export type Dogs = z.infer<typeof DogsSchema>;
27
-
@@ -1,24 +0,0 @@
1
- import { z } from "zod";
2
- import { DogsSchema, type Dogs } from "./dogs";
3
-
4
-
5
- export const MembersSchemaBase = z.object({
6
- $id: z.string().optional(),
7
- $createdAt: z.date().or(z.string()).optional(),
8
- $updatedAt: z.date().or(z.string()).optional(),
9
- idOrig: z.string().max(255, "Maximum length of 255 characters exceeded").nullish(),
10
- dogIds: z.array(z.string().max(255, "Maximum length of 255 characters exceeded")).nullish(),
11
- profilePhoto: z.string().max(255, "Maximum length of 255 characters exceeded").nullish(),
12
- profilePhotoTest: z.string().max(255, "Maximum length of 255 characters exceeded").nullish(),
13
- });
14
-
15
- export type MembersBase = z.infer<typeof MembersSchemaBase> & {
16
- dogs?: Dogs[];
17
- };
18
-
19
- export const MembersSchema: z.ZodType<MembersBase> = MembersSchemaBase.extend({
20
- dogs: z.lazy(() => DogsSchema.array().default([])),
21
- });
22
-
23
- export type Members = z.infer<typeof MembersSchema>;
24
-