@fairspec/agent 0.9.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 (90) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +3 -0
  3. package/build/actions/tableSchema/asHtml.d.ts +4 -0
  4. package/build/actions/tableSchema/asHtml.js +82 -0
  5. package/build/actions/tableSchema/asHtml.spec.d.ts +1 -0
  6. package/build/actions/tableSchema/asHtml.spec.js +356 -0
  7. package/build/actions/tableSchema/asMarkdown.d.ts +4 -0
  8. package/build/actions/tableSchema/asMarkdown.js +65 -0
  9. package/build/actions/tableSchema/asMarkdown.spec.d.ts +1 -0
  10. package/build/actions/tableSchema/asMarkdown.spec.js +133 -0
  11. package/build/document/Document.d.ts +2 -0
  12. package/build/document/Document.js +2 -0
  13. package/build/document/index.d.ts +3 -0
  14. package/build/document/index.js +3 -0
  15. package/build/document/types/Base.d.ts +3 -0
  16. package/build/document/types/Base.js +2 -0
  17. package/build/document/types/Json.d.ts +5 -0
  18. package/build/document/types/Json.js +2 -0
  19. package/build/document/validate.d.ts +5 -0
  20. package/build/document/validate.js +23 -0
  21. package/build/document/validate.spec.d.ts +1 -0
  22. package/build/document/validate.spec.js +71 -0
  23. package/build/index.d.ts +1 -0
  24. package/build/index.js +2 -0
  25. package/build/package.json +39 -0
  26. package/build/plugin.d.ts +6 -0
  27. package/build/plugin.js +15 -0
  28. package/build/schema/convert/toHtml.d.ts +4 -0
  29. package/build/schema/convert/toHtml.js +107 -0
  30. package/build/schema/convert/toHtml.spec.d.ts +1 -0
  31. package/build/schema/convert/toHtml.spec.js +432 -0
  32. package/build/schema/convert/toMarkdown.d.ts +4 -0
  33. package/build/schema/convert/toMarkdown.js +75 -0
  34. package/build/schema/convert/toMarkdown.spec.d.ts +1 -0
  35. package/build/schema/convert/toMarkdown.spec.js +137 -0
  36. package/build/schema/index.d.ts +2 -0
  37. package/build/schema/index.js +3 -0
  38. package/build/server.d.ts +2 -0
  39. package/build/server.js +29 -0
  40. package/build/tableSchema/convert/toHtml.d.ts +4 -0
  41. package/build/tableSchema/convert/toHtml.js +80 -0
  42. package/build/tableSchema/convert/toHtml.spec.d.ts +1 -0
  43. package/build/tableSchema/convert/toHtml.spec.js +375 -0
  44. package/build/tableSchema/convert/toMarkdown.d.ts +4 -0
  45. package/build/tableSchema/convert/toMarkdown.js +57 -0
  46. package/build/tableSchema/convert/toMarkdown.spec.d.ts +1 -0
  47. package/build/tableSchema/convert/toMarkdown.spec.js +141 -0
  48. package/build/tableSchema/index.d.ts +2 -0
  49. package/build/tableSchema/index.js +3 -0
  50. package/build/tools/data/validate.d.ts +971 -0
  51. package/build/tools/data/validate.js +15 -0
  52. package/build/tools/data/validate.spec.d.ts +1 -0
  53. package/build/tools/data/validate.spec.js +228 -0
  54. package/build/tools/dataSchema/infer.d.ts +797 -0
  55. package/build/tools/dataSchema/infer.js +15 -0
  56. package/build/tools/dataSchema/infer.spec.d.ts +1 -0
  57. package/build/tools/dataSchema/infer.spec.js +215 -0
  58. package/build/tools/dataSchema/validate.d.ts +177 -0
  59. package/build/tools/dataSchema/validate.js +17 -0
  60. package/build/tools/dataSchema/validate.spec.d.ts +1 -0
  61. package/build/tools/dataSchema/validate.spec.js +148 -0
  62. package/build/tools/dataset/infer.d.ts +1985 -0
  63. package/build/tools/dataset/infer.js +15 -0
  64. package/build/tools/dataset/infer.spec.d.ts +1 -0
  65. package/build/tools/dataset/infer.spec.js +181 -0
  66. package/build/tools/dataset/validate.d.ts +1168 -0
  67. package/build/tools/dataset/validate.js +17 -0
  68. package/build/tools/dataset/validate.spec.d.ts +1 -0
  69. package/build/tools/dataset/validate.spec.js +212 -0
  70. package/build/tools/dialect/infer.d.ts +889 -0
  71. package/build/tools/dialect/infer.js +16 -0
  72. package/build/tools/dialect/infer.spec.d.ts +1 -0
  73. package/build/tools/dialect/infer.spec.js +138 -0
  74. package/build/tools/table/query.d.ts +798 -0
  75. package/build/tools/table/query.js +24 -0
  76. package/build/tools/table/query.spec.d.ts +1 -0
  77. package/build/tools/table/query.spec.js +138 -0
  78. package/build/tools/table/validate.d.ts +999 -0
  79. package/build/tools/table/validate.js +16 -0
  80. package/build/tools/table/validate.spec.d.ts +1 -0
  81. package/build/tools/table/validate.spec.js +106 -0
  82. package/build/tools/tableSchema/infer.d.ts +1316 -0
  83. package/build/tools/tableSchema/infer.js +16 -0
  84. package/build/tools/tableSchema/infer.spec.d.ts +1 -0
  85. package/build/tools/tableSchema/infer.spec.js +152 -0
  86. package/build/tools/tableSchema/validate.d.ts +177 -0
  87. package/build/tools/tableSchema/validate.js +17 -0
  88. package/build/tools/tableSchema/validate.spec.d.ts +1 -0
  89. package/build/tools/tableSchema/validate.spec.js +121 -0
  90. package/package.json +39 -0
