appwrite-utils-cli 0.0.269 → 0.0.270
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 +21 -1
- package/dist/main.js +18 -1
- package/dist/migrations/appwriteToX.d.ts +11 -0
- package/dist/migrations/appwriteToX.js +8 -1
- package/dist/migrations/backup.d.ts +48 -2
- package/dist/migrations/dataLoader.d.ts +106 -12
- package/dist/migrations/openapi.d.ts +4 -0
- package/dist/migrations/openapi.js +44 -0
- package/dist/migrations/relationships.d.ts +1 -0
- package/dist/migrations/schema.d.ts +358 -49
- package/dist/migrations/schema.js +67 -10
- package/dist/migrations/schemaStrings.js +47 -41
- package/dist/schemas/authUser.d.ts +3 -3
- package/dist/utilsController.d.ts +4 -1
- package/dist/utilsController.js +18 -6
- package/package.json +2 -1
- package/src/main.ts +18 -1
- package/src/migrations/appwriteToX.ts +12 -1
- package/src/migrations/openapi.ts +69 -0
- package/src/migrations/schema.ts +89 -10
- package/src/migrations/schemaStrings.ts +49 -42
- package/src/utilsController.ts +22 -6
@@ -29,6 +29,12 @@ const stringAttributeSchema = z.object({
|
|
29
29
|
.boolean()
|
30
30
|
.optional()
|
31
31
|
.describe("Whether the attribute is encrypted or not"),
|
32
|
+
format: z.string().nullish().describe("The format of the attribute"),
|
33
|
+
description: z
|
34
|
+
.string()
|
35
|
+
.or(z.record(z.string()))
|
36
|
+
.nullish()
|
37
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
32
38
|
});
|
33
39
|
const integerAttributeSchema = z.object({
|
34
40
|
key: z.string().describe("The key of the attribute"),
|
@@ -64,6 +70,11 @@ const integerAttributeSchema = z.object({
|
|
64
70
|
.int()
|
65
71
|
.nullish()
|
66
72
|
.describe("The default value of the attribute"),
|
73
|
+
description: z
|
74
|
+
.string()
|
75
|
+
.or(z.record(z.string()))
|
76
|
+
.nullish()
|
77
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
67
78
|
});
|
68
79
|
const floatAttributeSchema = z.object({
|
69
80
|
key: z.string().describe("The key of the attribute"),
|
@@ -87,6 +98,11 @@ const floatAttributeSchema = z.object({
|
|
87
98
|
min: z.number().optional().describe("The minimum value of the attribute"),
|
88
99
|
max: z.number().optional().describe("The maximum value of the attribute"),
|
89
100
|
xdefault: z.number().nullish().describe("The default value of the attribute"),
|
101
|
+
description: z
|
102
|
+
.string()
|
103
|
+
.or(z.record(z.string()))
|
104
|
+
.nullish()
|
105
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
90
106
|
});
|
91
107
|
const booleanAttributeSchema = z.object({
|
92
108
|
key: z.string().describe("The key of the attribute"),
|
@@ -111,6 +127,11 @@ const booleanAttributeSchema = z.object({
|
|
111
127
|
.boolean()
|
112
128
|
.nullish()
|
113
129
|
.describe("The default value of the attribute"),
|
130
|
+
description: z
|
131
|
+
.string()
|
132
|
+
.or(z.record(z.string()))
|
133
|
+
.nullish()
|
134
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
114
135
|
});
|
115
136
|
const datetimeAttributeSchema = z.object({
|
116
137
|
key: z.string().describe("The key of the attribute"),
|
@@ -132,6 +153,11 @@ const datetimeAttributeSchema = z.object({
|
|
132
153
|
.default(false)
|
133
154
|
.describe("Whether the attribute is an array or not"),
|
134
155
|
xdefault: z.string().nullish().describe("The default value of the attribute"),
|
156
|
+
description: z
|
157
|
+
.string()
|
158
|
+
.or(z.record(z.string()))
|
159
|
+
.nullish()
|
160
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
135
161
|
});
|
136
162
|
const emailAttributeSchema = z.object({
|
137
163
|
key: z.string().describe("The key of the attribute"),
|
@@ -153,6 +179,11 @@ const emailAttributeSchema = z.object({
|
|
153
179
|
.default(false)
|
154
180
|
.describe("Whether the attribute is an array or not"),
|
155
181
|
xdefault: z.string().nullish().describe("The default value of the attribute"),
|
182
|
+
description: z
|
183
|
+
.string()
|
184
|
+
.or(z.record(z.string()))
|
185
|
+
.nullish()
|
186
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
156
187
|
});
|
157
188
|
const ipAttributeSchema = z.object({
|
158
189
|
key: z.string().describe("The key of the attribute"),
|
@@ -171,6 +202,11 @@ const ipAttributeSchema = z.object({
|
|
171
202
|
.default(false)
|
172
203
|
.describe("Whether the attribute is an array or not"),
|
173
204
|
xdefault: z.string().nullish().describe("The default value of the attribute"),
|
205
|
+
description: z
|
206
|
+
.string()
|
207
|
+
.or(z.record(z.string()))
|
208
|
+
.nullish()
|
209
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
174
210
|
});
|
175
211
|
const urlAttributeSchema = z.object({
|
176
212
|
key: z.string().describe("The key of the attribute"),
|
@@ -189,6 +225,11 @@ const urlAttributeSchema = z.object({
|
|
189
225
|
.default(false)
|
190
226
|
.describe("Whether the attribute is an array or not"),
|
191
227
|
xdefault: z.string().nullish().describe("The default value of the attribute"),
|
228
|
+
description: z
|
229
|
+
.string()
|
230
|
+
.or(z.record(z.string()))
|
231
|
+
.nullish()
|
232
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
192
233
|
});
|
193
234
|
const enumAttributeSchema = z.object({
|
194
235
|
key: z.string().describe("The key of the attribute"),
|
@@ -211,6 +252,11 @@ const enumAttributeSchema = z.object({
|
|
211
252
|
.describe("The elements of the enum attribute")
|
212
253
|
.default([]),
|
213
254
|
xdefault: z.string().nullish().describe("The default value of the attribute"),
|
255
|
+
description: z
|
256
|
+
.string()
|
257
|
+
.or(z.record(z.string()))
|
258
|
+
.nullish()
|
259
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
214
260
|
});
|
215
261
|
const relationshipAttributeSchema = z.object({
|
216
262
|
key: z.string().describe("The key of the attribute"),
|
@@ -257,6 +303,11 @@ const relationshipAttributeSchema = z.object({
|
|
257
303
|
})
|
258
304
|
.optional()
|
259
305
|
.describe("Configuration for mapping and resolving relationships during data import"),
|
306
|
+
description: z
|
307
|
+
.string()
|
308
|
+
.or(z.record(z.string()))
|
309
|
+
.nullish()
|
310
|
+
.describe("The description of the attribute, also used for OpenApi Generation"),
|
260
311
|
});
|
261
312
|
export const createRelationshipAttributes = (relatedCollection, relationType, twoWay, twoWayKey, onDelete, side) => {
|
262
313
|
return relationshipAttributeSchema.parse({
|
@@ -268,16 +319,18 @@ export const createRelationshipAttributes = (relatedCollection, relationType, tw
|
|
268
319
|
side,
|
269
320
|
});
|
270
321
|
};
|
271
|
-
export const attributeSchema =
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
322
|
+
export const attributeSchema = z.discriminatedUnion("type", [
|
323
|
+
stringAttributeSchema,
|
324
|
+
integerAttributeSchema,
|
325
|
+
floatAttributeSchema,
|
326
|
+
booleanAttributeSchema,
|
327
|
+
datetimeAttributeSchema,
|
328
|
+
emailAttributeSchema,
|
329
|
+
ipAttributeSchema,
|
330
|
+
urlAttributeSchema,
|
331
|
+
enumAttributeSchema,
|
332
|
+
relationshipAttributeSchema,
|
333
|
+
]);
|
281
334
|
export const parseAttribute = (attribute) => {
|
282
335
|
if (attribute.type === "string") {
|
283
336
|
return stringAttributeSchema.parse(attribute);
|
@@ -451,6 +504,10 @@ export const collectionSchema = z.object({
|
|
451
504
|
.boolean()
|
452
505
|
.default(false)
|
453
506
|
.describe("Whether document security is enabled or not"),
|
507
|
+
description: z
|
508
|
+
.string()
|
509
|
+
.optional()
|
510
|
+
.describe("The description of the collection, if any, used to generate OpenAPI documentation"),
|
454
511
|
$createdAt: z.string(),
|
455
512
|
$updatedAt: z.string(),
|
456
513
|
$permissions: z
|
@@ -166,14 +166,20 @@ export class SchemaGenerator {
|
|
166
166
|
};
|
167
167
|
typeToZod = (attribute) => {
|
168
168
|
let baseSchemaCode = "";
|
169
|
-
|
169
|
+
const finalAttribute = (attribute.type === "string" &&
|
170
|
+
attribute.format &&
|
171
|
+
attribute.format === "enum" &&
|
172
|
+
attribute.type === "string"
|
173
|
+
? { ...attribute, type: attribute.format }
|
174
|
+
: attribute);
|
175
|
+
switch (finalAttribute.type) {
|
170
176
|
case "string":
|
171
177
|
baseSchemaCode = "z.string()";
|
172
|
-
if (
|
173
|
-
baseSchemaCode += `.max(${
|
178
|
+
if (finalAttribute.size) {
|
179
|
+
baseSchemaCode += `.max(${finalAttribute.size}, "Maximum length of ${finalAttribute.size} characters exceeded")`;
|
174
180
|
}
|
175
|
-
if (
|
176
|
-
baseSchemaCode += `.default("${
|
181
|
+
if (finalAttribute.xdefault !== undefined) {
|
182
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
177
183
|
}
|
178
184
|
if (!attribute.required && !attribute.array) {
|
179
185
|
baseSchemaCode += ".nullish()";
|
@@ -181,95 +187,95 @@ export class SchemaGenerator {
|
|
181
187
|
break;
|
182
188
|
case "integer":
|
183
189
|
baseSchemaCode = "z.number().int()";
|
184
|
-
if (
|
185
|
-
if (BigInt(
|
186
|
-
delete
|
190
|
+
if (finalAttribute.min !== undefined) {
|
191
|
+
if (BigInt(finalAttribute.min) === BigInt(-9223372036854776000)) {
|
192
|
+
delete finalAttribute.min;
|
187
193
|
}
|
188
194
|
else {
|
189
|
-
baseSchemaCode += `.min(${
|
195
|
+
baseSchemaCode += `.min(${finalAttribute.min}, "Minimum value of ${finalAttribute.min} not met")`;
|
190
196
|
}
|
191
197
|
}
|
192
|
-
if (
|
193
|
-
if (BigInt(
|
194
|
-
delete
|
198
|
+
if (finalAttribute.max !== undefined) {
|
199
|
+
if (BigInt(finalAttribute.max) === BigInt(9223372036854776000)) {
|
200
|
+
delete finalAttribute.max;
|
195
201
|
}
|
196
202
|
else {
|
197
|
-
baseSchemaCode += `.max(${
|
203
|
+
baseSchemaCode += `.max(${finalAttribute.max}, "Maximum value of ${finalAttribute.max} exceeded")`;
|
198
204
|
}
|
199
205
|
}
|
200
|
-
if (
|
201
|
-
baseSchemaCode += `.default(${
|
206
|
+
if (finalAttribute.xdefault !== undefined) {
|
207
|
+
baseSchemaCode += `.default(${finalAttribute.xdefault})`;
|
202
208
|
}
|
203
|
-
if (!
|
209
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
204
210
|
baseSchemaCode += ".nullish()";
|
205
211
|
}
|
206
212
|
break;
|
207
213
|
case "float":
|
208
214
|
baseSchemaCode = "z.number()";
|
209
|
-
if (
|
210
|
-
baseSchemaCode += `.min(${
|
215
|
+
if (finalAttribute.min !== undefined) {
|
216
|
+
baseSchemaCode += `.min(${finalAttribute.min}, "Minimum value of ${finalAttribute.min} not met")`;
|
211
217
|
}
|
212
|
-
if (
|
213
|
-
baseSchemaCode += `.max(${
|
218
|
+
if (finalAttribute.max !== undefined) {
|
219
|
+
baseSchemaCode += `.max(${finalAttribute.max}, "Maximum value of ${finalAttribute.max} exceeded")`;
|
214
220
|
}
|
215
|
-
if (
|
216
|
-
baseSchemaCode += `.default(${
|
221
|
+
if (finalAttribute.xdefault !== undefined) {
|
222
|
+
baseSchemaCode += `.default(${finalAttribute.xdefault})`;
|
217
223
|
}
|
218
|
-
if (!
|
224
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
219
225
|
baseSchemaCode += ".nullish()";
|
220
226
|
}
|
221
227
|
break;
|
222
228
|
case "boolean":
|
223
229
|
baseSchemaCode = "z.boolean()";
|
224
|
-
if (
|
225
|
-
baseSchemaCode += `.default(${
|
230
|
+
if (finalAttribute.xdefault !== undefined) {
|
231
|
+
baseSchemaCode += `.default(${finalAttribute.xdefault})`;
|
226
232
|
}
|
227
|
-
if (!
|
233
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
228
234
|
baseSchemaCode += ".nullish()";
|
229
235
|
}
|
230
236
|
break;
|
231
237
|
case "datetime":
|
232
238
|
baseSchemaCode = "z.date()";
|
233
|
-
if (
|
234
|
-
baseSchemaCode += `.default(new Date("${
|
239
|
+
if (finalAttribute.xdefault !== undefined) {
|
240
|
+
baseSchemaCode += `.default(new Date("${finalAttribute.xdefault}"))`;
|
235
241
|
}
|
236
|
-
if (!
|
242
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
237
243
|
baseSchemaCode += ".nullish()";
|
238
244
|
}
|
239
245
|
break;
|
240
246
|
case "email":
|
241
247
|
baseSchemaCode = "z.string().email()";
|
242
|
-
if (
|
243
|
-
baseSchemaCode += `.default("${
|
248
|
+
if (finalAttribute.xdefault !== undefined) {
|
249
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
244
250
|
}
|
245
|
-
if (!
|
251
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
246
252
|
baseSchemaCode += ".nullish()";
|
247
253
|
}
|
248
254
|
break;
|
249
255
|
case "ip":
|
250
256
|
baseSchemaCode = "z.string()"; // Add custom validation as needed
|
251
|
-
if (
|
252
|
-
baseSchemaCode += `.default("${
|
257
|
+
if (finalAttribute.xdefault !== undefined) {
|
258
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
253
259
|
}
|
254
|
-
if (!
|
260
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
255
261
|
baseSchemaCode += ".nullish()";
|
256
262
|
}
|
257
263
|
break;
|
258
264
|
case "url":
|
259
265
|
baseSchemaCode = "z.string().url()";
|
260
|
-
if (
|
261
|
-
baseSchemaCode += `.default("${
|
266
|
+
if (finalAttribute.xdefault !== undefined) {
|
267
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
262
268
|
}
|
263
|
-
if (!
|
269
|
+
if (!finalAttribute.required && !finalAttribute.array) {
|
264
270
|
baseSchemaCode += ".nullish()";
|
265
271
|
}
|
266
272
|
break;
|
267
273
|
case "enum":
|
268
|
-
baseSchemaCode = `z.enum([${
|
274
|
+
baseSchemaCode = `z.enum([${finalAttribute.elements
|
269
275
|
.map((element) => `"${element}"`)
|
270
276
|
.join(", ")}])`;
|
271
|
-
if (
|
272
|
-
baseSchemaCode += `.default("${
|
277
|
+
if (finalAttribute.xdefault !== undefined) {
|
278
|
+
baseSchemaCode += `.default("${finalAttribute.xdefault}")`;
|
273
279
|
}
|
274
280
|
if (!attribute.required && !attribute.array) {
|
275
281
|
baseSchemaCode += ".nullish()";
|
@@ -29,8 +29,8 @@ export declare const AuthUserSchema: z.ZodObject<{
|
|
29
29
|
}>;
|
30
30
|
export type AuthUser = z.infer<typeof AuthUserSchema>;
|
31
31
|
export declare const AuthUserCreateSchema: z.ZodObject<{
|
32
|
-
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
33
32
|
name: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
33
|
+
email: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
34
34
|
$createdAt: z.ZodOptional<z.ZodString>;
|
35
35
|
$updatedAt: z.ZodOptional<z.ZodString>;
|
36
36
|
phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
@@ -41,16 +41,16 @@ export declare const AuthUserCreateSchema: z.ZodObject<{
|
|
41
41
|
}, "strip", z.ZodTypeAny, {
|
42
42
|
prefs: Record<string, string>;
|
43
43
|
labels: string[];
|
44
|
-
email?: string | null | undefined;
|
45
44
|
name?: string | null | undefined;
|
45
|
+
email?: string | null | undefined;
|
46
46
|
$createdAt?: string | undefined;
|
47
47
|
$updatedAt?: string | undefined;
|
48
48
|
phone?: string | null | undefined;
|
49
49
|
userId?: string | undefined;
|
50
50
|
password?: string | undefined;
|
51
51
|
}, {
|
52
|
-
email?: string | null | undefined;
|
53
52
|
name?: string | null | undefined;
|
53
|
+
email?: string | null | undefined;
|
54
54
|
$createdAt?: string | undefined;
|
55
55
|
$updatedAt?: string | undefined;
|
56
56
|
phone?: string | null | undefined;
|
@@ -15,6 +15,9 @@ export interface SetupOptions {
|
|
15
15
|
importData: boolean;
|
16
16
|
checkDuplicates: boolean;
|
17
17
|
shouldWriteFile: boolean;
|
18
|
+
endpoint?: string;
|
19
|
+
project?: string;
|
20
|
+
key?: string;
|
18
21
|
}
|
19
22
|
export declare class UtilsController {
|
20
23
|
private appwriteFolderPath;
|
@@ -27,6 +30,6 @@ export declare class UtilsController {
|
|
27
30
|
validityRuleDefinitions: ValidationRules;
|
28
31
|
afterImportActionsDefinitions: AfterImportActions;
|
29
32
|
constructor();
|
30
|
-
init(): Promise<void>;
|
33
|
+
init(setupOptions: SetupOptions): Promise<void>;
|
31
34
|
run(options: SetupOptions): Promise<void>;
|
32
35
|
}
|
package/dist/utilsController.js
CHANGED
@@ -66,14 +66,26 @@ export class UtilsController {
|
|
66
66
|
// console.error("Failed to load custom definitions:", error);
|
67
67
|
// }
|
68
68
|
// }
|
69
|
-
async init() {
|
69
|
+
async init(setupOptions) {
|
70
70
|
if (!this.config) {
|
71
71
|
console.log("Initializing appwrite client & loading config...");
|
72
72
|
this.config = await loadConfig(this.appwriteConfigPath);
|
73
|
-
this.appwriteServer = new Client()
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
this.appwriteServer = new Client();
|
74
|
+
if (setupOptions.endpoint) {
|
75
|
+
if (!setupOptions.project || !setupOptions.key) {
|
76
|
+
throw new Error("Project ID and API key required when setting endpoint");
|
77
|
+
}
|
78
|
+
this.appwriteServer
|
79
|
+
.setEndpoint(setupOptions.endpoint)
|
80
|
+
.setProject(setupOptions.project)
|
81
|
+
.setKey(setupOptions.key);
|
82
|
+
}
|
83
|
+
else {
|
84
|
+
this.appwriteServer
|
85
|
+
.setEndpoint(this.config.appwriteEndpoint)
|
86
|
+
.setProject(this.config.appwriteProject)
|
87
|
+
.setKey(this.config.appwriteKey);
|
88
|
+
}
|
77
89
|
this.database = new Databases(this.appwriteServer);
|
78
90
|
this.storage = new Storage(this.appwriteServer);
|
79
91
|
this.config.appwriteClient = this.appwriteServer;
|
@@ -81,7 +93,7 @@ export class UtilsController {
|
|
81
93
|
}
|
82
94
|
}
|
83
95
|
async run(options) {
|
84
|
-
await this.init(); // Ensure initialization is done
|
96
|
+
await this.init(options); // Ensure initialization is done
|
85
97
|
if (!this.database || !this.storage || !this.config) {
|
86
98
|
throw new Error("Database or storage not initialized");
|
87
99
|
}
|
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
|
+
"version": "0.0.270",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
@@ -30,6 +30,7 @@
|
|
30
30
|
"postinstall": "echo 'This package is intended for CLI use only and should not be added as a dependency in other projects.'"
|
31
31
|
},
|
32
32
|
"dependencies": {
|
33
|
+
"@asteasolutions/zod-to-openapi": "^7.0.0",
|
33
34
|
"js-yaml": "^4.1.0",
|
34
35
|
"lodash": "^4.17.21",
|
35
36
|
"luxon": "^3.4.4",
|
package/src/main.ts
CHANGED
@@ -5,7 +5,6 @@ const args = process.argv.slice(2);
|
|
5
5
|
|
6
6
|
async function main() {
|
7
7
|
const controller = new UtilsController();
|
8
|
-
await controller.init();
|
9
8
|
|
10
9
|
let sync = false;
|
11
10
|
let runProd = false;
|
@@ -18,6 +17,9 @@ async function main() {
|
|
18
17
|
let importData = false;
|
19
18
|
let wipeDocuments = false;
|
20
19
|
let shouldWriteFile = false;
|
20
|
+
let endpoint: string | undefined;
|
21
|
+
let project: string | undefined;
|
22
|
+
let key: string | undefined;
|
21
23
|
if (args.includes("--sync")) {
|
22
24
|
sync = true;
|
23
25
|
}
|
@@ -51,6 +53,15 @@ async function main() {
|
|
51
53
|
if (args.includes("--write-data") || args.includes("--writeData")) {
|
52
54
|
shouldWriteFile = true;
|
53
55
|
}
|
56
|
+
if (args.includes("--endpoint")) {
|
57
|
+
endpoint = args[args.indexOf("--endpoint") + 1];
|
58
|
+
}
|
59
|
+
if (args.includes("--project")) {
|
60
|
+
project = args[args.indexOf("--project") + 1];
|
61
|
+
}
|
62
|
+
if (args.includes("--key")) {
|
63
|
+
key = args[args.indexOf("--key") + 1];
|
64
|
+
}
|
54
65
|
if (args.includes("--init")) {
|
55
66
|
await controller.run({
|
56
67
|
sync: sync,
|
@@ -66,6 +77,9 @@ async function main() {
|
|
66
77
|
importData: false,
|
67
78
|
checkDuplicates: false,
|
68
79
|
shouldWriteFile: shouldWriteFile,
|
80
|
+
endpoint: endpoint,
|
81
|
+
project: project,
|
82
|
+
key: key,
|
69
83
|
});
|
70
84
|
} else {
|
71
85
|
await controller.run({
|
@@ -82,6 +96,9 @@ async function main() {
|
|
82
96
|
importData: importData,
|
83
97
|
checkDuplicates: false,
|
84
98
|
shouldWriteFile: shouldWriteFile,
|
99
|
+
endpoint: endpoint,
|
100
|
+
project: project,
|
101
|
+
key: key,
|
85
102
|
});
|
86
103
|
}
|
87
104
|
}
|
@@ -81,7 +81,18 @@ export class AppwriteToX {
|
|
81
81
|
collection.$permissions
|
82
82
|
);
|
83
83
|
const collAttributes = attributesSchema
|
84
|
-
.parse(
|
84
|
+
.parse(
|
85
|
+
collection.attributes.map((attr: any) => {
|
86
|
+
if (
|
87
|
+
attr.type === "string" &&
|
88
|
+
attr.format &&
|
89
|
+
attr.format.length > 0
|
90
|
+
) {
|
91
|
+
return { ...attr, type: attr.format };
|
92
|
+
}
|
93
|
+
return attr;
|
94
|
+
})
|
95
|
+
)
|
85
96
|
.filter((attribute) =>
|
86
97
|
attribute.type === "relationship"
|
87
98
|
? attribute.side !== "child"
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import {
|
2
|
+
OpenAPIRegistry,
|
3
|
+
OpenApiGeneratorV3,
|
4
|
+
OpenApiGeneratorV31,
|
5
|
+
} from "@asteasolutions/zod-to-openapi";
|
6
|
+
import {
|
7
|
+
attributeSchema,
|
8
|
+
collectionSchema,
|
9
|
+
type AppwriteConfig,
|
10
|
+
type Attribute,
|
11
|
+
type Collection,
|
12
|
+
type CollectionCreate,
|
13
|
+
} from "./schema.js";
|
14
|
+
import { z } from "zod";
|
15
|
+
import { writeFileSync } from "fs";
|
16
|
+
|
17
|
+
const registry = new OpenAPIRegistry();
|
18
|
+
|
19
|
+
export const generateOpenApi = async (config: AppwriteConfig) => {
|
20
|
+
for (const collection of config.collections) {
|
21
|
+
// Transform and register each attribute schema
|
22
|
+
const attributeSchemas = collection.attributes.map((attribute) => {
|
23
|
+
return transformTypeToOpenApi(attributeSchema);
|
24
|
+
});
|
25
|
+
|
26
|
+
// Create and register the collection schema with descriptions
|
27
|
+
const updatedCollectionSchema = collectionSchema
|
28
|
+
.extend({
|
29
|
+
// @ts-ignore
|
30
|
+
attributes: z.array(z.union(attributeSchemas)),
|
31
|
+
})
|
32
|
+
.openapi(collection.description ?? "No description");
|
33
|
+
|
34
|
+
// Register the updated collection schema under the collection name
|
35
|
+
registry.register(collection.name, updatedCollectionSchema);
|
36
|
+
}
|
37
|
+
|
38
|
+
// Convert the registry to OpenAPI JSON
|
39
|
+
// @ts-ignore
|
40
|
+
const openApiSpec = registry.toOpenAPI();
|
41
|
+
|
42
|
+
// Output the OpenAPI spec to a file
|
43
|
+
writeFileSync(
|
44
|
+
"./appwrite/openapi/openapi.json",
|
45
|
+
JSON.stringify(openApiSpec, null, 2)
|
46
|
+
);
|
47
|
+
};
|
48
|
+
|
49
|
+
export function transformTypeToOpenApi<T extends z.ZodTypeAny>(
|
50
|
+
schema: T
|
51
|
+
): z.infer<T> {
|
52
|
+
return schema.transform((data) => {
|
53
|
+
let finalData = data;
|
54
|
+
if (data._def.attributes) {
|
55
|
+
finalData._def.attributes = data._def.attributes.map(
|
56
|
+
(attribute: typeof attributeSchema) => {
|
57
|
+
if (attribute.description) {
|
58
|
+
return attribute.openapi(attribute.description);
|
59
|
+
}
|
60
|
+
return attribute;
|
61
|
+
}
|
62
|
+
);
|
63
|
+
}
|
64
|
+
if (schema.description) {
|
65
|
+
finalData.openapi(schema.description);
|
66
|
+
}
|
67
|
+
return finalData;
|
68
|
+
});
|
69
|
+
}
|