@sanity/runtime-cli 1.6.0 → 1.8.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 (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 +10 -4
  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 +120 -31
  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,10 +1,11 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
+ import { Spinner } from 'picospinner';
2
3
  import { readBlueprintOnDisk } from '../../actions/blueprints/blueprint.js';
3
- import { getLogs, streamLogs } from '../../actions/blueprints/logs.js';
4
+ import { findNewestLogTimestamp, getLogs, getRecentLogs, isNewerLog, streamLogs, } from '../../actions/blueprints/logs.js';
4
5
  import config from '../../config.js';
5
6
  import { formatTitle } from '../../utils/display/blueprints-formatting.js';
6
- import { blue, bold, green, red, yellow } from '../../utils/display/colors.js';
7
- import Spinner from '../../utils/spinner.js';
7
+ import { bold, red, yellow } from '../../utils/display/colors.js';
8
+ import { formatLogEntry, formatLogsByDay, organizeLogsByDay, } from '../../utils/display/logs-formatting.js';
8
9
  export default class Logs extends Command {
9
10
  static description = 'Display logs for a Blueprint stack';
10
11
  static examples = [
@@ -22,11 +23,9 @@ export default class Logs extends Command {
22
23
  async run() {
23
24
  const { flags } = await this.parse(Logs);
24
25
  const watchMode = flags.watch;
25
- const s = new Spinner();
26
26
  try {
27
27
  const { errors, deployedStack } = await readBlueprintOnDisk({ getStack: true });
28
28
  if (errors.length > 0) {
29
- // printErrors(errors)
30
29
  this.log('Blueprint parse errors:');
31
30
  console.dir(errors, { depth: null });
32
31
  return;
@@ -34,53 +33,37 @@ export default class Logs extends Command {
34
33
  if (!deployedStack)
35
34
  this.error('Stack not found'); // returns
36
35
  const { id: stackId, projectId, name } = deployedStack;
36
+ const spinner = new Spinner(`Fetching logs for stack ${yellow(`<${stackId}>`)}`);
37
+ spinner.start();
37
38
  if (watchMode) {
38
- // recent logs
39
- s.start(`Fetching recent logs for stack ${stackId}`);
40
39
  const { ok, logs, error } = await getLogs(stackId, projectId, config.token);
41
40
  if (!ok) {
42
- s.stop(`${red('Failed')} to retrieve logs`);
41
+ spinner.fail(`${red('Failed')} to retrieve logs`);
43
42
  this.log(`Error: ${error || 'Unknown error'}`);
44
43
  return;
45
44
  }
46
- s.stop(`${formatTitle('Blueprint', name)} ${bold('Live')} Logs`);
45
+ spinner.stop(); // stop and remove the spinner
46
+ this.log(`${formatTitle('Blueprint', name)} ${bold('Live')} Logs`);
47
47
  if (logs.length > 0) {
48
48
  this.log('\nMost recent logs:');
49
- const sortedLogs = [...logs].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
50
- const recentLogs = sortedLogs.slice(-10);
49
+ const recentLogs = getRecentLogs(logs);
51
50
  for (const log of recentLogs) {
52
- const date = new Date(log.timestamp);
53
- const time = date.toLocaleTimeString();
54
- const day = date.toLocaleDateString();
55
- this.log(` ${bold(day)} ${yellow(time)} ${log.message}`);
51
+ this.log(` ${formatLogEntry(log)}`);
56
52
  }
57
53
  }
58
54
  else {
59
55
  this.log(`No recent logs found for stack ${yellow(stackId)}`);
60
56
  }
61
57
  const onOpen = () => {
62
- this.log(`\n${bold('Watching')} for new logs...`);
63
- this.log(`Press ${bold('Ctrl+C')} to stop\n`);
58
+ this.log(`Watching for new logs... ${bold('ctrl+c')} to stop`);
64
59
  };
65
- let newestTimestamp = 0;
66
- if (logs.length > 0) {
67
- for (const log of logs) {
68
- const timestamp = new Date(log.timestamp).getTime();
69
- if (timestamp > newestTimestamp) {
70
- newestTimestamp = timestamp;
71
- }
72
- }
73
- }
60
+ let newestTimestamp = findNewestLogTimestamp(logs);
74
61
  const renderLog = (log) => {
75
- const logTimestamp = new Date(log.timestamp).getTime();
76
- if (logTimestamp <= newestTimestamp) {
62
+ if (!isNewerLog(log, newestTimestamp)) {
77
63
  return;
78
64
  }
79
- newestTimestamp = logTimestamp;
80
- const date = new Date(log.timestamp);
81
- const time = date.toLocaleTimeString();
82
- const day = date.toLocaleDateString();
83
- this.log(`${green('>')} ${bold(day)} ${yellow(time)} ${log.message}`);
65
+ newestTimestamp = new Date(log.timestamp).getTime();
66
+ this.log(formatLogEntry(log, true));
84
67
  };
85
68
  this.debug(`${yellow('Debug:')} Connecting to streaming endpoint for stack ${stackId}...`);
86
69
  streamLogs(stackId, projectId, config.token, renderLog, onOpen, (error) => this.log(`${red('Error:')} ${error}`));
@@ -88,49 +71,26 @@ export default class Logs extends Command {
88
71
  // hold the line until the user terminates with Ctrl+C
89
72
  });
90
73
  }
91
- s.start(`Fetching logs for stack ${stackId}`);
92
74
  const { ok, logs, error } = await getLogs(stackId, projectId, config.token);
93
75
  if (!ok) {
94
- s.stop(`${red('Failed')} to retrieve logs`);
76
+ spinner.fail(`${red('Failed')} to retrieve logs`);
95
77
  this.log(`Error: ${error || 'Unknown error'}`);
96
78
  return;
97
79
  }
98
80
  if (logs.length === 0) {
99
- s.stop(`No logs found for stack ${stackId}`);
81
+ spinner.info(`No logs found for stack ${stackId}`);
100
82
  return;
101
83
  }
102
- s.stop(`${formatTitle('Blueprint', name)} Logs`);
84
+ spinner.succeed(`${formatTitle('Blueprint', name)} Logs`);
103
85
  this.log(`Found ${bold(logs.length.toString())} log entries for stack ${yellow(stackId)}\n`);
104
- const logsByDay = new Map();
105
- for (const log of logs) {
106
- const date = new Date(log.timestamp);
107
- const day = date.toLocaleDateString();
108
- if (!logsByDay.has(day)) {
109
- logsByDay.set(day, []);
110
- }
111
- logsByDay.get(day)?.push(log);
112
- }
113
- const sortedDays = Array.from(logsByDay.keys()).sort((a, b) => {
114
- return new Date(a).getTime() - new Date(b).getTime();
115
- });
116
- for (const day of sortedDays) {
117
- this.log(`${blue('Date:')} ${bold(day)}`);
118
- const dayLogs = logsByDay.get(day) || [];
119
- dayLogs.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
120
- for (const [i, log] of dayLogs.entries()) {
121
- const date = new Date(log.timestamp);
122
- const time = date.toLocaleTimeString();
123
- const isLast = i === dayLogs.length - 1;
124
- this.log(` ${isLast ? '└─' : '├─'} ${yellow(time)} ${log.message}`);
125
- }
126
- // new line between days
127
- this.log('');
128
- }
86
+ // Organize and format logs by day
87
+ const logsByDay = organizeLogsByDay(logs);
88
+ this.log(formatLogsByDay(logsByDay));
129
89
  }
130
90
  catch (err) {
131
- s.stop('Failed to retrieve logs');
91
+ this.warn('Failed to retrieve logs');
132
92
  if (err instanceof Error) {
133
- this.log(`Error: ${err.message}`);
93
+ this.error(`Error: ${err.message}`);
134
94
  }
135
95
  }
136
96
  }
@@ -1,8 +1,8 @@
1
1
  import { Command } from '@oclif/core';
2
2
  import { readBlueprintOnDisk } from '../../actions/blueprints/blueprint.js';
3
3
  import { listStacks } from '../../actions/blueprints/stacks.js';
4
- import { bold, boldnblue, yellow } from '../../utils/display/colors.js';
5
- import { formatDate } from '../../utils/display/dates.js';
4
+ import { formatStacksListing } from '../../utils/display/blueprints-formatting.js';
5
+ import { bold, yellow } from '../../utils/display/colors.js';
6
6
  export default class Stacks extends Command {
7
7
  static description = 'List all Blueprint stacks';
8
8
  static examples = ['<%= config.bin %> <%= command.id %>'];
@@ -23,18 +23,6 @@ export default class Stacks extends Command {
23
23
  return;
24
24
  }
25
25
  this.log(`${bold('Project')} <${yellow(projectId)}> ${bold('Stacks')} :\n`);
26
- for (const stack of stacks) {
27
- const isCurrentStack = stackId === stack.id;
28
- const stackName = isCurrentStack ? boldnblue(stack.name) : bold(stack.name);
29
- this.log(`${stackName} <${yellow(stack.id)}>${isCurrentStack ? ' (current)' : ''}`);
30
- if (stack.createdAt) {
31
- this.log(` Created: ${formatDate(stack.createdAt)}`);
32
- }
33
- if (stack.updatedAt) {
34
- this.log(` Updated: ${formatDate(stack.updatedAt)}`);
35
- }
36
- this.log(` ${stack.resources.length} resource${stack.resources.length === 1 ? '' : 's'}`);
37
- this.log('');
38
- }
26
+ this.log(formatStacksListing(stacks, stackId));
39
27
  }
40
28
  }
@@ -1,7 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class Invoke extends Command {
3
3
  static args: {
4
- id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
4
+ name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
5
  };
6
6
  static description: string;
7
7
  static examples: string[];
@@ -1,12 +1,13 @@
1
1
  import { Args, Command, Flags } from '@oclif/core';
2
+ import { Spinner } from 'picospinner';
2
3
  import { readBlueprintOnDisk } from '../../actions/blueprints/blueprint.js';
3
4
  import { invoke } from '../../actions/functions/invoke.js';
4
5
  import config from '../../config.js';
5
6
  import { red } from '../../utils/display/colors.js';
6
- import Spinner from '../../utils/spinner.js';
7
+ import { findFunctionByName } from '../../utils/find-function.js';
7
8
  export default class Invoke extends Command {
8
9
  static args = {
9
- id: Args.string({ description: 'The ID of the function to invoke', required: true }),
10
+ name: Args.string({ description: 'The name of the Sanity Function', required: true }),
10
11
  };
11
12
  static description = 'Invoke a remote Sanity Function';
12
13
  static examples = [
@@ -23,19 +24,20 @@ export default class Invoke extends Command {
23
24
  };
24
25
  async run() {
25
26
  const { args, flags } = await this.parse(Invoke);
26
- const s = new Spinner();
27
+ const spinner = new Spinner(`Invoking function "${args.name}"`);
27
28
  const { deployedStack } = await readBlueprintOnDisk({ getStack: true });
28
29
  if (!deployedStack)
29
30
  this.error('Stack not found'); // returns
30
31
  const { projectId } = deployedStack;
31
- s.start(`Invoking function "${args.id}"`);
32
- const result = await invoke(args.id, { data: flags.data, file: flags.file }, { token: config.token, projectId });
32
+ spinner.start();
33
+ const { externalId } = findFunctionByName(deployedStack, args.name);
34
+ const result = await invoke(externalId, { data: flags.data, file: flags.file }, { token: config.token, projectId });
33
35
  if (result.ok) {
34
- s.stop(`Invocation of ${args.id} succeeded`);
36
+ spinner.succeed(`Invocation of ${args.name} succeeded`);
35
37
  this.log(JSON.stringify(result.json, null, 2));
36
38
  }
37
39
  else {
38
- s.stop(`${red('Failed')} to invoke function`);
40
+ spinner.fail(`${red('Failed')} to invoke function`);
39
41
  this.log(`Error: ${result.error || 'Unknown error'}`);
40
42
  }
41
43
  }
@@ -1,7 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class Logs extends Command {
3
3
  static args: {
4
- id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
4
+ name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
5
  };
6
6
  static description: string;
7
7
  static examples: string[];
@@ -1,38 +1,47 @@
1
1
  import { Args, Command } from '@oclif/core';
2
+ import { Spinner } from 'picospinner';
2
3
  import { readBlueprintOnDisk } from '../../actions/blueprints/blueprint.js';
3
4
  import { logs } from '../../actions/functions/logs.js';
4
5
  import config from '../../config.js';
5
6
  import { bold, red, yellow } from '../../utils/display/colors.js';
6
- import Spinner from '../../utils/spinner.js';
7
+ import { findFunctionByName } from '../../utils/find-function.js';
7
8
  export default class Logs extends Command {
8
9
  static args = {
9
- id: Args.string({ description: 'The ID of the function to retrieve logs for', required: true }),
10
+ name: Args.string({ description: 'The name of the Sanity Function', required: true }),
10
11
  };
11
12
  static description = 'Retrieve logs for a Sanity Function';
12
13
  static examples = ['<%= config.bin %> <%= command.id %> <ID>'];
13
14
  async run() {
14
15
  const { args } = await this.parse(Logs);
15
- const s = new Spinner();
16
+ const spinner = new Spinner(`Finding logs for function "${args.name}"`);
16
17
  const { deployedStack } = await readBlueprintOnDisk({ getStack: true });
17
18
  if (!deployedStack)
18
19
  this.error('Stack not found'); // returns
19
- s.start(`Finding logs for function "${args.id}"`);
20
20
  const { name, projectId } = deployedStack;
21
- const result = await logs(args.id, { token: config.token, projectId });
22
- console.log(JSON.stringify(result, null, 2));
21
+ spinner.start();
22
+ const { externalId } = findFunctionByName(deployedStack, args.name);
23
+ const result = await logs(externalId, { token: config.token, projectId });
23
24
  if (result.ok) {
24
- s.stop(`Found logs ${args.id} for blueprint "${name}"`);
25
+ spinner.succeed(`Found logs ${args.name} for blueprint "${name}"`);
25
26
  for (const logGroup of result.logs) {
26
27
  for (const log of logGroup.events) {
27
- const date = new Date(log.timestamp);
28
- const time = date.toLocaleTimeString();
29
- const day = date.toLocaleDateString();
30
- this.log(` ${bold(day)} ${yellow(time)} ${log.message}`);
28
+ const { message, timestamp } = log;
29
+ // INFO log format: year month date hr min sec ms req uuid
30
+ const logPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z\s+[0-9a-f-]+/;
31
+ if (logPattern.test(message)) {
32
+ const content = message.replace(logPattern, '').trim().replace(/^INFO/, '').trim();
33
+ if (content) {
34
+ const date = new Date(timestamp);
35
+ const time = date.toLocaleTimeString();
36
+ const day = date.toLocaleDateString();
37
+ this.log(` ${bold(day)} ${yellow(time)} ${content}`);
38
+ }
39
+ }
31
40
  }
32
41
  }
33
42
  }
34
43
  else {
35
- s.stop(`${red('Failed')} to retrieve logs`);
44
+ spinner.fail(`${red('Failed')} to retrieve logs`);
36
45
  this.log(`Error: ${result.error || 'Unknown error'}`);
37
46
  }
38
47
  }
@@ -1,7 +1,7 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class Test extends Command {
3
3
  static args: {
4
- path: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
4
+ name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
5
  };
6
6
  static description: string;
7
7
  static examples: string[];
@@ -1,14 +1,16 @@
1
1
  import { Args, Command, Flags } from '@oclif/core';
2
+ import { readBlueprintOnDisk } from '../../actions/blueprints/blueprint.js';
2
3
  import { testAction } from '../../actions/functions/test.js';
4
+ import { findFunctionByName } from '../../utils/find-function.js';
3
5
  export default class Test extends Command {
4
6
  static args = {
5
- path: Args.string({ description: 'The path to the function source code', required: true }),
7
+ name: Args.string({ description: 'The name of the Sanity Function', required: true }),
6
8
  };
7
9
  static description = 'Invoke a local Sanity Function';
8
10
  static examples = [
9
- `<%= config.bin %> <%= command.id %> ./test.ts --data '{ "id": 1 }'`,
10
- `<%= config.bin %> <%= command.id %> ./test.js --file 'payload.json'`,
11
- `<%= config.bin %> <%= command.id %> ./test.ts --data '{ "id": 1 }' --timeout 60`,
11
+ `<%= config.bin %> <%= command.id %> echo-fn --data '{ "id": 1 }'`,
12
+ `<%= config.bin %> <%= command.id %> echo-fn --file 'payload.json'`,
13
+ `<%= config.bin %> <%= command.id %> echo-fn --data '{ "id": 1 }' --timeout 60`,
12
14
  ];
13
15
  static flags = {
14
16
  data: Flags.string({ char: 'd', description: 'Data to send to the function', required: false }),
@@ -25,19 +27,26 @@ export default class Test extends Command {
25
27
  };
26
28
  async run() {
27
29
  const { args, flags } = await this.parse(Test);
28
- const { json, logs, error } = await testAction(args.path, {
29
- data: flags.data,
30
- file: flags.file,
31
- timeout: flags.timeout,
32
- });
33
- if (!error) {
34
- this.log('Logs:');
35
- this.log(logs);
36
- this.log('Response:');
37
- this.log(JSON.stringify(json, null, 2));
30
+ const { parsedBlueprint } = await readBlueprintOnDisk({ getStack: false });
31
+ try {
32
+ const func = findFunctionByName(parsedBlueprint, args.name);
33
+ const { json, logs, error } = await testAction(func.src, {
34
+ data: flags.data,
35
+ file: flags.file,
36
+ timeout: flags.timeout,
37
+ });
38
+ if (!error) {
39
+ this.log('Logs:');
40
+ this.log(logs);
41
+ this.log('Response:');
42
+ this.log(JSON.stringify(json, null, 2));
43
+ }
44
+ else {
45
+ this.log(error.toString());
46
+ }
38
47
  }
39
- else {
40
- this.log(error.toString());
48
+ catch (error) {
49
+ this.log(`Error: ${error || 'Unknown error'}`);
41
50
  }
42
51
  }
43
52
  }
package/dist/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  declare const _default: {
2
2
  token: string;
3
+ apiUrl: URL;
3
4
  server: {
4
5
  functions: URL;
5
6
  blueprints: URL;
package/dist/config.js CHANGED
@@ -1,23 +1,29 @@
1
1
  import { env } from 'node:process';
2
2
  import getToken from './utils/get-token.js';
3
- const nodeEnv = env.NODE_ENV ?? 'development';
3
+ const nodeEnv = env.NODE_ENV ?? 'production';
4
4
  const isTest = nodeEnv === 'test';
5
5
  const isDev = nodeEnv === 'development';
6
6
  const useProd = nodeEnv === 'production';
7
- const functionsUrls = {
7
+ const apiUrls = {
8
8
  production: 'https://api.sanity.io/',
9
9
  staging: 'https://api.sanity.work/',
10
+ };
11
+ const apiUrl = new URL(apiUrls[nodeEnv] ?? apiUrls.production);
12
+ const functionsUrls = {
13
+ production: apiUrl.toString(),
14
+ staging: apiUrl.toString(),
10
15
  default: 'http://localhost:4567',
11
16
  };
12
17
  const blueprintsUrls = {
13
- production: 'https://api.sanity.io/',
14
- staging: 'https://api.sanity.work/',
18
+ production: apiUrl.toString(),
19
+ staging: apiUrl.toString(),
15
20
  default: 'http://blueprints/',
16
21
  };
17
22
  const functionsUrl = new URL(functionsUrls[nodeEnv] ?? functionsUrls.default);
18
23
  const blueprintsUrl = new URL(blueprintsUrls[nodeEnv] ?? blueprintsUrls.default);
19
24
  export default {
20
25
  token: isDev || isTest ? 'token' : getToken({ prod: useProd }),
26
+ apiUrl,
21
27
  server: {
22
28
  functions: functionsUrl,
23
29
  blueprints: blueprintsUrl,
@@ -10,10 +10,10 @@ const app = (port) => {
10
10
  switch (req.url) {
11
11
  case '/blueprint': {
12
12
  try {
13
- const blueprint = readBlueprintOnDisk();
13
+ const { parsedBlueprint } = await readBlueprintOnDisk({ getStack: false });
14
14
  res.setHeader('Content-Type', 'application/json');
15
15
  res.writeHead(200);
16
- res.end(JSON.stringify(blueprint));
16
+ res.end(JSON.stringify(parsedBlueprint));
17
17
  }
18
18
  catch {
19
19
  res.writeHead(404);
@@ -1,48 +1,53 @@
1
1
  /* eslint-disable n/no-unsupported-features/node-builtins */
2
- import { Store } from './vendor/vendor.bundle.js';
2
+ import {Store} from './vendor/vendor.bundle.js'
3
+
3
4
  // eslint-disable-next-line new-cap
4
- const store = Store();
5
+ const store = Store()
6
+
5
7
  export default function API() {
6
- return {
7
- blueprint,
8
- invoke,
9
- store,
10
- subscribe: store.subscribe,
11
- unsubscribe: store.unsubscribe,
12
- };
8
+ return {
9
+ blueprint,
10
+ invoke,
11
+ store,
12
+ subscribe: store.subscribe,
13
+ unsubscribe: store.unsubscribe,
14
+ }
13
15
  }
16
+
14
17
  function invoke(payloadText = '{}') {
15
- store.inprogress = true;
16
- const start = Date.now();
17
- const payload = {
18
- data: payloadText,
19
- func: store.selectedIndex,
20
- };
21
- fetch('/invoke', {
22
- body: JSON.stringify(payload),
23
- headers: {
24
- 'Content-Type': 'application/json',
25
- },
26
- method: 'POST',
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
+ }
27
38
  })
28
- .then((response) => response.json())
29
- .then((data) => {
30
- store.inprogress = false;
31
- store.result = {
32
- ...data,
33
- time: Date.now() - start,
34
- };
35
- });
36
39
  }
40
+
37
41
  function blueprint() {
38
- fetch('/blueprint')
39
- .then((response) => response.json())
40
- .then((json) => {
41
- const functions = json?.document?.resources.filter((resource) => resource.kind === 'function');
42
- store.functions = functions;
43
- store.selectedIndex = functions[0].src;
42
+ fetch('/blueprint')
43
+ .then((response) => response.json())
44
+ .then((blueprint) => {
45
+ const functions = blueprint?.resources.filter((r) => r.type.startsWith('sanity.function.'))
46
+
47
+ store.functions = functions
48
+ store.selectedIndex = functions[0].src
49
+ })
50
+ .catch(() => {
51
+ store.functions = []
44
52
  })
45
- .catch(() => {
46
- store.functions = [];
47
- });
48
53
  }
@@ -1,9 +1,10 @@
1
1
  /* globals HTMLElement */
2
- import apiConstructor from '../api.js';
3
- const api = apiConstructor();
2
+ import apiConstructor from '../api.js'
3
+ const api = apiConstructor()
4
+
4
5
  export class ApiBaseElement extends HTMLElement {
5
- constructor() {
6
- super();
7
- this.api = api;
8
- }
6
+ constructor() {
7
+ super()
8
+ this.api = api
9
+ }
9
10
  }
@@ -1,50 +1,54 @@
1
1
  /* globals customElements */
2
- import { ApiBaseElement } from './api-base.js';
2
+ import {ApiBaseElement} from './api-base.js'
3
+
3
4
  const template = `<ol class="hidden-lg" type="content"></ol>
4
5
  <fieldset class="pad-sm hidden block-lg"><select></select></fieldset>
5
- `;
6
+ `
7
+
6
8
  class FunctionList extends ApiBaseElement {
7
- functionClicked = (event) => {
8
- // eslint-disable-next-line unicorn/prefer-dom-node-text-content
9
- const target = this.api.store.functions.find((func) => func.name === event.srcElement.innerText);
10
- this.api.store.selectedIndex = target.src;
11
- };
12
- functionSelected = (event) => {
13
- this.api.store.selectedIndex = event.srcElement.value;
14
- };
15
- renderFunctions = () => {
16
- if (this.api.store.functions.length > 0) {
17
- this.list.innerHTML = this.api.store.functions
18
- .map((func) => {
19
- const selected = this.api.store.selectedIndex === func.src ? 'selected' : '';
20
- return `<li class="pad-sm ${selected}">${func.name}</li>`;
21
- })
22
- .join('');
23
- this.select.innerHTML = this.api.store.functions
24
- .map((func) => {
25
- const selected = this.api.store.selectedIndex === func.src ? 'selected' : '';
26
- return `<option value="${func.src}" ${selected}>${func.name}</option>`;
27
- })
28
- .join('');
29
- }
30
- else {
31
- this.list.innerHTML = '<option class="pad-sm">No blueprint.json file found</li>';
32
- this.select.innerHTML = '<option>No blueprint.json file found</option>';
33
- }
34
- };
35
- connectedCallback() {
36
- this.innerHTML = template;
37
- this.list = this.querySelector('ol');
38
- this.select = this.querySelector('select');
39
- this.list.addEventListener('click', this.functionClicked);
40
- this.select.addEventListener('change', this.functionSelected);
41
- this.api.subscribe(this.renderFunctions, ['functions', 'selectedIndex']);
42
- this.api.blueprint();
43
- }
44
- disconnectedCallback() {
45
- this.list.removeEventListener('click', this.functionClicked);
46
- this.select.removeEventListener('change', this.functionSelected);
47
- this.api.unsubscribe(this.renderFunctions);
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>'
48
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
+ }
49
52
  }
50
- customElements.define('function-list', FunctionList);
53
+
54
+ customElements.define('function-list', FunctionList)