appwrite-utils-cli 0.0.274 → 0.0.276

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 (77) hide show
  1. package/README.md +4 -39
  2. package/dist/init.d.ts +2 -0
  3. package/dist/init.js +57 -0
  4. package/dist/main.js +62 -100
  5. package/dist/migrations/afterImportActions.d.ts +1 -4
  6. package/dist/migrations/afterImportActions.js +1 -0
  7. package/dist/migrations/appwriteToX.d.ts +46 -46
  8. package/dist/migrations/appwriteToX.js +6 -2
  9. package/dist/migrations/attributes.d.ts +1 -1
  10. package/dist/migrations/attributes.js +97 -71
  11. package/dist/migrations/backup.d.ts +240 -240
  12. package/dist/migrations/backup.js +1 -1
  13. package/dist/migrations/collections.d.ts +1 -1
  14. package/dist/migrations/collections.js +4 -4
  15. package/dist/migrations/converters.d.ts +9 -127
  16. package/dist/migrations/converters.js +1 -504
  17. package/dist/migrations/dataLoader.d.ts +470 -453
  18. package/dist/migrations/dataLoader.js +19 -1
  19. package/dist/migrations/dbHelpers.d.ts +1 -1
  20. package/dist/migrations/dbHelpers.js +3 -0
  21. package/dist/migrations/importController.d.ts +1 -1
  22. package/dist/migrations/importController.js +4 -7
  23. package/dist/migrations/importDataActions.d.ts +4 -6
  24. package/dist/migrations/importDataActions.js +6 -4
  25. package/dist/migrations/indexes.d.ts +1 -1
  26. package/dist/migrations/indexes.js +1 -1
  27. package/dist/migrations/migrationHelper.d.ts +29 -29
  28. package/dist/migrations/migrationHelper.js +1 -1
  29. package/dist/migrations/openapi.d.ts +1 -1
  30. package/dist/migrations/openapi.js +4 -1
  31. package/dist/migrations/queue.d.ts +1 -1
  32. package/dist/migrations/relationships.d.ts +5 -5
  33. package/dist/migrations/relationships.js +3 -0
  34. package/dist/migrations/schemaStrings.d.ts +2 -2
  35. package/dist/migrations/schemaStrings.js +93 -8
  36. package/dist/migrations/setupDatabase.d.ts +1 -1
  37. package/dist/migrations/setupDatabase.js +1 -1
  38. package/dist/migrations/storage.d.ts +1 -1
  39. package/dist/migrations/users.d.ts +1 -1
  40. package/dist/schemas/authUser.d.ts +12 -10
  41. package/dist/types.d.ts +0 -5
  42. package/dist/types.js +0 -2
  43. package/dist/utils/helperFunctions.d.ts +2 -3
  44. package/dist/utils/loadConfigs.d.ts +13 -0
  45. package/dist/utils/loadConfigs.js +47 -0
  46. package/dist/utils/setupFiles.d.ts +1 -0
  47. package/dist/utils/setupFiles.js +98 -223
  48. package/dist/utilsController.d.ts +1 -3
  49. package/dist/utilsController.js +14 -18
  50. package/package.json +9 -2
  51. package/src/init.ts +64 -0
  52. package/src/main.ts +73 -98
  53. package/src/migrations/afterImportActions.ts +1 -5
  54. package/src/migrations/appwriteToX.ts +6 -2
  55. package/src/migrations/attributes.ts +198 -150
  56. package/src/migrations/backup.ts +1 -1
  57. package/src/migrations/collections.ts +5 -11
  58. package/src/migrations/converters.ts +1 -540
  59. package/src/migrations/dataLoader.ts +19 -2
  60. package/src/migrations/dbHelpers.ts +4 -1
  61. package/src/migrations/importController.ts +5 -15
  62. package/src/migrations/importDataActions.ts +10 -14
  63. package/src/migrations/indexes.ts +1 -1
  64. package/src/migrations/migrationHelper.ts +1 -1
  65. package/src/migrations/openapi.ts +4 -1
  66. package/src/migrations/queue.ts +1 -1
  67. package/src/migrations/relationships.ts +4 -1
  68. package/src/migrations/schemaStrings.ts +106 -9
  69. package/src/migrations/setupDatabase.ts +1 -1
  70. package/src/migrations/storage.ts +1 -1
  71. package/src/migrations/users.ts +1 -1
  72. package/src/types.ts +0 -5
  73. package/src/utils/helperFunctions.ts +2 -3
  74. package/src/utils/loadConfigs.ts +55 -0
  75. package/src/utils/setupFiles.ts +114 -225
  76. package/src/utilsController.ts +27 -35
  77. package/src/migrations/schema.ts +0 -748
