@adinsure-ops/ops-cli 5.4.2 → 5.5.0-rc1
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 +140 -2
- package/bin/run.js +2 -6
- package/lib/command.base.d.ts +7 -1
- package/lib/command.base.jira.d.ts +23 -5
- package/lib/command.base.jira.js +47 -12
- package/lib/command.base.js +37 -8
- package/lib/command.download.d.ts +11 -0
- package/lib/command.download.js +27 -0
- package/lib/commands/config/get.d.ts +1 -1
- package/lib/commands/config/list.js +1 -1
- package/lib/commands/config/set.d.ts +2 -2
- package/lib/commands/config/set.js +2 -2
- package/lib/commands/config/unset.d.ts +1 -1
- package/lib/commands/docker/update-image-version.d.ts +31 -3
- package/lib/commands/docker/update-image-version.js +112 -6
- package/lib/commands/doctor.d.ts +1 -1
- package/lib/commands/download/client.d.ts +7 -20
- package/lib/commands/download/client.js +12 -47
- package/lib/commands/download/identity-server.d.ts +7 -20
- package/lib/commands/download/identity-server.js +12 -47
- package/lib/commands/download/jmeter.d.ts +3 -3
- package/lib/commands/download/jmeter.js +9 -11
- package/lib/commands/download/keycloak-scim.d.ts +4 -4
- package/lib/commands/download/keycloak-scim.js +9 -11
- package/lib/commands/download/platform.d.ts +7 -20
- package/lib/commands/download/platform.js +12 -47
- package/lib/commands/download/scheduler.d.ts +7 -20
- package/lib/commands/download/scheduler.js +12 -47
- package/lib/commands/download/server.d.ts +7 -20
- package/lib/commands/download/server.js +12 -47
- package/lib/commands/download/signalr.d.ts +7 -20
- package/lib/commands/download/signalr.js +12 -47
- package/lib/commands/download/studio.d.ts +12 -24
- package/lib/commands/download/studio.js +14 -48
- package/lib/commands/gitlab/get-tag-pipeline.d.ts +7 -7
- package/lib/commands/gitlab/get-tag-pipeline.js +5 -5
- package/lib/commands/gitlab/next-nightly-tag.d.ts +7 -7
- package/lib/commands/gitlab/next-nightly-tag.js +6 -6
- package/lib/commands/jira/issue.d.ts +4 -4
- package/lib/commands/jira/issue.js +2 -2
- package/lib/commands/jira/labels.d.ts +8 -9
- package/lib/commands/jira/labels.js +11 -10
- package/lib/commands/log/add.d.ts +10 -5
- package/lib/commands/log/add.js +42 -13
- package/lib/commands/log/generate.d.ts +6 -6
- package/lib/commands/log/generate.js +16 -8
- package/lib/commands/log/validate.js +2 -2
- package/lib/commands/login.d.ts +25 -5
- package/lib/commands/login.js +162 -40
- package/lib/commands/login.ru.d.ts +2 -2
- package/lib/commands/login.ru.js +1 -1
- package/lib/commands/npm/check-publish.d.ts +4 -4
- package/lib/commands/npm/check-publish.js +1 -1
- package/lib/commands/npm/dependency-update.d.ts +17 -4
- package/lib/commands/npm/dependency-update.js +64 -41
- package/lib/commands/npm/publish.d.ts +5 -5
- package/lib/commands/npm/publish.js +2 -2
- package/lib/commands/nuget/dependency-update.d.ts +3 -3
- package/lib/commands/prepare-content.d.ts +3 -3
- package/lib/commands/prepare-content.js +24 -41
- package/lib/commands/sql.d.ts +17 -17
- package/lib/commands/sql.js +23 -27
- package/lib/commands/translate.d.ts +8 -8
- package/lib/commands/translate.js +10 -8
- package/lib/commands/version.d.ts +10 -10
- package/lib/commands/version.js +6 -7
- package/lib/lib/command.d.ts +5 -3
- package/lib/lib/command.js +44 -44
- package/lib/lib/config.js +1 -1
- package/lib/lib/gitlab.d.ts +3 -1
- package/lib/lib/gitlab.js +13 -7
- package/lib/lib/http.d.ts +37 -0
- package/lib/lib/http.js +278 -0
- package/lib/lib/npm.d.ts +7 -4
- package/lib/lib/npm.js +15 -6
- package/lib/lib/npmrc.js +3 -3
- package/lib/lib/yarnrc.js +3 -3
- package/lib/security/cache.js +1 -1
- package/lib/security/context.d.ts +10 -8
- package/lib/security/context.js +49 -64
- package/oclif.manifest.json +533 -532
- package/package.json +71 -62
package/lib/lib/command.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { __asyncValues, __awaiter } from "tslib";
|
|
2
|
-
import { spawn } from 'child_process';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
3
|
export default class ChildProcessCommand {
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* @
|
|
5
|
+
* Run a command without a shell and collect its output.
|
|
6
|
+
* On Windows the command is started through `cmd /c` so that `.cmd` shims such as `yarn` and `code` are found.
|
|
7
|
+
* @param cmd Command and its arguments
|
|
8
|
+
* @returns {Promise<{ data: string, error: string }>} stdout and stderr of the command
|
|
8
9
|
*/
|
|
9
10
|
runCommand(cmd) {
|
|
10
11
|
return __awaiter(this, void 0, void 0, function* () {
|
|
11
|
-
var _a
|
|
12
|
-
var _g;
|
|
12
|
+
var _a;
|
|
13
13
|
let sh;
|
|
14
14
|
let args;
|
|
15
15
|
let cp;
|
|
@@ -25,47 +25,24 @@ export default class ChildProcessCommand {
|
|
|
25
25
|
cp = spawn(sh, args, {
|
|
26
26
|
// cwd:
|
|
27
27
|
// pkg.path,
|
|
28
|
-
env: Object.assign(Object.assign({}, process.env), process.stdout.isTTY ? { FORCE_COLOR: (
|
|
28
|
+
env: Object.assign(Object.assign({}, process.env), process.stdout.isTTY ? { FORCE_COLOR: (_a = process.env.FORCE_COLOR) !== null && _a !== void 0 ? _a : '1' } : {}),
|
|
29
29
|
stdio: 'pipe',
|
|
30
|
-
shell: true,
|
|
31
30
|
});
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
_h = false;
|
|
37
|
-
const chunk = _c;
|
|
38
|
-
data += chunk;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
42
|
-
finally {
|
|
43
|
-
try {
|
|
44
|
-
if (!_h && !_a && (_b = _j.return)) yield _b.call(_j);
|
|
45
|
-
}
|
|
46
|
-
finally { if (e_1) throw e_1.error; }
|
|
47
|
-
}
|
|
48
|
-
let error = '';
|
|
49
|
-
try {
|
|
50
|
-
for (var _l = true, _m = __asyncValues(cp.stderr), _o; _o = yield _m.next(), _d = _o.done, !_d; _l = true) {
|
|
51
|
-
_f = _o.value;
|
|
52
|
-
_l = false;
|
|
53
|
-
const chunk = _f;
|
|
54
|
-
error += chunk;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
58
|
-
finally {
|
|
59
|
-
try {
|
|
60
|
-
if (!_l && !_d && (_e = _m.return)) yield _e.call(_m);
|
|
61
|
-
}
|
|
62
|
-
finally { if (e_2) throw e_2.error; }
|
|
63
|
-
}
|
|
64
|
-
const exitCode = yield new Promise((resolve) => {
|
|
65
|
-
cp.on('close', resolve);
|
|
31
|
+
// Without a shell, a missing executable emits 'error' instead of exiting with a non-zero code
|
|
32
|
+
const exit = new Promise((resolve, reject) => {
|
|
33
|
+
cp.on('error', reject);
|
|
34
|
+
cp.on('close', (code, signal) => resolve({ code, signal }));
|
|
66
35
|
});
|
|
67
|
-
|
|
68
|
-
|
|
36
|
+
// Avoid an unhandled rejection while the output streams are being read
|
|
37
|
+
exit.catch(() => undefined);
|
|
38
|
+
// Read both streams at the same time, so a child filling the stderr pipe can't block on it
|
|
39
|
+
const [data, error] = yield Promise.all([this.readStream(cp.stdout), this.readStream(cp.stderr)]);
|
|
40
|
+
const { code, signal } = yield exit;
|
|
41
|
+
if (signal) {
|
|
42
|
+
throw new Error(`subprocess killed by ${signal}, ${error}`);
|
|
43
|
+
}
|
|
44
|
+
if (code) {
|
|
45
|
+
throw new Error(`subprocess error exit ${code}, ${error}`);
|
|
69
46
|
}
|
|
70
47
|
return { data, error };
|
|
71
48
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -75,4 +52,27 @@ export default class ChildProcessCommand {
|
|
|
75
52
|
}
|
|
76
53
|
});
|
|
77
54
|
}
|
|
55
|
+
readStream(stream) {
|
|
56
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
+
var _a, stream_1, stream_1_1;
|
|
58
|
+
var _b, e_1, _c, _d;
|
|
59
|
+
let result = '';
|
|
60
|
+
try {
|
|
61
|
+
for (_a = true, stream_1 = __asyncValues(stream); stream_1_1 = yield stream_1.next(), _b = stream_1_1.done, !_b; _a = true) {
|
|
62
|
+
_d = stream_1_1.value;
|
|
63
|
+
_a = false;
|
|
64
|
+
const chunk = _d;
|
|
65
|
+
result += chunk;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
69
|
+
finally {
|
|
70
|
+
try {
|
|
71
|
+
if (!_a && !_b && (_c = stream_1.return)) yield _c.call(stream_1);
|
|
72
|
+
}
|
|
73
|
+
finally { if (e_1) throw e_1.error; }
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
78
|
}
|
package/lib/lib/config.js
CHANGED
package/lib/lib/gitlab.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import semver from 'semver';
|
|
2
|
+
import HttpClient from './http.js';
|
|
2
3
|
export default class GitLab {
|
|
4
|
+
private readonly http;
|
|
3
5
|
private readonly pat;
|
|
4
6
|
private readonly host;
|
|
5
7
|
private readonly project;
|
|
6
8
|
private readonly apiBase;
|
|
7
|
-
constructor(host: string, project: string, pat: string);
|
|
9
|
+
constructor(host: string, project: string, pat: string, http?: HttpClient);
|
|
8
10
|
/**
|
|
9
11
|
* Try to figure out latest available version already created
|
|
10
12
|
* @param searchVersion Version to search for
|
package/lib/lib/gitlab.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { __awaiter } from "tslib";
|
|
2
|
-
import axios from 'axios';
|
|
3
2
|
import semver from 'semver';
|
|
3
|
+
import HttpClient from './http.js';
|
|
4
4
|
export default class GitLab {
|
|
5
|
-
constructor(host, project, pat) {
|
|
5
|
+
constructor(host, project, pat, http = new HttpClient()) {
|
|
6
|
+
this.http = http;
|
|
6
7
|
this.apiBase = '/api/v4/projects';
|
|
7
8
|
this.pat = pat;
|
|
8
9
|
this.host = host;
|
|
@@ -16,22 +17,24 @@ export default class GitLab {
|
|
|
16
17
|
*/
|
|
17
18
|
getLatestVersion(searchVersion_1) {
|
|
18
19
|
return __awaiter(this, arguments, void 0, function* (searchVersion, prefix = '') {
|
|
20
|
+
var _a;
|
|
19
21
|
const versions = [];
|
|
20
22
|
try {
|
|
21
23
|
let page = 1;
|
|
22
24
|
let totalPages = 1;
|
|
23
25
|
do {
|
|
24
|
-
const response = yield
|
|
26
|
+
const response = yield this.http.getJson(`${this.host}${this.apiBase}/${this.project}/repository/tags`, {
|
|
25
27
|
headers: {
|
|
26
28
|
Authorization: `Bearer ${this.pat}`,
|
|
27
29
|
},
|
|
28
30
|
params: {
|
|
29
31
|
search: `^${prefix}v${searchVersion}`,
|
|
30
|
-
// eslint-disable-next-line camelcase
|
|
31
32
|
per_page: 100,
|
|
32
33
|
page,
|
|
33
34
|
},
|
|
34
35
|
});
|
|
36
|
+
if (!Array.isArray(response.data))
|
|
37
|
+
throw new Error('Unexpected GitLab tags response');
|
|
35
38
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
39
|
response.data.forEach((tag) => {
|
|
37
40
|
const regex = new RegExp(`${prefix}v\\d+\\.\\d+\\.\\d+(-\\d{6}\\.\\d+)?$`);
|
|
@@ -52,7 +55,7 @@ export default class GitLab {
|
|
|
52
55
|
versions.push(semanticVersion);
|
|
53
56
|
}
|
|
54
57
|
});
|
|
55
|
-
totalPages = Number.parseInt(response.headers
|
|
58
|
+
totalPages = Number.parseInt((_a = response.headers.get('x-total-pages')) !== null && _a !== void 0 ? _a : '1', 10);
|
|
56
59
|
page++;
|
|
57
60
|
} while (page <= totalPages);
|
|
58
61
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -72,7 +75,7 @@ export default class GitLab {
|
|
|
72
75
|
createNewTag(tag_name, ref) {
|
|
73
76
|
return __awaiter(this, void 0, void 0, function* () {
|
|
74
77
|
try {
|
|
75
|
-
yield
|
|
78
|
+
yield this.http.postJson(`${this.host}${this.apiBase}/${this.project}/repository/tags`, {
|
|
76
79
|
tag_name,
|
|
77
80
|
ref,
|
|
78
81
|
}, {
|
|
@@ -92,7 +95,8 @@ export default class GitLab {
|
|
|
92
95
|
let pipelines = null;
|
|
93
96
|
tag = tag.replaceAll(/^v/g, ''); // trim if tag starts with v because already include it in search
|
|
94
97
|
try {
|
|
95
|
-
pipelines = yield
|
|
98
|
+
pipelines = yield this.http.getJson(`${this.host}${this.apiBase}/${this.project}/pipelines`, {
|
|
99
|
+
params: { ref: `v${tag}` },
|
|
96
100
|
headers: {
|
|
97
101
|
Authorization: `Bearer ${this.pat}`,
|
|
98
102
|
},
|
|
@@ -102,6 +106,8 @@ export default class GitLab {
|
|
|
102
106
|
catch (error) {
|
|
103
107
|
throw new Error(error);
|
|
104
108
|
}
|
|
109
|
+
if (!Array.isArray(pipelines.data))
|
|
110
|
+
throw new Error('Unexpected GitLab pipelines response');
|
|
105
111
|
if (pipelines.data.length > 0) {
|
|
106
112
|
return pipelines.data[0].status;
|
|
107
113
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface HttpResponse<T> {
|
|
2
|
+
data: T;
|
|
3
|
+
status: number;
|
|
4
|
+
headers: Headers;
|
|
5
|
+
}
|
|
6
|
+
export interface HttpOptions {
|
|
7
|
+
headers?: HeadersInit;
|
|
8
|
+
params?: Record<string, string | number | boolean | null | undefined>;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
export declare class HttpError extends Error {
|
|
12
|
+
readonly status: number;
|
|
13
|
+
readonly data: unknown;
|
|
14
|
+
constructor(status: number, data: unknown, message?: string);
|
|
15
|
+
}
|
|
16
|
+
export default class HttpClient {
|
|
17
|
+
private readonly debug;
|
|
18
|
+
private readonly proxyAgents;
|
|
19
|
+
private directAgent?;
|
|
20
|
+
constructor(debug?: (message: string) => void);
|
|
21
|
+
getJson<T>(url: string, options?: HttpOptions): Promise<HttpResponse<T>>;
|
|
22
|
+
getBuffer(url: string, options?: HttpOptions): Promise<HttpResponse<Buffer>>;
|
|
23
|
+
postJson<T>(url: string, data: unknown, options?: HttpOptions): Promise<HttpResponse<T>>;
|
|
24
|
+
putJson<T>(url: string, data: unknown, options?: HttpOptions): Promise<HttpResponse<T>>;
|
|
25
|
+
postForm<T>(url: string, data: URLSearchParams, options?: HttpOptions): Promise<HttpResponse<T>>;
|
|
26
|
+
close(): Promise<void>;
|
|
27
|
+
private sendJson;
|
|
28
|
+
private getDispatcher;
|
|
29
|
+
private forwardProxy;
|
|
30
|
+
private createHeaders;
|
|
31
|
+
private readBody;
|
|
32
|
+
private parseUrl;
|
|
33
|
+
private networkError;
|
|
34
|
+
private jsonResponse;
|
|
35
|
+
private readData;
|
|
36
|
+
private request;
|
|
37
|
+
}
|
package/lib/lib/http.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { __awaiter } from "tslib";
|
|
2
|
+
import { getProxyForUrl } from 'proxy-from-env';
|
|
3
|
+
import { Agent, buildConnector, Pool, ProxyAgent } from 'undici';
|
|
4
|
+
export class HttpError extends Error {
|
|
5
|
+
constructor(status, data, message = `Request failed with status code ${status}`) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.data = data;
|
|
9
|
+
this.name = 'HttpError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export default class HttpClient {
|
|
13
|
+
constructor(debug = () => { }) {
|
|
14
|
+
this.debug = debug;
|
|
15
|
+
this.proxyAgents = new Map();
|
|
16
|
+
}
|
|
17
|
+
getJson(url_1) {
|
|
18
|
+
return __awaiter(this, arguments, void 0, function* (url, options = {}) {
|
|
19
|
+
const response = yield this.request(url, 'GET', options);
|
|
20
|
+
return this.jsonResponse(response, options.signal);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
getBuffer(url_1) {
|
|
24
|
+
return __awaiter(this, arguments, void 0, function* (url, options = {}) {
|
|
25
|
+
const response = yield this.request(url, 'GET', options);
|
|
26
|
+
return { data: Buffer.from(yield this.readBody(() => response.arrayBuffer(), options.signal)), status: response.status, headers: response.headers };
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
postJson(url, data, options = {}) {
|
|
30
|
+
return this.sendJson('POST', url, data, options);
|
|
31
|
+
}
|
|
32
|
+
putJson(url, data, options = {}) {
|
|
33
|
+
return this.sendJson('PUT', url, data, options);
|
|
34
|
+
}
|
|
35
|
+
postForm(url_1, data_1) {
|
|
36
|
+
return __awaiter(this, arguments, void 0, function* (url, data, options = {}) {
|
|
37
|
+
const headers = this.createHeaders(options.headers);
|
|
38
|
+
headers.set('Content-Type', 'application/x-www-form-urlencoded');
|
|
39
|
+
return this.jsonResponse(yield this.request(url, 'POST', Object.assign(Object.assign({}, options), { headers }), data.toString()), options.signal);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
close() {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
var _a;
|
|
45
|
+
try {
|
|
46
|
+
yield Promise.all([(_a = this.directAgent) === null || _a === void 0 ? void 0 : _a.close(), ...[...this.proxyAgents.values()].map(agent => agent.close())]);
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
this.proxyAgents.clear();
|
|
50
|
+
this.directAgent = undefined;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
sendJson(method, url, data, options) {
|
|
55
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
const headers = this.createHeaders(options.headers);
|
|
57
|
+
if (!headers.has('Content-Type'))
|
|
58
|
+
headers.set('Content-Type', 'application/json');
|
|
59
|
+
return this.jsonResponse(yield this.request(url, method, Object.assign(Object.assign({}, options), { headers }), JSON.stringify(data)), options.signal);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
getDispatcher(url) {
|
|
63
|
+
var _a;
|
|
64
|
+
// Keep Axios' protocol selection, NO_PROXY matching and schemeless URL support.
|
|
65
|
+
// Resolve bypasses before parsing or constructing any proxy agent.
|
|
66
|
+
const proxy = getProxyForUrl(url.href);
|
|
67
|
+
if (!proxy)
|
|
68
|
+
return (_a = this.directAgent) !== null && _a !== void 0 ? _a : (this.directAgent = new Agent());
|
|
69
|
+
const key = `${url.protocol}:${proxy}`;
|
|
70
|
+
let agent = this.proxyAgents.get(key);
|
|
71
|
+
if (!agent) {
|
|
72
|
+
try {
|
|
73
|
+
const uri = new URL(proxy);
|
|
74
|
+
const token = uri.username || uri.password ?
|
|
75
|
+
`Basic ${Buffer.from(`${decodeURIComponent(uri.username)}:${decodeURIComponent(uri.password)}`).toString('base64')}` :
|
|
76
|
+
undefined;
|
|
77
|
+
uri.username = '';
|
|
78
|
+
uri.password = '';
|
|
79
|
+
// Forward plaintext destinations over either HTTP or TLS to the proxy.
|
|
80
|
+
// HTTPS destinations retain end-to-end TLS through a CONNECT tunnel.
|
|
81
|
+
agent = url.protocol === 'http:' ? this.forwardProxy(uri, token) : new ProxyAgent({ uri: uri.href, token });
|
|
82
|
+
this.proxyAgents.set(key, agent);
|
|
83
|
+
}
|
|
84
|
+
catch (_b) {
|
|
85
|
+
throw new Error('Invalid proxy configuration');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return agent;
|
|
89
|
+
}
|
|
90
|
+
forwardProxy(uri, token) {
|
|
91
|
+
const connect = buildConnector({});
|
|
92
|
+
return new Pool(uri, {
|
|
93
|
+
// The forwarded Host header identifies the destination, but TLS must
|
|
94
|
+
// authenticate the proxy hostname, never the destination hostname.
|
|
95
|
+
// Clearing servername makes undici derive SNI from the proxy host it
|
|
96
|
+
// connects to (and omit it for IP addresses, as RFC 6066 requires).
|
|
97
|
+
connect: (options, callback) => connect(Object.assign(Object.assign({}, options), { servername: undefined }), callback),
|
|
98
|
+
}).compose(dispatch => (options, handler) => {
|
|
99
|
+
// Node's bundled fetch versions use either flat header arrays or HeadersInit.
|
|
100
|
+
const raw = options.headers;
|
|
101
|
+
const pairs = Array.isArray(raw) && typeof raw[0] === 'string' ?
|
|
102
|
+
Array.from({ length: raw.length / 2 }, (_, i) => [raw[i * 2], raw[i * 2 + 1]]) : raw;
|
|
103
|
+
const headers = this.createHeaders(pairs);
|
|
104
|
+
if (!headers.has('host'))
|
|
105
|
+
headers.set('host', new URL(options.origin).host);
|
|
106
|
+
headers.delete('proxy-authorization');
|
|
107
|
+
if (token)
|
|
108
|
+
headers.set('proxy-authorization', token);
|
|
109
|
+
return dispatch(Object.assign(Object.assign({}, options), { origin: uri.origin, path: `${options.origin}${options.path}`, headers: Object.fromEntries(headers) }), {
|
|
110
|
+
onRequestStart: (controller, context) => { var _a; return (_a = handler.onRequestStart) === null || _a === void 0 ? void 0 : _a.call(handler, controller, context); },
|
|
111
|
+
onResponseStart: (controller, status, responseHeaders, statusMessage) => {
|
|
112
|
+
var _a;
|
|
113
|
+
if (status === 407) {
|
|
114
|
+
controller.abort(new HttpError(407, undefined, 'Proxy authentication required (HTTP 407)'));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
(_a = handler.onResponseStart) === null || _a === void 0 ? void 0 : _a.call(handler, controller, status, responseHeaders, statusMessage);
|
|
118
|
+
},
|
|
119
|
+
onResponseData: (controller, chunk) => { var _a; return (_a = handler.onResponseData) === null || _a === void 0 ? void 0 : _a.call(handler, controller, chunk); },
|
|
120
|
+
onResponseEnd: (controller, trailers) => { var _a; return (_a = handler.onResponseEnd) === null || _a === void 0 ? void 0 : _a.call(handler, controller, trailers); },
|
|
121
|
+
onResponseError: (controller, error) => { var _a; return (_a = handler.onResponseError) === null || _a === void 0 ? void 0 : _a.call(handler, controller, error); },
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
createHeaders(values) {
|
|
126
|
+
try {
|
|
127
|
+
return new Headers(values);
|
|
128
|
+
}
|
|
129
|
+
catch (_a) {
|
|
130
|
+
throw new Error('Invalid HTTP request headers');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
readBody(read, signal) {
|
|
134
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
try {
|
|
136
|
+
return yield read();
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (signal === null || signal === void 0 ? void 0 : signal.aborted)
|
|
140
|
+
throw error;
|
|
141
|
+
throw this.networkError(error);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
parseUrl(input, base) {
|
|
146
|
+
let url;
|
|
147
|
+
try {
|
|
148
|
+
url = new URL(input, base);
|
|
149
|
+
}
|
|
150
|
+
catch (_a) {
|
|
151
|
+
throw new Error('Invalid HTTP request URL');
|
|
152
|
+
}
|
|
153
|
+
if (url.username || url.password)
|
|
154
|
+
throw new Error('HTTP request URLs must not contain credentials');
|
|
155
|
+
return url;
|
|
156
|
+
}
|
|
157
|
+
networkError(error, url) {
|
|
158
|
+
// Native fetch hides DNS/TLS/socket errors in cause (sometimes AggregateError).
|
|
159
|
+
// Report diagnostic codes, never arbitrary messages containing URLs or secrets.
|
|
160
|
+
const codes = new Set();
|
|
161
|
+
const visited = new Set();
|
|
162
|
+
let proxyAuthentication = false;
|
|
163
|
+
let blockedPort = false;
|
|
164
|
+
const collect = (value) => {
|
|
165
|
+
if (!(value instanceof Error) || visited.has(value))
|
|
166
|
+
return;
|
|
167
|
+
visited.add(value);
|
|
168
|
+
// Recognize only fixed transport messages; never include their raw text.
|
|
169
|
+
proxyAuthentication || (proxyAuthentication = value instanceof HttpError && value.status === 407);
|
|
170
|
+
// undici words these differently across versions; match the status, not the exact text.
|
|
171
|
+
proxyAuthentication || (proxyAuthentication = /proxy/i.test(value.message) && /\b407\b|authentication required/i.test(value.message));
|
|
172
|
+
blockedPort || (blockedPort = value.message === 'bad port');
|
|
173
|
+
const code = value.code;
|
|
174
|
+
if (code && /^[A-Z][A-Z0-9_]{1,79}$/.test(code))
|
|
175
|
+
codes.add(code);
|
|
176
|
+
collect(value.cause);
|
|
177
|
+
if (value instanceof AggregateError)
|
|
178
|
+
value.errors.forEach(collect);
|
|
179
|
+
};
|
|
180
|
+
collect(error);
|
|
181
|
+
if (proxyAuthentication)
|
|
182
|
+
return new HttpError(407, undefined, 'Proxy authentication required (HTTP 407)');
|
|
183
|
+
if (blockedPort && url)
|
|
184
|
+
return new Error(`HTTP request port ${url.port} is blocked by native fetch`);
|
|
185
|
+
return new Error(`HTTP request failed${codes.size ? ` (${[...codes].join(', ')})` : ''}`);
|
|
186
|
+
}
|
|
187
|
+
jsonResponse(response, signal) {
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
return { data: yield this.readData(response, signal), status: response.status, headers: response.headers };
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
readData(response, signal) {
|
|
193
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
194
|
+
const text = yield this.readBody(() => response.text(), signal);
|
|
195
|
+
// Preserve axios' JSON, plain-text and empty-body response handling.
|
|
196
|
+
try {
|
|
197
|
+
return JSON.parse(text);
|
|
198
|
+
}
|
|
199
|
+
catch (_a) {
|
|
200
|
+
return text;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
request(input, method, options, body) {
|
|
205
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
206
|
+
var _a, _b, _c, _d;
|
|
207
|
+
let url = this.parseUrl(input);
|
|
208
|
+
for (const [key, value] of Object.entries((_a = options.params) !== null && _a !== void 0 ? _a : {})) {
|
|
209
|
+
if (value !== undefined && value !== null)
|
|
210
|
+
url.searchParams.set(key, String(value));
|
|
211
|
+
}
|
|
212
|
+
const headers = this.createHeaders(options.headers);
|
|
213
|
+
if (!headers.has('Accept'))
|
|
214
|
+
headers.set('Accept', 'application/json, text/plain, */*');
|
|
215
|
+
for (let redirects = 0;; redirects++) {
|
|
216
|
+
if (!['http:', 'https:'].includes(url.protocol))
|
|
217
|
+
throw new Error('Only HTTP and HTTPS URLs are supported');
|
|
218
|
+
// Never log authentication headers, request bodies or signed query strings.
|
|
219
|
+
this.debug(`HTTP ${method} ${url.origin}${url.pathname}`);
|
|
220
|
+
const init = {
|
|
221
|
+
method, headers, body, signal: options.signal,
|
|
222
|
+
redirect: 'manual',
|
|
223
|
+
dispatcher: this.getDispatcher(url),
|
|
224
|
+
};
|
|
225
|
+
let response;
|
|
226
|
+
try {
|
|
227
|
+
response = yield fetch(url, init);
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
if ((_b = options.signal) === null || _b === void 0 ? void 0 : _b.aborted)
|
|
231
|
+
throw error;
|
|
232
|
+
throw this.networkError(error, url);
|
|
233
|
+
}
|
|
234
|
+
const location = response.headers.get('location');
|
|
235
|
+
if ([301, 302, 303, 307, 308].includes(response.status) && location !== null) {
|
|
236
|
+
yield ((_c = response.body) === null || _c === void 0 ? void 0 : _c.cancel());
|
|
237
|
+
if (redirects >= 20)
|
|
238
|
+
throw new Error('Maximum number of redirects exceeded');
|
|
239
|
+
const target = this.parseUrl(location, url);
|
|
240
|
+
const switchesToGet = (response.status === 303 && method !== 'HEAD') ||
|
|
241
|
+
([301, 302].includes(response.status) && method === 'POST');
|
|
242
|
+
const preservesBody = !switchesToGet && body !== undefined;
|
|
243
|
+
if (target.origin !== url.origin) {
|
|
244
|
+
// Request bodies may carry credentials (e.g. the ACR access_token form).
|
|
245
|
+
if (preservesBody)
|
|
246
|
+
throw new Error('Refusing to resend a request body to another origin');
|
|
247
|
+
// GitLab package downloads may redirect to object storage on another host; never forward
|
|
248
|
+
// PRIVATE-TOKEN/JOB-TOKEN there (LJADIRD-66143). Covered by test/commands/download.redirect.test.ts.
|
|
249
|
+
for (const header of ['authorization', 'proxy-authorization', 'cookie', 'private-token', 'job-token']) {
|
|
250
|
+
headers.delete(header);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (switchesToGet) {
|
|
254
|
+
method = 'GET';
|
|
255
|
+
body = undefined;
|
|
256
|
+
headers.delete('content-type');
|
|
257
|
+
headers.delete('content-length');
|
|
258
|
+
}
|
|
259
|
+
url = target;
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
if (!response.ok) {
|
|
263
|
+
let data;
|
|
264
|
+
try {
|
|
265
|
+
data = yield this.readData(response, options.signal);
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
if ((_d = options.signal) === null || _d === void 0 ? void 0 : _d.aborted)
|
|
269
|
+
throw error;
|
|
270
|
+
// Keep the status even when the error body cannot be read.
|
|
271
|
+
}
|
|
272
|
+
throw new HttpError(response.status, data);
|
|
273
|
+
}
|
|
274
|
+
return response;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
package/lib/lib/npm.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { NpmPackage } from '../types/npm.types.js';
|
|
1
|
+
import HttpClient, { HttpResponse } from './http.js';
|
|
2
|
+
import { AzurePackageArray, NpmPackage } from '../types/npm.types.js';
|
|
3
3
|
export default class NpmContext {
|
|
4
|
+
private readonly http;
|
|
5
|
+
constructor(http?: HttpClient);
|
|
4
6
|
/**
|
|
5
7
|
* Get all workspaces
|
|
6
8
|
* @returns {Promise<string[]>} String array of all workspaces
|
|
@@ -8,12 +10,13 @@ export default class NpmContext {
|
|
|
8
10
|
getWorkspaces(): Promise<string[]>;
|
|
9
11
|
/**
|
|
10
12
|
* Get package names
|
|
13
|
+
* @param requireVersion Skip packages without a version, e.g. private workspace roots
|
|
11
14
|
*/
|
|
12
|
-
packageList(context: any, packages?: string[], excludes?: string[]): Promise<NpmPackage[]>;
|
|
15
|
+
packageList(context: any, packages?: string[], excludes?: string[], requireVersion?: boolean): Promise<NpmPackage[]>;
|
|
13
16
|
/**
|
|
14
17
|
* Get package all packages
|
|
15
18
|
* @param patToken Auth token
|
|
16
19
|
* @returns {Promise<string>} Returns all the NPM packages
|
|
17
20
|
*/
|
|
18
|
-
getAllNpmPackages(patToken?: string): Promise<
|
|
21
|
+
getAllNpmPackages(patToken?: string): Promise<HttpResponse<AzurePackageArray>>;
|
|
19
22
|
}
|
package/lib/lib/npm.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { __awaiter } from "tslib";
|
|
2
|
-
import axios from 'axios';
|
|
3
2
|
import chalk from 'chalk';
|
|
4
3
|
import fs from 'fs-extra';
|
|
5
4
|
import { globby } from 'globby';
|
|
6
5
|
import { minimatch } from 'minimatch';
|
|
7
|
-
import path from 'path';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import HttpClient from './http.js';
|
|
8
8
|
export default class NpmContext {
|
|
9
|
+
constructor(http = new HttpClient()) {
|
|
10
|
+
this.http = http;
|
|
11
|
+
}
|
|
9
12
|
/**
|
|
10
13
|
* Get all workspaces
|
|
11
14
|
* @returns {Promise<string[]>} String array of all workspaces
|
|
@@ -31,10 +34,11 @@ export default class NpmContext {
|
|
|
31
34
|
}
|
|
32
35
|
/**
|
|
33
36
|
* Get package names
|
|
37
|
+
* @param requireVersion Skip packages without a version, e.g. private workspace roots
|
|
34
38
|
*/
|
|
35
39
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
40
|
packageList(context_1) {
|
|
37
|
-
return __awaiter(this, arguments, void 0, function* (context, packages = ['**/*'], excludes = ['']) {
|
|
41
|
+
return __awaiter(this, arguments, void 0, function* (context, packages = ['**/*'], excludes = [''], requireVersion = true) {
|
|
38
42
|
try {
|
|
39
43
|
const workspaces = yield this.getWorkspaces();
|
|
40
44
|
let searchPattern = ['package.json', '**/package.json', '.**/package.json', '!**/node_modules'];
|
|
@@ -46,7 +50,7 @@ export default class NpmContext {
|
|
|
46
50
|
for (const pkgPath of pkgPaths) {
|
|
47
51
|
try {
|
|
48
52
|
const data = yield fs.readJSON(pkgPath);
|
|
49
|
-
if (!data.version || !data.name || excludes.includes(data.name) || !packages.some(pkg => minimatch(data.name, pkg))) {
|
|
53
|
+
if ((requireVersion && !data.version) || !data.name || excludes.includes(data.name) || !packages.some(pkg => minimatch(data.name, pkg))) {
|
|
50
54
|
continue;
|
|
51
55
|
}
|
|
52
56
|
// create object to simply remove duplicates
|
|
@@ -76,16 +80,21 @@ export default class NpmContext {
|
|
|
76
80
|
* @param patToken Auth token
|
|
77
81
|
* @returns {Promise<string>} Returns all the NPM packages
|
|
78
82
|
*/
|
|
79
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
80
83
|
getAllNpmPackages() {
|
|
81
84
|
return __awaiter(this, arguments, void 0, function* (patToken = '') {
|
|
85
|
+
var _a;
|
|
82
86
|
const uri = `https://feeds.dev.azure.com/adacta-fintech/adinsure/_apis/packaging/Feeds/feed/packages?api-version=6.0-preview.1&includeAllVersions=true&protocolType=Npm`;
|
|
83
|
-
|
|
87
|
+
const response = yield this.http.getJson(uri, {
|
|
84
88
|
headers: {
|
|
85
89
|
Authorization: 'Basic ' + Buffer.from(`:${patToken}`).toString('base64'),
|
|
86
90
|
'Content-Type': 'application/octet-strem',
|
|
87
91
|
},
|
|
88
92
|
});
|
|
93
|
+
// A missing or invalid PAT is redirected to an HTML sign-in page that returns 200.
|
|
94
|
+
if (!Array.isArray((_a = response.data) === null || _a === void 0 ? void 0 : _a.value)) {
|
|
95
|
+
throw new Error('Azure Artifacts did not return package metadata. Check that --pat is a valid Azure DevOps token with Packaging (Read) access.');
|
|
96
|
+
}
|
|
97
|
+
return response;
|
|
89
98
|
});
|
|
90
99
|
}
|
|
91
100
|
}
|
package/lib/lib/npmrc.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { __awaiter } from "tslib";
|
|
2
|
-
import { execSync } from 'child_process';
|
|
3
|
-
import fs from 'fs';
|
|
2
|
+
import { execSync } from 'node:child_process';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
4
|
import ini from 'ini';
|
|
5
|
-
import os from 'os';
|
|
5
|
+
import os from 'node:os';
|
|
6
6
|
export default class NpmRc {
|
|
7
7
|
constructor(createIfNotExists = true) {
|
|
8
8
|
this.config = {};
|
package/lib/lib/yarnrc.js
CHANGED