aws-delivlib 13.5.19 → 13.6.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/README.md +30 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -1
- package/lib/index.ts +1 -0
- package/lib/package-integrity/handler/JSONStream.d.ts +29 -0
- package/lib/package-integrity/handler/integrity.d.ts +103 -0
- package/lib/package-integrity/handler/integrity.js +238 -0
- package/lib/package-integrity/handler/integrity.ts +316 -0
- package/lib/package-integrity/handler/repository.d.ts +81 -0
- package/lib/package-integrity/handler/repository.js +111 -0
- package/lib/package-integrity/handler/repository.ts +185 -0
- package/lib/package-integrity/handler/validate.bundle.js +603534 -0
- package/lib/package-integrity/handler/validate.d.ts +2 -0
- package/lib/package-integrity/handler/validate.js +37 -0
- package/lib/package-integrity/handler/validate.sh +5 -0
- package/lib/package-integrity/handler/validate.ts +41 -0
- package/lib/package-integrity/index.d.ts +1 -0
- package/lib/package-integrity/index.js +14 -0
- package/lib/package-integrity/index.ts +1 -0
- package/lib/package-integrity/integrity.d.ts +64 -0
- package/lib/package-integrity/integrity.js +64 -0
- package/lib/package-integrity/integrity.ts +112 -0
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -815,6 +815,36 @@ const stack = new MyStack(...);
|
|
|
815
815
|
Aspects.of(stack).add(new EcrMirrorAspect(ecrMirrorStack.mirror));
|
|
816
816
|
```
|
|
817
817
|
|
|
818
|
+
## Package Integrity
|
|
819
|
+
|
|
820
|
+
To ensure the artifacts published into package managers exactly correspond to your source code, delivlib offers a `PackageIntegrityValidation` construct.
|
|
821
|
+
It will perform periodic integrity checks, comparing the published artifact against an artifact directly build from source code.
|
|
822
|
+
|
|
823
|
+
This can help detect scenarios where your publishing platform may have been compromised, and your packages no longer contain the expected bits.
|
|
824
|
+
|
|
825
|
+
```ts
|
|
826
|
+
// first import the secret containing your github token secret.
|
|
827
|
+
// the secret value should be the token in plain text.
|
|
828
|
+
const token = sm.Secret.fromSecretCompleteArn(stack, 'GitHubSecret', '<sercet-arn>');
|
|
829
|
+
|
|
830
|
+
// validate integrity of your package, hosted in a github repository.
|
|
831
|
+
new PackageIntegrityValidation(stack, 'PackageValidation', {
|
|
832
|
+
repository: '<repository-slug>',
|
|
833
|
+
buildImage: codebuild.LinuxBuildImage.fromDockerRegistry('<docker-image>'),
|
|
834
|
+
githubTokenSecret: token,
|
|
835
|
+
});
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
At a high level, the validation is performed like so:
|
|
839
|
+
|
|
840
|
+
1. Clone the GitHub repository and checkout to the latest tag.
|
|
841
|
+
2. Build the repository to produce local artifacts from the source code.
|
|
842
|
+
3. Download the corresponding artifacts from package managers.
|
|
843
|
+
4. Compare.
|
|
844
|
+
|
|
845
|
+
By default the validation will run once a day, but you can configure its schedule using the `schedule` option.
|
|
846
|
+
If the validation fails, a CloudWatch alarm will be triggered, which is accessible via the `failureAlarm` property.
|
|
847
|
+
|
|
818
848
|
## Contributing
|
|
819
849
|
|
|
820
850
|
See the [contribution guide](./CONTRIBUTING.md) for details on how to submit
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -27,4 +27,5 @@ __exportStar(require("./code-signing"), exports);
|
|
|
27
27
|
__exportStar(require("./pull-request"), exports);
|
|
28
28
|
__exportStar(require("./chime-notifier"), exports);
|
|
29
29
|
__exportStar(require("./pipeline-notifications"), exports);
|
|
30
|
-
|
|
30
|
+
__exportStar(require("./package-integrity"), exports);
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBQSwrQ0FBNkI7QUFDN0IsMkNBQXlCO0FBQ3pCLCtDQUE2QjtBQUM3QixpREFBK0I7QUFDL0Isb0RBQWtDO0FBQ2xDLHNEQUFvQztBQUNwQyxnREFBOEI7QUFDOUIsNkNBQTJCO0FBQzNCLCtDQUE2QjtBQUM3QixrREFBZ0M7QUFDaEMseUNBQXVCO0FBQ3ZCLDhDQUE0QjtBQUM1QixnREFBOEI7QUFDOUIsaURBQStCO0FBQy9CLGlEQUErQjtBQUMvQixtREFBaUM7QUFDakMsMkRBQXlDO0FBQ3pDLHNEQUFvQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vYXV0by1idWlsZCc7XG5leHBvcnQgKiBmcm9tICcuL2NhbmFyeSc7XG5leHBvcnQgKiBmcm9tICcuL2J1aWxkLXNwZWMnO1xuZXhwb3J0ICogZnJvbSAnLi9jb2RlLXNpZ25pbmcnO1xuZXhwb3J0ICogZnJvbSAnLi9jcmVkZW50aWFsLXBhaXInO1xuZXhwb3J0ICogZnJvbSAnLi9vcGVuLXBncC1rZXktcGFpcic7XG5leHBvcnQgKiBmcm9tICcuL3Blcm1pc3Npb25zJztcbmV4cG9ydCAqIGZyb20gJy4vcGlwZWxpbmUnO1xuZXhwb3J0ICogZnJvbSAnLi9wdWJsaXNoaW5nJztcbmV4cG9ydCAqIGZyb20gJy4vcmVnaXN0cnktc3luYyc7XG5leHBvcnQgKiBmcm9tICcuL3JlcG8nO1xuZXhwb3J0ICogZnJvbSAnLi9zaGVsbGFibGUnO1xuZXhwb3J0ICogZnJvbSAnLi9zaWduaW5nLWtleSc7XG5leHBvcnQgKiBmcm9tICcuL2NvZGUtc2lnbmluZyc7XG5leHBvcnQgKiBmcm9tICcuL3B1bGwtcmVxdWVzdCc7XG5leHBvcnQgKiBmcm9tICcuL2NoaW1lLW5vdGlmaWVyJztcbmV4cG9ydCAqIGZyb20gJy4vcGlwZWxpbmUtbm90aWZpY2F0aW9ucyc7XG5leHBvcnQgKiBmcm9tICcuL3BhY2thZ2UtaW50ZWdyaXR5JztcbiJdfQ==
|
package/lib/index.ts
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Partial hand-written declarations for the JSONStream module. Refer to the JS
|
|
3
|
+
* module's documentation for additional operations, and more explanations on
|
|
4
|
+
* possible usage.
|
|
5
|
+
*
|
|
6
|
+
* @see https://github.com/dominictarr/JSONStream
|
|
7
|
+
*/
|
|
8
|
+
declare module 'JSONStream' {
|
|
9
|
+
|
|
10
|
+
export function parse(pattern: any, map?: (value: any) => any): JSONStream;
|
|
11
|
+
export function parse(patterns: any[], map?: (value: any) => any): JSONStream;
|
|
12
|
+
|
|
13
|
+
interface JSONStream extends NodeJS.ReadWriteStream {
|
|
14
|
+
on(event: 'header', handler: (value: any) => void): this;
|
|
15
|
+
once(event: 'header', handler: (value: any) => void): this;
|
|
16
|
+
|
|
17
|
+
on(event: 'data', handler: (value: any) => void): this;
|
|
18
|
+
once(event: 'data', handler: (value: any) => void): this;
|
|
19
|
+
|
|
20
|
+
on(event: 'footer', handler: (value: any) => void): this;
|
|
21
|
+
once(event: 'footer', handler: (value: any) => void): this;
|
|
22
|
+
|
|
23
|
+
on(event: 'error', handler: (cause: any) => void): this;
|
|
24
|
+
once(event: 'error', handler: (cause: any) => void): this;
|
|
25
|
+
|
|
26
|
+
on(event: 'end', handler: () => void): this;
|
|
27
|
+
once(event: 'end', handler: () => void): this;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { RequestOptions, IncomingMessage } from 'http';
|
|
3
|
+
import { Repository } from './repository';
|
|
4
|
+
/**
|
|
5
|
+
* Published package.
|
|
6
|
+
*/
|
|
7
|
+
export interface PublishedPackage {
|
|
8
|
+
/**
|
|
9
|
+
* Name of the package as stored in the package manager.
|
|
10
|
+
*/
|
|
11
|
+
readonly name: string;
|
|
12
|
+
/**
|
|
13
|
+
* Version of the package as stored in the package manager.
|
|
14
|
+
*/
|
|
15
|
+
readonly version: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Integrity class for validating a local artifact against its published counterpart.
|
|
19
|
+
*
|
|
20
|
+
* Implementations differ based on the package manager in question.
|
|
21
|
+
*/
|
|
22
|
+
export declare abstract class ArtifactIntegrity {
|
|
23
|
+
/**
|
|
24
|
+
* The file extenstion of artifacts produced for this check. (e.g 'whl')
|
|
25
|
+
*/
|
|
26
|
+
protected abstract readonly ext: string;
|
|
27
|
+
/**
|
|
28
|
+
* Download a package to the target file.
|
|
29
|
+
*
|
|
30
|
+
* @param pkg The package to download.
|
|
31
|
+
* @param targetFile The file path to download the package to.
|
|
32
|
+
*/
|
|
33
|
+
protected abstract download(pkg: PublishedPackage, targetFile: string): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Extract the artifact into the target directory.
|
|
36
|
+
*
|
|
37
|
+
* @param artifact Path to an artifact file.
|
|
38
|
+
* @param targetDir The directory to extract to. It will exist by the time this method is invoked.
|
|
39
|
+
*/
|
|
40
|
+
protected abstract extract(artifact: string, targetDir: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Parse a local artifact file name into a structured package.
|
|
43
|
+
*
|
|
44
|
+
* @param artifactName Base name of the local artifact file.
|
|
45
|
+
* @returns The package this artifact correlates to.
|
|
46
|
+
*/
|
|
47
|
+
protected abstract parseArtifactName(artifactName: string): PublishedPackage;
|
|
48
|
+
/**
|
|
49
|
+
* Validate a local artifact against its published counterpart.
|
|
50
|
+
*
|
|
51
|
+
* @param localArtifactDir The directory of the local artifact. Must contain exactly one file with the appropriate extenstion.
|
|
52
|
+
*/
|
|
53
|
+
validate(localArtifactDir: string): Promise<void>;
|
|
54
|
+
protected log(message: string): void;
|
|
55
|
+
private findOne;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Properties for `RepositoryIntegrity`.
|
|
59
|
+
*/
|
|
60
|
+
export interface RepositoryIntegrityProps {
|
|
61
|
+
/**
|
|
62
|
+
* Repository to validate.
|
|
63
|
+
*/
|
|
64
|
+
readonly repository: Repository;
|
|
65
|
+
/**
|
|
66
|
+
* The command that produces the local artifacts.
|
|
67
|
+
*
|
|
68
|
+
* @default 'npx projen release'
|
|
69
|
+
*/
|
|
70
|
+
readonly packCommand?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Integrity class for validating the artifacts produced by this repository against their published counterparts.
|
|
74
|
+
*/
|
|
75
|
+
export declare class RepositoryIntegrity {
|
|
76
|
+
private readonly props;
|
|
77
|
+
constructor(props: RepositoryIntegrityProps);
|
|
78
|
+
/**
|
|
79
|
+
* Validate the artifacts of this repo against its published counterpart.
|
|
80
|
+
*/
|
|
81
|
+
validate(): Promise<void>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* NpmIntegiry is able to perform integiry checks against packages stored on npmjs.com
|
|
85
|
+
*/
|
|
86
|
+
export declare class NpmArtifactIntegrity extends ArtifactIntegrity {
|
|
87
|
+
protected readonly ext = "tgz";
|
|
88
|
+
protected download(pkg: PublishedPackage, target: string): Promise<void>;
|
|
89
|
+
extract(file: string, targetDir: string): Promise<void>;
|
|
90
|
+
protected parseArtifactName(artifactName: string): PublishedPackage;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* PyPIIntegiry is able to perform integiry checks against packages stored on pypi.org
|
|
94
|
+
*/
|
|
95
|
+
export declare class PyPIArtifactIntegrity extends ArtifactIntegrity {
|
|
96
|
+
protected readonly ext = "whl";
|
|
97
|
+
protected download(pkg: PublishedPackage, target: string): Promise<void>;
|
|
98
|
+
extract(artifact: string, target: string): Promise<void>;
|
|
99
|
+
protected parseArtifactName(artifactName: string): PublishedPackage;
|
|
100
|
+
}
|
|
101
|
+
export declare function jsonGet(url: string, jsonPath?: string[]): Promise<any>;
|
|
102
|
+
export declare function download(url: string, targetFile: string): Promise<any>;
|
|
103
|
+
export declare function get(url: string, handler: (res: IncomingMessage, ok: (value: unknown) => void, ko: (err: Error) => void) => void, options?: RequestOptions): Promise<unknown>;
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
+
};
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.get = exports.download = exports.jsonGet = exports.PyPIArtifactIntegrity = exports.NpmArtifactIntegrity = exports.RepositoryIntegrity = exports.ArtifactIntegrity = void 0;
|
|
26
|
+
const child_process_1 = require("child_process");
|
|
27
|
+
const https = __importStar(require("https"));
|
|
28
|
+
const os = __importStar(require("os"));
|
|
29
|
+
const path = __importStar(require("path"));
|
|
30
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
31
|
+
const adm_zip_1 = __importDefault(require("adm-zip"));
|
|
32
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
33
|
+
const fs = __importStar(require("fs-extra"));
|
|
34
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
35
|
+
const jstream = __importStar(require("JSONStream"));
|
|
36
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
37
|
+
const tar = __importStar(require("tar"));
|
|
38
|
+
/**
|
|
39
|
+
* Integrity class for validating a local artifact against its published counterpart.
|
|
40
|
+
*
|
|
41
|
+
* Implementations differ based on the package manager in question.
|
|
42
|
+
*/
|
|
43
|
+
class ArtifactIntegrity {
|
|
44
|
+
/**
|
|
45
|
+
* Validate a local artifact against its published counterpart.
|
|
46
|
+
*
|
|
47
|
+
* @param localArtifactDir The directory of the local artifact. Must contain exactly one file with the appropriate extenstion.
|
|
48
|
+
*/
|
|
49
|
+
async validate(localArtifactDir) {
|
|
50
|
+
const artifactPath = this.findOne(localArtifactDir);
|
|
51
|
+
const name = this.constructor.name;
|
|
52
|
+
this.log(`Validating ${artifactPath}`);
|
|
53
|
+
const workdir = fs.mkdtempSync(path.join(os.tmpdir(), 'integrity-check'));
|
|
54
|
+
try {
|
|
55
|
+
const downloaded = path.join(workdir, `${name}.downloaded`);
|
|
56
|
+
const remote = path.join(workdir, `${name}.remote`);
|
|
57
|
+
const local = path.join(workdir, `${name}.local`);
|
|
58
|
+
// parse the artifact name into a package.
|
|
59
|
+
const pkg = this.parseArtifactName(path.basename(artifactPath));
|
|
60
|
+
fs.mkdirSync(remote);
|
|
61
|
+
fs.mkdirSync(local);
|
|
62
|
+
// download the package
|
|
63
|
+
this.log(`Downloading ${pkg.name}@${pkg.version} to ${downloaded}`);
|
|
64
|
+
await this.download(pkg, downloaded);
|
|
65
|
+
// extract the downlaoded package
|
|
66
|
+
this.log(`Extracting remote artifact from ${downloaded} to ${remote}`);
|
|
67
|
+
await this.extract(downloaded, remote);
|
|
68
|
+
// extract the local artfiact
|
|
69
|
+
this.log(`Extracting local artifact from ${artifactPath} to ${local}`);
|
|
70
|
+
await this.extract(artifactPath, local);
|
|
71
|
+
this.log(`Comparing ${local} <> ${remote}`);
|
|
72
|
+
try {
|
|
73
|
+
(0, child_process_1.execSync)(`diff ${local} ${remote}`, { stdio: ['ignore', 'inherit', 'inherit'] });
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
throw new Error(`${name} validation failed`);
|
|
77
|
+
}
|
|
78
|
+
this.log('Success');
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
fs.removeSync(workdir);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
log(message) {
|
|
85
|
+
console.log(`${this.constructor.name} | ${message} `);
|
|
86
|
+
}
|
|
87
|
+
findOne(dir) {
|
|
88
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith(this.ext));
|
|
89
|
+
if (files.length === 0) {
|
|
90
|
+
throw new Error(`No files found in ${dir} with extension ${this.ext}`);
|
|
91
|
+
}
|
|
92
|
+
const [first, ...rest] = files;
|
|
93
|
+
if (rest.length > 0) {
|
|
94
|
+
throw new Error(`Multiple files found in ${dir} with extension ${this.ext}: ${first}, ${rest.join(', ')}`);
|
|
95
|
+
}
|
|
96
|
+
return path.join(dir, first);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.ArtifactIntegrity = ArtifactIntegrity;
|
|
100
|
+
/**
|
|
101
|
+
* Integrity class for validating the artifacts produced by this repository against their published counterparts.
|
|
102
|
+
*/
|
|
103
|
+
class RepositoryIntegrity {
|
|
104
|
+
constructor(props) {
|
|
105
|
+
this.props = props;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Validate the artifacts of this repo against its published counterpart.
|
|
109
|
+
*/
|
|
110
|
+
async validate() {
|
|
111
|
+
var _a;
|
|
112
|
+
// note that run 'release' by default to preserve the version number.
|
|
113
|
+
// this won't do a bump since the commit we are on is already tagged.
|
|
114
|
+
const artifacts = this.props.repository.pack((_a = this.props.packCommand) !== null && _a !== void 0 ? _a : 'npx projen release');
|
|
115
|
+
let integrity = undefined;
|
|
116
|
+
for (const artifact of artifacts) {
|
|
117
|
+
switch (artifact.lang) {
|
|
118
|
+
case 'js':
|
|
119
|
+
integrity = new NpmArtifactIntegrity();
|
|
120
|
+
break;
|
|
121
|
+
case 'python':
|
|
122
|
+
integrity = new PyPIArtifactIntegrity();
|
|
123
|
+
break;
|
|
124
|
+
case 'java':
|
|
125
|
+
case 'dotnet':
|
|
126
|
+
case 'go':
|
|
127
|
+
// we don't have integrity checks for these
|
|
128
|
+
// artifacts yet.
|
|
129
|
+
break;
|
|
130
|
+
default:
|
|
131
|
+
throw new Error(`Unsupported artifact language: ${artifact.lang}`);
|
|
132
|
+
}
|
|
133
|
+
if (integrity) {
|
|
134
|
+
await integrity.validate(artifact.directory);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
console.log('Validation done');
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
exports.RepositoryIntegrity = RepositoryIntegrity;
|
|
141
|
+
/**
|
|
142
|
+
* NpmIntegiry is able to perform integiry checks against packages stored on npmjs.com
|
|
143
|
+
*/
|
|
144
|
+
class NpmArtifactIntegrity extends ArtifactIntegrity {
|
|
145
|
+
constructor() {
|
|
146
|
+
super(...arguments);
|
|
147
|
+
this.ext = 'tgz';
|
|
148
|
+
}
|
|
149
|
+
async download(pkg, target) {
|
|
150
|
+
const tarballUrl = await jsonGet(`https://registry.npmjs.org/${encodeURIComponent(pkg.name)}/${encodeURIComponent(pkg.version)}`, ['dist', 'tarball']);
|
|
151
|
+
await download(tarballUrl, target);
|
|
152
|
+
}
|
|
153
|
+
async extract(file, targetDir) {
|
|
154
|
+
return tar.x({ cwd: targetDir, file: file, strip: 1 });
|
|
155
|
+
}
|
|
156
|
+
parseArtifactName(artifactName) {
|
|
157
|
+
// cdk8s@1.0.0-beta.59.jsii.tgz
|
|
158
|
+
const jsiiArtifact = /(.*)@(.*)\.jsii./;
|
|
159
|
+
// npm artifact: cdk8s-cli-1.0.0-beta59.tgz
|
|
160
|
+
// yarn artifact: cdk8s-cli-v1.0.0-beta59.tgz (add a 'v' before the version)
|
|
161
|
+
const npmOrYarnArtifact = /(.*)-v?(\d.*).(tgz|tar.gz)/;
|
|
162
|
+
const regex = artifactName.includes('.jsii.') ? jsiiArtifact : npmOrYarnArtifact;
|
|
163
|
+
const match = artifactName.match(regex);
|
|
164
|
+
if (!match) {
|
|
165
|
+
throw new Error(`Unable to parse artifact: ${artifactName}`);
|
|
166
|
+
}
|
|
167
|
+
return { name: match[1], version: match[2] };
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
exports.NpmArtifactIntegrity = NpmArtifactIntegrity;
|
|
171
|
+
/**
|
|
172
|
+
* PyPIIntegiry is able to perform integiry checks against packages stored on pypi.org
|
|
173
|
+
*/
|
|
174
|
+
class PyPIArtifactIntegrity extends ArtifactIntegrity {
|
|
175
|
+
constructor() {
|
|
176
|
+
super(...arguments);
|
|
177
|
+
this.ext = 'whl';
|
|
178
|
+
}
|
|
179
|
+
async download(pkg, target) {
|
|
180
|
+
const files = await jsonGet(`https://pypi.org/pypi/${encodeURIComponent(pkg.name)}/json`, ['releases', pkg.version]);
|
|
181
|
+
const wheels = files.filter((f) => f.url.endsWith('whl')).map((f) => f.url);
|
|
182
|
+
if (wheels.length === 0) {
|
|
183
|
+
throw new Error(`No wheels found for package ${pkg.name}-${pkg.version}`);
|
|
184
|
+
}
|
|
185
|
+
if (wheels.length > 1) {
|
|
186
|
+
throw new Error(`Multiple wheels found for package ${pkg.name}-${pkg.version}: ${wheels.join(',')}`);
|
|
187
|
+
}
|
|
188
|
+
await download(wheels[0], target);
|
|
189
|
+
}
|
|
190
|
+
async extract(artifact, target) {
|
|
191
|
+
const zip = new adm_zip_1.default(artifact);
|
|
192
|
+
return zip.extractAllTo(target);
|
|
193
|
+
}
|
|
194
|
+
parseArtifactName(artifactName) {
|
|
195
|
+
// cdk8s-1.0.0b63-py3-none-any.whl
|
|
196
|
+
const regex = /(.*)-v?(\d.*)-py.*.whl/;
|
|
197
|
+
const match = artifactName.match(regex);
|
|
198
|
+
if (!match) {
|
|
199
|
+
throw new Error(`Unable to parse artifact: ${artifactName}`);
|
|
200
|
+
}
|
|
201
|
+
return { name: match[1], version: match[2] };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
exports.PyPIArtifactIntegrity = PyPIArtifactIntegrity;
|
|
205
|
+
function jsonGet(url, jsonPath) {
|
|
206
|
+
return get(url, (res, ok, ko) => {
|
|
207
|
+
const json = jstream.parse(jsonPath);
|
|
208
|
+
json.once('data', ok);
|
|
209
|
+
json.once('error', ko);
|
|
210
|
+
res.pipe(json, { end: true });
|
|
211
|
+
}, { headers: { 'Accept': 'application/json', 'Accept-Encoding': 'identity' } });
|
|
212
|
+
}
|
|
213
|
+
exports.jsonGet = jsonGet;
|
|
214
|
+
async function download(url, targetFile) {
|
|
215
|
+
return get(url, (res, ok, ko) => {
|
|
216
|
+
const file = fs.createWriteStream(targetFile);
|
|
217
|
+
file.on('finish', ok);
|
|
218
|
+
file.on('error', ko);
|
|
219
|
+
res.pipe(file, { end: true });
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
exports.download = download;
|
|
223
|
+
async function get(url, handler, options = {}) {
|
|
224
|
+
return new Promise((ok, ko) => {
|
|
225
|
+
const request = https.get(url, options, (res) => {
|
|
226
|
+
if (res.statusCode !== 200) {
|
|
227
|
+
const error = new Error(`GET ${url} - HTTP ${res.statusCode} (${res.statusMessage})`);
|
|
228
|
+
Error.captureStackTrace(error);
|
|
229
|
+
return ko(error);
|
|
230
|
+
}
|
|
231
|
+
res.once('error', ko);
|
|
232
|
+
handler(res, ok, ko);
|
|
233
|
+
});
|
|
234
|
+
request.on('error', ko);
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
exports.get = get;
|
|
238
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZWdyaXR5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiaW50ZWdyaXR5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxpREFBeUM7QUFFekMsNkNBQStCO0FBQy9CLHVDQUF5QjtBQUN6QiwyQ0FBNkI7QUFDN0IsNkRBQTZEO0FBQzdELHNEQUE2QjtBQUM3Qiw2REFBNkQ7QUFDN0QsNkNBQStCO0FBQy9CLDZEQUE2RDtBQUM3RCxvREFBc0M7QUFDdEMsNkRBQTZEO0FBQzdELHlDQUEyQjtBQW9CM0I7Ozs7R0FJRztBQUNILE1BQXNCLGlCQUFpQjtJQStCckM7Ozs7T0FJRztJQUNJLEtBQUssQ0FBQyxRQUFRLENBQUMsZ0JBQXdCO1FBRTVDLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUNwRCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQztRQUVuQyxJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsWUFBWSxFQUFFLENBQUMsQ0FBQztRQUN2QyxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLGlCQUFpQixDQUFDLENBQUMsQ0FBQztRQUUxRSxJQUFJO1lBQ0YsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxJQUFJLGFBQWEsQ0FBQyxDQUFDO1lBQzVELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxTQUFTLENBQUMsQ0FBQztZQUNwRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxHQUFHLElBQUksUUFBUSxDQUFDLENBQUM7WUFFbEQsMENBQTBDO1lBQzFDLE1BQU0sR0FBRyxHQUFH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QztRQUN0QixJQUFJLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNyQixHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2hDLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQVBELDRCQU9DO0FBRU0sS0FBSyxVQUFVLEdBQUcsQ0FDdkIsR0FBVyxFQUNYLE9BQStGLEVBQy9GLFVBQTBCLEVBQUU7SUFFNUIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtRQUM1QixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxHQUFvQixFQUFFLEVBQUU7WUFDL0QsSUFBSSxHQUFHLENBQUMsVUFBVSxLQUFLLEdBQUcsRUFBRTtnQkFDMUIsTUFBTSxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQUMsT0FBTyxHQUFHLFdBQVcsR0FBRyxDQUFDLFVBQVUsS0FBSyxHQUFHLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQztnQkFDdEYsS0FBSyxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMvQixPQUFPLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUNsQjtZQUNELEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3RCLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZCLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDMUIsQ0FBQyxDQUFDLENBQUM7QUFFTCxDQUFDO0FBbEJELGtCQWtCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RPcHRpb25zLCBJbmNvbWluZ01lc3NhZ2UgfSBmcm9tICdodHRwJztcbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIG9zIGZyb20gJ29zJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgQWRtWmlwIGZyb20gJ2FkbS16aXAnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0ICogYXMganN0cmVhbSBmcm9tICdKU09OU3RyZWFtJztcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBpbXBvcnQvbm8tZXh0cmFuZW91cy1kZXBlbmRlbmNpZXNcbmltcG9ydCAqIGFzIHRhciBmcm9tICd0YXInO1xuaW1wb3J0IHsgUmVwb3NpdG9yeSB9IGZyb20gJy4vcmVwb3NpdG9yeSc7XG5cblxuLyoqXG4gKiBQdWJsaXNoZWQgcGFja2FnZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQdWJsaXNoZWRQYWNrYWdlIHtcblxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgcGFja2FnZSBhcyBzdG9yZWQgaW4gdGhlIHBhY2thZ2UgbWFuYWdlci5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVmVyc2lvbiBvZiB0aGUgcGFja2FnZSBhcyBzdG9yZWQgaW4gdGhlIHBhY2thZ2UgbWFuYWdlci5cbiAgICovXG4gIHJlYWRvbmx5IHZlcnNpb246IHN0cmluZztcbn1cblxuLyoqXG4gKiBJbnRlZ3JpdHkgY2xhc3MgZm9yIHZhbGlkYXRpbmcgYSBsb2NhbCBhcnRpZmFjdCBhZ2FpbnN0IGl0cyBwdWJsaXNoZWQgY291bnRlcnBhcnQuXG4gKlxuICogSW1wbGVtZW50YXRpb25zIGRpZmZlciBiYXNlZCBvbiB0aGUgcGFja2FnZSBtYW5hZ2VyIGluIHF1ZXN0aW9uLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQXJ0aWZhY3RJbnRlZ3JpdHkge1xuXG4gIC8qKlxuICAgKiBUaGUgZmlsZSBleHRlbnN0aW9uIG9mIGFydGlmYWN0cyBwcm9kdWNlZCBmb3IgdGhpcyBjaGVjay4gKGUuZyAnd2hsJylcbiAgICovXG4gIHByb3RlY3RlZCBhYnN0cmFjdCByZWFkb25seSBleHQ6IHN0cmluZztcblxuICAvKipcbiAgICogRG93bmxvYWQgYSBwYWNrYWdlIHRvIHRoZSB0YXJnZXQgZmlsZS5cbiAgICpcbiAgICogQHBhcmFtIHBrZyBUaGUgcGFja2FnZSB0byBkb3dubG9hZC5cbiAgICogQHBhcmFtIHRhcmdldEZpbGUgVGhlIGZpbGUgcGF0aCB0byBkb3dubG9hZCB0aGUgcGFja2FnZSB0by5cbiAgICovXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBkb3dubG9hZChwa2c6IFB1Ymxpc2hlZFBhY2thZ2UsIHRhcmdldEZpbGU6IHN0cmluZyk6IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIEV4dHJhY3QgdGhlIGFydGlmYWN0IGludG8gdGhlIHRhcmdldCBkaXJlY3RvcnkuXG4gICAqXG4gICAqIEBwYXJhbSBhcnRpZmFjdCBQYXRoIHRvIGFuIGFydGlmYWN0IGZpbGUuXG4gICAqIEBwYXJhbSB0YXJnZXREaXIgVGhlIGRpcmVjdG9yeSB0byBleHRyYWN0IHRvLiBJdCB3aWxsIGV4aXN0IGJ5IHRoZSB0aW1lIHRoaXMgbWV0aG9kIGlzIGludm9rZWQuXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgZXh0cmFjdChhcnRpZmFjdDogc3RyaW5nLCB0YXJnZXREaXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD47XG5cbiAgLyoqXG4gICAqIFBhcnNlIGEgbG9jYWwgYXJ0aWZhY3QgZmlsZSBuYW1lIGludG8gYSBzdHJ1Y3R1cmVkIHBhY2thZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBhcnRpZmFjdE5hbWUgQmFzZSBuYW1lIG9mIHRoZSBsb2NhbCBhcnRpZmFjdCBmaWxlLlxuICAgKiBAcmV0dXJucyBUaGUgcGFja2FnZSB0aGlzIGFydGlmYWN0IGNvcnJlbGF0ZXMgdG8uXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcGFyc2VBcnRpZmFjdE5hbWUoYXJ0aWZhY3ROYW1lOiBzdHJpbmcpOiBQdWJsaXNoZWRQYWNrYWdlO1xuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBhIGxvY2FsIGFydGlmYWN0IGFnYWluc3QgaXRzIHB1Ymxpc2hlZCBjb3VudGVycGFydC5cbiAgICpcbiAgICogQHBhcmFtIGxvY2FsQXJ0aWZhY3REaXIgVGhlIGRpcmVjdG9yeSBvZiB0aGUgbG9jYWwgYXJ0aWZhY3QuIE11c3QgY29udGFpbiBleGFjdGx5IG9uZSBmaWxlIHdpdGggdGhlIGFwcHJvcHJpYXRlIGV4dGVuc3Rpb24uXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdmFsaWRhdGUobG9jYWxBcnRpZmFjdERpcjogc3RyaW5nKSB7XG5cbiAgICBjb25zdCBhcnRpZmFjdFBhdGggPSB0aGlzLmZpbmRPbmUobG9jYWxBcnRpZmFjdERpcik7XG4gICAgY29uc3QgbmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcblxuICAgIHRoaXMubG9nKGBWYWxpZGF0aW5nICR7YXJ0aWZhY3RQYXRofWApO1xuICAgIGNvbnN0IHdvcmtkaXIgPSBmcy5ta2R0ZW1wU3luYyhwYXRoLmpvaW4ob3MudG1wZGlyKCksICdpbnRlZ3JpdHktY2hlY2snKSk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZG93bmxvYWRlZCA9IHBhdGguam9pbih3b3JrZGlyLCBgJHtuYW1lfS5kb3dubG9hZGVkYCk7XG4gICAgICBjb25zdCByZW1vdGUgPSBwYXRoLmpvaW4od29ya2RpciwgYCR7bmFtZX0ucmVtb3RlYCk7XG4gICAgICBjb25zdCBsb2NhbCA9IHBhdGguam9pbih3b3JrZGlyLCBgJHtuYW1lfS5sb2NhbGApO1xuXG4gICAgICAvLyBwYXJzZSB0aGUgYXJ0aWZhY3QgbmFtZSBpbnRvIGEgcGFja2FnZS5cbiAgICAgIGNvbnN0IHBrZyA9IHRoaXMucGFyc2VBcnRpZmFjdE5hbWUocGF0aC5iYXNlbmFtZShhcnRpZmFjdFBhdGgpKTtcblxuICAgICAgZnMubWtkaXJTeW5jKHJlbW90ZSk7XG4gICAgICBmcy5ta2RpclN5bmMobG9jYWwpO1xuXG4gICAgICAvLyBkb3dubG9hZCB0aGUgcGFja2FnZVxuICAgICAgdGhpcy5sb2coYERvd25sb2FkaW5nICR7cGtnLm5hbWV9QCR7cGtnLnZlcnNpb259IHRvICR7ZG93bmxvYWRlZH1gKTtcbiAgICAgIGF3YWl0IHRoaXMuZG93bmxvYWQocGtnLCBkb3dubG9hZGVkKTtcblxuICAgICAgLy8gZXh0cmFjdCB0aGUgZG93bmxhb2RlZCBwYWNrYWdlXG4gICAgICB0aGlzLmxvZyhgRXh0cmFjdGluZyByZW1vdGUgYXJ0aWZhY3QgZnJvbSAke2Rvd25sb2FkZWR9IHRvICR7cmVtb3RlfWApO1xuICAgICAgYXdhaXQgdGhpcy5leHRyYWN0KGRvd25sb2FkZWQsIHJlbW90ZSk7XG5cbiAgICAgIC8vIGV4dHJhY3QgdGhlIGxvY2FsIGFydGZpYWN0XG4gICAgICB0aGlzLmxvZyhgRXh0cmFjdGluZyBsb2NhbCBhcnRpZmFjdCBmcm9tICR7YXJ0aWZhY3RQYXRofSB0byAke2xvY2FsfWApO1xuICAgICAgYXdhaXQgdGhpcy5leHRyYWN0KGFydGlmYWN0UGF0aCwgbG9jYWwpO1xuXG4gICAgICB0aGlzLmxvZyhgQ29tcGFyaW5nICR7bG9jYWx9IDw+ICR7cmVtb3RlfWApO1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhlY1N5bmMoYGRpZmYgJHtsb2NhbH0gJHtyZW1vdGV9YCwgeyBzdGRpbzogWydpZ25vcmUnLCAnaW5oZXJpdCcsICdpbmhlcml0J10gfSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7bmFtZX0gdmFsaWRhdGlvbiBmYWlsZWRgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMubG9nKCdTdWNjZXNzJyk7XG5cbiAgICB9IGZpbmFsbHkge1xuICAgICAgZnMucmVtb3ZlU3luYyh3b3JrZGlyKTtcbiAgICB9XG5cbiAgfVxuXG4gIHByb3RlY3RlZCBsb2cobWVzc2FnZTogc3RyaW5nKSB7XG4gICAgY29uc29sZS5sb2coYCR7dGhpcy5jb25zdHJ1Y3Rvci5uYW1lfSB8ICR7bWVzc2FnZX0gYCk7XG4gIH1cblxuICBwcml2YXRlIGZpbmRPbmUoZGlyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGZpbGVzID0gZnMucmVhZGRpclN5bmMoZGlyKS5maWx0ZXIoZiA9PiBmLmVuZHNXaXRoKHRoaXMuZXh0KSk7XG4gICAgaWYgKGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyBmaWxlcyBmb3VuZCBpbiAke2Rpcn0gd2l0aCBleHRlbnNpb24gJHt0aGlzLmV4dH1gKTtcbiAgICB9XG4gICAgY29uc3QgW2ZpcnN0LCAuLi5yZXN0XSA9IGZpbGVzO1xuICAgIGlmIChyZXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTXVsdGlwbGUgZmlsZXMgZm91bmQgaW4gJHtkaXJ9IHdpdGggZXh0ZW5zaW9uICR7dGhpcy5leHR9OiAke2ZpcnN0fSwgJHtyZXN0LmpvaW4oJywgJyl9YCk7XG4gICAgfVxuICAgIHJldHVybiBwYXRoLmpvaW4oZGlyLCBmaXJzdCk7XG4gIH1cblxufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGBSZXBvc2l0b3J5SW50ZWdyaXR5YC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBvc2l0b3J5SW50ZWdyaXR5UHJvcHMge1xuICAvKipcbiAgICogUmVwb3NpdG9yeSB0byB2YWxpZGF0ZS5cbiAgICovXG4gIHJlYWRvbmx5IHJlcG9zaXRvcnk6IFJlcG9zaXRvcnk7XG5cbiAgLyoqXG4gICAqIFRoZSBjb21tYW5kIHRoYXQgcHJvZHVjZXMgdGhlIGxvY2FsIGFydGlmYWN0cy5cbiAgICpcbiAgICogQGRlZmF1bHQgJ25weCBwcm9qZW4gcmVsZWFzZSdcbiAgICovXG4gIHJlYWRvbmx5IHBhY2tDb21tYW5kPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEludGVncml0eSBjbGFzcyBmb3IgdmFsaWRhdGluZyB0aGUgYXJ0aWZhY3RzIHByb2R1Y2VkIGJ5IHRoaXMgcmVwb3NpdG9yeSBhZ2FpbnN0IHRoZWlyIHB1Ymxpc2hlZCBjb3VudGVycGFydHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBSZXBvc2l0b3J5SW50ZWdyaXR5IHtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBwcm9wczogUmVwb3NpdG9yeUludGVncml0eVByb3BzKSB7fVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGUgYXJ0aWZhY3RzIG9mIHRoaXMgcmVwbyBhZ2FpbnN0IGl0cyBwdWJsaXNoZWQgY291bnRlcnBhcnQuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdmFsaWRhdGUoKSB7XG5cbiAgICAvLyBub3RlIHRoYXQgcnVuICdyZWxlYXNlJyBieSBkZWZhdWx0IHRvIHByZXNlcnZlIHRoZSB2ZXJzaW9uIG51bWJlci5cbiAgICAvLyB0aGlzIHdvbid0IGRvIGEgYnVtcCBzaW5jZSB0aGUgY29tbWl0IHdlIGFyZSBvbiBpcyBhbHJlYWR5IHRhZ2dlZC5cbiAgICBjb25zdCBhcnRpZmFjdHMgPSB0aGlzLnByb3BzLnJlcG9zaXRvcnkucGFjayh0aGlzLnByb3BzLnBhY2tDb21tYW5kID8/ICducHggcHJvamVuIHJlbGVhc2UnKTtcblxuICAgIGxldCBpbnRlZ3JpdHkgPSB1bmRlZmluZWQ7XG4gICAgZm9yIChjb25zdCBhcnRpZmFjdCBvZiBhcnRpZmFjdHMpIHtcbiAgICAgIHN3aXRjaCAoYXJ0aWZhY3QubGFuZykge1xuICAgICAgICBjYXNlICdqcyc6XG4gICAgICAgICAgaW50ZWdyaXR5ID0gbmV3IE5wbUFydGlmYWN0SW50ZWdyaXR5KCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3B5dGhvbic6XG4gICAgICAgICAgaW50ZWdyaXR5ID0gbmV3IFB5UElBcnRpZmFjdEludGVncml0eSgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdqYXZhJzpcbiAgICAgICAgY2FzZSAnZG90bmV0JzpcbiAgICAgICAgY2FzZSAnZ28nOlxuICAgICAgICAgIC8vIHdlIGRvbid0IGhhdmUgaW50ZWdyaXR5IGNoZWNrcyBmb3IgdGhlc2VcbiAgICAgICAgICAvLyBhcnRpZmFjdHMgeWV0LlxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgYXJ0aWZhY3QgbGFuZ3VhZ2U6ICR7YXJ0aWZhY3QubGFuZ31gKTtcbiAgICAgIH1cbiAgICAgIGlmIChpbnRlZ3JpdHkpIHtcbiAgICAgICAgYXdhaXQgaW50ZWdyaXR5LnZhbGlkYXRlKGFydGlmYWN0LmRpcmVjdG9yeSk7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKCdWYWxpZGF0aW9uIGRvbmUnKTtcbiAgfVxuXG59XG5cbi8qKlxuICogTnBtSW50ZWdpcnkgaXMgYWJsZSB0byBwZXJmb3JtIGludGVnaXJ5IGNoZWNrcyBhZ2FpbnN0IHBhY2thZ2VzIHN0b3JlZCBvbiBucG1qcy5jb21cbiAqL1xuZXhwb3J0IGNsYXNzIE5wbUFydGlmYWN0SW50ZWdyaXR5IGV4dGVuZHMgQXJ0aWZhY3RJbnRlZ3JpdHkge1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBleHQgPSAndGd6JztcblxuICBwcm90ZWN0ZWQgYXN5bmMgZG93bmxvYWQocGtnOiBQdWJsaXNoZWRQYWNrYWdlLCB0YXJnZXQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHRhcmJhbGxVcmwgPSBhd2FpdCBqc29uR2V0KGBodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy8ke2VuY29kZVVSSUNvbXBvbmVudChwa2cubmFtZSl9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KHBrZy52ZXJzaW9uKX1gLCBbJ2Rpc3QnLCAndGFyYmFsbCddKTtcbiAgICBhd2FpdCBkb3dubG9hZCh0YXJiYWxsVXJsLCB0YXJnZXQpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGV4dHJhY3QoZmlsZTogc3RyaW5nLCB0YXJnZXREaXI6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0YXIueCh7IGN3ZDogdGFyZ2V0RGlyLCBmaWxlOiBmaWxlLCBzdHJpcDogMSB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBwYXJzZUFydGlmYWN0TmFtZShhcnRpZmFjdE5hbWU6IHN0cmluZyk6IFB1Ymxpc2hlZFBhY2thZ2Uge1xuXG4gICAgLy8gY2RrOHNAMS4wLjAtYmV0YS41OS5qc2lpLnRnelxuICAgIGNvbnN0IGpzaWlBcnRpZmFjdCA9IC8oLiopQCguKilcXC5qc2lpLi87XG5cbiAgICAvLyBucG0gYXJ0aWZhY3Q6IGNkazhzLWNsaS0xLjAuMC1iZXRhNTkudGd6XG4gICAgLy8geWFybiBhcnRpZmFjdDogY2RrOHMtY2xpLXYxLjAuMC1iZXRhNTkudGd6IChhZGQgYSAndicgYmVmb3JlIHRoZSB2ZXJzaW9uKVxuICAgIGNvbnN0IG5wbU9yWWFybkFydGlmYWN0ID0gLyguKiktdj8oXFxkLiopLih0Z3p8dGFyLmd6KS87XG5cbiAgICBjb25zdCByZWdleCA9IGFydGlmYWN0TmFtZS5pbmNsdWRlcygnLmpzaWkuJykgPyBqc2lpQXJ0aWZhY3QgOiBucG1Pcllhcm5BcnRpZmFjdDtcblxuICAgIGNvbnN0IG1hdGNoID0gYXJ0aWZhY3ROYW1lLm1hdGNoKHJlZ2V4KTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBwYXJzZSBhcnRpZmFjdDogJHthcnRpZmFjdE5hbWV9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgbmFtZTogbWF0Y2hbMV0sIHZlcnNpb246IG1hdGNoWzJdIH07XG5cbiAgfVxuXG59XG5cbi8qKlxuICogUHlQSUludGVnaXJ5IGlzIGFibGUgdG8gcGVyZm9ybSBpbnRlZ2lyeSBjaGVja3MgYWdhaW5zdCBwYWNrYWdlcyBzdG9yZWQgb24gcHlwaS5vcmdcbiAqL1xuZXhwb3J0IGNsYXNzIFB5UElBcnRpZmFjdEludGVncml0eSBleHRlbmRzIEFydGlmYWN0SW50ZWdyaXR5IHtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZXh0ID0gJ3dobCc7XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGRvd25sb2FkKHBrZzogUHVibGlzaGVkUGFja2FnZSwgdGFyZ2V0OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcblxuICAgIGNvbnN0IGZpbGVzID0gYXdhaXQganNvbkdldChgaHR0cHM6Ly9weXBpLm9yZy9weXBpLyR7ZW5jb2RlVVJJQ29tcG9uZW50KHBrZy5uYW1lKX0vanNvbmAsIFsncmVsZWFzZXMnLCBwa2cudmVyc2lvbl0pO1xuICAgIGNvbnN0IHdoZWVsczogc3RyaW5nW10gPSBmaWxlcy5maWx0ZXIoKGY6IGFueSkgPT4gZi51cmwuZW5kc1dpdGgoJ3dobCcpKS5tYXAoKGY6IGFueSkgPT4gZi51cmwpO1xuXG4gICAgaWYgKHdoZWVscy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gd2hlZWxzIGZvdW5kIGZvciBwYWNrYWdlICR7cGtnLm5hbWV9LSR7cGtnLnZlcnNpb259YCk7XG4gICAgfVxuXG4gICAgaWYgKHdoZWVscy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE11bHRpcGxlIHdoZWVscyBmb3VuZCBmb3IgcGFja2FnZSAke3BrZy5uYW1lfS0ke3BrZy52ZXJzaW9ufTogJHt3aGVlbHMuam9pbignLCcpfWApO1xuICAgIH1cblxuICAgIGF3YWl0IGRvd25sb2FkKHdoZWVsc1swXSwgdGFyZ2V0KTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBleHRyYWN0KGFydGlmYWN0OiBzdHJpbmcsIHRhcmdldDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgemlwID0gbmV3IEFkbVppcChhcnRpZmFjdCk7XG4gICAgcmV0dXJuIHppcC5leHRyYWN0QWxsVG8odGFyZ2V0KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBwYXJzZUFydGlmYWN0TmFtZShhcnRpZmFjdE5hbWU6IHN0cmluZyk6IFB1Ymxpc2hlZFBhY2thZ2Uge1xuXG4gICAgLy8gY2RrOHMtMS4wLjBiNjMtcHkzLW5vbmUtYW55LndobFxuICAgIGNvbnN0IHJlZ2V4ID0gLyguKiktdj8oXFxkLiopLXB5Lioud2hsLztcblxuICAgIGNvbnN0IG1hdGNoID0gYXJ0aWZhY3ROYW1lLm1hdGNoKHJlZ2V4KTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBwYXJzZSBhcnRpZmFjdDogJHthcnRpZmFjdE5hbWV9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgbmFtZTogbWF0Y2hbMV0sIHZlcnNpb246IG1hdGNoWzJdIH07XG5cbiAgfVxuXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBqc29uR2V0KHVybDogc3RyaW5nLCBqc29uUGF0aD86IHN0cmluZ1tdKTogUHJvbWlzZTxhbnk+IHtcbiAgcmV0dXJuIGdldCh1cmwsIChyZXMsIG9rLCBrbykgPT4ge1xuICAgIGNvbnN0IGpzb24gPSBqc3RyZWFtLnBhcnNlKGpzb25QYXRoKTtcbiAgICBqc29uLm9uY2UoJ2RhdGEnLCBvayk7XG4gICAganNvbi5vbmNlKCdlcnJvcicsIGtvKTtcblxuICAgIHJlcy5waXBlKGpzb24sIHsgZW5kOiB0cnVlIH0pO1xuICB9LCB7IGhlYWRlcnM6IHsgJ0FjY2VwdCc6ICdhcHBsaWNhdGlvbi9qc29uJywgJ0FjY2VwdC1FbmNvZGluZyc6ICdpZGVudGl0eScgfSB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkKHVybDogc3RyaW5nLCB0YXJnZXRGaWxlOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICByZXR1cm4gZ2V0KHVybCwgKHJlcywgb2ssIGtvKSA9PiB7XG4gICAgY29uc3QgZmlsZSA9IGZzLmNyZWF0ZVdyaXRlU3RyZWFtKHRhcmdldEZpbGUpO1xuICAgIGZpbGUub24oJ2ZpbmlzaCcsIG9rKTtcbiAgICBmaWxlLm9uKCdlcnJvcicsIGtvKTtcbiAgICByZXMucGlwZShmaWxlLCB7IGVuZDogdHJ1ZSB9KTtcbiAgfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXQoXG4gIHVybDogc3RyaW5nLFxuICBoYW5kbGVyOiAocmVzOiBJbmNvbWluZ01lc3NhZ2UsIG9rOiAodmFsdWU6IHVua25vd24pID0+IHZvaWQsIGtvOiAoZXJyOiBFcnJvcikgPT4gdm9pZCkgPT4gdm9pZCxcbiAgb3B0aW9uczogUmVxdWVzdE9wdGlvbnMgPSB7fSkge1xuXG4gIHJldHVybiBuZXcgUHJvbWlzZSgob2ssIGtvKSA9PiB7XG4gICAgY29uc3QgcmVxdWVzdCA9IGh0dHBzLmdldCh1cmwsIG9wdGlvbnMsIChyZXM6IEluY29taW5nTWVzc2FnZSkgPT4ge1xuICAgICAgaWYgKHJlcy5zdGF0dXNDb2RlICE9PSAyMDApIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoYEdFVCAke3VybH0gLSBIVFRQICR7cmVzLnN0YXR1c0NvZGV9ICgke3Jlcy5zdGF0dXNNZXNzYWdlfSlgKTtcbiAgICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UoZXJyb3IpO1xuICAgICAgICByZXR1cm4ga28oZXJyb3IpO1xuICAgICAgfVxuICAgICAgcmVzLm9uY2UoJ2Vycm9yJywga28pO1xuICAgICAgaGFuZGxlcihyZXMsIG9rLCBrbyk7XG4gICAgfSk7XG4gICAgcmVxdWVzdC5vbignZXJyb3InLCBrbyk7XG4gIH0pO1xuXG59XG4iXX0=
|