appwrite-utils-cli 1.3.5 → 1.4.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/dist/adapters/AdapterFactory.d.ts +87 -0
- package/dist/adapters/AdapterFactory.js +217 -0
- package/dist/adapters/DatabaseAdapter.d.ts +217 -0
- package/dist/adapters/DatabaseAdapter.js +50 -0
- package/dist/adapters/LegacyAdapter.d.ts +49 -0
- package/dist/adapters/LegacyAdapter.js +382 -0
- package/dist/adapters/TablesDBAdapter.d.ts +55 -0
- package/dist/adapters/TablesDBAdapter.js +302 -0
- package/dist/adapters/index.d.ts +11 -0
- package/dist/adapters/index.js +12 -0
- package/dist/collections/attributes.js +41 -22
- package/dist/collections/methods.d.ts +4 -3
- package/dist/collections/methods.js +34 -14
- package/dist/config/yamlConfig.d.ts +40 -437
- package/dist/config/yamlConfig.js +8 -2
- package/dist/databases/setup.js +2 -2
- package/dist/main.js +0 -0
- package/dist/migrations/appwriteToX.d.ts +26 -37
- package/dist/migrations/comprehensiveTransfer.js +4 -4
- package/dist/migrations/dataLoader.d.ts +124 -1484
- package/dist/migrations/dataLoader.js +2 -1
- package/dist/migrations/relationships.d.ts +2 -3
- package/dist/migrations/relationships.js +1 -1
- package/dist/migrations/services/UserMappingService.js +1 -1
- package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +24 -279
- package/dist/migrations/yaml/YamlImportConfigLoader.js +7 -2
- package/dist/schemas/authUser.d.ts +7 -47
- package/dist/schemas/authUser.js +1 -1
- package/dist/shared/jsonSchemaGenerator.d.ts +0 -2
- package/dist/shared/jsonSchemaGenerator.js +4 -17
- package/dist/shared/migrationHelpers.d.ts +17 -119
- package/dist/shared/operationQueue.js +16 -7
- package/dist/shared/schemaGenerator.js +2 -17
- package/dist/storage/schemas.d.ts +149 -296
- package/dist/users/methods.d.ts +2 -2
- package/dist/utils/configMigration.js +0 -1
- package/dist/utils/getClientFromConfig.d.ts +26 -0
- package/dist/utils/getClientFromConfig.js +37 -0
- package/dist/utils/loadConfigs.js +0 -2
- package/dist/utils/schemaStrings.js +2 -17
- package/dist/utils/setupFiles.js +2 -0
- package/dist/utils/versionDetection.d.ts +56 -0
- package/dist/utils/versionDetection.js +217 -0
- package/dist/utils/yamlConverter.d.ts +0 -1
- package/dist/utils/yamlConverter.js +0 -2
- package/dist/utilsController.js +2 -0
- package/package.json +3 -2
- package/src/adapters/AdapterFactory.ts +296 -0
- package/src/adapters/DatabaseAdapter.ts +290 -0
- package/src/adapters/LegacyAdapter.ts +667 -0
- package/src/adapters/TablesDBAdapter.ts +429 -0
- package/src/adapters/index.ts +37 -0
- package/src/collections/attributes.ts +347 -153
- package/src/collections/methods.ts +43 -28
- package/src/config/yamlConfig.ts +8 -2
- package/src/databases/setup.ts +2 -2
- package/src/migrations/afterImportActions.ts +2 -2
- package/src/migrations/comprehensiveTransfer.ts +4 -0
- package/src/migrations/dataLoader.ts +2 -1
- package/src/migrations/relationships.ts +1 -1
- package/src/migrations/services/UserMappingService.ts +1 -1
- package/src/migrations/yaml/YamlImportConfigLoader.ts +7 -2
- package/src/schemas/authUser.ts +1 -1
- package/src/shared/jsonSchemaGenerator.ts +4 -19
- package/src/shared/operationQueue.ts +20 -13
- package/src/shared/schemaGenerator.ts +2 -16
- package/src/types/node-appwrite-tablesdb.d.ts +44 -0
- package/src/users/methods.ts +2 -2
- package/src/utils/configMigration.ts +0 -1
- package/src/utils/getClientFromConfig.ts +56 -0
- package/src/utils/loadConfigs.ts +0 -2
- package/src/utils/schemaStrings.ts +2 -16
- package/src/utils/setupFiles.ts +2 -0
- package/src/utils/versionDetection.ts +265 -0
- package/src/utils/yamlConverter.ts +0 -2
- package/src/utilsController.ts +2 -0
- package/dist/functions/openapi.d.ts +0 -4
- package/dist/functions/openapi.js +0 -60
- package/dist/migrations/attributes.d.ts +0 -4
- package/dist/migrations/attributes.js +0 -301
- package/dist/migrations/backup.d.ts +0 -687
- package/dist/migrations/backup.js +0 -175
- package/dist/migrations/collections.d.ts +0 -22
- package/dist/migrations/collections.js +0 -347
- package/dist/migrations/converters.d.ts +0 -46
- package/dist/migrations/converters.js +0 -139
- package/dist/migrations/databases.d.ts +0 -2
- package/dist/migrations/databases.js +0 -28
- package/dist/migrations/dbHelpers.d.ts +0 -5
- package/dist/migrations/dbHelpers.js +0 -57
- package/dist/migrations/helper.d.ts +0 -3
- package/dist/migrations/helper.js +0 -21
- package/dist/migrations/indexes.d.ts +0 -4
- package/dist/migrations/indexes.js +0 -19
- package/dist/migrations/logging.d.ts +0 -10
- package/dist/migrations/logging.js +0 -46
- package/dist/migrations/migrationHelper.d.ts +0 -173
- package/dist/migrations/migrationHelper.js +0 -130
- package/dist/migrations/openapi.d.ts +0 -4
- package/dist/migrations/openapi.js +0 -60
- package/dist/migrations/queue.d.ts +0 -13
- package/dist/migrations/queue.js +0 -79
- package/dist/migrations/schemaStrings.d.ts +0 -14
- package/dist/migrations/schemaStrings.js +0 -478
- package/dist/migrations/setupDatabase.d.ts +0 -6
- package/dist/migrations/setupDatabase.js +0 -115
- package/dist/migrations/storage.d.ts +0 -10
- package/dist/migrations/storage.js +0 -340
- package/dist/migrations/users.d.ts +0 -16
- package/dist/migrations/users.js +0 -276
- package/dist/migrations/validationRules.d.ts +0 -43
- package/dist/migrations/validationRules.js +0 -42
- package/dist/shared/attributeManager.d.ts +0 -17
- package/dist/shared/attributeManager.js +0 -272
- package/src/functions/openapi.ts +0 -83
- package/src/shared/attributeManager.ts +0 -428
@@ -1,139 +0,0 @@
|
|
1
|
-
import { converterFunctions } from "appwrite-utils";
|
2
|
-
import { cloneDeep, isPlainObject } from "es-toolkit";
|
3
|
-
/**
|
4
|
-
* Deeply converts all properties of an object (or array) to strings.
|
5
|
-
* @param data The input data to convert.
|
6
|
-
* @returns The data with all its properties converted to strings.
|
7
|
-
*/
|
8
|
-
export const deepAnyToString = (data) => {
|
9
|
-
if (Array.isArray(data)) {
|
10
|
-
return data.map((item) => deepAnyToString(item));
|
11
|
-
}
|
12
|
-
else if (isPlainObject(data)) {
|
13
|
-
return Object.keys(data).reduce((acc, key) => {
|
14
|
-
acc[key] = deepAnyToString(data[key]);
|
15
|
-
return acc;
|
16
|
-
}, {});
|
17
|
-
}
|
18
|
-
else {
|
19
|
-
return converterFunctions.anyToString(data);
|
20
|
-
}
|
21
|
-
};
|
22
|
-
/**
|
23
|
-
* Performs a deep conversion of all values in a nested structure to the specified type.
|
24
|
-
* Uses a conversion function like anyToString, anyToNumber, etc.
|
25
|
-
* @param data The data to convert.
|
26
|
-
* @param convertFn The conversion function to apply.
|
27
|
-
* @returns The converted data.
|
28
|
-
*/
|
29
|
-
export const deepConvert = (data, convertFn) => {
|
30
|
-
if (Array.isArray(data)) {
|
31
|
-
return data.map((item) => deepConvert(item, convertFn));
|
32
|
-
}
|
33
|
-
else if (isPlainObject(data)) {
|
34
|
-
return Object.keys(data).reduce((acc, key) => {
|
35
|
-
acc[key] = deepConvert(data[key], convertFn);
|
36
|
-
return acc;
|
37
|
-
}, {});
|
38
|
-
}
|
39
|
-
else {
|
40
|
-
return convertFn(data);
|
41
|
-
}
|
42
|
-
};
|
43
|
-
/**
|
44
|
-
* Converts an entire object's properties to different types based on a provided schema.
|
45
|
-
* @param obj The object to convert.
|
46
|
-
* @param schema A mapping of object keys to conversion functions.
|
47
|
-
* @returns The converted object.
|
48
|
-
*/
|
49
|
-
export const convertObjectBySchema = (obj, schema) => {
|
50
|
-
return Object.keys(obj).reduce((acc, key) => {
|
51
|
-
const convertFn = schema[key];
|
52
|
-
acc[key] = convertFn ? convertFn(obj[key]) : obj[key];
|
53
|
-
return acc;
|
54
|
-
}, {});
|
55
|
-
};
|
56
|
-
/**
|
57
|
-
* Converts the keys of an object based on a provided attributeMappings.
|
58
|
-
* Each key in the object is checked against attributeMappings; if a matching entry is found,
|
59
|
-
* the key is renamed to the targetKey specified in attributeMappings.
|
60
|
-
*
|
61
|
-
* @param obj The object to convert.
|
62
|
-
* @param attributeMappings The attributeMappings defining how keys in the object should be converted.
|
63
|
-
* @returns The converted object with keys renamed according to attributeMappings.
|
64
|
-
*/
|
65
|
-
export const convertObjectByAttributeMappings = (obj, attributeMappings) => {
|
66
|
-
const result = {};
|
67
|
-
// Correctly handle [any] notation by mapping or aggregating over all elements or keys
|
68
|
-
const resolveValue = (obj, path) => {
|
69
|
-
const parts = path.split(".");
|
70
|
-
let current = obj;
|
71
|
-
for (let i = 0; i < parts.length; i++) {
|
72
|
-
if (parts[i] === "[any]") {
|
73
|
-
if (Array.isArray(current)) {
|
74
|
-
// If current is an array, apply resolution to each item
|
75
|
-
return current.map((item) => resolveValue(item, parts.slice(i + 1).join(".")));
|
76
|
-
}
|
77
|
-
else if (typeof current === "object" && current !== null) {
|
78
|
-
// If current is an object, aggregate values from all keys
|
79
|
-
return Object.values(current).map((value) => resolveValue(value, parts.slice(i + 1).join(".")));
|
80
|
-
}
|
81
|
-
}
|
82
|
-
else {
|
83
|
-
current = current[parts[i]];
|
84
|
-
if (current === undefined)
|
85
|
-
return undefined;
|
86
|
-
}
|
87
|
-
}
|
88
|
-
return current;
|
89
|
-
};
|
90
|
-
for (const mapping of attributeMappings) {
|
91
|
-
if (mapping.valueToSet !== undefined) {
|
92
|
-
result[mapping.targetKey] = mapping.valueToSet;
|
93
|
-
}
|
94
|
-
else if (Array.isArray(mapping.oldKeys)) {
|
95
|
-
// Collect and flatten values from multiple oldKeys
|
96
|
-
const values = mapping.oldKeys
|
97
|
-
.map((oldKey) => resolveValue(obj, oldKey))
|
98
|
-
.flat(Infinity);
|
99
|
-
if (values.length > 0) {
|
100
|
-
result[mapping.targetKey] = values.filter((value) => value !== undefined);
|
101
|
-
}
|
102
|
-
else {
|
103
|
-
result[mapping.targetKey] = null;
|
104
|
-
}
|
105
|
-
}
|
106
|
-
else if (mapping.oldKey) {
|
107
|
-
// Resolve single oldKey
|
108
|
-
const value = resolveValue(obj, mapping.oldKey);
|
109
|
-
if (value !== undefined) {
|
110
|
-
result[mapping.targetKey] = Array.isArray(value)
|
111
|
-
? value.flat(Infinity)
|
112
|
-
: value;
|
113
|
-
}
|
114
|
-
else {
|
115
|
-
result[mapping.targetKey] = value ? value : null;
|
116
|
-
}
|
117
|
-
}
|
118
|
-
}
|
119
|
-
return result;
|
120
|
-
};
|
121
|
-
/**
|
122
|
-
* Ensures data conversion without mutating the original input.
|
123
|
-
* @param data The data to convert.
|
124
|
-
* @param convertFn The conversion function to apply.
|
125
|
-
* @returns The converted data.
|
126
|
-
*/
|
127
|
-
export const immutableConvert = (data, convertFn) => {
|
128
|
-
const clonedData = cloneDeep(data);
|
129
|
-
return convertFn(clonedData);
|
130
|
-
};
|
131
|
-
/**
|
132
|
-
* Validates a string against a regular expression and returns the string if valid, or null.
|
133
|
-
* @param value The string to validate.
|
134
|
-
* @param pattern The regex pattern to validate against.
|
135
|
-
* @returns The original string if valid, otherwise null.
|
136
|
-
*/
|
137
|
-
export const validateString = (value, pattern) => {
|
138
|
-
return pattern.test(value) ? value : null;
|
139
|
-
};
|
@@ -1,28 +0,0 @@
|
|
1
|
-
import { Client, Databases, IndexType, Query, } from "node-appwrite";
|
2
|
-
import { getAppwriteClient, tryAwaitWithRetry, } from "../utils/helperFunctions.js";
|
3
|
-
export const fetchAllDatabases = async (database) => {
|
4
|
-
const databases = await tryAwaitWithRetry(async () => await database.list([Query.limit(25)]));
|
5
|
-
if (!databases)
|
6
|
-
return [];
|
7
|
-
const allDatabases = databases.databases;
|
8
|
-
if (allDatabases.length === 0)
|
9
|
-
return [];
|
10
|
-
let lastDatabaseId = allDatabases[allDatabases.length - 1].$id;
|
11
|
-
if (databases.databases.length < 25) {
|
12
|
-
return allDatabases;
|
13
|
-
}
|
14
|
-
else {
|
15
|
-
while (lastDatabaseId) {
|
16
|
-
const databases = await database.list([
|
17
|
-
Query.limit(25),
|
18
|
-
Query.cursorAfter(lastDatabaseId),
|
19
|
-
]);
|
20
|
-
allDatabases.push(...databases.databases);
|
21
|
-
if (databases.databases.length < 25) {
|
22
|
-
break;
|
23
|
-
}
|
24
|
-
lastDatabaseId = databases.databases[databases.databases.length - 1].$id;
|
25
|
-
}
|
26
|
-
}
|
27
|
-
return allDatabases;
|
28
|
-
};
|
@@ -1,5 +0,0 @@
|
|
1
|
-
import type { AppwriteConfig, Attribute } from "appwrite-utils";
|
2
|
-
export declare const categorizeCollectionByRelationshipSide: (attributes: Attribute[]) => "parent" | "mixed" | "child";
|
3
|
-
export declare const getDependencies: (attributes: Attribute[]) => string[];
|
4
|
-
export declare const sortCollections: (configCollections: AppwriteConfig["collections"]) => AppwriteConfig["collections"];
|
5
|
-
export declare const sortAttributesByRelationshipSide: (attributes: Attribute[]) => Attribute[];
|
@@ -1,57 +0,0 @@
|
|
1
|
-
// Helper function to categorize collections based on relationship sides
|
2
|
-
export const categorizeCollectionByRelationshipSide = (attributes) => {
|
3
|
-
let hasParent = false;
|
4
|
-
let hasChild = false;
|
5
|
-
for (const attr of attributes) {
|
6
|
-
if (attr.type === "relationship") {
|
7
|
-
if (attr.side === "parent") {
|
8
|
-
hasParent = true;
|
9
|
-
}
|
10
|
-
else if (attr.side === "child") {
|
11
|
-
hasChild = true;
|
12
|
-
}
|
13
|
-
}
|
14
|
-
}
|
15
|
-
if (hasParent && hasChild)
|
16
|
-
return "mixed";
|
17
|
-
if (hasParent)
|
18
|
-
return "parent";
|
19
|
-
return "child";
|
20
|
-
};
|
21
|
-
// Helper function to get all dependencies of a collection
|
22
|
-
export const getDependencies = (attributes) => {
|
23
|
-
return attributes
|
24
|
-
.filter((attr) => attr.type === "relationship" && attr.relatedCollection !== undefined)
|
25
|
-
.map((attr) => attr.relatedCollection);
|
26
|
-
};
|
27
|
-
// Function to sort collections based on dependencies and relationship sides
|
28
|
-
export const sortCollections = (configCollections) => {
|
29
|
-
if (!configCollections) {
|
30
|
-
return [];
|
31
|
-
}
|
32
|
-
// Categorize collections based on their relationship sides
|
33
|
-
const parentCollections = configCollections.filter(({ attributes }) => categorizeCollectionByRelationshipSide(attributes) === "parent");
|
34
|
-
const mixedCollections = configCollections.filter(({ attributes }) => categorizeCollectionByRelationshipSide(attributes) === "mixed");
|
35
|
-
const childCollections = configCollections.filter(({ attributes }) => categorizeCollectionByRelationshipSide(attributes) === "child");
|
36
|
-
// Sort mixedCollections to ensure parents are processed before children within the mixed category
|
37
|
-
// This might involve more sophisticated logic if you need to order mixed collections based on specific parent-child relationships
|
38
|
-
mixedCollections.sort((a, b) => {
|
39
|
-
// Example sorting logic for mixed collections; adjust based on your specific needs
|
40
|
-
const aDependencies = getDependencies(a.attributes).length;
|
41
|
-
const bDependencies = getDependencies(b.attributes).length;
|
42
|
-
return aDependencies - bDependencies;
|
43
|
-
});
|
44
|
-
// Combine them back into a single array with the desired order
|
45
|
-
// Children first because they have no dependencies and parents will create the relationship if it's twoWay
|
46
|
-
return [...childCollections, ...parentCollections, ...mixedCollections];
|
47
|
-
};
|
48
|
-
// Function to sort attributes within a collection based on relationship sides
|
49
|
-
export const sortAttributesByRelationshipSide = (attributes) => {
|
50
|
-
// Separate attributes into parent and child based on their relationship side
|
51
|
-
const parentAttributes = attributes.filter((attr) => attr.type === "relationship" && attr.side === "parent");
|
52
|
-
const childAttributes = attributes.filter((attr) => attr.type === "relationship" && attr.side === "child");
|
53
|
-
const otherAttributes = attributes.filter((attr) => attr.type !== "relationship");
|
54
|
-
// Combine them back into a single array with child attributes first, then other attributes, and parent attributes last
|
55
|
-
// as parent attributes will create the relationship with the child if needed
|
56
|
-
return [...childAttributes, ...otherAttributes, ...parentAttributes];
|
57
|
-
};
|
@@ -1,21 +0,0 @@
|
|
1
|
-
import { tryAwaitWithRetry } from "appwrite-utils";
|
2
|
-
import { ulid } from "ulidx";
|
3
|
-
export const logOperation = async (db, dbId, operationDetails, operationId) => {
|
4
|
-
try {
|
5
|
-
let operation;
|
6
|
-
if (operationId) {
|
7
|
-
// Update existing operation log
|
8
|
-
operation = await tryAwaitWithRetry(async () => await db.updateDocument("migrations", "currentOperations", operationId, operationDetails));
|
9
|
-
}
|
10
|
-
else {
|
11
|
-
// Create new operation log
|
12
|
-
operation = await db.createDocument("migrations", "currentOperations", ulid(), operationDetails);
|
13
|
-
}
|
14
|
-
console.log(`Operation logged: ${operation.$id}`);
|
15
|
-
return operation;
|
16
|
-
}
|
17
|
-
catch (error) {
|
18
|
-
console.error(`Error logging operation: ${error}`);
|
19
|
-
throw error;
|
20
|
-
}
|
21
|
-
};
|
@@ -1,4 +0,0 @@
|
|
1
|
-
import { type Index } from "appwrite-utils";
|
2
|
-
import { Databases, type Models } from "node-appwrite";
|
3
|
-
export declare const createOrUpdateIndex: (dbId: string, db: Databases, collectionId: string, index: Index) => Promise<Models.Index>;
|
4
|
-
export declare const createOrUpdateIndexes: (dbId: string, db: Databases, collectionId: string, indexes: Index[]) => Promise<void>;
|
@@ -1,19 +0,0 @@
|
|
1
|
-
import { indexSchema } from "appwrite-utils";
|
2
|
-
import { Databases, IndexType, Query } from "node-appwrite";
|
3
|
-
import { tryAwaitWithRetry } from "../utils/helperFunctions.js";
|
4
|
-
// import {}
|
5
|
-
export const createOrUpdateIndex = async (dbId, db, collectionId, index) => {
|
6
|
-
const existingIndex = await db.listIndexes(dbId, collectionId, [
|
7
|
-
Query.equal("key", index.key),
|
8
|
-
]);
|
9
|
-
if (existingIndex.total > 0) {
|
10
|
-
await db.deleteIndex(dbId, collectionId, existingIndex.indexes[0].key);
|
11
|
-
}
|
12
|
-
const newIndex = await db.createIndex(dbId, collectionId, index.key, index.type, index.attributes, index.orders);
|
13
|
-
return newIndex;
|
14
|
-
};
|
15
|
-
export const createOrUpdateIndexes = async (dbId, db, collectionId, indexes) => {
|
16
|
-
for (const index of indexes) {
|
17
|
-
await tryAwaitWithRetry(async () => await createOrUpdateIndex(dbId, db, collectionId, index));
|
18
|
-
}
|
19
|
-
};
|
@@ -1,10 +0,0 @@
|
|
1
|
-
import winston from "winston";
|
2
|
-
export interface LoggingConfig {
|
3
|
-
enabled: boolean;
|
4
|
-
level: string;
|
5
|
-
logDirectory?: string;
|
6
|
-
console: boolean;
|
7
|
-
}
|
8
|
-
export declare const configureLogging: (config?: Partial<LoggingConfig>) => void;
|
9
|
-
export declare let logger: winston.Logger;
|
10
|
-
export declare const updateLogger: () => void;
|
@@ -1,46 +0,0 @@
|
|
1
|
-
import winston from "winston";
|
2
|
-
import fs from "fs";
|
3
|
-
import path from "path";
|
4
|
-
const DEFAULT_LOGGING_CONFIG = {
|
5
|
-
enabled: false,
|
6
|
-
level: "info",
|
7
|
-
console: false,
|
8
|
-
};
|
9
|
-
let loggingConfig = DEFAULT_LOGGING_CONFIG;
|
10
|
-
export const configureLogging = (config = {}) => {
|
11
|
-
loggingConfig = { ...DEFAULT_LOGGING_CONFIG, ...config };
|
12
|
-
};
|
13
|
-
const createLogger = () => {
|
14
|
-
const transports = [];
|
15
|
-
// Add console transport if enabled
|
16
|
-
if (loggingConfig.console) {
|
17
|
-
transports.push(new winston.transports.Console({
|
18
|
-
format: winston.format.combine(winston.format.colorize(), winston.format.simple())
|
19
|
-
}));
|
20
|
-
}
|
21
|
-
// Add file transports if logging is enabled
|
22
|
-
if (loggingConfig.enabled) {
|
23
|
-
const logDir = loggingConfig.logDirectory || path.join(process.cwd(), "zlogs");
|
24
|
-
if (!fs.existsSync(logDir)) {
|
25
|
-
fs.mkdirSync(logDir, { recursive: true });
|
26
|
-
}
|
27
|
-
transports.push(new winston.transports.File({
|
28
|
-
filename: path.join(logDir, "error.log"),
|
29
|
-
level: "error",
|
30
|
-
}), new winston.transports.File({
|
31
|
-
filename: path.join(logDir, "combined.log"),
|
32
|
-
}));
|
33
|
-
}
|
34
|
-
return winston.createLogger({
|
35
|
-
level: loggingConfig.level,
|
36
|
-
format: winston.format.combine(winston.format.timestamp(), winston.format.errors({ stack: true }), winston.format.json()),
|
37
|
-
defaultMeta: { service: "appwrite-utils-cli" },
|
38
|
-
transports,
|
39
|
-
silent: !loggingConfig.enabled && !loggingConfig.console,
|
40
|
-
});
|
41
|
-
};
|
42
|
-
export let logger = createLogger();
|
43
|
-
// Recreate logger when config changes
|
44
|
-
export const updateLogger = () => {
|
45
|
-
logger = createLogger();
|
46
|
-
};
|
@@ -1,173 +0,0 @@
|
|
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) => Promise<void>;
|
143
|
-
export declare const addBatch: (database: Databases, data: string) => Promise<string>;
|
144
|
-
export declare const getAfterImportOperations: (database: Databases, collectionId: string) => 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) => Promise<void>;
|
171
|
-
export declare const maxDataLength = 1073741820;
|
172
|
-
export declare const maxBatchItems = 25;
|
173
|
-
export declare const splitIntoBatches: (data: any[]) => any[][];
|
@@ -1,130 +0,0 @@
|
|
1
|
-
import { ID, Query } from "node-appwrite";
|
2
|
-
import { BatchSchema, OperationSchema } from "./backup.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) => {
|
26
|
-
let operation = await findOrCreateOperation(database, collectionId, "afterImportAction");
|
27
|
-
if (!operation.batches) {
|
28
|
-
operation.batches = [];
|
29
|
-
}
|
30
|
-
// Directly create a new batch for the context without checking for an existing batch
|
31
|
-
const contextData = JSON.stringify(context);
|
32
|
-
// Create a new batch with the contextData
|
33
|
-
const newBatchId = await addBatch(database, contextData);
|
34
|
-
// Update the operation with the new batch's $id
|
35
|
-
operation.batches = [...operation.batches, newBatchId];
|
36
|
-
await database.updateDocument("migrations", "currentOperations", operation.$id, { batches: operation.batches });
|
37
|
-
};
|
38
|
-
export const addBatch = async (database, data) => {
|
39
|
-
const batch = await database.createDocument("migrations", "batches", ID.unique(), {
|
40
|
-
data,
|
41
|
-
processed: false,
|
42
|
-
});
|
43
|
-
return batch.$id;
|
44
|
-
};
|
45
|
-
export const getAfterImportOperations = async (database, collectionId) => {
|
46
|
-
let lastDocumentId;
|
47
|
-
const allOperations = [];
|
48
|
-
let total = 0;
|
49
|
-
do {
|
50
|
-
const query = [
|
51
|
-
Query.equal("collectionId", collectionId),
|
52
|
-
Query.equal("operationType", "afterImportAction"),
|
53
|
-
Query.limit(100),
|
54
|
-
];
|
55
|
-
if (lastDocumentId) {
|
56
|
-
query.push(Query.cursorAfter(lastDocumentId));
|
57
|
-
}
|
58
|
-
const operations = await database.listDocuments("migrations", "currentOperations", query);
|
59
|
-
total = operations.total; // Update total with the latest fetch
|
60
|
-
allOperations.push(...operations.documents);
|
61
|
-
if (operations.documents.length > 0 && operations.documents.length >= 100) {
|
62
|
-
lastDocumentId =
|
63
|
-
operations.documents[operations.documents.length - 1].$id;
|
64
|
-
}
|
65
|
-
} while (allOperations.length < total);
|
66
|
-
const allOps = allOperations.map((op) => OperationSchema.parse(op));
|
67
|
-
return allOps;
|
68
|
-
};
|
69
|
-
export const findOrCreateOperation = async (database, collectionId, operationType, additionalQueries) => {
|
70
|
-
const operations = await tryAwaitWithRetry(async () => await database.listDocuments("migrations", "currentOperations", [
|
71
|
-
Query.equal("collectionId", collectionId),
|
72
|
-
Query.equal("operationType", operationType),
|
73
|
-
Query.equal("status", "pending"),
|
74
|
-
...(additionalQueries || []),
|
75
|
-
]));
|
76
|
-
if (operations.documents.length > 0) {
|
77
|
-
return OperationSchema.parse(operations.documents[0]); // Assuming the first document is the operation we want
|
78
|
-
}
|
79
|
-
else {
|
80
|
-
// Create a new operation document
|
81
|
-
const op = await tryAwaitWithRetry(async () => await database.createDocument("migrations", "currentOperations", ID.unique(), {
|
82
|
-
operationType,
|
83
|
-
collectionId,
|
84
|
-
status: "pending",
|
85
|
-
batches: [],
|
86
|
-
progress: 0,
|
87
|
-
total: 0,
|
88
|
-
error: "",
|
89
|
-
}));
|
90
|
-
return OperationSchema.parse(op);
|
91
|
-
}
|
92
|
-
};
|
93
|
-
export const updateOperation = async (database, operationId, updateFields) => {
|
94
|
-
await tryAwaitWithRetry(async () => await database.updateDocument("migrations", "currentOperations", operationId, updateFields));
|
95
|
-
};
|
96
|
-
// Actual max 1073741824
|
97
|
-
export const maxDataLength = 1073741820;
|
98
|
-
export const maxBatchItems = 25;
|
99
|
-
export const splitIntoBatches = (data) => {
|
100
|
-
let batches = [];
|
101
|
-
let currentBatch = [];
|
102
|
-
let currentBatchLength = 0;
|
103
|
-
let currentBatchItemCount = 0;
|
104
|
-
data.forEach((item, index) => {
|
105
|
-
const itemLength = JSON.stringify(item).length;
|
106
|
-
if (itemLength > maxDataLength) {
|
107
|
-
console.log(item, `Large item found at index ${index} with length ${itemLength}:`);
|
108
|
-
}
|
109
|
-
// Check if adding the current item would exceed the max length or max items per batch
|
110
|
-
if (currentBatchLength + itemLength >= maxDataLength ||
|
111
|
-
currentBatchItemCount >= maxBatchItems) {
|
112
|
-
// If so, start a new batch
|
113
|
-
batches.push(currentBatch);
|
114
|
-
currentBatch = [item];
|
115
|
-
currentBatchLength = itemLength;
|
116
|
-
currentBatchItemCount = 1; // Reset item count for the new batch
|
117
|
-
}
|
118
|
-
else {
|
119
|
-
// Otherwise, add the item to the current batch
|
120
|
-
currentBatch.push(item);
|
121
|
-
currentBatchLength += itemLength;
|
122
|
-
currentBatchItemCount++;
|
123
|
-
}
|
124
|
-
});
|
125
|
-
// Don't forget to add the last batch if it's not empty
|
126
|
-
if (currentBatch.length > 0) {
|
127
|
-
batches.push(currentBatch);
|
128
|
-
}
|
129
|
-
return batches;
|
130
|
-
};
|
@@ -1,4 +0,0 @@
|
|
1
|
-
import { type AppwriteConfig } from "appwrite-utils";
|
2
|
-
import { z } from "zod";
|
3
|
-
export declare const generateOpenApi: (config: AppwriteConfig) => Promise<void>;
|
4
|
-
export declare function transformTypeToOpenApi<T extends z.ZodTypeAny>(schema: T, description?: string | Record<string, any> | null | undefined): T;
|