@hubspot/ui-extensions-dev-server 0.7.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/config.d.ts +9 -0
- package/dist/cli/config.js +79 -0
- package/dist/cli/run.d.ts +2 -0
- package/dist/cli/run.js +75 -0
- package/dist/cli/utils.d.ts +3 -0
- package/dist/cli/utils.js +65 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +14 -0
- package/dist/lib/DevModeInterface.d.ts +35 -0
- package/dist/lib/DevModeInterface.js +121 -0
- package/dist/lib/build.d.ts +14 -0
- package/dist/lib/build.js +80 -0
- package/dist/lib/constants.d.ts +19 -0
- package/dist/lib/constants.js +35 -0
- package/dist/lib/dev.d.ts +13 -0
- package/dist/lib/dev.js +109 -0
- package/dist/lib/extensionsService.d.ts +12 -0
- package/dist/lib/extensionsService.js +39 -0
- package/dist/lib/plugins/codeCheckingPlugin.d.ts +7 -0
- package/dist/lib/plugins/codeCheckingPlugin.js +27 -0
- package/dist/lib/plugins/codeInjectionPlugin.d.ts +8 -0
- package/dist/lib/plugins/codeInjectionPlugin.js +30 -0
- package/dist/lib/plugins/devBuildPlugin.d.ts +11 -0
- package/dist/lib/plugins/devBuildPlugin.js +139 -0
- package/dist/lib/plugins/friendlyLoggingPlugin.d.ts +11 -0
- package/dist/lib/plugins/friendlyLoggingPlugin.js +44 -0
- package/dist/lib/plugins/manifestPlugin.d.ts +8 -0
- package/dist/lib/plugins/manifestPlugin.js +95 -0
- package/dist/lib/self.d.ts +0 -0
- package/{lib → dist/lib}/self.js +1 -1
- package/dist/lib/server.d.ts +13 -0
- package/dist/lib/server.js +68 -0
- package/dist/lib/types.d.ts +48 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/utils.d.ts +4 -0
- package/dist/lib/utils.js +35 -0
- package/package.json +20 -23
- package/cli/config.js +0 -111
- package/cli/run.js +0 -62
- package/cli/utils.js +0 -67
- package/index.js +0 -14
- package/lib/DevModeInterface.js +0 -131
- package/lib/build.js +0 -86
- package/lib/constants.js +0 -39
- package/lib/dev.js +0 -98
- package/lib/extensionsService.js +0 -54
- package/lib/plugins/codeCheckingPlugin.js +0 -26
- package/lib/plugins/codeInjectionPlugin.js +0 -30
- package/lib/plugins/devBuildPlugin.js +0 -153
- package/lib/plugins/manifestPlugin.js +0 -109
- package/lib/server.js +0 -57
- package/lib/utils.js +0 -36
package/dist/lib/dev.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.startDevMode = void 0;
|
|
16
|
+
const vite_1 = require("vite");
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const server_1 = __importDefault(require("./server"));
|
|
19
|
+
const devBuildPlugin_1 = __importDefault(require("./plugins/devBuildPlugin"));
|
|
20
|
+
const utils_1 = require("./utils");
|
|
21
|
+
const constants_1 = require("./constants");
|
|
22
|
+
// @ts-expect-error no type defs
|
|
23
|
+
const logger_1 = require("@hubspot/cli-lib/logger");
|
|
24
|
+
// @ts-expect-error no type defs
|
|
25
|
+
const detect_port_1 = __importDefault(require("detect-port"));
|
|
26
|
+
function _createViteDevServer({ outputDir, extensionConfig, webSocketPort, baseMessage, root, cardConfigs, }) {
|
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
return yield (0, vite_1.createServer)({
|
|
29
|
+
root,
|
|
30
|
+
logLevel: 'silent',
|
|
31
|
+
appType: 'custom',
|
|
32
|
+
mode: 'development',
|
|
33
|
+
server: {
|
|
34
|
+
middlewareMode: true,
|
|
35
|
+
hmr: {
|
|
36
|
+
port: webSocketPort,
|
|
37
|
+
},
|
|
38
|
+
watch: {
|
|
39
|
+
ignored: [
|
|
40
|
+
path_1.default.join(outputDir, '/**/*'),
|
|
41
|
+
'**/src/app/app.functions/**/*',
|
|
42
|
+
'**/app.json',
|
|
43
|
+
'**/package.json',
|
|
44
|
+
'**/package-lock.json',
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
build: {
|
|
49
|
+
rollupOptions: {
|
|
50
|
+
input: extensionConfig.data.module.file,
|
|
51
|
+
output: { file: (0, utils_1.getUrlSafeFileName)(extensionConfig.data.module.file) },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
plugins: [
|
|
55
|
+
(0, devBuildPlugin_1.default)({
|
|
56
|
+
extensionConfig,
|
|
57
|
+
outputDir,
|
|
58
|
+
baseMessage,
|
|
59
|
+
cardConfigs,
|
|
60
|
+
}),
|
|
61
|
+
],
|
|
62
|
+
clearScreen: false,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function throwIfPortTaken(port) {
|
|
67
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
// detect takes a port and returns the next available port
|
|
69
|
+
// so a mismatch means the requested port was not available
|
|
70
|
+
if ((yield (0, detect_port_1.default)(port)) !== port) {
|
|
71
|
+
throw new Error(`Unable to start because port ${port} is already in use`);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function startDevMode({ extensionConfig, functionsConfig, outputDir = constants_1.OUTPUT_DIR, expressPort = constants_1.VITE_DEFAULT_PORT, webSocketPort = constants_1.WEBSOCKET_PORT, root = process.cwd(), cardConfigs, }) {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
if (!extensionConfig) {
|
|
78
|
+
throw new Error('Unable to determine which extension to run');
|
|
79
|
+
}
|
|
80
|
+
yield throwIfPortTaken(expressPort);
|
|
81
|
+
const actualWebSocketPort = yield (0, detect_port_1.default)(webSocketPort);
|
|
82
|
+
if (actualWebSocketPort !== webSocketPort) {
|
|
83
|
+
logger_1.logger.debug(`WebSocket port ${webSocketPort} is in use; using next available port ${actualWebSocketPort}`);
|
|
84
|
+
}
|
|
85
|
+
const baseMessage = Object.freeze({
|
|
86
|
+
appName: extensionConfig.data.appName,
|
|
87
|
+
title: extensionConfig.data.title,
|
|
88
|
+
callback: `http://hslocal.net:${expressPort}/${extensionConfig.output}`,
|
|
89
|
+
});
|
|
90
|
+
const viteDevServer = yield _createViteDevServer({
|
|
91
|
+
outputDir,
|
|
92
|
+
extensionConfig,
|
|
93
|
+
webSocketPort: actualWebSocketPort,
|
|
94
|
+
baseMessage,
|
|
95
|
+
root,
|
|
96
|
+
cardConfigs,
|
|
97
|
+
});
|
|
98
|
+
const shutdownServer = yield (0, server_1.default)({
|
|
99
|
+
outputDir,
|
|
100
|
+
expressPort,
|
|
101
|
+
webSocketPort: actualWebSocketPort,
|
|
102
|
+
baseMessage,
|
|
103
|
+
viteDevServer,
|
|
104
|
+
functionsConfig,
|
|
105
|
+
});
|
|
106
|
+
return shutdownServer;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
exports.startDevMode = startDevMode;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseMessage } from './types';
|
|
2
|
+
import { Response } from 'express/lib/response';
|
|
3
|
+
import { Request } from 'express/lib/request';
|
|
4
|
+
import { Application } from 'express/lib/application';
|
|
5
|
+
declare class ExtensionsService {
|
|
6
|
+
endpoint: string;
|
|
7
|
+
constructor();
|
|
8
|
+
add(server: Application, webSocketPort: number, outputDir: string, baseMessage: BaseMessage, capabilities: string[]): string[];
|
|
9
|
+
generateExtensionsHandler(baseMessage: BaseMessage, webSocketPort: number, outputDir: string, capabilities?: string[]): (_req: Request, res: Response) => void;
|
|
10
|
+
}
|
|
11
|
+
declare const _default: ExtensionsService;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const constants_1 = require("./constants");
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
class ExtensionsService {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.endpoint = '/extensions';
|
|
12
|
+
}
|
|
13
|
+
add(server, webSocketPort, outputDir, baseMessage, capabilities) {
|
|
14
|
+
server.get(this.endpoint, this.generateExtensionsHandler(baseMessage, webSocketPort, outputDir, capabilities));
|
|
15
|
+
return [this.endpoint];
|
|
16
|
+
}
|
|
17
|
+
generateExtensionsHandler(baseMessage, webSocketPort, outputDir, capabilities = []) {
|
|
18
|
+
return function extensionsHandler(_req, res) {
|
|
19
|
+
try {
|
|
20
|
+
const output = path_1.default.parse(baseMessage.callback).name;
|
|
21
|
+
const response = {
|
|
22
|
+
websocket: `ws://localhost:${webSocketPort}`,
|
|
23
|
+
version: constants_1.EXTENSIONS_MESSAGE_VERSION,
|
|
24
|
+
capabilities,
|
|
25
|
+
extensions: [
|
|
26
|
+
Object.assign(Object.assign({}, baseMessage), { manifest: (0, utils_1.loadManifest)(outputDir, output) }),
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
res.status(200).json(response);
|
|
30
|
+
}
|
|
31
|
+
catch (e) {
|
|
32
|
+
res.status(500).json({
|
|
33
|
+
message: 'Unable to determine which extensions are running',
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.default = new ExtensionsService();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Rollup } from 'vite';
|
|
2
|
+
export interface CodeCheckingPluginOptions {
|
|
3
|
+
output: string;
|
|
4
|
+
}
|
|
5
|
+
export type CodeCheckingPlugin = (options: CodeCheckingPluginOptions) => Rollup.Plugin;
|
|
6
|
+
declare const codeCheckingPlugin: CodeCheckingPlugin;
|
|
7
|
+
export default codeCheckingPlugin;
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
const fs_1 = __importDefault(require("fs"));
|
|
7
|
+
// @ts-expect-error no type defs for the logger
|
|
8
|
+
const logger_1 = require("@hubspot/cli-lib/logger");
|
|
9
|
+
const codeCheckingPlugin = options => {
|
|
10
|
+
const { output } = options;
|
|
11
|
+
return {
|
|
12
|
+
name: 'ui-extensions-code-checking-plugin',
|
|
13
|
+
enforce: 'post',
|
|
14
|
+
writeBundle(__options, __bundle) {
|
|
15
|
+
try {
|
|
16
|
+
const code = fs_1.default.readFileSync(output).toString();
|
|
17
|
+
if (!code.includes('const extend = (...args) => self.extend(...args);')) {
|
|
18
|
+
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
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
logger_1.logger.error('Unable to load bundle for code checking');
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
exports.default = codeCheckingPlugin;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Rollup } from 'vite';
|
|
2
|
+
export interface CodeInjectionPluginOptions {
|
|
3
|
+
file: string;
|
|
4
|
+
root?: string;
|
|
5
|
+
}
|
|
6
|
+
export type CodeInjectionPlugin = (options: CodeInjectionPluginOptions) => Rollup.Plugin;
|
|
7
|
+
declare const codeInjectionPlugin: CodeInjectionPlugin;
|
|
8
|
+
export default codeInjectionPlugin;
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
const path_1 = __importDefault(require("path"));
|
|
7
|
+
const codeInjectionPlugin = options => {
|
|
8
|
+
const { file, root = process.cwd() } = options;
|
|
9
|
+
return {
|
|
10
|
+
name: 'ui-extensions-code-injection-plugin',
|
|
11
|
+
enforce: 'post',
|
|
12
|
+
transform(code, fileBeingTransformed) {
|
|
13
|
+
const absoluteFilePath = path_1.default.isAbsolute(file)
|
|
14
|
+
? file
|
|
15
|
+
: path_1.default.join(root, file);
|
|
16
|
+
if (fileBeingTransformed !== absoluteFilePath) {
|
|
17
|
+
return { code, map: null }; // Not the file we care about, return the same code
|
|
18
|
+
}
|
|
19
|
+
// Update the code to import the self script which houses our overrides
|
|
20
|
+
// This needs to be the first line in the source file so that the overrides get hoisted
|
|
21
|
+
// to the top of the generated source file
|
|
22
|
+
const updatedCode = `import "@hubspot/ui-extensions-dev-server/self"; ${code}`;
|
|
23
|
+
// Return the updated source code. We don't need to include the new code in the
|
|
24
|
+
// sourcemap because we don't want it to show up in the users code when they
|
|
25
|
+
// view the source mapped code in the browser
|
|
26
|
+
return { code: updatedCode, map: null };
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
exports.default = codeInjectionPlugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import Vite from 'vite';
|
|
2
|
+
import { ExtensionConfig, BaseMessage } from '../types';
|
|
3
|
+
export interface DevBuildPluginOptions {
|
|
4
|
+
extensionConfig: ExtensionConfig;
|
|
5
|
+
outputDir: string;
|
|
6
|
+
baseMessage: BaseMessage;
|
|
7
|
+
cardConfigs: string[];
|
|
8
|
+
}
|
|
9
|
+
export type DevBuildPlugin = (options: DevBuildPluginOptions) => Vite.Plugin;
|
|
10
|
+
declare const devBuildPlugin: DevBuildPlugin;
|
|
11
|
+
export default devBuildPlugin;
|
|
@@ -0,0 +1,139 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const constants_1 = require("../constants");
|
|
16
|
+
const vite_1 = require("vite");
|
|
17
|
+
const manifestPlugin_1 = __importDefault(require("./manifestPlugin"));
|
|
18
|
+
const utils_1 = require("../utils");
|
|
19
|
+
const codeCheckingPlugin_1 = __importDefault(require("./codeCheckingPlugin"));
|
|
20
|
+
const path_1 = __importDefault(require("path"));
|
|
21
|
+
// @ts-expect-error no type defs
|
|
22
|
+
const logger_1 = require("@hubspot/cli-lib/logger");
|
|
23
|
+
const friendlyLoggingPlugin_1 = __importDefault(require("./friendlyLoggingPlugin"));
|
|
24
|
+
const devBuildPlugin = options => {
|
|
25
|
+
let lastBuildError;
|
|
26
|
+
const { extensionConfig, outputDir, baseMessage, cardConfigs } = options;
|
|
27
|
+
const versionedBaseMessage = Object.assign(Object.assign({}, baseMessage), { version: constants_1.WEBSOCKET_MESSAGE_VERSION });
|
|
28
|
+
const handleBuildError = (error, server) => {
|
|
29
|
+
const { plugin, errors, frame, loc, id } = error;
|
|
30
|
+
// Filter out our custom plugins, but send everything else
|
|
31
|
+
if (!(plugin === null || plugin === void 0 ? void 0 : plugin.startsWith('ui-extensions'))) {
|
|
32
|
+
// @ts-expect-error Our websocket messages don't match Vite format
|
|
33
|
+
server.ws.send(Object.assign(Object.assign({}, versionedBaseMessage), { event: 'error', error: {
|
|
34
|
+
details: {
|
|
35
|
+
errors,
|
|
36
|
+
formattedError: (0, utils_1.stripAnsiColorCodes)(frame),
|
|
37
|
+
location: loc,
|
|
38
|
+
file: id,
|
|
39
|
+
},
|
|
40
|
+
} }));
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const devBuild = (server) => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
+
try {
|
|
45
|
+
yield (0, vite_1.build)({
|
|
46
|
+
logLevel: 'warn',
|
|
47
|
+
mode: 'development',
|
|
48
|
+
define: {
|
|
49
|
+
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
|
|
50
|
+
},
|
|
51
|
+
esbuild: {
|
|
52
|
+
tsconfigRaw: {
|
|
53
|
+
compilerOptions: {
|
|
54
|
+
preserveValueImports: true,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
build: {
|
|
59
|
+
lib: {
|
|
60
|
+
entry: extensionConfig.data.module.file,
|
|
61
|
+
name: extensionConfig.output,
|
|
62
|
+
formats: ['iife'],
|
|
63
|
+
fileName: () => extensionConfig.output,
|
|
64
|
+
},
|
|
65
|
+
rollupOptions: Object.assign(Object.assign({}, constants_1.ROLLUP_OPTIONS), { plugins: [
|
|
66
|
+
(0, manifestPlugin_1.default)({
|
|
67
|
+
minify: false,
|
|
68
|
+
output: extensionConfig.output,
|
|
69
|
+
}),
|
|
70
|
+
(0, codeCheckingPlugin_1.default)({
|
|
71
|
+
output: path_1.default.join(outputDir, extensionConfig.output),
|
|
72
|
+
}),
|
|
73
|
+
(0, friendlyLoggingPlugin_1.default)(),
|
|
74
|
+
], output: Object.assign(Object.assign({}, constants_1.ROLLUP_OPTIONS.output), { sourcemap: 'inline' }) }),
|
|
75
|
+
outDir: outputDir,
|
|
76
|
+
emptyOutDir: true,
|
|
77
|
+
minify: false,
|
|
78
|
+
},
|
|
79
|
+
clearScreen: false,
|
|
80
|
+
});
|
|
81
|
+
lastBuildError = null;
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
lastBuildError = error;
|
|
86
|
+
logger_1.logger.debug(error);
|
|
87
|
+
handleBuildError(lastBuildError, server);
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
let localServer;
|
|
92
|
+
return {
|
|
93
|
+
name: 'ui-extensions-dev-build-plugin',
|
|
94
|
+
enforce: 'pre',
|
|
95
|
+
configureServer: (server) => __awaiter(void 0, void 0, void 0, function* () {
|
|
96
|
+
// Store a reference to the server to be used in hooks that don't get the server injected
|
|
97
|
+
// See https://vitejs.dev/guide/api-plugin.html#configureserver for information on this pattern
|
|
98
|
+
localServer = server;
|
|
99
|
+
localServer.ws.on('connection', () => {
|
|
100
|
+
logger_1.logger.info('Browser connected and listening for bundle updates');
|
|
101
|
+
// @ts-expect-error Our websocket messages don't match Vite format
|
|
102
|
+
localServer.ws.send(Object.assign(Object.assign({}, versionedBaseMessage), { event: 'start' }));
|
|
103
|
+
if (lastBuildError) {
|
|
104
|
+
handleBuildError(lastBuildError, server);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
yield devBuild(localServer);
|
|
108
|
+
}),
|
|
109
|
+
handleHotUpdate: ({ file, server }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
110
|
+
if (cardConfigs.includes(file)) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
const successful = yield devBuild(server);
|
|
114
|
+
if (!successful) {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
logger_1.logger.info(`Extension ${extensionConfig.data.title} updated, compiled`);
|
|
118
|
+
if (server.ws.clients.size === 0) {
|
|
119
|
+
logger_1.logger.debug('Bundle updated, no browsers connected to notify');
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
logger_1.logger.debug('Bundle updated, notifying connected browsers');
|
|
123
|
+
// @ts-expect-error Our websocket messages don't match Vite format
|
|
124
|
+
server.ws.send(Object.assign(Object.assign({}, versionedBaseMessage), { event: 'update' }));
|
|
125
|
+
return [];
|
|
126
|
+
}),
|
|
127
|
+
buildEnd(error) {
|
|
128
|
+
if (error) {
|
|
129
|
+
logger_1.logger.error(error);
|
|
130
|
+
}
|
|
131
|
+
logger_1.logger.debug('Sending shutdown message to connected browsers');
|
|
132
|
+
if (localServer && localServer.ws) {
|
|
133
|
+
// @ts-expect-error Our websocket messages don't match Vite format
|
|
134
|
+
localServer.ws.send(Object.assign(Object.assign({}, versionedBaseMessage), { event: 'shutdown' }));
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
exports.default = devBuildPlugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { RollupLog } from 'rollup';
|
|
2
|
+
import Vite from 'vite';
|
|
3
|
+
export interface MappedLog {
|
|
4
|
+
message?: string;
|
|
5
|
+
level?: 'error' | 'info' | 'warning' | 'debug';
|
|
6
|
+
}
|
|
7
|
+
export interface CodeToLogMapper {
|
|
8
|
+
[key: string]: (loggable: RollupLog) => MappedLog;
|
|
9
|
+
}
|
|
10
|
+
declare function friendlyLoggingPlugin(): Vite.Plugin;
|
|
11
|
+
export default friendlyLoggingPlugin;
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
// @ts-expect-error no type defs
|
|
7
|
+
const logger_1 = require("@hubspot/cli-lib/logger");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const unfriendlyCodeMapper = Object.freeze({
|
|
10
|
+
UNRESOLVED_IMPORT: (loggable) => {
|
|
11
|
+
const { exporter, id } = loggable;
|
|
12
|
+
const { base: extension } = path_1.default.parse(id);
|
|
13
|
+
return {
|
|
14
|
+
message: `${exporter} is imported by ${extension}, but ${exporter} cannot be resolved. Make sure ${exporter} is installed.`,
|
|
15
|
+
level: 'error',
|
|
16
|
+
};
|
|
17
|
+
},
|
|
18
|
+
MISSING_GLOBAL_NAME: () => {
|
|
19
|
+
return {};
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
const unfriendlyCodeList = Object.freeze(Object.keys(unfriendlyCodeMapper));
|
|
23
|
+
function friendlyLoggingPlugin() {
|
|
24
|
+
return {
|
|
25
|
+
name: 'ui-extensions-friendly-logging-plugin',
|
|
26
|
+
enforce: 'post',
|
|
27
|
+
onLog(_level, log) {
|
|
28
|
+
if (unfriendlyCodeList.includes(log.code || '')) {
|
|
29
|
+
const { message, level } = _mapMessageToFriendlyVersion(log);
|
|
30
|
+
if (message && level) {
|
|
31
|
+
logger_1.logger[level](message);
|
|
32
|
+
}
|
|
33
|
+
return false; // Filter the log message
|
|
34
|
+
}
|
|
35
|
+
return true; // We don't have a friendly log message, let it through
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function _mapMessageToFriendlyVersion(loggable) {
|
|
40
|
+
var _a, _b;
|
|
41
|
+
const { code } = loggable;
|
|
42
|
+
return (_b = (_a = unfriendlyCodeMapper[code]) === null || _a === void 0 ? void 0 : _a.call(unfriendlyCodeMapper, loggable)) !== null && _b !== void 0 ? _b : {};
|
|
43
|
+
}
|
|
44
|
+
exports.default = friendlyLoggingPlugin;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Rollup } from 'vite';
|
|
2
|
+
export interface ManifestPluginOptions {
|
|
3
|
+
output: string;
|
|
4
|
+
minify?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export type ManifestPlugin = (options: ManifestPluginOptions) => Rollup.Plugin;
|
|
7
|
+
declare const manifestPlugin: ManifestPlugin;
|
|
8
|
+
export default manifestPlugin;
|
|
@@ -0,0 +1,95 @@
|
|
|
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
|
+
const fs_1 = require("fs");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const constants_1 = require("../constants");
|
|
9
|
+
const path_2 = __importDefault(require("path"));
|
|
10
|
+
// @ts-expect-error no type defs for the logger
|
|
11
|
+
const logger_1 = require("@hubspot/cli-lib/logger");
|
|
12
|
+
const PACKAGE_LOCK_FILE = 'package-lock.json';
|
|
13
|
+
const PACKAGE_FILE = 'package.json';
|
|
14
|
+
const EXTENSIONS_PATH = 'src/app/extensions/';
|
|
15
|
+
const manifestPlugin = options => {
|
|
16
|
+
return {
|
|
17
|
+
name: 'ui-extensions-manifest-generation-plugin',
|
|
18
|
+
enforce: 'post',
|
|
19
|
+
generateBundle(_rollupOptions, bundle) {
|
|
20
|
+
const { output, minify = false } = options;
|
|
21
|
+
try {
|
|
22
|
+
const filename = path_2.default.parse(output).name;
|
|
23
|
+
const manifest = _generateManifestContents(bundle);
|
|
24
|
+
this.emitFile({
|
|
25
|
+
type: 'asset',
|
|
26
|
+
source: minify
|
|
27
|
+
? JSON.stringify(manifest)
|
|
28
|
+
: JSON.stringify(manifest, null, 2),
|
|
29
|
+
fileName: (0, path_1.normalize)(`${filename}-${constants_1.MANIFEST_FILE}`),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (e) {
|
|
33
|
+
logger_1.logger.warn(`\nUnable to write manifest file in ${output}, ${e}`);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
function _generateManifestContents(bundle) {
|
|
39
|
+
const baseManifest = {
|
|
40
|
+
package: _loadPackageFile(),
|
|
41
|
+
};
|
|
42
|
+
// The keys to bundle are the filename without any path information
|
|
43
|
+
const bundles = Object.keys(bundle).filter(cur => cur.endsWith('.js'));
|
|
44
|
+
if (bundles.length === 1) {
|
|
45
|
+
return Object.assign(Object.assign({}, _generateManifestEntry(bundle[bundles[0]])), baseManifest);
|
|
46
|
+
}
|
|
47
|
+
const manifest = bundles.reduce((acc, current) => {
|
|
48
|
+
return Object.assign(Object.assign({}, acc), { [current]: _generateManifestEntry(bundle[current]) });
|
|
49
|
+
}, {});
|
|
50
|
+
return Object.assign(Object.assign({}, manifest), baseManifest);
|
|
51
|
+
}
|
|
52
|
+
function _generateManifestEntry(subBundle) {
|
|
53
|
+
const { facadeModuleId, moduleIds, modules } = subBundle;
|
|
54
|
+
return {
|
|
55
|
+
entry: _stripPathPriorToExtDir(facadeModuleId),
|
|
56
|
+
modules: _buildModulesInfo(moduleIds, modules),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function _loadJsonFileSafely(filename) {
|
|
60
|
+
try {
|
|
61
|
+
return JSON.parse((0, fs_1.readFileSync)(filename).toString());
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function _loadPackageFile() {
|
|
68
|
+
// Look for package-lock.json then fallback to package.json
|
|
69
|
+
return (_loadJsonFileSafely(PACKAGE_LOCK_FILE) || _loadJsonFileSafely(PACKAGE_FILE));
|
|
70
|
+
}
|
|
71
|
+
function _stripPathPriorToExtDir(filepath) {
|
|
72
|
+
return filepath === null || filepath === void 0 ? void 0 : filepath.split(EXTENSIONS_PATH).pop();
|
|
73
|
+
}
|
|
74
|
+
function _buildModulesInfo(moduleIds, modules) {
|
|
75
|
+
const accumulator = {
|
|
76
|
+
internal: [],
|
|
77
|
+
external: [],
|
|
78
|
+
};
|
|
79
|
+
return moduleIds.reduce((acc, mod) => {
|
|
80
|
+
var _a;
|
|
81
|
+
const { renderedExports } = modules[mod];
|
|
82
|
+
const moduleData = {
|
|
83
|
+
module: _stripPathPriorToExtDir(mod),
|
|
84
|
+
renderedExports,
|
|
85
|
+
};
|
|
86
|
+
if ((_a = moduleData.module) === null || _a === void 0 ? void 0 : _a.includes('node_modules')) {
|
|
87
|
+
acc.external.push(moduleData);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
acc.internal.push(moduleData);
|
|
91
|
+
}
|
|
92
|
+
return acc;
|
|
93
|
+
}, accumulator);
|
|
94
|
+
}
|
|
95
|
+
exports.default = manifestPlugin;
|
|
File without changes
|
package/{lib → dist/lib}/self.js
RENAMED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseMessage } from './types';
|
|
2
|
+
import { ViteDevServer } from 'vite';
|
|
3
|
+
import { ServiceConfiguration } from '@hubspot/app-functions-dev-server/dist/types';
|
|
4
|
+
interface StartDevServerArgs {
|
|
5
|
+
outputDir: string;
|
|
6
|
+
expressPort: number;
|
|
7
|
+
webSocketPort: number;
|
|
8
|
+
baseMessage: BaseMessage;
|
|
9
|
+
viteDevServer: ViteDevServer;
|
|
10
|
+
functionsConfig: Partial<ServiceConfiguration>;
|
|
11
|
+
}
|
|
12
|
+
declare function startDevServer({ outputDir, expressPort, webSocketPort, baseMessage, viteDevServer, functionsConfig, }: StartDevServerArgs): Promise<() => Promise<void>>;
|
|
13
|
+
export default startDevServer;
|
|
@@ -0,0 +1,68 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const express_1 = __importDefault(require("express"));
|
|
16
|
+
const cors_1 = __importDefault(require("cors"));
|
|
17
|
+
const constants_1 = require("./constants");
|
|
18
|
+
const extensionsService_1 = __importDefault(require("./extensionsService"));
|
|
19
|
+
const app_functions_dev_server_1 = require("@hubspot/app-functions-dev-server");
|
|
20
|
+
// @ts-expect-error no type defs
|
|
21
|
+
const logger_1 = require("@hubspot/cli-lib/logger");
|
|
22
|
+
function listen(app, port) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const server = app
|
|
25
|
+
.listen({ port }, () => {
|
|
26
|
+
resolve(server);
|
|
27
|
+
})
|
|
28
|
+
.on('error', err => {
|
|
29
|
+
reject(err);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function startDevServer({ outputDir, expressPort, webSocketPort, baseMessage, viteDevServer, functionsConfig, }) {
|
|
34
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
const app = (0, express_1.default)();
|
|
36
|
+
// Setup middleware
|
|
37
|
+
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');
|
|
41
|
+
const endpointsAdded = extensionsService_1.default.add(app, webSocketPort, outputDir, baseMessage, constants_1.SERVER_CAPABILITIES);
|
|
42
|
+
endpointsAdded.forEach(endpoint => {
|
|
43
|
+
logger_1.logger.debug(`Listening at http://hslocal.net:${expressPort}${endpoint}`);
|
|
44
|
+
});
|
|
45
|
+
// Vite middlewares needs to go last because it's greedy and will block other middleware
|
|
46
|
+
app.use(viteDevServer.middlewares);
|
|
47
|
+
let server;
|
|
48
|
+
try {
|
|
49
|
+
server = yield listen(app, expressPort);
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
if (e.code === 'EADDRINUSE') {
|
|
53
|
+
throw new Error(`Port ${expressPort} is already in use.`);
|
|
54
|
+
}
|
|
55
|
+
throw new Error(e);
|
|
56
|
+
}
|
|
57
|
+
logger_1.logger.debug(`Listening at ${baseMessage.callback}`);
|
|
58
|
+
return function shutdown() {
|
|
59
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
+
yield viteDevServer.pluginContainer.close();
|
|
61
|
+
// Stop new connections to express server
|
|
62
|
+
server.close(() => { });
|
|
63
|
+
logger_1.logger.info('Extension dev server done cleaning up');
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
exports.default = startDevServer;
|