@coldsmirk/inkstone-elasticsearch 0.25.0 → 0.26.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.
@@ -0,0 +1,32 @@
1
+ import { a as ElasticsearchAssist, o as ElasticsearchBodyAssist, t as ElasticsearchMarker } from "./markers-DnaVJoMY.js";
2
+ import { CompletionSource } from "@codemirror/autocomplete";
3
+ import { Diagnostic } from "@codemirror/lint";
4
+ import { Extension } from "@codemirror/state";
5
+ //#region src/codemirror.d.ts
6
+ /**
7
+ * Completion over a whole request document, off an assist built with the host's catalog.
8
+ *
9
+ * Explicit or not: the list is asked for on `/`, on a quote and inside a word, the same three
10
+ * places `./monaco` names as trigger characters, and the engine half answers nothing where
11
+ * the caret is nowhere in particular.
12
+ */
13
+ declare function elasticsearchCompletion(assist: ElasticsearchAssist): CompletionSource;
14
+ /**
15
+ * Completion over a body standing on its own — a one-line filter field, whose document is a
16
+ * `query` object and nothing else (`createElasticsearchBodyAssist`).
17
+ */
18
+ declare function elasticsearchBodyCompletion(assist: ElasticsearchBodyAssist): CompletionSource;
19
+ /**
20
+ * The endpoint's card under the pointer, as `./monaco`'s hover provider gives it.
21
+ *
22
+ * The markdown is handed over as text: rendering it is the host's, since a tooltip's DOM is
23
+ * the host's design and this package ships none.
24
+ */
25
+ declare function elasticsearchHover(assist: ElasticsearchAssist, render: (markdown: string[]) => HTMLElement): Extension;
26
+ /**
27
+ * This package's markers as CodeMirror's diagnostics, the words beside each code the host's,
28
+ * as `setElasticsearchMarkers` takes them.
29
+ */
30
+ declare function elasticsearchDiagnostics(markers: readonly ElasticsearchMarker[], wording: (marker: ElasticsearchMarker) => string): Diagnostic[];
31
+ //#endregion
32
+ export { elasticsearchBodyCompletion, elasticsearchCompletion, elasticsearchDiagnostics, elasticsearchHover };
@@ -0,0 +1,60 @@
1
+ import { snippet } from "@codemirror/autocomplete";
2
+ import { hoverTooltip } from "@codemirror/view";
3
+ //#region src/codemirror.ts
4
+ const TYPES = {
5
+ method: "keyword",
6
+ endpoint: "namespace",
7
+ index: "class",
8
+ alias: "class",
9
+ key: "property"
10
+ };
11
+ function completion(candidate, at) {
12
+ return {
13
+ label: candidate.label,
14
+ type: TYPES[candidate.kind],
15
+ detail: candidate.detail,
16
+ info: candidate.documentation,
17
+ boost: -candidate.sortGroup * 10 - at / 1e3,
18
+ apply: candidate.snippet === true ? snippet(candidate.insertText) : candidate.insertText
19
+ };
20
+ }
21
+ function resultOf(candidates, pos) {
22
+ const first = candidates[0];
23
+ if (first === void 0) return null;
24
+ return {
25
+ from: pos - first.replace,
26
+ options: candidates.map((candidate, at) => completion(candidate, at)),
27
+ validFor: /^[\w.*@$-]*$/
28
+ };
29
+ }
30
+ function elasticsearchCompletion(assist) {
31
+ return (context) => resultOf(assist.complete(context.state.doc.toString(), context.pos), context.pos);
32
+ }
33
+ function elasticsearchBodyCompletion(assist) {
34
+ return (context) => resultOf(assist.complete(context.state.doc.toString(), context.pos), context.pos);
35
+ }
36
+ function elasticsearchHover(assist, render) {
37
+ return hoverTooltip((view, pos) => {
38
+ const card = assist.hover(view.state.doc.toString(), pos);
39
+ if (card === null) return null;
40
+ return {
41
+ pos: card.from,
42
+ end: card.to,
43
+ create: () => {
44
+ return { dom: render(card.markdown) };
45
+ }
46
+ };
47
+ });
48
+ }
49
+ function elasticsearchDiagnostics(markers, wording) {
50
+ return markers.map((marker) => {
51
+ return {
52
+ from: marker.from,
53
+ to: marker.to,
54
+ severity: marker.severity === "error" ? "error" : marker.severity === "warning" ? "warning" : "info",
55
+ message: wording(marker)
56
+ };
57
+ });
58
+ }
59
+ //#endregion
60
+ export { elasticsearchBodyCompletion, elasticsearchCompletion, elasticsearchDiagnostics, elasticsearchHover };
package/dist/index.d.ts CHANGED
@@ -1,34 +1,2 @@
1
- import { _ as readRequest, a as ElasticsearchAssist, b as runnableRequest, c as ElasticsearchHoverCard, d as REQUEST_METHODS, f as RequestMethod, g as caretContext, h as RunnableRequest, i as CatalogIndex, l as createElasticsearchAssist, m as RequestRefusal, n as ElasticsearchMarkerCode, o as ElasticsearchCatalog, p as RequestRead, r as requestMarkers, s as ElasticsearchCompletionCandidate, t as ElasticsearchMarker, u as CaretContext, v as requestAt, x as takesLines, y as requestSpans } from "./markers-BctX905j.js";
2
- //#region src/api.d.ts
3
- /**
4
- * The vocabulary the assist offers: the REST endpoints a bench reaches for, and the keys of a
5
- * body by where the caret stands in it. Curated, not exhaustive — the console's own
6
- * completion is a hint of the API's shape, and the server's answer is the authority.
7
- */
8
- /**
9
- * One endpoint: its path with `{index}`, `{id}` and `{name}` for the parts the reader fills
10
- * in, the methods it takes, and one line on what it does.
11
- */
12
- interface ApiEndpoint {
13
- path: string;
14
- methods: RequestMethod[];
15
- summary: string;
16
- }
17
- declare const API_ENDPOINTS: readonly ApiEndpoint[];
18
- /**
19
- * The endpoint a path names, `{…}` parts matching one segment each; null where none does.
20
- * The query string is not part of the match.
21
- */
22
- declare function endpointOf(path: string): ApiEndpoint | null;
23
- /**
24
- * What the request is for, read off its path — which decides the top-level keys of its body.
25
- */
26
- type BodyKind = "search" | "count" | "index" | "mapping" | "settings" | "document" | "update" | "update-by-query" | "reindex" | "aliases" | "analyze" | "sql" | "cluster-settings" | "template" | "explain" | "mget" | "other";
27
- declare function bodyKindOf(method: string, path: string): BodyKind;
28
- /**
29
- * The keys to offer at a key position in the body, by the request the body belongs to and the
30
- * keys enclosing the caret; empty where the names are the reader's own (a field, an aggregation).
31
- */
32
- declare function bodyKeys(kind: BodyKind, path: readonly string[]): string[];
33
- //#endregion
34
- export { API_ENDPOINTS, type ApiEndpoint, type BodyKind, type CaretContext, type CatalogIndex, type ElasticsearchAssist, type ElasticsearchCatalog, type ElasticsearchCompletionCandidate, type ElasticsearchHoverCard, type ElasticsearchMarker, type ElasticsearchMarkerCode, REQUEST_METHODS, type RequestMethod, type RequestRead, type RequestRefusal, type RunnableRequest, bodyKeys, bodyKindOf, caretContext, createElasticsearchAssist, endpointOf, readRequest, requestAt, requestMarkers, requestSpans, runnableRequest, takesLines };
1
+ import { A as runnableRequest, C as RequestRefusal, D as readRequest, E as keyPosition, O as requestAt, S as RequestRead, T as caretContext, _ as endpointOf, a as ElasticsearchAssist, b as REQUEST_METHODS, c as ElasticsearchCompletionCandidate, d as createElasticsearchBodyAssist, f as API_ENDPOINTS, g as bodyKindOf, h as bodyKeys, i as CatalogIndex, j as takesLines, k as requestSpans, l as ElasticsearchHoverCard, m as BodyKind, n as ElasticsearchMarkerCode, o as ElasticsearchBodyAssist, p as ApiEndpoint, r as requestMarkers, s as ElasticsearchCatalog, t as ElasticsearchMarker, u as createElasticsearchAssist, v as CaretContext, w as RunnableRequest, x as RequestMethod, y as KeyPosition } from "./markers-DnaVJoMY.js";
2
+ export { API_ENDPOINTS, type ApiEndpoint, type BodyKind, type CaretContext, type CatalogIndex, type ElasticsearchAssist, type ElasticsearchBodyAssist, type ElasticsearchCatalog, type ElasticsearchCompletionCandidate, type ElasticsearchHoverCard, type ElasticsearchMarker, type ElasticsearchMarkerCode, type KeyPosition, REQUEST_METHODS, type RequestMethod, type RequestRead, type RequestRefusal, type RunnableRequest, bodyKeys, bodyKindOf, caretContext, createElasticsearchAssist, createElasticsearchBodyAssist, endpointOf, keyPosition, readRequest, requestAt, requestMarkers, requestSpans, runnableRequest, takesLines };
package/dist/index.js CHANGED
@@ -1,9 +1,31 @@
1
- import { a as requestAt, c as takesLines, d as bodyKindOf, f as endpointOf, i as readRequest, l as API_ENDPOINTS, n as REQUEST_METHODS, o as requestSpans, r as caretContext, s as runnableRequest, t as requestMarkers, u as bodyKeys } from "./markers-DBJshw-Y.js";
1
+ import { a as readRequest, c as runnableRequest, d as bodyKeys, f as bodyKindOf, i as keyPosition, l as takesLines, n as REQUEST_METHODS, o as requestAt, p as endpointOf, r as caretContext, s as requestSpans, t as requestMarkers, u as API_ENDPOINTS } from "./markers-DwYWlWEq.js";
2
2
  //#region src/assist.ts
