@sanity/runtime-cli 1.6.0 → 1.8.1

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 (57) hide show
  1. package/README.md +184 -122
  2. package/dist/actions/blueprints/blueprint.d.ts +24 -7
  3. package/dist/actions/blueprints/blueprint.js +65 -44
  4. package/dist/actions/blueprints/logs.d.ts +3 -0
  5. package/dist/actions/blueprints/logs.js +24 -0
  6. package/dist/actions/blueprints/projects.d.ts +5 -0
  7. package/dist/actions/blueprints/projects.js +21 -0
  8. package/dist/actions/blueprints/resources.d.ts +13 -0
  9. package/dist/actions/blueprints/resources.js +37 -0
  10. package/dist/actions/blueprints/stacks.js +1 -1
  11. package/dist/commands/blueprints/add.d.ts +10 -0
  12. package/dist/commands/blueprints/add.js +67 -0
  13. package/dist/commands/blueprints/config.d.ts +9 -0
  14. package/dist/commands/blueprints/config.js +72 -0
  15. package/dist/commands/blueprints/deploy.js +13 -12
  16. package/dist/commands/blueprints/info.js +1 -1
  17. package/dist/commands/blueprints/init.d.ts +6 -0
  18. package/dist/commands/blueprints/init.js +56 -0
  19. package/dist/commands/blueprints/logs.js +24 -64
  20. package/dist/commands/blueprints/stacks.js +3 -15
  21. package/dist/commands/functions/invoke.d.ts +1 -1
  22. package/dist/commands/functions/invoke.js +9 -7
  23. package/dist/commands/functions/logs.d.ts +1 -1
  24. package/dist/commands/functions/logs.js +21 -12
  25. package/dist/commands/functions/test.d.ts +1 -1
  26. package/dist/commands/functions/test.js +25 -16
  27. package/dist/config.d.ts +1 -0
  28. package/dist/config.js +12 -5
  29. package/dist/server/app.js +2 -2
  30. package/dist/server/static/api.js +43 -38
  31. package/dist/server/static/components/api-base.js +7 -6
  32. package/dist/server/static/components/function-list.js +48 -44
  33. package/dist/server/static/components/network-spinner.js +7 -6
  34. package/dist/server/static/components/payload-panel.js +36 -32
  35. package/dist/server/static/components/response-panel.js +64 -50
  36. package/dist/server/static/vendor/vendor.bundle.js +1029 -913
  37. package/dist/utils/display/blueprints-formatting.d.ts +3 -1
  38. package/dist/utils/display/blueprints-formatting.js +27 -2
  39. package/dist/utils/display/logs-formatting.d.ts +5 -0
  40. package/dist/utils/display/logs-formatting.js +50 -0
  41. package/dist/utils/find-function.d.ts +2 -0
  42. package/dist/utils/find-function.js +6 -0
  43. package/dist/utils/types.d.ts +0 -1
  44. package/oclif.manifest.json +102 -13
  45. package/package.json +10 -10
  46. package/dist/server/static/static/api.js +0 -53
  47. package/dist/server/static/static/components/api-base.js +0 -10
  48. package/dist/server/static/static/components/function-list.js +0 -54
  49. package/dist/server/static/static/components/network-spinner.js +0 -71
  50. package/dist/server/static/static/components/payload-panel.js +0 -45
  51. package/dist/server/static/static/components/response-panel.js +0 -83
  52. package/dist/server/static/static/vendor/vendor.bundle.js +0 -26879
  53. package/dist/utils/spinner.d.ts +0 -9
  54. package/dist/utils/spinner.js +0 -25
  55. /package/dist/server/static/{static/components → components}/app.css +0 -0
  56. /package/dist/server/static/{static/index.html → index.html} +0 -0
  57. /package/dist/server/static/{static/sanity-logo-sm.svg → sanity-logo-sm.svg} +0 -0
@@ -1,4 +1,6 @@
1
- import type { BlueprintResource } from '../types.js';
1
+ import type { BlueprintResource, BlueprintStack } from '../types.js';
2
2
  export declare function formatTitle(title: string, name: string): string;
3
3
  export declare function formatStacksList(stacks: string[]): string;
4
4
  export declare function formatResourceTree(resources: BlueprintResource[], logger: (msg: string) => void): void;