@@ -1,224 +1,63 @@
1
1
  import { mkdirSync, writeFileSync, existsSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import configSchema from "./configSchema.json" assert { type: "json" };
4
+ import type { AppwriteConfig } from "appwrite-utils";
5
+ import { findAppwriteConfig } from "./loadConfigs.js";
6
+
7
+ // Example base configuration using types from appwrite-utils
8
+ const baseConfig: AppwriteConfig = {
9
+ appwriteEndpoint: "https://cloud.appwrite.io/v1",
10
+ appwriteProject: "YOUR_PROJECT_ID",
11
+ appwriteKey: "YOUR_API_KEY",
12
+ enableDevDatabase: true,
13
+ enableBackups: true,
14
+ backupInterval: 3600,
15
+ backupRetention: 30,
16
+ enableBackupCleanup: true,
17
+ enableMockData: false,
18
+ enableWipeOtherDatabases: true,
19
+ documentBucketId: "documents",
20
+ usersCollectionName: "Members",
21
+ databases: [
22
+ { $id: "main", name: "Main" },
23
+ { $id: "staging", name: "Staging" },
24
+ { $id: "dev", name: "Development" },
25
+ ],
26
+ };
4
27
 
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'`;
28
+ const collectionsConfig: { name: string; content: string }[] = [
29
+ {
30
+ name: "ExampleCollection",
31
+ content: `import { CollectionCreate } from "appwrite-utils";
32
+
33
+ const ExampleCollection: Partial<CollectionCreate> = {
34
+ name: 'ExampleCollection',
35
+ $permissions: [
36
+ { permission: 'read', target: 'any' },
37
+ { permission: 'create', target: 'users' },
38
+ { permission: 'update', target: 'users' },
39
+ { permission: 'delete', target: 'users' }
40
+ ],
41
+ attributes: [
42
+ { key: 'alterEgoName', type: 'string', size: 255, required: false },
43
+ // Add more attributes here
44
+ ],
45
+ indexes: [
46
+ { key: 'alterEgoName_search', type: 'fulltext', attributes: ['alterEgoName'] }
47
+ ],
48
+ importDefs: [
49
+ // Define import definitions here
50
+ ]
51
+ };
176
52
 
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'
53
+ export default ExampleCollection;`,
54
+ },
55
+ // Add more collections here
56
+ ];
204
57
 
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`;
58
+ // Define our YAML files
59
+ // Define our YAML files
60
+ const configFileExample = `d`;
222
61
 
223
62
  export const customDefinitionsFile = `import type { ConverterFunctions, ValidationRules, AfterImportActions } from "appwrite-utils";
224
63
 
@@ -232,9 +71,47 @@ export const customAfterImportActions: AfterImportActions = {
232
71
  // Add your custom after import actions here
233
72
  }`;
234
73
 
74
+ export const createEmptyCollection = (collectionName: string) => {
75
+ const emptyCollection = `import type { CollectionCreate } from "appwrite-utils";
76
+
77
+ const ${collectionName}: Partial<CollectionCreate> = {
78
+ name: '${collectionName}',
79
+ $permissions: [
80
+ { permission: 'read', target: 'any' },
81
+ { permission: 'create', target: 'users' },
82
+ { permission: 'update', target: 'users' },
83
+ { permission: 'delete', target: 'users' }
84
+ ],
85
+ attributes: [
86
+ // Add more attributes here
87
+ ],
88
+ indexes: [
89
+ // Add more indexes here
90
+ ],
91
+ };
92
+
93
+ export default ${collectionName};`;
94
+
95
+ const appwriteConfigPath = findAppwriteConfig(process.cwd());
96
+ if (!appwriteConfigPath) {
97
+ console.error("Failed to find appwriteConfig.ts");
98
+ return;
99
+ }
100
+
101
+ const collectionsFolder = path.join(
102
+ path.dirname(appwriteConfigPath),
103
+ "collections"
104
+ );
105
+ const collectionFilePath = path.join(
106
+ collectionsFolder,
107
+ `${collectionName}.ts`
108
+ );
109
+ writeFileSync(collectionFilePath, emptyCollection);
110
+ };
111
+
235
112
  export const setupDirsFiles = async (example: boolean = false) => {
236
113
  const basePath = process.cwd();
237
- const srcPath = path.join(basePath, "src");
114
+ const srcPath = path.join(basePath);
238
115
 
239
116
  // Check if src directory exists in the current working directory
240
117
  if (!existsSync(srcPath)) {
@@ -243,7 +120,7 @@ export const setupDirsFiles = async (example: boolean = false) => {
243
120
  }
244
121
 
245
122
  const appwriteFolder = path.join(srcPath, "appwrite");
246
- const appwriteConfigFile = path.join(appwriteFolder, "appwriteConfig.yaml");
123
+ const appwriteConfigFile = path.join(appwriteFolder, "appwriteConfig.ts");
247
124
  const appwriteCustomDefsFile = path.join(
248
125
  appwriteFolder,
249
126
  "customDefinitions.ts"
@@ -252,27 +129,39 @@ export const setupDirsFiles = async (example: boolean = false) => {
252
129
  const appwriteSchemaFolder = path.join(appwriteFolder, "schemas");
253
130
  const appwriteDataFolder = path.join(appwriteFolder, "importData");
254
131
  const appwriteHiddenFolder = path.join(appwriteFolder, ".appwrite");
132
+ const collectionsFolder = path.join(appwriteFolder, "collections");
255
133
 
256
134
  // Directory creation and file writing logic remains the same
257
135
  if (!existsSync(appwriteFolder)) {
258
136
  mkdirSync(appwriteFolder, { recursive: true });
259
137
  }
260
138
 
139
+ if (!existsSync(collectionsFolder)) {
140
+ mkdirSync(collectionsFolder, { recursive: true });
141
+ }
142
+
261
143
  if (!existsSync(appwriteConfigFile)) {
262
144
  if (example) {
263
145
  writeFileSync(appwriteConfigFile, configFileExample);
264
146
  } else {
265
- writeFileSync(appwriteConfigFile, configFile);
147
+ const baseConfigContent = `import { AppwriteConfig } from "appwrite-utils";
148
+
149
+ const appwriteConfig: AppwriteConfig = ${JSON.stringify(baseConfig, null, 2)};
150
+
151
+ export default appwriteConfig;
152
+ `;
153
+ writeFileSync(appwriteConfigFile, baseConfigContent);
266
154
  }
267
155
  }
268
156
 
269
- // if (!existsSync(appwriteCustomDefsFile)) {
270
- // writeFileSync(appwriteCustomDefsFile, customDefinitionsFile);
271
- // }
272
-
273
- // if (!existsSync(appwriteMigrationsFolder)) {
274
- // mkdirSync(appwriteMigrationsFolder, { recursive: true });
275
- // }
157
+ // Create TypeScript files for each collection
158
+ collectionsConfig.forEach((collection) => {
159
+ const collectionFilePath = path.join(
160
+ collectionsFolder,
161
+ `${collection.name}.ts`
162
+ );
163
+ writeFileSync(collectionFilePath, collection.content);
164
+ });
276
165
 
277
166
  if (!existsSync(appwriteSchemaFolder)) {
278
167
  mkdirSync(appwriteSchemaFolder, { recursive: true });
@@ -1,39 +1,35 @@
1
1
  import { Client, Databases, Storage } from "node-appwrite";
2
2
  import { startSetup } from "./migrations/setupDatabase.js";
3
- import {
4
- type AppwriteConfig,
5
- AppwriteConfigSchema,
6
- } from "./migrations/schema.js";
7
3
  import path from "path";
8
4
  import fs from "fs";
9
5
  import { load } from "js-yaml";
10
6
  import { ImportDataActions } from "./migrations/importDataActions.js";
11
- import {
12
- converterFunctions,
13
- type ConverterFunctions,
14
- } from "./migrations/converters.js";
15
7
  import { readFileSync } from "./utils/helperFunctions.js";
8
+ import { afterImportActions } from "./migrations/afterImportActions.js";
16
9
  import {
17
- afterImportActions,
18
10
  type AfterImportActions,
19
- } from "./migrations/afterImportActions.js";
20
- import {
11
+ type ConverterFunctions,
12
+ converterFunctions,
21
13
  validationRules,
22
14
  type ValidationRules,
23
- } from "./migrations/validationRules.js";
15
+ type AppwriteConfig,
16
+ AppwriteConfigSchema,
17
+ } from "appwrite-utils";
24
18
  import { ImportController } from "./migrations/importController.js";
25
19
  import _ from "lodash";
26
20
  import { AppwriteToX } from "./migrations/appwriteToX.js";
21
+ import { loadConfig as loadTsConfig } from "./utils/loadConfigs.js";
22
+ import { findAppwriteConfig } from "./utils/loadConfigs.js";
27
23
 
28
- async function loadConfig(configPath: string) {
29
- if (!fs.existsSync(configPath)) {
30
- throw new Error(`Configuration file not found at ${configPath}`);
31
- }
32
- const configModule = await load(readFileSync(configPath), {
33
- json: true,
34
- });
35
- return AppwriteConfigSchema.parse(configModule);
36
- }
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
+ // }
37
33
 
38
34
  export interface SetupOptions {
39
35
  sync: boolean;
@@ -54,12 +50,6 @@ export interface SetupOptions {
54
50
  key?: string;
55
51
  }
56
52
 
57
- type CollectionConfig = AppwriteConfig["collections"];
58
- type ImportDef = CollectionConfig[number]["importDefs"][number];
59
- type AttributeMappings = ImportDef["attributeMappings"];
60
- type AfterImportAction = AttributeMappings[number]["postImportActions"][number];
61
- type ValidityRule = AttributeMappings[number]["validationActions"][number];
62
-
63
53
  export class UtilsController {
64
54
  private appwriteFolderPath: string;
65
55
  private appwriteConfigPath: string;
@@ -73,13 +63,12 @@ export class UtilsController {
73
63
 
74
64
  constructor() {
75
65
  const basePath = process.cwd(); // Gets the current working directory
76
- const appwriteFolderPath = path.join(basePath, "src", "appwrite");
77
- const appwriteConfigPath = path.join(
78
- appwriteFolderPath,
79
- "appwriteConfig.yaml"
80
- );
81
- this.appwriteFolderPath = appwriteFolderPath;
82
- this.appwriteConfigPath = appwriteConfigPath;
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);
83
72
  }
84
73
 
85
74
  // async loadCustomDefinitions(): Promise<void> {
@@ -114,7 +103,10 @@ export class UtilsController {
114
103
  async init(setupOptions: SetupOptions) {
115
104
  if (!this.config) {
116
105
  console.log("Initializing appwrite client & loading config...");
117
- this.config = await loadConfig(this.appwriteConfigPath);
106
+ this.config = await loadTsConfig(this.appwriteFolderPath);
107
+ if (!this.config) {
108
+ throw new Error("Failed to load config");
109
+ }
118
110
  this.appwriteServer = new Client();
119
111
  if (setupOptions.endpoint) {
120
112
  if (!setupOptions.project || !setupOptions.key) {