@@ -0,0 +1,17 @@
1
+ import { Dataset, Report, validateDataset } from "@fairspec/library";
2
+ import { createTool } from "@mastra/core/tools";
3
+ import { z } from "zod";
4
+ export const validateDatasetTool = createTool({
5
+ id: "validate-dataset",
6
+ description: "Validate a dataset including all its resources and foreign keys. Returns a validation report with errors if any.",
7
+ inputSchema: z.object({
8
+ source: z
9
+ .union([Dataset, z.string()])
10
+ .describe("The dataset to validate (dataset object or file path)"),
11
+ }),
12
+ outputSchema: Report,
13
+ execute: async (input) => {
14
+ return await validateDataset(input.source);
15
+ },
16
+ });
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90b29scy9kYXRhc2V0L3ZhbGlkYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ3BFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLE1BQU0sS0FBSyxDQUFBO0FBRXZCLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLFVBQVUsQ0FBQztJQUM1QyxFQUFFLEVBQUUsa0JBQWtCO0lBQ3RCLFdBQVcsRUFDVCxrSEFBa0g7SUFDcEgsV0FBVyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDcEIsTUFBTSxFQUFFLENBQUM7YUFDTixLQUFLLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7YUFDNUIsUUFBUSxDQUFDLHVEQUF1RCxDQUFDO0tBQ3JFLENBQUM7SUFDRixZQUFZLEVBQUUsTUFBTTtJQUNwQixPQUFPLEVBQUUsS0FBSyxFQUFDLEtBQUssRUFBQyxFQUFFO1FBQ3JCLE9BQU8sTUFBTSxlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQzVDLENBQUM7Q0FDRixDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEYXRhc2V0LCBSZXBvcnQsIHZhbGlkYXRlRGF0YXNldCB9IGZyb20gXCJAZmFpcnNwZWMvbGlicmFyeVwiXG5pbXBvcnQgeyBjcmVhdGVUb29sIH0gZnJvbSBcIkBtYXN0cmEvY29yZS90b29sc1wiXG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiXG5cbmV4cG9ydCBjb25zdCB2YWxpZGF0ZURhdGFzZXRUb29sID0gY3JlYXRlVG9vbCh7XG4gIGlkOiBcInZhbGlkYXRlLWRhdGFzZXRcIixcbiAgZGVzY3JpcHRpb246XG4gICAgXCJWYWxpZGF0ZSBhIGRhdGFzZXQgaW5jbHVkaW5nIGFsbCBpdHMgcmVzb3VyY2VzIGFuZCBmb3JlaWduIGtleXMuIFJldHVybnMgYSB2YWxpZGF0aW9uIHJlcG9ydCB3aXRoIGVycm9ycyBpZiBhbnkuXCIsXG4gIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgc291cmNlOiB6XG4gICAgICAudW5pb24oW0RhdGFzZXQsIHouc3RyaW5nKCldKVxuICAgICAgLmRlc2NyaWJlKFwiVGhlIGRhdGFzZXQgdG8gdmFsaWRhdGUgKGRhdGFzZXQgb2JqZWN0IG9yIGZpbGUgcGF0aClcIiksXG4gIH0pLFxuICBvdXRwdXRTY2hlbWE6IFJlcG9ydCxcbiAgZXhlY3V0ZTogYXN5bmMgaW5wdXQgPT4ge1xuICAgIHJldHVybiBhd2FpdCB2YWxpZGF0ZURhdGFzZXQoaW5wdXQuc291cmNlKVxuICB9LFxufSlcbiJdfQ==
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,212 @@
1
+ import { writeTempFile } from "@fairspec/library";
2
+ import { describe, expect, it } from "vitest";
3
+ import { validateDatasetTool } from "./validate.js";
4
+ describe("validateDatasetTool", () => {
5
+ it("validates tool structure", () => {
6
+ expect(validateDatasetTool.id).toBe("validate-dataset");
7
+ expect(validateDatasetTool.description).toBeTruthy();
8
+ expect(validateDatasetTool.inputSchema).toBeTruthy();
9
+ expect(validateDatasetTool.outputSchema).toBeTruthy();
10
+ expect(validateDatasetTool.execute).toBeTypeOf("function");
11
+ });
12
+ it("validates a valid dataset with inline data", async () => {
13
+ const source = {
14
+ resources: [
15
+ {
16
+ name: "test_resource",
17
+ data: [
18
+ { id: 1, name: "Alice" },
19
+ { id: 2, name: "Bob" },
20
+ ],
21
+ tableSchema: {
22
+ properties: {
23
+ id: { type: "integer" },
24
+ name: { type: "string" },
25
+ },
26
+ },
27
+ },
28
+ ],
29
+ };
30
+ const result = await validateDatasetTool.execute?.({
31
+ source,
32
+ }, {});
33
+ expect.assert(result);
34
+ expect.assert(!("error" in result));
35
+ expect(result.valid).toBe(true);
36
+ expect(result.errors).toHaveLength(0);
37
+ });
38
+ it("detects invalid resource data", async () => {
39
+ const source = {
40
+ resources: [
41
+ {
42
+ name: "test_resource",
43
+ data: [
44
+ { id: 1, name: "Alice" },
45
+ { id: "not-a-number", name: "Bob" },
46
+ ],
47
+ tableSchema: {
48
+ properties: {
49
+ id: { type: "integer" },
50
+ name: { type: "string" },
51
+ },
52
+ },
53
+ },
54
+ ],
55
+ };
56
+ const result = await validateDatasetTool.execute?.({
57
+ source,
58
+ }, {});
59
+ expect.assert(result);
60
+ expect.assert(!("error" in result));
61
+ expect(result.valid).toBe(false);
62
+ expect(result.errors).toHaveLength(1);
63
+ expect(result.errors).toContainEqual({
64
+ type: "cell/type",
65
+ columnName: "id",
66
+ columnType: "integer",
67
+ rowNumber: 2,
68
+ resourceName: "test_resource",
69
+ cell: "not-a-number",
70
+ });
71
+ });
72
+ it("detects errors in multiple resources", async () => {
73
+ const source = {
74
+ resources: [
75
+ {
76
+ name: "resource_1",
77
+ data: [{ id: "invalid", name: "Alice" }],
78
+ tableSchema: {
79
+ properties: {
80
+ id: { type: "integer" },
81
+ name: { type: "string" },
82
+ },
83
+ },
84
+ },
85
+ {
86
+ name: "resource_2",
87
+ data: [{ id: 2, value: "invalid" }],
88
+ tableSchema: {
89
+ properties: {
90
+ id: { type: "integer" },
91
+ value: { type: "integer" },
92
+ },
93
+ },
94
+ },
95
+ ],
96
+ };
97
+ const result = await validateDatasetTool.execute?.({
98
+ source,
99
+ }, {});
100
+ expect.assert(result);
101
+ expect.assert(!("error" in result));
102
+ expect(result.valid).toBe(false);
103
+ expect(result.errors).toHaveLength(2);
104
+ });
105
+ it("validates dataset from file path", async () => {
106
+ const dataset = {
107
+ resources: [
108
+ {
109
+ name: "test",
110
+ data: [
111
+ { id: 1, name: "Alice" },
112
+ { id: 2, name: "Bob" },
113
+ ],
114
+ tableSchema: {
115
+ properties: {
116
+ id: { type: "integer" },
117
+ name: { type: "string" },
118
+ },
119
+ },
120
+ },
121
+ ],
122
+ };
123
+ const path = await writeTempFile(JSON.stringify(dataset), {
124
+ format: "json",
125
+ });
126
+ const result = await validateDatasetTool.execute?.({
127
+ source: path,
128
+ }, {});
129
+ expect.assert(result);
130
+ expect.assert(!("error" in result));
131
+ expect(result.valid).toBe(true);
132
+ expect(result.errors).toHaveLength(0);
133
+ });
134
+ it("validates empty dataset", async () => {
135
+ const source = {
136
+ resources: [],
137
+ };
138
+ const result = await validateDatasetTool.execute?.({
139
+ source,
140
+ }, {});
141
+ expect.assert(result);
142
+ expect.assert(!("error" in result));
143
+ expect(result.valid).toBe(true);
144
+ expect(result.errors).toHaveLength(0);
145
+ });
146
+ it("validates dataset with multiple valid resources", async () => {
147
+ const source = {
148
+ resources: [
149
+ {
150
+ name: "users",
151
+ data: [
152
+ { id: 1, name: "Alice" },
153
+ { id: 2, name: "Bob" },
154
+ ],
155
+ tableSchema: {
156
+ properties: {
157
+ id: { type: "integer" },
158
+ name: { type: "string" },
159
+ },
160
+ },
161
+ },
162
+ {
163
+ name: "scores",
164
+ data: [
165
+ { user_id: 1, score: 95 },
166
+ { user_id: 2, score: 87 },
167
+ ],
168
+ tableSchema: {
169
+ properties: {
170
+ user_id: { type: "integer" },
171
+ score: { type: "integer" },
172
+ },
173
+ },
174
+ },
175
+ ],
176
+ };
177
+ const result = await validateDatasetTool.execute?.({
178
+ source,
179
+ }, {});
180
+ expect.assert(result);
181
+ expect.assert(!("error" in result));
182
+ expect(result.valid).toBe(true);
183
+ expect(result.errors).toHaveLength(0);
184
+ });
185
+ it("detects schema mismatch in resource", async () => {
186
+ const source = {
187
+ resources: [
188
+ {
189
+ name: "test",
190
+ data: [
191
+ { id: 1, name: "Alice", extra: "field" },
192
+ { id: 2, name: "Bob", extra: "field" },
193
+ ],
194
+ tableSchema: {
195
+ properties: {
196
+ id: { type: "integer" },
197
+ name: { type: "string" },
198
+ },
199
+ },
200
+ },
201
+ ],
202
+ };
203
+ const result = await validateDatasetTool.execute?.({
204
+ source,
205
+ }, {});
206
+ expect.assert(result);
207
+ expect.assert(!("error" in result));
208
+ expect(result.valid).toBe(true);
209
+ expect(result.errors).toHaveLength(0);
210
+ });
211
+ });
212
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUuc3BlYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rvb2xzL2RhdGFzZXQvdmFsaWRhdGUuc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFDakQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sUUFBUSxDQUFBO0FBQzdDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUVuRCxRQUFRLENBQUMscUJBQXFCLEVBQUUsR0FBRyxFQUFFO0lBQ25DLEVBQUUsQ0FBQywwQkFBMEIsRUFBRSxHQUFHLEVBQUU7UUFDbEMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFBO1FBQ3ZELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxXQUFXLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQTtRQUNwRCxNQUFNLENBQUMsbUJBQW1CLENBQUMsV0FBVyxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUE7UUFDcEQsTUFBTSxDQUFDLG1CQUFtQixDQUFDLFlBQVksQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFBO1FBQ3JELE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDNUQsQ0FBQyxDQUFDLENBQUE7SUFFRixFQUFFLENBQUMsNENBQTRDLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDMUQsTUFBTSxNQUFNLEdBQVk7WUFDdEIsU0FBUyxFQUFFO2dCQUNUO29CQUNFLElBQUksRUFBRSxlQUFlO29CQUNyQixJQUFJLEVBQUU7d0JBQ0osRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUU7d0JBQ3hCLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxJQUFJLEVB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QyxDQUFDLENBQUE7QUFDSixDQUFDLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgRGF0YXNldCB9IGZyb20gXCJAZmFpcnNwZWMvbGlicmFyeVwiXG5pbXBvcnQgeyB3cml0ZVRlbXBGaWxlIH0gZnJvbSBcIkBmYWlyc3BlYy9saWJyYXJ5XCJcbmltcG9ydCB7IGRlc2NyaWJlLCBleHBlY3QsIGl0IH0gZnJvbSBcInZpdGVzdFwiXG5pbXBvcnQgeyB2YWxpZGF0ZURhdGFzZXRUb29sIH0gZnJvbSBcIi4vdmFsaWRhdGUudHNcIlxuXG5kZXNjcmliZShcInZhbGlkYXRlRGF0YXNldFRvb2xcIiwgKCkgPT4ge1xuICBpdChcInZhbGlkYXRlcyB0b29sIHN0cnVjdHVyZVwiLCAoKSA9PiB7XG4gICAgZXhwZWN0KHZhbGlkYXRlRGF0YXNldFRvb2wuaWQpLnRvQmUoXCJ2YWxpZGF0ZS1kYXRhc2V0XCIpXG4gICAgZXhwZWN0KHZhbGlkYXRlRGF0YXNldFRvb2wuZGVzY3JpcHRpb24pLnRvQmVUcnV0aHkoKVxuICAgIGV4cGVjdCh2YWxpZGF0ZURhdGFzZXRUb29sLmlucHV0U2NoZW1hKS50b0JlVHJ1dGh5KClcbiAgICBleHBlY3QodmFsaWRhdGVEYXRhc2V0VG9vbC5vdXRwdXRTY2hlbWEpLnRvQmVUcnV0aHkoKVxuICAgIGV4cGVjdCh2YWxpZGF0ZURhdGFzZXRUb29sLmV4ZWN1dGUpLnRvQmVUeXBlT2YoXCJmdW5jdGlvblwiKVxuICB9KVxuXG4gIGl0KFwidmFsaWRhdGVzIGEgdmFsaWQgZGF0YXNldCB3aXRoIGlubGluZSBkYXRhXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzb3VyY2U6IERhdGFzZXQgPSB7XG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdF9yZXNvdXJjZVwiLFxuICAgICAgICAgIGRhdGE6IFtcbiAgICAgICAgICAgIHsgaWQ6IDEsIG5hbWU6IFwiQWxpY2VcIiB9LFxuICAgICAgICAgICAgeyBpZDogMiwgbmFtZTogXCJCb2JcIiB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgdGFibGVTY2hlbWE6IHtcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgaWQ6IHsgdHlwZTogXCJpbnRlZ2VyXCIgfSxcbiAgICAgICAgICAgICAgbmFtZTogeyB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZhbGlkYXRlRGF0YXNldFRvb2wuZXhlY3V0ZT8uKFxuICAgICAge1xuICAgICAgICBzb3VyY2UsXG4gICAgICB9LFxuICAgICAge30sXG4gICAgKVxuXG4gICAgZXhwZWN0LmFzc2VydChyZXN1bHQpXG4gICAgZXhwZWN0LmFzc2VydCghKFwiZXJyb3JcIiBpbiByZXN1bHQpKVxuXG4gICAgZXhwZWN0KHJlc3VsdC52YWxpZCkudG9CZSh0cnVlKVxuICAgIGV4cGVjdChyZXN1bHQuZXJyb3JzKS50b0hhdmVMZW5ndGgoMClcbiAgfSlcblxuICBpdChcImRldGVjdHMgaW52YWxpZCByZXNvdXJjZSBkYXRhXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzb3VyY2U6IERhdGFzZXQgPSB7XG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdF9yZXNvdXJjZVwiLFxuICAgICAgICAgIGRhdGE6IFtcbiAgICAgICAgICAgIHsgaWQ6IDEsIG5hbWU6IFwiQWxpY2VcIiB9LFxuICAgICAgICAgICAgeyBpZDogXCJub3QtYS1udW1iZXJcIiwgbmFtZTogXCJCb2JcIiB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgdGFibGVTY2hlbWE6IHtcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgaWQ6IHsgdHlwZTogXCJpbnRlZ2VyXCIgfSxcbiAgICAgICAgICAgICAgbmFtZTogeyB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZhbGlkYXRlRGF0YXNldFRvb2wuZXhlY3V0ZT8uKFxuICAgICAge1xuICAgICAgICBzb3VyY2UsXG4gICAgICB9LFxuICAgICAge30sXG4gICAgKVxuXG4gICAgZXhwZWN0LmFzc2VydChyZXN1bHQpXG4gICAgZXhwZWN0LmFzc2VydCghKFwiZXJyb3JcIiBpbiByZXN1bHQpKVxuXG4gICAgZXhwZWN0KHJlc3VsdC52YWxpZCkudG9CZShmYWxzZSlcbiAgICBleHBlY3QocmVzdWx0LmVycm9ycykudG9IYXZlTGVuZ3RoKDEpXG4gICAgZXhwZWN0KHJlc3VsdC5lcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgIHR5cGU6IFwiY2VsbC90eXBlXCIsXG4gICAgICBjb2x1bW5OYW1lOiBcImlkXCIsXG4gICAgICBjb2x1bW5UeXBlOiBcImludGVnZXJcIixcbiAgICAgIHJvd051bWJlcjogMixcbiAgICAgIHJlc291cmNlTmFtZTogXCJ0ZXN0X3Jlc291cmNlXCIsXG4gICAgICBjZWxsOiBcIm5vdC1hLW51bWJlclwiLFxuICAgIH0pXG4gIH0pXG5cbiAgaXQoXCJkZXRlY3RzIGVycm9ycyBpbiBtdWx0aXBsZSByZXNvdXJjZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHNvdXJjZTogRGF0YXNldCA9IHtcbiAgICAgIHJlc291cmNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJyZXNvdXJjZV8xXCIsXG4gICAgICAgICAgZGF0YTogW3sgaWQ6IFwiaW52YWxpZFwiLCBuYW1lOiBcIkFsaWNlXCIgfV0sXG4gICAgICAgICAgdGFibGVTY2hlbWE6IHtcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgaWQ6IHsgdHlwZTogXCJpbnRlZ2VyXCIgfSxcbiAgICAgICAgICAgICAgbmFtZTogeyB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInJlc291cmNlXzJcIixcbiAgICAgICAgICBkYXRhOiBbeyBpZDogMiwgdmFsdWU6IFwiaW52YWxpZFwiIH1dLFxuICAgICAgICAgIHRhYmxlU2NoZW1hOiB7XG4gICAgICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgICAgIGlkOiB7IHR5cGU6IFwiaW50ZWdlclwiIH0sXG4gICAgICAgICAgICAgIHZhbHVlOiB7IHR5cGU6IFwiaW50ZWdlclwiIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZhbGlkYXRlRGF0YXNldFRvb2wuZXhlY3V0ZT8uKFxuICAgICAge1xuICAgICAgICBzb3VyY2UsXG4gICAgICB9LFxuICAgICAge30sXG4gICAgKVxuXG4gICAgZXhwZWN0LmFzc2VydChyZXN1bHQpXG4gICAgZXhwZWN0LmFzc2VydCghKFwiZXJyb3JcIiBpbiByZXN1bHQpKVxuXG4gICAgZXhwZWN0KHJlc3VsdC52YWxpZCkudG9CZShmYWxzZSlcbiAgICBleHBlY3QocmVzdWx0LmVycm9ycykudG9IYXZlTGVuZ3RoKDIpXG4gIH0pXG5cbiAgaXQoXCJ2YWxpZGF0ZXMgZGF0YXNldCBmcm9tIGZpbGUgcGF0aFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZGF0YXNldCA9IHtcbiAgICAgIHJlc291cmNlczogW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJ0ZXN0XCIsXG4gICAgICAgICAgZGF0YTogW1xuICAgICAgICAgICAgeyBpZDogMSwgbmFtZTogXCJBbGljZVwiIH0sXG4gICAgICAgICAgICB7IGlkOiAyLCBuYW1lOiBcIkJvYlwiIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0YWJsZVNjaGVtYToge1xuICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICBpZDogeyB0eXBlOiBcImludGVnZXJcIiB9LFxuICAgICAgICAgICAgICBuYW1lOiB7IHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfVxuICAgIGNvbnN0IHBhdGggPSBhd2FpdCB3cml0ZVRlbXBGaWxlKEpTT04uc3RyaW5naWZ5KGRhdGFzZXQpLCB7XG4gICAgICBmb3JtYXQ6IFwianNvblwiLFxuICAgIH0pXG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB2YWxpZGF0ZURhdGFzZXRUb29sLmV4ZWN1dGU/LihcbiAgICAgIHtcbiAgICAgICAgc291cmNlOiBwYXRoLFxuICAgICAgfSxcbiAgICAgIHt9LFxuICAgIClcblxuICAgIGV4cGVjdC5hc3NlcnQocmVzdWx0KVxuICAgIGV4cGVjdC5hc3NlcnQoIShcImVycm9yXCIgaW4gcmVzdWx0KSlcblxuICAgIGV4cGVjdChyZXN1bHQudmFsaWQpLnRvQmUodHJ1ZSlcbiAgICBleHBlY3QocmVzdWx0LmVycm9ycykudG9IYXZlTGVuZ3RoKDApXG4gIH0pXG5cbiAgaXQoXCJ2YWxpZGF0ZXMgZW1wdHkgZGF0YXNldFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc291cmNlOiBEYXRhc2V0ID0ge1xuICAgICAgcmVzb3VyY2VzOiBbXSxcbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB2YWxpZGF0ZURhdGFzZXRUb29sLmV4ZWN1dGU/LihcbiAgICAgIHtcbiAgICAgICAgc291cmNlLFxuICAgICAgfSxcbiAgICAgIHt9LFxuICAgIClcblxuICAgIGV4cGVjdC5hc3NlcnQocmVzdWx0KVxuICAgIGV4cGVjdC5hc3NlcnQoIShcImVycm9yXCIgaW4gcmVzdWx0KSlcblxuICAgIGV4cGVjdChyZXN1bHQudmFsaWQpLnRvQmUodHJ1ZSlcbiAgICBleHBlY3QocmVzdWx0LmVycm9ycykudG9IYXZlTGVuZ3RoKDApXG4gIH0pXG5cbiAgaXQoXCJ2YWxpZGF0ZXMgZGF0YXNldCB3aXRoIG11bHRpcGxlIHZhbGlkIHJlc291cmNlc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc291cmNlOiBEYXRhc2V0ID0ge1xuICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInVzZXJzXCIsXG4gICAgICAgICAgZGF0YTogW1xuICAgICAgICAgICAgeyBpZDogMSwgbmFtZTogXCJBbGljZVwiIH0sXG4gICAgICAgICAgICB7IGlkOiAyLCBuYW1lOiBcIkJvYlwiIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0YWJsZVNjaGVtYToge1xuICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICBpZDogeyB0eXBlOiBcImludGVnZXJcIiB9LFxuICAgICAgICAgICAgICBuYW1lOiB7IHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwic2NvcmVzXCIsXG4gICAgICAgICAgZGF0YTogW1xuICAgICAgICAgICAgeyB1c2VyX2lkOiAxLCBzY29yZTogOTUgfSxcbiAgICAgICAgICAgIHsgdXNlcl9pZDogMiwgc2NvcmU6IDg3IH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICB0YWJsZVNjaGVtYToge1xuICAgICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgICB1c2VyX2lkOiB7IHR5cGU6IFwiaW50ZWdlclwiIH0sXG4gICAgICAgICAgICAgIHNjb3JlOiB7IHR5cGU6IFwiaW50ZWdlclwiIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZhbGlkYXRlRGF0YXNldFRvb2wuZXhlY3V0ZT8uKFxuICAgICAge1xuICAgICAgICBzb3VyY2UsXG4gICAgICB9LFxuICAgICAge30sXG4gICAgKVxuXG4gICAgZXhwZWN0LmFzc2VydChyZXN1bHQpXG4gICAgZXhwZWN0LmFzc2VydCghKFwiZXJyb3JcIiBpbiByZXN1bHQpKVxuXG4gICAgZXhwZWN0KHJlc3VsdC52YWxpZCkudG9CZSh0cnVlKVxuICAgIGV4cGVjdChyZXN1bHQuZXJyb3JzKS50b0hhdmVMZW5ndGgoMClcbiAgfSlcblxuICBpdChcImRldGVjdHMgc2NoZW1hIG1pc21hdGNoIGluIHJlc291cmNlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBzb3VyY2U6IERhdGFzZXQgPSB7XG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdFwiLFxuICAgICAgICAgIGRhdGE6IFtcbiAgICAgICAgICAgIHsgaWQ6IDEsIG5hbWU6IFwiQWxpY2VcIiwgZXh0cmE6IFwiZmllbGRcIiB9LFxuICAgICAgICAgICAgeyBpZDogMiwgbmFtZTogXCJCb2JcIiwgZXh0cmE6IFwiZmllbGRcIiB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgdGFibGVTY2hlbWE6IHtcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgICAgaWQ6IHsgdHlwZTogXCJpbnRlZ2VyXCIgfSxcbiAgICAgICAgICAgICAgbmFtZTogeyB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHZhbGlkYXRlRGF0YXNldFRvb2wuZXhlY3V0ZT8uKFxuICAgICAge1xuICAgICAgICBzb3VyY2UsXG4gICAgICB9LFxuICAgICAge30sXG4gICAgKVxuXG4gICAgZXhwZWN0LmFzc2VydChyZXN1bHQpXG4gICAgZXhwZWN0LmFzc2VydCghKFwiZXJyb3JcIiBpbiByZXN1bHQpKVxuXG4gICAgZXhwZWN0KHJlc3VsdC52YWxpZCkudG9CZSh0cnVlKVxuICAgIGV4cGVjdChyZXN1bHQuZXJyb3JzKS50b0hhdmVMZW5ndGgoMClcbiAgfSlcbn0pXG4iXX0=