@push.rocks/smartlinuxrepo 0.0.0-stage → 0.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.
Files changed (131) hide show
  1. package/.smartconfig.json +64 -0
  2. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  3. package/dist_ts/00_commitinfo_data.js +9 -0
  4. package/dist_ts/alpine/apkindex.d.ts +39 -0
  5. package/dist_ts/alpine/apkindex.js +211 -0
  6. package/dist_ts/alpine/pkginfo.d.ts +45 -0
  7. package/dist_ts/alpine/pkginfo.js +159 -0
  8. package/dist_ts/alpine/reader.d.ts +20 -0
  9. package/dist_ts/alpine/reader.js +89 -0
  10. package/dist_ts/arch/builder.d.ts +41 -0
  11. package/dist_ts/arch/builder.js +234 -0
  12. package/dist_ts/arch/reader.d.ts +16 -0
  13. package/dist_ts/arch/reader.js +271 -0
  14. package/dist_ts/arch/signer.d.ts +21 -0
  15. package/dist_ts/arch/signer.js +66 -0
  16. package/dist_ts/arch/vercmp.d.ts +12 -0
  17. package/dist_ts/arch/vercmp.js +170 -0
  18. package/dist_ts/debian/control.d.ts +22 -0
  19. package/dist_ts/debian/control.js +137 -0
  20. package/dist_ts/debian/gostring.d.ts +26 -0
  21. package/dist_ts/debian/gostring.js +145 -0
  22. package/dist_ts/debian/indexbuilder.d.ts +47 -0
  23. package/dist_ts/debian/indexbuilder.js +299 -0
  24. package/dist_ts/debian/mailaddress.d.ts +12 -0
  25. package/dist_ts/debian/mailaddress.js +736 -0
  26. package/dist_ts/debian/reader.d.ts +30 -0
  27. package/dist_ts/debian/reader.js +110 -0
  28. package/dist_ts/index.d.ts +23 -0
  29. package/dist_ts/index.js +18 -0
  30. package/dist_ts/plugins.d.ts +8 -0
  31. package/dist_ts/plugins.js +11 -0
  32. package/dist_ts/readers/ar.d.ts +31 -0
  33. package/dist_ts/readers/ar.js +87 -0
  34. package/dist_ts/readers/bytes.d.ts +58 -0
  35. package/dist_ts/readers/bytes.js +147 -0
  36. package/dist_ts/readers/bytesource.d.ts +40 -0
  37. package/dist_ts/readers/bytesource.js +154 -0
  38. package/dist_ts/readers/decompress.d.ts +43 -0
  39. package/dist_ts/readers/decompress.js +269 -0
  40. package/dist_ts/readers/gzipmember.d.ts +32 -0
  41. package/dist_ts/readers/gzipmember.js +176 -0
  42. package/dist_ts/readers/tar.d.ts +85 -0
  43. package/dist_ts/readers/tar.js +731 -0
  44. package/dist_ts/readers/text.d.ts +16 -0
  45. package/dist_ts/readers/text.js +96 -0
  46. package/dist_ts/rpm/builder.d.ts +28 -0
  47. package/dist_ts/rpm/builder.js +208 -0
  48. package/dist_ts/rpm/header.d.ts +138 -0
  49. package/dist_ts/rpm/header.js +546 -0
  50. package/dist_ts/rpm/reader.d.ts +20 -0
  51. package/dist_ts/rpm/reader.js +306 -0
  52. package/dist_ts/rpm/repoconfig.d.ts +15 -0
  53. package/dist_ts/rpm/repoconfig.js +38 -0
  54. package/dist_ts/rpm/repodata.d.ts +44 -0
  55. package/dist_ts/rpm/repodata.js +148 -0
  56. package/dist_ts/rpm/sign.d.ts +30 -0
  57. package/dist_ts/rpm/sign.js +183 -0
  58. package/dist_ts/rpm/updates.d.ts +38 -0
  59. package/dist_ts/rpm/updates.js +265 -0
  60. package/dist_ts/rpm/xml.d.ts +18 -0
  61. package/dist_ts/rpm/xml.js +90 -0
  62. package/dist_ts/shared/architecture.d.ts +8 -0
  63. package/dist_ts/shared/architecture.js +17 -0
  64. package/dist_ts/shared/errors.d.ts +38 -0
  65. package/dist_ts/shared/errors.js +22 -0
  66. package/dist_ts/shared/gopath.d.ts +13 -0
  67. package/dist_ts/shared/gopath.js +53 -0
  68. package/dist_ts/shared/gostrings.d.ts +14 -0
  69. package/dist_ts/shared/gostrings.js +29 -0
  70. package/dist_ts/shared/limits.d.ts +47 -0
  71. package/dist_ts/shared/limits.js +57 -0
  72. package/dist_ts/shared/types.d.ts +213 -0
  73. package/dist_ts/shared/types.js +13 -0
  74. package/dist_ts/shared/url.d.ts +18 -0
  75. package/dist_ts/shared/url.js +371 -0
  76. package/dist_ts/shared/validation.d.ts +21 -0
  77. package/dist_ts/shared/validation.js +58 -0
  78. package/dist_ts/signing/keys.d.ts +36 -0
  79. package/dist_ts/signing/keys.js +89 -0
  80. package/dist_ts/signing/openpgpframing.d.ts +33 -0
  81. package/dist_ts/signing/openpgpframing.js +93 -0
  82. package/dist_ts/signing/signers.d.ts +63 -0
  83. package/dist_ts/signing/signers.js +248 -0
  84. package/dist_ts/writers/gotar.d.ts +43 -0
  85. package/dist_ts/writers/gotar.js +218 -0
  86. package/license.md +19 -0
  87. package/package.json +56 -3
  88. package/readme.md +176 -0
  89. package/ts/00_commitinfo_data.ts +8 -0
  90. package/ts/alpine/apkindex.ts +241 -0
  91. package/ts/alpine/pkginfo.ts +183 -0
  92. package/ts/alpine/reader.ts +96 -0
  93. package/ts/arch/builder.ts +283 -0
  94. package/ts/arch/reader.ts +307 -0
  95. package/ts/arch/signer.ts +70 -0
  96. package/ts/arch/vercmp.ts +188 -0
  97. package/ts/debian/control.ts +150 -0
  98. package/ts/debian/gostring.ts +150 -0
  99. package/ts/debian/indexbuilder.ts +355 -0
  100. package/ts/debian/mailaddress.ts +754 -0
  101. package/ts/debian/reader.ts +126 -0
  102. package/ts/index.ts +46 -0
  103. package/ts/plugins.ts +13 -0
  104. package/ts/readers/ar.ts +102 -0
  105. package/ts/readers/bytes.ts +182 -0
  106. package/ts/readers/bytesource.ts +164 -0
  107. package/ts/readers/decompress.ts +332 -0
  108. package/ts/readers/gzipmember.ts +209 -0
  109. package/ts/readers/tar.ts +835 -0
  110. package/ts/readers/text.ts +91 -0
  111. package/ts/rpm/builder.ts +253 -0
  112. package/ts/rpm/header.ts +628 -0
  113. package/ts/rpm/reader.ts +317 -0
  114. package/ts/rpm/repoconfig.ts +45 -0
  115. package/ts/rpm/repodata.ts +219 -0
  116. package/ts/rpm/sign.ts +200 -0
  117. package/ts/rpm/updates.ts +314 -0
  118. package/ts/rpm/xml.ts +101 -0
  119. package/ts/shared/architecture.ts +16 -0
  120. package/ts/shared/errors.ts +78 -0
  121. package/ts/shared/gopath.ts +54 -0
  122. package/ts/shared/gostrings.ts +31 -0
  123. package/ts/shared/limits.ts +93 -0
  124. package/ts/shared/types.ts +251 -0
  125. package/ts/shared/url.ts +387 -0
  126. package/ts/shared/validation.ts +71 -0
  127. package/ts/signing/keys.ts +110 -0
  128. package/ts/signing/openpgpframing.ts +115 -0
  129. package/ts/signing/signers.ts +315 -0
  130. package/ts/writers/gotar.ts +256 -0
  131. package/README.md +0 -3
