appwrite-utils-cli 0.0.286 → 0.9.2
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 +162 -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 +224 -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 +289 -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
@@ -1,70 +1,83 @@
|
|
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 "appwrite-utils";
|
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
|
-
if (!config.collections) {
|
21
|
-
return;
|
22
|
-
}
|
23
|
-
for (const collection of config.collections) {
|
24
|
-
// Transform and register each attribute schema
|
25
|
-
const attributeSchemas = collection.attributes.map((attribute) => {
|
26
|
-
return transformTypeToOpenApi(attributeSchema);
|
27
|
-
});
|
28
|
-
|
29
|
-
// Create and register the collection schema with descriptions
|
30
|
-
const updatedCollectionSchema = CollectionSchema.extend({
|
31
|
-
// @ts-ignore
|
32
|
-
attributes:
|
33
|
-
}).openapi(collection.description ?? "No description");
|
34
|
-
|
35
|
-
// Register the updated collection schema under the collection name
|
36
|
-
registry.register(collection.name, updatedCollectionSchema);
|
37
|
-
}
|
38
|
-
|
39
|
-
// Convert the registry to OpenAPI JSON
|
40
|
-
|
41
|
-
const openApiSpec =
|
42
|
-
|
43
|
-
// Output the OpenAPI spec to a file
|
44
|
-
writeFileSync(
|
45
|
-
"./appwrite/openapi/openapi.json",
|
46
|
-
JSON.stringify(openApiSpec, null, 2)
|
47
|
-
);
|
48
|
-
};
|
49
|
-
|
50
|
-
export function transformTypeToOpenApi<T extends z.ZodTypeAny>(
|
51
|
-
schema: T
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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 "appwrite-utils";
|
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
|
+
if (!config.collections) {
|
21
|
+
return;
|
22
|
+
}
|
23
|
+
for (const collection of config.collections) {
|
24
|
+
// Transform and register each attribute schema
|
25
|
+
const attributeSchemas = collection.attributes.map((attribute) => {
|
26
|
+
return transformTypeToOpenApi(attributeSchema, attribute.description);
|
27
|
+
});
|
28
|
+
|
29
|
+
// Create and register the collection schema with descriptions
|
30
|
+
const updatedCollectionSchema = CollectionSchema.extend({
|
31
|
+
// @ts-ignore
|
32
|
+
attributes: attributeSchemas,
|
33
|
+
}).openapi(collection.description ?? "No description");
|
34
|
+
|
35
|
+
// Register the updated collection schema under the collection name
|
36
|
+
registry.register(collection.name, updatedCollectionSchema);
|
37
|
+
}
|
38
|
+
|
39
|
+
// Convert the registry to OpenAPI JSON
|
40
|
+
const generator = new OpenApiGeneratorV31(registry.definitions);
|
41
|
+
const openApiSpec = generator.generateComponents();
|
42
|
+
|
43
|
+
// Output the OpenAPI spec to a file
|
44
|
+
writeFileSync(
|
45
|
+
"./appwrite/openapi/openapi.json",
|
46
|
+
JSON.stringify(openApiSpec, null, 2)
|
47
|
+
);
|
48
|
+
};
|
49
|
+
|
50
|
+
export function transformTypeToOpenApi<T extends z.ZodTypeAny>(
|
51
|
+
schema: T,
|
52
|
+
description?: string | Record<string, any> | null | undefined
|
53
|
+
): T {
|
54
|
+
// Check if description is an object (OpenAPI properties) or a string
|
55
|
+
let updatedSchema: z.infer<T>;
|
56
|
+
if (!description) {
|
57
|
+
return schema;
|
58
|
+
}
|
59
|
+
if (typeof description === "string") {
|
60
|
+
updatedSchema = schema.openapi(description);
|
61
|
+
} else if (typeof description === "object") {
|
62
|
+
updatedSchema = schema.openapi(description);
|
63
|
+
} else {
|
64
|
+
updatedSchema = schema;
|
65
|
+
}
|
66
|
+
|
67
|
+
// Check and transform attributes if they exist
|
68
|
+
if ((schema as any)._def && (schema as any)._def.shape) {
|
69
|
+
const shape = (schema as any)._def.shape();
|
70
|
+
for (const key in shape) {
|
71
|
+
const attributeDesc = shape[key].description;
|
72
|
+
if (attributeDesc) {
|
73
|
+
if (typeof attributeDesc === "string") {
|
74
|
+
shape[key] = shape[key].openapi(attributeDesc);
|
75
|
+
} else if (typeof attributeDesc === "object") {
|
76
|
+
shape[key] = shape[key].openapi(attributeDesc);
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
return updatedSchema;
|
83
|
+
}
|
package/src/migrations/queue.ts
CHANGED
@@ -1,119 +1,118 @@
|
|
1
|
-
import { Query, type Databases, type Models } from "node-appwrite";
|
2
|
-
import type { Attribute } from "appwrite-utils";
|
3
|
-
import { createOrUpdateAttribute } from "./attributes.js";
|
4
|
-
import _ from "lodash";
|
5
|
-
import { fetchAndCacheCollectionByName } from "./collections.js";
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
export const
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
console.log(
|
24
|
-
console.log(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
if
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
operation.collectionId
|
43
|
-
);
|
44
|
-
} catch (e) {
|
45
|
-
console.log(
|
46
|
-
`\tCollection not found by ID: ${operation.collectionId}`
|
47
|
-
);
|
48
|
-
}
|
49
|
-
}
|
50
|
-
// Attempt to resolve related collection if specified and not already found
|
51
|
-
if (!collectionFound && operation.attribute?.relatedCollection) {
|
52
|
-
collectionFound = await fetchAndCacheCollectionByName(
|
53
|
-
db,
|
54
|
-
dbId,
|
55
|
-
operation.attribute.relatedCollection
|
56
|
-
);
|
57
|
-
}
|
58
|
-
// Handle dependencies if collection still not found
|
59
|
-
if (!collectionFound) {
|
60
|
-
for (const dep of operation.dependencies || []) {
|
61
|
-
collectionFound = await fetchAndCacheCollectionByName(
|
62
|
-
db,
|
63
|
-
dbId,
|
64
|
-
dep
|
65
|
-
);
|
66
|
-
if (collectionFound) break; // Break early if collection is found
|
67
|
-
}
|
68
|
-
}
|
69
|
-
} else if (operation.collectionId) {
|
70
|
-
// Handle non-relationship operations with a specified collectionId
|
71
|
-
console.log(`\tFetching collection by ID: ${operation.collectionId}`);
|
72
|
-
try {
|
73
|
-
collectionFound = await
|
74
|
-
dbId,
|
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
|
-
console.
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
console.log(
|
117
|
-
console.log(
|
118
|
-
|
119
|
-
};
|
1
|
+
import { Query, type Databases, type Models } from "node-appwrite";
|
2
|
+
import type { Attribute } from "appwrite-utils";
|
3
|
+
import { createOrUpdateAttribute } from "./attributes.js";
|
4
|
+
import _ from "lodash";
|
5
|
+
import { fetchAndCacheCollectionByName } from "./collections.js";
|
6
|
+
import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
7
|
+
|
8
|
+
export interface QueuedOperation {
|
9
|
+
type: "attribute";
|
10
|
+
collectionId?: string;
|
11
|
+
attribute?: Attribute;
|
12
|
+
collection?: Models.Collection;
|
13
|
+
dependencies?: string[];
|
14
|
+
}
|
15
|
+
export const queuedOperations: QueuedOperation[] = [];
|
16
|
+
export const nameToIdMapping: Map<string, string> = new Map();
|
17
|
+
|
18
|
+
export const enqueueOperation = (operation: QueuedOperation) => {
|
19
|
+
queuedOperations.push(operation);
|
20
|
+
};
|
21
|
+
|
22
|
+
export const processQueue = async (db: Databases, dbId: string) => {
|
23
|
+
console.log("---------------------------------");
|
24
|
+
console.log(`Starting Queue processing of ${dbId}`);
|
25
|
+
console.log("---------------------------------");
|
26
|
+
let progress = true;
|
27
|
+
|
28
|
+
while (progress) {
|
29
|
+
progress = false;
|
30
|
+
console.log("Processing queued operations:");
|
31
|
+
for (let i = 0; i < queuedOperations.length; i++) {
|
32
|
+
const operation = queuedOperations[i];
|
33
|
+
let collectionFound: Models.Collection | undefined;
|
34
|
+
|
35
|
+
// Handle relationship attribute operations
|
36
|
+
if (operation.attribute?.type === "relationship") {
|
37
|
+
// Attempt to resolve the collection directly if collectionId is specified
|
38
|
+
if (operation.collectionId) {
|
39
|
+
console.log(`\tFetching collection by ID: ${operation.collectionId}`);
|
40
|
+
try {
|
41
|
+
collectionFound = await tryAwaitWithRetry(
|
42
|
+
async () => await db.getCollection(dbId, operation.collectionId!)
|
43
|
+
);
|
44
|
+
} catch (e) {
|
45
|
+
console.log(
|
46
|
+
`\tCollection not found by ID: ${operation.collectionId}`
|
47
|
+
);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
// Attempt to resolve related collection if specified and not already found
|
51
|
+
if (!collectionFound && operation.attribute?.relatedCollection) {
|
52
|
+
collectionFound = await fetchAndCacheCollectionByName(
|
53
|
+
db,
|
54
|
+
dbId,
|
55
|
+
operation.attribute.relatedCollection
|
56
|
+
);
|
57
|
+
}
|
58
|
+
// Handle dependencies if collection still not found
|
59
|
+
if (!collectionFound) {
|
60
|
+
for (const dep of operation.dependencies || []) {
|
61
|
+
collectionFound = await fetchAndCacheCollectionByName(
|
62
|
+
db,
|
63
|
+
dbId,
|
64
|
+
dep
|
65
|
+
);
|
66
|
+
if (collectionFound) break; // Break early if collection is found
|
67
|
+
}
|
68
|
+
}
|
69
|
+
} else if (operation.collectionId) {
|
70
|
+
// Handle non-relationship operations with a specified collectionId
|
71
|
+
console.log(`\tFetching collection by ID: ${operation.collectionId}`);
|
72
|
+
try {
|
73
|
+
collectionFound = await tryAwaitWithRetry(
|
74
|
+
async () => await db.getCollection(dbId, operation.collectionId!)
|
75
|
+
);
|
76
|
+
} catch (e) {
|
77
|
+
console.log(
|
78
|
+
`\tCollection not found by ID: ${operation.collectionId}`
|
79
|
+
);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
// Process the operation if the collection is found
|
84
|
+
if (collectionFound && operation.attribute) {
|
85
|
+
console.log(
|
86
|
+
`\tProcessing attribute: ${operation.attribute.key} for collection ID: ${collectionFound.$id}`
|
87
|
+
);
|
88
|
+
await createOrUpdateAttribute(
|
89
|
+
db,
|
90
|
+
dbId,
|
91
|
+
collectionFound,
|
92
|
+
operation.attribute
|
93
|
+
);
|
94
|
+
queuedOperations.splice(i, 1);
|
95
|
+
i--; // Adjust index since we're modifying the array
|
96
|
+
progress = true;
|
97
|
+
} else {
|
98
|
+
console.error(
|
99
|
+
`\tCollection not found for operation, removing from queue: ${JSON.stringify(
|
100
|
+
operation
|
101
|
+
)}`
|
102
|
+
);
|
103
|
+
queuedOperations.splice(i, 1);
|
104
|
+
i--; // Adjust index since we're modifying the array
|
105
|
+
}
|
106
|
+
}
|
107
|
+
console.log(`\tFinished processing queued operations`);
|
108
|
+
}
|
109
|
+
|
110
|
+
if (queuedOperations.length > 0) {
|
111
|
+
console.error("Unresolved operations remain due to unmet dependencies.");
|
112
|
+
console.log(queuedOperations);
|
113
|
+
}
|
114
|
+
|
115
|
+
console.log("---------------------------------");
|
116
|
+
console.log(`Queue processing complete for ${dbId}`);
|
117
|
+
console.log("---------------------------------");
|
118
|
+
};
|