@hubspot/ui-extensions-dev-server 0.8.9 → 0.8.12

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.
@@ -1,23 +1,18 @@
1
- import type { ExtensionConfig, PlatformVersion, ProjectComponentMap } from './types';
2
- import type { ServiceConfiguration } from '@hubspot/app-functions-dev-server/dist/types';
1
+ import { ExtensionConfig, Logger, PlatformVersion, ProjectComponentMap, ProjectConfig } from './types';
3
2
  import { PromptModule } from 'inquirer';
4
3
  import { DevServerState } from './DevServerState';
5
4
  interface SetupArguments {
6
5
  components: ProjectComponentMap;
7
- debug?: boolean;
8
- extensionConfig?: ExtensionConfig;
9
6
  onUploadRequired?: VoidFunction;
10
7
  promptUser: PromptModule;
11
- }
12
- interface ProjectConfig {
13
- name: string;
14
- srcDir: string;
15
- platformVersion?: PlatformVersion;
8
+ logger: Logger;
9
+ urls: {
10
+ api: string;
11
+ web: string;
12
+ };
16
13
  }
17
14
  interface StartArguments {
18
15
  accountId?: number;
19
- debug?: boolean;
20
- httpClient?: ServiceConfiguration['httpClient'];
21
16
  requestPorts?: (requestPortsData: Array<{
22
17
  instanceId: string;
23
18
  port?: number;
@@ -35,11 +30,15 @@ declare class DevModeInterface {
35
30
  devServerState?: DevServerState;
36
31
  onUploadRequired?: VoidFunction;
37
32
  shutdown?: () => Promise<void>;
33
+ logger: Logger;
34
+ urls?: SetupArguments['urls'];
35
+ isConfigured?: boolean;
36
+ isRunning?: boolean;
38
37
  _generateAppExtensionMappings(components: ProjectComponentMap): AppExtensionMapping[];
39
38
  _getPlatformVersion(projectConfig?: ProjectConfig): PlatformVersion;
40
- setup({ components, debug, extensionConfig, onUploadRequired, promptUser, }: SetupArguments): Promise<void>;
39
+ setup({ components, onUploadRequired, promptUser, logger, urls, }: SetupArguments): Promise<void>;
41
40
  fileChange(filePath: string, __event: unknown): Promise<void>;
42
- start({ requestPorts, accountId, debug, httpClient, projectConfig, }: StartArguments): Promise<void>;
41
+ start({ requestPorts, accountId, projectConfig }: StartArguments): Promise<void>;
43
42
  cleanup(): Promise<void>;
44
43
  }
45
44
  declare const _default: DevModeInterface;
@@ -15,19 +15,33 @@ const dev_1 = require("./dev");
15
15
  const constants_1 = require("./constants");
16
16
  const constants_2 = require("./constants");
17
17
  const config_1 = require("./config");
18
- // @ts-expect-error no type defs
19
- const logger_1 = require("@hubspot/cli-lib/logger");
20
18
  const DevServerState_1 = require("./DevServerState");
21
19
  const utils_1 = require("./utils");
20
+ const defaultLogger = {
21
+ info: (...args) => {
22
+ console.log(...args);
23
+ },
24
+ debug: (...args) => {
25
+ console.log(...args);
26
+ },
27
+ warn: (...args) => {
28
+ console.error(...args);
29
+ },
30
+ error: (...args) => {
31
+ console.error(...args);
32
+ },
33
+ };
22
34
  class DevModeInterface {
35
+ constructor() {
36
+ this.logger = defaultLogger;
37
+ }
23
38
  _generateAppExtensionMappings(components) {
24
39
  // Loop over all of the app configs that are passed in
25
40
  const allComponentNames = Object.keys(components);
26
41
  return allComponentNames.reduce((appExtensionMappings, componentName) => {
27
- var _a, _b;
28
42
  const component = components[componentName];
29
- if (!((_b = (_a = component.config.extensions) === null || _a === void 0 ? void 0 : _a.crm) === null || _b === void 0 ? void 0 : _b.cards)) {
30
- return appExtensionMappings; // It's not an app
43
+ if (!constants_1.SUPPORTED_APP_TYPES.includes(component.type)) {
44
+ return appExtensionMappings; // It's not a modern app, skip it
31
45
  }
32
46
  // Load all of the extension configs for a particular app.json file
33
47
  const extensionsConfigForApp = (0, config_1.loadExtensionConfig)(component.config, component.path);
@@ -57,14 +71,16 @@ class DevModeInterface {
57
71
  return (0, utils_1.throwUnhandledPlatformVersionError)(platformVersion);
58
72
  }
59
73
  }
60
- setup({ components, debug = false, extensionConfig, onUploadRequired, promptUser, }) {
74
+ setup({ components, onUploadRequired, promptUser, logger, urls, }) {
61
75
  return __awaiter(this, void 0, void 0, function* () {
62
- (0, logger_1.setLogLevel)(debug ? logger_1.LOG_LEVEL.DEBUG : logger_1.LOG_LEVEL.LOG);
63
- this.onUploadRequired = onUploadRequired;
64
- if (extensionConfig) {
65
- this.configs = [extensionConfig];
76
+ logger.debug('Setup function was invoked', { components, urls });
77
+ if (this.isConfigured) {
78
+ logger.debug('Dev server has already been configured, skipping');
66
79
  return;
67
80
  }
81
+ this.logger = logger;
82
+ this.onUploadRequired = onUploadRequired;
83
+ this.urls = urls;
68
84
  const choices = this._generateAppExtensionMappings(components);
69
85
  if (choices.length === 0) {
70
86
  throw new Error('No extensions to run');
@@ -91,6 +107,7 @@ class DevModeInterface {
91
107
  });
92
108
  this.configs = answers.extensions;
93
109
  }
110
+ this.isConfigured = true;
94
111
  });
95
112
  }
96
113
  // The contract is for this to be async, so eslint can chill
@@ -106,10 +123,15 @@ class DevModeInterface {
106
123
  }
107
124
  });
108
125
  }
109
- start({ requestPorts, accountId, debug, httpClient, projectConfig, }) {
126
+ start({ requestPorts, accountId, projectConfig }) {
110
127
  return __awaiter(this, void 0, void 0, function* () {
111
- if (debug !== undefined) {
112
- (0, logger_1.setLogLevel)(debug ? logger_1.LOG_LEVEL.DEBUG : logger_1.LOG_LEVEL.LOG);
128
+ this.logger.debug('Start function was invoked', {
129
+ accountId,
130
+ projectConfig,
131
+ });
132
+ if (this.isRunning) {
133
+ this.logger.debug('Dev server is already running, not starting again');
134
+ return;
113
135
  }
114
136
  let expressPort = constants_1.EXPRESS_DEFAULT_PORT;
115
137
  let webSocketPort = constants_1.WEBSOCKET_DEFAULT_PORT;
@@ -123,28 +145,32 @@ class DevModeInterface {
123
145
  webSocketPort = portData[constants_1.VITE_DEV_SERVER_ID];
124
146
  }
125
147
  catch (e) {
126
- logger_1.logger.debug('Call to port manager failed, using default ports');
148
+ this.logger.debug('Call to port manager failed, using default ports');
127
149
  }
128
150
  }
129
151
  this.devServerState = new DevServerState_1.DevServerState({
130
152
  extensionConfigs: this.configs,
131
153
  accountId,
132
- httpClient,
133
154
  platformVersion: this._getPlatformVersion(projectConfig),
134
155
  expressPort,
135
156
  webSocketPort,
157
+ logger: this.logger,
158
+ urls: this.urls,
136
159
  });
137
160
  this.shutdown = yield (0, dev_1.startDevMode)(this.devServerState);
138
- this.devServerState.extensionsMetadata.forEach((metadata) => {
161
+ const { extensionsMetadata } = this.devServerState;
162
+ extensionsMetadata.forEach((metadata) => {
139
163
  const { config: { data: { title, appName }, }, } = metadata;
140
- logger_1.logger.info(`Running extension '${title}' from app '${appName}'`);
164
+ this.logger.info(`Running extension '${title}' from app '${appName}'`);
141
165
  });
166
+ this.isRunning = true;
142
167
  });
143
168
  }
144
169
  cleanup() {
145
170
  return __awaiter(this, void 0, void 0, function* () {
146
- if (this.shutdown) {
171
+ if (this.shutdown && this.isRunning) {
147
172
  yield this.shutdown();
173
+ this.isRunning = false;
148
174
  }
149
175
  });
150
176
  }
@@ -1,12 +1,16 @@
1
- import { ExtensionConfig, ExtensionMetadata, PlatformVersion } from './types';
1
+ import { ExtensionConfig, ExtensionMetadata, Logger, PlatformVersion } from './types';
2
2
  import { ServiceConfiguration } from '@hubspot/app-functions-dev-server/dist/types';
3
3
  interface DevServerStateArgs {
4
4
  extensionConfigs?: ExtensionConfig[];
5
5
  accountId: number | undefined;
6
- httpClient: ServiceConfiguration['httpClient'] | undefined;
7
6
  expressPort: number;
8
7
  webSocketPort: number;
9
8
  platformVersion: PlatformVersion;
9
+ logger: Logger;
10
+ urls: {
11
+ api: string;
12
+ web: string;
13
+ };
10
14
  }
11
15
  export declare class DevServerState {
12
16
  private _webSocketPort;
@@ -16,7 +20,8 @@ export declare class DevServerState {
16
20
  private _appPath;
17
21
  private _extensionsMetadata;
18
22
  private _portalId?;
19
- constructor({ extensionConfigs, accountId, httpClient, expressPort, webSocketPort, platformVersion, }: DevServerStateArgs);
23
+ logger: Logger;
24
+ constructor({ extensionConfigs, accountId, expressPort, webSocketPort, platformVersion, logger, urls, }: DevServerStateArgs);
20
25
  get portalId(): number | undefined;
21
26
  get webSocketPort(): number;
22
27
  get expressPort(): number;
@@ -7,7 +7,7 @@ exports.DevServerState = void 0;
7
7
  const constants_1 = require("./constants");
8
8
  const path_1 = __importDefault(require("path"));
9
9
  class DevServerState {
10
- constructor({ extensionConfigs, accountId, httpClient, expressPort, webSocketPort, platformVersion, }) {
10
+ constructor({ extensionConfigs, accountId, expressPort, webSocketPort, platformVersion, logger, urls, }) {
11
11
  if (!extensionConfigs) {
12
12
  throw new Error('Unable to load the required extension configuration files');
13
13
  }
@@ -35,9 +35,11 @@ class DevServerState {
35
35
  this._functionsConfig = {
36
36
  app: { path: this._appPath },
37
37
  accountId,
38
- httpClient,
39
38
  platformVersion,
39
+ hubspotApiOrigin: urls.api,
40
+ hubspotWebsiteOrigin: urls.web,
40
41
  };
42
+ this.logger = logger;
41
43
  Object.freeze(this);
42
44
  }
43
45
  get portalId() {
package/dist/lib/build.js CHANGED
@@ -18,8 +18,8 @@ const constants_1 = require("./constants");
18
18
  const manifestPlugin_1 = __importDefault(require("./plugins/manifestPlugin"));
19
19
  const path_1 = __importDefault(require("path"));
20
20
  const utils_1 = require("./utils");
21
- const codeInjectionPlugin_1 = __importDefault(require("./plugins/codeInjectionPlugin"));
22
21
  const codeBlockingPlugin_1 = __importDefault(require("./plugins/codeBlockingPlugin"));
22
+ const friendlyLoggingPlugin_1 = __importDefault(require("./plugins/friendlyLoggingPlugin"));
23
23
  const allowedExtensions = ['.js', '.ts', '.tsx', '.jsx'];
24
24
  exports.extensionErrorBaseMessage = `Supported file extensions are [${allowedExtensions.join(', ')}], received:`;
25
25
  function buildSingleExtension({ file, outputDir = constants_1.OUTPUT_DIR, emptyOutDir = true, minify = false, root = process.cwd(), // This is the vite default, so using that as our default
@@ -39,9 +39,9 @@ function buildSingleExtension({ file, outputDir = constants_1.OUTPUT_DIR, emptyO
39
39
  fileName: () => output,
40
40
  },
41
41
  rollupOptions: Object.assign(Object.assign({}, constants_1.ROLLUP_OPTIONS), { plugins: [
42
- (0, manifestPlugin_1.default)({ output, extensionPath: root }),
43
- (0, codeInjectionPlugin_1.default)({ file }),
44
- (0, codeBlockingPlugin_1.default)(),
42
+ (0, manifestPlugin_1.default)({ output, extensionPath: root, logger: console }),
43
+ (0, friendlyLoggingPlugin_1.default)({ logger: console }),
44
+ (0, codeBlockingPlugin_1.default)({ logger: console }),
45
45
  ] }),
46
46
  outDir: outputDir,
47
47
  emptyOutDir,
@@ -1,5 +1,4 @@
1
1
  export declare const OUTPUT_DIR = "dist";
2
- export declare const MAIN_APP_CONFIG = "app.json";
3
2
  export declare const MANIFEST_FILE = "manifest.json";
4
3
  export declare const EXPRESS_SERVER_ID = "ui-extensions-dev-server";
5
4
  export declare const VITE_DEV_SERVER_ID = "ui-extensions-vite-dev-server";
@@ -22,3 +21,6 @@ export declare const PLATFORM_VERSION: {
22
21
  readonly V20231: "2023.1";
23
22
  readonly V20232: "2023.2";
24
23
  };
24
+ export declare const PUBLIC_APP = "public-app";
25
+ export declare const PRIVATE_APP = "private-app";
26
+ export declare const SUPPORTED_APP_TYPES: string[];
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PLATFORM_VERSION = exports.SERVER_CAPABILITIES = 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.MAIN_APP_CONFIG = exports.OUTPUT_DIR = void 0;
3
+ exports.SUPPORTED_APP_TYPES = exports.PRIVATE_APP = exports.PUBLIC_APP = exports.PLATFORM_VERSION = exports.SERVER_CAPABILITIES = 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
- exports.MAIN_APP_CONFIG = 'app.json';
6
5
  exports.MANIFEST_FILE = 'manifest.json';
7
6
  exports.EXPRESS_SERVER_ID = 'ui-extensions-dev-server';
8
7
  exports.VITE_DEV_SERVER_ID = 'ui-extensions-vite-dev-server';
@@ -32,3 +31,8 @@ exports.PLATFORM_VERSION = {
32
31
  V20231: '2023.1',
33
32
  V20232: '2023.2',
34
33
  };
34
+ exports.PUBLIC_APP = 'public-app';
35
+ // You gotta be kidding me linter
36
+ // eslint-disable-next-line hubspot-dev/no-private-classes
37
+ exports.PRIVATE_APP = 'private-app';
38
+ exports.SUPPORTED_APP_TYPES = [exports.PUBLIC_APP, exports.PRIVATE_APP];
@@ -1,7 +1,5 @@
1
- import { Response } from 'express/lib/response';
2
- import { Request } from 'express/lib/request';
3
- import { Application } from 'express/lib/application';
4
1
  import { DevServerState } from './DevServerState';
2
+ import { Request, Response, Application } from 'express';
5
3
  declare class ExtensionsService {
6
4
  endpoint: string;
7
5
  constructor();
@@ -1,4 +1,7 @@
1
1
  import { Rollup } from 'vite';
2
- export type CodeBlockingPlugin = () => Rollup.Plugin;
2
+ import { Logger } from '../types';
3
+ export type CodeBlockingPlugin = ({ logger, }: {
4
+ logger: Logger;
5
+ }) => Rollup.Plugin;
3
6
  declare const codeBlockingPlugin: CodeBlockingPlugin;
4
7
  export default codeBlockingPlugin;
@@ -3,9 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const utils_1 = require("../utils");
5
5
  const ast_1 = require("../ast");
6
- // @ts-expect-error no types
7
- const logger_1 = require("@hubspot/cli-lib/logger");
8
- const codeBlockingPlugin = () => {
6
+ const codeBlockingPlugin = ({ logger }) => {
9
7
  return {
10
8
  name: 'ui-extensions-code-blocking-plugin',
11
9
  enforce: 'post',
@@ -25,12 +23,12 @@ const codeBlockingPlugin = () => {
25
23
  ]);
26
24
  }
27
25
  catch (e) {
28
- logger_1.logger.debug('Unable to parse and traverse source code');
26
+ logger.debug('Unable to parse and traverse source code');
29
27
  return { code, map: null };
30
28
  }
31
29
  if (sourceCodeMetadata.functions[requireFunctionName] &&
32
30
  sourceCodeMetadata.functions[requireFunctionName].scope === 'Global') {
33
- logger_1.logger.warn('require statements are not supported, replace require statements with import');
31
+ logger.warn('require statements are not supported, replace require statements with import');
34
32
  }
35
33
  return { code, map: null };
36
34
  },
@@ -1,6 +1,8 @@
1
1
  import { Rollup } from 'vite';
2
+ import { Logger } from '../types';
2
3
  export interface CodeCheckingPluginOptions {
3
4
  output: string;
5
+ logger: Logger;
4
6
  }
5
7
  export type CodeCheckingPlugin = (options: CodeCheckingPluginOptions) => Rollup.Plugin;
6
8
  declare const codeCheckingPlugin: CodeCheckingPlugin;
@@ -4,10 +4,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
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
7
  const codeCheckingPlugin = (options) => {
10
- const { output } = options;
8
+ const { output, logger } = options;
11
9
  return {
12
10
  name: 'ui-extensions-code-checking-plugin',
13
11
  enforce: 'post',
@@ -16,11 +14,11 @@ const codeCheckingPlugin = (options) => {
16
14
  const code = fs_1.default.readFileSync(output).toString();
17
15
  if (!code.includes('const extend = (...args) => self.extend(...args);') &&
18
16
  !code.includes('self.extend_V2(renderExtensionCallback)')) {
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');
17
+ logger.warn('Unable to determine if your extension entry point is calling hubspot.extend, this may prevent it from rendering as expected');
20
18
  }
21
19
  }
22
20
  catch (e) {
23
- logger_1.logger.error('Unable to load bundle for code checking');
21
+ logger.error('Unable to load bundle for code checking');
24
22
  }
25
23
  },
26
24
  };
@@ -43,8 +43,6 @@ const manifestPlugin_1 = __importDefault(require("./manifestPlugin"));
43
43
  const utils_1 = require("../utils");
44
44
  const codeCheckingPlugin_1 = __importDefault(require("./codeCheckingPlugin"));
45
45
  const path_1 = __importDefault(require("path"));
46
- // @ts-expect-error no type defs
47
- const logger_1 = require("@hubspot/cli-lib/logger");
48
46
  const friendlyLoggingPlugin_1 = __importDefault(require("./friendlyLoggingPlugin"));
49
47
  const relevantModulesPlugin_1 = __importStar(require("./relevantModulesPlugin"));
50
48
  const codeBlockingPlugin_1 = __importDefault(require("./codeBlockingPlugin"));
@@ -53,6 +51,7 @@ function addVersionToBaseMessage(baseMessage) {
53
51
  }
54
52
  const devBuildPlugin = (options) => {
55
53
  const { devServerState } = options;
54
+ const { logger } = devServerState;
56
55
  let lastBuildErrorContext;
57
56
  const handleBuildError = (error, server) => {
58
57
  const { error: { plugin, errors, frame, loc, id }, extensionMetadata, } = error;
@@ -97,13 +96,18 @@ const devBuildPlugin = (options) => {
97
96
  minify: false,
98
97
  output: extensionConfig.output,
99
98
  extensionPath: extensionConfig.extensionPath,
99
+ logger,
100
100
  }),
101
101
  (0, codeCheckingPlugin_1.default)({
102
102
  output: path_1.default.join(devServerState.outputDir, extensionConfig.output),
103
+ logger,
103
104
  }),
104
- (0, friendlyLoggingPlugin_1.default)(),
105
- (0, relevantModulesPlugin_1.default)({ output: extensionConfig.output }),
106
- (0, codeBlockingPlugin_1.default)(),
105
+ (0, friendlyLoggingPlugin_1.default)({ logger }),
106
+ (0, relevantModulesPlugin_1.default)({
107
+ output: extensionConfig.output,
108
+ logger,
109
+ }),
110
+ (0, codeBlockingPlugin_1.default)({ logger }),
107
111
  ], output: Object.assign(Object.assign({}, constants_1.ROLLUP_OPTIONS.output), { sourcemap: 'inline' }) }),
108
112
  outDir: devServerState.outputDir,
109
113
  emptyOutDir,
@@ -119,7 +123,7 @@ const devBuildPlugin = (options) => {
119
123
  error: error,
120
124
  extensionMetadata,
121
125
  };
122
- logger_1.logger.debug(error);
126
+ logger.debug(error);
123
127
  handleBuildError(lastBuildErrorContext, server);
124
128
  return false;
125
129
  }
@@ -133,7 +137,7 @@ const devBuildPlugin = (options) => {
133
137
  // See https://vitejs.dev/guide/api-plugin.html#configureserver for information on this pattern
134
138
  localServer = server;
135
139
  localServer.ws.on('connection', () => {
136
- logger_1.logger.info('Browser connected and listening for bundle updates');
140
+ logger.info('Browser connected and listening for bundle updates');
137
141
  devServerState.extensionsMetadata.forEach((metadata) => {
138
142
  // @ts-expect-error Our websocket messages don't match Vite format
139
143
  localServer.ws.send(Object.assign(Object.assign({}, addVersionToBaseMessage(metadata.baseMessage)), { event: 'start' }));
@@ -159,12 +163,12 @@ const devBuildPlugin = (options) => {
159
163
  return [];
160
164
  }
161
165
  const { config: extensionConfig } = toRebuild;
162
- logger_1.logger.info(`Extension ${extensionConfig.data.title} updated, compiled`);
166
+ logger.info(`Extension ${extensionConfig.data.title} updated, compiled`);
163
167
  if (server.ws.clients.size === 0) {
164
- logger_1.logger.debug('Bundle updated, no browsers connected to notify');
168
+ logger.debug('Bundle updated, no browsers connected to notify');
165
169
  return [];
166
170
  }
167
- logger_1.logger.debug('Bundle updated, notifying connected browsers');
171
+ logger.debug('Bundle updated, notifying connected browsers');
168
172
  // @ts-expect-error Our websocket messages don't match Vite format
169
173
  server.ws.send(Object.assign(Object.assign({}, addVersionToBaseMessage(toRebuild.baseMessage)), { event: 'update' }));
170
174
  }
@@ -172,10 +176,10 @@ const devBuildPlugin = (options) => {
172
176
  }),
173
177
  buildEnd(error) {
174
178
  if (error) {
175
- logger_1.logger.error(error);
179
+ logger.error(error);
176
180
  }
177
181
  if (localServer && localServer.ws) {
178
- logger_1.logger.debug('Sending shutdown message to connected browsers');
182
+ logger.debug('Sending shutdown message to connected browsers');
179
183
  devServerState.extensionsMetadata.forEach((metadata) => {
180
184
  // @ts-expect-error Our websocket messages don't match Vite format
181
185
  localServer.ws.send(Object.assign(Object.assign({}, addVersionToBaseMessage(metadata.baseMessage)), { event: 'shutdown' }));
@@ -1,11 +1,14 @@
1
- import { RollupLog } from 'rollup';
1
+ import { RollupLog, LogLevel } from 'rollup';
2
2
  import Vite from 'vite';
3
+ import { Logger } from '../types';
3
4
  export interface MappedLog {
4
5
  message?: string;
5
- level?: 'error' | 'info' | 'warning' | 'debug';
6
+ level?: 'error' | LogLevel;
6
7
  }
7
8
  export interface CodeToLogMapper {
8
9
  [key: string]: (loggable: RollupLog) => MappedLog;
9
10
  }
10
- declare function friendlyLoggingPlugin(): Vite.Plugin;
11
+ declare function friendlyLoggingPlugin({ logger }: {
12
+ logger: Logger;
13
+ }): Vite.Plugin;
11
14
  export default friendlyLoggingPlugin;
@@ -5,8 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  return (mod && mod.__esModule) ? mod : { "default": mod };
6
6
  };
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- // @ts-expect-error no type defs
9
- const logger_1 = require("@hubspot/cli-lib/logger");
10
8
  const path_1 = __importDefault(require("path"));
11
9
  const unfriendlyCodeMapper = Object.freeze({
12
10
  UNRESOLVED_IMPORT: (loggable) => {
@@ -22,7 +20,7 @@ const unfriendlyCodeMapper = Object.freeze({
22
20
  },
23
21
  });
24
22
  const unfriendlyCodeList = Object.freeze(Object.keys(unfriendlyCodeMapper));
25
- function friendlyLoggingPlugin() {
23
+ function friendlyLoggingPlugin({ logger }) {
26
24
  return {
27
25
  name: 'ui-extensions-friendly-logging-plugin',
28
26
  enforce: 'post',
@@ -30,7 +28,7 @@ function friendlyLoggingPlugin() {
30
28
  if (unfriendlyCodeList.includes(log.code || '')) {
31
29
  const { message, level } = _mapMessageToFriendlyVersion(log);
32
30
  if (message && level) {
33
- logger_1.logger[level](message);
31
+ logger[level](message);
34
32
  }
35
33
  return false; // Filter the log message
36
34
  }
@@ -1,8 +1,10 @@
1
1
  import { Rollup } from 'vite';
2
+ import { Logger } from '../types';
2
3
  export interface ManifestPluginOptions {
3
4
  output: string;
4
5
  minify?: boolean;
5
6
  extensionPath?: string;
7
+ logger: Logger;
6
8
  }
7
9
  export type ManifestPlugin = (options: ManifestPluginOptions) => Rollup.Plugin;
8
10
  declare const manifestPlugin: ManifestPlugin;
@@ -9,8 +9,6 @@ const fs_1 = require("fs");
9
9
  const path_1 = require("path");
10
10
  const constants_1 = require("../constants");
11
11
  const path_2 = __importDefault(require("path"));
12
- // @ts-expect-error no type defs for the logger
13
- const logger_1 = require("@hubspot/cli-lib/logger");
14
12
  const utils_1 = require("../utils");
15
13
  const PACKAGE_LOCK_FILE = 'package-lock.json';
16
14
  const PACKAGE_FILE = 'package.json';
@@ -20,7 +18,7 @@ const manifestPlugin = (options) => {
20
18
  name: 'ui-extensions-manifest-generation-plugin',
21
19
  enforce: 'post',
22
20
  generateBundle(_rollupOptions, bundle) {
23
- const { output, minify = false, extensionPath = process.cwd() } = options;
21
+ const { output, minify = false, extensionPath = process.cwd(), logger, } = options;
24
22
  try {
25
23
  const filename = path_2.default.parse(output).name;
26
24
  const manifest = _generateManifestContents(bundle, extensionPath);
@@ -33,7 +31,7 @@ const manifestPlugin = (options) => {
33
31
  });
34
32
  }
35
33
  catch (e) {
36
- logger_1.logger.warn(`\nUnable to write manifest file in ${output}, ${e}`);
34
+ logger.warn(`\nUnable to write manifest file in ${output}, ${e}`);
37
35
  }
38
36
  },
39
37
  };
@@ -1,10 +1,12 @@
1
1
  import Vite from 'vite';
2
+ import { Logger } from '../types';
2
3
  export interface RelevantModules {
3
4
  [key: string]: string[];
4
5
  }
5
6
  export declare function getRelevantModules(output: string): string[];
6
7
  export interface RelevantModulesPluginOptions {
7
8
  output: string;
9
+ logger: Logger;
8
10
  }
9
11
  export type RelevantModulesPlugin = (options: RelevantModulesPluginOptions) => Vite.Plugin;
10
12
  declare const relevantModulesPlugin: RelevantModulesPlugin;
@@ -2,26 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getRelevantModules = void 0;
4
4
  const utils_1 = require("../utils");
5
- // @ts-expect-error no type defs for the logger
6
- const logger_1 = require("@hubspot/cli-lib/logger");
7
5
  const relevantModules = {};
8
6
  function getRelevantModules(output) {
9
7
  return relevantModules[output] || [];
10
8
  }
11
9
  exports.getRelevantModules = getRelevantModules;
12
- const relevantModulesPlugin = ({ output }) => {
10
+ const relevantModulesPlugin = ({ output, logger }) => {
13
11
  return {
14
12
  name: 'ui-extensions-relevant-modules-plugin',
15
13
  generateBundle(_options, bundle) {
16
14
  const subBundle = bundle[output];
17
15
  if (!subBundle || !subBundle.moduleIds) {
18
16
  // If this happens, something has gone horribly wrong
19
- logger_1.logger.error('Invalid bundle format, please try saving the extension again. If the problem persists try restarting `hs project dev`');
17
+ logger.error('Invalid bundle format, please try saving the extension again. If the problem persists try restarting `hs project dev`');
20
18
  return;
21
19
  }
22
20
  const updatedRelevantModules = subBundle.moduleIds.filter((moduleId) => !(0, utils_1.isNodeModule)(moduleId));
23
21
  if (updatedRelevantModules.length === 0) {
24
- logger_1.logger.error('Unable to determine relevant files to watch, please try saving the extension again. If the problem persists try restarting `hs project dev`');
22
+ logger.error('Unable to determine relevant files to watch, please try saving the extension again. If the problem persists try restarting `hs project dev`');
25
23
  return;
26
24
  }
27
25
  relevantModules[output] = updatedRelevantModules;
@@ -19,8 +19,6 @@ const cors_1 = __importDefault(require("cors"));
19
19
  const constants_1 = require("./constants");
20
20
  const extensionsService_1 = __importDefault(require("./extensionsService"));
21
21
  const app_functions_dev_server_1 = require("@hubspot/app-functions-dev-server");
22
- // @ts-expect-error no type defs
23
- const logger_1 = require("@hubspot/cli-lib/logger");
24
22
  function listen(app, port) {
25
23
  return new Promise((resolve, reject) => {
26
24
  const server = app
@@ -39,12 +37,12 @@ function startDevServer({ devServerState, viteDevServer, }) {
39
37
  // Setup middleware
40
38
  app.use((0, cors_1.default)());
41
39
  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})`);
40
+ app.use('/api/crm-extensibility/execution/internal/v3', (0, app_functions_dev_server_1.AppFunctionExecutionService)(Object.assign(Object.assign({}, devServerState.functionsConfig), { logger: devServerState.logger })));
41
+ devServerState.logger.info(`Serving app functions locally (platform version ${devServerState.functionsConfig.platformVersion})`);
44
42
  const endpointsAdded = extensionsService_1.default.add(app, devServerState, constants_1.SERVER_CAPABILITIES);
45
43
  const { expressPort } = devServerState;
46
44
  endpointsAdded.forEach((endpoint) => {
47
- logger_1.logger.debug(`Listening at http://hslocal.net:${expressPort}${endpoint}`);
45
+ devServerState.logger.debug(`Listening at http://hslocal.net:${expressPort}${endpoint}`);
48
46
  });
49
47
  // Vite middlewares needs to go last because it's greedy and will block other middleware
50
48
  app.use(viteDevServer.middlewares);
@@ -60,14 +58,14 @@ function startDevServer({ devServerState, viteDevServer, }) {
60
58
  }
61
59
  (_a = devServerState.extensionsMetadata) === null || _a === void 0 ? void 0 : _a.forEach((metadata) => {
62
60
  const { baseMessage } = metadata;
63
- logger_1.logger.debug(`Listening at ${baseMessage.callback}`);
61
+ devServerState.logger.debug(`Listening at ${baseMessage.callback}`);
64
62
  });
65
63
  return function shutdown() {
66
64
  return __awaiter(this, void 0, void 0, function* () {
67
65
  yield viteDevServer.pluginContainer.close();
68
66
  // Stop new connections to express server
69
67
  server.close(() => { });
70
- logger_1.logger.info('Extension dev server done cleaning up');
68
+ devServerState.logger.info('Extension dev server done cleaning up');
71
69
  });
72
70
  };
73
71
  });
@@ -1,4 +1,4 @@
1
- import { PLATFORM_VERSION } from './constants';
1
+ import { PLATFORM_VERSION, PRIVATE_APP, PUBLIC_APP } from './constants';
2
2
  export interface ObjectTypes {
3
3
  name: string;
4
4
  }
@@ -26,7 +26,12 @@ export interface ExtensionConfigMap {
26
26
  interface CardConfig {
27
27
  file: string;
28
28
  }
29
- export interface AppConfig {
29
+ export interface ProjectConfig {
30
+ name: string;
31
+ srcDir: string;
32
+ platformVersion?: PlatformVersion;
33
+ }
34
+ export interface PrivateAppConfig {
30
35
  name: string;
31
36
  description: string;
32
37
  scopes: string[];
@@ -38,7 +43,35 @@ export interface AppConfig {
38
43
  };
39
44
  uid?: string;
40
45
  }
46
+ export interface PublicAppConfig {
47
+ name: string;
48
+ uid: string;
49
+ logo?: string;
50
+ description?: string;
51
+ allowedExternalUrls?: string[];
52
+ auth?: {
53
+ preventAdditionalScopes: boolean;
54
+ preventOptionalScopes: boolean;
55
+ redirectUrls: string[];
56
+ requiredScopes: string[];
57
+ optionalScopes: string[];
58
+ additionalScopes: string[];
59
+ };
60
+ support?: {
61
+ supportUrl: string;
62
+ supportEmail: string;
63
+ documentationUrl: string;
64
+ supportPhone: string;
65
+ };
66
+ extensions: {
67
+ crm: {
68
+ cards: CardConfig[];
69
+ };
70
+ };
71
+ }
72
+ export type AppConfig = PrivateAppConfig | PublicAppConfig;
41
73
  export interface ProjectComponent {
74
+ type: typeof PUBLIC_APP | typeof PRIVATE_APP;
42
75
  config: AppConfig;
43
76
  path: string;
44
77
  }
@@ -71,4 +104,10 @@ export interface FunctionInvocationCheck {
71
104
  functionName: string;
72
105
  }
73
106
  export type SourceCodeChecks = FunctionInvocationCheck[];
107
+ export interface Logger {
108
+ info: (...args: any[]) => void;
109
+ debug: (...args: any[]) => void;
110
+ warn: (...args: any[]) => void;
111
+ error: (...args: any[]) => void;
112
+ }
74
113
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/ui-extensions-dev-server",
3
- "version": "0.8.9",
3
+ "version": "0.8.12",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "jest",
@@ -10,14 +10,15 @@
10
10
  "prepare": "npm run build",
11
11
  "lint": "echo 'no lint step for @hubspot/ui-extensions-dev-server'",
12
12
  "jest": "jest --watch",
13
- "integration-test": "npm run build && npm run integration-test --prefix ./integrationTests/fixtures"
13
+ "integration-test-private-app": "npm run integration-test-private-app --prefix ./integrationTests/fixtures",
14
+ "integration-test-public-app": "npm run integration-test-public-app --prefix ./integrationTests/fixtures",
15
+ "integration-test": "npm run build && npm run integration-test-private-app && npm run integration-test-public-app"
14
16
  },
15
17
  "publishConfig": {
16
18
  "access": "public"
17
19
  },
18
20
  "exports": {
19
- ".": "./dist/index.js",
20
- "./self": "./dist/lib/self.js"
21
+ ".": "./dist/index.js"
21
22
  },
22
23
  "files": [
23
24
  "dist",
@@ -25,11 +26,7 @@
25
26
  ],
26
27
  "license": "MIT",
27
28
  "dependencies": {
28
- "@hubspot/app-functions-dev-server": "^0.8.9",
29
- "@hubspot/cli-lib": "^4.1.6",
30
- "command-line-args": "^5.2.1",
31
- "command-line-usage": "^7.0.1",
32
- "console-log-colors": "^0.4.0",
29
+ "@hubspot/app-functions-dev-server": "^0.8.11",
33
30
  "cors": "^2.8.5",
34
31
  "detect-port": "1.5.1",
35
32
  "estraverse": "^5.3.0",
@@ -39,7 +36,7 @@
39
36
  },
40
37
  "devDependencies": {
41
38
  "@types/estree": "^1.0.5",
42
- "@types/express": "types/express",
39
+ "@types/express": "^4.17.17",
43
40
  "@types/inquirer": "^9.0.3",
44
41
  "@types/jest": "^29.5.4",
45
42
  "acorn": "^8.11.2",
@@ -67,5 +64,5 @@
67
64
  "optional": true
68
65
  }
69
66
  },
70
- "gitHead": "03c10fd116330e174654829acfa99c5e41ff870e"
67
+ "gitHead": "de63cea5e941c10de794210c1a095ae2468d6a9d"
71
68
  }
@@ -1,8 +0,0 @@
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;
@@ -1,30 +0,0 @@
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;
File without changes
package/dist/lib/self.js DELETED
@@ -1,4 +0,0 @@
1
- "use strict";
2
- /* eslint-disable hubspot-dev/no-confusing-browser-globals */
3
- // Set methods on the self object to undefined so they are not available within the worker code
4
- self.importScripts = undefined;