3
3
  const NO_CATALOG = { indices: () => [] };
4
+ function createElasticsearchBodyAssist(kind) {
5
+ return { complete: (body, offset) => {
6
+ const at = keyPosition(body.slice(0, offset));
7
+ return at === null ? [] : keyCandidates(kind, at);
8
+ } };
9
+ }
4
10
  function tailOf(endpoint, prefix) {
5
11
  return endpoint.path.slice(prefix.length).replaceAll(/\/\{[^}]+\}/gu, "").replace(/^\//u, "");
6
12
  }
13
+ function keyCandidates(kind, at) {
14
+ return bodyKeys(kind, at.path).map((key) => at.quoted ? {
15
+ label: key,
16
+ kind: "key",
17
+ insertText: key,
18
+ replace: at.typed.length,
19
+ sortGroup: 0
20
+ } : {
21
+ label: key,
22
+ kind: "key",
23
+ insertText: `"${key}": $0`,
24
+ snippet: true,
25
+ replace: 0,
26
+ sortGroup: 0
27
+ });
28
+ }
7
29
  function endpointCandidate(endpoint, label, replace) {
8
30
  return {
9
31
  label,
@@ -59,23 +81,7 @@ function createElasticsearchAssist(catalog = NO_CATALOG) {
59
81
  }
60
82
  return [];
61
83
  }
62
- case "body-key": {
63
- const kind = bodyKindOf(context.request.method, context.request.path);
64
- return bodyKeys(kind, context.path).map((key) => context.quoted ? {
65
- label: key,
66
- kind: "key",
67
- insertText: key,
68
- replace: context.typed.length,
69
- sortGroup: 0
70
- } : {
71
- label: key,
72
- kind: "key",
73
- insertText: `"${key}": $0`,
74
- snippet: true,
75
- replace: 0,
76
- sortGroup: 0
77
- });
78
- }
84
+ case "body-key": return keyCandidates(bodyKindOf(context.request.method, context.request.path), context);
79
85
  default: return [];
80
86
  }
