@hubspot/ui-extensions-dev-server 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli/config.js ADDED
@@ -0,0 +1,119 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { getUrlSafeFileName } = require('../lib/utils');
4
+ const { MAIN_APP_CONFIG } = require('../lib/constants');
5
+
6
+ function getAppConfigPath(projectFiles) {
7
+ return projectFiles.find(filePath => filePath.endsWith(MAIN_APP_CONFIG));
8
+ }
9
+
10
+ function loadConfigByPath(configPath) {
11
+ if (configPath) {
12
+ try {
13
+ const source = fs.readFileSync(configPath);
14
+ const parsedConfig = JSON.parse(source);
15
+ return parsedConfig;
16
+ } catch (e) {
17
+ console.log(e);
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+
23
+ function loadExtensionConfig(appConfig, appPath) {
24
+ const crmCardsSubConfigFiles = appConfig?.extensions?.crm?.cards;
25
+
26
+ const outputConfig = {};
27
+
28
+ crmCardsSubConfigFiles.forEach(card => {
29
+ const cardConfigPath = path.join(appPath, card.file);
30
+
31
+ try {
32
+ const cardConfig = loadConfigByPath(cardConfigPath);
33
+
34
+ if (cardConfig && cardConfig.data) {
35
+ const extensionsDir = path.join(appPath, 'extensions');
36
+
37
+ const entryPointPath = path.join(
38
+ extensionsDir,
39
+ cardConfig.data?.module?.file
40
+ );
41
+
42
+ cardConfig.data.module.file = entryPointPath;
43
+
44
+ outputConfig[entryPointPath] = cardConfig;
45
+ outputConfig[entryPointPath].output = getUrlSafeFileName(
46
+ entryPointPath
47
+ );
48
+ outputConfig[entryPointPath].data.appName = appConfig.name;
49
+ }
50
+ } catch (e) {
51
+ console.log(e);
52
+ }
53
+ });
54
+
55
+ return outputConfig;
56
+ }
57
+
58
+ /**
59
+ * @deprecated Will be removed after integration with hubspot-cli is complete
60
+ * This version of load config makes assumptions about the location it is being ran from where the others do not
61
+ */
62
+ function loadConfig() {
63
+ // app.json is one level up from the extensions directory, which is where these commands
64
+ // will need to be ran from, the extensions directory
65
+ const configPath = path.join(process.cwd(), '..', MAIN_APP_CONFIG);
66
+
67
+ const mainAppConfig = loadConfigByPath(configPath);
68
+
69
+ const crmCardsSubConfigFiles = mainAppConfig?.extensions?.crm?.cards;
70
+ if (!crmCardsSubConfigFiles || crmCardsSubConfigFiles.length === 0) {
71
+ throw new Error(
72
+ `The "extensions.crm.cards" array in ${configPath} is missing or empty, it is a required configuration property`
73
+ );
74
+ }
75
+
76
+ const outputConfig = {};
77
+
78
+ crmCardsSubConfigFiles.forEach(card => {
79
+ const cardConfigPath = path.join(process.cwd(), '..', card.file);
80
+ try {
81
+ const cardConfig = require(cardConfigPath);
82
+ if (!cardConfig.data) {
83
+ throw new Error(
84
+ `Invalid config file at path ${cardConfigPath}, data is a required config property`
85
+ );
86
+ }
87
+
88
+ if (!cardConfig.data.module) {
89
+ throw new Error(
90
+ `Invalid config file at path ${cardConfigPath}, data.module is a require property`
91
+ );
92
+ }
93
+
94
+ // Path.join with a single argument will strip off any relative prefixing such as './'
95
+ const entryPointPath = path.join(cardConfig.data.module.file);
96
+
97
+ cardConfig.data.module.file = entryPointPath;
98
+
99
+ outputConfig[entryPointPath] = cardConfig;
100
+ outputConfig[entryPointPath].data.appName = mainAppConfig.name;
101
+ } catch (e) {
102
+ if (e?.code === 'MODULE_NOT_FOUND') {
103
+ throw new Error(
104
+ `Unable to load "${cardConfigPath}" file. \nPlease make sure you are running the command from the src/app/extensions directory and that your card JSON config exists within it.`
105
+ );
106
+ }
107
+ throw e;
108
+ }
109
+ });
110
+
111
+ return outputConfig;
112
+ }
113
+
114
+ module.exports = {
115
+ getAppConfigPath,
116
+ loadConfigByPath,
117
+ loadExtensionConfig,
118
+ loadConfig,
119
+ };
package/cli/run.js CHANGED
@@ -4,12 +4,14 @@ const { parseArgs, showHelp } = require('../cli/utils');
4
4
  const {
5
5
  buildAllExtensions,
6
6
  buildSingleExtension,
7
- startDevMode,
7
+ DevModeInterface,
8
8
  } = require('../index');
9
9
 
10
10
  const { promptForExtensionToRun } = require('./userInput');
11
11
  const OUTPUT_DIR = 'dist';
12
12
  const logger = require('./logger');
13
+ const path = require('path');
14
+ const { MAIN_APP_CONFIG } = require('../lib/constants');
13
15
 
14
16
  // eslint-disable-next-line no-floating-promise/no-floating-promise
15
17
  (async () => {
@@ -18,10 +20,12 @@ const logger = require('./logger');
18
20
  if (help || !(DEV_MODE || BUILD_MODE)) {
19
21
  showHelp(OUTPUT_DIR);
20
22
  } else if (DEV_MODE) {
21
- startDevMode({
22
- extension: extension || (await promptForExtensionToRun()),
23
- outputDir: OUTPUT_DIR,
23
+ DevModeInterface.start({
24
+ extension: extension
25
+ ? path.parse(extension).name
26
+ : await promptForExtensionToRun(),
24
27
  logger,
28
+ projectFiles: [path.join(process.cwd(), '..', MAIN_APP_CONFIG)],
25
29
  });
26
30
  } else if (BUILD_MODE) {
27
31
  if (extension) {
@@ -34,3 +38,11 @@ const logger = require('./logger');
34
38
  }
35
39
  }
36
40
  })();
41
+
42
+ async function shutdown() {
43
+ await DevModeInterface.cleanup();
44
+ process.exit(0);
45
+ }
46
+
47
+ process.on('SIGINT', shutdown);
48
+ process.on('SIGTERM', shutdown);
package/cli/userInput.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const prompts = require('prompts');
2
+ const path = require('path');
2
3
 
3
- const { getExtensionsList } = require('../lib/extensions');
4
+ const { getExtensionsList } = require('./extensions');
4
5
 
5
6
  async function promptForExtensionToRun() {
6
7
  const extensionOptions = getExtensionsList();
@@ -24,7 +25,7 @@ async function promptForExtensionToRun() {
24
25
  },
25
26
  }
26
27
  );
27
- return response.extension;
28
+ return path.parse(response.extension).name;
28
29
  }
29
30
 
30
31
  module.exports = {
package/index.js CHANGED
@@ -4,11 +4,11 @@ const {
4
4
  buildSingleExtension,
5
5
  } = require('./lib/build');
6
6
 
7
- const { startDevMode } = require('./lib/dev');
7
+ const DevModeInterface = require('./lib/DevModeInterface');
8
8
 
9
9
  module.exports = {
10
10
  remoteBuild,
11
11
  buildAllExtensions,
12
12
  buildSingleExtension,
13
- startDevMode,
13
+ DevModeInterface,
14
14
  };
@@ -0,0 +1,73 @@
1
+ const { startDevMode } = require('./dev');
2
+ const path = require('path');
3
+ const { OUTPUT_DIR } = require('./constants');
4
+ const {
5
+ getAppConfigPath,
6
+ loadConfigByPath,
7
+ loadExtensionConfig,
8
+ } = require('../cli/config');
9
+
10
+ class DevModeInterface {
11
+ constructor() {
12
+ this.shutdown = null;
13
+ }
14
+
15
+ async start({ extension, logger = console, projectFiles }) {
16
+ this.logger = logger;
17
+ this.logger.info('UIE Dev server initializing...');
18
+
19
+ const appConfigPath = getAppConfigPath(projectFiles);
20
+ if (!appConfigPath) {
21
+ const message = 'Unable to determine the location of the app.json file';
22
+ this.logger.error(message);
23
+ throw new Error(message);
24
+ }
25
+
26
+ const appPath = path.dirname(appConfigPath);
27
+ const appConfig = loadConfigByPath(appConfigPath);
28
+ if (!appConfig) {
29
+ const message = 'Unable to load app.json';
30
+ this.logger.error(message);
31
+ throw new Error(message);
32
+ }
33
+
34
+ const extensionsConfigs = loadExtensionConfig(appConfig, appPath);
35
+
36
+ if (!extension || !extensionsConfigs) {
37
+ const message =
38
+ 'Unable to load the extension config, was an extension specified?';
39
+ this.logger.error(message);
40
+ throw new Error(message);
41
+ }
42
+
43
+ const extensionConfigKey = Object.keys(extensionsConfigs).find(
44
+ extensionPath => {
45
+ return (
46
+ extensionPath.endsWith(`${extension}.jsx`) ||
47
+ extensionPath.endsWith(`${extension}.tsx`)
48
+ );
49
+ }
50
+ );
51
+
52
+ if (!extensionConfigKey) {
53
+ const message = `Unable to find config for extension: ${extension}`;
54
+ this.logger.error(message);
55
+ throw new Error(message);
56
+ }
57
+
58
+ this.shutdown = await startDevMode({
59
+ extensionConfig: extensionsConfigs[extensionConfigKey],
60
+ outputDir: path.join(appPath, 'extensions', OUTPUT_DIR),
61
+ logger: this.logger,
62
+ });
63
+ this.logger.info('UIE Dev server done initializing...');
64
+ }
65
+
66
+ async cleanup() {
67
+ if (this.shutdown) {
68
+ await this.shutdown();
69
+ }
70
+ }
71
+ }
72
+
73
+ module.exports = new DevModeInterface();
package/lib/build.js CHANGED
@@ -3,14 +3,14 @@ const { ROLLUP_OPTIONS, OUTPUT_DIR } = require('./constants');
3
3
  const manifestPlugin = require('./plugins/manifestPlugin');
4
4
  const path = require('path');
5
5
  const { getUrlSafeFileName } = require('./utils');
6
- const { loadConfig } = require('./config');
6
+ const { loadConfig } = require('../cli/config');
7
7
 
8
8
  const allowedExtensions = ['.js', '.ts', '.tsx', '.jsx'];
9
9
  const extensionErrorBaseMessage = `Supported file extensions are [${allowedExtensions.join(
10
10
  ', '
11
11
  )}], received:`;
12
12
 
13
- async function buildAllExtensions({ outputDir }) {
13
+ async function buildAllExtensions({ outputDir, logger = console }) {
14
14
  const config = loadConfig();
15
15
  const extensionKeys = Object.keys(config);
16
16
  for (let i = 0; i < extensionKeys.length; ++i) {
@@ -22,7 +22,10 @@ async function buildAllExtensions({ outputDir }) {
22
22
  emptyOutDir: i === 0,
23
23
  plugins: {
24
24
  rollup: [
25
- manifestPlugin({ output: getUrlSafeFileName(data.module.file) }),
25
+ manifestPlugin({
26
+ output: getUrlSafeFileName(data.module.file),
27
+ logger,
28
+ }),
26
29
  ],
27
30
  },
28
31
  });
@@ -35,6 +38,7 @@ async function buildSingleExtension({
35
38
  emptyOutDir = true,
36
39
  minify = false,
37
40
  root = process.cwd(), // This is the vite default, so using that as our default
41
+ logger = console,
38
42
  }) {
39
43
  const output = getUrlSafeFileName(file);
40
44
  await build({
@@ -53,7 +57,7 @@ async function buildSingleExtension({
53
57
  },
54
58
  rollupOptions: {
55
59
  ...ROLLUP_OPTIONS,
56
- plugins: [manifestPlugin({ output })],
60
+ plugins: [manifestPlugin({ output, logger })],
57
61
  },
58
62
  outDir: outputDir,
59
63
  emptyOutDir,
@@ -62,7 +66,12 @@ async function buildSingleExtension({
62
66
  });
63
67
  }
64
68
 
65
- async function remoteBuild(root, entryPoint, outputDir = OUTPUT_DIR) {
69
+ async function remoteBuild(
70
+ root,
71
+ entryPoint,
72
+ outputDir = OUTPUT_DIR,
73
+ logger = console
74
+ ) {
66
75
  const fileInfo = path.parse(entryPoint);
67
76
 
68
77
  if (!allowedExtensions.includes(fileInfo.ext)) {
@@ -75,7 +84,7 @@ async function remoteBuild(root, entryPoint, outputDir = OUTPUT_DIR) {
75
84
  outputFileName: output,
76
85
  outputDir,
77
86
  plugins: {
78
- rollup: [manifestPlugin({ minify: true, output })],
87
+ rollup: [manifestPlugin({ minify: true, output, logger })],
79
88
  },
80
89
  minify: true,
81
90
  root,
package/lib/dev.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const { createServer } = require('vite');
2
+ const path = require('path');
2
3
  const startDevServer = require('./server');
3
4
  const devBuildPlugin = require('./plugins/devBuildPlugin');
4
5
  const { getUrlSafeFileName } = require('./utils');
@@ -7,7 +8,6 @@ const {
7
8
  WEBSOCKET_PORT,
8
9
  OUTPUT_DIR,
9
10
  } = require('./constants');
10
- const { loadConfig } = require('./config');
11
11
 
12
12
  async function _createViteDevServer(
13
13
  outputDir,
@@ -25,7 +25,7 @@ async function _createViteDevServer(
25
25
  port: websocketPort,
26
26
  },
27
27
  watch: {
28
- ignored: [`${process.cwd()}/${outputDir}/**/*`],
28
+ ignored: [path.join(outputDir, '/**/*')],
29
29
  },
30
30
  },
31
31
  build: {
@@ -35,32 +35,28 @@ async function _createViteDevServer(
35
35
  },
36
36
  },
37
37
  plugins: [
38
- devBuildPlugin({ extensionConfig, outputDir, baseMessage, logger }),
38
+ devBuildPlugin({
39
+ extensionConfig,
40
+ outputDir,
41
+ baseMessage,
42
+ logger,
43
+ }),
39
44
  ],
45
+ clearScreen: false,
40
46
  });
41
47
  }
42
48
 
43
49
  async function startDevMode({
44
- extension,
50
+ extensionConfig,
45
51
  logger,
46
52
  outputDir = OUTPUT_DIR,
47
53
  expressPort = VITE_DEFAULT_PORT,
48
54
  webSocketPort = WEBSOCKET_PORT,
49
55
  }) {
50
- if (!extension) {
51
- throw new Error('Unable to determine which extension to run');
52
- }
53
-
54
- const config = loadConfig();
55
- const extensionConfig = config[extension];
56
56
  if (!extensionConfig) {
57
- throw new Error(
58
- `Unable to locate a configuration file for the specified extension ${extension}`
59
- );
57
+ throw new Error('Unable to determine which extension to run');
60
58
  }
61
59
 
62
- extensionConfig.output = getUrlSafeFileName(extensionConfig.data.module.file);
63
-
64
60
  const baseMessage = Object.freeze({
65
61
  appName: extensionConfig.data.appName,
66
62
  title: extensionConfig.data.title,
@@ -74,7 +70,7 @@ async function startDevMode({
74
70
  baseMessage,
75
71
  logger
76
72
  );
77
- startDevServer(
73
+ return startDevServer(
78
74
  outputDir,
79
75
  expressPort,
80
76
  webSocketPort,
@@ -0,0 +1,43 @@
1
+ const path = require('path');
2
+ const { EXTENSIONS_MESSAGE_VERSION } = require('./constants');
3
+ const { loadManifest } = require('./utils');
4
+
5
+ class ExtensionsService {
6
+ constructor() {
7
+ this.endpoint = '/extensions';
8
+ }
9
+
10
+ add(server, webSocketPort, outputDir, baseMessage) {
11
+ server.get(
12
+ this.endpoint,
13
+ this.generateExtensionsHandler(baseMessage, webSocketPort, outputDir)
14
+ );
15
+ return [this.endpoint];
16
+ }
17
+
18
+ generateExtensionsHandler(baseMessage, webSocketPort, outputDir) {
19
+ return function extensionsHandler(_req, res) {
20
+ try {
21
+ const output = path.parse(baseMessage.callback).name;
22
+
23
+ const response = {
24
+ websocket: `ws://localhost:${webSocketPort}`,
25
+ version: EXTENSIONS_MESSAGE_VERSION,
26
+ extensions: [
27
+ {
28
+ ...baseMessage,
29
+ manifest: loadManifest(outputDir, output),
30
+ },
31
+ ],
32
+ };
33
+ res.status(200).json(response);
34
+ } catch (e) {
35
+ res.status(500).json({
36
+ message: 'Unable to determine which extensions are running',
37
+ });
38
+ }
39
+ };
40
+ }
41
+ }
42
+
43
+ module.exports = new ExtensionsService();
@@ -52,10 +52,10 @@ function devBuildPlugin(options = {}) {
52
52
  rollupOptions: {
53
53
  ...ROLLUP_OPTIONS,
54
54
  plugins: [
55
- ...(ROLLUP_OPTIONS.plugins || []),
56
55
  manifestPlugin({
57
56
  minify: false,
58
57
  output: extensionConfig.output,
58
+ logger,
59
59
  }),
60
60
  ],
61
61
  output: {
@@ -67,6 +67,7 @@ function devBuildPlugin(options = {}) {
67
67
  emptyOutDir: true,
68
68
  minify: false,
69
69
  },
70
+ clearScreen: false,
70
71
  });
71
72
  return true;
72
73
  } catch (error) {
@@ -110,7 +111,7 @@ function devBuildPlugin(options = {}) {
110
111
  }
111
112
 
112
113
  if (server.ws.clients.size === 0) {
113
- logger.warn('Bundle updated, no browsers connected to notify');
114
+ logger.info('Bundle updated, no browsers connected to notify');
114
115
  return [];
115
116
  }
116
117
 
@@ -125,7 +126,7 @@ function devBuildPlugin(options = {}) {
125
126
  if (error) {
126
127
  logger.error(error);
127
128
  }
128
- logger.warn('Sending shutdown message to connected browsers');
129
+ logger.info('Sending shutdown message to connected browsers');
129
130
  if (localServer && localServer.ws) {
130
131
  localServer.ws.send({
131
132
  ...versionedBaseMessage,
@@ -7,7 +7,7 @@ const PACKAGE_LOCK_FILE = 'package-lock.json';
7
7
  const PACKAGE_FILE = 'package.json';
8
8
  const EXTENSIONS_PATH = 'src/app/extensions/';
9
9
 
10
- function plugin(options = {}) {
10
+ function manifestPlugin(options = {}) {
11
11
  return {
12
12
  name: 'ui-extensions-manifest-generation-plugin',
13
13
  enforce: 'post', // run after default rollup plugins
@@ -37,7 +37,6 @@ function _generateManifestContents(bundle) {
37
37
 
38
38
  // The keys to bundle are the filename without any path information
39
39
  const bundles = Object.keys(bundle).filter(cur => cur.endsWith('.js'));
40
-
41
40
  if (bundles.length === 1) {
42
41
  return {
43
42
  ..._generateManifestEntry(bundle[bundles[0]]),
@@ -106,4 +105,4 @@ function _buildModulesInfo(moduleIds, modules) {
106
105
  );
107
106
  }
108
107
 
109
- module.exports = plugin;
108
+ module.exports = manifestPlugin;
package/lib/server.js CHANGED
@@ -1,8 +1,6 @@
1
1
  const express = require('express');
2
- const path = require('path');
3
2
  const cors = require('cors');
4
- const fs = require('fs');
5
- const { EXTENSIONS_MESSAGE_VERSION, MANIFEST_FILE } = require('./constants');
3
+ const extensionsService = require('./extensionsService');
6
4
 
7
5
  function startDevServer(
8
6
  outputDir,
@@ -17,75 +15,31 @@ function startDevServer(
17
15
  // Setup middleware
18
16
  app.use(cors());
19
17
  app.use(express.static(outputDir));
20
- _addExtensionsEndpoint(
18
+ const endpointsAdded = extensionsService.add(
21
19
  app,
22
- expressPort,
23
20
  webSocketPort,
24
21
  outputDir,
25
- baseMessage,
26
- logger
22
+ baseMessage
27
23
  );
28
24
 
25
+ endpointsAdded.forEach(endpoint => {
26
+ logger.info(`Listening at http://hslocal.net:${expressPort}${endpoint}`);
27
+ });
28
+
29
29
  // Vite middlewares needs to go last because it's greedy and will block other middleware
30
30
  app.use(viteDevServer.middlewares);
31
31
 
32
32
  const server = app.listen({ port: expressPort }, () => {
33
- logger.warn(`Listening at ${baseMessage.callback}`);
33
+ logger.info(`Listening at ${baseMessage.callback}`);
34
34
  });
35
35
 
36
- _configureShutDownHandlers(server, viteDevServer, logger);
37
- }
38
-
39
- function _addExtensionsEndpoint(
40
- server,
41
- expressPort,
42
- webSocketPort,
43
- outputDir,
44
- baseMessage,
45
- logger
46
- ) {
47
- const endpoint = '/extensions';
48
- server.get(endpoint, (_req, res) => {
49
- try {
50
- const output = path.parse(baseMessage.callback).name;
51
- const manifest = JSON.parse(
52
- fs.readFileSync(
53
- path.join(process.cwd(), `${outputDir}/${output}-${MANIFEST_FILE}`)
54
- )
55
- );
56
-
57
- const response = {
58
- websocket: `ws://localhost:${webSocketPort}`,
59
- version: EXTENSIONS_MESSAGE_VERSION,
60
- extensions: [
61
- {
62
- ...baseMessage,
63
- manifest,
64
- },
65
- ],
66
- };
67
- res.status(200).json(response);
68
- } catch (e) {
69
- res.status(500).json({
70
- message: 'Unable to load manifest file',
71
- });
72
- }
73
- });
74
- logger.warn(`Listening at http://hslocal.net:${expressPort}${endpoint}`);
75
- }
76
-
77
- function _configureShutDownHandlers(server, viteDevServer, logger) {
78
- async function shutdown() {
79
- logger.warn('\nCleaning up after ourselves...');
36
+ return async function shutdown() {
80
37
  await viteDevServer.pluginContainer.close();
81
38
  // Stop new connections to express server
82
39
  server.close(() => {});
83
40
  logger.info('Clean up done, exiting.');
84
41
  process.exit(0);
85
- }
86
-
87
- process.on('SIGINT', shutdown);
88
- process.on('SIGTERM', shutdown);
42
+ };
89
43
  }
90
44
 
91
45
  module.exports = startDevServer;
package/lib/utils.js CHANGED
@@ -1,4 +1,6 @@
1
1
  const path = require('path');
2
+ const fs = require('fs');
3
+ const { MANIFEST_FILE } = require('./constants');
2
4
 
3
5
  function getUrlSafeFileName(filePath) {
4
6
  const { name } = path.parse(filePath);
@@ -14,7 +16,18 @@ function stripAnsiColorCodes(string) {
14
16
  );
15
17
  }
16
18
 
19
+ function loadManifest(outputDir, output) {
20
+ try {
21
+ return JSON.parse(
22
+ fs.readFileSync(path.join(outputDir, `${output}-${MANIFEST_FILE}`))
23
+ );
24
+ } catch (e) {
25
+ return {};
26
+ }
27
+ }
28
+
17
29
  module.exports = {
18
30
  getUrlSafeFileName,
19
31
  stripAnsiColorCodes,
32
+ loadManifest,
20
33
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/ui-extensions-dev-server",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -11,16 +11,18 @@
11
11
  "access": "public"
12
12
  },
13
13
  "files": [
14
+ "cli/config.js",
15
+ "cli/extensions.js",
14
16
  "cli/logger.js",
15
17
  "cli/run.js",
16
18
  "cli/userInput.js",
17
19
  "cli/utils.js",
18
20
  "lib/plugins/*",
19
21
  "lib/build.js",
20
- "lib/config.js",
21
22
  "lib/constants.js",
22
23
  "lib/dev.js",
23
- "lib/extensions.js",
24
+ "lib/extensionsService.js",
25
+ "lib/DevModeInterface.js",
24
26
  "lib/server.js",
25
27
  "lib/utils.js",
26
28
  "index.js",
@@ -61,5 +63,5 @@
61
63
  "optional": true
62
64
  }
63
65
  },
64
- "gitHead": "0b20c005a9564bbde58c22ce21959c713f354607"
66
+ "gitHead": "1269fb86282dd5f6b9686d064b6c652f00cb863f"
65
67
  }
package/lib/config.js DELETED
@@ -1,81 +0,0 @@
1
- const path = require('path');
2
- const { MAIN_APP_CONFIG } = require('./constants');
3
-
4
- function _loadRequiredConfigFile(filePath) {
5
- let config;
6
- try {
7
- config = require(filePath);
8
- } catch (e) {
9
- throw new Error(
10
- `Unable to load ${filePath} file. Please make sure you are running the command from the src/app/extensions directory and that ${filePath} exists`
11
- );
12
- }
13
- return config;
14
- }
15
-
16
- function loadConfig() {
17
- // app.json is one level up from the extensions directory, which is where these commands
18
- // will need to be ran from, the extensions directory
19
- const configPath = path.join(process.cwd(), '..', MAIN_APP_CONFIG);
20
-
21
- const mainAppConfig = _loadRequiredConfigFile(configPath);
22
-
23
- const crmCardsSubConfigFiles = mainAppConfig?.extensions?.crm?.cards;
24
- if (!crmCardsSubConfigFiles || crmCardsSubConfigFiles.length === 0) {
25
- throw new Error(
26
- `The "extensions.crm.cards" array in ${configPath} is missing or empty, it is a required configuration property`
27
- );
28
- }
29
-
30
- const outputConfig = {};
31
-
32
- crmCardsSubConfigFiles.forEach(card => {
33
- const parsedFile = path.parse(card.file);
34
- if (parsedFile.dir.startsWith('./extensions')) {
35
- parsedFile.dir = parsedFile.dir.replace('./extensions', './'); // go up one level
36
- }
37
- // Get the path to the config file relative to the extensions directory
38
- const configPathRelativeToExtensions = parsedFile.dir;
39
- const extensionsPrefixRemoved = path.format(parsedFile);
40
- const cardConfigPath = path.join(process.cwd(), extensionsPrefixRemoved);
41
-
42
- try {
43
- const cardConfig = require(cardConfigPath);
44
- if (!cardConfig.data) {
45
- throw new Error(
46
- `Invalid config file at path ${cardConfigPath}, data is a required config property`
47
- );
48
- }
49
-
50
- if (!cardConfig.data.module) {
51
- throw new Error(
52
- `Invalid config file at path ${cardConfigPath}, data.module is a require property`
53
- );
54
- }
55
-
56
- // Join the two relative paths
57
- const entryPointPath = path.join(
58
- configPathRelativeToExtensions,
59
- cardConfig.data.module.file
60
- );
61
-
62
- cardConfig.data.module.file = entryPointPath;
63
-
64
- outputConfig[entryPointPath] = cardConfig;
65
- outputConfig[entryPointPath].data.appName = mainAppConfig.name;
66
- } catch (e) {
67
- if (e?.code === 'MODULE_NOT_FOUND') {
68
- throw new Error(
69
- `Unable to load "${cardConfigPath}" file. \nPlease make sure you are running the command from the src/app/extensions directory and that your card JSON config exists within it.`
70
- );
71
- }
72
- throw e;
73
- }
74
- });
75
-
76
- return outputConfig;
77
- }
78
-
79
- module.exports = {
80
- loadConfig,
81
- };
File without changes