@sanity/runtime-cli 9.1.1 → 9.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +26 -24
  2. package/dist/actions/functions/dev.js +1 -1
  3. package/dist/commands/functions/test.d.ts +2 -0
  4. package/dist/commands/functions/test.js +17 -1
  5. package/dist/cores/functions/test.d.ts +2 -0
  6. package/dist/cores/functions/test.js +24 -5
  7. package/dist/server/app.d.ts +7 -1
  8. package/dist/server/app.js +59 -1
  9. package/dist/server/static/api.d.ts +6 -0
  10. package/dist/server/static/api.js +12 -0
  11. package/dist/server/static/components/api-base.d.ts +5 -0
  12. package/dist/server/static/components/app.css +0 -2
  13. package/dist/server/static/components/console-panel.js +3 -2
  14. package/dist/server/static/components/fetch-button.d.ts +7 -0
  15. package/dist/server/static/components/fetch-button.js +80 -0
  16. package/dist/server/static/components/filters.js +38 -7
  17. package/dist/server/static/components/help-button.d.ts +3 -0
  18. package/dist/server/static/components/help-button.js +59 -0
  19. package/dist/server/static/components/payload-panel.js +20 -1
  20. package/dist/server/static/components/run-panel.js +1 -0
  21. package/dist/server/static/components/select-dropdown.js +118 -0
  22. package/dist/server/static/components/toggle-switch.d.ts +2 -1
  23. package/dist/server/static/components/toggle-switch.js +40 -29
  24. package/dist/server/static/index.html +3 -2
  25. package/dist/utils/functions/fetch-document.d.ts +2 -0
  26. package/dist/utils/functions/fetch-document.js +9 -0
  27. package/dist/utils/invoke-local.js +0 -1
  28. package/dist/utils/types.d.ts +1 -0
  29. package/oclif.manifest.json +31 -1
  30. package/package.json +2 -2
  31. package/dist/server/static/components/dataset-dropdown.js +0 -47
  32. package/dist/server/static/components/projects-dropdown.d.ts +0 -1
  33. package/dist/server/static/components/projects-dropdown.js +0 -44
  34. /package/dist/server/static/components/{dataset-dropdown.d.ts → select-dropdown.d.ts} +0 -0
package/README.md CHANGED
@@ -20,7 +20,7 @@ $ npm install -g @sanity/runtime-cli
20
20
  $ sanity-run COMMAND
21
21
  running command...
22
22
  $ sanity-run (--version)
23
- @sanity/runtime-cli/9.1.1 linux-x64 node-v22.16.0
23
+ @sanity/runtime-cli/9.2.0 linux-x64 node-v22.17.0
24
24
  $ sanity-run --help [COMMAND]
25
25
  USAGE
26
26
  $ sanity-run COMMAND
@@ -86,7 +86,7 @@ EXAMPLES
86
86
  $ sanity-run blueprints add function --name my-function --fn-type document-publish --lang js
87
87
  ```
88
88
 
89
- _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/blueprints/add.ts)_
89
+ _See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/blueprints/add.ts)_
90
90
 
91
91
  ## `sanity-run blueprints config`
92
92
 
@@ -117,7 +117,7 @@ EXAMPLES
117
117
  $ sanity-run blueprints config --edit --project-id <projectId> --stack-id <stackId>
118
118
  ```
119
119
 
120
- _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/blueprints/config.ts)_
120
+ _See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/blueprints/config.ts)_
121
121
 
122
122
  ## `sanity-run blueprints deploy`
123
123
 
@@ -139,7 +139,7 @@ EXAMPLES
139
139
  $ sanity-run blueprints deploy --no-wait
140
140
  ```
141
141
 
142
- _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/blueprints/deploy.ts)_
142
+ _See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/blueprints/deploy.ts)_
143
143
 
144
144
  ## `sanity-run blueprints destroy`
145
145
 
@@ -164,7 +164,7 @@ EXAMPLES
164
164
  $ sanity-run blueprints destroy --stack-id <stackId> --project-id <projectId> --force --no-wait
165
165
  ```
166
166
 
167
- _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/blueprints/destroy.ts)_
167
+ _See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/blueprints/destroy.ts)_
168
168
 
169
169
  ## `sanity-run blueprints info`
170
170
 
@@ -186,7 +186,7 @@ EXAMPLES
186
186
  $ sanity-run blueprints info --stack-id <stackId>
187
187
  ```
188
188
 
189
- _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/blueprints/info.ts)_
189
+ _See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/blueprints/info.ts)_
190
190
 
191
191
  ## `sanity-run blueprints init [DIR]`
192
192
 
@@ -224,7 +224,7 @@ EXAMPLES
224
224
  $ sanity-run blueprints init --blueprint-type <json|js|ts> --stack-name <stackName>
225
225
  ```
226
226
 
227
- _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/blueprints/init.ts)_
227
+ _See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/blueprints/init.ts)_
228
228
 
229
229
  ## `sanity-run blueprints logs`
230
230
 
@@ -246,7 +246,7 @@ EXAMPLES
246
246
  $ sanity-run blueprints logs --watch
247
247
  ```
248
248
 
249
- _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/blueprints/logs.ts)_
249
+ _See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/blueprints/logs.ts)_
250
250
 
251
251
  ## `sanity-run blueprints plan`
252
252
 
@@ -263,7 +263,7 @@ EXAMPLES
263
263
  $ sanity-run blueprints plan
264
264
  ```
265
265
 
266
- _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/blueprints/plan.ts)_
266
+ _See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/blueprints/plan.ts)_
267
267
 
268
268
  ## `sanity-run blueprints stacks`
269
269
 
@@ -285,7 +285,7 @@ EXAMPLES
285
285
  $ sanity-run blueprints stacks --project-id <projectId>
286
286
  ```
287
287
 
288
- _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/blueprints/stacks.ts)_
288
+ _See code: [src/commands/blueprints/stacks.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/blueprints/stacks.ts)_
289
289
 
290
290
  ## `sanity-run functions dev`
291
291
 
@@ -305,7 +305,7 @@ EXAMPLES
305
305
  $ sanity-run functions dev --port 8974
306
306
  ```
307
307
 
308
- _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/functions/dev.ts)_
308
+ _See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/functions/dev.ts)_
309
309
 
310
310
  ## `sanity-run functions env add NAME KEY VALUE`
