@foss.global/codefeed 5.1.0 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +45 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.giteasourceinventory.d.ts +35 -9
- package/dist_ts/classes.giteasourceinventory.js +284 -26
- package/dist_ts/classes.giteasourcetransfer.d.ts +151 -6
- package/dist_ts/classes.giteasourcetransfer.js +411 -9
- package/dist_ts/forgeinventory.client.d.ts +43 -5
- package/dist_ts/forgeinventory.client.js +57 -13
- package/dist_ts/forgeinventory.transport.d.ts +21 -7
- package/dist_ts/forgeinventory.transport.js +15 -10
- package/dist_ts/giteasourceinventory.packages.d.ts +46 -0
- package/dist_ts/giteasourceinventory.packages.js +139 -0
- package/dist_ts/giteasourcetransfer.documents.d.ts +35 -0
- package/dist_ts/giteasourcetransfer.documents.js +86 -0
- package/dist_ts/index.d.ts +3 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts/plugins.d.ts +2 -2
- package/dist_ts/plugins.js +3 -1
- package/package.json +3 -3
- package/readme.md +37 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.giteasourceinventory.ts +293 -24
- package/ts/classes.giteasourcetransfer.ts +532 -8
- package/ts/forgeinventory.client.ts +106 -13
- package/ts/forgeinventory.transport.ts +33 -13
- package/ts/giteasourceinventory.packages.ts +160 -0
- package/ts/giteasourcetransfer.documents.ts +97 -0
- package/ts/index.ts +3 -0
- package/ts/plugins.ts +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as transport from './forgeinventory.transport.js';
|
|
2
2
|
export interface IForgeRequestMetrics {
|
|
3
3
|
requests: number;
|
|
4
4
|
responseBytes: number;
|
|
@@ -26,15 +26,53 @@ export interface IForgeJsonResponse {
|
|
|
26
26
|
body: unknown;
|
|
27
27
|
headers: transport.IForgeTransportResponse['headers'];
|
|
28
28
|
}
|
|
29
|
+
export interface IForgeBytesRequestOptions {
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
/** Optional lower response-body budget for this request. */
|
|
32
|
+
maxResponseBytes?: number;
|
|
33
|
+
/** Additional request headers. */
|
|
34
|
+
headers?: Record<string, string>;
|
|
35
|
+
/** Sent as `accept`; the response may carry any content type, which the caller checks. */
|
|
36
|
+
accept: string;
|
|
37
|
+
}
|
|
38
|
+
export interface IForgeBytesResponse {
|
|
39
|
+
/** The response body exactly as it arrived. */
|
|
40
|
+
bytes: Buffer;
|
|
41
|
+
/** The response's media type without parameters, lowercased; null when it sent none. */
|
|
42
|
+
mediaType: string | null;
|
|
43
|
+
headers: transport.IForgeTransportResponse['headers'];
|
|
44
|
+
}
|
|
45
|
+
/** A redirect a read returned instead of refusing: never followed, its body discarded. */
|
|
46
|
+
export interface IForgeRedirectResponse {
|
|
47
|
+
/** One of 301, 302, 303, 307 and 308. */
|
|
48
|
+
status: number;
|
|
49
|
+
/** The `Location` header verbatim; null when the response sent none. */
|
|
50
|
+
location: string | null;
|
|
51
|
+
}
|
|
52
|
+
/** The answer of `requestBytesOrRedirect`: the body of a 200, or the redirect. */
|
|
53
|
+
export type TForgeBytesOrRedirect = ({
|
|
54
|
+
kind: 'bytes';
|
|
55
|
+
} & IForgeBytesResponse) | ({
|
|
56
|
+
kind: 'redirect';
|
|
57
|
+
} & IForgeRedirectResponse);
|
|
29
58
|
/**
|
|
30
|
-
* One bounded, credential-scoped
|
|
31
|
-
*
|
|
32
|
-
* content type. Failures surface as
|
|
33
|
-
*
|
|
59
|
+
* One bounded, credential-scoped read at a time, a GET or a POST with a JSON
|
|
60
|
+
* body: a per-request deadline, a response-size budget and, for JSON, a
|
|
61
|
+
* strict content type. Failures surface as `ForgeInventoryError` codes that
|
|
62
|
+
* never contain bodies, URLs or credentials.
|
|
34
63
|
*/
|
|
35
64
|
export declare class ForgeRequestClient {
|
|
36
65
|
#private;
|
|
37
66
|
constructor(optionsArg: IForgeRequestClientOptions);
|
|
38
67
|
get metrics(): IForgeRequestMetrics;
|
|
39
68
|
request(url: URL, requestArg?: IForgeRequestOptions): Promise<IForgeJsonResponse>;
|
|
69
|
+
/** A GET whose body is returned as the bytes that arrived, with the media type the response declared. */
|
|
70
|
+
requestBytes(url: URL, requestArg: IForgeBytesRequestOptions): Promise<IForgeBytesResponse>;
|
|
71
|
+
/**
|
|
72
|
+
* A GET like `requestBytes`, except that a redirect status resolves as
|
|
73
|
+
* `{ kind: 'redirect', status, location }` instead of rejecting. The
|
|
74
|
+
* redirect is never followed and its body is discarded unread; any status
|
|
75
|
+
* other than 200 and a redirect still rejects with `http-<status>`.
|
|
76
|
+
*/
|
|
77
|
+
requestBytesOrRedirect(url: URL, requestArg: IForgeBytesRequestOptions): Promise<TForgeBytesOrRedirect>;
|
|
40
78
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import * as transport from './forgeinventory.transport.js';
|
|
1
2
|
import * as validation from './forgeinventory.validation.js';
|
|
2
3
|
/**
|
|
3
|
-
* One bounded, credential-scoped
|
|
4
|
-
*
|
|
5
|
-
* content type. Failures surface as
|
|
6
|
-
*
|
|
4
|
+
* One bounded, credential-scoped read at a time, a GET or a POST with a JSON
|
|
5
|
+
* body: a per-request deadline, a response-size budget and, for JSON, a
|
|
6
|
+
* strict content type. Failures surface as `ForgeInventoryError` codes that
|
|
7
|
+
* never contain bodies, URLs or credentials.
|
|
7
8
|
*/
|
|
8
9
|
export class ForgeRequestClient {
|
|
9
10
|
#options;
|
|
@@ -13,6 +14,44 @@ export class ForgeRequestClient {
|
|
|
13
14
|
}
|
|
14
15
|
get metrics() { return { ...this.#metrics }; }
|
|
15
16
|
async request(url, requestArg = {}) {
|
|
17
|
+
const mediaType = requestArg.mediaType ?? 'application/json';
|
|
18
|
+
const response = await this.#body(url, {
|
|
19
|
+
signal: requestArg.signal, maxResponseBytes: requestArg.maxResponseBytes, headers: requestArg.headers, accept: mediaType, requiredMediaType: mediaType,
|
|
20
|
+
...(requestArg.json === undefined ? {} : { body: { mediaType, bytes: new TextEncoder().encode(JSON.stringify(requestArg.json)) } }),
|
|
21
|
+
});
|
|
22
|
+
try {
|
|
23
|
+
return { body: JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(response.bytes)), headers: response.headers };
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
throw new validation.ForgeInventoryError('request-or-json-failed');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** A GET whose body is returned as the bytes that arrived, with the media type the response declared. */
|
|
30
|
+
async requestBytes(url, requestArg) {
|
|
31
|
+
const response = await this.#body(url, requestArg);
|
|
32
|
+
return { bytes: response.bytes, mediaType: mediaTypeOf(response.headers), headers: response.headers };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A GET like `requestBytes`, except that a redirect status resolves as
|
|
36
|
+
* `{ kind: 'redirect', status, location }` instead of rejecting. The
|
|
37
|
+
* redirect is never followed and its body is discarded unread; any status
|
|
38
|
+
* other than 200 and a redirect still rejects with `http-<status>`.
|
|
39
|
+
*/
|
|
40
|
+
async requestBytesOrRedirect(url, requestArg) {
|
|
41
|
+
const response = await this.#read(url, { ...requestArg, redirect: 'return' });
|
|
42
|
+
return response.kind === 'redirect'
|
|
43
|
+
? response
|
|
44
|
+
: { kind: 'bytes', bytes: response.bytes, mediaType: mediaTypeOf(response.headers), headers: response.headers };
|
|
45
|
+
}
|
|
46
|
+
/** A read that refuses redirects, so it always answers a body. */
|
|
47
|
+
async #body(url, requestArg) {
|
|
48
|
+
const response = await this.#read(url, requestArg);
|
|
49
|
+
// The transport refuses every redirect status in this mode, so a redirect never arrives here.
|
|
50
|
+
if (response.kind === 'redirect')
|
|
51
|
+
throw new validation.ForgeInventoryError('request-or-json-failed');
|
|
52
|
+
return response;
|
|
53
|
+
}
|
|
54
|
+
async #read(url, requestArg) {
|
|
16
55
|
const { signal } = requestArg;
|
|
17
56
|
const maxBytes = requestArg.maxResponseBytes ?? this.#options.maxResponseBytes;
|
|
18
57
|
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1)
|
|
@@ -27,17 +66,22 @@ export class ForgeRequestClient {
|
|
|
27
66
|
let bodyChunks;
|
|
28
67
|
try {
|
|
29
68
|
this.#metrics.requests++;
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const response = await this.#options.transport(url, headers, controller.signal,
|
|
69
|
+
const headers = {
|
|
70
|
+
accept: requestArg.accept, ...(requestArg.body ? { 'content-type': requestArg.body.mediaType } : {}), ...requestArg.headers, ...this.#options.headers,
|
|
71
|
+
};
|
|
72
|
+
const response = await this.#options.transport(url, headers, controller.signal, requestArg.body?.bytes, { redirect: requestArg.redirect ?? 'refuse' });
|
|
34
73
|
bodyChunks = response.body?.[Symbol.asyncIterator]();
|
|
35
74
|
if (response.status === 429)
|
|
36
75
|
this.#metrics.rateLimitedRequests++;
|
|
76
|
+
if (requestArg.redirect === 'return' && transport.redirectStatuses.has(response.status)) {
|
|
77
|
+
// The body is discarded unread by the `finally` below.
|
|
78
|
+
return { kind: 'redirect', status: response.status, location: response.headers.get('location') };
|
|
79
|
+
}
|
|
37
80
|
if (response.status !== 200)
|
|
38
81
|
throw new validation.ForgeInventoryError(`http-${response.status}`);
|
|
39
|
-
if (
|
|
82
|
+
if ((requestArg.requiredMediaType !== undefined && mediaTypeOf(response.headers) !== requestArg.requiredMediaType) || !bodyChunks) {
|
|
40
83
|
throw new validation.ForgeInventoryError('invalid-content-type');
|
|
84
|
+
}
|
|
41
85
|
const chunks = [];
|
|
42
86
|
let bytes = 0;
|
|
43
87
|
while (true) {
|
|
@@ -52,11 +96,9 @@ export class ForgeRequestClient {
|
|
|
52
96
|
throw new validation.ForgeInventoryError('request-aborted-or-timed-out');
|
|
53
97
|
chunks.push(result.value);
|
|
54
98
|
}
|
|
55
|
-
const text = new TextDecoder('utf-8', { fatal: true }).decode(Buffer.concat(chunks));
|
|
56
|
-
const body = JSON.parse(text);
|
|
57
99
|
if (controller.signal.aborted || Date.now() >= deadline)
|
|
58
100
|
throw new validation.ForgeInventoryError('request-aborted-or-timed-out');
|
|
59
|
-
return {
|
|
101
|
+
return { kind: 'bytes', bytes: Buffer.concat(chunks), headers: response.headers };
|
|
60
102
|
}
|
|
61
103
|
catch (error) {
|
|
62
104
|
if (error instanceof validation.ForgeInventoryError)
|
|
@@ -75,4 +117,6 @@ export class ForgeRequestClient {
|
|
|
75
117
|
}
|
|
76
118
|
}
|
|
77
119
|
}
|
|
78
|
-
|
|
120
|
+
/** A response's media type without parameters, lowercased; null when it sent none. */
|
|
121
|
+
const mediaTypeOf = (headersArg) => headersArg.get('content-type')?.split(';')[0].trim().toLowerCase() || null;
|
|
122
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZ2VpbnZlbnRvcnkuY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvZm9yZ2VpbnZlbnRvcnkuY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxTQUFTLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxLQUFLLFVBQVUsTUFBTSxnQ0FBZ0MsQ0FBQztBQThFN0Q7Ozs7O0dBS0c7QUFDSCxNQUFNLE9BQU8sa0JBQWtCO0lBQ3BCLFFBQVEsQ0FBNkI7SUFDckMsUUFBUSxHQUF5QixFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUUsYUFBYSxFQUFFLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUVwRyxZQUFZLFVBQXNDO1FBQ2hELElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxHQUFHLFVBQVUsRUFBRSxPQUFPLEVBQUUsRUFBRSxHQUFHLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO0lBQ3hFLENBQUM7SUFFRCxJQUFXLE9BQU8sS0FBMkIsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUVwRSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQVEsRUFBRSxVQUFVLEdBQXlCLEVBQUU7UUFDbEUsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLFNBQVMsSUFBSSxrQkFBa0IsQ0FBQztRQUM3RCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFO1lBQ3JDLE1BQU0sRUFBRSxVQUFVLENBQUMsTUFBTSxFQUFFLGdCQUFnQixFQUFFLFVBQVUsQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLGlCQUFpQixFQUFFLFNBQVM7WUFDdEosR0FBRyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxF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
|
|
@@ -6,13 +6,24 @@ export interface IForgeTransportResponse {
|
|
|
6
6
|
/** Iterated at most once; returning the iterator before the end cancels the body and discards the connection. */
|
|
7
7
|
body: AsyncIterable<Uint8Array> | null;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* What a transport does with a redirect status: `refuse` rejects it, `return`
|
|
11
|
+
* resolves it as the response it is, `Location` included. Neither follows it.
|
|
12
|
+
*/
|
|
13
|
+
export type TForgeRedirectMode = 'refuse' | 'return';
|
|
14
|
+
export interface IForgeTransportOptions {
|
|
15
|
+
/** Defaults to `refuse`. */
|
|
16
|
+
redirect?: TForgeRedirectMode;
|
|
17
|
+
}
|
|
9
18
|
/**
|
|
10
19
|
* Sends one credential-scoped GET, or a POST of `body` when one is given, and
|
|
11
|
-
* resolves once response headers arrive. A redirect status
|
|
12
|
-
*
|
|
13
|
-
* body is still being read.
|
|
20
|
+
* resolves once response headers arrive. A redirect status is never followed:
|
|
21
|
+
* it rejects, unless `options.redirect` is `return`. Aborting `signal`
|
|
22
|
+
* discards the connection, also while the body is still being read.
|
|
14
23
|
*/
|
|
15
|
-
export type TForgeTransport = (url: URL, headers: Record<string, string>, signal: AbortSignal, body?: Uint8Array<ArrayBuffer
|
|
24
|
+
export type TForgeTransport = (url: URL, headers: Record<string, string>, signal: AbortSignal, body?: Uint8Array<ArrayBuffer>, options?: IForgeTransportOptions) => Promise<IForgeTransportResponse>;
|
|
25
|
+
/** The fetch statuses whose redirect mode `error` turns them into a network error. */
|
|
26
|
+
export declare const redirectStatuses: ReadonlySet<number>;
|
|
16
27
|
/** Node's global `fetch` with the process-wide default trust store. */
|
|
17
28
|
export declare const globalFetchTransport: TForgeTransport;
|
|
18
29
|
/** The agents a node request may use; a URL whose protocol has no agent is refused. */
|
|
@@ -27,6 +38,8 @@ export interface INodeRequest {
|
|
|
27
38
|
body?: Uint8Array | AsyncIterable<Uint8Array>;
|
|
28
39
|
signal: AbortSignal;
|
|
29
40
|
agents: INodeRequestAgents;
|
|
41
|
+
/** Defaults to `refuse`. */
|
|
42
|
+
redirect?: TForgeRedirectMode;
|
|
30
43
|
}
|
|
31
44
|
export interface INodeResponse extends IForgeTransportResponse {
|
|
32
45
|
/**
|
|
@@ -42,9 +55,10 @@ export interface INodeResponse extends IForgeTransportResponse {
|
|
|
42
55
|
export declare const createNodeAgents: (caCertificatesArg?: string[], allowHttpArg?: boolean) => INodeRequestAgents;
|
|
43
56
|
/**
|
|
44
57
|
* Sends one request through `node:http` or `node:https` and resolves once
|
|
45
|
-
* response headers arrive. A redirect status
|
|
46
|
-
*
|
|
47
|
-
* sent or read. A streamed body that fails
|
|
58
|
+
* response headers arrive. A redirect status is never followed: it rejects,
|
|
59
|
+
* unless `redirect` is `return`. Aborting `signal` discards the connection,
|
|
60
|
+
* also while a body is still being sent or read. A streamed body that fails
|
|
61
|
+
* destroys the request and rejects.
|
|
48
62
|
*/
|
|
49
63
|
export declare const sendNodeRequest: (url: URL, requestArg: INodeRequest) => Promise<INodeResponse>;
|
|
50
64
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
/** The fetch statuses whose redirect mode `error` turns them into a network error. */
|
|
3
|
-
const redirectStatuses = new Set([301, 302, 303, 307, 308]);
|
|
3
|
+
export const redirectStatuses = new Set([301, 302, 303, 307, 308]);
|
|
4
4
|
/**
|
|
5
5
|
* Idle keep-alive sockets close after this delay, or earlier when the server
|
|
6
6
|
* announces a shorter `Keep-Alive: timeout`, so a pooled socket is not reused
|
|
@@ -8,8 +8,10 @@ const redirectStatuses = new Set([301, 302, 303, 307, 308]);
|
|
|
8
8
|
*/
|
|
9
9
|
const idleSocketTimeoutMs = 4_000;
|
|
10
10
|
/** Node's global `fetch` with the process-wide default trust store. */
|
|
11
|
-
export const globalFetchTransport = async (url, headers, signal, body) => {
|
|
12
|
-
|
|
11
|
+
export const globalFetchTransport = async (url, headers, signal, body, options) => {
|
|
12
|
+
// Node's fetch answers `manual` with the redirect response itself, status and `Location` included.
|
|
13
|
+
const redirect = options?.redirect === 'return' ? 'manual' : 'error';
|
|
14
|
+
const response = await fetch(url, { method: body ? 'POST' : 'GET', headers, body, redirect, credentials: 'omit', signal });
|
|
13
15
|
return { status: response.status, headers: response.headers, body: response.body };
|
|
14
16
|
};
|
|
15
17
|
/**
|
|
@@ -29,9 +31,10 @@ const drained = (requestArg) => new Promise((resolve, reject) => {
|
|
|
29
31
|
});
|
|
30
32
|
/**
|
|
31
33
|
* Sends one request through `node:http` or `node:https` and resolves once
|
|
32
|
-
* response headers arrive. A redirect status
|
|
33
|
-
*
|
|
34
|
-
* sent or read. A streamed body that fails
|
|
34
|
+
* response headers arrive. A redirect status is never followed: it rejects,
|
|
35
|
+
* unless `redirect` is `return`. Aborting `signal` discards the connection,
|
|
36
|
+
* also while a body is still being sent or read. A streamed body that fails
|
|
37
|
+
* destroys the request and rejects.
|
|
35
38
|
*/
|
|
36
39
|
export const sendNodeRequest = (url, requestArg) => new Promise((resolve, reject) => {
|
|
37
40
|
const { signal } = requestArg;
|
|
@@ -86,7 +89,7 @@ export const sendNodeRequest = (url, requestArg) => new Promise((resolve, reject
|
|
|
86
89
|
request.on('response', (response) => {
|
|
87
90
|
try {
|
|
88
91
|
const status = response.statusCode ?? 0;
|
|
89
|
-
if (redirectStatuses.has(status))
|
|
92
|
+
if (redirectStatuses.has(status) && requestArg.redirect !== 'return')
|
|
90
93
|
throw new Error('Refused redirect.');
|
|
91
94
|
// Same combination rules as fetch: repeated fields join with ", ".
|
|
92
95
|
const responseHeaders = new Headers();
|
|
@@ -111,9 +114,11 @@ export const sendNodeRequest = (url, requestArg) => new Promise((resolve, reject
|
|
|
111
114
|
*/
|
|
112
115
|
export const createHttpsTransport = (caCertificates) => {
|
|
113
116
|
const agents = createNodeAgents(caCertificates);
|
|
114
|
-
return async (url, headers, signal, body) => {
|
|
115
|
-
const { sent: _sent, ...response } = await sendNodeRequest(url, {
|
|
117
|
+
return async (url, headers, signal, body, options) => {
|
|
118
|
+
const { sent: _sent, ...response } = await sendNodeRequest(url, {
|
|
119
|
+
method: body ? 'POST' : 'GET', headers, body, signal, agents, redirect: options?.redirect,
|
|
120
|
+
});
|
|
116
121
|
return response;
|
|
117
122
|
};
|
|
118
123
|
};
|
|
119
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
124
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZ2VpbnZlbnRvcnkudHJhbnNwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvZm9yZ2VpbnZlbnRvcnkudHJhbnNwb3J0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBK0J4QyxzRkFBc0Y7QUFDdEYsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQXdCLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFFeEY7Ozs7R0FJRztBQUNILE1BQU0sbUJBQW1CLEdBQUcsS0FBSyxDQUFDO0FBRWxDLHVFQUF1RTtBQUN2RSxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBb0IsS0FBSyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUNqRyxtR0FBbUc7SUFDbkcsTUFBTSxRQUFRLEdBQUcsT0FBTyxFQUFFLFFBQVEsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0lBQ3JFLE1BQU0sUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUMzSCxPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNyRixDQUFDLENBQUM7QUEyQkY7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1B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
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
type IPackageRef = plugins.fossInterfaces.data.IForgeSourcePackageRef;
|
|
3
|
+
type IPackageRecord = plugins.fossInterfaces.data.IForgeSourcePackageInventory;
|
|
4
|
+
type IPackageContentTotals = plugins.fossInterfaces.data.IForgeSourcePackageContentTotals;
|
|
5
|
+
/** Media types Gitea serves an index or a manifest list as; an index candidate must be one of them. */
|
|
6
|
+
export declare const containerIndexMediaTypes: readonly string[];
|
|
7
|
+
/** Every manifest media type Gitea serves: images, indexes and manifest lists, OCI and Docker. */
|
|
8
|
+
export declare const containerManifestMediaTypes: readonly string[];
|
|
9
|
+
/** A package type as Gitea names it; it names reason paths, so it must be one of Gitea's plain identifiers. */
|
|
10
|
+
export declare const packageTypePattern: RegExp;
|
|
11
|
+
/** The key of a package within one instance: owner, type and name, which Gitea keeps unique (the name without case). */
|
|
12
|
+
export declare const packageKey: (refArg: IPackageRef) => string;
|
|
13
|
+
/** Orders packages by owner, type and name in code-unit order. */
|
|
14
|
+
export declare const comparePackages: (aArg: IPackageRef, bArg: IPackageRef) => number;
|
|
15
|
+
/** The path segment(s) of an npm package in Gitea's npm registry: the name unencoded, as Gitea's npm routes match it. */
|
|
16
|
+
export declare const npmPackagePath: (nameArg: string) => string;
|
|
17
|
+
/** The path of a crate's entry in the Cargo sparse index, lowercased, per the Cargo registry index layout. */
|
|
18
|
+
export declare const cargoIndexPath: (nameArg: string) => string;
|
|
19
|
+
/** The scope and name of a Swift package stored as `scope.name`. */
|
|
20
|
+
export declare const swiftPackageParts: (nameArg: string) => {
|
|
21
|
+
scope: string;
|
|
22
|
+
name: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The digest of the manifest a container version holds: `sha256:` and the
|
|
26
|
+
* SHA-256 of the blob holding the version's `manifest.json`; null for a
|
|
27
|
+
* version without one.
|
|
28
|
+
*/
|
|
29
|
+
export declare const containerManifestDigest: (packageArg: IPackageRecord, versionIdArg: string) => string | null;
|
|
30
|
+
/**
|
|
31
|
+
* The version ids of a package's tagged-and-referenced selection: for a
|
|
32
|
+
* container package the tagged versions and the versions holding a manifest
|
|
33
|
+
* a tagged index references; every version of any other type.
|
|
34
|
+
*/
|
|
35
|
+
export declare const taggedAndReferencedVersionIds: (packageArg: IPackageRecord) => Set<string>;
|
|
36
|
+
/**
|
|
37
|
+
* The distinct content of an inventory's packages, `totals.packageContent`:
|
|
38
|
+
* a pure function of the discovered packages and the records their units
|
|
39
|
+
* returned. Every SHA-256 counts once per scope, globally and per owner, each
|
|
40
|
+
* by type, over all versions and over the tagged versions with the manifests
|
|
41
|
+
* their indexes reference. A measure is complete only when every discovered
|
|
42
|
+
* package of its scope has a record; otherwise it is partial with the sum of
|
|
43
|
+
* the records read. Records of packages discovery does not list are ignored.
|
|
44
|
+
*/
|
|
45
|
+
export declare const composeGiteaPackageContent: (discoveredArg: readonly IPackageRef[], packagesArg: readonly IPackageRecord[]) => IPackageContentTotals;
|
|
46
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import * as validation from './forgeinventory.validation.js';
|
|
3
|
+
/** Media types Gitea serves an index or a manifest list as; an index candidate must be one of them. */
|
|
4
|
+
export const containerIndexMediaTypes = Object.freeze([
|
|
5
|
+
'application/vnd.oci.image.index.v1+json',
|
|
6
|
+
'application/vnd.docker.distribution.manifest.list.v2+json',
|
|
7
|
+
]);
|
|
8
|
+
/** Every manifest media type Gitea serves: images, indexes and manifest lists, OCI and Docker. */
|
|
9
|
+
export const containerManifestMediaTypes = Object.freeze([
|
|
10
|
+
...containerIndexMediaTypes,
|
|
11
|
+
'application/vnd.oci.image.manifest.v1+json',
|
|
12
|
+
'application/vnd.docker.distribution.manifest.v2+json',
|
|
13
|
+
]);
|
|
14
|
+
/** A package type as Gitea names it; it names reason paths, so it must be one of Gitea's plain identifiers. */
|
|
15
|
+
export const packageTypePattern = /^[a-z][a-z0-9_-]{0,31}$/;
|
|
16
|
+
/** Gitea's npm name rule (`modules/packages/npm/creator.go`): `name` or `@scope/name`, URL-safe as it stands. */
|
|
17
|
+
const npmNamePattern = /^(?:@[a-z0-9-][a-z0-9-._]*\/)?[a-z0-9-][a-z0-9-._]*$/;
|
|
18
|
+
/** Gitea's Cargo crate name rule (`modules/packages/cargo/parser.go`). */
|
|
19
|
+
const cargoNamePattern = /^[A-Za-z][A-Za-z0-9-_]{0,63}$/;
|
|
20
|
+
/** Gitea's Swift scope and name rules (`routers/api/packages/swift/swift.go`); it stores the package as `scope.name`. */
|
|
21
|
+
const swiftPackagePattern = /^([A-Za-z0-9][A-Za-z0-9-]{0,38})\.([A-Za-z0-9][A-Za-z0-9-_]{0,99})$/;
|
|
22
|
+
const compareText = (aArg, bArg) => (aArg < bArg ? -1 : aArg > bArg ? 1 : 0);
|
|
23
|
+
/** The key of a package within one instance: owner, type and name, which Gitea keeps unique (the name without case). */
|
|
24
|
+
export const packageKey = (refArg) => `${refArg.owner}/${refArg.type}/${refArg.name}`;
|
|
25
|
+
/** Orders packages by owner, type and name in code-unit order. */
|
|
26
|
+
export const comparePackages = (aArg, bArg) => compareText(aArg.owner, bArg.owner) || compareText(aArg.type, bArg.type) || compareText(aArg.name, bArg.name);
|
|
27
|
+
/** The path segment(s) of an npm package in Gitea's npm registry: the name unencoded, as Gitea's npm routes match it. */
|
|
28
|
+
export const npmPackagePath = (nameArg) => {
|
|
29
|
+
if (!npmNamePattern.test(nameArg) || nameArg.length > 214)
|
|
30
|
+
throw new validation.ForgeInventoryError('invalid-npm-name');
|
|
31
|
+
return nameArg;
|
|
32
|
+
};
|
|
33
|
+
/** The path of a crate's entry in the Cargo sparse index, lowercased, per the Cargo registry index layout. */
|
|
34
|
+
export const cargoIndexPath = (nameArg) => {
|
|
35
|
+
if (!cargoNamePattern.test(nameArg))
|
|
36
|
+
throw new validation.ForgeInventoryError('invalid-cargo-name');
|
|
37
|
+
const name = nameArg.toLowerCase();
|
|
38
|
+
if (name.length === 1)
|
|
39
|
+
return `1/${name}`;
|
|
40
|
+
if (name.length === 2)
|
|
41
|
+
return `2/${name}`;
|
|
42
|
+
if (name.length === 3)
|
|
43
|
+
return `3/${name[0]}/${name}`;
|
|
44
|
+
return `${name.slice(0, 2)}/${name.slice(2, 4)}/${name}`;
|
|
45
|
+
};
|
|
46
|
+
/** The scope and name of a Swift package stored as `scope.name`. */
|
|
47
|
+
export const swiftPackageParts = (nameArg) => {
|
|
48
|
+
const match = swiftPackagePattern.exec(nameArg);
|
|
49
|
+
if (!match)
|
|
50
|
+
throw new validation.ForgeInventoryError('invalid-swift-name');
|
|
51
|
+
return { scope: match[1], name: match[2] };
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* The digest of the manifest a container version holds: `sha256:` and the
|
|
55
|
+
* SHA-256 of the blob holding the version's `manifest.json`; null for a
|
|
56
|
+
* version without one.
|
|
57
|
+
*/
|
|
58
|
+
export const containerManifestDigest = (packageArg, versionIdArg) => {
|
|
59
|
+
const blob = packageArg.blobs.find((blobArg) => blobArg.files.some((fileArg) => fileArg.versionId === versionIdArg && fileArg.name === 'manifest.json'));
|
|
60
|
+
return blob ? `sha256:${blob.sha256}` : null;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* The version ids of a package's tagged-and-referenced selection: for a
|
|
64
|
+
* container package the tagged versions and the versions holding a manifest
|
|
65
|
+
* a tagged index references; every version of any other type.
|
|
66
|
+
*/
|
|
67
|
+
export const taggedAndReferencedVersionIds = (packageArg) => {
|
|
68
|
+
if (packageArg.type !== 'container')
|
|
69
|
+
return new Set(packageArg.versions.map((versionArg) => versionArg.id));
|
|
70
|
+
const tagged = packageArg.versions.filter((versionArg) => !versionArg.version.startsWith('sha256:'));
|
|
71
|
+
const referenced = new Set(tagged.flatMap((versionArg) => versionArg.references ?? []));
|
|
72
|
+
const selected = new Set(tagged.map((versionArg) => versionArg.id));
|
|
73
|
+
for (const version of packageArg.versions) {
|
|
74
|
+
const digest = containerManifestDigest(packageArg, version.id);
|
|
75
|
+
if (digest !== null && referenced.has(digest))
|
|
76
|
+
selected.add(version.id);
|
|
77
|
+
}
|
|
78
|
+
return selected;
|
|
79
|
+
};
|
|
80
|
+
const contentMeasure = (sumArg, missingArg) => {
|
|
81
|
+
const blobs = BigInt(sumArg.blobs.size);
|
|
82
|
+
const bytes = [...sumArg.blobs.values()].reduce((totalArg, sizeArg) => totalArg + sizeArg, 0n);
|
|
83
|
+
if (missingArg === 0)
|
|
84
|
+
return { blobs: { status: 'complete', value: blobs.toString() }, bytes: { status: 'complete', value: bytes.toString() } };
|
|
85
|
+
const reason = `Package units not measured: ${missingArg}.`;
|
|
86
|
+
const partial = (valueArg) => ({ status: 'partial', observedValue: valueArg.toString(), reason });
|
|
87
|
+
return { blobs: partial(blobs), bytes: partial(bytes) };
|
|
88
|
+
};
|
|
89
|
+
/** Distinct content of a set of package records over both selections; `missingArg` packages of the set were not read. */
|
|
90
|
+
const selection = (packagesArg, missingArg) => {
|
|
91
|
+
const all = { blobs: new Map() };
|
|
92
|
+
const tagged = { blobs: new Map() };
|
|
93
|
+
for (const record of packagesArg) {
|
|
94
|
+
const selected = taggedAndReferencedVersionIds(record);
|
|
95
|
+
for (const blob of record.blobs) {
|
|
96
|
+
const size = BigInt(blob.size);
|
|
97
|
+
all.blobs.set(blob.sha256, size);
|
|
98
|
+
if (blob.files.some((fileArg) => selected.has(fileArg.versionId)))
|
|
99
|
+
tagged.blobs.set(blob.sha256, size);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { allVersions: contentMeasure(all, missingArg), taggedAndReferenced: contentMeasure(tagged, missingArg) };
|
|
103
|
+
};
|
|
104
|
+
/** A group of packages with its content by type; `refsArg` are the group's discovered packages. */
|
|
105
|
+
const group = (refsArg, recordsArg) => {
|
|
106
|
+
const read = (refs) => refs.flatMap((refArg) => {
|
|
107
|
+
const record = recordsArg.get(packageKey(refArg));
|
|
108
|
+
return record ? [record] : [];
|
|
109
|
+
});
|
|
110
|
+
const missing = (refs) => refs.filter((refArg) => !recordsArg.has(packageKey(refArg))).length;
|
|
111
|
+
const types = [...new Set(refsArg.map((refArg) => refArg.type))].sort(compareText);
|
|
112
|
+
return {
|
|
113
|
+
...selection(read(refsArg), missing(refsArg)),
|
|
114
|
+
types: types.map((typeArg) => {
|
|
115
|
+
const refs = refsArg.filter((refArg) => refArg.type === typeArg);
|
|
116
|
+
return { type: typeArg, ...selection(read(refs), missing(refs)) };
|
|
117
|
+
}),
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* The distinct content of an inventory's packages, `totals.packageContent`:
|
|
122
|
+
* a pure function of the discovered packages and the records their units
|
|
123
|
+
* returned. Every SHA-256 counts once per scope, globally and per owner, each
|
|
124
|
+
* by type, over all versions and over the tagged versions with the manifests
|
|
125
|
+
* their indexes reference. A measure is complete only when every discovered
|
|
126
|
+
* package of its scope has a record; otherwise it is partial with the sum of
|
|
127
|
+
* the records read. Records of packages discovery does not list are ignored.
|
|
128
|
+
*/
|
|
129
|
+
export const composeGiteaPackageContent = (discoveredArg, packagesArg) => {
|
|
130
|
+
const discovered = new Set(discoveredArg.map(packageKey));
|
|
131
|
+
const records = new Map(packagesArg.filter((recordArg) => discovered.has(packageKey(recordArg))).map((recordArg) => [packageKey(recordArg), recordArg]));
|
|
132
|
+
const refs = [...new Map(discoveredArg.map((refArg) => [packageKey(refArg), { owner: refArg.owner, type: refArg.type, name: refArg.name }])).values()];
|
|
133
|
+
const owners = [...new Set(refs.map((refArg) => refArg.owner))].sort(compareText);
|
|
134
|
+
return {
|
|
135
|
+
global: group(refs, records),
|
|
136
|
+
owners: owners.map((ownerArg) => ({ owner: ownerArg, ...group(refs.filter((refArg) => refArg.owner === ownerArg), records) })),
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2l0ZWFzb3VyY2VpbnZlbnRvcnkucGFja2FnZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9naXRlYXNvdXJjZWludmVudG9yeS5wYWNrYWdlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEtBQUssVUFBVSxNQUFNLGdDQUFnQyxDQUFDO0FBVTdELHVHQUF1RztBQUN2RyxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBc0IsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUN2RSx5Q0FBeUM7SUFDekMsMkRBQTJEO0NBQzVELENBQUMsQ0FBQztBQUVILGtHQUFrRztBQUNsRyxNQUFNLENBQUMsTUFBTSwyQkFBMkIsR0FBc0IsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUMxRSxHQUFHLHdCQUF3QjtJQUMzQiw0Q0FBNEM7SUFDNUMsc0RBQXNEO0NBQ3ZELENBQUMsQ0FBQztBQUVILCtHQUErRztBQUMvRyxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyx5QkFBeUIsQ0FBQztBQUU1RCxpSEFBaUg7QUFDakgsTUFBTSxjQUFjLEdBQUcsc0RBQXNELENBQUM7QUFDOUUsMEVBQTBFO0FBQzFFLE1BQU0sZ0JBQWdCLEdBQUcsK0JBQStCLENBQUM7QUFDekQseUhBQXlIO0FBQ3pILE1BQU0sbUJBQW1CLEdBQUcscUVBQXFFLENBQUM7QUFFbEcsTUFBTSxXQUFXLEdBQUcsQ0FBQyxJQUFZLEVBQUUsSUFBWSxFQUFVLEVBQUUsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBRXJHLHdIQUF3SDtBQUN4SCxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUcsQ0FBQyxNQUFtQixFQUFVLEVBQUUs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
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package metadata documents that are JSON, which `canonicalPackageDocument`
|
|
3
|
+
* brings into one form: an npm version document, Swift release metadata, a
|
|
4
|
+
* crate version's line of the Cargo sparse index, and `{"description":…}`
|
|
5
|
+
* of a crate's latest version as the Cargo search serves it.
|
|
6
|
+
*/
|
|
7
|
+
export type TGiteaCanonicalPackageDocumentKind = 'npm-version' | 'swift-release' | 'cargo-index-entry' | 'cargo-description';
|
|
8
|
+
export interface IGiteaCanonicalPackageDocument {
|
|
9
|
+
/** The canonical JSON, UTF-8. */
|
|
10
|
+
bytes: Buffer;
|
|
11
|
+
/** Lowercase hex SHA-256 of `bytes`. */
|
|
12
|
+
sha256: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The canonical form of a package metadata document and its SHA-256, which a
|
|
16
|
+
* consumer records and compares instead of the bytes Gitea served: Gitea 28
|
|
17
|
+
* writes JSON objects held in maps (a crate's `features`, npm's maps) in a
|
|
18
|
+
* different key order on every read, and documents carry state that changes
|
|
19
|
+
* without a new version. In this order: decode as UTF-8 (fatal), parse as a
|
|
20
|
+
* JSON object, remove the kind's top-level mutable-state member (`yanked`
|
|
21
|
+
* for `cargo-index-entry`, `deprecated` for `npm-version`), and write it
|
|
22
|
+
* compact, object keys sorted by code point at every depth, arrays in their
|
|
23
|
+
* order, strings and safe integers as `JSON.stringify` writes them. Anything
|
|
24
|
+
* else, a number that is not a safe integer included, rejects with
|
|
25
|
+
* `document-not-canonical`; an unknown kind with
|
|
26
|
+
* `package-document-kind-invalid`. The same document gives the same bytes
|
|
27
|
+
* whatever order its keys arrived in.
|
|
28
|
+
*/
|
|
29
|
+
export declare const canonicalPackageDocument: (kindArg: TGiteaCanonicalPackageDocumentKind, bytesArg: Uint8Array) => IGiteaCanonicalPackageDocument;
|
|
30
|
+
/**
|
|
31
|
+
* A Swift version as Gitea keys an alternate manifest (`Package@swift-<v>.swift`),
|
|
32
|
+
* trimmed by its `TrimmedVersionString`: major and minor, and the patch only
|
|
33
|
+
* when it is not zero.
|
|
34
|
+
*/
|
|
35
|
+
export declare const swiftManifestVersionPattern: RegExp;
|