dsh-codegraph-visualizer 0.1.1 → 0.3.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 (58) hide show
  1. package/README.md +391 -226
  2. package/assets/icon-180.png +0 -0
  3. package/assets/icon.svg +30 -0
  4. package/cordis.patch.yml +22 -17
  5. package/dist/CodeGraphAdapter-C8JvcS7m.js +10 -0
  6. package/dist/CodeGraphAdapter-eyrhs0K0.js +422 -0
  7. package/dist/CodeGraphAdapter-eyrhs0K0.js.map +1 -0
  8. package/dist/FileSystemAdapter-CgasSGbB.js +524 -0
  9. package/dist/FileSystemAdapter-CgasSGbB.js.map +1 -0
  10. package/dist/LensAdapter-C9Saf_i_.js +89 -0
  11. package/dist/LensAdapter-C9Saf_i_.js.map +1 -0
  12. package/dist/Logger-DUIJSeNu.js +80 -0
  13. package/dist/Logger-DUIJSeNu.js.map +1 -0
  14. package/dist/TreeSitterAdapter-C-EWy8br.js +631 -0
  15. package/dist/TreeSitterAdapter-C-EWy8br.js.map +1 -0
  16. package/dist/TreeSitterAdapter-C6FcO2_s.js +8 -0
  17. package/dist/client/index.css +8900 -1777
  18. package/dist/client/index.css.map +1 -0
  19. package/dist/client/index.d.ts +634 -0
  20. package/dist/client/index.d.ts.map +1 -0
  21. package/dist/client/index.esm.js +57219 -20978
  22. package/dist/client/index.js.map +1 -0
  23. package/dist/client/{index.js → worker/layoutWorker.js} +7657 -8787
  24. package/dist/client.js +90067 -0
  25. package/dist/codeGraphDb-BT9nZCEO.js +357 -0
  26. package/dist/codeGraphDb-BT9nZCEO.js.map +1 -0
  27. package/dist/codeGraphDb-Bg7bWud2.js +9 -0
  28. package/dist/codeGraphRows-BhZX34uB.js +6 -0
  29. package/dist/codeGraphRows-C7hqu35E.js +246 -0
  30. package/dist/codeGraphRows-C7hqu35E.js.map +1 -0
  31. package/dist/constants-CQq93l3e.js +399 -0
  32. package/dist/constants-CQq93l3e.js.map +1 -0
  33. package/dist/graphFingerprint-CeARo7jG.js +4 -0
  34. package/dist/graphFingerprint-PuxORZUF.js +277 -0
  35. package/dist/graphFingerprint-PuxORZUF.js.map +1 -0
  36. package/dist/graphMetrics-C0F30730.js +555 -0
  37. package/dist/graphMetrics-C0F30730.js.map +1 -0
  38. package/dist/index.d.ts +572 -9
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +14734 -2003
  41. package/dist/index.js.map +1 -1
  42. package/dist/inheritanceEnhancer-Bi3UoYJS.js +291 -0
  43. package/dist/inheritanceEnhancer-Bi3UoYJS.js.map +1 -0
  44. package/dist/layerUtils-DDm-EsaD.js +72 -0
  45. package/dist/layerUtils-DDm-EsaD.js.map +1 -0
  46. package/dist/nativeIndex-Cx7RLXUp.js +5 -0
  47. package/dist/nativeIndex-DlSpD611.js +347 -0
  48. package/dist/nativeIndex-DlSpD611.js.map +1 -0
  49. package/dist/treeSitterExtractors-B1ybKNrC.js +394 -0
  50. package/dist/treeSitterExtractors-B1ybKNrC.js.map +1 -0
  51. package/dist/types-BUDxI_00.js +23 -0
  52. package/dist/types-BUDxI_00.js.map +1 -0
  53. package/locale/en.json +6 -0
  54. package/locale/zh-CN.json +6 -0
  55. package/locale/zh.json +6 -0
  56. package/package.json +100 -20
  57. package/dist/client-cjs/index.cjs +0 -44283
  58. package/dist/client-cjs/index.css +0 -2404
