@hubspot/ui-extensions-dev-server 1.1.3 → 1.1.5

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.
@@ -733,5 +733,26 @@ describe('ast', () => {
733
733
  const expectedReferenceId = generateHash('CrmRecordAssociationProperties', '0-1', 'firstname-lastname');
734
734
  expect(dep.referenceId).toBe(expectedReferenceId);
735
735
  });
736
+ it('should use default pageLength of 100 when offset is present but pageLength is missing', () => {
737
+ const source = `
738
+ import { useAssociations } from '@hubspot/ui-extensions/crm';
739
+ const result = useAssociations({
740
+ toObjectType: '0-1',
741
+ properties: ['firstname'],
742
+ offset: 50
743
+ });
744
+ `;
745
+ const program = localParse(source);
746
+ const output = traverseAbstractSyntaxTree(program, [], extensionPath, mockLogger);
747
+ expect(output.dataDependencies.dependencies).toHaveLength(1);
748
+ const dep = output.dataDependencies.dependencies[0];
749
+ expect(dep.properties.type).toBe('CrmRecordAssociationProperties');
750
+ if (dep.properties.type === 'CrmRecordAssociationProperties') {
751
+ expect(dep.properties.paginationOptions).toEqual({
752
+ pageLength: 100,
753
+ offset: 50,
754
+ });
755
+ }
756
+ });
736
757
  });
737
758
  });
@@ -1,5 +1,6 @@
1
1
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
2
  import friendlyLoggingPlugin from "../../plugins/friendlyLoggingPlugin.js";
3
+ import path from 'path';
3
4
  describe('friendlyLoggingPlugin', () => {
4
5
  let plugin;
5
6
  let logger;
@@ -25,24 +26,24 @@ describe('friendlyLoggingPlugin', () => {
25
26
  });
26
27
  });
