@shard-for-obsidian/lib 0.2.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 (48) hide show
  1. package/README.md +77 -0
  2. package/dist/client/FetchAdapter.d.ts +14 -0
  3. package/dist/client/FetchAdapter.d.ts.map +1 -0
  4. package/dist/client/FetchAdapter.js +1 -0
  5. package/dist/client/OciRegistryClient.d.ts +196 -0
  6. package/dist/client/OciRegistryClient.d.ts.map +1 -0
  7. package/dist/client/OciRegistryClient.js +704 -0
  8. package/dist/client/RegistryClientOptions.d.ts +18 -0
  9. package/dist/client/RegistryClientOptions.d.ts.map +1 -0
  10. package/dist/client/RegistryClientOptions.js +1 -0
  11. package/dist/errors/RegistryErrors.d.ts +39 -0
  12. package/dist/errors/RegistryErrors.d.ts.map +1 -0
  13. package/dist/errors/RegistryErrors.js +52 -0
  14. package/dist/ghcr/GhcrConstants.d.ts +5 -0
  15. package/dist/ghcr/GhcrConstants.d.ts.map +1 -0
  16. package/dist/ghcr/GhcrConstants.js +4 -0
  17. package/dist/index.d.ts +15 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +13 -0
  20. package/dist/index.js.map +7 -0
  21. package/dist/parsing/IndexParser.d.ts +26 -0
  22. package/dist/parsing/IndexParser.d.ts.map +1 -0
  23. package/dist/parsing/IndexParser.js +106 -0
  24. package/dist/parsing/LinkHeaderParser.d.ts +8 -0
  25. package/dist/parsing/LinkHeaderParser.d.ts.map +1 -0
  26. package/dist/parsing/LinkHeaderParser.js +34 -0
  27. package/dist/parsing/RepoParser.d.ts +54 -0
  28. package/dist/parsing/RepoParser.d.ts.map +1 -0
  29. package/dist/parsing/RepoParser.js +186 -0
  30. package/dist/types/AuthTypes.d.ts +14 -0
  31. package/dist/types/AuthTypes.d.ts.map +1 -0
  32. package/dist/types/AuthTypes.js +4 -0
  33. package/dist/types/ManifestTypes.d.ts +98 -0
  34. package/dist/types/ManifestTypes.d.ts.map +1 -0
  35. package/dist/types/ManifestTypes.js +7 -0
  36. package/dist/types/RegistryTypes.d.ts +48 -0
  37. package/dist/types/RegistryTypes.d.ts.map +1 -0
  38. package/dist/types/RegistryTypes.js +4 -0
  39. package/dist/types/RequestTypes.d.ts +23 -0
  40. package/dist/types/RequestTypes.d.ts.map +1 -0
  41. package/dist/types/RequestTypes.js +4 -0
  42. package/dist/utils/DigestUtils.d.ts +9 -0
  43. package/dist/utils/DigestUtils.d.ts.map +1 -0
  44. package/dist/utils/DigestUtils.js +26 -0
  45. package/dist/utils/ValidationUtils.d.ts +2 -0
  46. package/dist/utils/ValidationUtils.d.ts.map +1 -0
  47. package/dist/utils/ValidationUtils.js +6 -0
  48. package/package.json +50 -0
