@dpkit/table
Version: 
Data Package implementation in TypeScript.
265 lines • 32.6 kB
JavaScript
import { DataFrame } from "nodejs-polars";
import { describe, expect, it } from "vitest";
import { validateTable } from "./validate.js";
describe("validateTable", () => {
    describe("fields validation with fieldsMatch='exact'", () => {
        it("should pass when fields exactly match", async () => {
            const table = DataFrame({
                id: [1, 2],
                name: ["John", "Jane"],
            }).lazy();
            const schema = {
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toEqual([]);
        });
        it("should not have fields error when fields same length", async () => {
            const table = DataFrame({
                id: [1, 2],
                age: [30, 25],
            }).lazy();
            const schema = {
                fieldsMatch: "exact",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "number" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toEqual([
                {
                    type: "field/name",
                    fieldName: "name",
                    actualFieldName: "age",
                },
            ]);
        });
    });
    it("should detect extra fields", async () => {
        const table = DataFrame({
            id: [1, 2],
            name: ["John", "Jane"],
            age: [30, 25],
        }).lazy();
        const schema = {
            fields: [
                { name: "id", type: "number" },
                { name: "name", type: "string" },
            ],
        };
        const { errors } = await validateTable(table, { schema });
        expect(errors).toContainEqual({
            type: "fields/extra",
            fieldNames: ["age"],
        });
    });
    it("should detect missing fields", async () => {
        const table = DataFrame({
            id: [1, 2],
        }).lazy();
        const schema = {
            fields: [
                { name: "id", type: "number" },
                { name: "name", type: "string" },
            ],
        };
        const { errors } = await validateTable(table, { schema });
        expect(errors).toContainEqual({
            type: "fields/missing",
            fieldNames: ["name"],
        });
    });
    describe("fields validation with fieldsMatch='equal'", () => {
        it("should pass when field names match regardless of order", async () => {
            const table = DataFrame({
                name: ["John", "Jane"],
                id: [1, 2],
            }).lazy();
            const schema = {
                fieldsMatch: "equal",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toEqual([]);
        });
        it("should detect extra fields", async () => {
            const table = DataFrame({
                id: [1, 2],
                name: ["John", "Jane"],
                age: [30, 25],
            }).lazy();
            const schema = {
                fieldsMatch: "equal",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toContainEqual({
                type: "fields/extra",
                fieldNames: ["age"],
            });
        });
        it("should detect missing fields", async () => {
            const table = DataFrame({
                id: [1, 2],
            }).lazy();
            const schema = {
                fieldsMatch: "equal",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toContainEqual({
                type: "fields/missing",
                fieldNames: ["name"],
            });
        });
    });
    describe("fields validation with fieldsMatch='subset'", () => {
        it("should pass when data contains all schema fields", async () => {
            const table = DataFrame({
                id: [1, 2],
                name: ["John", "Jane"],
                age: [30, 25],
            }).lazy();
            const schema = {
                fieldsMatch: "subset",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toEqual([]);
        });
        it("should pass when data contains exact schema fields", async () => {
            const table = DataFrame({
                id: [1, 2],
                name: ["John", "Jane"],
            }).lazy();
            const schema = {
                fieldsMatch: "subset",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toEqual([]);
        });
        it("should detect missing fields", async () => {
            const table = DataFrame({
                id: [1, 2],
            }).lazy();
            const schema = {
                fieldsMatch: "subset",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toContainEqual({
                type: "fields/missing",
                fieldNames: ["name"],
            });
        });
    });
    describe("fields validation with fieldsMatch='superset'", () => {
        it("should pass when schema contains all data fields", async () => {
            const table = DataFrame({
                id: [1, 2],
            }).lazy();
            const schema = {
                fieldsMatch: "superset",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toEqual([]);
        });
        it("should pass when schema contains exact data fields", async () => {
            const table = DataFrame({
                id: [1, 2],
                name: ["John", "Jane"],
            }).lazy();
            const schema = {
                fieldsMatch: "superset",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toEqual([]);
        });
        it("should detect extra fields", async () => {
            const table = DataFrame({
                id: [1, 2],
                name: ["John", "Jane"],
                age: [30, 25],
            }).lazy();
            const schema = {
                fieldsMatch: "superset",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toContainEqual({
                type: "fields/extra",
                fieldNames: ["age"],
            });
        });
    });
    describe("fields validation with fieldsMatch='partial'", () => {
        it("should pass when at least one field matches", async () => {
            const table = DataFrame({
                id: [1, 2],
                age: [30, 25],
            }).lazy();
            const schema = {
                fieldsMatch: "partial",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toEqual([]);
        });
        it("should detect when no fields match", async () => {
            const table = DataFrame({
                age: [30, 25],
                email: ["john@example.com", "jane@example.com"],
            }).lazy();
            const schema = {
                fieldsMatch: "partial",
                fields: [
                    { name: "id", type: "number" },
                    { name: "name", type: "string" },
                ],
            };
            const { errors } = await validateTable(table, { schema });
            expect(errors).toContainEqual({
                type: "fields/missing",
                fieldNames: ["id", "name"],
            });
        });
    });
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUuc3BlYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RhYmxlL3ZhbGlkYXRlLnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUN6QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsTUFBTSxRQUFRLENBQUE7QUFDN0MsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUU3QyxRQUFRLENBQUMsZUFBZSxFQUFFLEdBQUcsRUFBRTtJQUM3QixRQUFRLENBQUMsNENBQTRDLEVBQUUsR0FBRyxFQUFFO1FBQzFELEVBQUUsQ0FBQyx1Q0FBdUMsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNyRCxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUM7Z0JBQ3RCLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ1YsSUFBSSxFQUFFLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQzthQUN2QixDQUFDLENBQUMsSUFBSSxFQUFFLENBQUE7WUFFVCxNQUFNLE1BQU0sR0FBVztnQkFDckIsTUFBTSxFQUFFO29CQUNOLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO29CQUM5QixFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtpQkFDakM7YUFDRixDQUFBO1lBRUQsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sYUFBYSxDQUFDLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUE7WUFFekQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUM1QixDQUFDLENBQUMsQ0FBQTtRQUVGLEVBQUUsQ0FBQyxzREFBc0QsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNwRSxNQUFNLEtBQUssR0FB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QUFDLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUE7WUFDekQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUM1QixDQUFDLENBQUMsQ0FBQTtRQUVGLEVBQUUsQ0FBQyxvQ0FBb0MsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNsRCxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUM7Z0JBQ3RCLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUM7Z0JBQ2IsS0FBSyxFQUFFLENBQUMsa0JBQWtCLEVBQUUsa0JBQWtCLENBQUM7YUFDaEQsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFBO1lBRVQsTUFBTSxNQUFNLEdBQVc7Z0JBQ3JCLFdBQVcsRUFBRSxTQUFTO2dCQUN0QixNQUFNLEVBQUU7b0JBQ04sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUU7b0JBQzlCLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO2lCQUNqQzthQUNGLENBQUE7WUFFRCxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsTUFBTSxhQUFhLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQTtZQUN6RCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsY0FBYyxDQUFDO2dCQUM1QixJQUFJLEVBQUUsZ0JBQWdCO2dCQUN0QixVQUFVLEVBQUUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDO2FBQzNCLENBQUMsQ0FBQTtRQUNKLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU2NoZW1hIH0gZnJvbSBcIkBkcGtpdC9jb3JlXCJcbmltcG9ydCB7IERhdGFGcmFtZSB9IGZyb20gXCJub2RlanMtcG9sYXJzXCJcbmltcG9ydCB7IGRlc2NyaWJlLCBleHBlY3QsIGl0IH0gZnJvbSBcInZpdGVzdFwiXG5pbXBvcnQgeyB2YWxpZGF0ZVRhYmxlIH0gZnJvbSBcIi4vdmFsaWRhdGUudHNcIlxuXG5kZXNjcmliZShcInZhbGlkYXRlVGFibGVcIiwgKCkgPT4ge1xuICBkZXNjcmliZShcImZpZWxkcyB2YWxpZGF0aW9uIHdpdGggZmllbGRzTWF0Y2g9J2V4YWN0J1wiLCAoKSA9PiB7XG4gICAgaXQoXCJzaG91bGQgcGFzcyB3aGVuIGZpZWxkcyBleGFjdGx5IG1hdGNoXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgICAgbmFtZTogW1wiSm9oblwiLCBcIkphbmVcIl0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgdmFsaWRhdGVUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcblxuICAgICAgZXhwZWN0KGVycm9ycykudG9FcXVhbChbXSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgbm90IGhhdmUgZmllbGRzIGVycm9yIHdoZW4gZmllbGRzIHNhbWUgbGVuZ3RoXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgICAgYWdlOiBbMzAsIDI1XSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzTWF0Y2g6IFwiZXhhY3RcIixcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgZXJyb3JzIH0gPSBhd2FpdCB2YWxpZGF0ZVRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiBcImZpZWxkL25hbWVcIixcbiAgICAgICAgICBmaWVsZE5hbWU6IFwibmFtZVwiLFxuICAgICAgICAgIGFjdHVhbEZpZWxkTmFtZTogXCJhZ2VcIixcbiAgICAgICAgfSxcbiAgICAgIF0pXG4gICAgfSlcbiAgfSlcblxuICBpdChcInNob3VsZCBkZXRlY3QgZXh0cmEgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICBpZDogWzEsIDJdLFxuICAgICAgbmFtZTogW1wiSm9oblwiLCBcIkphbmVcIl0sXG4gICAgICBhZ2U6IFszMCwgMjVdLFxuICAgIH0pLmxhenkoKVxuXG4gICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICBmaWVsZHM6IFtcbiAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgdmFsaWRhdGVUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcbiAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICB0eXBlOiBcImZpZWxkcy9leHRyYVwiLFxuICAgICAgZmllbGROYW1lczogW1wiYWdlXCJdLFxuICAgIH0pXG4gIH0pXG5cbiAgaXQoXCJzaG91bGQgZGV0ZWN0IG1pc3NpbmcgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICBpZDogWzEsIDJdLFxuICAgIH0pLmxhenkoKVxuXG4gICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICBmaWVsZHM6IFtcbiAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgdmFsaWRhdGVUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcbiAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICB0eXBlOiBcImZpZWxkcy9taXNzaW5nXCIsXG4gICAgICBmaWVsZE5hbWVzOiBbXCJuYW1lXCJdLFxuICAgIH0pXG4gIH0pXG5cbiAgZGVzY3JpYmUoXCJmaWVsZHMgdmFsaWRhdGlvbiB3aXRoIGZpZWxkc01hdGNoPSdlcXVhbCdcIiwgKCkgPT4ge1xuICAgIGl0KFwic2hvdWxkIHBhc3Mgd2hlbiBmaWVsZCBuYW1lcyBtYXRjaCByZWdhcmRsZXNzIG9mIG9yZGVyXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgbmFtZTogW1wiSm9oblwiLCBcIkphbmVcIl0sXG4gICAgICAgIGlkOiBbMSwgMl0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkc01hdGNoOiBcImVxdWFsXCIsXG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgdmFsaWRhdGVUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvRXF1YWwoW10pXG4gICAgfSlcblxuICAgIGl0KFwic2hvdWxkIGRldGVjdCBleHRyYSBmaWVsZHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBpZDogWzEsIDJdLFxuICAgICAgICBuYW1lOiBbXCJKb2huXCIsIFwiSmFuZVwiXSxcbiAgICAgICAgYWdlOiBbMzAsIDI1XSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzTWF0Y2g6IFwiZXF1YWxcIixcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgZXJyb3JzIH0gPSBhd2FpdCB2YWxpZGF0ZVRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImZpZWxkcy9leHRyYVwiLFxuICAgICAgICBmaWVsZE5hbWVzOiBbXCJhZ2VcIl0sXG4gICAgICB9KVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBkZXRlY3QgbWlzc2luZyBmaWVsZHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBpZDogWzEsIDJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHNNYXRjaDogXCJlcXVhbFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBlcnJvcnMgfSA9IGF3YWl0IHZhbGlkYXRlVGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICAgIHR5cGU6IFwiZmllbGRzL21pc3NpbmdcIixcbiAgICAgICAgZmllbGROYW1lczogW1wibmFtZVwiXSxcbiAgICAgIH0pXG4gICAgfSlcbiAgfSlcblxuICBkZXNjcmliZShcImZpZWxkcyB2YWxpZGF0aW9uIHdpdGggZmllbGRzTWF0Y2g9J3N1YnNldCdcIiwgKCkgPT4ge1xuICAgIGl0KFwic2hvdWxkIHBhc3Mgd2hlbiBkYXRhIGNvbnRhaW5zIGFsbCBzY2hlbWEgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgICAgbmFtZTogW1wiSm9oblwiLCBcIkphbmVcIl0sXG4gICAgICAgIGFnZTogWzMwLCAyNV0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkc01hdGNoOiBcInN1YnNldFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBlcnJvcnMgfSA9IGF3YWl0IHZhbGlkYXRlVGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0VxdWFsKFtdKVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBwYXNzIHdoZW4gZGF0YSBjb250YWlucyBleGFjdCBzY2hlbWEgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgICAgbmFtZTogW1wiSm9oblwiLCBcIkphbmVcIl0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkc01hdGNoOiBcInN1YnNldFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBlcnJvcnMgfSA9IGF3YWl0IHZhbGlkYXRlVGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0VxdWFsKFtdKVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBkZXRlY3QgbWlzc2luZyBmaWVsZHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBpZDogWzEsIDJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHNNYXRjaDogXCJzdWJzZXRcIixcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgZXJyb3JzIH0gPSBhd2FpdCB2YWxpZGF0ZVRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImZpZWxkcy9taXNzaW5nXCIsXG4gICAgICAgIGZpZWxkTmFtZXM6IFtcIm5hbWVcIl0sXG4gICAgICB9KVxuICAgIH0pXG4gIH0pXG5cbiAgZGVzY3JpYmUoXCJmaWVsZHMgdmFsaWRhdGlvbiB3aXRoIGZpZWxkc01hdGNoPSdzdXBlcnNldCdcIiwgKCkgPT4ge1xuICAgIGl0KFwic2hvdWxkIHBhc3Mgd2hlbiBzY2hlbWEgY29udGFpbnMgYWxsIGRhdGEgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzTWF0Y2g6IFwic3VwZXJzZXRcIixcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgZXJyb3JzIH0gPSBhd2FpdCB2YWxpZGF0ZVRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9FcXVhbChbXSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgcGFzcyB3aGVuIHNjaGVtYSBjb250YWlucyBleGFjdCBkYXRhIGZpZWxkc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGlkOiBbMSwgMl0sXG4gICAgICAgIG5hbWU6IFtcIkpvaG5cIiwgXCJKYW5lXCJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHNNYXRjaDogXCJzdXBlcnNldFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBlcnJvcnMgfSA9IGF3YWl0IHZhbGlkYXRlVGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0VxdWFsKFtdKVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBkZXRlY3QgZXh0cmEgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgICAgbmFtZTogW1wiSm9oblwiLCBcIkphbmVcIl0sXG4gICAgICAgIGFnZTogWzMwLCAyNV0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkc01hdGNoOiBcInN1cGVyc2V0XCIsXG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgdmFsaWRhdGVUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgICAgdHlwZTogXCJmaWVsZHMvZXh0cmFcIixcbiAgICAgICAgZmllbGROYW1lczogW1wiYWdlXCJdLFxuICAgICAgfSlcbiAgICB9KVxuICB9KVxuXG4gIGRlc2NyaWJlKFwiZmllbGRzIHZhbGlkYXRpb24gd2l0aCBmaWVsZHNNYXRjaD0ncGFydGlhbCdcIiwgKCkgPT4ge1xuICAgIGl0KFwic2hvdWxkIHBhc3Mgd2hlbiBhdCBsZWFzdCBvbmUgZmllbGQgbWF0Y2hlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGlkOiBbMSwgMl0sXG4gICAgICAgIGFnZTogWzMwLCAyNV0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkc01hdGNoOiBcInBhcnRpYWxcIixcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgZXJyb3JzIH0gPSBhd2FpdCB2YWxpZGF0ZVRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9FcXVhbChbXSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgZGV0ZWN0IHdoZW4gbm8gZmllbGRzIG1hdGNoXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgYWdlOiBbMzAsIDI1XSxcbiAgICAgICAgZW1haWw6IFtcImpvaG5AZXhhbXBsZS5jb21cIiwgXCJqYW5lQGV4YW1wbGUuY29tXCJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHNNYXRjaDogXCJwYXJ0aWFsXCIsXG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgdmFsaWRhdGVUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgICAgdHlwZTogXCJmaWVsZHMvbWlzc2luZ1wiLFxuICAgICAgICBmaWVsZE5hbWVzOiBbXCJpZFwiLCBcIm5hbWVcIl0sXG4gICAgICB9KVxuICAgIH0pXG4gIH0pXG59KVxuIl19