27
28
  describe('onLog', () => {
28
- it('should return true if it is a log message we do not want altered', () => {
29
- // @ts-expect-error TS doesn't think lifecycle hooks are functions
30
- const result = plugin.onLog('error', {
31
- code: "it's an older code but it checks out",
29
+ it('should not filter logs that are not mapped', () => {
30
+ const onLog = plugin.onLog;
31
+ const message = 'this is a test message';
32
+ const result = onLog('warn', {
33
+ code: 'some-unmapped-code',
34
+ message,
32
35
  });
33
- expect(result).toBe(true);
34
- });
35
- it('should return false if it is a log message we want to transform', () => {
36
- // @ts-expect-error TS doesn't think lifecycle hooks are functions
37
- const result = plugin.onLog('error', {
38
- code: 'MISSING_GLOBAL_NAME',
39
- });
40
- expect(result).toBe(false);
36
+ expect(result).toBe(true); // We always filter logs since we handle the logging
37
+ expect(logger.error).toHaveBeenCalledTimes(0);
38
+ expect(logger.info).toHaveBeenCalledTimes(0);
39
+ expect(logger.debug).toHaveBeenCalledTimes(0);
40
+ expect(logger.warn).toHaveBeenCalledTimes(0);
41
41
  });
42
- it('should not log MISSING_GLOBAL_NAME errors', () => {
43
- // @ts-expect-error TS doesn't think lifecycle hooks are functions
44
- const result = plugin.onLog('error', {
42
+ it('should suppress MISSING_GLOBAL_NAME logs', () => {
43
+ const onLog = plugin.onLog;
44
+ const result = onLog('error', {
45
45
  code: 'MISSING_GLOBAL_NAME',
46
+ message: 'this is a test message',
46
47
  });
47
48
  expect(result).toBe(false);
48
49
  expect(logger.error).toHaveBeenCalledTimes(0);
@@ -50,16 +51,31 @@ describe('friendlyLoggingPlugin', () => {
50
51
  expect(logger.debug).toHaveBeenCalledTimes(0);
51
52
  expect(logger.warn).toHaveBeenCalledTimes(0);
52
53
  });
53
- it('should call the logger correctly for UNRESOLVED_IMPORT errors', () => {
54
- // @ts-expect-error TS doesn't think lifecycle hooks are functions
55
- const result = plugin.onLog('we ignore this for now', {
56
- code: 'UNRESOLVED_IMPORT',
57
- id: 'the/file/that/imported/the/bad/import.jsx',
58
- exporter: '@hubspot/extensions',
54
+ it('should map UNRESOLVED_IMPORT logs to errors that throw', () => {
55
+ const onLog = plugin.onLog;
56
+ const importer = 'importer.jsx';
57
+ const exporter = 'missing-package';
58
+ const importerRelativePath = path.relative(process.cwd(), importer);
59
+ expect(() => {
60
+ onLog('warn', {
61
+ code: 'UNRESOLVED_IMPORT',
62
+ id: importer,
63
+ exporter,
64
+ message: 'this is a test message',
65
+ });
66
+ }).toThrow(`Build failed due to unresolved import. "${exporter}" is imported by "${importerRelativePath}", but "${exporter}" cannot be resolved. Make sure "${exporter}" is installed by adding it to your project's dependencies and running \`hs project install-deps\`.`);
67
+ });
68
+ it('should not filter unsupported log levels', () => {
69
+ const onLog = plugin.onLog;
70
+ const result = onLog('unsupported-log-level', {
71
+ code: 'some-unmapped-code',
72
+ message: 'this is a test message',
59
73
  });
60
- expect(result).toBe(false);
61
- expect(logger.error).toHaveBeenCalledTimes(1);
62
- expect(logger.error).toHaveBeenCalledWith('@hubspot/extensions is imported by import.jsx, but @hubspot/extensions cannot be resolved. Make sure @hubspot/extensions is installed by running `hs project install-deps`.');
74
+ expect(result).toBe(true);
75
+ expect(logger.error).toHaveBeenCalledTimes(0);
76
+ expect(logger.info).toHaveBeenCalledTimes(0);
77
+ expect(logger.debug).toHaveBeenCalledTimes(0);
78
+ expect(logger.warn).toHaveBeenCalledTimes(0);
63
79
  });
64
80
  });
65
81
  });
package/dist/lib/ast.js CHANGED
@@ -166,6 +166,13 @@ function _processAssociationsHook(node, output) {
166
166
  if (request.pageLength !== undefined) {
167
167
  paginationOptions.pageLength = request.pageLength;
168
168
  }
169
+ else if (request.offset !== undefined) {
170
+ /**
171
+ * If an offset is provided without a pageLength, we default to 100 (as we do at runtime)
172
+ * This avoids validation errors on the BE
173
+ */
174
+ paginationOptions.pageLength = 100;
175
+ }
169
176
  if (request.offset !== undefined) {
170
177
  paginationOptions.offset = request.offset;
171
178
  }
@@ -64,6 +64,7 @@ async function runCommand(command, options) {
64
64
  spinner.succeed(chalk.green(success));
65
65
  }
66
66
  catch (err) {
67
+ console.error('ERROR:', err);
67
68
  spinner.fail(chalk.red(error));
68
69
  process.exit(1);
69
70
  }
@@ -1,10 +1,10 @@
1
1
  import path from 'path';
2
2
  const unfriendlyCodeMapper = Object.freeze({
3
- UNRESOLVED_IMPORT: (loggable) => {
4
- const { exporter, id } = loggable;
5
- const { base: extension } = path.parse(id);
3
+ UNRESOLVED_IMPORT: (log) => {
4
+ const { exporter, id } = log;
5
+ const importerRelativePath = path.relative(process.cwd(), id);
6
6
  return {
7
- message: `${exporter} is imported by ${extension}, but ${exporter} cannot be resolved. Make sure ${exporter} is installed by running \`hs project install-deps\`.`,
7
+ message: `Build failed due to unresolved import. "${exporter}" is imported by "${importerRelativePath}", but "${exporter}" cannot be resolved. Make sure "${exporter}" is installed by adding it to your project's dependencies and running \`hs project install-deps\`.`,
8
8
  level: 'error',
9
9
  };
10
10
  },
@@ -12,25 +12,33 @@ const unfriendlyCodeMapper = Object.freeze({
12
12
  return {};
13
13
  },
14
14
  });
15
- const unfriendlyCodeList = Object.freeze(Object.keys(unfriendlyCodeMapper));
16
15
  function friendlyLoggingPlugin({ logger }) {
17
16
  return {
18
17
  name: 'ui-extensions-friendly-logging-plugin',
19
18
  enforce: 'post',
20
- onLog(_level, log) {
21
- if (unfriendlyCodeList.includes(log.code || '')) {
22
- const { message, level } = _mapMessageToFriendlyVersion(log);
23
- if (message && level) {
24
- logger[level](message);
19
+ onLog(logLevel, log) {
20
+ const logMessage = log.message;
21
+ const logCode = log.code || '';
22
+ const mappedLog = logCode in unfriendlyCodeMapper
23
+ ? unfriendlyCodeMapper[logCode](log)
24
+ : null;
25
+ if (mappedLog) {
26
+ const targetLogLevel = mappedLog.level;
27
+ const targetLogMessage = mappedLog.message || logMessage;
28
+ if (!targetLogLevel) {
29
+ // If the log is mapped, but doesn't have a level then suppress it
30
+ return false;
25
31
  }
26
- return false; // Filter the log message
32
+ if (targetLogLevel === 'error') {
33
+ // For errors, we want to throw the error so that the build fails
34
+ throw new Error(targetLogMessage);
35
+ }
36
+ logger[targetLogLevel](targetLogMessage);
37
+ return false;
27
38
  }
28
- return true; // We don't have a friendly log message, let it through
39
+ // We want to filter out the log so that it doesn't get logged again
40
+ return true;
29
41
  },
30
42
  };
31
43
  }
32
- function _mapMessageToFriendlyVersion(loggable) {
33
- const { code } = loggable;
34
- return unfriendlyCodeMapper[code]?.(loggable) ?? {};
35
- }
36
44
  export default friendlyLoggingPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/ui-extensions-dev-server",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,7 +42,8 @@
42
42
  "express": "5.1.0",
43
43
  "inquirer": "12.9.6",
44
44
  "ora": "8.2.0",
45
- "vite": "6.3.6"
45
+ "vite": "6.3.6",
46
+ "ws": "^8.18.3"
46
47
  },
47
48
  "devDependencies": {
48
49
  "@changesets/cli": "^2.29.7",
@@ -63,8 +64,7 @@
63
64
  "lint-staged": "^10.5.4",
64
65
  "prettier": "^3.6.2",
65
66
  "typescript": "^5.9.2",
66
- "vitest": "^2.1.9",
67
- "ws": "^8.18.3"
67
+ "vitest": "^2.1.9"
68
68
  },
69
69
  "engines": {
70
70
  "node": ">=18"