@hubspot/ui-extensions-dev-server 0.8.3 → 0.8.4
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/lib/DevModeInterface.d.ts +3 -5
- package/dist/lib/DevModeInterface.js +25 -33
- package/dist/lib/DevServerState.d.ts +28 -0
- package/dist/lib/DevServerState.js +67 -0
- package/dist/lib/dev.d.ts +2 -12
- package/dist/lib/dev.js +10 -30
- package/dist/lib/extensionsService.d.ts +3 -3
- package/dist/lib/extensionsService.js +12 -9
- package/dist/lib/plugins/codeCheckingPlugin.js +2 -1
- package/dist/lib/plugins/devBuildPlugin.d.ts +2 -4
- package/dist/lib/plugins/devBuildPlugin.js +51 -34
- package/dist/lib/server.d.ts +3 -8
- package/dist/lib/server.js +15 -8
- package/dist/lib/types.d.ts +4 -0
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ExtensionConfig, PlatformVersion, ProjectComponentMap } from './types';
|
|
2
2
|
import type { ServiceConfiguration } from '@hubspot/app-functions-dev-server/dist/types';
|
|
3
3
|
import { PromptModule } from 'inquirer';
|
|
4
|
+
import { DevServerState } from './DevServerState';
|
|
4
5
|
interface SetupArguments {
|
|
5
6
|
components: ProjectComponentMap;
|
|
6
7
|
debug?: boolean;
|
|
@@ -24,13 +25,10 @@ interface AppExtensionMapping {
|
|
|
24
25
|
value: ExtensionConfig;
|
|
25
26
|
}
|
|
26
27
|
declare class DevModeInterface {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
title?: string;
|
|
30
|
-
extensionConfigPath?: string;
|
|
28
|
+
configs?: ExtensionConfig[];
|
|
29
|
+
devServerState?: DevServerState;
|
|
31
30
|
onUploadRequired?: VoidFunction;
|
|
32
31
|
shutdown?: () => Promise<void>;
|
|
33
|
-
_setDataFromExtensionConfig(extensionConfig: ExtensionConfig): void;
|
|
34
32
|
_generateAppExtensionMappings(components: ProjectComponentMap): AppExtensionMapping[];
|
|
35
33
|
_getPlatformVersion(projectConfig?: ProjectConfig): PlatformVersion;
|
|
36
34
|
setup({ components, debug, extensionConfig, onUploadRequired, promptUser, }: SetupArguments): Promise<void>;
|
|
@@ -10,24 +10,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
11
11
|
});
|
|
12
12
|
};
|
|
13
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
-
};
|
|
16
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
14
|
const dev_1 = require("./dev");
|
|
18
|
-
const path_1 = __importDefault(require("path"));
|
|
19
15
|
const constants_1 = require("./constants");
|
|
20
16
|
const config_1 = require("./config");
|
|
21
17
|
// @ts-expect-error no type defs
|
|
22
18
|
const logger_1 = require("@hubspot/cli-lib/logger");
|
|
19
|
+
const DevServerState_1 = require("./DevServerState");
|
|
23
20
|
const utils_1 = require("./utils");
|
|
24
21
|
class DevModeInterface {
|
|
25
|
-
_setDataFromExtensionConfig(extensionConfig) {
|
|
26
|
-
this.config = extensionConfig;
|
|
27
|
-
this.extensionConfigPath = extensionConfig.extensionConfigPath;
|
|
28
|
-
this.appName = extensionConfig.data.appName;
|
|
29
|
-
this.title = extensionConfig.data.title;
|
|
30
|
-
}
|
|
31
22
|
_generateAppExtensionMappings(components) {
|
|
32
23
|
// Loop over all of the app configs that are passed in
|
|
33
24
|
const allComponentNames = Object.keys(components);
|
|
@@ -70,7 +61,7 @@ class DevModeInterface {
|
|
|
70
61
|
(0, logger_1.setLogLevel)(debug ? logger_1.LOG_LEVEL.DEBUG : logger_1.LOG_LEVEL.LOG);
|
|
71
62
|
this.onUploadRequired = onUploadRequired;
|
|
72
63
|
if (extensionConfig) {
|
|
73
|
-
this.
|
|
64
|
+
this.configs = [extensionConfig];
|
|
74
65
|
return;
|
|
75
66
|
}
|
|
76
67
|
const choices = this._generateAppExtensionMappings(components);
|
|
@@ -78,16 +69,22 @@ class DevModeInterface {
|
|
|
78
69
|
throw new Error('No extensions to run');
|
|
79
70
|
}
|
|
80
71
|
else if (choices.length === 1) {
|
|
81
|
-
this.
|
|
72
|
+
this.configs = [choices[0].value];
|
|
82
73
|
}
|
|
83
74
|
else {
|
|
84
75
|
const answers = yield promptUser({
|
|
85
|
-
type: '
|
|
86
|
-
name: '
|
|
87
|
-
message: 'Which extension would you like to run?',
|
|
76
|
+
type: 'checkbox',
|
|
77
|
+
name: 'extensions',
|
|
78
|
+
message: 'Which extension(s) would you like to run?',
|
|
79
|
+
validate: input => {
|
|
80
|
+
if (!input || input.length === 0) {
|
|
81
|
+
return 'Select at least one extension to run';
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
},
|
|
88
85
|
choices,
|
|
89
86
|
});
|
|
90
|
-
this.
|
|
87
|
+
this.configs = answers.extensions;
|
|
91
88
|
}
|
|
92
89
|
});
|
|
93
90
|
}
|
|
@@ -95,9 +92,11 @@ class DevModeInterface {
|
|
|
95
92
|
// eslint-disable-next-line require-await
|
|
96
93
|
fileChange(filePath, __event) {
|
|
97
94
|
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
-
if (this.
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
if (!this.devServerState || !this.devServerState.extensionsMetadata) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const relevantConfigFileChanged = this.devServerState.extensionsMetadata.some(metadata => metadata.config.extensionConfigPath === filePath);
|
|
99
|
+
if (relevantConfigFileChanged && this.onUploadRequired) {
|
|
101
100
|
this.onUploadRequired();
|
|
102
101
|
}
|
|
103
102
|
});
|
|
@@ -107,24 +106,17 @@ class DevModeInterface {
|
|
|
107
106
|
if (debug !== undefined) {
|
|
108
107
|
(0, logger_1.setLogLevel)(debug ? logger_1.LOG_LEVEL.DEBUG : logger_1.LOG_LEVEL.LOG);
|
|
109
108
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
const appPath = this.config.path;
|
|
114
|
-
// Pass options from the CLI for running app functions locally
|
|
115
|
-
const functionsConfig = {
|
|
116
|
-
app: { path: appPath },
|
|
109
|
+
this.devServerState = new DevServerState_1.DevServerState({
|
|
110
|
+
extensionConfigs: this.configs,
|
|
117
111
|
accountId,
|
|
118
112
|
httpClient,
|
|
119
113
|
platformVersion: this._getPlatformVersion(projectConfig),
|
|
120
|
-
};
|
|
121
|
-
this.shutdown = yield (0, dev_1.startDevMode)({
|
|
122
|
-
extensionConfig: this.config,
|
|
123
|
-
outputDir: path_1.default.join(this.config.extensionPath, constants_1.OUTPUT_DIR),
|
|
124
|
-
functionsConfig,
|
|
125
|
-
root: appPath,
|
|
126
114
|
});
|
|
127
|
-
|
|
115
|
+
this.shutdown = yield (0, dev_1.startDevMode)(this.devServerState);
|
|
116
|
+
this.devServerState.extensionsMetadata.forEach(metadata => {
|
|
117
|
+
const { config: { data: { title, appName }, }, } = metadata;
|
|
118
|
+
logger_1.logger.info(`Running extension '${title}' from app '${appName}'`);
|
|
119
|
+
});
|
|
128
120
|
});
|
|
129
121
|
}
|
|
130
122
|
cleanup() {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ExtensionConfig, ExtensionMetadata, PlatformVersion } from './types';
|
|
2
|
+
import { ServiceConfiguration } from '@hubspot/app-functions-dev-server/dist/types';
|
|
3
|
+
interface DevServerStateArgs {
|
|
4
|
+
extensionConfigs?: ExtensionConfig[];
|
|
5
|
+
accountId: number | undefined;
|
|
6
|
+
httpClient: ServiceConfiguration['httpClient'] | undefined;
|
|
7
|
+
expressPort?: number;
|
|
8
|
+
webSocketPort?: number;
|
|
9
|
+
platformVersion: PlatformVersion;
|
|
10
|
+
}
|
|
11
|
+
export declare class DevServerState {
|
|
12
|
+
private _webSocketPort;
|
|
13
|
+
private _expressPort;
|
|
14
|
+
private _functionsConfig;
|
|
15
|
+
private _outputDir;
|
|
16
|
+
private _appPath;
|
|
17
|
+
private _extensionsMetadata;
|
|
18
|
+
private _portalId?;
|
|
19
|
+
constructor({ extensionConfigs, accountId, httpClient, expressPort, webSocketPort, platformVersion, }: DevServerStateArgs);
|
|
20
|
+
get portalId(): number | undefined;
|
|
21
|
+
get webSocketPort(): number;
|
|
22
|
+
get expressPort(): number;
|
|
23
|
+
get extensionsMetadata(): ExtensionMetadata[];
|
|
24
|
+
get functionsConfig(): Partial<ServiceConfiguration>;
|
|
25
|
+
get outputDir(): string;
|
|
26
|
+
get appPath(): string;
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DevServerState = void 0;
|
|
7
|
+
const constants_1 = require("./constants");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
class DevServerState {
|
|
10
|
+
constructor({ extensionConfigs, accountId, httpClient, expressPort = constants_1.VITE_DEFAULT_PORT, webSocketPort = constants_1.WEBSOCKET_PORT, platformVersion, }) {
|
|
11
|
+
this._webSocketPort = constants_1.WEBSOCKET_PORT;
|
|
12
|
+
this._expressPort = constants_1.VITE_DEFAULT_PORT;
|
|
13
|
+
if (!extensionConfigs) {
|
|
14
|
+
throw new Error('Unable to load the required extension configuration files');
|
|
15
|
+
}
|
|
16
|
+
const extensionsMetadata = [];
|
|
17
|
+
extensionConfigs.forEach(config => {
|
|
18
|
+
const { appName, title, sourceId } = config.data;
|
|
19
|
+
extensionsMetadata.push({
|
|
20
|
+
config,
|
|
21
|
+
baseMessage: {
|
|
22
|
+
appName,
|
|
23
|
+
title,
|
|
24
|
+
sourceId,
|
|
25
|
+
callback: `http://hslocal.net:${expressPort}/${config.output}`,
|
|
26
|
+
portalId: accountId,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
this._webSocketPort = webSocketPort;
|
|
31
|
+
this._expressPort = expressPort;
|
|
32
|
+
this._extensionsMetadata = extensionsMetadata;
|
|
33
|
+
this._appPath = extensionConfigs[0].path;
|
|
34
|
+
this._portalId = accountId;
|
|
35
|
+
this._outputDir = path_1.default.join(this._appPath, constants_1.OUTPUT_DIR);
|
|
36
|
+
// Pass options from the CLI for running app functions locally
|
|
37
|
+
this._functionsConfig = {
|
|
38
|
+
app: { path: this._appPath },
|
|
39
|
+
accountId,
|
|
40
|
+
httpClient,
|
|
41
|
+
platformVersion,
|
|
42
|
+
};
|
|
43
|
+
Object.freeze(this);
|
|
44
|
+
}
|
|
45
|
+
get portalId() {
|
|
46
|
+
return this._portalId;
|
|
47
|
+
}
|
|
48
|
+
get webSocketPort() {
|
|
49
|
+
return this._webSocketPort;
|
|
50
|
+
}
|
|
51
|
+
get expressPort() {
|
|
52
|
+
return this._expressPort;
|
|
53
|
+
}
|
|
54
|
+
get extensionsMetadata() {
|
|
55
|
+
return this._extensionsMetadata;
|
|
56
|
+
}
|
|
57
|
+
get functionsConfig() {
|
|
58
|
+
return this._functionsConfig;
|
|
59
|
+
}
|
|
60
|
+
get outputDir() {
|
|
61
|
+
return this._outputDir;
|
|
62
|
+
}
|
|
63
|
+
get appPath() {
|
|
64
|
+
return this._appPath;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.DevServerState = DevServerState;
|
package/dist/lib/dev.d.ts
CHANGED
|
@@ -1,12 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
interface StartDevModeArgs {
|
|
4
|
-
outputDir?: string;
|
|
5
|
-
extensionConfig: ExtensionConfig;
|
|
6
|
-
webSocketPort?: number;
|
|
7
|
-
expressPort?: number;
|
|
8
|
-
root?: string;
|
|
9
|
-
functionsConfig: Partial<ServiceConfiguration>;
|
|
10
|
-
}
|
|
11
|
-
export declare function startDevMode({ extensionConfig, functionsConfig, outputDir, expressPort, webSocketPort, root, }: StartDevModeArgs): Promise<() => Promise<void>>;
|
|
12
|
-
export {};
|
|
1
|
+
import { DevServerState } from './DevServerState';
|
|
2
|
+
export declare function startDevMode(devServerState: DevServerState): Promise<() => Promise<void>>;
|
package/dist/lib/dev.js
CHANGED
|
@@ -17,26 +17,25 @@ const vite_1 = require("vite");
|
|
|
17
17
|
const path_1 = __importDefault(require("path"));
|
|
18
18
|
const server_1 = __importDefault(require("./server"));
|
|
19
19
|
const devBuildPlugin_1 = __importDefault(require("./plugins/devBuildPlugin"));
|
|
20
|
-
const constants_1 = require("./constants");
|
|
21
20
|
// @ts-expect-error no type defs
|
|
22
21
|
const logger_1 = require("@hubspot/cli-lib/logger");
|
|
23
22
|
// @ts-expect-error no type defs
|
|
24
23
|
const detect_port_1 = __importDefault(require("detect-port"));
|
|
25
|
-
function _createViteDevServer(
|
|
24
|
+
function _createViteDevServer(devServerState) {
|
|
26
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
27
26
|
return yield (0, vite_1.createServer)({
|
|
28
|
-
root,
|
|
27
|
+
root: devServerState.appPath,
|
|
29
28
|
logLevel: 'silent',
|
|
30
29
|
appType: 'custom',
|
|
31
30
|
mode: 'development',
|
|
32
31
|
server: {
|
|
33
32
|
middlewareMode: true,
|
|
34
33
|
hmr: {
|
|
35
|
-
port: webSocketPort,
|
|
34
|
+
port: devServerState.webSocketPort,
|
|
36
35
|
},
|
|
37
36
|
watch: {
|
|
38
37
|
ignored: [
|
|
39
|
-
path_1.default.join(outputDir, '/**/*'),
|
|
38
|
+
path_1.default.join(devServerState.outputDir, '/**/*'),
|
|
40
39
|
'**/src/app/app.functions/**/*',
|
|
41
40
|
'**/app.json',
|
|
42
41
|
'**/package.json',
|
|
@@ -46,9 +45,7 @@ function _createViteDevServer({ outputDir, extensionConfig, webSocketPort, baseM
|
|
|
46
45
|
},
|
|
47
46
|
plugins: [
|
|
48
47
|
(0, devBuildPlugin_1.default)({
|
|
49
|
-
|
|
50
|
-
outputDir,
|
|
51
|
-
baseMessage,
|
|
48
|
+
devServerState,
|
|
52
49
|
}),
|
|
53
50
|
],
|
|
54
51
|
clearScreen: false,
|
|
@@ -64,38 +61,21 @@ function throwIfPortTaken(port) {
|
|
|
64
61
|
}
|
|
65
62
|
});
|
|
66
63
|
}
|
|
67
|
-
function startDevMode(
|
|
64
|
+
function startDevMode(devServerState) {
|
|
68
65
|
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
-
if (!
|
|
66
|
+
if (!devServerState || !devServerState.extensionsMetadata) {
|
|
70
67
|
throw new Error('Unable to determine which extension to run');
|
|
71
68
|
}
|
|
69
|
+
const { expressPort, webSocketPort } = devServerState;
|
|
72
70
|
yield throwIfPortTaken(expressPort);
|
|
73
71
|
const actualWebSocketPort = yield (0, detect_port_1.default)(webSocketPort);
|
|
74
72
|
if (actualWebSocketPort !== webSocketPort) {
|
|
75
73
|
logger_1.logger.debug(`WebSocket port ${webSocketPort} is in use; using next available port ${actualWebSocketPort}`);
|
|
76
74
|
}
|
|
77
|
-
const
|
|
78
|
-
const baseMessage = Object.freeze({
|
|
79
|
-
appName,
|
|
80
|
-
title,
|
|
81
|
-
sourceId,
|
|
82
|
-
callback: `http://hslocal.net:${expressPort}/${extensionConfig.output}`,
|
|
83
|
-
portalId: functionsConfig.accountId,
|
|
84
|
-
});
|
|
85
|
-
const viteDevServer = yield _createViteDevServer({
|
|
86
|
-
outputDir,
|
|
87
|
-
extensionConfig,
|
|
88
|
-
webSocketPort: actualWebSocketPort,
|
|
89
|
-
baseMessage,
|
|
90
|
-
root,
|
|
91
|
-
});
|
|
75
|
+
const viteDevServer = yield _createViteDevServer(devServerState);
|
|
92
76
|
const shutdownServer = yield (0, server_1.default)({
|
|
93
|
-
|
|
94
|
-
expressPort,
|
|
95
|
-
webSocketPort: actualWebSocketPort,
|
|
96
|
-
baseMessage,
|
|
77
|
+
devServerState,
|
|
97
78
|
viteDevServer,
|
|
98
|
-
functionsConfig,
|
|
99
79
|
});
|
|
100
80
|
return shutdownServer;
|
|
101
81
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { BaseMessage } from './types';
|
|
2
1
|
import { Response } from 'express/lib/response';
|
|
3
2
|
import { Request } from 'express/lib/request';
|
|
4
3
|
import { Application } from 'express/lib/application';
|
|
4
|
+
import { DevServerState } from './DevServerState';
|
|
5
5
|
declare class ExtensionsService {
|
|
6
6
|
endpoint: string;
|
|
7
7
|
constructor();
|
|
8
|
-
add(server: Application,
|
|
9
|
-
generateExtensionsHandler(
|
|
8
|
+
add(server: Application, devServerState: DevServerState, capabilities: string[]): string[];
|
|
9
|
+
generateExtensionsHandler(devServerState: DevServerState, capabilities?: string[]): (_req: Request, res: Response) => void;
|
|
10
10
|
}
|
|
11
11
|
declare const _default: ExtensionsService;
|
|
12
12
|
export default _default;
|
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable hubspot-dev/no-unsupported-ts-syntax */
|
|
6
7
|
const path_1 = __importDefault(require("path"));
|
|
7
8
|
const constants_1 = require("./constants");
|
|
8
9
|
const utils_1 = require("./utils");
|
|
@@ -10,22 +11,24 @@ class ExtensionsService {
|
|
|
10
11
|
constructor() {
|
|
11
12
|
this.endpoint = '/extensions';
|
|
12
13
|
}
|
|
13
|
-
add(server,
|
|
14
|
-
server.get(this.endpoint, this.generateExtensionsHandler(
|
|
14
|
+
add(server, devServerState, capabilities) {
|
|
15
|
+
server.get(this.endpoint, this.generateExtensionsHandler(devServerState, capabilities));
|
|
15
16
|
return [this.endpoint];
|
|
16
17
|
}
|
|
17
|
-
generateExtensionsHandler(
|
|
18
|
+
generateExtensionsHandler(devServerState, capabilities = []) {
|
|
18
19
|
return function extensionsHandler(_req, res) {
|
|
19
20
|
try {
|
|
20
|
-
const
|
|
21
|
+
const extensions = devServerState.extensionsMetadata.map(metadata => {
|
|
22
|
+
const { baseMessage } = metadata;
|
|
23
|
+
const output = path_1.default.parse(baseMessage.callback).name;
|
|
24
|
+
return Object.assign(Object.assign({}, baseMessage), { manifest: (0, utils_1.loadManifest)(devServerState.outputDir, output) });
|
|
25
|
+
});
|
|
21
26
|
const response = {
|
|
22
|
-
websocket: `ws://localhost:${webSocketPort}`,
|
|
27
|
+
websocket: `ws://localhost:${devServerState.webSocketPort}`,
|
|
23
28
|
version: constants_1.EXTENSIONS_MESSAGE_VERSION,
|
|
24
29
|
capabilities,
|
|
25
|
-
portalId:
|
|
26
|
-
extensions
|
|
27
|
-
Object.assign(Object.assign({}, baseMessage), { manifest: (0, utils_1.loadManifest)(outputDir, output) }),
|
|
28
|
-
],
|
|
30
|
+
portalId: devServerState.portalId,
|
|
31
|
+
extensions,
|
|
29
32
|
};
|
|
30
33
|
res.status(200).json(response);
|
|
31
34
|
}
|
|
@@ -14,7 +14,8 @@ const codeCheckingPlugin = options => {
|
|
|
14
14
|
writeBundle(__options, __bundle) {
|
|
15
15
|
try {
|
|
16
16
|
const code = fs_1.default.readFileSync(output).toString();
|
|
17
|
-
if (!code.includes('const extend = (...args) => self.extend(...args);')
|
|
17
|
+
if (!code.includes('const extend = (...args) => self.extend(...args);') &&
|
|
18
|
+
!code.includes('self.extend_V2(renderExtensionCallback)')) {
|
|
18
19
|
logger_1.logger.warn('Unable to determine if your extension entry point is calling hubspot.extend, this may prevent it from rendering as expected');
|
|
19
20
|
}
|
|
20
21
|
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import Vite from 'vite';
|
|
2
|
-
import {
|
|
2
|
+
import { DevServerState } from '../DevServerState';
|
|
3
3
|
export interface DevBuildPluginOptions {
|
|
4
|
-
|
|
5
|
-
outputDir: string;
|
|
6
|
-
baseMessage: BaseMessage;
|
|
4
|
+
devServerState: DevServerState;
|
|
7
5
|
}
|
|
8
6
|
export type DevBuildPlugin = (options: DevBuildPluginOptions) => Vite.Plugin;
|
|
9
7
|
declare const devBuildPlugin: DevBuildPlugin;
|
|
@@ -47,16 +47,18 @@ const path_1 = __importDefault(require("path"));
|
|
|
47
47
|
const logger_1 = require("@hubspot/cli-lib/logger");
|
|
48
48
|
const friendlyLoggingPlugin_1 = __importDefault(require("./friendlyLoggingPlugin"));
|
|
49
49
|
const relevantModulesPlugin_1 = __importStar(require("./relevantModulesPlugin"));
|
|
50
|
+
function addVersionToBaseMessage(baseMessage) {
|
|
51
|
+
return Object.assign(Object.assign({}, baseMessage), { version: constants_1.WEBSOCKET_MESSAGE_VERSION });
|
|
52
|
+
}
|
|
50
53
|
const devBuildPlugin = options => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const versionedBaseMessage = Object.assign(Object.assign({}, baseMessage), { version: constants_1.WEBSOCKET_MESSAGE_VERSION });
|
|
54
|
+
const { devServerState } = options;
|
|
55
|
+
let lastBuildErrorContext;
|
|
54
56
|
const handleBuildError = (error, server) => {
|
|
55
|
-
const { plugin, errors, frame, loc, id } = error;
|
|
57
|
+
const { error: { plugin, errors, frame, loc, id }, extensionMetadata, } = error;
|
|
56
58
|
// Filter out our custom plugins, but send everything else
|
|
57
59
|
if (!(plugin === null || plugin === void 0 ? void 0 : plugin.startsWith('ui-extensions'))) {
|
|
58
60
|
// @ts-expect-error Our websocket messages don't match Vite format
|
|
59
|
-
server.ws.send(Object.assign(Object.assign({},
|
|
61
|
+
server.ws.send(Object.assign(Object.assign({}, addVersionToBaseMessage(extensionMetadata.baseMessage)), { event: 'error', error: {
|
|
60
62
|
details: {
|
|
61
63
|
errors,
|
|
62
64
|
formattedError: (0, utils_1.stripAnsiColorCodes)(frame),
|
|
@@ -66,8 +68,9 @@ const devBuildPlugin = options => {
|
|
|
66
68
|
} }));
|
|
67
69
|
}
|
|
68
70
|
};
|
|
69
|
-
const devBuild = (server) => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
|
+
const devBuild = (server, extensionMetadata, emptyOutDir = false) => __awaiter(void 0, void 0, void 0, function* () {
|
|
70
72
|
try {
|
|
73
|
+
const { config: extensionConfig } = extensionMetadata;
|
|
71
74
|
yield (0, vite_1.build)({
|
|
72
75
|
logLevel: 'warn',
|
|
73
76
|
mode: 'development',
|
|
@@ -95,24 +98,27 @@ const devBuildPlugin = options => {
|
|
|
95
98
|
extensionPath: extensionConfig.extensionPath,
|
|
96
99
|
}),
|
|
97
100
|
(0, codeCheckingPlugin_1.default)({
|
|
98
|
-
output: path_1.default.join(outputDir, extensionConfig.output),
|
|
101
|
+
output: path_1.default.join(devServerState.outputDir, extensionConfig.output),
|
|
99
102
|
}),
|
|
100
103
|
(0, friendlyLoggingPlugin_1.default)(),
|
|
101
104
|
(0, relevantModulesPlugin_1.default)({ output: extensionConfig.output }),
|
|
102
105
|
], output: Object.assign(Object.assign({}, constants_1.ROLLUP_OPTIONS.output), { sourcemap: 'inline' }) }),
|
|
103
|
-
outDir: outputDir,
|
|
104
|
-
emptyOutDir
|
|
106
|
+
outDir: devServerState.outputDir,
|
|
107
|
+
emptyOutDir,
|
|
105
108
|
minify: false,
|
|
106
109
|
},
|
|
107
110
|
clearScreen: false,
|
|
108
111
|
});
|
|
109
|
-
|
|
112
|
+
lastBuildErrorContext = null;
|
|
110
113
|
return true;
|
|
111
114
|
}
|
|
112
115
|
catch (error) {
|
|
113
|
-
|
|
116
|
+
lastBuildErrorContext = {
|
|
117
|
+
error: error,
|
|
118
|
+
extensionMetadata,
|
|
119
|
+
};
|
|
114
120
|
logger_1.logger.debug(error);
|
|
115
|
-
handleBuildError(
|
|
121
|
+
handleBuildError(lastBuildErrorContext, server);
|
|
116
122
|
return false;
|
|
117
123
|
}
|
|
118
124
|
});
|
|
@@ -126,41 +132,52 @@ const devBuildPlugin = options => {
|
|
|
126
132
|
localServer = server;
|
|
127
133
|
localServer.ws.on('connection', () => {
|
|
128
134
|
logger_1.logger.info('Browser connected and listening for bundle updates');
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
devServerState.extensionsMetadata.forEach(metadata => {
|
|
136
|
+
// @ts-expect-error Our websocket messages don't match Vite format
|
|
137
|
+
localServer.ws.send(Object.assign(Object.assign({}, addVersionToBaseMessage(metadata.baseMessage)), { event: 'start' }));
|
|
138
|
+
});
|
|
139
|
+
if (lastBuildErrorContext) {
|
|
140
|
+
handleBuildError(lastBuildErrorContext, server);
|
|
133
141
|
}
|
|
134
142
|
});
|
|
135
|
-
|
|
143
|
+
for (let i = 0; i < devServerState.extensionsMetadata.length; ++i) {
|
|
144
|
+
yield devBuild(localServer, devServerState.extensionsMetadata[i], i === 0);
|
|
145
|
+
}
|
|
136
146
|
}),
|
|
137
147
|
handleHotUpdate: ({ file, server }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
138
148
|
// If the file is not in the relevantModules list, it's update is inconsequential
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
149
|
+
const extensionsToRebuild = devServerState.extensionsMetadata.filter(metadata => {
|
|
150
|
+
const { config } = metadata;
|
|
151
|
+
return (0, relevantModulesPlugin_1.getRelevantModules)(config.output).includes(file);
|
|
152
|
+
});
|
|
153
|
+
for (let i = 0; i < extensionsToRebuild.length; ++i) {
|
|
154
|
+
const toRebuild = extensionsToRebuild[i];
|
|
155
|
+
const successful = yield devBuild(server, toRebuild);
|
|
156
|
+
if (!successful) {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
const { config: extensionConfig } = toRebuild;
|
|
160
|
+
logger_1.logger.info(`Extension ${extensionConfig.data.title} updated, compiled`);
|
|
161
|
+
if (server.ws.clients.size === 0) {
|
|
162
|
+
logger_1.logger.debug('Bundle updated, no browsers connected to notify');
|
|
163
|
+
return [];
|
|
164
|
+
}
|
|
165
|
+
logger_1.logger.debug('Bundle updated, notifying connected browsers');
|
|
166
|
+
// @ts-expect-error Our websocket messages don't match Vite format
|
|
167
|
+
server.ws.send(Object.assign(Object.assign({}, addVersionToBaseMessage(toRebuild.baseMessage)), { event: 'update' }));
|
|
150
168
|
}
|
|
151
|
-
logger_1.logger.debug('Bundle updated, notifying connected browsers');
|
|
152
|
-
// @ts-expect-error Our websocket messages don't match Vite format
|
|
153
|
-
server.ws.send(Object.assign(Object.assign({}, versionedBaseMessage), { event: 'update' }));
|
|
154
169
|
return [];
|
|
155
170
|
}),
|
|
156
171
|
buildEnd(error) {
|
|
157
172
|
if (error) {
|
|
158
173
|
logger_1.logger.error(error);
|
|
159
174
|
}
|
|
160
|
-
logger_1.logger.debug('Sending shutdown message to connected browsers');
|
|
161
175
|
if (localServer && localServer.ws) {
|
|
162
|
-
|
|
163
|
-
|
|
176
|
+
logger_1.logger.debug('Sending shutdown message to connected browsers');
|
|
177
|
+
devServerState.extensionsMetadata.forEach(metadata => {
|
|
178
|
+
// @ts-expect-error Our websocket messages don't match Vite format
|
|
179
|
+
localServer.ws.send(Object.assign(Object.assign({}, addVersionToBaseMessage(metadata.baseMessage)), { event: 'shutdown' }));
|
|
180
|
+
});
|
|
164
181
|
}
|
|
165
182
|
},
|
|
166
183
|
};
|
package/dist/lib/server.d.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import { BaseMessage } from './types';
|
|
2
1
|
import { ViteDevServer } from 'vite';
|
|
3
|
-
import {
|
|
2
|
+
import { DevServerState } from './DevServerState';
|
|
4
3
|
interface StartDevServerArgs {
|
|
5
|
-
|
|
6
|
-
expressPort: number;
|
|
7
|
-
webSocketPort: number;
|
|
8
|
-
baseMessage: BaseMessage;
|
|
4
|
+
devServerState: DevServerState;
|
|
9
5
|
viteDevServer: ViteDevServer;
|
|
10
|
-
functionsConfig: Partial<ServiceConfiguration>;
|
|
11
6
|
}
|
|
12
|
-
declare function startDevServer({
|
|
7
|
+
declare function startDevServer({ devServerState, viteDevServer, }: StartDevServerArgs): Promise<() => Promise<void>>;
|
|
13
8
|
export default startDevServer;
|
package/dist/lib/server.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/* eslint-disable hubspot-dev/no-unsupported-ts-syntax */
|
|
3
|
+
/* eslint-disable no-unused-expressions */
|
|
2
4
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
5
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
6
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -30,15 +32,17 @@ function listen(app, port) {
|
|
|
30
32
|
});
|
|
31
33
|
});
|
|
32
34
|
}
|
|
33
|
-
function startDevServer({
|
|
35
|
+
function startDevServer({ devServerState, viteDevServer, }) {
|
|
36
|
+
var _a;
|
|
34
37
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
38
|
const app = (0, express_1.default)();
|
|
36
39
|
// Setup middleware
|
|
37
40
|
app.use((0, cors_1.default)());
|
|
38
|
-
app.use(express_1.default.static(outputDir));
|
|
39
|
-
app.use('/api/crm-extensibility/execution/internal/v3', (0, app_functions_dev_server_1.AppFunctionExecutionService)(Object.assign(Object.assign({}, functionsConfig), { logger: logger_1.logger })));
|
|
40
|
-
logger_1.logger.info(`Serving app functions locally (platform version ${functionsConfig.platformVersion})`);
|
|
41
|
-
const endpointsAdded = extensionsService_1.default.add(app,
|
|
41
|
+
app.use(express_1.default.static(devServerState.outputDir));
|
|
42
|
+
app.use('/api/crm-extensibility/execution/internal/v3', (0, app_functions_dev_server_1.AppFunctionExecutionService)(Object.assign(Object.assign({}, devServerState.functionsConfig), { logger: logger_1.logger })));
|
|
43
|
+
logger_1.logger.info(`Serving app functions locally (platform version ${devServerState.functionsConfig.platformVersion})`);
|
|
44
|
+
const endpointsAdded = extensionsService_1.default.add(app, devServerState, constants_1.SERVER_CAPABILITIES);
|
|
45
|
+
const { expressPort } = devServerState;
|
|
42
46
|
endpointsAdded.forEach(endpoint => {
|
|
43
47
|
logger_1.logger.debug(`Listening at http://hslocal.net:${expressPort}${endpoint}`);
|
|
44
48
|
});
|
|
@@ -46,15 +50,18 @@ function startDevServer({ outputDir, expressPort, webSocketPort, baseMessage, vi
|
|
|
46
50
|
app.use(viteDevServer.middlewares);
|
|
47
51
|
let server;
|
|
48
52
|
try {
|
|
49
|
-
server = yield listen(app, expressPort);
|
|
53
|
+
server = yield listen(app, devServerState.expressPort);
|
|
50
54
|
}
|
|
51
55
|
catch (e) {
|
|
52
56
|
if (e.code === 'EADDRINUSE') {
|
|
53
|
-
throw new Error(`Port ${expressPort} is already in use.`);
|
|
57
|
+
throw new Error(`Port ${devServerState.expressPort} is already in use.`);
|
|
54
58
|
}
|
|
55
59
|
throw new Error(e);
|
|
56
60
|
}
|
|
57
|
-
|
|
61
|
+
(_a = devServerState.extensionsMetadata) === null || _a === void 0 ? void 0 : _a.forEach(metadata => {
|
|
62
|
+
const { baseMessage } = metadata;
|
|
63
|
+
logger_1.logger.debug(`Listening at ${baseMessage.callback}`);
|
|
64
|
+
});
|
|
58
65
|
return function shutdown() {
|
|
59
66
|
return __awaiter(this, void 0, void 0, function* () {
|
|
60
67
|
yield viteDevServer.pluginContainer.close();
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -52,5 +52,9 @@ export interface BaseMessage {
|
|
|
52
52
|
sourceId?: string | null;
|
|
53
53
|
portalId?: number;
|
|
54
54
|
}
|
|
55
|
+
export interface ExtensionMetadata {
|
|
56
|
+
baseMessage: BaseMessage;
|
|
57
|
+
config: ExtensionConfig;
|
|
58
|
+
}
|
|
55
59
|
export type PlatformVersion = typeof PLATFORM_VERSION[keyof typeof PLATFORM_VERSION];
|
|
56
60
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/ui-extensions-dev-server",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "jest",
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"optional": true
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "41e3484343d34136e81540d774a101ccf99642b3"
|
|
67
67
|
}
|