init.ts 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import fs from 'fs-extra';
  2. import Handlebars from 'handlebars';
  3. import path from 'path';
  4. import { PromptObject } from 'prompts';
  5. import prompts from 'prompts';
  6. // tslint:disable:no-console
  7. export async function init(): Promise<string> {
  8. function defaultPort(_dbType: string) {
  9. switch (_dbType) {
  10. case 'mysql':
  11. return 3306;
  12. case 'postgres':
  13. return 5432;
  14. case 'mssql':
  15. return 1433;
  16. case 'oracle':
  17. return 1521;
  18. default:
  19. return 3306;
  20. }
  21. }
  22. function onSubmit(prompt: PromptObject, answer: any) {
  23. if (prompt.name === 'dbType') {
  24. dbType = answer;
  25. }
  26. }
  27. let dbType: string;
  28. console.log(`Let's get started with a new Vendure server!\n`);
  29. const answers = await prompts(
  30. [
  31. {
  32. type: 'select',
  33. name: 'dbType',
  34. message: 'Which database are you using?',
  35. choices: [
  36. { title: 'MySQL / MariaDB', value: 'mysql' },
  37. { title: 'Postgres', value: 'postgres' },
  38. { title: 'SQLite', value: 'sqlite' },
  39. { title: 'SQL.js', value: 'sqljs' },
  40. { title: 'MS SQL Server', value: 'mssql' },
  41. { title: 'Oracle', value: 'oracle' },
  42. ],
  43. initial: 0 as any,
  44. },
  45. {
  46. type: (() => (dbType === 'sqlite' || dbType === 'sqljs' ? null : 'text')) as any,
  47. name: 'dbHost',
  48. message: `What's the database host address?`,
  49. initial: '192.168.99.100',
  50. },
  51. {
  52. type: (() => (dbType === 'sqlite' || dbType === 'sqljs' ? null : 'text')) as any,
  53. name: 'dbPort',
  54. message: `What port is the database listening on?`,
  55. initial: (() => defaultPort(dbType)) as any,
  56. },
  57. {
  58. type: 'text',
  59. name: 'dbName',
  60. message: () =>
  61. dbType === 'sqlite' || dbType === 'sqljs'
  62. ? `What is the path to the database file?`
  63. : `What's the name of the database?`,
  64. initial: (() =>
  65. dbType === 'sqlite' || dbType === 'sqljs'
  66. ? path.join(process.cwd(), 'vendure.sqlite')
  67. : 'vendure') as any,
  68. },
  69. {
  70. type: (() => (dbType === 'sqlite' || dbType === 'sqljs' ? null : 'text')) as any,
  71. name: 'dbUserName',
  72. message: `What's the database user name?`,
  73. initial: 'root',
  74. },
  75. {
  76. type: (() => (dbType === 'sqlite' || dbType === 'sqljs' ? null : 'password')) as any,
  77. name: 'dbPassword',
  78. message: `What's the database password?`,
  79. },
  80. {
  81. type: 'select',
  82. name: 'language',
  83. message: 'Which programming language will you be using?',
  84. choices: [{ title: 'TypeScript', value: 'ts' }, { title: 'JavaScript', value: 'js' }],
  85. initial: 0 as any,
  86. },
  87. ],
  88. {
  89. onSubmit,
  90. onCancel() {
  91. /* */
  92. },
  93. },
  94. );
  95. if (!answers.language) {
  96. console.log('Setup aborted. No changes made');
  97. process.exit(0);
  98. }
  99. await createDirectoryStructure();
  100. await copyEmailTemplates();
  101. return createFilesForBootstrap(answers);
  102. }
  103. /**
  104. * Generate the default directory structure for a new Vendure project
  105. */
  106. async function createDirectoryStructure() {
  107. const cwd = process.cwd();
  108. await fs.ensureDir(path.join(cwd, 'vendure', 'email', 'test-emails'));
  109. await fs.ensureDir(path.join(cwd, 'vendure', 'import-assets'));
  110. await fs.ensureDir(path.join(cwd, 'vendure', 'assets'));
  111. }
  112. /**
  113. * Copy the email templates into the app
  114. */
  115. async function copyEmailTemplates() {
  116. const templateDir = path.join(__dirname, 'assets', 'email-templates');
  117. try {
  118. await fs.copy(templateDir, path.join(process.cwd(), 'vendure', 'email', 'templates'));
  119. } catch (err) {
  120. console.error(`Failed to copy email templates.`);
  121. }
  122. }
  123. /**
  124. * Create the server index and config files based on the options specified by the CLI prompts.
  125. */
  126. async function createFilesForBootstrap(answers: any): Promise<string> {
  127. const cwd = process.cwd();
  128. const filePath = (fileName: string): string => path.join(cwd, `${fileName}.${answers.language}`);
  129. const templateContext = {
  130. ...answers,
  131. isTs: answers.language === 'ts',
  132. isSQLite: answers.dbType === 'sqlite',
  133. isSQLjs: answers.dbType === 'sqljs',
  134. requiresConnection: answers.dbType !== 'sqlite' && answers.dbType !== 'sqljs',
  135. normalizedDbName:
  136. answers.dbType === 'sqlite' || answers.dbType === 'sqljs'
  137. ? normalizeFilePath(answers.dbName)
  138. : answers.dbName,
  139. sessionSecret: Math.random()
  140. .toString(36)
  141. .substr(3),
  142. };
  143. const configTemplate = await fs.readFile(path.join(__dirname, 'assets', 'vendure-config.hbs'), 'utf-8');
  144. const configSource = Handlebars.compile(configTemplate)(templateContext);
  145. await fs.writeFile(filePath('vendure-config'), configSource);
  146. const indexTemplate = await fs.readFile(path.join(__dirname, 'assets', 'index.hbs'), 'utf-8');
  147. const indexSource = Handlebars.compile(indexTemplate)(templateContext);
  148. await fs.writeFile(filePath('index'), indexSource);
  149. return filePath('index');
  150. }
  151. /**
  152. * Escape backslashed for Windows file paths.
  153. */
  154. function normalizeFilePath(filePath: string): string {
  155. return String.raw`${filePath}`.replace(/\\/g, '\\\\');
  156. }