@forge/manifest 4.9.2 → 4.10.0-next.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/CHANGELOG.md +12 -0
- package/out/scopes/shipyard-scopes.json +2 -0
- package/out/text/errors.d.ts +3 -1
- package/out/text/errors.d.ts.map +1 -1
- package/out/text/errors.js +5 -3
- package/out/validators/resources-validator.d.ts.map +1 -1
- package/out/validators/resources-validator.js +40 -24
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @forge/manifest
|
|
2
2
|
|
|
3
|
+
## 4.10.0-next.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 6e015d7: Update validation logic to handle CSUIK manifests
|
|
8
|
+
|
|
9
|
+
## 4.9.3-next.0
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 59c693e: Update manifest definitions
|
|
14
|
+
|
|
3
15
|
## 4.9.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/out/text/errors.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare const errors: {
|
|
|
27
27
|
duplicateKeyFound: (key: string) => string;
|
|
28
28
|
wrongFunctionReference: (module: string, functionKey: string) => string;
|
|
29
29
|
wrongResourceReference: (module: string, resourceKey: string) => string;
|
|
30
|
+
wrongResourceType: (folder: string) => string;
|
|
30
31
|
singleEntryOfTheModule: (moduleType: string) => string;
|
|
31
32
|
singleEntryOfModuleWithoutConfigureAndStartedParams: (moduleType: string) => string;
|
|
32
33
|
singleEntryOfModuleWithConfigureParam: (moduleType: string) => string;
|
|
@@ -84,11 +85,12 @@ export declare const errors: {
|
|
|
84
85
|
};
|
|
85
86
|
};
|
|
86
87
|
resources: {
|
|
87
|
-
|
|
88
|
+
missingResource: (folder: string, key: string) => string;
|
|
88
89
|
emptyDirectory: (folder: string, key: string) => string;
|
|
89
90
|
missingEntrypoint: (folder: string, key: string) => string;
|
|
90
91
|
deprecatedCspPolicyDefinition: (folder: string) => string;
|
|
91
92
|
tooManyResourcesError: (limit: number) => string;
|
|
93
|
+
nonDirectory: (folder: string, key: string) => string;
|
|
92
94
|
};
|
|
93
95
|
deprecationInfo: {
|
|
94
96
|
app: {
|
package/out/text/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/text/errors.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM;8BACS,MAAM,KAAG,MAAM;2BACpB,MAAM;yBAEN,MAAM,GAAG,SAAS,QAAQ,MAAM,EAAE,UAAU,MAAM,GAAG,SAAS,KAAG,MAAM;;uBAO3E,MAAM,EAAE,EAAE,GAAG,SAAS,KAAG,MAAM;4BAI1B,MAAM,EAAE,KAAG,MAAM;mCACV,MAAM,SAAS,MAAM,mBAAmB,MAAM,KAAG,MAAM;mDAIvC,MAAM,KAAG,MAAM;4BAEtC,MAAM,EAAE,GAAG,SAAS,KAAG,MAAM;;;qCAMpB,MAAM,SAAS,MAAM,KAAG,MAAM;4CAEvB,MAAM,SAAS,MAAM,KAAG,MAAM;wCAElC,MAAM,SAAS,MAAM,EAAE,KAAG,MAAM;;;uCAMjC,MAAM,KAAG,MAAM;oCACpB,MAAM;iCAEP,MAAM,KAAG,MAAM;4CACJ,MAAM,KAAG,MAAM;;;gCAG3B,MAAM,KAAG,MAAM;6BACpB,MAAM;+BACJ,MAAM;iCACF,MAAM,KAAG,MAAM;yCACP,MAAM,eAAe,MAAM,KAAG,MAAM;yCAEpC,MAAM,eAAe,MAAM,KAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/text/errors.ts"],"names":[],"mappings":"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"}
|
package/out/text/errors.js
CHANGED
|
@@ -41,6 +41,7 @@ exports.errors = {
|
|
|
41
41
|
duplicateKeyFound: (key) => `found duplicate module key '${key}'`,
|
|
42
42
|
wrongFunctionReference: (module, functionKey) => `${module} references undefined function module with key '${functionKey}'`,
|
|
43
43
|
wrongResourceReference: (module, resourceKey) => `missing resource key '${resourceKey}' is being referenced by ${module} module`,
|
|
44
|
+
wrongResourceType: (folder) => `Client Side UI Kit resource (${folder}) cannot be a directory`,
|
|
44
45
|
singleEntryOfTheModule: (moduleType) => `Only a single entry of the ${moduleType} module can be defined in the manifest`,
|
|
45
46
|
singleEntryOfModuleWithoutConfigureAndStartedParams: (moduleType) => `The ${moduleType} module can only have a single entry that doesn’t include either useAsConfig or useAsGetStarted properties.`,
|
|
46
47
|
singleEntryOfModuleWithConfigureParam: (moduleType) => `The ${moduleType} module can only have a single entry that includes the useAsConfig property.`,
|
|
@@ -98,11 +99,12 @@ exports.errors = {
|
|
|
98
99
|
}
|
|
99
100
|
},
|
|
100
101
|
resources: {
|
|
101
|
-
|
|
102
|
+
missingResource: (folder, key) => `missing resource '${folder}' is being referenced by '${key}' in resources`,
|
|
102
103
|
emptyDirectory: (folder, key) => `empty directory '${folder}' is being referenced by '${key}' in resources`,
|
|
103
|
-
missingEntrypoint: (folder, key) => `missing index.html file in directory (${folder}) is being referenced by a
|
|
104
|
+
missingEntrypoint: (folder, key) => `missing index.html file in directory (${folder}) is being referenced by a Custom UI resource in ${key} module`,
|
|
104
105
|
deprecatedCspPolicyDefinition: (folder) => `The index.html file in the (${folder}) directory is using a deprecated method of defining CSP. To use the supported method, go to: https://go.atlassian.com/forge-content-security-and-egress-controls`,
|
|
105
|
-
tooManyResourcesError: (limit) => `document exceeds ${limit} resources
|
|
106
|
+
tooManyResourcesError: (limit) => `document exceeds ${limit} resources`,
|
|
107
|
+
nonDirectory: (folder, key) => `Custom UI resource must be a directory. (${folder}) in ${key} module is not a directory`
|
|
106
108
|
},
|
|
107
109
|
deprecationInfo: {
|
|
108
110
|
app: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources-validator.d.ts","sourceRoot":"","sources":["../../src/validators/resources-validator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAmB,MAAM,UAAU,CAAC;AAGrF,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAK3D,qBAAa,kBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IACnF,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"resources-validator.d.ts","sourceRoot":"","sources":["../../src/validators/resources-validator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAmB,MAAM,UAAU,CAAC;AAGrF,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAK3D,qBAAa,kBACX,YAAW,kBAAkB,CAAC,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,EAAE,cAAc,CAAC;IACnF,QAAQ,CACZ,QAAQ,EAAE,cAAc,CAAC,cAAc,CAAC,GAAG,SAAS,GACnD,OAAO,CAAC,wBAAwB,CAAC,cAAc,CAAC,CAAC;CAsKrD"}
|
|
@@ -37,33 +37,48 @@ class ResourcesValidator {
|
|
|
37
37
|
(0, utils_2.findInvalidResourceReferences)(module, resources).forEach((resourceKey) => {
|
|
38
38
|
validationErrors.push(Object.assign({ message: text_1.errors.modules.wrongResourceReference(moduleKey, resourceKey), reference: text_1.References.Resources, level: 'error' }, (0, utils_1.findPosition)(moduleKey, yamlContentByLine)));
|
|
39
39
|
});
|
|
40
|
+
const resourcePath = resourceMap.get(module.resource);
|
|
41
|
+
if (resourcePath === undefined)
|
|
42
|
+
return;
|
|
43
|
+
const resourcePathDir = (0, path_1.resolve)(resourcePath);
|
|
44
|
+
if (module.render === 'native') {
|
|
45
|
+
if (fs_1.default.lstatSync(resourcePathDir).isDirectory()) {
|
|
46
|
+
validationErrors.push(Object.assign({ message: text_1.errors.modules.wrongResourceType(resourcePath), reference: text_1.References.Resources, level: 'error' }, (0, utils_1.findPosition)(moduleKey, yamlContentByLine)));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
if (fs_1.default.lstatSync(resourcePathDir).isDirectory() &&
|
|
51
|
+
!fs_1.default.existsSync((0, path_1.resolve)(manifestDir, resourcePath, 'index.html'))) {
|
|
52
|
+
validationErrors.push(Object.assign({ message: text_1.errors.resources.missingEntrypoint(resourcePath, moduleKey), reference: text_1.References.Resources, level: 'error' }, (0, utils_1.findPosition)(resourcePath, yamlContentByLine)));
|
|
53
|
+
}
|
|
54
|
+
else if (!fs_1.default.lstatSync(resourcePathDir).isDirectory()) {
|
|
55
|
+
validationErrors.push(Object.assign({ message: text_1.errors.resources.nonDirectory(resourcePath, moduleKey), reference: text_1.References.Resources, level: 'error' }, (0, utils_1.findPosition)(resourcePath, yamlContentByLine)));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
40
58
|
});
|
|
41
59
|
});
|
|
42
60
|
(0, utils_1.getValidModules)(modules).forEach((moduleKey) => {
|
|
43
61
|
const uniquePaths = new Set(modules[moduleKey].map(({ resource }) => resourceMap.get(resource)));
|
|
44
62
|
uniquePaths.forEach((path) => {
|
|
45
63
|
var _a, _b, _c;
|
|
46
|
-
if (path)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
missingContentStylePermission: 'unsafe-inline'
|
|
65
|
-
} }, (0, utils_1.findPosition)(path, yamlContentByLine)));
|
|
66
|
-
}
|
|
64
|
+
if (!path)
|
|
65
|
+
return;
|
|
66
|
+
if (fs_1.default.existsSync((0, path_1.resolve)(manifestDir, path, 'index.html'))) {
|
|
67
|
+
const content = fs_1.default.readFileSync((0, path_1.resolve)(manifestDir, path, 'index.html'));
|
|
68
|
+
const $ = cheerio_1.default.load(content);
|
|
69
|
+
const cspContent = $('meta[http-equiv="Content-Security-Policy"]').attr('content');
|
|
70
|
+
if (cspContent) {
|
|
71
|
+
const cspStyleSrc = cspContent.split(';').find((s) => s.startsWith('style-src'));
|
|
72
|
+
if (cspStyleSrc === null || cspStyleSrc === void 0 ? void 0 : cspStyleSrc.includes("'unsafe-inline'")) {
|
|
73
|
+
const existingStylesPermissions = (_c = (_b = (_a = manifest.typedContent) === null || _a === void 0 ? void 0 : _a.permissions) === null || _b === void 0 ? void 0 : _b.content) === null || _c === void 0 ? void 0 : _c.styles;
|
|
74
|
+
let shouldShowError = false;
|
|
75
|
+
if (!(existingStylesPermissions === null || existingStylesPermissions === void 0 ? void 0 : existingStylesPermissions.length) || !(existingStylesPermissions === null || existingStylesPermissions === void 0 ? void 0 : existingStylesPermissions.includes('unsafe-inline'))) {
|
|
76
|
+
shouldShowError = true;
|
|
77
|
+
}
|
|
78
|
+
if (shouldShowError) {
|
|
79
|
+
validationErrors.push(Object.assign({ message: text_1.errors.resources.deprecatedCspPolicyDefinition(path), reference: text_1.References.Resources, level: 'error', metadata: {
|
|
80
|
+
missingContentStylePermission: 'unsafe-inline'
|
|
81
|
+
} }, (0, utils_1.findPosition)(path, yamlContentByLine)));
|
|
67
82
|
}
|
|
68
83
|
}
|
|
69
84
|
}
|
|
@@ -75,10 +90,11 @@ class ResourcesValidator {
|
|
|
75
90
|
.map((resource) => {
|
|
76
91
|
const { key, path } = resource;
|
|
77
92
|
const manifestDir = (0, path_1.dirname)(filePath);
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
const resourceDirPath = (0, path_1.resolve)(manifestDir, path);
|
|
94
|
+
if (!fs_1.default.existsSync(resourceDirPath)) {
|
|
95
|
+
return Object.assign({ message: text_1.errors.resources.missingResource(path, key), reference: text_1.References.Resources, level: 'error' }, (0, utils_1.findPosition)(path, yamlContentByLine));
|
|
80
96
|
}
|
|
81
|
-
else if (fs_1.default.
|
|
97
|
+
else if (fs_1.default.lstatSync(resourceDirPath).isDirectory() && fs_1.default.readdirSync(resourceDirPath).length === 0) {
|
|
82
98
|
return Object.assign({ message: text_1.errors.resources.emptyDirectory(path, key), reference: text_1.References.Resources, level: 'error' }, (0, utils_1.findPosition)(path, yamlContentByLine));
|
|
83
99
|
}
|
|
84
100
|
})
|