311
311
 
@@ -327,7 +327,7 @@ EXAMPLES
327
327
  $ sanity-run functions env add MyFunction API_URL https://api.example.com/
328
328
  ```
329
329
 
330
- _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/functions/env/add.ts)_
330
+ _See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/functions/env/add.ts)_
331
331
 
332
332
  ## `sanity-run functions env list NAME`
333
333
 
@@ -347,7 +347,7 @@ EXAMPLES
347
347
  $ sanity-run functions env list MyFunction
348
348
  ```
349
349
 
350
- _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/functions/env/list.ts)_
350
+ _See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/functions/env/list.ts)_
351
351
 
352
352
  ## `sanity-run functions env remove NAME KEY`
353
353
 
@@ -368,7 +368,7 @@ EXAMPLES
368
368
  $ sanity-run functions env remove MyFunction API_URL
369
369
  ```
370
370
 
371
- _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/functions/env/remove.ts)_
371
+ _See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/functions/env/remove.ts)_
372
372
 
373
373
  ## `sanity-run functions logs NAME`
374
374
 
@@ -402,7 +402,7 @@ EXAMPLES
402
402
  $ sanity-run functions logs <name> --delete
403
403
  ```
404
404
 
405
- _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/functions/logs.ts)_
405
+ _See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/functions/logs.ts)_
406
406
 
407
407
  ## `sanity-run functions test NAME`
408
408
 
@@ -410,19 +410,21 @@ Invoke a local Sanity Function
410
410
 
411
411
  ```
412
412
  USAGE
413
- $ sanity-run functions test NAME [-d <value>] [-f <value>] [-t <value>] [-a <value>] [--dataset <value>]
414
- [--project-id <value>]
413
+ $ sanity-run functions test NAME [-d <value> | -f <value> | --document-id <value>] [-t <value>] [-a <value>]
414
+ [--dataset <value>] [--project-id <value>] [--with-user-token]
415
415
 
416
416
  ARGUMENTS
417
417
  NAME The name of the Sanity Function
418
418
 
419
419
  FLAGS
420
- -a, --api=<value> Sanity API Version to use
421
- -d, --data=<value> Data to send to the function
422
- -f, --file=<value> Read data from file and send to the function
423
- -t, --timeout=<value> Execution timeout value in seconds
424
- --dataset=<value> The Sanity dataset to use
425
- --project-id=<value> Sanity Project ID to use
420
+ -a, --api=<value> Sanity API Version to use
421
+ -d, --data=<value> Data to send to the function
422
+ -f, --file=<value> Read data from file and send to the function
423
+ -t, --timeout=<value> Execution timeout value in seconds
424
+ --dataset=<value> The Sanity dataset to use
425
+ --document-id=<value> Document to fetch and send to function
426
+ --project-id=<value> Sanity Project ID to use
427
+ --with-user-token Prime access token from CLI config
426
428
 
427
429
  DESCRIPTION
428
430
  Invoke a local Sanity Function
@@ -435,7 +437,7 @@ EXAMPLES
435
437
  $ sanity-run functions test <name> --data '{ "id": 1 }' --timeout 60
436
438
  ```
437
439
 
438
- _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v9.1.1/src/commands/functions/test.ts)_
440
+ _See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v9.2.0/src/commands/functions/test.ts)_
439
441
 
440
442
  ## `sanity-run help [COMMAND]`
441
443
 
@@ -1,4 +1,4 @@
1
- import app from '../../server/app.js';
1
+ import { app } from '../../server/app.js';
2
2
  export async function dev(port) {
3
3
  app(Number(port));
4
4
  }
@@ -12,6 +12,8 @@ export default class TestCommand extends BlueprintCommand<typeof TestCommand> {
12
12
  api: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
13
  dataset: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
14
  'project-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
+ 'document-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
+ 'with-user-token': import("@oclif/core/interfaces").BooleanFlag<boolean>;
15
17
  };
16
18
  run(): Promise<void>;
17
19
  }
@@ -12,10 +12,16 @@ export default class TestCommand extends BlueprintCommand {
12
12
  `<%= config.bin %> <%= command.id %> <name> --data '{ "id": 1 }' --timeout 60`,
13
13
  ];
