@xano/cli 0.0.13 → 0.0.15
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 +97 -12
- package/dist/commands/profile/create/index.d.ts +2 -0
- package/dist/commands/profile/create/index.js +15 -0
- package/dist/commands/profile/edit/index.d.ts +4 -0
- package/dist/commands/profile/edit/index.js +37 -1
- package/dist/commands/profile/list/index.js +5 -0
- package/dist/commands/profile/project/index.d.ts +6 -0
- package/dist/commands/profile/project/index.js +54 -0
- package/dist/commands/profile/token/index.d.ts +6 -0
- package/dist/commands/profile/token/index.js +54 -0
- package/dist/commands/profile/wizard/index.d.ts +1 -0
- package/dist/commands/profile/wizard/index.js +70 -0
- package/dist/commands/run/env/delete/index.d.ts +13 -0
- package/dist/commands/run/env/delete/index.js +65 -0
- package/dist/commands/run/env/get/index.d.ts +13 -0
- package/dist/commands/run/env/get/index.js +52 -0
- package/dist/commands/run/env/list/index.d.ts +11 -0
- package/dist/commands/run/env/list/index.js +58 -0
- package/dist/commands/run/env/set/index.d.ts +13 -0
- package/dist/commands/run/env/set/index.js +51 -0
- package/dist/commands/{ephemeral/run/job → run/exec}/index.d.ts +4 -3
- package/dist/commands/run/exec/index.js +353 -0
- package/dist/commands/{ephemeral/run/service → run/info}/index.d.ts +3 -5
- package/dist/commands/run/info/index.js +160 -0
- package/dist/commands/run/projects/create/index.d.ts +13 -0
- package/dist/commands/run/projects/create/index.js +75 -0
- package/dist/commands/run/projects/delete/index.d.ts +13 -0
- package/dist/commands/run/projects/delete/index.js +65 -0
- package/dist/commands/run/projects/list/index.d.ts +12 -0
- package/dist/commands/run/projects/list/index.js +66 -0
- package/dist/commands/run/projects/update/index.d.ts +15 -0
- package/dist/commands/run/projects/update/index.js +86 -0
- package/dist/commands/run/secrets/delete/index.d.ts +13 -0
- package/dist/commands/run/secrets/delete/index.js +65 -0
- package/dist/commands/run/secrets/get/index.d.ts +13 -0
- package/dist/commands/run/secrets/get/index.js +52 -0
- package/dist/commands/run/secrets/list/index.d.ts +11 -0
- package/dist/commands/run/secrets/list/index.js +62 -0
- package/dist/commands/run/secrets/set/index.d.ts +15 -0
- package/dist/commands/run/secrets/set/index.js +74 -0
- package/dist/commands/run/sessions/delete/index.d.ts +13 -0
- package/dist/commands/run/sessions/delete/index.js +65 -0
- package/dist/commands/run/sessions/get/index.d.ts +13 -0
- package/dist/commands/run/sessions/get/index.js +72 -0
- package/dist/commands/run/sessions/list/index.d.ts +12 -0
- package/dist/commands/run/sessions/list/index.js +64 -0
- package/dist/commands/run/sessions/start/index.d.ts +13 -0
- package/dist/commands/run/sessions/start/index.js +56 -0
- package/dist/commands/run/sessions/stop/index.d.ts +13 -0
- package/dist/commands/run/sessions/stop/index.js +56 -0
- package/dist/commands/run/sink/get/index.d.ts +13 -0
- package/dist/commands/run/sink/get/index.js +63 -0
- package/dist/lib/base-run-command.d.ts +41 -0
- package/dist/lib/base-run-command.js +73 -0
- package/dist/lib/run-http-client.d.ts +58 -0
- package/dist/lib/run-http-client.js +136 -0
- package/dist/lib/run-types.d.ts +226 -0
- package/dist/lib/run-types.js +5 -0
- package/oclif.manifest.json +1423 -306
- package/package.json +1 -1
- package/dist/commands/ephemeral/run/job/index.js +0 -311
- package/dist/commands/ephemeral/run/service/index.js +0 -287
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import BaseRunCommand from '../../../../lib/base-run-command.js';
|
|
3
|
+
export default class RunEnvGet extends BaseRunCommand {
|
|
4
|
+
static args = {
|
|
5
|
+
name: Args.string({
|
|
6
|
+
description: 'Environment variable name',
|
|
7
|
+
required: true,
|
|
8
|
+
}),
|
|
9
|
+
};
|
|
10
|
+
static flags = {
|
|
11
|
+
...BaseRunCommand.baseFlags,
|
|
12
|
+
output: Flags.string({
|
|
13
|
+
char: 'o',
|
|
14
|
+
description: 'Output format',
|
|
15
|
+
required: false,
|
|
16
|
+
default: 'value',
|
|
17
|
+
options: ['value', 'json'],
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
static description = 'Get an environment variable value';
|
|
21
|
+
static examples = [
|
|
22
|
+
`$ xano run env get API_KEY
|
|
23
|
+
my-secret-api-key
|
|
24
|
+
`,
|
|
25
|
+
`$ xano run env get API_KEY -o json
|
|
26
|
+
{ "name": "API_KEY", "value": "my-secret-api-key" }
|
|
27
|
+
`,
|
|
28
|
+
];
|
|
29
|
+
async run() {
|
|
30
|
+
const { args, flags } = await this.parse(RunEnvGet);
|
|
31
|
+
// Initialize with project required
|
|
32
|
+
await this.initRunCommandWithProject(flags.profile);
|
|
33
|
+
try {
|
|
34
|
+
const url = this.httpClient.buildProjectUrl('/env', { name: args.name });
|
|
35
|
+
const result = await this.httpClient.get(url);
|
|
36
|
+
if (flags.output === 'json') {
|
|
37
|
+
this.outputJson(result);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.log(result.value);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (error instanceof Error) {
|
|
45
|
+
this.error(`Failed to get environment variable: ${error.message}`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.error(`Failed to get environment variable: ${String(error)}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import BaseRunCommand from '../../../../lib/base-run-command.js';
|
|
2
|
+
export default class RunEnvList extends BaseRunCommand {
|
|
3
|
+
static args: {};
|
|
4
|
+
static flags: {
|
|
5
|
+
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
};
|
|
8
|
+
static description: string;
|
|
9
|
+
static examples: string[];
|
|
10
|
+
run(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import BaseRunCommand from '../../../../lib/base-run-command.js';
|
|
3
|
+
export default class RunEnvList extends BaseRunCommand {
|
|
4
|
+
static args = {};
|
|
5
|
+
static flags = {
|
|
6
|
+
...BaseRunCommand.baseFlags,
|
|
7
|
+
output: Flags.string({
|
|
8
|
+
char: 'o',
|
|
9
|
+
description: 'Output format',
|
|
10
|
+
required: false,
|
|
11
|
+
default: 'list',
|
|
12
|
+
options: ['list', 'json'],
|
|
13
|
+
}),
|
|
14
|
+
};
|
|
15
|
+
static description = 'List all environment variable keys';
|
|
16
|
+
static examples = [
|
|
17
|
+
`$ xano run env list
|
|
18
|
+
Environment variables:
|
|
19
|
+
- API_KEY
|
|
20
|
+
- DATABASE_URL
|
|
21
|
+
- DEBUG
|
|
22
|
+
`,
|
|
23
|
+
`$ xano run env list -o json
|
|
24
|
+
{ "env": ["API_KEY", "DATABASE_URL", "DEBUG"] }
|
|
25
|
+
`,
|
|
26
|
+
];
|
|
27
|
+
async run() {
|
|
28
|
+
const { flags } = await this.parse(RunEnvList);
|
|
29
|
+
// Initialize with project required
|
|
30
|
+
await this.initRunCommandWithProject(flags.profile);
|
|
31
|
+
try {
|
|
32
|
+
const url = this.httpClient.buildProjectUrl('/env/key');
|
|
33
|
+
const result = await this.httpClient.get(url);
|
|
34
|
+
if (flags.output === 'json') {
|
|
35
|
+
this.outputJson(result);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
if (result.env.length === 0) {
|
|
39
|
+
this.log('No environment variables found.');
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
this.log('Environment variables:');
|
|
43
|
+
for (const key of result.env) {
|
|
44
|
+
this.log(` - ${key}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (error instanceof Error) {
|
|
51
|
+
this.error(`Failed to list environment variables: ${error.message}`);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
this.error(`Failed to list environment variables: ${String(error)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import BaseRunCommand from '../../../../lib/base-run-command.js';
|
|
2
|
+
export default class RunEnvSet extends BaseRunCommand {
|
|
3
|
+
static args: {
|
|
4
|
+
name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
value: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
6
|
+
};
|
|
7
|
+
static flags: {
|
|
8
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
static description: string;
|
|
11
|
+
static examples: string[];
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Args } from '@oclif/core';
|
|
2
|
+
import BaseRunCommand from '../../../../lib/base-run-command.js';
|
|
3
|
+
export default class RunEnvSet extends BaseRunCommand {
|
|
4
|
+
static args = {
|
|
5
|
+
name: Args.string({
|
|
6
|
+
description: 'Environment variable name',
|
|
7
|
+
required: true,
|
|
8
|
+
}),
|
|
9
|
+
value: Args.string({
|
|
10
|
+
description: 'Environment variable value',
|
|
11
|
+
required: true,
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
static flags = {
|
|
15
|
+
...BaseRunCommand.baseFlags,
|
|
16
|
+
};
|
|
17
|
+
static description = 'Set an environment variable';
|
|
18
|
+
static examples = [
|
|
19
|
+
`$ xano run env set API_KEY my-secret-key
|
|
20
|
+
Environment variable 'API_KEY' set successfully!
|
|
21
|
+
`,
|
|
22
|
+
`$ xano run env set DATABASE_URL "postgres://user:pass@host/db"
|
|
23
|
+
Environment variable 'DATABASE_URL' set successfully!
|
|
24
|
+
`,
|
|
25
|
+
];
|
|
26
|
+
async run() {
|
|
27
|
+
const { args, flags } = await this.parse(RunEnvSet);
|
|
28
|
+
// Initialize with project required
|
|
29
|
+
await this.initRunCommandWithProject(flags.profile);
|
|
30
|
+
const input = {
|
|
31
|
+
name: args.name,
|
|
32
|
+
env: {
|
|
33
|
+
name: args.name,
|
|
34
|
+
value: args.value,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
const url = this.httpClient.buildProjectUrl('/env');
|
|
39
|
+
await this.httpClient.patch(url, input);
|
|
40
|
+
this.log(`Environment variable '${args.name}' set successfully!`);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (error instanceof Error) {
|
|
44
|
+
this.error(`Failed to set environment variable: ${error.message}`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
this.error(`Failed to set environment variable: ${String(error)}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
export default class
|
|
1
|
+
import BaseRunCommand from '../../../lib/base-run-command.js';
|
|
2
|
+
export default class RunExec extends BaseRunCommand {
|
|
3
3
|
static args: {};
|
|
4
4
|
static flags: {
|
|
5
5
|
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -7,13 +7,14 @@ export default class EphemeralRunJob extends BaseCommand {
|
|
|
7
7
|
edit: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
8
|
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
args: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
env: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
11
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
12
|
};
|
|
12
13
|
static description: string;
|
|
13
14
|
static examples: string[];
|
|
14
15
|
run(): Promise<void>;
|
|
16
|
+
private outputSummary;
|
|
15
17
|
private editFile;
|
|
16
18
|
private isUrl;
|
|
17
19
|
private readStdin;
|
|
18
|
-
private loadCredentials;
|
|
19
20
|
}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { execSync } from 'node:child_process';
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import * as os from 'node:os';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import BaseRunCommand from '../../../lib/base-run-command.js';
|
|
7
|
+
export default class RunExec extends BaseRunCommand {
|
|
8
|
+
static args = {};
|
|
9
|
+
static flags = {
|
|
10
|
+
...BaseRunCommand.baseFlags,
|
|
11
|
+
file: Flags.string({
|
|
12
|
+
char: 'f',
|
|
13
|
+
description: 'Path or URL to file containing XanoScript code',
|
|
14
|
+
required: false,
|
|
15
|
+
exclusive: ['stdin'],
|
|
16
|
+
}),
|
|
17
|
+
stdin: Flags.boolean({
|
|
18
|
+
char: 's',
|
|
19
|
+
description: 'Read XanoScript code from stdin',
|
|
20
|
+
required: false,
|
|
21
|
+
default: false,
|
|
22
|
+
exclusive: ['file'],
|
|
23
|
+
}),
|
|
24
|
+
edit: Flags.boolean({
|
|
25
|
+
char: 'e',
|
|
26
|
+
description: 'Open file in editor before running (requires --file)',
|
|
27
|
+
required: false,
|
|
28
|
+
default: false,
|
|
29
|
+
dependsOn: ['file'],
|
|
30
|
+
}),
|
|
31
|
+
output: Flags.string({
|
|
32
|
+
char: 'o',
|
|
33
|
+
description: 'Output format',
|
|
34
|
+
required: false,
|
|
35
|
+
default: 'summary',
|
|
36
|
+
options: ['summary', 'json'],
|
|
37
|
+
}),
|
|
38
|
+
args: Flags.string({
|
|
39
|
+
char: 'a',
|
|
40
|
+
description: 'Path or URL to JSON file containing input arguments',
|
|
41
|
+
required: false,
|
|
42
|
+
}),
|
|
43
|
+
env: Flags.string({
|
|
44
|
+
description: 'Environment variable override (key=value)',
|
|
45
|
+
required: false,
|
|
46
|
+
multiple: true,
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
static description = 'Execute XanoScript code (job or service)';
|
|
50
|
+
static examples = [
|
|
51
|
+
`$ xano run exec -f script.xs
|
|
52
|
+
Executed successfully!
|
|
53
|
+
...
|
|
54
|
+
`,
|
|
55
|
+
`$ xano run exec -f script.xs --edit
|
|
56
|
+
# Opens script.xs in $EDITOR, then executes
|
|
57
|
+
Executed successfully!
|
|
58
|
+
...
|
|
59
|
+
`,
|
|
60
|
+
`$ cat script.xs | xano run exec --stdin
|
|
61
|
+
Executed successfully!
|
|
62
|
+
...
|
|
63
|
+
`,
|
|
64
|
+
`$ xano run exec -f script.xs -o json
|
|
65
|
+
{
|
|
66
|
+
"run": { ... }
|
|
67
|
+
}
|
|
68
|
+
`,
|
|
69
|
+
`$ xano run exec -f script.xs -a args.json
|
|
70
|
+
# Executes with input arguments from args.json
|
|
71
|
+
Executed successfully!
|
|
72
|
+
...
|
|
73
|
+
`,
|
|
74
|
+
`$ xano run exec -f script.xs --env API_KEY=secret --env DEBUG=true
|
|
75
|
+
# Executes with environment variable overrides
|
|
76
|
+
Executed successfully!
|
|
77
|
+
...
|
|
78
|
+
`,
|
|
79
|
+
];
|
|
80
|
+
async run() {
|
|
81
|
+
const { flags } = await this.parse(RunExec);
|
|
82
|
+
// Initialize with project required
|
|
83
|
+
await this.initRunCommandWithProject(flags.profile);
|
|
84
|
+
// Read XanoScript content
|
|
85
|
+
let xanoscript;
|
|
86
|
+
if (flags.file) {
|
|
87
|
+
if (this.isUrl(flags.file)) {
|
|
88
|
+
// Fetch URL content
|
|
89
|
+
try {
|
|
90
|
+
const response = await fetch(flags.file);
|
|
91
|
+
if (!response.ok) {
|
|
92
|
+
this.error(`Failed to fetch URL: ${response.status} ${response.statusText}`);
|
|
93
|
+
}
|
|
94
|
+
xanoscript = await response.text();
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
this.error(`Failed to fetch URL '${flags.file}': ${error}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else if (flags.edit) {
|
|
101
|
+
// If edit flag is set, copy to temp file and open in editor
|
|
102
|
+
const fileToRead = await this.editFile(flags.file);
|
|
103
|
+
xanoscript = fs.readFileSync(fileToRead, 'utf8');
|
|
104
|
+
// Clean up temp file
|
|
105
|
+
try {
|
|
106
|
+
fs.unlinkSync(fileToRead);
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Ignore cleanup errors
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
try {
|
|
114
|
+
xanoscript = fs.readFileSync(flags.file, 'utf8');
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
this.error(`Failed to read file '${flags.file}': ${error}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else if (flags.stdin) {
|
|
122
|
+
try {
|
|
123
|
+
xanoscript = await this.readStdin();
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
this.error(`Failed to read from stdin: ${error}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
this.error('Either --file or --stdin must be specified to provide XanoScript code');
|
|
131
|
+
}
|
|
132
|
+
// Validate xanoscript is not empty
|
|
133
|
+
if (!xanoscript || xanoscript.trim().length === 0) {
|
|
134
|
+
this.error('XanoScript content is empty');
|
|
135
|
+
}
|
|
136
|
+
// Load args from JSON file or URL if provided
|
|
137
|
+
let inputArgs;
|
|
138
|
+
if (flags.args) {
|
|
139
|
+
if (this.isUrl(flags.args)) {
|
|
140
|
+
try {
|
|
141
|
+
const response = await fetch(flags.args);
|
|
142
|
+
if (!response.ok) {
|
|
143
|
+
this.error(`Failed to fetch args URL: ${response.status} ${response.statusText}`);
|
|
144
|
+
}
|
|
145
|
+
const argsContent = await response.text();
|
|
146
|
+
inputArgs = JSON.parse(argsContent);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
this.error(`Failed to fetch or parse args '${flags.args}': ${error}`);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
try {
|
|
154
|
+
const argsContent = fs.readFileSync(flags.args, 'utf8');
|
|
155
|
+
inputArgs = JSON.parse(argsContent);
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
this.error(`Failed to read or parse args '${flags.args}': ${error}`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Parse env overrides
|
|
163
|
+
let envOverrides;
|
|
164
|
+
if (flags.env && flags.env.length > 0) {
|
|
165
|
+
envOverrides = {};
|
|
166
|
+
for (const envStr of flags.env) {
|
|
167
|
+
const eqIndex = envStr.indexOf('=');
|
|
168
|
+
if (eqIndex === -1) {
|
|
169
|
+
this.error(`Invalid env format '${envStr}'. Expected format: key=value`);
|
|
170
|
+
}
|
|
171
|
+
const key = envStr.slice(0, eqIndex);
|
|
172
|
+
const value = envStr.slice(eqIndex + 1);
|
|
173
|
+
envOverrides[key] = value;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Build query params
|
|
177
|
+
const queryParams = {};
|
|
178
|
+
if (inputArgs) {
|
|
179
|
+
queryParams.args = inputArgs;
|
|
180
|
+
}
|
|
181
|
+
if (envOverrides) {
|
|
182
|
+
queryParams.env = envOverrides;
|
|
183
|
+
}
|
|
184
|
+
// Execute via API
|
|
185
|
+
try {
|
|
186
|
+
const url = this.httpClient.buildProjectUrl('/run/exec', queryParams);
|
|
187
|
+
const result = await this.httpClient.postXanoScript(url, xanoscript);
|
|
188
|
+
// Output results
|
|
189
|
+
if (flags.output === 'json') {
|
|
190
|
+
this.outputJson(result);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
this.outputSummary(result);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
if (error instanceof Error) {
|
|
198
|
+
this.error(`Failed to execute: ${error.message}`);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
this.error(`Failed to execute: ${String(error)}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
outputSummary(result) {
|
|
206
|
+
this.log('Executed successfully!');
|
|
207
|
+
this.log('');
|
|
208
|
+
// Handle service-specific output
|
|
209
|
+
if (result.service) {
|
|
210
|
+
this.log(` Service ID: ${result.service.id}`);
|
|
211
|
+
this.log(` Run ID: ${result.service.run.id}`);
|
|
212
|
+
this.log('');
|
|
213
|
+
}
|
|
214
|
+
// Handle run/session info
|
|
215
|
+
if (result.run?.id) {
|
|
216
|
+
this.log(` Run ID: ${result.run.id}`);
|
|
217
|
+
}
|
|
218
|
+
if (result.run?.session) {
|
|
219
|
+
const session = result.run.session;
|
|
220
|
+
this.log(` Session ID: ${session.id}`);
|
|
221
|
+
this.log(` State: ${session.state}`);
|
|
222
|
+
this.log('');
|
|
223
|
+
}
|
|
224
|
+
// Handle timing info
|
|
225
|
+
const timing = result.run?.result || result.run?.session || result.result;
|
|
226
|
+
if (timing) {
|
|
227
|
+
const formatTime = (time) => time !== undefined ? `${(time * 1000).toFixed(2)}ms` : undefined;
|
|
228
|
+
const times = [
|
|
229
|
+
{ label: 'Total', value: formatTime(timing.total_time) },
|
|
230
|
+
{ label: 'Boot', value: formatTime(timing.boot_time) },
|
|
231
|
+
{ label: 'Main', value: formatTime(timing.main_time) },
|
|
232
|
+
{ label: 'Pre', value: formatTime(timing.pre_time) },
|
|
233
|
+
{ label: 'Post', value: formatTime(timing.post_time) },
|
|
234
|
+
].filter(t => t.value !== undefined);
|
|
235
|
+
if (times.length > 0) {
|
|
236
|
+
this.log(' Timing:');
|
|
237
|
+
for (const t of times) {
|
|
238
|
+
this.log(` ${t.label.padEnd(6)} ${t.value}`);
|
|
239
|
+
}
|
|
240
|
+
this.log('');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// Handle service endpoints
|
|
244
|
+
if (result.result?.endpoints && result.result.endpoints.length > 0) {
|
|
245
|
+
this.log(' Endpoints:');
|
|
246
|
+
for (const endpoint of result.result.endpoints) {
|
|
247
|
+
this.log(` ${endpoint.verb.padEnd(6)} ${endpoint.url}`);
|
|
248
|
+
if (endpoint.input.length > 0) {
|
|
249
|
+
for (const input of endpoint.input) {
|
|
250
|
+
const required = input.required ? '*' : '';
|
|
251
|
+
const nullable = input.nullable ? '?' : '';
|
|
252
|
+
this.log(` └─ ${input.name}${required}: ${input.type}${nullable} (${input.source})`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
this.log('');
|
|
257
|
+
}
|
|
258
|
+
// Handle metadata API
|
|
259
|
+
if (result.result?.metadata_api) {
|
|
260
|
+
this.log(' Metadata API:');
|
|
261
|
+
this.log(` ${result.result.metadata_api.url}`);
|
|
262
|
+
this.log('');
|
|
263
|
+
}
|
|
264
|
+
// Handle response
|
|
265
|
+
const response = result.run?.result?.response ?? result.run?.session?.response ?? result.result?.response;
|
|
266
|
+
if (response !== undefined) {
|
|
267
|
+
this.log(' Response:');
|
|
268
|
+
const responseStr = typeof response === 'string'
|
|
269
|
+
? response
|
|
270
|
+
: JSON.stringify(response, null, 2);
|
|
271
|
+
const indentedResponse = responseStr.split('\n').map((line) => ` ${line}`).join('\n');
|
|
272
|
+
this.log(indentedResponse);
|
|
273
|
+
}
|
|
274
|
+
// Handle problems/errors
|
|
275
|
+
if (result.run?.problems && result.run.problems.length > 0) {
|
|
276
|
+
this.log('');
|
|
277
|
+
this.log(' Problems:');
|
|
278
|
+
for (const problem of result.run.problems) {
|
|
279
|
+
this.log(` - [${problem.severity}] ${problem.message}`);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (result.run?.session?.error_msg) {
|
|
283
|
+
this.log('');
|
|
284
|
+
this.log(` Error: ${result.run.session.error_msg}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// Editor value comes from EDITOR/VISUAL environment variables, not user input
|
|
288
|
+
async editFile(filePath) {
|
|
289
|
+
const editor = process.env.EDITOR || process.env.VISUAL;
|
|
290
|
+
if (!editor) {
|
|
291
|
+
this.error('No editor configured. Please set the EDITOR or VISUAL environment variable.\n' +
|
|
292
|
+
'Example: export EDITOR=vim');
|
|
293
|
+
}
|
|
294
|
+
// Validate editor executable exists
|
|
295
|
+
try {
|
|
296
|
+
execSync(`which ${editor.split(' ')[0]}`, { stdio: 'ignore' });
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
this.error(`Editor '${editor}' not found. Please set EDITOR to a valid editor.\n` +
|
|
300
|
+
'Example: export EDITOR=vim');
|
|
301
|
+
}
|
|
302
|
+
// Read the original file
|
|
303
|
+
let originalContent;
|
|
304
|
+
try {
|
|
305
|
+
originalContent = fs.readFileSync(filePath, 'utf8');
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
this.error(`Failed to read file '${filePath}': ${error}`);
|
|
309
|
+
}
|
|
310
|
+
// Create a temporary file with the same extension
|
|
311
|
+
const ext = path.extname(filePath);
|
|
312
|
+
const tmpFile = path.join(os.tmpdir(), `xano-edit-${Date.now()}${ext}`);
|
|
313
|
+
// Copy content to temp file
|
|
314
|
+
try {
|
|
315
|
+
fs.writeFileSync(tmpFile, originalContent, 'utf8');
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
this.error(`Failed to create temporary file: ${error}`);
|
|
319
|
+
}
|
|
320
|
+
// Open the editor
|
|
321
|
+
try {
|
|
322
|
+
execSync(`${editor} ${tmpFile}`, { stdio: 'inherit' });
|
|
323
|
+
}
|
|
324
|
+
catch (error) {
|
|
325
|
+
try {
|
|
326
|
+
fs.unlinkSync(tmpFile);
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
// Ignore cleanup errors
|
|
330
|
+
}
|
|
331
|
+
this.error(`Editor exited with an error: ${error}`);
|
|
332
|
+
}
|
|
333
|
+
return tmpFile;
|
|
334
|
+
}
|
|
335
|
+
isUrl(str) {
|
|
336
|
+
return str.startsWith('http://') || str.startsWith('https://');
|
|
337
|
+
}
|
|
338
|
+
async readStdin() {
|
|
339
|
+
return new Promise((resolve, reject) => {
|
|
340
|
+
const chunks = [];
|
|
341
|
+
process.stdin.on('data', (chunk) => {
|
|
342
|
+
chunks.push(chunk);
|
|
343
|
+
});
|
|
344
|
+
process.stdin.on('end', () => {
|
|
345
|
+
resolve(Buffer.concat(chunks).toString('utf8'));
|
|
346
|
+
});
|
|
347
|
+
process.stdin.on('error', (error) => {
|
|
348
|
+
reject(error);
|
|
349
|
+
});
|
|
350
|
+
process.stdin.resume();
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import
|
|
2
|
-
export default class
|
|
1
|
+
import BaseRunCommand from '../../../lib/base-run-command.js';
|
|
2
|
+
export default class RunInfo extends BaseRunCommand {
|
|
3
3
|
static args: {};
|
|
4
4
|
static flags: {
|
|
5
5
|
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
6
|
stdin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
-
edit: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
7
|
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
8
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
9
|
};
|
|
11
10
|
static description: string;
|
|
12
11
|
static examples: string[];
|
|
13
12
|
run(): Promise<void>;
|
|
14
|
-
private
|
|
13
|
+
private outputSummary;
|
|
15
14
|
private isUrl;
|
|
16
15
|
private readStdin;
|
|
17
|
-
private loadCredentials;
|
|
18
16
|
}
|