@@ -0,0 +1,18 @@
1
+ import type { RegistryRepo } from "../types/RegistryTypes.js";
2
+ export interface RegistryClientOptions {
3
+ name?: string;
4
+ repo?: RegistryRepo;
5
+ username?: string;
6
+ password?: string;
7
+ token?: string;
8
+ insecure?: boolean;
9
+ scheme?: "https" | "http";
10
+ acceptOCIManifests?: boolean;
11
+ acceptManifestLists?: boolean;
12
+ userAgent?: string;
13
+ scopes?: string[];
14
+ adapter: {
15
+ fetch(input: string | Request, init?: RequestInit): Promise<Response>;
16
+ };
17
+ }
18
+ //# sourceMappingURL=RegistryClientOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegistryClientOptions.d.ts","sourceRoot":"","sources":["../../src/client/RegistryClientOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,YAAY,CAAC;IAEpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE;QACP,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;KACvE,CAAC;CACH"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,39 @@
1
+ import type { DockerResponse, RegistryError } from "../types/RegistryTypes.js";
2
+ /** Base class for custom error classes. */
3
+ export declare class ApiError extends Error {
4
+ constructor(message: string);
5
+ }
6
+ export declare class HttpError extends ApiError {
7
+ resp: DockerResponse;
8
+ errors: RegistryError[];
9
+ name: string;
10
+ constructor(resp: DockerResponse, errors: RegistryError[], message: string);
11
+ }
12
+ export declare class BadDigestError extends ApiError {
13
+ readonly name = "BadDigestError";
14
+ }
15
+ export declare class InvalidContentError extends ApiError {
16
+ readonly name = "InvalidContentError";
17
+ }
18
+ export declare class InternalError extends ApiError {
19
+ readonly name = "InternalError";
20
+ }
21
+ export declare class ManifestVerificationError extends ApiError {
22
+ readonly name = "ManifestVerificationError";
23
+ }
24
+ export declare class InvalidManifestError extends ApiError {
25
+ readonly name = "InvalidManifestError";
26
+ }
27
+ export declare class DownloadError extends ApiError {
28
+ readonly name = "DownloadError";
29
+ }
30
+ export declare class UploadError extends ApiError {
31
+ readonly name = "UploadError";
32
+ }
33
+ export declare class BlobReadError extends ApiError {
34
+ readonly name = "BlobReadError";
35
+ }
36
+ export declare class TooManyRedirectsError extends ApiError {
37
+ readonly name = "TooManyRedirectsError";
38
+ }
39
+ //# sourceMappingURL=RegistryErrors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegistryErrors.d.ts","sourceRoot":"","sources":["../../src/errors/RegistryErrors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAM/E,2CAA2C;AAC3C,qBAAa,QAAS,SAAQ,KAAK;gBACrB,OAAO,EAAE,MAAM;CAK5B;AAED,qBAAa,SAAU,SAAQ,QAAQ;IAG5B,IAAI,EAAE,cAAc;IACpB,MAAM,EAAE,aAAa,EAAE;IAHvB,IAAI,SAAe;gBAEnB,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,aAAa,EAAE,EAC9B,OAAO,EAAE,MAAM;CAIlB;AACD,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,SAAkB,IAAI,oBAAoB;CAC3C;AACD,qBAAa,mBAAoB,SAAQ,QAAQ;IAC/C,SAAkB,IAAI,yBAAyB;CAChD;AAED,qBAAa,aAAc,SAAQ,QAAQ;IACzC,SAAkB,IAAI,mBAAmB;CAC1C;AAED,qBAAa,yBAA0B,SAAQ,QAAQ;IACrD,SAAkB,IAAI,+BAA+B;CACtD;AAED,qBAAa,oBAAqB,SAAQ,QAAQ;IAChD,SAAkB,IAAI,0BAA0B;CACjD;AAED,qBAAa,aAAc,SAAQ,QAAQ;IACzC,SAAkB,IAAI,mBAAmB;CAC1C;AAED,qBAAa,WAAY,SAAQ,QAAQ;IACvC,SAAkB,IAAI,iBAAiB;CACxC;AAED,qBAAa,aAAc,SAAQ,QAAQ;IACzC,SAAkB,IAAI,mBAAmB;CAC1C;AAOD,qBAAa,qBAAsB,SAAQ,QAAQ;IACjD,SAAkB,IAAI,2BAA2B;CAClD"}
@@ -0,0 +1,52 @@
1
+ /*
2
+ * Error classes that docker-registry-client may produce.
3
+ */
4
+ /** Base class for custom error classes. */
5
+ export class ApiError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = new.target.name;
9
+ Error.captureStackTrace?.(this, new.target);
10
+ }
11
+ }
12
+ export class HttpError extends ApiError {
13
+ resp;
14
+ errors;
15
+ name = "HttpError";
16
+ constructor(resp, errors, message) {
17
+ super(message);
18
+ this.resp = resp;
19
+ this.errors = errors;
20
+ }
21
+ }
22
+ export class BadDigestError extends ApiError {
23
+ name = "BadDigestError";
24
+ }
25
+ export class InvalidContentError extends ApiError {
26
+ name = "InvalidContentError";
27
+ }
28
+ export class InternalError extends ApiError {
29
+ name = "InternalError";
30
+ }
31
+ export class ManifestVerificationError extends ApiError {
32
+ name = "ManifestVerificationError";
33
+ }
34
+ export class InvalidManifestError extends ApiError {
35
+ name = "InvalidManifestError";
36
+ }
37
+ export class DownloadError extends ApiError {
38
+ name = "DownloadError";
39
+ }
40
+ export class UploadError extends ApiError {
41
+ name = "UploadError";
42
+ }
43
+ export class BlobReadError extends ApiError {
44
+ name = "BlobReadError";
45
+ }
46
+ // export class UnauthorizedError extends HttpError {
47
+ // readonly name = 'UnauthorizedError';
48
+ // readonly statusCode = 401;
49
+ // }
50
+ export class TooManyRedirectsError extends ApiError {
51
+ name = "TooManyRedirectsError";
52
+ }
@@ -0,0 +1,5 @@
1
+ export declare const REALM = "https://ghcr.io/token";
2
+ export declare const SERVICE = "ghcr.io";
3
+ export declare const SCOPE_REPO_PREFIX = "repository:";
4
+ export declare const SCOPE_PULL_SUFFIX = ":pull";
5
+ //# sourceMappingURL=GhcrConstants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GhcrConstants.d.ts","sourceRoot":"","sources":["../../src/ghcr/GhcrConstants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,0BAA0B,CAAC;AAC7C,eAAO,MAAM,OAAO,YAAY,CAAC;AACjC,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,iBAAiB,UAAU,CAAC"}
@@ -0,0 +1,4 @@
1
+ export const REALM = "https://ghcr.io/token";
2
+ export const SERVICE = "ghcr.io";
3
+ export const SCOPE_REPO_PREFIX = "repository:";
4
+ export const SCOPE_PULL_SUFFIX = ":pull";
@@ -0,0 +1,15 @@
1
+ export * from "./client/OciRegistryClient.js";
2
+ export * from "./types/ManifestTypes.js";
3
+ export * from "./types/RegistryTypes.js";
4
+ export * from "./types/AuthTypes.js";
5
+ export * from "./types/RequestTypes.js";
6
+ export * from "./parsing/RepoParser.js";
7
+ export * from "./parsing/IndexParser.js";
8
+ export * from "./parsing/LinkHeaderParser.js";
9
+ export * from "./utils/ValidationUtils.js";
10
+ export * from "./utils/DigestUtils.js";
11
+ export * from "./errors/RegistryErrors.js";
12
+ export * from "./ghcr/GhcrConstants.js";
13
+ export type { FetchAdapter } from "./client/FetchAdapter.js";
14
+ export type { RegistryClientOptions } from "./client/RegistryClientOptions.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,YAAY,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ // Re-export everything from new structure
2
+ export * from "./client/OciRegistryClient.js";
3
+ export * from "./types/ManifestTypes.js";
4
+ export * from "./types/RegistryTypes.js";
5
+ export * from "./types/AuthTypes.js";
6
+ export * from "./types/RequestTypes.js";
7
+ export * from "./parsing/RepoParser.js";
8
+ export * from "./parsing/IndexParser.js";
9
+ export * from "./parsing/LinkHeaderParser.js";
10
+ export * from "./utils/ValidationUtils.js";
11
+ export * from "./utils/DigestUtils.js";
12
+ export * from "./errors/RegistryErrors.js";
13
+ export * from "./ghcr/GhcrConstants.js";
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": ["// Re-export everything from new structure\nexport * from \"./client/OciRegistryClient.js\";\nexport * from \"./types/ManifestTypes.js\";\nexport * from \"./types/RegistryTypes.js\";\nexport * from \"./types/AuthTypes.js\";\nexport * from \"./types/RequestTypes.js\";\nexport * from \"./parsing/RepoParser.js\";\nexport * from \"./parsing/IndexParser.js\";\nexport * from \"./parsing/LinkHeaderParser.js\";\nexport * from \"./utils/ValidationUtils.js\";\nexport * from \"./utils/DigestUtils.js\";\nexport * from \"./errors/RegistryErrors.js\";\nexport * from \"./ghcr/GhcrConstants.js\";\nexport type { FetchAdapter } from \"./client/FetchAdapter.js\";\nexport type { RegistryClientOptions } from \"./client/RegistryClientOptions.js\";\n"],
5
+ "mappings": "AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ import type { RegistryIndex } from "../types/RegistryTypes.js";
2
+ export declare const DEFAULT_INDEX_NAME = "docker.io";
3
+ export declare const DEFAULT_INDEX_URL = "https://registry-1.docker.io";
4
+ export declare const DEFAULT_LOGIN_SERVERNAME = "https://index.docker.io/v1/";
5
+ /**
6
+ * Parse a docker index name or index URL.
7
+ *
8
+ * Examples:
9
+ * docker.io (no scheme implies 'https')
10
+ * index.docker.io (normalized to docker.io)
11
+ * https://docker.io
12
+ * http://localhost:5000
13
+ * https://index.docker.io/v1/ (special case)
14
+ *
15
+ * Special case: `docker` still refers to "https://index.docker.io/v1/"
16
+ * when dealing with auth (including in its json file).
17
+ *
18
+ * @param {String} arg: Optional. Index name (optionally with leading scheme).
19
+ */
20
+ export declare function parseIndex(arg?: string): RegistryIndex;
21
+ /**
22
+ * Similar in spirit to docker.git:registry/endpoint.go#NewEndpoint().
23
+ */
24
+ export declare function urlFromIndex(index: RegistryIndex, scheme?: "http" | "https"): string;
25
+ export declare function isLocalhost(host: string): boolean;
26
+ //# sourceMappingURL=IndexParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IndexParser.d.ts","sourceRoot":"","sources":["../../src/parsing/IndexParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAK/D,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,iBAAiB,iCAAiC,CAAC;AAEhE,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AAEtE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,aAAa,CAwEtD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,aAAa,EACpB,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GACxB,MAAM,CAeR;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOjD"}
@@ -0,0 +1,106 @@
1
+ // --- globals
2
+ // See `INDEXNAME` in docker/docker.git:registry/config.go.
3
+ export const DEFAULT_INDEX_NAME = "docker.io";
4
+ export const DEFAULT_INDEX_URL = "https://registry-1.docker.io";
5
+ export const DEFAULT_LOGIN_SERVERNAME = "https://index.docker.io/v1/";
6
+ /**
7
+ * Parse a docker index name or index URL.
8
+ *
9
+ * Examples:
10
+ * docker.io (no scheme implies 'https')
11
+ * index.docker.io (normalized to docker.io)
12
+ * https://docker.io
13
+ * http://localhost:5000
14
+ * https://index.docker.io/v1/ (special case)
15
+ *
16
+ * Special case: `docker` still refers to "https://index.docker.io/v1/"
17
+ * when dealing with auth (including in its json file).
18
+ *
19
+ * @param {String} arg: Optional. Index name (optionally with leading scheme).
20
+ */
21
+ export function parseIndex(arg) {
22
+ if (!arg || arg === DEFAULT_LOGIN_SERVERNAME) {
23
+ // Default index.
24
+ return {
25
+ scheme: "https",
26
+ name: DEFAULT_INDEX_NAME,
27
+ official: true,
28
+ };
29
+ }
30
+ // Optional protocol/scheme.
31
+ let indexName;
32
+ let scheme = "https";
33
+ const protoSepIdx = arg.indexOf("://");
34
+ if (protoSepIdx !== -1) {
35
+ const foundScheme = arg.slice(0, protoSepIdx);
36
+ if (foundScheme !== "http" && foundScheme !== "https") {
37
+ throw new Error("invalid index scheme, must be " + '"http" or "https": ' + arg);
38
+ }
39
+ scheme = foundScheme;
40
+ indexName = arg.slice(protoSepIdx + 3);
41
+ }
42
+ else {
43
+ scheme = isLocalhost(arg) ? "http" : "https";
44
+ indexName = arg;
45
+ }
46
+ if (!indexName) {
47
+ throw new Error("invalid index, empty host: " + arg);
48
+ }
49
+ else if (indexName.indexOf(".") === -1 &&
50
+ indexName.indexOf(":") === -1 &&
51
+ indexName !== "localhost") {
52
+ throw new Error(`invalid index, "${indexName}" does not look like a valid host: ${arg}`);
53
+ }
54
+ else {
55
+ // Allow a trailing '/' as from some URL builder functions that
56
+ // add a default '/' path to a URL, e.g. 'https://docker.io/'.
57
+ if (indexName[indexName.length - 1] === "/") {
58
+ indexName = indexName.slice(0, indexName.length - 1);
59
+ }
60
+ // Ensure no trailing repo.
61
+ if (indexName.indexOf("/") !== -1) {
62
+ throw new Error("invalid index, trailing repo: " + arg);
63
+ }
64
+ }
65
+ // Per docker.git's `ValidateIndexName`.
66
+ if (indexName === "index." + DEFAULT_INDEX_NAME) {
67
+ indexName = DEFAULT_INDEX_NAME;
68
+ }
69
+ const index = {
70
+ name: indexName,
71
+ official: indexName === DEFAULT_INDEX_NAME,
72
+ scheme,
73
+ };
74
+ // Disallow official and 'http'.
75
+ if (index.official && index.scheme === "http") {
76
+ throw new Error("invalid index, plaintext HTTP to official index " +
77
+ "is disallowed: " +
78
+ arg);
79
+ }
80
+ return index;
81
+ }
82
+ /**
83
+ * Similar in spirit to docker.git:registry/endpoint.go#NewEndpoint().
84
+ */
85
+ export function urlFromIndex(index, scheme) {
86
+ if (index.official) {
87
+ // v1
88
+ if (scheme != null && scheme !== "https")
89
+ throw new Error(`Unencrypted communication with docker.io is not allowed`);
90
+ return DEFAULT_INDEX_URL;
91
+ }
92
+ else {
93
+ if (scheme != null && scheme !== "https" && scheme !== "http")
94
+ throw new Error(`Non-HTTP communication with docker registries is not allowed`);
95
+ return `${scheme ?? index.scheme}://${index.name}`;
96
+ }
97
+ }
98
+ export function isLocalhost(host) {
99
+ const lead = host.split(":")[0];
100
+ if (lead === "localhost" || lead === "127.0.0.1" || host.includes("::1")) {
101
+ return true;
102
+ }
103
+ else {
104
+ return false;
105
+ }
106
+ }
@@ -0,0 +1,8 @@
1
+ type Link = {
2
+ rel: string;
3
+ url: string;
4
+ params: Record<string, string>;
5
+ };
6
+ export declare function parseLinkHeader(rawHeader: string | null): Link[];
7
+ export {};
8
+ //# sourceMappingURL=LinkHeaderParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkHeaderParser.d.ts","sourceRoot":"","sources":["../../src/parsing/LinkHeaderParser.ts"],"names":[],"mappings":"AAAA,KAAK,IAAI,GAAG;IACV,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAGF,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,EAAE,CA+BhE"}
@@ -0,0 +1,34 @@
1
+ const linkRegex = /^<([^>]+)>(?:\s*;\s*(.+))?$/;
2
+ export function parseLinkHeader(rawHeader) {
3
+ if (!rawHeader)
4
+ return [];
5
+ return rawHeader
6
+ .split(",")
7
+ .slice(0, 5) // Arbitrary limit to how many links we are willing to parse
8
+ .flatMap((piece) => {
9
+ const matches = piece.trim().match(linkRegex);
10
+ if (!matches)
11
+ return [];
12
+ const { rel, ...params } = matches[2]
13
+ ?.split(";")
14
+ .map((param) => param.trim().split("="))
15
+ .reduce((acc, [key, value]) => {
16
+ if (!value)
17
+ return acc;
18
+ if (value.startsWith('"') && value.endsWith('"')) {
19
+ value = value.slice(1, -1);
20
+ }
21
+ acc[key] = value;
22
+ return acc;
23
+ }, {}) ?? {};
24
+ if (!rel)
25
+ return [];
26
+ return [
27
+ {
28
+ rel,
29
+ url: matches[1],
30
+ params,
31
+ },
32
+ ];
33
+ });
34
+ }
@@ -0,0 +1,54 @@
1
+ import type { RegistryImage, RegistryIndex, RegistryRepo } from "../types/RegistryTypes.js";
2
+ export declare const DEFAULT_TAG = "latest";
3
+ /**
4
+ * Parse a docker repo and tag string: [INDEX/]REPO[:TAG|@DIGEST]
5
+ *
6
+ * Examples:
7
+ * busybox
8
+ * google/python
9
+ * docker.io/ubuntu
10
+ * localhost:5000/blarg
11
+ * http://localhost:5000/blarg
12
+ *
13
+ * Dev Notes:
14
+ * - This is meant to mimic
15
+ * docker.git:registry/config.go#ServiceConfig.NewRepositoryInfo
16
+ * as much as reasonable -- with the addition that we maintain the
17
+ * 'tag' field. Also, that we accept the scheme on the "INDEX" is
18
+ * different than docker.git's parsing.
19
+ * - TODO: what about the '@digest' digest alternative to a tag? See:
20
+ * // JSSTYLED
21
+ * https://github.com/docker/docker/blob/0c7b51089c8cd7ef3510a9b40edaa139a7ca91aa/pkg/parsers/parsers.go#L68
22
+ *
23
+ * @param arg {String} The docker repo string to parse. See examples above.
24
+ * @param defaultIndex {Object|String} Optional. The default index to use
25
+ * if not specified with `arg`. If not given the default is 'docker.io'.
26
+ * If given it may either be a string, e.g. 'https://myreg.example.com',
27
+ * or parsed index object, as from `parseIndex()`.
28
+ */
29
+ export declare function parseRepo(arg: string, defaultIndex?: string | RegistryIndex): RegistryRepo;
30
+ /**
31
+ * Parse a docker repo and tag/digest string: [INDEX/]REPO[:TAG|@DIGEST|:TAG@DIGEST]
32
+ *
33
+ * Examples:
34
+ * busybox
35
+ * busybox:latest
36
+ * google/python:3.3
37
+ * docker.io/ubuntu
38
+ * localhost:5000/blarg
39
+ * http://localhost:5000/blarg:latest
40
+ * google/python:3.3@sha256:fb9f16730ac6316afa4d97caa51302199...
41
+ * alpine@sha256:fb9f16730ac6316afa4d97caa5130219927bfcecf0b0...
42
+ *
43
+ * Dev Notes:
44
+ * - TODO Validation on digest and tag would be nice.
45
+ *
46
+ * @param arg {String} The docker repo:tag string to parse. See examples above.
47
+ * @param defaultIndex {Object|String} Optional. The default index to use
48
+ * if not specified with `arg`. If not given the default is 'docker.io'.
49
+ * If given it may either be a string, e.g. 'https://myreg.example.com',
50
+ * or parsed index object, as from `parseIndex()`.
51
+ */
52
+ export declare function parseRepoAndRef(arg: string, defaultIndex?: string | RegistryIndex): RegistryImage;
53
+ export declare const parseRepoAndTag: typeof parseRepoAndRef;
54
+ //# sourceMappingURL=RepoParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RepoParser.d.ts","sourceRoot":"","sources":["../../src/parsing/RepoParser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,YAAY,EACb,MAAM,2BAA2B,CAAC;AAMnC,eAAO,MAAM,WAAW,WAAW,CAAC;AAKpC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GACpC,YAAY,CAkHd;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GACpC,aAAa,CAgCf;AAED,eAAO,MAAM,eAAe,wBAAkB,CAAC"}
@@ -0,0 +1,186 @@
1
+ import { parseIndex } from "./IndexParser.js";
2
+ import { splitIntoTwo } from "../utils/ValidationUtils.js";
3
+ // JSSTYLED
4
+ // 'DEFAULTTAG' from https://github.com/docker/docker/blob/0c7b51089c8cd7ef3510a9b40edaa139a7ca91aa/graph/tags.go#L25
5
+ export const DEFAULT_TAG = "latest";
6
+ const VALID_NS = /^[a-z0-9._-]*$/;
7
+ const VALID_REPO = /^[a-z0-9_/.-]*$/;
8
+ /**
9
+ * Parse a docker repo and tag string: [INDEX/]REPO[:TAG|@DIGEST]
10
+ *
11
+ * Examples:
12
+ * busybox
13
+ * google/python
14
+ * docker.io/ubuntu
15
+ * localhost:5000/blarg
16
+ * http://localhost:5000/blarg
17
+ *
18
+ * Dev Notes:
19
+ * - This is meant to mimic
20
+ * docker.git:registry/config.go#ServiceConfig.NewRepositoryInfo
21
+ * as much as reasonable -- with the addition that we maintain the
22
+ * 'tag' field. Also, that we accept the scheme on the "INDEX" is
23
+ * different than docker.git's parsing.
24
+ * - TODO: what about the '@digest' digest alternative to a tag? See:
25
+ * // JSSTYLED
26
+ * https://github.com/docker/docker/blob/0c7b51089c8cd7ef3510a9b40edaa139a7ca91aa/pkg/parsers/parsers.go#L68
27
+ *
28
+ * @param arg {String} The docker repo string to parse. See examples above.
29
+ * @param defaultIndex {Object|String} Optional. The default index to use
30
+ * if not specified with `arg`. If not given the default is 'docker.io'.
31
+ * If given it may either be a string, e.g. 'https://myreg.example.com',
32
+ * or parsed index object, as from `parseIndex()`.
33
+ */
34
+ export function parseRepo(arg, defaultIndex) {
35
+ let index;
36
+ // Strip off optional leading `INDEX/`, parse it to `info.index` and
37
+ // leave the rest in `remoteName`.
38
+ let remoteNameRaw;
39
+ const protoSepIdx = arg.indexOf("://");
40
+ if (protoSepIdx !== -1) {
41
+ // (A) repo with a protocol, e.g. 'https://host/repo'.
42
+ const slashIdx = arg.indexOf("/", protoSepIdx + 3);
43
+ if (slashIdx === -1) {
44
+ throw new Error('invalid repository name, no "/REPO" after ' + "hostame: " + arg);
45
+ }
46
+ const indexName = arg.slice(0, slashIdx);
47
+ remoteNameRaw = arg.slice(slashIdx + 1);
48
+ index = parseIndex(indexName);
49
+ }
50
+ else {
51
+ const parts = splitIntoTwo(arg, "/");
52
+ if (parts.length === 1 ||
53
+ /* or if parts[0] doesn't look like a hostname or IP */
54
+ (parts[0].indexOf(".") === -1 &&
55
+ parts[0].indexOf(":") === -1 &&
56
+ parts[0] !== "localhost")) {
57
+ // (B) repo without leading 'INDEX/'.
58
+ if (defaultIndex === undefined) {
59
+ index = parseIndex();
60
+ }
61
+ else if (typeof defaultIndex === "string") {
62
+ index = parseIndex(defaultIndex);
63
+ }
64
+ else {
65
+ index = defaultIndex;
66
+ }
67
+ remoteNameRaw = arg;
68
+ }
69
+ else {
70
+ // (C) repo with leading 'INDEX/' (without protocol).
71
+ index = parseIndex(parts[0]);
72
+ remoteNameRaw = parts[1];
73
+ }
74
+ }
75
+ // Validate remoteName (docker `validateRemoteName`).
76
+ const nameParts = splitIntoTwo(remoteNameRaw, "/");
77
+ let ns = "", name;
78
+ if (nameParts.length === 2) {
79
+ name = nameParts[1];
80
+ // Validate ns.
81
+ ns = nameParts[0];
82
+ if (ns.length < 2 || ns.length > 255) {
83
+ throw new Error("invalid repository namespace, must be between " +
84
+ "2 and 255 characters: " +
85
+ ns);
86
+ }
87
+ if (!VALID_NS.test(ns)) {
88
+ throw new Error("invalid repository namespace, may only contain " +
89
+ "[a-z0-9._-] characters: " +
90
+ ns);
91
+ }
92
+ if (ns[0] === "-" && ns[ns.length - 1] === "-") {
93
+ throw new Error("invalid repository namespace, cannot start or " +
94
+ "end with a hypen: " +
95
+ ns);
96
+ }
97
+ if (ns.indexOf("--") !== -1) {
98
+ throw new Error("invalid repository namespace, cannot contain " +
99
+ "consecutive hyphens: " +
100
+ ns);
101
+ }
102
+ }
103
+ else {
104
+ name = remoteNameRaw;
105
+ if (index.official) {
106
+ ns = "library";
107
+ }
108
+ }
109
+ // Validate name.
110
+ if (!VALID_REPO.test(name)) {
111
+ throw new Error("invalid repository name, may only contain " +
112
+ "[a-z0-9_/.-] characters: " +
113
+ name);
114
+ }
115
+ const isLibrary = index.official && ns === "library";
116
+ const remoteName = ns ? `${ns}/${name}` : name;
117
+ const localName = index.official
118
+ ? isLibrary
119
+ ? name
120
+ : remoteName
121
+ : `${index.name}/${remoteName}`;
122
+ const canonicalName = index.official
123
+ ? `${parseIndex().name}/${localName}`
124
+ : localName;
125
+ return {
126
+ index,
127
+ official: isLibrary,
128
+ remoteName,
129
+ localName,
130
+ canonicalName,
131
+ };
132
+ }
133
+ /**
134
+ * Parse a docker repo and tag/digest string: [INDEX/]REPO[:TAG|@DIGEST|:TAG@DIGEST]
135
+ *
136
+ * Examples:
137
+ * busybox
138
+ * busybox:latest
139
+ * google/python:3.3
140
+ * docker.io/ubuntu
141
+ * localhost:5000/blarg
142
+ * http://localhost:5000/blarg:latest
143
+ * google/python:3.3@sha256:fb9f16730ac6316afa4d97caa51302199...
144
+ * alpine@sha256:fb9f16730ac6316afa4d97caa5130219927bfcecf0b0...
145
+ *
146
+ * Dev Notes:
147
+ * - TODO Validation on digest and tag would be nice.
148
+ *
149
+ * @param arg {String} The docker repo:tag string to parse. See examples above.
150
+ * @param defaultIndex {Object|String} Optional. The default index to use
151
+ * if not specified with `arg`. If not given the default is 'docker.io'.
152
+ * If given it may either be a string, e.g. 'https://myreg.example.com',
153
+ * or parsed index object, as from `parseIndex()`.
154
+ */
155
+ export function parseRepoAndRef(arg, defaultIndex) {
156
+ // Parse off the tag/digest per
157
+ // https://github.com/docker/docker/blob/0c7b51089c8cd7ef3510a9b40edaa139a7ca91aa/pkg/parsers/parsers.go#L69
158
+ let digest = null;
159
+ let tag = null;
160
+ const atIdx = arg.lastIndexOf("@");
161
+ if (atIdx !== -1) {
162
+ digest = arg.slice(atIdx + 1);
163
+ arg = arg.slice(0, atIdx);
164
+ }
165
+ else {
166
+ tag = DEFAULT_TAG;
167
+ }
168
+ const colonIdx = arg.lastIndexOf(":");
169
+ const slashIdx = arg.lastIndexOf("/");
170
+ if (colonIdx !== -1 && colonIdx > slashIdx) {
171
+ tag = arg.slice(colonIdx + 1);
172
+ arg = arg.slice(0, colonIdx);
173
+ }
174
+ const repo = parseRepo(arg, defaultIndex);
175
+ return {
176
+ ...repo,
177
+ digest,
178
+ tag,
179
+ canonicalRef: [
180
+ repo.canonicalName,
181
+ tag ? `:${tag}` : "",
182
+ digest ? `@${digest}` : "",
183
+ ].join(""),
184
+ };
185
+ }
186
+ export const parseRepoAndTag = parseRepoAndRef;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Authentication types for registry operations
3
+ */
4
+ export type AuthInfo = {
5
+ type: "None";
6
+ } | {
7
+ type: "Basic";
8
+ username: string;
9
+ password: string;
10
+ } | {
11
+ type: "Bearer";
12
+ token: string;
13
+ };
14
+ //# sourceMappingURL=AuthTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthTypes.d.ts","sourceRoot":"","sources":["../../src/types/AuthTypes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Authentication types for registry operations
3
+ */
4
+ export {};