@hubspot/ui-extensions-dev-server 0.8.16 → 0.8.17

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/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { remoteBuild, buildSingleExtension } from './lib/build';
2
- import DevModeInterface from './lib/DevModeInterface';
3
- export { remoteBuild, buildSingleExtension, DevModeInterface };
2
+ import DevModeInterface, { DevModeInterfaceNonSingleton } from './lib/DevModeInterface';
3
+ export { remoteBuild, buildSingleExtension, DevModeInterface, DevModeInterfaceNonSingleton, };
package/dist/index.js CHANGED
@@ -1,11 +1,32 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
4
24
  };
5
25
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DevModeInterface = exports.buildSingleExtension = exports.remoteBuild = void 0;
26
+ exports.DevModeInterfaceNonSingleton = exports.DevModeInterface = exports.buildSingleExtension = exports.remoteBuild = void 0;
7
27
  const build_1 = require("./lib/build");
8
28
  Object.defineProperty(exports, "remoteBuild", { enumerable: true, get: function () { return build_1.remoteBuild; } });
9
29
  Object.defineProperty(exports, "buildSingleExtension", { enumerable: true, get: function () { return build_1.buildSingleExtension; } });
10
- const DevModeInterface_1 = __importDefault(require("./lib/DevModeInterface"));
30
+ const DevModeInterface_1 = __importStar(require("./lib/DevModeInterface"));
11
31
  exports.DevModeInterface = DevModeInterface_1.default;
32
+ Object.defineProperty(exports, "DevModeInterfaceNonSingleton", { enumerable: true, get: function () { return DevModeInterface_1.DevModeInterfaceNonSingleton; } });
@@ -37,10 +37,12 @@ declare class DevModeInterface {
37
37
  isRunning?: boolean;
38
38
  _generateAppExtensionMappings(components: ProjectComponentMap): AppExtensionMapping[];
39
39
  _getPlatformVersion(projectConfig?: ProjectConfig): PlatformVersion;
40
+ _reset(): void;
40
41
  setup({ components, onUploadRequired, promptUser, logger, urls, setActiveApp, }: SetupArguments): Promise<void>;
41
42
  fileChange(filePath: string, __event: unknown): Promise<void>;
42
43
  start({ requestPorts, accountId, projectConfig }: StartArguments): Promise<void>;
43
44
  cleanup(): Promise<void>;
44
45
  }
46
+ export { DevModeInterface as DevModeInterfaceNonSingleton };
45
47
  declare const _default: DevModeInterface;
46
48
  export default _default;
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  });
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.DevModeInterfaceNonSingleton = void 0;
14
15
  const dev_1 = require("./dev");
15
16
  const constants_1 = require("./constants");
16
17
  const constants_2 = require("./constants");
