@hubspot/ui-extensions-dev-server 0.7.3 → 0.8.1

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.
Files changed (52) hide show
  1. package/dist/cli/config.d.ts +8 -0
  2. package/dist/cli/config.js +80 -0
  3. package/dist/cli/run.d.ts +2 -0
  4. package/dist/cli/run.js +89 -0
  5. package/dist/cli/utils.d.ts +3 -0
  6. package/dist/cli/utils.js +79 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.js +12 -0
  9. package/dist/lib/DevModeInterface.d.ts +35 -0
  10. package/dist/lib/DevModeInterface.js +121 -0
  11. package/dist/lib/build.d.ts +14 -0
  12. package/dist/lib/build.js +82 -0
  13. package/dist/lib/constants.d.ts +18 -0
  14. package/dist/lib/constants.js +28 -0
  15. package/dist/lib/dev.d.ts +13 -0
  16. package/dist/lib/dev.js +112 -0
  17. package/dist/lib/extensionsService.d.ts +12 -0
  18. package/dist/lib/extensionsService.js +40 -0
  19. package/dist/lib/plugins/codeCheckingPlugin.d.ts +7 -0
  20. package/dist/lib/plugins/codeCheckingPlugin.js +27 -0
  21. package/dist/lib/plugins/codeInjectionPlugin.d.ts +8 -0
  22. package/dist/lib/plugins/codeInjectionPlugin.js +30 -0
  23. package/dist/lib/plugins/devBuildPlugin.d.ts +11 -0
  24. package/dist/lib/plugins/devBuildPlugin.js +140 -0
  25. package/dist/lib/plugins/friendlyLoggingPlugin.d.ts +11 -0
  26. package/dist/lib/plugins/friendlyLoggingPlugin.js +44 -0
  27. package/dist/lib/plugins/manifestPlugin.d.ts +9 -0
  28. package/dist/lib/plugins/manifestPlugin.js +96 -0
  29. package/dist/lib/self.d.ts +0 -0
  30. package/{lib → dist/lib}/self.js +1 -1
  31. package/dist/lib/server.d.ts +13 -0
  32. package/dist/lib/server.js +68 -0
  33. package/dist/lib/types.d.ts +53 -0
  34. package/dist/lib/types.js +2 -0
  35. package/dist/lib/utils.d.ts +5 -0
  36. package/dist/lib/utils.js +42 -0
  37. package/package.json +20 -23
  38. package/cli/config.js +0 -111
  39. package/cli/run.js +0 -62
  40. package/cli/utils.js +0 -67
  41. package/index.js +0 -14
  42. package/lib/DevModeInterface.js +0 -131
  43. package/lib/build.js +0 -86
  44. package/lib/constants.js +0 -39
  45. package/lib/dev.js +0 -98
  46. package/lib/extensionsService.js +0 -54
  47. package/lib/plugins/codeCheckingPlugin.js +0 -26
  48. package/lib/plugins/codeInjectionPlugin.js +0 -30
  49. package/lib/plugins/devBuildPlugin.js +0 -153
  50. package/lib/plugins/manifestPlugin.js +0 -109
  51. package/lib/server.js +0 -57
  52. package/lib/utils.js +0 -36
