Skip to content

Commit 7e2456a

Browse files
Merge pull request #562 from appwrite/feat-cli-buckets
Feat: CLI buckets init&deploy
2 parents b3eb3a0 + 2e5ae7b commit 7e2456a

File tree

4 files changed

+188
-1
lines changed

4 files changed

+188
-1
lines changed

templates/cli/lib/commands/deploy.js.twig

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const inquirer = require("inquirer");
22
const JSONbig = require("json-bigint")({ storeAsString: false });
33
const { Command } = require("commander");
44
const { localConfig } = require("../config");
5-
const { questionsDeployTeams, questionsDeployFunctions, questionsGetEntrypoint, questionsDeployCollections, questionsConfirmDeployCollections } = require("../questions");
5+
const { questionsDeployBuckets, questionsDeployTeams, questionsDeployFunctions, questionsGetEntrypoint, questionsDeployCollections, questionsConfirmDeployCollections } = require("../questions");
66
const { actionRunner, success, log, error, commandDescriptions } = require("../parser");
77
const { functionsGet, functionsCreate, functionsUpdate, functionsCreateDeployment, functionsUpdateDeployment, functionsListVariables, functionsDeleteVariable, functionsCreateVariable } = require('./functions');
88
const {
@@ -26,6 +26,9 @@ const {
2626
databasesDeleteIndex,
2727
databasesUpdateCollection
2828
} = require("./databases");
29+
const {
30+
storageGetBucket, storageUpdateBucket, storageCreateBucket
31+
} = require("./storage");
2932
const {
3033
teamsGet,
3134
teamsUpdate,
@@ -624,6 +627,93 @@ const deployCollection = async ({ all, yes } = {}) => {
624627
}
625628
}
626629

630+
const deployBucket = async ({ all, yes } = {}) => {
631+
let response = {};
632+
633+
let bucketIds = [];
634+
const configBuckets = localConfig.getBuckets();
635+
636+
if(all) {
637+
if (configBuckets.length === 0) {
638+
throw new Error("No buckets found in the current directory. Run `appwrite init bucket` to fetch all your buckets.");
639+
}
640+
bucketIds.push(...configBuckets.map((b) => b.$id));
641+
}
642+
643+
if(bucketIds.length === 0) {
644+
let answers = await inquirer.prompt(questionsDeployBuckets[0])
645+
bucketIds.push(...answers.buckets);
646+
}
647+
648+
let buckets = [];
649+
650+
for(const bucketId of bucketIds) {
651+
const idBuckets = configBuckets.filter((b) => b.$id === bucketId);
652+
buckets.push(...idBuckets);
653+
}
654+
655+
for (let bucket of buckets) {
656+
log(`Deploying bucket ${bucket.name} ( ${bucket['$id']} )`)
657+
658+
try {
659+
response = await storageGetBucket({
660+
bucketId: bucket['$id'],
661+
parseOutput: false,
662+
})
663+
log(`Bucket ${bucket.name} ( ${bucket['$id']} ) already exists.`);
664+
665+
if(!yes) {
666+
answers = await inquirer.prompt(questionsDeployBuckets[1])
667+
if (answers.override !== "YES") {
668+
log(`Received "${answers.override}". Skipping ${bucket.name} ( ${bucket['$id']} )`);
669+
continue;
670+
}
671+
}
672+
673+
log(`Updating bucket ...`)
674+
675+
await storageUpdateBucket({
676+
bucketId: bucket['$id'],
677+
name: bucket.name,
678+
permissions: bucket['$permissions'],
679+
fileSecurity: bucket.fileSecurity,
680+
enabled: bucket.enabled,
681+
maximumFileSize: bucket.maximumFileSize,
682+
allowedFileExtensions: bucket.allowedFileExtensions,
683+
compression: bucket.compression,
684+
encryption: bucket.encryption,
685+
antivirus: bucket.antivirus,
686+
compression: bucket.compression,
687+
parseOutput: false
688+
});
689+
690+
success(`Deployed ${bucket.name} ( ${bucket['$id']} )`);
691+
} catch (e) {
692+
if (e.code == 404) {
693+
log(`Bucket ${bucket.name} does not exist in the project. Creating ... `);
694+
695+
response = await storageCreateBucket({
696+
bucketId: bucket['$id'],
697+
name: bucket.name,
698+
permissions: bucket['$permissions'],
699+
fileSecurity: bucket.fileSecurity,
700+
enabled: bucket.enabled,
701+
maximumFileSize: bucket.maximumFileSize,
702+
allowedFileExtensions: bucket.allowedFileExtensions,
703+
compression: bucket.compression,
704+
encryption: bucket.encryption,
705+
antivirus: bucket.antivirus,
706+
parseOutput: false
707+
})
708+
709+
success(`Deployed ${bucket.name} ( ${bucket['$id']} )`);
710+
} else {
711+
throw e;
712+
}
713+
}
714+
}
715+
}
716+
627717
const deployTeam = async ({ all, yes } = {}) => {
628718
let response = {};
629719

@@ -709,6 +799,13 @@ deploy
709799
.option(`--yes`, `Flag to confirm all warnings`)
710800
.action(actionRunner(deployCollection));
711801

802+
deploy
803+
.command("bucket")
804+
.description("Deploy buckets in the current project.")
805+
.option(`--all`, `Flag to deploy all buckets`)
806+
.option(`--yes`, `Flag to confirm all warnings`)
807+
.action(actionRunner(deployBucket));
808+
712809
deploy
713810
.command("team")
714811
.description("Deploy teams in the current project.")

templates/cli/lib/commands/init.js.twig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const { teamsCreate, teamsList } = require("./teams");
77
const { projectsCreate } = require("./projects");
88
const { functionsCreate } = require("./functions");
99
const { databasesListCollections, databasesList } = require("./databases");
10+
const { storageListBuckets } = require("./storage");
1011
const { sdkForConsole } = require("../sdks");
1112
const { localConfig } = require("../config");
1213
const { questionsInitProject, questionsInitFunction, questionsInitCollection } = require("../questions");
@@ -200,6 +201,24 @@ const initCollection = async ({ all, databaseId } = {}) => {
200201
success();
201202
}
202203

204+
const initBucket = async () => {
205+
// TODO: Pagination?
206+
let response = await storageListBuckets({
207+
queries: [ 'limit(100)' ],
208+
parseOutput: false
209+
})
210+
211+
let buckets = response.buckets;
212+
log(`Found ${buckets.length} buckets`);
213+
214+
buckets.forEach(async bucket => {
215+
log(`Fetching ${bucket.name} ...`);
216+
localConfig.addBucket(bucket);
217+
});
218+
219+
success();
220+
}
221+
203222
const initTeam = async () => {
204223
// TODO: Pagination?
205224
let response = await teamsList({
@@ -240,6 +259,11 @@ init
240259
.option(`--all`, `Flag to initialize all databases`)
241260
.action(actionRunner(initCollection))
242261

262+
init
263+
.command("bucket")
264+
.description("Initialise your Appwrite buckets")
265+
.action(actionRunner(initBucket))
266+
243267
init
244268
.command("team")
245269
.description("Initialise your Appwrite teams")

templates/cli/lib/config.js.twig

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,45 @@ class Local extends Config {
166166
this.set("collections", collections);
167167
}
168168

169+
getBuckets() {
170+
if (!this.has("buckets")) {
171+
return [];
172+
}
173+
return this.get("buckets");
174+
}
175+
176+
getBucket($id) {
177+
if (!this.has("buckets")) {
178+
return {};
179+
}
180+
181+
let buckets = this.get("buckets");
182+
for (let i = 0; i < buckets.length; i++) {
183+
if (buckets[i]['$id'] == $id) {
184+
return buckets[i];
185+
}
186+
}
187+
188+
return {};
189+
}
190+
191+
addBucket(props) {
192+
if (!this.has("buckets")) {
193+
this.set("buckets", []);
194+
}
195+
196+
let buckets = this.get("buckets");
197+
for (let i = 0; i < buckets.length; i++) {
198+
if (buckets[i]['$id'] == props['$id']) {
199+
buckets[i] = props;
200+
this.set("buckets", buckets);
201+
return;
202+
}
203+
}
204+
buckets.push(props);
205+
this.set("buckets", buckets);
206+
}
207+
169208
getDatabases() {
170209
if (!this.has("databases")) {
171210
return [];

templates/cli/lib/questions.js.twig

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,32 @@ const questionsDeployCollections = [
285285
},
286286
]
287287

288+
const questionsDeployBuckets = [
289+
{
290+
type: "checkbox",
291+
name: "buckets",
292+
message: "Which buckets would you like to deploy?",
293+
choices: () => {
294+
let buckets = localConfig.getBuckets();
295+
if (buckets.length === 0) {
296+
throw new Error("No buckets found in the current directory. Run `appwrite init bucket` to fetch all your buckets.");
297+
}
298+
let choices = buckets.map((bucket, idx) => {
299+
return {
300+
name: `${bucket.name} (${bucket['$id']})`,
301+
value: bucket.$id
302+
}
303+
})
304+
return choices;
305+
}
306+
},
307+
{
308+
type: "input",
309+
name: "override",
310+
message: 'Are you sure you want to override this bucket? This can lead to loss of data! Type "YES" to confirm.'
311+
},
312+
]
313+
288314
const questionsGetEntrypoint = [
289315
{
290316
type: "input",
@@ -333,6 +359,7 @@ module.exports = {
333359
questionsInitCollection,
334360
questionsDeployFunctions,
335361
questionsDeployCollections,
362+
questionsDeployBuckets,
336363
questionsDeployTeams,
337364
questionsGetEntrypoint
338365
};

0 commit comments

Comments
 (0)