@hubspot/ui-extensions-dev-server 0.10.2 → 1.0.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.
Files changed (95) hide show
  1. package/README.md +23 -4
  2. package/dist/index.d.ts +3 -3
  3. package/dist/index.js +4 -45
  4. package/dist/lib/DevModeInterface.d.ts +2 -2
  5. package/dist/lib/DevModeInterface.js +12 -28
  6. package/dist/lib/DevModeParentInterface.d.ts +2 -2
  7. package/dist/lib/DevModeParentInterface.js +138 -154
  8. package/dist/lib/DevModeUnifiedInterface.d.ts +2 -2
  9. package/dist/lib/DevModeUnifiedInterface.js +28 -49
  10. package/dist/lib/DevServerState.d.ts +9 -5
  11. package/dist/lib/DevServerState.js +37 -18
  12. package/dist/lib/ExtensionsWebSocket.d.ts +25 -0
  13. package/dist/lib/ExtensionsWebSocket.js +110 -0
  14. package/dist/lib/__mocks__/config.d.ts +2 -0
  15. package/dist/lib/__mocks__/config.js +5 -0
  16. package/dist/lib/__mocks__/isExtensionFile.d.ts +5 -0
  17. package/dist/lib/__mocks__/isExtensionFile.js +11 -0
  18. package/dist/lib/__tests__/DevModeInterface.spec.d.ts +1 -0
  19. package/dist/lib/__tests__/DevModeInterface.spec.js +155 -0
  20. package/dist/lib/__tests__/DevModeParentInterface.spec.d.ts +1 -0
  21. package/dist/lib/__tests__/DevModeParentInterface.spec.js +179 -0
  22. package/dist/lib/__tests__/DevModeUnifiedInterface.spec.d.ts +1 -0
  23. package/dist/lib/__tests__/DevModeUnifiedInterface.spec.js +236 -0
  24. package/dist/lib/__tests__/ExtensionsWebSocket.spec.d.ts +1 -0
  25. package/dist/lib/__tests__/ExtensionsWebSocket.spec.js +304 -0
  26. package/dist/lib/__tests__/ast.spec.d.ts +1 -0
  27. package/dist/lib/__tests__/ast.spec.js +737 -0
  28. package/dist/lib/__tests__/build.spec.d.ts +1 -0
  29. package/dist/lib/__tests__/build.spec.js +159 -0
  30. package/dist/lib/__tests__/config.spec.d.ts +1 -0
  31. package/dist/lib/__tests__/config.spec.js +291 -0
  32. package/dist/lib/__tests__/dev.spec.d.ts +1 -0
  33. package/dist/lib/__tests__/dev.spec.js +80 -0
  34. package/dist/lib/__tests__/extensionsService.spec.d.ts +1 -0
  35. package/dist/lib/__tests__/extensionsService.spec.js +150 -0
  36. package/dist/lib/__tests__/factories.d.ts +48 -0
  37. package/dist/lib/__tests__/factories.js +32 -0
  38. package/dist/lib/__tests__/fixtures/extensionConfig.d.ts +182 -0
  39. package/dist/lib/__tests__/fixtures/extensionConfig.js +304 -0
  40. package/dist/lib/__tests__/fixtures/urls.d.ts +4 -0
  41. package/dist/lib/__tests__/fixtures/urls.js +4 -0
  42. package/dist/lib/__tests__/parsing-utils.spec.d.ts +1 -0
  43. package/dist/lib/__tests__/parsing-utils.spec.js +467 -0
  44. package/dist/lib/__tests__/plugins/codeBlockingPlugin.spec.d.ts +1 -0
  45. package/dist/lib/__tests__/plugins/codeBlockingPlugin.spec.js +112 -0
  46. package/dist/lib/__tests__/plugins/codeCheckingPlugin.spec.d.ts +1 -0
  47. package/dist/lib/__tests__/plugins/codeCheckingPlugin.spec.js +73 -0
  48. package/dist/lib/__tests__/plugins/devBuildPlugin.spec.d.ts +1 -0
  49. package/dist/lib/__tests__/plugins/devBuildPlugin.spec.js +256 -0
  50. package/dist/lib/__tests__/plugins/friendlyLoggingPlugin.spec.d.ts +1 -0
  51. package/dist/lib/__tests__/plugins/friendlyLoggingPlugin.spec.js +65 -0
  52. package/dist/lib/__tests__/plugins/manifestPlugin.spec.d.ts +1 -0
  53. package/dist/lib/__tests__/plugins/manifestPlugin.spec.js +455 -0
  54. package/dist/lib/__tests__/plugins/relevantModulesPlugin.spec.d.ts +1 -0
  55. package/dist/lib/__tests__/plugins/relevantModulesPlugin.spec.js +81 -0
  56. package/dist/lib/__tests__/server.spec.d.ts +1 -0
  57. package/dist/lib/__tests__/server.spec.js +152 -0
  58. package/dist/lib/__tests__/test-utils/ast.d.ts +1 -0
  59. package/dist/lib/__tests__/test-utils/ast.js +4 -0
  60. package/dist/lib/__tests__/utils.spec.d.ts +1 -0
  61. package/dist/lib/__tests__/utils.spec.js +176 -0
  62. package/dist/lib/ast.d.ts +1 -1
  63. package/dist/lib/ast.js +22 -29
  64. package/dist/lib/bin/cli.js +52 -72
  65. package/dist/lib/build.d.ts +1 -1
  66. package/dist/lib/build.js +60 -78
  67. package/dist/lib/config.d.ts +1 -1
  68. package/dist/lib/config.js +31 -34
  69. package/dist/lib/constants.d.ts +0 -2
  70. package/dist/lib/constants.js +20 -27
  71. package/dist/lib/dev.d.ts +1 -1
  72. package/dist/lib/dev.js +52 -69
  73. package/dist/lib/extensionsService.d.ts +1 -1
  74. package/dist/lib/extensionsService.js +21 -15
  75. package/dist/lib/parsing-utils.d.ts +1 -1
  76. package/dist/lib/parsing-utils.js +7 -11
  77. package/dist/lib/plugins/codeBlockingPlugin.d.ts +1 -1
  78. package/dist/lib/plugins/codeBlockingPlugin.js +5 -8
  79. package/dist/lib/plugins/codeCheckingPlugin.d.ts +1 -1
  80. package/dist/lib/plugins/codeCheckingPlugin.js +4 -9
  81. package/dist/lib/plugins/devBuildPlugin.d.ts +2 -2
  82. package/dist/lib/plugins/devBuildPlugin.js +74 -99
  83. package/dist/lib/plugins/friendlyLoggingPlugin.d.ts +2 -2
  84. package/dist/lib/plugins/friendlyLoggingPlugin.js +4 -12
  85. package/dist/lib/plugins/manifestPlugin.d.ts +1 -1
  86. package/dist/lib/plugins/manifestPlugin.js +46 -26
  87. package/dist/lib/plugins/relevantModulesPlugin.d.ts +2 -2
  88. package/dist/lib/plugins/relevantModulesPlugin.js +4 -7
  89. package/dist/lib/server.d.ts +7 -2
  90. package/dist/lib/server.js +85 -84
  91. package/dist/lib/types.d.ts +1 -1
  92. package/dist/lib/types.js +4 -7
  93. package/dist/lib/utils.d.ts +1 -1
  94. package/dist/lib/utils.js +23 -40
  95. package/package.json +44 -31
