@pnpm/network.auth-header 1101.1.0 → 1101.1.2
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/lib/getAuthHeadersFromConfig.d.ts +8 -2
- package/lib/getAuthHeadersFromConfig.js +41 -4
- package/lib/index.d.ts +6 -3
- package/lib/index.js +49 -9
- package/package.json +5 -5
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
import type
|
|
2
|
-
export
|
|
1
|
+
import { type RegistryConfig } from '@pnpm/types';
|
|
2
|
+
export interface AuthHeaders {
|
|
3
|
+
authHeaderValueByURI: Record<string, string>;
|
|
4
|
+
scopedAuthHeaderValueByURI: Record<string, Record<string, string>>;
|
|
5
|
+
}
|
|
6
|
+
export type AuthHeadersByScope = Record<string, Record<string, string>>;
|
|
7
|
+
export declare function getAuthHeadersFromCreds(configByUri: Record<string, RegistryConfig>): AuthHeaders;
|
|
8
|
+
export declare function getAuthHeadersByScope(authHeaders: AuthHeaders): AuthHeadersByScope;
|
|
@@ -1,14 +1,51 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
2
|
import { PnpmError } from '@pnpm/error';
|
|
3
|
+
import { DEFAULT_REGISTRY_SCOPE } from '@pnpm/types';
|
|
3
4
|
export function getAuthHeadersFromCreds(configByUri) {
|
|
4
|
-
const
|
|
5
|
+
const authHeaders = {
|
|
6
|
+
authHeaderValueByURI: {},
|
|
7
|
+
scopedAuthHeaderValueByURI: {},
|
|
8
|
+
};
|
|
5
9
|
for (const [uri, registryConfig] of Object.entries(configByUri)) {
|
|
6
|
-
const
|
|
10
|
+
const normalizedUri = normalizeAuthKey(uri);
|
|
11
|
+
const header = credsToHeader(registryConfig[DEFAULT_REGISTRY_SCOPE]);
|
|
7
12
|
if (header) {
|
|
8
|
-
authHeaderValueByURI[
|
|
13
|
+
authHeaders.authHeaderValueByURI[normalizedUri] = header;
|
|
9
14
|
}
|
|
15
|
+
for (const scope of getRegistryScopes(registryConfig)) {
|
|
16
|
+
if (scope === DEFAULT_REGISTRY_SCOPE)
|
|
17
|
+
continue;
|
|
18
|
+
const scopedCreds = registryConfig[scope];
|
|
19
|
+
const scopedHeader = credsToHeader(scopedCreds);
|
|
20
|
+
if (scopedHeader) {
|
|
21
|
+
authHeaders.scopedAuthHeaderValueByURI[normalizedUri] ??= {};
|
|
22
|
+
authHeaders.scopedAuthHeaderValueByURI[normalizedUri][scope] = scopedHeader;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return authHeaders;
|
|
27
|
+
}
|
|
28
|
+
export function getAuthHeadersByScope(authHeaders) {
|
|
29
|
+
const result = {};
|
|
30
|
+
for (const [registryURI, authHeader] of Object.entries(authHeaders.authHeaderValueByURI)) {
|
|
31
|
+
result[registryURI] ??= {};
|
|
32
|
+
result[registryURI][DEFAULT_REGISTRY_SCOPE] = authHeader;
|
|
10
33
|
}
|
|
11
|
-
|
|
34
|
+
for (const [registryURI, scopedAuthHeaders] of Object.entries(authHeaders.scopedAuthHeaderValueByURI)) {
|
|
35
|
+
result[registryURI] ??= {};
|
|
36
|
+
for (const [scope, authHeader] of Object.entries(scopedAuthHeaders)) {
|
|
37
|
+
result[registryURI][scope] = authHeader;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
function getRegistryScopes(registryConfig) {
|
|
43
|
+
return Object.keys(registryConfig).filter((scope) => scope.startsWith('@'));
|
|
44
|
+
}
|
|
45
|
+
function normalizeAuthKey(uri) {
|
|
46
|
+
if (!uri)
|
|
47
|
+
return uri;
|
|
48
|
+
return uri.endsWith('/') ? uri : `${uri}/`;
|
|
12
49
|
}
|
|
13
50
|
function credsToHeader(creds) {
|
|
14
51
|
if (!creds)
|
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { RegistryConfig } from '@pnpm/types';
|
|
2
|
-
import { getAuthHeadersFromCreds } from './getAuthHeadersFromConfig.js';
|
|
3
|
-
export { getAuthHeadersFromCreds };
|
|
4
|
-
|
|
2
|
+
import { type AuthHeaders, type AuthHeadersByScope, getAuthHeadersByScope, getAuthHeadersFromCreds } from './getAuthHeadersFromConfig.js';
|
|
3
|
+
export { type AuthHeaders, type AuthHeadersByScope, getAuthHeadersByScope, getAuthHeadersFromCreds };
|
|
4
|
+
interface GetAuthHeaderOptions {
|
|
5
|
+
pkgName?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function createGetAuthHeaderByURI(configByUri: Record<string, RegistryConfig>): (uri: string, opts?: GetAuthHeaderOptions) => string | undefined;
|
package/lib/index.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { nerfDart } from '@pnpm/config.nerf-dart';
|
|
2
|
-
import { getAuthHeadersFromCreds } from './getAuthHeadersFromConfig.js';
|
|
2
|
+
import { getAuthHeadersByScope, getAuthHeadersFromCreds } from './getAuthHeadersFromConfig.js';
|
|
3
3
|
import { removePort } from './helpers/removePort.js';
|
|
4
|
-
// Re-exported so callers
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
export { getAuthHeadersFromCreds };
|
|
4
|
+
// Re-exported so callers can build the same URL/scoped credential lookup
|
|
5
|
+
// without re-implementing `credsToHeader`.
|
|
6
|
+
export { getAuthHeadersByScope, getAuthHeadersFromCreds };
|
|
8
7
|
export function createGetAuthHeaderByURI(configByUri) {
|
|
9
8
|
const authHeaders = getAuthHeadersFromCreds(configByUri);
|
|
10
|
-
|
|
9
|
+
const registryURIs = Object.keys(authHeaders.authHeaderValueByURI);
|
|
10
|
+
const scopedAuthHeaderValueByScope = getScopedAuthHeaderValueByScope(authHeaders.scopedAuthHeaderValueByURI);
|
|
11
|
+
if (registryURIs.length === 0 && Object.keys(scopedAuthHeaderValueByScope).length === 0)
|
|
11
12
|
return (uri) => basicAuth(new URL(uri));
|
|
12
|
-
return getAuthHeaderByURI.bind(null, authHeaders,
|
|
13
|
+
return getAuthHeaderByURI.bind(null, authHeaders, {
|
|
14
|
+
maxParts: getMaxParts(registryURIs),
|
|
15
|
+
scopedAuthHeaderValueByScope,
|
|
16
|
+
});
|
|
13
17
|
}
|
|
14
18
|
function getMaxParts(uris) {
|
|
15
19
|
return uris.reduce((max, uri) => {
|
|
@@ -17,7 +21,24 @@ function getMaxParts(uris) {
|
|
|
17
21
|
return parts > max ? parts : max;
|
|
18
22
|
}, 0);
|
|
19
23
|
}
|
|
20
|
-
function
|
|
24
|
+
function getScopedAuthHeaderValueByScope(authHeaders) {
|
|
25
|
+
const result = {};
|
|
26
|
+
for (const [uri, scopedAuthHeaders] of Object.entries(authHeaders)) {
|
|
27
|
+
const parts = uri.split('/').length;
|
|
28
|
+
for (const [scope, authHeader] of Object.entries(scopedAuthHeaders)) {
|
|
29
|
+
const scopedAuthHeaderLookup = result[scope] ??= {
|
|
30
|
+
authHeaderValueByURI: {},
|
|
31
|
+
maxParts: 0,
|
|
32
|
+
};
|
|
33
|
+
scopedAuthHeaderLookup.authHeaderValueByURI[uri] = authHeader;
|
|
34
|
+
if (parts > scopedAuthHeaderLookup.maxParts) {
|
|
35
|
+
scopedAuthHeaderLookup.maxParts = parts;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
function getAuthHeaderByURI(authHeaders, lookup, uri, opts) {
|
|
21
42
|
if (!uri.endsWith('/')) {
|
|
22
43
|
uri += '/';
|
|
23
44
|
}
|
|
@@ -25,6 +46,17 @@ function getAuthHeaderByURI(authHeaders, maxParts, uri) {
|
|
|
25
46
|
const basic = basicAuth(parsedUri);
|
|
26
47
|
if (basic)
|
|
27
48
|
return basic;
|
|
49
|
+
const scope = getScope(opts?.pkgName);
|
|
50
|
+
const scopedAuthHeaderLookup = scope ? lookup.scopedAuthHeaderValueByScope[scope] : undefined;
|
|
51
|
+
if (scopedAuthHeaderLookup) {
|
|
52
|
+
const scopedAuth = getAuthHeaderByNerfedURI(scopedAuthHeaderLookup.authHeaderValueByURI, scopedAuthHeaderLookup.maxParts, uri);
|
|
53
|
+
if (scopedAuth)
|
|
54
|
+
return scopedAuth;
|
|
55
|
+
}
|
|
56
|
+
return getAuthHeaderByNerfedURI(authHeaders.authHeaderValueByURI, lookup.maxParts, uri);
|
|
57
|
+
}
|
|
58
|
+
function getAuthHeaderByNerfedURI(authHeaders, maxParts, uri) {
|
|
59
|
+
const parsedUri = new URL(uri);
|
|
28
60
|
const nerfed = nerfDart(uri);
|
|
29
61
|
const parts = nerfed.split('/');
|
|
30
62
|
for (let i = Math.min(parts.length, maxParts) - 1; i >= 3; i--) {
|
|
@@ -34,10 +66,18 @@ function getAuthHeaderByURI(authHeaders, maxParts, uri) {
|
|
|
34
66
|
}
|
|
35
67
|
const urlWithoutPort = removePort(parsedUri);
|
|
36
68
|
if (urlWithoutPort !== uri) {
|
|
37
|
-
return
|
|
69
|
+
return getAuthHeaderByNerfedURI(authHeaders, maxParts, urlWithoutPort);
|
|
38
70
|
}
|
|
39
71
|
return undefined;
|
|
40
72
|
}
|
|
73
|
+
function getScope(pkgName) {
|
|
74
|
+
if (!pkgName?.startsWith('@'))
|
|
75
|
+
return undefined;
|
|
76
|
+
const index = pkgName.indexOf('/');
|
|
77
|
+
if (index <= 1)
|
|
78
|
+
return undefined;
|
|
79
|
+
return pkgName.slice(0, index);
|
|
80
|
+
}
|
|
41
81
|
function basicAuth(uri) {
|
|
42
82
|
if (!uri.username && !uri.password)
|
|
43
83
|
return undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/network.auth-header",
|
|
3
|
-
"version": "1101.1.
|
|
3
|
+
"version": "1101.1.2",
|
|
4
4
|
"description": "Gets the authorization header for the given URI",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
"!*.map"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@pnpm/config.nerf-dart": "^
|
|
31
|
+
"@pnpm/config.nerf-dart": "^2.0.1",
|
|
32
32
|
"@pnpm/error": "1100.0.0",
|
|
33
|
-
"@pnpm/types": "1101.3.
|
|
33
|
+
"@pnpm/types": "1101.3.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@jest/globals": "30.
|
|
36
|
+
"@jest/globals": "30.4.1",
|
|
37
37
|
"safe-buffer": "5.2.1",
|
|
38
|
-
"@pnpm/network.auth-header": "1101.1.
|
|
38
|
+
"@pnpm/network.auth-header": "1101.1.2"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=22.13"
|