@rushstack/rush-amazon-s3-build-cache-plugin 0.0.0 → 5.57.0-dev.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.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "@rushstack/rush-amazon-s3-build-cache-plugin",
3
+ "entries": [
4
+ {
5
+ "version": "0.0.1",
6
+ "tag": "@rushstack/rush-amazon-s3-build-cache-plugin_v0.0.1",
7
+ "date": "Thu, 11 Nov 2021 16:07:47 GMT",
8
+ "comments": {}
9
+ }
10
+ ]
11
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Change Log - @rushstack/rush-amazon-s3-build-cache-plugin
2
+
3
+ This log was last generated on Thu, 11 Nov 2021 16:07:47 GMT and should not be manually modified.
4
+
5
+ ## 0.0.1
6
+ Thu, 11 Nov 2021 16:07:47 GMT
7
+
8
+ _Initial release_
9
+
package/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ @rushstack/rush-amazon-s3-build-cache-plugin
2
+
3
+ Copyright (c) Microsoft Corporation. All rights reserved.
4
+
5
+ MIT License
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining
8
+ a copy of this software and associated documentation files (the
9
+ "Software"), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @rushstack/rush-amazon-s3-build-cache-plugin
2
+
3
+ This is a Rush plugin for using Amazon S3 as cloud build cache provider during the "build" and "rebuild" command.
4
+
5
+ ## Links
6
+
7
+ - [CHANGELOG.md](
8
+ https://github.com/microsoft/rushstack/blob/master/rush-plugins/rush-amazon-s3-build-cache-plugin/CHANGELOG.md) - Find
9
+ out what's new in the latest version
@@ -0,0 +1,14 @@
1
+ import type { IRushPlugin } from '@rushstack/rush-sdk';
2
+ import type { RushConfiguration } from '@rushstack/rush-sdk';
3
+ import type { RushSession } from '@rushstack/rush-sdk';
4
+
5
+ /**
6
+ * @public
7
+ */
8
+ declare class RushAmazonS3BuildCachePlugin implements IRushPlugin {
9
+ pluginName: string;
10
+ apply(rushSession: RushSession, rushConfig: RushConfiguration): void;
11
+ }
12
+ export default RushAmazonS3BuildCachePlugin;
13
+
14
+ export { }
@@ -0,0 +1,28 @@
1
+ /// <reference types="node" />
2
+ import { ITerminal } from '@rushstack/node-core-library';
3
+ import { ICloudBuildCacheProvider, RushSession } from '@rushstack/rush-sdk';
4
+ export interface IAmazonS3BuildCacheProviderOptions {
5
+ s3Bucket: string;
6
+ s3Region: string;
7
+ s3Prefix?: string;
8
+ isCacheWriteAllowed: boolean;
9
+ }
10
+ export declare class AmazonS3BuildCacheProvider implements ICloudBuildCacheProvider {
11
+ private readonly _options;
12
+ private readonly _s3Prefix;
13
+ private readonly _environmentCredential;
14
+ private readonly _isCacheWriteAllowedByConfiguration;
15
+ private __credentialCacheId;
16
+ private _rushSession;
17
+ get isCacheWriteAllowed(): boolean;
18
+ private __s3Client;
19
+ constructor(options: IAmazonS3BuildCacheProviderOptions, rushSession: RushSession);
20
+ private get _credentialCacheId();
21
+ private _getS3ClientAsync;
22
+ tryGetCacheEntryBufferByIdAsync(terminal: ITerminal, cacheId: string): Promise<Buffer | undefined>;
23
+ trySetCacheEntryBufferAsync(terminal: ITerminal, cacheId: string, objectBuffer: Buffer): Promise<boolean>;
24
+ updateCachedCredentialAsync(terminal: ITerminal, credential: string): Promise<void>;
25
+ updateCachedCredentialInteractiveAsync(terminal: ITerminal): Promise<void>;
26
+ deleteCachedCredentialsAsync(terminal: ITerminal): Promise<void>;
27
+ }
28
+ //# sourceMappingURL=AmazonS3BuildCacheProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AmazonS3BuildCacheProvider.d.ts","sourceRoot":"","sources":["../src/AmazonS3BuildCacheProvider.ts"],"names":[],"mappings":";AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EACL,wBAAwB,EAGxB,WAAW,EAIZ,MAAM,qBAAqB,CAAC;AAK7B,MAAM,WAAW,kCAAkC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,qBAAa,0BAA2B,YAAW,wBAAwB;IACzE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqB;IAC/C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAqB;IAC5D,OAAO,CAAC,QAAQ,CAAC,mCAAmC,CAAU;IAC9D,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,YAAY,CAAc;IAElC,IAAW,mBAAmB,IAAI,OAAO,CAExC;IAED,OAAO,CAAC,UAAU,CAA6B;gBAE5B,OAAO,EAAE,kCAAkC,EAAE,WAAW,EAAE,WAAW;IAQxF,OAAO,KAAK,kBAAkB,GAY7B;YAEa,iBAAiB;IA2ClB,+BAA+B,CAC1C,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAUjB,2BAA2B,CACtC,QAAQ,EAAE,SAAS,EACnB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,OAAO,CAAC;IAgBN,2BAA2B,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnF,sCAAsC,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1E,4BAA4B,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;CAW9E"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.AmazonS3BuildCacheProvider = void 0;
6
+ const rush_sdk_1 = require("@rushstack/rush-sdk");
7
+ const AmazonS3Client_1 = require("./AmazonS3Client");
8
+ const WebClient_1 = require("./WebClient");
9
+ class AmazonS3BuildCacheProvider {
10
+ constructor(options, rushSession) {
11
+ this._rushSession = rushSession;
12
+ this._options = options;
13
+ this._s3Prefix = options.s3Prefix;
14
+ this._environmentCredential = rush_sdk_1.EnvironmentConfiguration.buildCacheCredential;
15
+ this._isCacheWriteAllowedByConfiguration = options.isCacheWriteAllowed;
16
+ }
17
+ get isCacheWriteAllowed() {
18
+ var _a;
19
+ return (_a = rush_sdk_1.EnvironmentConfiguration.buildCacheWriteAllowed) !== null && _a !== void 0 ? _a : this._isCacheWriteAllowedByConfiguration;
20
+ }
21
+ get _credentialCacheId() {
22
+ if (!this.__credentialCacheId) {
23
+ const cacheIdParts = ['aws-s3', this._options.s3Region, this._options.s3Bucket];
24
+ if (this._isCacheWriteAllowedByConfiguration) {
25
+ cacheIdParts.push('cacheWriteAllowed');
26
+ }
27
+ this.__credentialCacheId = cacheIdParts.join('|');
28
+ }
29
+ return this.__credentialCacheId;
30
+ }
31
+ async _getS3ClientAsync() {
32
+ var _a;
33
+ if (!this.__s3Client) {
34
+ let credentials = AmazonS3Client_1.AmazonS3Client.tryDeserializeCredentials(this._environmentCredential);
35
+ if (!credentials) {
36
+ let cacheEntry;
37
+ await rush_sdk_1.CredentialCache.usingAsync({
38
+ supportEditing: false
39
+ }, (credentialsCache) => {
40
+ cacheEntry = credentialsCache.tryGetCacheEntry(this._credentialCacheId);
41
+ });
42
+ if (cacheEntry) {
43
+ const expirationTime = (_a = cacheEntry.expires) === null || _a === void 0 ? void 0 : _a.getTime();
44
+ if (expirationTime && expirationTime < Date.now()) {
45
+ throw new Error('Cached Amazon S3 credentials have expired. ' +
46
+ `Update the credentials by running "rush ${rush_sdk_1.RushConstants.updateCloudCredentialsCommandName}".`);
47
+ }
48
+ else {
49
+ credentials = AmazonS3Client_1.AmazonS3Client.tryDeserializeCredentials(cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.credential);
50
+ }
51
+ }
52
+ else if (this._isCacheWriteAllowedByConfiguration) {
53
+ throw new Error("An Amazon S3 credential hasn't been provided, or has expired. " +
54
+ `Update the credentials by running "rush ${rush_sdk_1.RushConstants.updateCloudCredentialsCommandName}", ` +
55
+ `or provide an <AccessKeyId>:<SecretAccessKey> pair in the ` +
56
+ `${rush_sdk_1.EnvironmentVariableNames.RUSH_BUILD_CACHE_CREDENTIAL} environment variable`);
57
+ }
58
+ }
59
+ this.__s3Client = new AmazonS3Client_1.AmazonS3Client(credentials, this._options, new WebClient_1.WebClient());
60
+ }
61
+ return this.__s3Client;
62
+ }
63
+ async tryGetCacheEntryBufferByIdAsync(terminal, cacheId) {
64
+ try {
65
+ const client = await this._getS3ClientAsync();
66
+ return await client.getObjectAsync(this._s3Prefix ? `${this._s3Prefix}/${cacheId}` : cacheId);
67
+ }
68
+ catch (e) {
69
+ terminal.writeWarningLine(`Error getting cache entry from S3: ${e}`);
70
+ return undefined;
71
+ }
72
+ }
73
+ async trySetCacheEntryBufferAsync(terminal, cacheId, objectBuffer) {
74
+ if (!this.isCacheWriteAllowed) {
75
+ terminal.writeErrorLine('Writing to S3 cache is not allowed in the current configuration.');
76
+ return false;
77
+ }
78
+ try {
79
+ const client = await this._getS3ClientAsync();
80
+ await client.uploadObjectAsync(this._s3Prefix ? `${this._s3Prefix}/${cacheId}` : cacheId, objectBuffer);
81
+ return true;
82
+ }
83
+ catch (e) {
84
+ terminal.writeWarningLine(`Error uploading cache entry to S3: ${e}`);
85
+ return false;
86
+ }
87
+ }
88
+ async updateCachedCredentialAsync(terminal, credential) {
89
+ await rush_sdk_1.CredentialCache.usingAsync({
90
+ supportEditing: true
91
+ }, async (credentialsCache) => {
92
+ credentialsCache.setCacheEntry(this._credentialCacheId, credential);
93
+ await credentialsCache.saveIfModifiedAsync();
94
+ });
95
+ }
96
+ async updateCachedCredentialInteractiveAsync(terminal) {
97
+ throw new Error('The interactive cloud credentials flow is not supported for Amazon S3.\n' +
98
+ 'Provide your credentials to rush using the --credential flag instead. Credentials must be ' +
99
+ 'in the form of <ACCESS KEY ID>:<SECRET ACCESS KEY> or ' +
100
+ '<ACCESS KEY ID>:<SECRET ACCESS KEY>:<SESSION TOKEN>.');
101
+ }
102
+ async deleteCachedCredentialsAsync(terminal) {
103
+ await rush_sdk_1.CredentialCache.usingAsync({
104
+ supportEditing: true
105
+ }, async (credentialsCache) => {
106
+ credentialsCache.deleteCacheEntry(this._credentialCacheId);
107
+ await credentialsCache.saveIfModifiedAsync();
108
+ });
109
+ }
110
+ }
111
+ exports.AmazonS3BuildCacheProvider = AmazonS3BuildCacheProvider;
112
+ //# sourceMappingURL=AmazonS3BuildCacheProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AmazonS3BuildCacheProvider.js","sourceRoot":"","sources":["../src/AmazonS3BuildCacheProvider.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { ITerminal } from '@rushstack/node-core-library';\r\nimport {\r\n ICloudBuildCacheProvider,\r\n ICredentialCacheEntry,\r\n CredentialCache,\r\n RushSession,\r\n RushConstants,\r\n EnvironmentVariableNames,\r\n EnvironmentConfiguration\r\n} from '@rushstack/rush-sdk';\r\n\r\nimport { AmazonS3Client, IAmazonS3Credentials } from './AmazonS3Client';\r\nimport { WebClient } from './WebClient';\r\n\r\nexport interface IAmazonS3BuildCacheProviderOptions {\r\n s3Bucket: string;\r\n s3Region: string;\r\n s3Prefix?: string;\r\n isCacheWriteAllowed: boolean;\r\n}\r\n\r\nexport class AmazonS3BuildCacheProvider implements ICloudBuildCacheProvider {\r\n private readonly _options: IAmazonS3BuildCacheProviderOptions;\r\n private readonly _s3Prefix: string | undefined;\r\n private readonly _environmentCredential: string | undefined;\r\n private readonly _isCacheWriteAllowedByConfiguration: boolean;\r\n private __credentialCacheId: string | undefined;\r\n private _rushSession: RushSession;\r\n\r\n public get isCacheWriteAllowed(): boolean {\r\n return EnvironmentConfiguration.buildCacheWriteAllowed ?? this._isCacheWriteAllowedByConfiguration;\r\n }\r\n\r\n private __s3Client: AmazonS3Client | undefined;\r\n\r\n public constructor(options: IAmazonS3BuildCacheProviderOptions, rushSession: RushSession) {\r\n this._rushSession = rushSession;\r\n this._options = options;\r\n this._s3Prefix = options.s3Prefix;\r\n this._environmentCredential = EnvironmentConfiguration.buildCacheCredential;\r\n this._isCacheWriteAllowedByConfiguration = options.isCacheWriteAllowed;\r\n }\r\n\r\n private get _credentialCacheId(): string {\r\n if (!this.__credentialCacheId) {\r\n const cacheIdParts: string[] = ['aws-s3', this._options.s3Region, this._options.s3Bucket];\r\n\r\n if (this._isCacheWriteAllowedByConfiguration) {\r\n cacheIdParts.push('cacheWriteAllowed');\r\n }\r\n\r\n this.__credentialCacheId = cacheIdParts.join('|');\r\n }\r\n\r\n return this.__credentialCacheId;\r\n }\r\n\r\n private async _getS3ClientAsync(): Promise<AmazonS3Client> {\r\n if (!this.__s3Client) {\r\n let credentials: IAmazonS3Credentials | undefined = AmazonS3Client.tryDeserializeCredentials(\r\n this._environmentCredential\r\n );\r\n\r\n if (!credentials) {\r\n let cacheEntry: ICredentialCacheEntry | undefined;\r\n await CredentialCache.usingAsync(\r\n {\r\n supportEditing: false\r\n },\r\n (credentialsCache: CredentialCache) => {\r\n cacheEntry = credentialsCache.tryGetCacheEntry(this._credentialCacheId);\r\n }\r\n );\r\n\r\n if (cacheEntry) {\r\n const expirationTime: number | undefined = cacheEntry.expires?.getTime();\r\n if (expirationTime && expirationTime < Date.now()) {\r\n throw new Error(\r\n 'Cached Amazon S3 credentials have expired. ' +\r\n `Update the credentials by running \"rush ${RushConstants.updateCloudCredentialsCommandName}\".`\r\n );\r\n } else {\r\n credentials = AmazonS3Client.tryDeserializeCredentials(cacheEntry?.credential);\r\n }\r\n } else if (this._isCacheWriteAllowedByConfiguration) {\r\n throw new Error(\r\n \"An Amazon S3 credential hasn't been provided, or has expired. \" +\r\n `Update the credentials by running \"rush ${RushConstants.updateCloudCredentialsCommandName}\", ` +\r\n `or provide an <AccessKeyId>:<SecretAccessKey> pair in the ` +\r\n `${EnvironmentVariableNames.RUSH_BUILD_CACHE_CREDENTIAL} environment variable`\r\n );\r\n }\r\n }\r\n\r\n this.__s3Client = new AmazonS3Client(credentials, this._options, new WebClient());\r\n }\r\n\r\n return this.__s3Client;\r\n }\r\n\r\n public async tryGetCacheEntryBufferByIdAsync(\r\n terminal: ITerminal,\r\n cacheId: string\r\n ): Promise<Buffer | undefined> {\r\n try {\r\n const client: AmazonS3Client = await this._getS3ClientAsync();\r\n return await client.getObjectAsync(this._s3Prefix ? `${this._s3Prefix}/${cacheId}` : cacheId);\r\n } catch (e) {\r\n terminal.writeWarningLine(`Error getting cache entry from S3: ${e}`);\r\n return undefined;\r\n }\r\n }\r\n\r\n public async trySetCacheEntryBufferAsync(\r\n terminal: ITerminal,\r\n cacheId: string,\r\n objectBuffer: Buffer\r\n ): Promise<boolean> {\r\n if (!this.isCacheWriteAllowed) {\r\n terminal.writeErrorLine('Writing to S3 cache is not allowed in the current configuration.');\r\n return false;\r\n }\r\n\r\n try {\r\n const client: AmazonS3Client = await this._getS3ClientAsync();\r\n await client.uploadObjectAsync(this._s3Prefix ? `${this._s3Prefix}/${cacheId}` : cacheId, objectBuffer);\r\n return true;\r\n } catch (e) {\r\n terminal.writeWarningLine(`Error uploading cache entry to S3: ${e}`);\r\n return false;\r\n }\r\n }\r\n\r\n public async updateCachedCredentialAsync(terminal: ITerminal, credential: string): Promise<void> {\r\n await CredentialCache.usingAsync(\r\n {\r\n supportEditing: true\r\n },\r\n async (credentialsCache: CredentialCache) => {\r\n credentialsCache.setCacheEntry(this._credentialCacheId, credential);\r\n await credentialsCache.saveIfModifiedAsync();\r\n }\r\n );\r\n }\r\n\r\n public async updateCachedCredentialInteractiveAsync(terminal: ITerminal): Promise<void> {\r\n throw new Error(\r\n 'The interactive cloud credentials flow is not supported for Amazon S3.\\n' +\r\n 'Provide your credentials to rush using the --credential flag instead. Credentials must be ' +\r\n 'in the form of <ACCESS KEY ID>:<SECRET ACCESS KEY> or ' +\r\n '<ACCESS KEY ID>:<SECRET ACCESS KEY>:<SESSION TOKEN>.'\r\n );\r\n }\r\n\r\n public async deleteCachedCredentialsAsync(terminal: ITerminal): Promise<void> {\r\n await CredentialCache.usingAsync(\r\n {\r\n supportEditing: true\r\n },\r\n async (credentialsCache: CredentialCache) => {\r\n credentialsCache.deleteCacheEntry(this._credentialCacheId);\r\n await credentialsCache.saveIfModifiedAsync();\r\n }\r\n );\r\n }\r\n}\r\n"]}
@@ -0,0 +1,31 @@
1
+ /// <reference types="node" />
2
+ import { IAmazonS3BuildCacheProviderOptions } from './AmazonS3BuildCacheProvider';
3
+ import { WebClient } from './WebClient';
4
+ export interface IAmazonS3Credentials {
5
+ accessKeyId: string;
6
+ secretAccessKey: string;
7
+ sessionToken: string | undefined;
8
+ }
9
+ export declare class AmazonS3Client {
10
+ private readonly _credentials;
11
+ private readonly _s3Bucket;
12
+ private readonly _s3Region;
13
+ private readonly _webClient;
14
+ constructor(credentials: IAmazonS3Credentials | undefined, options: IAmazonS3BuildCacheProviderOptions, webClient: WebClient);
15
+ static tryDeserializeCredentials(credentialString: string | undefined): IAmazonS3Credentials | undefined;
16
+ getObjectAsync(objectName: string): Promise<Buffer | undefined>;
17
+ uploadObjectAsync(objectName: string, objectBuffer: Buffer): Promise<void>;
18
+ private _makeRequestAsync;
19
+ _getSha256Hmac(key: string | Buffer, data: string): Buffer;
20
+ _getSha256Hmac(key: string | Buffer, data: string, encoding: 'hex'): string;
21
+ private _getSha256;
22
+ private _getIsoDateString;
23
+ private _throwS3Error;
24
+ private _getHost;
25
+ /**
26
+ * Validates a S3 bucket name.
27
+ * {@link https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-s3-bucket-naming-requirements.html}
28
+ */
29
+ private _validateBucketName;
30
+ }
31
+ //# sourceMappingURL=AmazonS3Client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AmazonS3Client.d.ts","sourceRoot":"","sources":["../src/AmazonS3Client.ts"],"names":[],"mappings":";AAMA,OAAO,EAAE,kCAAkC,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAsC,SAAS,EAAE,MAAM,aAAa,CAAC;AAS5E,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AAOD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAmC;IAChE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;gBAGrC,WAAW,EAAE,oBAAoB,GAAG,SAAS,EAC7C,OAAO,EAAE,kCAAkC,EAC3C,SAAS,EAAE,SAAS;WAYR,yBAAyB,CACrC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,oBAAoB,GAAG,SAAS;IAiBtB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAa/D,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAWzE,iBAAiB;IAkGxB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAC1D,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,GAAG,MAAM;IAWlF,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,QAAQ;IAQhB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;CAsC5B"}
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
7
+ }) : (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ o[k2] = m[k];
10
+ }));
11
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
12
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
13
+ }) : function(o, v) {
14
+ o["default"] = v;
15
+ });
16
+ var __importStar = (this && this.__importStar) || function (mod) {
17
+ if (mod && mod.__esModule) return mod;
18
+ var result = {};
19
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
20
+ __setModuleDefault(result, mod);
21
+ return result;
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.AmazonS3Client = void 0;
25
+ const crypto = __importStar(require("crypto"));
26
+ const fetch = __importStar(require("node-fetch"));
27
+ const CONTENT_HASH_HEADER_NAME = 'x-amz-content-sha256';
28
+ const DATE_HEADER_NAME = 'x-amz-date';
29
+ const HOST_HEADER_NAME = 'host';
30
+ const SECURITY_TOKEN_HEADER_NAME = 'x-amz-security-token';
31
+ const DEFAULT_S3_REGION = 'us-east-1';
32
+ class AmazonS3Client {
33
+ constructor(credentials, options, webClient) {
34
+ this._credentials = credentials;
35
+ this._validateBucketName(options.s3Bucket);
36
+ this._s3Bucket = options.s3Bucket;
37
+ this._s3Region = options.s3Region;
38
+ this._webClient = webClient;
39
+ }
40
+ static tryDeserializeCredentials(credentialString) {
41
+ if (!credentialString) {
42
+ return undefined;
43
+ }
44
+ const fields = credentialString.split(':');
45
+ if (fields.length < 2 || fields.length > 3) {
46
+ throw new Error('Amazon S3 credential is in an unexpected format.');
47
+ }
48
+ return {
49
+ accessKeyId: fields[0],
50
+ secretAccessKey: fields[1],
51
+ sessionToken: fields[2]
52
+ };
53
+ }
54
+ async getObjectAsync(objectName) {
55
+ const response = await this._makeRequestAsync('GET', objectName);
56
+ if (response.ok) {
57
+ return await response.buffer();
58
+ }
59
+ else if (response.status === 404) {
60
+ return undefined;
61
+ }
62
+ else if (response.status === 403 && !this._credentials) {
63
+ return undefined;
64
+ }
65
+ else {
66
+ this._throwS3Error(response);
67
+ }
68
+ }
69
+ async uploadObjectAsync(objectName, objectBuffer) {
70
+ if (!this._credentials) {
71
+ throw new Error('Credentials are required to upload objects to S3.');
72
+ }
73
+ const response = await this._makeRequestAsync('PUT', objectName, objectBuffer);
74
+ if (!response.ok) {
75
+ this._throwS3Error(response);
76
+ }
77
+ }
78
+ async _makeRequestAsync(verb, objectName, body) {
79
+ const isoDateString = this._getIsoDateString();
80
+ const bodyHash = this._getSha256(body);
81
+ const host = this._getHost();
82
+ const headers = new fetch.Headers();
83
+ headers.set(DATE_HEADER_NAME, isoDateString.dateTime);
84
+ headers.set(CONTENT_HASH_HEADER_NAME, bodyHash);
85
+ if (this._credentials) {
86
+ // Compute the authorization header. See https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
87
+ const signedHeaderNames = [HOST_HEADER_NAME, CONTENT_HASH_HEADER_NAME, DATE_HEADER_NAME];
88
+ const canonicalHeaders = [
89
+ `${HOST_HEADER_NAME}:${host}`,
90
+ `${CONTENT_HASH_HEADER_NAME}:${bodyHash}`,
91
+ `${DATE_HEADER_NAME}:${isoDateString.dateTime}`
92
+ ];
93
+ // Handle signing with temporary credentials (via sts:assume-role)
94
+ if (this._credentials.sessionToken) {
95
+ signedHeaderNames.push(SECURITY_TOKEN_HEADER_NAME);
96
+ canonicalHeaders.push(`${SECURITY_TOKEN_HEADER_NAME}:${this._credentials.sessionToken}`);
97
+ }
98
+ const signedHeaderNamesString = signedHeaderNames.join(';');
99
+ // The canonical request looks like this:
100
+ // GET
101
+ // /test.txt
102
+ //
103
+ // host:examplebucket.s3.amazonaws.com
104
+ // range:bytes=0-9
105
+ // x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
106
+ // x-amz-date:20130524T000000Z
107
+ //
108
+ // host;range;x-amz-content-sha256;x-amz-date
109
+ // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
110
+ const canonicalRequest = [
111
+ verb,
112
+ `/${objectName}`,
113
+ '',
114
+ ...canonicalHeaders,
115
+ '',
116
+ signedHeaderNamesString,
117
+ bodyHash
118
+ ].join('\n');
119
+ const canonicalRequestHash = this._getSha256(canonicalRequest);
120
+ const scope = `${isoDateString.date}/${this._s3Region}/s3/aws4_request`;
121
+ // The string to sign looks like this:
122
+ // AWS4-HMAC-SHA256
123
+ // 20130524T423589Z
124
+ // 20130524/us-east-1/s3/aws4_request
125
+ // 7344ae5b7ee6c3e7e6b0fe0640412a37625d1fbfff95c48bbb2dc43964946972
126
+ const stringToSign = [
127
+ 'AWS4-HMAC-SHA256',
128
+ isoDateString.dateTime,
129
+ scope,
130
+ canonicalRequestHash
131
+ ].join('\n');
132
+ const dateKey = this._getSha256Hmac(`AWS4${this._credentials.secretAccessKey}`, isoDateString.date);
133
+ const dateRegionKey = this._getSha256Hmac(dateKey, this._s3Region);
134
+ const dateRegionServiceKey = this._getSha256Hmac(dateRegionKey, 's3');
135
+ const signingKey = this._getSha256Hmac(dateRegionServiceKey, 'aws4_request');
136
+ const signature = this._getSha256Hmac(signingKey, stringToSign, 'hex');
137
+ const authorizationHeader = `AWS4-HMAC-SHA256 Credential=${this._credentials.accessKeyId}/${scope},SignedHeaders=${signedHeaderNamesString},Signature=${signature}`;
138
+ headers.set('Authorization', authorizationHeader);
139
+ if (this._credentials.sessionToken) {
140
+ // Handle signing with temporary credentials (via sts:assume-role)
141
+ headers.set('X-Amz-Security-Token', this._credentials.sessionToken);
142
+ }
143
+ }
144
+ const webFetchOptions = {
145
+ verb,
146
+ headers
147
+ };
148
+ if (verb === 'PUT') {
149
+ webFetchOptions.body = body;
150
+ }
151
+ const response = await this._webClient.fetchAsync(`https://${host}/${objectName}`, webFetchOptions);
152
+ return response;
153
+ }
154
+ _getSha256Hmac(key, data, encoding) {
155
+ const hash = crypto.createHmac('sha256', key);
156
+ hash.update(data);
157
+ if (encoding) {
158
+ return hash.digest(encoding);
159
+ }
160
+ else {
161
+ return hash.digest();
162
+ }
163
+ }
164
+ _getSha256(data) {
165
+ if (data) {
166
+ const hash = crypto.createHash('sha256');
167
+ hash.update(data);
168
+ return hash.digest('hex');
169
+ }
170
+ else {
171
+ // This is the null SHA256 hash
172
+ return 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
173
+ }
174
+ }
175
+ _getIsoDateString(date = new Date()) {
176
+ let dateString = date.toISOString();
177
+ dateString = dateString.replace(/[-:]/g, ''); // Remove separator characters
178
+ dateString = dateString.substring(0, 15); // Drop milliseconds
179
+ // dateTime is an ISO8601 date. It looks like "20130524T423589"
180
+ // date is an ISO date. It looks like "20130524"
181
+ return {
182
+ dateTime: `${dateString}Z`,
183
+ date: dateString.substring(0, 8)
184
+ };
185
+ }
186
+ _throwS3Error(response) {
187
+ throw new Error(`Amazon S3 responded with status code ${response.status} (${response.statusText})`);
188
+ }
189
+ _getHost() {
190
+ if (this._s3Region === DEFAULT_S3_REGION) {
191
+ return `${this._s3Bucket}.s3.amazonaws.com`;
192
+ }
193
+ else {
194
+ return `${this._s3Bucket}.s3-${this._s3Region}.amazonaws.com`;
195
+ }
196
+ }
197
+ /**
198
+ * Validates a S3 bucket name.
199
+ * {@link https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-s3-bucket-naming-requirements.html}
200
+ */
201
+ _validateBucketName(s3BucketName) {
202
+ if (!s3BucketName) {
203
+ throw new Error('A S3 bucket name must be provided');
204
+ }
205
+ if (!s3BucketName.match(/^[a-z\d-.]{3,63}$/)) {
206
+ throw new Error(`The bucket name "${s3BucketName}" is invalid. A S3 bucket name must only contain lowercase ` +
207
+ 'alphanumerical characters, dashes, and periods and must be between 3 and 63 characters long.');
208
+ }
209
+ if (!s3BucketName.match(/^[a-z\d]/)) {
210
+ throw new Error(`The bucket name "${s3BucketName}" is invalid. A S3 bucket name must start with a lowercase ` +
211
+ 'alphanumerical character.');
212
+ }
213
+ if (s3BucketName.match(/-$/)) {
214
+ throw new Error(`The bucket name "${s3BucketName}" is invalid. A S3 bucket name must not end in a dash.`);
215
+ }
216
+ if (s3BucketName.match(/(\.\.)|(\.-)|(-\.)/)) {
217
+ throw new Error(`The bucket name "${s3BucketName}" is invalid. A S3 bucket name must not have consecutive periods or ` +
218
+ 'dashes adjacent to periods.');
219
+ }
220
+ if (s3BucketName.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)) {
221
+ throw new Error(`The bucket name "${s3BucketName}" is invalid. A S3 bucket name must not be formatted as an IP address.`);
222
+ }
223
+ }
224
+ }
225
+ exports.AmazonS3Client = AmazonS3Client;
226
+ //# sourceMappingURL=AmazonS3Client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AmazonS3Client.js","sourceRoot":"","sources":["../src/AmazonS3Client.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport * as crypto from 'crypto';\r\nimport * as fetch from 'node-fetch';\r\n\r\nimport { IAmazonS3BuildCacheProviderOptions } from './AmazonS3BuildCacheProvider';\r\nimport { IGetFetchOptions, IPutFetchOptions, WebClient } from './WebClient';\r\n\r\nconst CONTENT_HASH_HEADER_NAME: 'x-amz-content-sha256' = 'x-amz-content-sha256';\r\nconst DATE_HEADER_NAME: 'x-amz-date' = 'x-amz-date';\r\nconst HOST_HEADER_NAME: 'host' = 'host';\r\nconst SECURITY_TOKEN_HEADER_NAME: 'x-amz-security-token' = 'x-amz-security-token';\r\n\r\nconst DEFAULT_S3_REGION: 'us-east-1' = 'us-east-1';\r\n\r\nexport interface IAmazonS3Credentials {\r\n accessKeyId: string;\r\n secretAccessKey: string;\r\n sessionToken: string | undefined;\r\n}\r\n\r\ninterface IIsoDateString {\r\n date: string;\r\n dateTime: string;\r\n}\r\n\r\nexport class AmazonS3Client {\r\n private readonly _credentials: IAmazonS3Credentials | undefined;\r\n private readonly _s3Bucket: string;\r\n private readonly _s3Region: string;\r\n\r\n private readonly _webClient: WebClient;\r\n\r\n public constructor(\r\n credentials: IAmazonS3Credentials | undefined,\r\n options: IAmazonS3BuildCacheProviderOptions,\r\n webClient: WebClient\r\n ) {\r\n this._credentials = credentials;\r\n\r\n this._validateBucketName(options.s3Bucket);\r\n\r\n this._s3Bucket = options.s3Bucket;\r\n this._s3Region = options.s3Region;\r\n\r\n this._webClient = webClient;\r\n }\r\n\r\n public static tryDeserializeCredentials(\r\n credentialString: string | undefined\r\n ): IAmazonS3Credentials | undefined {\r\n if (!credentialString) {\r\n return undefined;\r\n }\r\n\r\n const fields: string[] = credentialString.split(':');\r\n if (fields.length < 2 || fields.length > 3) {\r\n throw new Error('Amazon S3 credential is in an unexpected format.');\r\n }\r\n\r\n return {\r\n accessKeyId: fields[0],\r\n secretAccessKey: fields[1],\r\n sessionToken: fields[2]\r\n };\r\n }\r\n\r\n public async getObjectAsync(objectName: string): Promise<Buffer | undefined> {\r\n const response: fetch.Response = await this._makeRequestAsync('GET', objectName);\r\n if (response.ok) {\r\n return await response.buffer();\r\n } else if (response.status === 404) {\r\n return undefined;\r\n } else if (response.status === 403 && !this._credentials) {\r\n return undefined;\r\n } else {\r\n this._throwS3Error(response);\r\n }\r\n }\r\n\r\n public async uploadObjectAsync(objectName: string, objectBuffer: Buffer): Promise<void> {\r\n if (!this._credentials) {\r\n throw new Error('Credentials are required to upload objects to S3.');\r\n }\r\n\r\n const response: fetch.Response = await this._makeRequestAsync('PUT', objectName, objectBuffer);\r\n if (!response.ok) {\r\n this._throwS3Error(response);\r\n }\r\n }\r\n\r\n private async _makeRequestAsync(\r\n verb: 'GET' | 'PUT',\r\n objectName: string,\r\n body?: Buffer\r\n ): Promise<fetch.Response> {\r\n const isoDateString: IIsoDateString = this._getIsoDateString();\r\n const bodyHash: string = this._getSha256(body);\r\n const host: string = this._getHost();\r\n const headers: fetch.Headers = new fetch.Headers();\r\n headers.set(DATE_HEADER_NAME, isoDateString.dateTime);\r\n headers.set(CONTENT_HASH_HEADER_NAME, bodyHash);\r\n\r\n if (this._credentials) {\r\n // Compute the authorization header. See https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html\r\n const signedHeaderNames: string[] = [HOST_HEADER_NAME, CONTENT_HASH_HEADER_NAME, DATE_HEADER_NAME];\r\n const canonicalHeaders: string[] = [\r\n `${HOST_HEADER_NAME}:${host}`,\r\n `${CONTENT_HASH_HEADER_NAME}:${bodyHash}`,\r\n `${DATE_HEADER_NAME}:${isoDateString.dateTime}`\r\n ];\r\n\r\n // Handle signing with temporary credentials (via sts:assume-role)\r\n if (this._credentials.sessionToken) {\r\n signedHeaderNames.push(SECURITY_TOKEN_HEADER_NAME);\r\n canonicalHeaders.push(`${SECURITY_TOKEN_HEADER_NAME}:${this._credentials.sessionToken}`);\r\n }\r\n\r\n const signedHeaderNamesString: string = signedHeaderNames.join(';');\r\n\r\n // The canonical request looks like this:\r\n // GET\r\n // /test.txt\r\n //\r\n // host:examplebucket.s3.amazonaws.com\r\n // range:bytes=0-9\r\n // x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\r\n // x-amz-date:20130524T000000Z\r\n //\r\n // host;range;x-amz-content-sha256;x-amz-date\r\n // e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\r\n const canonicalRequest: string = [\r\n verb,\r\n `/${objectName}`,\r\n '', // we don't use query strings for these requests\r\n ...canonicalHeaders,\r\n '',\r\n signedHeaderNamesString,\r\n bodyHash\r\n ].join('\\n');\r\n const canonicalRequestHash: string = this._getSha256(canonicalRequest);\r\n\r\n const scope: string = `${isoDateString.date}/${this._s3Region}/s3/aws4_request`;\r\n // The string to sign looks like this:\r\n // AWS4-HMAC-SHA256\r\n // 20130524T423589Z\r\n // 20130524/us-east-1/s3/aws4_request\r\n // 7344ae5b7ee6c3e7e6b0fe0640412a37625d1fbfff95c48bbb2dc43964946972\r\n const stringToSign: string = [\r\n 'AWS4-HMAC-SHA256',\r\n isoDateString.dateTime,\r\n scope,\r\n canonicalRequestHash\r\n ].join('\\n');\r\n\r\n const dateKey: Buffer = this._getSha256Hmac(\r\n `AWS4${this._credentials.secretAccessKey}`,\r\n isoDateString.date\r\n );\r\n const dateRegionKey: Buffer = this._getSha256Hmac(dateKey, this._s3Region);\r\n const dateRegionServiceKey: Buffer = this._getSha256Hmac(dateRegionKey, 's3');\r\n const signingKey: Buffer = this._getSha256Hmac(dateRegionServiceKey, 'aws4_request');\r\n const signature: string = this._getSha256Hmac(signingKey, stringToSign, 'hex');\r\n\r\n const authorizationHeader: string = `AWS4-HMAC-SHA256 Credential=${this._credentials.accessKeyId}/${scope},SignedHeaders=${signedHeaderNamesString},Signature=${signature}`;\r\n\r\n headers.set('Authorization', authorizationHeader);\r\n if (this._credentials.sessionToken) {\r\n // Handle signing with temporary credentials (via sts:assume-role)\r\n headers.set('X-Amz-Security-Token', this._credentials.sessionToken);\r\n }\r\n }\r\n\r\n const webFetchOptions: IGetFetchOptions | IPutFetchOptions = {\r\n verb,\r\n headers\r\n };\r\n if (verb === 'PUT') {\r\n (webFetchOptions as IPutFetchOptions).body = body;\r\n }\r\n\r\n const response: fetch.Response = await this._webClient.fetchAsync(\r\n `https://${host}/${objectName}`,\r\n webFetchOptions\r\n );\r\n\r\n return response;\r\n }\r\n\r\n public _getSha256Hmac(key: string | Buffer, data: string): Buffer;\r\n public _getSha256Hmac(key: string | Buffer, data: string, encoding: 'hex'): string;\r\n public _getSha256Hmac(key: string | Buffer, data: string, encoding?: 'hex'): Buffer | string {\r\n const hash: crypto.Hash = crypto.createHmac('sha256', key);\r\n hash.update(data);\r\n if (encoding) {\r\n return hash.digest(encoding);\r\n } else {\r\n return hash.digest();\r\n }\r\n }\r\n\r\n private _getSha256(data?: string | Buffer): string {\r\n if (data) {\r\n const hash: crypto.Hash = crypto.createHash('sha256');\r\n hash.update(data);\r\n return hash.digest('hex');\r\n } else {\r\n // This is the null SHA256 hash\r\n return 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';\r\n }\r\n }\r\n\r\n private _getIsoDateString(date: Date = new Date()): IIsoDateString {\r\n let dateString: string = date.toISOString();\r\n dateString = dateString.replace(/[-:]/g, ''); // Remove separator characters\r\n dateString = dateString.substring(0, 15); // Drop milliseconds\r\n\r\n // dateTime is an ISO8601 date. It looks like \"20130524T423589\"\r\n // date is an ISO date. It looks like \"20130524\"\r\n return {\r\n dateTime: `${dateString}Z`,\r\n date: dateString.substring(0, 8)\r\n };\r\n }\r\n\r\n private _throwS3Error(response: fetch.Response): never {\r\n throw new Error(`Amazon S3 responded with status code ${response.status} (${response.statusText})`);\r\n }\r\n\r\n private _getHost(): string {\r\n if (this._s3Region === DEFAULT_S3_REGION) {\r\n return `${this._s3Bucket}.s3.amazonaws.com`;\r\n } else {\r\n return `${this._s3Bucket}.s3-${this._s3Region}.amazonaws.com`;\r\n }\r\n }\r\n\r\n /**\r\n * Validates a S3 bucket name.\r\n * {@link https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-s3-bucket-naming-requirements.html}\r\n */\r\n private _validateBucketName(s3BucketName: string): void {\r\n if (!s3BucketName) {\r\n throw new Error('A S3 bucket name must be provided');\r\n }\r\n\r\n if (!s3BucketName.match(/^[a-z\\d-.]{3,63}$/)) {\r\n throw new Error(\r\n `The bucket name \"${s3BucketName}\" is invalid. A S3 bucket name must only contain lowercase ` +\r\n 'alphanumerical characters, dashes, and periods and must be between 3 and 63 characters long.'\r\n );\r\n }\r\n\r\n if (!s3BucketName.match(/^[a-z\\d]/)) {\r\n throw new Error(\r\n `The bucket name \"${s3BucketName}\" is invalid. A S3 bucket name must start with a lowercase ` +\r\n 'alphanumerical character.'\r\n );\r\n }\r\n\r\n if (s3BucketName.match(/-$/)) {\r\n throw new Error(\r\n `The bucket name \"${s3BucketName}\" is invalid. A S3 bucket name must not end in a dash.`\r\n );\r\n }\r\n\r\n if (s3BucketName.match(/(\\.\\.)|(\\.-)|(-\\.)/)) {\r\n throw new Error(\r\n `The bucket name \"${s3BucketName}\" is invalid. A S3 bucket name must not have consecutive periods or ` +\r\n 'dashes adjacent to periods.'\r\n );\r\n }\r\n\r\n if (s3BucketName.match(/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/)) {\r\n throw new Error(\r\n `The bucket name \"${s3BucketName}\" is invalid. A S3 bucket name must not be formatted as an IP address.`\r\n );\r\n }\r\n }\r\n}\r\n"]}
@@ -0,0 +1,30 @@
1
+ import type { IRushPlugin, RushSession, RushConfiguration } from '@rushstack/rush-sdk';
2
+ /**
3
+ * @public
4
+ */
5
+ export interface IAmazonS3ConfigurationJson {
6
+ /**
7
+ * The Amazon S3 region of the bucket to use for build cache (e.g. "us-east-1").
8
+ */
9
+ s3Region: string;
10
+ /**
11
+ * The name of the bucket in Amazon S3 to use for build cache.
12
+ */
13
+ s3Bucket: string;
14
+ /**
15
+ * An optional prefix ("folder") for cache items.
16
+ */
17
+ s3Prefix?: string;
18
+ /**
19
+ * If set to true, allow writing to the cache. Defaults to false.
20
+ */
21
+ isCacheWriteAllowed?: boolean;
22
+ }
23
+ /**
24
+ * @public
25
+ */
26
+ export declare class RushAmazonS3BuildCachePlugin implements IRushPlugin {
27
+ pluginName: string;
28
+ apply(rushSession: RushSession, rushConfig: RushConfiguration): void;
29
+ }
30
+ //# sourceMappingURL=RushAmazonS3BuildCachePlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RushAmazonS3BuildCachePlugin.d.ts","sourceRoot":"","sources":["../src/RushAmazonS3BuildCachePlugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAUvF;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,qBAAa,4BAA6B,YAAW,WAAW;IACvD,UAAU,EAAE,MAAM,CAAe;IAEjC,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,iBAAiB,GAAG,IAAI;CAsB5E"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.RushAmazonS3BuildCachePlugin = void 0;
6
+ const node_core_library_1 = require("@rushstack/node-core-library");
7
+ const AmazonS3BuildCacheProviderModule = node_core_library_1.Import.lazy('./AmazonS3BuildCacheProvider', require);
8
+ const PLUGIN_NAME = 'AmazonS3BuildCachePlugin';
9
+ /**
10
+ * @public
11
+ */
12
+ class RushAmazonS3BuildCachePlugin {
13
+ constructor() {
14
+ this.pluginName = PLUGIN_NAME;
15
+ }
16
+ apply(rushSession, rushConfig) {
17
+ rushSession.hooks.initialize.tap(PLUGIN_NAME, () => {
18
+ rushSession.registerCloudBuildCacheProviderFactory('amazon-s3', (buildCacheConfig) => {
19
+ const { amazonS3Configuration } = buildCacheConfig;
20
+ return new AmazonS3BuildCacheProviderModule.AmazonS3BuildCacheProvider({
21
+ s3Region: amazonS3Configuration.s3Region,
22
+ s3Bucket: amazonS3Configuration.s3Bucket,
23
+ s3Prefix: amazonS3Configuration.s3Prefix,
24
+ isCacheWriteAllowed: !!amazonS3Configuration.isCacheWriteAllowed
25
+ }, rushSession);
26
+ });
27
+ });
28
+ }
29
+ }
30
+ exports.RushAmazonS3BuildCachePlugin = RushAmazonS3BuildCachePlugin;
31
+ //# sourceMappingURL=RushAmazonS3BuildCachePlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RushAmazonS3BuildCachePlugin.js","sourceRoot":"","sources":["../src/RushAmazonS3BuildCachePlugin.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;;AAE3D,oEAAsD;AAItD,MAAM,gCAAgC,GAAkD,0BAAM,CAAC,IAAI,CACjG,8BAA8B,EAC9B,OAAO,CACR,CAAC;AAEF,MAAM,WAAW,GAAW,0BAA0B,CAAC;AA2BvD;;GAEG;AACH,MAAa,4BAA4B;IAAzC;QACS,eAAU,GAAW,WAAW,CAAC;IAwB1C,CAAC;IAtBQ,KAAK,CAAC,WAAwB,EAAE,UAA6B;QAClE,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE;YACjD,WAAW,CAAC,sCAAsC,CAChD,WAAW,EACX,CAAC,gBAAgB,EAA8B,EAAE;gBAI/C,MAAM,EAAE,qBAAqB,EAAE,GAAG,gBAA+B,CAAC;gBAClE,OAAO,IAAI,gCAAgC,CAAC,0BAA0B,CACpE;oBACE,QAAQ,EAAE,qBAAqB,CAAC,QAAQ;oBACxC,QAAQ,EAAE,qBAAqB,CAAC,QAAQ;oBACxC,QAAQ,EAAE,qBAAqB,CAAC,QAAQ;oBACxC,mBAAmB,EAAE,CAAC,CAAC,qBAAqB,CAAC,mBAAmB;iBACjE,EACD,WAAW,CACZ,CAAC;YACJ,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAzBD,oEAyBC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { Import } from '@rushstack/node-core-library';\r\nimport type { IRushPlugin, RushSession, RushConfiguration } from '@rushstack/rush-sdk';\r\nimport type { AmazonS3BuildCacheProvider } from './AmazonS3BuildCacheProvider';\r\n\r\nconst AmazonS3BuildCacheProviderModule: typeof import('./AmazonS3BuildCacheProvider') = Import.lazy(\r\n './AmazonS3BuildCacheProvider',\r\n require\r\n);\r\n\r\nconst PLUGIN_NAME: string = 'AmazonS3BuildCachePlugin';\r\n\r\n/**\r\n * @public\r\n */\r\nexport interface IAmazonS3ConfigurationJson {\r\n /**\r\n * The Amazon S3 region of the bucket to use for build cache (e.g. \"us-east-1\").\r\n */\r\n s3Region: string;\r\n\r\n /**\r\n * The name of the bucket in Amazon S3 to use for build cache.\r\n */\r\n s3Bucket: string;\r\n\r\n /**\r\n * An optional prefix (\"folder\") for cache items.\r\n */\r\n s3Prefix?: string;\r\n\r\n /**\r\n * If set to true, allow writing to the cache. Defaults to false.\r\n */\r\n isCacheWriteAllowed?: boolean;\r\n}\r\n\r\n/**\r\n * @public\r\n */\r\nexport class RushAmazonS3BuildCachePlugin implements IRushPlugin {\r\n public pluginName: string = PLUGIN_NAME;\r\n\r\n public apply(rushSession: RushSession, rushConfig: RushConfiguration): void {\r\n rushSession.hooks.initialize.tap(PLUGIN_NAME, () => {\r\n rushSession.registerCloudBuildCacheProviderFactory(\r\n 'amazon-s3',\r\n (buildCacheConfig): AmazonS3BuildCacheProvider => {\r\n type IBuildCache = typeof buildCacheConfig & {\r\n amazonS3Configuration: IAmazonS3ConfigurationJson;\r\n };\r\n const { amazonS3Configuration } = buildCacheConfig as IBuildCache;\r\n return new AmazonS3BuildCacheProviderModule.AmazonS3BuildCacheProvider(\r\n {\r\n s3Region: amazonS3Configuration.s3Region,\r\n s3Bucket: amazonS3Configuration.s3Bucket,\r\n s3Prefix: amazonS3Configuration.s3Prefix,\r\n isCacheWriteAllowed: !!amazonS3Configuration.isCacheWriteAllowed\r\n },\r\n rushSession\r\n );\r\n }\r\n );\r\n });\r\n }\r\n}\r\n"]}
@@ -0,0 +1,49 @@
1
+ /// <reference types="node" />
2
+ import * as fetch from 'node-fetch';
3
+ /**
4
+ * For use with {@link WebClient}.
5
+ */
6
+ export declare type WebClientResponse = fetch.Response;
7
+ /**
8
+ * For use with {@link WebClient}.
9
+ */
10
+ export interface IWebFetchOptionsBase {
11
+ timeoutMs?: number;
12
+ verb?: 'GET' | 'PUT';
13
+ headers?: fetch.Headers;
14
+ }
15
+ /**
16
+ * For use with {@link WebClient}.
17
+ */
18
+ export interface IGetFetchOptions extends IWebFetchOptionsBase {
19
+ verb: 'GET' | never;
20
+ }
21
+ /**
22
+ * For use with {@link WebClient}.
23
+ */
24
+ export interface IPutFetchOptions extends IWebFetchOptionsBase {
25
+ verb: 'PUT';
26
+ body?: Buffer;
27
+ }
28
+ /**
29
+ * For use with {@link WebClient}.
30
+ */
31
+ export declare enum WebClientProxy {
32
+ None = 0,
33
+ Detect = 1,
34
+ Fiddler = 2
35
+ }
36
+ /**
37
+ * A helper for issuing HTTP requests.
38
+ */
39
+ export declare class WebClient {
40
+ readonly standardHeaders: fetch.Headers;
41
+ accept: string | undefined;
42
+ userAgent: string | undefined;
43
+ proxy: WebClientProxy;
44
+ constructor();
45
+ static mergeHeaders(target: fetch.Headers, source: fetch.Headers): void;
46
+ addBasicAuthHeader(userName: string, password: string): void;
47
+ fetchAsync(url: string, options?: IGetFetchOptions | IPutFetchOptions): Promise<WebClientResponse>;
48
+ }
49
+ //# sourceMappingURL=WebClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebClient.d.ts","sourceRoot":"","sources":["../src/WebClient.ts"],"names":[],"mappings":";AAaA,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AAMpC;;GAEG;AACH,oBAAY,iBAAiB,GAAG,KAAK,CAAC,QAAQ,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACrB,OAAO,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB;IAC5D,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,oBAAoB;IAC5D,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,oBAAY,cAAc;IACxB,IAAI,IAAA;IACJ,MAAM,IAAA;IACN,OAAO,IAAA;CACR;AAED;;GAEG;AACH,qBAAa,SAAS;IACpB,SAAgB,eAAe,EAAE,KAAK,CAAC,OAAO,CAAuB;IAE9D,MAAM,EAAE,MAAM,GAAG,SAAS,CAAS;IACnC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAgE;IAE7F,KAAK,EAAE,cAAc,CAAyB;;WAIvC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,OAAO,GAAG,IAAI;IAMvE,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAOtD,UAAU,CACrB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,GAC5C,OAAO,CAAC,iBAAiB,CAAC;CAsD9B"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
7
+ }) : (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ o[k2] = m[k];
10
+ }));
11
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
12
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
13
+ }) : function(o, v) {
14
+ o["default"] = v;
15
+ });
16
+ var __importStar = (this && this.__importStar) || function (mod) {
17
+ if (mod && mod.__esModule) return mod;
18
+ var result = {};
19
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
20
+ __setModuleDefault(result, mod);
21
+ return result;
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.WebClient = exports.WebClientProxy = void 0;
25
+ // ===================================================================================================================
26
+ // AS A TEMPORARY WORKAROUND, THIS FILE WAS COPY+PASTED FROM THE "rush-lib" PROJECT.
27
+ //
28
+ // Eventually we plan to convert it into a more generic API for "node-core-library" or
29
+ // else replace it with a third party solution such as Axios. See the discussion here:
30
+ // https://github.com/microsoft/rushstack/pull/3036#discussion_r758010126
31
+ // ===================================================================================================================
32
+ const os = __importStar(require("os"));
33
+ const process = __importStar(require("process"));
34
+ const fetch = __importStar(require("node-fetch"));
35
+ const node_core_library_1 = require("@rushstack/node-core-library");
36
+ const createHttpsProxyAgent = node_core_library_1.Import.lazy('https-proxy-agent', require);
37
+ /**
38
+ * For use with {@link WebClient}.
39
+ */
40
+ var WebClientProxy;
41
+ (function (WebClientProxy) {
42
+ WebClientProxy[WebClientProxy["None"] = 0] = "None";
43
+ WebClientProxy[WebClientProxy["Detect"] = 1] = "Detect";
44
+ WebClientProxy[WebClientProxy["Fiddler"] = 2] = "Fiddler";
45
+ })(WebClientProxy = exports.WebClientProxy || (exports.WebClientProxy = {}));
46
+ /**
47
+ * A helper for issuing HTTP requests.
48
+ */
49
+ class WebClient {
50
+ constructor() {
51
+ this.standardHeaders = new fetch.Headers();
52
+ this.accept = '*/*';
53
+ this.userAgent = `rush node/${process.version} ${os.platform()} ${os.arch()}`;
54
+ this.proxy = WebClientProxy.Detect;
55
+ }
56
+ static mergeHeaders(target, source) {
57
+ source.forEach((value, name) => {
58
+ target.set(name, value);
59
+ });
60
+ }
61
+ addBasicAuthHeader(userName, password) {
62
+ this.standardHeaders.set('Authorization', 'Basic ' + Buffer.from(userName + ':' + password).toString('base64'));
63
+ }
64
+ async fetchAsync(url, options) {
65
+ const headers = new fetch.Headers();
66
+ WebClient.mergeHeaders(headers, this.standardHeaders);
67
+ if (options === null || options === void 0 ? void 0 : options.headers) {
68
+ WebClient.mergeHeaders(headers, options.headers);
69
+ }
70
+ if (this.userAgent) {
71
+ headers.set('user-agent', this.userAgent);
72
+ }
73
+ if (this.accept) {
74
+ headers.set('accept', this.accept);
75
+ }
76
+ let proxyUrl = '';
77
+ switch (this.proxy) {
78
+ case WebClientProxy.Detect:
79
+ if (process.env.HTTPS_PROXY) {
80
+ proxyUrl = process.env.HTTPS_PROXY;
81
+ }
82
+ else if (process.env.HTTP_PROXY) {
83
+ proxyUrl = process.env.HTTP_PROXY;
84
+ }
85
+ break;
86
+ case WebClientProxy.Fiddler:
87
+ // For debugging, disable cert validation
88
+ // eslint-disable-next-line
89
+ process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
90
+ proxyUrl = 'http://localhost:8888/';
91
+ break;
92
+ }
93
+ let agent = undefined;
94
+ if (proxyUrl) {
95
+ agent = createHttpsProxyAgent(proxyUrl);
96
+ }
97
+ const timeoutMs = (options === null || options === void 0 ? void 0 : options.timeoutMs) !== undefined ? options.timeoutMs : 15 * 1000; // 15 seconds
98
+ const requestInit = {
99
+ method: options === null || options === void 0 ? void 0 : options.verb,
100
+ headers: headers,
101
+ agent: agent,
102
+ timeout: timeoutMs
103
+ };
104
+ const putOptions = options;
105
+ if (putOptions === null || putOptions === void 0 ? void 0 : putOptions.body) {
106
+ requestInit.body = putOptions.body;
107
+ }
108
+ return await fetch.default(url, requestInit);
109
+ }
110
+ }
111
+ exports.WebClient = WebClient;
112
+ //# sourceMappingURL=WebClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebClient.js","sourceRoot":"","sources":["../src/WebClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\n// ===================================================================================================================\r\n// AS A TEMPORARY WORKAROUND, THIS FILE WAS COPY+PASTED FROM THE \"rush-lib\" PROJECT.\r\n//\r\n// Eventually we plan to convert it into a more generic API for \"node-core-library\" or\r\n// else replace it with a third party solution such as Axios. See the discussion here:\r\n// https://github.com/microsoft/rushstack/pull/3036#discussion_r758010126\r\n// ===================================================================================================================\r\n\r\nimport * as os from 'os';\r\nimport * as process from 'process';\r\nimport * as fetch from 'node-fetch';\r\nimport * as http from 'http';\r\nimport { Import } from '@rushstack/node-core-library';\r\n\r\nconst createHttpsProxyAgent: typeof import('https-proxy-agent') = Import.lazy('https-proxy-agent', require);\r\n\r\n/**\r\n * For use with {@link WebClient}.\r\n */\r\nexport type WebClientResponse = fetch.Response;\r\n\r\n/**\r\n * For use with {@link WebClient}.\r\n */\r\nexport interface IWebFetchOptionsBase {\r\n timeoutMs?: number;\r\n verb?: 'GET' | 'PUT';\r\n headers?: fetch.Headers;\r\n}\r\n\r\n/**\r\n * For use with {@link WebClient}.\r\n */\r\nexport interface IGetFetchOptions extends IWebFetchOptionsBase {\r\n verb: 'GET' | never;\r\n}\r\n\r\n/**\r\n * For use with {@link WebClient}.\r\n */\r\nexport interface IPutFetchOptions extends IWebFetchOptionsBase {\r\n verb: 'PUT';\r\n body?: Buffer;\r\n}\r\n\r\n/**\r\n * For use with {@link WebClient}.\r\n */\r\nexport enum WebClientProxy {\r\n None,\r\n Detect,\r\n Fiddler\r\n}\r\n\r\n/**\r\n * A helper for issuing HTTP requests.\r\n */\r\nexport class WebClient {\r\n public readonly standardHeaders: fetch.Headers = new fetch.Headers();\r\n\r\n public accept: string | undefined = '*/*';\r\n public userAgent: string | undefined = `rush node/${process.version} ${os.platform()} ${os.arch()}`;\r\n\r\n public proxy: WebClientProxy = WebClientProxy.Detect;\r\n\r\n public constructor() {}\r\n\r\n public static mergeHeaders(target: fetch.Headers, source: fetch.Headers): void {\r\n source.forEach((value, name) => {\r\n target.set(name, value);\r\n });\r\n }\r\n\r\n public addBasicAuthHeader(userName: string, password: string): void {\r\n this.standardHeaders.set(\r\n 'Authorization',\r\n 'Basic ' + Buffer.from(userName + ':' + password).toString('base64')\r\n );\r\n }\r\n\r\n public async fetchAsync(\r\n url: string,\r\n options?: IGetFetchOptions | IPutFetchOptions\r\n ): Promise<WebClientResponse> {\r\n const headers: fetch.Headers = new fetch.Headers();\r\n\r\n WebClient.mergeHeaders(headers, this.standardHeaders);\r\n\r\n if (options?.headers) {\r\n WebClient.mergeHeaders(headers, options.headers);\r\n }\r\n\r\n if (this.userAgent) {\r\n headers.set('user-agent', this.userAgent);\r\n }\r\n if (this.accept) {\r\n headers.set('accept', this.accept);\r\n }\r\n\r\n let proxyUrl: string = '';\r\n\r\n switch (this.proxy) {\r\n case WebClientProxy.Detect:\r\n if (process.env.HTTPS_PROXY) {\r\n proxyUrl = process.env.HTTPS_PROXY;\r\n } else if (process.env.HTTP_PROXY) {\r\n proxyUrl = process.env.HTTP_PROXY;\r\n }\r\n break;\r\n\r\n case WebClientProxy.Fiddler:\r\n // For debugging, disable cert validation\r\n // eslint-disable-next-line\r\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\r\n proxyUrl = 'http://localhost:8888/';\r\n break;\r\n }\r\n\r\n let agent: http.Agent | undefined = undefined;\r\n if (proxyUrl) {\r\n agent = createHttpsProxyAgent(proxyUrl);\r\n }\r\n\r\n const timeoutMs: number = options?.timeoutMs !== undefined ? options.timeoutMs : 15 * 1000; // 15 seconds\r\n const requestInit: fetch.RequestInit = {\r\n method: options?.verb,\r\n headers: headers,\r\n agent: agent,\r\n timeout: timeoutMs\r\n };\r\n const putOptions: IPutFetchOptions | undefined = options as IPutFetchOptions | undefined;\r\n if (putOptions?.body) {\r\n requestInit.body = putOptions.body;\r\n }\r\n\r\n return await fetch.default(url, requestInit);\r\n }\r\n}\r\n"]}
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { RushAmazonS3BuildCachePlugin } from './RushAmazonS3BuildCachePlugin';
2
+ export default RushAmazonS3BuildCachePlugin;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAE9E,eAAe,4BAA4B,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3
+ // See LICENSE in the project root for license information.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ const RushAmazonS3BuildCachePlugin_1 = require("./RushAmazonS3BuildCachePlugin");
6
+ exports.default = RushAmazonS3BuildCachePlugin_1.RushAmazonS3BuildCachePlugin;
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,4FAA4F;AAC5F,2DAA2D;;AAE3D,iFAA8E;AAE9E,kBAAe,2DAA4B,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.\r\n// See LICENSE in the project root for license information.\r\n\r\nimport { RushAmazonS3BuildCachePlugin } from './RushAmazonS3BuildCachePlugin';\r\n\r\nexport default RushAmazonS3BuildCachePlugin;\r\n"]}
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "title": "Configuration for build cache with Amazon S3 configuration",
4
+
5
+ "type": "object",
6
+
7
+ "additionalProperties": false,
8
+
9
+ "required": ["s3Region", "s3Bucket"],
10
+
11
+ "properties": {
12
+ "s3Region": {
13
+ "type": "string",
14
+ "description": "(Required) The Amazon S3 region of the bucket to use for build cache (e.g. \"us-east-1\")."
15
+ },
16
+
17
+ "s3Bucket": {
18
+ "type": "string",
19
+ "description": "(Required) The name of the bucket in Amazon S3 to use for build cache."
20
+ },
21
+
22
+ "s3Prefix": {
23
+ "type": "string",
24
+ "description": "An optional prefix (\"folder\") for cache items."
25
+ },
26
+
27
+ "isCacheWriteAllowed": {
28
+ "type": "boolean",
29
+ "description": "If set to true, allow writing to the cache. Defaults to false."
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,11 @@
1
+ // This file is read by tools that parse documentation comments conforming to the TSDoc standard.
2
+ // It should be published with your NPM package. It should not be tracked by Git.
3
+ {
4
+ "tsdocVersion": "0.12",
5
+ "toolPackages": [
6
+ {
7
+ "packageName": "@microsoft/api-extractor",
8
+ "packageVersion": "7.18.19"
9
+ }
10
+ ]
11
+ }
package/package.json CHANGED
@@ -1,5 +1,32 @@
1
1
  {
2
- "license": "MIT",
3
- "name": "@rushstack/rush-amazon-s3-build-cache-plugin",
4
- "version": "0.0.0"
2
+ "name": "@rushstack/rush-amazon-s3-build-cache-plugin",
3
+ "version": "5.57.0-dev.1",
4
+ "description": "Rush plugin for Amazon S3 cloud build cache",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/microsoft/rushstack/tree/master/heft-plugins/heft-webpack5-plugin"
8
+ },
9
+ "homepage": "https://rushjs.io",
10
+ "main": "lib/index.js",
11
+ "types": "lib/index.d.ts",
12
+ "license": "MIT",
13
+ "dependencies": {
14
+ "@rushstack/node-core-library": "3.43.2",
15
+ "@rushstack/rush-sdk": "5.57.0-dev.1",
16
+ "https-proxy-agent": "~5.0.0",
17
+ "node-fetch": "2.6.2"
18
+ },
19
+ "devDependencies": {
20
+ "@microsoft/rush-lib": "5.57.0-dev.1",
21
+ "@rushstack/eslint-config": "2.4.5",
22
+ "@rushstack/heft": "0.42.3",
23
+ "@rushstack/heft-node-rig": "1.2.31",
24
+ "@types/heft-jest": "1.0.1",
25
+ "@types/node": "12.20.24",
26
+ "@types/node-fetch": "1.6.9"
27
+ },
28
+ "scripts": {
29
+ "build": "heft test --clean",
30
+ "start": "heft test --clean --watch"
31
+ }
5
32
  }