@@ -0,0 +1,152 @@
1
+ import { afterEach, describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import * as devServer from '@hubspot/app-functions-dev-server';
3
+ import startDevServer from "../server.js";
4
+ import { DevServerState } from "../DevServerState.js";
5
+ import { createMockLogger, createDevServerConfig, createMockViteDevServer, } from "./factories.js";
6
+ const useMock = vi.fn();
7
+ vi.mock('@hubspot/app-functions-dev-server', () => ({
8
+ AppProxyService: vi.fn(() => vi.fn((req, res, next) => next())),
9
+ AppFunctionExecutionService: vi.fn(() => vi.fn((req, res, next) => next())),
10
+ }));
11
+ vi.mock('express', () => {
12
+ const expressMock = () => ({
13
+ use: useMock,
14
+ get: vi.fn(),
15
+ listen: (__, callback) => {
16
+ // simulate async listen
17
+ const serverMock = {
18
+ on: vi.fn(function (event) {
19
+ if (event === 'error') {
20
+ // Don't call error handler in tests
21
+ }
22
+ return this;
23
+ }),
24
+ close: vi.fn((cb) => cb && cb()),
25
+ };
26
+ setTimeout(callback, 1);
27
+ return serverMock;
28
+ },
29
+ });
30
+ expressMock.static = vi.fn(() => vi.fn());
31
+ return { default: expressMock };
32
+ });
33
+ describe('server', () => {
34
+ let logger;
35
+ let devServerConfig;
36
+ beforeEach(() => {
37
+ logger = createMockLogger();
38
+ devServerConfig = createDevServerConfig(logger);
39
+ });
40
+ afterEach(() => {
41
+ vi.resetAllMocks();
42
+ });
43
+ describe('startDevServer', () => {
44
+ beforeEach(() => {
45
+ useMock.mockClear();
46
+ vi.mocked(devServer.AppFunctionExecutionService).mockReturnValue(vi.fn());
47
+ vi.mocked(devServer.AppProxyService).mockReturnValue(vi.fn());
48
+ vi.clearAllMocks();
49
+ });
50
+ it('should add the AppProxyService middleware when localDevUrlMapping is provided', async () => {
51
+ const devServerState = new DevServerState({
52
+ ...devServerConfig,
53
+ localDevUrlMapping: {
54
+ 'https://inbound.com': 'http://localhost',
55
+ },
56
+ });
57
+ await startDevServer({
58
+ devServerState,
59
+ viteDevServer: createMockViteDevServer(),
60
+ });
61
+ expect(useMock).toHaveBeenNthCalledWith(3, '/api/crm-extensibility/execution/internal/v3', expect.any(Function),
62
+ // This is the AppProxyService middleware
63
+ expect.any(Function));
64
+ expect(devServer.AppProxyService).toHaveBeenCalledTimes(1);
65
+ expect(devServer.AppProxyService).toHaveBeenCalledWith({
66
+ accountId: devServerConfig.accountId,
67
+ allowedUrls: [],
68
+ localDevUrlMapping: devServerState.localDevUrlMapping,
69
+ logger: devServerState.logger,
70
+ });
71
+ });
72
+ it('should not add the AppProxyService middleware when the localDevUrlMapping is empty', async () => {
73
+ const devServerState = new DevServerState({
74
+ ...devServerConfig,
75
+ localDevUrlMapping: {},
76
+ });
77
+ await startDevServer({
78
+ devServerState,
79
+ viteDevServer: createMockViteDevServer(),
80
+ });
81
+ expect(useMock).toHaveBeenNthCalledWith(3, '/api/crm-extensibility/execution/internal/v3', expect.any(Function));
82
+ expect(devServer.AppProxyService).toHaveBeenCalledTimes(0);
83
+ });
84
+ it('should not add the AppProxyService middleware when localDevUrlMapping is not provided', async () => {
85
+ const devServerState = new DevServerState({
86
+ ...devServerConfig,
87
+ localDevUrlMapping: undefined,
88
+ });
89
+ await startDevServer({
90
+ devServerState,
91
+ viteDevServer: createMockViteDevServer(),
92
+ });
93
+ expect(useMock).toHaveBeenNthCalledWith(3, '/api/crm-extensibility/execution/internal/v3', expect.any(Function));
94
+ expect(devServer.AppProxyService).toHaveBeenCalledTimes(0);
95
+ });
96
+ it('should add the AppFunctionExecutionService middleware if is a private app', async () => {
97
+ const devServerState = new DevServerState({
98
+ ...devServerConfig,
99
+ localDevUrlMapping: {
100
+ 'https://inbound.com': 'http://localhost',
101
+ },
102
+ });
103
+ await startDevServer({
104
+ devServerState,
105
+ viteDevServer: createMockViteDevServer(),
106
+ });
107
+ expect(devServer.AppFunctionExecutionService).toHaveBeenCalledTimes(1);
108
+ });
109
+ it('should not add the AppFunctionExecutionService middleware if is a public app', async () => {
110
+ const devServerState = new DevServerState({
111
+ ...devServerConfig,
112
+ appConfig: { isPublicApp: true },
113
+ localDevUrlMapping: {
114
+ 'https://inbound.com': 'http://localhost',
115
+ },
116
+ });
117
+ await startDevServer({
118
+ devServerState,
119
+ viteDevServer: createMockViteDevServer(),
120
+ });
121
+ expect(devServer.AppFunctionExecutionService).not.toHaveBeenCalled();
122
+ });
123
+ it('should return httpServer and shutdown function', async () => {
124
+ const devServerState = new DevServerState(devServerConfig);
125
+ const result = await startDevServer({
126
+ devServerState,
127
+ viteDevServer: createMockViteDevServer(),
128
+ });
129
+ expect(result).toHaveProperty('httpServer');
130
+ expect(result).toHaveProperty('shutdown');
131
+ expect(typeof result.shutdown).toBe('function');
132
+ });
133
+ it('should initialize ExtensionsWebSocket on devServerState', async () => {
134
+ const devServerState = new DevServerState(devServerConfig);
135
+ await startDevServer({
136
+ devServerState,
137
+ viteDevServer: createMockViteDevServer(),
138
+ });
139
+ expect(devServerState.extensionsWebSocket).toBeDefined();
140
+ });
141
+ it('should trigger WebSocket setup after initialization', async () => {
142
+ const triggerSpy = vi.spyOn(DevServerState.prototype, 'triggerWebSocketSetup');
143
+ const devServerState = new DevServerState(devServerConfig);
144
+ await startDevServer({
145
+ devServerState,
146
+ viteDevServer: createMockViteDevServer(),
147
+ });
148
+ expect(triggerSpy).toHaveBeenCalledTimes(1);
149
+ triggerSpy.mockRestore();
150
+ });
151
+ });
152
+ });
@@ -0,0 +1 @@
1
+ export declare const localParse: (code: string) => import("acorn").Program;
@@ -0,0 +1,4 @@
1
+ import { parse } from 'acorn';
2
+ export const localParse = (code) => {
3
+ return parse(code, { ecmaVersion: 'latest', sourceType: 'module' });
4
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,176 @@
1
+ import { describe, it, expect, vi, beforeAll, afterAll, beforeEach, afterEach, } from 'vitest';
2
+ import { OUTPUT_DIR } from "../constants.js";
3
+ import { getUrlSafeFileName, stripAnsiColorCodes, loadManifest, buildSourceId, isNodeModule, isExtensionFile, generateHash, } from "../utils.js";
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ describe('utils', () => {
7
+ describe('getUrlSafeFileName', () => {
8
+ it('should uri encode the filename', () => {
9
+ const fileName = 'test File ?@#$%^&*()Name who would name a file like this!';
10
+ const actual = getUrlSafeFileName(`${fileName}.tsx`);
11
+ expect(actual).toEqual(`${encodeURIComponent(fileName)}.js`);
12
+ });
13
+ });
14
+ describe('stripAnsiColorCodes', () => {
15
+ it('should strip all color codes out of a string', () => {
16
+ const withColorCodes = '\x1B[33mThis is a test\x1B[39m';
17
+ const actual = stripAnsiColorCodes(withColorCodes);
18
+ expect(actual).toEqual('This is a test');
19
+ });
20
+ it('should return null if the provided string is null', () => {
21
+ const actual = stripAnsiColorCodes(undefined);
22
+ expect(actual).toEqual(null);
23
+ });
24
+ it('should return null if the provided string is undefined', () => {
25
+ const actual = stripAnsiColorCodes(undefined);
26
+ expect(actual).toEqual(null);
27
+ });
28
+ it('should return null if the provided string is empty', () => {
29
+ const actual = stripAnsiColorCodes('');
30
+ expect(actual).toEqual(null);
31
+ });
32
+ });
33
+ describe('loadManifest', () => {
34
+ beforeEach(() => {
35
+ vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify({
36
+ manifest: true,
37
+ }));
38
+ });
39
+ afterEach(() => {
40
+ vi.restoreAllMocks();
41
+ });
42
+ it('should return the manifest file when it is able to load it from disk', () => {
43
+ const actual = loadManifest(OUTPUT_DIR, 'test-file-name');
44
+ expect(fs.readFileSync).toHaveBeenCalledTimes(1);
45
+ expect(actual).toStrictEqual({
46
+ manifest: true,
47
+ });
48
+ });
49
+ it('should return an empty object when it fails to load from disk', () => {
50
+ vi.spyOn(fs, 'readFileSync').mockImplementationOnce(() => {
51
+ throw new Error('OH NO!');
52
+ });
53
+ const actual = loadManifest(OUTPUT_DIR, 'test-file-name');
54
+ expect(actual).toStrictEqual({});
55
+ });
56
+ });
57
+ describe('buildSourceId', () => {
58
+ it('should return null when there is no uid in app config', () => {
59
+ expect(buildSourceId({}, { data: { uid: 'some-uid' } })).toBe(null);
60
+ });
61
+ it('should return null when there is no uid in extension config', () => {
62
+ expect(buildSourceId({ uid: 'some-uid' }, { data: {} })).toBe(null);
63
+ });
64
+ it('should return a valid sourceId', () => {
65
+ const appUID = 'app-uid';
66
+ const extensionUID = 'extension-uid';
67
+ expect(buildSourceId({ uid: appUID }, { data: { uid: extensionUID } })).toBe(`${appUID}::${extensionUID}`);
68
+ });
69
+ });
70
+ describe('isNodeModule', () => {
71
+ it('should return false if the path is undefined', () => {
72
+ expect(isNodeModule(undefined)).toBe(false);
73
+ });
74
+ it('should return false if the path is not a node_modules', () => {
75
+ expect(isNodeModule('foo.js')).toBe(false);
76
+ });
77
+ it('should return true if the path is a node_modules', () => {
78
+ expect(isNodeModule('node_modules/foo.js')).toBe(true);
79
+ });
80
+ });
81
+ describe('isExtensionFile', () => {
82
+ /**
83
+ * This function relies on the file system. Mocking doesn't allow us to fully test all scenarios.
84
+ * In order to effectively test it, we need to create a temporary directory structure.
85
+ * Being thorough here allows us to safely mock it elsewhere.
86
+ */
87
+ const tempDir = path.join(__dirname, 'temp');
88
+ const extensionDir = path.join(tempDir, 'test/path/extension');
89
+ const indexFile = path.join(extensionDir, 'index.js');
90
+ const nestedFile = path.join(extensionDir, 'src/file.ts');
91
+ const otherFile = path.join(tempDir, 'different/path/file.ts');
92
+ const relativeOtherFile = path.join(tempDir, '../different/path/file.ts');
93
+ beforeAll(() => {
94
+ fs.mkdirSync(extensionDir, { recursive: true });
95
+ fs.mkdirSync(path.dirname(nestedFile), { recursive: true });
96
+ fs.mkdirSync(path.dirname(otherFile), { recursive: true });
97
+ fs.mkdirSync(path.dirname(relativeOtherFile), { recursive: true });
98
+ fs.writeFileSync(otherFile, '');
99
+ fs.writeFileSync(nestedFile, '');
100
+ fs.writeFileSync(indexFile, '');
101
+ fs.writeFileSync(relativeOtherFile, '');
102
+ });
103
+ afterAll(() => {
104
+ fs.rmSync(tempDir, { recursive: true, force: true });
105
+ fs.rmSync(relativeOtherFile, { recursive: true, force: true });
106
+ });
107
+ it('should return false if filepath is undefined', () => {
108
+ expect(isExtensionFile(undefined, extensionDir)).toBe(false);
109
+ });
110
+ it('should return true if file is within extension path', () => {
111
+ expect(isExtensionFile(nestedFile, extensionDir)).toBe(true);
112
+ expect(isExtensionFile(indexFile, extensionDir)).toBe(true);
113
+ });
114
+ it('should return false if file is outside extension path', () => {
115
+ expect(isExtensionFile(otherFile, extensionDir)).toBe(false);
116
+ });
117
+ it('should handle relative paths correctly', () => {
118
+ const originalCwd = process.cwd();
119
+ process.chdir(tempDir);
120
+ expect(isExtensionFile('./test/path/extension/src/file.ts', './test/path/extension')).toBe(true);
121
+ expect(isExtensionFile('../different/path/file.ts', './test/path/extension')).toBe(false);
122
+ process.chdir(originalCwd);
123
+ });
124
+ it('should return true if the extension path is nested within the provided path', () => {
125
+ const originalCwd = process.cwd();
126
+ process.chdir(tempDir);
127
+ expect(isExtensionFile('../temp/test/path/extension/src/file.ts', './test/path/extension/')).toBe(true);
128
+ process.chdir(originalCwd);
129
+ });
130
+ });
131
+ describe('generateHash', () => {
132
+ it('should generate consistent hashes for same inputs', () => {
133
+ const hash1 = generateHash('test', ['a', 'b'], { foo: 'bar' });
134
+ const hash2 = generateHash('test', ['a', 'b'], { foo: 'bar' });
135
+ expect(hash1).toBe(hash2);
136
+ });
137
+ it('should handle different types of arguments', () => {
138
+ expect(generateHash('test')).toBe('364492');
139
+ expect(generateHash(123)).toBe('be32');
140
+ expect(generateHash(['a', 'b'])).toBe('171f6');
141
+ expect(generateHash({ foo: 'bar' })).toBe('4a4201ac');
142
+ expect(generateHash(null)).toBe('33c587');
143
+ expect(generateHash(undefined)).toBe('42201c7f');
144
+ });
145
+ it('should generate the correct hash for multiple arguments', () => {
146
+ const hash1 = generateHash('arg1', ['foo', 'bar']);
147
+ const hash2 = generateHash('test', ['a', 'c', 'd', 'e']);
148
+ expect(hash1).toBe('1ec304f1');
149
+ expect(hash2).toBe('607ad458');
150
+ });
151
+ it('should normalize arrays regardless of order', () => {
152
+ const hash1 = generateHash(['a', 'b', 'c']);
153
+ const hash2 = generateHash(['c', 'a', 'b']);
154
+ expect(hash1).toBe(hash2);
155
+ });
156
+ it('should normalize objects regardless of key order', () => {
157
+ const hash1 = generateHash({ a: 1, b: 2 });
158
+ const hash2 = generateHash({ b: 2, a: 1 });
159
+ expect(hash1).toBe(hash2);
160
+ });
161
+ it('should return an empty string and log an error if an error is thrown', () => {
162
+ // Mock console.error to prevent it from logging to the console
163
+ const consoleErrorSpy = vi
164
+ .spyOn(console, 'error')
165
+ .mockImplementation(() => { });
166
+ // Create an argument that will cause an error.
167
+ const circularReference = {};
168
+ circularReference.self = circularReference;
169
+ const hash = generateHash(circularReference);
170
+ expect(hash).toBe('');
171
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Error generating hash: ', expect.any(TypeError));
172
+ // Restore console.error
173
+ consoleErrorSpy.mockRestore();
174
+ });
175
+ });
176
+ });
package/dist/lib/ast.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SourceCodeMetadata, SourceCodeChecks, Logger, NodeValue } from './types';
1
+ import { SourceCodeMetadata, SourceCodeChecks, Logger, NodeValue } from './types.ts';
2
2
  import { Program, Node } from 'estree';
