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.
- package/README.md +4 -39
- package/dist/init.d.ts +2 -0
- package/dist/init.js +57 -0
- package/dist/main.js +62 -100
- package/dist/migrations/afterImportActions.d.ts +1 -4
- package/dist/migrations/afterImportActions.js +1 -0
- package/dist/migrations/appwriteToX.d.ts +46 -46
- package/dist/migrations/appwriteToX.js +6 -2
- package/dist/migrations/attributes.d.ts +1 -1
- package/dist/migrations/attributes.js +97 -71
- package/dist/migrations/backup.d.ts +240 -240
- package/dist/migrations/backup.js +1 -1
- package/dist/migrations/collections.d.ts +1 -1
- package/dist/migrations/collections.js +4 -4
- package/dist/migrations/converters.d.ts +9 -127
- package/dist/migrations/converters.js +1 -504
- package/dist/migrations/dataLoader.d.ts +470 -453
- package/dist/migrations/dataLoader.js +19 -1
- package/dist/migrations/dbHelpers.d.ts +1 -1
- package/dist/migrations/dbHelpers.js +3 -0
- package/dist/migrations/importController.d.ts +1 -1
- package/dist/migrations/importController.js +4 -7
- package/dist/migrations/importDataActions.d.ts +4 -6
- package/dist/migrations/importDataActions.js +6 -4
- package/dist/migrations/indexes.d.ts +1 -1
- package/dist/migrations/indexes.js +1 -1
- package/dist/migrations/migrationHelper.d.ts +29 -29
- package/dist/migrations/migrationHelper.js +1 -1
- package/dist/migrations/openapi.d.ts +1 -1
- package/dist/migrations/openapi.js +4 -1
- package/dist/migrations/queue.d.ts +1 -1
- package/dist/migrations/relationships.d.ts +5 -5
- package/dist/migrations/relationships.js +3 -0
- package/dist/migrations/schemaStrings.d.ts +2 -2
- package/dist/migrations/schemaStrings.js +93 -8
- package/dist/migrations/setupDatabase.d.ts +1 -1
- package/dist/migrations/setupDatabase.js +1 -1
- package/dist/migrations/storage.d.ts +1 -1
- package/dist/migrations/users.d.ts +1 -1
- package/dist/schemas/authUser.d.ts +12 -10
- package/dist/types.d.ts +0 -5
- package/dist/types.js +0 -2
- package/dist/utils/helperFunctions.d.ts +2 -3
- package/dist/utils/loadConfigs.d.ts +13 -0
- package/dist/utils/loadConfigs.js +47 -0
- package/dist/utils/setupFiles.d.ts +1 -0
- package/dist/utils/setupFiles.js +98 -223
- package/dist/utilsController.d.ts +1 -3
- package/dist/utilsController.js +14 -18
- package/package.json +9 -2
- package/src/init.ts +64 -0
- package/src/main.ts +73 -98
- package/src/migrations/afterImportActions.ts +1 -5
- package/src/migrations/appwriteToX.ts +6 -2
- package/src/migrations/attributes.ts +198 -150
- package/src/migrations/backup.ts +1 -1
- package/src/migrations/collections.ts +5 -11
- package/src/migrations/converters.ts +1 -540
- package/src/migrations/dataLoader.ts +19 -2
- package/src/migrations/dbHelpers.ts +4 -1
- package/src/migrations/importController.ts +5 -15
- package/src/migrations/importDataActions.ts +10 -14
- package/src/migrations/indexes.ts +1 -1
- package/src/migrations/migrationHelper.ts +1 -1
- package/src/migrations/openapi.ts +4 -1
- package/src/migrations/queue.ts +1 -1
- package/src/migrations/relationships.ts +4 -1
- package/src/migrations/schemaStrings.ts +106 -9
- package/src/migrations/setupDatabase.ts +1 -1
- package/src/migrations/storage.ts +1 -1
- package/src/migrations/users.ts +1 -1
- package/src/types.ts +0 -5
- package/src/utils/helperFunctions.ts +2 -3
- package/src/utils/loadConfigs.ts +55 -0
- package/src/utils/setupFiles.ts +114 -225
- package/src/utilsController.ts +27 -35
- package/src/migrations/schema.ts +0 -748
@@ -0,0 +1,47 @@
|
|
1
|
+
import path from "path";
|
2
|
+
import fs from "fs";
|
3
|
+
import {} from "appwrite-utils";
|
4
|
+
import { register } from "tsx/esm/api"; // Import the register function
|
5
|
+
/**
|
6
|
+
* Recursively searches for a file named 'appwriteConfig.ts' starting from the given directory.
|
7
|
+
* @param dir The directory to start the search from.
|
8
|
+
* @returns The path to the file if found, or null if not found.
|
9
|
+
*/
|
10
|
+
export const findAppwriteConfig = (dir) => {
|
11
|
+
const files = fs.readdirSync(dir, { withFileTypes: true });
|
12
|
+
for (const file of files) {
|
13
|
+
if (file.isDirectory()) {
|
14
|
+
const result = findAppwriteConfig(path.join(dir, file.name));
|
15
|
+
if (result)
|
16
|
+
return result;
|
17
|
+
}
|
18
|
+
else if (file.name === "appwriteConfig.ts") {
|
19
|
+
return path.join(dir, file.name);
|
20
|
+
}
|
21
|
+
}
|
22
|
+
return null;
|
23
|
+
};
|
24
|
+
/**
|
25
|
+
* Loads the Appwrite configuration and all collection configurations from a specified directory.
|
26
|
+
* @param configDir The directory containing the appwriteConfig.ts and collections folder.
|
27
|
+
* @returns The loaded Appwrite configuration including collections.
|
28
|
+
*/
|
29
|
+
export const loadConfig = async (configDir) => {
|
30
|
+
const unregister = register(); // Register tsx enhancement
|
31
|
+
try {
|
32
|
+
const configPath = path.resolve(configDir, "appwriteConfig.ts");
|
33
|
+
const config = (await import(configPath)).default;
|
34
|
+
const collectionsDir = path.resolve(configDir, "collections");
|
35
|
+
const collectionFiles = fs.readdirSync(collectionsDir);
|
36
|
+
config.collections = [];
|
37
|
+
for (const file of collectionFiles) {
|
38
|
+
const filePath = path.resolve(collectionsDir, file);
|
39
|
+
const collectionModule = (await import(filePath)).default;
|
40
|
+
config.collections.push(collectionModule);
|
41
|
+
}
|
42
|
+
return config;
|
43
|
+
}
|
44
|
+
finally {
|
45
|
+
unregister(); // Unregister tsx when done
|
46
|
+
}
|
47
|
+
};
|
@@ -1,2 +1,3 @@
|
|
1
1
|
export declare const customDefinitionsFile = "import type { ConverterFunctions, ValidationRules, AfterImportActions } from \"appwrite-utils\";\n\nexport const customConverterFunctions: ConverterFunctions = {\n // Add your custom converter functions here\n}\nexport const customValidationRules: ValidationRules = {\n // Add your custom validation rules here\n}\nexport const customAfterImportActions: AfterImportActions = {\n // Add your custom after import actions here\n}";
|
2
|
+
export declare const createEmptyCollection: (collectionName: string) => void;
|
2
3
|
export declare const setupDirsFiles: (example?: boolean) => Promise<void>;
|
package/dist/utils/setupFiles.js
CHANGED
@@ -1,222 +1,59 @@
|
|
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 { findAppwriteConfig } from "./loadConfigs.js";
|
5
|
+
// Example base configuration using types from appwrite-utils
|
6
|
+
const baseConfig = {
|
7
|
+
appwriteEndpoint: "https://cloud.appwrite.io/v1",
|
8
|
+
appwriteProject: "YOUR_PROJECT_ID",
|
9
|
+
appwriteKey: "YOUR_API_KEY",
|
10
|
+
enableDevDatabase: true,
|
11
|
+
enableBackups: true,
|
12
|
+
backupInterval: 3600,
|
13
|
+
backupRetention: 30,
|
14
|
+
enableBackupCleanup: true,
|
15
|
+
enableMockData: false,
|
16
|
+
enableWipeOtherDatabases: true,
|
17
|
+
documentBucketId: "documents",
|
18
|
+
usersCollectionName: "Members",
|
19
|
+
databases: [
|
20
|
+
{ $id: "main", name: "Main" },
|
21
|
+
{ $id: "staging", name: "Staging" },
|
22
|
+
{ $id: "dev", name: "Development" },
|
23
|
+
],
|
24
|
+
};
|
25
|
+
const collectionsConfig = [
|
26
|
+
{
|
27
|
+
name: "ExampleCollection",
|
28
|
+
content: `import { CollectionCreate } from "appwrite-utils";
|
29
|
+
|
30
|
+
const ExampleCollection: Partial<CollectionCreate> = {
|
31
|
+
name: 'ExampleCollection',
|
32
|
+
$permissions: [
|
33
|
+
{ permission: 'read', target: 'any' },
|
34
|
+
{ permission: 'create', target: 'users' },
|
35
|
+
{ permission: 'update', target: 'users' },
|
36
|
+
{ permission: 'delete', target: 'users' }
|
37
|
+
],
|
38
|
+
attributes: [
|
39
|
+
{ key: 'alterEgoName', type: 'string', size: 255, required: false },
|
40
|
+
// Add more attributes here
|
41
|
+
],
|
42
|
+
indexes: [
|
43
|
+
{ key: 'alterEgoName_search', type: 'fulltext', attributes: ['alterEgoName'] }
|
44
|
+
],
|
45
|
+
importDefs: [
|
46
|
+
// Define import definitions here
|
47
|
+
]
|
48
|
+
};
|
49
|
+
|
50
|
+
export default ExampleCollection;`,
|
51
|
+
},
|
52
|
+
// Add more collections here
|
53
|
+
];
|
4
54
|
// Define our YAML files
|
5
55
|
// Define our YAML files
|
6
|
-
const configFileExample =
|
7
|
-
# Appwrite configuration settings
|
8
|
-
appwriteEndpoint: 'https://cloud.appwrite.io/v1' # Your Appwrite endpoint. Default: 'https://cloud.appwrite.io/v1'
|
9
|
-
appwriteProject: 'YOUR_PROJECT_ID' # Your Appwrite project ID
|
10
|
-
appwriteKey: 'YOUR_API_KEY' # Your Appwrite API key (needs storage and databases at minimum)
|
11
|
-
appwriteClient: null # Your Appwrite client -- don't worry about this
|
12
|
-
enableDevDatabase: true # Enable development database alongside main
|
13
|
-
enableBackups: true # Enable backups
|
14
|
-
backupInterval: 3600 # Backup interval in seconds
|
15
|
-
backupRetention: 30 # Backup retention in days
|
16
|
-
enableBackupCleanup: true # Enable backup cleanup
|
17
|
-
enableMockData: false # Enable mock data generation
|
18
|
-
enableWipeOtherDatabases: true # Enable wiping other databases
|
19
|
-
documentBucketId: 'documents' # Your Appwrite bucket ID for documents
|
20
|
-
usersCollectionName: 'Members' # Your Appwrite collection for any extra info while importing members (if any)
|
21
|
-
# This allows you to use any targetKey in the users field to create your user
|
22
|
-
# these are: name, email, phone, labels, prefs, password, userId and (not yet added)
|
23
|
-
# $createdAt, $updatedAt -- Add them to your attributeMappings (NOT attributes) to define them and set the
|
24
|
-
# targetKey to the same as the Appwrite targetKey
|
25
|
-
databases:
|
26
|
-
- $id: 'main'
|
27
|
-
name: 'Main'
|
28
|
-
- $id: 'staging'
|
29
|
-
name: 'Staging'
|
30
|
-
- $id: 'dev'
|
31
|
-
name: 'Development'
|
32
|
-
collections:
|
33
|
-
- name: 'Members'
|
34
|
-
$permissions:
|
35
|
-
- permission: read
|
36
|
-
target: any
|
37
|
-
- permission: create
|
38
|
-
target: users
|
39
|
-
- permission: update
|
40
|
-
target: users
|
41
|
-
- permission: delete
|
42
|
-
target: users
|
43
|
-
attributes:
|
44
|
-
- key: 'idOrig'
|
45
|
-
type: 'string'
|
46
|
-
size: 255
|
47
|
-
required: false
|
48
|
-
- key: 'dogs'
|
49
|
-
type: 'relationship'
|
50
|
-
relatedCollection: 'Dogs'
|
51
|
-
relationType: 'oneToMany'
|
52
|
-
twoWay: true
|
53
|
-
twoWayKey: 'owner'
|
54
|
-
side: 'parent'
|
55
|
-
onDelete: 'cascade'
|
56
|
-
importMapping: { originalIdField: 'idOrig', targetField: 'ownerIdOrig' }
|
57
|
-
- key: 'dogIds'
|
58
|
-
type: 'string'
|
59
|
-
size: 255
|
60
|
-
array: true
|
61
|
-
- key: 'profilePhoto'
|
62
|
-
type: 'string'
|
63
|
-
size: 255
|
64
|
-
required: false
|
65
|
-
- key: 'profilePhotoTest'
|
66
|
-
type: 'string'
|
67
|
-
size: 255
|
68
|
-
required: false
|
69
|
-
indexes:
|
70
|
-
- key: 'idOrig_index'
|
71
|
-
type: 'key'
|
72
|
-
attributes: ['idOrig']
|
73
|
-
importDefs:
|
74
|
-
- filePath: 'importData/members.json'
|
75
|
-
basePath: 'RECORDS'
|
76
|
-
attributeMappings:
|
77
|
-
- oldKey: 'id'
|
78
|
-
targetKey: 'idOrig'
|
79
|
-
converters: ['anyToString']
|
80
|
-
postImportActions:
|
81
|
-
- action: 'checkAndUpdateFieldInDocument'
|
82
|
-
params:
|
83
|
-
- "{dbId}"
|
84
|
-
- "{collId}"
|
85
|
-
- "{docId}"
|
86
|
-
- "idOrig"
|
87
|
-
- "{id}"
|
88
|
-
- "{$id}"
|
89
|
-
- oldKey: 'name'
|
90
|
-
targetKey: 'name'
|
91
|
-
- oldKey: 'email'
|
92
|
-
targetKey: 'email'
|
93
|
-
- oldKey: 'doesntMatter'
|
94
|
-
targetKey: 'profilePhoto'
|
95
|
-
fileData: { name: "profilePhoto_{id}", path: "importData/profilePhotos" }
|
96
|
-
- oldKey: 'photoUrl'
|
97
|
-
targetKey: 'profilePhotoTest'
|
98
|
-
fileData: { name: "profilePhotoTest_{id}", path: "{photoUrl}" }
|
99
|
-
- name: 'Dogs'
|
100
|
-
$permissions:
|
101
|
-
- permission: read
|
102
|
-
target: any
|
103
|
-
- permission: create
|
104
|
-
target: users
|
105
|
-
- permission: update
|
106
|
-
target: users
|
107
|
-
- permission: delete
|
108
|
-
target: users
|
109
|
-
attributes:
|
110
|
-
- key: 'name'
|
111
|
-
type: 'string'
|
112
|
-
size: 255
|
113
|
-
required: true
|
114
|
-
- key: 'breed'
|
115
|
-
type: 'string'
|
116
|
-
size: 255
|
117
|
-
required: false
|
118
|
-
- key: 'age'
|
119
|
-
type: 'integer'
|
120
|
-
required: false
|
121
|
-
min: 0
|
122
|
-
max: 100
|
123
|
-
- key: 'idOrig'
|
124
|
-
type: 'string'
|
125
|
-
size: 20
|
126
|
-
required: false
|
127
|
-
- key: 'ownerIdOrig'
|
128
|
-
type: 'string'
|
129
|
-
size: 255
|
130
|
-
required: false
|
131
|
-
- key: 'vetRecords'
|
132
|
-
type: 'string'
|
133
|
-
size: 255
|
134
|
-
required: false
|
135
|
-
- key: 'vetRecordIds'
|
136
|
-
type: 'string'
|
137
|
-
size: 255
|
138
|
-
array: true
|
139
|
-
required: false
|
140
|
-
indexes:
|
141
|
-
- key: 'ownerIdIndex'
|
142
|
-
type: 'key'
|
143
|
-
attributes: ['ownerIdOrig']
|
144
|
-
importDefs:
|
145
|
-
- filePath: 'importData/dogs.json'
|
146
|
-
basePath: 'RECORDS'
|
147
|
-
attributeMappings:
|
148
|
-
- oldKey: 'id'
|
149
|
-
targetKey: 'idOrig'
|
150
|
-
- oldKey: 'name'
|
151
|
-
targetKey: 'name'
|
152
|
-
- oldKey: 'breed'
|
153
|
-
targetKey: 'breed'
|
154
|
-
- oldKey: 'age'
|
155
|
-
targetKey: 'age'
|
156
|
-
- oldKey: 'ownerId'
|
157
|
-
targetKey: 'ownerIdOrig'
|
158
|
-
- oldKey: 'vetRecords'
|
159
|
-
targetKey: 'vetRecords'
|
160
|
-
converters: ['stringifyObject']
|
161
|
-
- oldKey: 'vetRecords.[any].id'
|
162
|
-
targetKey: 'vetRecordIds'
|
163
|
-
converters: ['anyToString']
|
164
|
-
- filePath: 'importData/dogs.json'
|
165
|
-
basePath: 'RECORDS'
|
166
|
-
type: 'update'
|
167
|
-
updateMapping: { originalIdField: 'id', targetField: 'idOrig' }
|
168
|
-
attributeMappings:
|
169
|
-
- oldKey: 'name'
|
170
|
-
targetKey: 'name'
|
171
|
-
- oldKey: 'breed'
|
172
|
-
targetKey: 'breed'
|
173
|
-
- oldKey: 'age'
|
174
|
-
targetKey: 'age'`;
|
175
|
-
const configFile = `# yaml-language-server: $schema=./.appwrite/appwriteUtilsConfigSchema.json
|
176
|
-
# Basic Appwrite configuration settings
|
177
|
-
appwriteEndpoint: 'https://cloud.appwrite.io/v1' # Your Appwrite endpoint
|
178
|
-
appwriteProject: 'YOUR_PROJECT_ID' # Your Appwrite project ID
|
179
|
-
appwriteKey: 'YOUR_API_KEY' # Your Appwrite API key (needs storage and databases at minimum)
|
180
|
-
enableDevDatabase: true # Enable development database alongside main. Default: true
|
181
|
-
enableBackups: true # Enable backups. Default: true
|
182
|
-
backupInterval: 3600 # Backup interval in seconds. Default: 3600 - DOES NOTHING RIGHT NOW
|
183
|
-
backupRetention: 30 # Backup retention in days. Default: 30 - DOES NOTHING RIGHT NOW
|
184
|
-
enableBackupCleanup: true # Enable backup cleanup. Default: true - DOES NOTHING RIGHT NOW
|
185
|
-
enableMockData: false # Enable mock data generation. Default: false - DOES NOTHING RIGHT NOW
|
186
|
-
enableWipeOtherDatabases: true # Enable wiping other databases. Default: true
|
187
|
-
documentBucketId: 'documents' # Your Appwrite bucket ID for documents. Default: 'documents'
|
188
|
-
usersCollectionName: 'Members' # Your Appwrite collection for any extra info while importing members (if any). Default: 'Members'
|
189
|
-
# Databases configuration
|
190
|
-
# The first one is *always* Production
|
191
|
-
# The second is *always* Staging
|
192
|
-
# The third is *always* Development
|
193
|
-
# They are found by name matching (without spaces and all lowercase), not $id
|
194
|
-
# If no $id is included for anything defined, Appwrite will auto-generate one in its stead
|
195
|
-
databases:
|
196
|
-
- $id: 'main' # Database ID
|
197
|
-
name: 'Main' # Database name
|
198
|
-
- $id: 'staging'
|
199
|
-
name: 'Staging'
|
200
|
-
- $id: 'dev'
|
201
|
-
name: 'Development'
|
202
|
-
|
203
|
-
# Collections configuration
|
204
|
-
collections:
|
205
|
-
- name: 'ExampleCollection' # Collection name
|
206
|
-
$permissions: # Permissions for the collection
|
207
|
-
- permission: read # Permission type
|
208
|
-
target: any # Permission target
|
209
|
-
- permission: create
|
210
|
-
target: users
|
211
|
-
- permission: update
|
212
|
-
target: users
|
213
|
-
- permission: delete
|
214
|
-
target: users
|
215
|
-
attributes: # Attributes of the collection
|
216
|
-
- key: 'exampleKey' # Attribute key
|
217
|
-
type: 'string' # Attribute type
|
218
|
-
size: 255 # Size of the attribute (for strings)
|
219
|
-
required: true # Whether the attribute is required`;
|
56
|
+
const configFileExample = `d`;
|
220
57
|
export const customDefinitionsFile = `import type { ConverterFunctions, ValidationRules, AfterImportActions } from "appwrite-utils";
|
221
58
|
|
222
59
|
export const customConverterFunctions: ConverterFunctions = {
|
@@ -228,39 +65,77 @@ export const customValidationRules: ValidationRules = {
|
|
228
65
|
export const customAfterImportActions: AfterImportActions = {
|
229
66
|
// Add your custom after import actions here
|
230
67
|
}`;
|
68
|
+
export const createEmptyCollection = (collectionName) => {
|
69
|
+
const emptyCollection = `import type { CollectionCreate } from "appwrite-utils";
|
70
|
+
|
71
|
+
const ${collectionName}: Partial<CollectionCreate> = {
|
72
|
+
name: '${collectionName}',
|
73
|
+
$permissions: [
|
74
|
+
{ permission: 'read', target: 'any' },
|
75
|
+
{ permission: 'create', target: 'users' },
|
76
|
+
{ permission: 'update', target: 'users' },
|
77
|
+
{ permission: 'delete', target: 'users' }
|
78
|
+
],
|
79
|
+
attributes: [
|
80
|
+
// Add more attributes here
|
81
|
+
],
|
82
|
+
indexes: [
|
83
|
+
// Add more indexes here
|
84
|
+
],
|
85
|
+
};
|
86
|
+
|
87
|
+
export default ${collectionName};`;
|
88
|
+
const appwriteConfigPath = findAppwriteConfig(process.cwd());
|
89
|
+
if (!appwriteConfigPath) {
|
90
|
+
console.error("Failed to find appwriteConfig.ts");
|
91
|
+
return;
|
92
|
+
}
|
93
|
+
const collectionsFolder = path.join(path.dirname(appwriteConfigPath), "collections");
|
94
|
+
const collectionFilePath = path.join(collectionsFolder, `${collectionName}.ts`);
|
95
|
+
writeFileSync(collectionFilePath, emptyCollection);
|
96
|
+
};
|
231
97
|
export const setupDirsFiles = async (example = false) => {
|
232
98
|
const basePath = process.cwd();
|
233
|
-
const srcPath = path.join(basePath
|
99
|
+
const srcPath = path.join(basePath);
|
234
100
|
// Check if src directory exists in the current working directory
|
235
101
|
if (!existsSync(srcPath)) {
|
236
102
|
console.error("No 'src' directory found in the current working directory.");
|
237
103
|
return;
|
238
104
|
}
|
239
105
|
const appwriteFolder = path.join(srcPath, "appwrite");
|
240
|
-
const appwriteConfigFile = path.join(appwriteFolder, "appwriteConfig.
|
106
|
+
const appwriteConfigFile = path.join(appwriteFolder, "appwriteConfig.ts");
|
241
107
|
const appwriteCustomDefsFile = path.join(appwriteFolder, "customDefinitions.ts");
|
242
108
|
// const appwriteMigrationsFolder = path.join(appwriteFolder, "migrations");
|
243
109
|
const appwriteSchemaFolder = path.join(appwriteFolder, "schemas");
|
244
110
|
const appwriteDataFolder = path.join(appwriteFolder, "importData");
|
245
111
|
const appwriteHiddenFolder = path.join(appwriteFolder, ".appwrite");
|
112
|
+
const collectionsFolder = path.join(appwriteFolder, "collections");
|
246
113
|
// Directory creation and file writing logic remains the same
|
247
114
|
if (!existsSync(appwriteFolder)) {
|
248
115
|
mkdirSync(appwriteFolder, { recursive: true });
|
249
116
|
}
|
117
|
+
if (!existsSync(collectionsFolder)) {
|
118
|
+
mkdirSync(collectionsFolder, { recursive: true });
|
119
|
+
}
|
250
120
|
if (!existsSync(appwriteConfigFile)) {
|
251
121
|
if (example) {
|
252
122
|
writeFileSync(appwriteConfigFile, configFileExample);
|
253
123
|
}
|
254
124
|
else {
|
255
|
-
|
125
|
+
const baseConfigContent = `import { AppwriteConfig } from "appwrite-utils";
|
126
|
+
|
127
|
+
const appwriteConfig: AppwriteConfig = ${JSON.stringify(baseConfig, null, 2)};
|
128
|
+
|
129
|
+
export default appwriteConfig;
|
130
|
+
`;
|
131
|
+
writeFileSync(appwriteConfigFile, baseConfigContent);
|
256
132
|
}
|
257
133
|
}
|
258
|
-
//
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
// }
|
134
|
+
// Create TypeScript files for each collection
|
135
|
+
collectionsConfig.forEach((collection) => {
|
136
|
+
const collectionFilePath = path.join(collectionsFolder, `${collection.name}.ts`);
|
137
|
+
writeFileSync(collectionFilePath, collection.content);
|
138
|
+
});
|
264
139
|
if (!existsSync(appwriteSchemaFolder)) {
|
265
140
|
mkdirSync(appwriteSchemaFolder, { recursive: true });
|
266
141
|
}
|
@@ -1,6 +1,4 @@
|
|
1
|
-
import { type ConverterFunctions } from "
|
2
|
-
import { type AfterImportActions } from "./migrations/afterImportActions.js";
|
3
|
-
import { type ValidationRules } from "./migrations/validationRules.js";
|
1
|
+
import { type AfterImportActions, type ConverterFunctions, type ValidationRules } from "appwrite-utils";
|
4
2
|
export interface SetupOptions {
|
5
3
|
sync: boolean;
|
6
4
|
runProd: boolean;
|
package/dist/utilsController.js
CHANGED
@@ -1,26 +1,17 @@
|
|
1
1
|
import { Client, Databases, Storage } from "node-appwrite";
|
2
2
|
import { startSetup } from "./migrations/setupDatabase.js";
|
3
|
-
import { AppwriteConfigSchema, } from "./migrations/schema.js";
|
4
3
|
import path from "path";
|
5
4
|
import fs from "fs";
|
6
5
|
import { load } from "js-yaml";
|
7
6
|
import { ImportDataActions } from "./migrations/importDataActions.js";
|
8
|
-
import { converterFunctions, } from "./migrations/converters.js";
|
9
7
|
import { readFileSync } from "./utils/helperFunctions.js";
|
10
|
-
import { afterImportActions
|
11
|
-
import { validationRules, } from "
|
8
|
+
import { afterImportActions } from "./migrations/afterImportActions.js";
|
9
|
+
import { converterFunctions, validationRules, AppwriteConfigSchema, } from "appwrite-utils";
|
12
10
|
import { ImportController } from "./migrations/importController.js";
|
13
11
|
import _ from "lodash";
|
14
12
|
import { AppwriteToX } from "./migrations/appwriteToX.js";
|
15
|
-
|
16
|
-
|
17
|
-
throw new Error(`Configuration file not found at ${configPath}`);
|
18
|
-
}
|
19
|
-
const configModule = await load(readFileSync(configPath), {
|
20
|
-
json: true,
|
21
|
-
});
|
22
|
-
return AppwriteConfigSchema.parse(configModule);
|
23
|
-
}
|
13
|
+
import { loadConfig as loadTsConfig } from "./utils/loadConfigs.js";
|
14
|
+
import { findAppwriteConfig } from "./utils/loadConfigs.js";
|
24
15
|
export class UtilsController {
|
25
16
|
appwriteFolderPath;
|
26
17
|
appwriteConfigPath;
|
@@ -33,10 +24,12 @@ export class UtilsController {
|
|
33
24
|
afterImportActionsDefinitions = afterImportActions;
|
34
25
|
constructor() {
|
35
26
|
const basePath = process.cwd(); // Gets the current working directory
|
36
|
-
const
|
37
|
-
|
38
|
-
|
39
|
-
|
27
|
+
const appwriteConfigFound = findAppwriteConfig(basePath);
|
28
|
+
if (!appwriteConfigFound) {
|
29
|
+
throw new Error("Failed to find appwriteConfig.ts");
|
30
|
+
}
|
31
|
+
this.appwriteConfigPath = appwriteConfigFound;
|
32
|
+
this.appwriteFolderPath = path.dirname(appwriteConfigFound);
|
40
33
|
}
|
41
34
|
// async loadCustomDefinitions(): Promise<void> {
|
42
35
|
// try {
|
@@ -69,7 +62,10 @@ export class UtilsController {
|
|
69
62
|
async init(setupOptions) {
|
70
63
|
if (!this.config) {
|
71
64
|
console.log("Initializing appwrite client & loading config...");
|
72
|
-
this.config = await
|
65
|
+
this.config = await loadTsConfig(this.appwriteFolderPath);
|
66
|
+
if (!this.config) {
|
67
|
+
throw new Error("Failed to load config");
|
68
|
+
}
|
73
69
|
this.appwriteServer = new Client();
|
74
70
|
if (setupOptions.endpoint) {
|
75
71
|
if (!setupOptions.project || !setupOptions.key) {
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "appwrite-utils-cli",
|
3
3
|
"description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
|
4
|
-
"version": "0.0.
|
4
|
+
"version": "0.0.276",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
@@ -21,21 +21,28 @@
|
|
21
21
|
"utility"
|
22
22
|
],
|
23
23
|
"bin": {
|
24
|
-
"appwrite-
|
24
|
+
"appwrite-init": "./dist/init.js",
|
25
25
|
"appwrite-migrate": "./dist/main.js"
|
26
26
|
},
|
27
27
|
"scripts": {
|
28
28
|
"build": "bun run tsc",
|
29
|
+
"init": "tsx --no-cache src/init.ts",
|
30
|
+
"migrate": "tsx --no-cache src/main.ts",
|
29
31
|
"deploy": "bun run build && npm publish --access public",
|
30
32
|
"postinstall": "echo 'This package is intended for CLI use only and should not be added as a dependency in other projects.'"
|
31
33
|
},
|
32
34
|
"dependencies": {
|
33
35
|
"@asteasolutions/zod-to-openapi": "^7.0.0",
|
36
|
+
"@types/inquirer": "^9.0.7",
|
37
|
+
"appwrite-utils": "latest",
|
38
|
+
"commander": "^12.0.0",
|
39
|
+
"inquirer": "^9.2.20",
|
34
40
|
"js-yaml": "^4.1.0",
|
35
41
|
"lodash": "^4.17.21",
|
36
42
|
"luxon": "^3.4.4",
|
37
43
|
"nanostores": "^0.10.3",
|
38
44
|
"node-appwrite": "^12.0.1",
|
45
|
+
"tsx": "^4.9.3",
|
39
46
|
"winston": "^3.13.0",
|
40
47
|
"zod": "^3.22.4"
|
41
48
|
},
|
package/src/init.ts
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
import inquirer from "inquirer";
|
3
|
+
import { createEmptyCollection, setupDirsFiles } from "./utils/setupFiles.js";
|
4
|
+
|
5
|
+
console.log("Welcome to Appwrite Utils CLI Tool by Zach Handley");
|
6
|
+
console.log(
|
7
|
+
"For more information, visit https://github.com/zachhandley/appwrite-utils"
|
8
|
+
);
|
9
|
+
|
10
|
+
async function main() {
|
11
|
+
const answers = await inquirer.prompt([
|
12
|
+
{
|
13
|
+
type: "list",
|
14
|
+
name: "action",
|
15
|
+
message: "What would you like to do?",
|
16
|
+
choices: [
|
17
|
+
"Create collection config file",
|
18
|
+
"Create function (not available)",
|
19
|
+
"Setup directories and files",
|
20
|
+
"Setup directories and files with example data",
|
21
|
+
"Exit",
|
22
|
+
],
|
23
|
+
},
|
24
|
+
]);
|
25
|
+
|
26
|
+
switch (answers.action) {
|
27
|
+
case "Create collection config file":
|
28
|
+
const { collectionName } = await inquirer.prompt([
|
29
|
+
{
|
30
|
+
type: "input",
|
31
|
+
name: "collectionName",
|
32
|
+
message: "Enter the name of the collection:",
|
33
|
+
validate: (input) =>
|
34
|
+
input.trim() !== "" || "Collection name cannot be empty.",
|
35
|
+
},
|
36
|
+
]);
|
37
|
+
console.log(`Creating collection config file for '${collectionName}'...`);
|
38
|
+
createEmptyCollection(collectionName);
|
39
|
+
break;
|
40
|
+
case "Create function (not available)":
|
41
|
+
console.log("This feature is not available yet.");
|
42
|
+
break;
|
43
|
+
case "Setup directories and files":
|
44
|
+
console.log("Setting up directories and files...");
|
45
|
+
setupDirsFiles(false); // Assuming false means no example data
|
46
|
+
break;
|
47
|
+
case "Setup directories and files with example data":
|
48
|
+
console.log("Setting up directories and files with example data...");
|
49
|
+
setupDirsFiles(true); // Assuming false means no example data
|
50
|
+
break;
|
51
|
+
case "Exit":
|
52
|
+
console.log("Exiting...");
|
53
|
+
process.exit(0);
|
54
|
+
break;
|
55
|
+
default:
|
56
|
+
console.log("Invalid option, please try again.");
|
57
|
+
break;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
main().catch((error) => {
|
62
|
+
console.error("An error occurred:", error);
|
63
|
+
process.exit(1);
|
64
|
+
});
|