appwrite-utils-cli 0.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.
Files changed (86) hide show
  1. package/README.md +80 -0
  2. package/dist/main.d.ts +2 -0
  3. package/dist/main.js +74 -0
  4. package/dist/migrations/afterImportActions.d.ts +12 -0
  5. package/dist/migrations/afterImportActions.js +196 -0
  6. package/dist/migrations/attributes.d.ts +4 -0
  7. package/dist/migrations/attributes.js +158 -0
  8. package/dist/migrations/backup.d.ts +621 -0
  9. package/dist/migrations/backup.js +159 -0
  10. package/dist/migrations/collections.d.ts +16 -0
  11. package/dist/migrations/collections.js +207 -0
  12. package/dist/migrations/converters.d.ts +179 -0
  13. package/dist/migrations/converters.js +575 -0
  14. package/dist/migrations/dbHelpers.d.ts +5 -0
  15. package/dist/migrations/dbHelpers.js +54 -0
  16. package/dist/migrations/importController.d.ts +44 -0
  17. package/dist/migrations/importController.js +312 -0
  18. package/dist/migrations/importDataActions.d.ts +44 -0
  19. package/dist/migrations/importDataActions.js +219 -0
  20. package/dist/migrations/indexes.d.ts +4 -0
  21. package/dist/migrations/indexes.js +18 -0
  22. package/dist/migrations/logging.d.ts +2 -0
  23. package/dist/migrations/logging.js +14 -0
  24. package/dist/migrations/migrationHelper.d.ts +18 -0
  25. package/dist/migrations/migrationHelper.js +66 -0
  26. package/dist/migrations/queue.d.ts +13 -0
  27. package/dist/migrations/queue.js +79 -0
  28. package/dist/migrations/relationships.d.ts +90 -0
  29. package/dist/migrations/relationships.js +209 -0
  30. package/dist/migrations/schema.d.ts +3142 -0
  31. package/dist/migrations/schema.js +485 -0
  32. package/dist/migrations/schemaStrings.d.ts +12 -0
  33. package/dist/migrations/schemaStrings.js +261 -0
  34. package/dist/migrations/setupDatabase.d.ts +7 -0
  35. package/dist/migrations/setupDatabase.js +151 -0
  36. package/dist/migrations/storage.d.ts +8 -0
  37. package/dist/migrations/storage.js +241 -0
  38. package/dist/migrations/users.d.ts +11 -0
  39. package/dist/migrations/users.js +114 -0
  40. package/dist/migrations/validationRules.d.ts +43 -0
  41. package/dist/migrations/validationRules.js +42 -0
  42. package/dist/schemas/authUser.d.ts +62 -0
  43. package/dist/schemas/authUser.js +17 -0
  44. package/dist/setup.d.ts +2 -0
  45. package/dist/setup.js +5 -0
  46. package/dist/types.d.ts +9 -0
  47. package/dist/types.js +5 -0
  48. package/dist/utils/configSchema.json +742 -0
  49. package/dist/utils/helperFunctions.d.ts +34 -0
  50. package/dist/utils/helperFunctions.js +72 -0
  51. package/dist/utils/index.d.ts +2 -0
  52. package/dist/utils/index.js +2 -0
  53. package/dist/utils/setupFiles.d.ts +2 -0
  54. package/dist/utils/setupFiles.js +276 -0
  55. package/dist/utilsController.d.ts +30 -0
  56. package/dist/utilsController.js +106 -0
  57. package/package.json +34 -0
  58. package/src/main.ts +77 -0
  59. package/src/migrations/afterImportActions.ts +300 -0
  60. package/src/migrations/attributes.ts +315 -0
  61. package/src/migrations/backup.ts +189 -0
  62. package/src/migrations/collections.ts +303 -0
  63. package/src/migrations/converters.ts +628 -0
  64. package/src/migrations/dbHelpers.ts +89 -0
  65. package/src/migrations/importController.ts +509 -0
  66. package/src/migrations/importDataActions.ts +313 -0
  67. package/src/migrations/indexes.ts +37 -0
  68. package/src/migrations/logging.ts +15 -0
  69. package/src/migrations/migrationHelper.ts +100 -0
  70. package/src/migrations/queue.ts +119 -0
  71. package/src/migrations/relationships.ts +336 -0
  72. package/src/migrations/schema.ts +590 -0
  73. package/src/migrations/schemaStrings.ts +310 -0
  74. package/src/migrations/setupDatabase.ts +219 -0
  75. package/src/migrations/storage.ts +351 -0
  76. package/src/migrations/users.ts +148 -0
  77. package/src/migrations/validationRules.ts +63 -0
  78. package/src/schemas/authUser.ts +23 -0
  79. package/src/setup.ts +8 -0
  80. package/src/types.ts +14 -0
  81. package/src/utils/configSchema.json +742 -0
  82. package/src/utils/helperFunctions.ts +111 -0
  83. package/src/utils/index.ts +2 -0
  84. package/src/utils/setupFiles.ts +295 -0
  85. package/src/utilsController.ts +173 -0
  86. package/tsconfig.json +37 -0
