appwrite-utils-cli 0.10.85 → 1.0.1
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/.appwrite/.yaml_schemas/appwrite-config.schema.json +380 -0
- package/.appwrite/.yaml_schemas/collection.schema.json +255 -0
- package/.appwrite/collections/Categories.yaml +182 -0
- package/.appwrite/collections/ExampleCollection.yaml +36 -0
- package/.appwrite/collections/Posts.yaml +227 -0
- package/.appwrite/collections/Users.yaml +149 -0
- package/.appwrite/config.yaml +109 -0
- package/.appwrite/import/README.md +148 -0
- package/.appwrite/import/categories-import.yaml +129 -0
- package/.appwrite/import/posts-import.yaml +208 -0
- package/.appwrite/import/users-import.yaml +130 -0
- package/.appwrite/importData/categories.json +194 -0
- package/.appwrite/importData/posts.json +270 -0
- package/.appwrite/importData/users.json +220 -0
- package/.appwrite/schemas/categories.json +128 -0
- package/.appwrite/schemas/exampleCollection.json +52 -0
- package/.appwrite/schemas/posts.json +173 -0
- package/.appwrite/schemas/users.json +125 -0
- package/README.md +261 -33
- package/dist/collections/attributes.js +3 -2
- package/dist/collections/methods.js +56 -38
- package/dist/config/yamlConfig.d.ts +501 -0
- package/dist/config/yamlConfig.js +452 -0
- package/dist/databases/setup.d.ts +6 -0
- package/dist/databases/setup.js +119 -0
- package/dist/functions/methods.d.ts +1 -1
- package/dist/functions/methods.js +5 -2
- package/dist/functions/openapi.d.ts +4 -0
- package/dist/functions/openapi.js +60 -0
- package/dist/interactiveCLI.d.ts +5 -0
- package/dist/interactiveCLI.js +196 -52
- package/dist/main.js +91 -30
- package/dist/migrations/afterImportActions.js +2 -2
- package/dist/migrations/appwriteToX.d.ts +10 -0
- package/dist/migrations/appwriteToX.js +15 -4
- package/dist/migrations/backup.d.ts +16 -16
- package/dist/migrations/dataLoader.d.ts +83 -1
- package/dist/migrations/dataLoader.js +4 -4
- package/dist/migrations/importController.js +25 -18
- package/dist/migrations/importDataActions.js +2 -2
- package/dist/migrations/logging.d.ts +9 -1
- package/dist/migrations/logging.js +41 -22
- package/dist/migrations/migrationHelper.d.ts +4 -4
- package/dist/migrations/relationships.js +1 -1
- package/dist/migrations/services/DataTransformationService.d.ts +55 -0
- package/dist/migrations/services/DataTransformationService.js +158 -0
- package/dist/migrations/services/FileHandlerService.d.ts +75 -0
- package/dist/migrations/services/FileHandlerService.js +236 -0
- package/dist/migrations/services/ImportOrchestrator.d.ts +97 -0
- package/dist/migrations/services/ImportOrchestrator.js +488 -0
- package/dist/migrations/services/RateLimitManager.d.ts +138 -0
- package/dist/migrations/services/RateLimitManager.js +279 -0
- package/dist/migrations/services/RelationshipResolver.d.ts +120 -0
- package/dist/migrations/services/RelationshipResolver.js +332 -0
- package/dist/migrations/services/UserMappingService.d.ts +109 -0
- package/dist/migrations/services/UserMappingService.js +277 -0
- package/dist/migrations/services/ValidationService.d.ts +74 -0
- package/dist/migrations/services/ValidationService.js +260 -0
- package/dist/migrations/transfer.d.ts +0 -6
- package/dist/migrations/transfer.js +16 -132
- package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +384 -0
- package/dist/migrations/yaml/YamlImportConfigLoader.js +375 -0
- package/dist/migrations/yaml/YamlImportIntegration.d.ts +87 -0
- package/dist/migrations/yaml/YamlImportIntegration.js +330 -0
- package/dist/migrations/yaml/generateImportSchemas.d.ts +17 -0
- package/dist/migrations/yaml/generateImportSchemas.js +575 -0
- package/dist/schemas/authUser.d.ts +9 -9
- package/dist/shared/attributeManager.d.ts +17 -0
- package/dist/shared/attributeManager.js +273 -0
- package/dist/shared/confirmationDialogs.d.ts +75 -0
- package/dist/shared/confirmationDialogs.js +236 -0
- package/dist/shared/functionManager.d.ts +48 -0
- package/dist/shared/functionManager.js +322 -0
- package/dist/shared/indexManager.d.ts +24 -0
- package/dist/shared/indexManager.js +150 -0
- package/dist/shared/jsonSchemaGenerator.d.ts +51 -0
- package/dist/shared/jsonSchemaGenerator.js +313 -0
- package/dist/shared/logging.d.ts +10 -0
- package/dist/shared/logging.js +46 -0
- package/dist/shared/messageFormatter.d.ts +37 -0
- package/dist/shared/messageFormatter.js +152 -0
- package/dist/shared/migrationHelpers.d.ts +173 -0
- package/dist/shared/migrationHelpers.js +142 -0
- package/dist/shared/operationLogger.d.ts +3 -0
- package/dist/shared/operationLogger.js +25 -0
- package/dist/shared/operationQueue.d.ts +13 -0
- package/dist/shared/operationQueue.js +79 -0
- package/dist/shared/progressManager.d.ts +62 -0
- package/dist/shared/progressManager.js +215 -0
- package/dist/shared/schemaGenerator.d.ts +18 -0
- package/dist/shared/schemaGenerator.js +523 -0
- package/dist/storage/methods.d.ts +3 -1
- package/dist/storage/methods.js +144 -55
- package/dist/storage/schemas.d.ts +56 -16
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/dist/users/methods.d.ts +16 -0
- package/dist/users/methods.js +276 -0
- package/dist/utils/configMigration.d.ts +1 -0
- package/dist/utils/configMigration.js +156 -0
- package/dist/utils/dataConverters.d.ts +46 -0
- package/dist/utils/dataConverters.js +139 -0
- package/dist/utils/loadConfigs.d.ts +15 -4
- package/dist/utils/loadConfigs.js +377 -51
- package/dist/utils/schemaStrings.js +2 -1
- package/dist/utils/setupFiles.d.ts +2 -1
- package/dist/utils/setupFiles.js +723 -28
- package/dist/utils/validationRules.d.ts +43 -0
- package/dist/utils/validationRules.js +42 -0
- package/dist/utils/yamlConverter.d.ts +48 -0
- package/dist/utils/yamlConverter.js +98 -0
- package/dist/utilsController.js +65 -43
- package/package.json +19 -15
- package/src/collections/attributes.ts +3 -2
- package/src/collections/methods.ts +85 -51
- package/src/config/yamlConfig.ts +488 -0
- package/src/{migrations/setupDatabase.ts → databases/setup.ts} +11 -5
- package/src/functions/methods.ts +8 -4
- package/src/functions/templates/count-docs-in-collection/package.json +25 -0
- package/src/functions/templates/count-docs-in-collection/tsconfig.json +28 -0
- package/src/functions/templates/typescript-node/package.json +24 -0
- package/src/functions/templates/typescript-node/tsconfig.json +28 -0
- package/src/functions/templates/uv/README.md +31 -0
- package/src/functions/templates/uv/pyproject.toml +29 -0
- package/src/interactiveCLI.ts +230 -63
- package/src/main.ts +111 -37
- package/src/migrations/afterImportActions.ts +2 -2
- package/src/migrations/appwriteToX.ts +17 -4
- package/src/migrations/dataLoader.ts +4 -4
- package/src/migrations/importController.ts +30 -22
- package/src/migrations/importDataActions.ts +2 -2
- package/src/migrations/relationships.ts +1 -1
- package/src/migrations/services/DataTransformationService.ts +196 -0
- package/src/migrations/services/FileHandlerService.ts +311 -0
- package/src/migrations/services/ImportOrchestrator.ts +669 -0
- package/src/migrations/services/RateLimitManager.ts +363 -0
- package/src/migrations/services/RelationshipResolver.ts +461 -0
- package/src/migrations/services/UserMappingService.ts +345 -0
- package/src/migrations/services/ValidationService.ts +349 -0
- package/src/migrations/transfer.ts +22 -228
- package/src/migrations/yaml/YamlImportConfigLoader.ts +427 -0
- package/src/migrations/yaml/YamlImportIntegration.ts +419 -0
- package/src/migrations/yaml/generateImportSchemas.ts +589 -0
- package/src/shared/attributeManager.ts +429 -0
- package/src/shared/confirmationDialogs.ts +327 -0
- package/src/shared/functionManager.ts +515 -0
- package/src/shared/indexManager.ts +253 -0
- package/src/shared/jsonSchemaGenerator.ts +403 -0
- package/src/shared/logging.ts +74 -0
- package/src/shared/messageFormatter.ts +195 -0
- package/src/{migrations/migrationHelper.ts → shared/migrationHelpers.ts} +22 -4
- package/src/{migrations/helper.ts → shared/operationLogger.ts} +7 -2
- package/src/{migrations/queue.ts → shared/operationQueue.ts} +1 -1
- package/src/shared/progressManager.ts +278 -0
- package/src/{migrations/schemaStrings.ts → shared/schemaGenerator.ts} +71 -17
- package/src/storage/methods.ts +199 -78
- package/src/types.ts +2 -2
- package/src/{migrations/users.ts → users/methods.ts} +2 -2
- package/src/utils/configMigration.ts +212 -0
- package/src/utils/loadConfigs.ts +414 -52
- package/src/utils/schemaStrings.ts +2 -1
- package/src/utils/setupFiles.ts +742 -40
- package/src/{migrations → utils}/validationRules.ts +1 -1
- package/src/utils/yamlConverter.ts +131 -0
- package/src/utilsController.ts +75 -54
- package/src/functions/templates/poetry/README.md +0 -30
- package/src/functions/templates/poetry/pyproject.toml +0 -16
- package/src/migrations/attributes.ts +0 -561
- package/src/migrations/backup.ts +0 -205
- package/src/migrations/databases.ts +0 -39
- package/src/migrations/dbHelpers.ts +0 -92
- package/src/migrations/indexes.ts +0 -40
- package/src/migrations/logging.ts +0 -29
- package/src/migrations/storage.ts +0 -538
- /package/src/{migrations → functions}/openapi.ts +0 -0
- /package/src/functions/templates/{poetry → uv}/src/__init__.py +0 -0
- /package/src/functions/templates/{poetry → uv}/src/index.py +0 -0
- /package/src/{migrations/converters.ts → utils/dataConverters.ts} +0 -0
@@ -0,0 +1,173 @@
|
|
1
|
+
import { type Databases } from "node-appwrite";
|
2
|
+
import { z } from "zod";
|
3
|
+
/**
|
4
|
+
* Object that contains the context for an action that needs to be executed after import
|
5
|
+
* Used in the afterImportActionsDefinitions
|
6
|
+
* @type {ContextObject}
|
7
|
+
* @typedef {Object} ContextObject
|
8
|
+
* @property {string} collectionId - The ID of the collection
|
9
|
+
* @property {any} finalItem - The final item that was imported
|
10
|
+
* @property {string} action - The name of the action
|
11
|
+
* @property {string[]} params - The parameters for the action
|
12
|
+
* @property {Object} context - The context object for the action (all the data of this specific item)
|
13
|
+
*/
|
14
|
+
export declare const ContextObject: z.ZodObject<{
|
15
|
+
dbId: z.ZodString;
|
16
|
+
collectionId: z.ZodString;
|
17
|
+
finalItem: z.ZodAny;
|
18
|
+
attributeMappings: z.ZodArray<z.ZodObject<{
|
19
|
+
oldKey: z.ZodOptional<z.ZodString>;
|
20
|
+
oldKeys: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
21
|
+
targetKey: z.ZodString;
|
22
|
+
valueToSet: z.ZodOptional<z.ZodAny>;
|
23
|
+
fileData: z.ZodOptional<z.ZodObject<{
|
24
|
+
name: z.ZodString;
|
25
|
+
path: z.ZodString;
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
27
|
+
path: string;
|
28
|
+
name: string;
|
29
|
+
}, {
|
30
|
+
path: string;
|
31
|
+
name: string;
|
32
|
+
}>>;
|
33
|
+
converters: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString, "many">>>;
|
34
|
+
validationActions: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
|
35
|
+
action: z.ZodString;
|
36
|
+
params: z.ZodArray<z.ZodString, "many">;
|
37
|
+
}, "strip", z.ZodTypeAny, {
|
38
|
+
params: string[];
|
39
|
+
action: string;
|
40
|
+
}, {
|
41
|
+
params: string[];
|
42
|
+
action: string;
|
43
|
+
}>, "many">>>;
|
44
|
+
postImportActions: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodObject<{
|
45
|
+
action: z.ZodString;
|
46
|
+
params: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodAny>]>, "many">;
|
47
|
+
}, "strip", z.ZodTypeAny, {
|
48
|
+
params: (string | Record<string, any>)[];
|
49
|
+
action: string;
|
50
|
+
}, {
|
51
|
+
params: (string | Record<string, any>)[];
|
52
|
+
action: string;
|
53
|
+
}>, "many">>>;
|
54
|
+
}, "strip", z.ZodTypeAny, {
|
55
|
+
targetKey: string;
|
56
|
+
oldKey?: string | undefined;
|
57
|
+
oldKeys?: string[] | undefined;
|
58
|
+
valueToSet?: any;
|
59
|
+
fileData?: {
|
60
|
+
path: string;
|
61
|
+
name: string;
|
62
|
+
} | undefined;
|
63
|
+
converters?: string[] | undefined;
|
64
|
+
validationActions?: {
|
65
|
+
params: string[];
|
66
|
+
action: string;
|
67
|
+
}[] | undefined;
|
68
|
+
postImportActions?: {
|
69
|
+
params: (string | Record<string, any>)[];
|
70
|
+
action: string;
|
71
|
+
}[] | undefined;
|
72
|
+
}, {
|
73
|
+
targetKey: string;
|
74
|
+
oldKey?: string | undefined;
|
75
|
+
oldKeys?: string[] | undefined;
|
76
|
+
valueToSet?: any;
|
77
|
+
fileData?: {
|
78
|
+
path: string;
|
79
|
+
name: string;
|
80
|
+
} | undefined;
|
81
|
+
converters?: string[] | undefined;
|
82
|
+
validationActions?: {
|
83
|
+
params: string[];
|
84
|
+
action: string;
|
85
|
+
}[] | undefined;
|
86
|
+
postImportActions?: {
|
87
|
+
params: (string | Record<string, any>)[];
|
88
|
+
action: string;
|
89
|
+
}[] | undefined;
|
90
|
+
}>, "many">;
|
91
|
+
context: z.ZodAny;
|
92
|
+
}, "strip", z.ZodTypeAny, {
|
93
|
+
collectionId: string;
|
94
|
+
attributeMappings: {
|
95
|
+
targetKey: string;
|
96
|
+
oldKey?: string | undefined;
|
97
|
+
oldKeys?: string[] | undefined;
|
98
|
+
valueToSet?: any;
|
99
|
+
fileData?: {
|
100
|
+
path: string;
|
101
|
+
name: string;
|
102
|
+
} | undefined;
|
103
|
+
converters?: string[] | undefined;
|
104
|
+
validationActions?: {
|
105
|
+
params: string[];
|
106
|
+
action: string;
|
107
|
+
}[] | undefined;
|
108
|
+
postImportActions?: {
|
109
|
+
params: (string | Record<string, any>)[];
|
110
|
+
action: string;
|
111
|
+
}[] | undefined;
|
112
|
+
}[];
|
113
|
+
dbId: string;
|
114
|
+
context?: any;
|
115
|
+
finalItem?: any;
|
116
|
+
}, {
|
117
|
+
collectionId: string;
|
118
|
+
attributeMappings: {
|
119
|
+
targetKey: string;
|
120
|
+
oldKey?: string | undefined;
|
121
|
+
oldKeys?: string[] | undefined;
|
122
|
+
valueToSet?: any;
|
123
|
+
fileData?: {
|
124
|
+
path: string;
|
125
|
+
name: string;
|
126
|
+
} | undefined;
|
127
|
+
converters?: string[] | undefined;
|
128
|
+
validationActions?: {
|
129
|
+
params: string[];
|
130
|
+
action: string;
|
131
|
+
}[] | undefined;
|
132
|
+
postImportActions?: {
|
133
|
+
params: (string | Record<string, any>)[];
|
134
|
+
action: string;
|
135
|
+
}[] | undefined;
|
136
|
+
}[];
|
137
|
+
dbId: string;
|
138
|
+
context?: any;
|
139
|
+
finalItem?: any;
|
140
|
+
}>;
|
141
|
+
export type ContextObject = z.infer<typeof ContextObject>;
|
142
|
+
export declare const createOrFindAfterImportOperation: (database: Databases, collectionId: string, context: ContextObject, useMigrations?: boolean) => Promise<void>;
|
143
|
+
export declare const addBatch: (database: Databases, data: string) => Promise<string>;
|
144
|
+
export declare const getAfterImportOperations: (database: Databases, collectionId: string, useMigrations?: boolean) => Promise<{
|
145
|
+
status: "error" | "pending" | "ready" | "in_progress" | "completed" | "cancelled";
|
146
|
+
error: string;
|
147
|
+
$id: string;
|
148
|
+
$createdAt: string;
|
149
|
+
$updatedAt: string;
|
150
|
+
collectionId: string;
|
151
|
+
operationType: string;
|
152
|
+
progress: number;
|
153
|
+
total: number;
|
154
|
+
data?: any;
|
155
|
+
batches?: string[] | undefined;
|
156
|
+
}[]>;
|
157
|
+
export declare const findOrCreateOperation: (database: Databases, collectionId: string, operationType: string, additionalQueries?: string[]) => Promise<{
|
158
|
+
status: "error" | "pending" | "ready" | "in_progress" | "completed" | "cancelled";
|
159
|
+
error: string;
|
160
|
+
$id: string;
|
161
|
+
$createdAt: string;
|
162
|
+
$updatedAt: string;
|
163
|
+
collectionId: string;
|
164
|
+
operationType: string;
|
165
|
+
progress: number;
|
166
|
+
total: number;
|
167
|
+
data?: any;
|
168
|
+
batches?: string[] | undefined;
|
169
|
+
}>;
|
170
|
+
export declare const updateOperation: (database: Databases, operationId: string, updateFields: any, useMigrations?: boolean) => Promise<void>;
|
171
|
+
export declare const maxDataLength = 1073741820;
|
172
|
+
export declare const maxBatchItems = 25;
|
173
|
+
export declare const splitIntoBatches: (data: any[]) => any[][];
|
@@ -0,0 +1,142 @@
|
|
1
|
+
import { ID, Query } from "node-appwrite";
|
2
|
+
import { BatchSchema, OperationSchema } from "../storage/schemas.js";
|
3
|
+
import { AttributeMappingsSchema } from "appwrite-utils";
|
4
|
+
import { z } from "zod";
|
5
|
+
import { logger } from "./logging.js";
|
6
|
+
import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
7
|
+
/**
|
8
|
+
* Object that contains the context for an action that needs to be executed after import
|
9
|
+
* Used in the afterImportActionsDefinitions
|
10
|
+
* @type {ContextObject}
|
11
|
+
* @typedef {Object} ContextObject
|
12
|
+
* @property {string} collectionId - The ID of the collection
|
13
|
+
* @property {any} finalItem - The final item that was imported
|
14
|
+
* @property {string} action - The name of the action
|
15
|
+
* @property {string[]} params - The parameters for the action
|
16
|
+
* @property {Object} context - The context object for the action (all the data of this specific item)
|
17
|
+
*/
|
18
|
+
export const ContextObject = z.object({
|
19
|
+
dbId: z.string(),
|
20
|
+
collectionId: z.string(),
|
21
|
+
finalItem: z.any(),
|
22
|
+
attributeMappings: AttributeMappingsSchema,
|
23
|
+
context: z.any(),
|
24
|
+
});
|
25
|
+
export const createOrFindAfterImportOperation = async (database, collectionId, context, useMigrations = true) => {
|
26
|
+
if (!useMigrations) {
|
27
|
+
logger.info("Migrations disabled, skipping after import operation tracking");
|
28
|
+
return;
|
29
|
+
}
|
30
|
+
let operation = await findOrCreateOperation(database, collectionId, "afterImportAction");
|
31
|
+
if (!operation.batches) {
|
32
|
+
operation.batches = [];
|
33
|
+
}
|
34
|
+
// Directly create a new batch for the context without checking for an existing batch
|
35
|
+
const contextData = JSON.stringify(context);
|
36
|
+
// Create a new batch with the contextData
|
37
|
+
const newBatchId = await addBatch(database, contextData);
|
38
|
+
// Update the operation with the new batch's $id
|
39
|
+
operation.batches = [...operation.batches, newBatchId];
|
40
|
+
await database.updateDocument("migrations", "currentOperations", operation.$id, { batches: operation.batches });
|
41
|
+
};
|
42
|
+
export const addBatch = async (database, data) => {
|
43
|
+
const batch = await database.createDocument("migrations", "batches", ID.unique(), {
|
44
|
+
data,
|
45
|
+
processed: false,
|
46
|
+
});
|
47
|
+
return batch.$id;
|
48
|
+
};
|
49
|
+
export const getAfterImportOperations = async (database, collectionId, useMigrations = true) => {
|
50
|
+
if (!useMigrations) {
|
51
|
+
logger.info("Migrations disabled, returning empty operations list");
|
52
|
+
return [];
|
53
|
+
}
|
54
|
+
let lastDocumentId;
|
55
|
+
const allOperations = [];
|
56
|
+
let total = 0;
|
57
|
+
do {
|
58
|
+
const query = [
|
59
|
+
Query.equal("collectionId", collectionId),
|
60
|
+
Query.equal("operationType", "afterImportAction"),
|
61
|
+
Query.limit(100),
|
62
|
+
];
|
63
|
+
if (lastDocumentId) {
|
64
|
+
query.push(Query.cursorAfter(lastDocumentId));
|
65
|
+
}
|
66
|
+
const operations = await database.listDocuments("migrations", "currentOperations", query);
|
67
|
+
total = operations.total; // Update total with the latest fetch
|
68
|
+
allOperations.push(...operations.documents);
|
69
|
+
if (operations.documents.length > 0 && operations.documents.length >= 100) {
|
70
|
+
lastDocumentId =
|
71
|
+
operations.documents[operations.documents.length - 1].$id;
|
72
|
+
}
|
73
|
+
} while (allOperations.length < total);
|
74
|
+
const allOps = allOperations.map((op) => OperationSchema.parse(op));
|
75
|
+
return allOps;
|
76
|
+
};
|
77
|
+
export const findOrCreateOperation = async (database, collectionId, operationType, additionalQueries) => {
|
78
|
+
const operations = await tryAwaitWithRetry(async () => await database.listDocuments("migrations", "currentOperations", [
|
79
|
+
Query.equal("collectionId", collectionId),
|
80
|
+
Query.equal("operationType", operationType),
|
81
|
+
Query.equal("status", "pending"),
|
82
|
+
...(additionalQueries || []),
|
83
|
+
]));
|
84
|
+
if (operations.documents.length > 0) {
|
85
|
+
return OperationSchema.parse(operations.documents[0]); // Assuming the first document is the operation we want
|
86
|
+
}
|
87
|
+
else {
|
88
|
+
// Create a new operation document
|
89
|
+
const op = await tryAwaitWithRetry(async () => await database.createDocument("migrations", "currentOperations", ID.unique(), {
|
90
|
+
operationType,
|
91
|
+
collectionId,
|
92
|
+
status: "pending",
|
93
|
+
batches: [],
|
94
|
+
progress: 0,
|
95
|
+
total: 0,
|
96
|
+
error: "",
|
97
|
+
}));
|
98
|
+
return OperationSchema.parse(op);
|
99
|
+
}
|
100
|
+
};
|
101
|
+
export const updateOperation = async (database, operationId, updateFields, useMigrations = true) => {
|
102
|
+
if (!useMigrations) {
|
103
|
+
logger.info("Migrations disabled, skipping operation update");
|
104
|
+
return;
|
105
|
+
}
|
106
|
+
await tryAwaitWithRetry(async () => await database.updateDocument("migrations", "currentOperations", operationId, updateFields));
|
107
|
+
};
|
108
|
+
// Actual max 1073741824
|
109
|
+
export const maxDataLength = 1073741820;
|
110
|
+
export const maxBatchItems = 25;
|
111
|
+
export const splitIntoBatches = (data) => {
|
112
|
+
let batches = [];
|
113
|
+
let currentBatch = [];
|
114
|
+
let currentBatchLength = 0;
|
115
|
+
let currentBatchItemCount = 0;
|
116
|
+
data.forEach((item, index) => {
|
117
|
+
const itemLength = JSON.stringify(item).length;
|
118
|
+
if (itemLength > maxDataLength) {
|
119
|
+
console.log(item, `Large item found at index ${index} with length ${itemLength}:`);
|
120
|
+
}
|
121
|
+
// Check if adding the current item would exceed the max length or max items per batch
|
122
|
+
if (currentBatchLength + itemLength >= maxDataLength ||
|
123
|
+
currentBatchItemCount >= maxBatchItems) {
|
124
|
+
// If so, start a new batch
|
125
|
+
batches.push(currentBatch);
|
126
|
+
currentBatch = [item];
|
127
|
+
currentBatchLength = itemLength;
|
128
|
+
currentBatchItemCount = 1; // Reset item count for the new batch
|
129
|
+
}
|
130
|
+
else {
|
131
|
+
// Otherwise, add the item to the current batch
|
132
|
+
currentBatch.push(item);
|
133
|
+
currentBatchLength += itemLength;
|
134
|
+
currentBatchItemCount++;
|
135
|
+
}
|
136
|
+
});
|
137
|
+
// Don't forget to add the last batch if it's not empty
|
138
|
+
if (currentBatch.length > 0) {
|
139
|
+
batches.push(currentBatch);
|
140
|
+
}
|
141
|
+
return batches;
|
142
|
+
};
|
@@ -0,0 +1,3 @@
|
|
1
|
+
import type { Databases, Models } from "node-appwrite";
|
2
|
+
import type { OperationCreate } from "../storage/schemas.js";
|
3
|
+
export declare const logOperation: (db: Databases, dbId: string, operationDetails: OperationCreate, operationId?: string, useMigrations?: boolean) => Promise<Models.Document | null>;
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { tryAwaitWithRetry } from "appwrite-utils";
|
2
|
+
import { ulid } from "ulidx";
|
3
|
+
export const logOperation = async (db, dbId, operationDetails, operationId, useMigrations = true) => {
|
4
|
+
if (!useMigrations) {
|
5
|
+
console.log("Migrations disabled, skipping operation logging");
|
6
|
+
return null;
|
7
|
+
}
|
8
|
+
try {
|
9
|
+
let operation;
|
10
|
+
if (operationId) {
|
11
|
+
// Update existing operation log
|
12
|
+
operation = await tryAwaitWithRetry(async () => await db.updateDocument("migrations", "currentOperations", operationId, operationDetails));
|
13
|
+
}
|
14
|
+
else {
|
15
|
+
// Create new operation log
|
16
|
+
operation = await db.createDocument("migrations", "currentOperations", ulid(), operationDetails);
|
17
|
+
}
|
18
|
+
console.log(`Operation logged: ${operation.$id}`);
|
19
|
+
return operation;
|
20
|
+
}
|
21
|
+
catch (error) {
|
22
|
+
console.error(`Error logging operation: ${error}`);
|
23
|
+
throw error;
|
24
|
+
}
|
25
|
+
};
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { type Databases, type Models } from "node-appwrite";
|
2
|
+
import type { Attribute } from "appwrite-utils";
|
3
|
+
export interface QueuedOperation {
|
4
|
+
type: "attribute";
|
5
|
+
collectionId?: string;
|
6
|
+
attribute?: Attribute;
|
7
|
+
collection?: Models.Collection;
|
8
|
+
dependencies?: string[];
|
9
|
+
}
|
10
|
+
export declare const queuedOperations: QueuedOperation[];
|
11
|
+
export declare const nameToIdMapping: Map<string, string>;
|
12
|
+
export declare const enqueueOperation: (operation: QueuedOperation) => void;
|
13
|
+
export declare const processQueue: (db: Databases, dbId: string) => Promise<void>;
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import { Query } from "node-appwrite";
|
2
|
+
import { createOrUpdateAttribute } from "../collections/attributes.js";
|
3
|
+
import { fetchAndCacheCollectionByName } from "../collections/methods.js";
|
4
|
+
import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
5
|
+
export const queuedOperations = [];
|
6
|
+
export const nameToIdMapping = new Map();
|
7
|
+
export const enqueueOperation = (operation) => {
|
8
|
+
queuedOperations.push(operation);
|
9
|
+
};
|
10
|
+
export const processQueue = async (db, dbId) => {
|
11
|
+
console.log("---------------------------------");
|
12
|
+
console.log(`Starting Queue processing of ${dbId}`);
|
13
|
+
console.log("---------------------------------");
|
14
|
+
let progress = true;
|
15
|
+
while (progress) {
|
16
|
+
progress = false;
|
17
|
+
console.log("Processing queued operations:");
|
18
|
+
for (let i = 0; i < queuedOperations.length; i++) {
|
19
|
+
const operation = queuedOperations[i];
|
20
|
+
let collectionFound;
|
21
|
+
// Handle relationship attribute operations
|
22
|
+
if (operation.attribute?.type === "relationship") {
|
23
|
+
// Attempt to resolve the collection directly if collectionId is specified
|
24
|
+
if (operation.collectionId) {
|
25
|
+
console.log(`\tFetching collection by ID: ${operation.collectionId}`);
|
26
|
+
try {
|
27
|
+
collectionFound = await tryAwaitWithRetry(async () => await db.getCollection(dbId, operation.collectionId));
|
28
|
+
}
|
29
|
+
catch (e) {
|
30
|
+
console.log(`\tCollection not found by ID: ${operation.collectionId}`);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
// Attempt to resolve related collection if specified and not already found
|
34
|
+
if (!collectionFound && operation.attribute?.relatedCollection) {
|
35
|
+
collectionFound = await fetchAndCacheCollectionByName(db, dbId, operation.attribute.relatedCollection);
|
36
|
+
}
|
37
|
+
// Handle dependencies if collection still not found
|
38
|
+
if (!collectionFound) {
|
39
|
+
for (const dep of operation.dependencies || []) {
|
40
|
+
collectionFound = await fetchAndCacheCollectionByName(db, dbId, dep);
|
41
|
+
if (collectionFound)
|
42
|
+
break; // Break early if collection is found
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
else if (operation.collectionId) {
|
47
|
+
// Handle non-relationship operations with a specified collectionId
|
48
|
+
console.log(`\tFetching collection by ID: ${operation.collectionId}`);
|
49
|
+
try {
|
50
|
+
collectionFound = await tryAwaitWithRetry(async () => await db.getCollection(dbId, operation.collectionId));
|
51
|
+
}
|
52
|
+
catch (e) {
|
53
|
+
console.log(`\tCollection not found by ID: ${operation.collectionId}`);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
// Process the operation if the collection is found
|
57
|
+
if (collectionFound && operation.attribute) {
|
58
|
+
console.log(`\tProcessing attribute: ${operation.attribute.key} for collection ID: ${collectionFound.$id}`);
|
59
|
+
await createOrUpdateAttribute(db, dbId, collectionFound, operation.attribute);
|
60
|
+
queuedOperations.splice(i, 1);
|
61
|
+
i--; // Adjust index since we're modifying the array
|
62
|
+
progress = true;
|
63
|
+
}
|
64
|
+
else {
|
65
|
+
console.error(`\tCollection not found for operation, removing from queue: ${JSON.stringify(operation)}`);
|
66
|
+
queuedOperations.splice(i, 1);
|
67
|
+
i--; // Adjust index since we're modifying the array
|
68
|
+
}
|
69
|
+
}
|
70
|
+
console.log(`\tFinished processing queued operations`);
|
71
|
+
}
|
72
|
+
if (queuedOperations.length > 0) {
|
73
|
+
console.error("Unresolved operations remain due to unmet dependencies.");
|
74
|
+
console.log(queuedOperations);
|
75
|
+
}
|
76
|
+
console.log("---------------------------------");
|
77
|
+
console.log(`Queue processing complete for ${dbId}`);
|
78
|
+
console.log("---------------------------------");
|
79
|
+
};
|
@@ -0,0 +1,62 @@
|
|
1
|
+
export interface ProgressOptions {
|
2
|
+
title?: string;
|
3
|
+
showETA?: boolean;
|
4
|
+
showSpeed?: boolean;
|
5
|
+
showPercentage?: boolean;
|
6
|
+
width?: number;
|
7
|
+
format?: string;
|
8
|
+
}
|
9
|
+
export declare class ProgressManager {
|
10
|
+
private static instances;
|
11
|
+
private bar;
|
12
|
+
private startTime;
|
13
|
+
private totalItems;
|
14
|
+
private completed;
|
15
|
+
private id;
|
16
|
+
private title;
|
17
|
+
private constructor();
|
18
|
+
static create(id: string, total: number, options?: ProgressOptions): ProgressManager;
|
19
|
+
static get(id: string): ProgressManager | undefined;
|
20
|
+
update(current: number, detail?: string): void;
|
21
|
+
increment(amount?: number, detail?: string): void;
|
22
|
+
setTotal(total: number): void;
|
23
|
+
stop(showSummary?: boolean): void;
|
24
|
+
fail(error: string): void;
|
25
|
+
getStats(): {
|
26
|
+
completed: number;
|
27
|
+
total: number;
|
28
|
+
percentage: number;
|
29
|
+
duration: number;
|
30
|
+
rate: number;
|
31
|
+
remaining: number;
|
32
|
+
eta: number;
|
33
|
+
};
|
34
|
+
static stopAll(): void;
|
35
|
+
}
|
36
|
+
export declare class MultiProgressManager {
|
37
|
+
private multiBar;
|
38
|
+
private bars;
|
39
|
+
private startTime;
|
40
|
+
constructor(options?: ProgressOptions);
|
41
|
+
addTask(id: string, total: number, title: string): void;
|
42
|
+
updateTask(id: string, current: number, detail?: string): void;
|
43
|
+
incrementTask(id: string, amount?: number, detail?: string): void;
|
44
|
+
completeTask(id: string): void;
|
45
|
+
failTask(id: string, error: string): void;
|
46
|
+
stop(showSummary?: boolean): void;
|
47
|
+
getTaskStats(id: string): {
|
48
|
+
completed: number;
|
49
|
+
total: number;
|
50
|
+
percentage: number;
|
51
|
+
remaining: number;
|
52
|
+
} | null;
|
53
|
+
getAllStats(): Map<string, any>;
|
54
|
+
}
|
55
|
+
export declare const ProgressUtils: {
|
56
|
+
withProgress<T>(id: string, total: number, title: string, operation: (progress: ProgressManager) => Promise<T>): Promise<T>;
|
57
|
+
processArrayWithProgress<T, R>(items: T[], processor: (item: T, index: number) => Promise<R>, options?: {
|
58
|
+
title?: string;
|
59
|
+
batchSize?: number;
|
60
|
+
showDetail?: boolean;
|
61
|
+
}): Promise<R[]>;
|
62
|
+
};
|