@hubspot/project-parsing-lib 0.10.0-beta.0 → 0.10.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.
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@hubspot/project-parsing-lib",
3
- "version": "0.10.0-beta.0",
3
+ "version": "0.10.0",
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
- "ts-node": "^10.9.2",
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": "ts-node ./scripts/build.ts",
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": "yarn ts-node ./scripts/release.ts 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 transformation = (0, transform_1.transform)(metafileContents, translationContext, hsProfileContents);
25
- const intermediateRepresentation = (0, transform_1.getIntermediateRepresentation)(transformation, hsProfileContents, skipValidation);
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, transformation, translationContext);
28
+ await (0, validation_1.validateIntermediateRepresentation)(intermediateRepresentation, transformations, translationContext);
29
29
  }
30
30
  return intermediateRepresentation;
31
31
  }
@@ -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[];
@@ -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 = {};
@@ -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, transformation: Transformation[], translationContext: TranslationContext): Promise<ValidResult>;
14
+ export declare function validateIntermediateRepresentation(intermediateRepresentation: IntermediateRepresentation, transformations: Transformation[], translationContext: TranslationContext): Promise<ValidResult>;
@@ -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, index, translationContext) {
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[index].fileParseResult.errors.length > 0) {
29
+ if (transformation.fileParseResult.errors.length > 0) {
30
30
  return {
31
31
  valid: false,
32
- errors: (0, errors_1.compileError)(transformation[index]),
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[index].fileParseResult.errors.push(copy_1.errorMessages.validation.missingUid);
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[index].fileParseResult.errors.push(uidValidationResult);
43
+ transformation.fileParseResult.errors.push(uidValidationResult);
44
44
  }
45
45
  }
46
46
  if (!irNode.config) {
47
- transformation[index].fileParseResult.errors.push(copy_1.errorMessages.validation.missingConfig);
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[index].fileParseResult.errors.push(copy_1.errorMessages.validation.missingType);
53
+ transformation.fileParseResult.errors.push(copy_1.errorMessages.validation.missingType);
54
54
  }
55
55
  else {
56
- transformation[index].fileParseResult.errors.push(copy_1.errorMessages.validation.unsupportedType(irNode.componentType));
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[index].fileParseResult.file);
68
+ const actualLocation = path_1.default.dirname(transformation.fileParseResult.file);
69
69
  if (expectedLocation !== actualLocation) {
70
- transformation[index].fileParseResult.errors.push(copy_1.errorMessages.validation.wrongDirectoryForComponent(actualLocation, userFacingType, component, path_1.default.join(translationContext.projectSourceDir, expectedLocation)));
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[index]),
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[index].fileParseResult;
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[index]),
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, transformation, translationContext) {
99
- const hasAnyFileParseErrors = transformation.some(t => t.fileParseResult.errors.length > 0);
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((irNode, index) => {
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
- return validateIntermediateRepresentationNode(schema, transformation, irNode, index, translationContext);
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
- transformation
120
- .find(transform => transform.intermediateRepresentation?.uid === duplicate.uid)
121
- ?.fileParseResult.errors.push(copy_1.errorMessages.project.duplicateComponent(componentType));
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, transformation, schemaValidationErrors, translationContext);
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
  }