@@ -49,6 +50,9 @@ class DevModeInterface {
49
50
  // Loop over the loaded extension configs and generate the list of choices to use to prompt the user for input
50
51
  extensionConfigKeys.forEach((extensionKey) => {
51
52
  const extensionConfig = extensionsConfigForApp[extensionKey];
53
+ if (extensionConfig.appConfig) {
54
+ extensionConfig.appConfig.isPublicApp = component.type === constants_1.PUBLIC_APP;
55
+ }
52
56
  appExtensionMappings.push({
53
57
  name: `${componentName}/${extensionConfig.data.title}`,
54
58
  value: extensionConfig,
@@ -71,6 +75,16 @@ class DevModeInterface {
71
75
  return (0, utils_1.throwUnhandledPlatformVersionError)(platformVersion);
72
76
  }
73
77
  }
78
+ _reset() {
79
+ this.configs = undefined;
80
+ this.devServerState = undefined;
81
+ this.onUploadRequired = undefined;
82
+ this.shutdown = undefined;
83
+ this.logger = defaultLogger;
84
+ this.urls = undefined;
85
+ this.isConfigured = false;
86
+ this.isRunning = false;
87
+ }
74
88
  setup({ components, onUploadRequired, promptUser, logger, urls, setActiveApp, }) {
75
89
  var _a, _b, _c;
76
90
  return __awaiter(this, void 0, void 0, function* () {
@@ -153,7 +167,7 @@ class DevModeInterface {
153
167
  this.logger.debug('Call to port manager failed, using default ports');
154
168
  }
155
169
  }
156
- const { proxy: localDevUrlMapping } = (0, config_1.loadLocalConfig)(((_b = (_a = this.configs) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.path) || '') || {};
170
+ const { proxy: localDevUrlMapping } = (0, config_1.loadLocalConfig)(((_b = (_a = this.configs) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.path) || '', this.logger) || {};
157
171
  this.devServerState = new DevServerState_1.DevServerState({
158
172
  localDevUrlMapping,
159
173
  extensionConfigs: this.configs,
@@ -176,11 +190,13 @@ class DevModeInterface {
176
190
  }
177
191
  cleanup() {
178
192
  return __awaiter(this, void 0, void 0, function* () {
179
- if (this.shutdown && this.isRunning) {
193
+ if (this.shutdown) {
180
194
  yield this.shutdown();
181
- this.isRunning = false;
182
195
  }
196
+ // Since the DevModeInterface is a singleton, we need to wipe out the state when we shutdown
197
+ this._reset();
183
198
  });
184
199
  }
185
200
  }
201
+ exports.DevModeInterfaceNonSingleton = DevModeInterface;
186
202
  exports.default = new DevModeInterface();
@@ -35,5 +35,6 @@ export declare class DevServerState {
35
35
  get outputDir(): string;
36
36
  get appPath(): string;
37
37
  get localDevUrlMapping(): DevServerStateLocalDevUrlMapping;
38
+ isPublicApp(): boolean;
38
39
  }
39
40
  export {};
@@ -68,5 +68,9 @@ class DevServerState {
68
68
  get localDevUrlMapping() {
69
69
  return this._localDevUrlMapping;
70
70
  }
71
+ isPublicApp() {
72
+ var _a;
73
+ return !!((_a = this.appConfig) === null || _a === void 0 ? void 0 : _a.isPublicApp);
74
+ }
71
75
  }
72
76
  exports.DevServerState = DevServerState;
@@ -1,11 +1,14 @@
1
+ import { InlineConfig } from 'vite';
1
2
  interface BuildSingleExtensionArgs {
2
3
  file: string;
3
4
  outputDir?: string;
4
5
  emptyOutDir?: boolean;
5
6
  minify?: boolean;
6
7
  root?: string;
8
+ logLevel?: InlineConfig['logLevel'];
7
9
  }
8
10
  export declare const extensionErrorBaseMessage: string;
9
- export declare function buildSingleExtension({ file, outputDir, emptyOutDir, minify, root, }: BuildSingleExtensionArgs): Promise<void>;
10
- export declare function remoteBuild(root: string, entryPoint: string, outputDir?: string): Promise<void>;
11
+ export declare function buildSingleExtension({ file, outputDir, emptyOutDir, minify, root, // This is the vite default, so using that as our default
12
+ logLevel, }: BuildSingleExtensionArgs): Promise<void>;
13
+ export declare function remoteBuild(root: string, entryPoint: string, outputDir?: string, logLevel?: BuildSingleExtensionArgs['logLevel']): Promise<void>;
11
14
  export {};
package/dist/lib/build.js CHANGED
@@ -23,10 +23,11 @@ const friendlyLoggingPlugin_1 = __importDefault(require("./plugins/friendlyLoggi
23
23
  const allowedExtensions = ['.js', '.ts', '.tsx', '.jsx'];
24
24
  exports.extensionErrorBaseMessage = `Supported file extensions are [${allowedExtensions.join(', ')}], received:`;
25
25
  function buildSingleExtension({ file, outputDir = constants_1.OUTPUT_DIR, emptyOutDir = true, minify = false, root = process.cwd(), // This is the vite default, so using that as our default
26
- }) {
26
+ logLevel = 'info', }) {
27
27
  return __awaiter(this, void 0, void 0, function* () {
28
28
  const output = (0, utils_1.getUrlSafeFileName)(file);
29
29
  yield (0, vite_1.build)({
30
+ logLevel,
30
31
  root,
31
32
  define: {
32
33
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production'),
@@ -51,7 +52,7 @@ function buildSingleExtension({ file, outputDir = constants_1.OUTPUT_DIR, emptyO
51
52
  });
52
53
  }
53
54
  exports.buildSingleExtension = buildSingleExtension;
54
- function remoteBuild(root, entryPoint, outputDir = constants_1.OUTPUT_DIR) {
55
+ function remoteBuild(root, entryPoint, outputDir = constants_1.OUTPUT_DIR, logLevel) {
55
56
  return __awaiter(this, void 0, void 0, function* () {
56
57
  const fileInfo = path_1.default.parse(entryPoint);
57
58
  if (!allowedExtensions.includes(fileInfo.ext)) {
@@ -62,6 +63,7 @@ function remoteBuild(root, entryPoint, outputDir = constants_1.OUTPUT_DIR) {
62
63
  outputDir,
63
64
  minify: true,
64
65
  root,
66
+ logLevel,
65
67
  });
66
68
  });
67
69
  }
@@ -1,4 +1,6 @@
1
- import { AppConfig, ExtensionConfigMap, LocalAppConfig } from './types';
1
+ import { AppConfig, ExtensionConfigMap, LocalAppConfig, Logger } from './types';
2
2
  export declare function loadConfigByPath<T = unknown>(configPath: string): T;
3
3
  export declare function loadExtensionConfig(appConfig: AppConfig, appPath: string): ExtensionConfigMap;
4
- export declare function loadLocalConfig(appPath: string): LocalAppConfig | undefined;
4
+ export declare function validateProxyConfigKey(urlKey: string, logger: Logger, localConfigPath: string): void;
5
+ export declare function validateProxyConfigValue(value: string, key: string, logger: Logger, localConfigPath: string): void;
6
+ export declare function loadLocalConfig(appPath: string, logger: Logger): LocalAppConfig | undefined;
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  return (mod && mod.__esModule) ? mod : { "default": mod };
6
6
  };
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.loadLocalConfig = exports.loadExtensionConfig = exports.loadConfigByPath = void 0;
8
+ exports.loadLocalConfig = exports.validateProxyConfigValue = exports.validateProxyConfigKey = exports.loadExtensionConfig = exports.loadConfigByPath = void 0;
9
9
  const fs_1 = __importDefault(require("fs"));
10
10
  const path_1 = __importDefault(require("path"));
11
11
  const utils_1 = require("./utils");
@@ -17,6 +17,9 @@ exports.loadConfigByPath = loadConfigByPath;
17
17
  function loadExtensionConfig(appConfig, appPath) {
18
18
  var _a, _b;
19
19
  const crmCardsSubConfigFiles = (_b = (_a = appConfig === null || appConfig === void 0 ? void 0 : appConfig.extensions) === null || _a === void 0 ? void 0 : _a.crm) === null || _b === void 0 ? void 0 : _b.cards;
20
+ if (!crmCardsSubConfigFiles) {
21
+ throw new Error("Unable to find extensions files, make sure the 'extensions.crm.cards' array is defined in the application configuration file");
22
+ }
20
23
  const outputConfig = {};
21
24
  crmCardsSubConfigFiles.forEach((card) => {
22
25
  var _a, _b;
@@ -38,16 +41,47 @@ function loadExtensionConfig(appConfig, appPath) {
38
41
  return outputConfig;
39
42
  }
40
43
  exports.loadExtensionConfig = loadExtensionConfig;
41
- function loadLocalConfig(appPath) {
44
+ function validateProxyConfigKey(urlKey, logger, localConfigPath) {
42
45
  try {
43
- const localConfig = path_1.default.join(appPath, 'local.json');
44
- if (fs_1.default.existsSync(localConfig)) {
45
- return JSON.parse(fs_1.default.readFileSync(localConfig).toString());
46
+ const url = new URL(urlKey);
47
+ if (url.pathname !== '/') {
48
+ logger.warn(`The key "${urlKey}" in "${localConfigPath}" is invalid, paths are not supported for keys`);
46
49
  }
47
50
  }
48
51
  catch (e) {
52
+ logger.warn(`The key "${urlKey}" in "${localConfigPath}" is an invalid url`);
53
+ }
54
+ }
55
+ exports.validateProxyConfigKey = validateProxyConfigKey;
56
+ function validateProxyConfigValue(value, key, logger, localConfigPath) {
57
+ try {
58
+ // eslint-disable-next-line no-new
59
+ new URL(value);
60
+ }
61
+ catch (e) {
62
+ logger.warn(`The value "${value}" for key "${key}" in "${localConfigPath}" is an invalid url`);
63
+ }
64
+ }
65
+ exports.validateProxyConfigValue = validateProxyConfigValue;
66
+ function loadLocalConfig(appPath, logger) {
67
+ const localConfigFilename = 'local.json';
68
+ const localConfigPath = path_1.default.join(appPath, localConfigFilename);
69
+ if (!fs_1.default.existsSync(localConfigPath)) {
70
+ return undefined;
71
+ }
72
+ try {
73
+ const localConfig = JSON.parse(fs_1.default.readFileSync(localConfigPath).toString());
74
+ const { proxy = {} } = localConfig;
75
+ Object.entries(proxy).forEach((entry) => {
76
+ const [key, value] = entry;
77
+ validateProxyConfigKey(key, logger, localConfigFilename);
78
+ validateProxyConfigValue(value, key, logger, localConfigFilename);
79
+ });
80
+ return localConfig;
81
+ }
82
+ catch (e) {
83
+ logger.error(`Error loading and parsing ${localConfigPath}, ${e}`);
49
84
  return undefined;
50
85
  }
51
- return undefined;
52
86
  }
53
87
  exports.loadLocalConfig = loadLocalConfig;
@@ -39,9 +39,11 @@ function startDevServer({ devServerState, viteDevServer, }) {
39
39
  app.use((0, cors_1.default)());
40
40
  app.use(express_1.default.static(devServerState.outputDir));
41
41
  const capabilities = [...constants_1.SERVER_CAPABILITIES];
42
- const middlewares = [
43
- (0, app_functions_dev_server_1.AppFunctionExecutionService)(Object.assign(Object.assign({}, devServerState.functionsConfig), { logger: devServerState.logger })),
44
- ];
42
+ const middlewares = [];
43
+ if (!devServerState.isPublicApp()) {
44
+ middlewares.push((0, app_functions_dev_server_1.AppFunctionExecutionService)(Object.assign(Object.assign({}, devServerState.functionsConfig), { logger: devServerState.logger })));
45
+ devServerState.logger.info(`Serving app functions locally (platform version ${devServerState.functionsConfig.platformVersion})`);
46
+ }
45
47
  if (devServerState.localDevUrlMapping) {
46
48
  devServerState.logger.info('Proxy config discovered, enabling local proxy mode');
47
49
  middlewares.push((0, app_functions_dev_server_1.AppProxyService)({
@@ -52,8 +54,9 @@ function startDevServer({ devServerState, viteDevServer, }) {
52
54
  }));
53
55
  capabilities.push(constants_1.PROXY_CAPABILITY);
54
56
  }
55
- app.use('/api/crm-extensibility/execution/internal/v3', ...middlewares);
56
- devServerState.logger.info(`Serving app functions locally (platform version ${devServerState.functionsConfig.platformVersion})`);
57
+ if (middlewares.length > 0) {
58
+ app.use('/api/crm-extensibility/execution/internal/v3', ...middlewares);
59
+ }
57
60
  const endpointsAdded = extensionsService_1.default.add(app, devServerState, capabilities);
58
61
  const { expressPort } = devServerState;
59
62
  endpointsAdded.forEach((endpoint) => {
@@ -77,9 +80,15 @@ function startDevServer({ devServerState, viteDevServer, }) {
77
80
  });
78
81
  return function shutdown() {
79
82
  return __awaiter(this, void 0, void 0, function* () {
80
- yield viteDevServer.pluginContainer.close();
81
- // Stop new connections to express server
82
- server.close(() => { });
83
+ try {
84
+ yield viteDevServer.pluginContainer.close();
85
+ // Stop new connections to express server
86
+ server.close(() => { });
87
+ yield viteDevServer.close();
88
+ }
89
+ catch (e) {
90
+ devServerState.logger.debug(`Error shutting down ${e}`);
91
+ }
83
92
  devServerState.logger.info('Extension dev server done cleaning up');
84
93
  });
85
94
  };
@@ -74,7 +74,10 @@ export interface PublicAppConfig {
74
74
  };
75
75
  };
76
76
  }
77
- export type AppConfig = PrivateAppConfig | PublicAppConfig;
77
+ export interface NonCanonicalAppMetadata {
78
+ isPublicApp?: boolean;
79
+ }
80
+ export type AppConfig = (PrivateAppConfig | PublicAppConfig) & NonCanonicalAppMetadata;
78
81
  export interface ProjectComponent {
79
82
  type: typeof PUBLIC_APP | typeof PRIVATE_APP;
80
83
  config: AppConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/ui-extensions-dev-server",
3
- "version": "0.8.16",
3
+ "version": "0.8.17",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "jest",
@@ -10,9 +10,8 @@
10
10
  "prepare": "npm run build",
11
11
  "lint": "echo 'no lint step for @hubspot/ui-extensions-dev-server'",
12
12
  "jest": "jest --watch",
13
- "integration-test-private-app": "npm run integration-test-private-app --prefix ./integrationTests/fixtures",
14
- "integration-test-public-app": "npm run integration-test-public-app --prefix ./integrationTests/fixtures",
15
- "integration-test": "npm run build && npm run integration-test-private-app && npm run integration-test-public-app"
13
+ "integration-test": "npm run --prefix 'integrationTests' integration-test",
14
+ "integration-test-no-setup": "npm run --prefix 'integrationTests' integration-test-no-setup"
16
15
  },
17
16
  "publishConfig": {
18
17
  "access": "public"
@@ -25,7 +24,7 @@
25
24
  ],
26
25
  "license": "MIT",
27
26
  "dependencies": {
28
- "@hubspot/app-functions-dev-server": "0.8.16",
27
+ "@hubspot/app-functions-dev-server": "0.8.17",
29
28
  "cors": "^2.8.5",
30
29
  "detect-port": "1.5.1",
31
30
  "estraverse": "^5.3.0",
@@ -39,7 +38,8 @@
39
38
  "@types/inquirer": "^9.0.3",
40
39
  "@types/jest": "^29.5.4",
41
40
  "acorn": "^8.11.2",
42
- "axios": "^1.4.0",
41
+ "ava": "4.3.3",
42
+ "axios": "^1.6.8",
43
43
  "jest": "^29.5.0",
44
44
  "ts-jest": "^29.1.1",
45
45
  "typescript": "^5.1.6",
@@ -63,5 +63,5 @@
63
63
  "optional": true
64
64
  }
65
65
  },
66
- "gitHead": "706b594ee7fce544d7261eb8e16b73a77264b506"
66
+ "gitHead": "c056fcf4f48454c6f4cd7986fd1f5b5f619d1605"
67
67
  }