5
+ export declare function formatStackInfo(stack: BlueprintStack, isCurrentStack?: boolean): string;
6
+ export declare function formatStacksListing(stacks: BlueprintStack[], currentStackId?: string): string;
@@ -1,4 +1,5 @@
1
1
  import { blue, bold, boldnblue, green, yellow } from './colors.js';
2
+ import { formatDate } from './dates.js';
2
3
  export function formatTitle(title, name) {
3
4
  return `${boldnblue(title)} ${bold(`"${name}"`)}`;
4
5
  }
@@ -18,8 +19,8 @@ export function formatResourceTree(resources, logger) {
18
19
  return;
19
20
  }
20
21
  logger(`${blue('Stack Resources')} [${resources.length}]`);
21
- const functionResources = resources.filter((r) => r.type?.startsWith('sanity.function.') || r.kind === 'function');
22
- const otherResources = resources.filter((r) => !r.type?.startsWith('sanity.function.') && r.kind !== 'function');
22
+ const functionResources = resources.filter((r) => r.type?.startsWith('sanity.function.'));
23
+ const otherResources = resources.filter((r) => !r.type?.startsWith('sanity.function.'));
23
24
  const hasOtherResources = otherResources.length > 0;
24
25
  if (functionResources.length > 0) {
25
26
  logger(` ${hasOtherResources ? '├─' : '└─'} ${bold('Functions')} [${functionResources.length}]`);
@@ -40,3 +41,27 @@ export function formatResourceTree(resources, logger) {
40
41
  }
41
42
  }
42
43
  }
