@testsmith/api-spector 0.7.6 → 0.7.8

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 (31) hide show
  1. package/bin/cli.js +4 -0
  2. package/out/main/chunks/{broker-client-5IyCTx40.js → broker-client-BYpWeOWT.js} +4 -1
  3. package/out/main/chunks/{flow-engine-BVzjz4lJ.js → flow-engine-BxwjEy37.js} +66 -1
  4. package/out/main/chunks/{handle-DRmKOL-s.js → handle-Crv1i9hb.js} +61 -0
  5. package/out/main/chunks/{import-B5T5wDu7.js → import-DTcZMRNu.js} +2 -2
  6. package/out/main/chunks/perf-report-ChaO3K0w.js +124 -0
  7. package/out/main/chunks/perf-run-uZBqnG3S.js +578 -0
  8. package/out/main/chunks/{request-collection-KGPuvN7o.js → request-collection-gkOYlWml.js} +68 -11
  9. package/out/main/chunks/{request-exec-CwJ8_OKC.js → request-exec-Cv2jkrO1.js} +458 -12
  10. package/out/main/chunks/run-concurrent-468tH0AX.js +26 -0
  11. package/out/main/chunks/{soap-handler-DTfFnzNY.js → soap-handler-Brr7BPWO.js} +2 -2
  12. package/out/main/contract.js +6 -3
  13. package/out/main/flow.js +8 -5
  14. package/out/main/index.js +1338 -179
  15. package/out/main/lib.js +6 -3
  16. package/out/main/perf-worker.js +45 -0
  17. package/out/main/perf.js +253 -0
  18. package/out/main/runner.js +181 -7
  19. package/out/main/socketio.js +172 -0
  20. package/out/main/wsdl.js +3 -3
  21. package/out/preload/index.js +127 -0
  22. package/out/renderer/assets/{GraphQLEditor-CDLI1OHR.js → GraphQLEditor-Dv2K4wdd.js} +59 -14
  23. package/out/renderer/assets/{SoapEditor-CSUFJk7c.js → SoapEditor-Cnz3M4Dz.js} +3 -3
  24. package/out/renderer/assets/ajv-CJPwFjiP.js +6718 -0
  25. package/out/renderer/assets/{codemirror-F6m3Hm1M.js → codemirror-CdIFBPs2.js} +1214 -1207
  26. package/out/renderer/assets/{index-8bbf24uI.js → index-CtCdFiRx.js} +16957 -13834
  27. package/out/renderer/assets/index-DkhdKzQJ.css +627 -0
  28. package/out/renderer/index.html +4 -4
  29. package/package.json +12 -6
  30. package/out/renderer/assets/ajv-2MAg6kGF.js +0 -6153
  31. package/out/renderer/assets/index-CYArpqm5.css +0 -627
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ const socket_ioClient = require("socket.io-client");
4
+ const cliCommon = require("./chunks/cli-common-GnihVSjU.js");
5
+ require("node:fs/promises");
6
+ require("node:path");
7
+ require("./chunks/data-files-BYqhsoPe.js");
8
+ require("node:crypto");
9
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
10
+ function printHelp() {
11
+ console.log(`
12
+ API Spector - Socket.IO
13
+
14
+ api-spector socketio --url <url> [--namespace /ns] [--auth '{"token":"x"}']
15
+ [--header K:V] [--emit 'event:[args]'] [--ack]
16
+ [--listen <seconds>] [--json]
17
+ api-spector socketio --workspace <path> --request <name> [same options]
18
+ `);
19
+ }
20
+ function jsonText(value) {
21
+ try {
22
+ return JSON.stringify(value);
23
+ } catch {
24
+ return String(value);
25
+ }
26
+ }
27
+ function targetUrl(url, namespace) {
28
+ const ns = (namespace ?? "").trim();
29
+ if (!ns || ns === "/") return url;
30
+ return url.replace(/\/+$/, "") + (ns.startsWith("/") ? ns : `/${ns}`);
31
+ }
32
+ function parseEmit(spec) {
33
+ const i = spec.indexOf(":");
34
+ if (i === -1) return { event: spec, args: [] };
35
+ const event = spec.slice(0, i);
36
+ const rest = spec.slice(i + 1).trim();
37
+ if (!rest) return { event, args: [] };
38
+ let parsed;
39
+ try {
40
+ parsed = JSON.parse(rest);
41
+ } catch {
42
+ throw new Error(`--emit "${spec}": arguments after ':' must be JSON`);
43
+ }
44
+ return { event, args: Array.isArray(parsed) ? parsed : [parsed] };
45
+ }
46
+ async function sourceFromWorkspace(wsPath, name) {
47
+ const { workspace, dir } = await cliCommon.loadWorkspace(wsPath);
48
+ const collections = await cliCommon.loadCollections(workspace, dir);
49
+ let found;
50
+ for (const col of collections) {
51
+ for (const req of Object.values(col.requests)) {
52
+ if (req.name === name) {
53
+ found = req;
54
+ break;
55
+ }
56
+ }
57
+ if (found) break;
58
+ }
59
+ if (!found) throw new Error(`Request "${name}" not found in the workspace`);
60
+ const headers = {};
61
+ for (const h of found.headers ?? []) if (h.enabled && h.key) headers[h.key] = h.value;
62
+ return { url: found.url, headers, namespace: found.socketio?.namespace, auth: found.socketio?.auth };
63
+ }
64
+ async function main() {
65
+ const args = cliCommon.parseArgs(process.argv.slice(2), ["emit", "header"]);
66
+ if (args.help || args.h) {
67
+ printHelp();
68
+ return;
69
+ }
70
+ let url = typeof args.url === "string" ? args.url : "";
71
+ let headers = {};
72
+ let namespace = typeof args.namespace === "string" ? args.namespace : void 0;
73
+ let auth = typeof args.auth === "string" ? args.auth : void 0;
74
+ if (typeof args.workspace === "string" && typeof args.request === "string") {
75
+ const src = await sourceFromWorkspace(args.workspace, args.request);
76
+ url = url || src.url;
77
+ headers = { ...src.headers };
78
+ namespace = namespace ?? src.namespace;
79
+ auth = auth ?? src.auth;
80
+ }
81
+ const headerList = Array.isArray(args.header) ? args.header : typeof args.header === "string" ? [args.header] : [];
82
+ for (const h of headerList) {
83
+ const idx = h.indexOf(":");
84
+ if (idx > 0) headers[h.slice(0, idx).trim()] = h.slice(idx + 1).trim();
85
+ }
86
+ if (!url) {
87
+ console.error(cliCommon.color(" [error] Provide --url, or --workspace with --request.", cliCommon.C.red));
88
+ printHelp();
89
+ process.exit(1);
90
+ }
91
+ let authObj;
92
+ if (auth && auth.trim()) {
93
+ try {
94
+ authObj = JSON.parse(auth);
95
+ } catch {
96
+ console.error(cliCommon.color(" [error] --auth is not valid JSON", cliCommon.C.red));
97
+ process.exit(1);
98
+ }
99
+ }
100
+ const emits = (Array.isArray(args.emit) ? args.emit : typeof args.emit === "string" ? [args.emit] : []).map(parseEmit);
101
+ const listenMs = Math.round((typeof args.listen === "string" ? Number(args.listen) : 5) * 1e3) || 5e3;
102
+ const asJson = Boolean(args.json);
103
+ const ack = Boolean(args.ack);
104
+ const received = [];
105
+ const log = (s) => {
106
+ if (!asJson) console.log(s);
107
+ };
108
+ if (!asJson) {
109
+ console.log("");
110
+ console.log(` ${cliCommon.color("Socket.IO", cliCommon.C.bold)} ${cliCommon.color(targetUrl(url, namespace), cliCommon.C.dim)}`);
111
+ }
112
+ const socket = socket_ioClient.io(targetUrl(url, namespace), {
113
+ path: typeof args.path === "string" ? args.path : "/socket.io",
114
+ transports: ["websocket", "polling"],
115
+ extraHeaders: headers,
116
+ auth: authObj,
117
+ forceNew: true,
118
+ reconnection: false
119
+ });
120
+ socket.onAny((event, ...a) => {
121
+ received.push({ at: Date.now(), event, args: a });
122
+ log(` ${cliCommon.color("←", cliCommon.C.green)} ${cliCommon.color(event, cliCommon.C.bold)} ${cliCommon.color(jsonText(a), cliCommon.C.dim)}`);
123
+ });
124
+ await new Promise((resolve, reject) => {
125
+ socket.on("connect_error", (err) => reject(err));
126
+ socket.on("connect", async () => {
127
+ log(` ${cliCommon.color("connected", cliCommon.C.green)} ${cliCommon.color(`(id ${socket.id})`, cliCommon.C.dim)}`);
128
+ for (const { event, args: emitArgs } of emits) {
129
+ if (ack) {
130
+ try {
131
+ const resp = await socket.timeout(5e3).emitWithAck(event, ...emitArgs);
132
+ log(` ${cliCommon.color("→", cliCommon.C.cyan)} ${cliCommon.color(event, cliCommon.C.bold)} ${cliCommon.color(jsonText(emitArgs), cliCommon.C.dim)} ${cliCommon.color("ack", cliCommon.C.green)} ${cliCommon.color(jsonText(resp), cliCommon.C.dim)}`);
133
+ } catch {
134
+ log(` ${cliCommon.color("→", cliCommon.C.cyan)} ${cliCommon.color(event, cliCommon.C.bold)} ${cliCommon.color(jsonText(emitArgs), cliCommon.C.dim)} ${cliCommon.color("(no ack)", cliCommon.C.yellow)}`);
135
+ }
136
+ } else {
137
+ socket.emit(event, ...emitArgs);
138
+ log(` ${cliCommon.color("→", cliCommon.C.cyan)} ${cliCommon.color(event, cliCommon.C.bold)} ${cliCommon.color(jsonText(emitArgs), cliCommon.C.dim)}`);
139
+ }
140
+ }
141
+ if (listenMs > 0) {
142
+ log(cliCommon.color(` listening for ${listenMs / 1e3}s…`, cliCommon.C.dim));
143
+ await sleep(listenMs);
144
+ }
145
+ resolve();
146
+ });
147
+ }).catch((err) => {
148
+ socket.close();
149
+ if (asJson) console.log(JSON.stringify({ url, namespace: namespace ?? "/", connected: false, error: err.message }, null, 2));
150
+ else console.error(cliCommon.color(` [error] Connection failed: ${err.message}`, cliCommon.C.red));
151
+ process.exit(1);
152
+ });
153
+ socket.disconnect();
154
+ if (asJson) {
155
+ console.log(JSON.stringify({
156
+ url,
157
+ namespace: namespace ?? "/",
158
+ connected: true,
159
+ emitted: emits.map((e) => ({ event: e.event, args: e.args })),
160
+ received: received.map((r) => ({ event: r.event, args: r.args }))
161
+ }, null, 2));
162
+ } else {
163
+ console.log("");
164
+ console.log(` ${cliCommon.color(String(received.length), cliCommon.C.bold)} event(s) received, ${emits.length} emitted.`);
165
+ console.log("");
166
+ }
167
+ process.exit(0);
168
+ }
169
+ main().catch((err) => {
170
+ console.error(cliCommon.color(` [error] ${err instanceof Error ? err.message : String(err)}`, cliCommon.C.red));
171
+ process.exit(1);
172
+ });
package/out/main/wsdl.js CHANGED
@@ -4,10 +4,10 @@ const promises = require("node:fs/promises");
4
4
  const path = require("node:path");
