@foss.global/codefeed 2.1.0 → 3.1.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.
@@ -1,7 +1,8 @@
1
1
  import * as validation from './forgeinventory.validation.js';
2
2
  /**
3
- * One bounded, credential-scoped JSON GET at a time: a per-request deadline, a
4
- * response-size budget and a strict JSON content type. Failures surface as
3
+ * One bounded, credential-scoped JSON read at a time, a GET or a POST with a
4
+ * JSON body: a per-request deadline, a response-size budget and a strict JSON
5
+ * content type. Failures surface as
5
6
  * `ForgeInventoryError` codes that never contain bodies, URLs or credentials.
6
7
  */
7
8
  export class ForgeRequestClient {
@@ -26,14 +27,16 @@ export class ForgeRequestClient {
26
27
  let bodyChunks;
27
28
  try {
28
29
  this.#metrics.requests++;
29
- const headers = { accept: 'application/json', ...requestArg.headers, ...this.#options.headers };
30
- const response = await this.#options.transport(url, headers, controller.signal);
30
+ const mediaType = requestArg.mediaType ?? 'application/json';
31
+ const requestBody = requestArg.json === undefined ? undefined : new TextEncoder().encode(JSON.stringify(requestArg.json));
32
+ const headers = { accept: mediaType, ...(requestBody ? { 'content-type': mediaType } : {}), ...requestArg.headers, ...this.#options.headers };
33
+ const response = await this.#options.transport(url, headers, controller.signal, requestBody);
31
34
  bodyChunks = response.body?.[Symbol.asyncIterator]();
32
35
  if (response.status === 429)
33
36
  this.#metrics.rateLimitedRequests++;
34
37
  if (response.status !== 200)
35
38
  throw new validation.ForgeInventoryError(`http-${response.status}`);
36
- if (response.headers.get('content-type')?.split(';')[0].trim().toLowerCase() !== 'application/json' || !bodyChunks)
39
+ if (response.headers.get('content-type')?.split(';')[0].trim().toLowerCase() !== mediaType || !bodyChunks)
37
40
  throw new validation.ForgeInventoryError('invalid-content-type');
38
41
  const chunks = [];
39
42
  let bytes = 0;
@@ -72,4 +75,4 @@ export class ForgeRequestClient {
72
75
  }
73
76
  }
74
77
  }
75
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZ2VpbnZlbnRvcnkuY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvZm9yZ2VpbnZlbnRvcnkuY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxVQUFVLE1BQU0sZ0NBQWdDLENBQUM7QUE2QjdEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sa0JBQWtCO0lBQ3BCLFFBQVEsQ0FBNkI7SUFDckMsUUFBUSxHQUF5QixFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUUsYUFBYSxFQUFFLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxDQUFDLEVBQUUsQ0FBQztJQUVwRyxZQUFZLFVBQXNDO1FBQ2hELElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxHQUFHLFVBQVUsRUFBRSxPQUFPLEVBQUUsRUFBRSxHQUFHLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO0lBQ3hFLENBQUM7SUFFRCxJQUFXLE9BQU8sS0FBMkIsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUVwRSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQVEsRUFBRSxVQUFVLEdBQXlCLEVBQUU7UUFDbEUsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLFVBQVUsQ0FBQztRQUM5QixNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsZ0JBQWdCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQztRQUMvRSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsSUFBSSxRQUFRLEdBQUcsQ0FBQztZQUFFLE1BQU0sSUFBSSxVQUFVLENBQUMsbUJBQW1CLENBQUMseUJBQXlCLENBQUMsQ0FBQztRQUN6SCxNQUFNLFVBQVUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO1FBQ3pDLE1BQU0sS0FBSyxHQUFHLEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN2QyxJQUFJLE1BQU0sRUFBRSxPQUFPO1lBQUUsTUFBTSxJQUFJLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ2pGLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDekQsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDbEUsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUM7UUFDN0QsSUFBSSxVQUFpRCxDQUFDO1FBQ3RELElBQUksQ0FBQztZQUNILElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDekIsTUFBTSxPQUFPLEdBQUcsRUFBRSxNQUFNLEVBQUUsa0JBQWtCLEVBQUUsR0FBRyxVQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNoRyxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2hGLFVBQVUsR0FBRyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7WUFDckQsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEdBQUc7Z0JBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQ2pFLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxHQUFHO2dCQUFFLE1BQU0sSUFBSSxVQUFVLENBQUMsbUJBQW1CLENBQUMsUUFBUSxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUNqRyxJQUFJLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsS0FBSyxrQkFBa0IsSUFBSSxDQUFDLFVBQVU7Z0JBQUUsTUFBTSxJQUFJLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1lBQ3JMLE1BQU0sTUFBTSxHQUFpQixFQUFFLENBQUM7WUFDaEMsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO1lBQ2QsT0FBTyxJQUFJLEVBQUUsQ0FBQztnQkFDWixNQUFNLE1BQU0sR0FBRyxNQUFNLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDdkMsSUFBSSxNQUFNLENBQUMsSUFBSTtvQkFBRSxNQUFNO2dCQUN2QixLQUFLLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUM7Z0JBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUM7Z0JBQ3pGLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUM7b0JBQUUsTUFBTSxJQUFJLFVBQVUsQ0FBQyxtQkFBbUIsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO2dCQUNoSSxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxRQUFRO29CQUFFLE1BQU0sSUFBSSxVQUFVLENBQUMsbUJBQW1CLENBQUMsOEJBQThCLENBQUMsQ0FBQztnQkFDbEksTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDNUIsQ0FBQztZQUNELE1BQU0sSUFBSSxHQUFHLElBQUksV0FBVyxDQUFDLE9BQU8sRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDckYsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQVksQ0FBQztZQUN6QyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxRQUFRO2dCQUFFLE1BQU0sSUFBSSxVQUFVLENBQUMsbUJBQW1CLENBQUMsOEJBQThCLENBQUMsQ0FBQztZQUNsSSxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDN0MsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixJQUFJLEtBQUssWUFBWSxVQUFVLENBQUMsbUJBQW1CO2dCQUFFLE1BQU0sS0FBSyxDQUFDO1lBQ2pFLE1BQU0sSUFBSSxVQUFVLENBQUMsbUJBQW1CLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLDhCQUE4QixDQUFDLENBQUMsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQ2xJLENBQUM7Z0JBQVMsQ0FBQztZQUNULFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUFDLE1BQU0sRUFBRSxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDdkYsb0dBQW9HO1lBQ3BHLElBQUksQ0FBQztnQkFBQyxNQUFNLFVBQVUsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQUMsQ0FBQztZQUFDLE1BQU0sQ0FBQyxDQUFDLDJDQUEyQyxDQUFDLENBQUM7UUFDN0YsQ0FBQztJQUNILENBQUM7Q0FDRiJ9
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZ2VpbnZlbnRvcnkuY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvZm9yZ2VpbnZlbnRvcnkuY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxVQUFVLE1BQU0sZ0NBQWdDLENBQUM7QUFpQzdEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLGtCQUFrQjtJQUNwQixRQUFRLENBQTZCO0lBQ3JDLFFBQVEsR0FBeUIsRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFFLGFBQWEsRUFBRSxDQUFDLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQyxFQUFFLENBQUM7SUFFcEcsWUFBWSxVQUFzQztRQUNoRCxJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsR0FBRyxVQUFVLEVBQUUsT0FBTyxFQUFFLEVBQUUsR0FBRyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztJQUN4RSxDQUFDO0lBRUQsSUFBVyxPQUFPLEtBQTJCLE9BQU8sRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFcEUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFRLEVBQUUsVUFBVSxHQUF5QixFQUFFO1FBQ2xFLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxVQUFVLENBQUM7UUFDOUIsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUM7UUFDL0UsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLElBQUksUUFBUSxHQUFHLENBQUM7WUFBRSxNQUFNLElBQUksVUFBVSxDQUFDLG1CQUFtQixDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFDekgsTUFBTSxVQUFVLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUN6QyxNQUFNLEtBQUssR0FBRyxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLENBQUM7UUFD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
@@ -1,3 +1,4 @@
1
+ import * as plugins from './plugins.js';
1
2
  /** The transport-neutral part of a response that the adapter evaluates. */
2
3
  export interface IForgeTransportResponse {
3
4
  status: number;
@@ -6,13 +7,46 @@ export interface IForgeTransportResponse {
6
7
  body: AsyncIterable<Uint8Array> | null;
7
8
  }
8
9
  /**
9
- * Sends one credential-scoped GET and resolves once response headers arrive.
10
- * A redirect status rejects and is never followed; aborting `signal` discards
11
- * the connection, also while the body is still being read.
10
+ * Sends one credential-scoped GET, or a POST of `body` when one is given, and
11
+ * resolves once response headers arrive. A redirect status rejects and is
12
+ * never followed; aborting `signal` discards the connection, also while the
13
+ * body is still being read.
12
14
  */
13
- export type TForgeTransport = (url: URL, headers: Record<string, string>, signal: AbortSignal) => Promise<IForgeTransportResponse>;
15
+ export type TForgeTransport = (url: URL, headers: Record<string, string>, signal: AbortSignal, body?: Uint8Array<ArrayBuffer>) => Promise<IForgeTransportResponse>;
14
16
  /** Node's global `fetch` with the process-wide default trust store. */
15
17
  export declare const globalFetchTransport: TForgeTransport;
18
+ /** The agents a node request may use; a URL whose protocol has no agent is refused. */
19
+ export interface INodeRequestAgents {
20
+ http?: InstanceType<typeof plugins.http.Agent>;
21
+ https?: InstanceType<typeof plugins.https.Agent>;
22
+ }
23
+ export interface INodeRequest {
24
+ method: string;
25
+ headers: Record<string, string>;
26
+ /** Sent in full, or streamed with backpressure; a streamed body needs its own `content-length` header. */
27
+ body?: Uint8Array | AsyncIterable<Uint8Array>;
28
+ signal: AbortSignal;
29
+ agents: INodeRequestAgents;
30
+ }
31
+ export interface INodeResponse extends IForgeTransportResponse {
32
+ /**
33
+ * Settles once the request body has been sent, or rejects with the error
34
+ * that ended it, such as the body source's own error. Always handled.
35
+ */
36
+ sent: Promise<void>;
37
+ }
38
+ /**
39
+ * Idle keep-alive agents that unreference their pooled sockets, so pooled
40
+ * connections never keep the process alive.
41
+ */
42
+ export declare const createNodeAgents: (caCertificatesArg?: string[], allowHttpArg?: boolean) => INodeRequestAgents;
43
+ /**
44
+ * Sends one request through `node:http` or `node:https` and resolves once
45
+ * response headers arrive. A redirect status rejects and is never followed;
46
+ * aborting `signal` discards the connection, also while a body is still being
47
+ * sent or read. A streamed body that fails destroys the request and rejects.
48
+ */
49
+ export declare const sendNodeRequest: (url: URL, requestArg: INodeRequest) => Promise<INodeResponse>;
16
50
  /**
17
51
  * `node:https` with an owned keep-alive agent whose `ca` list replaces the
18
52
  * default trust store for these connections only. The agent unreferences idle
@@ -8,51 +8,112 @@ 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) => {
12
- const response = await fetch(url, { method: 'GET', headers, redirect: 'error', credentials: 'omit', signal });
11
+ export const globalFetchTransport = async (url, headers, signal, body) => {
12
+ const response = await fetch(url, { method: body ? 'POST' : 'GET', headers, body, redirect: 'error', credentials: 'omit', signal });
13
13
  return { status: response.status, headers: response.headers, body: response.body };
14
14
  };
15
+ /**
16
+ * Idle keep-alive agents that unreference their pooled sockets, so pooled
17
+ * connections never keep the process alive.
18
+ */
19
+ export const createNodeAgents = (caCertificatesArg, allowHttpArg = false) => ({
20
+ https: new plugins.https.Agent({ ...(caCertificatesArg ? { ca: caCertificatesArg } : {}), keepAlive: true, timeout: idleSocketTimeoutMs }),
21
+ ...(allowHttpArg ? { http: new plugins.http.Agent({ keepAlive: true, timeout: idleSocketTimeoutMs }) } : {}),
22
+ });
23
+ /** Waits until the request can take more body bytes; rejects once it has closed. */
24
+ const drained = (requestArg) => new Promise((resolve, reject) => {
25
+ const done = () => { requestArg.off('drain', done); requestArg.off('close', closed); resolve(); };
26
+ const closed = () => { requestArg.off('drain', done); requestArg.off('close', closed); reject(new Error('Request closed.')); };
27
+ requestArg.on('drain', done);
28
+ requestArg.on('close', closed);
29
+ });
30
+ /**
31
+ * Sends one request through `node:http` or `node:https` and resolves once
32
+ * response headers arrive. A redirect status rejects and is never followed;
33
+ * aborting `signal` discards the connection, also while a body is still being
34
+ * sent or read. A streamed body that fails destroys the request and rejects.
35
+ */
36
+ export const sendNodeRequest = (url, requestArg) => new Promise((resolve, reject) => {
37
+ const { signal } = requestArg;
38
+ if (signal.aborted)
39
+ return reject(signal.reason);
40
+ const agent = url.protocol === 'https:' ? requestArg.agents.https : url.protocol === 'http:' ? requestArg.agents.http : undefined;
41
+ if (!agent)
42
+ return reject(new Error('Refused protocol.'));
43
+ const module = url.protocol === 'https:' ? plugins.https : plugins.http;
44
+ // Bodies are read as sent, so ask for them without a content coding.
45
+ const request = module.request(url, { method: requestArg.method, headers: { ...requestArg.headers, 'accept-encoding': 'identity' }, agent });
46
+ let settled = false;
47
+ const fail = (errorArg) => {
48
+ if (!settled) {
49
+ settled = true;
50
+ reject(errorArg);
51
+ }
52
+ };
53
+ // Stays attached for the request's lifetime, so a connection failure while
54
+ // the body is read never becomes an unhandled 'error' event.
55
+ request.on('error', fail);
56
+ // Destroyed without an error on purpose: an error would be re-emitted on the
57
+ // socket, which no longer has a listener once a keep-alive response completed.
58
+ const abort = () => {
59
+ fail(signal.reason);
60
+ request.destroy();
61
+ };
62
+ signal.addEventListener('abort', abort, { once: true });
63
+ request.once('close', () => signal.removeEventListener('abort', abort));
64
+ const sent = (async () => {
65
+ const { body } = requestArg;
66
+ if (body === undefined || body instanceof Uint8Array) {
67
+ request.end(body);
68
+ return;
69
+ }
70
+ try {
71
+ for await (const chunk of body) {
72
+ if (request.destroyed)
73
+ throw new Error('Request closed.');
74
+ if (!request.write(chunk))
75
+ await drained(request);
76
+ }
77
+ request.end();
78
+ }
79
+ catch (error) {
80
+ fail(error);
81
+ request.destroy();
82
+ throw error;
83
+ }
84
+ })();
85
+ sent.catch(() => undefined);
86
+ request.on('response', (response) => {
87
+ try {
88
+ const status = response.statusCode ?? 0;
89
+ if (redirectStatuses.has(status))
90
+ throw new Error('Refused redirect.');
91
+ // Same combination rules as fetch: repeated fields join with ", ".
92
+ const responseHeaders = new Headers();
93
+ for (let index = 0; index < response.rawHeaders.length; index += 2) {
94
+ responseHeaders.append(response.rawHeaders[index], response.rawHeaders[index + 1]);
95
+ }
96
+ if (settled)
97
+ return void request.destroy();
98
+ settled = true;
99
+ resolve({ status, headers: responseHeaders, body: response, sent });
100
+ }
101
+ catch (error) {
102
+ fail(error);
103
+ request.destroy();
104
+ }
105
+ });
106
+ });
15
107
  /**
16
108
  * `node:https` with an owned keep-alive agent whose `ca` list replaces the
17
109
  * default trust store for these connections only. The agent unreferences idle
18
110
  * sockets, so pooled connections never keep the process alive.
19
111
  */
20
112
  export const createHttpsTransport = (caCertificates) => {
21
- const agent = new plugins.https.Agent({ ca: caCertificates, keepAlive: true, timeout: idleSocketTimeoutMs });
22
- return (url, headers, signal) => new Promise((resolve, reject) => {
23
- if (signal.aborted)
24
- return reject(signal.reason);
25
- // Bodies are read as sent, so ask for them without a content coding.
26
- const request = plugins.https.request(url, { method: 'GET', headers: { ...headers, 'accept-encoding': 'identity' }, agent });
27
- // Stays attached for the request's lifetime, so a connection failure while
28
- // the body is read never becomes an unhandled 'error' event.
29
- request.on('error', reject);
30
- // Destroyed without an error on purpose: an error would be re-emitted on the
31
- // socket, which no longer has a listener once a keep-alive response completed.
32
- const abort = () => {
33
- reject(signal.reason);
34
- request.destroy();
35
- };
36
- signal.addEventListener('abort', abort, { once: true });
37
- request.once('close', () => signal.removeEventListener('abort', abort));
38
- request.on('response', (response) => {
39
- try {
40
- const status = response.statusCode ?? 0;
41
- if (redirectStatuses.has(status))
42
- throw new Error('Refused redirect.');
43
- // Same combination rules as fetch: repeated fields join with ", ".
44
- const responseHeaders = new Headers();
45
- for (let index = 0; index < response.rawHeaders.length; index += 2) {
46
- responseHeaders.append(response.rawHeaders[index], response.rawHeaders[index + 1]);
47
- }
48
- resolve({ status, headers: responseHeaders, body: response });
49
- }
50
- catch (error) {
51
- reject(error);
52
- request.destroy();
53
- }
54
- });
55
- request.end();
56
- });
113
+ const agents = createNodeAgents(caCertificates);
114
+ return async (url, headers, signal, body) => {
115
+ const { sent: _sent, ...response } = await sendNodeRequest(url, { method: body ? 'POST' : 'GET', headers, body, signal, agents });
116
+ return response;
117
+ };
57
118
  };
58
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZ2VpbnZlbnRvcnkudHJhbnNwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvZm9yZ2VpbnZlbnRvcnkudHJhbnNwb3J0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBaUJ4QyxzRkFBc0Y7QUFDdEYsTUFBTSxnQkFBZ0IsR0FBd0IsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUVqRjs7OztHQUlHO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxLQUFLLENBQUM7QUFFbEMsdUVBQXVFO0FBQ3ZFLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFvQixLQUFLLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtJQUNsRixNQUFNLFFBQVEsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUM5RyxPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNyRixDQUFDLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxjQUF3QixFQUFtQixFQUFFO0lBQ2hGLE1BQU0sS0FBSyxHQUFHLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLENBQUMsQ0FBQztJQUM3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
119
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZ2VpbnZlbnRvcnkudHJhbnNwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvZm9yZ2VpbnZlbnRvcnkudHJhbnNwb3J0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBa0J4QyxzRkFBc0Y7QUFDdEYsTUFBTSxnQkFBZ0IsR0FBd0IsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUVqRjs7OztHQUlHO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxLQUFLLENBQUM7QUFFbEMsdUVBQXVFO0FBQ3ZFLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFvQixLQUFLLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUU7SUFDeEYsTUFBTSxRQUFRLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztJQUNwSSxPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNyRixDQUFDLENBQUM7QUF5QkY7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxpQkFBNEIsRUFBRSxZQUFZLEdBQUcsS0FBSyxFQUFzQixFQUFFLENBQUMsQ0FBQztJQUMzRyxLQUFLLEVBQUUsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUss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
@@ -0,0 +1,86 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { ForgeRequestClient } from './forgeinventory.client.js';
3
+ type IGitCounts = Omit<plugins.fossInterfaces.data.IForgeSourceGitCounts, 'reportedSizeKiB'>;
4
+ type ILfsCounts = plugins.fossInterfaces.data.IForgeSourceLfsCounts;
5
+ export interface IGiteaMirrorSource {
6
+ /** Instance root without a trailing slash. */
7
+ baseUrl: string;
8
+ owner: string;
9
+ name: string;
10
+ /** The reader's login and token; Gitea accepts a token as the Basic password for Git and LFS. */
11
+ username: string;
12
+ token: string;
13
+ caCertificates?: string[];
14
+ /** Private directory that holds the temporary mirror. */
15
+ workDir: string;
16
+ /** The repository size Gitea reports, which sizes the mirror's scratch reservation. */
17
+ reportedSizeKiB: bigint;
18
+ /** Wall-clock limit of the mirror clone. */
19
+ timeoutMs: number;
20
+ /** Sends LFS batch reads with the reader's Basic credentials. */
21
+ lfsClient: ForgeRequestClient;
22
+ signal?: AbortSignal;
23
+ }
24
+ /**
25
+ * Scratch space reserved for one mirror: twice the size Gitea reports, because
26
+ * a clone holds received and indexed packs, plus fixed headroom for refs, the
27
+ * index and a size Gitea has not updated yet.
28
+ */
29
+ export declare const mirrorScratchBytes: (reportedSizeKiBArg: bigint) => bigint;
30
+ /**
31
+ * Admits mirror clones on one file system in arrival order while the scratch
32
+ * they reserve fits its free space. A clone's reservation counts in full until
33
+ * it is released, although part of it is already written, so the check never
34
+ * admits more than fits. A clone that does not fit waits until the clones in
35
+ * flight release their reservations; one that does not fit even alone is
36
+ * refused.
37
+ */
38
+ export declare class GitScratchBudget {
39
+ #private;
40
+ constructor(freeBytesArg?: (directoryArg: string) => Promise<bigint>);
41
+ /**
42
+ * Reserves `bytesArg` in `directoryArg` and resolves with the function that
43
+ * releases them, or with null when they exceed the free space with no other
44
+ * clone in flight. Rejects when the free space cannot be read or `signalArg`
45
+ * aborts.
46
+ */
47
+ reserve(directoryArg: string, bytesArg: bigint, signalArg?: AbortSignal): Promise<(() => void) | null>;
48
+ /**
49
+ * The process-wide budget of the file system that holds `directoryArg`,
50
+ * keyed by its device; every mirror clone and every scratch GitManager in
51
+ * the process reserves through it.
52
+ */
53
+ static forDirectory(directoryArg: string): Promise<GitScratchBudget>;
54
+ }
55
+ /**
56
+ * Reserves the scratch of one mirror clone into `directoryArg` in the
57
+ * process-wide budget of its file system and resolves with the function that
58
+ * releases it. Rejects with `git-workdir-too-small` when the clone does not
59
+ * fit even alone, `git-workdir-failed` when the directory or its free space
60
+ * cannot be read and `request-aborted` when `signalArg` aborts first.
61
+ */
62
+ export declare const reserveMirrorScratch: (directoryArg: string, reportedSizeKiBArg: bigint, signalArg?: AbortSignal) => Promise<() => void>;
63
+ /** The HTTPS Git URL of a Gitea repository; it never carries credentials. */
64
+ export declare const giteaCloneUrl: (baseUrlArg: string, ownerArg: string, nameArg: string) => string;
65
+ /**
66
+ * Measures one repository at the Git level: clones every ref Gitea advertises
67
+ * into a temporary mirror, counts its refs and objects, finds the LFS pointers
68
+ * of every reachable revision and checks through the LFS batch API which of
69
+ * their objects Gitea holds. The mirror is removed afterwards. The clone starts
70
+ * only once its scratch reservation fits the work directory's free space; a
71
+ * repository too large for it fails with `git-workdir-too-small`.
72
+ */
73
+ export declare const measureGiteaMirror: (sourceArg: IGiteaMirrorSource) => Promise<{
74
+ git: IGitCounts;
75
+ lfs: ILfsCounts;
76
+ }>;
77
+ /**
78
+ * Asks Gitea's LFS batch API, as a `download`, which referenced objects it
79
+ * holds: a held object answers with a download action, a missing one with
80
+ * error 404. Actions, their URLs and headers are never retained.
81
+ */
82
+ export declare const giteaLfsPresence: (sourceArg: Pick<IGiteaMirrorSource, 'baseUrl' | 'owner' | 'name' | 'lfsClient' | 'signal'>, pointersArg: Array<{
83
+ oid: string;
84
+ sizeBytes: number;
85
+ }>) => Promise<ILfsCounts>;
86
+ export {};