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

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,8 @@
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, 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>;
45
6
  }
46
7
  export { DevModeInterface as DevModeInterfaceNonSingleton };
47
8
  declare const _default: DevModeInterface;
@@ -12,30 +12,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.DevModeInterfaceNonSingleton = void 0;
15
- const dev_1 = require("./dev");
16
15
  const constants_1 = require("./constants");
17
- const constants_2 = require("./constants");
18
16
  const config_1 = require("./config");
19
- 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
- }
17
+ const DevModeParentInterface_1 = require("./DevModeParentInterface");
18
+ class DevModeInterface extends DevModeParentInterface_1.DevModeParentInterface {
39
19
  _generateAppExtensionMappings(components) {
40
20
  // Loop over all of the app configs that are passed in
41
21
  const allComponentNames = Object.keys(components);
@@ -61,143 +41,10 @@ class DevModeInterface {
61
41
  return appExtensionMappings;
62
42
  }, []);
63
43
  }
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;
44
+ setup(args) {
90
45
  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
- }
129
- });
130
- }
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 }) {
145
- var _a, _b, _c, _d;
146
- return __awaiter(this, void 0, void 0, function* () {
147
- this.logger.debug('Start function was invoked', {
148
- accountId,
149
- projectConfig,
150
- });
151
- if (this.isRunning) {
152
- this.logger.debug('Dev server is already running, not starting again');
153
- return;
154
- }
155
- let expressPort = constants_1.EXPRESS_DEFAULT_PORT;
156
- let webSocketPort = constants_1.WEBSOCKET_DEFAULT_PORT;
157
- if (requestPorts) {
158
- try {
159
- const portData = yield requestPorts([
160
- { instanceId: constants_1.EXPRESS_SERVER_ID, port: constants_1.EXPRESS_DEFAULT_PORT },
161
- { instanceId: constants_1.VITE_DEV_SERVER_ID, port: constants_1.WEBSOCKET_DEFAULT_PORT },
162
- ]);
163
- expressPort = portData[constants_1.EXPRESS_SERVER_ID];
164
- webSocketPort = portData[constants_1.VITE_DEV_SERVER_ID];
165
- }
166
- catch (e) {
167
- if ((e === null || e === void 0 ? void 0 : e.status) === 409) {
168
- throw new Error('Another instance is already running. To proceed, please stop the existing server and try again.');
169
- }
170
- this.logger.debug('Call to port manager failed, using default ports');
171
- }
172
- }
173
- 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) || {};
174
- this.devServerState = new DevServerState_1.DevServerState({
175
- localDevUrlMapping,
176
- extensionConfigs: this.configs,
177
- accountId,
178
- platformVersion: this._getPlatformVersion(projectConfig),
179
- expressPort,
180
- webSocketPort,
181
- logger: this.logger,
182
- urls: this.urls,
183
- appConfig: (_d = (_c = this.configs) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.appConfig,
184
- });
185
- this.shutdown = yield (0, dev_1.startDevMode)(this.devServerState);
186
- const { extensionsMetadata } = this.devServerState;
187
- extensionsMetadata.forEach((metadata) => {
188
- const { config: { data: { title, appName }, }, } = metadata;
189
- this.logger.info(`Running extension '${title}' from app '${appName}'`);
190
- });
191
- this.isRunning = true;
192
- });
193
- }
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();
46
+ args.choices = this._generateAppExtensionMappings(args.components);
47
+ yield this.parentSetup(args);
201
48
  });
202
49
  }
203
50
  }