5
5
  const https = require("node:https");
6
6
  const http = require("node:http");
7
- const soapHandler = require("./chunks/soap-handler-DTfFnzNY.js");
8
- const _import = require("./chunks/import-B5T5wDu7.js");
7
+ const soapHandler = require("./chunks/soap-handler-Brr7BPWO.js");
8
+ const _import = require("./chunks/import-DTcZMRNu.js");
9
9
  const cliCommon = require("./chunks/cli-common-GnihVSjU.js");
10
- require("./chunks/handle-DRmKOL-s.js");
10
+ require("./chunks/handle-Crv1i9hb.js");
11
11
  require("@xmldom/xmldom");
12
12
  require("uuid");
13
13
  require("./chunks/data-files-BYqhsoPe.js");
@@ -42,6 +42,7 @@ const IPC = {
42
42
  secret: {
43
43
  checkMasterKey: "secret:checkMasterKey",
44
44
  setMasterKey: "secret:setMasterKey",
45
+ encryptWithMasterKey: "secret:encryptWithMasterKey",
45
46
  set: "secret:set",
46
47
  has: "secret:has",
47
48
  delete: "secret:delete"
@@ -80,6 +81,8 @@ const IPC = {
80
81
  insomnia: "import:insomnia",
81
82
  bruno: "import:bruno",
82
83
  http: "import:http",
84
+ har: "import:har",
85
+ arazzo: "import:arazzo",
83
86
  spector: "import:spector",
84
87
  openapiSchemas: "import:openapi-schemas",
85
88
  openapiSchemasUrl: "import:openapi-schemas-url"
@@ -114,11 +117,69 @@ const IPC = {
114
117
  connect: "ws:connect",
115
118
  send: "ws:send",
116
119
  disconnect: "ws:disconnect",
120
+ /** Run a WebSocket request as a test: connect, optionally send, collect for
121
+ * a window, then assert over the received frames. */
122
+ test: "ws:test",
117
123
  /** Event: inbound/outbound WS message. */
118
124
  message: "ws:message",
119
125
  /** Event: connection status change. */
120
126
  status: "ws:status"
121
127
  },
128
+ // ─── jq (JSON response filtering) ───────────────────────────────────────────
129
+ jq: {
130
+ filter: "jq:filter"
131
+ },
132
+ // ─── GraphQL subscriptions (graphql-ws) ─────────────────────────────────────
133
+ graphqlws: {
134
+ subscribe: "graphqlws:subscribe",
135
+ stop: "graphqlws:stop",
136
+ /** Run a GraphQL subscription as a test: subscribe, collect the emitted
137
+ * payloads for a window, then assert over them. */
138
+ test: "graphqlws:test",
139
+ /** Event: a next / error / complete / system message. */
140
+ message: "graphqlws:message",
141
+ /** Event: connection status change. */
142
+ status: "graphqlws:status"
143
+ },
144
+ // ─── Socket.IO ─────────────────────────────────────────────────────────────
145
+ socketio: {
146
+ connect: "socketio:connect",
147
+ emit: "socketio:emit",
148
+ disconnect: "socketio:disconnect",
149
+ /** Run a Socket.IO request as a test: connect, optionally emit, collect the
150
+ * received events for a window, then assert over them. */
151
+ test: "socketio:test",
152
+ /** Event: inbound/outbound Socket.IO event, ack, or system note. */
153
+ message: "socketio:message",
154
+ /** Event: connection status change. */
155
+ status: "socketio:status"
156
+ },
157
+ // ─── MQTT ──────────────────────────────────────────────────────────────────
158
+ mqtt: {
159
+ connect: "mqtt:connect",
160
+ publish: "mqtt:publish",
161
+ subscribe: "mqtt:subscribe",
162
+ unsubscribe: "mqtt:unsubscribe",
163
+ disconnect: "mqtt:disconnect",
164
+ /** Run an MQTT request as a test: connect, subscribe, optionally publish,
165
+ * collect for a window, then assert over the messages. */
166
+ test: "mqtt:test",
167
+ /** Event: a published / received message, or a system note. */
168
+ message: "mqtt:message",
169
+ /** Event: connection status change. */
170
+ status: "mqtt:status"
171
+ },
172
+ // ─── Performance (load) testing ─────────────────────────────────────────────
173
+ perf: {
174
+ /** Run a load test for a request; resolves with the aggregate result. */
175
+ run: "perf:run",
176
+ /** Abort the active run early. */
177
+ stop: "perf:stop",
178
+ /** Export a finished run as a self-contained HTML report (save dialog). */
179
+ exportHtml: "perf:exportHtml",
180
+ /** Event: live progress while a run is in flight. */
181
+ progress: "perf:progress"
182
+ },
122
183
  // ─── SOAP / WSDL ───────────────────────────────────────────────────────────
123
184
  wsdl: {
124
185
  fetch: "wsdl:fetch",
@@ -279,6 +340,9 @@ const api = {
279
340
  // ─── Secrets (encrypted, master-key-based) ───────────────────────────────
280
341
  checkMasterKey: () => electron.ipcRenderer.invoke(IPC.secret.checkMasterKey),
281
342
  setMasterKey: (value) => electron.ipcRenderer.invoke(IPC.secret.setMasterKey, value),
343
+ /** Encrypt a secret in the main process with the master key already set there
344
+ * (API_SPECTOR_MASTER_KEY) — no password prompt needed. */
345
+ encryptWithMasterKey: (plaintext) => electron.ipcRenderer.invoke(IPC.secret.encryptWithMasterKey, plaintext),
282
346
  /** Save a named secret to the OS keychain (safeStorage). */
283
347
  setSecret: (ref, value) => electron.ipcRenderer.invoke(IPC.secret.set, ref, value),
284
348
  /** Whether a secret exists (never returns the value itself). */
@@ -315,6 +379,10 @@ const api = {
315
379
  importInsomnia: () => electron.ipcRenderer.invoke(IPC.import.insomnia),
316
380
  importBruno: () => electron.ipcRenderer.invoke(IPC.import.bruno),
317
381
  importHttpFile: () => electron.ipcRenderer.invoke(IPC.import.http),
382
+ importHar: () => electron.ipcRenderer.invoke(IPC.import.har),
383
+ /** Import an Arazzo workflow doc: builds a collection (from its OpenAPI
384
+ * sources) plus one Flow per workflow, with any translation warnings. */
385
+ importArazzo: () => electron.ipcRenderer.invoke(IPC.import.arazzo),
318
386
  importSpectorCollection: () => electron.ipcRenderer.invoke(IPC.import.spector),
319
387
  /** Extract response-body schemas from an OpenAPI spec file (no full import). */
320
388
  extractOpenApiSchemas: () => electron.ipcRenderer.invoke(IPC.import.openapiSchemas),
@@ -373,6 +441,65 @@ const api = {
373
441
  electron.ipcRenderer.removeAllListeners(IPC.ws.message);
374
442
  electron.ipcRenderer.removeAllListeners(IPC.ws.status);
375
443
  },
444
+ wsTest: (cfg) => electron.ipcRenderer.invoke(IPC.ws.test, cfg),
445
+ // ─── Socket.IO ────────────────────────────────────────────────────────────
446
+ socketIoConnect: (requestId, opts) => electron.ipcRenderer.invoke(IPC.socketio.connect, requestId, opts),
447
+ socketIoEmit: (requestId, opts) => electron.ipcRenderer.invoke(IPC.socketio.emit, requestId, opts),
448
+ socketIoDisconnect: (requestId) => electron.ipcRenderer.invoke(IPC.socketio.disconnect, requestId),
449
+ onSocketIoMessage: (cb) => {
450
+ electron.ipcRenderer.on(IPC.socketio.message, (_e, payload) => cb(payload));
451
+ },
452
+ onSocketIoStatus: (cb) => {
453
+ electron.ipcRenderer.on(IPC.socketio.status, (_e, payload) => cb(payload));
454
+ },
455
+ offSocketIoEvents: () => {
456
+ electron.ipcRenderer.removeAllListeners(IPC.socketio.message);
457
+ electron.ipcRenderer.removeAllListeners(IPC.socketio.status);
458
+ },
459
+ socketIoTest: (cfg) => electron.ipcRenderer.invoke(IPC.socketio.test, cfg),
460
+ // ─── jq (JSON response filtering) ─────────────────────────────────────────
461
+ jqFilter: (json, filter) => electron.ipcRenderer.invoke(IPC.jq.filter, json, filter),
462
+ // ─── GraphQL subscriptions (graphql-ws) ───────────────────────────────────
463
+ graphqlWsSubscribe: (requestId, opts) => electron.ipcRenderer.invoke(IPC.graphqlws.subscribe, requestId, opts),
464
+ graphqlWsStop: (requestId) => electron.ipcRenderer.invoke(IPC.graphqlws.stop, requestId),
465
+ onGraphqlWsMessage: (cb) => {
466
+ electron.ipcRenderer.on(IPC.graphqlws.message, (_e, payload) => cb(payload));
467
+ },
468
+ onGraphqlWsStatus: (cb) => {
469
+ electron.ipcRenderer.on(IPC.graphqlws.status, (_e, payload) => cb(payload));
470
+ },
471
+ offGraphqlWsEvents: () => {
472
+ electron.ipcRenderer.removeAllListeners(IPC.graphqlws.message);
473
+ electron.ipcRenderer.removeAllListeners(IPC.graphqlws.status);
474
+ },
475
+ graphqlWsTest: (cfg) => electron.ipcRenderer.invoke(IPC.graphqlws.test, cfg),
476
+ // ─── MQTT ──────────────────────────────────────────────────────────────────
477
+ mqttConnect: (requestId, opts) => electron.ipcRenderer.invoke(IPC.mqtt.connect, requestId, opts),
478
+ mqttPublish: (requestId, opts) => electron.ipcRenderer.invoke(IPC.mqtt.publish, requestId, opts),
479
+ mqttSubscribe: (requestId, opts) => electron.ipcRenderer.invoke(IPC.mqtt.subscribe, requestId, opts),
480
+ mqttUnsubscribe: (requestId, opts) => electron.ipcRenderer.invoke(IPC.mqtt.unsubscribe, requestId, opts),
481
+ mqttDisconnect: (requestId) => electron.ipcRenderer.invoke(IPC.mqtt.disconnect, requestId),
482
+ mqttTest: (cfg) => electron.ipcRenderer.invoke(IPC.mqtt.test, cfg),
483
+ onMqttMessage: (cb) => {
484
+ electron.ipcRenderer.on(IPC.mqtt.message, (_e, payload) => cb(payload));
485
+ },
486
+ onMqttStatus: (cb) => {
487
+ electron.ipcRenderer.on(IPC.mqtt.status, (_e, payload) => cb(payload));
488
+ },
489
+ offMqttEvents: () => {
490
+ electron.ipcRenderer.removeAllListeners(IPC.mqtt.message);
491
+ electron.ipcRenderer.removeAllListeners(IPC.mqtt.status);
492
+ },
493
+ // ─── Performance (load) testing ─────────────────────────────────────────────
494
+ perfRun: (payload) => electron.ipcRenderer.invoke(IPC.perf.run, payload),
495
+ perfStop: () => electron.ipcRenderer.invoke(IPC.perf.stop),
496
+ perfExportHtml: (result, meta) => electron.ipcRenderer.invoke(IPC.perf.exportHtml, result, meta),
497
+ onPerfProgress: (cb) => {
498
+ electron.ipcRenderer.on(IPC.perf.progress, (_e, payload) => cb(payload));
499
+ },
500
+ offPerfEvents: () => {
501
+ electron.ipcRenderer.removeAllListeners(IPC.perf.progress);
502
+ },
376
503
  // ─── gRPC ─────────────────────────────────────────────────────────────────
377
504
  grpcLoadProto: (src) => electron.ipcRenderer.invoke(IPC.grpc.loadProto, src),
378
505
  grpcInvoke: (requestId, opts) => electron.ipcRenderer.invoke(IPC.grpc.invoke, requestId, opts),
@@ -1,6 +1,6 @@
1
- import { l as linter, E as EditorView, L as LanguageSupport, e as LRLanguage, s as styleTags, i as indentNodeProp, f as delimitedIndent, m as foldNodeProp, n as foldInside, S as StateField, p as LRParser, q as StateEffect, u as tags, r as reactExports, j as jsxRuntimeExports, c as ReactCodeMirror, o as oneDark, b as json } from "./codemirror-F6m3Hm1M.js";
2
- import { u as useT, a as useStore, b as useActiveEnvironment } from "./index-8bbf24uI.js";
3
- import "./ajv-2MAg6kGF.js";
1
+ import { l as linter, E as EditorView, L as LanguageSupport, f as LRLanguage, s as styleTags, i as indentNodeProp, m as delimitedIndent, n as foldNodeProp, p as foldInside, S as StateField, q as LRParser, u as StateEffect, v as tags, a as reactExports, j as jsxRuntimeExports, d as ReactCodeMirror, o as oneDark, c as json } from "./codemirror-CdIFBPs2.js";
2
+ import { u as useT, a as useStore, b as useActiveEnvironment, i as isSubscriptionQuery } from "./index-CtCdFiRx.js";
3
+ import "./ajv-CJPwFjiP.js";
4
4
  function devAssert(condition, message) {
5
5
  const booleanCondition = Boolean(condition);
6
6
  if (!booleanCondition) {
@@ -673,12 +673,33 @@ function readNextToken(lexer, start) {
673
673
  while (position < bodyLength) {
674
674
  const code = body.charCodeAt(position);
675
675
  switch (code) {
676
+ // Ignored ::
677
+ // - UnicodeBOM
678
+ // - WhiteSpace
679
+ // - LineTerminator
680
+ // - Comment
681
+ // - Comma
682
+ //
683
+ // UnicodeBOM :: "Byte Order Mark (U+FEFF)"
684
+ //
685
+ // WhiteSpace ::
686
+ // - "Horizontal Tab (U+0009)"
687
+ // - "Space (U+0020)"
688
+ //
689
+ // Comma :: ,
676
690
  case 65279:
691
+ // <BOM>
677
692
  case 9:
693
+ // \t
678
694
  case 32:
695
+ // <space>
679
696
  case 44:
680
697
  ++position;
681
698
  continue;
699
+ // LineTerminator ::
700
+ // - "New Line (U+000A)"
701
+ // - "Carriage Return (U+000D)" [lookahead != "New Line (U+000A)"]
702
+ // - "Carriage Return (U+000D)" "New Line (U+000A)"
682
703
  case 10:
683
704
  ++position;
684
705
  ++lexer.line;
@@ -693,8 +714,17 @@ function readNextToken(lexer, start) {
693
714
  ++lexer.line;
694
715
  lexer.lineStart = position;
695
716
  continue;
717
+ // Comment
696
718
  case 35:
697
719
  return readComment(lexer, position);
720
+ // Token ::
721
+ // - Punctuator
722
+ // - Name
723
+ // - IntValue
724
+ // - FloatValue
725
+ // - StringValue
726
+ //
727
+ // Punctuator :: one of ! $ & ( ) ... : = @ [ ] { | }
698
728
  case 33:
699
729
  return createToken(lexer, TokenKind.BANG, position, position + 1);
700
730
  case 36:
@@ -726,6 +756,7 @@ function readNextToken(lexer, start) {
726
756
  return createToken(lexer, TokenKind.PIPE, position, position + 1);
727
757
  case 125:
728
758
  return createToken(lexer, TokenKind.BRACE_R, position, position + 1);
759
+ // StringValue
729
760
  case 34:
730
761
  if (body.charCodeAt(position + 1) === 34 && body.charCodeAt(position + 2) === 34) {
731
762
  return readBlockString(lexer, position);
@@ -6221,6 +6252,8 @@ function getDirectiveLocationForASTPath(ancestors) {
6221
6252
  "kind" in parentNode || invariant$1(false);
6222
6253
  return parentNode.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION ? DirectiveLocation.INPUT_FIELD_DEFINITION : DirectiveLocation.ARGUMENT_DEFINITION;
6223
6254
  }
6255
+ // Not reachable, all possible types have been considered.
6256
+ /* c8 ignore next */
6224
6257
  default:
6225
6258
  invariant$1(false, "Unexpected kind: " + inspect(appliedTo.kind));
6226
6259
  }
@@ -11340,18 +11373,25 @@ function unwrapType(state) {
11340
11373
  }
11341
11374
  return state;
11342
11375
  }
11343
- var nullthrows$1 = { exports: {} };
11344
- function nullthrows(x, message) {
11345
- if (x != null) {
11346
- return x;
11376
+ var nullthrows = { exports: {} };
11377
+ var hasRequiredNullthrows;
11378
+ function requireNullthrows() {
11379
+ if (hasRequiredNullthrows) return nullthrows.exports;
11380
+ hasRequiredNullthrows = 1;
11381
+ function nullthrows$1(x, message) {
11382
+ if (x != null) {
11383
+ return x;
11384
+ }
11385
+ var error = new Error(message !== void 0 ? message : "Got unexpected " + x);
11386
+ error.framesToPop = 1;
11387
+ throw error;
11347
11388
  }
11348
- var error = new Error(message !== void 0 ? message : "Got unexpected " + x);
11349
- error.framesToPop = 1;
11350
- throw error;
11389
+ nullthrows.exports = nullthrows$1;
11390
+ nullthrows.exports.default = nullthrows$1;
11391
+ Object.defineProperty(nullthrows.exports, "__esModule", { value: true });
11392
+ return nullthrows.exports;
11351
11393
  }
11352
- nullthrows$1.exports = nullthrows;
11353
- nullthrows$1.exports.default = nullthrows;
11354
- Object.defineProperty(nullthrows$1.exports, "__esModule", { value: true });
11394
+ requireNullthrows();
11355
11395
  class Range {
11356
11396
  constructor(start, end) {
11357
11397
  this.containsPosition = (position) => {
@@ -12397,7 +12437,12 @@ function GraphQLEditor({ request, onChange }) {
12397
12437
  basicSetup: { lineNumbers: false, foldGutter: false }
12398
12438
  }
12399
12439
  ) })
12400
- ] })
12440
+ ] }),
12441
+ isSubscriptionQuery(gql.query) && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-shrink-0 border-t border-surface-800 pt-2 mt-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[10px] text-surface-600", children: [
12442
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-fuchsia-300 uppercase tracking-wider font-medium", children: t2("Subscription") }),
12443
+ " — ",
12444
+ t2("run it to stream the results and tests in the Response pane.")
12445
+ ] }) })
12401
12446
  ] })
12402
12447
  ] })
12403
12448
  ] });
@@ -1,6 +1,6 @@
1
- import { r as reactExports, j as jsxRuntimeExports, c as ReactCodeMirror, o as oneDark, x as xml } from "./codemirror-F6m3Hm1M.js";
2
- import { u as useT, c as btnPrimaryCls, d as commentKeymap } from "./index-8bbf24uI.js";
3
- import "./ajv-2MAg6kGF.js";
1
+ import { a as reactExports, j as jsxRuntimeExports, d as ReactCodeMirror, o as oneDark, x as xml } from "./codemirror-CdIFBPs2.js";
2
+ import { u as useT, c as btnPrimaryCls, d as commentKeymap } from "./index-CtCdFiRx.js";
3
+ import "./ajv-CJPwFjiP.js";
4
4
  const SOAP_11_CONTENT_TYPE = "text/xml; charset=utf-8";
5
5
  const SOAP_12_CONTENT_TYPE = "application/soap+xml; charset=utf-8";
6
6
  function contentTypeForSoap(version) {