@@ -0,0 +1,154 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { LinuxRepoError, limitExceeded } from '../shared/errors.js';
3
+ import { takeFront } from './bytes.js';
4
+ /**
5
+ * The digest tee: pulls the caller's package bytes once, counts them against
6
+ * `maxPackageBytes`, and feeds every byte exactly once into MD5, SHA-1,
7
+ * SHA-256 and SHA-512 at the moment it is pulled.
8
+ *
9
+ * - It pulls with `next()` only. It never calls `return()` or `throw()` on the
10
+ * caller's iterator, so a web `ReadableStream` is never cancelled.
11
+ * - An error from the caller's iterator propagates unchanged. After any error
12
+ * the source stops pulling for good.
13
+ * - `drain()` reads the rest of the input so the digests cover the whole file;
14
+ * `digests()` is available only after the input has ended.
15
+ */
16
+ export class PackageByteSource {
17
+ source;
18
+ maxPackageBytes;
19
+ iterator = null;
20
+ pushedBack = [];
21
+ hashes = {
22
+ md5: plugins.crypto.createHash('md5'),
23
+ sha1: plugins.crypto.createHash('sha1'),
24
+ sha256: plugins.crypto.createHash('sha256'),
25
+ sha512: plugins.crypto.createHash('sha512'),
26
+ };
27
+ pulledBytes = 0;
28
+ deliveredBytes = 0;
29
+ ended = false;
30
+ failure = undefined;
31
+ failed = false;
32
+ finalDigests = null;
33
+ constructor(sourceArg, maxPackageBytesArg) {
34
+ if (sourceArg === null ||
35
+ typeof sourceArg !== 'object' ||
36
+ typeof sourceArg[Symbol.asyncIterator] !== 'function') {
37
+ throw new LinuxRepoError('invalid-input', 'source must be an AsyncIterable<Uint8Array>', {
38
+ field: 'source',
39
+ });
40
+ }
41
+ this.source = sourceArg;
42
+ this.maxPackageBytes = maxPackageBytesArg;
43
+ }
44
+ /** Offset of the next byte `read` returns, counted from the start of the file. */
45
+ get position() {
46
+ return this.deliveredBytes;
47
+ }
48
+ /** Bytes pulled from the caller so far. */
49
+ get pulled() {
50
+ return this.pulledBytes;
51
+ }
52
+ async read(maxArg) {
53
+ const pushed = this.pushedBack.pop();
54
+ if (pushed !== undefined) {
55
+ const chunk = takeFront(pushed, maxArg, this.pushedBack);
56
+ this.deliveredBytes += chunk.length;
57
+ return chunk;
58
+ }
59
+ const pulled = await this.pull();
60
+ if (pulled === null) {
61
+ return null;
62
+ }
63
+ const chunk = takeFront(pulled, maxArg, this.pushedBack);
64
+ this.deliveredBytes += chunk.length;
65
+ return chunk;
66
+ }
67
+ unread(bytesArg) {
68
+ if (bytesArg.length === 0) {
69
+ return;
70
+ }
71
+ this.pushedBack.push(bytesArg);
72
+ this.deliveredBytes -= bytesArg.length;
73
+ }
74
+ /** Reads and discards the rest of the input. */
75
+ async drain() {
76
+ this.deliveredBytes += this.pushedBack.reduce((sum, chunk) => sum + chunk.length, 0);
77
+ this.pushedBack.length = 0;
78
+ while ((await this.pull()) !== null) {
79
+ // every pulled chunk is hashed and counted inside pull()
80
+ }
81
+ this.deliveredBytes = this.pulledBytes;
82
+ }
83
+ /** Size and digests of the whole input; only after the input has ended. */
84
+ digests() {
85
+ if (!this.ended || this.failed) {
86
+ throw new Error('PackageByteSource.digests() called before the input ended');
87
+ }
88
+ if (this.finalDigests === null) {
89
+ this.finalDigests = {
90
+ size: this.pulledBytes,
91
+ md5: this.hashes.md5.digest('hex'),
92
+ sha1: this.hashes.sha1.digest('hex'),
93
+ sha256: this.hashes.sha256.digest('hex'),
94
+ sha512: this.hashes.sha512.digest('hex'),
95
+ };
96
+ }
97
+ return { ...this.finalDigests };
98
+ }
99
+ async pull() {
100
+ if (this.failed) {
101
+ throw this.failure;
102
+ }
103
+ if (this.ended) {
104
+ return null;
105
+ }
106
+ try {
107
+ this.iterator ??= this.source[Symbol.asyncIterator]();
108
+ for (;;) {
109
+ let result;
110
+ try {
111
+ result = await this.iterator.next();
112
+ }
113
+ catch (error) {
114
+ // the caller's error, unchanged
115
+ this.fail(error);
116
+ throw error;
117
+ }
118
+ if (result.done) {
119
+ this.ended = true;
120
+ return null;
121
+ }
122
+ const value = result.value;
123
+ if (!(value instanceof Uint8Array)) {
124
+ throw new LinuxRepoError('invalid-input', 'source yielded a chunk that is not a Uint8Array', {
125
+ field: 'source',
126
+ });
127
+ }
128
+ if (value.length === 0) {
129
+ continue;
130
+ }
131
+ if (this.pulledBytes + value.length > this.maxPackageBytes) {
132
+ throw limitExceeded('maxPackageBytes', this.maxPackageBytes, 'package input');
133
+ }
134
+ this.pulledBytes += value.length;
135
+ this.hashes.md5.update(value);
136
+ this.hashes.sha1.update(value);
137
+ this.hashes.sha256.update(value);
138
+ this.hashes.sha512.update(value);
139
+ return value;
140
+ }
141
+ }
142
+ catch (error) {
143
+ this.fail(error);
144
+ throw error;
145
+ }
146
+ }
147
+ fail(errorArg) {
148
+ if (!this.failed) {
149
+ this.failed = true;
150
+ this.failure = errorArg;
151
+ }
152
+ }
153
+ }
154
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnl0ZXNvdXJjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3JlYWRlcnMvYnl0ZXNvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRXBFLE9BQU8sRUFBRSxTQUFTLEVBQW9CLE1BQU0sWUFBWSxDQUFDO0FBRXpEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQUNYLE1BQU0sQ0FBNEI7SUFDbEMsZUFBZSxDQUFTO0lBQ2pDLFFBQVEsR0FBcUMsSUFBSSxDQUFDO0lBQ3pDLFVBQVUsR0FBaUIsRUFBRSxDQUFDO0lBQzlCLE1BQU0sR0FBRztRQUN4QixHQUFHLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBQ3JDLElBQUksRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7UUFDdkMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQztRQUMzQyxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDO0tBQzVDLENBQUM7SUFDTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO0lBQ2hCLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFDbkIsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUNkLE9BQU8sR0FBWSxTQUFTLENBQUM7SUFDN0IsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUNmLFlBQVksR0FBZ0MsSUFBSSxDQUFDO0lBRXpELFlBQVksU0FBb0MsRUFBRSxrQkFBMEI7UUFDMUUsSUFDRSxTQUFTLEtBQUssSUFBSTtZQUNsQixPQUFPLFNBQVMsS0FBSyxRQUFRO1lBQzdCLE9BQVEsU0FBZ0QsQ0FBQyxNQUFNLENBQUMsYUFB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
@@ -0,0 +1,43 @@
1
+ import type { ILinuxPackageLimits } from '../shared/limits.js';
2
+ import { type IByteReader } from './bytes.js';
3
+ /** The stream compressions the readers decode. */
4
+ export type TLinuxCompression = 'none' | 'gzip' | 'xz' | 'zstd';
5
+ export interface IDecompressOptions {
6
+ /** Bound on the decompressed bytes delivered. */
7
+ maxOutputBytes: number;
8
+ outputLimit: keyof ILinuxPackageLimits;
9
+ }
10
+ /**
11
+ * A reader over the decompressed bytes of an inner reader. Pulling is lazy
12
+ * and bounded: decompressed output past `maxOutputBytes` fails with
13
+ * `limit-exceeded` and stops the decoder. `close()` releases the decoder and
14
+ * must be called (see `withDecompressingReader`).
15
+ *
16
+ * - gzip (multi-member) and zstd come from `node:zlib`, xz from
17
+ * `@napi-rs/lzma` `xz.decompressStream` (64 KiB chunks, cancellable).
18
+ * - An error from the inner reader (the caller's source, or a codec limit on
19
+ * it) propagates unchanged.
20
+ * - A compressed stream that ends early is `truncated`; corrupt data is
21
+ * `malformed-archive` with the decoder error as `cause`.
22
+ * - The decoder reads the inner reader ahead and never hands bytes back, so
23
+ * the compressed stream must run to the end of the inner reader (a whole
24
+ * package, or a `LimitedReader` over one archive member).
25
+ * - Opening a zstd decoder on a Node.js without nodejs/node#64593 throws a
26
+ * plain `Error` (see `isZstdDecodingSafe`): a server fault, not a verdict
27
+ * on the package.
28
+ */
29
+ export interface IDecompressingReader extends IByteReader {
30
+ readonly outputBytes: number;
31
+ close(): Promise<void>;
32
+ }
33
+ export declare function openDecompressingReader(inputArg: IByteReader, compressionArg: TLinuxCompression, optionsArg: IDecompressOptions): IDecompressingReader;
34
+ /**
35
+ * True when Node.js `versionArg` (a `process.versions.node` string) carries
36
+ * nodejs/node#64593, so node:zlib reports a zstd frame that ends early as
37
+ * `Z_BUF_ERROR` instead of returning a prefix: 24.x from 24.20.0, 26.x from
38
+ * 26.6.0, and every major from 27 on. Anything else, including all of 22.x,
39
+ * 23.x and 25.x, is false.
40
+ */
41
+ export declare function isZstdDecodingSafe(versionArg: string): boolean;
42
+ /** Runs `bodyArg` with a decompressing reader and always closes it. */
43
+ export declare function withDecompressingReader<T>(inputArg: IByteReader, compressionArg: TLinuxCompression, optionsArg: IDecompressOptions, bodyArg: (readerArg: IDecompressingReader) => Promise<T>): Promise<T>;
@@ -0,0 +1,269 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { LinuxRepoError, limitExceeded, truncated } from '../shared/errors.js';
3
+ import { READ_CHUNK_BYTES, takeFront } from './bytes.js';
4
+ export function openDecompressingReader(inputArg, compressionArg, optionsArg) {
5
+ let source;
6
+ switch (compressionArg) {
7
+ case 'none':
8
+ source = new PassThroughSource(inputArg);
9
+ break;
10
+ case 'gzip':
11
+ source = new ZlibSource(inputArg, 'gzip');
12
+ break;
13
+ case 'zstd':
14
+ if (!isZstdDecodingSafe(process.versions.node)) {
15
+ throw new Error(`zstd decoding needs Node.js ${ZSTD_NODE_FLOOR} (nodejs/node#64593 reports a zstd frame that ends early); ` +
16
+ `this process runs Node.js ${process.versions.node}`);
17
+ }
18
+ source = new ZlibSource(inputArg, 'zstd');
19
+ break;
20
+ case 'xz':
21
+ source = new XzSource(inputArg);
22
+ break;
23
+ default:
24
+ throw new LinuxRepoError('unsupported-compression', `unknown compression "${String(compressionArg)}"`, {
25
+ field: 'compression',
26
+ });
27
+ }
28
+ return new BoundedOutputReader(source, optionsArg);
29
+ }
30
+ /** The Node.js releases whose node:zlib reports a truncated zstd frame. */
31
+ const ZSTD_NODE_FLOOR = '^24.20.0 || >=26.6.0';
32
+ /**
33
+ * True when Node.js `versionArg` (a `process.versions.node` string) carries
34
+ * nodejs/node#64593, so node:zlib reports a zstd frame that ends early as
35
+ * `Z_BUF_ERROR` instead of returning a prefix: 24.x from 24.20.0, 26.x from
36
+ * 26.6.0, and every major from 27 on. Anything else, including all of 22.x,
37
+ * 23.x and 25.x, is false.
38
+ */
39
+ export function isZstdDecodingSafe(versionArg) {
40
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:$|[-+])/.exec(versionArg);
41
+ if (match === null) {
42
+ return false;
43
+ }
44
+ const major = Number(match[1]);
45
+ const minor = Number(match[2]);
46
+ if (major === 24) {
47
+ return minor >= 20;
48
+ }
49
+ if (major === 26) {
50
+ return minor >= 6;
51
+ }
52
+ return major >= 27;
53
+ }
54
+ /** Runs `bodyArg` with a decompressing reader and always closes it. */
55
+ export async function withDecompressingReader(inputArg, compressionArg, optionsArg, bodyArg) {
56
+ const reader = openDecompressingReader(inputArg, compressionArg, optionsArg);
57
+ try {
58
+ return await bodyArg(reader);
59
+ }
60
+ finally {
61
+ await reader.close();
62
+ }
63
+ }
64
+ class BoundedOutputReader {
65
+ source;
66
+ options;
67
+ delivered = 0;
68
+ pushedBack = [];
69
+ closed = false;
70
+ constructor(source, options) {
71
+ this.source = source;
72
+ this.options = options;
73
+ }
74
+ get outputBytes() {
75
+ return this.delivered;
76
+ }
77
+ async read(maxArg) {
78
+ const pushed = this.pushedBack.pop();
79
+ if (pushed !== undefined) {
80
+ return takeFront(pushed, maxArg, this.pushedBack);
81
+ }
82
+ if (this.closed) {
83
+ return null;
84
+ }
85
+ const chunk = await this.source.next();
86
+ if (chunk === null) {
87
+ return null;
88
+ }
89
+ this.delivered += chunk.length;
90
+ if (this.delivered > this.options.maxOutputBytes) {
91
+ await this.close();
92
+ throw limitExceeded(this.options.outputLimit, this.options.maxOutputBytes, 'decompressed data');
93
+ }
94
+ return takeFront(chunk, maxArg, this.pushedBack);
95
+ }
96
+ unread(bytesArg) {
97
+ if (bytesArg.length > 0) {
98
+ this.pushedBack.push(bytesArg);
99
+ }
100
+ }
101
+ async close() {
102
+ this.pushedBack.length = 0;
103
+ if (this.closed) {
104
+ return;
105
+ }
106
+ this.closed = true;
107
+ await this.source.close();
108
+ }
109
+ }
110
+ class PassThroughSource {
111
+ input;
112
+ constructor(input) {
113
+ this.input = input;
114
+ }
115
+ next() {
116
+ return this.input.read(READ_CHUNK_BYTES);
117
+ }
118
+ async close() { }
119
+ }
120
+ /** gzip (multi-member, like Go's default) and zstd through `node:zlib`, with stream backpressure. */
121
+ class ZlibSource {
122
+ kind;
123
+ feeder;
124
+ decoder;
125
+ iterator;
126
+ inputFailed = false;
127
+ inputError = undefined;
128
+ finished = false;
129
+ constructor(inputArg, kindArg) {
130
+ this.kind = kindArg;
131
+ const pump = async function* () {
132
+ for (;;) {
133
+ let chunk;
134
+ try {
135
+ chunk = await inputArg.read(READ_CHUNK_BYTES);
136
+ }
137
+ catch (error) {
138
+ this.inputFailed = true;
139
+ this.inputError = error;
140
+ throw error;
141
+ }
142
+ if (chunk === null) {
143
+ return;
144
+ }
145
+ yield chunk;
146
+ }
147
+ };
148
+ this.feeder = plugins.stream.Readable.from(pump.call(this), { objectMode: false });
149
+ this.decoder = kindArg === 'gzip' ? plugins.zlib.createGunzip() : plugins.zlib.createZstdDecompress();
150
+ // errors surface through the iterator below; the callback only completes the pipeline
151
+ plugins.stream.pipeline(this.feeder, this.decoder, () => { });
152
+ this.iterator = this.decoder[Symbol.asyncIterator]();
153
+ }
154
+ async next() {
155
+ if (this.finished) {
156
+ return null;
157
+ }
158
+ try {
159
+ const result = await this.iterator.next();
160
+ if (result.done) {
161
+ this.finished = true;
162
+ return null;
163
+ }
164
+ return result.value;
165
+ }
166
+ catch (error) {
167
+ this.finished = true;
168
+ if (this.inputFailed) {
169
+ throw this.inputError;
170
+ }
171
+ throw mapZlibError(error, this.kind);
172
+ }
173
+ }
174
+ async close() {
175
+ this.finished = true;
176
+ this.feeder.destroy();
177
+ this.decoder.destroy();
178
+ }
179
+ }
180
+ function mapZlibError(errorArg, kindArg) {
181
+ const code = errorArg?.code;
182
+ // gunzip, and zstd on the Node.js floor, report an input that ended inside the stream as Z_BUF_ERROR
183
+ if (code === 'Z_BUF_ERROR') {
184
+ const error = truncated(`${kindArg} stream`);
185
+ return new LinuxRepoError(error.code, error.message, error.detail, { cause: errorArg });
186
+ }
187
+ return new LinuxRepoError('malformed-archive', `corrupt ${kindArg} data`, { field: `${kindArg} stream` }, {
188
+ cause: errorArg,
189
+ });
190
+ }
191
+ /**
192
+ * xz through `@napi-rs/lzma` `xz.decompressStream`, the one bounded decoder of
193
+ * that package (its class API buffers whole outputs). The input is a
194
+ * pull-based web stream that never reads ahead; cancelling the output stops it.
195
+ */
196
+ class XzSource {
197
+ reader;
198
+ inputFailed = false;
199
+ inputError = undefined;
200
+ inputEnded = false;
201
+ finished = false;
202
+ stopped = false;
203
+ constructor(inputArg) {
204
+ const input = new ReadableStream({
205
+ pull: async (controller) => {
206
+ if (this.stopped) {
207
+ controller.close();
208
+ return;
209
+ }
210
+ let chunk;
211
+ try {
212
+ chunk = await inputArg.read(READ_CHUNK_BYTES);
213
+ }
214
+ catch (error) {
215
+ this.inputFailed = true;
216
+ this.inputError = error;
217
+ controller.error(error);
218
+ return;
219
+ }
220
+ if (chunk === null) {
221
+ this.inputEnded = true;
222
+ controller.close();
223
+ }
224
+ else {
225
+ controller.enqueue(chunk);
226
+ }
227
+ },
228
+ cancel: () => {
229
+ this.stopped = true;
230
+ },
231
+ }, { highWaterMark: 0 });
232
+ this.reader = plugins.lzma.xz.decompressStream(input).getReader();
233
+ }
234
+ async next() {
235
+ if (this.finished) {
236
+ return null;
237
+ }
238
+ try {
239
+ const result = await this.reader.read();
240
+ if (result.done) {
241
+ this.finished = true;
242
+ return null;
243
+ }
244
+ return result.value;
245
+ }
246
+ catch (error) {
247
+ this.finished = true;
248
+ if (this.inputFailed) {
249
+ throw this.inputError;
250
+ }
251
+ // @napi-rs/lzma 1.5.3 reports a decoder that ran out of input as Rust's
252
+ // read_exact error; with the input at its end that is a truncated stream
253
+ const message = error instanceof Error ? error.message : '';
254
+ if (this.inputEnded && message.includes('failed to fill whole buffer')) {
255
+ const base = truncated('xz stream');
256
+ throw new LinuxRepoError(base.code, base.message, base.detail, { cause: error });
257
+ }
258
+ throw new LinuxRepoError('malformed-archive', 'corrupt xz data', { field: 'xz stream' }, { cause: error });
259
+ }
260
+ }
261
+ async close() {
262
+ this.stopped = true;
263
+ if (!this.finished) {
264
+ this.finished = true;
265
+ await this.reader.cancel();
266
+ }
267
+ }
268
+ }
269
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb21wcmVzcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3JlYWRlcnMvZGVjb21wcmVzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUUvRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsU0FBUyxFQUFvQixNQUFNLFlBQVksQ0FBQztBQXdDM0UsTUFBTSxVQUFVLHVCQUF1QixDQUNyQyxRQUFxQixFQUNyQixjQUFpQyxFQUNqQyxVQUE4QjtJQUU5QixJQUFJLE1BQW9CLENBQUM7SUFDekIsUUFBUSxjQUFjLEVBQUUsQ0FBQztRQUN2QixLQUFLLE1BQU07WUFDVCxNQUFNLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN6QyxNQUFNO1FBQ1IsS0FBSyxNQUFNO1lBQ1QsTUFBTSxHQUFHLElBQUksVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUMxQyxNQUFNO1FBQ1IsS0FBSyxNQUFNO1lBQ1QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDL0MsTUFBTSxJQUFJLEtBQUssQ0FDYiwrQkFBK0IsZUFBZSw2REFBNkQ7b0JBQ3pHLDZCQUE2QixPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUN2RCxDQUFDO1lBQ0osQ0FBQztZQUNELE1BQU0sR0FBRyxJQUFJLFVBQVUsQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDMUMsTUFBTTtRQUNSLEtBQUssSUFBSTtZQUNQLE1BQU0sR0FBRyxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNoQyxNQUFNO1FBQ1I7WUFDRSxNQUFNLElBQUksY0FBYyxDQUFDLHlCQUF5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
@@ -0,0 +1,32 @@
1
+ import type { ILinuxPackageLimits } from '../shared/limits.js';
2
+ import { type IByteReader } from './bytes.js';
3
+ export interface IGzipMemberOptions {
4
+ /** Bound on the member's own bytes (header, deflate data and trailer). */
5
+ maxMemberBytes: number;
6
+ memberLimit: keyof ILinuxPackageLimits;
7
+ /** Bound on the member's decompressed bytes. */
8
+ maxOutputBytes: number;
9
+ outputLimit: keyof ILinuxPackageLimits;
10
+ /** Bound on the header's FNAME and FCOMMENT strings. */
11
+ maxHeaderBytes: number;
12
+ }
13
+ export interface IGzipMember {
14
+ /** The decompressed member. */
15
+ output: Uint8Array;
16
+ /** The member's own byte count: header, deflate data and trailer. */
17
+ memberBytes: number;
18
+ /** Lowercase hex SHA-1 of exactly the member's bytes. */
19
+ memberSha1: string;
20
+ }
21
+ /**
22
+ * Reads exactly one gzip member (RFC 1952) from `inputArg` and leaves the
23
+ * reader positioned at the first byte after it, so concatenated members (an
24
+ * apk v2 package) can be read one at a time with their exact boundaries.
25
+ *
26
+ * The header is parsed here; the deflate data is inflated with
27
+ * `zlib.createInflateRaw()`, whose `bytesWritten` counts only the bytes the
28
+ * deflate stream consumed, and the bytes past the stream's end are pushed back
29
+ * with `unread`. The trailer's CRC-32 and ISIZE are checked. Returns `null`
30
+ * when the input ends exactly where a member would start.
31
+ */
32
+ export declare function readGzipMember(inputArg: IByteReader, optionsArg: IGzipMemberOptions): Promise<IGzipMember | null>;