@@ -15,6 +15,7 @@ const { localConfig, globalConfig } = require("../config");
15
15
const {
16
16
questionsCreateFunction,
17
17
questionsCreateFunctionSelectTemplate,
18
+ questionsCreateSite,
18
19
questionsCreateBucket,
19
20
questionsCreateMessagingTopic,
20
21
questionsCreateCollection,
@@ -25,11 +26,13 @@ const {
25
26
} = require("../questions");
26
27
const { cliConfig, success, log, hint, error, actionRunner, commandDescriptions } = require("../parser");
27
28
const { accountGet } = require("./account");
29
+ const { sitesListTemplates } = require("./sites");
28
30
const { sdkForConsole } = require("../sdks");
29
31
30
32
const initResources = async () => {
31
33
const actions = {
32
34
function: initFunction,
35
+ site: initSite,
33
36
collection: initCollection,
34
37
bucket: initBucket,
35
38
team: initTeam,
@@ -318,6 +321,153 @@ const initFunction = async () => {
318
321
log("Next you can use 'appwrite run function' to develop a function locally. To deploy the function, use 'appwrite push function'");
319
322
}
320
323
324
+ const initSite = async () => {
325
+ process.chdir(localConfig.configDirectoryPath)
326
+
327
+ const answers = await inquirer.prompt(questionsCreateSite);
328
+ const siteFolder = path.join(process.cwd(), 'sites');
329
+
330
+ if (!fs.existsSync(siteFolder)) {
331
+ fs.mkdirSync(siteFolder, {
332
+ recursive: true
333
+ });
334
+ }
335
+
336
+ const siteId = answers.id === 'unique()' ? ID.unique() : answers.id;
337
+ const siteName = answers.name;
338
+ const siteDir = path.join(siteFolder, siteName);
339
+ const templatesDir = path.join(siteFolder, `${siteId}-templates`);
340
+
341
+ if (fs.existsSync(siteDir)) {
342
+ throw new Error(`( ${siteName} ) already exists in the current directory. Please choose another name.`);
343
+ }
344
+
345
+ let templateDetails;
346
+ try {
347
+ const response = await sitesListTemplates({
348
+ frameworks: [answers.framework.key],
349
+ useCases: ['starter'],
350
+ limit: 1,
351
+ parseOutput: false
352
+ });
353
+ if (response.total == 0) {
354
+ throw new Error(`No starter template found for framework ${answers.framework.key}`);
355
+ }
356
+ templateDetails = response.templates[0];
357
+ } catch (error) {
358
+ throw new Error(`Failed to fetch template for framework ${answers.framework.key}: ${error.message}`);
359
+ }
360
+
361
+ fs.mkdirSync(siteDir, "777");
362
+ fs.mkdirSync(templatesDir, "777");
363
+ const repo = `https://github.com/${templateDetails.providerOwner}/${templateDetails.providerRepositoryId}`;
364
+ let selected = { template: templateDetails.frameworks[0].providerRootDirectory };
365
+
366
+ let gitInitCommands = '';
367
+ let gitPullCommands = '';
368
+
369
+ const sparse = selected.template.startsWith('./') ? selected.template.substring(2) : selected.template;
370
+
371
+ log('Fetching site code ...');
372
+
373
+ if(selected.template === './') {
374
+ gitInitCommands = `git clone --single-branch --depth 1 ${repo} .`;
375
+ } else {
376
+ gitInitCommands = `git clone --single-branch --depth 1 --sparse ${repo} .`; // depth prevents fetching older commits reducing the amount fetched
377
+ gitPullCommands = `git sparse-checkout add ${sparse}`;
378
+ }
379
+
380
+ /* Force use CMD as powershell does not support && */
381
+ if (process.platform === 'win32') {
382
+ gitInitCommands = 'cmd /c "' + gitInitCommands + '"';
383
+ if(gitPullCommands)
384
+ gitPullCommands = 'cmd /c "' + gitPullCommands + '"';
385
+ }
386
+
387
+ /* Execute the child process but do not print any std output */
388
+ try {
389
+ childProcess.execSync(gitInitCommands, { stdio: 'pipe', cwd: templatesDir });
390
+ if(gitPullCommands)
391
+ childProcess.execSync(gitPullCommands, { stdio: 'pipe', cwd: templatesDir });
392
+ } catch (error) {
393
+ /* Specialised errors with recommended actions to take */
394
+ if (error.message.includes('error: unknown option')) {
395
+ throw new Error(`${error.message} \n\nSuggestion: Try updating your git to the latest version, then trying to run this command again.`)
396
+ } else if (error.message.includes('is not recognized as an internal or external command,') || error.message.includes('command not found')) {
397
+ throw new Error(`${error.message} \n\nSuggestion: It appears that git is not installed, try installing git then trying to run this command again.`)
398
+ } else {
399
+ throw error;
400
+ }
401
+ }
402
+
403
+ fs.rmSync(path.join(templatesDir, ".git"), { recursive: true });
404
+
405
+ const copyRecursiveSync = (src, dest) => {
406
+ let exists = fs.existsSync(src);
407
+ let stats = exists && fs.statSync(src);
408
+ let isDirectory = exists && stats.isDirectory();
409
+ if (isDirectory) {
410
+ if (!fs.existsSync(dest)) {
411
+ fs.mkdirSync(dest);
412
+ }
413
+
414
+ fs.readdirSync(src).forEach(function (childItemName) {
415
+ copyRecursiveSync(path.join(src, childItemName), path.join(dest, childItemName));
416
+ });
417
+ } else {
418
+ fs.copyFileSync(src, dest);
419
+ }
420
+ };
421
+ copyRecursiveSync(selected.template === './' ? templatesDir : path.join(templatesDir, selected.template), siteDir);
422
+
423
+ fs.rmSync(templatesDir, { recursive: true, force: true });
424
+
425
+ const readmePath = path.join(process.cwd(), 'sites', siteName, 'README.md');
426
+ const readmeFile = fs.readFileSync(readmePath).toString();
427
+ const newReadmeFile = readmeFile.split('\n');
428
+ newReadmeFile[0] = `# ${answers.key}`;
429
+ newReadmeFile.splice(1, 2);
430
+ fs.writeFileSync(readmePath, newReadmeFile.join('\n'));
431
+
432
+ let data = {
433
+ $id: siteId,
434
+ name: answers.name,
435
+ framework: answers.framework.key,
436
+ adapter: templateDetails.frameworks[0].adapter || '',
437
+ buildRuntime: templateDetails.frameworks[0].buildRuntime || '',
438
+ installCommand: templateDetails.frameworks[0].installCommand || '',
439
+ buildCommand: templateDetails.frameworks[0].buildCommand || '',
440
+ outputDirectory: templateDetails.frameworks[0].outputDirectory || '',
441
+ fallbackFile: templateDetails.frameworks[0].fallbackFile || '',
442
+ specification: answers.specification,
443
+ enabled: true,
444
+ timeout: 30,
445
+ logging: true,
446
+ ignore: answers.framework.ignore || null,
447
+ path: `sites/${siteName}`,
448
+ };
449
+
450
+ if (!data.buildRuntime) {
451
+ log(`Build runtime for this framework not found. You will be asked to configure build runtime when you first push the site.`);
452
+ }
453
+
454
+ if (!data.installCommand) {
455
+ log(`Installation command for this framework not found. You will be asked to configure the install command when you first push the site.`);
456
+ }
457
+
458
+ if (!data.buildCommand) {
459
+ log(`Build command for this framework not found. You will be asked to configure the build command when you first push the site.`);
460
+ }
461
+
462
+ if (!data.outputDirectory) {
463
+ log(`Output directory for this framework not found. You will be asked to configure the output directory when you first push the site.`);
464
+ }
465
+
466
+ localConfig.addSite(data);
467
+ success("Initializing site");
468
+ log("Next you can use 'appwrite push site' to deploy the changes.");
469
+ };
470
+
321
471
const init = new Command("init")
322
472
.description(commandDescriptions['init'])
323
473
.action(actionRunner(initResources));
@@ -336,6 +486,12 @@ init
336
486
.description("Init a new {{ spec .title | caseUcfirst }} function")
337
487
.action(actionRunner(initFunction));
338
488
489
+ init
490
+ .command("site")
491
+ .alias("sites")
492
+ .description("Init a new {{ spec .title | caseUcfirst }} site")
493
+ .action(actionRunner(initSite));
494
+
339
495
init
340
496
.command("bucket")
341
497
.alias("buckets")
0 commit comments