@@ -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 _generateAppExtensionMappings(components: ProjectComponentMap | UnifiedProjectComponentMap): AppExtensionMapping[];
13
+ _getPlatformVersion(projectConfig?: ProjectConfig): PlatformVersion;
14
+ _reset(): void;
15
+ parentSetup({ onUploadRequired, promptUser, logger, urls, setActiveApp, choices, }: DevModeBaseSetupArguments): Promise<void>;
16
+ start({ requestPorts, accountId, projectConfig, }: DevModeStartArguments): Promise<void>;
17
+ fileChange(filePath: string, __event: unknown): Promise<void>;
18
+ cleanup(): Promise<void>;
19
+ }
@@ -0,0 +1,189 @@
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 dev_1 = require("./dev");
15
+ const config_1 = require("./config");
16
+ const constants_2 = require("./constants");
17
+ const utils_1 = require("./utils");
18
+ const DevServerState_1 = require("./DevServerState");
19
+ const defaultLogger = {
20
+ info: (...args) => {
21
+ console.log(...args);
22
+ },
23
+ debug: (...args) => {
24
+ console.log(...args);
25
+ },
26
+ warn: (...args) => {
27
+ console.error(...args);
28
+ },
29
+ error: (...args) => {
30
+ console.error(...args);
31
+ },
32
+ };
33
+ class DevModeParentInterface {
34
+ constructor() {
35
+ this.logger = defaultLogger;
36
+ }
37
+ _getPlatformVersion(projectConfig) {
38
+ const { platformVersion } = projectConfig !== null && projectConfig !== void 0 ? projectConfig : {};
39
+ if (!platformVersion) {
40
+ return constants_1.PLATFORM_VERSION.V20231;
41
+ }
42
+ switch (platformVersion) {
43
+ case constants_1.PLATFORM_VERSION.V20231:
44
+ return constants_1.PLATFORM_VERSION.V20231;
45
+ case constants_1.PLATFORM_VERSION.V20232:
46
+ return constants_1.PLATFORM_VERSION.V20232;
47
+ case constants_1.PLATFORM_VERSION.V20252:
48
+ return constants_1.PLATFORM_VERSION.V20252;
49
+ default:
50
+ return (0, utils_1.throwUnhandledPlatformVersionError)(platformVersion);
51
+ }
52
+ }
53
+ _reset() {
54
+ this.configs = undefined;
55
+ this.devServerState = undefined;
56
+ this.onUploadRequired = undefined;
57
+ this.shutdown = undefined;
58
+ this.logger = defaultLogger;
59
+ this.urls = undefined;
60
+ this.isConfigured = false;
61
+ this.isRunning = false;
62
+ }
63
+ parentSetup({ onUploadRequired, promptUser, logger, urls, setActiveApp, choices = [], }) {
64
+ var _a, _b, _c;
65
+ return __awaiter(this, void 0, void 0, function* () {
66
+ if (this.isConfigured) {
67
+ logger.debug('Dev server has already been configured, skipping');
68
+ return;
69
+ }
70
+ this.logger = logger;
71
+ this.onUploadRequired = onUploadRequired;
72
+ this.urls = urls;
73
+ if (choices.length === 0) {
74
+ throw new Error('No extensions to run');
75
+ }
76
+ else if (choices.length === 1) {
77
+ this.configs = [choices[0].value];
78
+ }
79
+ else {
80
+ const answers = yield promptUser({
81
+ type: 'checkbox',
82
+ name: 'extensions',
83
+ message: 'Which extension(s) would you like to run?',
84
+ validate: (input) => {
85
+ if (!input || input.length === 0) {
86
+ return 'Select at least one extension to run';
87
+ }
88
+ const appNames = new Set(input.map((choice) => choice.data.appName));
89
+ if (appNames.size > 1) {
90
+ return 'Running multiple extensions is only supported for a single application';
91
+ }
92
+ return true;
93
+ },
94
+ choices,
95
+ });
96
+ this.configs = answers.extensions;
97
+ }
98
+ this.isConfigured = true;
99
+ if (typeof setActiveApp === 'function') {
100
+ 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);
101
+ }
102
+ });
103
+ }
104
+ start({ requestPorts, accountId, projectConfig, }) {
105
+ var _a, _b, _c, _d;
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ this.logger.debug('Start function was invoked', {
108
+ accountId,
109
+ projectConfig,
110
+ });
111
+ if (this.isRunning) {
112
+ this.logger.debug('Dev server is already running, not starting again');
113
+ return;
114
+ }
115
+ let expressPort = constants_2.EXPRESS_DEFAULT_PORT;
116
+ let webSocketPort = constants_2.WEBSOCKET_DEFAULT_PORT;
117
+ if (requestPorts) {
118
+ try {
119
+ const portData = yield requestPorts([
120
+ { instanceId: constants_2.EXPRESS_SERVER_ID, port: constants_2.EXPRESS_DEFAULT_PORT },
121
+ { instanceId: constants_2.VITE_DEV_SERVER_ID, port: constants_2.WEBSOCKET_DEFAULT_PORT },
122
+ ]);
123
+ expressPort = portData[constants_2.EXPRESS_SERVER_ID];
124
+ webSocketPort = portData[constants_2.VITE_DEV_SERVER_ID];
125
+ }
126
+ catch (e) {
127
+ if ((e === null || e === void 0 ? void 0 : e.status) === 409) {
128
+ throw new Error('Another instance is already running. To proceed, please stop the existing server and try again.');
129
+ }
130
+ this.logger.debug('Call to port manager failed, using default ports');
131
+ }
132
+ }
133
+ 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) || {};
134
+ try {
135
+ this.devServerState = new DevServerState_1.DevServerState({
136
+ localDevUrlMapping,
137
+ extensionConfigs: this.configs,
138
+ accountId,
139
+ platformVersion: this._getPlatformVersion(projectConfig),
140
+ expressPort,
141
+ webSocketPort,
142
+ logger: this.logger,
143
+ urls: this.urls,
144
+ appConfig: (_d = (_c = this.configs) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.appConfig,
145
+ });
146
+ }
147
+ catch (e) {
148
+ this.logger.debug('Error setting up DevServerState', e);
149
+ throw e;
150
+ }
151
+ try {
152
+ this.shutdown = yield (0, dev_1.startDevMode)(this.devServerState);
153
+ }
154
+ catch (e) {
155
+ this.logger.debug('Error starting dev mode', e);
156
+ throw e;
157
+ }
158
+ const { extensionsMetadata } = this.devServerState;
159
+ extensionsMetadata.forEach((metadata) => {
160
+ const { config: { data: { title, appName }, }, } = metadata;
161
+ this.logger.info(`Running extension '${title}' from app '${appName}'`);
162
+ });
163
+ this.isRunning = true;
164
+ });
165
+ }
166
+ // The contract is for this to be async, so eslint can chill
167
+ // eslint-disable-next-line require-await
168
+ fileChange(filePath, __event) {
169
+ return __awaiter(this, void 0, void 0, function* () {
170
+ if (!this.devServerState || !this.devServerState.extensionsMetadata) {
171
+ return;
172
+ }
173
+ const relevantConfigFileChanged = this.devServerState.extensionsMetadata.some((metadata) => metadata.config.extensionConfigPath === filePath);
174
+ if (relevantConfigFileChanged && this.onUploadRequired) {
175
+ this.onUploadRequired();
176
+ }
177
+ });
178
+ }
179
+ cleanup() {
180
+ return __awaiter(this, void 0, void 0, function* () {
181
+ if (this.shutdown) {
182
+ yield this.shutdown();
183
+ }
184
+ // Since the DevModeInterface is a singleton, we need to wipe out the state when we shutdown
185
+ this._reset();
186
+ });
187
+ }
188
+ }
189
+ exports.DevModeParentInterface = DevModeParentInterface;
@@ -0,0 +1,9 @@
1
+ import { AppExtensionMapping, UnifiedProjectComponentMap, UnifiedDevModeSetupArguments } from './types';
2
+ import { DevModeParentInterface } from './DevModeParentInterface';
3
+ declare class DevModeUnifiedInterface extends DevModeParentInterface {
4
+ _generateAppExtensionMappings(components: UnifiedProjectComponentMap): AppExtensionMapping[];
5
+ setup(args: UnifiedDevModeSetupArguments): Promise<void>;
6
+ }
7
+ export { DevModeUnifiedInterface as DevModeUnifiedInterfaceNonSingleton };
8
+ declare const _default: DevModeUnifiedInterface;
9
+ export default _default;
@@ -0,0 +1,123 @@
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 constants_1 = require("./constants");
20
+ const types_1 = require("./types");
21
+ const DevModeParentInterface_1 = require("./DevModeParentInterface");
22
+ const utils_1 = require("./utils");
23
+ class DevModeUnifiedInterface extends DevModeParentInterface_1.DevModeParentInterface {
24
+ _generateAppExtensionMappings(components) {
25
+ var _a, _b, _c, _d;
26
+ const mappings = [];
27
+ // Loop over all of the components that are passed in
28
+ const allComponentUids = Object.keys(components);
29
+ // Find the app component
30
+ const appUid = allComponentUids.find((componentUid) => {
31
+ return (components[componentUid].componentType ===
32
+ types_1.UnifiedComponentTypes.APPLICATION);
33
+ });
34
+ // This should fail a lot sooner (on the cli side), but added this just in case.
35
+ if (!appUid) {
36
+ this.logger.error('Application configuration is missing.');
37
+ return mappings;
38
+ }
39
+ const appData = components[appUid];
40
+ // Use the app data to generate the app config in the expected shape, to match old projects.
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
+ // Update the extension entrypoint to be "relative" to the extension directory (eg from /app/card/card.jsx to ./card.jsx)
67
+ extension.config.entrypoint = `./${path_1.default.basename(extension.config.entrypoint)}`;
68
+ // Add them to the app config
69
+ switch (extension.componentType) {
70
+ case types_1.UnifiedComponentTypes.CARD:
71
+ default:
72
+ appConfig.extensions.crm.cards.push({
73
+ file: extension.config.entrypoint,
74
+ });
75
+ }
76
+ // Generate the name and other extension data for the mapping.
77
+ const extensionName = `${appData.config.name}/${extension.config.name}`;
78
+ const extensionOutput = (0, utils_1.getUrlSafeFileName)(path_1.default.resolve(extension.localDev.componentRoot, extension.config.entrypoint));
79
+ const filePath = path_1.default.resolve(extension.localDev.componentRoot, extension.config.entrypoint);
80
+ // Build the config in the correct shape
81
+ const extensionData = {
82
+ title: extension.config.name,
83
+ uid: extension.uid,
84
+ location: extension.config.location,
85
+ module: {
86
+ file: filePath,
87
+ },
88
+ objectTypes: [],
89
+ appName: appData.config.name,
90
+ sourceId: `${appConfig.uid}::${extension.uid}`,
91
+ };
92
+ // Generate object types
93
+ if (extension.config.objectTypes) {
94
+ extension.config.objectTypes.forEach((objectType) => {
95
+ extensionData.objectTypes.push({
96
+ name: objectType,
97
+ });
98
+ });
99
+ }
100
+ mappings.push({
101
+ name: extensionName,
102
+ value: {
103
+ type: extension.componentType.toLowerCase(),
104
+ data: extensionData,
105
+ output: extensionOutput,
106
+ path: appData.localDev.componentRoot,
107
+ extensionPath: extension.localDev.componentRoot,
108
+ extensionConfigPath: extension.localDev.componentConfigPath,
109
+ appConfig,
110
+ },
111
+ });
112
+ });
113
+ return mappings;
114
+ }
115
+ setup(args) {
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ args.choices = this._generateAppExtensionMappings(args.components);
118
+ yield this.parentSetup(args);
119
+ });
120
+ }
121
+ }
122
+ exports.DevModeUnifiedInterfaceNonSingleton = DevModeUnifiedInterface;
123
+ 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,33 @@ 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 declare enum UnifiedAppAuthTypes {
74
+ OAUTH = "OAUTH",
75
+ STATIC = "STATIC"
76
+ }
77
+ export interface UnifiedAppAuth {
78
+ type: UnifiedAppAuthTypes;
79
+ redirectUrls?: string[];
80
+ requiredScopes?: string[];
81
+ optionalScopes?: string[];
82
+ conditionallyRequiredScopes?: string[];
83
+ }
84
+ export type AppAuth = PublicAppAuth | UnifiedAppAuth;
63
85
  export interface PublicAppConfig {
64
86
  name: string;
65
87
  uid: string;
66
88
  logo?: string;
67
89
  description?: string;
68
90
  allowedUrls?: string[];
69
- auth?: {
70
- preventAdditionalScopes: boolean;
71
- preventOptionalScopes: boolean;
72
- redirectUrls: string[];
73
- requiredScopes: string[];
74
- optionalScopes: string[];
75
- additionalScopes: string[];
76
- };
91
+ auth?: AppAuth;
77
92
  support?: {
78
93
  supportUrl: string;
79
94
  supportEmail: string;
@@ -98,6 +113,73 @@ export interface ProjectComponent {
98
113
  export interface ProjectComponentMap {
99
114
  [key: string]: ProjectComponent;
100
115
  }
116
+ export type UnifiedCardConfig = {
117
+ uid: string;
118
+ type: 'card';
119
+ config: {
120
+ name: string;
121
+ description?: string;
122
+ location: string;
123
+ entrypoint: string;
124
+ objectTypes?: string[];
125
+ previewImage?: {
126
+ file: string;
127
+ altText: string;
128
+ };
129
+ };
130
+ };
131
+ export declare enum UnifiedComponentTypes {
132
+ CARD = "CARD",
133
+ APPLICATION = "APPLICATION"
134
+ }
135
+ export type UnifiedExtensionComponent = Omit<UnifiedCardConfig, 'type'> & {
136
+ componentType: UnifiedComponentTypes.CARD;
137
+ componentDeps: {
138
+ app: string;
139
+ };
140
+ metaFilePath: string;
141
+ files: {};
142
+ localDev: {
143
+ componentRoot: string;
144
+ componentConfigPath: string;
145
+ };
146
+ };
147
+ export interface UnifiedAppComponent {
148
+ uid: string;
149
+ config: {
150
+ description: string;
151
+ name: string;
152
+ logo?: string;
153
+ auth: UnifiedAppAuth;
154
+ permittedUrls?: {
155
+ fetch: string[];
156
+ iframe: string[];
157
+ img: string[];
158
+ };
159
+ support?: {
160
+ supportEmail: string;
161
+ documentationUrl: string;
162
+ supportUrl: string;
163
+ supportPhone: string;
164
+ };
165
+ };
166
+ componentType: UnifiedComponentTypes.APPLICATION;
167
+ componentDeps: {};
168
+ metaFilePath: string;
169
+ files: {};
170
+ localDev: {
171
+ componentRoot: string;
172
+ componentConfigPath: string;
173
+ };
174
+ }
175
+ export type UnifiedAppConfig = Omit<PublicAppConfig, 'auth'> & {
176
+ auth: UnifiedAppAuth;
177
+ isPublicApp: boolean;
178
+ };
179
+ export type UnifiedComponent = UnifiedExtensionComponent | UnifiedAppComponent;
180
+ export interface UnifiedProjectComponentMap {
181
+ [key: string]: UnifiedComponent;
182
+ }
101
183
  export interface BaseMessage {
102
184
  appName: string;
103
185
  title: string;
@@ -139,4 +221,35 @@ export interface Logger {
139
221
  warn: (...args: any[]) => void;
140
222
  error: (...args: any[]) => void;
141
223
  }
224
+ export interface AppExtensionMapping {
225
+ name: string;
226
+ value: ExtensionOutputConfig;
227
+ }
228
+ export interface DevModeStartArguments {
229
+ accountId?: number;
230
+ requestPorts?: (requestPortsData: Array<{
231
+ instanceId: string;
232
+ port?: number;
233
+ }>) => Promise<{
234
+ [instanceId: string]: number;
235
+ }>;
236
+ projectConfig?: ProjectConfig;
237
+ }
238
+ export interface DevModeBaseSetupArguments {
239
+ onUploadRequired?: VoidFunction;
240
+ promptUser: PromptModule;
241
+ logger: Logger;
242
+ urls: {
243
+ api: string;
244
+ web: string;
245
+ };
246
+ setActiveApp: (appUid: string | undefined) => Promise<void>;
247
+ choices?: AppExtensionMapping[];
248
+ }
249
+ export interface DevModeSetupArguments extends DevModeBaseSetupArguments {
250
+ components: ProjectComponentMap;
251
+ }
252
+ export interface UnifiedDevModeSetupArguments extends DevModeBaseSetupArguments {
253
+ components: UnifiedProjectComponentMap;
254
+ }
142
255
  export {};
package/dist/lib/types.js CHANGED
@@ -1,2 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UnifiedComponentTypes = exports.UnifiedAppAuthTypes = void 0;
4
+ var UnifiedAppAuthTypes;
5
+ (function (UnifiedAppAuthTypes) {
6
+ UnifiedAppAuthTypes["OAUTH"] = "OAUTH";
7
+ UnifiedAppAuthTypes["STATIC"] = "STATIC";
8
+ })(UnifiedAppAuthTypes || (exports.UnifiedAppAuthTypes = UnifiedAppAuthTypes = {}));
9
+ var UnifiedComponentTypes;
10
+ (function (UnifiedComponentTypes) {
11
+ UnifiedComponentTypes["CARD"] = "CARD";
12
+ UnifiedComponentTypes["APPLICATION"] = "APPLICATION";
13
+ })(UnifiedComponentTypes || (exports.UnifiedComponentTypes = UnifiedComponentTypes = {}));
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.47",
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.47",
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": "6aa0e60d7241a0218512617a5126df688f8fb894"
73
73
  }