@hubspot/ui-extensions-dev-server 0.9.4 → 0.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/DevModeUnifiedInterface.js +12 -2
- package/dist/lib/ast.d.ts +0 -6
- package/dist/lib/ast.js +128 -258
- package/dist/lib/constants.d.ts +1 -0
- package/dist/lib/constants.js +7 -2
- package/dist/lib/parsing-utils.d.ts +31 -0
- package/dist/lib/parsing-utils.js +294 -0
- package/dist/lib/types.d.ts +14 -3
- package/dist/lib/types.js +1 -0
- package/package.json +2 -2
|
@@ -20,6 +20,14 @@ const constants_1 = require("./constants");
|
|
|
20
20
|
const types_1 = require("./types");
|
|
21
21
|
const DevModeParentInterface_1 = require("./DevModeParentInterface");
|
|
22
22
|
const utils_1 = require("./utils");
|
|
23
|
+
function getComponentName(componentType) {
|
|
24
|
+
if (componentType === types_1.UnifiedComponentTypes.SETTINGS) {
|
|
25
|
+
return 'Settings';
|
|
26
|
+
}
|
|
27
|
+
if (componentType === types_1.UnifiedComponentTypes.PAGE) {
|
|
28
|
+
return 'App Home';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
23
31
|
class DevModeUnifiedInterface extends DevModeParentInterface_1.DevModeParentInterface {
|
|
24
32
|
_generateAppExtensionMappings(components) {
|
|
25
33
|
var _a, _b, _c, _d;
|
|
@@ -62,12 +70,14 @@ class DevModeUnifiedInterface extends DevModeParentInterface_1.DevModeParentInte
|
|
|
62
70
|
});
|
|
63
71
|
// Build the extension mapping data
|
|
64
72
|
extensionUids.forEach((extensionUid) => {
|
|
73
|
+
var _a;
|
|
65
74
|
const extension = components[extensionUid];
|
|
66
75
|
// Update the extension entrypoint to be "relative" to the extension directory (eg from /app/card/card.jsx to ./card.jsx)
|
|
67
76
|
extension.config.entrypoint = `./${path_1.default.basename(extension.config.entrypoint)}`;
|
|
68
77
|
// Hardcode the extension name if this is a settings extension (the user does not provide a name for their settings card).
|
|
69
|
-
if (extension.componentType === types_1.UnifiedComponentTypes.SETTINGS
|
|
70
|
-
extension.
|
|
78
|
+
if (extension.componentType === types_1.UnifiedComponentTypes.SETTINGS ||
|
|
79
|
+
extension.componentType === types_1.UnifiedComponentTypes.PAGE) {
|
|
80
|
+
extension.config.name = (_a = getComponentName(extension.componentType)) !== null && _a !== void 0 ? _a : '';
|
|
71
81
|
}
|
|
72
82
|
// Add them to the app config
|
|
73
83
|
switch (extension.componentType) {
|
package/dist/lib/ast.d.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { SourceCodeMetadata, SourceCodeChecks, Logger, NodeValue } from './types';
|
|
2
2
|
import { Program, Node } from 'estree';
|
|
3
|
-
/**
|
|
4
|
-
* This is a simple utility function to rebuild the value from a node.
|
|
5
|
-
* It'll work for simple stuff, but it's likely to fail in complicated cases.
|
|
6
|
-
* Use with caution!
|
|
7
|
-
*/
|
|
8
|
-
export declare function getValueFromNode(node: Node, state: SourceCodeMetadata): NodeValue;
|
|
9
3
|
/**
|
|
10
4
|
* We only support image imports that are within the extension directory.
|
|
11
5
|
* 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.
|
package/dist/lib/ast.js
CHANGED
|
@@ -4,36 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.traverseAbstractSyntaxTree = exports.checkForOutOfBoundsImageImports =
|
|
8
|
-
const UNSUPPORTED_SPREAD = Symbol('unsupported-spread');
|
|
7
|
+
exports.traverseAbstractSyntaxTree = exports.checkForOutOfBoundsImageImports = void 0;
|
|
9
8
|
const path_1 = __importDefault(require("path"));
|
|
10
9
|
// @ts-expect-error no type defs
|
|
11
10
|
const estraverse_1 = require("estraverse");
|
|
12
11
|
const utils_1 = require("./utils");
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
if (!node) {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
return ((node.type === 'ImportSpecifier' && node.imported.name === variableName) ||
|
|
19
|
-
(node.type === 'ImportDefaultSpecifier' &&
|
|
20
|
-
node.local.name === variableName) ||
|
|
21
|
-
(node.type === 'ImportNamespaceSpecifier' &&
|
|
22
|
-
node.local.name === variableName));
|
|
23
|
-
}
|
|
24
|
-
function _isIdentifierDefined(node, parent, name) {
|
|
25
|
-
if (parent &&
|
|
26
|
-
(parent.type === 'MemberExpression' || parent.type === 'CallExpression')) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
return node.type === 'Identifier' && node.name === name;
|
|
30
|
-
}
|
|
31
|
-
function _isFunctionInvoked(node, functionName) {
|
|
32
|
-
return (node.type === 'CallExpression' &&
|
|
33
|
-
node.callee &&
|
|
34
|
-
'name' in node.callee &&
|
|
35
|
-
node.callee.name === functionName);
|
|
36
|
-
}
|
|
12
|
+
const parsing_utils_1 = require("./parsing-utils");
|
|
13
|
+
const PARSED_HOOKS = ['useCrmProperties', 'useAssociations'];
|
|
37
14
|
function _checkForFunctionMetadata(node, parent, output, functionName) {
|
|
38
15
|
if (!node) {
|
|
39
16
|
return;
|
|
@@ -41,7 +18,7 @@ function _checkForFunctionMetadata(node, parent, output, functionName) {
|
|
|
41
18
|
if (!output.functions[functionName]) {
|
|
42
19
|
output.functions[functionName] = {};
|
|
43
20
|
}
|
|
44
|
-
if (
|
|
21
|
+
if ((0, parsing_utils_1.isFunctionInvoked)(node, functionName)) {
|
|
45
22
|
output.functions[functionName].invoked = true;
|
|
46
23
|
// If the function is invoked before being defined we will assume it is a global function
|
|
47
24
|
output.functions[functionName].scope = output.functions[functionName]
|
|
@@ -49,8 +26,8 @@ function _checkForFunctionMetadata(node, parent, output, functionName) {
|
|
|
49
26
|
? 'Local'
|
|
50
27
|
: 'Global';
|
|
51
28
|
}
|
|
52
|
-
else if (
|
|
53
|
-
|
|
29
|
+
else if ((0, parsing_utils_1.isIdentifierDefined)(node, parent, functionName) ||
|
|
30
|
+
(0, parsing_utils_1.isVariableImported)(node, functionName)) {
|
|
54
31
|
output.functions[functionName].defined = true;
|
|
55
32
|
}
|
|
56
33
|
}
|
|
@@ -65,8 +42,10 @@ function _collectVariableDeclarations(node, state) {
|
|
|
65
42
|
declaration.id.type === 'Identifier' &&
|
|
66
43
|
declaration.init) {
|
|
67
44
|
const variableName = declaration.id.name;
|
|
68
|
-
const
|
|
69
|
-
|
|
45
|
+
const result = (0, parsing_utils_1.getValueFromNode)(declaration.init, state);
|
|
46
|
+
if (result.status === 'SUCCESS') {
|
|
47
|
+
state.variableDeclarations.set(variableName, result.nodeValue);
|
|
48
|
+
}
|
|
70
49
|
}
|
|
71
50
|
});
|
|
72
51
|
}
|
|
@@ -74,185 +53,13 @@ function _collectVariableDeclarations(node, state) {
|
|
|
74
53
|
if (node.type === 'AssignmentExpression' && node.left.type === 'Identifier') {
|
|
75
54
|
const variableName = node.left.name;
|
|
76
55
|
if (state.variableDeclarations.has(variableName)) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* This is a simple utility function to rebuild the value from a node.
|
|
84
|
-
* It'll work for simple stuff, but it's likely to fail in complicated cases.
|
|
85
|
-
* Use with caution!
|
|
86
|
-
*/
|
|
87
|
-
function getValueFromNode(node, state) {
|
|
88
|
-
switch (node.type) {
|
|
89
|
-
case 'Literal':
|
|
90
|
-
return node.value;
|
|
91
|
-
case 'Identifier': {
|
|
92
|
-
const name = node.name;
|
|
93
|
-
switch (name) {
|
|
94
|
-
case 'undefined':
|
|
95
|
-
return undefined;
|
|
96
|
-
case 'NaN':
|
|
97
|
-
return NaN;
|
|
98
|
-
case 'Infinity':
|
|
99
|
-
return Infinity;
|
|
100
|
-
default:
|
|
101
|
-
if (state.variableDeclarations.has(name)) {
|
|
102
|
-
return state.variableDeclarations.get(name);
|
|
103
|
-
}
|
|
104
|
-
return name;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
case 'ArrayExpression': {
|
|
108
|
-
const arrayValue = [];
|
|
109
|
-
if (node.elements.length === 0) {
|
|
110
|
-
return arrayValue;
|
|
111
|
-
}
|
|
112
|
-
// Arrays have to be built from their elements, to handle special cases like nested arrays from spread operators.
|
|
113
|
-
node.elements.forEach((element) => {
|
|
114
|
-
if (typeof element === 'object' && element !== null) {
|
|
115
|
-
if (element.type === 'SpreadElement') {
|
|
116
|
-
const value = getValueFromNode(element, state);
|
|
117
|
-
if (Array.isArray(value)) {
|
|
118
|
-
arrayValue.push(...value);
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
arrayValue.push(value);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
const value = getValueFromNode(element, state);
|
|
126
|
-
arrayValue.push(value);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
arrayValue.push(element);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
return arrayValue;
|
|
134
|
-
}
|
|
135
|
-
case 'ObjectExpression': {
|
|
136
|
-
const obj = {};
|
|
137
|
-
node.properties.forEach((prop) => {
|
|
138
|
-
switch (prop.type) {
|
|
139
|
-
case 'Property': {
|
|
140
|
-
const property = prop;
|
|
141
|
-
let key = undefined;
|
|
142
|
-
if (property.key.type === 'Identifier') {
|
|
143
|
-
key = property.key.name;
|
|
144
|
-
}
|
|
145
|
-
else if (property.key.type === 'Literal') {
|
|
146
|
-
key = String(property.key.value);
|
|
147
|
-
}
|
|
148
|
-
if (key) {
|
|
149
|
-
obj[key] = getValueFromNode(property.value, state);
|
|
150
|
-
}
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
153
|
-
case 'SpreadElement': {
|
|
154
|
-
const spreadValue = getValueFromNode(prop, state);
|
|
155
|
-
if (spreadValue !== UNSUPPORTED_SPREAD &&
|
|
156
|
-
spreadValue &&
|
|
157
|
-
typeof spreadValue === 'object') {
|
|
158
|
-
Object.assign(obj, spreadValue);
|
|
159
|
-
}
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
default:
|
|
163
|
-
// Ignore unsupported property types, as we don't have a key for them.
|
|
164
|
-
// This could be a computed property or something else we don't handle.
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
return obj;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Spread elements are a bit tricky. They can be used to directly spread an array or object,
|
|
172
|
-
* or they can be used to spread a variable that is defined elsewhere. Our strategy is to return
|
|
173
|
-
* whatever element should be spread, and then handle the spreading in the parent array or object.
|
|
174
|
-
*
|
|
175
|
-
* There are also trickier cases we don't handle, like spreading a function call that returns an
|
|
176
|
-
* array or object. When the spread element is unsupported, we return a special symbol.
|
|
177
|
-
*/
|
|
178
|
-
case 'SpreadElement':
|
|
179
|
-
if (node.argument) {
|
|
180
|
-
if (node.argument.type === 'Identifier' && node.argument.name) {
|
|
181
|
-
return state.variableDeclarations.get(node.argument.name) || null;
|
|
182
|
-
}
|
|
183
|
-
else if (node.argument.type === 'ArrayExpression' ||
|
|
184
|
-
node.argument.type === 'ObjectExpression') {
|
|
185
|
-
return getValueFromNode(node.argument, state);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return UNSUPPORTED_SPREAD;
|
|
189
|
-
/**
|
|
190
|
-
* Template literals are built of an alternating sequence of static
|
|
191
|
-
* strings and expressions. We will concatenate the static strings and
|
|
192
|
-
* evaluate the expressions to build the final string.
|
|
193
|
-
*/
|
|
194
|
-
case 'TemplateLiteral': {
|
|
195
|
-
let result = '';
|
|
196
|
-
if (node.expressions && node.quasis) {
|
|
197
|
-
const { quasis, expressions } = node;
|
|
198
|
-
for (let i = 0; i < quasis.length; i++) {
|
|
199
|
-
// Prefer cooked value if available, otherwise use raw.
|
|
200
|
-
result += quasis[i].value.cooked || quasis[i].value.raw;
|
|
201
|
-
if (i < expressions.length) {
|
|
202
|
-
const expression = expressions[i];
|
|
203
|
-
const expressionValue = getValueFromNode(expression, state);
|
|
204
|
-
if (expressionValue === null ||
|
|
205
|
-
expressionValue === undefined ||
|
|
206
|
-
typeof expressionValue === 'string' ||
|
|
207
|
-
typeof expressionValue === 'number' ||
|
|
208
|
-
typeof expressionValue === 'boolean') {
|
|
209
|
-
result += String(expressionValue);
|
|
210
|
-
}
|
|
211
|
-
else if (Array.isArray(expressionValue)) {
|
|
212
|
-
result += expressionValue.join(',');
|
|
213
|
-
}
|
|
214
|
-
else if (typeof expressionValue === 'object') {
|
|
215
|
-
result += '[object Object]';
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
return result;
|
|
221
|
-
}
|
|
222
|
-
case 'UnaryExpression': {
|
|
223
|
-
const arg = getValueFromNode(node.argument, state);
|
|
224
|
-
switch (node.operator) {
|
|
225
|
-
case '-':
|
|
226
|
-
return typeof arg === 'number' ? -arg : NaN;
|
|
227
|
-
case '+':
|
|
228
|
-
return typeof arg === 'number' ? +arg : NaN;
|
|
229
|
-
case '!':
|
|
230
|
-
return !arg;
|
|
231
|
-
case 'typeof':
|
|
232
|
-
return typeof arg;
|
|
233
|
-
default:
|
|
234
|
-
return undefined;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
// Member expressions are used to access properties of objects.
|
|
238
|
-
case 'MemberExpression': {
|
|
239
|
-
if (node.property.type === 'Identifier' && node.property.name) {
|
|
240
|
-
// We have to recursively get the value of the object, due to the way that nested objects are parsed.
|
|
241
|
-
const objectData = getValueFromNode(node.object, state);
|
|
242
|
-
if (objectData &&
|
|
243
|
-
typeof objectData === 'object' &&
|
|
244
|
-
!Array.isArray(objectData) &&
|
|
245
|
-
!(objectData instanceof RegExp)) {
|
|
246
|
-
return objectData[node.property.name];
|
|
247
|
-
}
|
|
56
|
+
const result = (0, parsing_utils_1.getValueFromNode)(node.right, state);
|
|
57
|
+
if (result.status === 'SUCCESS') {
|
|
58
|
+
state.variableDeclarations.set(variableName, result.nodeValue);
|
|
248
59
|
}
|
|
249
|
-
return undefined;
|
|
250
60
|
}
|
|
251
|
-
default:
|
|
252
|
-
return `Unsupported node type: ${node.type}`;
|
|
253
61
|
}
|
|
254
62
|
}
|
|
255
|
-
exports.getValueFromNode = getValueFromNode;
|
|
256
63
|
/**
|
|
257
64
|
* We only support image imports that are within the extension directory.
|
|
258
65
|
* 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.
|
|
@@ -276,6 +83,112 @@ function checkForOutOfBoundsImageImports(node, output, extensionPath) {
|
|
|
276
83
|
}
|
|
277
84
|
}
|
|
278
85
|
exports.checkForOutOfBoundsImageImports = checkForOutOfBoundsImageImports;
|
|
86
|
+
function _processCrmPropertiesHook(node, output) {
|
|
87
|
+
if (node.type !== 'CallExpression')
|
|
88
|
+
return;
|
|
89
|
+
const propertyType = 'CrmRecordProperties';
|
|
90
|
+
const propertiesNode = node.arguments[0];
|
|
91
|
+
const optionsNode = node.arguments[1];
|
|
92
|
+
const requestedProperties = [];
|
|
93
|
+
const propertiesResult = propertiesNode
|
|
94
|
+
? (0, parsing_utils_1.getValueFromNode)(propertiesNode, output)
|
|
95
|
+
: null;
|
|
96
|
+
if (propertiesResult &&
|
|
97
|
+
propertiesResult.status === 'SUCCESS' &&
|
|
98
|
+
Array.isArray(propertiesResult.nodeValue)) {
|
|
99
|
+
propertiesResult.nodeValue.forEach((val) => {
|
|
100
|
+
if (typeof val === 'string') {
|
|
101
|
+
requestedProperties.push(val);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (requestedProperties.length > 0) {
|
|
106
|
+
let options = {};
|
|
107
|
+
const optionsResult = optionsNode
|
|
108
|
+
? (0, parsing_utils_1.getValueFromNode)(optionsNode, output)
|
|
109
|
+
: null;
|
|
110
|
+
if (optionsResult &&
|
|
111
|
+
optionsResult.status === 'SUCCESS' &&
|
|
112
|
+
optionsResult.nodeValue &&
|
|
113
|
+
typeof optionsResult.nodeValue === 'object' &&
|
|
114
|
+
!Array.isArray(optionsResult.nodeValue) &&
|
|
115
|
+
!(optionsResult.nodeValue instanceof RegExp)) {
|
|
116
|
+
options = optionsResult.nodeValue;
|
|
117
|
+
}
|
|
118
|
+
output.dataDependencies.dependencies.push({
|
|
119
|
+
referenceId: (0, utils_1.generateHash)(propertyType, requestedProperties),
|
|
120
|
+
properties: {
|
|
121
|
+
type: propertyType,
|
|
122
|
+
recordProperties: requestedProperties,
|
|
123
|
+
options,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function _processAssociationsHook(node, output) {
|
|
129
|
+
if (node.type !== 'CallExpression')
|
|
130
|
+
return;
|
|
131
|
+
const propertyType = 'CrmRecordAssociationProperties';
|
|
132
|
+
const requestNode = node.arguments[0];
|
|
133
|
+
const optionsNode = node.arguments[1];
|
|
134
|
+
const requestResult = requestNode
|
|
135
|
+
? (0, parsing_utils_1.getValueFromNode)(requestNode, output)
|
|
136
|
+
: null;
|
|
137
|
+
if (!requestResult ||
|
|
138
|
+
requestResult.status === 'FAIL' ||
|
|
139
|
+
!requestResult.nodeValue ||
|
|
140
|
+
typeof requestResult.nodeValue !== 'object' ||
|
|
141
|
+
Array.isArray(requestResult.nodeValue)) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const request = requestResult.nodeValue;
|
|
145
|
+
const toObjectTypeId = request.toObjectType;
|
|
146
|
+
const requestProperties = request.properties;
|
|
147
|
+
if (typeof toObjectTypeId !== 'string') {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const propertiesArray = [];
|
|
151
|
+
if (requestProperties && Array.isArray(requestProperties)) {
|
|
152
|
+
requestProperties.forEach((val) => {
|
|
153
|
+
if (typeof val === 'string') {
|
|
154
|
+
propertiesArray.push(val);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
const paginationOptions = {};
|
|
159
|
+
const otherOptions = {};
|
|
160
|
+
const optionsResult = optionsNode
|
|
161
|
+
? (0, parsing_utils_1.getValueFromNode)(optionsNode, output)
|
|
162
|
+
: null;
|
|
163
|
+
if (optionsResult &&
|
|
164
|
+
optionsResult.status === 'SUCCESS' &&
|
|
165
|
+
optionsResult.nodeValue &&
|
|
166
|
+
typeof optionsResult.nodeValue === 'object' &&
|
|
167
|
+
!Array.isArray(optionsResult.nodeValue) &&
|
|
168
|
+
!(optionsResult.nodeValue instanceof RegExp)) {
|
|
169
|
+
const options = optionsResult.nodeValue;
|
|
170
|
+
Object.keys(options).forEach((key) => {
|
|
171
|
+
otherOptions[key] = options[key];
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (request.pageLength !== undefined) {
|
|
175
|
+
paginationOptions.pageLength = request.pageLength;
|
|
176
|
+
}
|
|
177
|
+
if (request.offset !== undefined) {
|
|
178
|
+
paginationOptions.offset = request.offset;
|
|
179
|
+
}
|
|
180
|
+
const sortedPropertiesForHash = [...propertiesArray].sort();
|
|
181
|
+
output.dataDependencies.dependencies.push({
|
|
182
|
+
referenceId: (0, utils_1.generateHash)(propertyType, toObjectTypeId, sortedPropertiesForHash.join('-')),
|
|
183
|
+
properties: {
|
|
184
|
+
type: propertyType,
|
|
185
|
+
toObjectTypeId,
|
|
186
|
+
requestProperties: propertiesArray,
|
|
187
|
+
paginationOptions,
|
|
188
|
+
options: otherOptions,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
}
|
|
279
192
|
/**
|
|
280
193
|
* This function collects all internal data dependencies for the extension
|
|
281
194
|
* Specifically, it collects dependencies which are using our custom hooks, eg `useCrmProperties`
|
|
@@ -289,13 +202,11 @@ function _collectDataDependencies(node, output, logger) {
|
|
|
289
202
|
if (node.type === 'ImportDeclaration' &&
|
|
290
203
|
typeof node.source.value === 'string' &&
|
|
291
204
|
node.source.value.startsWith('@hubspot/ui-extensions')) {
|
|
292
|
-
const isExperimental = node.source.value === '@hubspot/ui-extensions/experimental';
|
|
293
205
|
// If the imports are coming from our own package, loop over them to check for hooks
|
|
294
206
|
node.specifiers.forEach((specifier) => {
|
|
295
207
|
// If the specifier is an ImportSpecifier and the imported name is one of our tracked hooks, we will track it.
|
|
296
208
|
if (specifier.type === 'ImportSpecifier' &&
|
|
297
|
-
|
|
298
|
-
EXPERIMENTAL_HOOKS.includes(specifier.imported.name)) {
|
|
209
|
+
PARSED_HOOKS.includes(specifier.imported.name)) {
|
|
299
210
|
// 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.
|
|
300
211
|
output.dataDependencies.importedHooks[`${specifier.local.name}`] =
|
|
301
212
|
specifier.imported.name;
|
|
@@ -303,12 +214,10 @@ function _collectDataDependencies(node, output, logger) {
|
|
|
303
214
|
else if (
|
|
304
215
|
// We also have to track namespace level imports
|
|
305
216
|
specifier.type === 'ImportNamespaceSpecifier') {
|
|
306
|
-
// If the specifier is a namespace import, we will track all hooks that are imported from that namespace.
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
});
|
|
311
|
-
}
|
|
217
|
+
// If the specifier is a namespace import, we will track all hooks that are imported from that namespace.
|
|
218
|
+
PARSED_HOOKS.forEach((hook) => {
|
|
219
|
+
output.dataDependencies.importedHooks[`${specifier.local.name}.${hook}`] = hook;
|
|
220
|
+
});
|
|
312
221
|
}
|
|
313
222
|
});
|
|
314
223
|
// Check for calls to our hooks.
|
|
@@ -331,49 +240,10 @@ function _collectDataDependencies(node, output, logger) {
|
|
|
331
240
|
}
|
|
332
241
|
// Then we handle each hook individually, as the usages and tracking format are different.
|
|
333
242
|
if (hookName === 'useCrmProperties') {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
const resolveValue = (astNode) => {
|
|
339
|
-
if (!astNode)
|
|
340
|
-
return null;
|
|
341
|
-
if (astNode.type === 'Identifier' &&
|
|
342
|
-
output.variableDeclarations.has(astNode.name)) {
|
|
343
|
-
return output.variableDeclarations.get(astNode.name);
|
|
344
|
-
}
|
|
345
|
-
return getValueFromNode(astNode, output);
|
|
346
|
-
};
|
|
347
|
-
const propertiesValue = resolveValue(propertiesNode);
|
|
348
|
-
if (propertiesValue && Array.isArray(propertiesValue)) {
|
|
349
|
-
propertiesValue.forEach((val) => {
|
|
350
|
-
if (typeof val === 'string') {
|
|
351
|
-
requestedProperties.push(val);
|
|
352
|
-
}
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
if (requestedProperties.length > 0) {
|
|
356
|
-
let options = {};
|
|
357
|
-
const optionsValue = resolveValue(optionsNode);
|
|
358
|
-
if (optionsValue &&
|
|
359
|
-
typeof optionsValue === 'object' &&
|
|
360
|
-
!Array.isArray(optionsValue) &&
|
|
361
|
-
!(optionsValue instanceof RegExp)) {
|
|
362
|
-
options = optionsValue;
|
|
363
|
-
}
|
|
364
|
-
output.dataDependencies.dependencies.push({
|
|
365
|
-
/**
|
|
366
|
-
* This referenceId is a hash of the property type and the requested properties.
|
|
367
|
-
* This should allow us to create the same hash at execution time, to find the correct data from BE.
|
|
368
|
-
*/
|
|
369
|
-
referenceId: (0, utils_1.generateHash)(propertyType, requestedProperties),
|
|
370
|
-
properties: {
|
|
371
|
-
type: propertyType,
|
|
372
|
-
recordProperties: requestedProperties,
|
|
373
|
-
options,
|
|
374
|
-
},
|
|
375
|
-
});
|
|
376
|
-
}
|
|
243
|
+
_processCrmPropertiesHook(node, output);
|
|
244
|
+
}
|
|
245
|
+
else if (hookName === 'useAssociations') {
|
|
246
|
+
_processAssociationsHook(node, output);
|
|
377
247
|
}
|
|
378
248
|
}
|
|
379
249
|
}
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -29,5 +29,6 @@ export declare const PUBLIC_APP = "public-app";
|
|
|
29
29
|
export declare const PRIVATE_APP = "private-app";
|
|
30
30
|
export declare const CARD_EXTENSION = "CARD";
|
|
31
31
|
export declare const SETTINGS_EXTENSION = "SETTINGS";
|
|
32
|
+
export declare const PAGE_EXTENSION = "PAGE";
|
|
32
33
|
export declare const SUPPORTED_APP_TYPES: string[];
|
|
33
34
|
export declare const SUPPORTED_EXTENSION_TYPES: string[];
|
package/dist/lib/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SUPPORTED_EXTENSION_TYPES = exports.SUPPORTED_APP_TYPES = exports.SETTINGS_EXTENSION = exports.CARD_EXTENSION = exports.PRIVATE_APP = exports.PUBLIC_APP = exports.PLATFORM_VERSION = exports.SERVER_CAPABILITIES = exports.PROXY_CAPABILITY = 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;
|
|
3
|
+
exports.SUPPORTED_EXTENSION_TYPES = exports.SUPPORTED_APP_TYPES = exports.PAGE_EXTENSION = exports.SETTINGS_EXTENSION = exports.CARD_EXTENSION = exports.PRIVATE_APP = exports.PUBLIC_APP = exports.PLATFORM_VERSION = exports.SERVER_CAPABILITIES = exports.PROXY_CAPABILITY = 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
5
|
exports.MANIFEST_FILE = 'manifest.json';
|
|
6
6
|
exports.EXPRESS_SERVER_ID = 'ui-extensions-dev-server';
|
|
@@ -41,5 +41,10 @@ exports.PUBLIC_APP = 'public-app';
|
|
|
41
41
|
exports.PRIVATE_APP = 'private-app';
|
|
42
42
|
exports.CARD_EXTENSION = 'CARD';
|
|
43
43
|
exports.SETTINGS_EXTENSION = 'SETTINGS';
|
|
44
|
+
exports.PAGE_EXTENSION = 'PAGE';
|
|
44
45
|
exports.SUPPORTED_APP_TYPES = [exports.PUBLIC_APP, exports.PRIVATE_APP];
|
|
45
|
-
exports.SUPPORTED_EXTENSION_TYPES = [
|
|
46
|
+
exports.SUPPORTED_EXTENSION_TYPES = [
|
|
47
|
+
exports.CARD_EXTENSION,
|
|
48
|
+
exports.SETTINGS_EXTENSION,
|
|
49
|
+
exports.PAGE_EXTENSION,
|
|
50
|
+
];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Node } from 'estree';
|
|
2
|
+
import { NodeValue, SourceCodeMetadata } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Extracts the value from a given AST node based on its type.
|
|
5
|
+
* This function handles various node types such as Literal, Identifier (aka variables), ArrayExpression,
|
|
6
|
+
* ObjectExpression, SpreadElement, TemplateLiteral, UnaryExpression, and MemberExpression (accessing props on objects).
|
|
7
|
+
* It also supports nested structures and handles special cases like undefined, NaN, and Infinity.
|
|
8
|
+
*
|
|
9
|
+
* It does not handle function calls, complex expressions, or anything that requires evaluation of code logic.
|
|
10
|
+
* This is not a full JavaScript interpreter, but rather a utility to extract static values from the AST.
|
|
11
|
+
*
|
|
12
|
+
* Use this function carefully, as it assumes that the AST is well-formed and that the node types are as expected.
|
|
13
|
+
* Many types are not yet supported. Anything this function is used for should have a backup runtime evaluation,
|
|
14
|
+
* or be set up to fail gracefully if parsing fails.
|
|
15
|
+
*
|
|
16
|
+
* @param node - The AST node from which to extract the value.
|
|
17
|
+
* @param state - The current state of the source code metadata, including variable declarations.
|
|
18
|
+
* @returns An object containing the status of the operation, the extracted node value,
|
|
19
|
+
* or an error message if the extraction fails.
|
|
20
|
+
* The status can be 'SUCCESS' or 'FAIL'.
|
|
21
|
+
* If the status is 'SUCCESS', nodeValue will contain the extracted value.
|
|
22
|
+
* If the status is 'FAIL', error will contain the error message.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getValueFromNode(node: Node, state: SourceCodeMetadata): {
|
|
25
|
+
status: 'SUCCESS' | 'FAIL';
|
|
26
|
+
nodeValue?: NodeValue;
|
|
27
|
+
error?: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function isVariableImported(node: Node, variableName: string): boolean;
|
|
30
|
+
export declare function isIdentifierDefined(node: Node, parent: Node | null, name: string): boolean;
|
|
31
|
+
export declare function isFunctionInvoked(node: Node, functionName: string): boolean;
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isFunctionInvoked = exports.isIdentifierDefined = exports.isVariableImported = exports.getValueFromNode = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Extracts the value from a given AST node based on its type.
|
|
6
|
+
* This function handles various node types such as Literal, Identifier (aka variables), ArrayExpression,
|
|
7
|
+
* ObjectExpression, SpreadElement, TemplateLiteral, UnaryExpression, and MemberExpression (accessing props on objects).
|
|
8
|
+
* It also supports nested structures and handles special cases like undefined, NaN, and Infinity.
|
|
9
|
+
*
|
|
10
|
+
* It does not handle function calls, complex expressions, or anything that requires evaluation of code logic.
|
|
11
|
+
* This is not a full JavaScript interpreter, but rather a utility to extract static values from the AST.
|
|
12
|
+
*
|
|
13
|
+
* Use this function carefully, as it assumes that the AST is well-formed and that the node types are as expected.
|
|
14
|
+
* Many types are not yet supported. Anything this function is used for should have a backup runtime evaluation,
|
|
15
|
+
* or be set up to fail gracefully if parsing fails.
|
|
16
|
+
*
|
|
17
|
+
* @param node - The AST node from which to extract the value.
|
|
18
|
+
* @param state - The current state of the source code metadata, including variable declarations.
|
|
19
|
+
* @returns An object containing the status of the operation, the extracted node value,
|
|
20
|
+
* or an error message if the extraction fails.
|
|
21
|
+
* The status can be 'SUCCESS' or 'FAIL'.
|
|
22
|
+
* If the status is 'SUCCESS', nodeValue will contain the extracted value.
|
|
23
|
+
* If the status is 'FAIL', error will contain the error message.
|
|
24
|
+
*/
|
|
25
|
+
function getValueFromNode(node, state) {
|
|
26
|
+
try {
|
|
27
|
+
switch (node.type) {
|
|
28
|
+
case 'Literal':
|
|
29
|
+
return { status: 'SUCCESS', nodeValue: node.value };
|
|
30
|
+
case 'Identifier': {
|
|
31
|
+
const name = node.name;
|
|
32
|
+
switch (name) {
|
|
33
|
+
case 'undefined':
|
|
34
|
+
return { status: 'SUCCESS', nodeValue: undefined };
|
|
35
|
+
case 'NaN':
|
|
36
|
+
return { status: 'SUCCESS', nodeValue: NaN };
|
|
37
|
+
case 'Infinity':
|
|
38
|
+
return { status: 'SUCCESS', nodeValue: Infinity };
|
|
39
|
+
default:
|
|
40
|
+
if (state.variableDeclarations.has(name)) {
|
|
41
|
+
return {
|
|
42
|
+
status: 'SUCCESS',
|
|
43
|
+
nodeValue: state.variableDeclarations.get(name),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// If for some reason the variable tracking fails, return unsupported.
|
|
47
|
+
return { status: 'FAIL', error: `Identifier ${name} is not found` };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
case 'ArrayExpression': {
|
|
51
|
+
const arrayValue = [];
|
|
52
|
+
if (node.elements.length === 0) {
|
|
53
|
+
return { status: 'SUCCESS', nodeValue: arrayValue };
|
|
54
|
+
}
|
|
55
|
+
// Arrays have to be built from their elements, to handle special cases like nested arrays from spread operators.
|
|
56
|
+
for (const element of node.elements) {
|
|
57
|
+
if (typeof element === 'object' && element !== null) {
|
|
58
|
+
if (element.type === 'SpreadElement') {
|
|
59
|
+
const result = getValueFromNode(element, state);
|
|
60
|
+
if (result.status === 'FAIL') {
|
|
61
|
+
return {
|
|
62
|
+
status: 'FAIL',
|
|
63
|
+
error: `Array spread element failed: ${result.error}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const value = result.nodeValue;
|
|
67
|
+
if (Array.isArray(value)) {
|
|
68
|
+
arrayValue.push(...value);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
arrayValue.push(value);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const result = getValueFromNode(element, state);
|
|
76
|
+
if (result.status === 'FAIL') {
|
|
77
|
+
return {
|
|
78
|
+
status: 'FAIL',
|
|
79
|
+
error: `Array element failed: ${result.error}`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
arrayValue.push(result.nodeValue);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
arrayValue.push(element);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { status: 'SUCCESS', nodeValue: arrayValue };
|
|
90
|
+
}
|
|
91
|
+
case 'ObjectExpression': {
|
|
92
|
+
const obj = {};
|
|
93
|
+
for (const prop of node.properties) {
|
|
94
|
+
switch (prop.type) {
|
|
95
|
+
case 'Property': {
|
|
96
|
+
const property = prop;
|
|
97
|
+
let key = undefined;
|
|
98
|
+
if (property.key.type === 'Identifier') {
|
|
99
|
+
key = property.key.name;
|
|
100
|
+
}
|
|
101
|
+
else if (property.key.type === 'Literal') {
|
|
102
|
+
key = String(property.key.value);
|
|
103
|
+
}
|
|
104
|
+
if (key) {
|
|
105
|
+
const result = getValueFromNode(property.value, state);
|
|
106
|
+
if (result.status === 'FAIL') {
|
|
107
|
+
return {
|
|
108
|
+
status: 'FAIL',
|
|
109
|
+
error: `Object property '${key}' failed: ${result.error}`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
obj[key] = result.nodeValue;
|
|
113
|
+
}
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case 'SpreadElement': {
|
|
117
|
+
const result = getValueFromNode(prop, state);
|
|
118
|
+
if (result.status === 'FAIL') {
|
|
119
|
+
return {
|
|
120
|
+
status: 'FAIL',
|
|
121
|
+
error: `Object spread element failed: ${result.error}`,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const spreadValue = result.nodeValue;
|
|
125
|
+
if (spreadValue && typeof spreadValue === 'object') {
|
|
126
|
+
Object.assign(obj, spreadValue);
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
default:
|
|
131
|
+
// Ignore unsupported property types, as we don't have a key for them.
|
|
132
|
+
// This could be a computed property or something else we don't handle.
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { status: 'SUCCESS', nodeValue: obj };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Spread elements are a bit tricky. They can be used to directly spread an array or object,
|
|
140
|
+
* or they can be used to spread a variable that is defined elsewhere. Our strategy is to return
|
|
141
|
+
* whatever element should be spread, and then handle the spreading in the parent array or object.
|
|
142
|
+
*
|
|
143
|
+
* There are also trickier cases we don't handle, like spreading a function call that returns an
|
|
144
|
+
* array or object. When the spread element is unsupported, we return a special symbol.
|
|
145
|
+
*/
|
|
146
|
+
case 'SpreadElement':
|
|
147
|
+
if (node.argument) {
|
|
148
|
+
if (node.argument.type === 'Identifier' && node.argument.name) {
|
|
149
|
+
return {
|
|
150
|
+
status: 'SUCCESS',
|
|
151
|
+
nodeValue: state.variableDeclarations.get(node.argument.name) || null,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
else if (node.argument.type === 'ArrayExpression' ||
|
|
155
|
+
node.argument.type === 'ObjectExpression') {
|
|
156
|
+
return getValueFromNode(node.argument, state);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
status: 'FAIL',
|
|
161
|
+
error: `Unsupported SpreadElement type: ${node.argument.type}`,
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Template literals are built of an alternating sequence of static
|
|
165
|
+
* strings and expressions. We will concatenate the static strings and
|
|
166
|
+
* evaluate the expressions to build the final string.
|
|
167
|
+
*/
|
|
168
|
+
case 'TemplateLiteral': {
|
|
169
|
+
let result = '';
|
|
170
|
+
if (node.expressions && node.quasis) {
|
|
171
|
+
const { quasis, expressions } = node;
|
|
172
|
+
for (let i = 0; i < quasis.length; i++) {
|
|
173
|
+
// Prefer cooked value if available, otherwise use raw.
|
|
174
|
+
result += quasis[i].value.cooked || quasis[i].value.raw;
|
|
175
|
+
if (i < expressions.length) {
|
|
176
|
+
const expression = expressions[i];
|
|
177
|
+
const expressionResult = getValueFromNode(expression, state);
|
|
178
|
+
if (expressionResult.status === 'SUCCESS') {
|
|
179
|
+
const expressionValue = expressionResult.nodeValue;
|
|
180
|
+
if (expressionValue === null ||
|
|
181
|
+
expressionValue === undefined ||
|
|
182
|
+
typeof expressionValue === 'string' ||
|
|
183
|
+
typeof expressionValue === 'number' ||
|
|
184
|
+
typeof expressionValue === 'boolean') {
|
|
185
|
+
result += String(expressionValue);
|
|
186
|
+
}
|
|
187
|
+
else if (Array.isArray(expressionValue)) {
|
|
188
|
+
result += expressionValue.join(',');
|
|
189
|
+
}
|
|
190
|
+
else if (typeof expressionValue === 'object') {
|
|
191
|
+
result += '[object Object]';
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
result += `Unsupported TemplateLiteral expression value type: ${typeof expressionValue}`;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
result += expressionResult.error;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return { status: 'SUCCESS', nodeValue: result };
|
|
204
|
+
}
|
|
205
|
+
case 'UnaryExpression': {
|
|
206
|
+
const argResult = getValueFromNode(node.argument, state);
|
|
207
|
+
if (argResult.status === 'FAIL') {
|
|
208
|
+
return argResult;
|
|
209
|
+
}
|
|
210
|
+
const arg = argResult.nodeValue;
|
|
211
|
+
switch (node.operator) {
|
|
212
|
+
case '-':
|
|
213
|
+
return {
|
|
214
|
+
status: 'SUCCESS',
|
|
215
|
+
nodeValue: typeof arg === 'number' ? -arg : NaN,
|
|
216
|
+
};
|
|
217
|
+
case '+':
|
|
218
|
+
return {
|
|
219
|
+
status: 'SUCCESS',
|
|
220
|
+
nodeValue: typeof arg === 'number' ? +arg : NaN,
|
|
221
|
+
};
|
|
222
|
+
case '!':
|
|
223
|
+
return { status: 'SUCCESS', nodeValue: !arg };
|
|
224
|
+
case 'typeof':
|
|
225
|
+
return { status: 'SUCCESS', nodeValue: typeof arg };
|
|
226
|
+
default:
|
|
227
|
+
return {
|
|
228
|
+
status: 'FAIL',
|
|
229
|
+
error: `Unsupported unary operator: ${node.operator}`,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// Member expressions are used to access properties of objects.
|
|
234
|
+
case 'MemberExpression': {
|
|
235
|
+
if (node.property.type === 'Identifier' && node.property.name) {
|
|
236
|
+
// We have to recursively get the value of the object, due to the way that nested objects are parsed.
|
|
237
|
+
const objectResult = getValueFromNode(node.object, state);
|
|
238
|
+
if (objectResult.status === 'FAIL') {
|
|
239
|
+
return objectResult;
|
|
240
|
+
}
|
|
241
|
+
const objectData = objectResult.nodeValue;
|
|
242
|
+
if (objectData &&
|
|
243
|
+
typeof objectData === 'object' &&
|
|
244
|
+
!Array.isArray(objectData) &&
|
|
245
|
+
!(objectData instanceof RegExp)) {
|
|
246
|
+
return {
|
|
247
|
+
status: 'SUCCESS',
|
|
248
|
+
nodeValue: objectData[node.property.name],
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
status: 'FAIL',
|
|
254
|
+
error: `Unsupported MemberExpression property type: ${node.property.type}`,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
default:
|
|
258
|
+
return { status: 'FAIL', error: `Unsupported node type: ${node.type}` };
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
return {
|
|
263
|
+
status: 'FAIL',
|
|
264
|
+
error: error instanceof Error ? error.message : String(error),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
exports.getValueFromNode = getValueFromNode;
|
|
269
|
+
function isVariableImported(node, variableName) {
|
|
270
|
+
if (!node) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
return ((node.type === 'ImportSpecifier' && node.imported.name === variableName) ||
|
|
274
|
+
(node.type === 'ImportDefaultSpecifier' &&
|
|
275
|
+
node.local.name === variableName) ||
|
|
276
|
+
(node.type === 'ImportNamespaceSpecifier' &&
|
|
277
|
+
node.local.name === variableName));
|
|
278
|
+
}
|
|
279
|
+
exports.isVariableImported = isVariableImported;
|
|
280
|
+
function isIdentifierDefined(node, parent, name) {
|
|
281
|
+
if (parent &&
|
|
282
|
+
(parent.type === 'MemberExpression' || parent.type === 'CallExpression')) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
return node.type === 'Identifier' && node.name === name;
|
|
286
|
+
}
|
|
287
|
+
exports.isIdentifierDefined = isIdentifierDefined;
|
|
288
|
+
function isFunctionInvoked(node, functionName) {
|
|
289
|
+
return (node.type === 'CallExpression' &&
|
|
290
|
+
node.callee &&
|
|
291
|
+
'name' in node.callee &&
|
|
292
|
+
node.callee.name === functionName);
|
|
293
|
+
}
|
|
294
|
+
exports.isFunctionInvoked = isFunctionInvoked;
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -130,10 +130,11 @@ export type UnifiedCardConfig = {
|
|
|
130
130
|
export declare enum UnifiedComponentTypes {
|
|
131
131
|
CARD = "CARD",
|
|
132
132
|
APPLICATION = "APPLICATION",
|
|
133
|
-
SETTINGS = "SETTINGS"
|
|
133
|
+
SETTINGS = "SETTINGS",
|
|
134
|
+
PAGE = "PAGE"
|
|
134
135
|
}
|
|
135
136
|
export type UnifiedExtensionComponent = Omit<UnifiedCardConfig, 'type'> & {
|
|
136
|
-
componentType: UnifiedComponentTypes.CARD | UnifiedComponentTypes.SETTINGS;
|
|
137
|
+
componentType: UnifiedComponentTypes.CARD | UnifiedComponentTypes.SETTINGS | UnifiedComponentTypes.PAGE;
|
|
137
138
|
componentDeps: {
|
|
138
139
|
app: string;
|
|
139
140
|
};
|
|
@@ -200,11 +201,21 @@ export interface FunctionMetadata {
|
|
|
200
201
|
export type DataDependency = {
|
|
201
202
|
referenceId: string;
|
|
202
203
|
properties: {
|
|
203
|
-
type:
|
|
204
|
+
type: 'CrmRecordProperties';
|
|
204
205
|
recordProperties: string[];
|
|
205
206
|
options: {
|
|
206
207
|
[key: string]: any;
|
|
207
208
|
};
|
|
209
|
+
} | {
|
|
210
|
+
type: 'CrmRecordAssociationProperties';
|
|
211
|
+
toObjectTypeId: string;
|
|
212
|
+
requestProperties: string[];
|
|
213
|
+
paginationOptions: {
|
|
214
|
+
[key: string]: any;
|
|
215
|
+
};
|
|
216
|
+
options: {
|
|
217
|
+
[key: string]: any;
|
|
218
|
+
};
|
|
208
219
|
};
|
|
209
220
|
};
|
|
210
221
|
export type NodeValue = string | number | boolean | null | undefined | RegExp | bigint | symbol | NodeValue[] | NodeObject;
|
package/dist/lib/types.js
CHANGED
|
@@ -11,4 +11,5 @@ var UnifiedComponentTypes;
|
|
|
11
11
|
UnifiedComponentTypes["CARD"] = "CARD";
|
|
12
12
|
UnifiedComponentTypes["APPLICATION"] = "APPLICATION";
|
|
13
13
|
UnifiedComponentTypes["SETTINGS"] = "SETTINGS";
|
|
14
|
+
UnifiedComponentTypes["PAGE"] = "PAGE";
|
|
14
15
|
})(UnifiedComponentTypes || (exports.UnifiedComponentTypes = UnifiedComponentTypes = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/ui-extensions-dev-server",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.8",
|
|
4
4
|
"description": "",
|
|
5
5
|
"bin": {
|
|
6
6
|
"uie": "./dist/lib/bin/cli.js"
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"optional": true
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "68d176099343d6d202421ec241c131f1d07562a8"
|
|
74
74
|
}
|