dev-config.ts 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. /* eslint-disable no-console */
  2. import { AdminUiPlugin } from '@vendure/admin-ui-plugin';
  3. import { AssetServerPlugin } from '@vendure/asset-server-plugin';
  4. import { ADMIN_API_PATH, API_PORT, SHOP_API_PATH } from '@vendure/common/lib/shared-constants';
  5. import {
  6. Asset,
  7. DefaultJobQueuePlugin,
  8. DefaultLogger,
  9. DefaultSearchPlugin,
  10. dummyPaymentHandler,
  11. LanguageCode,
  12. LogLevel,
  13. VendureConfig,
  14. } from '@vendure/core';
  15. import { ElasticsearchPlugin } from '@vendure/elasticsearch-plugin';
  16. import { defaultEmailHandlers, EmailPlugin } from '@vendure/email-plugin';
  17. import { BullMQJobQueuePlugin } from '@vendure/job-queue-plugin/package/bullmq';
  18. import 'dotenv/config';
  19. import { compileUiExtensions } from '@vendure/ui-devkit/compiler';
  20. import path from 'path';
  21. import { DataSourceOptions } from 'typeorm';
  22. import { MultivendorPlugin } from './test-plugins/multivendor-plugin/multivendor.plugin';
  23. /**
  24. * Config settings used during development
  25. */
  26. export const devConfig: VendureConfig = {
  27. apiOptions: {
  28. port: API_PORT,
  29. adminApiPath: ADMIN_API_PATH,
  30. adminApiPlayground: {
  31. settings: {
  32. 'request.credentials': 'include',
  33. } as any,
  34. },
  35. adminApiDebug: true,
  36. shopApiPath: SHOP_API_PATH,
  37. shopApiPlayground: {
  38. settings: {
  39. 'request.credentials': 'include',
  40. } as any,
  41. },
  42. shopApiDebug: true,
  43. },
  44. authOptions: {
  45. disableAuth: false,
  46. tokenMethod: ['bearer', 'cookie'] as const,
  47. requireVerification: true,
  48. customPermissions: [],
  49. cookieOptions: {
  50. secret: 'abc',
  51. },
  52. },
  53. dbConnectionOptions: {
  54. synchronize: false,
  55. logging: false,
  56. migrations: [path.join(__dirname, 'migrations/*.ts')],
  57. ...getDbConfig(),
  58. },
  59. paymentOptions: {
  60. paymentMethodHandlers: [dummyPaymentHandler],
  61. },
  62. customFields: {
  63. // ProductVariant: [
  64. // {
  65. // name: 'weight',
  66. // type: 'int',
  67. // defaultValue: 0,
  68. // nullable: false,
  69. // min: 0,
  70. // step: 1,
  71. // public: true,
  72. // label: [{ languageCode: LanguageCode.en, value: 'Weight' }],
  73. // ui: { component: 'number-form-input', suffix: 'g' },
  74. // },
  75. // {
  76. // name: 'gtin',
  77. // type: 'string',
  78. // nullable: true,
  79. // public: true,
  80. // label: [{ languageCode: LanguageCode.en, value: 'GTIN (barcode)' }],
  81. // },
  82. // ],
  83. },
  84. /* customFields: {
  85. ProductVariant: [
  86. {
  87. name: 'weight',
  88. type: 'int',
  89. defaultValue: 0,
  90. nullable: false,
  91. min: 0,
  92. step: 1,
  93. public: true,
  94. label: [{ languageCode: LanguageCode.en, value: 'Weight' }],
  95. ui: { component: 'number-form-input', suffix: 'g' },
  96. },
  97. {
  98. name: 'rrp',
  99. type: 'int',
  100. nullable: true,
  101. min: 0,
  102. step: 1,
  103. public: true,
  104. label: [{ languageCode: LanguageCode.en, value: 'RRP' }],
  105. ui: { component: 'currency-form-input' },
  106. },
  107. {
  108. name: 'gtin',
  109. type: 'string',
  110. nullable: true,
  111. public: true,
  112. label: [{ languageCode: LanguageCode.en, value: 'GTIN (barcode)' }],
  113. },
  114. {
  115. name: 'additionalInformation',
  116. type: 'text',
  117. nullable: true,
  118. public: true,
  119. label: [{ languageCode: LanguageCode.en, value: 'Additional Information' }],
  120. ui: { component: 'json-editor-form-input' },
  121. },
  122. ],
  123. Product: [
  124. {
  125. name: 'searchKeywords',
  126. label: [{ languageCode: LanguageCode.en, value: 'Search keywords' }],
  127. type: 'string',
  128. defaultValue: '',
  129. public: false,
  130. },
  131. {
  132. name: 'pageType',
  133. label: [{ languageCode: LanguageCode.en, value: 'Page type' }],
  134. type: 'string',
  135. defaultValue: 'default',
  136. public: true,
  137. options: [
  138. { value: 'default', label: [{ languageCode: LanguageCode.en, value: 'Default' }] },
  139. {
  140. value: 'colour-chart',
  141. label: [{ languageCode: LanguageCode.en, value: 'Colour chart' }],
  142. },
  143. {
  144. value: 'select-menu',
  145. label: [{ languageCode: LanguageCode.en, value: 'Select menu' }],
  146. },
  147. { value: 'gift-card', label: [{ languageCode: LanguageCode.en, value: 'Gift card' }] },
  148. ],
  149. ui: { tab: 'Display' },
  150. },
  151. {
  152. name: 'keyFeatures',
  153. label: [{ languageCode: LanguageCode.en, value: 'Key features' }],
  154. type: 'text',
  155. public: true,
  156. nullable: true,
  157. ui: { component: 'rich-text-form-input' },
  158. },
  159. {
  160. name: 'videoUrls',
  161. label: [{ languageCode: LanguageCode.en, value: 'Video urls' }],
  162. type: 'string',
  163. list: true,
  164. public: true,
  165. nullable: false,
  166. defaultValue: [],
  167. },
  168. {
  169. name: 'variantOrdering',
  170. label: [{ languageCode: LanguageCode.en, value: 'Variant ordering' }],
  171. type: 'string',
  172. defaultValue: 'default',
  173. public: true,
  174. options: [
  175. { value: 'default', label: [{ languageCode: LanguageCode.en, value: 'Default' }] },
  176. {
  177. value: 'alphabetical',
  178. label: [{ languageCode: LanguageCode.en, value: 'Alphabetical' }],
  179. },
  180. {
  181. value: 'brush-size',
  182. label: [{ languageCode: LanguageCode.en, value: 'Brush size (000, 00, 0, 1, ...)' }],
  183. },
  184. {
  185. value: 'dimension',
  186. label: [
  187. { languageCode: LanguageCode.en, value: 'Dimension (5" x 5", 10" x 12",...)' },
  188. ],
  189. },
  190. ],
  191. ui: { tab: 'Display' },
  192. },
  193. {
  194. name: 'seoTitle',
  195. type: 'localeString',
  196. public: true,
  197. label: [{ languageCode: LanguageCode.en, value: 'SEO Title' }],
  198. nullable: true,
  199. ui: { tab: 'SEO' },
  200. },
  201. {
  202. name: 'seoDescription',
  203. type: 'localeString',
  204. public: true,
  205. label: [{ languageCode: LanguageCode.en, value: 'SEO Description' }],
  206. nullable: true,
  207. ui: { tab: 'SEO', component: 'textarea-form-input' },
  208. },
  209. {
  210. name: 'seoImage',
  211. type: 'relation',
  212. entity: Asset,
  213. public: true,
  214. label: [{ languageCode: LanguageCode.en, value: 'SEO Image' }],
  215. nullable: true,
  216. ui: { tab: 'SEO' },
  217. },
  218. {
  219. name: 'boost',
  220. type: 'int',
  221. public: true,
  222. defaultValue: 0,
  223. min: 0,
  224. max: 5,
  225. label: [{ languageCode: LanguageCode.en, value: 'Boost in list pages' }],
  226. nullable: true,
  227. },
  228. {
  229. name: 'minimumOrderQuantity',
  230. type: 'int',
  231. public: true,
  232. min: 0,
  233. label: [{ languageCode: LanguageCode.en, value: 'Minimum order quantity' }],
  234. description: [
  235. {
  236. languageCode: LanguageCode.en,
  237. value: 'If set, the customer must order at least this number of any variants of this product',
  238. },
  239. ],
  240. nullable: true,
  241. },
  242. ],
  243. Collection: [
  244. {
  245. name: 'excludeFromNavMenu',
  246. label: [{ languageCode: LanguageCode.en, value: 'Exclude from nav menu' }],
  247. type: 'boolean',
  248. defaultValue: false,
  249. public: true,
  250. },
  251. {
  252. name: 'excludeFromSubCollections',
  253. label: [{ languageCode: LanguageCode.en, value: 'Exclude from sub collections' }],
  254. type: 'boolean',
  255. defaultValue: false,
  256. public: true,
  257. },
  258. {
  259. name: 'noIndex',
  260. label: [{ languageCode: LanguageCode.en, value: 'Do not allow crawlers to index' }],
  261. type: 'boolean',
  262. defaultValue: false,
  263. public: true,
  264. ui: { tab: 'SEO' },
  265. },
  266. {
  267. name: 'searchKeywords',
  268. label: [{ languageCode: LanguageCode.en, value: 'Search keywords' }],
  269. type: 'string',
  270. defaultValue: '',
  271. public: false,
  272. },
  273. {
  274. name: 'layout',
  275. type: 'string',
  276. public: true,
  277. nullable: false,
  278. defaultValue: 'fullWidth',
  279. label: [{ languageCode: LanguageCode.en, value: 'Layout mode' }],
  280. options: [
  281. { value: 'default', label: [{ languageCode: LanguageCode.en, value: 'Default' }] },
  282. { value: 'fullWidth', label: [{ languageCode: LanguageCode.en, value: 'Full width' }] },
  283. ],
  284. },
  285. {
  286. name: 'seoTitle',
  287. type: 'localeString',
  288. public: true,
  289. label: [{ languageCode: LanguageCode.en, value: 'SEO Meta Title' }],
  290. nullable: true,
  291. ui: { tab: 'SEO' },
  292. },
  293. {
  294. name: 'seoDescription',
  295. type: 'localeString',
  296. public: true,
  297. label: [{ languageCode: LanguageCode.en, value: 'SEO Meta Description' }],
  298. nullable: true,
  299. ui: { tab: 'SEO', component: 'textarea-form-input' },
  300. },
  301. {
  302. name: 'seoImage',
  303. type: 'relation',
  304. entity: Asset,
  305. public: true,
  306. label: [{ languageCode: LanguageCode.en, value: 'SEO Meta Image' }],
  307. nullable: true,
  308. ui: { tab: 'SEO' },
  309. },
  310. {
  311. name: 'extendedDescription',
  312. type: 'text',
  313. public: true,
  314. label: [{ languageCode: LanguageCode.en, value: 'Extended description' }],
  315. nullable: true,
  316. ui: { tab: 'SEO', component: 'rich-text-form-input' },
  317. },
  318. {
  319. name: 'isOfferCollection',
  320. type: 'boolean',
  321. public: true,
  322. label: [{ languageCode: LanguageCode.en, value: 'Is offer collecion' }],
  323. nullable: true,
  324. defaultValue: false,
  325. ui: { tab: 'Offers' },
  326. },
  327. {
  328. name: 'offerName',
  329. type: 'string',
  330. public: true,
  331. label: [{ languageCode: LanguageCode.en, value: 'Offer name' }],
  332. nullable: true,
  333. ui: { tab: 'Offers' },
  334. },
  335. {
  336. name: 'offerDescription',
  337. type: 'string',
  338. public: true,
  339. label: [{ languageCode: LanguageCode.en, value: 'Offer description' }],
  340. nullable: true,
  341. ui: { tab: 'Offers', component: 'rich-text-form-input' },
  342. },
  343. {
  344. name: 'displayRrpDiscount',
  345. type: 'boolean',
  346. public: true,
  347. label: [{ languageCode: LanguageCode.en, value: 'Display RRP discount' }],
  348. description: [
  349. {
  350. languageCode: LanguageCode.en,
  351. value: 'When enabled, the RRP discount of included products will be displayed in the storefront',
  352. },
  353. ],
  354. nullable: true,
  355. ui: { tab: 'Offers' },
  356. },
  357. ],
  358. }, */
  359. logger: new DefaultLogger({ level: LogLevel.Verbose }),
  360. importExportOptions: {
  361. importAssetsDir: path.join(__dirname, 'import-assets'),
  362. },
  363. plugins: [
  364. // MultivendorPlugin,
  365. AssetServerPlugin.init({
  366. route: 'assets',
  367. assetUploadDir: path.join(__dirname, 'assets'),
  368. }),
  369. DefaultSearchPlugin.init({ bufferUpdates: false, indexStockStatus: false }),
  370. BullMQJobQueuePlugin.init({}),
  371. // DefaultJobQueuePlugin.init({}),
  372. // JobQueueTestPlugin.init({ queueCount: 10 }),
  373. // ElasticsearchPlugin.init({
  374. // host: 'http://localhost',
  375. // port: 9200,
  376. // bufferUpdates: true,
  377. // }),
  378. EmailPlugin.init({
  379. devMode: true,
  380. route: 'mailbox',
  381. handlers: defaultEmailHandlers,
  382. templatePath: path.join(__dirname, '../email-plugin/templates'),
  383. outputPath: path.join(__dirname, 'test-emails'),
  384. globalTemplateVars: {
  385. verifyEmailAddressUrl: 'http://localhost:4201/verify',
  386. passwordResetUrl: 'http://localhost:4201/reset-password',
  387. changeEmailAddressUrl: 'http://localhost:4201/change-email-address',
  388. },
  389. }),
  390. AdminUiPlugin.init({
  391. route: 'admin',
  392. port: 5001,
  393. // Un-comment to compile a custom admin ui
  394. app: compileUiExtensions({
  395. outputPath: path.join(__dirname, './custom-admin-ui'),
  396. extensions: [
  397. {
  398. id: 'test-ui-extension',
  399. extensionPath: path.join(__dirname, 'test-plugins/with-ui-extension/ui'),
  400. ngModules: [
  401. {
  402. type: 'lazy',
  403. route: 'greetz',
  404. ngModuleFileName: 'greeter.module.ts',
  405. ngModuleName: 'GreeterModule',
  406. },
  407. {
  408. type: 'shared',
  409. ngModuleFileName: 'greeter-shared.module.ts',
  410. ngModuleName: 'GreeterSharedModule',
  411. },
  412. ],
  413. },
  414. {
  415. globalStyles: path.join(
  416. __dirname,
  417. 'test-plugins/with-ui-extension/ui/custom-theme.scss',
  418. ),
  419. },
  420. {
  421. id: 'external-ui-extension',
  422. extensionPath: path.join(__dirname, 'test-plugins/with-external-ui-extension'),
  423. ngModules: [
  424. {
  425. type: 'lazy',
  426. route: 'greet',
  427. ngModuleFileName: 'external-ui-extension.ts',
  428. ngModuleName: 'ExternalUiExtensionModule',
  429. },
  430. ],
  431. staticAssets: [
  432. {
  433. path: path.join(__dirname, 'test-plugins/with-external-ui-extension/app'),
  434. rename: 'external-app',
  435. },
  436. ],
  437. },
  438. ],
  439. devMode: true,
  440. }),
  441. }),
  442. ],
  443. };
  444. function getDbConfig(): DataSourceOptions {
  445. const dbType = process.env.DB || 'mysql';
  446. switch (dbType) {
  447. case 'postgres':
  448. console.log('Using postgres connection');
  449. return {
  450. synchronize: false,
  451. type: 'postgres',
  452. host: process.env.DB_HOST || 'localhost',
  453. port: Number(process.env.DB_PORT) || 5432,
  454. username: process.env.DB_USERNAME || 'postgres',
  455. password: process.env.DB_PASSWORD || 'postgres',
  456. database: process.env.DB_NAME || 'vendure',
  457. schema: process.env.DB_SCHEMA || 'public',
  458. };
  459. case 'sqlite':
  460. console.log('Using sqlite connection');
  461. return {
  462. synchronize: false,
  463. type: 'better-sqlite3',
  464. database: path.join(__dirname, 'vendure.sqlite'),
  465. };
  466. case 'sqljs':
  467. console.log('Using sql.js connection');
  468. return {
  469. type: 'sqljs',
  470. autoSave: true,
  471. database: new Uint8Array([]),
  472. location: path.join(__dirname, 'vendure.sqlite'),
  473. };
  474. case 'mysql':
  475. default:
  476. console.log('Using mysql connection');
  477. return {
  478. synchronize: false,
  479. type: 'mariadb',
  480. host: '127.0.0.1',
  481. port: 3306,
  482. username: 'root',
  483. password: '',
  484. database: 'vendure2-dev',
  485. };
  486. }
  487. }