@hubspot/ui-extensions-dev-server 0.8.45 → 0.8.46

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,4 @@
1
1
  import { remoteBuild, buildSingleExtension } from './lib/build';
2
2
  import DevModeInterface, { DevModeInterfaceNonSingleton } from './lib/DevModeInterface';
3
- export { remoteBuild, buildSingleExtension, DevModeInterface, DevModeInterfaceNonSingleton, };
3
+ import DevModeUnifiedInterface, { DevModeUnifiedInterfaceNonSingleton } from './lib/DevModeUnifiedInterface';
4
+ export { remoteBuild, buildSingleExtension, DevModeInterface, DevModeInterfaceNonSingleton, DevModeUnifiedInterface, DevModeUnifiedInterfaceNonSingleton, };
package/dist/index.js CHANGED
@@ -23,10 +23,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.DevModeInterfaceNonSingleton = exports.DevModeInterface = exports.buildSingleExtension = exports.remoteBuild = void 0;
26
+ exports.DevModeUnifiedInterfaceNonSingleton = exports.DevModeUnifiedInterface = exports.DevModeInterfaceNonSingleton = exports.DevModeInterface = exports.buildSingleExtension = exports.remoteBuild = void 0;
27
27
  const build_1 = require("./lib/build");
28
28
  Object.defineProperty(exports, "remoteBuild", { enumerable: true, get: function () { return build_1.remoteBuild; } });
29
29
  Object.defineProperty(exports, "buildSingleExtension", { enumerable: true, get: function () { return build_1.buildSingleExtension; } });
30
30
  const DevModeInterface_1 = __importStar(require("./lib/DevModeInterface"));
31
31
  exports.DevModeInterface = DevModeInterface_1.default;
32
32
  Object.defineProperty(exports, "DevModeInterfaceNonSingleton", { enumerable: true, get: function () { return DevModeInterface_1.DevModeInterfaceNonSingleton; } });