3
3
  /**
4
4
  * We only support image imports that are within the extension directory.
package/dist/lib/ast.js CHANGED
@@ -1,16 +1,8 @@
1
- "use strict";
2
- /* eslint-disable hubspot-dev/no-unsupported-ts-syntax */
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod };
5
- };
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.checkForOutOfBoundsImageImports = checkForOutOfBoundsImageImports;
8
- exports.traverseAbstractSyntaxTree = traverseAbstractSyntaxTree;
9
- const path_1 = __importDefault(require("path"));
1
+ import path from 'path';
10
2
  // @ts-expect-error no type defs
11
- const estraverse_1 = require("estraverse");
12
- const utils_1 = require("./utils");
13
- const parsing_utils_1 = require("./parsing-utils");
3
+ import { traverse } from 'estraverse';
4
+ import { generateHash, isExtensionFile, isImage } from "./utils.js";
5
+ import { getValueFromNode, isFunctionInvoked, isIdentifierDefined, isVariableImported, } from "./parsing-utils.js";
14
6
  const PARSED_HOOKS = ['useCrmProperties', 'useAssociations'];
15
7
  function _checkForFunctionMetadata(node, parent, output, functionName) {
16
8
  if (!node) {
@@ -19,7 +11,7 @@ function _checkForFunctionMetadata(node, parent, output, functionName) {
19
11
  if (!output.functions[functionName]) {
20
12
  output.functions[functionName] = {};
21
13
  }
22
- if ((0, parsing_utils_1.isFunctionInvoked)(node, functionName)) {
14
+ if (isFunctionInvoked(node, functionName)) {
23
15
  output.functions[functionName].invoked = true;
24
16
  // If the function is invoked before being defined we will assume it is a global function
25
17
  output.functions[functionName].scope = output.functions[functionName]
@@ -27,8 +19,8 @@ function _checkForFunctionMetadata(node, parent, output, functionName) {
27
19
  ? 'Local'
28
20
  : 'Global';
29
21
  }
30
- else if ((0, parsing_utils_1.isIdentifierDefined)(node, parent, functionName) ||
31
- (0, parsing_utils_1.isVariableImported)(node, functionName)) {
22
+ else if (isIdentifierDefined(node, parent, functionName) ||
23
+ isVariableImported(node, functionName)) {
32
24
  output.functions[functionName].defined = true;
33
25
  }
34
26
  }
@@ -43,7 +35,7 @@ function _collectVariableDeclarations(node, state) {
43
35
  declaration.id.type === 'Identifier' &&
44
36
  declaration.init) {
45
37
  const variableName = declaration.id.name;
46
- const result = (0, parsing_utils_1.getValueFromNode)(declaration.init, state);
38
+ const result = getValueFromNode(declaration.init, state);
47
39
  if (result.status === 'SUCCESS') {
48
40
  state.variableDeclarations.set(variableName, result.nodeValue);
49
41
  }
@@ -54,7 +46,7 @@ function _collectVariableDeclarations(node, state) {
54
46
  if (node.type === 'AssignmentExpression' && node.left.type === 'Identifier') {
55
47
  const variableName = node.left.name;
56
48
  if (state.variableDeclarations.has(variableName)) {
57
- const result = (0, parsing_utils_1.getValueFromNode)(node.right, state);
49
+ const result = getValueFromNode(node.right, state);
58
50
  if (result.status === 'SUCCESS') {
59
51
  state.variableDeclarations.set(variableName, result.nodeValue);
60
52
  }
@@ -65,7 +57,7 @@ function _collectVariableDeclarations(node, state) {
65
57
  * We only support image imports that are within the extension directory.
66
58
  * This function will check if an image is out of bounds and collect any that are out of bounds, so we can warn the user before they run into build issues.
67
59
  */
68
- function checkForOutOfBoundsImageImports(node, output, extensionPath) {
60
+ export function checkForOutOfBoundsImageImports(node, output, extensionPath) {
69
61
  if (!node) {
70
62
  return;
71
63
  }
@@ -73,12 +65,12 @@ function checkForOutOfBoundsImageImports(node, output, extensionPath) {
73
65
  typeof node.source.value === 'string') {
74
66
  const importPath = node.source.value;
75
67
  // Only do the check for images.
76
- if (!(0, utils_1.isImage)(importPath)) {
68
+ if (!isImage(importPath)) {
77
69
  return;
78
70
  }
79
71
  // Build the full path to the import, using the extension path as the base.
80
- const absoluteImportPath = path_1.default.resolve(extensionPath, importPath);
81
- if (!(0, utils_1.isExtensionFile)(absoluteImportPath, extensionPath)) {
72
+ const absoluteImportPath = path.resolve(extensionPath, importPath);
73
+ if (!isExtensionFile(absoluteImportPath, extensionPath)) {
82
74
  output.badImports.push(importPath);
83
75
  }
84
76
  }
@@ -91,7 +83,7 @@ function _processCrmPropertiesHook(node, output) {
91
83
  const optionsNode = node.arguments[1];
92
84
  const requestedProperties = [];
93
85
  const propertiesResult = propertiesNode
94
- ? (0, parsing_utils_1.getValueFromNode)(propertiesNode, output)
86
+ ? getValueFromNode(propertiesNode, output)
95
87
  : null;
96
88
  if (propertiesResult &&
97
89
  propertiesResult.status === 'SUCCESS' &&
@@ -105,7 +97,7 @@ function _processCrmPropertiesHook(node, output) {
105
97
  if (requestedProperties.length > 0) {
106
98
  let options = {};
107
99
  const optionsResult = optionsNode
108
- ? (0, parsing_utils_1.getValueFromNode)(optionsNode, output)
100
+ ? getValueFromNode(optionsNode, output)
109
101
  : null;
110
102
  if (optionsResult &&
111
103
  optionsResult.status === 'SUCCESS' &&
@@ -116,7 +108,7 @@ function _processCrmPropertiesHook(node, output) {
116
108
  options = optionsResult.nodeValue;
117
109
  }
118
110
  output.dataDependencies.dependencies.push({
119
- referenceId: (0, utils_1.generateHash)(propertyType, requestedProperties),
111
+ referenceId: generateHash(propertyType, requestedProperties),
120
112
  properties: {
121
113
  type: propertyType,
122
114
  recordProperties: requestedProperties,
@@ -132,7 +124,7 @@ function _processAssociationsHook(node, output) {
132
124
  const requestNode = node.arguments[0];
133
125
  const optionsNode = node.arguments[1];
134
126
  const requestResult = requestNode
135
- ? (0, parsing_utils_1.getValueFromNode)(requestNode, output)
127
+ ? getValueFromNode(requestNode, output)
136
128
  : null;
137
129
  if (!requestResult ||
138
130
  requestResult.status === 'FAIL' ||
@@ -158,7 +150,7 @@ function _processAssociationsHook(node, output) {
158
150
  const paginationOptions = {};
159
151
  const otherOptions = {};
160
152
  const optionsResult = optionsNode
161
- ? (0, parsing_utils_1.getValueFromNode)(optionsNode, output)
153
+ ? getValueFromNode(optionsNode, output)
162
154
  : null;
163
155
  if (optionsResult &&
164
156
  optionsResult.status === 'SUCCESS' &&
@@ -179,7 +171,7 @@ function _processAssociationsHook(node, output) {
179
171
  }
180
172
  const sortedPropertiesForHash = [...propertiesArray].sort();
181
173
  output.dataDependencies.dependencies.push({
182
- referenceId: (0, utils_1.generateHash)(propertyType, toObjectTypeId, sortedPropertiesForHash.join('-')),
174
+ referenceId: generateHash(propertyType, toObjectTypeId, sortedPropertiesForHash.join('-')),
183
175
  properties: {
184
176
  type: propertyType,
185
177
  toObjectTypeId,
@@ -206,6 +198,7 @@ function _collectDataDependencies(node, output, logger) {
206
198
  node.specifiers.forEach((specifier) => {
207
199
  // If the specifier is an ImportSpecifier and the imported name is one of our tracked hooks, we will track it.
208
200
  if (specifier.type === 'ImportSpecifier' &&
201
+ specifier.imported.type === 'Identifier' &&
209
202
  PARSED_HOOKS.includes(specifier.imported.name)) {
210
203
  // The local name is the name the hook is imported as in the file, and the imported name is the original name of the hook.
211
204
  output.dataDependencies.importedHooks[`${specifier.local.name}`] =
@@ -253,7 +246,7 @@ function _collectDataDependencies(node, output, logger) {
253
246
  }
254
247
  // Traverses an ESTree as defined by the EsTree spec https://github.com/estree/estree
255
248
  // Uses the checks array to search the source code for matches
256
- function traverseAbstractSyntaxTree(ast, checks, extensionPath, logger) {
249
+ export function traverseAbstractSyntaxTree(ast, checks, extensionPath, logger) {
257
250
  const state = {
258
251
  functions: {},
259
252
  badImports: [],
@@ -264,7 +257,7 @@ function traverseAbstractSyntaxTree(ast, checks, extensionPath, logger) {
264
257
  variableDeclarations: new Map(),
265
258
  };
266
259
  try {
267
- (0, estraverse_1.traverse)(ast, {
260
+ traverse(ast, {
268
261
  enter(node, parent) {
269
262
  try {
270
263
  checks.forEach((check) => {