44
+ export function formatStackInfo(stack, isCurrentStack = false) {
45
+ let result = '';
46
+ const stackName = isCurrentStack ? boldnblue(stack.name) : bold(stack.name);
47
+ result += `${stackName} <${yellow(stack.id)}>${isCurrentStack ? ' (current)' : ''}\n`;
48
+ if (stack.createdAt) {
49
+ result += ` Created: ${formatDate(stack.createdAt)}\n`;
50
+ }
51
+ if (stack.updatedAt) {
52
+ result += ` Updated: ${formatDate(stack.updatedAt)}\n`;
53
+ }
54
+ result += ` ${stack.resources.length} resource${stack.resources.length === 1 ? '' : 's'}\n\n`;
55
+ return result;
56
+ }
57
+ export function formatStacksListing(stacks, currentStackId) {
58
+ if (!stacks || stacks.length === 0) {
59
+ return 'No stacks found';
60
+ }
61
+ let result = '';
62
+ for (const stack of stacks) {
63
+ const isCurrentStack = currentStackId === stack.id;
64
+ result += formatStackInfo(stack, isCurrentStack);
65
+ }
66
+ return result;
67
+ }
@@ -0,0 +1,5 @@
1
+ import type { BlueprintLog } from '../types.js';
2
+ export declare function formatLogEntry(log: BlueprintLog, isNewest?: boolean): string;
3
+ export declare function formatRecentLogs(logs: BlueprintLog[]): string;
4
+ export declare function organizeLogsByDay(logs: BlueprintLog[]): Map<string, BlueprintLog[]>;
5
+ export declare function formatLogsByDay(logsByDay: Map<string, BlueprintLog[]>): string;
@@ -0,0 +1,50 @@
1
+ import { blue, bold, green, yellow } from './colors.js';
2
+ export function formatLogEntry(log, isNewest = false) {
3
+ const date = new Date(log.timestamp);
4
+ const time = date.toLocaleTimeString();
5
+ const day = date.toLocaleDateString();
6
+ return `${isNewest ? `${green('>')} ` : ''}${bold(day)} ${yellow(time)} ${log.message}`;
7
+ }
8
+ export function formatRecentLogs(logs) {
9
+ if (logs.length === 0)
10
+ return 'No recent logs found';
11
+ const sortedLogs = [...logs].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
12
+ const recentLogs = sortedLogs.slice(-10);
13
+ let result = '\nMost recent logs:\n';
14
+ for (const log of recentLogs) {
15
+ result += ` ${formatLogEntry(log)}\n`;
16
+ }
17
+ return result;
18
+ }
19
+ export function organizeLogsByDay(logs) {
20
+ const logsByDay = new Map();
21
+ for (const log of logs) {
22
+ const date = new Date(log.timestamp);
23
+ const day = date.toLocaleDateString();
24
+ if (!logsByDay.has(day)) {
25
+ logsByDay.set(day, []);
26
+ }
27
+ logsByDay.get(day)?.push(log);
28
+ }
29
+ return logsByDay;
30
+ }
31
+ export function formatLogsByDay(logsByDay) {
32
+ let result = '';
33
+ const sortedDays = Array.from(logsByDay.keys()).sort((a, b) => {
34
+ return new Date(a).getTime() - new Date(b).getTime();
35
+ });
36
+ for (const day of sortedDays) {
37
+ result += `${blue('Date:')} ${bold(day)}\n`;
38
+ const dayLogs = logsByDay.get(day) || [];
39
+ dayLogs.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
40
+ for (const [i, log] of dayLogs.entries()) {
41
+ const date = new Date(log.timestamp);
42
+ const time = date.toLocaleTimeString();
43
+ const isLast = i === dayLogs.length - 1;
44
+ result += ` ${isLast ? '└─' : '├─'} ${yellow(time)} ${log.message}\n`;
45
+ }
46
+ // new line between days
47
+ result += '\n';
48
+ }
49
+ return result;
50
+ }
@@ -0,0 +1,2 @@
1
+ import type { Blueprint, BlueprintResource, BlueprintStack } from './types.js';
2
+ export declare function findFunctionByName(blueprint: Blueprint | BlueprintStack, name: string): BlueprintResource;
@@ -0,0 +1,6 @@
1
+ export function findFunctionByName(blueprint, name) {
2
+ const func = blueprint?.resources.find((r) => r?.type?.startsWith('sanity.function.') && r.name === name);
3
+ if (!func)
4
+ throw Error(`Unable to find function ${name}`);
5
+ return func;
6
+ }
@@ -37,7 +37,6 @@ export interface BlueprintResource {
37
37
  id: string;
38
38
  displayName: string;
39
39
  name: string;
40
- kind: string;
41
40
  type: string;
42
41
  src: string;
43
42
  externalId: string;
@@ -1,5 +1,70 @@
1
1
  {
2
2
  "commands": {
3
+ "blueprints:add": {
4
+ "aliases": [],
5
+ "args": {
6
+ "type": {
7
+ "description": "Type of resource to add (e.g. function)",
8
+ "name": "type",
9
+ "options": [
10
+ "function"
11
+ ],
12
+ "required": true
13
+ }
14
+ },
15
+ "description": "Add a resource to a Blueprint",
16
+ "examples": [
17
+ "<%= config.bin %> <%= command.id %> function"
18
+ ],
19
+ "flags": {},
20
+ "hasDynamicHelp": false,
21
+ "hiddenAliases": [],
22
+ "id": "blueprints:add",
23
+ "pluginAlias": "@sanity/runtime-cli",
24
+ "pluginName": "@sanity/runtime-cli",
25
+ "pluginType": "core",
26
+ "strict": true,
27
+ "enableJsonFlag": false,
28
+ "isESM": true,
29
+ "relativePath": [
30
+ "dist",
31
+ "commands",
32
+ "blueprints",
33
+ "add.js"
34
+ ]
35
+ },
36
+ "blueprints:config": {
37
+ "aliases": [],
38
+ "args": {},
39
+ "description": "View or edit Blueprint configuration",
40
+ "examples": [
41
+ "<%= config.bin %> <%= command.id %>",
42
+ "<%= config.bin %> <%= command.id %> --edit"
43
+ ],
44
+ "flags": {
45
+ "edit": {
46
+ "description": "Edit the configuration",
47
+ "name": "edit",
48
+ "allowNo": false,
49
+ "type": "boolean"
50
+ }
51
+ },
52
+ "hasDynamicHelp": false,
53
+ "hiddenAliases": [],
54
+ "id": "blueprints:config",
55
+ "pluginAlias": "@sanity/runtime-cli",
56
+ "pluginName": "@sanity/runtime-cli",
57
+ "pluginType": "core",
58
+ "strict": true,
59
+ "enableJsonFlag": false,
60
+ "isESM": true,
61
+ "relativePath": [
62
+ "dist",
63
+ "commands",
64
+ "blueprints",
65
+ "config.js"
66
+ ]
67
+ },
3
68
  "blueprints:deploy": {
4
69
  "aliases": [],
5
70
  "args": {},
@@ -58,6 +123,30 @@
58
123
  "info.js"
59
124
  ]
60
125
  },
126
+ "blueprints:init": {
127
+ "aliases": [],
128
+ "args": {},
129
+ "description": "Initialize a new Blueprint",
130
+ "examples": [
131
+ "<%= config.bin %> <%= command.id %>"
132
+ ],
133
+ "flags": {},
134
+ "hasDynamicHelp": false,
135
+ "hiddenAliases": [],
136
+ "id": "blueprints:init",
137
+ "pluginAlias": "@sanity/runtime-cli",
138
+ "pluginName": "@sanity/runtime-cli",
139
+ "pluginType": "core",
140
+ "strict": true,
141
+ "enableJsonFlag": false,
142
+ "isESM": true,
143
+ "relativePath": [
144
+ "dist",
145
+ "commands",
146
+ "blueprints",
147
+ "init.js"
148
+ ]
149
+ },
61
150
  "blueprints:logs": {
62
151
  "aliases": [],
63
152
  "args": {},
@@ -177,9 +266,9 @@
177
266
  "functions:invoke": {
178
267
  "aliases": [],
179
268
  "args": {
180
- "id": {
181
- "description": "The ID of the function to invoke",
182
- "name": "id",
269
+ "name": {
270
+ "description": "The name of the Sanity Function",
271
+ "name": "name",
183
272
  "required": true
184
273
  }
185
274
  },
@@ -227,9 +316,9 @@
227
316
  "functions:logs": {
228
317
  "aliases": [],
229
318
  "args": {
230
- "id": {
231
- "description": "The ID of the function to retrieve logs for",
232
- "name": "id",
319
+ "name": {
320
+ "description": "The name of the Sanity Function",
321
+ "name": "name",
233
322
  "required": true
234
323
  }
235
324
  },
@@ -257,17 +346,17 @@
257
346
  "functions:test": {
258
347
  "aliases": [],
259
348
  "args": {
260
- "path": {
261
- "description": "The path to the function source code",
262
- "name": "path",
349
+ "name": {
350
+ "description": "The name of the Sanity Function",
351
+ "name": "name",
263
352
  "required": true
264
353
  }
265
354
  },
266
355
  "description": "Invoke a local Sanity Function",
267
356
  "examples": [
268
- "<%= config.bin %> <%= command.id %> ./test.ts --data '{ \"id\": 1 }'",
269
- "<%= config.bin %> <%= command.id %> ./test.js --file 'payload.json'",
270
- "<%= config.bin %> <%= command.id %> ./test.ts --data '{ \"id\": 1 }' --timeout 60"
357
+ "<%= config.bin %> <%= command.id %> echo-fn --data '{ \"id\": 1 }'",
358
+ "<%= config.bin %> <%= command.id %> echo-fn --file 'payload.json'",
359
+ "<%= config.bin %> <%= command.id %> echo-fn --data '{ \"id\": 1 }' --timeout 60"
271
360
  ],
272
361
  "flags": {
273
362
  "data": {
@@ -315,5 +404,5 @@
315
404
  ]
316
405
  }
317
406
  },
318
- "version": "1.6.0"
407
+ "version": "1.8.1"
319
408
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sanity/runtime-cli",
3
3
  "description": "A new CLI generated with oclif",
4
- "version": "1.6.0",
4
+ "version": "1.8.1",
5
5
  "author": "Sanity Runtime Team",
6
6
  "type": "module",
7
7
  "license": "MIT",
@@ -22,13 +22,13 @@
22
22
  "./oclif.manifest.json"
23
23
  ],
24
24
  "bin": {
25
- "sanity": "./bin/run.js"
25
+ "sanity-run": "./bin/run.js"
26
26
  },
27
27
  "scripts": {
28
28
  "build": "rollup -c && npm run build:bin && npm run build:static",
29
29
  "build:bin": "shx rm -rf dist *.tsbuildinfo && tsc -b",
30
30
  "build:static": "npm run copy:wrapper && npm run copy:server",
31
- "copy:server": "shx cp -r ./src/server/static ./dist/server/static",
31
+ "copy:server": "shx cp -r ./src/server/static ./dist/server",
32
32
  "copy:wrapper": "shx cp ./src/utils/child-process-wrapper.js ./dist/utils/child-process-wrapper.js",
33
33
  "lint": "biome ci",
34
34
  "lint:write": "biome check --write",
@@ -47,6 +47,9 @@
47
47
  "inquirer": "^12.5.0",
48
48
  "jszip": "^3.10.1",
49
49
  "mime-types": "^2.1.35",
50
+ "picocolors": "^1.1.1",
51
+ "picospinner": "^3.0.0",
52
+ "tinyhighlight": "^0.3.2",
50
53
  "xdg-basedir": "^5.1.0"
51
54
  },
52
55
  "devDependencies": {
@@ -72,19 +75,16 @@
72
75
  "vitest": "3.0.8"
73
76
  },
74
77
  "oclif": {
75
- "bin": "sanity",
76
- "dirname": "sanity",
78
+ "bin": "sanity-run",
79
+ "dirname": "sanity-run",
77
80
  "commands": "./dist/commands",
78
81
  "plugins": [
79
82
  "@oclif/plugin-help",
80
83
  "@oclif/plugin-plugins"
81
84
  ],
85
+ "state": "beta",
82
86
  "topicSeparator": " ",
83
- "topics": {
84
- "hello": {
85
- "description": "Say hello to the world and others"
86
- }
87
- }
87
+ "topics": {}
88
88
  },
89
89
  "publishConfig": {
90
90
  "access": "public",
@@ -1,53 +0,0 @@
1
- /* eslint-disable n/no-unsupported-features/node-builtins */
2
- import {Store} from './vendor/vendor.bundle.js'
3
-
4
- // eslint-disable-next-line new-cap
5
- const store = Store()
6
-
7
- export default function API() {
8
- return {
9
- blueprint,
10
- invoke,
11
- store,
12
- subscribe: store.subscribe,
13
- unsubscribe: store.unsubscribe,
14
- }
15
- }
16
-
17
- function invoke(payloadText = '{}') {
18
- store.inprogress = true
19
- const start = Date.now()
20
- const payload = {
21
- data: payloadText,
22
- func: store.selectedIndex,
23
- }
24
- fetch('/invoke', {
25
- body: JSON.stringify(payload),
26
- headers: {
27
- 'Content-Type': 'application/json',
28
- },
29
- method: 'POST',
30
- })
31
- .then((response) => response.json())
32
- .then((data) => {
33
- store.inprogress = false
34
- store.result = {
35
- ...data,
36
- time: Date.now() - start,
37
- }
38
- })
39
- }
40
-
41
- function blueprint() {
42
- fetch('/blueprint')
43
- .then((response) => response.json())
44
- .then((json) => {
45
- const functions = json?.document?.resources.filter((resource) => resource.kind === 'function')
46
-
47
- store.functions = functions
48
- store.selectedIndex = functions[0].src
49
- })
50
- .catch(() => {
51
- store.functions = []
52
- })
53
- }
@@ -1,10 +0,0 @@
1
- /* globals HTMLElement */
2
- import apiConstructor from '../api.js'
3
- const api = apiConstructor()
4
-
5
- export class ApiBaseElement extends HTMLElement {
6
- constructor() {
7
- super()
8
- this.api = api
9
- }
10
- }
@@ -1,54 +0,0 @@
1
- /* globals customElements */
2
- import {ApiBaseElement} from './api-base.js'
3
-
4
- const template = `<ol class="hidden-lg" type="content"></ol>
5
- <fieldset class="pad-sm hidden block-lg"><select></select></fieldset>
6
- `
7
-
8
- class FunctionList extends ApiBaseElement {
9
- functionClicked = (event) => {
10
- // eslint-disable-next-line unicorn/prefer-dom-node-text-content
11
- const target = this.api.store.functions.find((func) => func.name === event.srcElement.innerText)
12
- this.api.store.selectedIndex = target.src
13
- }
14
- functionSelected = (event) => {
15
- this.api.store.selectedIndex = event.srcElement.value
16
- }
17
- renderFunctions = () => {
18
- if (this.api.store.functions.length > 0) {
19
- this.list.innerHTML = this.api.store.functions
20
- .map((func) => {
21
- const selected = this.api.store.selectedIndex === func.src ? 'selected' : ''
22
- return `<li class="pad-sm ${selected}">${func.name}</li>`
23
- })
24
- .join('')
25
- this.select.innerHTML = this.api.store.functions
26
- .map((func) => {
27
- const selected = this.api.store.selectedIndex === func.src ? 'selected' : ''
28
- return `<option value="${func.src}" ${selected}>${func.name}</option>`
29
- })
30
- .join('')
31
- } else {
32
- this.list.innerHTML = '<option class="pad-sm">No blueprint.json file found</li>'
33
- this.select.innerHTML = '<option>No blueprint.json file found</option>'
34
- }
35
- }
36
-
37
- connectedCallback() {
38
- this.innerHTML = template
39
- this.list = this.querySelector('ol')
40
- this.select = this.querySelector('select')
41
- this.list.addEventListener('click', this.functionClicked)
42
- this.select.addEventListener('change', this.functionSelected)
43
- this.api.subscribe(this.renderFunctions, ['functions', 'selectedIndex'])
44
- this.api.blueprint()
45
- }
46
-
47
- disconnectedCallback() {
48
- this.list.removeEventListener('click', this.functionClicked)
49
- this.select.removeEventListener('change', this.functionSelected)
50
- this.api.unsubscribe(this.renderFunctions)
51
- }
52
- }
53
-
54
- customElements.define('function-list', FunctionList)
@@ -1,71 +0,0 @@
1
- /* globals customElements HTMLElement */
2
- const template = `<style>
3
- network-spinner {
4
- --track-width: 2px;
5
- --track-color: var(--card-border-color);
6
- --indicator-color: var(--text-color);
7
- --speed: 2s;
8
-
9
- display: inline-flex;
10
- width: 1em;
11
- height: 1em;
12
- flex: none;
13
- }
14
-
15
- .spinner {
16
- flex: 1 1 auto;
17
- height: 100%;
18
- width: 100%;
19
- }
20
-
21
- .spinner__track,
22
- .spinner__indicator {
23
- fill: none;
24
- stroke-width: var(--track-width);
25
- r: calc(0.5em - var(--track-width) / 2);
26
- cx: 0.5em;
27
- cy: 0.5em;
28
- transform-origin: 50% 50%;
29
- }
30
-
31
- .spinner__track {
32
- stroke: var(--track-color);
33
- transform-origin: 0% 0%;
34
- }
35
-
36
- .spinner__indicator {
37
- stroke: var(--indicator-color);
38
- stroke-linecap: round;
39
- stroke-dasharray: 150% 75%;
40
- animation: spin var(--speed) linear infinite;
41
- }
42
-
43
- @keyframes spin {
44
- 0% {
45
- transform: rotate(0deg);
46
- stroke-dasharray: 0.05em, 3em;
47
- }
48
-
49
- 50% {
50
- transform: rotate(450deg);
51
- stroke-dasharray: 1.375em, 1.375em;
52
- }
53
-
54
- 100% {
55
- transform: rotate(1080deg);
56
- stroke-dasharray: 0.05em, 3em;
57
- }
58
- }
59
- </style>
60
- <svg part="base" class="spinner" role="progressbar" aria-label="loading">
61
- <circle class="spinner__track"></circle>
62
- <circle class="spinner__indicator"></circle>
63
- </svg>`
64
-
65
- class NetworkSpinner extends HTMLElement {
66
- connectedCallback() {
67
- this.innerHTML = template
68
- }
69
- }
70
-
71
- customElements.define('network-spinner', NetworkSpinner)
@@ -1,45 +0,0 @@
1
- /* globals customElements */
2
- import {EditorView, basicSetup, json} from '../vendor/vendor.bundle.js'
3
- import {ApiBaseElement} from './api-base.js'
4
-
5
- const template = `<m-box>
6
- <h2 class="mar-t-0">Payload</h2>
7
- <div id="payload" name="payload"></div>
8
- <button ord="primary" class="mar-t-sm sanity-button">Invoke</button>
9
- </m-box>
10
- `
11
- class PayloadPanel extends ApiBaseElement {
12
- invoke = () => {
13
- const payloadText = this.api.store.payload.state.doc.text.join('') || '{}'
14
- this.api.invoke(payloadText)
15
- }
16
- updateButtonText = ({inprogress}) => {
17
- if (inprogress) {
18
- this.button.setAttribute('disabled', '')
19
- this.button.innerHTML = '<network-spinner></network-spinner>'
20
- } else {
21
- this.button.removeAttribute('disabled')
22
- this.button.innerText = 'Invoke'
23
- }
24
- }
25
-
26
- connectedCallback() {
27
- this.innerHTML = template
28
- this.payload = this.querySelector('#payload')
29
- this.button = this.querySelector('button')
30
- this.button.addEventListener('click', this.invoke)
31
- this.api.subscribe(this.updateButtonText, ['inprogress'])
32
-
33
- this.api.store.payload = new EditorView({
34
- doc: '\n\n\n\n',
35
- extensions: [basicSetup, json()],
36
- parent: this.payload,
37
- })
38
- }
39
-
40
- disconnectedCallback() {
41
- this.button.removeEventListener('click', this.invoke)
42
- }
43
- }
44
-
45
- customElements.define('payload-panel', PayloadPanel)
@@ -1,83 +0,0 @@
1
- /* eslint-disable unicorn/prefer-dom-node-text-content */
2
- /* globals customElements document */
3
- import {
4
- EditorState,
5
- EditorView,
6
- basicSetup,
7
- json,
8
- prettyBytes,
9
- prettyMilliseconds,
10
- } from '../vendor/vendor.bundle.js'
11
- import {ApiBaseElement} from './api-base.js'
12
-
13
- const template = `<m-box>
14
- <m-tabs role="tablist">
15
- <button id="a" role="tab" aria-selected="true">Response</button>
16
- <button id="b" role="tab">Console</button>
17
- </m-tabs>
18
- <div role="tabpanel" data-tab-id="a" class="pad-t-sm">
19
- <div class="mar-b-sm">
20
- <span id="time"></span> <span id="size"></span>
21
- </div>
22
- <div id="response" name="response"></div>
23
- </div>
24
- <div role="tabpanel" data-tab-id="b" class="pad-t-sm" hidden><pre></pre></div>
25
- </m-box>
26
- `
27
- class ResponsePanel extends ApiBaseElement {
28
- switchTab = (e) => {
29
- const selectedTabId = e.target.closest('[role=tab]').id
30
-
31
- // Select the tab and its panel
32
- for (const tab of e.currentTarget.querySelectorAll('[role=tab]')) {
33
- tab.ariaSelected = tab.id === selectedTabId
34
- }
35
-
36
- for (const panel of document.querySelectorAll('[role=tabpanel')) {
37
- panel.hidden = panel.dataset.tabId !== selectedTabId
38
- }
39
- }
40
- updateResponse = ({result}) => {
41
- const {error, json, logs, time} = result
42
- if (!error) {
43
- const transaction = this.api.store.response.state.update({
44
- changes: {
45
- from: 0,
46
- insert: JSON.stringify(json, null, 2),
47
- to: this.api.store.response.state.doc.length,
48
- },
49
- })
50
- this.api.store.response.dispatch(transaction)
51
-
52
- this.size.innerText = json ? prettyBytes(JSON.stringify(json).length) : ''
53
- this.time.innerText = prettyMilliseconds(time)
54
- this.consoleTab.innerText = logs
55
- } else {
56
- this.consoleTab.innerText = error?.details?.error
57
- }
58
- }
59
-
60
- connectedCallback() {
61
- this.innerHTML = template
62
- this.response = this.querySelector('#response')
63
- this.size = this.querySelector('#size')
64
- this.time = this.querySelector('#time')
65
- this.consoleTab = this.querySelector('pre')
66
- this.tabs = this.querySelector('m-tabs')
67
- this.tabs.addEventListener('click', this.switchTab)
68
- this.api.subscribe(this.updateResponse, ['result'])
69
-
70
- this.api.store.response = new EditorView({
71
- doc: '\n\n\n\n',
72
- extensions: [basicSetup, json(), EditorState.readOnly.of(true)],
73
- parent: this.response,
74
- })
75
- }
76
-
77
- disconnectedCallback() {
78
- this.tabs.removeEventListener('click', this.switchTab)
79
- this.api.unsubscribe(this.updateResponse)
80
- }
81
- }
82
-
83
- customElements.define('response-panel', ResponsePanel)