"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DockerHubTagsPage = exports.DockerHubTag = exports.ManifestJson = exports.Manifest = exports.DistributionListManifest = exports.DistributionManifest = exports.OciImageIndexManifest = exports.OciImageManifest = exports.OciHelmConfig = exports.OciImageConfig = exports.Descriptor = exports.ManifestObject = void 0;
const zod_1 = require("zod");
const logger_1 = require("../../../logger");
const schema_utils_1 = require("../../../util/schema-utils");
// OCI manifests
/**
 *  OCI manifest object
 */
exports.ManifestObject = zod_1.z.object({
    schemaVersion: zod_1.z.literal(2),
    mediaType: zod_1.z.string().optional(),
});
/**
 * Oci descriptor
 * https://github.com/opencontainers/image-spec/blob/main/descriptor.md
 */
exports.Descriptor = zod_1.z.object({
    mediaType: zod_1.z.string(),
    digest: zod_1.z.string(),
    size: zod_1.z.number().int().gt(0).optional(),
});
/**
 * OCI platform properties
 * https://github.com/opencontainers/image-spec/blob/main/image-index.md
 */
const OciPlatform = zod_1.z
    .object({
    architecture: zod_1.z.string().optional(),
})
    .optional();
/**
 * OCI Image Configuration.
 *
 * Compatible with old docker configiguration.
 * https://github.com/opencontainers/image-spec/blob/main/config.md
 */
exports.OciImageConfig = zod_1.z.object({
    // This is required by the spec, but probably not present in the wild.
    architecture: zod_1.z.string().optional(),
    config: zod_1.z.object({ Labels: zod_1.z.record(zod_1.z.string()).optional() }).optional(),
});
/**
 * OCI Helm Configuration
 * https://helm.sh/docs/topics/charts/#the-chartyaml-file
 */
exports.OciHelmConfig = zod_1.z.object({
    name: zod_1.z.string(),
    version: zod_1.z.string(),
    home: zod_1.z.string().optional(),
    sources: zod_1.z.array(zod_1.z.string()).optional(),
});
/**
 * OCI Image Manifest
 * The same structure as docker image manifest, but mediaType is not required and is not present in the wild.
 * https://github.com/opencontainers/image-spec/blob/main/manifest.md
 */
exports.OciImageManifest = exports.ManifestObject.extend({
    mediaType: zod_1.z.literal('application/vnd.oci.image.manifest.v1+json'),
    config: exports.Descriptor.extend({
        mediaType: zod_1.z.enum([
            'application/vnd.oci.image.config.v1+json',
            'application/vnd.cncf.helm.config.v1+json',
        ]),
    }),
    annotations: zod_1.z.record(zod_1.z.string()).optional(),
});
/**
 * OCI Image List
 * mediaType is not required.
 * https://github.com/opencontainers/image-spec/blob/main/image-index.md
 */
exports.OciImageIndexManifest = exports.ManifestObject.extend({
    mediaType: zod_1.z.literal('application/vnd.oci.image.index.v1+json'),
    manifests: zod_1.z.array(exports.Descriptor.extend({
        mediaType: zod_1.z.enum([
            'application/vnd.oci.image.manifest.v1+json',
            'application/vnd.oci.image.index.v1+json',
        ]),
        platform: OciPlatform,
    })),
    annotations: zod_1.z.record(zod_1.z.string()).optional(),
});
// Old Docker manifests
/**
 * Image Manifest
 * https://docs.docker.com/registry/spec/manifest-v2-2/#image-manifest
 */
exports.DistributionManifest = exports.ManifestObject.extend({
    mediaType: zod_1.z.literal('application/vnd.docker.distribution.manifest.v2+json'),
    config: exports.Descriptor.extend({
        mediaType: zod_1.z.literal('application/vnd.docker.container.image.v1+json'),
    }),
});
/**
 * Manifest List
 * https://docs.docker.com/registry/spec/manifest-v2-2/#manifest-list
 */
exports.DistributionListManifest = exports.ManifestObject.extend({
    mediaType: zod_1.z.literal('application/vnd.docker.distribution.manifest.list.v2+json'),
    manifests: zod_1.z.array(exports.Descriptor.extend({
        mediaType: zod_1.z.literal('application/vnd.docker.distribution.manifest.v2+json'),
        platform: OciPlatform,
    })),
});
// Combined manifests
exports.Manifest = exports.ManifestObject.passthrough()
    .transform((value, ctx) => {
    if (value.mediaType === undefined) {
        if ('config' in value) {
            value.mediaType = 'application/vnd.oci.image.manifest.v1+json';
        }
        else if ('manifests' in value) {
            value.mediaType = 'application/vnd.oci.image.index.v1+json';
        }
        else {
            ctx.addIssue({
                code: 'custom',
                message: 'Invalid manifest, missing mediaType.',
            });
            return zod_1.z.NEVER;
        }
    }
    return value;
})
    .pipe(zod_1.z.discriminatedUnion('mediaType', [
    exports.DistributionManifest,
    exports.DistributionListManifest,
    exports.OciImageManifest,
    exports.OciImageIndexManifest,
]));
exports.ManifestJson = schema_utils_1.Json.pipe(exports.Manifest);
exports.DockerHubTag = zod_1.z
    .object({
    name: zod_1.z.string(),
    tag_last_pushed: zod_1.z.string().datetime().nullable().catch(null),
    digest: zod_1.z.string().nullable().catch(null),
})
    .transform(({ name, tag_last_pushed, digest }) => {
    const release = { version: name };
    if (tag_last_pushed) {
        release.releaseTimestamp = tag_last_pushed;
    }
    if (digest) {
        release.newDigest = digest;
    }
    return release;
});
exports.DockerHubTagsPage = zod_1.z
    .object({
    next: zod_1.z.string().nullable().catch(null),
    results: (0, schema_utils_1.LooseArray)(exports.DockerHubTag, {
        onError: /* istanbul ignore next */ ({ error }) => {
            logger_1.logger.debug({ error }, 'Docker: Failed to parse some tags from Docker Hub');
        },
    }),
})
    .transform(({ next, results }) => ({
    nextPage: next,
    items: results,
}));
//# sourceMappingURL=schema.js.map