appwrite-utils-cli 0.0.32 → 0.0.34
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 +103 -97
- package/dist/migrations/backup.d.ts +2 -0
- package/dist/migrations/dataLoader.d.ts +40 -4
- package/dist/migrations/dataLoader.js +119 -126
- package/dist/migrations/importController.js +54 -50
- package/dist/migrations/schemaStrings.js +38 -38
- package/dist/migrations/users.js +4 -0
- package/package.json +54 -54
- package/src/main.ts +83 -83
- package/src/migrations/dataLoader.ts +140 -169
- package/src/migrations/importController.ts +62 -63
- package/src/migrations/openapi.ts +83 -83
- package/src/migrations/schemaStrings.ts +473 -473
- package/src/migrations/users.ts +4 -0
- package/src/utilsController.ts +194 -194
package/src/migrations/users.ts
CHANGED
|
@@ -78,6 +78,9 @@ export class UsersController {
|
|
|
78
78
|
async getAllUsers() {
|
|
79
79
|
const allUsers: Models.User<Models.Preferences>[] = [];
|
|
80
80
|
const users = await this.users.list([Query.limit(200)]);
|
|
81
|
+
if (users.users.length === 0) {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
81
84
|
if (users.users.length === 200) {
|
|
82
85
|
let lastDocumentId = users.users[users.users.length - 1].$id;
|
|
83
86
|
allUsers.push(...users.users);
|
|
@@ -129,6 +132,7 @@ export class UsersController {
|
|
|
129
132
|
if (e instanceof Error) {
|
|
130
133
|
logger.error("FAILED CREATING USER: ", e.message);
|
|
131
134
|
}
|
|
135
|
+
console.log("FAILED CREATING USER: ", e);
|
|
132
136
|
throw e;
|
|
133
137
|
}
|
|
134
138
|
}
|
package/src/utilsController.ts
CHANGED
|
@@ -1,194 +1,194 @@
|
|
|
1
|
-
import { Client, Databases, Storage } from "node-appwrite";
|
|
2
|
-
import { startSetup } from "./migrations/setupDatabase.js";
|
|
3
|
-
import path from "path";
|
|
4
|
-
import fs from "fs";
|
|
5
|
-
import { load } from "js-yaml";
|
|
6
|
-
import { ImportDataActions } from "./migrations/importDataActions.js";
|
|
7
|
-
import { readFileSync } from "./utils/helperFunctions.js";
|
|
8
|
-
import { afterImportActions } from "./migrations/afterImportActions.js";
|
|
9
|
-
import {
|
|
10
|
-
type AfterImportActions,
|
|
11
|
-
type ConverterFunctions,
|
|
12
|
-
converterFunctions,
|
|
13
|
-
validationRules,
|
|
14
|
-
type ValidationRules,
|
|
15
|
-
type AppwriteConfig,
|
|
16
|
-
AppwriteConfigSchema,
|
|
17
|
-
} from "appwrite-utils";
|
|
18
|
-
import { ImportController } from "./migrations/importController.js";
|
|
19
|
-
import _ from "lodash";
|
|
20
|
-
import { AppwriteToX } from "./migrations/appwriteToX.js";
|
|
21
|
-
import { loadConfig as loadTsConfig } from "./utils/loadConfigs.js";
|
|
22
|
-
import { findAppwriteConfig } from "./utils/loadConfigs.js";
|
|
23
|
-
|
|
24
|
-
// async function loadConfig(configPath: string) {
|
|
25
|
-
// if (!fs.existsSync(configPath)) {
|
|
26
|
-
// throw new Error(`Configuration file not found at ${configPath}`);
|
|
27
|
-
// }
|
|
28
|
-
// const configModule = await load(readFileSync(configPath), {
|
|
29
|
-
// json: true,
|
|
30
|
-
// });
|
|
31
|
-
// return AppwriteConfigSchema.parse(configModule);
|
|
32
|
-
// }
|
|
33
|
-
|
|
34
|
-
export interface SetupOptions {
|
|
35
|
-
sync: boolean;
|
|
36
|
-
runProd: boolean;
|
|
37
|
-
runStaging: boolean;
|
|
38
|
-
runDev: boolean;
|
|
39
|
-
doBackup: boolean;
|
|
40
|
-
wipeDatabases: boolean;
|
|
41
|
-
wipeDocumentStorage: boolean;
|
|
42
|
-
wipeUsers: boolean;
|
|
43
|
-
generateSchemas: boolean;
|
|
44
|
-
generateMockData: boolean;
|
|
45
|
-
importData: boolean;
|
|
46
|
-
checkDuplicates: boolean;
|
|
47
|
-
shouldWriteFile: boolean;
|
|
48
|
-
endpoint?: string;
|
|
49
|
-
project?: string;
|
|
50
|
-
key?: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export class UtilsController {
|
|
54
|
-
private appwriteFolderPath: string;
|
|
55
|
-
private appwriteConfigPath: string;
|
|
56
|
-
private config?: AppwriteConfig;
|
|
57
|
-
private appwriteServer?: Client;
|
|
58
|
-
private database?: Databases;
|
|
59
|
-
private storage?: Storage;
|
|
60
|
-
public converterDefinitions: ConverterFunctions = converterFunctions;
|
|
61
|
-
public validityRuleDefinitions: ValidationRules = validationRules;
|
|
62
|
-
public afterImportActionsDefinitions: AfterImportActions = afterImportActions;
|
|
63
|
-
|
|
64
|
-
constructor(currentUserDir: string) {
|
|
65
|
-
const basePath = currentUserDir; // Gets the current working directory
|
|
66
|
-
const appwriteConfigFound = findAppwriteConfig(basePath);
|
|
67
|
-
if (!appwriteConfigFound) {
|
|
68
|
-
throw new Error("Failed to find appwriteConfig.ts");
|
|
69
|
-
}
|
|
70
|
-
this.appwriteConfigPath = appwriteConfigFound;
|
|
71
|
-
this.appwriteFolderPath = path.dirname(appwriteConfigFound);
|
|
72
|
-
if (!this.appwriteFolderPath) {
|
|
73
|
-
throw new Error("Failed to get appwriteFolderPath");
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// async loadCustomDefinitions(): Promise<void> {
|
|
78
|
-
// try {
|
|
79
|
-
// const customDefinitionsPath = path.join(
|
|
80
|
-
// this.appwriteFolderPath,
|
|
81
|
-
// "customDefinitions.ts"
|
|
82
|
-
// );
|
|
83
|
-
// if (fs.existsSync(customDefinitionsPath)) {
|
|
84
|
-
// // Dynamically import custom definitions
|
|
85
|
-
// const customDefinitions = (await import(
|
|
86
|
-
// customDefinitionsPath
|
|
87
|
-
// )) as typeof import("customDefinitions");
|
|
88
|
-
// this.converterDefinitions = {
|
|
89
|
-
// ...this.converterDefinitions,
|
|
90
|
-
// ...customDefinitions.converterDefinitions,
|
|
91
|
-
// };
|
|
92
|
-
// this.validityRuleDefinitions = {
|
|
93
|
-
// ...this.validityRuleDefinitions,
|
|
94
|
-
// ...customDefinitions.validityRuleDefinitions,
|
|
95
|
-
// };
|
|
96
|
-
// this.afterImportActionsDefinitions = {
|
|
97
|
-
// ...this.afterImportActionsDefinitions,
|
|
98
|
-
// ...customDefinitions.afterImportActionsDefinitions,
|
|
99
|
-
// };
|
|
100
|
-
// }
|
|
101
|
-
// } catch (error) {
|
|
102
|
-
// console.error("Failed to load custom definitions:", error);
|
|
103
|
-
// }
|
|
104
|
-
// }
|
|
105
|
-
|
|
106
|
-
async init(setupOptions: SetupOptions) {
|
|
107
|
-
if (!this.config) {
|
|
108
|
-
console.log("Initializing appwrite client & loading config...");
|
|
109
|
-
this.config = await loadTsConfig(this.appwriteFolderPath);
|
|
110
|
-
if (!this.config) {
|
|
111
|
-
throw new Error("Failed to load config");
|
|
112
|
-
}
|
|
113
|
-
this.appwriteServer = new Client();
|
|
114
|
-
if (setupOptions.endpoint) {
|
|
115
|
-
if (!setupOptions.project || !setupOptions.key) {
|
|
116
|
-
throw new Error(
|
|
117
|
-
"Project ID and API key required when setting endpoint"
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
this.appwriteServer
|
|
121
|
-
.setEndpoint(setupOptions.endpoint)
|
|
122
|
-
.setProject(setupOptions.project)
|
|
123
|
-
.setKey(setupOptions.key);
|
|
124
|
-
} else {
|
|
125
|
-
this.appwriteServer
|
|
126
|
-
.setEndpoint(this.config.appwriteEndpoint)
|
|
127
|
-
.setProject(this.config.appwriteProject)
|
|
128
|
-
.setKey(this.config.appwriteKey);
|
|
129
|
-
}
|
|
130
|
-
this.database = new Databases(this.appwriteServer);
|
|
131
|
-
this.storage = new Storage(this.appwriteServer);
|
|
132
|
-
this.config.appwriteClient = this.appwriteServer;
|
|
133
|
-
// await this.loadCustomDefinitions();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async run(options: SetupOptions) {
|
|
138
|
-
await this.init(options); // Ensure initialization is done
|
|
139
|
-
if (!this.database || !this.storage || !this.config) {
|
|
140
|
-
throw new Error("Database or storage not initialized");
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (options.sync) {
|
|
144
|
-
console.log("Starting synchronization with server...");
|
|
145
|
-
const appwriteToX = new AppwriteToX(this.config, this.appwriteFolderPath);
|
|
146
|
-
await appwriteToX.toSchemas();
|
|
147
|
-
console.log("Synchronization complete, YAML and Schemas updated");
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Start the setup
|
|
151
|
-
console.log(
|
|
152
|
-
"Starting setup, this step sets up migrations, runs backup, wipes databases, and updates schemas (depending on your options)..."
|
|
153
|
-
);
|
|
154
|
-
await startSetup(
|
|
155
|
-
this.database,
|
|
156
|
-
this.storage,
|
|
157
|
-
this.config,
|
|
158
|
-
options,
|
|
159
|
-
this.appwriteFolderPath
|
|
160
|
-
);
|
|
161
|
-
console.log("Setup complete.");
|
|
162
|
-
|
|
163
|
-
if (options.generateMockData) {
|
|
164
|
-
// TODO: Figure out how to do this dynamically
|
|
165
|
-
// await this.generateMockData();
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (options.importData) {
|
|
169
|
-
console.log("Starting import data...");
|
|
170
|
-
const importDataActions = new ImportDataActions(
|
|
171
|
-
this.database,
|
|
172
|
-
this.storage,
|
|
173
|
-
this.config,
|
|
174
|
-
this.converterDefinitions,
|
|
175
|
-
this.validityRuleDefinitions,
|
|
176
|
-
this.afterImportActionsDefinitions
|
|
177
|
-
);
|
|
178
|
-
const importController = new ImportController(
|
|
179
|
-
this.config!,
|
|
180
|
-
this.database!,
|
|
181
|
-
this.storage!,
|
|
182
|
-
this.appwriteFolderPath,
|
|
183
|
-
importDataActions,
|
|
184
|
-
options
|
|
185
|
-
);
|
|
186
|
-
await importController.run();
|
|
187
|
-
console.log("Import data complete.");
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// if (options.checkDuplicates) {
|
|
191
|
-
// await this.checkDuplicates();
|
|
192
|
-
// }
|
|
193
|
-
}
|
|
194
|
-
}
|
|
1
|
+
import { Client, Databases, Storage } from "node-appwrite";
|
|
2
|
+
import { startSetup } from "./migrations/setupDatabase.js";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import { load } from "js-yaml";
|
|
6
|
+
import { ImportDataActions } from "./migrations/importDataActions.js";
|
|
7
|
+
import { readFileSync } from "./utils/helperFunctions.js";
|
|
8
|
+
import { afterImportActions } from "./migrations/afterImportActions.js";
|
|
9
|
+
import {
|
|
10
|
+
type AfterImportActions,
|
|
11
|
+
type ConverterFunctions,
|
|
12
|
+
converterFunctions,
|
|
13
|
+
validationRules,
|
|
14
|
+
type ValidationRules,
|
|
15
|
+
type AppwriteConfig,
|
|
16
|
+
AppwriteConfigSchema,
|
|
17
|
+
} from "appwrite-utils";
|
|
18
|
+
import { ImportController } from "./migrations/importController.js";
|
|
19
|
+
import _ from "lodash";
|
|
20
|
+
import { AppwriteToX } from "./migrations/appwriteToX.js";
|
|
21
|
+
import { loadConfig as loadTsConfig } from "./utils/loadConfigs.js";
|
|
22
|
+
import { findAppwriteConfig } from "./utils/loadConfigs.js";
|
|
23
|
+
|
|
24
|
+
// async function loadConfig(configPath: string) {
|
|
25
|
+
// if (!fs.existsSync(configPath)) {
|
|
26
|
+
// throw new Error(`Configuration file not found at ${configPath}`);
|
|
27
|
+
// }
|
|
28
|
+
// const configModule = await load(readFileSync(configPath), {
|
|
29
|
+
// json: true,
|
|
30
|
+
// });
|
|
31
|
+
// return AppwriteConfigSchema.parse(configModule);
|
|
32
|
+
// }
|
|
33
|
+
|
|
34
|
+
export interface SetupOptions {
|
|
35
|
+
sync: boolean;
|
|
36
|
+
runProd: boolean;
|
|
37
|
+
runStaging: boolean;
|
|
38
|
+
runDev: boolean;
|
|
39
|
+
doBackup: boolean;
|
|
40
|
+
wipeDatabases: boolean;
|
|
41
|
+
wipeDocumentStorage: boolean;
|
|
42
|
+
wipeUsers: boolean;
|
|
43
|
+
generateSchemas: boolean;
|
|
44
|
+
generateMockData: boolean;
|
|
45
|
+
importData: boolean;
|
|
46
|
+
checkDuplicates: boolean;
|
|
47
|
+
shouldWriteFile: boolean;
|
|
48
|
+
endpoint?: string;
|
|
49
|
+
project?: string;
|
|
50
|
+
key?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export class UtilsController {
|
|
54
|
+
private appwriteFolderPath: string;
|
|
55
|
+
private appwriteConfigPath: string;
|
|
56
|
+
private config?: AppwriteConfig;
|
|
57
|
+
private appwriteServer?: Client;
|
|
58
|
+
private database?: Databases;
|
|
59
|
+
private storage?: Storage;
|
|
60
|
+
public converterDefinitions: ConverterFunctions = converterFunctions;
|
|
61
|
+
public validityRuleDefinitions: ValidationRules = validationRules;
|
|
62
|
+
public afterImportActionsDefinitions: AfterImportActions = afterImportActions;
|
|
63
|
+
|
|
64
|
+
constructor(currentUserDir: string) {
|
|
65
|
+
const basePath = currentUserDir; // Gets the current working directory
|
|
66
|
+
const appwriteConfigFound = findAppwriteConfig(basePath);
|
|
67
|
+
if (!appwriteConfigFound) {
|
|
68
|
+
throw new Error("Failed to find appwriteConfig.ts");
|
|
69
|
+
}
|
|
70
|
+
this.appwriteConfigPath = appwriteConfigFound;
|
|
71
|
+
this.appwriteFolderPath = path.dirname(appwriteConfigFound);
|
|
72
|
+
if (!this.appwriteFolderPath) {
|
|
73
|
+
throw new Error("Failed to get appwriteFolderPath");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// async loadCustomDefinitions(): Promise<void> {
|
|
78
|
+
// try {
|
|
79
|
+
// const customDefinitionsPath = path.join(
|
|
80
|
+
// this.appwriteFolderPath,
|
|
81
|
+
// "customDefinitions.ts"
|
|
82
|
+
// );
|
|
83
|
+
// if (fs.existsSync(customDefinitionsPath)) {
|
|
84
|
+
// // Dynamically import custom definitions
|
|
85
|
+
// const customDefinitions = (await import(
|
|
86
|
+
// customDefinitionsPath
|
|
87
|
+
// )) as typeof import("customDefinitions");
|
|
88
|
+
// this.converterDefinitions = {
|
|
89
|
+
// ...this.converterDefinitions,
|
|
90
|
+
// ...customDefinitions.converterDefinitions,
|
|
91
|
+
// };
|
|
92
|
+
// this.validityRuleDefinitions = {
|
|
93
|
+
// ...this.validityRuleDefinitions,
|
|
94
|
+
// ...customDefinitions.validityRuleDefinitions,
|
|
95
|
+
// };
|
|
96
|
+
// this.afterImportActionsDefinitions = {
|
|
97
|
+
// ...this.afterImportActionsDefinitions,
|
|
98
|
+
// ...customDefinitions.afterImportActionsDefinitions,
|
|
99
|
+
// };
|
|
100
|
+
// }
|
|
101
|
+
// } catch (error) {
|
|
102
|
+
// console.error("Failed to load custom definitions:", error);
|
|
103
|
+
// }
|
|
104
|
+
// }
|
|
105
|
+
|
|
106
|
+
async init(setupOptions: SetupOptions) {
|
|
107
|
+
if (!this.config) {
|
|
108
|
+
console.log("Initializing appwrite client & loading config...");
|
|
109
|
+
this.config = await loadTsConfig(this.appwriteFolderPath);
|
|
110
|
+
if (!this.config) {
|
|
111
|
+
throw new Error("Failed to load config");
|
|
112
|
+
}
|
|
113
|
+
this.appwriteServer = new Client();
|
|
114
|
+
if (setupOptions.endpoint) {
|
|
115
|
+
if (!setupOptions.project || !setupOptions.key) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
"Project ID and API key required when setting endpoint"
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
this.appwriteServer
|
|
121
|
+
.setEndpoint(setupOptions.endpoint)
|
|
122
|
+
.setProject(setupOptions.project)
|
|
123
|
+
.setKey(setupOptions.key);
|
|
124
|
+
} else {
|
|
125
|
+
this.appwriteServer
|
|
126
|
+
.setEndpoint(this.config.appwriteEndpoint)
|
|
127
|
+
.setProject(this.config.appwriteProject)
|
|
128
|
+
.setKey(this.config.appwriteKey);
|
|
129
|
+
}
|
|
130
|
+
this.database = new Databases(this.appwriteServer);
|
|
131
|
+
this.storage = new Storage(this.appwriteServer);
|
|
132
|
+
this.config.appwriteClient = this.appwriteServer;
|
|
133
|
+
// await this.loadCustomDefinitions();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async run(options: SetupOptions) {
|
|
138
|
+
await this.init(options); // Ensure initialization is done
|
|
139
|
+
if (!this.database || !this.storage || !this.config) {
|
|
140
|
+
throw new Error("Database or storage not initialized");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (options.sync) {
|
|
144
|
+
console.log("Starting synchronization with server...");
|
|
145
|
+
const appwriteToX = new AppwriteToX(this.config, this.appwriteFolderPath);
|
|
146
|
+
await appwriteToX.toSchemas();
|
|
147
|
+
console.log("Synchronization complete, YAML and Schemas updated");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Start the setup
|
|
151
|
+
console.log(
|
|
152
|
+
"Starting setup, this step sets up migrations, runs backup, wipes databases, and updates schemas (depending on your options)..."
|
|
153
|
+
);
|
|
154
|
+
await startSetup(
|
|
155
|
+
this.database,
|
|
156
|
+
this.storage,
|
|
157
|
+
this.config,
|
|
158
|
+
options,
|
|
159
|
+
this.appwriteFolderPath
|
|
160
|
+
);
|
|
161
|
+
console.log("Setup complete.");
|
|
162
|
+
|
|
163
|
+
if (options.generateMockData) {
|
|
164
|
+
// TODO: Figure out how to do this dynamically
|
|
165
|
+
// await this.generateMockData();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (options.importData) {
|
|
169
|
+
console.log("Starting import data...");
|
|
170
|
+
const importDataActions = new ImportDataActions(
|
|
171
|
+
this.database,
|
|
172
|
+
this.storage,
|
|
173
|
+
this.config,
|
|
174
|
+
this.converterDefinitions,
|
|
175
|
+
this.validityRuleDefinitions,
|
|
176
|
+
this.afterImportActionsDefinitions
|
|
177
|
+
);
|
|
178
|
+
const importController = new ImportController(
|
|
179
|
+
this.config!,
|
|
180
|
+
this.database!,
|
|
181
|
+
this.storage!,
|
|
182
|
+
this.appwriteFolderPath,
|
|
183
|
+
importDataActions,
|
|
184
|
+
options
|
|
185
|
+
);
|
|
186
|
+
await importController.run();
|
|
187
|
+
console.log("Import data complete.");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// if (options.checkDuplicates) {
|
|
191
|
+
// await this.checkDuplicates();
|
|
192
|
+
// }
|
|
193
|
+
}
|
|
194
|
+
}
|