@hubspot/project-parsing-lib 0.2.2-beta.0 → 0.2.2-experimental.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/README.md +4 -35
- package/package.json +128 -22
- package/src/exports/constants.d.ts +1 -0
- package/src/exports/constants.js +1 -0
- package/src/exports/lang.d.ts +1 -0
- package/src/exports/lang.js +1 -0
- package/src/exports/migrate.d.ts +1 -0
- package/src/exports/migrate.js +1 -0
- package/src/exports/profiles.d.ts +3 -0
- package/src/exports/profiles.js +2 -0
- package/src/exports/projects.d.ts +4 -0
- package/src/exports/projects.js +3 -0
- package/src/exports/schema.d.ts +2 -0
- package/src/exports/schema.js +1 -0
- package/src/exports/themes.d.ts +2 -0
- package/src/exports/themes.js +1 -0
- package/src/exports/transform.d.ts +2 -0
- package/src/exports/transform.js +1 -0
- package/src/exports/translate.d.ts +3 -0
- package/src/exports/translate.js +2 -0
- package/src/exports/uid.d.ts +1 -0
- package/src/exports/uid.js +1 -0
- package/src/exports/validation.d.ts +3 -0
- package/src/exports/validation.js +2 -0
- package/src/exports/workspaces.d.ts +2 -0
- package/src/exports/workspaces.js +1 -0
- package/src/lang/copy.d.ts +12 -1
- package/src/lang/copy.js +33 -32
- package/src/lib/constants.d.ts +56 -29
- package/src/lib/constants.js +180 -126
- package/src/lib/errors.d.ts +3 -3
- package/src/lib/errors.js +25 -33
- package/src/lib/files.d.ts +3 -3
- package/src/lib/files.js +46 -42
- package/src/lib/localDev.d.ts +4 -0
- package/src/lib/localDev.js +72 -0
- package/src/lib/migrate.d.ts +1 -0
- package/src/lib/migrate.js +43 -45
- package/src/lib/migrateThemes.d.ts +25 -0
- package/src/lib/migrateThemes.js +120 -0
- package/src/lib/minimalArboristTree.d.ts +118 -0
- package/src/lib/minimalArboristTree.js +32 -0
- package/src/lib/platformVersion.d.ts +4 -0
- package/src/lib/platformVersion.js +30 -0
- package/src/lib/profiles.d.ts +6 -1
- package/src/lib/profiles.js +95 -40
- package/src/lib/project.js +22 -17
- package/src/lib/schemas.d.ts +2 -2
- package/src/lib/schemas.js +11 -11
- package/src/lib/transform.d.ts +4 -2
- package/src/lib/transform.js +109 -59
- package/src/lib/translate.d.ts +3 -0
- package/src/lib/translate.js +62 -0
- package/src/lib/types.d.ts +37 -6
- package/src/lib/types.js +1 -2
- package/src/lib/uid.d.ts +2 -0
- package/src/lib/uid.js +14 -9
- package/src/lib/utils.d.ts +3 -0
- package/src/lib/utils.js +16 -0
- package/src/lib/validation.d.ts +4 -4
- package/src/lib/validation.js +66 -53
- package/src/lib/workspaces.d.ts +113 -0
- package/src/lib/workspaces.js +403 -0
- package/src/index.d.ts +0 -18
- package/src/index.js +0 -87
package/src/lib/types.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { ErrorObject } from 'ajv
|
|
1
|
+
import type { ErrorObject } from 'ajv';
|
|
2
2
|
export type Dependencies = Record<string, string | string[]>;
|
|
3
|
-
export interface
|
|
3
|
+
export interface ComponentPermissions {
|
|
4
|
+
requiredScopes?: string[];
|
|
5
|
+
optionalScopes?: string[];
|
|
6
|
+
conditionallyRequiredScopes?: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface ComponentMeta {
|
|
4
9
|
uid: string;
|
|
5
10
|
type: string;
|
|
6
11
|
config: unknown;
|
|
7
12
|
dependencies?: Dependencies;
|
|
13
|
+
permissions?: ComponentPermissions;
|
|
8
14
|
}
|
|
9
15
|
export interface FileActionResult {
|
|
10
16
|
file: string;
|
|
@@ -15,7 +21,7 @@ export interface FileLoadResult extends FileActionResult {
|
|
|
15
21
|
content?: string;
|
|
16
22
|
}
|
|
17
23
|
export interface FileParseResult extends FileActionResult {
|
|
18
|
-
content?:
|
|
24
|
+
content?: ComponentMeta;
|
|
19
25
|
}
|
|
20
26
|
export interface IntermediateRepresentationNode {
|
|
21
27
|
componentType: string;
|
|
@@ -24,22 +30,39 @@ export interface IntermediateRepresentationNode {
|
|
|
24
30
|
uid: string;
|
|
25
31
|
config: unknown;
|
|
26
32
|
files: unknown;
|
|
33
|
+
permissions?: ComponentPermissions;
|
|
34
|
+
}
|
|
35
|
+
export type BEProfileVariableType = 'PROFILE_INT' | 'PROFILE_LONG' | 'PROFILE_STRING' | 'PROFILE_BOOLEAN';
|
|
36
|
+
export interface BEProfileVariables {
|
|
37
|
+
[key: string]: {
|
|
38
|
+
variableType: BEProfileVariableType;
|
|
39
|
+
value: HSProfileVariableType;
|
|
40
|
+
};
|
|
27
41
|
}
|
|
28
42
|
export interface IntermediateRepresentation {
|
|
29
43
|
intermediateNodesIndexedByUid: {
|
|
30
44
|
[key: string]: IntermediateRepresentationNode;
|
|
31
45
|
};
|
|
46
|
+
profileData?: {
|
|
47
|
+
vars: {
|
|
48
|
+
profileVariables: BEProfileVariables;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
32
51
|
}
|
|
33
52
|
export interface IntermediateRepresentationNodeLocalDev extends IntermediateRepresentationNode {
|
|
34
53
|
localDev: {
|
|
35
54
|
componentRoot: string;
|
|
36
55
|
componentConfigPath: string;
|
|
56
|
+
configUpdatedSinceLastUpload: boolean;
|
|
57
|
+
removed: boolean;
|
|
58
|
+
parsingErrors: string[];
|
|
37
59
|
};
|
|
38
60
|
}
|
|
39
61
|
export interface IntermediateRepresentationLocalDev {
|
|
40
62
|
intermediateNodesIndexedByUid: {
|
|
41
63
|
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
42
64
|
};
|
|
65
|
+
profileData: HSProfileVariables;
|
|
43
66
|
}
|
|
44
67
|
export type Transformation = {
|
|
45
68
|
intermediateRepresentation?: IntermediateRepresentationNode | null;
|
|
@@ -58,9 +81,17 @@ export interface TranslationOptions {
|
|
|
58
81
|
skipValidation?: boolean;
|
|
59
82
|
profile?: string;
|
|
60
83
|
}
|
|
84
|
+
export interface TranslationOptionsLocalDev extends TranslationOptions {
|
|
85
|
+
projectNodesAtLastUpload?: {
|
|
86
|
+
[key: string]: IntermediateRepresentationNodeLocalDev;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
type HSProfileVariableType = string | number | boolean;
|
|
90
|
+
export type HSProfileVariables = {
|
|
91
|
+
[key: string]: HSProfileVariableType;
|
|
92
|
+
};
|
|
61
93
|
export interface HsProfileFile {
|
|
62
94
|
accountId: number;
|
|
63
|
-
variables?:
|
|
64
|
-
[key: string]: string | number | boolean;
|
|
65
|
-
};
|
|
95
|
+
variables?: HSProfileVariables;
|
|
66
96
|
}
|
|
97
|
+
export {};
|
package/src/lib/types.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
package/src/lib/uid.d.ts
CHANGED
package/src/lib/uid.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const copy_1 = require("../lang/copy");
|
|
5
|
-
function validateUid(uid) {
|
|
1
|
+
import { errorMessages } from '../lang/copy.js';
|
|
2
|
+
export const MAX_UID_LENGTH = 64;
|
|
3
|
+
export function validateUid(uid) {
|
|
6
4
|
if (uid === '' || !uid) {
|
|
7
|
-
return
|
|
5
|
+
return errorMessages.validation.emptyUid;
|
|
8
6
|
}
|
|
9
|
-
if (uid.length >
|
|
10
|
-
return
|
|
7
|
+
if (uid.length > MAX_UID_LENGTH) {
|
|
8
|
+
return errorMessages.validation.uidTooLong;
|
|
11
9
|
}
|
|
12
10
|
if (!/^[a-zA-Z0-9_\-.]+$/.test(uid)) {
|
|
13
|
-
return
|
|
11
|
+
return errorMessages.validation.invalidUid;
|
|
14
12
|
}
|
|
15
13
|
}
|
|
14
|
+
export function coerceToValidUid(potentialUid) {
|
|
15
|
+
if (typeof potentialUid !== 'string') {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const newUid = potentialUid.replace(/[^a-zA-Z0-9_\-.]/g, '');
|
|
19
|
+
return newUid.length === 0 ? undefined : newUid.substring(0, MAX_UID_LENGTH);
|
|
20
|
+
}
|
package/src/lib/utils.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { PROFILE_VARIABLE_TYPES } from './constants.js';
|
|
3
|
+
export function loadJsonFile(filename) {
|
|
4
|
+
return JSON.parse(fs.readFileSync(filename, {
|
|
5
|
+
encoding: 'utf-8',
|
|
6
|
+
}));
|
|
7
|
+
}
|
|
8
|
+
export function getJavaNumberType(value) {
|
|
9
|
+
const JAVA_INT_MIN = -2_147_483_648;
|
|
10
|
+
const JAVA_INT_MAX = 2_147_483_647;
|
|
11
|
+
// Check if the value fits in Java int range
|
|
12
|
+
if (value >= JAVA_INT_MIN && value <= JAVA_INT_MAX) {
|
|
13
|
+
return PROFILE_VARIABLE_TYPES.PROFILE_INT;
|
|
14
|
+
}
|
|
15
|
+
return PROFILE_VARIABLE_TYPES.PROFILE_LONG;
|
|
16
|
+
}
|
package/src/lib/validation.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CompiledError, IntermediateRepresentation, Transformation, TranslationContext } from './types';
|
|
2
|
-
import
|
|
1
|
+
import { CompiledError, IntermediateRepresentation, Transformation, TranslationContext } from './types.js';
|
|
2
|
+
import { Ajv2020, ValidateFunction } from 'ajv/dist/2020.js';
|
|
3
3
|
export type ValidResult = {
|
|
4
4
|
valid: true;
|
|
5
5
|
errors?: null;
|
|
@@ -10,5 +10,5 @@ export type ValidationResults = {
|
|
|
10
10
|
errors?: CompiledError;
|
|
11
11
|
schemaValidationErrors?: ValidateFunction['errors'];
|
|
12
12
|
} | ValidResult;
|
|
13
|
-
export declare function createAjvInstance():
|
|
14
|
-
export declare function validateIntermediateRepresentation(intermediateRepresentation: IntermediateRepresentation,
|
|
13
|
+
export declare function createAjvInstance(): Ajv2020;
|
|
14
|
+
export declare function validateIntermediateRepresentation(intermediateRepresentation: IntermediateRepresentation, transformations: Transformation[], translationContext: TranslationContext): Promise<ValidResult>;
|
package/src/lib/validation.js
CHANGED
|
@@ -1,85 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
(
|
|
1
|
+
import { getIntermediateRepresentationSchema } from './schemas.js';
|
|
2
|
+
import { Ajv2020, } from 'ajv/dist/2020.js';
|
|
3
|
+
import { compileError, TranslationError } from './errors.js';
|
|
4
|
+
import { errorMessages } from '../lang/copy.js';
|
|
5
|
+
import { AUTO_GENERATED_COMPONENT_TYPES, Components } from './constants.js';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { findTransformationByUid, mapToUserFacingType } from './transform.js';
|
|
8
|
+
import { supportsComponentPermissions } from './platformVersion.js';
|
|
9
|
+
import { validateUid } from './uid.js';
|
|
10
|
+
// ajv-formats does not play nicely with ESM and TS
|
|
11
|
+
import addFormatsModule from 'ajv-formats';
|
|
12
|
+
const addFormats = addFormatsModule;
|
|
13
|
+
export function createAjvInstance() {
|
|
14
|
+
const ajv = new Ajv2020({
|
|
15
|
+
allErrors: true,
|
|
16
|
+
code: { esm: true },
|
|
17
|
+
strict: false, // Allow Draft 2020-12 features
|
|
18
|
+
});
|
|
19
|
+
addFormats(ajv);
|
|
20
20
|
return ajv;
|
|
21
21
|
}
|
|
22
|
-
function validateIntermediateRepresentationNode(schema, transformation, irNode,
|
|
23
|
-
if (
|
|
22
|
+
function validateIntermediateRepresentationNode(schema, transformation, irNode, translationContext) {
|
|
23
|
+
if (AUTO_GENERATED_COMPONENT_TYPES.includes(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:
|
|
32
|
+
errors: 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(errorMessages.validation.missingUid);
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
|
-
const uidValidationResult =
|
|
41
|
+
const uidValidationResult = 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(errorMessages.validation.missingConfig);
|
|
48
48
|
// If there is no config block, there is nothing to validation
|
|
49
49
|
shouldSkipValidation = true;
|
|
50
50
|
}
|
|
51
|
+
if (irNode.permissions &&
|
|
52
|
+
!supportsComponentPermissions(translationContext.platformVersion)) {
|
|
53
|
+
transformation.fileParseResult.errors.push(errorMessages.validation.permissionsNotSupported(translationContext.platformVersion));
|
|
54
|
+
}
|
|
51
55
|
if (!schema[irNode.componentType]) {
|
|
52
56
|
if (!irNode.componentType) {
|
|
53
|
-
transformation
|
|
57
|
+
transformation.fileParseResult.errors.push(errorMessages.validation.missingType);
|
|
54
58
|
}
|
|
55
59
|
else {
|
|
56
|
-
transformation
|
|
60
|
+
transformation.fileParseResult.errors.push(errorMessages.validation.unsupportedType(irNode.componentType));
|
|
57
61
|
}
|
|
58
62
|
// If there is no schema for the component type, there is no way to validate
|
|
59
63
|
shouldSkipValidation = true;
|
|
60
64
|
}
|
|
61
|
-
const userFacingType =
|
|
62
|
-
const component =
|
|
65
|
+
const userFacingType = mapToUserFacingType(irNode.componentType);
|
|
66
|
+
const component = Components[userFacingType];
|
|
63
67
|
if (userFacingType && component) {
|
|
64
68
|
const expectedParentDir = component.parentComponent
|
|
65
|
-
?
|
|
69
|
+
? Components[component.parentComponent].dir
|
|
66
70
|
: '';
|
|
67
|
-
const expectedLocation =
|
|
68
|
-
const actualLocation =
|
|
71
|
+
const expectedLocation = path.join(expectedParentDir, component.dir);
|
|
72
|
+
const actualLocation = path.dirname(transformation.fileParseResult.file);
|
|
69
73
|
if (expectedLocation !== actualLocation) {
|
|
70
|
-
transformation
|
|
74
|
+
transformation.fileParseResult.errors.push(errorMessages.validation.wrongDirectoryForComponent(actualLocation, userFacingType, component, path.join(translationContext.projectSourceDir, expectedLocation)));
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
if (shouldSkipValidation) {
|
|
74
78
|
return {
|
|
75
79
|
valid: false,
|
|
76
|
-
errors:
|
|
80
|
+
errors: compileError(transformation),
|
|
77
81
|
};
|
|
78
82
|
}
|
|
79
83
|
const validate = ajv.compile(schema[irNode.componentType]);
|
|
80
84
|
const valid = validate(irNode.config);
|
|
81
85
|
if (valid) {
|
|
82
|
-
const { errors } = transformation
|
|
86
|
+
const { errors } = transformation.fileParseResult;
|
|
83
87
|
// Even through it passed the schema validation, it may have had other errors along the way
|
|
84
88
|
return errors.length === 0
|
|
85
89
|
? {
|
|
@@ -87,7 +91,7 @@ function validateIntermediateRepresentationNode(schema, transformation, irNode,
|
|
|
87
91
|
}
|
|
88
92
|
: {
|
|
89
93
|
valid: false,
|
|
90
|
-
errors:
|
|
94
|
+
errors: compileError(transformation),
|
|
91
95
|
};
|
|
92
96
|
}
|
|
93
97
|
return {
|
|
@@ -95,18 +99,24 @@ function validateIntermediateRepresentationNode(schema, transformation, irNode,
|
|
|
95
99
|
schemaValidationErrors: validate.errors,
|
|
96
100
|
};
|
|
97
101
|
}
|
|
98
|
-
async function validateIntermediateRepresentation(intermediateRepresentation,
|
|
99
|
-
const
|
|
102
|
+
export async function validateIntermediateRepresentation(intermediateRepresentation, transformations, translationContext) {
|
|
103
|
+
const hasAnyFileParseErrors = transformations.some(t => t.fileParseResult.errors.length > 0);
|
|
104
|
+
const schema = await getIntermediateRepresentationSchema(translationContext);
|
|
100
105
|
const potentialDuplicatesByComponent = {};
|
|
101
|
-
const results = Object.values(intermediateRepresentation.intermediateNodesIndexedByUid).map(
|
|
102
|
-
const userFacingType =
|
|
103
|
-
const component =
|
|
106
|
+
const results = Object.values(intermediateRepresentation.intermediateNodesIndexedByUid).map(irNode => {
|
|
107
|
+
const userFacingType = mapToUserFacingType(irNode.componentType);
|
|
108
|
+
const component = Components[userFacingType];
|
|
104
109
|
if (component && component.singularComponent) {
|
|
105
|
-
potentialDuplicatesByComponent[userFacingType] =
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
potentialDuplicatesByComponent[userFacingType] =
|
|
111
|
+
potentialDuplicatesByComponent[userFacingType]
|
|
112
|
+
? [...potentialDuplicatesByComponent[userFacingType], irNode]
|
|
113
|
+
: [irNode];
|
|
108
114
|
}
|
|
109
|
-
|
|
115
|
+
const transformation = findTransformationByUid(transformations, irNode.uid);
|
|
116
|
+
if (!transformation) {
|
|
117
|
+
return { valid: false, errors: [errorMessages.validation.missingUid] };
|
|
118
|
+
}
|
|
119
|
+
return validateIntermediateRepresentationNode(schema, transformation, irNode, translationContext);
|
|
110
120
|
});
|
|
111
121
|
let hasDuplicates = false;
|
|
112
122
|
Object.entries(potentialDuplicatesByComponent).forEach(([componentType, potentialDuplicates]) => {
|
|
@@ -115,17 +125,20 @@ async function validateIntermediateRepresentation(intermediateRepresentation, tr
|
|
|
115
125
|
}
|
|
116
126
|
hasDuplicates = true;
|
|
117
127
|
potentialDuplicates.forEach(duplicate => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
const potentialDuplicateTransformation = findTransformationByUid(transformations, duplicate.uid);
|
|
129
|
+
if (potentialDuplicateTransformation) {
|
|
130
|
+
potentialDuplicateTransformation.fileParseResult.errors.push(errorMessages.project.duplicateComponent(componentType));
|
|
131
|
+
}
|
|
121
132
|
});
|
|
122
133
|
});
|
|
123
|
-
const valid = !
|
|
134
|
+
const valid = !hasAnyFileParseErrors &&
|
|
135
|
+
!hasDuplicates &&
|
|
136
|
+
results.every(result => result.valid);
|
|
124
137
|
if (valid) {
|
|
125
138
|
return {
|
|
126
139
|
valid,
|
|
127
140
|
};
|
|
128
141
|
}
|
|
129
|
-
const schemaValidationErrors = results.map(result => result.schemaValidationErrors);
|
|
130
|
-
throw new
|
|
142
|
+
const schemaValidationErrors = results.map(result => 'schemaValidationErrors' in result ? result.schemaValidationErrors : null);
|
|
143
|
+
throw new TranslationError(errorMessages.project.failedToTranslateProject, transformations, schemaValidationErrors, translationContext);
|
|
131
144
|
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error thrown when a workspace directory cannot be resolved
|
|
3
|
+
*/
|
|
4
|
+
export declare class WorkspaceResolutionError extends Error {
|
|
5
|
+
workspaceDir: string;
|
|
6
|
+
sourcePackageJson: string;
|
|
7
|
+
constructor(workspaceDir: string, sourcePackageJson: string, cause?: Error);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Error thrown when a file: dependency cannot be resolved
|
|
11
|
+
*/
|
|
12
|
+
export declare class FileDependencyResolutionError extends Error {
|
|
13
|
+
packageName: string;
|
|
14
|
+
dependencyPath: string;
|
|
15
|
+
sourcePackageJson: string;
|
|
16
|
+
constructor(packageName: string, dependencyPath: string, sourcePackageJson: string, cause?: Error);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Error thrown when a `workspace:` protocol dependency does not match any known
|
|
20
|
+
* workspace member. npm itself does not support the `workspace:` protocol —
|
|
21
|
+
* only pnpm and yarn berry do — so the install fails with a confusing message
|
|
22
|
+
* server-side. Surface a clearer error up front.
|
|
23
|
+
*/
|
|
24
|
+
export declare class OrphanWorkspaceProtocolError extends Error {
|
|
25
|
+
packageName: string;
|
|
26
|
+
sourcePackageJson: string;
|
|
27
|
+
constructor(packageName: string, sourcePackageJson: string);
|
|
28
|
+
}
|
|
29
|
+
interface PackageJson {
|
|
30
|
+
name?: string;
|
|
31
|
+
workspaces?: string[] | {
|
|
32
|
+
packages?: string[];
|
|
33
|
+
nohoist?: string[];
|
|
34
|
+
};
|
|
35
|
+
dependencies?: Record<string, string>;
|
|
36
|
+
}
|
|
37
|
+
export interface ParsedPackageJson {
|
|
38
|
+
path: string;
|
|
39
|
+
dir: string;
|
|
40
|
+
content: PackageJson | null;
|
|
41
|
+
}
|
|
42
|
+
export interface WorkspaceMapping {
|
|
43
|
+
workspaceDir: string;
|
|
44
|
+
sourcePackageJsonPath: string;
|
|
45
|
+
}
|
|
46
|
+
export type FileDependencyKind = 'directory' | 'tarball';
|
|
47
|
+
export type LocalDependencyProtocol = 'file' | 'link';
|
|
48
|
+
export interface FileDependencyMapping {
|
|
49
|
+
packageName: string;
|
|
50
|
+
localPath: string;
|
|
51
|
+
sourcePackageJsonPath: string;
|
|
52
|
+
kind: FileDependencyKind;
|
|
53
|
+
protocol: LocalDependencyProtocol;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Parses a `file:` or `link:` dependency spec into its protocol and raw path.
|
|
57
|
+
* Handles all npm-supported shapes:
|
|
58
|
+
* - file:./relative/path
|
|
59
|
+
* - file:relative/path (no leading slash/dot)
|
|
60
|
+
* - file:/absolute/path
|
|
61
|
+
* - file://./relative — npm-style file URL with relative path
|
|
62
|
+
* - file:///absolute — file URL with absolute path
|
|
63
|
+
* - link:./relative/path (symlink semantics for directories only)
|
|
64
|
+
*/
|
|
65
|
+
export declare function parseLocalSpec(spec: string): {
|
|
66
|
+
protocol: LocalDependencyProtocol;
|
|
67
|
+
rawPath: string;
|
|
68
|
+
} | null;
|
|
69
|
+
/**
|
|
70
|
+
* Finds and parses all package.json files in a directory.
|
|
71
|
+
* This is the single entry point for discovering package.json files and parsing their contents.
|
|
72
|
+
*/
|
|
73
|
+
export declare function findAndParsePackageJsonFiles(srcDir: string): Promise<ParsedPackageJson[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Resolves workspace glob patterns to actual directories.
|
|
76
|
+
*
|
|
77
|
+
* Uses @npmcli/map-workspaces (npm's reference impl) so that negation patterns
|
|
78
|
+
* like `["packages/*", "!packages/excluded"]` are honored — a hand-rolled
|
|
79
|
+
* per-pattern glob() silently accepted negations without actually excluding.
|
|
80
|
+
*/
|
|
81
|
+
export declare function resolveWorkspaceDirectories(baseDir: string, workspaceGlobs: string[]): Promise<string[]>;
|
|
82
|
+
/**
|
|
83
|
+
* Collects all workspace directories that need to be uploaded.
|
|
84
|
+
* Handles edge cases like circular references, symlinks, and overlapping paths.
|
|
85
|
+
* Returns mappings that track which package.json defined each workspace.
|
|
86
|
+
*/
|
|
87
|
+
export declare function collectWorkspaceDirectories(parsedPackageJsons: ParsedPackageJson[]): Promise<WorkspaceMapping[]>;
|
|
88
|
+
/**
|
|
89
|
+
* Collects all `file:` and `link:` dependencies that need to be uploaded.
|
|
90
|
+
* Returns mappings that track the package name, resolved path, source
|
|
91
|
+
* package.json, kind (directory vs tarball) and protocol (file vs link).
|
|
92
|
+
*/
|
|
93
|
+
export declare function collectFileDependencies(parsedPackageJsons: ParsedPackageJson[]): Promise<FileDependencyMapping[]>;
|
|
94
|
+
/**
|
|
95
|
+
* Validates that every `workspace:` protocol dependency in the parsed package
|
|
96
|
+
* trees matches a known workspace member. Throws OrphanWorkspaceProtocolError
|
|
97
|
+
* for the first orphan found.
|
|
98
|
+
*
|
|
99
|
+
* npm itself does not implement the `workspace:` protocol; only pnpm and yarn
|
|
100
|
+
* berry do. If a project uses `workspace:*` without a matching member declared
|
|
101
|
+
* under `workspaces`, the install fails server-side with a confusing message —
|
|
102
|
+
* fail fast with a clearer one.
|
|
103
|
+
*/
|
|
104
|
+
export declare function validateWorkspaceProtocolDependencies(parsedPackageJsons: ParsedPackageJson[], workspaceMappings: WorkspaceMapping[]): void;
|
|
105
|
+
/**
|
|
106
|
+
* Returns the set of files that npm would include when publishing a package.
|
|
107
|
+
* Uses npm-packlist which respects the "files" field in package.json,
|
|
108
|
+
* .npmignore, and .gitignore rules.
|
|
109
|
+
*
|
|
110
|
+
* @throws Error if packlist fails to generate the file list
|
|
111
|
+
*/
|
|
112
|
+
export declare function getPackableFiles(dir: string): Promise<Set<string>>;
|
|
113
|
+
export {};
|