populate.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { INestApplication } from '@nestjs/common';
  2. import fs from 'fs-extra';
  3. import path from 'path';
  4. import { logColored } from './cli-utils';
  5. // tslint:disable:no-var-requires
  6. let Populator: any;
  7. let Importer: any;
  8. try {
  9. Populator = require('@vendure/core').Populator;
  10. Importer = require('@vendure/core').Importer;
  11. } catch (e) {
  12. Populator = require('../src/data-import/providers/populator/populator').Populator;
  13. Importer = require('../src/data-import/providers/importer/importer').Importer;
  14. }
  15. // tslint:disable:no-console
  16. export async function populate(
  17. bootstrapFn: () => Promise<INestApplication | undefined>,
  18. initialDataPath: string,
  19. ): Promise<INestApplication>;
  20. export async function populate(
  21. bootstrapFn: () => Promise<INestApplication | undefined>,
  22. initialDataPath: string,
  23. productsCsvPath: string,
  24. imageSourcePath: string,
  25. ): Promise<INestApplication>;
  26. export async function populate(
  27. bootstrapFn: () => Promise<INestApplication | undefined>,
  28. initialDataPath: string,
  29. productsCsvPath?: string,
  30. imageSourcePath?: string,
  31. ): Promise<INestApplication> {
  32. const app = await bootstrapFn();
  33. if (!app) {
  34. throw new Error('Could not bootstrap the Vendure app');
  35. }
  36. const initialData = require(initialDataPath);
  37. await populateInitialData(app, initialData);
  38. if (productsCsvPath && imageSourcePath) {
  39. await importProductsFromFile(app, productsCsvPath, initialData.defaultLanguage);
  40. await populateCollections(app, initialData);
  41. }
  42. logColored('\nDone!');
  43. return app;
  44. }
  45. export async function importProducts(csvPath: string, languageCode: string) {
  46. logColored(`\nImporting from "${csvPath}"...\n`);
  47. const app = await getApplicationRef();
  48. if (app) {
  49. await importProductsFromFile(app, csvPath, languageCode);
  50. logColored('\nDone!');
  51. await app.close();
  52. process.exit(0);
  53. }
  54. }
  55. async function getApplicationRef(): Promise<INestApplication | undefined> {
  56. const tsConfigFile = path.join(process.cwd(), 'vendure-config.ts');
  57. const jsConfigFile = path.join(process.cwd(), 'vendure-config.js');
  58. let isTs = false;
  59. let configFile: string | undefined;
  60. if (fs.existsSync(tsConfigFile)) {
  61. configFile = tsConfigFile;
  62. isTs = true;
  63. } else if (fs.existsSync(jsConfigFile)) {
  64. configFile = jsConfigFile;
  65. }
  66. if (!configFile) {
  67. console.error(`Could not find a config file`);
  68. console.error(`Checked "${tsConfigFile}", "${jsConfigFile}"`);
  69. process.exit(1);
  70. return;
  71. }
  72. if (isTs) {
  73. // we expect ts-node to be available
  74. const tsNode = require('ts-node');
  75. if (!tsNode) {
  76. console.error(`For "populate" to work with TypeScript projects, you must have ts-node installed`);
  77. process.exit(1);
  78. return;
  79. }
  80. require('ts-node').register();
  81. }
  82. const index = require(configFile);
  83. if (!index) {
  84. console.error(`Could not read the contents of "${configFile}"`);
  85. process.exit(1);
  86. return;
  87. }
  88. if (!index.config) {
  89. console.error(`The file "${configFile}" does not export a "config" object`);
  90. process.exit(1);
  91. return;
  92. }
  93. const config = index.config;
  94. // Force the sync mode on, so that all the tables are created
  95. // on this initial run.
  96. config.dbConnectionOptions.synchronize = true;
  97. const { bootstrap } = require('@vendure/core');
  98. console.log('Bootstrapping Vendure server...');
  99. const app = await bootstrap(config);
  100. return app;
  101. }
  102. async function populateInitialData(app: INestApplication, initialData: object) {
  103. const populator = app.get(Populator);
  104. try {
  105. await populator.populateInitialData(initialData);
  106. } catch (err) {
  107. console.error(err.message);
  108. }
  109. }
  110. async function populateCollections(app: INestApplication, initialData: object) {
  111. const populator = app.get(Populator);
  112. try {
  113. await populator.populateCollections(initialData);
  114. } catch (err) {
  115. console.error(err.message);
  116. }
  117. }
  118. async function importProductsFromFile(app: INestApplication, csvPath: string, languageCode: string) {
  119. // import the csv of same product data
  120. const importer = app.get(Importer);
  121. const productData = await fs.readFile(csvPath, 'utf-8');
  122. const importResult = await importer.parseAndImport(productData, languageCode, true).toPromise();
  123. if (importResult.errors.length) {
  124. const errorFile = path.join(process.cwd(), 'vendure-import-error.log');
  125. console.log(
  126. `${importResult.errors.length} errors encountered when importing product data. See: ${errorFile}`,
  127. );
  128. await fs.writeFile(errorFile, importResult.errors.join('\n'));
  129. }
  130. logColored(`\nImported ${importResult.imported} products`);
  131. }