@hubspot/project-parsing-lib 0.9.0 → 0.10.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -4
- package/src/index.js +3 -3
- package/src/lang/copy.d.ts +1 -0
- package/src/lang/copy.js +1 -0
- package/src/lib/constants.d.ts +3 -0
- package/src/lib/constants.js +15 -1
- package/src/lib/files.js +11 -0
- package/src/lib/transform.d.ts +1 -0
- package/src/lib/transform.js +4 -0
- package/src/lib/validation.d.ts +1 -1
- package/src/lib/validation.js +29 -22
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/project-parsing-lib",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0-beta.1",
|
|
4
4
|
"description": "Parsing library for converting projects directory structures to their intermediate representation",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "src/index.js",
|
|
7
7
|
"devDependencies": {
|
|
8
8
|
"@hubspot/local-dev-lib": "^3.18.0",
|
|
9
|
+
"@hubspot/npm-scripts": "0.0.4",
|
|
9
10
|
"@inquirer/prompts": "^7.1.0",
|
|
10
11
|
"@types/jest": "^29.5.14",
|
|
11
12
|
"@types/semver": "^7.5.8",
|
|
@@ -19,7 +20,7 @@
|
|
|
19
20
|
"prettier": "^1.19.1",
|
|
20
21
|
"semver": "^7.6.3",
|
|
21
22
|
"ts-jest": "^29.2.5",
|
|
22
|
-
"
|
|
23
|
+
"tsx": "^4.20.5",
|
|
23
24
|
"typescript": "^5.6.2"
|
|
24
25
|
},
|
|
25
26
|
"dependencies": {
|
|
@@ -30,13 +31,14 @@
|
|
|
30
31
|
"@hubspot/local-dev-lib": "^3.16.0"
|
|
31
32
|
},
|
|
32
33
|
"scripts": {
|
|
33
|
-
"build": "
|
|
34
|
+
"build": "tsx ./scripts/build.ts",
|
|
34
35
|
"lint": "echo 'Linting is disabled for Blazar'",
|
|
35
36
|
"lint:local": "eslint --max-warnings=0 . && prettier ./src/** --check",
|
|
36
37
|
"local-dev": "yarn build && cd dist && yarn link && cd .. && tsc --watch --rootDir . --outdir dist",
|
|
38
|
+
"local-link": "hubspot-linking",
|
|
37
39
|
"prettier:write": "prettier ./src/** --write",
|
|
38
40
|
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ./node_modules/.bin/jest",
|
|
39
|
-
"release": "
|
|
41
|
+
"release": "tsx ./scripts/release.ts release",
|
|
40
42
|
"reset-north-star": "git submodule update --init",
|
|
41
43
|
"acceptance-test": "yarn --cwd=./acceptance-tests test",
|
|
42
44
|
"update-north-star": "git submodule update --remote"
|
package/src/index.js
CHANGED
|
@@ -21,11 +21,11 @@ async function translate(translationContext, translationOptions = defaultOptions
|
|
|
21
21
|
if (translationOptions.profile) {
|
|
22
22
|
hsProfileContents = (0, files_1.loadHsProfileFile)(translationContext.projectSourceDir, translationOptions.profile);
|
|
23
23
|
}
|
|
24
|
-
const
|
|
25
|
-
const intermediateRepresentation = (0, transform_1.getIntermediateRepresentation)(
|
|
24
|
+
const transformations = (0, transform_1.transform)(metafileContents, translationContext, hsProfileContents);
|
|
25
|
+
const intermediateRepresentation = (0, transform_1.getIntermediateRepresentation)(transformations, hsProfileContents, skipValidation);
|
|
26
26
|
// Remove once extensions and serverless functions are supported
|
|
27
27
|
if (!skipValidation) {
|
|
28
|
-
await (0, validation_1.validateIntermediateRepresentation)(intermediateRepresentation,
|
|
28
|
+
await (0, validation_1.validateIntermediateRepresentation)(intermediateRepresentation, transformations, translationContext);
|
|
29
29
|
}
|
|
30
30
|
return intermediateRepresentation;
|
|
31
31
|
}
|
package/src/lang/copy.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export declare const errorMessages: {
|
|
|
31
31
|
unsupportedType: (type: string) => string;
|
|
32
32
|
errorWithField: (field: string, error: string | undefined) => string;
|
|
33
33
|
invalidJson: string;
|
|
34
|
+
unexpectedToplevelFields: (unexpectedFields: string) => string;
|
|
34
35
|
wrongDirectoryForComponent: (directory: string, componentType: string, componentMetadata: ComponentMetadata, correctDir: string) => string;
|
|
35
36
|
};
|
|
36
37
|
migrateThemes: {
|
package/src/lang/copy.js
CHANGED
|
@@ -42,6 +42,7 @@ exports.errorMessages = {
|
|
|
42
42
|
unsupportedType: (type) => `Unsupported type: ${(0, transform_1.mapToUserFacingType)(type)}`,
|
|
43
43
|
errorWithField: (field, error) => `${field}: ${error || 'Unknown error'}`,
|
|
44
44
|
invalidJson: 'Invalid JSON',
|
|
45
|
+
unexpectedToplevelFields: (unexpectedFields) => `Unexpected top-level properties found: ${unexpectedFields}`,
|
|
45
46
|
wrongDirectoryForComponent: (directory, componentType, componentMetadata, correctDir) => `The directory '${directory}' is incorrect for type '${componentType}'. ${componentMetadata.userFriendlyName} ${componentMetadata.userFriendlyTypePlural} should only be placed in the '${correctDir}' directory`,
|
|
46
47
|
},
|
|
47
48
|
migrateThemes: {
|
package/src/lib/constants.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Components as ComponentsTopLevel } from './types';
|
|
1
2
|
export declare const AppKey = "app";
|
|
2
3
|
export declare const ThemeKey = "theme";
|
|
3
4
|
export declare const CmsAssetsKey = "cms-assets";
|
|
@@ -16,6 +17,7 @@ export declare const SettingsKey = "settings";
|
|
|
16
17
|
export declare const TelemetryKey = "telemetry";
|
|
17
18
|
export declare const VideoConferencingKey = "video-conferencing";
|
|
18
19
|
export declare const WebhooksKey = "webhooks";
|
|
20
|
+
export declare const WebhooksJournalKey = "webhooks-journal";
|
|
19
21
|
export declare const WorkflowActionsKey = "workflow-action";
|
|
20
22
|
export declare const AppFunctionsPackageKey = "serverless-package";
|
|
21
23
|
export declare const AutoGeneratedComponentTypes: string[];
|
|
@@ -52,3 +54,4 @@ export declare const ProfileVariableTypes: {
|
|
|
52
54
|
readonly PROFILE_STRING: "PROFILE_STRING";
|
|
53
55
|
readonly PROFILE_BOOLEAN: "PROFILE_BOOLEAN";
|
|
54
56
|
};
|
|
57
|
+
export declare const allowedTopLevelFields: Set<keyof ComponentsTopLevel>;
|
package/src/lib/constants.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.ProfileVariableTypes = exports.allowedSubComponentDirectories = exports.allowedComponentDirectories = exports.ProjectStructure = exports.allowedCmsAssetSubComponentDirs = exports.allowedThemeSubComponentsDirs = exports.allowedAppSubComponentsDirs = exports.packageLockJson = exports.packageJson = exports.hsProjectJsonFilename = exports.profileFilePrefix = exports.metafileExtension = exports.internalTypeToUserFacing = exports.userFacingToInternalType = exports.Components = exports.AutoGeneratedComponentTypes = exports.AppFunctionsPackageKey = exports.WorkflowActionsKey = exports.WebhooksKey = exports.VideoConferencingKey = exports.TelemetryKey = exports.SettingsKey = exports.MediaBridgeKey = exports.MCPRegistryKey = exports.MarketingEventsKey = exports.SCIMKey = exports.CardsKey = exports.CallingKey = exports.AppObjectAssociationKey = exports.AppObjectKey = exports.PagesKey = exports.AppFunctionsKey = exports.AppEventsKey = exports.CmsAssetsKey = exports.ThemeKey = exports.AppKey = void 0;
|
|
36
|
+
exports.allowedTopLevelFields = exports.ProfileVariableTypes = exports.allowedSubComponentDirectories = exports.allowedComponentDirectories = exports.ProjectStructure = exports.allowedCmsAssetSubComponentDirs = exports.allowedThemeSubComponentsDirs = exports.allowedAppSubComponentsDirs = exports.packageLockJson = exports.packageJson = exports.hsProjectJsonFilename = exports.profileFilePrefix = exports.metafileExtension = exports.internalTypeToUserFacing = exports.userFacingToInternalType = exports.Components = exports.AutoGeneratedComponentTypes = exports.AppFunctionsPackageKey = exports.WorkflowActionsKey = exports.WebhooksJournalKey = exports.WebhooksKey = exports.VideoConferencingKey = exports.TelemetryKey = exports.SettingsKey = exports.MediaBridgeKey = exports.MCPRegistryKey = exports.MarketingEventsKey = exports.SCIMKey = exports.CardsKey = exports.CallingKey = exports.AppObjectAssociationKey = exports.AppObjectKey = exports.PagesKey = exports.AppFunctionsKey = exports.AppEventsKey = exports.CmsAssetsKey = exports.ThemeKey = exports.AppKey = void 0;
|
|
37
37
|
// Top Level Component types
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
39
|
// Component types
|
|
@@ -56,6 +56,7 @@ exports.SettingsKey = 'settings';
|
|
|
56
56
|
exports.TelemetryKey = 'telemetry';
|
|
57
57
|
exports.VideoConferencingKey = 'video-conferencing';
|
|
58
58
|
exports.WebhooksKey = 'webhooks';
|
|
59
|
+
exports.WebhooksJournalKey = 'webhooks-journal';
|
|
59
60
|
exports.WorkflowActionsKey = 'workflow-action';
|
|
60
61
|
// Auto-generated component types
|
|
61
62
|
exports.AppFunctionsPackageKey = 'serverless-package';
|
|
@@ -170,6 +171,13 @@ exports.Components = {
|
|
|
170
171
|
...SubComponentFields,
|
|
171
172
|
singularComponent: true,
|
|
172
173
|
},
|
|
174
|
+
[exports.WebhooksJournalKey]: {
|
|
175
|
+
dir: exports.WebhooksJournalKey,
|
|
176
|
+
parentComponent: exports.AppKey,
|
|
177
|
+
userFriendlyName: 'Webhooks Journal',
|
|
178
|
+
...SubComponentFields,
|
|
179
|
+
singularComponent: true,
|
|
180
|
+
},
|
|
173
181
|
[exports.WorkflowActionsKey]: {
|
|
174
182
|
dir: 'workflow-actions',
|
|
175
183
|
parentComponent: exports.AppKey,
|
|
@@ -230,3 +238,9 @@ exports.ProfileVariableTypes = {
|
|
|
230
238
|
PROFILE_STRING: 'PROFILE_STRING',
|
|
231
239
|
PROFILE_BOOLEAN: 'PROFILE_BOOLEAN',
|
|
232
240
|
};
|
|
241
|
+
exports.allowedTopLevelFields = new Set([
|
|
242
|
+
'uid',
|
|
243
|
+
'type',
|
|
244
|
+
'config',
|
|
245
|
+
'dependencies',
|
|
246
|
+
]);
|
package/src/lib/files.js
CHANGED
|
@@ -107,6 +107,17 @@ function parseFile(fileLoadResult) {
|
|
|
107
107
|
catch (_e) {
|
|
108
108
|
fileLoadResult.errors?.push(copy_1.errorMessages.validation.invalidJson);
|
|
109
109
|
}
|
|
110
|
+
// Validate top-level fields (only uid, type, and config are expected)
|
|
111
|
+
if (parsedFileContents &&
|
|
112
|
+
typeof parsedFileContents === 'object' &&
|
|
113
|
+
!Array.isArray(parsedFileContents)) {
|
|
114
|
+
const actualFields = Object.keys(parsedFileContents);
|
|
115
|
+
const unexpectedFields = actualFields.filter(field => !constants_1.allowedTopLevelFields.has(field));
|
|
116
|
+
if (unexpectedFields.length > 0) {
|
|
117
|
+
const unexpectedFieldsList = unexpectedFields.join(', ');
|
|
118
|
+
fileLoadResult.errors?.push(copy_1.errorMessages.validation.unexpectedToplevelFields(unexpectedFieldsList));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
110
121
|
return { ...fileLoadResult, content: parsedFileContents };
|
|
111
122
|
}
|
|
112
123
|
async function projectContainsHsMetaFiles(projectSourceDir) {
|
package/src/lib/transform.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Dependencies, FileParseResult, HsProfileFile, IntermediateRepresentatio
|
|
|
2
2
|
export declare function mapToInternalType(type: string): string;
|
|
3
3
|
export declare function mapToUserFacingType(type: string): string;
|
|
4
4
|
export declare function mapToUserFriendlyName(internalType: string): string;
|
|
5
|
+
export declare function findTransformationByUid(transformations: Transformation[], uid: string): Transformation | undefined;
|
|
5
6
|
export declare function transform(fileParseResults: FileParseResult[], translationContext: TranslationContext, hsProfileContents?: HsProfileFile): Transformation[];
|
|
6
7
|
export declare function getIntermediateRepresentation(transformations: Transformation[], hsProfileContents?: HsProfileFile, skipValidation?: boolean): IntermediateRepresentation;
|
|
7
8
|
export declare function getParsingErrors(transformations: Transformation[]): FileParseResult[];
|
package/src/lib/transform.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.mapToInternalType = mapToInternalType;
|
|
7
7
|
exports.mapToUserFacingType = mapToUserFacingType;
|
|
8
8
|
exports.mapToUserFriendlyName = mapToUserFriendlyName;
|
|
9
|
+
exports.findTransformationByUid = findTransformationByUid;
|
|
9
10
|
exports.transform = transform;
|
|
10
11
|
exports.getIntermediateRepresentation = getIntermediateRepresentation;
|
|
11
12
|
exports.getParsingErrors = getParsingErrors;
|
|
@@ -59,6 +60,9 @@ function mapToUserFacingType(type) {
|
|
|
59
60
|
function mapToUserFriendlyName(internalType) {
|
|
60
61
|
return constants_1.Components[mapToUserFacingType(internalType)]?.userFriendlyName || '';
|
|
61
62
|
}
|
|
63
|
+
function findTransformationByUid(transformations, uid) {
|
|
64
|
+
return transformations.find(t => t.intermediateRepresentation?.uid === uid);
|
|
65
|
+
}
|
|
62
66
|
function transform(fileParseResults, translationContext, hsProfileContents) {
|
|
63
67
|
const parentTypes = Object.keys(constants_1.ProjectStructure);
|
|
64
68
|
const parentComponents = {};
|
package/src/lib/validation.d.ts
CHANGED
|
@@ -11,4 +11,4 @@ export type ValidationResults = {
|
|
|
11
11
|
schemaValidationErrors?: ValidateFunction['errors'];
|
|
12
12
|
} | ValidResult;
|
|
13
13
|
export declare function createAjvInstance(): Ajv;
|
|
14
|
-
export declare function validateIntermediateRepresentation(intermediateRepresentation: IntermediateRepresentation,
|
|
14
|
+
export declare function validateIntermediateRepresentation(intermediateRepresentation: IntermediateRepresentation, transformations: Transformation[], translationContext: TranslationContext): Promise<ValidResult>;
|
package/src/lib/validation.js
CHANGED
|
@@ -19,41 +19,41 @@ function createAjvInstance() {
|
|
|
19
19
|
(0, ajv_formats_1.default)(ajv);
|
|
20
20
|
return ajv;
|
|
21
21
|
}
|
|
22
|
-
function validateIntermediateRepresentationNode(schema, transformation, irNode,
|
|
22
|
+
function validateIntermediateRepresentationNode(schema, transformation, irNode, translationContext) {
|
|
23
23
|
if (constants_1.AutoGeneratedComponentTypes.includes((0, transform_1.mapToUserFacingType)(irNode.componentType))) {
|
|
24
24
|
// Skip validation for auto-generated components
|
|
25
25
|
return {
|
|
26
26
|
valid: true,
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
-
if (transformation
|
|
29
|
+
if (transformation.fileParseResult.errors.length > 0) {
|
|
30
30
|
return {
|
|
31
31
|
valid: false,
|
|
32
|
-
errors: (0, errors_1.compileError)(transformation
|
|
32
|
+
errors: (0, errors_1.compileError)(transformation),
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
const ajv = createAjvInstance();
|
|
36
36
|
let shouldSkipValidation = false;
|
|
37
37
|
if (!irNode.uid) {
|
|
38
|
-
transformation
|
|
38
|
+
transformation.fileParseResult.errors.push(copy_1.errorMessages.validation.missingUid);
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
41
|
const uidValidationResult = (0, uid_1.validateUid)(irNode.uid);
|
|
42
42
|
if (uidValidationResult) {
|
|
43
|
-
transformation
|
|
43
|
+
transformation.fileParseResult.errors.push(uidValidationResult);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
if (!irNode.config) {
|
|
47
|
-
transformation
|
|
47
|
+
transformation.fileParseResult.errors.push(copy_1.errorMessages.validation.missingConfig);
|
|
48
48
|
// If there is no config block, there is nothing to validation
|
|
49
49
|
shouldSkipValidation = true;
|
|
50
50
|
}
|
|
51
51
|
if (!schema[irNode.componentType]) {
|
|
52
52
|
if (!irNode.componentType) {
|
|
53
|
-
transformation
|
|
53
|
+
transformation.fileParseResult.errors.push(copy_1.errorMessages.validation.missingType);
|
|
54
54
|
}
|
|
55
55
|
else {
|
|
56
|
-
transformation
|
|
56
|
+
transformation.fileParseResult.errors.push(copy_1.errorMessages.validation.unsupportedType(irNode.componentType));
|
|
57
57
|
}
|
|
58
58
|
// If there is no schema for the component type, there is no way to validate
|
|
59
59
|
shouldSkipValidation = true;
|
|
@@ -65,21 +65,23 @@ function validateIntermediateRepresentationNode(schema, transformation, irNode,
|
|
|
65
65
|
? constants_1.Components[component.parentComponent].dir
|
|
66
66
|
: '';
|
|
67
67
|
const expectedLocation = path_1.default.join(expectedParentDir, component.dir);
|
|
68
|
-
const actualLocation = path_1.default.dirname(transformation
|
|
68
|
+
const actualLocation = path_1.default.dirname(transformation.fileParseResult.file);
|
|
69
69
|
if (expectedLocation !== actualLocation) {
|
|
70
|
-
transformation
|
|
70
|
+
transformation.fileParseResult.errors.push(copy_1.errorMessages.validation.wrongDirectoryForComponent(actualLocation, userFacingType, component, path_1.default.join(translationContext.projectSourceDir, expectedLocation)));
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
if (shouldSkipValidation) {
|
|
74
74
|
return {
|
|
75
75
|
valid: false,
|
|
76
|
-
errors: (0, errors_1.compileError)(transformation
|
|
76
|
+
errors: (0, errors_1.compileError)(transformation),
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
|
+
console.log('schema[irNode.componentType]', schema[irNode.componentType]);
|
|
80
|
+
console.log('irNode.config', irNode.config);
|
|
79
81
|
const validate = ajv.compile(schema[irNode.componentType]);
|
|
80
82
|
const valid = validate(irNode.config);
|
|
81
83
|
if (valid) {
|
|
82
|
-
const { errors } = transformation
|
|
84
|
+
const { errors } = transformation.fileParseResult;
|
|
83
85
|
// Even through it passed the schema validation, it may have had other errors along the way
|
|
84
86
|
return errors.length === 0
|
|
85
87
|
? {
|
|
@@ -87,7 +89,7 @@ function validateIntermediateRepresentationNode(schema, transformation, irNode,
|
|
|
87
89
|
}
|
|
88
90
|
: {
|
|
89
91
|
valid: false,
|
|
90
|
-
errors: (0, errors_1.compileError)(transformation
|
|
92
|
+
errors: (0, errors_1.compileError)(transformation),
|
|
91
93
|
};
|
|
92
94
|
}
|
|
93
95
|
return {
|
|
@@ -95,11 +97,11 @@ function validateIntermediateRepresentationNode(schema, transformation, irNode,
|
|
|
95
97
|
schemaValidationErrors: validate.errors,
|
|
96
98
|
};
|
|
97
99
|
}
|
|
98
|
-
async function validateIntermediateRepresentation(intermediateRepresentation,
|
|
99
|
-
const hasAnyFileParseErrors =
|
|
100
|
+
async function validateIntermediateRepresentation(intermediateRepresentation, transformations, translationContext) {
|
|
101
|
+
const hasAnyFileParseErrors = transformations.some(t => t.fileParseResult.errors.length > 0);
|
|
100
102
|
const schema = await (0, schemas_1.getIntermediateRepresentationSchema)(translationContext);
|
|
101
103
|
const potentialDuplicatesByComponent = {};
|
|
102
|
-
const results = Object.values(intermediateRepresentation.intermediateNodesIndexedByUid).map(
|
|
104
|
+
const results = Object.values(intermediateRepresentation.intermediateNodesIndexedByUid).map(irNode => {
|
|
103
105
|
const userFacingType = (0, transform_1.mapToUserFacingType)(irNode.componentType);
|
|
104
106
|
const component = constants_1.Components[userFacingType];
|
|
105
107
|
if (component && component.singularComponent) {
|
|
@@ -107,7 +109,11 @@ async function validateIntermediateRepresentation(intermediateRepresentation, tr
|
|
|
107
109
|
? [...potentialDuplicatesByComponent[userFacingType], irNode]
|
|
108
110
|
: [irNode];
|
|
109
111
|
}
|
|
110
|
-
|
|
112
|
+
const transformation = (0, transform_1.findTransformationByUid)(transformations, irNode.uid);
|
|
113
|
+
if (!transformation) {
|
|
114
|
+
return { valid: false, errors: [copy_1.errorMessages.validation.missingUid] };
|
|
115
|
+
}
|
|
116
|
+
return validateIntermediateRepresentationNode(schema, transformation, irNode, translationContext);
|
|
111
117
|
});
|
|
112
118
|
let hasDuplicates = false;
|
|
113
119
|
Object.entries(potentialDuplicatesByComponent).forEach(([componentType, potentialDuplicates]) => {
|
|
@@ -116,9 +122,10 @@ async function validateIntermediateRepresentation(intermediateRepresentation, tr
|
|
|
116
122
|
}
|
|
117
123
|
hasDuplicates = true;
|
|
118
124
|
potentialDuplicates.forEach(duplicate => {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
125
|
+
const potentialDuplicateTransformation = (0, transform_1.findTransformationByUid)(transformations, duplicate.uid);
|
|
126
|
+
if (potentialDuplicateTransformation) {
|
|
127
|
+
potentialDuplicateTransformation.fileParseResult.errors.push(copy_1.errorMessages.project.duplicateComponent(componentType));
|
|
128
|
+
}
|
|
122
129
|
});
|
|
123
130
|
});
|
|
124
131
|
const valid = !hasAnyFileParseErrors &&
|
|
@@ -129,6 +136,6 @@ async function validateIntermediateRepresentation(intermediateRepresentation, tr
|
|
|
129
136
|
valid,
|
|
130
137
|
};
|
|
131
138
|
}
|
|
132
|
-
const schemaValidationErrors = results.map(result => result.schemaValidationErrors);
|
|
133
|
-
throw new errors_1.TranslationError(copy_1.errorMessages.project.failedToTranslateProject,
|
|
139
|
+
const schemaValidationErrors = results.map(result => 'schemaValidationErrors' in result ? result.schemaValidationErrors : null);
|
|
140
|
+
throw new errors_1.TranslationError(copy_1.errorMessages.project.failedToTranslateProject, transformations, schemaValidationErrors, translationContext);
|
|
134
141
|
}
|