@sanity/runtime-cli 7.0.3 → 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/dev.d.ts +2 -2
- package/dist/commands/functions/dev.js +13 -7
- package/dist/commands/functions/env/add.js +2 -2
- package/dist/commands/functions/env/list.js +2 -2
- package/dist/commands/functions/env/remove.js +2 -2
- package/dist/commands/functions/logs.d.ts +1 -12
- package/dist/commands/functions/logs.js +20 -83
- package/dist/commands/functions/test.js +10 -31
- package/dist/cores/blueprints/add.js +21 -21
- package/dist/cores/functions/dev.d.ts +7 -0
- package/dist/cores/functions/dev.js +22 -0
- package/dist/cores/functions/env/add.d.ts +2 -2
- package/dist/cores/functions/env/add.js +1 -1
- package/dist/cores/functions/env/list.d.ts +2 -2
- package/dist/cores/functions/env/list.js +1 -1
- package/dist/cores/functions/env/remove.d.ts +2 -2
- package/dist/cores/functions/env/remove.js +1 -1
- package/dist/cores/functions/index.d.ts +12 -6
- package/dist/cores/functions/index.js +6 -3
- package/dist/cores/functions/logs.d.ts +15 -0
- package/dist/cores/functions/logs.js +108 -0
- package/dist/cores/functions/test.d.ts +17 -0
- package/dist/cores/functions/test.js +43 -0
- package/dist/utils/types.d.ts +1 -1
- 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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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.0
|
|
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
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
export default class
|
|
2
|
+
export default class DevCommand extends Command {
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
6
|
-
port: import("@oclif/core/interfaces").OptionFlag<
|
|
6
|
+
port: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
7
|
};
|
|
8
8
|
run(): Promise<void>;
|
|
9
9
|
}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
|
-
import {
|
|
3
|
-
export default class
|
|
2
|
+
import { functionDevCore } from '../../cores/functions/dev.js';
|
|
3
|
+
export default class DevCommand extends Command {
|
|
4
4
|
static description = 'Start the Sanity Function emulator';
|
|
5
5
|
static examples = ['<%= config.bin %> <%= command.id %> --port 8974'];
|
|
6
6
|
static flags = {
|
|
7
|
-
port: Flags.
|
|
7
|
+
port: Flags.integer({ char: 'p', description: 'Port to start emulator on', required: false }),
|
|
8
8
|
};
|
|
9
9
|
async run() {
|
|
10
|
-
const { flags } = await this.parse(
|
|
11
|
-
const {
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const { flags } = await this.parse(DevCommand);
|
|
11
|
+
const { success, error, streaming } = await functionDevCore({
|
|
12
|
+
bin: this.config.bin,
|
|
13
|
+
log: (msg) => this.log(msg),
|
|
14
|
+
flags,
|
|
15
|
+
});
|
|
16
|
+
if (!success)
|
|
17
|
+
this.error(error);
|
|
18
|
+
if (streaming)
|
|
19
|
+
await streaming;
|
|
14
20
|
}
|
|
15
21
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
2
|
import { DeployedBlueprintCommand } from '../../../baseCommands.js';
|
|
3
|
-
import {
|
|
3
|
+
import { functionEnvAddCore } from '../../../cores/functions/env/add.js';
|
|
4
4
|
export default class EnvAddCommand extends DeployedBlueprintCommand {
|
|
5
5
|
static args = {
|
|
6
6
|
name: Args.string({ description: 'The name of the Sanity Function', required: true }),
|
|
@@ -12,7 +12,7 @@ export default class EnvAddCommand extends DeployedBlueprintCommand {
|
|
|
12
12
|
'<%= config.bin %> <%= command.id %> MyFunction API_URL https://api.example.com/',
|
|
13
13
|
];
|
|
14
14
|
async run() {
|
|
15
|
-
const { success, error } = await
|
|
15
|
+
const { success, error } = await functionEnvAddCore({
|
|
16
16
|
bin: this.config.bin,
|
|
17
17
|
log: (msg) => this.log(msg),
|
|
18
18
|
args: this.args,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
2
|
import { DeployedBlueprintCommand } from '../../../baseCommands.js';
|
|
3
|
-
import {
|
|
3
|
+
import { functionEnvListCore } from '../../../cores/functions/env/list.js';
|
|
4
4
|
export default class EnvListCommand extends DeployedBlueprintCommand {
|
|
5
5
|
static args = {
|
|
6
6
|
name: Args.string({ description: 'The name of the Sanity Function', required: true }),
|
|
@@ -8,7 +8,7 @@ export default class EnvListCommand extends DeployedBlueprintCommand {
|
|
|
8
8
|
static description = 'List the environment variables for a Sanity function';
|
|
9
9
|
static examples = ['<%= config.bin %> <%= command.id %> MyFunction'];
|
|
10
10
|
async run() {
|
|
11
|
-
const { success, error } = await
|
|
11
|
+
const { success, error } = await functionEnvListCore({
|
|
12
12
|
bin: this.config.bin,
|
|
13
13
|
log: (msg) => this.log(msg),
|
|
14
14
|
args: this.args,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Args } from '@oclif/core';
|
|
2
2
|
import { DeployedBlueprintCommand } from '../../../baseCommands.js';
|
|
3
|
-
import {
|
|
3
|
+
import { functionEnvRemoveCore } from '../../../cores/functions/env/remove.js';
|
|
4
4
|
export default class EnvRemoveCommand extends DeployedBlueprintCommand {
|
|
5
5
|
static args = {
|
|
6
6
|
name: Args.string({ description: 'The name of the Sanity Function', required: true }),
|
|
@@ -9,7 +9,7 @@ export default class EnvRemoveCommand extends DeployedBlueprintCommand {
|
|
|
9
9
|
static description = 'Remove an environment variable for a Sanity function';
|
|
10
10
|
static examples = ['<%= config.bin %> <%= command.id %> MyFunction API_URL'];
|
|
11
11
|
async run() {
|
|
12
|
-
const { success, error } = await
|
|
12
|
+
const { success, error } = await functionEnvRemoveCore({
|
|
13
13
|
bin: this.config.bin,
|
|
14
14
|
log: (msg) => this.log(msg),
|
|
15
15
|
args: this.args,
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import { DeployedBlueprintCommand } from '../../baseCommands.js';
|
|
2
|
-
type RunDeleteOptions = {
|
|
3
|
-
force: boolean;
|
|
4
|
-
};
|
|
5
|
-
type RunGetOptions = {
|
|
6
|
-
limit: number;
|
|
7
|
-
json?: boolean;
|
|
8
|
-
utc?: boolean;
|
|
9
|
-
};
|
|
10
2
|
export default class LogsCommand extends DeployedBlueprintCommand<typeof LogsCommand> {
|
|
11
3
|
static args: {
|
|
12
4
|
name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -19,10 +11,7 @@ export default class LogsCommand extends DeployedBlueprintCommand<typeof LogsCom
|
|
|
19
11
|
utc: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
20
12
|
delete: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
21
13
|
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
watch: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
15
|
};
|
|
23
|
-
externalId: string | undefined;
|
|
24
16
|
run(): Promise<void>;
|
|
25
|
-
runDeleteLogs(name: string, options: RunDeleteOptions): Promise<void>;
|
|
26
|
-
runGetLogs(name: string, options: RunGetOptions): Promise<void>;
|
|
27
17
|
}
|
|
28
|
-
export {};
|
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import inquirer from 'inquirer';
|
|
4
|
-
import ora from 'ora';
|
|
5
|
-
import { deleteLogs as deleteLogsAction, logs as getLogsAction, } from '../../actions/functions/logs.js';
|
|
6
2
|
import { DeployedBlueprintCommand } from '../../baseCommands.js';
|
|
7
|
-
import {
|
|
8
|
-
import { findFunctionByName } from '../../utils/find-function.js';
|
|
9
|
-
function logLevel(level) {
|
|
10
|
-
if (level === 'ERROR') {
|
|
11
|
-
return chalk.red(level);
|
|
12
|
-
}
|
|
13
|
-
if (level === 'WARN') {
|
|
14
|
-
return chalk.yellow(level);
|
|
15
|
-
}
|
|
16
|
-
return chalk.green(level);
|
|
17
|
-
}
|
|
3
|
+
import { functionLogsCore } from '../../cores/functions/logs.js';
|
|
18
4
|
export default class LogsCommand extends DeployedBlueprintCommand {
|
|
19
5
|
static args = {
|
|
20
6
|
name: Args.string({ description: 'The name of the Sanity Function', required: true }),
|
|
@@ -55,75 +41,26 @@ export default class LogsCommand extends DeployedBlueprintCommand {
|
|
|
55
41
|
description: 'Skip confirmation for deleting logs',
|
|
56
42
|
required: false,
|
|
57
43
|
}),
|
|
44
|
+
watch: Flags.boolean({
|
|
45
|
+
char: 'w',
|
|
46
|
+
description: 'Watch for new logs (streaming mode)',
|
|
47
|
+
aliases: ['follow'],
|
|
48
|
+
}),
|
|
58
49
|
};
|
|
59
|
-
externalId;
|
|
60
50
|
async run() {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!
|
|
74
|
-
this.error(
|
|
75
|
-
if (!options.force) {
|
|
76
|
-
const { certain } = await inquirer.prompt({
|
|
77
|
-
type: 'confirm',
|
|
78
|
-
name: 'certain',
|
|
79
|
-
message: `Are you sure you want to delete ${chalk.bold('all')} logs for function ${chalk.yellow(name)}?`,
|
|
80
|
-
default: false,
|
|
81
|
-
});
|
|
82
|
-
if (!certain)
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const spinner = ora(`Deleting logs for function ${chalk.yellow(name)}`).start();
|
|
86
|
-
const { ok, error } = await deleteLogsAction(this.externalId, this.auth);
|
|
87
|
-
if (!ok) {
|
|
88
|
-
spinner.fail(`${chalk.red('Failed')} to retrieve logs`);
|
|
89
|
-
this.log(`Error: ${error || 'Unknown error'}`);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
spinner.succeed('Logs deleted');
|
|
93
|
-
}
|
|
94
|
-
async runGetLogs(name, options) {
|
|
95
|
-
if (!this.externalId)
|
|
96
|
-
this.error('Unable to retrieve logs. Unable to determine function ID.');
|
|
97
|
-
const spinner = ora(`Finding logs for function "${name}"`).start();
|
|
98
|
-
const { ok, error, logs, total } = await getLogsAction(this.externalId, { limit: options.limit }, this.auth);
|
|
99
|
-
if (!ok) {
|
|
100
|
-
spinner.fail(`${chalk.red('Failed')} to retrieve logs`);
|
|
101
|
-
this.log(`Error: ${error || 'Unknown error'}`);
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
const filteredLogs = logs.filter((entry) => entry.level && entry.message);
|
|
105
|
-
if (filteredLogs.length === 0) {
|
|
106
|
-
spinner.info(`No logs found for function ${name}`);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
spinner.succeed(`${formatTitle('Function', name)} Logs`);
|
|
110
|
-
if (!options.json) {
|
|
111
|
-
this.log(`Found ${chalk.bold(total)} log entries for function ${chalk.yellow(name)}`);
|
|
112
|
-
if (logs.length < total) {
|
|
113
|
-
this.log(`Here are the last ${chalk.bold(filteredLogs.length.toString())} entries`);
|
|
114
|
-
}
|
|
115
|
-
this.log('\n');
|
|
116
|
-
for (const log of filteredLogs) {
|
|
117
|
-
const { time, level, message } = log;
|
|
118
|
-
const date = new Date(time);
|
|
119
|
-
const [dateString, timeString] = options.utc
|
|
120
|
-
? date.toISOString().slice(0, 19).split('T')
|
|
121
|
-
: [date.toLocaleDateString(), date.toLocaleTimeString()];
|
|
122
|
-
this.log([chalk.bold(dateString), chalk.bold.blue(timeString), logLevel(level), message].join(' '));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
this.log(JSON.stringify(filteredLogs, null, 2));
|
|
127
|
-
}
|
|
51
|
+
const { success, error } = await functionLogsCore({
|
|
52
|
+
bin: this.config.bin,
|
|
53
|
+
log: (msg) => this.log(msg),
|
|
54
|
+
args: this.args,
|
|
55
|
+
flags: this.flags,
|
|
56
|
+
auth: this.auth,
|
|
57
|
+
blueprint: this.blueprint,
|
|
58
|
+
deployedStack: this.deployedStack,
|
|
59
|
+
projectId: this.projectId,
|
|
60
|
+
token: this.sanityToken,
|
|
61
|
+
stackId: this.stackId,
|
|
62
|
+
});
|
|
63
|
+
if (!success)
|
|
64
|
+
this.error(error);
|
|
128
65
|
}
|
|
129
66
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import { testAction } from '../../actions/functions/test.js';
|
|
3
2
|
import { BlueprintCommand } from '../../baseCommands.js';
|
|
4
|
-
import {
|
|
3
|
+
import { functionTestCore } from '../../cores/functions/test.js';
|
|
5
4
|
export default class TestCommand extends BlueprintCommand {
|
|
6
5
|
static args = {
|
|
7
6
|
name: Args.string({ description: 'The name of the Sanity Function', required: true }),
|
|
@@ -40,34 +39,14 @@ export default class TestCommand extends BlueprintCommand {
|
|
|
40
39
|
}),
|
|
41
40
|
};
|
|
42
41
|
async run() {
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}, {
|
|
53
|
-
clientOptions: {
|
|
54
|
-
apiVersion: flags.api,
|
|
55
|
-
dataset: flags.dataset,
|
|
56
|
-
projectId: flags['project-id'],
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
if (!error) {
|
|
60
|
-
this.log('Logs:');
|
|
61
|
-
this.log(logs);
|
|
62
|
-
this.log('Response:');
|
|
63
|
-
this.log(JSON.stringify(json, null, 2));
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
this.log(error.toString());
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
this.log(`Error: ${error || 'Unknown error'}`);
|
|
71
|
-
}
|
|
42
|
+
const { success, error } = await functionTestCore({
|
|
43
|
+
bin: this.config.bin,
|
|
44
|
+
log: (msg) => this.log(msg),
|
|
45
|
+
args: this.args,
|
|
46
|
+
flags: this.flags,
|
|
47
|
+
blueprint: this.blueprint,
|
|
48
|
+
});
|
|
49
|
+
if (!success)
|
|
50
|
+
this.error(error);
|
|
72
51
|
}
|
|
73
52
|
}
|
|
@@ -7,37 +7,38 @@ import { validateFunctionName } from '../../utils/validate/resource.js';
|
|
|
7
7
|
export async function blueprintAddCore(options) {
|
|
8
8
|
const { bin = 'sanity', log, blueprint, args, flags } = options;
|
|
9
9
|
const { type: resourceType } = args;
|
|
10
|
-
const { name: flagResourceName, 'fn-type': flagFnType, javascript: flagJs, 'fn-helpers': flagFnHelpers, install: flagI,
|
|
11
|
-
let { language: flagFnLang, 'fn-installer': flagFnInstaller, // can be 'skip'!
|
|
10
|
+
const { name: flagResourceName, 'fn-type': flagFnType, javascript: flagJs, 'fn-helpers': flagFnHelpers, install: flagI, 'fn-installer': flagFnInstaller, // can be 'skip'!
|
|
12
11
|
} = flags;
|
|
12
|
+
let { language: flagFnLang } = flags;
|
|
13
13
|
flagFnLang = flagJs ? 'js' : flagFnLang;
|
|
14
|
-
flagFnInstaller = flagFnInstaller === 'skip' ? undefined : flagFnInstaller;
|
|
15
14
|
if (resourceType !== 'function') {
|
|
16
15
|
return {
|
|
17
16
|
success: false,
|
|
18
17
|
error: `Unsupported Resource type: ${resourceType}`,
|
|
19
18
|
};
|
|
20
19
|
}
|
|
21
|
-
if (flagI
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
if (flagI) {
|
|
21
|
+
if (flagFnInstaller) {
|
|
22
|
+
return {
|
|
23
|
+
success: false,
|
|
24
|
+
error: 'Cannot use --fn-installer flag with the --install flag',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (!flagFnHelpers) {
|
|
28
|
+
return {
|
|
29
|
+
success: false,
|
|
30
|
+
error: 'Cannot use --no-fn-helpers flag with the --install flag',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
26
33
|
}
|
|
27
|
-
if (
|
|
34
|
+
if (flagResourceName && !validateFunctionName(flagResourceName)) {
|
|
35
|
+
// if provided && invalid, return error ASAP
|
|
28
36
|
return {
|
|
29
37
|
success: false,
|
|
30
|
-
error:
|
|
38
|
+
error: `Invalid function name: ${flagResourceName}`,
|
|
31
39
|
};
|
|
32
40
|
}
|
|
33
41
|
try {
|
|
34
|
-
if (flagResourceName && !validateFunctionName(flagResourceName)) {
|
|
35
|
-
// if provided && invalid, return error
|
|
36
|
-
return {
|
|
37
|
-
success: false,
|
|
38
|
-
error: `Invalid function name: ${flagResourceName}`,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
42
|
const fnName = flagResourceName || (await promptForFunctionName());
|
|
42
43
|
// look for existing function with same name
|
|
43
44
|
if (blueprint.parsedBlueprint.resources?.some((r) => r.name === fnName)) {
|
|
@@ -69,9 +70,8 @@ export async function blueprintAddCore(options) {
|
|
|
69
70
|
installCommand = 'npm';
|
|
70
71
|
}
|
|
71
72
|
else if (flagFnInstaller) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
installCommand = flagFnInstaller;
|
|
73
|
+
addHelpers = true; // if installer is passed, assume addHelpers
|
|
74
|
+
installCommand = flagFnInstaller === 'skip' ? null : flagFnInstaller;
|
|
75
75
|
}
|
|
76
76
|
else {
|
|
77
77
|
// unsure; ask...
|
|
@@ -90,7 +90,7 @@ export async function blueprintAddCore(options) {
|
|
|
90
90
|
log(`\nCreated function: ${filePath.replace(cwd(), '')}`);
|
|
91
91
|
if (!resourceAdded) {
|
|
92
92
|
// print the resource JSON for manual addition
|
|
93
|
-
log('\nAdd this Function resource to your
|
|
93
|
+
log('\nAdd this Function resource to your Blueprint:');
|
|
94
94
|
log(highlight(JSON.stringify(resource, null, 2), undefined, undefined, 2));
|
|
95
95
|
}
|
|
96
96
|
else {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { dev } from '../../actions/functions/dev.js';
|
|
2
|
+
export async function functionDevCore(options) {
|
|
3
|
+
const { log, flags } = options;
|
|
4
|
+
const { port = 8080 } = flags;
|
|
5
|
+
try {
|
|
6
|
+
await dev(Number(port));
|
|
7
|
+
log(`Server is running on http://localhost:${port}\n`);
|
|
8
|
+
return {
|
|
9
|
+
success: true,
|
|
10
|
+
// hold the line...
|
|
11
|
+
streaming: new Promise(() => { }),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
16
|
+
log(`Error starting server: ${errorMessage}`);
|
|
17
|
+
return {
|
|
18
|
+
success: false,
|
|
19
|
+
error: errorMessage,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { CoreResult, DeployedBlueprintConfig } from '../../index.js';
|
|
2
|
-
export interface
|
|
2
|
+
export interface FunctionEnvAddOptions extends DeployedBlueprintConfig {
|
|
3
3
|
args: {
|
|
4
4
|
name: string;
|
|
5
5
|
key: string;
|
|
6
6
|
value: string;
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
|
-
export declare function
|
|
9
|
+
export declare function functionEnvAddCore(options: FunctionEnvAddOptions): Promise<CoreResult>;
|
|
@@ -2,7 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
import { update } from '../../../actions/functions/env/update.js';
|
|
4
4
|
import { findFunctionByName } from '../../../utils/find-function.js';
|
|
5
|
-
export async function
|
|
5
|
+
export async function functionEnvAddCore(options) {
|
|
6
6
|
const args = options.args;
|
|
7
7
|
const spinner = ora(`Updating "${args.key}" environment variable in "${args.name}"`).start();
|
|
8
8
|
const { externalId } = findFunctionByName(options.deployedStack, args.name);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CoreResult, DeployedBlueprintConfig } from '../../index.js';
|
|
2
|
-
export interface
|
|
2
|
+
export interface FunctionEnvListOptions extends DeployedBlueprintConfig {
|
|
3
3
|
args: {
|
|
4
4
|
name: string;
|
|
5
5
|
};
|
|
6
6
|
}
|
|
7
|
-
export declare function
|
|
7
|
+
export declare function functionEnvListCore(options: FunctionEnvListOptions): Promise<CoreResult>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import ora from 'ora';
|
|
2
2
|
import { list } from '../../../actions/functions/env/list.js';
|
|
3
3
|
import { findFunctionByName } from '../../../utils/find-function.js';
|
|
4
|
-
export async function
|
|
4
|
+
export async function functionEnvListCore(options) {
|
|
5
5
|
const args = options.args;
|
|
6
6
|
const spinner = ora(`Listing environment variables for "${args.name}"`).start();
|
|
7
7
|
const { externalId } = findFunctionByName(options.deployedStack, args.name);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { CoreResult, DeployedBlueprintConfig } from '../../index.js';
|
|
2
|
-
export interface
|
|
2
|
+
export interface FunctionEnvRemoveOptions extends DeployedBlueprintConfig {
|
|
3
3
|
args: {
|
|
4
4
|
name: string;
|
|
5
5
|
key: string;
|
|
6
6
|
};
|
|
7
7
|
}
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function functionEnvRemoveCore(options: FunctionEnvRemoveOptions): Promise<CoreResult>;
|
|
@@ -2,7 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
import { remove } from '../../../actions/functions/env/remove.js';
|
|
4
4
|
import { findFunctionByName } from '../../../utils/find-function.js';
|
|
5
|
-
export async function
|
|
5
|
+
export async function functionEnvRemoveCore(options) {
|
|
6
6
|
const args = options.args;
|
|
7
7
|
const spinner = ora(`Removing "${args.key}" environment variable in "${args.name}"`).start();
|
|
8
8
|
const { externalId } = findFunctionByName(options.deployedStack, args.name);
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type { EnvAddOptions } from './env/add.js';
|
|
3
|
-
export {
|
|
4
|
-
export type { EnvListOptions } from './env/list.js';
|
|
5
|
-
export {
|
|
6
|
-
export type { EnvRemoveOptions } from './env/remove.js';
|
|
1
|
+
export { functionEnvAddCore } from './env/add.js';
|
|
2
|
+
export type { FunctionEnvAddOptions as EnvAddOptions } from './env/add.js';
|
|
3
|
+
export { functionEnvListCore } from './env/list.js';
|
|
4
|
+
export type { FunctionEnvListOptions as EnvListOptions } from './env/list.js';
|
|
5
|
+
export { functionEnvRemoveCore } from './env/remove.js';
|
|
6
|
+
export type { FunctionEnvRemoveOptions as EnvRemoveOptions } from './env/remove.js';
|
|
7
|
+
export { functionLogsCore } from './logs.js';
|
|
8
|
+
export type { FunctionLogsOptions } from './logs.js';
|
|
9
|
+
export { functionTestCore } from './test.js';
|
|
10
|
+
export type { FunctionTestOptions } from './test.js';
|
|
11
|
+
export { functionDevCore } from './dev.js';
|
|
12
|
+
export type { FunctionDevOptions } from './dev.js';
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
1
|
+
export { functionEnvAddCore } from './env/add.js';
|
|
2
|
+
export { functionEnvListCore } from './env/list.js';
|
|
3
|
+
export { functionEnvRemoveCore } from './env/remove.js';
|
|
4
|
+
export { functionLogsCore } from './logs.js';
|
|
5
|
+
export { functionTestCore } from './test.js';
|
|
6
|
+
export { functionDevCore } from './dev.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CoreResult, DeployedBlueprintConfig } from '../index.js';
|
|
2
|
+
export interface FunctionLogsOptions extends DeployedBlueprintConfig {
|
|
3
|
+
args: {
|
|
4
|
+
name: string;
|
|
5
|
+
};
|
|
6
|
+
flags: {
|
|
7
|
+
limit: number;
|
|
8
|
+
json?: boolean;
|
|
9
|
+
utc?: boolean;
|
|
10
|
+
delete?: boolean;
|
|
11
|
+
force?: boolean;
|
|
12
|
+
watch?: boolean;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare function functionLogsCore(options: FunctionLogsOptions): Promise<CoreResult>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { deleteLogs as deleteLogsAction, logs as getLogsAction, streamLogs as streamLogsAction, } from '../../actions/functions/logs.js';
|
|
5
|
+
import { formatTitle } from '../../utils/display/blueprints-formatting.js';
|
|
6
|
+
import { niceId } from '../../utils/display/presenters.js';
|
|
7
|
+
import { findFunctionByName } from '../../utils/find-function.js';
|
|
8
|
+
export async function functionLogsCore(options) {
|
|
9
|
+
const { args, flags, log, auth, deployedStack } = options;
|
|
10
|
+
const { name } = args;
|
|
11
|
+
const { delete: shouldDelete, watch: shouldWatch, force, limit, json, utc } = flags;
|
|
12
|
+
const { externalId } = findFunctionByName(deployedStack, name); // throws if not found
|
|
13
|
+
if (shouldDelete)
|
|
14
|
+
return deleteLogs({ name, externalId, auth, force, log });
|
|
15
|
+
if (shouldWatch)
|
|
16
|
+
return streamLogs({ name, externalId, auth, json, utc, log });
|
|
17
|
+
return getLogs({ name, externalId, auth, limit, json, utc, log });
|
|
18
|
+
}
|
|
19
|
+
async function deleteLogs({ name, externalId, auth, force, log, }) {
|
|
20
|
+
if (!force) {
|
|
21
|
+
const { certain } = await inquirer.prompt({
|
|
22
|
+
type: 'confirm',
|
|
23
|
+
name: 'certain',
|
|
24
|
+
message: `Are you sure you want to delete ${chalk.bold('all')} logs for function ${chalk.yellow(name)}?`,
|
|
25
|
+
default: false,
|
|
26
|
+
});
|
|
27
|
+
if (!certain)
|
|
28
|
+
return { success: true };
|
|
29
|
+
}
|
|
30
|
+
const spinner = ora(`Deleting logs for function ${chalk.yellow(name)}`).start();
|
|
31
|
+
const { ok, error } = await deleteLogsAction(externalId, auth);
|
|
32
|
+
if (!ok) {
|
|
33
|
+
spinner.fail(`${chalk.red('Failed')} to delete logs`);
|
|
34
|
+
return { success: false, error: error || 'Unknown error' };
|
|
35
|
+
}
|
|
36
|
+
spinner.succeed('Logs deleted');
|
|
37
|
+
return { success: true };
|
|
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
|
+
}
|
|
67
|
+
async function getLogs({ name, externalId, auth, limit, json, utc, log, }) {
|
|
68
|
+
const spinner = ora(`Finding logs for function "${name}"`).start();
|
|
69
|
+
const { ok, error, logs, total } = await getLogsAction(externalId, { limit }, auth);
|
|
70
|
+
if (!ok) {
|
|
71
|
+
spinner.fail(`${chalk.red('Failed')} to retrieve logs`);
|
|
72
|
+
return { success: false, error: error || 'Unknown error' };
|
|
73
|
+
}
|
|
74
|
+
const filteredLogs = logs.filter((entry) => entry.level && entry.message);
|
|
75
|
+
if (filteredLogs.length === 0) {
|
|
76
|
+
spinner.info(`No logs found for function ${name}`);
|
|
77
|
+
return { success: true };
|
|
78
|
+
}
|
|
79
|
+
spinner.succeed(`${formatTitle('Function', name)} Logs`);
|
|
80
|
+
if (!json) {
|
|
81
|
+
log(`Found ${chalk.bold(total)} log entries for function ${chalk.yellow(name)}`);
|
|
82
|
+
if (logs.length < total) {
|
|
83
|
+
log(`Here are the last ${chalk.bold(filteredLogs.length.toString())} entries`);
|
|
84
|
+
}
|
|
85
|
+
log('\n');
|
|
86
|
+
for (const { time, level, message } of filteredLogs) {
|
|
87
|
+
log(formatLog(time, level, message, utc));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
log(JSON.stringify(filteredLogs, null, 2));
|
|
92
|
+
}
|
|
93
|
+
return { success: true };
|
|
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
|
+
}
|
|
102
|
+
function logLevel(level) {
|
|
103
|
+
if (level === 'ERROR')
|
|
104
|
+
return chalk.red(level);
|
|
105
|
+
if (level === 'WARN')
|
|
106
|
+
return chalk.yellow(level);
|
|
107
|
+
return chalk.green(level);
|
|
108
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ReadBlueprintResult } from '../../actions/blueprints/blueprint.js';
|
|
2
|
+
import type { CoreConfig, CoreResult } from '../index.js';
|
|
3
|
+
export interface FunctionTestOptions extends CoreConfig {
|
|
4
|
+
blueprint: ReadBlueprintResult;
|
|
5
|
+
args: {
|
|
6
|
+
name: string;
|
|
7
|
+
};
|
|
8
|
+
flags: {
|
|
9
|
+
data?: string;
|
|
10
|
+
file?: string;
|
|
11
|
+
timeout?: number;
|
|
12
|
+
api?: string;
|
|
13
|
+
dataset?: string;
|
|
14
|
+
'project-id'?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export declare function functionTestCore(options: FunctionTestOptions): Promise<CoreResult>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { testAction } from '../../actions/functions/test.js';
|
|
2
|
+
import { findFunctionByName } from '../../utils/find-function.js';
|
|
3
|
+
export async function functionTestCore(options) {
|
|
4
|
+
const { blueprint, log, args, flags } = options;
|
|
5
|
+
const { name: fnName } = args;
|
|
6
|
+
const { data, file, timeout, api, dataset, 'project-id': projectId } = flags;
|
|
7
|
+
const { parsedBlueprint } = blueprint;
|
|
8
|
+
try {
|
|
9
|
+
const resource = findFunctionByName(parsedBlueprint, fnName); // throws if not found
|
|
10
|
+
const invokeOptions = {
|
|
11
|
+
data,
|
|
12
|
+
file,
|
|
13
|
+
timeout,
|
|
14
|
+
};
|
|
15
|
+
const contextOptions = {
|
|
16
|
+
clientOptions: {
|
|
17
|
+
apiVersion: api,
|
|
18
|
+
dataset,
|
|
19
|
+
projectId,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
const { json, logs, error } = await testAction(resource, invokeOptions, contextOptions);
|
|
23
|
+
if (error) {
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
error: error.toString(),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
log('Logs:');
|
|
30
|
+
log(logs || '');
|
|
31
|
+
if (json) {
|
|
32
|
+
log('Response:');
|
|
33
|
+
log(JSON.stringify(json, null, 2));
|
|
34
|
+
}
|
|
35
|
+
return { success: true };
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return {
|
|
39
|
+
success: false,
|
|
40
|
+
error: error instanceof Error ? error.message : String(error),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -82,10 +82,10 @@ export interface Stack {
|
|
|
82
82
|
/** @internal */
|
|
83
83
|
export interface StackResource {
|
|
84
84
|
id: string;
|
|
85
|
-
displayName: string;
|
|
86
85
|
name: string;
|
|
87
86
|
type: string;
|
|
88
87
|
externalId: string;
|
|
88
|
+
displayName?: string;
|
|
89
89
|
parameters?: Record<string, unknown>;
|
|
90
90
|
}
|
|
91
91
|
/** @internal */
|
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.0
|
|
842
|
+
"version": "7.2.0"
|
|
833
843
|
}
|