appwrite-utils-cli 0.0.286 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -96
- package/dist/collections/attributes.d.ts +4 -0
- package/dist/collections/attributes.js +224 -0
- package/dist/collections/indexes.d.ts +4 -0
- package/dist/collections/indexes.js +27 -0
- package/dist/collections/methods.d.ts +16 -0
- package/dist/collections/methods.js +216 -0
- package/dist/databases/methods.d.ts +6 -0
- package/dist/databases/methods.js +33 -0
- package/dist/interactiveCLI.d.ts +19 -0
- package/dist/interactiveCLI.js +555 -0
- package/dist/main.js +227 -62
- package/dist/migrations/afterImportActions.js +37 -40
- package/dist/migrations/appwriteToX.d.ts +26 -25
- package/dist/migrations/appwriteToX.js +42 -6
- package/dist/migrations/attributes.js +21 -20
- package/dist/migrations/backup.d.ts +93 -87
- package/dist/migrations/collections.d.ts +6 -0
- package/dist/migrations/collections.js +149 -20
- package/dist/migrations/converters.d.ts +2 -18
- package/dist/migrations/converters.js +13 -2
- package/dist/migrations/dataLoader.d.ts +276 -161
- package/dist/migrations/dataLoader.js +535 -292
- package/dist/migrations/databases.js +8 -2
- package/dist/migrations/helper.d.ts +3 -0
- package/dist/migrations/helper.js +21 -0
- package/dist/migrations/importController.d.ts +5 -2
- package/dist/migrations/importController.js +125 -88
- package/dist/migrations/importDataActions.d.ts +9 -1
- package/dist/migrations/importDataActions.js +15 -3
- package/dist/migrations/indexes.js +3 -2
- package/dist/migrations/logging.js +20 -8
- package/dist/migrations/migrationHelper.d.ts +9 -4
- package/dist/migrations/migrationHelper.js +6 -5
- package/dist/migrations/openapi.d.ts +1 -1
- package/dist/migrations/openapi.js +33 -18
- package/dist/migrations/queue.js +3 -2
- package/dist/migrations/relationships.d.ts +2 -2
- package/dist/migrations/schemaStrings.js +53 -41
- package/dist/migrations/setupDatabase.d.ts +2 -4
- package/dist/migrations/setupDatabase.js +24 -105
- package/dist/migrations/storage.d.ts +3 -1
- package/dist/migrations/storage.js +110 -16
- package/dist/migrations/transfer.d.ts +30 -0
- package/dist/migrations/transfer.js +337 -0
- package/dist/migrations/users.d.ts +2 -1
- package/dist/migrations/users.js +78 -43
- package/dist/schemas/authUser.d.ts +2 -2
- package/dist/storage/methods.d.ts +15 -0
- package/dist/storage/methods.js +207 -0
- package/dist/storage/schemas.d.ts +687 -0
- package/dist/storage/schemas.js +175 -0
- package/dist/utils/getClientFromConfig.d.ts +4 -0
- package/dist/utils/getClientFromConfig.js +16 -0
- package/dist/utils/helperFunctions.d.ts +11 -1
- package/dist/utils/helperFunctions.js +38 -0
- package/dist/utils/retryFailedPromises.d.ts +2 -0
- package/dist/utils/retryFailedPromises.js +21 -0
- package/dist/utils/schemaStrings.d.ts +13 -0
- package/dist/utils/schemaStrings.js +403 -0
- package/dist/utils/setupFiles.js +110 -61
- package/dist/utilsController.d.ts +40 -22
- package/dist/utilsController.js +164 -84
- package/package.json +13 -15
- package/src/collections/attributes.ts +483 -0
- package/src/collections/indexes.ts +53 -0
- package/src/collections/methods.ts +331 -0
- package/src/databases/methods.ts +47 -0
- package/src/init.ts +64 -64
- package/src/interactiveCLI.ts +767 -0
- package/src/main.ts +292 -83
- package/src/migrations/afterImportActions.ts +553 -490
- package/src/migrations/appwriteToX.ts +237 -174
- package/src/migrations/attributes.ts +483 -422
- package/src/migrations/backup.ts +205 -205
- package/src/migrations/collections.ts +545 -300
- package/src/migrations/converters.ts +161 -150
- package/src/migrations/dataLoader.ts +1615 -1304
- package/src/migrations/databases.ts +44 -25
- package/src/migrations/dbHelpers.ts +92 -92
- package/src/migrations/helper.ts +40 -0
- package/src/migrations/importController.ts +448 -384
- package/src/migrations/importDataActions.ts +315 -307
- package/src/migrations/indexes.ts +40 -37
- package/src/migrations/logging.ts +29 -16
- package/src/migrations/migrationHelper.ts +207 -201
- package/src/migrations/openapi.ts +83 -70
- package/src/migrations/queue.ts +118 -119
- package/src/migrations/relationships.ts +324 -324
- package/src/migrations/schemaStrings.ts +472 -460
- package/src/migrations/setupDatabase.ts +118 -219
- package/src/migrations/storage.ts +538 -358
- package/src/migrations/transfer.ts +608 -0
- package/src/migrations/users.ts +362 -285
- package/src/migrations/validationRules.ts +63 -63
- package/src/schemas/authUser.ts +23 -23
- package/src/setup.ts +8 -8
- package/src/storage/methods.ts +371 -0
- package/src/storage/schemas.ts +205 -0
- package/src/types.ts +9 -9
- package/src/utils/getClientFromConfig.ts +17 -0
- package/src/utils/helperFunctions.ts +181 -127
- package/src/utils/index.ts +2 -2
- package/src/utils/loadConfigs.ts +59 -59
- package/src/utils/retryFailedPromises.ts +27 -0
- package/src/utils/schemaStrings.ts +473 -0
- package/src/utils/setupFiles.ts +228 -182
- package/src/utilsController.ts +325 -194
- package/tsconfig.json +37 -37
@@ -0,0 +1,403 @@
|
|
1
|
+
import { toCamelCase, toPascalCase } from "../utils/index.js";
|
2
|
+
import { Databases } from "node-appwrite";
|
3
|
+
import { z } from "zod";
|
4
|
+
import fs from "fs";
|
5
|
+
import path from "path";
|
6
|
+
import { dump } from "js-yaml";
|
7
|
+
export class SchemaGenerator {
|
8
|
+
relationshipMap = new Map();
|
9
|
+
config;
|
10
|
+
appwriteFolderPath;
|
11
|
+
constructor(config, appwriteFolderPath) {
|
12
|
+
this.config = config;
|
13
|
+
this.appwriteFolderPath = appwriteFolderPath;
|
14
|
+
this.extractRelationships();
|
15
|
+
}
|
16
|
+
updateTsSchemas() {
|
17
|
+
const collections = this.config.collections;
|
18
|
+
delete this.config.collections;
|
19
|
+
const configPath = path.join(this.appwriteFolderPath, "appwriteConfig.ts");
|
20
|
+
const configContent = `import { type AppwriteConfig } from "appwrite-utils";
|
21
|
+
|
22
|
+
const appwriteConfig: AppwriteConfig = {
|
23
|
+
appwriteEndpoint: "${this.config.appwriteEndpoint}",
|
24
|
+
appwriteProject: "${this.config.appwriteProject}",
|
25
|
+
appwriteKey: "${this.config.appwriteKey}",
|
26
|
+
enableBackups: ${this.config.enableBackups},
|
27
|
+
backupInterval: ${this.config.backupInterval},
|
28
|
+
backupRetention: ${this.config.backupRetention},
|
29
|
+
enableBackupCleanup: ${this.config.enableBackupCleanup},
|
30
|
+
enableMockData: ${this.config.enableMockData},
|
31
|
+
documentBucketId: "${this.config.documentBucketId}",
|
32
|
+
usersCollectionName: "${this.config.usersCollectionName}",
|
33
|
+
databases: ${JSON.stringify(this.config.databases)},
|
34
|
+
buckets: ${JSON.stringify(this.config.buckets)},
|
35
|
+
};
|
36
|
+
|
37
|
+
export default appwriteConfig;
|
38
|
+
`;
|
39
|
+
fs.writeFileSync(configPath, configContent, { encoding: "utf-8" });
|
40
|
+
const collectionsFolderPath = path.join(this.appwriteFolderPath, "collections");
|
41
|
+
if (!fs.existsSync(collectionsFolderPath)) {
|
42
|
+
fs.mkdirSync(collectionsFolderPath, { recursive: true });
|
43
|
+
}
|
44
|
+
collections?.forEach((collection) => {
|
45
|
+
const { databaseId, ...collectionWithoutDbId } = collection; // Destructure to exclude databaseId
|
46
|
+
const collectionFilePath = path.join(collectionsFolderPath, `${collection.name}.ts`);
|
47
|
+
const collectionContent = `import { type CollectionCreate } from "appwrite-utils";
|
48
|
+
|
49
|
+
const ${collection.name}Config: Partial<CollectionCreate> = {
|
50
|
+
name: "${collection.name}",
|
51
|
+
$id: "${collection.$id}",
|
52
|
+
enabled: ${collection.enabled},
|
53
|
+
documentSecurity: ${collection.documentSecurity},
|
54
|
+
$permissions: [
|
55
|
+
${collection.$permissions
|
56
|
+
.map((permission) => `{ permission: "${permission.permission}", target: "${permission.target}" }`)
|
57
|
+
.join(",\n ")}
|
58
|
+
],
|
59
|
+
attributes: [
|
60
|
+
${collection.attributes
|
61
|
+
.map((attr) => {
|
62
|
+
return `{ ${Object.entries(attr)
|
63
|
+
.map(([key, value]) => {
|
64
|
+
// Check the type of the value and format it accordingly
|
65
|
+
if (typeof value === "string") {
|
66
|
+
// If the value is a string, wrap it in quotes
|
67
|
+
return `${key}: "${value.replace(/"/g, '\\"')}"`; // Escape existing quotes in the string
|
68
|
+
}
|
69
|
+
else if (Array.isArray(value)) {
|
70
|
+
// If the value is an array, join it with commas
|
71
|
+
if (value.length > 0) {
|
72
|
+
return `${key}: [${value
|
73
|
+
.map((item) => `"${item}"`)
|
74
|
+
.join(", ")}]`;
|
75
|
+
}
|
76
|
+
else {
|
77
|
+
return `${key}: []`;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
else {
|
81
|
+
// If the value is not a string (e.g., boolean or number), output it directly
|
82
|
+
return `${key}: ${value}`;
|
83
|
+
}
|
84
|
+
})
|
85
|
+
.join(", ")} }`;
|
86
|
+
})
|
87
|
+
.join(",\n ")}
|
88
|
+
],
|
89
|
+
indexes: [
|
90
|
+
${(collection.indexes?.map((index) => {
|
91
|
+
// Map each attribute to ensure it is properly quoted
|
92
|
+
const formattedAttributes = index.attributes.map((attr) => `"${attr}"`).join(", ") ?? "";
|
93
|
+
return `{ key: "${index.key}", type: "${index.type}", attributes: [${formattedAttributes}], orders: [${index.orders
|
94
|
+
?.filter((order) => order !== null)
|
95
|
+
.map((order) => `"${order}"`)
|
96
|
+
.join(", ") ?? ""}] }`;
|
97
|
+
}) ?? []).join(",\n ")}
|
98
|
+
]
|
99
|
+
};
|
100
|
+
|
101
|
+
export default ${collection.name}Config;
|
102
|
+
`;
|
103
|
+
fs.writeFileSync(collectionFilePath, collectionContent, {
|
104
|
+
encoding: "utf-8",
|
105
|
+
});
|
106
|
+
console.log(`Collection schema written to ${collectionFilePath}`);
|
107
|
+
});
|
108
|
+
}
|
109
|
+
extractRelationships() {
|
110
|
+
if (!this.config.collections) {
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
this.config.collections.forEach((collection) => {
|
114
|
+
collection.attributes.forEach((attr) => {
|
115
|
+
if (attr.type === "relationship" && attr.twoWay && attr.twoWayKey) {
|
116
|
+
const relationshipAttr = attr;
|
117
|
+
let isArrayParent = false;
|
118
|
+
let isArrayChild = false;
|
119
|
+
switch (relationshipAttr.relationType) {
|
120
|
+
case "oneToMany":
|
121
|
+
isArrayParent = true;
|
122
|
+
isArrayChild = false;
|
123
|
+
break;
|
124
|
+
case "manyToMany":
|
125
|
+
isArrayParent = true;
|
126
|
+
isArrayChild = true;
|
127
|
+
break;
|
128
|
+
case "oneToOne":
|
129
|
+
isArrayParent = false;
|
130
|
+
isArrayChild = false;
|
131
|
+
break;
|
132
|
+
case "manyToOne":
|
133
|
+
isArrayParent = false;
|
134
|
+
isArrayChild = true;
|
135
|
+
break;
|
136
|
+
default:
|
137
|
+
break;
|
138
|
+
}
|
139
|
+
this.addRelationship(collection.name, relationshipAttr.relatedCollection, attr.key, relationshipAttr.twoWayKey, isArrayParent, isArrayChild);
|
140
|
+
console.log(`Extracted relationship: ${attr.key}\n\t${collection.name} -> ${relationshipAttr.relatedCollection}, databaseId: ${collection.databaseId}`);
|
141
|
+
}
|
142
|
+
});
|
143
|
+
});
|
144
|
+
}
|
145
|
+
addRelationship(parentCollection, childCollection, parentKey, childKey, isArrayParent, isArrayChild) {
|
146
|
+
const relationshipsChild = this.relationshipMap.get(childCollection) || [];
|
147
|
+
const relationshipsParent = this.relationshipMap.get(parentCollection) || [];
|
148
|
+
relationshipsParent.push({
|
149
|
+
parentCollection,
|
150
|
+
childCollection,
|
151
|
+
parentKey,
|
152
|
+
childKey,
|
153
|
+
isArray: isArrayParent,
|
154
|
+
isChild: false,
|
155
|
+
});
|
156
|
+
relationshipsChild.push({
|
157
|
+
parentCollection,
|
158
|
+
childCollection,
|
159
|
+
parentKey,
|
160
|
+
childKey,
|
161
|
+
isArray: isArrayChild,
|
162
|
+
isChild: true,
|
163
|
+
});
|
164
|
+
this.relationshipMap.set(childCollection, relationshipsChild);
|
165
|
+
this.relationshipMap.set(parentCollection, relationshipsParent);
|
166
|
+
}
|
167
|
+
generateSchemas() {
|
168
|
+
if (!this.config.collections) {
|
169
|
+
return;
|
170
|
+
}
|
171
|
+
this.config.collections.forEach((collection) => {
|
172
|
+
const schemaString = this.createSchemaString(collection.name, collection.attributes);
|
173
|
+
const camelCaseName = toCamelCase(collection.name);
|
174
|
+
const schemaPath = path.join(this.appwriteFolderPath, "schemas", `${camelCaseName}.ts`);
|
175
|
+
fs.writeFileSync(schemaPath, schemaString, { encoding: "utf-8" });
|
176
|
+
console.log(`Schema written to ${schemaPath}`);
|
177
|
+
});
|
178
|
+
}
|
179
|
+
createSchemaString = (name, attributes) => {
|
180
|
+
const pascalName = toPascalCase(name);
|
181
|
+
let imports = `import { z } from "zod";\n`;
|
182
|
+
const hasDescription = attributes.some((attr) => attr.description);
|
183
|
+
if (hasDescription) {
|
184
|
+
imports += `import { extendZodWithOpenApi } from "@asteasolutions/zod-to-openapi";\n`;
|
185
|
+
imports += `extendZodWithOpenApi(z);\n`;
|
186
|
+
}
|
187
|
+
// Use the relationshipMap to find related collections
|
188
|
+
const relationshipDetails = this.relationshipMap.get(name) || [];
|
189
|
+
const relatedCollections = relationshipDetails
|
190
|
+
.filter((detail, index, self) => {
|
191
|
+
const uniqueKey = `${detail.parentCollection}-${detail.childCollection}-${detail.parentKey}-${detail.childKey}`;
|
192
|
+
return (index ===
|
193
|
+
self.findIndex((obj) => `${obj.parentCollection}-${obj.childCollection}-${obj.parentKey}-${obj.childKey}` ===
|
194
|
+
uniqueKey));
|
195
|
+
})
|
196
|
+
.map((detail) => {
|
197
|
+
const relatedCollectionName = detail.isChild
|
198
|
+
? detail.parentCollection
|
199
|
+
: detail.childCollection;
|
200
|
+
const key = detail.isChild ? detail.childKey : detail.parentKey;
|
201
|
+
const isArray = detail.isArray ? "array" : "";
|
202
|
+
return [relatedCollectionName, key, isArray];
|
203
|
+
});
|
204
|
+
let relatedTypes = "";
|
205
|
+
let relatedTypesLazy = "";
|
206
|
+
let curNum = 0;
|
207
|
+
let maxNum = relatedCollections.length;
|
208
|
+
relatedCollections.forEach((relatedCollection) => {
|
209
|
+
console.log(relatedCollection);
|
210
|
+
let relatedPascalName = toPascalCase(relatedCollection[0]);
|
211
|
+
let relatedCamelName = toCamelCase(relatedCollection[0]);
|
212
|
+
curNum++;
|
213
|
+
let endNameTypes = relatedPascalName;
|
214
|
+
let endNameLazy = `${relatedPascalName}Schema`;
|
215
|
+
if (relatedCollection[2] === "array") {
|
216
|
+
endNameTypes += "[]";
|
217
|
+
endNameLazy += ".array().default([])";
|
218
|
+
}
|
219
|
+
else if (!(relatedCollection[2] === "array")) {
|
220
|
+
endNameTypes += " | null";
|
221
|
+
endNameLazy += ".nullish()";
|
222
|
+
}
|
223
|
+
imports += `import { ${relatedPascalName}Schema, type ${relatedPascalName} } from "./${relatedCamelName}";\n`;
|
224
|
+
relatedTypes += `${relatedCollection[1]}?: ${endNameTypes};\n`;
|
225
|
+
if (relatedTypes.length > 0 && curNum !== maxNum) {
|
226
|
+
relatedTypes += " ";
|
227
|
+
}
|
228
|
+
relatedTypesLazy += `${relatedCollection[1]}: z.lazy(() => ${endNameLazy}),\n`;
|
229
|
+
if (relatedTypesLazy.length > 0 && curNum !== maxNum) {
|
230
|
+
relatedTypesLazy += " ";
|
231
|
+
}
|
232
|
+
});
|
233
|
+
let schemaString = `${imports}\n\n`;
|
234
|
+
schemaString += `export const ${pascalName}SchemaBase = z.object({\n`;
|
235
|
+
schemaString += ` $id: z.string().optional(),\n`;
|
236
|
+
schemaString += ` $createdAt: z.date().or(z.string()).optional(),\n`;
|
237
|
+
schemaString += ` $updatedAt: z.date().or(z.string()).optional(),\n`;
|
238
|
+
for (const attribute of attributes) {
|
239
|
+
if (attribute.type === "relationship") {
|
240
|
+
continue;
|
241
|
+
}
|
242
|
+
schemaString += ` ${attribute.key}: ${this.typeToZod(attribute)},\n`;
|
243
|
+
}
|
244
|
+
schemaString += `});\n\n`;
|
245
|
+
schemaString += `export type ${pascalName}Base = z.infer<typeof ${pascalName}SchemaBase>`;
|
246
|
+
if (relatedTypes.length > 0) {
|
247
|
+
schemaString += ` & {\n ${relatedTypes}};\n\n`;
|
248
|
+
}
|
249
|
+
else {
|
250
|
+
schemaString += `;\n\n`;
|
251
|
+
}
|
252
|
+
schemaString += `export const ${pascalName}Schema: z.ZodType<${pascalName}Base> = ${pascalName}SchemaBase`;
|
253
|
+
if (relatedTypes.length > 0) {
|
254
|
+
schemaString += `.extend({\n ${relatedTypesLazy}});\n\n`;
|
255
|
+
}
|
256
|
+
else {
|
257
|
+
schemaString += `;\n`;
|
258
|
+
}
|
259
|
+
schemaString += `export type ${pascalName} = z.infer<typeof ${pascalName}Schema>;\n\n`;
|
260
|
+
return schemaString;
|
261
|
+
};
|
262
|
+
typeToZod = (attribute) => {
|
263
|
+
let baseSchemaCode = "";
|
264
|
+
const finalAttribute = (attribute.type === "string" &&
|
265
|
+
attribute.format &&
|
266
|
+
attribute.format === "enum" &&
|
267
|
+
attribute.type === "string"
|
268
|
+
? { ...attribute, type: attribute.format }
|
269
|
+
: attribute);
|
270
|
+
switch (finalAttribute.type) {
|
271
|
+
case "string":
|
272
|
+
baseSchemaCode = "z.string()";
|
273
|
+
if (finalAttribute.size) {
|
274
|
+
baseSchemaCode += `.max(${finalAttribute.size}, "Maximum length of ${finalAttribute.size} characters exceeded")`;
|
275
|
+
}
|
276
|
+
if (finalAttribute.xdefault !== undefined) {
|
277
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
278
|
+
}
|
279
|
+
if (!attribute.required && !attribute.array) {
|
280
|
+
baseSchemaCode += ".nullish()";
|
281
|
+
}
|
282
|
+
break;
|
283
|
+
case "integer":
|
284
|
+
baseSchemaCode = "z.number().int()";
|
285
|
+
if (finalAttribute.min !== undefined) {
|
286
|
+
if (BigInt(finalAttribute.min) === BigInt(-9223372036854776000)) {
|
287
|
+
delete finalAttribute.min;
|
288
|
+
}
|
289
|
+
else {
|
290
|
+
baseSchemaCode += `.min(${finalAttribute.min}, "Minimum value of ${finalAttribute.min} not met")`;
|
291
|
+
}
|
292
|
+
}
|
293
|
+
if (finalAttribute.max !== undefined) {
|
294
|
+
if (BigInt(finalAttribute.max) === BigInt(9223372036854776000)) {
|
295
|
+
delete finalAttribute.max;
|
296
|
+
}
|
297
|
+
else {
|
298
|
+
baseSchemaCode += `.max(${finalAttribute.max}, "Maximum value of ${finalAttribute.max} exceeded")`;
|
299
|
+
}
|
300
|
+
}
|
301
|
+
if (finalAttribute.xdefault !== undefined) {
|
302
|
+
baseSchemaCode += `.default(${finalAttribute.xdefault})`;
|
303
|
+
}
|
304
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
305
|
+
baseSchemaCode += ".nullish()";
|
306
|
+
}
|
307
|
+
break;
|
308
|
+
case "float":
|
309
|
+
baseSchemaCode = "z.number()";
|
310
|
+
if (finalAttribute.min !== undefined) {
|
311
|
+
baseSchemaCode += `.min(${finalAttribute.min}, "Minimum value of ${finalAttribute.min} not met")`;
|
312
|
+
}
|
313
|
+
if (finalAttribute.max !== undefined) {
|
314
|
+
baseSchemaCode += `.max(${finalAttribute.max}, "Maximum value of ${finalAttribute.max} exceeded")`;
|
315
|
+
}
|
316
|
+
if (finalAttribute.xdefault !== undefined) {
|
317
|
+
baseSchemaCode += `.default(${finalAttribute.xdefault})`;
|
318
|
+
}
|
319
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
320
|
+
baseSchemaCode += ".nullish()";
|
321
|
+
}
|
322
|
+
break;
|
323
|
+
case "boolean":
|
324
|
+
baseSchemaCode = "z.boolean()";
|
325
|
+
if (finalAttribute.xdefault !== undefined) {
|
326
|
+
baseSchemaCode += `.default(${finalAttribute.xdefault})`;
|
327
|
+
}
|
328
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
329
|
+
baseSchemaCode += ".nullish()";
|
330
|
+
}
|
331
|
+
break;
|
332
|
+
case "datetime":
|
333
|
+
baseSchemaCode = "z.date()";
|
334
|
+
if (finalAttribute.xdefault !== undefined) {
|
335
|
+
baseSchemaCode += `.default(new Date("${finalAttribute.xdefault}"))`;
|
336
|
+
}
|
337
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
338
|
+
baseSchemaCode += ".nullish()";
|
339
|
+
}
|
340
|
+
break;
|
341
|
+
case "email":
|
342
|
+
baseSchemaCode = "z.string().email()";
|
343
|
+
if (finalAttribute.xdefault !== undefined) {
|
344
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
345
|
+
}
|
346
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
347
|
+
baseSchemaCode += ".nullish()";
|
348
|
+
}
|
349
|
+
break;
|
350
|
+
case "ip":
|
351
|
+
baseSchemaCode = "z.string()"; // Add custom validation as needed
|
352
|
+
if (finalAttribute.xdefault !== undefined) {
|
353
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
354
|
+
}
|
355
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
356
|
+
baseSchemaCode += ".nullish()";
|
357
|
+
}
|
358
|
+
break;
|
359
|
+
case "url":
|
360
|
+
baseSchemaCode = "z.string().url()";
|
361
|
+
if (finalAttribute.xdefault !== undefined) {
|
362
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
363
|
+
}
|
364
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
365
|
+
baseSchemaCode += ".nullish()";
|
366
|
+
}
|
367
|
+
break;
|
368
|
+
case "enum":
|
369
|
+
baseSchemaCode = `z.enum([${finalAttribute.elements
|
370
|
+
.map((element) => `"${element}"`)
|
371
|
+
.join(", ")}])`;
|
372
|
+
if (finalAttribute.xdefault !== undefined) {
|
373
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
374
|
+
}
|
375
|
+
if (!attribute.required && !attribute.array) {
|
376
|
+
baseSchemaCode += ".nullish()";
|
377
|
+
}
|
378
|
+
break;
|
379
|
+
case "relationship":
|
380
|
+
break;
|
381
|
+
default:
|
382
|
+
baseSchemaCode = "z.any()";
|
383
|
+
}
|
384
|
+
// Handle arrays
|
385
|
+
if (attribute.array) {
|
386
|
+
baseSchemaCode = `z.array(${baseSchemaCode})`;
|
387
|
+
}
|
388
|
+
if (attribute.array && !attribute.required) {
|
389
|
+
baseSchemaCode += ".nullish()";
|
390
|
+
}
|
391
|
+
if (attribute.description) {
|
392
|
+
if (typeof attribute.description === "string") {
|
393
|
+
baseSchemaCode += `.openapi({ description: "${attribute.description}" })`;
|
394
|
+
}
|
395
|
+
else {
|
396
|
+
baseSchemaCode += `.openapi(${Object.entries(attribute.description)
|
397
|
+
.map(([key, value]) => `"${key}": ${value}`)
|
398
|
+
.join(", ")})`;
|
399
|
+
}
|
400
|
+
}
|
401
|
+
return baseSchemaCode;
|
402
|
+
};
|
403
|
+
}
|
package/dist/utils/setupFiles.js
CHANGED
@@ -1,51 +1,98 @@
|
|
1
1
|
import { mkdirSync, writeFileSync, existsSync } from "node:fs";
|
2
2
|
import path from "node:path";
|
3
3
|
import { findAppwriteConfig } from "./loadConfigs.js";
|
4
|
+
import { ID } from "node-appwrite";
|
5
|
+
import { ulid } from "ulidx";
|
4
6
|
// Example base configuration using types from appwrite-utils
|
5
7
|
const baseConfig = {
|
6
8
|
appwriteEndpoint: "https://cloud.appwrite.io/v1",
|
7
9
|
appwriteProject: "YOUR_PROJECT_ID",
|
8
10
|
appwriteKey: "YOUR_API_KEY",
|
9
|
-
enableDevDatabase: true,
|
10
11
|
enableBackups: true,
|
11
12
|
backupInterval: 3600,
|
12
13
|
backupRetention: 30,
|
13
14
|
enableBackupCleanup: true,
|
14
15
|
enableMockData: false,
|
15
|
-
enableWipeOtherDatabases: true,
|
16
16
|
documentBucketId: "documents",
|
17
17
|
usersCollectionName: "Members",
|
18
18
|
databases: [
|
19
|
-
{
|
20
|
-
|
21
|
-
|
19
|
+
{
|
20
|
+
$id: "main",
|
21
|
+
name: "Main",
|
22
|
+
bucket: {
|
23
|
+
$id: "main_bucket",
|
24
|
+
name: "Main Bucket",
|
25
|
+
enabled: true,
|
26
|
+
maximumFileSize: 30000000,
|
27
|
+
allowedFileExtensions: [],
|
28
|
+
encryption: true,
|
29
|
+
antivirus: true,
|
30
|
+
},
|
31
|
+
},
|
32
|
+
{
|
33
|
+
$id: "staging",
|
34
|
+
name: "Staging",
|
35
|
+
bucket: {
|
36
|
+
$id: "staging_bucket",
|
37
|
+
name: "Staging Bucket",
|
38
|
+
enabled: true,
|
39
|
+
maximumFileSize: 30000000,
|
40
|
+
allowedFileExtensions: [],
|
41
|
+
encryption: true,
|
42
|
+
antivirus: true,
|
43
|
+
},
|
44
|
+
},
|
45
|
+
{
|
46
|
+
$id: "dev",
|
47
|
+
name: "Development",
|
48
|
+
bucket: {
|
49
|
+
$id: "dev_bucket",
|
50
|
+
name: "Development Bucket",
|
51
|
+
enabled: true,
|
52
|
+
maximumFileSize: 30000000,
|
53
|
+
allowedFileExtensions: [],
|
54
|
+
encryption: true,
|
55
|
+
antivirus: true,
|
56
|
+
},
|
57
|
+
},
|
58
|
+
],
|
59
|
+
buckets: [
|
60
|
+
{
|
61
|
+
$id: "global_bucket",
|
62
|
+
name: "Global Bucket",
|
63
|
+
enabled: true,
|
64
|
+
maximumFileSize: 30000000,
|
65
|
+
allowedFileExtensions: [],
|
66
|
+
encryption: true,
|
67
|
+
antivirus: true,
|
68
|
+
},
|
22
69
|
],
|
23
70
|
};
|
24
71
|
const collectionsConfig = [
|
25
72
|
{
|
26
73
|
name: "ExampleCollection",
|
27
|
-
content: `import { CollectionCreate } from "appwrite-utils";
|
28
|
-
|
29
|
-
const ExampleCollection: Partial<CollectionCreate> = {
|
30
|
-
name: 'ExampleCollection',
|
31
|
-
$permissions: [
|
32
|
-
{ permission: 'read', target: 'any' },
|
33
|
-
{ permission: 'create', target: 'users' },
|
34
|
-
{ permission: 'update', target: 'users' },
|
35
|
-
{ permission: 'delete', target: 'users' }
|
36
|
-
],
|
37
|
-
attributes: [
|
38
|
-
{ key: 'alterEgoName', type: 'string', size: 255, required: false },
|
39
|
-
// Add more attributes here
|
40
|
-
],
|
41
|
-
indexes: [
|
42
|
-
{ key: 'alterEgoName_search', type: 'fulltext', attributes: ['alterEgoName'] }
|
43
|
-
],
|
44
|
-
importDefs: [
|
45
|
-
// Define import definitions here
|
46
|
-
]
|
47
|
-
};
|
48
|
-
|
74
|
+
content: `import { CollectionCreate } from "appwrite-utils";
|
75
|
+
|
76
|
+
const ExampleCollection: Partial<CollectionCreate> = {
|
77
|
+
name: 'ExampleCollection',
|
78
|
+
$permissions: [
|
79
|
+
{ permission: 'read', target: 'any' },
|
80
|
+
{ permission: 'create', target: 'users' },
|
81
|
+
{ permission: 'update', target: 'users' },
|
82
|
+
{ permission: 'delete', target: 'users' }
|
83
|
+
],
|
84
|
+
attributes: [
|
85
|
+
{ key: 'alterEgoName', type: 'string', size: 255, required: false },
|
86
|
+
// Add more attributes here
|
87
|
+
],
|
88
|
+
indexes: [
|
89
|
+
{ key: 'alterEgoName_search', type: 'fulltext', attributes: ['alterEgoName'] }
|
90
|
+
],
|
91
|
+
importDefs: [
|
92
|
+
// Define import definitions here
|
93
|
+
]
|
94
|
+
};
|
95
|
+
|
49
96
|
export default ExampleCollection;`,
|
50
97
|
},
|
51
98
|
// Add more collections here
|
@@ -53,36 +100,39 @@ export default ExampleCollection;`,
|
|
53
100
|
// Define our YAML files
|
54
101
|
// Define our YAML files
|
55
102
|
const configFileExample = `d`;
|
56
|
-
export const customDefinitionsFile = `import type { ConverterFunctions, ValidationRules, AfterImportActions } from "appwrite-utils";
|
57
|
-
|
58
|
-
export const customConverterFunctions: ConverterFunctions = {
|
59
|
-
// Add your custom converter functions here
|
60
|
-
}
|
61
|
-
export const customValidationRules: ValidationRules = {
|
62
|
-
// Add your custom validation rules here
|
63
|
-
}
|
64
|
-
export const customAfterImportActions: AfterImportActions = {
|
65
|
-
// Add your custom after import actions here
|
103
|
+
export const customDefinitionsFile = `import type { ConverterFunctions, ValidationRules, AfterImportActions } from "appwrite-utils";
|
104
|
+
|
105
|
+
export const customConverterFunctions: ConverterFunctions = {
|
106
|
+
// Add your custom converter functions here
|
107
|
+
}
|
108
|
+
export const customValidationRules: ValidationRules = {
|
109
|
+
// Add your custom validation rules here
|
110
|
+
}
|
111
|
+
export const customAfterImportActions: AfterImportActions = {
|
112
|
+
// Add your custom after import actions here
|
66
113
|
}`;
|
67
114
|
export const createEmptyCollection = (collectionName) => {
|
68
|
-
const emptyCollection = `import type { CollectionCreate } from "appwrite-utils";
|
69
|
-
|
70
|
-
const ${collectionName}: Partial<CollectionCreate> = {
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
{ permission: '
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
],
|
81
|
-
|
82
|
-
// Add more
|
83
|
-
],
|
84
|
-
|
85
|
-
|
115
|
+
const emptyCollection = `import type { CollectionCreate } from "appwrite-utils";
|
116
|
+
|
117
|
+
const ${collectionName}: Partial<CollectionCreate> = {
|
118
|
+
$id: '${ulid()}',
|
119
|
+
documentSecurity: false,
|
120
|
+
enabled: true,
|
121
|
+
name: '${collectionName}',
|
122
|
+
$permissions: [
|
123
|
+
{ permission: 'read', target: 'any' },
|
124
|
+
{ permission: 'create', target: 'users' },
|
125
|
+
{ permission: 'update', target: 'users' },
|
126
|
+
{ permission: 'delete', target: 'users' }
|
127
|
+
],
|
128
|
+
attributes: [
|
129
|
+
// Add more attributes here
|
130
|
+
],
|
131
|
+
indexes: [
|
132
|
+
// Add more indexes here
|
133
|
+
],
|
134
|
+
};
|
135
|
+
|
86
136
|
export default ${collectionName};`;
|
87
137
|
const appwriteConfigPath = findAppwriteConfig(process.cwd());
|
88
138
|
if (!appwriteConfigPath) {
|
@@ -121,11 +171,11 @@ export const setupDirsFiles = async (example = false) => {
|
|
121
171
|
writeFileSync(appwriteConfigFile, configFileExample);
|
122
172
|
}
|
123
173
|
else {
|
124
|
-
const baseConfigContent = `import { type AppwriteConfig } from "appwrite-utils";
|
125
|
-
|
126
|
-
const appwriteConfig: AppwriteConfig = ${JSON.stringify(baseConfig, null, 2)};
|
127
|
-
|
128
|
-
export default appwriteConfig;
|
174
|
+
const baseConfigContent = `import { type AppwriteConfig } from "appwrite-utils";
|
175
|
+
|
176
|
+
const appwriteConfig: AppwriteConfig = ${JSON.stringify(baseConfig, null, 2)};
|
177
|
+
|
178
|
+
export default appwriteConfig;
|
129
179
|
`;
|
130
180
|
writeFileSync(appwriteConfigFile, baseConfigContent);
|
131
181
|
}
|
@@ -144,6 +194,5 @@ export default appwriteConfig;
|
|
144
194
|
if (!existsSync(appwriteHiddenFolder)) {
|
145
195
|
mkdirSync(appwriteHiddenFolder, { recursive: true });
|
146
196
|
}
|
147
|
-
const schemaFilePath = path.join(appwriteHiddenFolder, "appwriteUtilsConfigSchema.json");
|
148
197
|
console.log("Created config and setup files/directories successfully.");
|
149
198
|
};
|