@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,17 @@
1
+ /**
2
+ * Whether an architecture can name an index path segment. Readers record any
3
+ * architecture a package states (Gitea accepts them); builders refuse an entry
4
+ * whose architecture fails this rule with `invalid-input`, and never skip it
5
+ * silently. Refused: the empty string, `.` and `..`, and any value containing
6
+ * `/`, whitespace or a control character.
7
+ */
8
+ export function isIndexableArchitecture(architectureArg) {
9
+ if (typeof architectureArg !== 'string') {
10
+ return false;
11
+ }
12
+ if (architectureArg === '' || architectureArg === '.' || architectureArg === '..') {
13
+ return false;
14
+ }
15
+ return !/[/\s\p{Cc}]/u.test(architectureArg);
16
+ }
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJjaGl0ZWN0dXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc2hhcmVkL2FyY2hpdGVjdHVyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsdUJBQXVCLENBQUMsZUFBdUI7SUFDN0QsSUFBSSxPQUFPLGVBQWUsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUN4QyxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxJQUFJLGVBQWUsS0FBSyxFQUFFLElBQUksZUFBZSxLQUFLLEdBQUcsSUFBSSxlQUFlLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDbEYsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBQ0QsT0FBTyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7QUFDL0MsQ0FBQyJ9
@@ -0,0 +1,38 @@
1
+ import type { ILinuxPackageLimits } from './limits.js';
2
+ /**
3
+ * Stable error codes.
4
+ * - `limit-exceeded`: an `ILinuxPackageLimits` bound was crossed (`detail.limit` names it).
5
+ * - `unsupported-compression`: a compression the format does not allow.
6
+ * - `malformed-archive`: broken container structure (ar, tar, gzip, xz, zstd framing or data).
7
+ * - `malformed-header`: a broken package header (RPM lead and headers).
8
+ * - `missing-field` / `invalid-field`: package metadata that is absent or not acceptable.
9
+ * - `unsupported-package-format`: input that is not the expected package format, or uses a form of it
10
+ * the codec does not read (the data of a sparse tar entry).
11
+ * - `truncated`: only a clean early end of input.
12
+ * - `digest-mismatch`: a digest the package carries does not match its bytes.
13
+ * - `invalid-input`: a bad argument from the caller.
14
+ * - `invalid-key`: a key the codec cannot use.
15
+ * - `signing-failed`: a codec signer failed, or a signer returned something that is not signature bytes.
16
+ *
17
+ * The codec never wraps an error it did not raise: an error from the caller's
18
+ * source or from a caller-supplied signer propagates unchanged. An underlying
19
+ * error the codec reacts to is kept in the standard `cause`.
20
+ */
21
+ export type TLinuxRepoErrorCode = 'limit-exceeded' | 'unsupported-compression' | 'malformed-archive' | 'malformed-header' | 'missing-field' | 'invalid-field' | 'unsupported-package-format' | 'truncated' | 'digest-mismatch' | 'invalid-input' | 'invalid-key' | 'signing-failed';
22
+ /** Names the field, structure or limit an error is about. */
23
+ export interface ILinuxRepoErrorDetail {
24
+ field?: string;
25
+ limit?: keyof ILinuxPackageLimits;
26
+ value?: number | string;
27
+ }
28
+ export declare class LinuxRepoError extends Error {
29
+ readonly code: TLinuxRepoErrorCode;
30
+ readonly detail: Readonly<ILinuxRepoErrorDetail>;
31
+ constructor(codeArg: TLinuxRepoErrorCode, messageArg: string, detailArg?: ILinuxRepoErrorDetail, optionsArg?: {
32
+ cause?: unknown;
33
+ });
34
+ }
35
+ /** Builds the `limit-exceeded` error for one limit. */
36
+ export declare function limitExceeded(limitArg: keyof ILinuxPackageLimits, maximumArg: number, whatArg: string): LinuxRepoError;
37
+ /** Builds the `truncated` error for a structure the input ended inside. */
38
+ export declare function truncated(whatArg: string): LinuxRepoError;
@@ -0,0 +1,22 @@
1
+ export class LinuxRepoError extends Error {
2
+ code;
3
+ detail;
4
+ constructor(codeArg, messageArg, detailArg = {}, optionsArg) {
5
+ super(messageArg, optionsArg !== undefined && 'cause' in optionsArg ? { cause: optionsArg.cause } : undefined);
6
+ this.name = 'LinuxRepoError';
7
+ this.code = codeArg;
8
+ this.detail = Object.freeze({ ...detailArg });
9
+ }
10
+ }
11
+ /** Builds the `limit-exceeded` error for one limit. */
12
+ export function limitExceeded(limitArg, maximumArg, whatArg) {
13
+ return new LinuxRepoError('limit-exceeded', `${whatArg} exceeds ${limitArg} (${maximumArg})`, {
14
+ limit: limitArg,
15
+ value: maximumArg,
16
+ });
17
+ }
18
+ /** Builds the `truncated` error for a structure the input ended inside. */
19
+ export function truncated(whatArg) {
20
+ return new LinuxRepoError('truncated', `input ended inside ${whatArg}`, { field: whatArg });
21
+ }
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc2hhcmVkL2Vycm9ycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUEwQ0EsTUFBTSxPQUFPLGNBQWUsU0FBUSxLQUFLO0lBQ3ZCLElBQUksQ0FBc0I7SUFDMUIsTUFBTSxDQUFrQztJQUV4RCxZQUNFLE9BQTRCLEVBQzVCLFVBQWtCLEVBQ2xCLFNBQVMsR0FBMEIsRUFBRSxFQUNyQyxVQUFnQztRQUVoQyxLQUFLLENBQ0gsVUFBVSxFQUNWLFVBQVUsS0FBSyxTQUFTLElBQUksT0FBTyxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQzVGLENBQUM7UUFDRixJQUFJLENBQUMsSUFBSSxHQUFHLGdCQUFnQixDQUFDO1FBQzdCLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEdBQUcsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUNoRCxDQUFDO0NBQ0Y7QUFFRCx1REFBdUQ7QUFDdkQsTUFBTSxVQUFVLGFBQWEsQ0FDM0IsUUFBbUMsRUFDbkMsVUFBa0IsRUFDbEIsT0FBZTtJQUVmLE9BQU8sSUFBSSxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsR0FBRyxPQUFPLFlBQVksUUFBUSxLQUFLLFVBQVUsR0FBRyxFQUFFO1FBQzVGLEtBQUssRUFBRSxRQUFRO1FBQ2YsS0FBSyxFQUFFLFVBQVU7S0FDbEIsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELDJFQUEyRTtBQUMzRSxNQUFNLFVBQVUsU0FBUyxDQUFDLE9BQWU7SUFDdkMsT0FBTyxJQUFJLGNBQWMsQ0FBQyxXQUFXLEVBQUUsc0JBQXNCLE9BQU8sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7QUFDOUYsQ0FBQyJ9
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Go 1.27 `path` semantics (slash-separated paths) the codec mirrors where
3
+ * Gitea 28.2.0 output depends on them.
4
+ */
5
+ /** Go `path.Clean` (`src/path/path.go:72`). */
6
+ export declare function goPathClean(pathArg: string): string;
7
+ /**
8
+ * Go `path.Join` (`src/path/path.go:155`): empty elements are ignored, the
9
+ * result is cleaned, and all-empty input gives `''`.
10
+ */
11
+ export declare function goPathJoin(elementsArg: string[]): string;
12
+ /** Go `path.Base` (`src/path/path.go:192`). */
13
+ export declare function goPathBase(pathArg: string): string;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Go 1.27 `path` semantics (slash-separated paths) the codec mirrors where
3
+ * Gitea 28.2.0 output depends on them.
4
+ */
5
+ /** Go `path.Clean` (`src/path/path.go:72`). */
6
+ export function goPathClean(pathArg) {
7
+ if (pathArg === '') {
8
+ return '.';
9
+ }
10
+ const rooted = pathArg.startsWith('/');
11
+ const parts = [];
12
+ for (const element of pathArg.split('/')) {
13
+ if (element === '' || element === '.') {
14
+ continue;
15
+ }
16
+ if (element === '..') {
17
+ if (parts.length > 0 && parts[parts.length - 1] !== '..') {
18
+ parts.pop();
19
+ }
20
+ else if (!rooted) {
21
+ parts.push('..');
22
+ }
23
+ continue;
24
+ }
25
+ parts.push(element);
26
+ }
27
+ const joined = parts.join('/');
28
+ if (rooted) {
29
+ return `/${joined}`;
30
+ }
31
+ return joined === '' ? '.' : joined;
32
+ }
33
+ /**
34
+ * Go `path.Join` (`src/path/path.go:155`): empty elements are ignored, the
35
+ * result is cleaned, and all-empty input gives `''`.
36
+ */
37
+ export function goPathJoin(elementsArg) {
38
+ const joined = elementsArg.filter((element) => element !== '').join('/');
39
+ return joined === '' ? '' : goPathClean(joined);
40
+ }
41
+ /** Go `path.Base` (`src/path/path.go:192`). */
42
+ export function goPathBase(pathArg) {
43
+ if (pathArg === '') {
44
+ return '.';
45
+ }
46
+ let path = pathArg.replace(/\/+$/, '');
47
+ const slash = path.lastIndexOf('/');
48
+ if (slash >= 0) {
49
+ path = path.slice(slash + 1);
50
+ }
51
+ return path === '' ? '/' : path;
52
+ }
53
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ29wYXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc2hhcmVkL2dvcGF0aC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCwrQ0FBK0M7QUFDL0MsTUFBTSxVQUFVLFdBQVcsQ0FBQyxPQUFlO0lBQ3pDLElBQUksT0FBTyxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ25CLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUNELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkMsTUFBTSxLQUFLLEdBQWEsRUFBRSxDQUFDO0lBQzNCLEtBQUssTUFBTSxPQUFPLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3pDLElBQUksT0FBTyxLQUFLLEVBQUUsSUFBSSxPQUFPLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDdEMsU0FBUztRQUNYLENBQUM7UUFDRCxJQUFJLE9BQU8sS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUNyQixJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUN6RCxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDZCxDQUFDO2lCQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDbkIsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNuQixDQUFDO1lBQ0QsU0FBUztRQUNYLENBQUM7UUFDRCxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLElBQUksTUFBTSxFQUFFLENBQUM7UUFDWCxPQUFPLElBQUksTUFBTSxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUNELE9BQU8sTUFBTSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7QUFDdEMsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxVQUFVLENBQUMsV0FBcUI7SUFDOUMsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN6RSxPQUFPLE1BQU0sS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2xELENBQUM7QUFFRCwrQ0FBK0M7QUFDL0MsTUFBTSxVQUFVLFVBQVUsQ0FBQyxPQUFlO0lBQ3hDLElBQUksT0FBTyxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ25CLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUNELElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDcEMsSUFBSSxLQUFLLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDZixJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUNELE9BQU8sSUFBSSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDbEMsQ0FBQyJ9
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Go standard-library string semantics the Arch and Alpine readers mirror, so
3
+ * derived values match Gitea 28.2.0 (`modules/packages/{arch,alpine}/metadata.go`).
4
+ */
5
+ /**
6
+ * Go `strings.TrimSpace`: trims Unicode `White_Space` (Go `unicode.IsSpace`).
7
+ * Unlike `String.prototype.trim` it keeps U+FEFF and trims U+0085.
8
+ */
9
+ export declare function goTrimSpace(valueArg: string): string;
10
+ /**
11
+ * Go `strconv.ParseInt(value, 10, 64)`: an optional sign and ASCII digits,
12
+ * within int64. Returns `null` where Go returns an error.
13
+ */
14
+ export declare function goParseInt64(valueArg: string): bigint | null;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Go standard-library string semantics the Arch and Alpine readers mirror, so
3
+ * derived values match Gitea 28.2.0 (`modules/packages/{arch,alpine}/metadata.go`).
4
+ */
5
+ /**
6
+ * Go `strings.TrimSpace`: trims Unicode `White_Space` (Go `unicode.IsSpace`).
7
+ * Unlike `String.prototype.trim` it keeps U+FEFF and trims U+0085.
8
+ */
9
+ export function goTrimSpace(valueArg) {
10
+ return valueArg.replace(GO_SPACE_START, '').replace(GO_SPACE_END, '');
11
+ }
12
+ const GO_SPACE_CLASS = '[\\t\\n\\v\\f\\r \\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]';
13
+ const GO_SPACE_START = new RegExp(`^${GO_SPACE_CLASS}+`);
14
+ const GO_SPACE_END = new RegExp(`${GO_SPACE_CLASS}+$`);
15
+ /**
16
+ * Go `strconv.ParseInt(value, 10, 64)`: an optional sign and ASCII digits,
17
+ * within int64. Returns `null` where Go returns an error.
18
+ */
19
+ export function goParseInt64(valueArg) {
20
+ if (!/^[+-]?[0-9]+$/.test(valueArg)) {
21
+ return null;
22
+ }
23
+ const value = BigInt(valueArg);
24
+ if (value > 0x7fffffffffffffffn || value < -0x8000000000000000n) {
25
+ return null;
26
+ }
27
+ return value;
28
+ }
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ29zdHJpbmdzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc2hhcmVkL2dvc3RyaW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUFDLFFBQWdCO0lBQzFDLE9BQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQztBQUN4RSxDQUFDO0FBRUQsTUFBTSxjQUFjLEdBQUcsMkZBQTJGLENBQUM7QUFDbkgsTUFBTSxjQUFjLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxjQUFjLEdBQUcsQ0FBQyxDQUFDO0FBQ3pELE1BQU0sWUFBWSxHQUFHLElBQUksTUFBTSxDQUFDLEdBQUcsY0FBYyxJQUFJLENBQUMsQ0FBQztBQUV2RDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsWUFBWSxDQUFDLFFBQWdCO0lBQzNDLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDcEMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQy9CLElBQUksS0FBSyxHQUFHLG1CQUFtQixJQUFJLEtBQUssR0FBRyxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDaEUsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsT0FBTyxLQUFLLENBQUM7QUFDZixDQUFDIn0=
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Hard bounds for reading a package. Callers override them per call with a
3
+ * `Partial`; every value is a positive safe integer. The defaults accept
4
+ * everything a stock Gitea 28.2.0 stores except a deb control member that
5
+ * decompresses past 32 MiB (see `DEFAULT_LINUX_PACKAGE_LIMITS`); an override
6
+ * below a default may refuse packages Gitea accepts.
7
+ */
8
+ export interface ILinuxPackageLimits {
9
+ /** The whole package input, in bytes. */
10
+ maxPackageBytes: number;
11
+ /**
12
+ * One buffered metadata unit, in bytes: the apk control gzip member, the deb
13
+ * control member, or the RPM signature header plus main header.
14
+ */
15
+ maxMetadataBytes: number;
16
+ /** The decompressed deb `control.tar`, the apk control tar, or Arch's `.PKGINFO`, in bytes. */
17
+ maxDecompressedMetadataBytes: number;
18
+ /** The decompressed Arch payload walked for the file list, in bytes. */
19
+ maxPayloadBytes: number;
20
+ /** Tar or ar entries per archive, and values per multi-valued metadata field. */
21
+ maxEntries: number;
22
+ /** Total bytes of Arch file names. */
23
+ maxFileListBytes: number;
24
+ /**
25
+ * One tar header chain (the header blocks plus PAX records and GNU long
26
+ * names), or one metadata line, in bytes. RPM headers count under
27
+ * `maxMetadataBytes`, not here.
28
+ */
29
+ maxHeaderBytes: number;
30
+ }
31
+ /**
32
+ * The default limits. They accept anything a stock Gitea 28.2.0 stores in
33
+ * practice (Gitea has no package size cap), with one exception:
34
+ * - `maxDecompressedMetadataBytes` is Gitea's 32 MiB deb control bound, but
35
+ * Gitea cuts the decompressed stream there and keeps a `control` found
36
+ * before the cut, where the codec refuses the member with `limit-exceeded`;
37
+ * - `maxEntries` and `maxFileListBytes` are Gitea's Arch file-list caps
38
+ * (Alpine's 1024 `.PKGINFO` values fold into `maxEntries`);
39
+ * - `maxHeaderBytes` covers a full PAX + GNU long name + GNU long link chain at
40
+ * Go `archive/tar`'s 1 MiB per special record, and Gitea's 64 KiB line limit.
41
+ */
42
+ export declare const DEFAULT_LINUX_PACKAGE_LIMITS: Readonly<ILinuxPackageLimits>;
43
+ /**
44
+ * Merges per-call overrides over the defaults. Unknown keys and values that
45
+ * are not positive safe integers are refused with `invalid-input`.
46
+ */
47
+ export declare function resolveLinuxPackageLimits(overrides?: Partial<ILinuxPackageLimits>): Readonly<ILinuxPackageLimits>;
@@ -0,0 +1,57 @@
1
+ import { LinuxRepoError } from './errors.js';
2
+ const KiB = 1024;
3
+ const MiB = 1024 * KiB;
4
+ const GiB = 1024 * MiB;
5
+ /**
6
+ * The default limits. They accept anything a stock Gitea 28.2.0 stores in
7
+ * practice (Gitea has no package size cap), with one exception:
8
+ * - `maxDecompressedMetadataBytes` is Gitea's 32 MiB deb control bound, but
9
+ * Gitea cuts the decompressed stream there and keeps a `control` found
10
+ * before the cut, where the codec refuses the member with `limit-exceeded`;
11
+ * - `maxEntries` and `maxFileListBytes` are Gitea's Arch file-list caps
12
+ * (Alpine's 1024 `.PKGINFO` values fold into `maxEntries`);
13
+ * - `maxHeaderBytes` covers a full PAX + GNU long name + GNU long link chain at
14
+ * Go `archive/tar`'s 1 MiB per special record, and Gitea's 64 KiB line limit.
15
+ */
16
+ export const DEFAULT_LINUX_PACKAGE_LIMITS = Object.freeze({
17
+ maxPackageBytes: 8 * GiB,
18
+ maxMetadataBytes: 64 * MiB,
19
+ maxDecompressedMetadataBytes: 32 * MiB,
20
+ maxPayloadBytes: 16 * GiB,
21
+ maxEntries: 100_000,
22
+ maxFileListBytes: 16 * MiB,
23
+ maxHeaderBytes: 4 * MiB,
24
+ });
25
+ const LIMIT_KEYS = Object.keys(DEFAULT_LINUX_PACKAGE_LIMITS);
26
+ /**
27
+ * Merges per-call overrides over the defaults. Unknown keys and values that
28
+ * are not positive safe integers are refused with `invalid-input`.
29
+ */
30
+ export function resolveLinuxPackageLimits(overrides) {
31
+ if (overrides === undefined) {
32
+ return DEFAULT_LINUX_PACKAGE_LIMITS;
33
+ }
34
+ if (overrides === null || typeof overrides !== 'object' || Array.isArray(overrides)) {
35
+ throw new LinuxRepoError('invalid-input', 'limits must be an object', { field: 'limits' });
36
+ }
37
+ const resolved = { ...DEFAULT_LINUX_PACKAGE_LIMITS };
38
+ for (const key of Object.keys(overrides)) {
39
+ if (!LIMIT_KEYS.includes(key)) {
40
+ throw new LinuxRepoError('invalid-input', `unknown limit "${key}"`, { field: 'limits', value: key });
41
+ }
42
+ const limitKey = key;
43
+ const value = overrides[limitKey];
44
+ if (value === undefined) {
45
+ continue;
46
+ }
47
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value <= 0) {
48
+ throw new LinuxRepoError('invalid-input', `limit ${limitKey} must be a positive safe integer`, {
49
+ field: 'limits',
50
+ limit: limitKey,
51
+ });
52
+ }
53
+ resolved[limitKey] = value;
54
+ }
55
+ return Object.freeze(resolved);
56
+ }
57
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGltaXRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc2hhcmVkL2xpbWl0cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBaUM3QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUM7QUFDakIsTUFBTSxHQUFHLEdBQUcsSUFBSSxHQUFHLEdBQUcsQ0FBQztBQUN2QixNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsR0FBRyxDQUFDO0FBRXZCOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLENBQUMsTUFBTSw0QkFBNEIsR0FBa0MsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUN2RixlQUFlLEVBQUUsQ0FBQyxHQUFHLEdBQUc7SUFDeEIsZ0JBQWdCLEVBQUUsRUFBRSxHQUFHLEdBQUc7SUFDMUIsNEJBQTRCLEVBQUUsRUFBRSxHQUFHLEdBQUc7SUFDdEMsZUFBZSxFQUFFLEVBQUUsR0FBRyxHQUFHO0lBQ3pCLFVBQVUsRUFBRSxPQUFPO0lBQ25CLGdCQUFnQixFQUFFLEVBQUUsR0FBRyxHQUFHO0lBQzFCLGNBQWMsRUFBRSxDQUFDLEdBQUcsR0FBRztDQUN4QixDQUFDLENBQUM7QUFFSCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixDQUFxQyxDQUFDO0FBRWpHOzs7R0FHRztBQUNILE1BQU0sVUFBVSx5QkFBeUIsQ0FDdkMsU0FBd0M7SUFFeEMsSUFBSSxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDNUIsT0FBTyw0QkFBNEIsQ0FBQztJQUN0QyxDQUFDO0lBQ0QsSUFBSSxTQUFTLEtBQUssSUFBSSxJQUFJLE9BQU8sU0FBUyxLQUFLLFFBQVEsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDcEYsTUFBTSxJQUFJLGNBQWMsQ0FBQyxlQUFlLEVBQUUsMEJBQTBCLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUM3RixDQUFDO0lBQ0QsTUFBTSxRQUFRLEdBQXdCLEVBQUUsR0FBRyw0QkFBNEIsRUFBRSxDQUFDO0lBQzFFLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQ3pDLElBQUksQ0FBRSxVQUF1QixDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzVDLE1BQU0sSUFBSSxjQUFjLENBQUMsZUFBZSxFQUFFLGtCQUFrQixHQUFHLEdBQUcsRUFBRSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDdkcsQ0FBQztRQUNELE1BQU0sUUFBUSxHQUFHLEdBQWdDLENBQUM7UUFDbEQsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2xDLElBQUksS0FBSyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3hCLFNBQVM7UUFDWCxDQUFDO1FBQ0QsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUM1RSxNQUFNLElBQUksY0FBYyxDQUFDLGVBQWUsRUFBRSxTQUFTLFFBQVEsa0NBQWtDLEVBQUU7Z0JBQzdGLEtBQUssRUFBRSxRQUFRO2dCQUNmLEtBQUssRUFBRSxRQUFRO2FBQ2hCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxRQUFRLENBQUMsUUFBUSxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQzdCLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDakMsQ0FBQyJ9
@@ -0,0 +1,213 @@
1
+ /**
2
+ * The persisted record shapes of `@push.rocks/smartlinuxrepo`.
3
+ *
4
+ * Records are public API: every field is plain JSON (strings,
5
+ * integers within `Number.MAX_SAFE_INTEGER`, booleans, arrays and objects; no
6
+ * `Date`, no `Uint8Array`). Hashes are lowercase hex. Every 1.0.0 key is
7
+ * required and always present, using Gitea's zero values (`''`, `0`, `[]`);
8
+ * keys added in a later minor are optional because older persisted records lack
9
+ * them. Changing a shape needs a major release. The union is not closed: a
10
+ * later minor may add a fifth format.
11
+ */
12
+ /** The package formats the codec reads and indexes. */
13
+ export type TLinuxPackageFormat = 'alpine' | 'debian' | 'rpm' | 'arch';
14
+ /** Size and digests over the whole package file. */
15
+ export interface ILinuxPackageDigests {
16
+ /** Byte count of the whole file. */
17
+ size: number;
18
+ md5: string;
19
+ sha1: string;
20
+ sha256: string;
21
+ sha512: string;
22
+ }
23
+ export interface IAlpinePackageDigests extends ILinuxPackageDigests {
24
+ /**
25
+ * SHA-1 of the exact bytes of the gzip member holding `.PKGINFO`. The
26
+ * APKINDEX `C:` value is `'Q1'` plus the base64 of these 20 bytes.
27
+ */
28
+ controlSha1: string;
29
+ }
30
+ export interface ILinuxPackageRecordBase {
31
+ format: TLinuxPackageFormat;
32
+ name: string;
33
+ /** Gitea's version string (RPM: `V-R`, or `E-V-R` with a dash when the epoch is not `0`). */
34
+ version: string;
35
+ /** The architecture as the package states it (`''` is possible for Alpine). */
36
+ architecture: string;
37
+ /** Gitea's stored file name for the package. */
38
+ fileName: string;
39
+ digests: ILinuxPackageDigests;
40
+ }
41
+ export interface IAlpinePackageMetadata {
42
+ description: string;
43
+ license: string;
44
+ /** The `.PKGINFO` url when Gitea's URL validation accepts it, else `''`. */
45
+ projectUrl: string;
46
+ maintainer: string;
47
+ packager: string;
48
+ buildDate: number;
49
+ installedSize: number;
50
+ origin: string;
51
+ commit: string;
52
+ installIf: string;
53
+ provides: string[];
54
+ dependencies: string[];
55
+ providerPriority: number;
56
+ }
57
+ export interface IAlpinePackageRecord extends ILinuxPackageRecordBase {
58
+ format: 'alpine';
59
+ digests: IAlpinePackageDigests;
60
+ metadata: IAlpinePackageMetadata;
61
+ }
62
+ export interface IDebianPackageMetadata {
63
+ /**
64
+ * Gitea's trimmed control stanza, exactly as Gitea 28.2.0 derives it. It is
65
+ * the source of truth for the `Packages` stanza. Index-owned fields a crafted
66
+ * control file carries (`Filename`, `Size`, `MD5sum`, `SHA1`, `SHA256`,
67
+ * `SHA512`) stay in this text; `renderDebianPackagesStanza` strips them
68
+ * because it writes those fields itself.
69
+ */
70
+ control: string;
71
+ /** The name part of the `Maintainer` field, as Gitea derives it. */
72
+ maintainer: string;
73
+ /** The `Homepage` field when Gitea's URL validation accepts it, else `''`. */
74
+ projectUrl: string;
75
+ description: string;
76
+ dependencies: string[];
77
+ }
78
+ export interface IDebianPackageRecord extends ILinuxPackageRecordBase {
79
+ format: 'debian';
80
+ metadata: IDebianPackageMetadata;
81
+ }
82
+ export interface IRpmDependency {
83
+ name: string;
84
+ flags: '' | 'EQ' | 'LT' | 'GT' | 'LE' | 'GE';
85
+ epoch: string;
86
+ version: string;
87
+ release: string;
88
+ }
89
+ export interface IRpmFile {
90
+ path: string;
91
+ type: '' | 'dir' | 'ghost';
92
+ isExecutable: boolean;
93
+ }
94
+ export interface IRpmChangelog {
95
+ author: string;
96
+ date: number;
97
+ text: string;
98
+ }
99
+ export interface IRpmPackageMetadata {
100
+ epoch: string;
101
+ upstreamVersion: string;
102
+ release: string;
103
+ /** True for a source RPM (lead type). `architecture` stays the ARCH tag, Gitea's identity and path segment. */
104
+ isSourcePackage: boolean;
105
+ summary: string;
106
+ description: string;
107
+ license: string;
108
+ /** The URL tag when Gitea's URL validation accepts it, else `''`. */
109
+ projectUrl: string;
110
+ vendor: string;
111
+ group: string;
112
+ packager: string;
113
+ sourceRpm: string;
114
+ buildHost: string;
115
+ buildTime: number;
116
+ fileTime: number;
117
+ installedSize: number;
118
+ archiveSize: number;
119
+ provides: IRpmDependency[];
120
+ requires: IRpmDependency[];
121
+ conflicts: IRpmDependency[];
122
+ obsoletes: IRpmDependency[];
123
+ files: IRpmFile[];
124
+ changelogs: IRpmChangelog[];
125
+ }
126
+ export interface IRpmPackageRecord extends ILinuxPackageRecordBase {
127
+ format: 'rpm';
128
+ metadata: IRpmPackageMetadata;
129
+ }
130
+ /**
131
+ * One RPM errata update (updateinfo `<update>`), plain JSON. Ported from Gitea
132
+ * 28.2.0 `modules/packages/rpm/metadata.go`. Dates are `YYYY-MM-DD HH:MM:SS`
133
+ * (UTC when the codec writes them) or `null`.
134
+ */
135
+ export interface IRpmUpdate {
136
+ id: string;
137
+ from: string;
138
+ status: string;
139
+ type: string;
140
+ version: string;
141
+ title: string;
142
+ severity: string;
143
+ description: string;
144
+ issued: string | null;
145
+ updated: string | null;
146
+ references: IRpmUpdateReference[];
147
+ collections: IRpmUpdateCollection[];
148
+ }
149
+ export interface IRpmUpdateReference {
150
+ href: string;
151
+ id: string;
152
+ title: string;
153
+ type: string;
154
+ }
155
+ export interface IRpmUpdateCollection {
156
+ short: string;
157
+ packages: IRpmUpdatePackage[];
158
+ }
159
+ export interface IRpmUpdatePackage {
160
+ name: string;
161
+ version: string;
162
+ release: string;
163
+ arch: string;
164
+ src: string;
165
+ fileName: string;
166
+ }
167
+ export interface IArchPackageMetadata {
168
+ compression: 'zst' | 'xz' | 'gz';
169
+ base: string;
170
+ description: string;
171
+ /** The `.PKGINFO` url when Gitea's URL validation accepts it, else `''`. */
172
+ projectUrl: string;
173
+ licenses: string[];
174
+ installedSize: number;
175
+ buildDate: number;
176
+ packager: string;
177
+ groups: string[];
178
+ provides: string[];
179
+ replaces: string[];
180
+ depends: string[];
181
+ optDepends: string[];
182
+ makeDepends: string[];
183
+ checkDepends: string[];
184
+ conflicts: string[];
185
+ xdata: string[];
186
+ backup: string[];
187
+ files: string[];
188
+ }
189
+ export interface IArchPackageRecord extends ILinuxPackageRecordBase {
190
+ format: 'arch';
191
+ metadata: IArchPackageMetadata;
192
+ }
193
+ export type TLinuxPackageRecord = IAlpinePackageRecord | IDebianPackageRecord | IRpmPackageRecord | IArchPackageRecord;
194
+ /**
195
+ * Write order of an index file: every `content` file is written before any
196
+ * `pointer` file (the signed top-level documents that name the content files).
197
+ */
198
+ export type TLinuxIndexFileStage = 'content' | 'pointer';
199
+ /**
200
+ * One file of a built index set. A builder returns the complete set of files
201
+ * that should exist; any previously written file not in the set is stale.
202
+ */
203
+ export interface ILinuxIndexFile {
204
+ /** Path relative to the format root, in Gitea's layout. */
205
+ path: string;
206
+ bytes: Uint8Array;
207
+ /** Lowercase hex SHA-256 of `bytes`. */
208
+ sha256: string;
209
+ mediaType: string;
210
+ stage: TLinuxIndexFileStage;
211
+ /** Other paths serving the same bytes (Debian `by-hash/<ALGO>/<hex>` for every listed hash). */
212
+ aliases: string[];
213
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The persisted record shapes of `@push.rocks/smartlinuxrepo`.
3
+ *
4
+ * Records are public API: every field is plain JSON (strings,
5
+ * integers within `Number.MAX_SAFE_INTEGER`, booleans, arrays and objects; no
6
+ * `Date`, no `Uint8Array`). Hashes are lowercase hex. Every 1.0.0 key is
7
+ * required and always present, using Gitea's zero values (`''`, `0`, `[]`);
8
+ * keys added in a later minor are optional because older persisted records lack
9
+ * them. Changing a shape needs a major release. The union is not closed: a
10
+ * later minor may add a fifth format.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9zaGFyZWQvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7R0FVRyJ9
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Gitea 28.2.0's URL check for package metadata (`validation.IsValidURL`,
3
+ * `modules/validation/helpers.go:42-50`): Go 1.27's `url.ParseRequestURI`
4
+ * succeeds, the scheme is `http` or `https` (case-insensitive), and the host's
5
+ * port part holds only digits (`portOnly`/`validPort`,
6
+ * `modules/validation/binding.go:131-152`; no range check, an empty port
7
+ * passes). Readers keep a URL field only when this returns true.
8
+ *
9
+ * The port follows Go's `net/url` byte for byte on the UTF-8 encoding of the
10
+ * value, including its quirks: `http:x` is an opaque URL and passes,
11
+ * `http://` (empty host) passes, a query or fragment is never validated, and a
12
+ * `#` before the first `/` is part of the host and fails. Only the parts of the
13
+ * parser that can change the result for `http`/`https` are ported. Expected
14
+ * values come from Go: `test/fixtures/url/isvalidurl.gitea.json`.
15
+ *
16
+ * Internal: not exported from the package entry.
17
+ */
18
+ export declare function isValidUrl(valueArg: string): boolean;