@package-broker/runtime-node 0.0.0-stage → 2.0.0-rc.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.
Files changed (100) hide show
  1. package/LICENSE +661 -0
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/assets.d.ts +4 -0
  4. package/dist/assets.d.ts.map +1 -0
  5. package/dist/assets.js +68 -0
  6. package/dist/assets.js.map +1 -0
  7. package/dist/blob/archive-staging.d.ts +15 -0
  8. package/dist/blob/archive-staging.d.ts.map +1 -0
  9. package/dist/blob/archive-staging.js +154 -0
  10. package/dist/blob/archive-staging.js.map +1 -0
  11. package/dist/blob/filesystem.d.ts +18 -0
  12. package/dist/blob/filesystem.d.ts.map +1 -0
  13. package/dist/blob/filesystem.js +631 -0
  14. package/dist/blob/filesystem.js.map +1 -0
  15. package/dist/blob/hasher.d.ts +3 -0
  16. package/dist/blob/hasher.d.ts.map +1 -0
  17. package/dist/blob/hasher.js +26 -0
  18. package/dist/blob/hasher.js.map +1 -0
  19. package/dist/blob/s3.d.ts +40 -0
  20. package/dist/blob/s3.d.ts.map +1 -0
  21. package/dist/blob/s3.js +494 -0
  22. package/dist/blob/s3.js.map +1 -0
  23. package/dist/cache/lru.d.ts +8 -0
  24. package/dist/cache/lru.d.ts.map +1 -0
  25. package/dist/cache/lru.js +103 -0
  26. package/dist/cache/lru.js.map +1 -0
  27. package/dist/client-ip.d.ts +22 -0
  28. package/dist/client-ip.d.ts.map +1 -0
  29. package/dist/client-ip.js +104 -0
  30. package/dist/client-ip.js.map +1 -0
  31. package/dist/codec/node-codec.d.ts +3 -0
  32. package/dist/codec/node-codec.d.ts.map +1 -0
  33. package/dist/codec/node-codec.js +163 -0
  34. package/dist/codec/node-codec.js.map +1 -0
  35. package/dist/db/better-sqlite3-executor.d.ts +10 -0
  36. package/dist/db/better-sqlite3-executor.d.ts.map +1 -0
  37. package/dist/db/better-sqlite3-executor.js +129 -0
  38. package/dist/db/better-sqlite3-executor.js.map +1 -0
  39. package/dist/entry.d.ts +32 -0
  40. package/dist/entry.d.ts.map +1 -0
  41. package/dist/entry.js +158 -0
  42. package/dist/entry.js.map +1 -0
  43. package/dist/import-jobs.d.ts +18 -0
  44. package/dist/import-jobs.d.ts.map +1 -0
  45. package/dist/import-jobs.js +56 -0
  46. package/dist/import-jobs.js.map +1 -0
  47. package/dist/index.d.ts +113 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +981 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/internal/seams-key.d.ts +2 -0
  52. package/dist/internal/seams-key.d.ts.map +1 -0
  53. package/dist/internal/seams-key.js +2 -0
  54. package/dist/internal/seams-key.js.map +1 -0
  55. package/dist/jobs/loop.d.ts +38 -0
  56. package/dist/jobs/loop.d.ts.map +1 -0
  57. package/dist/jobs/loop.js +318 -0
  58. package/dist/jobs/loop.js.map +1 -0
  59. package/dist/observability/stdio.d.ts +11 -0
  60. package/dist/observability/stdio.d.ts.map +1 -0
  61. package/dist/observability/stdio.js +47 -0
  62. package/dist/observability/stdio.js.map +1 -0
  63. package/dist/organization-administration.d.ts +5 -0
  64. package/dist/organization-administration.d.ts.map +1 -0
  65. package/dist/organization-administration.js +16 -0
  66. package/dist/organization-administration.js.map +1 -0
  67. package/dist/sources/dns-guard.d.ts +33 -0
  68. package/dist/sources/dns-guard.d.ts.map +1 -0
  69. package/dist/sources/dns-guard.js +202 -0
  70. package/dist/sources/dns-guard.js.map +1 -0
  71. package/dist/sources/git-provider.d.ts +30 -0
  72. package/dist/sources/git-provider.d.ts.map +1 -0
  73. package/dist/sources/git-provider.js +213 -0
  74. package/dist/sources/git-provider.js.map +1 -0
  75. package/dist/sources/guarded-fetch.d.ts +15 -0
  76. package/dist/sources/guarded-fetch.d.ts.map +1 -0
  77. package/dist/sources/guarded-fetch.js +217 -0
  78. package/dist/sources/guarded-fetch.js.map +1 -0
  79. package/dist/sources/ssh-archive-store.d.ts +19 -0
  80. package/dist/sources/ssh-archive-store.d.ts.map +1 -0
  81. package/dist/sources/ssh-archive-store.js +284 -0
  82. package/dist/sources/ssh-archive-store.js.map +1 -0
  83. package/dist/sources/ssh-git.d.ts +46 -0
  84. package/dist/sources/ssh-git.d.ts.map +1 -0
  85. package/dist/sources/ssh-git.js +430 -0
  86. package/dist/sources/ssh-git.js.map +1 -0
  87. package/dist/sources/ssh-provider.d.ts +55 -0
  88. package/dist/sources/ssh-provider.d.ts.map +1 -0
  89. package/dist/sources/ssh-provider.js +369 -0
  90. package/dist/sources/ssh-provider.js.map +1 -0
  91. package/dist/startup.d.ts +49 -0
  92. package/dist/startup.d.ts.map +1 -0
  93. package/dist/startup.js +688 -0
  94. package/dist/startup.js.map +1 -0
  95. package/dist/token-jobs.d.ts +18 -0
  96. package/dist/token-jobs.d.ts.map +1 -0
  97. package/dist/token-jobs.js +45 -0
  98. package/dist/token-jobs.js.map +1 -0
  99. package/package.json +45 -3
  100. package/README.md +0 -3