81
87
  },
@@ -99,4 +105,4 @@ function createElasticsearchAssist(catalog = NO_CATALOG) {
99
105
  };
100
106
  }
101
107
  //#endregion
102
- export { API_ENDPOINTS, REQUEST_METHODS, bodyKeys, bodyKindOf, caretContext, createElasticsearchAssist, endpointOf, readRequest, requestAt, requestMarkers, requestSpans, runnableRequest, takesLines };
108
+ export { API_ENDPOINTS, REQUEST_METHODS, bodyKeys, bodyKindOf, caretContext, createElasticsearchAssist, createElasticsearchBodyAssist, endpointOf, keyPosition, readRequest, requestAt, requestMarkers, requestSpans, runnableRequest, takesLines };
@@ -127,6 +127,66 @@ type CaretContext = {
127
127
  kind: "none";
128
128
  };
129
129
  declare function caretContext(text: string, offset: number): CaretContext;
130
+ /**
131
+ * A caret standing where an object's key goes: which keys enclose it, what of its own is
132
+ * typed, and whether a quote was opened for it.
133
+ */
134
+ interface KeyPosition {
135
+ /**
136
+ * The keys of the objects enclosing the caret, outermost first, arrays passed through:
137
+ * `["query", "bool"]` inside the bool's own object.
138
+ */
139
+ path: string[];
140
+ /**
141
+ * The key's own characters typed before the caret.
142
+ */
143
+ typed: string;
144
+ /**
145
+ * Whether those characters are inside a quote the reader already opened — which decides
146
+ * whether a completion inserts the name alone or the whole `"key": ` around it.
147
+ */
148
+ quoted: boolean;
149
+ }
150
+ /**
151
+ * Whether the end of `body` — the text before the caret — is a key position in an object, and
152
+ * which keys enclose it. A light scan, not a parse: a body being typed is rarely valid JSON.
153
+ *
154
+ * Exported because a body is a surface of its own: a `query` object typed into a one-line
155
+ * field has no request line above it to be read with (`createElasticsearchBodyAssist`).
156
+ */
157
+ declare function keyPosition(body: string): KeyPosition | null;
158
+ //#endregion
159
+ //#region src/api.d.ts
160
+ /**
161
+ * The vocabulary the assist offers: the REST endpoints a bench reaches for, and the keys of a
162
+ * body by where the caret stands in it. Curated, not exhaustive — the console's own
163
+ * completion is a hint of the API's shape, and the server's answer is the authority.
164
+ */
165
+ /**
166
+ * One endpoint: its path with `{index}`, `{id}` and `{name}` for the parts the reader fills
167
+ * in, the methods it takes, and one line on what it does.
168
+ */
169
+ interface ApiEndpoint {
170
+ path: string;
171
+ methods: RequestMethod[];
172
+ summary: string;
173
+ }
174
+ declare const API_ENDPOINTS: readonly ApiEndpoint[];
175
+ /**
176
+ * The endpoint a path names, `{…}` parts matching one segment each; null where none does.
177
+ * The query string is not part of the match.
178
+ */
179
+ declare function endpointOf(path: string): ApiEndpoint | null;
180
+ /**
181
+ * What the request is for, read off its path — which decides the top-level keys of its body.
182
+ */
183
+ type BodyKind = "search" | "count" | "index" | "mapping" | "settings" | "document" | "update" | "update-by-query" | "reindex" | "aliases" | "analyze" | "sql" | "cluster-settings" | "template" | "explain" | "mget" | "other";
184
+ declare function bodyKindOf(method: string, path: string): BodyKind;
185
+ /**
186
+ * The keys to offer at a key position in the body, by the request the body belongs to and the
187
+ * keys enclosing the caret; empty where the names are the reader's own (a field, an aggregation).
188
+ */
189
+ declare function bodyKeys(kind: BodyKind, path: readonly string[]): string[];
130
190
  //#endregion
