@dpkit/core
Version:
Fast TypeScript data management framework built on top of the Data Package standard and Polars DataFrames
272 lines • 27.3 kB
JavaScript
import { join, relative } from "node:path";
import { describe, expect, it } from "vitest";
import { denormalizePath, getBasepath, getFilename, isRemotePath, normalizePath, } from "./path.js";
describe("isRemotePath", () => {
it.each([
{
description: "http URL",
path: "http://example.com/path/to/file.txt",
isRemote: true,
},
{
description: "https URL",
path: "https://example.com/path/to/file.txt",
isRemote: true,
},
{
description: "ftp URL",
path: "ftp://example.com/path/to/file.txt",
isRemote: true,
},
{
description: "file URL",
path: "file:///path/to/file.txt",
isRemote: false,
},
{
description: "absolute path",
path: "/path/to/file.txt",
isRemote: false,
},
{
description: "relative path",
path: "path/to/file.txt",
isRemote: false,
},
{
description: "current directory path",
path: "./file.txt",
isRemote: false,
},
{
description: "parent directory path",
path: "../file.txt",
isRemote: false,
},
{
description: "empty string",
path: "",
isRemote: false,
},
{
// new URL considers this to be a valid URL
description: "protocol without slashes",
path: "http:example.com",
isRemote: true,
},
])("$description", ({ path, isRemote }) => {
expect(isRemotePath(path)).toBe(isRemote);
});
});
describe("getFilename", () => {
it.each([
{
description: "simple filename",
path: "file.txt",
filename: "file.txt",
},
{
description: "directory path with filename",
path: "some/path/to/file.txt",
filename: "file.txt",
},
{
description: "remote HTTP URL",
path: "http://example.com/path/to/file.txt",
filename: "file.txt",
},
{
description: "remote HTTPS URL",
path: "https://example.com/path/to/file.txt",
filename: "file.txt",
},
{
description: "URL with query parameters",
path: "https://example.com/path/to/file.txt?query=param",
filename: "file.txt",
},
{
description: "URL with hash",
path: "https://example.com/path/to/file.txt#section",
filename: "file.txt",
},
{
description: "URL with query and hash",
path: "https://example.com/path/to/file.txt?query=param#section",
filename: "file.txt",
},
{
description: "URL with no filename",
path: "https://example.com/path/",
filename: undefined,
},
{
description: "local path with no filename",
path: "some/path/",
filename: undefined,
},
])("$description", ({ path, filename }) => {
expect(getFilename(path)).toEqual(filename);
});
});
describe("getBasepath", () => {
it.each([
{
description: "http URL with file",
path: "http://example.com/path/to/file.txt",
basepath: "http://example.com/path/to",
},
{
description: "https URL with file",
path: "https://example.com/path/to/file.txt",
basepath: "https://example.com/path/to",
},
{
description: "URL with query parameters",
path: "https://example.com/path/to/file.txt?query=param",
basepath: "https://example.com/path/to",
},
{
description: "URL with hash",
path: "https://example.com/path/to/file.txt#section",
basepath: "https://example.com/path/to",
},
{
description: "URL with no file",
path: "https://example.com/path/to/",
basepath: "https://example.com/path/to",
},
{
description: "URL with only domain",
path: "https://example.com",
basepath: "https://example.com",
},
{
description: "local file path",
path: "some/path/to/file.txt",
basepath: join("some", "path", "to"),
},
{
description: "local path with no file",
path: "some/path/to/",
basepath: join("some", "path"),
},
{
description: "root level file",
path: "file.txt",
basepath: "",
},
])("$description", ({ path, basepath }) => {
expect(getBasepath(path)).toEqual(basepath);
});
});
describe("normalizePath", () => {
it.each([
{
description: "local path without basepath",
path: "path/to/file.txt",
basepath: undefined,
normalizedPath: join("path", "to", "file.txt"),
},
{
description: "local path with local basepath",
path: "file.txt",
basepath: "path/to",
normalizedPath: join("path", "to", "file.txt"),
},
{
description: "remote path",
path: "http://example.com/path/to/file.txt",
basepath: undefined,
normalizedPath: "http://example.com/path/to/file.txt",
},
{
description: "remote path with query string",
path: "http://example.com/path/to/file.txt?query=param",
basepath: undefined,
normalizedPath: "http://example.com/path/to/file.txt?query=param",
},
{
description: "local path with remote basepath",
path: "path/to/file.txt",
basepath: "http://example.com",
normalizedPath: "http://example.com/path/to/file.txt",
},
{
description: "local path with absolute basepath",
path: "file.txt",
basepath: "/absolute/path",
normalizedPath: relative(process.cwd(), "/absolute/path/file.txt"),
},
{
description: "path with empty basepath",
path: "path/to/file.txt",
basepath: "",
normalizedPath: join("path", "to", "file.txt"),
},
])("$description", ({ path, basepath, normalizedPath }) => {
expect(normalizePath(path, { basepath })).toEqual(normalizedPath);
});
it.each([
{
description: "absolute path",
path: "/absolute/path/to/file.txt",
basepath: undefined,
},
{
description: "local traversed path",
path: "../file.txt",
basepath: "/folder",
},
{
description: "remote traversed path",
path: "../file.txt",
basepath: "http://example.com/data",
},
])("$description -- throw", ({ path, basepath }) => {
expect(() => normalizePath(path, { basepath })).toThrow();
});
});
describe("denormalizePath", () => {
it.each([
{
description: "remote URL without basepath",
path: "http://example.com/path/to/file.txt",
basepath: undefined,
denormalizedPath: "http://example.com/path/to/file.txt",
},
{
description: "remote URL with basepath",
path: "http://example.com/path/to/file.txt",
basepath: "data",
denormalizedPath: "http://example.com/path/to/file.txt",
},
{
description: "local file in subfolder",
path: "/tmp/data/file.csv",
basepath: "/tmp",
denormalizedPath: "data/file.csv",
},
{
description: "local file in direct child folder",
path: "/tmp/file.csv",
basepath: "/tmp",
denormalizedPath: "file.csv",
},
{
description: "local file with deeply nested basepath",
path: "/tmp/data/nested/deep/file.csv",
basepath: "/tmp/data/nested",
denormalizedPath: "deep/file.csv",
},
{
description: "local file with multi-level basepath",
path: "/home/user/projects/data/file.csv",
basepath: "/home/user/projects",
denormalizedPath: "data/file.csv",
},
])("$description", ({ path, basepath, denormalizedPath }) => {
expect(denormalizePath(path, { basepath })).toEqual(denormalizedPath);
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0aC5zcGVjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vZ2VuZXJhbC9wYXRoLnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDMUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sUUFBUSxDQUFBO0FBQzdDLE9BQU8sRUFDTCxlQUFlLEVBQ2YsV0FBVyxFQUNYLFdBQVcsRUFDWCxZQUFZLEVBQ1osYUFBYSxHQUNkLE1BQU0sV0FBVyxDQUFBO0FBRWxCLFFBQVEsQ0FBQyxjQUFjLEVBQUUsR0FBRyxFQUFFO0lBQzVCLEVBQUUsQ0FBQyxJQUFJLENBQUM7UUFDTjtZQUNFLFdBQVcsRUFBRSxVQUFVO1lBQ3ZCLElBQUksRUFBRSxxQ0FBcUM7WUFDM0MsUUFBUSxFQUFFLElBQUk7U0FDZjtRQUNEO1lBQ0UsV0FBVyxFQUFFLFdBQVc7WUFDeEIsSUFBSSxFQUFFLHNDQUFzQztZQUM1QyxRQUFRLEVBQUUsSUFBSTtTQUNmO1FBQ0Q7WUFDRSxXQUFXLEVBQUUsU0FBUztZQUN0QixJQUFJLEVBQUUsb0NBQW9DO1lBQzFDLFFBQVEsRUFBRSxJQUFJO1NBQ2Y7UUFDRDtZQUNFLFdBQVcsRUFBRSxVQUFVO1lBQ3ZCLElBQUksRUFBRSwwQkFBMEI7WUFDaEMsUUFBUSxFQUFFLEtBQUs7U0FDaEI7UUFDRDtZQUNFLFdBQVcsRUFBRSxlQUFlO1lBQzVCLElBQUksRUFBRSxtQkFBbUI7WUFDekIsUUFBUSxFQUFFLEtBQUs7U0FDaEI7UUFDRDtZQUNFLFdBQVcsRUFBRSxlQUFlO1lBQzVCLElBQUksRUFBRSxrQkFBa0I7WUFDeEIsUUFBUSxFQUFFLEtBQUs7U0FDaEI7UUFDRDtZQUNFLFdBQVcsRUFBRSx3QkFBd0I7WUFDckMsSUFBSSxFQUFFLFlBQVk7WUFDbEIsUUFBUSxFQUFFLEtBQUs7U0FDaEI7UUFDRDtZQUNF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QUFxQjtZQUMvQixnQkFBZ0IsRUFBRSxlQUFlO1NBQ2xDO0tBQ0YsQ0FBQyxDQUFDLGNBQWMsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLEVBQUU7UUFDMUQsTUFBTSxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUE7SUFDdkUsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGpvaW4sIHJlbGF0aXZlIH0gZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyBkZXNjcmliZSwgZXhwZWN0LCBpdCB9IGZyb20gXCJ2aXRlc3RcIlxuaW1wb3J0IHtcbiAgZGVub3JtYWxpemVQYXRoLFxuICBnZXRCYXNlcGF0aCxcbiAgZ2V0RmlsZW5hbWUsXG4gIGlzUmVtb3RlUGF0aCxcbiAgbm9ybWFsaXplUGF0aCxcbn0gZnJvbSBcIi4vcGF0aC50c1wiXG5cbmRlc2NyaWJlKFwiaXNSZW1vdGVQYXRoXCIsICgpID0+IHtcbiAgaXQuZWFjaChbXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiaHR0cCBVUkxcIixcbiAgICAgIHBhdGg6IFwiaHR0cDovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHRcIixcbiAgICAgIGlzUmVtb3RlOiB0cnVlLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiaHR0cHMgVVJMXCIsXG4gICAgICBwYXRoOiBcImh0dHBzOi8vZXhhbXBsZS5jb20vcGF0aC90by9maWxlLnR4dFwiLFxuICAgICAgaXNSZW1vdGU6IHRydWUsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJmdHAgVVJMXCIsXG4gICAgICBwYXRoOiBcImZ0cDovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHRcIixcbiAgICAgIGlzUmVtb3RlOiB0cnVlLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiZmlsZSBVUkxcIixcbiAgICAgIHBhdGg6IFwiZmlsZTovLy9wYXRoL3RvL2ZpbGUudHh0XCIsXG4gICAgICBpc1JlbW90ZTogZmFsc2UsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJhYnNvbHV0ZSBwYXRoXCIsXG4gICAgICBwYXRoOiBcIi9wYXRoL3RvL2ZpbGUudHh0XCIsXG4gICAgICBpc1JlbW90ZTogZmFsc2UsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJyZWxhdGl2ZSBwYXRoXCIsXG4gICAgICBwYXRoOiBcInBhdGgvdG8vZmlsZS50eHRcIixcbiAgICAgIGlzUmVtb3RlOiBmYWxzZSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcImN1cnJlbnQgZGlyZWN0b3J5IHBhdGhcIixcbiAgICAgIHBhdGg6IFwiLi9maWxlLnR4dFwiLFxuICAgICAgaXNSZW1vdGU6IGZhbHNlLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwicGFyZW50IGRpcmVjdG9yeSBwYXRoXCIsXG4gICAgICBwYXRoOiBcIi4uL2ZpbGUudHh0XCIsXG4gICAgICBpc1JlbW90ZTogZmFsc2UsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJlbXB0eSBzdHJpbmdcIixcbiAgICAgIHBhdGg6IFwiXCIsXG4gICAgICBpc1JlbW90ZTogZmFsc2UsXG4gICAgfSxcbiAgICB7XG4gICAgICAvLyBuZXcgVVJMIGNvbnNpZGVycyB0aGlzIHRvIGJlIGEgdmFsaWQgVVJMXG4gICAgICBkZXNjcmlwdGlvbjogXCJwcm90b2NvbCB3aXRob3V0IHNsYXNoZXNcIixcbiAgICAgIHBhdGg6IFwiaHR0cDpleGFtcGxlLmNvbVwiLFxuICAgICAgaXNSZW1vdGU6IHRydWUsXG4gICAgfSxcbiAgXSkoXCIkZGVzY3JpcHRpb25cIiwgKHsgcGF0aCwgaXNSZW1vdGUgfSkgPT4ge1xuICAgIGV4cGVjdChpc1JlbW90ZVBhdGgocGF0aCkpLnRvQmUoaXNSZW1vdGUpXG4gIH0pXG59KVxuXG5kZXNjcmliZShcImdldEZpbGVuYW1lXCIsICgpID0+IHtcbiAgaXQuZWFjaChbXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwic2ltcGxlIGZpbGVuYW1lXCIsXG4gICAgICBwYXRoOiBcImZpbGUudHh0XCIsXG4gICAgICBmaWxlbmFtZTogXCJmaWxlLnR4dFwiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiZGlyZWN0b3J5IHBhdGggd2l0aCBmaWxlbmFtZVwiLFxuICAgICAgcGF0aDogXCJzb21lL3BhdGgvdG8vZmlsZS50eHRcIixcbiAgICAgIGZpbGVuYW1lOiBcImZpbGUudHh0XCIsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJyZW1vdGUgSFRUUCBVUkxcIixcbiAgICAgIHBhdGg6IFwiaHR0cDovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHRcIixcbiAgICAgIGZpbGVuYW1lOiBcImZpbGUudHh0XCIsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJyZW1vdGUgSFRUUFMgVVJMXCIsXG4gICAgICBwYXRoOiBcImh0dHBzOi8vZXhhbXBsZS5jb20vcGF0aC90by9maWxlLnR4dFwiLFxuICAgICAgZmlsZW5hbWU6IFwiZmlsZS50eHRcIixcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIlVSTCB3aXRoIHF1ZXJ5IHBhcmFtZXRlcnNcIixcbiAgICAgIHBhdGg6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9wYXRoL3RvL2ZpbGUudHh0P3F1ZXJ5PXBhcmFtXCIsXG4gICAgICBmaWxlbmFtZTogXCJmaWxlLnR4dFwiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiVVJMIHdpdGggaGFzaFwiLFxuICAgICAgcGF0aDogXCJodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHQjc2VjdGlvblwiLFxuICAgICAgZmlsZW5hbWU6IFwiZmlsZS50eHRcIixcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcIlVSTCB3aXRoIHF1ZXJ5IGFuZCBoYXNoXCIsXG4gICAgICBwYXRoOiBcImh0dHBzOi8vZXhhbXBsZS5jb20vcGF0aC90by9maWxlLnR4dD9xdWVyeT1wYXJhbSNzZWN0aW9uXCIsXG4gICAgICBmaWxlbmFtZTogXCJmaWxlLnR4dFwiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiVVJMIHdpdGggbm8gZmlsZW5hbWVcIixcbiAgICAgIHBhdGg6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9wYXRoL1wiLFxuICAgICAgZmlsZW5hbWU6IHVuZGVmaW5lZCxcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcImxvY2FsIHBhdGggd2l0aCBubyBmaWxlbmFtZVwiLFxuICAgICAgcGF0aDogXCJzb21lL3BhdGgvXCIsXG4gICAgICBmaWxlbmFtZTogdW5kZWZpbmVkLFxuICAgIH0sXG4gIF0pKFwiJGRlc2NyaXB0aW9uXCIsICh7IHBhdGgsIGZpbGVuYW1lIH0pID0+IHtcbiAgICBleHBlY3QoZ2V0RmlsZW5hbWUocGF0aCkpLnRvRXF1YWwoZmlsZW5hbWUpXG4gIH0pXG59KVxuXG5kZXNjcmliZShcImdldEJhc2VwYXRoXCIsICgpID0+IHtcbiAgaXQuZWFjaChbXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiaHR0cCBVUkwgd2l0aCBmaWxlXCIsXG4gICAgICBwYXRoOiBcImh0dHA6Ly9leGFtcGxlLmNvbS9wYXRoL3RvL2ZpbGUudHh0XCIsXG4gICAgICBiYXNlcGF0aDogXCJodHRwOi8vZXhhbXBsZS5jb20vcGF0aC90b1wiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiaHR0cHMgVVJMIHdpdGggZmlsZVwiLFxuICAgICAgcGF0aDogXCJodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHRcIixcbiAgICAgIGJhc2VwYXRoOiBcImh0dHBzOi8vZXhhbXBsZS5jb20vcGF0aC90b1wiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiVVJMIHdpdGggcXVlcnkgcGFyYW1ldGVyc1wiLFxuICAgICAgcGF0aDogXCJodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHQ/cXVlcnk9cGFyYW1cIixcbiAgICAgIGJhc2VwYXRoOiBcImh0dHBzOi8vZXhhbXBsZS5jb20vcGF0aC90b1wiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiVVJMIHdpdGggaGFzaFwiLFxuICAgICAgcGF0aDogXCJodHRwczovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHQjc2VjdGlvblwiLFxuICAgICAgYmFzZXBhdGg6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9wYXRoL3RvXCIsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJVUkwgd2l0aCBubyBmaWxlXCIsXG4gICAgICBwYXRoOiBcImh0dHBzOi8vZXhhbXBsZS5jb20vcGF0aC90by9cIixcbiAgICAgIGJhc2VwYXRoOiBcImh0dHBzOi8vZXhhbXBsZS5jb20vcGF0aC90b1wiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwiVVJMIHdpdGggb25seSBkb21haW5cIixcbiAgICAgIHBhdGg6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbVwiLFxuICAgICAgYmFzZXBhdGg6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbVwiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwibG9jYWwgZmlsZSBwYXRoXCIsXG4gICAgICBwYXRoOiBcInNvbWUvcGF0aC90by9maWxlLnR4dFwiLFxuICAgICAgYmFzZXBhdGg6IGpvaW4oXCJzb21lXCIsIFwicGF0aFwiLCBcInRvXCIpLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwibG9jYWwgcGF0aCB3aXRoIG5vIGZpbGVcIixcbiAgICAgIHBhdGg6IFwic29tZS9wYXRoL3RvL1wiLFxuICAgICAgYmFzZXBhdGg6IGpvaW4oXCJzb21lXCIsIFwicGF0aFwiKSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcInJvb3QgbGV2ZWwgZmlsZVwiLFxuICAgICAgcGF0aDogXCJmaWxlLnR4dFwiLFxuICAgICAgYmFzZXBhdGg6IFwiXCIsXG4gICAgfSxcbiAgXSkoXCIkZGVzY3JpcHRpb25cIiwgKHsgcGF0aCwgYmFzZXBhdGggfSkgPT4ge1xuICAgIGV4cGVjdChnZXRCYXNlcGF0aChwYXRoKSkudG9FcXVhbChiYXNlcGF0aClcbiAgfSlcbn0pXG5cbmRlc2NyaWJlKFwibm9ybWFsaXplUGF0aFwiLCAoKSA9PiB7XG4gIGl0LmVhY2goW1xuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcImxvY2FsIHBhdGggd2l0aG91dCBiYXNlcGF0aFwiLFxuICAgICAgcGF0aDogXCJwYXRoL3RvL2ZpbGUudHh0XCIsXG4gICAgICBiYXNlcGF0aDogdW5kZWZpbmVkLFxuICAgICAgbm9ybWFsaXplZFBhdGg6IGpvaW4oXCJwYXRoXCIsIFwidG9cIiwgXCJmaWxlLnR4dFwiKSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcImxvY2FsIHBhdGggd2l0aCBsb2NhbCBiYXNlcGF0aFwiLFxuICAgICAgcGF0aDogXCJmaWxlLnR4dFwiLFxuICAgICAgYmFzZXBhdGg6IFwicGF0aC90b1wiLFxuICAgICAgbm9ybWFsaXplZFBhdGg6IGpvaW4oXCJwYXRoXCIsIFwidG9cIiwgXCJmaWxlLnR4dFwiKSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcInJlbW90ZSBwYXRoXCIsXG4gICAgICBwYXRoOiBcImh0dHA6Ly9leGFtcGxlLmNvbS9wYXRoL3RvL2ZpbGUudHh0XCIsXG4gICAgICBiYXNlcGF0aDogdW5kZWZpbmVkLFxuICAgICAgbm9ybWFsaXplZFBhdGg6IFwiaHR0cDovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHRcIixcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcInJlbW90ZSBwYXRoIHdpdGggcXVlcnkgc3RyaW5nXCIsXG4gICAgICBwYXRoOiBcImh0dHA6Ly9leGFtcGxlLmNvbS9wYXRoL3RvL2ZpbGUudHh0P3F1ZXJ5PXBhcmFtXCIsXG4gICAgICBiYXNlcGF0aDogdW5kZWZpbmVkLFxuICAgICAgbm9ybWFsaXplZFBhdGg6IFwiaHR0cDovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHQ/cXVlcnk9cGFyYW1cIixcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcImxvY2FsIHBhdGggd2l0aCByZW1vdGUgYmFzZXBhdGhcIixcbiAgICAgIHBhdGg6IFwicGF0aC90by9maWxlLnR4dFwiLFxuICAgICAgYmFzZXBhdGg6IFwiaHR0cDovL2V4YW1wbGUuY29tXCIsXG4gICAgICBub3JtYWxpemVkUGF0aDogXCJodHRwOi8vZXhhbXBsZS5jb20vcGF0aC90by9maWxlLnR4dFwiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwibG9jYWwgcGF0aCB3aXRoIGFic29sdXRlIGJhc2VwYXRoXCIsXG4gICAgICBwYXRoOiBcImZpbGUudHh0XCIsXG4gICAgICBiYXNlcGF0aDogXCIvYWJzb2x1dGUvcGF0aFwiLFxuICAgICAgbm9ybWFsaXplZFBhdGg6IHJlbGF0aXZlKHByb2Nlc3MuY3dkKCksIFwiL2Fic29sdXRlL3BhdGgvZmlsZS50eHRcIiksXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJwYXRoIHdpdGggZW1wdHkgYmFzZXBhdGhcIixcbiAgICAgIHBhdGg6IFwicGF0aC90by9maWxlLnR4dFwiLFxuICAgICAgYmFzZXBhdGg6IFwiXCIsXG4gICAgICBub3JtYWxpemVkUGF0aDogam9pbihcInBhdGhcIiwgXCJ0b1wiLCBcImZpbGUudHh0XCIpLFxuICAgIH0sXG4gIF0pKFwiJGRlc2NyaXB0aW9uXCIsICh7IHBhdGgsIGJhc2VwYXRoLCBub3JtYWxpemVkUGF0aCB9KSA9PiB7XG4gICAgZXhwZWN0KG5vcm1hbGl6ZVBhdGgocGF0aCwgeyBiYXNlcGF0aCB9KSkudG9FcXVhbChub3JtYWxpemVkUGF0aClcbiAgfSlcblxuICBpdC5lYWNoKFtcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJhYnNvbHV0ZSBwYXRoXCIsXG4gICAgICBwYXRoOiBcIi9hYnNvbHV0ZS9wYXRoL3RvL2ZpbGUudHh0XCIsXG4gICAgICBiYXNlcGF0aDogdW5kZWZpbmVkLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwibG9jYWwgdHJhdmVyc2VkIHBhdGhcIixcbiAgICAgIHBhdGg6IFwiLi4vZmlsZS50eHRcIixcbiAgICAgIGJhc2VwYXRoOiBcIi9mb2xkZXJcIixcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcInJlbW90ZSB0cmF2ZXJzZWQgcGF0aFwiLFxuICAgICAgcGF0aDogXCIuLi9maWxlLnR4dFwiLFxuICAgICAgYmFzZXBhdGg6IFwiaHR0cDovL2V4YW1wbGUuY29tL2RhdGFcIixcbiAgICB9LFxuICBdKShcIiRkZXNjcmlwdGlvbiAtLSB0aHJvd1wiLCAoeyBwYXRoLCBiYXNlcGF0aCB9KSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IG5vcm1hbGl6ZVBhdGgocGF0aCwgeyBiYXNlcGF0aCB9KSkudG9UaHJvdygpXG4gIH0pXG59KVxuXG5kZXNjcmliZShcImRlbm9ybWFsaXplUGF0aFwiLCAoKSA9PiB7XG4gIGl0LmVhY2goW1xuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcInJlbW90ZSBVUkwgd2l0aG91dCBiYXNlcGF0aFwiLFxuICAgICAgcGF0aDogXCJodHRwOi8vZXhhbXBsZS5jb20vcGF0aC90by9maWxlLnR4dFwiLFxuICAgICAgYmFzZXBhdGg6IHVuZGVmaW5lZCxcbiAgICAgIGRlbm9ybWFsaXplZFBhdGg6IFwiaHR0cDovL2V4YW1wbGUuY29tL3BhdGgvdG8vZmlsZS50eHRcIixcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcInJlbW90ZSBVUkwgd2l0aCBiYXNlcGF0aFwiLFxuICAgICAgcGF0aDogXCJodHRwOi8vZXhhbXBsZS5jb20vcGF0aC90by9maWxlLnR4dFwiLFxuICAgICAgYmFzZXBhdGg6IFwiZGF0YVwiLFxuICAgICAgZGVub3JtYWxpemVkUGF0aDogXCJodHRwOi8vZXhhbXBsZS5jb20vcGF0aC90by9maWxlLnR4dFwiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwibG9jYWwgZmlsZSBpbiBzdWJmb2xkZXJcIixcbiAgICAgIHBhdGg6IFwiL3RtcC9kYXRhL2ZpbGUuY3N2XCIsXG4gICAgICBiYXNlcGF0aDogXCIvdG1wXCIsXG4gICAgICBkZW5vcm1hbGl6ZWRQYXRoOiBcImRhdGEvZmlsZS5jc3ZcIixcbiAgICB9LFxuICAgIHtcbiAgICAgIGRlc2NyaXB0aW9uOiBcImxvY2FsIGZpbGUgaW4gZGlyZWN0IGNoaWxkIGZvbGRlclwiLFxuICAgICAgcGF0aDogXCIvdG1wL2ZpbGUuY3N2XCIsXG4gICAgICBiYXNlcGF0aDogXCIvdG1wXCIsXG4gICAgICBkZW5vcm1hbGl6ZWRQYXRoOiBcImZpbGUuY3N2XCIsXG4gICAgfSxcbiAgICB7XG4gICAgICBkZXNjcmlwdGlvbjogXCJsb2NhbCBmaWxlIHdpdGggZGVlcGx5IG5lc3RlZCBiYXNlcGF0aFwiLFxuICAgICAgcGF0aDogXCIvdG1wL2RhdGEvbmVzdGVkL2RlZXAvZmlsZS5jc3ZcIixcbiAgICAgIGJhc2VwYXRoOiBcIi90bXAvZGF0YS9uZXN0ZWRcIixcbiAgICAgIGRlbm9ybWFsaXplZFBhdGg6IFwiZGVlcC9maWxlLmNzdlwiLFxuICAgIH0sXG4gICAge1xuICAgICAgZGVzY3JpcHRpb246IFwibG9jYWwgZmlsZSB3aXRoIG11bHRpLWxldmVsIGJhc2VwYXRoXCIsXG4gICAgICBwYXRoOiBcIi9ob21lL3VzZXIvcHJvamVjdHMvZGF0YS9maWxlLmNzdlwiLFxuICAgICAgYmFzZXBhdGg6IFwiL2hvbWUvdXNlci9wcm9qZWN0c1wiLFxuICAgICAgZGVub3JtYWxpemVkUGF0aDogXCJkYXRhL2ZpbGUuY3N2XCIsXG4gICAgfSxcbiAgXSkoXCIkZGVzY3JpcHRpb25cIiwgKHsgcGF0aCwgYmFzZXBhdGgsIGRlbm9ybWFsaXplZFBhdGggfSkgPT4ge1xuICAgIGV4cGVjdChkZW5vcm1hbGl6ZVBhdGgocGF0aCwgeyBiYXNlcGF0aCB9KSkudG9FcXVhbChkZW5vcm1hbGl6ZWRQYXRoKVxuICB9KVxufSlcbiJdfQ==