@@ -0,0 +1,89 @@
1
+ import { EdgeId, NodeId } from "./types-BUDxI_00.js";
2
+ import "./constants-CQq93l3e.js";
3
+ import { scoped } from "./Logger-DUIJSeNu.js";
4
+ import { inferLayerFromPath } from "./layerUtils-DDm-EsaD.js";
5
+
6
+ //#region src/adapters/LensAdapter.ts
7
+ const log = scoped("lens-adapter");
8
+ var LensAdapter = class {
9
+ source = "lens";
10
+ async fetchData(repoId, invoke) {
11
+ try {
12
+ const raw = await invoke("lens_analyze", { repoId });
13
+ if (!raw) return {
14
+ nodes: [],
15
+ edges: [],
16
+ source: this.source,
17
+ timestamp: Date.now()
18
+ };
19
+ const symbols = Array.isArray(raw.symbols) ? raw.symbols : [];
20
+ const references = Array.isArray(raw.references) ? raw.references : [];
21
+ const fileNodeMap = new Map();
22
+ for (const s of symbols) if (s.category === "module" || s.category === "file") fileNodeMap.set(s.file, s.id);
23
+ const nodes = symbols.map((s) => {
24
+ const parentId = s.category !== "module" && s.category !== "file" ? fileNodeMap.get(s.file) : void 0;
25
+ return {
26
+ id: NodeId(s.id),
27
+ label: s.name,
28
+ type: this.mapCategory(s.category),
29
+ filePath: s.file,
30
+ lineNumber: s.line,
31
+ properties: { scope: s.scope },
32
+ ...parentId ? { parentId: NodeId(parentId) } : {},
33
+ layer: inferLayerFromPath(s.file)
34
+ };
35
+ });
36
+ const edges = references.map((r) => {
37
+ const edgeType = this.mapRelation(r.relation);
38
+ return {
39
+ id: EdgeId(`${r.from}->${r.to}:${edgeType}`),
40
+ source: NodeId(r.from),
41
+ target: NodeId(r.to),
42
+ type: edgeType,
43
+ properties: {}
44
+ };
45
+ });
46
+ return {
47
+ nodes,
48
+ edges,
49
+ source: this.source,
50
+ timestamp: Date.now()
51
+ };
52
+ } catch (e) {
53
+ const errorMsg = e instanceof Error ? e.message : String(e);
54
+ log.warn("Lens fetchData failed — lens is optional, returning empty", e);
55
+ return {
56
+ nodes: [],
57
+ edges: [],
58
+ source: this.source,
59
+ timestamp: Date.now(),
60
+ error: errorMsg
61
+ };
62
+ }
63
+ }
64
+ mapCategory(cat) {
65
+ const map = {
66
+ function: "function",
67
+ class: "class",
68
+ variable: "variable",
69
+ module: "module",
70
+ interface: "interface",
71
+ type: "type"
72
+ };
73
+ return map[cat] ?? "module";
74
+ }
75
+ mapRelation(rel) {
76
+ const map = {
77
+ call: "call",
78
+ reference: "dependency",
79
+ import: "import",
80
+ extend: "extend",
81
+ implement: "implement"
82
+ };
83
+ return map[rel] ?? "dependency";
84
+ }
85
+ };
86
+
87
+ //#endregion
88
+ export { LensAdapter };
89
+ //# sourceMappingURL=LensAdapter-C9Saf_i_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LensAdapter-C9Saf_i_.js","names":["repoId: string","invoke: UpstreamInvoker","nodes: GraphNode[]","edges: GraphEdge[]","cat: string","map: Record<string, GraphNode['type']>","rel: string","map: Record<string, GraphEdge['type']>"],"sources":["../src/adapters/LensAdapter.ts"],"sourcesContent":["// LensAdapter - adapter for the optional dsh-tool-lens data source.\r\nimport type { GraphNode, GraphEdge, AdapterResult, DataSourceType } from '../types/index.ts';\r\nimport { NodeId, EdgeId } from '../types/index.ts';\r\nimport type { IDataAdapter, UpstreamInvoker } from './IAdapter.ts';\r\nimport { scoped } from '../shared/Logger.ts';\r\nimport { inferLayerFromPath } from '../shared/layerUtils.ts';\r\n\r\nconst log = scoped('lens-adapter');\r\n\r\ninterface LensToolResult {\r\n symbols: Array<{\r\n id: string;\r\n name: string;\r\n scope: string;\r\n file: string;\r\n line: number;\r\n category: string;\r\n }>;\r\n references: Array<{\r\n from: string;\r\n to: string;\r\n relation: string;\r\n }>;\r\n}\r\n\r\n\r\nexport class LensAdapter implements IDataAdapter {\r\n readonly source: DataSourceType = 'lens';\r\n\r\n async fetchData(repoId: string, invoke: UpstreamInvoker): Promise<AdapterResult> {\r\n try {\r\n const raw = (await invoke('lens_analyze', { repoId })) as LensToolResult | null;\r\n if (!raw) return { nodes: [], edges: [], source: this.source, timestamp: Date.now() };\r\n\r\n const symbols = Array.isArray(raw.symbols) ? raw.symbols : [];\r\n const references = Array.isArray(raw.references) ? raw.references : [];\r\n\r\n const fileNodeMap = new Map<string, string>();\r\n for (const s of symbols) {\r\n if (s.category === 'module' || s.category === 'file') {\r\n fileNodeMap.set(s.file, s.id);\r\n }\r\n }\r\n\r\n const nodes: GraphNode[] = symbols.map((s) => {\r\n const parentId = (s.category !== 'module' && s.category !== 'file')\r\n ? fileNodeMap.get(s.file)\r\n : undefined;\r\n return {\r\n id: NodeId(s.id),\r\n label: s.name,\r\n type: this.mapCategory(s.category),\r\n filePath: s.file,\r\n lineNumber: s.line,\r\n properties: { scope: s.scope },\r\n ...(parentId ? { parentId: NodeId(parentId) } : {}),\r\n layer: inferLayerFromPath(s.file),\r\n };\r\n });\r\n\r\n const edges: GraphEdge[] = references.map((r) => {\r\n const edgeType = this.mapRelation(r.relation);\r\n return {\r\n id: EdgeId(`${r.from}->${r.to}:${edgeType}`),\r\n source: NodeId(r.from),\r\n target: NodeId(r.to),\r\n type: edgeType,\r\n properties: {},\r\n };\r\n });\r\n\r\n return { nodes, edges, source: this.source, timestamp: Date.now() };\r\n } catch (e) {\r\n const errorMsg = e instanceof Error ? e.message : String(e);\r\n log.warn('Lens fetchData failed — lens is optional, returning empty', e);\r\n return { nodes: [], edges: [], source: this.source, timestamp: Date.now(), error: errorMsg };\r\n }\r\n }\r\n\r\n private mapCategory(cat: string): GraphNode['type'] {\r\n const map: Record<string, GraphNode['type']> = {\r\n function: 'function',\r\n class: 'class',\r\n variable: 'variable',\r\n module: 'module',\r\n interface: 'interface',\r\n type: 'type',\r\n };\r\n return map[cat] ?? 'module';\r\n }\r\n\r\n private mapRelation(rel: string): GraphEdge['type'] {\r\n const map: Record<string, GraphEdge['type']> = {\r\n call: 'call',\r\n reference: 'dependency',\r\n import: 'import',\r\n extend: 'extend',\r\n implement: 'implement',\r\n };\r\n return map[rel] ?? 'dependency';\r\n }\r\n}"],"mappings":";;;;;;AAOA,MAAM,MAAM,OAAO,eAAe;AAmBlC,IAAa,cAAb,MAAiD;CAC/C,AAAS,SAAyB;CAElC,MAAM,UAAUA,QAAgBC,QAAiD;AAC/E,MAAI;GACF,MAAM,MAAO,MAAM,OAAO,gBAAgB,EAAE,OAAQ,EAAC;AACrD,QAAK,IAAK,QAAO;IAAE,OAAO,CAAE;IAAE,OAAO,CAAE;IAAE,QAAQ,KAAK;IAAQ,WAAW,KAAK,KAAK;GAAE;GAErF,MAAM,UAAU,MAAM,QAAQ,IAAI,QAAQ,GAAG,IAAI,UAAU,CAAE;GAC7D,MAAM,aAAa,MAAM,QAAQ,IAAI,WAAW,GAAG,IAAI,aAAa,CAAE;GAEtE,MAAM,cAAc,IAAI;AACxB,QAAK,MAAM,KAAK,QACd,KAAI,EAAE,aAAa,YAAY,EAAE,aAAa,OAC5C,aAAY,IAAI,EAAE,MAAM,EAAE,GAAG;GAIjC,MAAMC,QAAqB,QAAQ,IAAI,CAAC,MAAM;IAC5C,MAAM,WAAY,EAAE,aAAa,YAAY,EAAE,aAAa,SACxD,YAAY,IAAI,EAAE,KAAK;AAE3B,WAAO;KACL,IAAI,OAAO,EAAE,GAAG;KAChB,OAAO,EAAE;KACT,MAAM,KAAK,YAAY,EAAE,SAAS;KAClC,UAAU,EAAE;KACZ,YAAY,EAAE;KACd,YAAY,EAAE,OAAO,EAAE,MAAO;KAC9B,GAAI,WAAW,EAAE,UAAU,OAAO,SAAS,CAAE,IAAG,CAAE;KAClD,OAAO,mBAAmB,EAAE,KAAK;IAClC;GACF,EAAC;GAEF,MAAMC,QAAqB,WAAW,IAAI,CAAC,MAAM;IAC/C,MAAM,WAAW,KAAK,YAAY,EAAE,SAAS;AAC7C,WAAO;KACL,IAAI,QAAQ,EAAE,EAAE,KAAK,IAAI,EAAE,GAAG,GAAG,SAAS,EAAE;KAC5C,QAAQ,OAAO,EAAE,KAAK;KACtB,QAAQ,OAAO,EAAE,GAAG;KACpB,MAAM;KACN,YAAY,CAAE;IACf;GACF,EAAC;AAEF,UAAO;IAAE;IAAO;IAAO,QAAQ,KAAK;IAAQ,WAAW,KAAK,KAAK;GAAE;EACpE,SAAQ,GAAG;GACV,MAAM,WAAW,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;AAC3D,OAAI,KAAK,6DAA6D,EAAE;AACxE,UAAO;IAAE,OAAO,CAAE;IAAE,OAAO,CAAE;IAAE,QAAQ,KAAK;IAAQ,WAAW,KAAK,KAAK;IAAE,OAAO;GAAU;EAC7F;CACF;CAED,AAAQ,YAAYC,KAAgC;EAClD,MAAMC,MAAyC;GAC7C,UAAU;GACV,OAAO;GACP,UAAU;GACV,QAAQ;GACR,WAAW;GACX,MAAM;EACP;AACD,SAAO,IAAI,QAAQ;CACpB;CAED,AAAQ,YAAYC,KAAgC;EAClD,MAAMC,MAAyC;GAC7C,MAAM;GACN,WAAW;GACX,QAAQ;GACR,QAAQ;GACR,WAAW;EACZ;AACD,SAAO,IAAI,QAAQ;CACpB;AACF"}
@@ -0,0 +1,80 @@
1
+ import { LOGGER } from "./constants-CQq93l3e.js";
2
+
3
+ //#region src/shared/Logger.ts
4
+ const LEVEL_ORDER = {
5
+ debug: 0,
6
+ info: 1,
7
+ warn: 2,
8
+ error: 3
9
+ };
10
+ var LoggerImpl = class {
11
+ buffer = [];
12
+ listeners = new Set();
13
+ minLevel = typeof globalThis !== "undefined" && globalThis.__CG_DEBUG ? "debug" : "info";
14
+ log(level, scope, message, data) {
15
+ if (LEVEL_ORDER[level] < LEVEL_ORDER[this.minLevel]) return;
16
+ const entry = {
17
+ ts: Date.now(),
18
+ level,
19
+ scope,
20
+ message,
21
+ data
22
+ };
23
+ this.buffer.push(entry);
24
+ if (this.buffer.length > LOGGER.RING_SIZE) this.buffer.splice(0, this.buffer.length - LOGGER.RING_SIZE);
25
+ this.emit();
26
+ const fn = level === "error" ? console.error : level === "warn" ? console.warn : console.log;
27
+ try {
28
+ if (typeof fn === "function") fn(`[codegraph:${scope}] ${message}`, data ?? "");
29
+ } catch {}
30
+ }
31
+ debug(scope, message, data) {
32
+ this.log("debug", scope, message, data);
33
+ }
34
+ info(scope, message, data) {
35
+ this.log("info", scope, message, data);
36
+ }
37
+ warn(scope, message, data) {
38
+ this.log("warn", scope, message, data);
39
+ }
40
+ error(scope, message, data) {
41
+ this.log("error", scope, message, data);
42
+ }
43
+ entries() {
44
+ return this.buffer.slice();
45
+ }
46
+ clear() {
47
+ this.buffer = [];
48
+ this.emit();
49
+ }
50
+ subscribe(fn) {
51
+ this.listeners.add(fn);
52
+ fn(this.entries());
53
+ return () => {
54
+ this.listeners.delete(fn);
55
+ };
56
+ }
57
+ clearListeners() {
58
+ this.listeners.clear();
59
+ }
60
+ emit() {
61
+ if (this.listeners.size === 0) return;
62
+ const snapshot = this.entries();
63
+ for (const fn of this.listeners) try {
64
+ fn(snapshot);
65
+ } catch {}
66
+ }
67
+ };
68
+ const logger = new LoggerImpl();
69
+ function scoped(scope) {
70
+ return {
71
+ debug: (m, d) => logger.debug(scope, m, d),
72
+ info: (m, d) => logger.info(scope, m, d),
73
+ warn: (m, d) => logger.warn(scope, m, d),
74
+ error: (m, d) => logger.error(scope, m, d)
75
+ };
76
+ }
77
+
78
+ //#endregion
79
+ export { scoped };
80
+ //# sourceMappingURL=Logger-DUIJSeNu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger-DUIJSeNu.js","names":["LEVEL_ORDER: Record<LogLevel, number>","level: LogLevel","scope: string","message: string","data?: unknown","entry: LogEntry","fn: (entries: LogEntry[]) => void","m: string","d?: unknown"],"sources":["../src/shared/Logger.ts"],"sourcesContent":["// Lightweight structured logger with an in-memory ring buffer for UI surfacing.\r\n// Ponytail: no deps, ~60 lines. Levels respect host console when available.\r\n/* eslint-disable no-console */\r\n\r\nimport { LOGGER } from './constants.ts';\r\n\r\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\r\n\r\nexport interface LogEntry {\r\n ts: number;\r\n level: LogLevel;\r\n scope: string;\r\n message: string;\r\n data?: unknown;\r\n}\r\n\r\nconst LEVEL_ORDER: Record<LogLevel, number> = { debug: 0, info: 1, warn: 2, error: 3 };\r\n\r\n\r\nclass LoggerImpl {\r\n private buffer: LogEntry[] = [];\r\n private listeners = new Set<(entries: LogEntry[]) => void>();\r\n minLevel: LogLevel = (typeof globalThis !== 'undefined' &&\r\n (globalThis as unknown as { __CG_DEBUG?: boolean }).__CG_DEBUG) ? 'debug' : 'info';\r\n\r\n log(level: LogLevel, scope: string, message: string, data?: unknown): void {\r\n if (LEVEL_ORDER[level] < LEVEL_ORDER[this.minLevel]) return;\r\n const entry: LogEntry = { ts: Date.now(), level, scope, message, data };\r\n this.buffer.push(entry);\r\n if (this.buffer.length > LOGGER.RING_SIZE) this.buffer.splice(0, this.buffer.length - LOGGER.RING_SIZE);\r\n this.emit();\r\n const fn = level === 'error' ? console.error : level === 'warn' ? console.warn : console.log;\r\n try { if (typeof fn === 'function') fn(`[codegraph:${scope}] ${message}`, data ?? ''); } catch { /* console unavailable */ }\r\n }\r\n\r\n debug(scope: string, message: string, data?: unknown): void { this.log('debug', scope, message, data); }\r\n info(scope: string, message: string, data?: unknown): void { this.log('info', scope, message, data); }\r\n warn(scope: string, message: string, data?: unknown): void { this.log('warn', scope, message, data); }\r\n error(scope: string, message: string, data?: unknown): void { this.log('error', scope, message, data); }\r\n\r\n entries(): LogEntry[] { return this.buffer.slice(); }\r\n clear(): void { this.buffer = []; this.emit(); }\r\n\r\n subscribe(fn: (entries: LogEntry[]) => void): () => void {\r\n this.listeners.add(fn);\r\n fn(this.entries());\r\n return () => { this.listeners.delete(fn); };\r\n }\r\n\r\n clearListeners(): void {\r\n this.listeners.clear();\r\n }\r\n\r\n private emit(): void {\r\n if (this.listeners.size === 0) return;\r\n const snapshot = this.entries();\r\n for (const fn of this.listeners) { try { fn(snapshot); } catch { /* listener fault */ } }\r\n }\r\n}\r\n\r\nexport const logger = new LoggerImpl();\r\n\r\n// Convenience scoped logger factory.\r\nexport function scoped(scope: string) {\r\n return {\r\n debug: (m: string, d?: unknown) => logger.debug(scope, m, d),\r\n info: (m: string, d?: unknown) => logger.info(scope, m, d),\r\n warn: (m: string, d?: unknown) => logger.warn(scope, m, d),\r\n error: (m: string, d?: unknown) => logger.error(scope, m, d),\r\n };\r\n}\r\nexport function resetLoggerListeners(): void {\r\n logger.clearListeners();\r\n}"],"mappings":";;;AAgBA,MAAMA,cAAwC;CAAE,OAAO;CAAG,MAAM;CAAG,MAAM;CAAG,OAAO;AAAG;AAGtF,IAAM,aAAN,MAAiB;CACf,AAAQ,SAAqB,CAAE;CAC/B,AAAQ,YAAY,IAAI;CACxB,kBAA6B,eAAe,eACzC,WAAmD,aAAc,UAAU;CAE9E,IAAIC,OAAiBC,OAAeC,SAAiBC,MAAsB;AACzE,MAAI,YAAY,SAAS,YAAY,KAAK,UAAW;EACrD,MAAMC,QAAkB;GAAE,IAAI,KAAK,KAAK;GAAE;GAAO;GAAO;GAAS;EAAM;AACvE,OAAK,OAAO,KAAK,MAAM;AACvB,MAAI,KAAK,OAAO,SAAS,OAAO,UAAW,MAAK,OAAO,OAAO,GAAG,KAAK,OAAO,SAAS,OAAO,UAAU;AACvG,OAAK,MAAM;EACX,MAAM,KAAK,UAAU,UAAU,QAAQ,QAAQ,UAAU,SAAS,QAAQ,OAAO,QAAQ;AACzF,MAAI;AAAE,cAAW,OAAO,WAAY,KAAI,aAAa,MAAM,IAAI,QAAQ,GAAG,QAAQ,GAAG;EAAG,QAAO,CAA6B;CAC7H;CAED,MAAMH,OAAeC,SAAiBC,MAAsB;AAAE,OAAK,IAAI,SAAS,OAAO,SAAS,KAAK;CAAG;CACxG,KAAKF,OAAeC,SAAiBC,MAAsB;AAAE,OAAK,IAAI,QAAQ,OAAO,SAAS,KAAK;CAAG;CACtG,KAAKF,OAAeC,SAAiBC,MAAsB;AAAE,OAAK,IAAI,QAAQ,OAAO,SAAS,KAAK;CAAG;CACtG,MAAMF,OAAeC,SAAiBC,MAAsB;AAAE,OAAK,IAAI,SAAS,OAAO,SAAS,KAAK;CAAG;CAExG,UAAsB;AAAE,SAAO,KAAK,OAAO,OAAO;CAAG;CACrD,QAAc;AAAE,OAAK,SAAS,CAAE;AAAE,OAAK,MAAM;CAAG;CAEhD,UAAUE,IAA+C;AACvD,OAAK,UAAU,IAAI,GAAG;AACtB,KAAG,KAAK,SAAS,CAAC;AAClB,SAAO,MAAM;AAAE,QAAK,UAAU,OAAO,GAAG;EAAG;CAC5C;CAED,iBAAuB;AACrB,OAAK,UAAU,OAAO;CACvB;CAED,AAAQ,OAAa;AACnB,MAAI,KAAK,UAAU,SAAS,EAAG;EAC/B,MAAM,WAAW,KAAK,SAAS;AAC/B,OAAK,MAAM,MAAM,KAAK,UAAa,KAAI;AAAE,MAAG,SAAS;EAAG,QAAO,CAAwB;CACxF;AACF;AAED,MAAa,SAAS,IAAI;AAG1B,SAAgB,OAAOJ,OAAe;AACpC,QAAO;EACL,OAAO,CAACK,GAAWC,MAAgB,OAAO,MAAM,OAAO,GAAG,EAAE;EAC5D,MAAM,CAACD,GAAWC,MAAgB,OAAO,KAAK,OAAO,GAAG,EAAE;EAC1D,MAAM,CAACD,GAAWC,MAAgB,OAAO,KAAK,OAAO,GAAG,EAAE;EAC1D,OAAO,CAACD,GAAWC,MAAgB,OAAO,MAAM,OAAO,GAAG,EAAE;CAC7D;AACF"}