@flanksource/clicky-ui 0.3.18 → 0.3.19

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 (191) hide show
  1. package/dist/components/ComboboxMenu.cjs +5 -1
  2. package/dist/components/ComboboxMenu.cjs.map +1 -1
  3. package/dist/components/ComboboxMenu.d.ts.map +1 -1
  4. package/dist/components/ComboboxMenu.js +5 -1
  5. package/dist/components/ComboboxMenu.js.map +1 -1
  6. package/dist/components/EndpointSelector.model.cjs +96 -0
  7. package/dist/components/EndpointSelector.model.cjs.map +1 -0
  8. package/dist/components/EndpointSelector.model.d.ts +2 -0
  9. package/dist/components/EndpointSelector.model.d.ts.map +1 -1
  10. package/dist/components/EndpointSelector.model.js +96 -0
  11. package/dist/components/EndpointSelector.model.js.map +1 -0
  12. package/dist/components/FilterBar.cjs +52 -2
  13. package/dist/components/FilterBar.cjs.map +1 -1
  14. package/dist/components/FilterBar.d.ts +20 -2
  15. package/dist/components/FilterBar.d.ts.map +1 -1
  16. package/dist/components/FilterBar.js +52 -2
  17. package/dist/components/FilterBar.js.map +1 -1
  18. package/dist/components/JSONPathField.cjs +87 -66
  19. package/dist/components/JSONPathField.cjs.map +1 -1
  20. package/dist/components/JSONPathField.d.ts +26 -9
  21. package/dist/components/JSONPathField.d.ts.map +1 -1
  22. package/dist/components/JSONPathField.js +88 -67
  23. package/dist/components/JSONPathField.js.map +1 -1
  24. package/dist/components/JSONPathPlayground.cjs +225 -0
  25. package/dist/components/JSONPathPlayground.cjs.map +1 -0
  26. package/dist/components/JSONPathPlayground.d.ts +59 -0
  27. package/dist/components/JSONPathPlayground.d.ts.map +1 -0
  28. package/dist/components/JSONPathPlayground.js +225 -0
  29. package/dist/components/JSONPathPlayground.js.map +1 -0
  30. package/dist/components/OnePasswordSelector.cjs +178 -0
  31. package/dist/components/OnePasswordSelector.cjs.map +1 -0
  32. package/dist/components/OnePasswordSelector.d.ts +8 -0
  33. package/dist/components/OnePasswordSelector.d.ts.map +1 -0
  34. package/dist/components/OnePasswordSelector.js +178 -0
  35. package/dist/components/OnePasswordSelector.js.map +1 -0
  36. package/dist/components/OnePasswordSelector.model.cjs +31 -0
  37. package/dist/components/OnePasswordSelector.model.cjs.map +1 -0
  38. package/dist/components/OnePasswordSelector.model.d.ts +27 -0
  39. package/dist/components/OnePasswordSelector.model.d.ts.map +1 -0
  40. package/dist/components/OnePasswordSelector.model.js +31 -0
  41. package/dist/components/OnePasswordSelector.model.js.map +1 -0
  42. package/dist/components/SecretFormField.cjs +142 -0
  43. package/dist/components/SecretFormField.cjs.map +1 -0
  44. package/dist/components/SecretFormField.d.ts +9 -0
  45. package/dist/components/SecretFormField.d.ts.map +1 -0
  46. package/dist/components/SecretFormField.js +142 -0
  47. package/dist/components/SecretFormField.js.map +1 -0
  48. package/dist/components/SecretKeySelector.cjs +20 -14
  49. package/dist/components/SecretKeySelector.cjs.map +1 -1
  50. package/dist/components/SecretKeySelector.d.ts +4 -1
  51. package/dist/components/SecretKeySelector.d.ts.map +1 -1
  52. package/dist/components/SecretKeySelector.js +20 -14
  53. package/dist/components/SecretKeySelector.js.map +1 -1
  54. package/dist/components/TreePickerField.cjs +55 -29
  55. package/dist/components/TreePickerField.cjs.map +1 -1
  56. package/dist/components/TreePickerField.d.ts +10 -1
  57. package/dist/components/TreePickerField.d.ts.map +1 -1
  58. package/dist/components/TreePickerField.js +56 -30
  59. package/dist/components/TreePickerField.js.map +1 -1
  60. package/dist/components/combobox-types.d.ts +9 -0
  61. package/dist/components/combobox-types.d.ts.map +1 -1
  62. package/dist/components/filter-bar-utils.cjs +7 -0
  63. package/dist/components/filter-bar-utils.cjs.map +1 -1
  64. package/dist/components/filter-bar-utils.d.ts.map +1 -1
  65. package/dist/components/filter-bar-utils.js +7 -0
  66. package/dist/components/filter-bar-utils.js.map +1 -1
  67. package/dist/components/jotai-bindings-core.cjs.map +1 -1
  68. package/dist/components/jotai-bindings-core.d.ts +4 -1
  69. package/dist/components/jotai-bindings-core.d.ts.map +1 -1
  70. package/dist/components/jotai-bindings-core.js.map +1 -1
  71. package/dist/components/json-schema-form-render.cjs +2 -1
  72. package/dist/components/json-schema-form-render.cjs.map +1 -1
  73. package/dist/components/json-schema-form-render.d.ts.map +1 -1
  74. package/dist/components/json-schema-form-render.js +2 -1
  75. package/dist/components/json-schema-form-render.js.map +1 -1
  76. package/dist/components/json-schema-form-types.d.ts +9 -0
  77. package/dist/components/json-schema-form-types.d.ts.map +1 -1
  78. package/dist/components/jsonPathTree.cjs +189 -0
  79. package/dist/components/jsonPathTree.cjs.map +1 -0
  80. package/dist/components/jsonPathTree.d.ts +92 -0
  81. package/dist/components/jsonPathTree.d.ts.map +1 -0
  82. package/dist/components/jsonPathTree.js +189 -0
  83. package/dist/components/jsonPathTree.js.map +1 -0
  84. package/dist/components/secret-form-extension.cjs +30 -0
  85. package/dist/components/secret-form-extension.cjs.map +1 -0
  86. package/dist/components/secret-form-extension.d.ts +23 -0
  87. package/dist/components/secret-form-extension.d.ts.map +1 -0
  88. package/dist/components/secret-form-extension.js +30 -0
  89. package/dist/components/secret-form-extension.js.map +1 -0
  90. package/dist/components.cjs +16 -0
  91. package/dist/components.cjs.map +1 -1
  92. package/dist/components.d.ts +6 -0
  93. package/dist/components.d.ts.map +1 -1
  94. package/dist/components.js +16 -0
  95. package/dist/components.js.map +1 -1
  96. package/dist/data/TaskExecDetails.cjs +40 -0
  97. package/dist/data/TaskExecDetails.cjs.map +1 -0
  98. package/dist/data/TaskExecDetails.d.ts +5 -0
  99. package/dist/data/TaskExecDetails.d.ts.map +1 -0
  100. package/dist/data/TaskExecDetails.js +40 -0
  101. package/dist/data/TaskExecDetails.js.map +1 -0
  102. package/dist/data/TaskProgress.cjs +9 -3
  103. package/dist/data/TaskProgress.cjs.map +1 -1
  104. package/dist/data/TaskProgress.d.ts.map +1 -1
  105. package/dist/data/TaskProgress.js +9 -3
  106. package/dist/data/TaskProgress.js.map +1 -1
  107. package/dist/data/TaskSnapshot.cjs.map +1 -1
  108. package/dist/data/TaskSnapshot.d.ts +12 -1
  109. package/dist/data/TaskSnapshot.d.ts.map +1 -1
  110. package/dist/data/TaskSnapshot.js.map +1 -1
  111. package/dist/data/TreeNode.cjs +3 -0
  112. package/dist/data/TreeNode.cjs.map +1 -1
  113. package/dist/data/TreeNode.d.ts.map +1 -1
  114. package/dist/data/TreeNode.js +3 -0
  115. package/dist/data/TreeNode.js.map +1 -1
  116. package/dist/data/data-table-filter-values.cjs +20 -0
  117. package/dist/data/data-table-filter-values.cjs.map +1 -1
  118. package/dist/data/data-table-filter-values.d.ts +16 -0
  119. package/dist/data/data-table-filter-values.d.ts.map +1 -1
  120. package/dist/data/data-table-filter-values.js +20 -0
  121. package/dist/data/data-table-filter-values.js.map +1 -1
  122. package/dist/data/data-table-server-filters.cjs +23 -29
  123. package/dist/data/data-table-server-filters.cjs.map +1 -1
  124. package/dist/data/data-table-server-filters.d.ts.map +1 -1
  125. package/dist/data/data-table-server-filters.js +21 -27
  126. package/dist/data/data-table-server-filters.js.map +1 -1
  127. package/dist/data/query-browser/QueryBrowser.cjs +129 -157
  128. package/dist/data/query-browser/QueryBrowser.cjs.map +1 -1
  129. package/dist/data/query-browser/QueryBrowser.d.ts +1 -71
  130. package/dist/data/query-browser/QueryBrowser.d.ts.map +1 -1
  131. package/dist/data/query-browser/QueryBrowser.editor.cjs +88 -0
  132. package/dist/data/query-browser/QueryBrowser.editor.cjs.map +1 -0
  133. package/dist/data/query-browser/QueryBrowser.editor.d.ts +12 -0
  134. package/dist/data/query-browser/QueryBrowser.editor.d.ts.map +1 -0
  135. package/dist/data/query-browser/QueryBrowser.editor.js +88 -0
  136. package/dist/data/query-browser/QueryBrowser.editor.js.map +1 -0
  137. package/dist/data/query-browser/QueryBrowser.js +130 -158
  138. package/dist/data/query-browser/QueryBrowser.js.map +1 -1
  139. package/dist/data/query-browser/QueryBrowser.types.cjs +11 -0
  140. package/dist/data/query-browser/QueryBrowser.types.cjs.map +1 -0
  141. package/dist/data/query-browser/QueryBrowser.types.d.ts +92 -0
  142. package/dist/data/query-browser/QueryBrowser.types.d.ts.map +1 -0
  143. package/dist/data/query-browser/QueryBrowser.types.js +11 -0
  144. package/dist/data/query-browser/QueryBrowser.types.js.map +1 -0
  145. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.cjs +56 -0
  146. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.cjs.map +1 -0
  147. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.d.ts +5 -0
  148. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.d.ts.map +1 -0
  149. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.js +56 -0
  150. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.js.map +1 -0
  151. package/dist/data/query-browser/QueryBrowserResults.cjs +80 -0
  152. package/dist/data/query-browser/QueryBrowserResults.cjs.map +1 -0
  153. package/dist/data/query-browser/QueryBrowserResults.d.ts +16 -0
  154. package/dist/data/query-browser/QueryBrowserResults.d.ts.map +1 -0
  155. package/dist/data/query-browser/QueryBrowserResults.js +80 -0
  156. package/dist/data/query-browser/QueryBrowserResults.js.map +1 -0
  157. package/dist/data/query-browser/index.d.ts +2 -1
  158. package/dist/data/query-browser/index.d.ts.map +1 -1
  159. package/dist/data/task-exec-details.cjs +9 -0
  160. package/dist/data/task-exec-details.cjs.map +1 -0
  161. package/dist/data/task-exec-details.d.ts +3 -0
  162. package/dist/data/task-exec-details.d.ts.map +1 -0
  163. package/dist/data/task-exec-details.js +9 -0
  164. package/dist/data/task-exec-details.js.map +1 -0
  165. package/dist/data/version-info.cjs +3 -3
  166. package/dist/data/version-info.js +3 -3
  167. package/dist/data.cjs +2 -0
  168. package/dist/data.cjs.map +1 -1
  169. package/dist/data.d.ts +1 -1
  170. package/dist/data.d.ts.map +1 -1
  171. package/dist/data.js +2 -0
  172. package/dist/data.js.map +1 -1
  173. package/dist/index.cjs +18 -0
  174. package/dist/index.cjs.map +1 -1
  175. package/dist/index.js +18 -0
  176. package/dist/index.js.map +1 -1
  177. package/dist/rpc/FilterForm.cjs +20 -0
  178. package/dist/rpc/FilterForm.cjs.map +1 -1
  179. package/dist/rpc/FilterForm.js +20 -0
  180. package/dist/rpc/FilterForm.js.map +1 -1
  181. package/dist/rpc/formMetadata.cjs +34 -0
  182. package/dist/rpc/formMetadata.cjs.map +1 -1
  183. package/dist/rpc/formMetadata.d.ts.map +1 -1
  184. package/dist/rpc/formMetadata.js +35 -1
  185. package/dist/rpc/formMetadata.js.map +1 -1
  186. package/dist/rpc/types.cjs.map +1 -1
  187. package/dist/rpc/types.d.ts +9 -1
  188. package/dist/rpc/types.d.ts.map +1 -1
  189. package/dist/rpc/types.js.map +1 -1
  190. package/dist/styles.css +1 -1
  191. package/package.json +1 -1
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const SIMPLE_PROPERTY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
4
+ const DEFAULT_MAX_DEPTH = 12;
5
+ const DEFAULT_MAX_OBJECT_PROPERTIES = 100;
6
+ const DEFAULT_MAX_CHILDREN = 1e3;
7
+ function jsonPathKind(value) {
8
+ if (Array.isArray(value)) return "array";
9
+ return value !== null && typeof value === "object" ? "object" : "scalar";
10
+ }
11
+ function appendJSONPath(path, key) {
12
+ if (typeof key === "number") return `${path}[${key}]`;
13
+ return SIMPLE_PROPERTY.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
14
+ }
15
+ function summarizeJSON(value) {
16
+ if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? "" : "s"}]`;
17
+ if (value !== null && typeof value === "object") {
18
+ const count = Object.keys(value).length;
19
+ return `{${count} ${count === 1 ? "property" : "properties"}}`;
20
+ }
21
+ if (typeof value === "string") return JSON.stringify(value.length > 80 ? `${value.slice(0, 77)}…` : value);
22
+ return String(value);
23
+ }
24
+ function entryCount(value) {
25
+ if (Array.isArray(value)) return value.length;
26
+ if (value !== null && typeof value === "object") return Object.keys(value).length;
27
+ return 0;
28
+ }
29
+ function buildJSONPathNode(value, path, depth, options = {}) {
30
+ const {
31
+ maxDepth = DEFAULT_MAX_DEPTH,
32
+ maxObjectProperties = DEFAULT_MAX_OBJECT_PROPERTIES,
33
+ arrayMode = "first"
34
+ } = options;
35
+ const kind = jsonPathKind(value);
36
+ const node = {
37
+ key: path,
38
+ path,
39
+ value,
40
+ kind,
41
+ summary: summarizeJSON(value),
42
+ childCount: entryCount(value)
43
+ };
44
+ if (kind === "scalar" || depth >= maxDepth) return node;
45
+ const entries = Array.isArray(value) ? arrayMode === "all" ? value.map((entry, index) => [index, entry]) : value.length > 0 ? [[0, value[0]]] : [] : Object.entries(value).slice(0, maxObjectProperties);
46
+ node.children = entries.map(
47
+ ([key, child]) => buildJSONPathNode(child, appendJSONPath(path, key), depth + 1, options)
48
+ );
49
+ return node;
50
+ }
51
+ function createLazyJSONPathTree(json, options = {}) {
52
+ const { maxChildren = DEFAULT_MAX_CHILDREN, parseEmbeddedJSON = true, keyPrefix = "" } = options;
53
+ const nodes = /* @__PURE__ */ new Map();
54
+ const decoded = /* @__PURE__ */ new Map();
55
+ function embedded(node2) {
56
+ if (!parseEmbeddedJSON || typeof node2.value !== "string") return void 0;
57
+ if (decoded.has(node2.key)) return decoded.get(node2.key);
58
+ const text = node2.value.trim();
59
+ let parsed = void 0;
60
+ if (text.startsWith("{") || text.startsWith("[")) {
61
+ try {
62
+ const candidate = JSON.parse(text);
63
+ if (jsonPathKind(candidate) !== "scalar") parsed = candidate;
64
+ } catch {
65
+ parsed = void 0;
66
+ }
67
+ }
68
+ decoded.set(node2.key, parsed);
69
+ return parsed;
70
+ }
71
+ function contents(node2) {
72
+ const inner = embedded(node2);
73
+ const scope = inner === void 0 ? { value: node2.value, path: node2.path } : { value: inner, path: "$" };
74
+ const root = inner === void 0 ? node2.root : node2.root ?? sourceColumn(node2.path);
75
+ if (root !== void 0) scope.root = root;
76
+ return scope;
77
+ }
78
+ function node(value, path, key, root) {
79
+ const cached = nodes.get(key);
80
+ if (cached) return cached;
81
+ const created = {
82
+ key,
83
+ path,
84
+ value,
85
+ kind: jsonPathKind(value),
86
+ summary: summarizeJSON(value),
87
+ childCount: entryCount(value)
88
+ };
89
+ if (root !== void 0) created.root = root;
90
+ nodes.set(key, created);
91
+ return created;
92
+ }
93
+ function entriesOf(value) {
94
+ if (Array.isArray(value)) return value.map((entry, index) => [index, entry]);
95
+ if (value !== null && typeof value === "object") return Object.entries(value);
96
+ return [];
97
+ }
98
+ function materializeChildren(parent) {
99
+ if (parent.children) return parent.children;
100
+ const scope = contents(parent);
101
+ const entries = entriesOf(scope.value);
102
+ const limit = Math.min(entries.length, maxChildren);
103
+ const children = entries.slice(0, limit).map(([key, value]) => {
104
+ const path = appendJSONPath(scope.path, key);
105
+ return node(value, path, `${parent.key}>${path}`, scope.root);
106
+ });
107
+ if (limit < entries.length) {
108
+ children.push({
109
+ key: `${parent.key}>…`,
110
+ path: scope.path,
111
+ value: void 0,
112
+ kind: "more",
113
+ summary: `${entries.length - limit} more not shown — address them by index`,
114
+ childCount: entries.length - limit
115
+ });
116
+ }
117
+ parent.children = children;
118
+ return children;
119
+ }
120
+ function expandable(node2) {
121
+ if (node2.kind === "more") return false;
122
+ if (node2.kind !== "scalar") return node2.childCount > 0;
123
+ const inner = embedded(node2);
124
+ return inner !== void 0 && entryCount(inner) > 0;
125
+ }
126
+ const rootNode = node(json, "$", `${keyPrefix}$`, void 0);
127
+ return {
128
+ roots: json === void 0 ? [] : [rootNode],
129
+ getChildren: (node2) => node2.children,
130
+ hasMoreChildren: (node2) => node2.children === void 0 && expandable(node2),
131
+ loadChildren: (parent) => Promise.resolve(materializeChildren(parent)),
132
+ materializePath: (expression) => {
133
+ const segments = literalSegments(expression);
134
+ if (!segments) return void 0;
135
+ let current = rootNode;
136
+ for (const segment of segments) {
137
+ const target = appendJSONPath(contents(current).path, segment);
138
+ const next = materializeChildren(current).find((child) => child.path === target);
139
+ if (!next) return void 0;
140
+ current = next;
141
+ }
142
+ return current;
143
+ }
144
+ };
145
+ }
146
+ function sourceColumn(path) {
147
+ var _a;
148
+ return (_a = literalSegments(path)) == null ? void 0 : _a.slice(0, 1).map(String)[0];
149
+ }
150
+ function literalSegments(expression) {
151
+ let rest = expression.trim();
152
+ if (rest === "") return void 0;
153
+ if (!rest.startsWith("$")) return void 0;
154
+ rest = rest.slice(1);
155
+ const segments = [];
156
+ while (rest.length > 0) {
157
+ if (rest.startsWith("..")) return void 0;
158
+ if (rest.startsWith(".")) {
159
+ const match = /^\.([A-Za-z_$][A-Za-z0-9_$]*)/.exec(rest);
160
+ if (!match) return void 0;
161
+ segments.push(match[1]);
162
+ rest = rest.slice(match[0].length);
163
+ continue;
164
+ }
165
+ if (rest.startsWith("[")) {
166
+ const close = rest.indexOf("]");
167
+ if (close < 0) return void 0;
168
+ const inner = rest.slice(1, close).trim();
169
+ if (/^\d+$/.test(inner)) segments.push(Number(inner));
170
+ else if (/^"(?:[^"\\]|\\.)*"$/.test(inner)) segments.push(JSON.parse(inner));
171
+ else if (/^'[^']*'$/.test(inner)) segments.push(inner.slice(1, -1));
172
+ else return void 0;
173
+ rest = rest.slice(close + 1);
174
+ continue;
175
+ }
176
+ return void 0;
177
+ }
178
+ return segments;
179
+ }
180
+ exports.DEFAULT_MAX_CHILDREN = DEFAULT_MAX_CHILDREN;
181
+ exports.DEFAULT_MAX_DEPTH = DEFAULT_MAX_DEPTH;
182
+ exports.DEFAULT_MAX_OBJECT_PROPERTIES = DEFAULT_MAX_OBJECT_PROPERTIES;
183
+ exports.appendJSONPath = appendJSONPath;
184
+ exports.buildJSONPathNode = buildJSONPathNode;
185
+ exports.createLazyJSONPathTree = createLazyJSONPathTree;
186
+ exports.jsonPathKind = jsonPathKind;
187
+ exports.literalSegments = literalSegments;
188
+ exports.summarizeJSON = summarizeJSON;
189
+ //# sourceMappingURL=jsonPathTree.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonPathTree.cjs","sources":["../../src/components/jsonPathTree.ts"],"sourcesContent":["// The JSON→JSONPath tree model shared by the inline picker dropdown and the\n// full playground dialog.\n//\n// The two want opposite things from the same walk. The dropdown is a *preview*\n// of a row that has to render the instant it opens, so it builds eagerly and\n// pays for that with caps: depth, property count, and one array element. The\n// playground is a *browser* of the row, so it must have no caps at all — which\n// is only affordable if the walk is lazy, materialising a level at a time as the\n// operator opens it.\n\nconst SIMPLE_PROPERTY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nexport const DEFAULT_MAX_DEPTH = 12;\nexport const DEFAULT_MAX_OBJECT_PROPERTIES = 100;\n/**\n * Entries the uncapped tree renders under one node before it stops and says so.\n *\n * Depth is what the playground removes the limit on; breadth still has to render\n * as DOM rows the moment a node opens, and a hundred-thousand-element array\n * would take the tab down. The remainder is reported in a visible row rather\n * than dropped quietly — an index past it is still reachable by typing it.\n */\nexport const DEFAULT_MAX_CHILDREN = 1000;\n\nexport type JSONPathNodeKind = \"array\" | \"object\" | \"scalar\" | \"more\";\n\nexport interface JSONPathNode {\n key: string;\n path: string;\n value: unknown;\n kind: JSONPathNodeKind;\n summary: string;\n children?: JSONPathNode[];\n /**\n * The top-level column this node's path is rooted at, set only inside a\n * subtree decoded out of a JSON-encoded string. Such a path cannot be read\n * from the row directly — the backend reaches it by way of the column's\n * `source`, so the two have to be committed together.\n */\n root?: string;\n /** Number of entries the node holds, before any paging. */\n childCount: number;\n}\n\nexport interface BuildJSONPathNodeOptions {\n maxDepth?: number;\n maxObjectProperties?: number;\n /** \"first\" exposes only element [0] of an array; \"all\" exposes every element. */\n arrayMode?: \"first\" | \"all\";\n}\n\nexport function jsonPathKind(value: unknown): JSONPathNodeKind {\n if (Array.isArray(value)) return \"array\";\n return value !== null && typeof value === \"object\" ? \"object\" : \"scalar\";\n}\n\nexport function appendJSONPath(path: string, key: string | number): string {\n if (typeof key === \"number\") return `${path}[${key}]`;\n return SIMPLE_PROPERTY.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;\n}\n\nexport function summarizeJSON(value: unknown): string {\n if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? \"\" : \"s\"}]`;\n if (value !== null && typeof value === \"object\") {\n const count = Object.keys(value).length;\n return `{${count} ${count === 1 ? \"property\" : \"properties\"}}`;\n }\n if (typeof value === \"string\") return JSON.stringify(value.length > 80 ? `${value.slice(0, 77)}…` : value);\n return String(value);\n}\n\nfunction entryCount(value: unknown): number {\n if (Array.isArray(value)) return value.length;\n if (value !== null && typeof value === \"object\") return Object.keys(value).length;\n return 0;\n}\n\n/**\n * The eager, capped walk behind the inline dropdown. Deep, wide, or long values\n * are truncated on purpose: the dropdown opens on a click and cannot afford to\n * walk an arbitrary document first.\n */\nexport function buildJSONPathNode(\n value: unknown,\n path: string,\n depth: number,\n options: BuildJSONPathNodeOptions = {},\n): JSONPathNode {\n const {\n maxDepth = DEFAULT_MAX_DEPTH,\n maxObjectProperties = DEFAULT_MAX_OBJECT_PROPERTIES,\n arrayMode = \"first\",\n } = options;\n const kind = jsonPathKind(value);\n const node: JSONPathNode = {\n key: path,\n path,\n value,\n kind,\n summary: summarizeJSON(value),\n childCount: entryCount(value),\n };\n if (kind === \"scalar\" || depth >= maxDepth) return node;\n const entries = Array.isArray(value)\n ? arrayMode === \"all\"\n ? value.map((entry, index) => [index, entry] as const)\n : value.length > 0\n ? [[0, value[0]] as const]\n : []\n : Object.entries(value as Record<string, unknown>).slice(0, maxObjectProperties);\n node.children = entries.map(([key, child]) =>\n buildJSONPathNode(child, appendJSONPath(path, key), depth + 1, options),\n );\n return node;\n}\n\nexport interface LazyJSONPathTreeOptions {\n maxChildren?: number;\n /**\n * Namespaces every node key. Two trees over different documents share their\n * paths, and Tree keys its React elements by node key — without a distinct\n * prefix, swapping the document underneath reuses the old subtree along with\n * the children it had already loaded.\n */\n keyPrefix?: string;\n /**\n * Descend into a string that parses as JSON. Providers routinely hand back a\n * document as an encoded column, and the backend already decodes one when a\n * column names it as its `source` — without this the picker shows the single\n * most interesting column in such a row as an opaque blob.\n */\n parseEmbeddedJSON?: boolean;\n}\n\nexport interface LazyJSONPathTree {\n roots: JSONPathNode[];\n /** Children already materialised, or undefined while the branch is unopened. */\n getChildren: (node: JSONPathNode) => JSONPathNode[] | undefined;\n hasMoreChildren: (node: JSONPathNode) => boolean;\n loadChildren: (node: JSONPathNode) => Promise<JSONPathNode[]>;\n /**\n * Materialise the branch a literal expression addresses and return its node,\n * so a tree can reveal the value it opened with. Returns undefined for an\n * expression that selects rather than addresses (a wildcard, a descent, a\n * filter) or for one the document does not carry.\n */\n materializePath: (expression: string) => JSONPathNode | undefined;\n}\n\n/**\n * An uncapped tree over `json`: every property, every array element, any depth.\n *\n * Nothing is walked until it is opened, so an arbitrarily deep or wide document\n * costs only what the operator actually looks at. Nodes are cached by path so\n * re-opening a branch returns the *same objects* — `TreeNode` compares the\n * selected node by identity, and a rebuilt node would silently lose the\n * highlight.\n */\nexport function createLazyJSONPathTree(\n json: unknown,\n options: LazyJSONPathTreeOptions = {},\n): LazyJSONPathTree {\n const { maxChildren = DEFAULT_MAX_CHILDREN, parseEmbeddedJSON = true, keyPrefix = \"\" } = options;\n const nodes = new Map<string, JSONPathNode>();\n\n // hasMoreChildren runs on every render of every visible row, so the decode is\n // memoised per node rather than re-parsing a long string each time.\n const decoded = new Map<string, unknown>();\n\n function embedded(node: JSONPathNode): unknown {\n if (!parseEmbeddedJSON || typeof node.value !== \"string\") return undefined;\n if (decoded.has(node.key)) return decoded.get(node.key);\n const text = node.value.trim();\n let parsed: unknown = undefined;\n if (text.startsWith(\"{\") || text.startsWith(\"[\")) {\n try {\n const candidate: unknown = JSON.parse(text);\n if (jsonPathKind(candidate) !== \"scalar\") parsed = candidate;\n } catch {\n parsed = undefined;\n }\n }\n decoded.set(node.key, parsed);\n return parsed;\n }\n\n // What a node's children are drawn from: its own value, or the document\n // decoded out of it when it holds JSON as text. An embedded document restarts\n // at `$` because that is where the backend evaluates it from once the column\n // is named as a `source`.\n function contents(node: JSONPathNode): { value: unknown; path: string; root?: string } {\n const inner = embedded(node);\n const scope: { value: unknown; path: string; root?: string } =\n inner === undefined\n ? { value: node.value, path: node.path }\n : { value: inner, path: \"$\" };\n const root = inner === undefined ? node.root : node.root ?? sourceColumn(node.path);\n if (root !== undefined) scope.root = root;\n return scope;\n }\n\n function node(\n value: unknown,\n path: string,\n key: string,\n root: string | undefined,\n ): JSONPathNode {\n const cached = nodes.get(key);\n if (cached) return cached;\n const created: JSONPathNode = {\n key,\n path,\n value,\n kind: jsonPathKind(value),\n summary: summarizeJSON(value),\n childCount: entryCount(value),\n };\n if (root !== undefined) created.root = root;\n nodes.set(key, created);\n return created;\n }\n\n function entriesOf(value: unknown): Array<readonly [string | number, unknown]> {\n if (Array.isArray(value)) return value.map((entry, index) => [index, entry] as const);\n if (value !== null && typeof value === \"object\") return Object.entries(value as Record<string, unknown>);\n return [];\n }\n\n function materializeChildren(parent: JSONPathNode): JSONPathNode[] {\n if (parent.children) return parent.children;\n const scope = contents(parent);\n const entries = entriesOf(scope.value);\n const limit = Math.min(entries.length, maxChildren);\n const children = entries.slice(0, limit).map(([key, value]) => {\n const path = appendJSONPath(scope.path, key);\n // The key namespaces on the parent so an embedded document — which\n // restarts its paths at `$` — cannot collide with the outer row.\n return node(value, path, `${parent.key}>${path}`, scope.root);\n });\n if (limit < entries.length) {\n children.push({\n key: `${parent.key}>…`,\n path: scope.path,\n value: undefined,\n kind: \"more\",\n summary: `${entries.length - limit} more not shown — address them by index`,\n childCount: entries.length - limit,\n });\n }\n parent.children = children;\n return children;\n }\n\n function expandable(node: JSONPathNode): boolean {\n if (node.kind === \"more\") return false;\n if (node.kind !== \"scalar\") return node.childCount > 0;\n const inner = embedded(node);\n return inner !== undefined && entryCount(inner) > 0;\n }\n\n const rootNode = node(json, \"$\", `${keyPrefix}$`, undefined);\n\n return {\n roots: json === undefined ? [] : [rootNode],\n getChildren: (node) => node.children,\n hasMoreChildren: (node) => node.children === undefined && expandable(node),\n loadChildren: (parent) => Promise.resolve(materializeChildren(parent)),\n materializePath: (expression) => {\n const segments = literalSegments(expression);\n if (!segments) return undefined;\n let current = rootNode;\n for (const segment of segments) {\n const target = appendJSONPath(contents(current).path, segment);\n const next = materializeChildren(current).find((child) => child.path === target);\n if (!next) return undefined;\n current = next;\n }\n return current;\n },\n };\n}\n\n/** The top-level column a row-rooted path starts at, e.g. `$.payload.x` → `payload`. */\nfunction sourceColumn(path: string): string | undefined {\n return literalSegments(path)?.slice(0, 1).map(String)[0];\n}\n\n/**\n * The literal key/index chain an expression addresses, or undefined when it\n * selects instead — a wildcard, a descent, or a filter matches a set whose shape\n * depends on the document, so there is no single branch to walk to.\n */\nexport function literalSegments(expression: string): Array<string | number> | undefined {\n let rest = expression.trim();\n if (rest === \"\") return undefined;\n if (!rest.startsWith(\"$\")) return undefined;\n rest = rest.slice(1);\n const segments: Array<string | number> = [];\n while (rest.length > 0) {\n if (rest.startsWith(\"..\")) return undefined;\n if (rest.startsWith(\".\")) {\n const match = /^\\.([A-Za-z_$][A-Za-z0-9_$]*)/.exec(rest);\n if (!match) return undefined;\n segments.push(match[1]!);\n rest = rest.slice(match[0].length);\n continue;\n }\n if (rest.startsWith(\"[\")) {\n const close = rest.indexOf(\"]\");\n if (close < 0) return undefined;\n const inner = rest.slice(1, close).trim();\n if (/^\\d+$/.test(inner)) segments.push(Number(inner));\n else if (/^\"(?:[^\"\\\\]|\\\\.)*\"$/.test(inner)) segments.push(JSON.parse(inner) as string);\n else if (/^'[^']*'$/.test(inner)) segments.push(inner.slice(1, -1));\n else return undefined;\n rest = rest.slice(close + 1);\n continue;\n }\n return undefined;\n }\n return segments;\n}\n"],"names":["node"],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ export declare const DEFAULT_MAX_DEPTH = 12;
2
+ export declare const DEFAULT_MAX_OBJECT_PROPERTIES = 100;
3
+ /**
4
+ * Entries the uncapped tree renders under one node before it stops and says so.
5
+ *
6
+ * Depth is what the playground removes the limit on; breadth still has to render
7
+ * as DOM rows the moment a node opens, and a hundred-thousand-element array
8
+ * would take the tab down. The remainder is reported in a visible row rather
9
+ * than dropped quietly — an index past it is still reachable by typing it.
10
+ */
11
+ export declare const DEFAULT_MAX_CHILDREN = 1000;
12
+ export type JSONPathNodeKind = "array" | "object" | "scalar" | "more";
13
+ export interface JSONPathNode {
14
+ key: string;
15
+ path: string;
16
+ value: unknown;
17
+ kind: JSONPathNodeKind;
18
+ summary: string;
19
+ children?: JSONPathNode[];
20
+ /**
21
+ * The top-level column this node's path is rooted at, set only inside a
22
+ * subtree decoded out of a JSON-encoded string. Such a path cannot be read
23
+ * from the row directly — the backend reaches it by way of the column's
24
+ * `source`, so the two have to be committed together.
25
+ */
26
+ root?: string;
27
+ /** Number of entries the node holds, before any paging. */
28
+ childCount: number;
29
+ }
30
+ export interface BuildJSONPathNodeOptions {
31
+ maxDepth?: number;
32
+ maxObjectProperties?: number;
33
+ /** "first" exposes only element [0] of an array; "all" exposes every element. */
34
+ arrayMode?: "first" | "all";
35
+ }
36
+ export declare function jsonPathKind(value: unknown): JSONPathNodeKind;
37
+ export declare function appendJSONPath(path: string, key: string | number): string;
38
+ export declare function summarizeJSON(value: unknown): string;
39
+ /**
40
+ * The eager, capped walk behind the inline dropdown. Deep, wide, or long values
41
+ * are truncated on purpose: the dropdown opens on a click and cannot afford to
42
+ * walk an arbitrary document first.
43
+ */
44
+ export declare function buildJSONPathNode(value: unknown, path: string, depth: number, options?: BuildJSONPathNodeOptions): JSONPathNode;
45
+ export interface LazyJSONPathTreeOptions {
46
+ maxChildren?: number;
47
+ /**
48
+ * Namespaces every node key. Two trees over different documents share their
49
+ * paths, and Tree keys its React elements by node key — without a distinct
50
+ * prefix, swapping the document underneath reuses the old subtree along with
51
+ * the children it had already loaded.
52
+ */
53
+ keyPrefix?: string;
54
+ /**
55
+ * Descend into a string that parses as JSON. Providers routinely hand back a
56
+ * document as an encoded column, and the backend already decodes one when a
57
+ * column names it as its `source` — without this the picker shows the single
58
+ * most interesting column in such a row as an opaque blob.
59
+ */
60
+ parseEmbeddedJSON?: boolean;
61
+ }
62
+ export interface LazyJSONPathTree {
63
+ roots: JSONPathNode[];
64
+ /** Children already materialised, or undefined while the branch is unopened. */
65
+ getChildren: (node: JSONPathNode) => JSONPathNode[] | undefined;
66
+ hasMoreChildren: (node: JSONPathNode) => boolean;
67
+ loadChildren: (node: JSONPathNode) => Promise<JSONPathNode[]>;
68
+ /**
69
+ * Materialise the branch a literal expression addresses and return its node,
70
+ * so a tree can reveal the value it opened with. Returns undefined for an
71
+ * expression that selects rather than addresses (a wildcard, a descent, a
72
+ * filter) or for one the document does not carry.
73
+ */
74
+ materializePath: (expression: string) => JSONPathNode | undefined;
75
+ }
76
+ /**
77
+ * An uncapped tree over `json`: every property, every array element, any depth.
78
+ *
79
+ * Nothing is walked until it is opened, so an arbitrarily deep or wide document
80
+ * costs only what the operator actually looks at. Nodes are cached by path so
81
+ * re-opening a branch returns the *same objects* — `TreeNode` compares the
82
+ * selected node by identity, and a rebuilt node would silently lose the
83
+ * highlight.
84
+ */
85
+ export declare function createLazyJSONPathTree(json: unknown, options?: LazyJSONPathTreeOptions): LazyJSONPathTree;
86
+ /**
87
+ * The literal key/index chain an expression addresses, or undefined when it
88
+ * selects instead — a wildcard, a descent, or a filter matches a set whose shape
89
+ * depends on the document, so there is no single branch to walk to.
90
+ */
91
+ export declare function literalSegments(expression: string): Array<string | number> | undefined;
92
+ //# sourceMappingURL=jsonPathTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonPathTree.d.ts","sourceRoot":"","sources":["../../src/components/jsonPathTree.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,6BAA6B,MAAM,CAAC;AACjD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtE,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;CAC7B;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAG7D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAGzE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQpD;AAQD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,wBAA6B,GACrC,YAAY,CA2Bd;AAED,MAAM,WAAW,uBAAuB;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,gFAAgF;IAChF,WAAW,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,YAAY,EAAE,GAAG,SAAS,CAAC;IAChE,eAAe,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC;IACjD,YAAY,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC9D;;;;;OAKG;IACH,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,YAAY,GAAG,SAAS,CAAC;CACnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,OAAO,EACb,OAAO,GAAE,uBAA4B,GACpC,gBAAgB,CAuHlB;AAOD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,CA6BtF"}
@@ -0,0 +1,189 @@
1
+ const SIMPLE_PROPERTY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
2
+ const DEFAULT_MAX_DEPTH = 12;
3
+ const DEFAULT_MAX_OBJECT_PROPERTIES = 100;
4
+ const DEFAULT_MAX_CHILDREN = 1e3;
5
+ function jsonPathKind(value) {
6
+ if (Array.isArray(value)) return "array";
7
+ return value !== null && typeof value === "object" ? "object" : "scalar";
8
+ }
9
+ function appendJSONPath(path, key) {
10
+ if (typeof key === "number") return `${path}[${key}]`;
11
+ return SIMPLE_PROPERTY.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;
12
+ }
13
+ function summarizeJSON(value) {
14
+ if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? "" : "s"}]`;
15
+ if (value !== null && typeof value === "object") {
16
+ const count = Object.keys(value).length;
17
+ return `{${count} ${count === 1 ? "property" : "properties"}}`;
18
+ }
19
+ if (typeof value === "string") return JSON.stringify(value.length > 80 ? `${value.slice(0, 77)}…` : value);
20
+ return String(value);
21
+ }
22
+ function entryCount(value) {
23
+ if (Array.isArray(value)) return value.length;
24
+ if (value !== null && typeof value === "object") return Object.keys(value).length;
25
+ return 0;
26
+ }
27
+ function buildJSONPathNode(value, path, depth, options = {}) {
28
+ const {
29
+ maxDepth = DEFAULT_MAX_DEPTH,
30
+ maxObjectProperties = DEFAULT_MAX_OBJECT_PROPERTIES,
31
+ arrayMode = "first"
32
+ } = options;
33
+ const kind = jsonPathKind(value);
34
+ const node = {
35
+ key: path,
36
+ path,
37
+ value,
38
+ kind,
39
+ summary: summarizeJSON(value),
40
+ childCount: entryCount(value)
41
+ };
42
+ if (kind === "scalar" || depth >= maxDepth) return node;
43
+ const entries = Array.isArray(value) ? arrayMode === "all" ? value.map((entry, index) => [index, entry]) : value.length > 0 ? [[0, value[0]]] : [] : Object.entries(value).slice(0, maxObjectProperties);
44
+ node.children = entries.map(
45
+ ([key, child]) => buildJSONPathNode(child, appendJSONPath(path, key), depth + 1, options)
46
+ );
47
+ return node;
48
+ }
49
+ function createLazyJSONPathTree(json, options = {}) {
50
+ const { maxChildren = DEFAULT_MAX_CHILDREN, parseEmbeddedJSON = true, keyPrefix = "" } = options;
51
+ const nodes = /* @__PURE__ */ new Map();
52
+ const decoded = /* @__PURE__ */ new Map();
53
+ function embedded(node2) {
54
+ if (!parseEmbeddedJSON || typeof node2.value !== "string") return void 0;
55
+ if (decoded.has(node2.key)) return decoded.get(node2.key);
56
+ const text = node2.value.trim();
57
+ let parsed = void 0;
58
+ if (text.startsWith("{") || text.startsWith("[")) {
59
+ try {
60
+ const candidate = JSON.parse(text);
61
+ if (jsonPathKind(candidate) !== "scalar") parsed = candidate;
62
+ } catch {
63
+ parsed = void 0;
64
+ }
65
+ }
66
+ decoded.set(node2.key, parsed);
67
+ return parsed;
68
+ }
69
+ function contents(node2) {
70
+ const inner = embedded(node2);
71
+ const scope = inner === void 0 ? { value: node2.value, path: node2.path } : { value: inner, path: "$" };
72
+ const root = inner === void 0 ? node2.root : node2.root ?? sourceColumn(node2.path);
73
+ if (root !== void 0) scope.root = root;
74
+ return scope;
75
+ }
76
+ function node(value, path, key, root) {
77
+ const cached = nodes.get(key);
78
+ if (cached) return cached;
79
+ const created = {
80
+ key,
81
+ path,
82
+ value,
83
+ kind: jsonPathKind(value),
84
+ summary: summarizeJSON(value),
85
+ childCount: entryCount(value)
86
+ };
87
+ if (root !== void 0) created.root = root;
88
+ nodes.set(key, created);
89
+ return created;
90
+ }
91
+ function entriesOf(value) {
92
+ if (Array.isArray(value)) return value.map((entry, index) => [index, entry]);
93
+ if (value !== null && typeof value === "object") return Object.entries(value);
94
+ return [];
95
+ }
96
+ function materializeChildren(parent) {
97
+ if (parent.children) return parent.children;
98
+ const scope = contents(parent);
99
+ const entries = entriesOf(scope.value);
100
+ const limit = Math.min(entries.length, maxChildren);
101
+ const children = entries.slice(0, limit).map(([key, value]) => {
102
+ const path = appendJSONPath(scope.path, key);
103
+ return node(value, path, `${parent.key}>${path}`, scope.root);
104
+ });
105
+ if (limit < entries.length) {
106
+ children.push({
107
+ key: `${parent.key}>…`,
108
+ path: scope.path,
109
+ value: void 0,
110
+ kind: "more",
111
+ summary: `${entries.length - limit} more not shown — address them by index`,
112
+ childCount: entries.length - limit
113
+ });
114
+ }
115
+ parent.children = children;
116
+ return children;
117
+ }
118
+ function expandable(node2) {
119
+ if (node2.kind === "more") return false;
120
+ if (node2.kind !== "scalar") return node2.childCount > 0;
121
+ const inner = embedded(node2);
122
+ return inner !== void 0 && entryCount(inner) > 0;
123
+ }
124
+ const rootNode = node(json, "$", `${keyPrefix}$`, void 0);
125
+ return {
126
+ roots: json === void 0 ? [] : [rootNode],
127
+ getChildren: (node2) => node2.children,
128
+ hasMoreChildren: (node2) => node2.children === void 0 && expandable(node2),
129
+ loadChildren: (parent) => Promise.resolve(materializeChildren(parent)),
130
+ materializePath: (expression) => {
131
+ const segments = literalSegments(expression);
132
+ if (!segments) return void 0;
133
+ let current = rootNode;
134
+ for (const segment of segments) {
135
+ const target = appendJSONPath(contents(current).path, segment);
136
+ const next = materializeChildren(current).find((child) => child.path === target);
137
+ if (!next) return void 0;
138
+ current = next;
139
+ }
140
+ return current;
141
+ }
142
+ };
143
+ }
144
+ function sourceColumn(path) {
145
+ var _a;
146
+ return (_a = literalSegments(path)) == null ? void 0 : _a.slice(0, 1).map(String)[0];
147
+ }
148
+ function literalSegments(expression) {
149
+ let rest = expression.trim();
150
+ if (rest === "") return void 0;
151
+ if (!rest.startsWith("$")) return void 0;
152
+ rest = rest.slice(1);
153
+ const segments = [];
154
+ while (rest.length > 0) {
155
+ if (rest.startsWith("..")) return void 0;
156
+ if (rest.startsWith(".")) {
157
+ const match = /^\.([A-Za-z_$][A-Za-z0-9_$]*)/.exec(rest);
158
+ if (!match) return void 0;
159
+ segments.push(match[1]);
160
+ rest = rest.slice(match[0].length);
161
+ continue;
162
+ }
163
+ if (rest.startsWith("[")) {
164
+ const close = rest.indexOf("]");
165
+ if (close < 0) return void 0;
166
+ const inner = rest.slice(1, close).trim();
167
+ if (/^\d+$/.test(inner)) segments.push(Number(inner));
168
+ else if (/^"(?:[^"\\]|\\.)*"$/.test(inner)) segments.push(JSON.parse(inner));
169
+ else if (/^'[^']*'$/.test(inner)) segments.push(inner.slice(1, -1));
170
+ else return void 0;
171
+ rest = rest.slice(close + 1);
172
+ continue;
173
+ }
174
+ return void 0;
175
+ }
176
+ return segments;
177
+ }
178
+ export {
179
+ DEFAULT_MAX_CHILDREN,
180
+ DEFAULT_MAX_DEPTH,
181
+ DEFAULT_MAX_OBJECT_PROPERTIES,
182
+ appendJSONPath,
183
+ buildJSONPathNode,
184
+ createLazyJSONPathTree,
185
+ jsonPathKind,
186
+ literalSegments,
187
+ summarizeJSON
188
+ };
189
+ //# sourceMappingURL=jsonPathTree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonPathTree.js","sources":["../../src/components/jsonPathTree.ts"],"sourcesContent":["// The JSON→JSONPath tree model shared by the inline picker dropdown and the\n// full playground dialog.\n//\n// The two want opposite things from the same walk. The dropdown is a *preview*\n// of a row that has to render the instant it opens, so it builds eagerly and\n// pays for that with caps: depth, property count, and one array element. The\n// playground is a *browser* of the row, so it must have no caps at all — which\n// is only affordable if the walk is lazy, materialising a level at a time as the\n// operator opens it.\n\nconst SIMPLE_PROPERTY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\nexport const DEFAULT_MAX_DEPTH = 12;\nexport const DEFAULT_MAX_OBJECT_PROPERTIES = 100;\n/**\n * Entries the uncapped tree renders under one node before it stops and says so.\n *\n * Depth is what the playground removes the limit on; breadth still has to render\n * as DOM rows the moment a node opens, and a hundred-thousand-element array\n * would take the tab down. The remainder is reported in a visible row rather\n * than dropped quietly — an index past it is still reachable by typing it.\n */\nexport const DEFAULT_MAX_CHILDREN = 1000;\n\nexport type JSONPathNodeKind = \"array\" | \"object\" | \"scalar\" | \"more\";\n\nexport interface JSONPathNode {\n key: string;\n path: string;\n value: unknown;\n kind: JSONPathNodeKind;\n summary: string;\n children?: JSONPathNode[];\n /**\n * The top-level column this node's path is rooted at, set only inside a\n * subtree decoded out of a JSON-encoded string. Such a path cannot be read\n * from the row directly — the backend reaches it by way of the column's\n * `source`, so the two have to be committed together.\n */\n root?: string;\n /** Number of entries the node holds, before any paging. */\n childCount: number;\n}\n\nexport interface BuildJSONPathNodeOptions {\n maxDepth?: number;\n maxObjectProperties?: number;\n /** \"first\" exposes only element [0] of an array; \"all\" exposes every element. */\n arrayMode?: \"first\" | \"all\";\n}\n\nexport function jsonPathKind(value: unknown): JSONPathNodeKind {\n if (Array.isArray(value)) return \"array\";\n return value !== null && typeof value === \"object\" ? \"object\" : \"scalar\";\n}\n\nexport function appendJSONPath(path: string, key: string | number): string {\n if (typeof key === \"number\") return `${path}[${key}]`;\n return SIMPLE_PROPERTY.test(key) ? `${path}.${key}` : `${path}[${JSON.stringify(key)}]`;\n}\n\nexport function summarizeJSON(value: unknown): string {\n if (Array.isArray(value)) return `[${value.length} item${value.length === 1 ? \"\" : \"s\"}]`;\n if (value !== null && typeof value === \"object\") {\n const count = Object.keys(value).length;\n return `{${count} ${count === 1 ? \"property\" : \"properties\"}}`;\n }\n if (typeof value === \"string\") return JSON.stringify(value.length > 80 ? `${value.slice(0, 77)}…` : value);\n return String(value);\n}\n\nfunction entryCount(value: unknown): number {\n if (Array.isArray(value)) return value.length;\n if (value !== null && typeof value === \"object\") return Object.keys(value).length;\n return 0;\n}\n\n/**\n * The eager, capped walk behind the inline dropdown. Deep, wide, or long values\n * are truncated on purpose: the dropdown opens on a click and cannot afford to\n * walk an arbitrary document first.\n */\nexport function buildJSONPathNode(\n value: unknown,\n path: string,\n depth: number,\n options: BuildJSONPathNodeOptions = {},\n): JSONPathNode {\n const {\n maxDepth = DEFAULT_MAX_DEPTH,\n maxObjectProperties = DEFAULT_MAX_OBJECT_PROPERTIES,\n arrayMode = \"first\",\n } = options;\n const kind = jsonPathKind(value);\n const node: JSONPathNode = {\n key: path,\n path,\n value,\n kind,\n summary: summarizeJSON(value),\n childCount: entryCount(value),\n };\n if (kind === \"scalar\" || depth >= maxDepth) return node;\n const entries = Array.isArray(value)\n ? arrayMode === \"all\"\n ? value.map((entry, index) => [index, entry] as const)\n : value.length > 0\n ? [[0, value[0]] as const]\n : []\n : Object.entries(value as Record<string, unknown>).slice(0, maxObjectProperties);\n node.children = entries.map(([key, child]) =>\n buildJSONPathNode(child, appendJSONPath(path, key), depth + 1, options),\n );\n return node;\n}\n\nexport interface LazyJSONPathTreeOptions {\n maxChildren?: number;\n /**\n * Namespaces every node key. Two trees over different documents share their\n * paths, and Tree keys its React elements by node key — without a distinct\n * prefix, swapping the document underneath reuses the old subtree along with\n * the children it had already loaded.\n */\n keyPrefix?: string;\n /**\n * Descend into a string that parses as JSON. Providers routinely hand back a\n * document as an encoded column, and the backend already decodes one when a\n * column names it as its `source` — without this the picker shows the single\n * most interesting column in such a row as an opaque blob.\n */\n parseEmbeddedJSON?: boolean;\n}\n\nexport interface LazyJSONPathTree {\n roots: JSONPathNode[];\n /** Children already materialised, or undefined while the branch is unopened. */\n getChildren: (node: JSONPathNode) => JSONPathNode[] | undefined;\n hasMoreChildren: (node: JSONPathNode) => boolean;\n loadChildren: (node: JSONPathNode) => Promise<JSONPathNode[]>;\n /**\n * Materialise the branch a literal expression addresses and return its node,\n * so a tree can reveal the value it opened with. Returns undefined for an\n * expression that selects rather than addresses (a wildcard, a descent, a\n * filter) or for one the document does not carry.\n */\n materializePath: (expression: string) => JSONPathNode | undefined;\n}\n\n/**\n * An uncapped tree over `json`: every property, every array element, any depth.\n *\n * Nothing is walked until it is opened, so an arbitrarily deep or wide document\n * costs only what the operator actually looks at. Nodes are cached by path so\n * re-opening a branch returns the *same objects* — `TreeNode` compares the\n * selected node by identity, and a rebuilt node would silently lose the\n * highlight.\n */\nexport function createLazyJSONPathTree(\n json: unknown,\n options: LazyJSONPathTreeOptions = {},\n): LazyJSONPathTree {\n const { maxChildren = DEFAULT_MAX_CHILDREN, parseEmbeddedJSON = true, keyPrefix = \"\" } = options;\n const nodes = new Map<string, JSONPathNode>();\n\n // hasMoreChildren runs on every render of every visible row, so the decode is\n // memoised per node rather than re-parsing a long string each time.\n const decoded = new Map<string, unknown>();\n\n function embedded(node: JSONPathNode): unknown {\n if (!parseEmbeddedJSON || typeof node.value !== \"string\") return undefined;\n if (decoded.has(node.key)) return decoded.get(node.key);\n const text = node.value.trim();\n let parsed: unknown = undefined;\n if (text.startsWith(\"{\") || text.startsWith(\"[\")) {\n try {\n const candidate: unknown = JSON.parse(text);\n if (jsonPathKind(candidate) !== \"scalar\") parsed = candidate;\n } catch {\n parsed = undefined;\n }\n }\n decoded.set(node.key, parsed);\n return parsed;\n }\n\n // What a node's children are drawn from: its own value, or the document\n // decoded out of it when it holds JSON as text. An embedded document restarts\n // at `$` because that is where the backend evaluates it from once the column\n // is named as a `source`.\n function contents(node: JSONPathNode): { value: unknown; path: string; root?: string } {\n const inner = embedded(node);\n const scope: { value: unknown; path: string; root?: string } =\n inner === undefined\n ? { value: node.value, path: node.path }\n : { value: inner, path: \"$\" };\n const root = inner === undefined ? node.root : node.root ?? sourceColumn(node.path);\n if (root !== undefined) scope.root = root;\n return scope;\n }\n\n function node(\n value: unknown,\n path: string,\n key: string,\n root: string | undefined,\n ): JSONPathNode {\n const cached = nodes.get(key);\n if (cached) return cached;\n const created: JSONPathNode = {\n key,\n path,\n value,\n kind: jsonPathKind(value),\n summary: summarizeJSON(value),\n childCount: entryCount(value),\n };\n if (root !== undefined) created.root = root;\n nodes.set(key, created);\n return created;\n }\n\n function entriesOf(value: unknown): Array<readonly [string | number, unknown]> {\n if (Array.isArray(value)) return value.map((entry, index) => [index, entry] as const);\n if (value !== null && typeof value === \"object\") return Object.entries(value as Record<string, unknown>);\n return [];\n }\n\n function materializeChildren(parent: JSONPathNode): JSONPathNode[] {\n if (parent.children) return parent.children;\n const scope = contents(parent);\n const entries = entriesOf(scope.value);\n const limit = Math.min(entries.length, maxChildren);\n const children = entries.slice(0, limit).map(([key, value]) => {\n const path = appendJSONPath(scope.path, key);\n // The key namespaces on the parent so an embedded document — which\n // restarts its paths at `$` — cannot collide with the outer row.\n return node(value, path, `${parent.key}>${path}`, scope.root);\n });\n if (limit < entries.length) {\n children.push({\n key: `${parent.key}>…`,\n path: scope.path,\n value: undefined,\n kind: \"more\",\n summary: `${entries.length - limit} more not shown — address them by index`,\n childCount: entries.length - limit,\n });\n }\n parent.children = children;\n return children;\n }\n\n function expandable(node: JSONPathNode): boolean {\n if (node.kind === \"more\") return false;\n if (node.kind !== \"scalar\") return node.childCount > 0;\n const inner = embedded(node);\n return inner !== undefined && entryCount(inner) > 0;\n }\n\n const rootNode = node(json, \"$\", `${keyPrefix}$`, undefined);\n\n return {\n roots: json === undefined ? [] : [rootNode],\n getChildren: (node) => node.children,\n hasMoreChildren: (node) => node.children === undefined && expandable(node),\n loadChildren: (parent) => Promise.resolve(materializeChildren(parent)),\n materializePath: (expression) => {\n const segments = literalSegments(expression);\n if (!segments) return undefined;\n let current = rootNode;\n for (const segment of segments) {\n const target = appendJSONPath(contents(current).path, segment);\n const next = materializeChildren(current).find((child) => child.path === target);\n if (!next) return undefined;\n current = next;\n }\n return current;\n },\n };\n}\n\n/** The top-level column a row-rooted path starts at, e.g. `$.payload.x` → `payload`. */\nfunction sourceColumn(path: string): string | undefined {\n return literalSegments(path)?.slice(0, 1).map(String)[0];\n}\n\n/**\n * The literal key/index chain an expression addresses, or undefined when it\n * selects instead — a wildcard, a descent, or a filter matches a set whose shape\n * depends on the document, so there is no single branch to walk to.\n */\nexport function literalSegments(expression: string): Array<string | number> | undefined {\n let rest = expression.trim();\n if (rest === \"\") return undefined;\n if (!rest.startsWith(\"$\")) return undefined;\n rest = rest.slice(1);\n const segments: Array<string | number> = [];\n while (rest.length > 0) {\n if (rest.startsWith(\"..\")) return undefined;\n if (rest.startsWith(\".\")) {\n const match = /^\\.([A-Za-z_$][A-Za-z0-9_$]*)/.exec(rest);\n if (!match) return undefined;\n segments.push(match[1]!);\n rest = rest.slice(match[0].length);\n continue;\n }\n if (rest.startsWith(\"[\")) {\n const close = rest.indexOf(\"]\");\n if (close < 0) return undefined;\n const inner = rest.slice(1, close).trim();\n if (/^\\d+$/.test(inner)) segments.push(Number(inner));\n else if (/^\"(?:[^\"\\\\]|\\\\.)*\"$/.test(inner)) segments.push(JSON.parse(inner) as string);\n else if (/^'[^']*'$/.test(inner)) segments.push(inner.slice(1, -1));\n else return undefined;\n rest = rest.slice(close + 1);\n continue;\n }\n return undefined;\n }\n return segments;\n}\n"],"names":["node"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const react = require("react");
4
+ const SecretFormField = require("./SecretFormField.cjs");
5
+ function createSecretFormExtensions(options) {
6
+ const post = (field, nodes, context) => {
7
+ const component = field.schema["x-clicky-component"];
8
+ if (component !== "k8s-secret-selector" && component !== "k8s-url-selector") {
9
+ return nodes;
10
+ }
11
+ return {
12
+ label: nodes.label,
13
+ value: react.createElement(SecretFormField.SecretFormField, {
14
+ ...options,
15
+ field,
16
+ namespace: namespaceFor(options, context),
17
+ allowWorkload: component === "k8s-url-selector"
18
+ })
19
+ };
20
+ };
21
+ return { post: [post] };
22
+ }
23
+ function namespaceFor(options, context) {
24
+ var _a;
25
+ if (options.getNamespace) return options.getNamespace(context == null ? void 0 : context.rootValue);
26
+ const namespace = (_a = context == null ? void 0 : context.rootValue) == null ? void 0 : _a.namespace;
27
+ return typeof namespace === "string" ? namespace : "";
28
+ }
29
+ exports.createSecretFormExtensions = createSecretFormExtensions;
30
+ //# sourceMappingURL=secret-form-extension.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-form-extension.cjs","sources":["../../src/components/secret-form-extension.ts"],"sourcesContent":["import { createElement } from \"react\";\nimport { SecretFormField } from \"./SecretFormField\";\nimport type {\n PostExtension,\n PostExtensionContext,\n} from \"./json-schema-form-types\";\nimport type { OnePasswordLoaders } from \"./OnePasswordSelector.model\";\nimport type {\n KeyPreview,\n SecretKind,\n SecretResource,\n SecretValueSource,\n} from \"./SecretKeySelector\";\nimport type {\n WorkloadKind,\n WorkloadResource,\n} from \"./workload-picker-utils\";\n\nexport type SecretFormLoaders = {\n loadResources: (\n kind: SecretKind,\n namespace: string,\n ) => Promise<SecretResource[]>;\n loadKeyPreview: (\n kind: SecretKind,\n name: string,\n namespace: string,\n ) => Promise<KeyPreview[]>;\n loadServiceAccounts: (namespace: string) => Promise<SecretResource[]>;\n loadOnePasswordVaults: OnePasswordLoaders[\"loadVaults\"];\n loadOnePasswordItems: OnePasswordLoaders[\"loadItems\"];\n loadOnePasswordFields: OnePasswordLoaders[\"loadFields\"];\n loadWorkloads: (\n namespace: string,\n kinds: WorkloadKind[],\n ) => Promise<Record<WorkloadKind, WorkloadResource[]>>;\n};\n\nexport type SecretFormExtensionOptions = {\n loaders: SecretFormLoaders;\n secretSources?: SecretValueSource[];\n urlSources?: SecretValueSource[];\n getNamespace?: (rootValue: Record<string, unknown> | undefined) => string;\n};\n\nexport function createSecretFormExtensions(\n options: SecretFormExtensionOptions,\n): { post: PostExtension[] } {\n const post: PostExtension = (field, nodes, context) => {\n const component = field.schema[\"x-clicky-component\"];\n if (\n component !== \"k8s-secret-selector\" &&\n component !== \"k8s-url-selector\"\n ) {\n return nodes;\n }\n return {\n label: nodes.label,\n value: createElement(SecretFormField, {\n ...options,\n field,\n namespace: namespaceFor(options, context),\n allowWorkload: component === \"k8s-url-selector\",\n }),\n };\n };\n return { post: [post] };\n}\n\nfunction namespaceFor(\n options: SecretFormExtensionOptions,\n context: PostExtensionContext | undefined,\n): string {\n if (options.getNamespace) return options.getNamespace(context?.rootValue);\n const namespace = context?.rootValue?.namespace;\n return typeof namespace === \"string\" ? namespace : \"\";\n}\n"],"names":["createElement","SecretFormField"],"mappings":";;;;AA6CO,SAAS,2BACd,SAC2B;AAC3B,QAAM,OAAsB,CAAC,OAAO,OAAO,YAAY;AACrD,UAAM,YAAY,MAAM,OAAO,oBAAoB;AACnD,QACE,cAAc,yBACd,cAAc,oBACd;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,OAAO,MAAM;AAAA,MACb,OAAOA,MAAAA,cAAcC,iCAAiB;AAAA,QACpC,GAAG;AAAA,QACH;AAAA,QACA,WAAW,aAAa,SAAS,OAAO;AAAA,QACxC,eAAe,cAAc;AAAA,MAAA,CAC9B;AAAA,IAAA;AAAA,EAEL;AACA,SAAO,EAAE,MAAM,CAAC,IAAI,EAAA;AACtB;AAEA,SAAS,aACP,SACA,SACQ;;AACR,MAAI,QAAQ,aAAc,QAAO,QAAQ,aAAa,mCAAS,SAAS;AACxE,QAAM,aAAY,wCAAS,cAAT,mBAAoB;AACtC,SAAO,OAAO,cAAc,WAAW,YAAY;AACrD;;"}
@@ -0,0 +1,23 @@
1
+ import { PostExtension } from './json-schema-form-types';
2
+ import { OnePasswordLoaders } from './OnePasswordSelector.model';
3
+ import { KeyPreview, SecretKind, SecretResource, SecretValueSource } from './SecretKeySelector';
4
+ import { WorkloadKind, WorkloadResource } from './workload-picker-utils';
5
+ export type SecretFormLoaders = {
6
+ loadResources: (kind: SecretKind, namespace: string) => Promise<SecretResource[]>;
7
+ loadKeyPreview: (kind: SecretKind, name: string, namespace: string) => Promise<KeyPreview[]>;
8
+ loadServiceAccounts: (namespace: string) => Promise<SecretResource[]>;
9
+ loadOnePasswordVaults: OnePasswordLoaders["loadVaults"];
10
+ loadOnePasswordItems: OnePasswordLoaders["loadItems"];
11
+ loadOnePasswordFields: OnePasswordLoaders["loadFields"];
12
+ loadWorkloads: (namespace: string, kinds: WorkloadKind[]) => Promise<Record<WorkloadKind, WorkloadResource[]>>;
13
+ };
14
+ export type SecretFormExtensionOptions = {
15
+ loaders: SecretFormLoaders;
16
+ secretSources?: SecretValueSource[];
17
+ urlSources?: SecretValueSource[];
18
+ getNamespace?: (rootValue: Record<string, unknown> | undefined) => string;
19
+ };
20
+ export declare function createSecretFormExtensions(options: SecretFormExtensionOptions): {
21
+ post: PostExtension[];
22
+ };
23
+ //# sourceMappingURL=secret-form-extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-form-extension.d.ts","sourceRoot":"","sources":["../../src/components/secret-form-extension.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EAEd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,aAAa,EAAE,CACb,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IAC/B,cAAc,EAAE,CACd,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,KACd,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAC3B,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACtE,qBAAqB,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC;IACxD,oBAAoB,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACtD,qBAAqB,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC;IACxD,aAAa,EAAE,CACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,YAAY,EAAE,KAClB,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,aAAa,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACpC,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;IACjC,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,KAAK,MAAM,CAAC;CAC3E,CAAC;AAEF,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,0BAA0B,GAClC;IAAE,IAAI,EAAE,aAAa,EAAE,CAAA;CAAE,CAoB3B"}