@xano/cli 0.0.11 → 0.0.13
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/dist/commands/ephemeral/run/job/index.d.ts +0 -1
- package/dist/commands/ephemeral/run/job/index.js +6 -28
- package/dist/commands/ephemeral/run/service/index.d.ts +0 -1
- package/dist/commands/ephemeral/run/service/index.js +5 -27
- package/dist/commands/profile/edit/index.d.ts +4 -3
- package/dist/commands/profile/edit/index.js +20 -13
- package/dist/commands/profile/me/index.d.ts +12 -0
- package/dist/commands/profile/me/index.js +146 -0
- package/oclif.manifest.json +393 -350
- package/package.json +1 -1
|
@@ -2,7 +2,6 @@ import BaseCommand from '../../../../base-command.js';
|
|
|
2
2
|
export default class EphemeralRunJob extends BaseCommand {
|
|
3
3
|
static args: {};
|
|
4
4
|
static flags: {
|
|
5
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
5
|
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
6
|
stdin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
7
|
edit: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -9,11 +9,6 @@ export default class EphemeralRunJob extends BaseCommand {
|
|
|
9
9
|
static args = {};
|
|
10
10
|
static flags = {
|
|
11
11
|
...BaseCommand.baseFlags,
|
|
12
|
-
workspace: Flags.string({
|
|
13
|
-
char: 'w',
|
|
14
|
-
description: 'Workspace ID (optional if set in profile)',
|
|
15
|
-
required: false,
|
|
16
|
-
}),
|
|
17
12
|
file: Flags.string({
|
|
18
13
|
char: 'f',
|
|
19
14
|
description: 'Path or URL to file containing XanoScript code',
|
|
@@ -47,32 +42,28 @@ export default class EphemeralRunJob extends BaseCommand {
|
|
|
47
42
|
required: false,
|
|
48
43
|
}),
|
|
49
44
|
};
|
|
50
|
-
static description = 'Run an ephemeral job
|
|
45
|
+
static description = 'Run an ephemeral job';
|
|
51
46
|
static examples = [
|
|
52
|
-
`$ xano ephemeral:run:job -w 1 -f script.xs
|
|
53
|
-
Job executed successfully!
|
|
54
|
-
...
|
|
55
|
-
`,
|
|
56
47
|
`$ xano ephemeral:run:job -f script.xs
|
|
57
48
|
Job executed successfully!
|
|
58
49
|
...
|
|
59
50
|
`,
|
|
60
|
-
`$ xano ephemeral:run:job -
|
|
51
|
+
`$ xano ephemeral:run:job -f script.xs --edit
|
|
61
52
|
# Opens script.xs in $EDITOR, then runs job with edited content
|
|
62
53
|
Job executed successfully!
|
|
63
54
|
...
|
|
64
55
|
`,
|
|
65
|
-
`$ cat script.xs | xano ephemeral:run:job
|
|
56
|
+
`$ cat script.xs | xano ephemeral:run:job --stdin
|
|
66
57
|
Job executed successfully!
|
|
67
58
|
...
|
|
68
59
|
`,
|
|
69
|
-
`$ xano ephemeral:run:job -
|
|
60
|
+
`$ xano ephemeral:run:job -f script.xs -o json
|
|
70
61
|
{
|
|
71
62
|
"job": { "id": 1, "run": { "id": 1 } },
|
|
72
63
|
"result": { ... }
|
|
73
64
|
}
|
|
74
65
|
`,
|
|
75
|
-
`$ xano ephemeral:run:job -
|
|
66
|
+
`$ xano ephemeral:run:job -f script.xs -a args.json
|
|
76
67
|
# Runs job with input arguments from args.json
|
|
77
68
|
Job executed successfully!
|
|
78
69
|
...
|
|
@@ -97,19 +88,6 @@ Job executed successfully!
|
|
|
97
88
|
if (!profile.access_token) {
|
|
98
89
|
this.error(`Profile '${profileName}' is missing access_token`);
|
|
99
90
|
}
|
|
100
|
-
// Determine workspace_id from flag or profile
|
|
101
|
-
let workspaceId;
|
|
102
|
-
if (flags.workspace) {
|
|
103
|
-
workspaceId = flags.workspace;
|
|
104
|
-
}
|
|
105
|
-
else if (profile.workspace) {
|
|
106
|
-
workspaceId = profile.workspace;
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
this.error(`Workspace ID is required. Either:\n` +
|
|
110
|
-
` 1. Provide it as a flag: xano ephemeral:run:job -w <workspace_id>\n` +
|
|
111
|
-
` 2. Set it in your profile using: xano profile:edit ${profileName} -w <workspace_id>`);
|
|
112
|
-
}
|
|
113
91
|
// Read XanoScript content or use URL
|
|
114
92
|
let xanoscript;
|
|
115
93
|
let xanoscriptUrl;
|
|
@@ -174,7 +152,7 @@ Job executed successfully!
|
|
|
174
152
|
}
|
|
175
153
|
}
|
|
176
154
|
// Construct the API URL
|
|
177
|
-
const apiUrl = `${profile.instance_origin}/api:meta/beta/
|
|
155
|
+
const apiUrl = `${profile.instance_origin}/api:meta/beta/ephemeral/job`;
|
|
178
156
|
// Build request body
|
|
179
157
|
const formData = new FormData();
|
|
180
158
|
if (xanoscriptUrl) {
|
|
@@ -2,7 +2,6 @@ import BaseCommand from '../../../../base-command.js';
|
|
|
2
2
|
export default class EphemeralRunService extends BaseCommand {
|
|
3
3
|
static args: {};
|
|
4
4
|
static flags: {
|
|
5
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
5
|
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
6
|
stdin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
7
|
edit: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -9,11 +9,6 @@ export default class EphemeralRunService extends BaseCommand {
|
|
|
9
9
|
static args = {};
|
|
10
10
|
static flags = {
|
|
11
11
|
...BaseCommand.baseFlags,
|
|
12
|
-
workspace: Flags.string({
|
|
13
|
-
char: 'w',
|
|
14
|
-
description: 'Workspace ID (optional if set in profile)',
|
|
15
|
-
required: false,
|
|
16
|
-
}),
|
|
17
12
|
file: Flags.string({
|
|
18
13
|
char: 'f',
|
|
19
14
|
description: 'Path or URL to file containing XanoScript code',
|
|
@@ -42,26 +37,22 @@ export default class EphemeralRunService extends BaseCommand {
|
|
|
42
37
|
options: ['summary', 'json'],
|
|
43
38
|
}),
|
|
44
39
|
};
|
|
45
|
-
static description = 'Run an ephemeral service
|
|
40
|
+
static description = 'Run an ephemeral service';
|
|
46
41
|
static examples = [
|
|
47
|
-
`$ xano ephemeral:run:service -w 1 -f service.xs
|
|
48
|
-
Service created successfully!
|
|
49
|
-
...
|
|
50
|
-
`,
|
|
51
42
|
`$ xano ephemeral:run:service -f service.xs
|
|
52
43
|
Service created successfully!
|
|
53
44
|
...
|
|
54
45
|
`,
|
|
55
|
-
`$ xano ephemeral:run:service -
|
|
46
|
+
`$ xano ephemeral:run:service -f service.xs --edit
|
|
56
47
|
# Opens service.xs in $EDITOR, then creates service with edited content
|
|
57
48
|
Service created successfully!
|
|
58
49
|
...
|
|
59
50
|
`,
|
|
60
|
-
`$ cat service.xs | xano ephemeral:run:service
|
|
51
|
+
`$ cat service.xs | xano ephemeral:run:service --stdin
|
|
61
52
|
Service created successfully!
|
|
62
53
|
...
|
|
63
54
|
`,
|
|
64
|
-
`$ xano ephemeral:run:service -
|
|
55
|
+
`$ xano ephemeral:run:service -f service.xs -o json
|
|
65
56
|
{
|
|
66
57
|
"service": { "id": 1 },
|
|
67
58
|
...
|
|
@@ -87,19 +78,6 @@ Service created successfully!
|
|
|
87
78
|
if (!profile.access_token) {
|
|
88
79
|
this.error(`Profile '${profileName}' is missing access_token`);
|
|
89
80
|
}
|
|
90
|
-
// Determine workspace_id from flag or profile
|
|
91
|
-
let workspaceId;
|
|
92
|
-
if (flags.workspace) {
|
|
93
|
-
workspaceId = flags.workspace;
|
|
94
|
-
}
|
|
95
|
-
else if (profile.workspace) {
|
|
96
|
-
workspaceId = profile.workspace;
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
this.error(`Workspace ID is required. Either:\n` +
|
|
100
|
-
` 1. Provide it as a flag: xano ephemeral:run:service -w <workspace_id>\n` +
|
|
101
|
-
` 2. Set it in your profile using: xano profile:edit ${profileName} -w <workspace_id>`);
|
|
102
|
-
}
|
|
103
81
|
// Read XanoScript content or use URL
|
|
104
82
|
let xanoscript;
|
|
105
83
|
let xanoscriptUrl;
|
|
@@ -146,7 +124,7 @@ Service created successfully!
|
|
|
146
124
|
this.error('XanoScript content is empty');
|
|
147
125
|
}
|
|
148
126
|
// Construct the API URL
|
|
149
|
-
const apiUrl = `${profile.instance_origin}/api:meta/beta/
|
|
127
|
+
const apiUrl = `${profile.instance_origin}/api:meta/beta/ephemeral/service`;
|
|
150
128
|
// Build request body
|
|
151
129
|
const formData = new FormData();
|
|
152
130
|
if (xanoscriptUrl) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
export default class ProfileEdit extends
|
|
1
|
+
import BaseCommand from '../../../base-command.js';
|
|
2
|
+
export default class ProfileEdit extends BaseCommand {
|
|
3
3
|
static args: {
|
|
4
|
-
name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
4
|
+
name: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
5
|
};
|
|
6
6
|
static flags: {
|
|
7
7
|
account_origin: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -11,6 +11,7 @@ export default class ProfileEdit extends Command {
|
|
|
11
11
|
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
12
|
'remove-workspace': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
13
|
'remove-branch': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
15
|
};
|
|
15
16
|
static description: string;
|
|
16
17
|
static examples: string[];
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import { Args,
|
|
1
|
+
import { Args, Flags } from '@oclif/core';
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import * as os from 'node:os';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import * as yaml from 'js-yaml';
|
|
6
|
-
|
|
6
|
+
import BaseCommand from '../../../base-command.js';
|
|
7
|
+
export default class ProfileEdit extends BaseCommand {
|
|
7
8
|
static args = {
|
|
8
9
|
name: Args.string({
|
|
9
|
-
description: 'Profile name to edit',
|
|
10
|
-
required:
|
|
10
|
+
description: 'Profile name to edit (uses default profile if not specified)',
|
|
11
|
+
required: false,
|
|
11
12
|
}),
|
|
12
13
|
};
|
|
13
14
|
static flags = {
|
|
15
|
+
...BaseCommand.baseFlags,
|
|
14
16
|
account_origin: Flags.string({
|
|
15
17
|
char: 'a',
|
|
16
18
|
description: 'Update account origin URL',
|
|
@@ -49,21 +51,26 @@ export default class ProfileEdit extends Command {
|
|
|
49
51
|
};
|
|
50
52
|
static description = 'Edit an existing profile configuration';
|
|
51
53
|
static examples = [
|
|
54
|
+
`$ xano profile:edit --access_token new_token123
|
|
55
|
+
Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
56
|
+
`,
|
|
52
57
|
`$ xano profile:edit production --access_token new_token123
|
|
53
58
|
Profile 'production' updated successfully at ~/.xano/credentials.yaml
|
|
54
59
|
`,
|
|
55
60
|
`$ xano profile:edit staging -i https://new-staging-instance.xano.com -t new_token456
|
|
56
61
|
Profile 'staging' updated successfully at ~/.xano/credentials.yaml
|
|
57
62
|
`,
|
|
58
|
-
`$ xano profile:edit
|
|
59
|
-
Profile '
|
|
63
|
+
`$ xano profile:edit -b new-branch
|
|
64
|
+
Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
60
65
|
`,
|
|
61
|
-
`$ xano profile:edit
|
|
62
|
-
Profile '
|
|
66
|
+
`$ xano profile:edit --remove-branch
|
|
67
|
+
Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
63
68
|
`,
|
|
64
69
|
];
|
|
65
70
|
async run() {
|
|
66
71
|
const { args, flags } = await this.parse(ProfileEdit);
|
|
72
|
+
// Use provided name or default profile
|
|
73
|
+
const profileName = args.name || this.getDefaultProfile();
|
|
67
74
|
const configDir = path.join(os.homedir(), '.xano');
|
|
68
75
|
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
69
76
|
// Check if credentials file exists
|
|
@@ -84,11 +91,11 @@ Profile 'dev' updated successfully at ~/.xano/credentials.yaml
|
|
|
84
91
|
this.error(`Failed to parse credentials file: ${error}`);
|
|
85
92
|
}
|
|
86
93
|
// Check if profile exists
|
|
87
|
-
if (!(
|
|
88
|
-
this.error(`Profile '${
|
|
94
|
+
if (!(profileName in credentials.profiles)) {
|
|
95
|
+
this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}`);
|
|
89
96
|
}
|
|
90
97
|
// Get the existing profile
|
|
91
|
-
const existingProfile = credentials.profiles[
|
|
98
|
+
const existingProfile = credentials.profiles[profileName];
|
|
92
99
|
// Check if any flags were provided
|
|
93
100
|
const hasFlags = flags.account_origin || flags.instance_origin || flags.access_token ||
|
|
94
101
|
flags.workspace || flags.branch || flags['remove-workspace'] || flags['remove-branch'];
|
|
@@ -111,7 +118,7 @@ Profile 'dev' updated successfully at ~/.xano/credentials.yaml
|
|
|
111
118
|
if (flags['remove-branch']) {
|
|
112
119
|
delete updatedProfile.branch;
|
|
113
120
|
}
|
|
114
|
-
credentials.profiles[
|
|
121
|
+
credentials.profiles[profileName] = updatedProfile;
|
|
115
122
|
// Write the updated credentials back to the file
|
|
116
123
|
try {
|
|
117
124
|
const yamlContent = yaml.dump(credentials, {
|
|
@@ -120,7 +127,7 @@ Profile 'dev' updated successfully at ~/.xano/credentials.yaml
|
|
|
120
127
|
noRefs: true,
|
|
121
128
|
});
|
|
122
129
|
fs.writeFileSync(credentialsPath, yamlContent, 'utf8');
|
|
123
|
-
this.log(`Profile '${
|
|
130
|
+
this.log(`Profile '${profileName}' updated successfully at ${credentialsPath}`);
|
|
124
131
|
}
|
|
125
132
|
catch (error) {
|
|
126
133
|
this.error(`Failed to write credentials file: ${error}`);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BaseCommand from '../../../base-command.js';
|
|
2
|
+
export default class ProfileMe extends BaseCommand {
|
|
3
|
+
static flags: {
|
|
4
|
+
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
5
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
|
+
};
|
|
7
|
+
static description: string;
|
|
8
|
+
static examples: string[];
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
private loadCredentials;
|
|
11
|
+
private formatKey;
|
|
12
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as os from 'node:os';
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import * as yaml from 'js-yaml';
|
|
6
|
+
import BaseCommand from '../../../base-command.js';
|
|
7
|
+
export default class ProfileMe extends BaseCommand {
|
|
8
|
+
static flags = {
|
|
9
|
+
...BaseCommand.baseFlags,
|
|
10
|
+
output: Flags.string({
|
|
11
|
+
char: 'o',
|
|
12
|
+
description: 'Output format',
|
|
13
|
+
required: false,
|
|
14
|
+
default: 'summary',
|
|
15
|
+
options: ['summary', 'json'],
|
|
16
|
+
}),
|
|
17
|
+
};
|
|
18
|
+
static description = 'Get information about the currently authenticated user';
|
|
19
|
+
static examples = [
|
|
20
|
+
`$ xano profile:me
|
|
21
|
+
User Information:
|
|
22
|
+
ID: 1
|
|
23
|
+
Name: John Doe
|
|
24
|
+
Email: john@example.com
|
|
25
|
+
`,
|
|
26
|
+
`$ xano profile:me --profile production
|
|
27
|
+
User Information:
|
|
28
|
+
ID: 42
|
|
29
|
+
Name: Admin User
|
|
30
|
+
Email: admin@example.com
|
|
31
|
+
`,
|
|
32
|
+
`$ xano profile:me --output json
|
|
33
|
+
{
|
|
34
|
+
"id": 1,
|
|
35
|
+
"name": "John Doe",
|
|
36
|
+
"email": "john@example.com"
|
|
37
|
+
}
|
|
38
|
+
`,
|
|
39
|
+
];
|
|
40
|
+
async run() {
|
|
41
|
+
const { flags } = await this.parse(ProfileMe);
|
|
42
|
+
// Get profile name (default or from flag/env)
|
|
43
|
+
const profileName = flags.profile || this.getDefaultProfile();
|
|
44
|
+
// Load credentials
|
|
45
|
+
const credentials = this.loadCredentials();
|
|
46
|
+
// Get the profile configuration
|
|
47
|
+
if (!(profileName in credentials.profiles)) {
|
|
48
|
+
this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}\n` +
|
|
49
|
+
`Create a profile using 'xano profile:create'`);
|
|
50
|
+
}
|
|
51
|
+
const profile = credentials.profiles[profileName];
|
|
52
|
+
// Validate required fields
|
|
53
|
+
if (!profile.instance_origin) {
|
|
54
|
+
this.error(`Profile '${profileName}' is missing instance_origin`);
|
|
55
|
+
}
|
|
56
|
+
if (!profile.access_token) {
|
|
57
|
+
this.error(`Profile '${profileName}' is missing access_token`);
|
|
58
|
+
}
|
|
59
|
+
// Construct the API URL
|
|
60
|
+
const apiUrl = `${profile.instance_origin}/api:meta/auth/me`;
|
|
61
|
+
// Fetch user info from the API
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch(apiUrl, {
|
|
64
|
+
method: 'GET',
|
|
65
|
+
headers: {
|
|
66
|
+
'accept': 'application/json',
|
|
67
|
+
'Authorization': `Bearer ${profile.access_token}`,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
const errorText = await response.text();
|
|
72
|
+
this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
|
|
73
|
+
}
|
|
74
|
+
const data = await response.json();
|
|
75
|
+
// Output results
|
|
76
|
+
if (flags.output === 'json') {
|
|
77
|
+
this.log(JSON.stringify(data, null, 2));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// summary format
|
|
81
|
+
this.log('User Information:');
|
|
82
|
+
if (data.id !== undefined) {
|
|
83
|
+
this.log(` ID: ${data.id}`);
|
|
84
|
+
}
|
|
85
|
+
if (data.name) {
|
|
86
|
+
this.log(` Name: ${data.name}`);
|
|
87
|
+
}
|
|
88
|
+
if (data.email) {
|
|
89
|
+
this.log(` Email: ${data.email}`);
|
|
90
|
+
}
|
|
91
|
+
if (data.created_at) {
|
|
92
|
+
const date = new Date(data.created_at * 1000);
|
|
93
|
+
this.log(` Created: ${date.toISOString()}`);
|
|
94
|
+
}
|
|
95
|
+
// Display any other fields that aren't already shown
|
|
96
|
+
const knownFields = ['id', 'name', 'email', 'created_at'];
|
|
97
|
+
for (const [key, value] of Object.entries(data)) {
|
|
98
|
+
if (!knownFields.includes(key) && value !== null && value !== undefined) {
|
|
99
|
+
if (typeof value === 'object') {
|
|
100
|
+
this.log(` ${this.formatKey(key)}: ${JSON.stringify(value)}`);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
this.log(` ${this.formatKey(key)}: ${value}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (error instanceof Error) {
|
|
111
|
+
this.error(`Failed to fetch user info: ${error.message}`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
this.error(`Failed to fetch user info: ${String(error)}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
loadCredentials() {
|
|
119
|
+
const configDir = path.join(os.homedir(), '.xano');
|
|
120
|
+
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
121
|
+
// Check if credentials file exists
|
|
122
|
+
if (!fs.existsSync(credentialsPath)) {
|
|
123
|
+
this.error(`Credentials file not found at ${credentialsPath}\n` +
|
|
124
|
+
`Create a profile using 'xano profile:create'`);
|
|
125
|
+
}
|
|
126
|
+
// Read credentials file
|
|
127
|
+
try {
|
|
128
|
+
const fileContent = fs.readFileSync(credentialsPath, 'utf8');
|
|
129
|
+
const parsed = yaml.load(fileContent);
|
|
130
|
+
if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
|
|
131
|
+
this.error('Credentials file has invalid format.');
|
|
132
|
+
}
|
|
133
|
+
return parsed;
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
this.error(`Failed to parse credentials file: ${error}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
formatKey(key) {
|
|
140
|
+
// Convert snake_case to Title Case
|
|
141
|
+
return key
|
|
142
|
+
.split('_')
|
|
143
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
144
|
+
.join(' ');
|
|
145
|
+
}
|
|
146
|
+
}
|