33
+ const DevModeUnifiedInterface_1 = __importStar(require("./lib/DevModeUnifiedInterface"));
34
+ exports.DevModeUnifiedInterface = DevModeUnifiedInterface_1.default;
35
+ Object.defineProperty(exports, "DevModeUnifiedInterfaceNonSingleton", { enumerable: true, get: function () { return DevModeUnifiedInterface_1.DevModeUnifiedInterfaceNonSingleton; } });
@@ -1,47 +1,9 @@
1
- import { ExtensionOutputConfig, Logger, PlatformVersion, ProjectComponentMap, ProjectConfig } from './types';
2
- import { PromptModule } from 'inquirer';
3
- import { DevServerState } from './DevServerState';
4
- interface SetupArguments {
5
- components: ProjectComponentMap;
6
- onUploadRequired?: VoidFunction;
7
- promptUser: PromptModule;
8
- logger: Logger;
9
- urls: {
10
- api: string;
11
- web: string;
12
- };
13
- setActiveApp: (appUid: string | undefined) => Promise<void>;
14
- }
15
- interface StartArguments {
16
- accountId?: number;
17
- requestPorts?: (requestPortsData: Array<{
18
- instanceId: string;
19
- port?: number;
20
- }>) => Promise<{
21
- [instanceId: string]: number;
22
- }>;
23
- projectConfig?: ProjectConfig;
24
- }
25
- interface AppExtensionMapping {
26
- name: string;
27
- value: ExtensionOutputConfig;
28
- }
29
- declare class DevModeInterface {
30
- configs?: ExtensionOutputConfig[];
31
- devServerState?: DevServerState;
32
- onUploadRequired?: VoidFunction;
33
- shutdown?: () => Promise<void>;
34
- logger: Logger;
35
- urls?: SetupArguments['urls'];
36
- isConfigured?: boolean;
37
- isRunning?: boolean;
1
+ import { ProjectComponentMap, AppExtensionMapping, DevModeStartArguments, DevModeSetupArguments } from './types';
2
+ import { DevModeParentInterface } from './DevModeParentInterface';
3
+ declare class DevModeInterface extends DevModeParentInterface {
38
4
  _generateAppExtensionMappings(components: ProjectComponentMap): AppExtensionMapping[];
39
- _getPlatformVersion(projectConfig?: ProjectConfig): PlatformVersion;
40
- _reset(): void;
41
- setup({ components, onUploadRequired, promptUser, logger, urls, setActiveApp, }: SetupArguments): Promise<void>;
42
- fileChange(filePath: string, __event: unknown): Promise<void>;
43
- start({ requestPorts, accountId, projectConfig }: StartArguments): Promise<void>;
44
- cleanup(): Promise<void>;
5
+ setup(args: DevModeSetupArguments): Promise<void>;
6
+ start({ requestPorts, accountId, projectConfig, }: DevModeStartArguments): Promise<void>;
45
7
  }
46
8
  export { DevModeInterface as DevModeInterfaceNonSingleton };
47
9
  declare const _default: DevModeInterface;
@@ -14,28 +14,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.DevModeInterfaceNonSingleton = void 0;
15
15
  const dev_1 = require("./dev");
16
16
  const constants_1 = require("./constants");
17
- const constants_2 = require("./constants");
18
17
  const config_1 = require("./config");
19
18
  const DevServerState_1 = require("./DevServerState");
20
- const utils_1 = require("./utils");
21
- const defaultLogger = {
22
- info: (...args) => {
23
- console.log(...args);
24
- },
25
- debug: (...args) => {
26
- console.log(...args);
27
- },
28
- warn: (...args) => {
29
- console.error(...args);
30
- },
31
- error: (...args) => {
32
- console.error(...args);
33
- },
34
- };
35
- class DevModeInterface {
36
- constructor() {
37
- this.logger = defaultLogger;
38
- }
19
+ const DevModeParentInterface_1 = require("./DevModeParentInterface");
20
+ class DevModeInterface extends DevModeParentInterface_1.DevModeParentInterface {
39
21
  _generateAppExtensionMappings(components) {
40
22
  // Loop over all of the app configs that are passed in
41
23
  const allComponentNames = Object.keys(components);
@@ -61,87 +43,13 @@ class DevModeInterface {
61
43
  return appExtensionMappings;
62
44
  }, []);
63
45
  }
64
- _getPlatformVersion(projectConfig) {
65
- const { platformVersion } = projectConfig !== null && projectConfig !== void 0 ? projectConfig : {};
66
- if (!platformVersion) {
67
- return constants_2.PLATFORM_VERSION.V20231;
68
- }
69
- switch (platformVersion) {
70
- case constants_2.PLATFORM_VERSION.V20231:
71
- return constants_2.PLATFORM_VERSION.V20231;
72
- case constants_2.PLATFORM_VERSION.V20232:
73
- return constants_2.PLATFORM_VERSION.V20232;
74
- default:
75
- return (0, utils_1.throwUnhandledPlatformVersionError)(platformVersion);
76
- }
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
- }
88
- setup({ components, onUploadRequired, promptUser, logger, urls, setActiveApp, }) {
89
- var _a, _b, _c;
46
+ setup(args) {
90
47
  return __awaiter(this, void 0, void 0, function* () {
91
- logger.debug('Setup function was invoked', { components, urls });
92
- if (this.isConfigured) {
93
- logger.debug('Dev server has already been configured, skipping');
94
- return;
95
- }
96
- this.logger = logger;
97
- this.onUploadRequired = onUploadRequired;
98
- this.urls = urls;
99
- const choices = this._generateAppExtensionMappings(components);
100
- if (choices.length === 0) {
101
- throw new Error('No extensions to run');
102
- }
103
- else if (choices.length === 1) {
104
- this.configs = [choices[0].value];
105
- }
106
- else {
107
- const answers = yield promptUser({
108
- type: 'checkbox',
109
- name: 'extensions',
110
- message: 'Which extension(s) would you like to run?',
111
- validate: (input) => {
112
- if (!input || input.length === 0) {
113
- return 'Select at least one extension to run';
114
- }
115
- const appNames = new Set(input.map((choice) => choice.data.appName));
116
- if (appNames.size > 1) {
117
- return 'Running multiple extensions is only supported for a single application';
118
- }
119
- return true;
120
- },
121
- choices,
122
- });
123
- this.configs = answers.extensions;
124
- }
125
- this.isConfigured = true;
126
- if (typeof setActiveApp === 'function') {
127
- yield setActiveApp((_c = (_b = (_a = this.configs) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.appConfig) === null || _c === void 0 ? void 0 : _c.uid);
128
- }
48
+ args.choices = this._generateAppExtensionMappings(args.components);
49
+ yield this.parentSetup(args);
129
50
  });
130
51
  }
131
- // The contract is for this to be async, so eslint can chill
132
- // eslint-disable-next-line require-await
133
- fileChange(filePath, __event) {
134
- return __awaiter(this, void 0, void 0, function* () {
135
- if (!this.devServerState || !this.devServerState.extensionsMetadata) {
136
- return;
137
- }
138
- const relevantConfigFileChanged = this.devServerState.extensionsMetadata.some((metadata) => metadata.config.extensionConfigPath === filePath);
139
- if (relevantConfigFileChanged && this.onUploadRequired) {
140
- this.onUploadRequired();
141
- }
142
- });
143
- }
144
- start({ requestPorts, accountId, projectConfig }) {
52
+ start({ requestPorts, accountId, projectConfig, }) {
145
53
  var _a, _b, _c, _d;
146
54
  return __awaiter(this, void 0, void 0, function* () {
147
55
  this.logger.debug('Start function was invoked', {
@@ -191,15 +99,6 @@ class DevModeInterface {
191
99
  this.isRunning = true;
192
100
  });
193
101
  }
194
- cleanup() {
195
- return __awaiter(this, void 0, void 0, function* () {
196
- if (this.shutdown) {
197
- yield this.shutdown();
198
- }
199
- // Since the DevModeInterface is a singleton, we need to wipe out the state when we shutdown
200
- this._reset();
201
- });
202
- }
203
102
  }
204
103
  exports.DevModeInterfaceNonSingleton = DevModeInterface;
205
104
  exports.default = new DevModeInterface();
@@ -0,0 +1,19 @@
1
+ import { PlatformVersion, ProjectConfig, Logger, ExtensionOutputConfig, ProjectComponentMap, AppExtensionMapping, DevModeStartArguments, DevModeSetupArguments, UnifiedProjectComponentMap, DevModeBaseSetupArguments } from './types';
2
+ import { DevServerState } from './DevServerState';
3
+ export declare abstract class DevModeParentInterface {
4
+ configs?: ExtensionOutputConfig[];
5
+ devServerState?: DevServerState;
6
+ onUploadRequired?: VoidFunction;
7
+ logger: Logger;
8
+ urls?: DevModeSetupArguments['urls'];
9
+ isConfigured?: boolean;
10
+ isRunning?: boolean;
11
+ shutdown?: () => Promise<void>;
12
+ protected abstract start(args: DevModeStartArguments): Promise<void>;
13
+ protected abstract _generateAppExtensionMappings(components: ProjectComponentMap | UnifiedProjectComponentMap): AppExtensionMapping[];
14
+ _getPlatformVersion(projectConfig?: ProjectConfig): PlatformVersion;
15
+ _reset(): void;
16
+ parentSetup({ onUploadRequired, promptUser, logger, urls, setActiveApp, choices, }: DevModeBaseSetupArguments): Promise<void>;
17
+ fileChange(filePath: string, __event: unknown): Promise<void>;
18
+ cleanup(): Promise<void>;
19
+ }
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DevModeParentInterface = void 0;
13
+ const constants_1 = require("./constants");
14
+ const utils_1 = require("./utils");
15
+ const defaultLogger = {
16
+ info: (...args) => {
17
+ console.log(...args);
18
+ },
19
+ debug: (...args) => {
20
+ console.log(...args);
21
+ },
22
+ warn: (...args) => {
23
+ console.error(...args);
24
+ },
25
+ error: (...args) => {
26
+ console.error(...args);
27
+ },
28
+ };
29
+ class DevModeParentInterface {
30
+ constructor() {
31
+ this.logger = defaultLogger;
32
+ }
33
+ _getPlatformVersion(projectConfig) {
34
+ const { platformVersion } = projectConfig !== null && projectConfig !== void 0 ? projectConfig : {};
35
+ if (!platformVersion) {
36
+ return constants_1.PLATFORM_VERSION.V20231;
37
+ }
38
+ switch (platformVersion) {
39
+ case constants_1.PLATFORM_VERSION.V20231:
40
+ return constants_1.PLATFORM_VERSION.V20231;
41
+ case constants_1.PLATFORM_VERSION.V20232:
42
+ return constants_1.PLATFORM_VERSION.V20232;
43
+ case constants_1.PLATFORM_VERSION.V20252:
44
+ return constants_1.PLATFORM_VERSION.V20252;
45
+ default:
46
+ return (0, utils_1.throwUnhandledPlatformVersionError)(platformVersion);
47
+ }
48
+ }
49
+ _reset() {
50
+ this.configs = undefined;
51
+ this.devServerState = undefined;
52
+ this.onUploadRequired = undefined;
53
+ this.shutdown = undefined;
54
+ this.logger = defaultLogger;
55
+ this.urls = undefined;
56
+ this.isConfigured = false;
57
+ this.isRunning = false;
58
+ }
59
+ parentSetup({ onUploadRequired, promptUser, logger, urls, setActiveApp, choices = [], }) {
60
+ var _a, _b, _c;
61
+ return __awaiter(this, void 0, void 0, function* () {
62
+ if (this.isConfigured) {
63
+ logger.debug('Dev server has already been configured, skipping');
64
+ return;
65
+ }
66
+ this.logger = logger;
67
+ this.onUploadRequired = onUploadRequired;
68
+ this.urls = urls;
69
+ if (choices.length === 0) {
70
+ throw new Error('No extensions to run');
71
+ }
72
+ else if (choices.length === 1) {
73
+ this.configs = [choices[0].value];
74
+ }
75
+ else {
76
+ const answers = yield promptUser({
77
+ type: 'checkbox',
78
+ name: 'extensions',
79
+ message: 'Which extension(s) would you like to run?',
80
+ validate: (input) => {
81
+ if (!input || input.length === 0) {
82
+ return 'Select at least one extension to run';
83
+ }
84
+ const appNames = new Set(input.map((choice) => choice.data.appName));
85
+ if (appNames.size > 1) {
86
+ return 'Running multiple extensions is only supported for a single application';
87
+ }
88
+ return true;
89
+ },
90
+ choices,
91
+ });
92
+ this.configs = answers.extensions;
93
+ }
94
+ this.isConfigured = true;
95
+ if (typeof setActiveApp === 'function') {
96
+ yield setActiveApp((_c = (_b = (_a = this.configs) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.appConfig) === null || _c === void 0 ? void 0 : _c.uid);
97
+ }
98
+ });
99
+ }
100
+ // The contract is for this to be async, so eslint can chill
101
+ // eslint-disable-next-line require-await
102
+ fileChange(filePath, __event) {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ if (!this.devServerState || !this.devServerState.extensionsMetadata) {
105
+ return;
106
+ }
107
+ const relevantConfigFileChanged = this.devServerState.extensionsMetadata.some((metadata) => metadata.config.extensionConfigPath === filePath);
108
+ if (relevantConfigFileChanged && this.onUploadRequired) {
109
+ this.onUploadRequired();
110
+ }
111
+ });
112
+ }
113
+ cleanup() {
114
+ return __awaiter(this, void 0, void 0, function* () {
115
+ if (this.shutdown) {
116
+ yield this.shutdown();
117
+ }
118
+ // Since the DevModeInterface is a singleton, we need to wipe out the state when we shutdown
119
+ this._reset();
120
+ });
121
+ }
122
+ }
123
+ exports.DevModeParentInterface = DevModeParentInterface;
@@ -0,0 +1,20 @@
1
+ import { ProjectConfig, AppExtensionMapping, UnifiedProjectComponentMap, UnifiedDevModeSetupArguments } from './types';
2
+ import { DevModeParentInterface } from './DevModeParentInterface';
3
+ interface StartArguments {
4
+ accountId?: number;
5
+ requestPorts?: (requestPortsData: Array<{
6
+ instanceId: string;
7
+ port?: number;
8
+ }>) => Promise<{
9
+ [instanceId: string]: number;
10
+ }>;
11
+ projectConfig?: ProjectConfig;
12
+ }
13
+ declare class DevModeUnifiedInterface extends DevModeParentInterface {
14
+ _generateAppExtensionMappings(components: UnifiedProjectComponentMap): AppExtensionMapping[];
15
+ setup(args: UnifiedDevModeSetupArguments): Promise<void>;
16
+ start({ requestPorts, accountId, projectConfig }: StartArguments): Promise<void>;
17
+ }
18
+ export { DevModeUnifiedInterface as DevModeUnifiedInterfaceNonSingleton };
19
+ declare const _default: DevModeUnifiedInterface;
20
+ export default _default;
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ /* hs-eslint ignored failing-rules */
3
+ /* eslint-disable hubspot-dev/no-unsupported-ts-syntax */
4
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
6
+ return new (P || (P = Promise))(function (resolve, reject) {
7
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
8
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
9
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
10
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
11
+ });
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.DevModeUnifiedInterfaceNonSingleton = void 0;
18
+ const path_1 = __importDefault(require("path"));
19
+ const dev_1 = require("./dev");
20
+ const constants_1 = require("./constants");
21
+ const config_1 = require("./config");
22
+ const DevServerState_1 = require("./DevServerState");
23
+ const DevModeParentInterface_1 = require("./DevModeParentInterface");
24
+ const utils_1 = require("./utils");
25
+ class DevModeUnifiedInterface extends DevModeParentInterface_1.DevModeParentInterface {
26
+ _generateAppExtensionMappings(components) {
27
+ var _a, _b, _c, _d;
28
+ const mappings = [];
29
+ // Loop over all of the app configs that are passed in
30
+ const allComponentUids = Object.keys(components);
31
+ // First, find the app data.
32
+ const appUid = allComponentUids.find((componentUid) => {
33
+ return components[componentUid].componentType === 'APPLICATION';
34
+ });
35
+ // TODO: Should we throw an error or something here instead? At least log something?
36
+ if (!appUid) {
37
+ return mappings;
38
+ }
39
+ const appData = components[appUid];
40
+ // Use the app data to generate the app config in the expected shape.
41
+ const appConfig = {
42
+ name: appData.config.name,
43
+ description: (_a = appData.config) === null || _a === void 0 ? void 0 : _a.description,
44
+ uid: appData.uid,
45
+ extensions: {
46
+ crm: {
47
+ cards: [],
48
+ },
49
+ },
50
+ auth: (_b = appData.config) === null || _b === void 0 ? void 0 : _b.auth,
51
+ support: (_c = appData.config) === null || _c === void 0 ? void 0 : _c.support,
52
+ // All unified apps are currently "public" meaning they don't support serverless and do support a proxy.
53
+ // The determination of what is "public" and "private" as it relates to our usage is still up in the air.
54
+ isPublicApp: true,
55
+ allowedUrls: ((_d = appData.config) === null || _d === void 0 ? void 0 : _d.permittedUrls)
56
+ ? Object.values(appData.config.permittedUrls).flat()
57
+ : [],
58
+ };
59
+ // Then get all the supported extensions
60
+ const extensionUids = allComponentUids.filter((componentUid) => {
61
+ return constants_1.SUPPORTED_EXTENSION_TYPES.includes(components[componentUid].componentType);
62
+ });
63
+ // Build the extension mapping data
64
+ extensionUids.forEach((extensionUid) => {
65
+ const extension = components[extensionUid];
66
+ // Add them to the app config
67
+ switch (extension.componentType) {
68
+ case 'CARD':
69
+ default:
70
+ appConfig.extensions.crm.cards.push({
71
+ file: extension.config.entrypoint,
72
+ });
73
+ }
74
+ // Generate the name
75
+ const extensionName = `${appData.config.name}/${extension.config.name}`;
76
+ // Transform the type from a format like CRM_CARD to crm-card
77
+ const extensionType = extension.componentType
78
+ .toLowerCase()
79
+ .replace('_', '-');
80
+ const extensionOutput = (0, utils_1.getUrlSafeFileName)(path_1.default.resolve(extension.localDev.componentRoot, extension.config.entrypoint));
81
+ const filePath = path_1.default.resolve(extension.localDev.componentRoot, extension.config.entrypoint);
82
+ const extensionData = {
83
+ title: extension.config.name,
84
+ uid: extension.uid,
85
+ location: extension.config.location,
86
+ module: {
87
+ file: filePath,
88
+ },
89
+ objectTypes: [],
90
+ appName: appData.config.name,
91
+ sourceId: `${appConfig.uid}::${extension.uid}`,
92
+ };
93
+ // Generate object types
94
+ extension.config.objectTypes.forEach((objectType) => {
95
+ extensionData.objectTypes.push({
96
+ name: objectType,
97
+ });
98
+ });
99
+ mappings.push({
100
+ name: extensionName,
101
+ value: {
102
+ type: extensionType,
103
+ data: extensionData,
104
+ output: extensionOutput,
105
+ path: appData.localDev.componentRoot,
106
+ extensionPath: extension.localDev.componentRoot,
107
+ extensionConfigPath: extension.localDev.componentConfigPath,
108
+ appConfig,
109
+ },
110
+ });
111
+ });
112
+ return mappings;
113
+ }
114
+ setup(args) {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ args.choices = this._generateAppExtensionMappings(args.components);
117
+ yield this.parentSetup(args);
118
+ });
119
+ }
120
+ start({ requestPorts, accountId, projectConfig }) {
121
+ var _a, _b, _c, _d;
122
+ return __awaiter(this, void 0, void 0, function* () {
123
+ this.logger.debug('Start function was invoked', {
124
+ accountId,
125
+ projectConfig,
126
+ });
127
+ if (this.isRunning) {
128
+ this.logger.debug('Dev server is already running, not starting again');
129
+ return;
130
+ }
131
+ let expressPort = constants_1.EXPRESS_DEFAULT_PORT;
132
+ let webSocketPort = constants_1.WEBSOCKET_DEFAULT_PORT;
133
+ if (requestPorts) {
134
+ try {
135
+ const portData = yield requestPorts([
136
+ { instanceId: constants_1.EXPRESS_SERVER_ID, port: constants_1.EXPRESS_DEFAULT_PORT },
137
+ { instanceId: constants_1.VITE_DEV_SERVER_ID, port: constants_1.WEBSOCKET_DEFAULT_PORT },
138
+ ]);
139
+ expressPort = portData[constants_1.EXPRESS_SERVER_ID];
140
+ webSocketPort = portData[constants_1.VITE_DEV_SERVER_ID];
141
+ }
142
+ catch (e) {
143
+ if ((e === null || e === void 0 ? void 0 : e.status) === 409) {
144
+ throw new Error('Another instance is already running. To proceed, please stop the existing server and try again.');
145
+ }
146
+ this.logger.debug('Call to port manager failed, using default ports');
147
+ }
148
+ }
149
+ 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) || {};
150
+ try {
151
+ this.devServerState = new DevServerState_1.DevServerState({
152
+ localDevUrlMapping,
153
+ extensionConfigs: this.configs,
154
+ accountId,
155
+ platformVersion: this._getPlatformVersion(projectConfig),
156
+ expressPort,
157
+ webSocketPort,
158
+ logger: this.logger,
159
+ urls: this.urls,
160
+ appConfig: (_d = (_c = this.configs) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.appConfig,
161
+ });
162
+ }
163
+ catch (e) {
164
+ this.logger.error('Error setting up DevServerState', e);
165
+ throw e;
166
+ }
167
+ this.shutdown = yield (0, dev_1.startDevMode)(this.devServerState);
168
+ const { extensionsMetadata } = this.devServerState;
169
+ extensionsMetadata.forEach((metadata) => {
170
+ const { config: { data: { title, appName }, }, } = metadata;
171
+ this.logger.info(`Running extension '${title}' from app '${appName}'`);
172
+ });
173
+ this.isRunning = true;
174
+ });
175
+ }
176
+ }
177
+ exports.DevModeUnifiedInterfaceNonSingleton = DevModeUnifiedInterface;
178
+ exports.default = new DevModeUnifiedInterface();
@@ -21,7 +21,10 @@ export declare const SERVER_CAPABILITIES: string[];
21
21
  export declare const PLATFORM_VERSION: {
22
22
  readonly V20231: "2023.1";
23
23
  readonly V20232: "2023.2";
24
+ readonly V20252: "2025.2";
24
25
  };
25
26
  export declare const PUBLIC_APP = "public-app";
26
27
  export declare const PRIVATE_APP = "private-app";
28
+ export declare const CARD_EXTENSION = "CARD";
27
29
  export declare const SUPPORTED_APP_TYPES: string[];
30
+ export declare const SUPPORTED_EXTENSION_TYPES: string[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SUPPORTED_APP_TYPES = exports.PRIVATE_APP = exports.PUBLIC_APP = exports.PLATFORM_VERSION = exports.SERVER_CAPABILITIES = exports.PROXY_CAPABILITY = exports.WEBSOCKET_MESSAGE_VERSION = exports.EXTENSIONS_MESSAGE_VERSION = exports.ROLLUP_OPTIONS = exports.WEBSOCKET_DEFAULT_PORT = exports.EXPRESS_DEFAULT_PORT = exports.VITE_DEV_SERVER_ID = exports.EXPRESS_SERVER_ID = exports.MANIFEST_FILE = exports.OUTPUT_DIR = void 0;
3
+ exports.SUPPORTED_EXTENSION_TYPES = exports.SUPPORTED_APP_TYPES = exports.CARD_EXTENSION = exports.PRIVATE_APP = exports.PUBLIC_APP = exports.PLATFORM_VERSION = exports.SERVER_CAPABILITIES = exports.PROXY_CAPABILITY = exports.WEBSOCKET_MESSAGE_VERSION = exports.EXTENSIONS_MESSAGE_VERSION = exports.ROLLUP_OPTIONS = exports.WEBSOCKET_DEFAULT_PORT = exports.EXPRESS_DEFAULT_PORT = exports.VITE_DEV_SERVER_ID = exports.EXPRESS_SERVER_ID = exports.MANIFEST_FILE = exports.OUTPUT_DIR = void 0;
4
4
  exports.OUTPUT_DIR = 'dist';
5
5
  exports.MANIFEST_FILE = 'manifest.json';
6
6
  exports.EXPRESS_SERVER_ID = 'ui-extensions-dev-server';
@@ -31,9 +31,12 @@ exports.SERVER_CAPABILITIES = [
31
31
  exports.PLATFORM_VERSION = {
32
32
  V20231: '2023.1',
33
33
  V20232: '2023.2',
34
+ V20252: '2025.2',
34
35
  };
35
36
  exports.PUBLIC_APP = 'public-app';
36
37
  // You gotta be kidding me linter
37
38
  // eslint-disable-next-line hubspot-dev/no-private-classes
38
39
  exports.PRIVATE_APP = 'private-app';
40
+ exports.CARD_EXTENSION = 'CARD';
39
41
  exports.SUPPORTED_APP_TYPES = [exports.PUBLIC_APP, exports.PRIVATE_APP];
42
+ exports.SUPPORTED_EXTENSION_TYPES = [exports.CARD_EXTENSION];
@@ -13,7 +13,6 @@ const utils_1 = require("../utils");
13
13
  const ast_1 = require("../ast");
14
14
  const PACKAGE_LOCK_FILE = 'package-lock.json';
15
15
  const PACKAGE_FILE = 'package.json';
16
- const EXTENSIONS_PATH = 'src/app/extensions/';
17
16
  const manifestPlugin = (options) => {
18
17
  let allDataDependencies;
19
18
  return {
@@ -73,18 +72,18 @@ function _generateManifestContents(bundle, extensionPath, allDataDependencies) {
73
72
  // The keys to bundle are the filename without any path information
74
73
  const bundles = Object.keys(bundle).filter((cur) => cur.endsWith('.js'));
75
74
  if (bundles.length === 1) {
76
- return Object.assign(Object.assign(Object.assign({}, _generateManifestEntry(bundle[bundles[0]])), dataDependencies), baseManifest);
75
+ return Object.assign(Object.assign(Object.assign({}, _generateManifestEntry(bundle[bundles[0]], extensionPath)), dataDependencies), baseManifest);
77
76
  }
78
77
  const manifest = bundles.reduce((acc, current) => {
79
- return Object.assign(Object.assign({}, acc), { [current]: _generateManifestEntry(bundle[current]) });
78
+ return Object.assign(Object.assign({}, acc), { [current]: _generateManifestEntry(bundle[current], extensionPath) });
80
79
  }, {});
81
80
  return Object.assign(Object.assign(Object.assign({}, manifest), dataDependencies), baseManifest);
82
81
  }
83
- function _generateManifestEntry(subBundle) {
82
+ function _generateManifestEntry(subBundle, extensionPath) {
84
83
  const { facadeModuleId, moduleIds, modules } = subBundle;
85
84
  return {
86
- entry: _stripPathPriorToExtDir(facadeModuleId),
87
- modules: _buildModulesInfo(moduleIds, modules),
85
+ entry: _stripPathPriorToExtDir(facadeModuleId, extensionPath),
86
+ modules: _buildModulesInfo(moduleIds, modules, extensionPath),
88
87
  };
89
88
  }
90
89
  function _loadJsonFileSafely(extensionPath, filename) {
@@ -100,10 +99,14 @@ function _loadPackageFile(extensionPath) {
100
99
  return (_loadJsonFileSafely(extensionPath, PACKAGE_LOCK_FILE) ||
101
100
  _loadJsonFileSafely(extensionPath, PACKAGE_FILE));
102
101
  }
103
- function _stripPathPriorToExtDir(filepath) {
104
- return filepath === null || filepath === void 0 ? void 0 : filepath.split(EXTENSIONS_PATH).pop();
102
+ function _stripPathPriorToExtDir(filepath, extensionPath) {
103
+ // Before stripping the path, make sure the given extensionPath ends with a slash.
104
+ extensionPath = extensionPath.endsWith('/')
105
+ ? extensionPath
106
+ : `${extensionPath}/`;
107
+ return filepath === null || filepath === void 0 ? void 0 : filepath.split(extensionPath).pop();
105
108
  }
106
- function _buildModulesInfo(moduleIds, modules) {
109
+ function _buildModulesInfo(moduleIds, modules, extensionPath) {
107
110
  const accumulator = {
108
111
  internal: [],
109
112
  external: [],
@@ -111,7 +114,7 @@ function _buildModulesInfo(moduleIds, modules) {
111
114
  return moduleIds.reduce((acc, mod) => {
112
115
  const { renderedExports } = modules[mod];
113
116
  const moduleData = {
114
- module: _stripPathPriorToExtDir(mod),
117
+ module: _stripPathPriorToExtDir(mod, extensionPath),
115
118
  renderedExports,
116
119
  };
117
120
  if ((0, utils_1.isNodeModule)(moduleData.module)) {
@@ -1,5 +1,6 @@
1
1
  import { PLATFORM_VERSION, PRIVATE_APP, PUBLIC_APP } from './constants';
2
2
  import { LocalDevUrlMapping } from '@hubspot/app-functions-dev-server';
3
+ import { PromptModule } from 'inquirer';
3
4
  export interface ObjectTypes {
4
5
  name: string;
5
6
  }
@@ -15,23 +16,24 @@ export interface ExtensionConfig {
15
16
  uid?: string;
16
17
  };
17
18
  }
19
+ export interface ExtensionOutputDataConfig {
20
+ appName: string;
21
+ title: string;
22
+ location: string;
23
+ module: {
24
+ file: string;
25
+ };
26
+ objectTypes: ObjectTypes[];
27
+ uid?: string;
28
+ sourceId?: string | null;
29
+ }
18
30
  export interface ExtensionOutputConfig extends ExtensionConfig {
19
31
  type: string;
20
32
  output: string;
21
33
  path: string;
22
34
  extensionPath: string;
23
35
  extensionConfigPath: string;
24
- data: {
25
- appName: string;
26
- title: string;
27
- location: string;
28
- module: {
29
- file: string;
30
- };
31
- objectTypes: ObjectTypes[];
32
- uid?: string;
33
- sourceId?: string | null;
34
- };
36
+ data: ExtensionOutputDataConfig;
35
37
  appConfig?: AppConfig;
36
38
  }
37
39
  export interface ExtensionConfigMap {
@@ -60,20 +62,29 @@ export interface PrivateAppConfig {
60
62
  export interface LocalAppConfig {
61
63
  proxy: LocalDevUrlMapping;
62
64
  }
65
+ export interface PublicAppAuth {
66
+ preventAdditionalScopes: boolean;
67
+ preventOptionalScopes: boolean;
68
+ redirectUrls: string[];
69
+ requiredScopes: string[];
70
+ optionalScopes: string[];
71
+ additionalScopes: string[];
72
+ }
73
+ export interface UnifiedAppAuth {
74
+ type: 'OAUTH';
75
+ redirectUrls: string[];
76
+ requiredScopes: string[];
77
+ optionalScopes: string[];
78
+ conditionallyRequiredScopes: string[];
79
+ }
80
+ export type AppAuth = PublicAppAuth | UnifiedAppAuth;
63
81
  export interface PublicAppConfig {
64
82
  name: string;
65
83
  uid: string;
66
84
  logo?: string;
67
85
  description?: string;
68
86
  allowedUrls?: string[];
69
- auth?: {
70
- preventAdditionalScopes: boolean;
71
- preventOptionalScopes: boolean;
72
- redirectUrls: string[];
73
- requiredScopes: string[];
74
- optionalScopes: string[];
75
- additionalScopes: string[];
76
- };
87
+ auth?: AppAuth;
77
88
  support?: {
78
89
  supportUrl: string;
79
90
  supportEmail: string;
@@ -98,6 +109,66 @@ export interface ProjectComponent {
98
109
  export interface ProjectComponentMap {
99
110
  [key: string]: ProjectComponent;
100
111
  }
112
+ export interface UnifiedExtensionComponent {
113
+ uid: string;
114
+ config: {
115
+ name: string;
116
+ description: string;
117
+ location: string;
118
+ entrypoint: string;
119
+ objectTypes: string[];
120
+ previewImage: {
121
+ file: string;
122
+ altText: string;
123
+ };
124
+ };
125
+ componentType: 'CARD';
126
+ componentDeps: {
127
+ app: string;
128
+ };
129
+ metaFilePath: string;
130
+ files: {};
131
+ localDev: {
132
+ componentRoot: string;
133
+ componentConfigPath: string;
134
+ };
135
+ }
136
+ export interface UnifiedAppComponent {
137
+ uid: string;
138
+ config: {
139
+ description: string;
140
+ name: string;
141
+ logo: string;
142
+ auth: UnifiedAppAuth;
143
+ permittedUrls: {
144
+ fetch: string[];
145
+ iframe: string[];
146
+ img: string[];
147
+ };
148
+ support: {
149
+ supportEmail: string;
150
+ documentationUrl: string;
151
+ supportUrl: string;
152
+ supportPhone: string;
153
+ };
154
+ };
155
+ componentType: 'APPLICATION';
156
+ componentDeps: {};
157
+ metaFilePath: string;
158
+ files: {};
159
+ localDev: {
160
+ componentRoot: string;
161
+ componentConfigPath: string;
162
+ };
163
+ }
164
+ export type UnifiedAppConfig = Omit<PublicAppConfig, 'auth'> & {
165
+ auth: UnifiedAppAuth;
166
+ isPublicApp: boolean;
167
+ };
168
+ export type UnifiedComponent = UnifiedExtensionComponent | UnifiedAppComponent;
169
+ export interface UnifiedProjectComponentMap {
170
+ [key: string]: UnifiedComponent;
171
+ }
101
172
  export interface BaseMessage {
102
173
  appName: string;
103
174
  title: string;
@@ -139,4 +210,35 @@ export interface Logger {
139
210
  warn: (...args: any[]) => void;
140
211
  error: (...args: any[]) => void;
141
212
  }
213
+ export interface AppExtensionMapping {
214
+ name: string;
215
+ value: ExtensionOutputConfig;
216
+ }
217
+ export interface DevModeStartArguments {
218
+ accountId?: number;
219
+ requestPorts?: (requestPortsData: Array<{
220
+ instanceId: string;
221
+ port?: number;
222
+ }>) => Promise<{
223
+ [instanceId: string]: number;
224
+ }>;
225
+ projectConfig?: ProjectConfig;
226
+ }
227
+ export interface DevModeBaseSetupArguments {
228
+ onUploadRequired?: VoidFunction;
229
+ promptUser: PromptModule;
230
+ logger: Logger;
231
+ urls: {
232
+ api: string;
233
+ web: string;
234
+ };
235
+ setActiveApp: (appUid: string | undefined) => Promise<void>;
236
+ choices?: AppExtensionMapping[];
237
+ }
238
+ export interface DevModeSetupArguments extends DevModeBaseSetupArguments {
239
+ components: ProjectComponentMap;
240
+ }
241
+ export interface UnifiedDevModeSetupArguments extends DevModeBaseSetupArguments {
242
+ components: UnifiedProjectComponentMap;
243
+ }
142
244
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/ui-extensions-dev-server",
3
- "version": "0.8.45",
3
+ "version": "0.8.46",
4
4
  "description": "",
5
5
  "bin": {
6
6
  "uie": "./dist/lib/bin/cli.js"
@@ -27,7 +27,7 @@
27
27
  ],
28
28
  "license": "MIT",
29
29
  "dependencies": {
30
- "@hubspot/app-functions-dev-server": "0.8.43",
30
+ "@hubspot/app-functions-dev-server": "0.8.46",
31
31
  "chalk": "5.4.1",
32
32
  "commander": "13.0.0",
33
33
  "cors": "2.8.5",
@@ -69,5 +69,5 @@
69
69
  "optional": true
70
70
  }
71
71
  },
72
- "gitHead": "27a34c0d8b88f6f9421b2c468a86cdd525ed126a"
72
+ "gitHead": "a97919f0e9d8a69a039f7a2861e074af93f2dda0"
73
73
  }