@@ -0,0 +1,202 @@
1
+ import { lookup as systemLookup } from 'node:dns/promises';
2
+ import { isIP } from 'node:net';
3
+ import { classifyAddress, parseAllowlist, } from '@package-broker/core/sources/url-policy';
4
+ export class DnsGuardError extends Error {
5
+ reason;
6
+ name = 'DnsGuardError';
7
+ constructor(reason) {
8
+ super(`outbound host refused: ${reason}`);
9
+ this.reason = reason;
10
+ }
11
+ }
12
+ const DEFAULT_TIMEOUT_MS = 5000;
13
+ const DEFAULT_MAX_IN_FLIGHT = 16;
14
+ const HTTPS_PORT = 443;
15
+ const systemResolver = async (host) => (await systemLookup(host, { all: true, verbatim: true })).map((entry) => ({
16
+ address: entry.address,
17
+ family: entry.family === 6 ? 6 : 4,
18
+ }));
19
+ function canonicalIpv6(text) {
20
+ if (isIP(text) !== 6 || text.includes('%'))
21
+ return null;
22
+ try {
23
+ return new URL(`http://[${text}]/`).hostname.slice(1, -1);
24
+ }
25
+ catch {
26
+ return null;
27
+ }
28
+ }
29
+ function stripBrackets(host) {
30
+ return host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host;
31
+ }
32
+ function comparableHost(host) {
33
+ const bare = stripBrackets(host.toLowerCase());
34
+ return canonicalIpv6(bare) ?? bare.replace(/\.$/, '');
35
+ }
36
+ function isAllowlisted(host, port, scheme, allowlist) {
37
+ if (scheme !== 'https' && scheme !== 'ssh')
38
+ return false;
39
+ const wanted = comparableHost(host);
40
+ return allowlist.some((entry) => {
41
+ const match = /^(\[[^\]]+\]|[^:]+)(?::(\d{1,5}))?$/.exec(entry);
42
+ if (!match?.[1] || comparableHost(match[1]) !== wanted)
43
+ return false;
44
+ if (match[2] !== undefined)
45
+ return Number(match[2]) === port;
46
+ return scheme === 'https' && port === HTTPS_PORT;
47
+ });
48
+ }
49
+ function normalizeAddress(raw) {
50
+ if (raw.includes('%'))
51
+ throw new DnsGuardError('zone_id');
52
+ const kind = isIP(raw);
53
+ if (kind === 4)
54
+ return { address: raw, family: 4 };
55
+ const canonical = kind === 6 ? canonicalIpv6(raw) : null;
56
+ if (!canonical)
57
+ throw new DnsGuardError('invalid_address');
58
+ const mapped = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/.exec(canonical);
59
+ if (mapped?.[1] && mapped[2]) {
60
+ const high = Number.parseInt(mapped[1], 16);
61
+ const low = Number.parseInt(mapped[2], 16);
62
+ return { address: `${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`, family: 4 };
63
+ }
64
+ return { address: canonical, family: 6 };
65
+ }
66
+ function ipv6Groups(canonical) {
67
+ const [head = '', tail] = canonical.split('::');
68
+ const left = head === '' ? [] : head.split(':');
69
+ const right = tail === undefined || tail === '' ? [] : tail.split(':');
70
+ const fill = tail === undefined ? [] : Array(8 - left.length - right.length).fill('0');
71
+ return [...left, ...fill, ...right].map((group) => Number.parseInt(group, 16));
72
+ }
73
+ function embeddedIpv4(high, low) {
74
+ return { address: `${high >> 8}.${high & 255}.${low >> 8}.${low & 255}`, family: 4 };
75
+ }
76
+ function isNeverAllowed({ address, family }) {
77
+ if (family === 4) {
78
+ const octets = address.split('.').map(Number);
79
+ const [first = 0, second = 0] = octets;
80
+ return first === 0 || first >= 224 || (first === 169 && second === 254);
81
+ }
82
+ if (address === '::' || address === 'fd00:ec2::254')
83
+ return true;
84
+ const g = ipv6Groups(address);
85
+ const [g0 = 0, g1 = 0, g2 = 0, g3 = 0, g4 = 0, g5 = 0, g6 = 0, g7 = 0] = g;
86
+ if (g0 >= 0xff00 || (g0 & 0xffc0) === 0xfe80)
87
+ return true;
88
+ if (g0 === 0x2002)
89
+ return isNeverAllowed(embeddedIpv4(g1, g2));
90
+ const zeroPrefix = g0 === 0 && g1 === 0 && g2 === 0 && g3 === 0;
91
+ const nat64 = g0 === 0x64 && g1 === 0xff9b && g2 === 0 && g3 === 0 && g4 === 0 && g5 === 0;
92
+ const siit = zeroPrefix && g4 === 0xffff && g5 === 0;
93
+ const compat = zeroPrefix && g4 === 0 && g5 === 0 && g6 !== 0;
94
+ return (nat64 || siit || compat) && isNeverAllowed(embeddedIpv4(g6, g7));
95
+ }
96
+ function wantedFamily(family) {
97
+ if (family === 4 || family === 'IPv4')
98
+ return 4;
99
+ if (family === 6 || family === 'IPv6')
100
+ return 6;
101
+ return undefined;
102
+ }
103
+ function withDeadline(work, timeoutMs, signal) {
104
+ return new Promise((resolve, reject) => {
105
+ if (signal?.aborted) {
106
+ reject(new DnsGuardError('aborted'));
107
+ return;
108
+ }
109
+ const onAbort = () => finish(() => reject(new DnsGuardError('aborted')));
110
+ const timer = setTimeout(() => finish(() => reject(new DnsGuardError('resolution_timeout'))), timeoutMs);
111
+ function finish(settle) {
112
+ clearTimeout(timer);
113
+ signal?.removeEventListener('abort', onAbort);
114
+ settle();
115
+ }
116
+ signal?.addEventListener('abort', onAbort, { once: true });
117
+ work.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error instanceof DnsGuardError ? error : new DnsGuardError('resolution_failed'))));
118
+ });
119
+ }
120
+ export function createDnsGuard(policy, options = {}) {
121
+ const resolver = options.resolver ?? systemResolver;
122
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
123
+ const maxInFlight = options.maxInFlight ?? DEFAULT_MAX_IN_FLIGHT;
124
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
125
+ throw new RangeError('timeoutMs must be a positive finite number');
126
+ }
127
+ if (!Number.isInteger(maxInFlight) || maxInFlight <= 0) {
128
+ throw new RangeError('maxInFlight must be a positive integer');
129
+ }
130
+ const allowlist = parseAllowlist(policy.allowPrivateHosts, policy.runtime);
131
+ let inFlight = 0;
132
+ function startResolution(target) {
133
+ if (inFlight >= maxInFlight)
134
+ return Promise.reject(new DnsGuardError('resolution_timeout'));
135
+ inFlight += 1;
136
+ const work = Promise.resolve().then(() => resolver(target));
137
+ const release = () => {
138
+ inFlight -= 1;
139
+ };
140
+ work.then(release, release);
141
+ return work;
142
+ }
143
+ async function resolveTarget(host, port, scheme) {
144
+ if (scheme !== 'https' && scheme !== 'http' && scheme !== 'ssh') {
145
+ throw new DnsGuardError('scheme');
146
+ }
147
+ if (scheme === 'http' &&
148
+ (port === HTTPS_PORT || isAllowlisted(host, port, 'https', allowlist))) {
149
+ throw new DnsGuardError('scheme');
150
+ }
151
+ const literal = canonicalIpv6(stripBrackets(host.toLowerCase()));
152
+ const target = literal ?? host;
153
+ const resolved = await withDeadline(startResolution(target), timeoutMs, options.signal);
154
+ if (resolved.length === 0)
155
+ throw new DnsGuardError('no_address');
156
+ const allowed = isAllowlisted(host, port, scheme, allowlist);
157
+ const addresses = resolved.map((entry) => {
158
+ const normalized = normalizeAddress(entry.address);
159
+ if (isNeverAllowed(normalized))
160
+ throw new DnsGuardError('blocked_address');
161
+ if (!allowed) {
162
+ const verdict = classifyAddress(normalized.address);
163
+ if (!verdict.ok)
164
+ throw new DnsGuardError(verdict.reason);
165
+ }
166
+ return normalized;
167
+ });
168
+ return { host: target, addresses };
169
+ }
170
+ return {
171
+ forTarget(host, port, scheme) {
172
+ const bound = comparableHost(host);
173
+ const lookup = (requested, lookupOptions, callback) => {
174
+ const wanted = wantedFamily(lookupOptions.family);
175
+ const all = lookupOptions.all === true;
176
+ const fail = (error) => {
177
+ process.nextTick(() => callback(error, all ? [] : '', 4));
178
+ };
179
+ if (comparableHost(requested) !== bound) {
180
+ fail(new DnsGuardError('blocked_host'));
181
+ return;
182
+ }
183
+ resolveTarget(host, port, scheme).then(({ addresses }) => {
184
+ const matching = addresses.filter((entry) => wanted === undefined || entry.family === wanted);
185
+ const first = matching[0];
186
+ if (!first) {
187
+ fail(new DnsGuardError('no_address'));
188
+ return;
189
+ }
190
+ process.nextTick(() => {
191
+ if (all)
192
+ callback(null, matching.map((entry) => ({ ...entry })));
193
+ else
194
+ callback(null, first.address, first.family);
195
+ });
196
+ }, (error) => fail(error instanceof DnsGuardError ? error : new DnsGuardError('resolution_failed')));
197
+ };
198
+ return { resolve: () => resolveTarget(host, port, scheme), lookup };
199
+ },
200
+ };
201
+ }
202
+ //# sourceMappingURL=dns-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dns-guard.js","sourceRoot":"","sources":["../../src/sources/dns-guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { ArchiveStaging } from '@package-broker/core/sources/git/archive';
2
+ import { type SourceProvider } from '@package-broker/core/sources/provider';
3
+ export interface NodeGitProviderOptions {
4
+ readonly staging: ArchiveStaging;
5
+ /** How long a built archive stays staged for the second read of a two-pass store. */
6
+ readonly reuseMs?: number;
7
+ readonly maxStaged?: number;
8
+ /** Archive builds running at once across all organizations; more answer busy. */
9
+ readonly maxConcurrentBuilds?: number;
10
+ }
11
+ /**
12
+ * Opens the git archive staging directory. Partial archives older than an hour are removed; a
13
+ * newer one may belong to another process sharing the volume.
14
+ */
15
+ export declare function openGitArchiveStaging(directory: string, now?: () => number): Promise<ArchiveStaging>;
16
+ /**
17
+ * The generic Git provider with dists built on demand: `openDist` builds the zip of the requested
18
+ * commit once and serves it to every reader, including both passes of the blob store.
19
+ */
20
+ export declare function createNodeGitProvider(options: NodeGitProviderOptions): SourceProvider;
21
+ /**
22
+ * The generic Git provider for a staging root, or null when the root cannot be used; the failure is
23
+ * logged once and the provider stays unregistered, so the broker neither reports nor accepts it.
24
+ */
25
+ export declare function nodeGitProviderFor(root: string, log: (record: {
26
+ level: 'error';
27
+ event: string;
28
+ error_name: string;
29
+ }) => void, options?: Omit<NodeGitProviderOptions, 'staging'>): Promise<SourceProvider | null>;
30
+ //# sourceMappingURL=git-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-provider.d.ts","sourceRoot":"","sources":["../../src/sources/git-provider.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAgB,MAAM,0CAA0C,CAAC;AAC7F,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,uCAAuC,CAAC;AAG/C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,qFAAqF;IACrF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,iFAAiF;IACjF,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACvC;AAqED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAM,MAAiB,GAC3B,OAAO,CAAC,cAAc,CAAC,CAWzB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,cAAc,CAmHrF;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,EAC5E,OAAO,GAAE,IAAI,CAAC,sBAAsB,EAAE,SAAS,CAAM,GACpD,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAahC"}
@@ -0,0 +1,213 @@
1
+ import { lstat, mkdir, readdir, unlink } from 'node:fs/promises';
2
+ import { open } from 'node:fs/promises';
3
+ import { isAbsolute, join } from 'node:path';
4
+ import { Readable } from 'node:stream';
5
+ import { GitProviderError, createGitProvider, } from '@package-broker/core/ingest/vcs/git-provider';
6
+ import { ProviderBusyError, } from '@package-broker/core/sources/provider';
7
+ import { ArchiveStagingDirectoryError, createNodeArchiveStaging } from '../blob/archive-staging.js';
8
+ const COMMIT = /^[a-f0-9]{40}$/;
9
+ const STAGED_PART = /^archive-[0-9a-f]{32}\.zip\.part$/;
10
+ const STALE_PART_MS = 60 * 60_000;
11
+ const REUSE_MS = 60_000;
12
+ const MAX_STAGED = 32;
13
+ const MAX_CONCURRENT_BUILDS = 2;
14
+ function repositoryOf(source) {
15
+ if (source.type !== 'vcs' || source.config.provider !== 'git') {
16
+ throw new GitProviderError('invalid_request');
17
+ }
18
+ return source.config.repository;
19
+ }
20
+ function untilAborted(work, signal) {
21
+ if (signal.aborted)
22
+ return Promise.reject(signal.reason);
23
+ return new Promise((resolve, reject) => {
24
+ const onAbort = () => reject(signal.reason);
25
+ signal.addEventListener('abort', onAbort, { once: true });
26
+ work.then((value) => {
27
+ signal.removeEventListener('abort', onAbort);
28
+ resolve(value);
29
+ }, (error) => {
30
+ signal.removeEventListener('abort', onAbort);
31
+ reject(error);
32
+ });
33
+ });
34
+ }
35
+ async function requireOwnedDirectory(directory) {
36
+ if (!isAbsolute(directory))
37
+ throw new ArchiveStagingDirectoryError();
38
+ try {
39
+ await mkdir(directory, { recursive: true, mode: 0o700 });
40
+ }
41
+ catch {
42
+ throw new ArchiveStagingDirectoryError();
43
+ }
44
+ let stats;
45
+ try {
46
+ stats = await lstat(directory);
47
+ }
48
+ catch {
49
+ throw new ArchiveStagingDirectoryError();
50
+ }
51
+ if (stats.isSymbolicLink() ||
52
+ !stats.isDirectory() ||
53
+ stats.uid !== process.getuid() ||
54
+ (stats.mode & 0o022) !== 0) {
55
+ throw new ArchiveStagingDirectoryError();
56
+ }
57
+ }
58
+ /**
59
+ * Opens the git archive staging directory. Partial archives older than an hour are removed; a
60
+ * newer one may belong to another process sharing the volume.
61
+ */
62
+ export async function openGitArchiveStaging(directory, now = Date.now) {
63
+ await requireOwnedDirectory(directory);
64
+ for (const name of await readdir(directory)) {
65
+ if (!STAGED_PART.test(name))
66
+ continue;
67
+ const path = join(directory, name);
68
+ const stats = await lstat(path).catch(() => null);
69
+ if (stats?.isFile() === true && now() - stats.mtimeMs > STALE_PART_MS) {
70
+ await unlink(path).catch(() => undefined);
71
+ }
72
+ }
73
+ return createNodeArchiveStaging({ directory });
74
+ }
75
+ /**
76
+ * The generic Git provider with dists built on demand: `openDist` builds the zip of the requested
77
+ * commit once and serves it to every reader, including both passes of the blob store.
78
+ */
79
+ export function createNodeGitProvider(options) {
80
+ const git = createGitProvider({ runtime: 'docker', staging: options.staging });
81
+ const reuseMs = options.reuseMs ?? REUSE_MS;
82
+ const maxStaged = options.maxStaged ?? MAX_STAGED;
83
+ const maxConcurrentBuilds = options.maxConcurrentBuilds ?? MAX_CONCURRENT_BUILDS;
84
+ const staged = new Map();
85
+ let building = 0;
86
+ function cleanup(entry) {
87
+ if (!entry.dead || entry.holders > 0 || !entry.settled)
88
+ return;
89
+ clearTimeout(entry.timer);
90
+ if (entry.archive !== undefined)
91
+ void unlink(entry.archive.path).catch(() => undefined);
92
+ }
93
+ function retire(key, entry) {
94
+ if (staged.get(key) === entry)
95
+ staged.delete(key);
96
+ entry.dead = true;
97
+ cleanup(entry);
98
+ }
99
+ function evictSettled() {
100
+ if (staged.size < maxStaged)
101
+ return;
102
+ for (const [key, entry] of staged) {
103
+ if (entry.settled) {
104
+ retire(key, entry);
105
+ return;
106
+ }
107
+ }
108
+ }
109
+ function start(key, ctx, source, commit) {
110
+ if (building >= maxConcurrentBuilds)
111
+ throw new ProviderBusyError();
112
+ evictSettled();
113
+ const controller = new AbortController();
114
+ building += 1;
115
+ const built = git.buildArchive({ ...ctx, signal: controller.signal }, source, commit);
116
+ const entry = {
117
+ key,
118
+ built,
119
+ controller,
120
+ waiting: 0,
121
+ holders: 0,
122
+ settled: false,
123
+ dead: false,
124
+ };
125
+ staged.set(key, entry);
126
+ built.then((archive) => {
127
+ building -= 1;
128
+ entry.archive = archive;
129
+ entry.settled = true;
130
+ if (entry.dead) {
131
+ cleanup(entry);
132
+ return;
133
+ }
134
+ entry.timer = setTimeout(() => retire(key, entry), reuseMs);
135
+ entry.timer.unref();
136
+ }, () => {
137
+ building -= 1;
138
+ entry.settled = true;
139
+ retire(key, entry);
140
+ });
141
+ return entry;
142
+ }
143
+ async function read(entry, signal) {
144
+ entry.holders += 1;
145
+ entry.waiting += 1;
146
+ let handle;
147
+ let released = false;
148
+ const release = () => {
149
+ if (released)
150
+ return;
151
+ released = true;
152
+ entry.holders -= 1;
153
+ cleanup(entry);
154
+ };
155
+ try {
156
+ const archive = await untilAborted(entry.built, signal).finally(() => {
157
+ entry.waiting -= 1;
158
+ if (entry.waiting === 0 && !entry.settled) {
159
+ retire(entry.key, entry);
160
+ entry.controller.abort(signal.reason);
161
+ }
162
+ });
163
+ handle = await open(archive.path, 'r');
164
+ const stream = handle.createReadStream();
165
+ stream.once('close', release);
166
+ return {
167
+ body: Readable.toWeb(stream),
168
+ size: archive.size,
169
+ };
170
+ }
171
+ catch (error) {
172
+ await handle?.close().catch(() => undefined);
173
+ release();
174
+ throw error;
175
+ }
176
+ }
177
+ return {
178
+ id: git.id,
179
+ sourceTypes: git.sourceTypes,
180
+ ecosystems: git.ecosystems,
181
+ listPackages: git.listPackages.bind(git),
182
+ describe: git.describe.bind(git),
183
+ async openDist(ctx, source, target) {
184
+ const repository = repositoryOf(source);
185
+ const commit = target.sourceRef;
186
+ if (commit === null || !COMMIT.test(commit))
187
+ throw new GitProviderError('invalid_request');
188
+ const key = JSON.stringify([ctx.org.orgId, source.id, repository, commit]);
189
+ const entry = staged.get(key) ?? start(key, ctx, source, commit);
190
+ return read(entry, ctx.signal);
191
+ },
192
+ };
193
+ }
194
+ /**
195
+ * The generic Git provider for a staging root, or null when the root cannot be used; the failure is
196
+ * logged once and the provider stays unregistered, so the broker neither reports nor accepts it.
197
+ */
198
+ export async function nodeGitProviderFor(root, log, options = {}) {
199
+ let staging;
200
+ try {
201
+ staging = await openGitArchiveStaging(root);
202
+ }
203
+ catch (error) {
204
+ log({
205
+ level: 'error',
206
+ event: 'startup.git_archive_staging_failed',
207
+ error_name: error instanceof Error ? error.name : 'Error',
208
+ });
209
+ return null;
210
+ }
211
+ return createNodeGitProvider({ ...options, staging });
212
+ }
213
+ //# sourceMappingURL=git-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-provider.js","sourceRoot":"","sources":["../../src/sources/git-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { FetchLike } from '@package-broker/core/platform/tracing';
2
+ import type { OutboundPolicy } from '@package-broker/core/sources/url-policy';
3
+ import { type DnsGuardOptions } from './dns-guard.js';
4
+ export interface GuardedFetchOptions extends DnsGuardOptions {
5
+ readonly tls?: {
6
+ readonly ca?: string | Buffer;
7
+ };
8
+ }
9
+ /**
10
+ * Redirects are never followed, whatever init.redirect or a Request default says;
11
+ * 3xx responses are returned as-is for the caller to vet. An explicit
12
+ * redirect: 'follow' is rejected.
13
+ */
14
+ export declare function createGuardedFetch(policy: OutboundPolicy, options?: GuardedFetchOptions): FetchLike;
15
+ //# sourceMappingURL=guarded-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guarded-fetch.d.ts","sourceRoot":"","sources":["../../src/sources/guarded-fetch.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAiC,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAErF,MAAM,WAAW,mBAAoB,SAAQ,eAAe;IAC1D,QAAQ,CAAC,GAAG,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;CAClD;AAwHD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,mBAAwB,GAChC,SAAS,CA4FX"}