14
14
  static flags = {
15
- data: Flags.string({ char: 'd', description: 'Data to send to the function', required: false }),
15
+ data: Flags.string({
16
+ char: 'd',
17
+ description: 'Data to send to the function',
18
+ exclusive: ['file', 'document-id'],
19
+ required: false,
20
+ }),
16
21
  file: Flags.string({
17
22
  char: 'f',
18
23
  description: 'Read data from file and send to the function',
24
+ exclusive: ['data', 'document-id'],
19
25
  required: false,
20
26
  }),
21
27
  timeout: Flags.integer({
@@ -37,6 +43,16 @@ export default class TestCommand extends BlueprintCommand {
37
43
  aliases: ['project', 'projectId'],
38
44
  required: false,
39
45
  }),
46
+ 'document-id': Flags.string({
47
+ description: 'Document to fetch and send to function',
48
+ aliases: ['doc', 'documentId'],
49
+ exclusive: ['data', 'file'],
50
+ required: false,
51
+ }),
52
+ 'with-user-token': Flags.boolean({
53
+ description: 'Prime access token from CLI config',
54
+ default: false,
55
+ }),
40
56
  };
41
57
  async run() {
42
58
  const { success, error } = await functionTestCore({
@@ -12,6 +12,8 @@ export interface FunctionTestOptions extends CoreConfig {
12
12
  api?: string;
13
13
  dataset?: string;
14
14
  'project-id'?: string;
15
+ 'document-id'?: string;
16
+ 'with-user-token'?: boolean;
15
17
  };
16
18
  }
17
19
  export declare function functionTestCore(options: FunctionTestOptions): Promise<CoreResult>;
@@ -1,10 +1,13 @@
1
+ import ora from 'ora';
1
2
  import { testAction } from '../../actions/functions/test.js';
3
+ import config from '../../config.js';
2
4
  import buildPayload from '../../utils/build-payload.js';
3
5
  import { findFunctionByName } from '../../utils/find-function.js';
6
+ import { fetchDocument } from '../../utils/functions/fetch-document.js';
4
7
  export async function functionTestCore(options) {
5
8
  const { blueprint, log, args, flags } = options;
6
9
  const { name: fnName } = args;
7
- const { data, file, timeout, api, dataset } = flags;
10
+ const { data, file, timeout, api, dataset, 'document-id': documentId, 'with-user-token': withUserToken, } = flags;
8
11
  let { 'project-id': projectId } = flags;
9
12
  const { parsedBlueprint } = blueprint;
10
13
  if (!projectId && blueprint?.projectId) {
@@ -12,10 +15,6 @@ export async function functionTestCore(options) {
12
15
  }
13
16
  try {
14
17
  const resource = findFunctionByName(parsedBlueprint, fnName); // throws if not found
15
- const invokeOptions = {
16
- payload: buildPayload({ data, file }),
17
- timeout: timeout ? timeout : resource.timeout,
18
- };
19
18
  const contextOptions = {
20
19
  clientOptions: {
21
20
  apiVersion: api,
@@ -23,13 +22,33 @@ export async function functionTestCore(options) {
23
22
  projectId,
24
23
  },
25
24
  };
25
+ // If the user sets the flag to use the real token set it in our options
26
+ if (withUserToken) {
27
+ contextOptions.clientOptions.token = config.token || undefined;
28
+ }
29
+ const payload = documentId
30
+ ? await fetchDocument(documentId, {
31
+ projectId,
32
+ dataset,
33
+ apiVersion: api,
34
+ apiHost: config.apiUrl,
35
+ token: config.token || undefined,
36
+ })
37
+ : buildPayload({ data, file });
38
+ const invokeOptions = {
39
+ payload,
40
+ timeout: timeout ? timeout : resource.timeout,
41
+ };
42
+ const spinner = ora('Executing function...').start();
26
43
  const { json, logs, error } = await testAction(resource, invokeOptions, contextOptions);
27
44
  if (error) {
45
+ spinner.fail('Function execution failed.');
28
46
  return {
29
47
  success: false,
30
48
  error: error.toString(),
31
49
  };
32
50
  }
51
+ spinner.succeed('Function execution succeeded.');
33
52
  log('Logs:');
34
53
  log(logs || '');
35
54
  if (json) {
@@ -1,2 +1,8 @@
1
1
  declare const app: (port: number) => void;
2
- export default app;
2
+ declare function parseDocumentUrl(url: string): {
3
+ projectId: string;
4
+ dataset: string;
5
+ docId: string;
6
+ } | null;
7
+ declare function buildApiUrl(projectId: string, dataset: string, docId: string, apiUrl: string): string;
8
+ export { app, parseDocumentUrl, buildApiUrl };
@@ -34,6 +34,14 @@ const app = (port) => {
34
34
  try {
35
35
  const { data, func: functionName } = parseInvokeRequest(Buffer.concat(body));
36
36
  const { context, event } = data;
37
+ // replace user token if required
38
+ if (context.clientOptions.token) {
39
+ context.clientOptions.token = config.token || undefined;
40
+ }
41
+ else {
42
+ // biome-ignore lint/performance/noDelete:
43
+ delete context.clientOptions.token;
44
+ }
37
45
  const start = performance.now();
38
46
  const { parsedBlueprint } = await readLocalBlueprint();
39
47
  const resource = findFunctionByName(parsedBlueprint, functionName);
@@ -104,6 +112,36 @@ const app = (port) => {
104
112
  }
105
113
  break;
106
114
  }
115
+ case req.url?.startsWith('/document'): {
116
+ const url = req.url || '';
117
+ const parsed = parseDocumentUrl(url);
118
+ if (parsed) {
119
+ const { projectId, dataset, docId } = parsed;
120
+ res.setHeader('Content-Type', 'application/json');
121
+ try {
122
+ let json = {};
123
+ const url = buildApiUrl(projectId, dataset, docId, config.apiUrl);
124
+ if (docId) {
125
+ const response = await fetch(url, {
126
+ headers: {
127
+ Authorization: `Bearer ${config.token}`,
128
+ },
129
+ });
130
+ const queryResponse = await response.json();
131
+ if (queryResponse?.result[0]) {
132
+ json = queryResponse?.result[0];
133
+ }
134
+ }
135
+ res.writeHead(200);
136
+ res.end(JSON.stringify(json));
137
+ }
138
+ catch (error) {
139
+ res.writeHead(200);
140
+ res.end(JSON.stringify([]));
141
+ }
142
+ }
143
+ break;
144
+ }
107
145
  default: {
108
146
  const requestPath = req.url?.endsWith('/') ? `${req.url}index.html` : req.url;
109
147
  const filePath = new URL(`./static${requestPath}`, import.meta.url).pathname;
@@ -133,6 +171,26 @@ const app = (port) => {
133
171
  });
134
172
  });
135
173
  };
174
+ // Helper function to test URL parsing and document fetching logic
175
+ function parseDocumentUrl(url) {
176
+ const matches = url.match(/[?&]project=([^&]+).*?[&]dataset=([^&]+).*?[&]doc=([^&]+)/) || [];
177
+ if (matches && matches.length === 4) {
178
+ const [, projectId, dataset, docId] = matches;
179
+ // Ensure all parameters are present and non-empty
180
+ if (projectId && dataset && docId) {
181
+ return { projectId, dataset, docId };
182
+ }
183
+ }
184
+ return null;
185
+ }
186
+ // Helper function to build expected API URL
187
+ function buildApiUrl(projectId, dataset, docId, apiUrl) {
188
+ const encodedQuery = encodeURIComponent(`*[_id == "${docId}"]`);
189
+ const baseUrl = apiUrl === 'https://api.sanity.io/'
190
+ ? `https://${projectId}.api.sanity.io/`
191
+ : `https://${projectId}.api.sanity.work/`;
192
+ return `${baseUrl}v1/data/query/${dataset}?query=${encodedQuery}`;
193
+ }
136
194
  function parseInvokeRequest(body) {
137
195
  let json;
138
196
  try {
@@ -189,4 +247,4 @@ function parseInvokeRequest(body) {
189
247
  };
190
248
  return { func, data: { context: { ...context, clientOptions }, event } };
191
249
  }
192
- export default app;
250
+ export { app, parseDocumentUrl, buildApiUrl };
@@ -1,5 +1,6 @@
1
1
  export default function API(): {
2
2
  blueprint: typeof blueprint;
3
+ document: typeof document;
3
4
  invoke: typeof invoke;
4
5
  projects: typeof projects;
5
6
  datasets: typeof datasets;
@@ -8,6 +9,11 @@ export default function API(): {
8
9
  unsubscribe: any;
9
10
  };
10
11
  declare function blueprint(): void;
12
+ declare function document({ projectId, dataset, docId }: {
13
+ projectId: any;
14
+ dataset: any;
15
+ docId: any;
16
+ }): Promise<void>;
11
17
  declare function invoke(payloadText?: string): void;
12
18
  declare function projects(): void;
13
19
  declare function datasets(selectedProject: any): void;
@@ -7,6 +7,7 @@ const store = Store()
7
7
  export default function API() {
8
8
  return {
9
9
  blueprint,
10
+ document,
10
11
  invoke,
11
12
  projects,
12
13
  datasets,
@@ -85,6 +86,17 @@ function datasets(selectedProject) {
85
86
  })
86
87
  }
87
88
 
89
+ function document({projectId, dataset, docId}) {
90
+ return fetch(`/document?project=${projectId}&dataset=${dataset}&doc=${docId}`)
91
+ .then((response) => response.json())
92
+ .then((doc) => {
93
+ store.document = doc
94
+ })
95
+ .catch(() => {
96
+ store.document = {}
97
+ })
98
+ }
99
+
88
100
  function getServerTimings(response) {
89
101
  const timings = {}
90
102
  const serverTiming = response.headers.get('Server-Timing')
@@ -1,6 +1,11 @@
1
1
  export class ApiBaseElement extends HTMLElement {
2
2
  api: {
3
3
  blueprint: () => void;
4
+ document: ({ projectId, dataset, docId }: {
5
+ projectId: any;
6
+ dataset: any;
7
+ docId: any;
8
+ }) => Promise<void>;
4
9
  invoke: (payloadText?: string) => void;
5
10
  projects: () => void;
6
11
  datasets: (selectedProject: any) => void;
@@ -1155,8 +1155,6 @@ payload-panel {
1155
1155
 
1156
1156
  toggle-switch {
1157
1157
  display: inline-block;
1158
- width: 2em;
1159
- height: 1em;
1160
1158
  cursor: pointer;
1161
1159
  }
1162
1160
 
@@ -9,8 +9,9 @@ const template = `
9
9
  Console
10
10
  </h3>
11
11
  <div style="background: var(--base-background-color); display: flex; justify-content: flex-end; align-items: center; padding: var(--space-0); padding-block-end: var(--space-2)">
12
- <toggle-switch></toggle-switch>
13
- <span class="slab-text" style="margin-left: var(--space-2);">Preserve Log</span>
12
+ <toggle-switch toggle-key="preserveLog">
13
+ <span class="slab-text" style="margin-left: var(--space-1);">Preserve Log</span>
14
+ </toggle-switch>
14
15
  <clear-button></clear-button>
15
16
  </div>
16
17
  </div>
@@ -0,0 +1,7 @@
1
+ export class FetchButton extends ApiBaseElement {
2
+ connectedCallback(): void;
3
+ button: HTMLButtonElement | null | undefined;
4
+ disconnectedCallback(): void;
5
+ fetchDoc: () => Promise<void>;
6
+ }
7
+ import { ApiBaseElement } from './api-base.js';
@@ -0,0 +1,80 @@
1
+ /* globals customElements document */
2
+ import {ApiBaseElement} from './api-base.js'
3
+
4
+ const template = document.createElement('template')
5
+ template.innerHTML = `
6
+ <style>
7
+ button {
8
+ height: 2.5rem;
9
+ width: 2.5rem;
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ padding: 0;
14
+ border: none;
15
+ background: none;
16
+ border: 1px solid light-dark(var(--gray-200), var(--gray-800));
17
+ color: var(--text-color);
18
+ }
19
+
20
+ button:hover {
21
+ color: light-dark(var(--gray-950), var(--gray-200));
22
+ background-color: light-dark(var(--gray-50), var(--gray-900));
23
+ }
24
+
25
+ button svg {
26
+ width: 1.25rem;
27
+ height: 1.25rem;
28
+ display: block;
29
+ }
30
+
31
+ </style>
32
+ <button aria-label="Fetch Document" title="Fetch Document" type="button">
33
+ <svg width="800px" height="800px" viewBox="0 0 21 21" xmlns="http://www.w3.org/2000/svg">
34
+ <g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" transform="translate(4 2)">
35
+ <path d="m4.5 1.5h-2.00245461c-1.1045695 0-2 .8954305-2 2v10c0 1.1045695.8954305 2 2 2h8.00000001c1.1043778-.000491 1.9997288-.8956223 2.0004909-2l.0019637-8-4-4"/>
36
+ <path d="m9.5 8.586-3 2.914-3-2.914"/>
37
+ <path d="m6.5.5v11"/>
38
+ </g>
39
+ </svg>
40
+ </button>
41
+ `
42
+
43
+ export class FetchButton extends ApiBaseElement {
44
+ constructor() {
45
+ super()
46
+ this.attachShadow({mode: 'open'}).appendChild(template.content.cloneNode(true))
47
+ }
48
+
49
+ connectedCallback() {
50
+ this.button = this.shadowRoot.querySelector('button')
51
+ this.addEventListener('click', this.fetchDoc)
52
+ }
53
+
54
+ disconnectedCallback() {
55
+ this.removeEventListener('click', this.fetchDoc)
56
+ }
57
+
58
+ fetchDoc = async () => {
59
+ const docId = document.querySelector('#docid').value.trim()
60
+
61
+ if (docId) {
62
+ const originalContent = this.button.innerHTML
63
+ this.button.innerHTML = '<network-spinner></network-spinner>'
64
+
65
+ try {
66
+ await this.api.document({
67
+ projectId: this.api.store.selectedProject,
68
+ dataset: this.api.store.selectedDataset,
69
+ docId,
70
+ })
71
+ } catch (err) {
72
+ console.error('Error fetching document:', err)
73
+ } finally {
74
+ this.button.innerHTML = originalContent
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ customElements.define('fetch-button', FetchButton)
@@ -1,17 +1,48 @@
1
1
  class FiltersComponent extends HTMLElement {
2
2
  connectedCallback() {
3
3
  this.innerHTML = `
4
- <form style="gap: 8px;padding-left: var(--space-3); padding-bottom: var(--space-3); border-bottom: 1px solid var(--card-border-color);">
5
- <projects-dropdown></projects-dropdown>
6
- <dataset-dropdown></dataset-dropdown>
4
+ <form style="gap: 8px; padding-left: var(--space-3); padding-bottom: var(--space-3); border-bottom: 1px solid var(--card-border-color);">
5
+ <fieldset style="display: flex; gap: var(--space-2);">
6
+ <legend class="config-label">Client Options</legend>
7
+ <select-dropdown
8
+ label="Project"
9
+ store-key="projects"
10
+ selected-key="selectedProject"
11
+ value-prop="id"
12
+ label-prop="displayName"
13
+ trigger-fetch
14
+ ></select-dropdown>
15
+ <select-dropdown
16
+ label="Dataset"
17
+ store-key="datasets"
18
+ selected-key="selectedDataset"
19
+ value-prop="name"
20
+ label-prop="name"
21
+ subscribe-to="selectedProject"
22
+ ></select-dropdown>
7
23
  <fieldset class="mar-t-sm">
8
- <label class="config-label">
9
- <span>API Version</span>
24
+ <label class="slab-text">
25
+ <span style="display: block; margin-bottom: var(--space-1);">API Version</span>
26
+ <input name="apiVersion" id="apiversion" style="background: transparent; border-color: light-dark(var(--gray-200), var(--gray-700)); height: 2.5rem; color: light-dark(var(--gray-950), var(--gray-300));">
27
+ </label>
28
+ </fieldset>
29
+
30
+ <fieldset class="mar-t-sm" style="display: flex; flex-direction: column; margin-top: 12px !important;">
31
+ <span class="slab-text" style="display: block; margin-bottom: var(--space-1);">With Token</span>
32
+ <toggle-switch toggle-key="withToken" style="display: flex; height: 2.5rem;"></toggle-switch>
33
+ </fieldset>
10
34
 
11
- <input name="apiVersion" id="apiversion" style="background: transparent; border-color: light-dark(var(--gray-200), var(--gray-700))">
35
+ <fieldset class="mar-t-sm" style="margin-top: 12px !important;">
36
+ <label class="slab-text">
37
+ <span style="display: block; margin-bottom: var(--space-1);">
38
+ <span style="display: flex; align-items: center;">Document ID <help-button></help-button></span>
39
+ </span>
40
+ <div style="display: flex; flex-direction: row; gap: var(--space-2);">
41
+ <input name="docid" id="docid" style="background: transparent; border-color: light-dark(var(--gray-200), var(--gray-700)); height: 2.5rem; color: light-dark(var(--gray-950), var(--gray-300));">
42
+ <fetch-button></fetch-button>
43
+ </div>
12
44
  </label>
13
45
  </fieldset>
14
-
15
46
 
16
47
  </form>
17
48
  `
@@ -0,0 +1,3 @@
1
+ export class HelpButton extends ApiBaseElement {
2
+ }
3
+ import { ApiBaseElement } from './api-base.js';
@@ -0,0 +1,59 @@
1
+ /* globals customElements document */
2
+ import {ApiBaseElement} from './api-base.js'
3
+
4
+ const template = document.createElement('template')
5
+ template.innerHTML = `
6
+ <style>
7
+ button {
8
+ anchor-name: --button;
9
+ background-color: transparent;
10
+ border-color: transparent;
11
+ display: flex;
12
+ align-items: center;
13
+ }
14
+ div[popover] {
15
+ position-anchor: --button;
16
+ max-width: 15rem;
17
+ left: anchor(left);
18
+ top: anchor(bottom);
19
+ display: block;
20
+ margin: 0;
21
+ opacity: 0;
22
+ transform: scale(0.95);
23
+ transform-origin: top left;
24
+ visibility: hidden;
25
+ transition:
26
+ opacity 500ms,
27
+ transform 500ms,
28
+ visibility 500ms;
29
+ border-width: var(--gutter-border-width);
30
+ border-color: light-dark(var(--gray-200), var(--gray-800));
31
+ border-radius: 0.375rem;
32
+ }
33
+
34
+ [popover]:popover-open {
35
+ transform: scale(1);
36
+ opacity: 1;
37
+ visibility: visible;
38
+ }
39
+ </style>
40
+ <button title="Info" popovertarget="popover-el">
41
+ <svg data-sanity-icon="help-circle" width="1em" height="1em" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12.5 13C12.5 11 14 11.5 14 10C14 9.34375 13.5 8.5 12.5 8.5C11.5 8.5 11 9 10.5 9.5M12.5 16V14.5M20.5 12.5C20.5 16.9183 16.9183 20.5 12.5 20.5C8.08172 20.5 4.5 16.9183 4.5 12.5C4.5 8.08172 8.08172 4.5 12.5 4.5C16.9183 4.5 20.5 8.08172 20.5 12.5Z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"></path></svg>
42
+ </button>
43
+ <div popover="" id="popover-el">
44
+ <div style="padding: 0.75rem;">
45
+ <p>Fill out "Document ID" text field and then click the "Fetch Document" button to pre-populate the Document panel.</p>
46
+ <p>The Document panel is an editable text field so you can edit the fetched document or replace it with any JSON data you want.</p>
47
+ <p>When you click the "Run" button the contents of the Document panel will be evaluated against your filter/projection and sent to your function as the event part of the payload.</p>
48
+ <div>
49
+ </div>
50
+ `
51
+
52
+ export class HelpButton extends ApiBaseElement {
53
+ constructor() {
54
+ super()
55
+ this.attachShadow({mode: 'open'}).appendChild(template.content.cloneNode(true))
56
+ }
57
+ }
58
+
59
+ customElements.define('help-button', HelpButton)
@@ -7,7 +7,7 @@ import {ApiBaseElement} from './api-base.js'
7
7
  const template = `<div class="gutter-gradient relative h-100 max-h-100 y-scroll border-top border-top-none-l">
8
8
  <div class="bg gutter-gradient sticky top-0 right-0 left-0 z-100">
9
9
  <div class="flex items-center space-between" style="padding: 8px 20px 8px 48px;">
10
- <h2 class="config-label mar-t-0 mar-b-0">Event</h2>
10
+ <h2 class="config-label mar-t-0 mar-b-0">Document</h2>
11
11
  </div>
12
12
  <hr class='hr-border' style='margin-left: 31px; ' />
13
13
  </div>
@@ -15,6 +15,18 @@ const template = `<div class="gutter-gradient relative h-100 max-h-100 y-scroll
15
15
  </div>
16
16
  `
17
17
  class PayloadPanel extends ApiBaseElement {
18
+ updatePayload = ({document}) => {
19
+ if (!document) return
20
+
21
+ const transaction = this.api.store.payload.state.update({
22
+ changes: {
23
+ from: 0,
24
+ insert: JSON.stringify(document, null, 2),
25
+ to: this.api.store.payload.state.doc.length,
26
+ },
27
+ })
28
+ this.api.store.payload.dispatch(transaction)
29
+ }
18
30
  connectedCallback() {
19
31
  this.innerHTML = template
20
32
  this.payload = this.querySelector('#payload')
@@ -24,6 +36,13 @@ class PayloadPanel extends ApiBaseElement {
24
36
  extensions: [basicSetup, json(), sanityCodeMirrorTheme],
25
37
  parent: this.payload,
26
38
  })
39
+
40
+ this.api.subscribe(this.updatePayload, ['document'])
41
+ }
42
+ disconnectedCallback() {
43
+ if (this.api) {
44
+ this.api.unsubscribe(this.updatePayload)
45
+ }
27
46
  }
28
47
  }
29
48
 
@@ -22,6 +22,7 @@ class RunPanel extends ApiBaseElement {
22
22
  apiVersion: this.apiVersion.value,
23
23
  dataset: this.api.store.selectedDataset,
24
24
  projectId: this.api.store.selectedProject,
25
+ token: this.api.store.withToken,
25
26
  },
26
27
  }
27
28
  this.api.invoke({context, event})
@@ -0,0 +1,118 @@
1
+ /* globals customElements */
2
+ import {ApiBaseElement} from './api-base.js'
3
+
4
+ const dropdownTemplate = ({label}) => `
5
+ <fieldset class="mar-t-sm">
6
+ <label class="slab-text">
7
+ <span style="display: block; margin-bottom: var(--space-1);">${label}</span>
8
+ <div data-ui="Select" style="position: relative; display: inline-block; width: 100%;">
9
+ <select
10
+ data-ui="Select"
11
+ style="
12
+ width: 100%;
13
+ appearance: none;
14
+ -webkit-appearance: none;
15
+ -moz-appearance: none;
16
+ background: transparent;
17
+ color: light-dark(var(--gray-950), var(--gray-300));
18
+ padding-right: 2rem;
19
+ border: 1px solid var(--gray-400);
20
+ border-radius: var(--radius-2);
21
+ height: var(--input-height, 2.5rem);
22
+ "
23
+ ></select>
24
+ <div
25
+ data-as="div"
26
+ data-ui="Box"
27
+ style="
28
+ position: absolute;
29
+ top: 50%;
30
+ right: 0.4rem;
31
+ transform: translateY(-50%);
32
+ pointer-events: none;
33
+ display: flex;
34
+ align-items: center;
35
+ height: 100%;
36
+ "
37
+ >
38
+ <svg
39
+ data-sanity-icon="chevron-down"
40
+ width="1.5rem"
41
+ height="1.5rem"
42
+ viewBox="0 0 25 25"
43
+ fill="none"
44
+ xmlns="http://www.w3.org/2000/svg"
45
+ >
46
+ <path
47
+ d="M17 10L12.5 14.5L8 10"
48
+ stroke="currentColor"
49
+ stroke-width="1.2"
50
+ stroke-linejoin="round"
51
+ ></path>
52
+ </svg>
53
+ </div>
54
+ </div>
55
+ </label>
56
+ </fieldset>
57
+ `
58
+
59
+ class SelectDropdown extends ApiBaseElement {
60
+ connectedCallback() {
61
+ this.label = this.getAttribute('label') || 'Select'
62
+ this.storeKey = this.getAttribute('store-key')
63
+ this.selectedKey = this.getAttribute('selected-key')
64
+ this.valueProp = this.getAttribute('value-prop') || 'id'
65
+ this.labelProp = this.getAttribute('label-prop') || 'displayName'
66
+ this.subscribeTo = this.getAttribute('subscribe-to')
67
+
68
+ this.innerHTML = dropdownTemplate({label: this.label})
69
+ this.select = this.querySelector('select')
70
+ this.select.addEventListener('change', this.handleSelect)
71
+
72
+ this.api.subscribe(this.renderOptions, [this.storeKey])
73
+
74
+ if (this.hasAttribute('trigger-fetch')) {
75
+ // e.g. this.api.projects()
76
+ this.api[this.storeKey]?.()
77
+ }
78
+
79
+ if (this.subscribeTo) {
80
+ this.api.subscribe(this.refreshOnChange, [this.subscribeTo])
81
+ }
82
+ }
83
+
84
+ disconnectedCallback() {
85
+ this.select.removeEventListener('change', this.handleSelect)
86
+ this.api.unsubscribe(this.renderOptions)
87
+ if (this.subscribeTo) {
88
+ this.api.unsubscribe(this.refreshOnChange)
89
+ }
90
+ }
91
+
92
+ handleSelect = (event) => {
93
+ this.api.store[this.selectedKey] = event.target.value
94
+ }
95
+
96
+ renderOptions = () => {
97
+ const items = this.api.store?.[this.storeKey] || []
98
+ const selectedVal = this.api.store?.[this.selectedKey]
99
+ if (items.length === 0) {
100
+ this.select.innerHTML = `<option>No ${this.label}s found</option>`
101
+ return
102
+ }
103
+ this.select.innerHTML = items
104
+ .map((item) => {
105
+ const val = item[this.valueProp]
106
+ const label = item[this.labelProp] ?? val
107
+ const selected = selectedVal === val ? 'selected' : ''
108
+ return `<option value="${val}" ${selected}>${label}</option>`
109
+ })
110
+ .join('')
111
+ }
112
+
113
+ refreshOnChange = () => {
114
+ this.api[this.storeKey]?.(this.api.store[this.subscribeTo])
115
+ }
116
+ }
117
+
118
+ customElements.define('select-dropdown', SelectDropdown)
@@ -1,8 +1,9 @@
1
1
  export class ToggleSwitch extends ApiBaseElement {
2
2
  static get observedAttributes(): string[];
3
3
  connectedCallback(): void;
4
+ toggleKey: string | null | undefined;
4
5
  disconnectedCallback(): void;
5
- attributeChangedCallback(name: any, oldValue: any, newValue: any): void;
6
+ attributeChangedCallback(name: any): void;
6
7
  set checked(value: boolean);
7
8
  get checked(): boolean;
8
9
  toggle: () => void;
@@ -4,38 +4,48 @@ import {ApiBaseElement} from './api-base.js'
4
4
  const template = document.createElement('template')
5
5
  template.innerHTML = `
6
6
  <style>
7
- span {
8
- box-sizing: border-box;
9
- display: inline-block;
10
- line-height: 1;
11
- }
7
+ :host {
8
+ display: inline-block;
9
+ }
12
10
 
13
- [part="track"] {
14
- width: 100%;
15
- height: 100%;
16
- background-color: #dddddd;
17
- text-align: left;
18
- }
11
+ .switch-container {
12
+ display: flex;
13
+ align-items: center;
14
+ }
19
15
 
20
- [part="slider"] {
21
- width: 50%;
22
- height: 100%;
23
- background-color: #777777;
24
- vertical-align: text-top;
25
- }
16
+ [part="track"] {
17
+ width: 1.5rem;
18
+ height: 0.75rem;
19
+ background-color: #dddddd;
20
+ text-align: left;
21
+ border-radius: 10px;
22
+ overflow: hidden;
23
+ position: relative;
24
+ }
26
25
 
27
- [part="track"], [part="slider"] {
28
- transition: all 256ms;
29
- }
26
+ [part="slider"] {
27
+ width: 50%;
28
+ height: 100%;
29
+ background-color: #777777;
30
+ transition: all 256ms;
31
+ position: absolute;
32
+ top: 0;
33
+ left: 0;
34
+ border-radius: 10px;
35
+ }
36
+
37
+ :host([checked]) [part="slider"] {
38
+ transform: translateX(100%);
39
+ }
40
+ </style>
30
41
 
31
- :host([checked]) [part="slider"] {
32
- transform: translateX(100%);
33
- }
34
- </style>
35
42
 
36
- <span part="track">
37
- <span part="slider"></span>
38
- </span>
43
+ <div class="switch-container">
44
+ <span part="track">
45
+ <span part="slider"></span>
46
+ </span>
47
+ <slot></slot>
48
+ </div>
39
49
  `
40
50
 
41
51
  export class ToggleSwitch extends ApiBaseElement {
@@ -51,6 +61,7 @@ export class ToggleSwitch extends ApiBaseElement {
51
61
  connectedCallback() {
52
62
  this.setAttribute('role', 'switch')
53
63
  this.setAttribute('tabindex', '0')
64
+ this.toggleKey = this.getAttribute('toggle-key')
54
65
  this.addEventListener('click', this.toggle)
55
66
  }
56
67
 
@@ -58,7 +69,7 @@ export class ToggleSwitch extends ApiBaseElement {
58
69
  this.removeEventListener('click', this.toggle)
59
70
  }
60
71
 
61
- attributeChangedCallback(name, oldValue, newValue) {
72
+ attributeChangedCallback(name) {
62
73
  if (name === 'checked') {
63
74
  this.setAttribute('aria-checked', this.checked.toString())
64
75
  }
@@ -73,7 +84,7 @@ export class ToggleSwitch extends ApiBaseElement {
73
84
 
74
85
  toggle = () => {
75
86
  this.checked = !this.checked
76
- this.api.store.preserveLog = this.checked
87
+ this.api.store[this.toggleKey] = this.checked
77
88
  }
78
89
  }
79
90
 
@@ -46,8 +46,7 @@
46
46
 
47
47
 
48
48
  <script src="./components/filters.js" type="module"></script>
49
- <script src="./components/dataset-dropdown.js" type="module"></script>
50
- <script src="./components/projects-dropdown.js" type="module"></script>
49
+ <script src="./components/select-dropdown.js" type="module"></script>
51
50
  <script src="./components/function-list.js" type="module"></script>
52
51
  <script src="./components/network-spinner.js" type="module"></script>
53
52
  <script src="./components/payload-panel.js" type="module"></script>
@@ -57,6 +56,8 @@
57
56
  <script src="./components/run-panel.js" type="module"></script>
58
57
  <script src="./components/toggle-switch.js" type="module"></script>
59
58
  <script src="./components/clear-button.js" type="module"></script>
59
+ <script src="./components/help-button.js" type="module"></script>
60
+ <script src="./components/fetch-button.js" type="module"></script>
60
61
  <script src="./hot-reload.js" type="module"></script>
61
62
  </body>
62
63
  </html>
@@ -0,0 +1,2 @@
1
+ import { type ClientConfig } from '@sanity/client';
2
+ export declare function fetchDocument(documentId: string, { projectId, dataset, useCdn, apiVersion, apiHost, token }: ClientConfig): Promise<Record<string, unknown> | undefined>;
@@ -0,0 +1,9 @@
1
+ import { createClient } from '@sanity/client';
2
+ import ora from 'ora';
3
+ export async function fetchDocument(documentId, { projectId, dataset, useCdn = true, apiVersion = '2025-02-06', apiHost, token }) {
4
+ const spinner = ora(`Fetching document ID ${documentId}...`).start();
5
+ const client = createClient({ projectId, dataset, useCdn, apiVersion, apiHost, token });
6
+ const data = await client.fetch(`*[_id == "${documentId}"]`);
7
+ spinner.stop();
8
+ return data[0] ? data[0] : undefined;
9
+ }
@@ -149,7 +149,6 @@ export default async function invoke(resource, data, context, options) {
149
149
  clientOptions: {
150
150
  ...context.clientOptions,
151
151
  apiHost: config.apiUrl,
152
- token: config.token,
153
152
  },
154
153
  },
155
154
  };
@@ -122,6 +122,7 @@ export interface InvokeContextOptions {
122
122
  apiVersion?: string;
123
123
  dataset?: string;
124
124
  projectId?: string;
125
+ token?: string;
125
126
  };
126
127
  }
127
128
  /** @internal */
@@ -696,6 +696,10 @@
696
696
  "data": {
697
697
  "char": "d",
698
698
  "description": "Data to send to the function",
699
+ "exclusive": [
700
+ "file",
701
+ "document-id"
702
+ ],
699
703
  "name": "data",
700
704
  "required": false,
701
705
  "hasDynamicHelp": false,
@@ -705,6 +709,10 @@
705
709
  "file": {
706
710
  "char": "f",
707
711
  "description": "Read data from file and send to the function",
712
+ "exclusive": [
713
+ "data",
714
+ "document-id"
715
+ ],
708
716
  "name": "file",
709
717
  "required": false,
710
718
  "hasDynamicHelp": false,
@@ -748,6 +756,28 @@
748
756
  "hasDynamicHelp": false,
749
757
  "multiple": false,
750
758
  "type": "option"
759
+ },
760
+ "document-id": {
761
+ "aliases": [
762
+ "doc",
763
+ "documentId"
764
+ ],
765
+ "description": "Document to fetch and send to function",
766
+ "exclusive": [
767
+ "data",
768
+ "file"
769
+ ],
770
+ "name": "document-id",
771
+ "required": false,
772
+ "hasDynamicHelp": false,
773
+ "multiple": false,
774
+ "type": "option"
775
+ },
776
+ "with-user-token": {
777
+ "description": "Prime access token from CLI config",
778
+ "name": "with-user-token",
779
+ "allowNo": false,
780
+ "type": "boolean"
751
781
  }
752
782
  },
753
783
  "hasDynamicHelp": false,
@@ -871,5 +901,5 @@
871
901
  ]
872
902
  }
873
903
  },
874
- "version": "9.1.1"
904
+ "version": "9.2.0"
875
905
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sanity/runtime-cli",
3
3
  "description": "Sanity's Runtime CLI for Blueprints and Functions",
4
- "version": "9.1.1",
4
+ "version": "9.2.0",
5
5
  "author": "Sanity Runtime Team",
6
6
  "type": "module",
7
7
  "license": "MIT",
@@ -79,6 +79,7 @@
79
79
  "@architect/inventory": "^4.0.9",
80
80
  "@oclif/core": "^4.3.0",
81
81
  "@oclif/plugin-help": "^6.2.28",
82
+ "@sanity/client": "^7.3.0",
82
83
  "adm-zip": "^0.5.16",
83
84
  "array-treeify": "^0.1.5",
84
85
  "cardinal": "^2.1.1",
@@ -106,7 +107,6 @@
106
107
  "@playwright/test": "^1.52.0",
107
108
  "@rollup/plugin-node-resolve": "^16.0.1",
108
109
  "@sanity/blueprints": "^0.1.0",
109
- "@sanity/client": "^7.3.0",
110
110
  "@sanity/functions": "^1.0.3",
111
111
  "@types/adm-zip": "^0.5.7",
112
112
  "@types/cardinal": "^2.1.1",
@@ -1,47 +0,0 @@
1
- /* globals customElements */
2
- import {ApiBaseElement} from './api-base.js'
3
-
4
- const template = `<fieldset class="mar-t-sm">
5
- <label class="config-label">
6
- <span>Dataset</span>
7
- <select id="datasetname" style="background: transparent; color: light-dark(var(--gray-950), var(--gray-300));">
8
- </select>
9
- </label>
10
- </fieldset>
11
- `
12
-
13
- class DatasetDropdown extends ApiBaseElement {
14
- datasetSelected = (event) => {
15
- this.api.store.selectedDataset = event.srcElement.value
16
- }
17
- renderDatasets = () => {
18
- if (this.api.store?.datasets?.length > 0) {
19
- this.select.innerHTML = this.api.store.datasets
20
- .map((dataset) => {
21
- const selected = this.api.store.selectedDataset === dataset.name ? 'selected' : ''
22
- return `<option value="${dataset.name}" ${selected}>${dataset.name}</option>`
23
- })
24
- .join('')
25
- } else {
26
- this.select.innerHTML = '<option>No Datasets found</option>'
27
- }
28
- }
29
- queryDatasets = () => {
30
- this.api.datasets(this.api.store.selectedProject)
31
- }
32
-
33
- connectedCallback() {
34
- this.innerHTML = template
35
- this.select = this.querySelector('select')
36
- this.select.addEventListener('change', this.datasetSelected)
37
- this.api.subscribe(this.renderDatasets, ['datasets'])
38
- this.api.subscribe(this.queryDatasets, ['selectedProject'])
39
- }
40
-
41
- disconnectedCallback() {
42
- this.select.removeEventListener('change', this.datasetSelected)
43
- this.api.unsubscribe(this.renderProjects)
44
- }
45
- }
46
-
47
- customElements.define('dataset-dropdown', DatasetDropdown)
@@ -1 +0,0 @@
1
- export {};
@@ -1,44 +0,0 @@
1
- /* globals customElements */
2
- import {ApiBaseElement} from './api-base.js'
3
-
4
- const template = `<fieldset class="mar-t-sm">
5
- <label class='config-label'>
6
- <span>Project</span>
7
- <select id="project" style="background: transparent; color: light-dark(var(--gray-950), var(--gray-300));">
8
- </select>
9
- </label>
10
- </fieldset>
11
- `
12
-
13
- class ProjectsDropdown extends ApiBaseElement {
14
- projectSelected = (event) => {
15
- this.api.store.selectedProject = event.srcElement.value
16
- }
17
- renderProjects = () => {
18
- if (this.api.store.projects.length > 0) {
19
- this.select.innerHTML = this.api.store.projects
20
- .map((proj) => {
21
- const selected = this.api.store.selectedProject === proj.id ? 'selected' : ''
22
- return `<option value="${proj.id}" ${selected}>${proj.displayName}</option>`
23
- })
24
- .join('')
25
- } else {
26
- this.select.innerHTML = '<option>No Projects found</option>'
27
- }
28
- }
29
-
30
- connectedCallback() {
31
- this.innerHTML = template
32
- this.select = this.querySelector('select')
33
- this.select.addEventListener('change', this.projectSelected)
34
- this.api.subscribe(this.renderProjects, ['projects'])
35
- this.api.projects()
36
- }
37
-
38
- disconnectedCallback() {
39
- this.select.removeEventListener('change', this.projectSelected)
40
- this.api.unsubscribe(this.renderProjects)
41
- }
42
- }
43
-
44
- customElements.define('projects-dropdown', ProjectsDropdown)