@@ -0,0 +1,112 @@
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 { appName, title, sourceId } = extensionConfig.data;
86
+ const baseMessage = Object.freeze({
87
+ appName,
88
+ title,
89
+ sourceId,
90
+ callback: `http://hslocal.net:${expressPort}/${extensionConfig.output}`,
91
+ portalId: functionsConfig.accountId,
92
+ });
93
+ const viteDevServer = yield _createViteDevServer({
94
+ outputDir,
95
+ extensionConfig,
96
+ webSocketPort: actualWebSocketPort,
97
+ baseMessage,
98
+ root,
99
+ cardConfigs,
100
+ });
101
+ const shutdownServer = yield (0, server_1.default)({
102
+ outputDir,
103
+ expressPort,
104
+ webSocketPort: actualWebSocketPort,
105
+ baseMessage,
106
+ viteDevServer,
107
+ functionsConfig,
108
+ });
109
+ return shutdownServer;
110
+ });
111
+ }
112
+ 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,40 @@
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
+ portalId: baseMessage.portalId,
26
+ extensions: [
27
+ Object.assign(Object.assign({}, baseMessage), { manifest: (0, utils_1.loadManifest)(outputDir, output) }),
28
+ ],
29
+ };
30
+ res.status(200).json(response);
31
+ }
32
+ catch (e) {
33
+ res.status(500).json({
34
+ message: 'Unable to determine which extensions are running',
35
+ });
36
+ }
37
+ };
38
+ }
39
+ }
40
+ 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,140 @@
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
+ extensionPath: extensionConfig.extensionPath,
70
+ }),
71
+ (0, codeCheckingPlugin_1.default)({
72
+ output: path_1.default.join(outputDir, extensionConfig.output),
73
+ }),
74
+ (0, friendlyLoggingPlugin_1.default)(),
75
+ ], output: Object.assign(Object.assign({}, constants_1.ROLLUP_OPTIONS.output), { sourcemap: 'inline' }) }),
76
+ outDir: outputDir,
77
+ emptyOutDir: true,
78
+ minify: false,
79
+ },
80
+ clearScreen: false,
81
+ });
82
+ lastBuildError = null;
83
+ return true;
84
+ }
85
+ catch (error) {
86
+ lastBuildError = error;
87
+ logger_1.logger.debug(error);
88
+ handleBuildError(lastBuildError, server);
89
+ return false;
90
+ }
91
+ });
92
+ let localServer;
93
+ return {
94
+ name: 'ui-extensions-dev-build-plugin',
95
+ enforce: 'pre',
96
+ configureServer: (server) => __awaiter(void 0, void 0, void 0, function* () {
97
+ // Store a reference to the server to be used in hooks that don't get the server injected
98
+ // See https://vitejs.dev/guide/api-plugin.html#configureserver for information on this pattern
99
+ localServer = server;
100
+ localServer.ws.on('connection', () => {
101
+ logger_1.logger.info('Browser connected and listening for bundle updates');
102
+ // @ts-expect-error Our websocket messages don't match Vite format
103
+ localServer.ws.send(Object.assign(Object.assign({}, versionedBaseMessage), { event: 'start' }));
104
+ if (lastBuildError) {
105
+ handleBuildError(lastBuildError, server);
106
+ }
107
+ });
108
+ yield devBuild(localServer);
109
+ }),
110
+ handleHotUpdate: ({ file, server }) => __awaiter(void 0, void 0, void 0, function* () {
111
+ if (cardConfigs.includes(file)) {
112
+ return [];
113
+ }
114
+ const successful = yield devBuild(server);
115
+ if (!successful) {
116
+ return [];
117
+ }
118
+ logger_1.logger.info(`Extension ${extensionConfig.data.title} updated, compiled`);
119
+ if (server.ws.clients.size === 0) {
120
+ logger_1.logger.debug('Bundle updated, no browsers connected to notify');
121
+ return [];
122
+ }
123
+ logger_1.logger.debug('Bundle updated, notifying connected browsers');
124
+ // @ts-expect-error Our websocket messages don't match Vite format
125
+ server.ws.send(Object.assign(Object.assign({}, versionedBaseMessage), { event: 'update' }));
126
+ return [];
127
+ }),
128
+ buildEnd(error) {
129
+ if (error) {
130
+ logger_1.logger.error(error);
131
+ }
132
+ logger_1.logger.debug('Sending shutdown message to connected browsers');
133
+ if (localServer && localServer.ws) {
134
+ // @ts-expect-error Our websocket messages don't match Vite format
135
+ localServer.ws.send(Object.assign(Object.assign({}, versionedBaseMessage), { event: 'shutdown' }));
136
+ }
137
+ },
138
+ };
139
+ };
140
+ 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,9 @@
1
+ import { Rollup } from 'vite';
2
+ export interface ManifestPluginOptions {
3
+ output: string;
4
+ minify?: boolean;
5
+ extensionPath?: string;
6
+ }
7
+ export type ManifestPlugin = (options: ManifestPluginOptions) => Rollup.Plugin;
8
+ declare const manifestPlugin: ManifestPlugin;
9
+ export default manifestPlugin;
@@ -0,0 +1,96 @@
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, extensionPath = process.cwd() } = options;
21
+ try {
22
+ const filename = path_2.default.parse(output).name;
23
+ const manifest = _generateManifestContents(bundle, extensionPath);
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, extensionPath) {
39
+ const baseManifest = {
40
+ package: _loadPackageFile(extensionPath),
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(extensionPath, filename) {
60
+ try {
61
+ return JSON.parse((0, fs_1.readFileSync)(path_2.default.join(extensionPath, filename)).toString());
62
+ }
63
+ catch (e) {
64
+ return undefined;
65
+ }
66
+ }
67
+ function _loadPackageFile(extensionPath) {
68
+ // Look for package-lock.json then fallback to package.json
69
+ return (_loadJsonFileSafely(extensionPath, PACKAGE_LOCK_FILE) ||
70
+ _loadJsonFileSafely(extensionPath, PACKAGE_FILE));
71
+ }
72
+ function _stripPathPriorToExtDir(filepath) {
73
+ return filepath === null || filepath === void 0 ? void 0 : filepath.split(EXTENSIONS_PATH).pop();
74
+ }
75
+ function _buildModulesInfo(moduleIds, modules) {
76
+ const accumulator = {
77
+ internal: [],
78
+ external: [],
79
+ };
80
+ return moduleIds.reduce((acc, mod) => {
81
+ var _a;
82
+ const { renderedExports } = modules[mod];
83
+ const moduleData = {
84
+ module: _stripPathPriorToExtDir(mod),
85
+ renderedExports,
86
+ };
87
+ if ((_a = moduleData.module) === null || _a === void 0 ? void 0 : _a.includes('node_modules')) {
88
+ acc.external.push(moduleData);
89
+ }
90
+ else {
91
+ acc.internal.push(moduleData);
92
+ }
93
+ return acc;
94
+ }, accumulator);
95
+ }
96
+ exports.default = manifestPlugin;
File without changes
@@ -1,4 +1,4 @@
1
+ "use strict";
1
2
  /* eslint-disable hubspot-dev/no-confusing-browser-globals */
2
-
3
3
  // Set methods on the self object to undefined so they are not available within the worker code
4
4
  self.importScripts = undefined;
@@ -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;