sonamu 0.7.11 → 0.7.13
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.
- package/dist/api/config.d.ts +10 -6
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +2 -1
- package/dist/api/sonamu.d.ts +4 -0
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +49 -5
- package/dist/bin/cli.js +118 -170
- package/dist/database/base-model.d.ts +10 -50
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +19 -84
- package/dist/database/base-model.types.d.ts +4 -4
- package/dist/database/base-model.types.d.ts.map +1 -1
- package/dist/database/base-model.types.js +1 -1
- package/dist/database/db.d.ts +1 -0
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +24 -13
- package/dist/database/puri-subset.test-d.js +1 -1
- package/dist/database/puri-subset.types.d.ts +1 -0
- package/dist/database/puri-subset.types.d.ts.map +1 -1
- package/dist/database/puri-subset.types.js +2 -2
- package/dist/database/puri.d.ts +82 -3
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +180 -14
- package/dist/database/puri.types.d.ts +33 -6
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +1 -1
- package/dist/database/puri.types.test-d.js +1 -1
- package/dist/entity/entity-manager.d.ts +5 -4
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +8 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/migration/code-generation.d.ts.map +1 -1
- package/dist/migration/code-generation.js +33 -2
- package/dist/migration/postgresql-schema-reader.d.ts.map +1 -1
- package/dist/migration/postgresql-schema-reader.js +53 -22
- package/dist/naite/messaging-types.d.ts.map +1 -1
- package/dist/naite/messaging-types.js +1 -1
- package/dist/naite/naite.js +2 -2
- package/dist/stream/sse.d.ts +2 -6
- package/dist/stream/sse.d.ts.map +1 -1
- package/dist/stream/sse.js +9 -3
- package/dist/syncer/api-parser.d.ts.map +1 -1
- package/dist/syncer/api-parser.js +7 -2
- package/dist/syncer/file-patterns.d.ts +1 -1
- package/dist/syncer/file-patterns.d.ts.map +1 -1
- package/dist/syncer/file-patterns.js +6 -5
- package/dist/syncer/module-loader.d.ts +5 -0
- package/dist/syncer/module-loader.d.ts.map +1 -1
- package/dist/syncer/module-loader.js +17 -1
- package/dist/syncer/syncer.d.ts +5 -1
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +28 -19
- package/dist/tasks/decorator.d.ts +26 -0
- package/dist/tasks/decorator.d.ts.map +1 -0
- package/dist/tasks/decorator.js +28 -0
- package/dist/tasks/step-wrapper.d.ts +18 -0
- package/dist/tasks/step-wrapper.d.ts.map +1 -0
- package/dist/tasks/step-wrapper.js +38 -0
- package/dist/tasks/workflow-manager.d.ts +40 -0
- package/dist/tasks/workflow-manager.d.ts.map +1 -0
- package/dist/tasks/workflow-manager.js +193 -0
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +7 -3
- package/dist/types/types.d.ts +26 -10
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +15 -2
- package/dist/ui/ai-api.d.ts +1 -0
- package/dist/ui/ai-api.d.ts.map +1 -0
- package/dist/ui/ai-api.js +50 -0
- package/dist/ui/ai-client.d.ts +1 -0
- package/dist/ui/ai-client.d.ts.map +1 -0
- package/dist/ui/ai-client.js +438 -0
- package/dist/ui/api.d.ts +3 -0
- package/dist/ui/api.d.ts.map +1 -0
- package/dist/ui/api.js +680 -0
- package/dist/ui-web/assets/brand-icons-Cu_C0hZ4.svg +1008 -0
- package/dist/ui-web/assets/brand-icons-F3SPCeH1.woff +0 -0
- package/dist/ui-web/assets/brand-icons-XL9sxUpA.woff2 +0 -0
- package/dist/ui-web/assets/brand-icons-sqJ2Pg7a.eot +0 -0
- package/dist/ui-web/assets/brand-icons-ubhWoxly.ttf +0 -0
- package/dist/ui-web/assets/flags-DOLqOU7Y.png +0 -0
- package/dist/ui-web/assets/icons-BOCtAERH.woff +0 -0
- package/dist/ui-web/assets/icons-CHzK1VD9.eot +0 -0
- package/dist/ui-web/assets/icons-D29ZQHHw.ttf +0 -0
- package/dist/ui-web/assets/icons-Du6TOHnR.woff2 +0 -0
- package/dist/ui-web/assets/icons-RwhydX30.svg +1518 -0
- package/dist/ui-web/assets/index-CpaB9P6g.css +1 -0
- package/dist/ui-web/assets/index-J9MCfjCd.js +95 -0
- package/dist/ui-web/assets/outline-icons-BfdLr8tr.svg +366 -0
- package/dist/ui-web/assets/outline-icons-DD8jm0uy.ttf +0 -0
- package/dist/ui-web/assets/outline-icons-DInHoiqI.woff2 +0 -0
- package/dist/ui-web/assets/outline-icons-LX8adJ4n.eot +0 -0
- package/dist/ui-web/assets/outline-icons-aQ88nltS.woff +0 -0
- package/dist/ui-web/assets/provider-utils_false-BKJD46kk.js +1 -0
- package/dist/ui-web/assets/provider-utils_false-Bu5lmX18.js +1 -0
- package/dist/ui-web/index.html +13 -0
- package/dist/ui-web/vite.svg +1 -0
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +10 -2
- package/dist/utils/model.d.ts +9 -2
- package/dist/utils/model.d.ts.map +1 -1
- package/dist/utils/model.js +16 -1
- package/dist/utils/type-utils.d.ts.map +1 -1
- package/dist/utils/type-utils.js +3 -1
- package/dist/vector/embedding.d.ts +2 -5
- package/dist/vector/embedding.d.ts.map +1 -1
- package/dist/vector/embedding.js +9 -13
- package/dist/vector/types.d.ts.map +1 -1
- package/dist/vector/types.js +1 -1
- package/package.json +9 -5
- package/src/api/config.ts +15 -11
- package/src/api/sonamu.ts +60 -6
- package/src/bin/cli.ts +57 -119
- package/src/database/base-model.ts +21 -128
- package/src/database/base-model.types.ts +3 -4
- package/src/database/db.ts +28 -18
- package/src/database/puri-subset.test-d.ts +1 -0
- package/src/database/puri-subset.types.ts +2 -0
- package/src/database/puri.ts +238 -27
- package/src/database/puri.types.test-d.ts +1 -1
- package/src/database/puri.types.ts +49 -6
- package/src/entity/entity-manager.ts +9 -0
- package/src/index.ts +1 -1
- package/src/migration/code-generation.ts +40 -1
- package/src/migration/postgresql-schema-reader.ts +53 -22
- package/src/naite/messaging-types.ts +43 -44
- package/src/naite/naite.ts +1 -1
- package/src/shared/app.shared.ts.txt +13 -0
- package/src/shared/web.shared.ts.txt +13 -0
- package/src/stream/sse.ts +15 -3
- package/src/syncer/api-parser.ts +6 -1
- package/src/syncer/file-patterns.ts +11 -9
- package/src/syncer/module-loader.ts +35 -0
- package/src/syncer/syncer.ts +34 -21
- package/src/tasks/decorator.ts +71 -0
- package/src/tasks/step-wrapper.ts +84 -0
- package/src/tasks/workflow-manager.ts +330 -0
- package/src/template/implementations/generated.template.ts +19 -6
- package/src/types/types.ts +20 -4
- package/src/ui/ai-api.ts +60 -0
- package/src/ui/ai-client.ts +499 -0
- package/src/ui/api.ts +786 -0
- package/src/utils/formatter.ts +8 -1
- package/src/utils/model.ts +26 -2
- package/src/utils/type-utils.ts +2 -0
- package/src/vector/embedding.ts +10 -14
- package/src/vector/types.ts +1 -2
- package/dist/vector/vector-search.d.ts +0 -47
- package/dist/vector/vector-search.d.ts.map +0 -1
- package/dist/vector/vector-search.js +0 -176
- package/src/vector/vector-search.ts +0 -261
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
// import { anthropic } from "@ai-sdk/anthropic";
|
|
2
|
+
// import { type ModelMessage, stepCountIs, streamText, tool } from "ai";
|
|
3
|
+
// import assert from "assert";
|
|
4
|
+
// import fs from "fs";
|
|
5
|
+
// import path from "path";
|
|
6
|
+
// import {
|
|
7
|
+
// EntityManager,
|
|
8
|
+
// type EntityProp,
|
|
9
|
+
// type FixtureRecord,
|
|
10
|
+
// nonNullable,
|
|
11
|
+
// Sonamu,
|
|
12
|
+
// TemplateOptions,
|
|
13
|
+
// } from "sonamu";
|
|
14
|
+
// import { z } from "zod";
|
|
15
|
+
// type ValidationError = {
|
|
16
|
+
// field: string;
|
|
17
|
+
// message: string;
|
|
18
|
+
// };
|
|
19
|
+
// class AIClient {
|
|
20
|
+
// private model = anthropic("claude-sonnet-4-5");
|
|
21
|
+
// async init() {
|
|
22
|
+
// console.log("AI client initialized with AI SDK");
|
|
23
|
+
// }
|
|
24
|
+
// handleFixture(messages: ModelMessage[], fixtureRecords: FixtureRecord[]) {
|
|
25
|
+
// // 현재 fixtureRecords에서 사용된 엔티티들의 구조 정보 수집
|
|
26
|
+
// const usedEntityIds = [...new Set(fixtureRecords.map((r) => r.entityId))];
|
|
27
|
+
// const entityStructures = usedEntityIds.map((entityId) => {
|
|
28
|
+
// const entity = EntityManager.get(entityId);
|
|
29
|
+
// return {
|
|
30
|
+
// entityId: entity.id,
|
|
31
|
+
// table: entity.table,
|
|
32
|
+
// props: entity.props,
|
|
33
|
+
// relations: entity.relations,
|
|
34
|
+
// enumLabels: entity.enumLabels,
|
|
35
|
+
// };
|
|
36
|
+
// });
|
|
37
|
+
// const systemMessage = `
|
|
38
|
+
// 당신은 픽스쳐 레코드를 수정하고 생성할 수 있는 도우미입니다.
|
|
39
|
+
// 현재 픽스쳐 레코드:
|
|
40
|
+
// ${JSON.stringify(fixtureRecords, null, 2)}
|
|
41
|
+
// 엔티티 구조 정보:
|
|
42
|
+
// ${JSON.stringify(entityStructures, null, 2)}
|
|
43
|
+
// ## 픽스쳐 수정
|
|
44
|
+
// 사용자가 픽스쳐 값 수정을 요청하면 updateFixtures 도구를 사용하여 변경사항을 적용하세요.
|
|
45
|
+
// - fixtureId: 수정할 픽스쳐 ID (형식: "EntityId#id")
|
|
46
|
+
// - updates: 컬럼명을 키로, 새 값을 값으로 하는 객체
|
|
47
|
+
// 예시: "User#1" 픽스쳐의 "name" 컬럼을 "홍길동"으로 변경하려면:
|
|
48
|
+
// updateFixtures({ updates: [{ fixtureId: "User#1", updates: { name: "홍길동" } }] })
|
|
49
|
+
// 변경될 컬럼의 type이 relation인 경우, 관련 엔티티에도 반영되어야 할 컬럼이 있는지 확인하세요.
|
|
50
|
+
// ## 픽스쳐 생성
|
|
51
|
+
// 사용자가 새로운 픽스쳐 생성을 요청하면 createFixtures 도구를 사용하세요.
|
|
52
|
+
// - entityId: 생성할 엔티티 ID
|
|
53
|
+
// - id: 새 레코드의 ID (기존 픽스쳐와 중복되지 않는 음수 사용 권장, 예: -1, -2)
|
|
54
|
+
// - columns: 컬럼명을 키로, 값을 값으로 하는 객체 (엔티티 구조 참고)
|
|
55
|
+
// 예시: 새로운 User 픽스쳐를 생성하려면:
|
|
56
|
+
// createFixtures({ fixtures: [{ entityId: "User", id: -1, columns: { name: "홍길동", email: "hong@example.com" } }] })
|
|
57
|
+
// `;
|
|
58
|
+
// return streamText({
|
|
59
|
+
// model: this.model,
|
|
60
|
+
// system: systemMessage,
|
|
61
|
+
// messages,
|
|
62
|
+
// tools: {
|
|
63
|
+
// updateFixtures: tool({
|
|
64
|
+
// description:
|
|
65
|
+
// "픽스쳐 레코드의 값을 수정합니다. 사용자가 특정 컬럼이나 값을 변경해달라고 요청할 때 사용하세요.",
|
|
66
|
+
// inputSchema: z.object({
|
|
67
|
+
// updates: z.array(
|
|
68
|
+
// z.object({
|
|
69
|
+
// fixtureId: z.string().describe("수정할 픽스쳐 ID (형식: EntityId#id)"),
|
|
70
|
+
// updates: z
|
|
71
|
+
// .record(z.string(), z.unknown())
|
|
72
|
+
// .describe("컬럼명을 키로, 새 값을 값으로 하는 객체"),
|
|
73
|
+
// }),
|
|
74
|
+
// ),
|
|
75
|
+
// }),
|
|
76
|
+
// execute: async ({
|
|
77
|
+
// updates,
|
|
78
|
+
// }): Promise<{ success: boolean; updatedRecords: FixtureRecord[] }> => {
|
|
79
|
+
// // fixtureRecords를 복사하고 업데이트 적용
|
|
80
|
+
// const updatedRecords: FixtureRecord[] = fixtureRecords.map((record) => {
|
|
81
|
+
// const update = updates.find((u) => u.fixtureId === record.fixtureId);
|
|
82
|
+
// if (update) {
|
|
83
|
+
// // columns의 value를 업데이트
|
|
84
|
+
// for (const [columnName, newValue] of Object.entries(update.updates)) {
|
|
85
|
+
// record.columns[columnName].value =
|
|
86
|
+
// newValue as FixtureRecord["columns"][string]["value"];
|
|
87
|
+
// }
|
|
88
|
+
// return record;
|
|
89
|
+
// }
|
|
90
|
+
// return record;
|
|
91
|
+
// });
|
|
92
|
+
// return { success: true, updatedRecords };
|
|
93
|
+
// },
|
|
94
|
+
// }),
|
|
95
|
+
// createFixtures: tool({
|
|
96
|
+
// description:
|
|
97
|
+
// "새로운 픽스쳐 레코드를 생성합니다. 사용자가 새로운 데이터를 추가해달라고 요청할 때 사용하세요.",
|
|
98
|
+
// inputSchema: z.object({
|
|
99
|
+
// fixtures: z.array(
|
|
100
|
+
// z.object({
|
|
101
|
+
// entityId: z.string().describe("생성할 엔티티 ID"),
|
|
102
|
+
// id: z.number().describe("새 레코드의 ID (음수 권장, 예: -1, -2)"),
|
|
103
|
+
// columns: z
|
|
104
|
+
// .record(z.string(), z.unknown())
|
|
105
|
+
// .describe("컬럼명을 키로, 값을 값으로 하는 객체"),
|
|
106
|
+
// }),
|
|
107
|
+
// ),
|
|
108
|
+
// }),
|
|
109
|
+
// execute: async ({
|
|
110
|
+
// fixtures,
|
|
111
|
+
// }): Promise<{ success: boolean; updatedRecords: FixtureRecord[] }> => {
|
|
112
|
+
// const newRecords: FixtureRecord[] = fixtures.map((fixture) => {
|
|
113
|
+
// const entity = EntityManager.get(fixture.entityId);
|
|
114
|
+
// // 엔티티 props를 기반으로 columns 구성
|
|
115
|
+
// const columns: FixtureRecord["columns"] = {};
|
|
116
|
+
// for (const prop of entity.props) {
|
|
117
|
+
// if (prop.type === "virtual") continue;
|
|
118
|
+
// let value = fixture.columns[prop.name] ?? null;
|
|
119
|
+
// if (prop.name === "created_at") {
|
|
120
|
+
// // 현재 시간으로 설정
|
|
121
|
+
// value = new Date().toISOString();
|
|
122
|
+
// } else if (
|
|
123
|
+
// prop.type === "relation" &&
|
|
124
|
+
// (prop.relationType === "HasMany" || prop.relationType === "ManyToMany")
|
|
125
|
+
// ) {
|
|
126
|
+
// // 배열로 변환
|
|
127
|
+
// value = Array.isArray(value) ? value : [value].filter(nonNullable);
|
|
128
|
+
// }
|
|
129
|
+
// columns[prop.name] = {
|
|
130
|
+
// prop,
|
|
131
|
+
// value: value as FixtureRecord["columns"][string]["value"],
|
|
132
|
+
// };
|
|
133
|
+
// }
|
|
134
|
+
// return {
|
|
135
|
+
// fixtureId: `${fixture.entityId}#${fixture.id}`,
|
|
136
|
+
// entityId: fixture.entityId,
|
|
137
|
+
// id: fixture.id,
|
|
138
|
+
// columns,
|
|
139
|
+
// fetchedRecords: [],
|
|
140
|
+
// belongsRecords: [],
|
|
141
|
+
// override: false,
|
|
142
|
+
// };
|
|
143
|
+
// });
|
|
144
|
+
// // 새 레코드들의 relation 컬럼을 확인하여 기존 레코드들의 역방향 relation 업데이트
|
|
145
|
+
// for (const newRecord of newRecords) {
|
|
146
|
+
// for (const [_colName, col] of Object.entries(newRecord.columns)) {
|
|
147
|
+
// if (col.prop.type !== "relation" || col.value === null) continue;
|
|
148
|
+
// const relatedEntityId = col.prop.with;
|
|
149
|
+
// const relatedIds = Array.isArray(col.value) ? col.value : [col.value];
|
|
150
|
+
// for (const relatedId of relatedIds) {
|
|
151
|
+
// const relatedFixtureId = `${relatedEntityId}#${relatedId}`;
|
|
152
|
+
// const relatedRecord = newRecords.find((r) => r.fixtureId === relatedFixtureId);
|
|
153
|
+
// if (relatedRecord) {
|
|
154
|
+
// // 역방향 relation 찾기
|
|
155
|
+
// const reverseCol = Object.entries(relatedRecord.columns).find(
|
|
156
|
+
// ([, c]) => c.prop.type === "relation" && c.prop.with === newRecord.entityId,
|
|
157
|
+
// );
|
|
158
|
+
// if (reverseCol) {
|
|
159
|
+
// const [reverseColName, reverseColValue] = reverseCol;
|
|
160
|
+
// const currentValue = reverseColValue.value;
|
|
161
|
+
// // 역방향이 배열인 경우 (HasMany, ManyToMany)
|
|
162
|
+
// if (
|
|
163
|
+
// reverseColValue.prop.type === "relation" &&
|
|
164
|
+
// (reverseColValue.prop.relationType === "HasMany" ||
|
|
165
|
+
// reverseColValue.prop.relationType === "ManyToMany")
|
|
166
|
+
// ) {
|
|
167
|
+
// assert(Array.isArray(currentValue), "currentValue must be an array");
|
|
168
|
+
// if (!currentValue.includes(newRecord.id)) {
|
|
169
|
+
// relatedRecord.columns[reverseColName] = {
|
|
170
|
+
// ...reverseColValue,
|
|
171
|
+
// value: [...currentValue, newRecord.id],
|
|
172
|
+
// };
|
|
173
|
+
// }
|
|
174
|
+
// } else {
|
|
175
|
+
// // 역방향이 단일 값인 경우 (BelongsToOne, OneToOne)
|
|
176
|
+
// relatedRecord.columns[reverseColName] = {
|
|
177
|
+
// ...reverseColValue,
|
|
178
|
+
// value: newRecord.id,
|
|
179
|
+
// };
|
|
180
|
+
// }
|
|
181
|
+
// }
|
|
182
|
+
// }
|
|
183
|
+
// }
|
|
184
|
+
// }
|
|
185
|
+
// }
|
|
186
|
+
// return { success: true, updatedRecords: newRecords };
|
|
187
|
+
// },
|
|
188
|
+
// }),
|
|
189
|
+
// },
|
|
190
|
+
// });
|
|
191
|
+
// }
|
|
192
|
+
// handleEntity(messages: ModelMessage[]) {
|
|
193
|
+
// // entity.instructions.md 파일 읽기
|
|
194
|
+
// const instructionsPath = path.join(import.meta.dirname, "..", "entity.instructions.md");
|
|
195
|
+
// const instructions = fs.readFileSync(instructionsPath, "utf-8");
|
|
196
|
+
// // 현재 등록된 엔티티 정보 수집
|
|
197
|
+
// const entityIds = EntityManager.getAllIds();
|
|
198
|
+
// const existingEntities = entityIds.map((entityId) => {
|
|
199
|
+
// const entity = EntityManager.get(entityId);
|
|
200
|
+
// return {
|
|
201
|
+
// id: entity.id,
|
|
202
|
+
// title: entity.title,
|
|
203
|
+
// table: entity.table,
|
|
204
|
+
// props: entity.props.map((p) => ({
|
|
205
|
+
// name: p.name,
|
|
206
|
+
// type: p.type,
|
|
207
|
+
// desc: p.desc,
|
|
208
|
+
// })),
|
|
209
|
+
// };
|
|
210
|
+
// });
|
|
211
|
+
// const systemMessage = `
|
|
212
|
+
// 당신은 Sonamu 프레임워크에서 Entity와 Enum을 생성하는 도우미입니다.
|
|
213
|
+
// ${instructions}
|
|
214
|
+
// ## 현재 등록된 Entity 목록
|
|
215
|
+
// 다른 엔티티와 관계(relation)를 맺거나 subset에서 참조할 때 반드시 아래 정보를 확인하세요.
|
|
216
|
+
// ${JSON.stringify(existingEntities, null, 2)}
|
|
217
|
+
// ## Tool 사용 가이드
|
|
218
|
+
// ### Entity 생성 (createEntity)
|
|
219
|
+
// 사용자가 새로운 Entity 생성을 요청하면 createEntity 도구를 사용하세요.
|
|
220
|
+
// - entityId: PascalCase로 된 Entity ID (예: "User", "ProductCategory")
|
|
221
|
+
// - title: 한글 제목 (예: "사용자", "상품 카테고리")
|
|
222
|
+
// - table: snake_case로 된 테이블명 (예: "users", "product_categories")
|
|
223
|
+
// - parentId: 부모 Entity ID (선택사항)
|
|
224
|
+
// - props: Entity의 프로퍼티 배열 (위 문서의 Property Types 참고)
|
|
225
|
+
// - indexes: 인덱스 배열
|
|
226
|
+
// - subsets: 서브셋 정의 (기본값: { A: ["id"] })
|
|
227
|
+
// - enums: Enum 정의
|
|
228
|
+
// ### Entity 수정 (updateEntity)
|
|
229
|
+
// 기존 Entity를 수정할 때 updateEntity 도구를 사용하세요. Enum 추가, props 추가/수정, indexes 수정 등 모든 수정 작업에 사용합니다.
|
|
230
|
+
// - entityId: 수정할 Entity ID
|
|
231
|
+
// - updates: 수정할 필드들 (부분 업데이트)
|
|
232
|
+
// - title: 엔티티 한글 제목
|
|
233
|
+
// - table: 테이블명
|
|
234
|
+
// - props: 추가할 프로퍼티 배열 (기존 props에 추가, 같은 이름이면 교체)
|
|
235
|
+
// - indexes: 추가할 인덱스 배열 (기존 indexes에 추가)
|
|
236
|
+
// - subsets: 서브셋 정의 (기존 subsets에 병합)
|
|
237
|
+
// - enumLabels: Enum 정의 (기존 enumLabels에 병합)
|
|
238
|
+
// - mode: "merge"(기본값) 또는 "replace"
|
|
239
|
+
// - merge: 기존 값에 병합
|
|
240
|
+
// - replace: 해당 필드 전체 교체
|
|
241
|
+
// 예시: Employee에 새 Enum 추가
|
|
242
|
+
// updateEntity({ entityId: "Employee", updates: { enumLabels: { "EmployeeRole": { "admin": "관리자", "user": "일반" } } } })
|
|
243
|
+
// 예시: Project에 새 프로퍼티 추가
|
|
244
|
+
// updateEntity({ entityId: "Project", updates: { props: [{ name: "priority", type: "integer", desc: "우선순위" }] } })
|
|
245
|
+
// ## 필수 사항
|
|
246
|
+
// - Entity의 props에는 최소한 id(integer, unsigned), created_at(timestamp)가 포함되어야 합니다.
|
|
247
|
+
// - relation 필드는 onUpdate, onDelete가 필수입니다. (예외: OneToOne에서 hasJoinColumn이 false인 경우)
|
|
248
|
+
// - Enum ID는 보통 EntityId + 속성명 형태입니다 (예: UserStatus, ProductType)
|
|
249
|
+
// - subset에서 다른 엔티티의 프로퍼티를 참조할 때는 반드시 해당 엔티티의 실제 프로퍼티명을 사용하세요.
|
|
250
|
+
// ## 검증 오류 처리
|
|
251
|
+
// 도구 호출 결과로 검증 오류(validationErrors)가 반환되면:
|
|
252
|
+
// 1. 오류 메시지를 분석하여 문제점을 파악하세요.
|
|
253
|
+
// 2. 오류를 수정한 데이터로 createEntity를 다시 호출하세요.
|
|
254
|
+
// 3. 사용자에게 오류를 그대로 전달하지 말고, 수정 후 재시도하세요.
|
|
255
|
+
// ### 일반적인 검증 오류와 수정 방법
|
|
256
|
+
// | 오류 메시지 | 수정 방법 |
|
|
257
|
+
// |------------|----------|
|
|
258
|
+
// | "id 프로퍼티가 필수" | props에 { name: "id", type: "integer", unsigned: true } 추가 |
|
|
259
|
+
// | "created_at 프로퍼티가 필수" | props에 { name: "created_at", type: "timestamp", dbDefault: "CURRENT_TIMESTAMP" } 추가 |
|
|
260
|
+
// | "XxxOrderBy enum이 필수" | enums에 { "XxxOrderBy": { "id-desc": "ID최신순" } } 추가 |
|
|
261
|
+
// | "XxxSearchField enum이 필수" | enums에 { "XxxSearchField": { "id": "ID" } } 추가 |
|
|
262
|
+
// | "string 타입은 length가 필수" | 해당 prop에 length 추가 (예: 255) |
|
|
263
|
+
// | "text 타입은 textType이 필수" | 해당 prop에 textType 추가 ("text", "mediumtext", "longtext") |
|
|
264
|
+
// | "onUpdate가 필수" | 해당 relation prop에 onUpdate, onDelete 추가 ("CASCADE") |
|
|
265
|
+
// `;
|
|
266
|
+
// return streamText({
|
|
267
|
+
// model: this.model,
|
|
268
|
+
// system: systemMessage,
|
|
269
|
+
// messages,
|
|
270
|
+
// stopWhen: stepCountIs(2),
|
|
271
|
+
// tools: {
|
|
272
|
+
// createEntity: tool({
|
|
273
|
+
// description:
|
|
274
|
+
// "새로운 Entity를 생성합니다. 사용자가 새로운 엔티티나 테이블 생성을 요청할 때 사용하세요.",
|
|
275
|
+
// inputSchema: TemplateOptions.shape.entity,
|
|
276
|
+
// execute: async (
|
|
277
|
+
// entity,
|
|
278
|
+
// ): Promise<{
|
|
279
|
+
// success: boolean;
|
|
280
|
+
// entityId: string;
|
|
281
|
+
// error?: string;
|
|
282
|
+
// validationErrors?: ValidationError[];
|
|
283
|
+
// }> => {
|
|
284
|
+
// try {
|
|
285
|
+
// // 입력 검증
|
|
286
|
+
// const validationErrors = validateEntityJson(entity);
|
|
287
|
+
// if (validationErrors.length > 0) {
|
|
288
|
+
// return {
|
|
289
|
+
// success: false,
|
|
290
|
+
// entityId: entity.entityId,
|
|
291
|
+
// error: `검증 오류: ${validationErrors.map((e) => `[${e.field}] ${e.message}`).join(", ")}`,
|
|
292
|
+
// validationErrors,
|
|
293
|
+
// };
|
|
294
|
+
// }
|
|
295
|
+
// await Sonamu.syncer.createEntity({
|
|
296
|
+
// subsets: { A: ["id"] },
|
|
297
|
+
// enums: {},
|
|
298
|
+
// ...entity,
|
|
299
|
+
// });
|
|
300
|
+
// // EntityManager 리로드
|
|
301
|
+
// await EntityManager.reload();
|
|
302
|
+
// return { success: true, entityId: entity.entityId };
|
|
303
|
+
// } catch (e) {
|
|
304
|
+
// const error = e instanceof Error ? e.message : "Unknown error";
|
|
305
|
+
// return { success: false, entityId: entity.entityId, error };
|
|
306
|
+
// }
|
|
307
|
+
// },
|
|
308
|
+
// }),
|
|
309
|
+
// updateEntity: tool({
|
|
310
|
+
// description:
|
|
311
|
+
// "기존 Entity를 수정합니다. Enum 추가, props 추가/수정, indexes 수정, subsets 수정 등 모든 엔티티 수정 작업에 사용하세요.",
|
|
312
|
+
// inputSchema: z.object({
|
|
313
|
+
// entityId: z.string().describe("수정할 Entity ID"),
|
|
314
|
+
// updates: TemplateOptions.shape.entity.partial().describe("수정할 필드들"),
|
|
315
|
+
// mode: z
|
|
316
|
+
// .enum(["merge", "replace"])
|
|
317
|
+
// .optional()
|
|
318
|
+
// .describe("수정 모드: merge(기본값, 기존 값에 병합) 또는 replace(전체 교체)"),
|
|
319
|
+
// }),
|
|
320
|
+
// execute: async ({
|
|
321
|
+
// entityId,
|
|
322
|
+
// updates,
|
|
323
|
+
// mode = "merge",
|
|
324
|
+
// }): Promise<{
|
|
325
|
+
// success: boolean;
|
|
326
|
+
// entityId: string;
|
|
327
|
+
// error?: string;
|
|
328
|
+
// validationErrors?: ValidationError[];
|
|
329
|
+
// }> => {
|
|
330
|
+
// try {
|
|
331
|
+
// const entity = EntityManager.get(entityId);
|
|
332
|
+
// for (const [key, value] of Object.entries(updates)) {
|
|
333
|
+
// if (
|
|
334
|
+
// ["entityId", "parentId", "title", "table"].includes(key) &&
|
|
335
|
+
// value !== undefined
|
|
336
|
+
// ) {
|
|
337
|
+
// entity[key] = value;
|
|
338
|
+
// }
|
|
339
|
+
// }
|
|
340
|
+
// // props: merge 시 이름 기준 병합, replace 시 교체
|
|
341
|
+
// if (updates.props !== undefined) {
|
|
342
|
+
// if (mode === "replace") {
|
|
343
|
+
// entity.props = updates.props as EntityProp[];
|
|
344
|
+
// } else {
|
|
345
|
+
// for (const newProp of updates.props) {
|
|
346
|
+
// const existingIndex = entity.props.findIndex((p) => p.name === newProp.name);
|
|
347
|
+
// if (existingIndex >= 0) {
|
|
348
|
+
// entity.props[existingIndex] = newProp as EntityProp;
|
|
349
|
+
// } else {
|
|
350
|
+
// entity.props.push(newProp as EntityProp);
|
|
351
|
+
// }
|
|
352
|
+
// }
|
|
353
|
+
// }
|
|
354
|
+
// }
|
|
355
|
+
// // indexes: merge 시 추가, replace 시 교체
|
|
356
|
+
// if (updates.indexes !== undefined) {
|
|
357
|
+
// entity.indexes =
|
|
358
|
+
// mode === "replace" ? updates.indexes : [...entity.indexes, ...updates.indexes];
|
|
359
|
+
// }
|
|
360
|
+
// // subsets, enumLabels: assign으로 병합 또는 교체
|
|
361
|
+
// if (updates.subsets !== undefined) {
|
|
362
|
+
// entity.subsets =
|
|
363
|
+
// mode === "replace" ? updates.subsets : { ...entity.subsets, ...updates.subsets };
|
|
364
|
+
// }
|
|
365
|
+
// if (updates.enums !== undefined) {
|
|
366
|
+
// entity.enumLabels =
|
|
367
|
+
// mode === "replace" ? updates.enums : { ...entity.enumLabels, ...updates.enums };
|
|
368
|
+
// }
|
|
369
|
+
// // 저장 전 검증
|
|
370
|
+
// const validationErrors = validateEntityJson({
|
|
371
|
+
// ...entity,
|
|
372
|
+
// entityId: entity.id,
|
|
373
|
+
// enums: entity.enumLabels,
|
|
374
|
+
// });
|
|
375
|
+
// if (validationErrors.length > 0) {
|
|
376
|
+
// return {
|
|
377
|
+
// success: false,
|
|
378
|
+
// entityId,
|
|
379
|
+
// error: `검증 오류: ${validationErrors.map((e) => `[${e.field}] ${e.message}`).join(", ")}`,
|
|
380
|
+
// validationErrors,
|
|
381
|
+
// };
|
|
382
|
+
// }
|
|
383
|
+
// await entity.save();
|
|
384
|
+
// return { success: true, entityId };
|
|
385
|
+
// } catch (e) {
|
|
386
|
+
// const error = e instanceof Error ? e.message : "Unknown error";
|
|
387
|
+
// return { success: false, entityId, error };
|
|
388
|
+
// }
|
|
389
|
+
// },
|
|
390
|
+
// }),
|
|
391
|
+
// },
|
|
392
|
+
// });
|
|
393
|
+
// }
|
|
394
|
+
// }
|
|
395
|
+
// /**
|
|
396
|
+
// * Entity JSON이 entity.instructions.md의 규칙을 따르는지 검증합니다.
|
|
397
|
+
// */
|
|
398
|
+
// function validateEntityJson(input: TemplateOptions["entity"]): ValidationError[] {
|
|
399
|
+
// const errors: ValidationError[] = [];
|
|
400
|
+
// const { entityId, props, enums } = input;
|
|
401
|
+
// // 1. id, created_at prop 필수
|
|
402
|
+
// const hasIdProp = props?.some((p) => p.name === "id");
|
|
403
|
+
// if (!hasIdProp) {
|
|
404
|
+
// errors.push({ field: "props", message: "id 프로퍼티가 필수입니다." });
|
|
405
|
+
// }
|
|
406
|
+
// const hasCreatedAtProp = props?.some((p) => p.name === "created_at");
|
|
407
|
+
// if (!hasCreatedAtProp) {
|
|
408
|
+
// errors.push({ field: "props", message: "created_at 프로퍼티가 필수입니다." });
|
|
409
|
+
// }
|
|
410
|
+
// // 2. 필수 enum 검증: EntityNameOrderBy, EntityNameSearchField
|
|
411
|
+
// const orderByEnumId = `${entityId}OrderBy`;
|
|
412
|
+
// const searchFieldEnumId = `${entityId}SearchField`;
|
|
413
|
+
// if (!enums?.[orderByEnumId]) {
|
|
414
|
+
// errors.push({
|
|
415
|
+
// field: "enums",
|
|
416
|
+
// message: `${orderByEnumId} enum이 필수입니다. (예: { "id-desc": "ID최신순" })`,
|
|
417
|
+
// });
|
|
418
|
+
// }
|
|
419
|
+
// if (!enums?.[searchFieldEnumId]) {
|
|
420
|
+
// errors.push({
|
|
421
|
+
// field: "enums",
|
|
422
|
+
// message: `${searchFieldEnumId} enum이 필수입니다. (예: { "id": "ID" })`,
|
|
423
|
+
// });
|
|
424
|
+
// }
|
|
425
|
+
// // 3. enum prop의 id가 enums에 정의되어 있는지 확인 (cross-field 검증)
|
|
426
|
+
// for (const prop of props ?? []) {
|
|
427
|
+
// if (prop.type === "enum" && !enums?.[prop.id]) {
|
|
428
|
+
// errors.push({
|
|
429
|
+
// field: `props.${prop.name}`,
|
|
430
|
+
// message: `enum id "${prop.id}"가 enums에 정의되어 있지 않습니다.`,
|
|
431
|
+
// });
|
|
432
|
+
// }
|
|
433
|
+
// }
|
|
434
|
+
// return errors;
|
|
435
|
+
// }
|
|
436
|
+
// export const aiClient = new AIClient();
|
|
437
|
+
|
|
438
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91aS9haS1jbGllbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gaW1wb3J0IHsgYW50aHJvcGljIH0gZnJvbSBcIkBhaS1zZGsvYW50aHJvcGljXCI7XG4vLyBpbXBvcnQgeyB0eXBlIE1vZGVsTWVzc2FnZSwgc3RlcENvdW50SXMsIHN0cmVhbVRleHQsIHRvb2wgfSBmcm9tIFwiYWlcIjtcbi8vIGltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuLy8gaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuLy8gaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbi8vIGltcG9ydCB7XG4vLyAgIEVudGl0eU1hbmFnZXIsXG4vLyAgIHR5cGUgRW50aXR5UHJvcCxcbi8vICAgdHlwZSBGaXh0dXJlUmVjb3JkLFxuLy8gICBub25OdWxsYWJsZSxcbi8vICAgU29uYW11LFxuLy8gICBUZW1wbGF0ZU9wdGlvbnMsXG4vLyB9IGZyb20gXCJzb25hbXVcIjtcbi8vIGltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbi8vIHR5cGUgVmFsaWRhdGlvbkVycm9yID0ge1xuLy8gICBmaWVsZDogc3RyaW5nO1xuLy8gICBtZXNzYWdlOiBzdHJpbmc7XG4vLyB9O1xuXG4vLyBjbGFzcyBBSUNsaWVudCB7XG4vLyAgIHByaXZhdGUgbW9kZWwgPSBhbnRocm9waWMoXCJjbGF1ZGUtc29ubmV0LTQtNVwiKTtcblxuLy8gICBhc3luYyBpbml0KCkge1xuLy8gICAgIGNvbnNvbGUubG9nKFwiQUkgY2xpZW50IGluaXRpYWxpemVkIHdpdGggQUkgU0RLXCIpO1xuLy8gICB9XG5cbi8vICAgaGFuZGxlRml4dHVyZShtZXNzYWdlczogTW9kZWxNZXNzYWdlW10sIGZpeHR1cmVSZWNvcmRzOiBGaXh0dXJlUmVjb3JkW10pIHtcbi8vICAgICAvLyDtmITsnqwgZml4dHVyZVJlY29yZHPsl5DshJwg7IKs7Jqp65CcIOyXlO2LsO2LsOuTpOydmCDqtazsobAg7KCV67O0IOyImOynkVxuLy8gICAgIGNvbnN0IHVzZWRFbnRpdHlJZHMgPSBbLi4ubmV3IFNldChmaXh0dXJlUmVjb3Jkcy5tYXAoKHIpID0+IHIuZW50aXR5SWQpKV07XG4vLyAgICAgY29uc3QgZW50aXR5U3RydWN0dXJlcyA9IHVzZWRFbnRpdHlJZHMubWFwKChlbnRpdHlJZCkgPT4ge1xuLy8gICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZW50aXR5SWQpO1xuXG4vLyAgICAgICByZXR1cm4ge1xuLy8gICAgICAgICBlbnRpdHlJZDogZW50aXR5LmlkLFxuLy8gICAgICAgICB0YWJsZTogZW50aXR5LnRhYmxlLFxuLy8gICAgICAgICBwcm9wczogZW50aXR5LnByb3BzLFxuLy8gICAgICAgICByZWxhdGlvbnM6IGVudGl0eS5yZWxhdGlvbnMsXG4vLyAgICAgICAgIGVudW1MYWJlbHM6IGVudGl0eS5lbnVtTGFiZWxzLFxuLy8gICAgICAgfTtcbi8vICAgICB9KTtcblxuLy8gICAgIGNvbnN0IHN5c3RlbU1lc3NhZ2UgPSBgXG4vLyAgICAgICAgIOuLueyLoOydgCDtlL3siqTss5Ag66CI7L2U65Oc66W8IOyImOygle2VmOqzoCDsg53shLHtlaAg7IiYIOyeiOuKlCDrj4TsmrDrr7jsnoXri4jri6QuXG5cbi8vICAgICAgICAg7ZiE7J6sIO2UveyKpOyzkCDroIjsvZTrk5w6XG4vLyAgICAgICAgICR7SlNPTi5zdHJpbmdpZnkoZml4dHVyZVJlY29yZHMsIG51bGwsIDIpfVxuXG4vLyAgICAgICAgIOyXlO2LsO2LsCDqtazsobAg7KCV67O0OlxuLy8gICAgICAgICAke0pTT04uc3RyaW5naWZ5KGVudGl0eVN0cnVjdHVyZXMsIG51bGwsIDIpfVxuXG4vLyAgICAgICAgICMjIO2UveyKpOyzkCDsiJjsoJVcbi8vICAgICAgICAg7IKs7Jqp7J6Q6rCAIO2UveyKpOyzkCDqsJIg7IiY7KCV7J2EIOyalOyyre2VmOuptCB1cGRhdGVGaXh0dXJlcyDrj4Tqtazrpbwg7IKs7Jqp7ZWY7JesIOuzgOqyveyCrO2VreydhCDsoIHsmqntlZjshLjsmpQuXG4vLyAgICAgICAgIC0gZml4dHVyZUlkOiDsiJjsoJXtlaAg7ZS97Iqk7LOQIElEICjtmJXsi506IFwiRW50aXR5SWQjaWRcIilcbi8vICAgICAgICAgLSB1cGRhdGVzOiDsu6zrn7zrqoXsnYQg7YKk66GcLCDsg4gg6rCS7J2EIOqwkuycvOuhnCDtlZjripQg6rCd7LK0XG5cbi8vICAgICAgICAg7JiI7IucOiBcIlVzZXIjMVwiIO2UveyKpOyzkOydmCBcIm5hbWVcIiDsu6zrn7zsnYQgXCLtmY3quLjrj5lcIuycvOuhnCDrs4Dqsr3tlZjroKTrqbQ6XG4vLyAgICAgICAgIHVwZGF0ZUZpeHR1cmVzKHsgdXBkYXRlczogW3sgZml4dHVyZUlkOiBcIlVzZXIjMVwiLCB1cGRhdGVzOiB7IG5hbWU6IFwi7ZmN6ri464+ZXCIgfSB9XSB9KVxuXG4vLyAgICAgICAgIOuzgOqyveuQoCDsu6zrn7zsnZggdHlwZeydtCByZWxhdGlvbuyduCDqsr3smrAsIOq0gOugqCDsl5Tti7Dti7Dsl5Drj4Qg67CY7JiB65CY7Ja07JW8IO2VoCDsu6zrn7zsnbQg7J6I64qU7KeAIO2ZleyduO2VmOyEuOyalC5cblxuLy8gICAgICAgICAjIyDtlL3siqTss5Ag7IOd7ISxXG4vLyAgICAgICAgIOyCrOyaqeyekOqwgCDsg4jroZzsmrQg7ZS97Iqk7LOQIOyDneyEseydhCDsmpTssq3tlZjrqbQgY3JlYXRlRml4dHVyZXMg64+E6rWs66W8IOyCrOyaqe2VmOyEuOyalC5cbi8vICAgICAgICAgLSBlbnRpdHlJZDog7IOd7ISx7ZWgIOyXlO2LsO2LsCBJRFxuLy8gICAgICAgICAtIGlkOiDsg4gg66CI7L2U65Oc7J2YIElEICjquLDsobQg7ZS97Iqk7LOQ7JmAIOykkeuzteuQmOyngCDslYrripQg7J2M7IiYIOyCrOyaqSDqtozsnqUsIOyYiDogLTEsIC0yKVxuLy8gICAgICAgICAtIGNvbHVtbnM6IOy7rOufvOuqheydhCDtgqTroZwsIOqwkuydhCDqsJLsnLzroZwg7ZWY64qUIOqwneyytCAo7JeU7Yuw7YuwIOq1rOyhsCDssLjqs6ApXG5cbi8vICAgICAgICAg7JiI7IucOiDsg4jroZzsmrQgVXNlciDtlL3siqTss5Drpbwg7IOd7ISx7ZWY66Ck66m0OlxuLy8gICAgICAgICBjcmVhdGVGaXh0dXJlcyh7IGZpeHR1cmVzOiBbeyBlbnRpdHlJZDogXCJVc2VyXCIsIGlkOiAtMSwgY29sdW1uczogeyBuYW1lOiBcIu2Zjeq4uOuPmVwiLCBlbWFpbDogXCJob25nQGV4YW1wbGUuY29tXCIgfSB9XSB9KVxuLy8gICAgICAgYDtcblxuLy8gICAgIHJldHVybiBzdHJlYW1UZXh0KHtcbi8vICAgICAgIG1vZGVsOiB0aGlzLm1vZGVsLFxuLy8gICAgICAgc3lzdGVtOiBzeXN0ZW1NZXNzYWdlLFxuLy8gICAgICAgbWVzc2FnZXMsXG4vLyAgICAgICB0b29sczoge1xuLy8gICAgICAgICB1cGRhdGVGaXh0dXJlczogdG9vbCh7XG4vLyAgICAgICAgICAgZGVzY3JpcHRpb246XG4vLyAgICAgICAgICAgICBcIu2UveyKpOyzkCDroIjsvZTrk5zsnZgg6rCS7J2EIOyImOygle2VqeuLiOuLpC4g7IKs7Jqp7J6Q6rCAIO2KueyglSDsu6zrn7zsnbTrgpgg6rCS7J2EIOuzgOqyve2VtOuLrOudvOqzoCDsmpTssq3tlaAg65WMIOyCrOyaqe2VmOyEuOyalC5cIixcbi8vICAgICAgICAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuLy8gICAgICAgICAgICAgdXBkYXRlczogei5hcnJheShcbi8vICAgICAgICAgICAgICAgei5vYmplY3Qoe1xuLy8gICAgICAgICAgICAgICAgIGZpeHR1cmVJZDogei5zdHJpbmcoKS5kZXNjcmliZShcIuyImOygle2VoCDtlL3siqTss5AgSUQgKO2YleyLnTogRW50aXR5SWQjaWQpXCIpLFxuLy8gICAgICAgICAgICAgICAgIHVwZGF0ZXM6IHpcbi8vICAgICAgICAgICAgICAgICAgIC5yZWNvcmQoei5zdHJpbmcoKSwgei51bmtub3duKCkpXG4vLyAgICAgICAgICAgICAgICAgICAuZGVzY3JpYmUoXCLsu6zrn7zrqoXsnYQg7YKk66GcLCDsg4gg6rCS7J2EIOqwkuycvOuhnCDtlZjripQg6rCd7LK0XCIpLFxuLy8gICAgICAgICAgICAgICB9KSxcbi8vICAgICAgICAgICAgICksXG4vLyAgICAgICAgICAgfSksXG4vLyAgICAgICAgICAgZXhlY3V0ZTogYXN5bmMgKHtcbi8vICAgICAgICAgICAgIHVwZGF0ZXMsXG4vLyAgICAgICAgICAgfSk6IFByb21pc2U8eyBzdWNjZXNzOiBib29sZWFuOyB1cGRhdGVkUmVjb3JkczogRml4dHVyZVJlY29yZFtdIH0+ID0+IHtcbi8vICAgICAgICAgICAgIC8vIGZpeHR1cmVSZWNvcmRz66W8IOuzteyCrO2VmOqzoCDsl4XrjbDsnbTtirgg7KCB7JqpXG4vLyAgICAgICAgICAgICBjb25zdCB1cGRhdGVkUmVjb3JkczogRml4dHVyZVJlY29yZFtdID0gZml4dHVyZVJlY29yZHMubWFwKChyZWNvcmQpID0+IHtcbi8vICAgICAgICAgICAgICAgY29uc3QgdXBkYXRlID0gdXBkYXRlcy5maW5kKCh1KSA9PiB1LmZpeHR1cmVJZCA9PT0gcmVjb3JkLmZpeHR1cmVJZCk7XG4vLyAgICAgICAgICAgICAgIGlmICh1cGRhdGUpIHtcbi8vICAgICAgICAgICAgICAgICAvLyBjb2x1bW5z7J2YIHZhbHVl66W8IOyXheuNsOydtO2KuFxuLy8gICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2NvbHVtbk5hbWUsIG5ld1ZhbHVlXSBvZiBPYmplY3QuZW50cmllcyh1cGRhdGUudXBkYXRlcykpIHtcbi8vICAgICAgICAgICAgICAgICAgIHJlY29yZC5jb2x1bW5zW2NvbHVtbk5hbWVdLnZhbHVlID1cbi8vICAgICAgICAgICAgICAgICAgICAgbmV3VmFsdWUgYXMgRml4dHVyZVJlY29yZFtcImNvbHVtbnNcIl1bc3RyaW5nXVtcInZhbHVlXCJdO1xuLy8gICAgICAgICAgICAgICAgIH1cbi8vICAgICAgICAgICAgICAgICByZXR1cm4gcmVjb3JkO1xuLy8gICAgICAgICAgICAgICB9XG5cbi8vICAgICAgICAgICAgICAgcmV0dXJuIHJlY29yZDtcbi8vICAgICAgICAgICAgIH0pO1xuXG4vLyAgICAgICAgICAgICByZXR1cm4geyBzdWNjZXNzOiB0cnVlLCB1cGRhdGVkUmVjb3JkcyB9O1xuLy8gICAgICAgICAgIH0sXG4vLyAgICAgICAgIH0pLFxuLy8gICAgICAgICBjcmVhdGVGaXh0dXJlczogdG9vbCh7XG4vLyAgICAgICAgICAgZGVzY3JpcHRpb246XG4vLyAgICAgICAgICAgICBcIuyDiOuhnOyatCDtlL3siqTss5Ag66CI7L2U65Oc66W8IOyDneyEse2VqeuLiOuLpC4g7IKs7Jqp7J6Q6rCAIOyDiOuhnOyatCDrjbDsnbTthLDrpbwg7LaU6rCA7ZW064us65286rOgIOyalOyyre2VoCDrlYwg7IKs7Jqp7ZWY7IS47JqULlwiLFxuLy8gICAgICAgICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4vLyAgICAgICAgICAgICBmaXh0dXJlczogei5hcnJheShcbi8vICAgICAgICAgICAgICAgei5vYmplY3Qoe1xuLy8gICAgICAgICAgICAgICAgIGVudGl0eUlkOiB6LnN0cmluZygpLmRlc2NyaWJlKFwi7IOd7ISx7ZWgIOyXlO2LsO2LsCBJRFwiKSxcbi8vICAgICAgICAgICAgICAgICBpZDogei5udW1iZXIoKS5kZXNjcmliZShcIuyDiCDroIjsvZTrk5zsnZggSUQgKOydjOyImCDqtozsnqUsIOyYiDogLTEsIC0yKVwiKSxcbi8vICAgICAgICAgICAgICAgICBjb2x1bW5zOiB6XG4vLyAgICAgICAgICAgICAgICAgICAucmVjb3JkKHouc3RyaW5nKCksIHoudW5rbm93bigpKVxuLy8gICAgICAgICAgICAgICAgICAgLmRlc2NyaWJlKFwi7Lus65+866qF7J2EIO2CpOuhnCwg6rCS7J2EIOqwkuycvOuhnCDtlZjripQg6rCd7LK0XCIpLFxuLy8gICAgICAgICAgICAgICB9KSxcbi8vICAgICAgICAgICAgICksXG4vLyAgICAgICAgICAgfSksXG4vLyAgICAgICAgICAgZXhlY3V0ZTogYXN5bmMgKHtcbi8vICAgICAgICAgICAgIGZpeHR1cmVzLFxuLy8gICAgICAgICAgIH0pOiBQcm9taXNlPHsgc3VjY2VzczogYm9vbGVhbjsgdXBkYXRlZFJlY29yZHM6IEZpeHR1cmVSZWNvcmRbXSB9PiA9PiB7XG4vLyAgICAgICAgICAgICBjb25zdCBuZXdSZWNvcmRzOiBGaXh0dXJlUmVjb3JkW10gPSBmaXh0dXJlcy5tYXAoKGZpeHR1cmUpID0+IHtcbi8vICAgICAgICAgICAgICAgY29uc3QgZW50aXR5ID0gRW50aXR5TWFuYWdlci5nZXQoZml4dHVyZS5lbnRpdHlJZCk7XG5cbi8vICAgICAgICAgICAgICAgLy8g7JeU7Yuw7YuwIHByb3Bz66W8IOq4sOuwmOycvOuhnCBjb2x1bW5zIOq1rOyEsVxuLy8gICAgICAgICAgICAgICBjb25zdCBjb2x1bW5zOiBGaXh0dXJlUmVjb3JkW1wiY29sdW1uc1wiXSA9IHt9O1xuLy8gICAgICAgICAgICAgICBmb3IgKGNvbnN0IHByb3Agb2YgZW50aXR5LnByb3BzKSB7XG4vLyAgICAgICAgICAgICAgICAgaWYgKHByb3AudHlwZSA9PT0gXCJ2aXJ0dWFsXCIpIGNvbnRpbnVlO1xuXG4vLyAgICAgICAgICAgICAgICAgbGV0IHZhbHVlID0gZml4dHVyZS5jb2x1bW5zW3Byb3AubmFtZV0gPz8gbnVsbDtcblxuLy8gICAgICAgICAgICAgICAgIGlmIChwcm9wLm5hbWUgPT09IFwiY3JlYXRlZF9hdFwiKSB7XG4vLyAgICAgICAgICAgICAgICAgICAvLyDtmITsnqwg7Iuc6rCE7Jy866GcIOyEpOyglVxuLy8gICAgICAgICAgICAgICAgICAgdmFsdWUgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG4vLyAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChcbi8vICAgICAgICAgICAgICAgICAgIHByb3AudHlwZSA9PT0gXCJyZWxhdGlvblwiICYmXG4vLyAgICAgICAgICAgICAgICAgICAocHJvcC5yZWxhdGlvblR5cGUgPT09IFwiSGFzTWFueVwiIHx8IHByb3AucmVsYXRpb25UeXBlID09PSBcIk1hbnlUb01hbnlcIilcbi8vICAgICAgICAgICAgICAgICApIHtcbi8vICAgICAgICAgICAgICAgICAgIC8vIOuwsOyXtOuhnCDrs4DtmZhcbi8vICAgICAgICAgICAgICAgICAgIHZhbHVlID0gQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZSA6IFt2YWx1ZV0uZmlsdGVyKG5vbk51bGxhYmxlKTtcbi8vICAgICAgICAgICAgICAgICB9XG5cbi8vICAgICAgICAgICAgICAgICBjb2x1bW5zW3Byb3AubmFtZV0gPSB7XG4vLyAgICAgICAgICAgICAgICAgICBwcm9wLFxuLy8gICAgICAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlIGFzIEZpeHR1cmVSZWNvcmRbXCJjb2x1bW5zXCJdW3N0cmluZ11bXCJ2YWx1ZVwiXSxcbi8vICAgICAgICAgICAgICAgICB9O1xuLy8gICAgICAgICAgICAgICB9XG5cbi8vICAgICAgICAgICAgICAgcmV0dXJuIHtcbi8vICAgICAgICAgICAgICAgICBmaXh0dXJlSWQ6IGAke2ZpeHR1cmUuZW50aXR5SWR9IyR7Zml4dHVyZS5pZH1gLFxuLy8gICAgICAgICAgICAgICAgIGVudGl0eUlkOiBmaXh0dXJlLmVudGl0eUlkLFxuLy8gICAgICAgICAgICAgICAgIGlkOiBmaXh0dXJlLmlkLFxuLy8gICAgICAgICAgICAgICAgIGNvbHVtbnMsXG4vLyAgICAgICAgICAgICAgICAgZmV0Y2hlZFJlY29yZHM6IFtdLFxuLy8gICAgICAgICAgICAgICAgIGJlbG9uZ3NSZWNvcmRzOiBbXSxcbi8vICAgICAgICAgICAgICAgICBvdmVycmlkZTogZmFsc2UsXG4vLyAgICAgICAgICAgICAgIH07XG4vLyAgICAgICAgICAgICB9KTtcblxuLy8gICAgICAgICAgICAgLy8g7IOIIOugiOy9lOuTnOuTpOydmCByZWxhdGlvbiDsu6zrn7zsnYQg7ZmV7J247ZWY7JesIOq4sOyhtCDroIjsvZTrk5zrk6TsnZgg7Jet67Cp7ZalIHJlbGF0aW9uIOyXheuNsOydtO2KuFxuLy8gICAgICAgICAgICAgZm9yIChjb25zdCBuZXdSZWNvcmQgb2YgbmV3UmVjb3Jkcykge1xuLy8gICAgICAgICAgICAgICBmb3IgKGNvbnN0IFtfY29sTmFtZSwgY29sXSBvZiBPYmplY3QuZW50cmllcyhuZXdSZWNvcmQuY29sdW1ucykpIHtcbi8vICAgICAgICAgICAgICAgICBpZiAoY29sLnByb3AudHlwZSAhPT0gXCJyZWxhdGlvblwiIHx8IGNvbC52YWx1ZSA9PT0gbnVsbCkgY29udGludWU7XG5cbi8vICAgICAgICAgICAgICAgICBjb25zdCByZWxhdGVkRW50aXR5SWQgPSBjb2wucHJvcC53aXRoO1xuLy8gICAgICAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRJZHMgPSBBcnJheS5pc0FycmF5KGNvbC52YWx1ZSkgPyBjb2wudmFsdWUgOiBbY29sLnZhbHVlXTtcblxuLy8gICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcmVsYXRlZElkIG9mIHJlbGF0ZWRJZHMpIHtcbi8vICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlbGF0ZWRGaXh0dXJlSWQgPSBgJHtyZWxhdGVkRW50aXR5SWR9IyR7cmVsYXRlZElkfWA7XG4vLyAgICAgICAgICAgICAgICAgICBjb25zdCByZWxhdGVkUmVjb3JkID0gbmV3UmVjb3Jkcy5maW5kKChyKSA9PiByLmZpeHR1cmVJZCA9PT0gcmVsYXRlZEZpeHR1cmVJZCk7XG5cbi8vICAgICAgICAgICAgICAgICAgIGlmIChyZWxhdGVkUmVjb3JkKSB7XG4vLyAgICAgICAgICAgICAgICAgICAgIC8vIOyXreuwqe2WpSByZWxhdGlvbiDssL7quLBcbi8vICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmV2ZXJzZUNvbCA9IE9iamVjdC5lbnRyaWVzKHJlbGF0ZWRSZWNvcmQuY29sdW1ucykuZmluZChcbi8vICAgICAgICAgICAgICAgICAgICAgICAoWywgY10pID0+IGMucHJvcC50eXBlID09PSBcInJlbGF0aW9uXCIgJiYgYy5wcm9wLndpdGggPT09IG5ld1JlY29yZC5lbnRpdHlJZCxcbi8vICAgICAgICAgICAgICAgICAgICAgKTtcblxuLy8gICAgICAgICAgICAgICAgICAgICBpZiAocmV2ZXJzZUNvbCkge1xuLy8gICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFtyZXZlcnNlQ29sTmFtZSwgcmV2ZXJzZUNvbFZhbHVlXSA9IHJldmVyc2VDb2w7XG4vLyAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudFZhbHVlID0gcmV2ZXJzZUNvbFZhbHVlLnZhbHVlO1xuXG4vLyAgICAgICAgICAgICAgICAgICAgICAgLy8g7Jet67Cp7Zal7J20IOuwsOyXtOyduCDqsr3smrAgKEhhc01hbnksIE1hbnlUb01hbnkpXG4vLyAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgcmV2ZXJzZUNvbFZhbHVlLnByb3AudHlwZSA9PT0gXCJyZWxhdGlvblwiICYmXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAocmV2ZXJzZUNvbFZhbHVlLnByb3AucmVsYXRpb25UeXBlID09PSBcIkhhc01hbnlcIiB8fFxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgICByZXZlcnNlQ29sVmFsdWUucHJvcC5yZWxhdGlvblR5cGUgPT09IFwiTWFueVRvTWFueVwiKVxuLy8gICAgICAgICAgICAgICAgICAgICAgICkge1xuLy8gICAgICAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KEFycmF5LmlzQXJyYXkoY3VycmVudFZhbHVlKSwgXCJjdXJyZW50VmFsdWUgbXVzdCBiZSBhbiBhcnJheVwiKTtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY3VycmVudFZhbHVlLmluY2x1ZGVzKG5ld1JlY29yZC5pZCkpIHtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsYXRlZFJlY29yZC5jb2x1bW5zW3JldmVyc2VDb2xOYW1lXSA9IHtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5yZXZlcnNlQ29sVmFsdWUsXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IFsuLi5jdXJyZW50VmFsdWUsIG5ld1JlY29yZC5pZF0sXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4vLyAgICAgICAgICAgICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbi8vICAgICAgICAgICAgICAgICAgICAgICAgIC8vIOyXreuwqe2WpeydtCDri6jsnbwg6rCS7J24IOqyveyasCAoQmVsb25nc1RvT25lLCBPbmVUb09uZSlcbi8vICAgICAgICAgICAgICAgICAgICAgICAgIHJlbGF0ZWRSZWNvcmQuY29sdW1uc1tyZXZlcnNlQ29sTmFtZV0gPSB7XG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnJldmVyc2VDb2xWYWx1ZSxcbi8vICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG5ld1JlY29yZC5pZCxcbi8vICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4vLyAgICAgICAgICAgICAgICAgICAgICAgfVxuLy8gICAgICAgICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICAgICAgfVxuLy8gICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICB9XG5cbi8vICAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUsIHVwZGF0ZWRSZWNvcmRzOiBuZXdSZWNvcmRzIH07XG4vLyAgICAgICAgICAgfSxcbi8vICAgICAgICAgfSksXG4vLyAgICAgICB9LFxuLy8gICAgIH0pO1xuLy8gICB9XG5cbi8vICAgaGFuZGxlRW50aXR5KG1lc3NhZ2VzOiBNb2RlbE1lc3NhZ2VbXSkge1xuLy8gICAgIC8vIGVudGl0eS5pbnN0cnVjdGlvbnMubWQg7YyM7J28IOydveq4sFxuLy8gICAgIGNvbnN0IGluc3RydWN0aW9uc1BhdGggPSBwYXRoLmpvaW4oaW1wb3J0Lm1ldGEuZGlybmFtZSwgXCIuLlwiLCBcImVudGl0eS5pbnN0cnVjdGlvbnMubWRcIik7XG4vLyAgICAgY29uc3QgaW5zdHJ1Y3Rpb25zID0gZnMucmVhZEZpbGVTeW5jKGluc3RydWN0aW9uc1BhdGgsIFwidXRmLThcIik7XG5cbi8vICAgICAvLyDtmITsnqwg65Ox66Gd65CcIOyXlO2LsO2LsCDsoJXrs7Qg7IiY7KeRXG4vLyAgICAgY29uc3QgZW50aXR5SWRzID0gRW50aXR5TWFuYWdlci5nZXRBbGxJZHMoKTtcbi8vICAgICBjb25zdCBleGlzdGluZ0VudGl0aWVzID0gZW50aXR5SWRzLm1hcCgoZW50aXR5SWQpID0+IHtcbi8vICAgICAgIGNvbnN0IGVudGl0eSA9IEVudGl0eU1hbmFnZXIuZ2V0KGVudGl0eUlkKTtcbi8vICAgICAgIHJldHVybiB7XG4vLyAgICAgICAgIGlkOiBlbnRpdHkuaWQsXG4vLyAgICAgICAgIHRpdGxlOiBlbnRpdHkudGl0bGUsXG4vLyAgICAgICAgIHRhYmxlOiBlbnRpdHkudGFibGUsXG4vLyAgICAgICAgIHByb3BzOiBlbnRpdHkucHJvcHMubWFwKChwKSA9PiAoe1xuLy8gICAgICAgICAgIG5hbWU6IHAubmFtZSxcbi8vICAgICAgICAgICB0eXBlOiBwLnR5cGUsXG4vLyAgICAgICAgICAgZGVzYzogcC5kZXNjLFxuLy8gICAgICAgICB9KSksXG4vLyAgICAgICB9O1xuLy8gICAgIH0pO1xuXG4vLyAgICAgY29uc3Qgc3lzdGVtTWVzc2FnZSA9IGBcbi8vIOuLueyLoOydgCBTb25hbXUg7ZSE66CI7J6E7JuM7YGs7JeQ7IScIEVudGl0eeyZgCBFbnVt7J2EIOyDneyEse2VmOuKlCDrj4TsmrDrr7jsnoXri4jri6QuXG5cbi8vICR7aW5zdHJ1Y3Rpb25zfVxuXG4vLyAjIyDtmITsnqwg65Ox66Gd65CcIEVudGl0eSDrqqnroZ1cbi8vIOuLpOuluCDsl5Tti7Dti7DsmYAg6rSA6rOEKHJlbGF0aW9uKeulvCDrp7rqsbDrgpggc3Vic2V07JeQ7IScIOywuOyhsO2VoCDrlYwg67CY65Oc7IucIOyVhOuemCDsoJXrs7Trpbwg7ZmV7J247ZWY7IS47JqULlxuXG4vLyAke0pTT04uc3RyaW5naWZ5KGV4aXN0aW5nRW50aXRpZXMsIG51bGwsIDIpfVxuXG4vLyAjIyBUb29sIOyCrOyaqSDqsIDsnbTrk5xcblxuLy8gIyMjIEVudGl0eSDsg53shLEgKGNyZWF0ZUVudGl0eSlcbi8vIOyCrOyaqeyekOqwgCDsg4jroZzsmrQgRW50aXR5IOyDneyEseydhCDsmpTssq3tlZjrqbQgY3JlYXRlRW50aXR5IOuPhOq1rOulvCDsgqzsmqntlZjshLjsmpQuXG4vLyAtIGVudGl0eUlkOiBQYXNjYWxDYXNl66GcIOuQnCBFbnRpdHkgSUQgKOyYiDogXCJVc2VyXCIsIFwiUHJvZHVjdENhdGVnb3J5XCIpXG4vLyAtIHRpdGxlOiDtlZzquIAg7KCc66qpICjsmIg6IFwi7IKs7Jqp7J6QXCIsIFwi7IOB7ZKIIOy5tO2FjOqzoOumrFwiKVxuLy8gLSB0YWJsZTogc25ha2VfY2FzZeuhnCDrkJwg7YWM7J2067iU66qFICjsmIg6IFwidXNlcnNcIiwgXCJwcm9kdWN0X2NhdGVnb3JpZXNcIilcbi8vIC0gcGFyZW50SWQ6IOu2gOuqqCBFbnRpdHkgSUQgKOyEoO2DneyCrO2VrSlcbi8vIC0gcHJvcHM6IEVudGl0eeydmCDtlITroZztjbzti7Ag67Cw7Je0ICjsnIQg66y47ISc7J2YIFByb3BlcnR5IFR5cGVzIOywuOqzoClcbi8vIC0gaW5kZXhlczog7J24642x7IqkIOuwsOyXtFxuLy8gLSBzdWJzZXRzOiDshJzruIzshYsg7KCV7J2YICjquLDrs7jqsJI6IHsgQTogW1wiaWRcIl0gfSlcbi8vIC0gZW51bXM6IEVudW0g7KCV7J2YXG5cbi8vICMjIyBFbnRpdHkg7IiY7KCVICh1cGRhdGVFbnRpdHkpXG4vLyDquLDsobQgRW50aXR566W8IOyImOygle2VoCDrlYwgdXBkYXRlRW50aXR5IOuPhOq1rOulvCDsgqzsmqntlZjshLjsmpQuIEVudW0g7LaU6rCALCBwcm9wcyDstpTqsIAv7IiY7KCVLCBpbmRleGVzIOyImOyglSDrk7Eg66qo65OgIOyImOyglSDsnpHsl4Xsl5Ag7IKs7Jqp7ZWp64uI64ukLlxuLy8gLSBlbnRpdHlJZDog7IiY7KCV7ZWgIEVudGl0eSBJRFxuLy8gLSB1cGRhdGVzOiDsiJjsoJXtlaAg7ZWE65Oc65OkICjrtoDrtoQg7JeF642w7J207Yq4KVxuLy8gICAtIHRpdGxlOiDsl5Tti7Dti7Ag7ZWc6riAIOygnOuqqVxuLy8gICAtIHRhYmxlOiDthYzsnbTruJTrqoVcbi8vICAgLSBwcm9wczog7LaU6rCA7ZWgIO2UhOuhnO2NvO2LsCDrsLDsl7QgKOq4sOyhtCBwcm9wc+yXkCDstpTqsIAsIOqwmeydgCDsnbTrpoTsnbTrqbQg6rWQ7LK0KVxuLy8gICAtIGluZGV4ZXM6IOy2lOqwgO2VoCDsnbjrjbHsiqQg67Cw7Je0ICjquLDsobQgaW5kZXhlc+yXkCDstpTqsIApXG4vLyAgIC0gc3Vic2V0czog7ISc67iM7IWLIOygleydmCAo6riw7KG0IHN1YnNldHPsl5Ag67OR7ZWpKVxuLy8gICAtIGVudW1MYWJlbHM6IEVudW0g7KCV7J2YICjquLDsobQgZW51bUxhYmVsc+yXkCDrs5HtlakpXG4vLyAtIG1vZGU6IFwibWVyZ2VcIijquLDrs7jqsJIpIOuYkOuKlCBcInJlcGxhY2VcIlxuLy8gICAtIG1lcmdlOiDquLDsobQg6rCS7JeQIOuzke2VqVxuLy8gICAtIHJlcGxhY2U6IO2VtOuLuSDtlYTrk5wg7KCE7LK0IOq1kOyytFxuXG4vLyDsmIjsi5w6IEVtcGxveWVl7JeQIOyDiCBFbnVtIOy2lOqwgFxuLy8gdXBkYXRlRW50aXR5KHsgZW50aXR5SWQ6IFwiRW1wbG95ZWVcIiwgdXBkYXRlczogeyBlbnVtTGFiZWxzOiB7IFwiRW1wbG95ZWVSb2xlXCI6IHsgXCJhZG1pblwiOiBcIuq0gOumrOyekFwiLCBcInVzZXJcIjogXCLsnbzrsJhcIiB9IH0gfSB9KVxuXG4vLyDsmIjsi5w6IFByb2plY3Tsl5Ag7IOIIO2UhOuhnO2NvO2LsCDstpTqsIBcbi8vIHVwZGF0ZUVudGl0eSh7IGVudGl0eUlkOiBcIlByb2plY3RcIiwgdXBkYXRlczogeyBwcm9wczogW3sgbmFtZTogXCJwcmlvcml0eVwiLCB0eXBlOiBcImludGVnZXJcIiwgZGVzYzogXCLsmrDshKDsiJzsnIRcIiB9XSB9IH0pXG5cbi8vICMjIO2VhOyImCDsgqztla1cbi8vIC0gRW50aXR57J2YIHByb3Bz7JeQ64qUIOy1nOyGjO2VnCBpZChpbnRlZ2VyLCB1bnNpZ25lZCksIGNyZWF0ZWRfYXQodGltZXN0YW1wKeqwgCDtj6ztlajrkJjslrTslbwg7ZWp64uI64ukLlxuLy8gLSByZWxhdGlvbiDtlYTrk5zripQgb25VcGRhdGUsIG9uRGVsZXRl6rCAIO2VhOyImOyeheuLiOuLpC4gKOyYiOyZuDogT25lVG9PbmXsl5DshJwgaGFzSm9pbkNvbHVtbuydtCBmYWxzZeyduCDqsr3smrApXG4vLyAtIEVudW0gSUTripQg67O07Ya1IEVudGl0eUlkICsg7IaN7ISx66qFIO2Yle2DnOyeheuLiOuLpCAo7JiIOiBVc2VyU3RhdHVzLCBQcm9kdWN0VHlwZSlcbi8vIC0gc3Vic2V07JeQ7IScIOuLpOuluCDsl5Tti7Dti7DsnZgg7ZSE66Gc7Y287Yuw66W8IOywuOyhsO2VoCDrlYzripQg67CY65Oc7IucIO2VtOuLuSDsl5Tti7Dti7DsnZgg7Iuk7KCcIO2UhOuhnO2NvO2LsOuqheydhCDsgqzsmqntlZjshLjsmpQuXG5cbi8vICMjIOqygOymnSDsmKTrpZgg7LKY66asXG4vLyDrj4Tqtawg7Zi47LacIOqysOqzvOuhnCDqsoDspp0g7Jik66WYKHZhbGlkYXRpb25FcnJvcnMp6rCAIOuwmO2ZmOuQmOuptDpcbi8vIDEuIOyYpOulmCDrqZTsi5zsp4Drpbwg67aE7ISd7ZWY7JesIOusuOygnOygkOydhCDtjIzslYXtlZjshLjsmpQuXG4vLyAyLiDsmKTrpZjrpbwg7IiY7KCV7ZWcIOuNsOydtO2EsOuhnCBjcmVhdGVFbnRpdHnrpbwg64uk7IucIO2YuOy2nO2VmOyEuOyalC5cbi8vIDMuIOyCrOyaqeyekOyXkOqyjCDsmKTrpZjrpbwg6re464yA66GcIOyghOuLrO2VmOyngCDrp5Dqs6AsIOyImOyglSDtm4Qg7J6s7Iuc64+E7ZWY7IS47JqULlxuXG4vLyAjIyMg7J2867CY7KCB7J24IOqygOymnSDsmKTrpZjsmYAg7IiY7KCVIOuwqeuylVxuLy8gfCDsmKTrpZgg66mU7Iuc7KeAIHwg7IiY7KCVIOuwqeuylSB8XG4vLyB8LS0tLS0tLS0tLS0tfC0tLS0tLS0tLS18XG4vLyB8IFwiaWQg7ZSE66Gc7Y287Yuw6rCAIO2VhOyImFwiIHwgcHJvcHPsl5AgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwiaW50ZWdlclwiLCB1bnNpZ25lZDogdHJ1ZSB9IOy2lOqwgCB8XG4vLyB8IFwiY3JlYXRlZF9hdCDtlITroZztjbzti7DqsIAg7ZWE7IiYXCIgfCBwcm9wc+yXkCB7IG5hbWU6IFwiY3JlYXRlZF9hdFwiLCB0eXBlOiBcInRpbWVzdGFtcFwiLCBkYkRlZmF1bHQ6IFwiQ1VSUkVOVF9USU1FU1RBTVBcIiB9IOy2lOqwgCB8XG4vLyB8IFwiWHh4T3JkZXJCeSBlbnVt7J20IO2VhOyImFwiIHwgZW51bXPsl5AgeyBcIlh4eE9yZGVyQnlcIjogeyBcImlkLWRlc2NcIjogXCJJROy1nOyLoOyInFwiIH0gfSDstpTqsIAgfFxuLy8gfCBcIlh4eFNlYXJjaEZpZWxkIGVudW3snbQg7ZWE7IiYXCIgfCBlbnVtc+yXkCB7IFwiWHh4U2VhcmNoRmllbGRcIjogeyBcImlkXCI6IFwiSURcIiB9IH0g7LaU6rCAIHxcbi8vIHwgXCJzdHJpbmcg7YOA7J6F7J2AIGxlbmd0aOqwgCDtlYTsiJhcIiB8IO2VtOuLuSBwcm9w7JeQIGxlbmd0aCDstpTqsIAgKOyYiDogMjU1KSB8XG4vLyB8IFwidGV4dCDtg4DsnoXsnYAgdGV4dFR5cGXsnbQg7ZWE7IiYXCIgfCDtlbTri7kgcHJvcOyXkCB0ZXh0VHlwZSDstpTqsIAgKFwidGV4dFwiLCBcIm1lZGl1bXRleHRcIiwgXCJsb25ndGV4dFwiKSB8XG4vLyB8IFwib25VcGRhdGXqsIAg7ZWE7IiYXCIgfCDtlbTri7kgcmVsYXRpb24gcHJvcOyXkCBvblVwZGF0ZSwgb25EZWxldGUg7LaU6rCAIChcIkNBU0NBREVcIikgfFxuLy8gICAgICAgYDtcblxuLy8gICAgIHJldHVybiBzdHJlYW1UZXh0KHtcbi8vICAgICAgIG1vZGVsOiB0aGlzLm1vZGVsLFxuLy8gICAgICAgc3lzdGVtOiBzeXN0ZW1NZXNzYWdlLFxuLy8gICAgICAgbWVzc2FnZXMsXG4vLyAgICAgICBzdG9wV2hlbjogc3RlcENvdW50SXMoMiksXG4vLyAgICAgICB0b29sczoge1xuLy8gICAgICAgICBjcmVhdGVFbnRpdHk6IHRvb2woe1xuLy8gICAgICAgICAgIGRlc2NyaXB0aW9uOlxuLy8gICAgICAgICAgICAgXCLsg4jroZzsmrQgRW50aXR566W8IOyDneyEse2VqeuLiOuLpC4g7IKs7Jqp7J6Q6rCAIOyDiOuhnOyatCDsl5Tti7Dti7Drgpgg7YWM7J2067iUIOyDneyEseydhCDsmpTssq3tlaAg65WMIOyCrOyaqe2VmOyEuOyalC5cIixcbi8vICAgICAgICAgICBpbnB1dFNjaGVtYTogVGVtcGxhdGVPcHRpb25zLnNoYXBlLmVudGl0eSxcbi8vICAgICAgICAgICBleGVjdXRlOiBhc3luYyAoXG4vLyAgICAgICAgICAgICBlbnRpdHksXG4vLyAgICAgICAgICAgKTogUHJvbWlzZTx7XG4vLyAgICAgICAgICAgICBzdWNjZXNzOiBib29sZWFuO1xuLy8gICAgICAgICAgICAgZW50aXR5SWQ6IHN0cmluZztcbi8vICAgICAgICAgICAgIGVycm9yPzogc3RyaW5nO1xuLy8gICAgICAgICAgICAgdmFsaWRhdGlvbkVycm9ycz86IFZhbGlkYXRpb25FcnJvcltdO1xuLy8gICAgICAgICAgIH0+ID0+IHtcbi8vICAgICAgICAgICAgIHRyeSB7XG4vLyAgICAgICAgICAgICAgIC8vIOyeheugpSDqsoDspp1cbi8vICAgICAgICAgICAgICAgY29uc3QgdmFsaWRhdGlvbkVycm9ycyA9IHZhbGlkYXRlRW50aXR5SnNvbihlbnRpdHkpO1xuXG4vLyAgICAgICAgICAgICAgIGlmICh2YWxpZGF0aW9uRXJyb3JzLmxlbmd0aCA+IDApIHtcbi8vICAgICAgICAgICAgICAgICByZXR1cm4ge1xuLy8gICAgICAgICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4vLyAgICAgICAgICAgICAgICAgICBlbnRpdHlJZDogZW50aXR5LmVudGl0eUlkLFxuLy8gICAgICAgICAgICAgICAgICAgZXJyb3I6IGDqsoDspp0g7Jik66WYOiAke3ZhbGlkYXRpb25FcnJvcnMubWFwKChlKSA9PiBgWyR7ZS5maWVsZH1dICR7ZS5tZXNzYWdlfWApLmpvaW4oXCIsIFwiKX1gLFxuLy8gICAgICAgICAgICAgICAgICAgdmFsaWRhdGlvbkVycm9ycyxcbi8vICAgICAgICAgICAgICAgICB9O1xuLy8gICAgICAgICAgICAgICB9XG5cbi8vICAgICAgICAgICAgICAgYXdhaXQgU29uYW11LnN5bmNlci5jcmVhdGVFbnRpdHkoe1xuLy8gICAgICAgICAgICAgICAgIHN1YnNldHM6IHsgQTogW1wiaWRcIl0gfSxcbi8vICAgICAgICAgICAgICAgICBlbnVtczoge30sXG4vLyAgICAgICAgICAgICAgICAgLi4uZW50aXR5LFxuLy8gICAgICAgICAgICAgICB9KTtcblxuLy8gICAgICAgICAgICAgICAvLyBFbnRpdHlNYW5hZ2VyIOumrOuhnOuTnFxuLy8gICAgICAgICAgICAgICBhd2FpdCBFbnRpdHlNYW5hZ2VyLnJlbG9hZCgpO1xuXG4vLyAgICAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUsIGVudGl0eUlkOiBlbnRpdHkuZW50aXR5SWQgfTtcbi8vICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbi8vICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBcIlVua25vd24gZXJyb3JcIjtcbi8vICAgICAgICAgICAgICAgcmV0dXJuIHsgc3VjY2VzczogZmFsc2UsIGVudGl0eUlkOiBlbnRpdHkuZW50aXR5SWQsIGVycm9yIH07XG4vLyAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgfSxcbi8vICAgICAgICAgfSksXG4vLyAgICAgICAgIHVwZGF0ZUVudGl0eTogdG9vbCh7XG4vLyAgICAgICAgICAgZGVzY3JpcHRpb246XG4vLyAgICAgICAgICAgICBcIuq4sOyhtCBFbnRpdHnrpbwg7IiY7KCV7ZWp64uI64ukLiBFbnVtIOy2lOqwgCwgcHJvcHMg7LaU6rCAL+yImOyglSwgaW5kZXhlcyDsiJjsoJUsIHN1YnNldHMg7IiY7KCVIOuTsSDrqqjrk6Ag7JeU7Yuw7YuwIOyImOyglSDsnpHsl4Xsl5Ag7IKs7Jqp7ZWY7IS47JqULlwiLFxuLy8gICAgICAgICAgIGlucHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4vLyAgICAgICAgICAgICBlbnRpdHlJZDogei5zdHJpbmcoKS5kZXNjcmliZShcIuyImOygle2VoCBFbnRpdHkgSURcIiksXG4vLyAgICAgICAgICAgICB1cGRhdGVzOiBUZW1wbGF0ZU9wdGlvbnMuc2hhcGUuZW50aXR5LnBhcnRpYWwoKS5kZXNjcmliZShcIuyImOygle2VoCDtlYTrk5zrk6RcIiksXG4vLyAgICAgICAgICAgICBtb2RlOiB6XG4vLyAgICAgICAgICAgICAgIC5lbnVtKFtcIm1lcmdlXCIsIFwicmVwbGFjZVwiXSlcbi8vICAgICAgICAgICAgICAgLm9wdGlvbmFsKClcbi8vICAgICAgICAgICAgICAgLmRlc2NyaWJlKFwi7IiY7KCVIOuqqOuTnDogbWVyZ2Uo6riw67O46rCSLCDquLDsobQg6rCS7JeQIOuzke2VqSkg65iQ64qUIHJlcGxhY2Uo7KCE7LK0IOq1kOyytClcIiksXG4vLyAgICAgICAgICAgfSksXG4vLyAgICAgICAgICAgZXhlY3V0ZTogYXN5bmMgKHtcbi8vICAgICAgICAgICAgIGVudGl0eUlkLFxuLy8gICAgICAgICAgICAgdXBkYXRlcyxcbi8vICAgICAgICAgICAgIG1vZGUgPSBcIm1lcmdlXCIsXG4vLyAgICAgICAgICAgfSk6IFByb21pc2U8e1xuLy8gICAgICAgICAgICAgc3VjY2VzczogYm9vbGVhbjtcbi8vICAgICAgICAgICAgIGVudGl0eUlkOiBzdHJpbmc7XG4vLyAgICAgICAgICAgICBlcnJvcj86IHN0cmluZztcbi8vICAgICAgICAgICAgIHZhbGlkYXRpb25FcnJvcnM/OiBWYWxpZGF0aW9uRXJyb3JbXTtcbi8vICAgICAgICAgICB9PiA9PiB7XG4vLyAgICAgICAgICAgICB0cnkge1xuLy8gICAgICAgICAgICAgICBjb25zdCBlbnRpdHkgPSBFbnRpdHlNYW5hZ2VyLmdldChlbnRpdHlJZCk7XG5cbi8vICAgICAgICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXModXBkYXRlcykpIHtcbi8vICAgICAgICAgICAgICAgICBpZiAoXG4vLyAgICAgICAgICAgICAgICAgICBbXCJlbnRpdHlJZFwiLCBcInBhcmVudElkXCIsIFwidGl0bGVcIiwgXCJ0YWJsZVwiXS5pbmNsdWRlcyhrZXkpICYmXG4vLyAgICAgICAgICAgICAgICAgICB2YWx1ZSAhPT0gdW5kZWZpbmVkXG4vLyAgICAgICAgICAgICAgICAgKSB7XG4vLyAgICAgICAgICAgICAgICAgICBlbnRpdHlba2V5XSA9IHZhbHVlO1xuLy8gICAgICAgICAgICAgICAgIH1cbi8vICAgICAgICAgICAgICAgfVxuXG4vLyAgICAgICAgICAgICAgIC8vIHByb3BzOiBtZXJnZSDsi5wg7J2066aEIOq4sOykgCDrs5HtlaksIHJlcGxhY2Ug7IucIOq1kOyytFxuLy8gICAgICAgICAgICAgICBpZiAodXBkYXRlcy5wcm9wcyAhPT0gdW5kZWZpbmVkKSB7XG4vLyAgICAgICAgICAgICAgICAgaWYgKG1vZGUgPT09IFwicmVwbGFjZVwiKSB7XG4vLyAgICAgICAgICAgICAgICAgICBlbnRpdHkucHJvcHMgPSB1cGRhdGVzLnByb3BzIGFzIEVudGl0eVByb3BbXTtcbi8vICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuLy8gICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBuZXdQcm9wIG9mIHVwZGF0ZXMucHJvcHMpIHtcbi8vICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhpc3RpbmdJbmRleCA9IGVudGl0eS5wcm9wcy5maW5kSW5kZXgoKHApID0+IHAubmFtZSA9PT0gbmV3UHJvcC5uYW1lKTtcbi8vICAgICAgICAgICAgICAgICAgICAgaWYgKGV4aXN0aW5nSW5kZXggPj0gMCkge1xuLy8gICAgICAgICAgICAgICAgICAgICAgIGVudGl0eS5wcm9wc1tleGlzdGluZ0luZGV4XSA9IG5ld1Byb3AgYXMgRW50aXR5UHJvcDtcbi8vICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbi8vICAgICAgICAgICAgICAgICAgICAgICBlbnRpdHkucHJvcHMucHVzaChuZXdQcm9wIGFzIEVudGl0eVByb3ApO1xuLy8gICAgICAgICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICAgICAgICB9XG4vLyAgICAgICAgICAgICAgICAgfVxuLy8gICAgICAgICAgICAgICB9XG5cbi8vICAgICAgICAgICAgICAgLy8gaW5kZXhlczogbWVyZ2Ug7IucIOy2lOqwgCwgcmVwbGFjZSDsi5wg6rWQ7LK0XG4vLyAgICAgICAgICAgICAgIGlmICh1cGRhdGVzLmluZGV4ZXMgIT09IHVuZGVmaW5lZCkge1xuLy8gICAgICAgICAgICAgICAgIGVudGl0eS5pbmRleGVzID1cbi8vICAgICAgICAgICAgICAgICAgIG1vZGUgPT09IFwicmVwbGFjZVwiID8gdXBkYXRlcy5pbmRleGVzIDogWy4uLmVudGl0eS5pbmRleGVzLCAuLi51cGRhdGVzLmluZGV4ZXNdO1xuLy8gICAgICAgICAgICAgICB9XG5cbi8vICAgICAgICAgICAgICAgLy8gc3Vic2V0cywgZW51bUxhYmVsczogYXNzaWdu7Jy866GcIOuzke2VqSDrmJDripQg6rWQ7LK0XG4vLyAgICAgICAgICAgICAgIGlmICh1cGRhdGVzLnN1YnNldHMgIT09IHVuZGVmaW5lZCkge1xuLy8gICAgICAgICAgICAgICAgIGVudGl0eS5zdWJzZXRzID1cbi8vICAgICAgICAgICAgICAgICAgIG1vZGUgPT09IFwicmVwbGFjZVwiID8gdXBkYXRlcy5zdWJzZXRzIDogeyAuLi5lbnRpdHkuc3Vic2V0cywgLi4udXBkYXRlcy5zdWJzZXRzIH07XG4vLyAgICAgICAgICAgICAgIH1cblxuLy8gICAgICAgICAgICAgICBpZiAodXBkYXRlcy5lbnVtcyAhPT0gdW5kZWZpbmVkKSB7XG4vLyAgICAgICAgICAgICAgICAgZW50aXR5LmVudW1MYWJlbHMgPVxuLy8gICAgICAgICAgICAgICAgICAgbW9kZSA9PT0gXCJyZXBsYWNlXCIgPyB1cGRhdGVzLmVudW1zIDogeyAuLi5lbnRpdHkuZW51bUxhYmVscywgLi4udXBkYXRlcy5lbnVtcyB9O1xuLy8gICAgICAgICAgICAgICB9XG5cbi8vICAgICAgICAgICAgICAgLy8g7KCA7J6lIOyghCDqsoDspp1cbi8vICAgICAgICAgICAgICAgY29uc3QgdmFsaWRhdGlvbkVycm9ycyA9IHZhbGlkYXRlRW50aXR5SnNvbih7XG4vLyAgICAgICAgICAgICAgICAgLi4uZW50aXR5LFxuLy8gICAgICAgICAgICAgICAgIGVudGl0eUlkOiBlbnRpdHkuaWQsXG4vLyAgICAgICAgICAgICAgICAgZW51bXM6IGVudGl0eS5lbnVtTGFiZWxzLFxuLy8gICAgICAgICAgICAgICB9KTtcblxuLy8gICAgICAgICAgICAgICBpZiAodmFsaWRhdGlvbkVycm9ycy5sZW5ndGggPiAwKSB7XG4vLyAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbi8vICAgICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuLy8gICAgICAgICAgICAgICAgICAgZW50aXR5SWQsXG4vLyAgICAgICAgICAgICAgICAgICBlcnJvcjogYOqygOymnSDsmKTrpZg6ICR7dmFsaWRhdGlvbkVycm9ycy5tYXAoKGUpID0+IGBbJHtlLmZpZWxkfV0gJHtlLm1lc3NhZ2V9YCkuam9pbihcIiwgXCIpfWAsXG4vLyAgICAgICAgICAgICAgICAgICB2YWxpZGF0aW9uRXJyb3JzLFxuLy8gICAgICAgICAgICAgICAgIH07XG4vLyAgICAgICAgICAgICAgIH1cblxuLy8gICAgICAgICAgICAgICBhd2FpdCBlbnRpdHkuc2F2ZSgpO1xuXG4vLyAgICAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUsIGVudGl0eUlkIH07XG4vLyAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4vLyAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gZSBpbnN0YW5jZW9mIEVycm9yID8gZS5tZXNzYWdlIDogXCJVbmtub3duIGVycm9yXCI7XG4vLyAgICAgICAgICAgICAgIHJldHVybiB7IHN1Y2Nlc3M6IGZhbHNlLCBlbnRpdHlJZCwgZXJyb3IgfTtcbi8vICAgICAgICAgICAgIH1cbi8vICAgICAgICAgICB9LFxuLy8gICAgICAgICB9KSxcbi8vICAgICAgIH0sXG4vLyAgICAgfSk7XG4vLyAgIH1cbi8vIH1cblxuLy8gLyoqXG4vLyAgKiBFbnRpdHkgSlNPTuydtCBlbnRpdHkuaW5zdHJ1Y3Rpb25zLm1k7J2YIOq3nOy5meydhCDrlLDrpbTripTsp4Ag6rKA7Kad7ZWp64uI64ukLlxuLy8gICovXG4vLyBmdW5jdGlvbiB2YWxpZGF0ZUVudGl0eUpzb24oaW5wdXQ6IFRlbXBsYXRlT3B0aW9uc1tcImVudGl0eVwiXSk6IFZhbGlkYXRpb25FcnJvcltdIHtcbi8vICAgY29uc3QgZXJyb3JzOiBWYWxpZGF0aW9uRXJyb3JbXSA9IFtdO1xuLy8gICBjb25zdCB7IGVudGl0eUlkLCBwcm9wcywgZW51bXMgfSA9IGlucHV0O1xuXG4vLyAgIC8vIDEuIGlkLCBjcmVhdGVkX2F0IHByb3Ag7ZWE7IiYXG4vLyAgIGNvbnN0IGhhc0lkUHJvcCA9IHByb3BzPy5zb21lKChwKSA9PiBwLm5hbWUgPT09IFwiaWRcIik7XG4vLyAgIGlmICghaGFzSWRQcm9wKSB7XG4vLyAgICAgZXJyb3JzLnB1c2goeyBmaWVsZDogXCJwcm9wc1wiLCBtZXNzYWdlOiBcImlkIO2UhOuhnO2NvO2LsOqwgCDtlYTsiJjsnoXri4jri6QuXCIgfSk7XG4vLyAgIH1cbi8vICAgY29uc3QgaGFzQ3JlYXRlZEF0UHJvcCA9IHByb3BzPy5zb21lKChwKSA9PiBwLm5hbWUgPT09IFwiY3JlYXRlZF9hdFwiKTtcbi8vICAgaWYgKCFoYXNDcmVhdGVkQXRQcm9wKSB7XG4vLyAgICAgZXJyb3JzLnB1c2goeyBmaWVsZDogXCJwcm9wc1wiLCBtZXNzYWdlOiBcImNyZWF0ZWRfYXQg7ZSE66Gc7Y287Yuw6rCAIO2VhOyImOyeheuLiOuLpC5cIiB9KTtcbi8vICAgfVxuXG4vLyAgIC8vIDIuIO2VhOyImCBlbnVtIOqygOymnTogRW50aXR5TmFtZU9yZGVyQnksIEVudGl0eU5hbWVTZWFyY2hGaWVsZFxuLy8gICBjb25zdCBvcmRlckJ5RW51bUlkID0gYCR7ZW50aXR5SWR9T3JkZXJCeWA7XG4vLyAgIGNvbnN0IHNlYXJjaEZpZWxkRW51bUlkID0gYCR7ZW50aXR5SWR9U2VhcmNoRmllbGRgO1xuXG4vLyAgIGlmICghZW51bXM/LltvcmRlckJ5RW51bUlkXSkge1xuLy8gICAgIGVycm9ycy5wdXNoKHtcbi8vICAgICAgIGZpZWxkOiBcImVudW1zXCIsXG4vLyAgICAgICBtZXNzYWdlOiBgJHtvcmRlckJ5RW51bUlkfSBlbnVt7J20IO2VhOyImOyeheuLiOuLpC4gKOyYiDogeyBcImlkLWRlc2NcIjogXCJJROy1nOyLoOyInFwiIH0pYCxcbi8vICAgICB9KTtcbi8vICAgfVxuLy8gICBpZiAoIWVudW1zPy5bc2VhcmNoRmllbGRFbnVtSWRdKSB7XG4vLyAgICAgZXJyb3JzLnB1c2goe1xuLy8gICAgICAgZmllbGQ6IFwiZW51bXNcIixcbi8vICAgICAgIG1lc3NhZ2U6IGAke3NlYXJjaEZpZWxkRW51bUlkfSBlbnVt7J20IO2VhOyImOyeheuLiOuLpC4gKOyYiDogeyBcImlkXCI6IFwiSURcIiB9KWAsXG4vLyAgICAgfSk7XG4vLyAgIH1cblxuLy8gICAvLyAzLiBlbnVtIHByb3DsnZggaWTqsIAgZW51bXPsl5Ag7KCV7J2Y65CY7Ja0IOyeiOuKlOyngCDtmZXsnbggKGNyb3NzLWZpZWxkIOqygOymnSlcbi8vICAgZm9yIChjb25zdCBwcm9wIG9mIHByb3BzID8/IFtdKSB7XG4vLyAgICAgaWYgKHByb3AudHlwZSA9PT0gXCJlbnVtXCIgJiYgIWVudW1zPy5bcHJvcC5pZF0pIHtcbi8vICAgICAgIGVycm9ycy5wdXNoKHtcbi8vICAgICAgICAgZmllbGQ6IGBwcm9wcy4ke3Byb3AubmFtZX1gLFxuLy8gICAgICAgICBtZXNzYWdlOiBgZW51bSBpZCBcIiR7cHJvcC5pZH1cIuqwgCBlbnVtc+yXkCDsoJXsnZjrkJjslrQg7J6I7KeAIOyViuyKteuLiOuLpC5gLFxuLy8gICAgICAgfSk7XG4vLyAgICAgfVxuLy8gICB9XG5cbi8vICAgcmV0dXJuIGVycm9ycztcbi8vIH1cblxuLy8gZXhwb3J0IGNvbnN0IGFpQ2xpZW50ID0gbmV3IEFJQ2xpZW50KCk7XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsaURBQWlEO0FBQ2pELHlFQUF5RTtBQUN6RSwrQkFBK0I7QUFDL0IsdUJBQXVCO0FBQ3ZCLDJCQUEyQjtBQUMzQixXQUFXO0FBQ1gsbUJBQW1CO0FBQ25CLHFCQUFxQjtBQUNyQix3QkFBd0I7QUFDeEIsaUJBQWlCO0FBQ2pCLFlBQVk7QUFDWixxQkFBcUI7QUFDckIsbUJBQW1CO0FBQ25CLDJCQUEyQjtBQUUzQiwyQkFBMkI7QUFDM0IsbUJBQW1CO0FBQ25CLHFCQUFxQjtBQUNyQixLQUFLO0FBRUwsbUJBQW1CO0FBQ25CLG9EQUFvRDtBQUVwRCxtQkFBbUI7QUFDbkIsd0RBQXdEO0FBQ3hELE1BQU07QUFFTiwrRUFBK0U7QUFDL0UsZ0RBQWdEO0FBQ2hELGlGQUFpRjtBQUNqRixpRUFBaUU7QUFDakUsb0RBQW9EO0FBRXBELGlCQUFpQjtBQUNqQiwrQkFBK0I7QUFDL0IsK0JBQStCO0FBQy9CLCtCQUErQjtBQUMvQix1Q0FB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
|
package/dist/ui/api.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/ui/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AA4B/C,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,eAAe,iBAovB/D"}
|