@sanity/runtime-cli 7.1.0 → 7.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.
- package/README.md +17 -16
- package/dist/actions/functions/logs.d.ts +2 -1
- package/dist/actions/functions/logs.js +55 -0
- package/dist/commands/functions/logs.d.ts +1 -0
- package/dist/commands/functions/logs.js +5 -0
- package/dist/cores/functions/logs.d.ts +1 -0
- package/dist/cores/functions/logs.js +41 -7
- package/oclif.manifest.json +11 -1
- package/package.json +1 -1
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/7.
|
|
23
|
+
@sanity/runtime-cli/7.2.0 linux-x64 node-v22.15.0
|
|
24
24
|
$ sanity-run --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ sanity-run COMMAND
|
|
@@ -84,7 +84,7 @@ EXAMPLES
|
|
|
84
84
|
$ sanity-run blueprints add function --name my-function --fn-type document-publish --lang js
|
|
85
85
|
```
|
|
86
86
|
|
|
87
|
-
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
87
|
+
_See code: [src/commands/blueprints/add.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/blueprints/add.ts)_
|
|
88
88
|
|
|
89
89
|
## `sanity-run blueprints config`
|
|
90
90
|
|
|
@@ -112,7 +112,7 @@ EXAMPLES
|
|
|
112
112
|
$ sanity-run blueprints config --edit --project-id <projectId>
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
115
|
+
_See code: [src/commands/blueprints/config.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/blueprints/config.ts)_
|
|
116
116
|
|
|
117
117
|
## `sanity-run blueprints deploy`
|
|
118
118
|
|
|
@@ -134,7 +134,7 @@ EXAMPLES
|
|
|
134
134
|
$ sanity-run blueprints deploy --no-wait
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
-
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
137
|
+
_See code: [src/commands/blueprints/deploy.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/blueprints/deploy.ts)_
|
|
138
138
|
|
|
139
139
|
## `sanity-run blueprints destroy`
|
|
140
140
|
|
|
@@ -155,7 +155,7 @@ EXAMPLES
|
|
|
155
155
|
$ sanity-run blueprints destroy
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
-
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
158
|
+
_See code: [src/commands/blueprints/destroy.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/blueprints/destroy.ts)_
|
|
159
159
|
|
|
160
160
|
## `sanity-run blueprints info`
|
|
161
161
|
|
|
@@ -172,7 +172,7 @@ EXAMPLES
|
|
|
172
172
|
$ sanity-run blueprints info
|
|
173
173
|
```
|
|
174
174
|
|
|
175
|
-
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
175
|
+
_See code: [src/commands/blueprints/info.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/blueprints/info.ts)_
|
|
176
176
|
|
|
177
177
|
## `sanity-run blueprints init [DIR]`
|
|
178
178
|
|
|
@@ -204,7 +204,7 @@ EXAMPLES
|
|
|
204
204
|
$ sanity-run blueprints init --blueprint-type <json|js|ts> --project-id <projectId>
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
-
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
207
|
+
_See code: [src/commands/blueprints/init.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/blueprints/init.ts)_
|
|
208
208
|
|
|
209
209
|
## `sanity-run blueprints logs`
|
|
210
210
|
|
|
@@ -226,7 +226,7 @@ EXAMPLES
|
|
|
226
226
|
$ sanity-run blueprints logs --watch
|
|
227
227
|
```
|
|
228
228
|
|
|
229
|
-
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
229
|
+
_See code: [src/commands/blueprints/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/blueprints/logs.ts)_
|
|
230
230
|
|
|
231
231
|
## `sanity-run blueprints plan`
|
|
232
232
|
|
|
@@ -243,7 +243,7 @@ EXAMPLES
|
|
|
243
243
|
$ sanity-run blueprints plan
|
|
244
244
|
```
|
|
245
245
|
|
|
246
|
-
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
246
|
+
_See code: [src/commands/blueprints/plan.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/blueprints/plan.ts)_
|
|
247
247
|
|
|
248
248
|
## `sanity-run functions dev`
|
|
249
249
|
|
|
@@ -263,7 +263,7 @@ EXAMPLES
|
|
|
263
263
|
$ sanity-run functions dev --port 8974
|
|
264
264
|
```
|
|
265
265
|
|
|
266
|
-
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
266
|
+
_See code: [src/commands/functions/dev.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/functions/dev.ts)_
|
|
267
267
|
|
|
268
268
|
## `sanity-run functions env add NAME KEY VALUE`
|
|
269
269
|
|
|
@@ -285,7 +285,7 @@ EXAMPLES
|
|
|
285
285
|
$ sanity-run functions env add MyFunction API_URL https://api.example.com/
|
|
286
286
|
```
|
|
287
287
|
|
|
288
|
-
_See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
288
|
+
_See code: [src/commands/functions/env/add.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/functions/env/add.ts)_
|
|
289
289
|
|
|
290
290
|
## `sanity-run functions env list NAME`
|
|
291
291
|
|
|
@@ -305,7 +305,7 @@ EXAMPLES
|
|
|
305
305
|
$ sanity-run functions env list MyFunction
|
|
306
306
|
```
|
|
307
307
|
|
|
308
|
-
_See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
308
|
+
_See code: [src/commands/functions/env/list.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/functions/env/list.ts)_
|
|
309
309
|
|
|
310
310
|
## `sanity-run functions env remove NAME KEY`
|
|
311
311
|
|
|
@@ -326,7 +326,7 @@ EXAMPLES
|
|
|
326
326
|
$ sanity-run functions env remove MyFunction API_URL
|
|
327
327
|
```
|
|
328
328
|
|
|
329
|
-
_See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
329
|
+
_See code: [src/commands/functions/env/remove.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/functions/env/remove.ts)_
|
|
330
330
|
|
|
331
331
|
## `sanity-run functions logs NAME`
|
|
332
332
|
|
|
@@ -334,7 +334,7 @@ Retrieve or delete logs for a Sanity Function
|
|
|
334
334
|
|
|
335
335
|
```
|
|
336
336
|
USAGE
|
|
337
|
-
$ sanity-run functions logs NAME [-u] [-f [-d | -l <value> | -j]]
|
|
337
|
+
$ sanity-run functions logs NAME [-u] [-f [-d | -l <value> | -j]] [-w]
|
|
338
338
|
|
|
339
339
|
ARGUMENTS
|
|
340
340
|
NAME The name of the Sanity Function
|
|
@@ -345,6 +345,7 @@ FLAGS
|
|
|
345
345
|
-j, --json Return logs in JSON format
|
|
346
346
|
-l, --limit=<value> [default: 50] Total number of log entries to retrieve
|
|
347
347
|
-u, --utc Show dates in UTC time zone
|
|
348
|
+
-w, --watch Watch for new logs (streaming mode)
|
|
348
349
|
|
|
349
350
|
DESCRIPTION
|
|
350
351
|
Retrieve or delete logs for a Sanity Function
|
|
@@ -359,7 +360,7 @@ EXAMPLES
|
|
|
359
360
|
$ sanity-run functions logs <name> --delete
|
|
360
361
|
```
|
|
361
362
|
|
|
362
|
-
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
363
|
+
_See code: [src/commands/functions/logs.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/functions/logs.ts)_
|
|
363
364
|
|
|
364
365
|
## `sanity-run functions test NAME`
|
|
365
366
|
|
|
@@ -392,7 +393,7 @@ EXAMPLES
|
|
|
392
393
|
$ sanity-run functions test <name> --data '{ "id": 1 }' --timeout 60
|
|
393
394
|
```
|
|
394
395
|
|
|
395
|
-
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v7.
|
|
396
|
+
_See code: [src/commands/functions/test.ts](https://github.com/sanity-io/runtime-cli/blob/v7.2.0/src/commands/functions/test.ts)_
|
|
396
397
|
|
|
397
398
|
## `sanity-run help [COMMAND]`
|
|
398
399
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuthParams } from '../../utils/types.js';
|
|
1
|
+
import type { AuthParams, FunctionLog } from '../../utils/types.js';
|
|
2
2
|
/** @internal */
|
|
3
3
|
export interface LoggingOptions {
|
|
4
4
|
limit: number;
|
|
@@ -13,3 +13,4 @@ export declare function deleteLogs(id: string, auth: AuthParams): Promise<{
|
|
|
13
13
|
ok: boolean;
|
|
14
14
|
error: any;
|
|
15
15
|
}>;
|
|
16
|
+
export declare function streamLogs(id: string, auth: AuthParams, onLog: (log: FunctionLog) => void, onOpen: () => void, onError: (error: string) => void): () => void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EventSource } from 'eventsource';
|
|
1
2
|
import config from '../../config.js';
|
|
2
3
|
import getHeaders from '../../utils/get-headers.js';
|
|
3
4
|
const { apiUrl } = config;
|
|
@@ -26,3 +27,57 @@ export async function deleteLogs(id, auth) {
|
|
|
26
27
|
error: response.ok ? null : json?.error?.message,
|
|
27
28
|
};
|
|
28
29
|
}
|
|
30
|
+
// Create streaming logs connection
|
|
31
|
+
export function streamLogs(id, auth, onLog, onOpen, onError) {
|
|
32
|
+
const url = new URL(`${apiUrl}vX/functions/${id}/logs/stream`);
|
|
33
|
+
const headers = getHeaders(auth);
|
|
34
|
+
const eventSource = new EventSource(url.toString(), {
|
|
35
|
+
fetch: (input, init) => fetch(input, {
|
|
36
|
+
...init,
|
|
37
|
+
headers: {
|
|
38
|
+
...init?.headers,
|
|
39
|
+
...headers,
|
|
40
|
+
},
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
eventSource.onopen = onOpen;
|
|
44
|
+
eventSource.onmessage = (event) => {
|
|
45
|
+
try {
|
|
46
|
+
const log = JSON.parse(event.data);
|
|
47
|
+
onLog(log);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
onError(`Failed to parse log data: ${err instanceof Error ? err.message : String(err)}`);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
eventSource.addEventListener('logs', (event) => {
|
|
54
|
+
try {
|
|
55
|
+
const logData = JSON.parse(event.data);
|
|
56
|
+
// usually an array
|
|
57
|
+
if (Array.isArray(logData)) {
|
|
58
|
+
for (const log of logData)
|
|
59
|
+
onLog(log);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
onLog(logData);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
console.error('Error parsing logs event:', err);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
eventSource.onerror = (err) => {
|
|
70
|
+
onError('Connection to log stream failed or was closed');
|
|
71
|
+
if (eventSource.readyState === eventSource.CLOSED) {
|
|
72
|
+
console.log('Connection is CLOSED');
|
|
73
|
+
}
|
|
74
|
+
else if (eventSource.readyState === eventSource.CONNECTING) {
|
|
75
|
+
console.log('Connection is attempting to reconnect...');
|
|
76
|
+
return; // Don't close if trying to reconnect
|
|
77
|
+
}
|
|
78
|
+
eventSource.close();
|
|
79
|
+
};
|
|
80
|
+
return () => {
|
|
81
|
+
eventSource.close();
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -11,6 +11,7 @@ export default class LogsCommand extends DeployedBlueprintCommand<typeof LogsCom
|
|
|
11
11
|
utc: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
12
|
delete: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
13
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
watch: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
15
|
};
|
|
15
16
|
run(): Promise<void>;
|
|
16
17
|
}
|
|
@@ -41,6 +41,11 @@ export default class LogsCommand extends DeployedBlueprintCommand {
|
|
|
41
41
|
description: 'Skip confirmation for deleting logs',
|
|
42
42
|
required: false,
|
|
43
43
|
}),
|
|
44
|
+
watch: Flags.boolean({
|
|
45
|
+
char: 'w',
|
|
46
|
+
description: 'Watch for new logs (streaming mode)',
|
|
47
|
+
aliases: ['follow'],
|
|
48
|
+
}),
|
|
44
49
|
};
|
|
45
50
|
async run() {
|
|
46
51
|
const { success, error } = await functionLogsCore({
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import inquirer from 'inquirer';
|
|
3
3
|
import ora from 'ora';
|
|
4
|
-
import { deleteLogs as deleteLogsAction, logs as getLogsAction, } from '../../actions/functions/logs.js';
|
|
4
|
+
import { deleteLogs as deleteLogsAction, logs as getLogsAction, streamLogs as streamLogsAction, } from '../../actions/functions/logs.js';
|
|
5
5
|
import { formatTitle } from '../../utils/display/blueprints-formatting.js';
|
|
6
|
+
import { niceId } from '../../utils/display/presenters.js';
|
|
6
7
|
import { findFunctionByName } from '../../utils/find-function.js';
|
|
7
8
|
export async function functionLogsCore(options) {
|
|
8
9
|
const { args, flags, log, auth, deployedStack } = options;
|
|
9
10
|
const { name } = args;
|
|
10
|
-
const { delete: shouldDelete, force, limit, json, utc } = flags;
|
|
11
|
+
const { delete: shouldDelete, watch: shouldWatch, force, limit, json, utc } = flags;
|
|
11
12
|
const { externalId } = findFunctionByName(deployedStack, name); // throws if not found
|
|
12
13
|
if (shouldDelete)
|
|
13
14
|
return deleteLogs({ name, externalId, auth, force, log });
|
|
15
|
+
if (shouldWatch)
|
|
16
|
+
return streamLogs({ name, externalId, auth, json, utc, log });
|
|
14
17
|
return getLogs({ name, externalId, auth, limit, json, utc, log });
|
|
15
18
|
}
|
|
16
19
|
async function deleteLogs({ name, externalId, auth, force, log, }) {
|
|
@@ -33,6 +36,34 @@ async function deleteLogs({ name, externalId, auth, force, log, }) {
|
|
|
33
36
|
spinner.succeed('Logs deleted');
|
|
34
37
|
return { success: true };
|
|
35
38
|
}
|
|
39
|
+
async function streamLogs({ name, externalId, auth, json, utc, log, }) {
|
|
40
|
+
const spinner = ora(`Setting up streaming logs session for function ${niceId(name)}`).start();
|
|
41
|
+
try {
|
|
42
|
+
spinner.stop();
|
|
43
|
+
log(`Streaming log session for function ${niceId(name)}`);
|
|
44
|
+
log(`Watching for new logs... ${chalk.bold('ctrl+c')} to stop`);
|
|
45
|
+
const onOpen = () => {
|
|
46
|
+
// TODO delete line 97 and uncomment 101 when Fns service is updated
|
|
47
|
+
// log(`Watching for new logs... ${chalk.bold('ctrl+c')} to stop`)
|
|
48
|
+
};
|
|
49
|
+
const renderLog = (logEntry) => {
|
|
50
|
+
const { time, level, message } = logEntry;
|
|
51
|
+
log(formatLog(time, level, message, true));
|
|
52
|
+
};
|
|
53
|
+
streamLogsAction(externalId, auth, renderLog, onOpen, (error) => log(`${chalk.red('Error:')} ${error}`));
|
|
54
|
+
// Return a special key for streaming mode
|
|
55
|
+
return {
|
|
56
|
+
success: true,
|
|
57
|
+
streaming: new Promise(() => { }),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
spinner.fail('Failed to retrieve logs');
|
|
62
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
63
|
+
log(`Error: ${errorMessage}`);
|
|
64
|
+
return { success: false, error: errorMessage };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
36
67
|
async function getLogs({ name, externalId, auth, limit, json, utc, log, }) {
|
|
37
68
|
const spinner = ora(`Finding logs for function "${name}"`).start();
|
|
38
69
|
const { ok, error, logs, total } = await getLogsAction(externalId, { limit }, auth);
|
|
@@ -53,11 +84,7 @@ async function getLogs({ name, externalId, auth, limit, json, utc, log, }) {
|
|
|
53
84
|
}
|
|
54
85
|
log('\n');
|
|
55
86
|
for (const { time, level, message } of filteredLogs) {
|
|
56
|
-
|
|
57
|
-
const [dateString, timeString] = utc
|
|
58
|
-
? date.toISOString().slice(0, 19).split('T')
|
|
59
|
-
: [date.toLocaleDateString(), date.toLocaleTimeString()];
|
|
60
|
-
log([chalk.bold(dateString), chalk.bold.blue(timeString), logLevel(level), message].join(' '));
|
|
87
|
+
log(formatLog(time, level, message, utc));
|
|
61
88
|
}
|
|
62
89
|
}
|
|
63
90
|
else {
|
|
@@ -65,6 +92,13 @@ async function getLogs({ name, externalId, auth, limit, json, utc, log, }) {
|
|
|
65
92
|
}
|
|
66
93
|
return { success: true };
|
|
67
94
|
}
|
|
95
|
+
function formatLog(time, level, message, utc) {
|
|
96
|
+
const date = new Date(time);
|
|
97
|
+
const [dateString, timeString] = utc
|
|
98
|
+
? date.toISOString().slice(0, 19).split('T')
|
|
99
|
+
: [date.toLocaleDateString(), date.toLocaleTimeString()];
|
|
100
|
+
return [chalk.bold(dateString), chalk.bold.blue(timeString), logLevel(level), message].join(' ');
|
|
101
|
+
}
|
|
68
102
|
function logLevel(level) {
|
|
69
103
|
if (level === 'ERROR')
|
|
70
104
|
return chalk.red(level);
|
package/oclif.manifest.json
CHANGED
|
@@ -618,6 +618,16 @@
|
|
|
618
618
|
"required": false,
|
|
619
619
|
"allowNo": false,
|
|
620
620
|
"type": "boolean"
|
|
621
|
+
},
|
|
622
|
+
"watch": {
|
|
623
|
+
"aliases": [
|
|
624
|
+
"follow"
|
|
625
|
+
],
|
|
626
|
+
"char": "w",
|
|
627
|
+
"description": "Watch for new logs (streaming mode)",
|
|
628
|
+
"name": "watch",
|
|
629
|
+
"allowNo": false,
|
|
630
|
+
"type": "boolean"
|
|
621
631
|
}
|
|
622
632
|
},
|
|
623
633
|
"hasDynamicHelp": false,
|
|
@@ -829,5 +839,5 @@
|
|
|
829
839
|
]
|
|
830
840
|
}
|
|
831
841
|
},
|
|
832
|
-
"version": "7.
|
|
842
|
+
"version": "7.2.0"
|
|
833
843
|
}
|