131
191
  //#region src/assist.d.ts
132
192
  /**
@@ -174,6 +234,22 @@ interface ElasticsearchAssist {
174
234
  complete: (text: string, offset: number) => ElasticsearchCompletionCandidate[];
175
235
  hover: (text: string, offset: number) => ElasticsearchHoverCard | null;
176
236
  }
237
+ /**
238
+ * Completion for a request body standing on its own, with no request line above it to say
239
+ * what it is the body of — a `query` object typed into a one-line filter field, which is how
240
+ * a console browses an index without a command written out.
241
+ */
242
+ interface ElasticsearchBodyAssist {
243
+ complete: (body: string, offset: number) => ElasticsearchCompletionCandidate[];
244
+ }
245
+ /**
246
+ * The body vocabulary alone, for a surface that holds a body and nothing else.
247
+ *
248
+ * The caller names the `kind` because nothing in the text can: the whole point of this
249
+ * surface is that the method and the path are decided elsewhere — a filter field under a
250
+ * browsed index is always a `"search"` body, and says so once rather than on every keystroke.
251
+ */
252
+ declare function createElasticsearchBodyAssist(kind: BodyKind): ElasticsearchBodyAssist;
177
253
  /**
178
254
  * Completion for the request line and the body, hover for the endpoint on the request line —
179
255
  * both reading the request through `request.ts`, as the engine reads it.
@@ -201,4 +277,4 @@ interface ElasticsearchMarker {
201
277
  */
202
278
  declare function requestMarkers(text: string): ElasticsearchMarker[];
203
279
  //#endregion
204
- export { readRequest as _, ElasticsearchAssist as a, runnableRequest as b, ElasticsearchHoverCard as c, REQUEST_METHODS as d, RequestMethod as f, caretContext as g, RunnableRequest as h, CatalogIndex as i, createElasticsearchAssist as l, RequestRefusal as m, ElasticsearchMarkerCode as n, ElasticsearchCatalog as o, RequestRead as p, requestMarkers as r, ElasticsearchCompletionCandidate as s, ElasticsearchMarker as t, CaretContext as u, requestAt as v, takesLines as x, requestSpans as y };
280
+ export { runnableRequest as A, RequestRefusal as C, readRequest as D, keyPosition as E, requestAt as O, RequestRead as S, caretContext as T, endpointOf as _, ElasticsearchAssist as a, REQUEST_METHODS as b, ElasticsearchCompletionCandidate as c, createElasticsearchBodyAssist as d, API_ENDPOINTS as f, bodyKindOf as g, bodyKeys as h, CatalogIndex as i, takesLines as j, requestSpans as k, ElasticsearchHoverCard as l, BodyKind as m, ElasticsearchMarkerCode as n, ElasticsearchBodyAssist as o, ApiEndpoint as p, requestMarkers as r, ElasticsearchCatalog as s, ElasticsearchMarker as t, createElasticsearchAssist as u, CaretContext as v, RunnableRequest as w, RequestMethod as x, KeyPosition as y };
@@ -1238,4 +1238,4 @@ function requestMarkers(text) {
1238
1238
  return markers;
1239
1239
  }