@@ -0,0 +1,111 @@
1
+ import type { AppwriteConfig } from "../types.js";
2
+ import type { Models, Storage } from "node-appwrite";
3
+ import fs from "node:fs";
4
+ import path from "node:path";
5
+
6
+ export const toPascalCase = (str: string): string => {
7
+ return (
8
+ str
9
+ // Split the string into words on spaces or camelCase transitions
10
+ .split(/(?:\s+)|(?:([A-Z][a-z]+))/g)
11
+ // Filter out empty strings that can appear due to the split regex
12
+ .filter(Boolean)
13
+ // Capitalize the first letter of each word and join them together
14
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
15
+ .join("")
16
+ );
17
+ };
18
+
19
+ export const toCamelCase = (str: string): string => {
20
+ return str
21
+ .replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) =>
22
+ index === 0 ? word.toLowerCase() : word.toUpperCase()
23
+ )
24
+ .replace(/\s+/g, "");
25
+ };
26
+
27
+ export const ensureDirectoryExistence = (filePath: string) => {
28
+ const dirname = path.dirname(filePath);
29
+ if (fs.existsSync(dirname)) {
30
+ return true;
31
+ }
32
+ ensureDirectoryExistence(dirname);
33
+ fs.mkdirSync(dirname);
34
+ };
35
+
36
+ export const writeFileSync = (
37
+ filePath: string,
38
+ content: string,
39
+ options: { flag: string }
40
+ ) => {
41
+ ensureDirectoryExistence(filePath);
42
+ fs.writeFileSync(filePath, content, options);
43
+ };
44
+
45
+ export const readFileSync = (filePath: string) => {
46
+ return fs.readFileSync(filePath, "utf8");
47
+ };
48
+
49
+ export const existsSync = (filePath: string) => {
50
+ return fs.existsSync(filePath);
51
+ };
52
+
53
+ export const mkdirSync = (filePath: string) => {
54
+ ensureDirectoryExistence(filePath);
55
+ fs.mkdirSync(filePath);
56
+ };
57
+
58
+ export const readdirSync = (filePath: string) => {
59
+ return fs.readdirSync(filePath);
60
+ };
61
+
62
+ export const areCollectionNamesSame = (a: string, b: string) => {
63
+ return (
64
+ a.toLowerCase().trim().replace(" ", "") ===
65
+ b.toLowerCase().trim().replace(" ", "")
66
+ );
67
+ };
68
+
69
+ /**
70
+ * Generates the view URL for a specific file based on the provided endpoint, project ID, bucket ID, file ID, and optional JWT token.
71
+ *
72
+ * @param {string} endpoint - the base URL endpoint
73
+ * @param {string} projectId - the ID of the project
74
+ * @param {string} bucketId - the ID of the bucket
75
+ * @param {string} fileId - the ID of the file
76
+ * @param {Models.Jwt} [jwt] - optional JWT token generated via the Appwrite SDK
77
+ * @return {string} the generated view URL for the file
78
+ */
79
+ export const getFileViewUrl = (
80
+ endpoint: string,
81
+ projectId: string,
82
+ bucketId: string,
83
+ fileId: string,
84
+ jwt?: Models.Jwt
85
+ ) => {
86
+ return `${endpoint}/storage/buckets/${bucketId}/files/${fileId}/view?project=${projectId}${
87
+ jwt ? `&jwt=${jwt.jwt}` : ""
88
+ }`;
89
+ };
90
+
91
+ /**
92
+ * Generates a download URL for a file based on the provided endpoint, project ID, bucket ID, file ID, and optionally a JWT.
93
+ *
94
+ * @param {string} endpoint - The base URL endpoint.
95
+ * @param {string} projectId - The ID of the project.
96
+ * @param {string} bucketId - The ID of the bucket.
97
+ * @param {string} fileId - The ID of the file.
98
+ * @param {Models.Jwt} [jwt] - Optional JWT object for authentication with Appwrite.
99
+ * @return {string} The complete download URL for the file.
100
+ */
101
+ export const getFileDownloadUrl = (
102
+ endpoint: string,
103
+ projectId: string,
104
+ bucketId: string,
105
+ fileId: string,
106
+ jwt?: Models.Jwt
107
+ ) => {
108
+ return `${endpoint}/storage/buckets/${bucketId}/files/${fileId}/download?project=${projectId}${
109
+ jwt ? `&jwt=${jwt.jwt}` : ""
110
+ }`;
111
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./helperFunctions.js";
2
+ export * from "./setupFiles.js";
@@ -0,0 +1,295 @@
1
+ import { mkdirSync, writeFileSync, existsSync } from "node:fs";
2
+ import path from "node:path";
3
+ import configSchema from "./configSchema.json" assert { type: "json" };
4
+
5
+ // Define our YAML files
6
+ // Define our YAML files
7
+ const configFileExample = `# yaml-language-server: $schema=./.appwrite/appwriteUtilsConfigSchema.json
8
+ # Appwrite configuration settings
9
+ appwriteEndpoint: 'https://cloud.appwrite.io/v1' # Your Appwrite endpoint. Default: 'https://cloud.appwrite.io/v1'
10
+ appwriteProject: 'YOUR_PROJECT_ID' # Your Appwrite project ID
11
+ appwriteKey: 'YOUR_API_KEY' # Your Appwrite API key (needs storage and databases at minimum)
12
+ appwriteClient: null # Your Appwrite client -- don't worry about this
13
+ enableDevDatabase: true # Enable development database alongside main
14
+ enableBackups: true # Enable backups
15
+ backupInterval: 3600 # Backup interval in seconds
16
+ backupRetention: 30 # Backup retention in days
17
+ enableBackupCleanup: true # Enable backup cleanup
18
+ enableMockData: false # Enable mock data generation
19
+ enableWipeOtherDatabases: true # Enable wiping other databases
20
+ documentBucketId: 'documents' # Your Appwrite bucket ID for documents
21
+ usersCollectionName: 'Members' # Your Appwrite collection for any extra info while importing members (if any)
22
+ # This allows you to use any targetKey in the users field to create your user
23
+ # these are: name, email, phone, labels, prefs, password, userId and (not yet added)
24
+ # $createdAt, $updatedAt -- Add them to your attributeMappings (NOT attributes) to define them and set the
25
+ # targetKey to the same as the Appwrite targetKey
26
+ databases:
27
+ - $id: 'main'
28
+ name: 'Main'
29
+ - $id: 'staging'
30
+ name: 'Staging'
31
+ - $id: 'dev'
32
+ name: 'Development'
33
+ collections:
34
+ - name: 'Members'
35
+ $permissions:
36
+ - permission: read
37
+ target: any
38
+ - permission: create
39
+ target: users
40
+ - permission: update
41
+ target: users
42
+ - permission: delete
43
+ target: users
44
+ attributes:
45
+ - key: 'idOrig'
46
+ type: 'string'
47
+ size: 255
48
+ required: false
49
+ - key: 'dogs'
50
+ type: 'relationship'
51
+ relatedCollection: 'Dogs'
52
+ relationType: 'oneToMany'
53
+ twoWay: true
54
+ twoWayKey: 'owner'
55
+ side: 'parent'
56
+ onDelete: 'cascade'
57
+ importMapping: { originalIdField: 'idOrig', targetField: 'ownerIdOrig' }
58
+ - key: 'dogIds'
59
+ type: 'string'
60
+ size: 255
61
+ array: true
62
+ - key: 'profilePhoto'
63
+ type: 'string'
64
+ size: 255
65
+ required: false
66
+ - key: 'profilePhotoTest'
67
+ type: 'string'
68
+ size: 255
69
+ required: false
70
+ indexes:
71
+ - key: 'idOrig_index'
72
+ type: 'key'
73
+ attributes: ['idOrig']
74
+ importDefs:
75
+ - filePath: 'importData/members.json'
76
+ basePath: 'RECORDS'
77
+ attributeMappings:
78
+ - oldKey: 'id'
79
+ targetKey: 'idOrig'
80
+ converters: ['anyToString']
81
+ postImportActions:
82
+ - action: 'checkAndUpdateFieldInDocument'
83
+ params:
84
+ - "{dbId}"
85
+ - "{collId}"
86
+ - "{docId}"
87
+ - "idOrig"
88
+ - "{id}"
89
+ - "{$id}"
90
+ - oldKey: 'name'
91
+ targetKey: 'name'
92
+ - oldKey: 'email'
93
+ targetKey: 'email'
94
+ - oldKey: 'doesntMatter'
95
+ targetKey: 'profilePhoto'
96
+ fileData: { name: "profilePhoto_{id}", path: "importData/profilePhotos" }
97
+ - oldKey: 'photoUrl'
98
+ targetKey: 'profilePhotoTest'
99
+ fileData: { name: "profilePhotoTest_{id}", path: "{photoUrl}" }
100
+ - name: 'Dogs'
101
+ $permissions:
102
+ - permission: read
103
+ target: any
104
+ - permission: create
105
+ target: users
106
+ - permission: update
107
+ target: users
108
+ - permission: delete
109
+ target: users
110
+ attributes:
111
+ - key: 'name'
112
+ type: 'string'
113
+ size: 255
114
+ required: true
115
+ - key: 'breed'
116
+ type: 'string'
117
+ size: 255
118
+ required: false
119
+ - key: 'age'
120
+ type: 'integer'
121
+ required: false
122
+ min: 0
123
+ max: 100
124
+ - key: 'idOrig'
125
+ type: 'string'
126
+ size: 20
127
+ required: false
128
+ - key: 'ownerIdOrig'
129
+ type: 'string'
130
+ size: 255
131
+ required: false
132
+ - key: 'vetRecords'
133
+ type: 'string'
134
+ size: 255
135
+ required: false
136
+ - key: 'vetRecordIds'
137
+ type: 'string'
138
+ size: 255
139
+ array: true
140
+ required: false
141
+ indexes:
142
+ - key: 'ownerIdIndex'
143
+ type: 'key'
144
+ attributes: ['ownerIdOrig']
145
+ importDefs:
146
+ - filePath: 'importData/dogs.json'
147
+ basePath: 'RECORDS'
148
+ attributeMappings:
149
+ - oldKey: 'id'
150
+ targetKey: 'idOrig'
151
+ - oldKey: 'name'
152
+ targetKey: 'name'
153
+ - oldKey: 'breed'
154
+ targetKey: 'breed'
155
+ - oldKey: 'age'
156
+ targetKey: 'age'
157
+ - oldKey: 'ownerId'
158
+ targetKey: 'ownerIdOrig'
159
+ - oldKey: 'vetRecords'
160
+ targetKey: 'vetRecords'
161
+ converters: ['stringifyObject']
162
+ - oldKey: 'vetRecords.[any].id'
163
+ targetKey: 'vetRecordIds'
164
+ converters: ['anyToString']
165
+ - filePath: 'importData/dogs.json'
166
+ basePath: 'RECORDS'
167
+ type: 'update'
168
+ updateMapping: { originalIdField: 'id', targetField: 'idOrig' }
169
+ attributeMappings:
170
+ - oldKey: 'name'
171
+ targetKey: 'name'
172
+ - oldKey: 'breed'
173
+ targetKey: 'breed'
174
+ - oldKey: 'age'
175
+ targetKey: 'age'`;
176
+
177
+ const configFile = `# yaml-language-server: $schema=./.appwrite/appwriteUtilsConfigSchema.json
178
+ # Basic Appwrite configuration settings
179
+ appwriteEndpoint: 'https://cloud.appwrite.io/v1' # Your Appwrite endpoint
180
+ appwriteProject: 'YOUR_PROJECT_ID' # Your Appwrite project ID
181
+ appwriteKey: 'YOUR_API_KEY' # Your Appwrite API key (needs storage and databases at minimum)
182
+ enableDevDatabase: true # Enable development database alongside main. Default: true
183
+ enableBackups: true # Enable backups. Default: true
184
+ backupInterval: 3600 # Backup interval in seconds. Default: 3600 - DOES NOTHING RIGHT NOW
185
+ backupRetention: 30 # Backup retention in days. Default: 30 - DOES NOTHING RIGHT NOW
186
+ enableBackupCleanup: true # Enable backup cleanup. Default: true - DOES NOTHING RIGHT NOW
187
+ enableMockData: false # Enable mock data generation. Default: false - DOES NOTHING RIGHT NOW
188
+ enableWipeOtherDatabases: true # Enable wiping other databases. Default: true
189
+ documentBucketId: 'documents' # Your Appwrite bucket ID for documents. Default: 'documents'
190
+ usersCollectionName: 'Members' # Your Appwrite collection for any extra info while importing members (if any). Default: 'Members'
191
+ # Databases configuration
192
+ # The first one is *always* Production
193
+ # The second is *always* Staging
194
+ # The third is *always* Development
195
+ # They are found by name matching (without spaces and all lowercase), not $id
196
+ # If no $id is included for anything defined, Appwrite will auto-generate one in its stead
197
+ databases:
198
+ - $id: 'main' # Database ID
199
+ name: 'Main' # Database name
200
+ - $id: 'staging'
201
+ name: 'Staging'
202
+ - $id: 'dev'
203
+ name: 'Development'
204
+
205
+ # Collections configuration
206
+ collections:
207
+ - name: 'ExampleCollection' # Collection name
208
+ $permissions: # Permissions for the collection
209
+ - permission: read # Permission type
210
+ target: any # Permission target
211
+ - permission: create
212
+ target: users
213
+ - permission: update
214
+ target: users
215
+ - permission: delete
216
+ target: users
217
+ attributes: # Attributes of the collection
218
+ - key: 'exampleKey' # Attribute key
219
+ type: 'string' # Attribute type
220
+ size: 255 # Size of the attribute (for strings)
221
+ required: true # Whether the attribute is required`;
222
+
223
+ export const customDefinitionsFile = `import type { ConverterFunctions, ValidationRules, AfterImportActions } from "appwrite-utils";
224
+
225
+ export const customConverterFunctions: ConverterFunctions = {
226
+ // Add your custom converter functions here
227
+ }
228
+ export const customValidationRules: ValidationRules = {
229
+ // Add your custom validation rules here
230
+ }
231
+ export const customAfterImportActions: AfterImportActions = {
232
+ // Add your custom after import actions here
233
+ }`;
234
+
235
+ export const setupDirsFiles = async (example: boolean = false) => {
236
+ const basePath = process.cwd();
237
+ const srcPath = path.join(basePath, "src");
238
+
239
+ // Check if src directory exists in the current working directory
240
+ if (!existsSync(srcPath)) {
241
+ console.error("No 'src' directory found in the current working directory.");
242
+ return;
243
+ }
244
+
245
+ const appwriteFolder = path.join(srcPath, "appwrite");
246
+ const appwriteConfigFile = path.join(appwriteFolder, "appwriteConfig.yaml");
247
+ const appwriteCustomDefsFile = path.join(
248
+ appwriteFolder,
249
+ "customDefinitions.ts"
250
+ );
251
+ // const appwriteMigrationsFolder = path.join(appwriteFolder, "migrations");
252
+ const appwriteSchemaFolder = path.join(appwriteFolder, "schemas");
253
+ const appwriteDataFolder = path.join(appwriteFolder, "importData");
254
+ const appwriteHiddenFolder = path.join(appwriteFolder, ".appwrite");
255
+
256
+ // Directory creation and file writing logic remains the same
257
+ if (!existsSync(appwriteFolder)) {
258
+ mkdirSync(appwriteFolder, { recursive: true });
259
+ }
260
+
261
+ if (!existsSync(appwriteConfigFile)) {
262
+ if (example) {
263
+ writeFileSync(appwriteConfigFile, configFileExample);
264
+ } else {
265
+ writeFileSync(appwriteConfigFile, configFile);
266
+ }
267
+ }
268
+
269
+ if (!existsSync(appwriteCustomDefsFile)) {
270
+ writeFileSync(appwriteCustomDefsFile, customDefinitionsFile);
271
+ }
272
+
273
+ // if (!existsSync(appwriteMigrationsFolder)) {
274
+ // mkdirSync(appwriteMigrationsFolder, { recursive: true });
275
+ // }
276
+
277
+ if (!existsSync(appwriteSchemaFolder)) {
278
+ mkdirSync(appwriteSchemaFolder, { recursive: true });
279
+ }
280
+
281
+ if (!existsSync(appwriteDataFolder)) {
282
+ mkdirSync(appwriteDataFolder, { recursive: true });
283
+ }
284
+
285
+ if (!existsSync(appwriteHiddenFolder)) {
286
+ mkdirSync(appwriteHiddenFolder, { recursive: true });
287
+ }
288
+ const schemaFilePath = path.join(
289
+ appwriteHiddenFolder,
290
+ "appwriteUtilsConfigSchema.json"
291
+ );
292
+ writeFileSync(schemaFilePath, JSON.stringify(configSchema, undefined, 2));
293
+
294
+ console.log("Created config and setup files/directories successfully.");
295
+ };
@@ -0,0 +1,173 @@
1
+ import { Client, Databases, Storage } from "node-appwrite";
2
+ import { startSetup } from "./migrations/setupDatabase.js";
3
+ import {
4
+ type AppwriteConfig,
5
+ AppwriteConfigSchema,
6
+ } from "./migrations/schema.js";
7
+ import path from "path";
8
+ import fs from "fs";
9
+ import { load } from "js-yaml";
10
+ import { ImportDataActions } from "./migrations/importDataActions.js";
11
+ import {
12
+ converterFunctions,
13
+ type ConverterFunctions,
14
+ } from "./migrations/converters.js";
15
+ import { readFileSync } from "./utils/helperFunctions.js";
16
+ import {
17
+ afterImportActions,
18
+ type AfterImportActions,
19
+ } from "./migrations/afterImportActions.js";
20
+ import {
21
+ validationRules,
22
+ type ValidationRules,
23
+ } from "./migrations/validationRules.js";
24
+ import { ImportController } from "./migrations/importController.js";
25
+ import _ from "lodash";
26
+
27
+ async function loadConfig(configPath: string) {
28
+ if (!fs.existsSync(configPath)) {
29
+ throw new Error(`Configuration file not found at ${configPath}`);
30
+ }
31
+ const configModule = await load(readFileSync(configPath), {
32
+ json: true,
33
+ });
34
+ return AppwriteConfigSchema.parse(configModule);
35
+ }
36
+
37
+ export interface SetupOptions {
38
+ runProd: boolean;
39
+ runStaging: boolean;
40
+ runDev: boolean;
41
+ doBackup: boolean;
42
+ wipeDatabases: boolean;
43
+ wipeDocumentStorage: boolean;
44
+ wipeUsers: boolean;
45
+ generateSchemas: boolean;
46
+ generateMockData: boolean;
47
+ importData: boolean;
48
+ checkDuplicates: boolean;
49
+ }
50
+
51
+ type CollectionConfig = AppwriteConfig["collections"];
52
+ type ImportDef = CollectionConfig[number]["importDefs"][number];
53
+ type AttributeMappings = ImportDef["attributeMappings"];
54
+ type AfterImportAction = AttributeMappings[number]["postImportActions"][number];
55
+ type ValidityRule = AttributeMappings[number]["validationActions"][number];
56
+
57
+ export class UtilsController {
58
+ private appwriteFolderPath: string;
59
+ private appwriteConfigPath: string;
60
+ private config?: AppwriteConfig;
61
+ private appwriteServer?: Client;
62
+ private database?: Databases;
63
+ private storage?: Storage;
64
+ public converterDefinitions: ConverterFunctions = converterFunctions;
65
+ public validityRuleDefinitions: ValidationRules = validationRules;
66
+ public afterImportActionsDefinitions: AfterImportActions = afterImportActions;
67
+
68
+ constructor() {
69
+ const basePath = process.cwd(); // Gets the current working directory
70
+ const appwriteFolderPath = path.join(basePath, "src", "appwrite");
71
+ const appwriteConfigPath = path.join(
72
+ appwriteFolderPath,
73
+ "appwriteConfig.yaml"
74
+ );
75
+ this.appwriteFolderPath = appwriteFolderPath;
76
+ this.appwriteConfigPath = appwriteConfigPath;
77
+ }
78
+
79
+ // async loadCustomDefinitions(): Promise<void> {
80
+ // try {
81
+ // const customDefinitionsPath = path.join(
82
+ // this.appwriteFolderPath,
83
+ // "customDefinitions.ts"
84
+ // );
85
+ // if (fs.existsSync(customDefinitionsPath)) {
86
+ // // Dynamically import custom definitions
87
+ // const customDefinitions = (await import(
88
+ // customDefinitionsPath
89
+ // )) as typeof import("customDefinitions");
90
+ // this.converterDefinitions = {
91
+ // ...this.converterDefinitions,
92
+ // ...customDefinitions.converterDefinitions,
93
+ // };
94
+ // this.validityRuleDefinitions = {
95
+ // ...this.validityRuleDefinitions,
96
+ // ...customDefinitions.validityRuleDefinitions,
97
+ // };
98
+ // this.afterImportActionsDefinitions = {
99
+ // ...this.afterImportActionsDefinitions,
100
+ // ...customDefinitions.afterImportActionsDefinitions,
101
+ // };
102
+ // }
103
+ // } catch (error) {
104
+ // console.error("Failed to load custom definitions:", error);
105
+ // }
106
+ // }
107
+
108
+ async init() {
109
+ if (!this.config) {
110
+ console.log("Initializing appwrite client & loading config...");
111
+ this.config = await loadConfig(this.appwriteConfigPath);
112
+ this.appwriteServer = new Client()
113
+ .setEndpoint(this.config.appwriteEndpoint)
114
+ .setProject(this.config.appwriteProject)
115
+ .setKey(this.config.appwriteKey);
116
+ this.database = new Databases(this.appwriteServer);
117
+ this.storage = new Storage(this.appwriteServer);
118
+ this.config.appwriteClient = this.appwriteServer;
119
+ // await this.loadCustomDefinitions();
120
+ }
121
+ }
122
+
123
+ async run(options: SetupOptions) {
124
+ await this.init(); // Ensure initialization is done
125
+ if (!this.database || !this.storage || !this.config) {
126
+ throw new Error("Database or storage not initialized");
127
+ }
128
+
129
+ // Start the setup
130
+ console.log(
131
+ "Starting setup, this step sets up migrations, runs backup, wipes databases, and updates schemas (depending on your options)..."
132
+ );
133
+ await startSetup(
134
+ this.database,
135
+ this.storage,
136
+ this.config,
137
+ options,
138
+ this.appwriteFolderPath
139
+ );
140
+ console.log("Setup complete.");
141
+
142
+ if (options.generateMockData) {
143
+ // TODO: Figure out how to do this dynamically
144
+ // await this.generateMockData();
145
+ }
146
+
147
+ if (options.importData) {
148
+ console.log("Starting import data...");
149
+ const importDataActions = new ImportDataActions(
150
+ this.database,
151
+ this.storage,
152
+ this.config,
153
+ this.converterDefinitions,
154
+ this.validityRuleDefinitions,
155
+ this.afterImportActionsDefinitions
156
+ );
157
+ const importController = new ImportController(
158
+ this.config!,
159
+ this.database!,
160
+ this.storage!,
161
+ this.appwriteFolderPath,
162
+ importDataActions,
163
+ options
164
+ );
165
+ await importController.run();
166
+ console.log("Import data complete.");
167
+ }
168
+
169
+ // if (options.checkDuplicates) {
170
+ // await this.checkDuplicates();
171
+ // }
172
+ }
173
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "compilerOptions": {
3
+ // Enable latest features
4
+ "target": "ESNext",
5
+ "module": "NodeNext",
6
+ "lib": ["ESNext"],
7
+ "moduleDetection": "force",
8
+ "jsx": "react-jsx",
9
+ "allowJs": true,
10
+ "allowArbitraryExtensions": true,
11
+ "allowSyntheticDefaultImports": true,
12
+ "resolveJsonModule": true,
13
+
14
+ // NodeNext mode
15
+ "moduleResolution": "NodeNext",
16
+ "verbatimModuleSyntax": true,
17
+ "noEmit": false,
18
+ "emitDeclarationOnly": false,
19
+
20
+ // Best practices
21
+ "strict": true,
22
+ "skipLibCheck": true,
23
+ "noFallthroughCasesInSwitch": true,
24
+
25
+ // Some stricter flags (disabled by default)
26
+ "noUnusedLocals": false,
27
+ "noUnusedParameters": false,
28
+ "noPropertyAccessFromIndexSignature": false,
29
+ "baseUrl": ".",
30
+ "esModuleInterop": true,
31
+ "outDir": "./dist",
32
+ "rootDir": "./src",
33
+ "declaration": true
34
+ },
35
+ "include": ["src/main.ts", "src/**/*"],
36
+ "exclude": ["node_modules", "dist", "src/appwrite", "example/*"]
37
+ }