1240
1240
  //#endregion
1241
- export { requestAt as a, takesLines as c, bodyKindOf as d, endpointOf as f, readRequest as i, API_ENDPOINTS as l, REQUEST_METHODS as n, requestSpans as o, caretContext as r, runnableRequest as s, requestMarkers as t, bodyKeys as u };
1241
+ export { readRequest as a, runnableRequest as c, bodyKeys as d, bodyKindOf as f, keyPosition as i, takesLines as l, REQUEST_METHODS as n, requestAt as o, endpointOf as p, caretContext as r, requestSpans as s, requestMarkers as t, API_ENDPOINTS as u };
package/dist/monaco.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as ElasticsearchAssist, t as ElasticsearchMarker } from "./markers-BctX905j.js";
1
+ import { a as ElasticsearchAssist, t as ElasticsearchMarker } from "./markers-DnaVJoMY.js";
2
2
  import * as monacoEditor from "monaco-editor";
3
3
  import { IDisposable, editor } from "monaco-editor";
4
4
  //#region src/monaco.d.ts
package/dist/react.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as ElasticsearchAssist, t as ElasticsearchMarker } from "./markers-BctX905j.js";
1
+ import { a as ElasticsearchAssist, t as ElasticsearchMarker } from "./markers-DnaVJoMY.js";
2
2
  import { MonacoModule } from "./monaco.js";
3
3
  import { ReactNode } from "react";
4
4
  import { editor } from "monaco-editor";
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as requestMarkers } from "./markers-DBJshw-Y.js";
1
+ import { t as requestMarkers } from "./markers-DwYWlWEq.js";
2
2
  import { ELASTICSEARCH_LANGUAGE_ID, defineElasticsearchLanguage, registerElasticsearchLanguage, setElasticsearchMarkers } from "./monaco.js";
3
3
  import { MonacoEditor } from "@coldsmirk/inkstone-react/monaco";
4
4
  import { useEffect, useInsertionEffect, useRef, useState } from "react";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coldsmirk/inkstone-elasticsearch",
3
- "version": "0.25.0",
3
+ "version": "0.26.0",
4
4
  "description": "Elasticsearch request editing intelligence for Monaco: the console spelling (a method and a path, the body after), endpoint and index completion, body keys by context, request markers, and a drop-in React request editor.",
5
5
  "keywords": [
6
6
  "elasticsearch",
@@ -43,17 +43,37 @@
43
43
  "dist"
44
44
  ],
45
45
  "devDependencies": {
46
+ "@codemirror/autocomplete": "^6.20.3",
47
+ "@codemirror/lint": "^6.9.7",
48
+ "@codemirror/state": "^6.6.0",
49
+ "@codemirror/view": "^6.43.0",
46
50
  "monaco-editor": "^0.56.0",
47
51
  "react": "^19.2.8",
48
52
  "react-dom": "^19.2.8",
49
- "@coldsmirk/inkstone-react": "^0.25.0"
53
+ "@coldsmirk/inkstone-react": "^0.26.0"
50
54
  },
51
55
  "peerDependencies": {
56
+ "@codemirror/autocomplete": "^6.20.3",
57
+ "@codemirror/lint": "^6.9.7",
58
+ "@codemirror/state": "^6.6.0",
59
+ "@codemirror/view": "^6.43.0",
52
60
  "monaco-editor": "^0.56.0",
53
61
  "react": ">=19",
54
- "@coldsmirk/inkstone-react": "^0.25.0"
62
+ "@coldsmirk/inkstone-react": "^0.26.0"
55
63
  },
56
64
  "peerDependenciesMeta": {
65
+ "@codemirror/autocomplete": {
66
+ "optional": true
67
+ },
68
+ "@codemirror/lint": {
69
+ "optional": true
70
+ },
71
+ "@codemirror/state": {
72
+ "optional": true
73
+ },
74
+ "@codemirror/view": {
75
+ "optional": true
76
+ },
57
77
  "@coldsmirk/inkstone-react": {
58
78
  "optional": true
59
79
  },