@xano/cli 0.0.10 → 0.0.12
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 +1 -3
- package/dist/commands/ephemeral/run/job/index.js +54 -80
- package/dist/commands/ephemeral/run/service/index.d.ts +1 -3
- package/dist/commands/ephemeral/run/service/index.js +38 -60
- 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 +344 -301
- 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>;
|
|
@@ -14,8 +13,7 @@ export default class EphemeralRunJob extends BaseCommand {
|
|
|
14
13
|
static examples: string[];
|
|
15
14
|
run(): Promise<void>;
|
|
16
15
|
private editFile;
|
|
17
|
-
private readStdin;
|
|
18
16
|
private isUrl;
|
|
19
|
-
private
|
|
17
|
+
private readStdin;
|
|
20
18
|
private loadCredentials;
|
|
21
19
|
}
|
|
@@ -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,24 +88,16 @@ Job executed successfully!
|
|
|
97
88
|
if (!profile.access_token) {
|
|
98
89
|
this.error(`Profile '${profileName}' is missing access_token`);
|
|
99
90
|
}
|
|
100
|
-
//
|
|
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
|
-
// Read XanoScript content
|
|
91
|
+
// Read XanoScript content or use URL
|
|
114
92
|
let xanoscript;
|
|
93
|
+
let xanoscriptUrl;
|
|
115
94
|
if (flags.file) {
|
|
116
|
-
|
|
117
|
-
|
|
95
|
+
if (this.isUrl(flags.file)) {
|
|
96
|
+
// Pass URL directly to API
|
|
97
|
+
xanoscriptUrl = flags.file;
|
|
98
|
+
}
|
|
99
|
+
else if (flags.edit) {
|
|
100
|
+
// If edit flag is set, copy to temp file and open in editor
|
|
118
101
|
const fileToRead = await this.editFile(flags.file);
|
|
119
102
|
xanoscript = fs.readFileSync(fileToRead, 'utf8');
|
|
120
103
|
// Clean up temp file
|
|
@@ -126,7 +109,12 @@ Job executed successfully!
|
|
|
126
109
|
}
|
|
127
110
|
}
|
|
128
111
|
else {
|
|
129
|
-
|
|
112
|
+
try {
|
|
113
|
+
xanoscript = fs.readFileSync(flags.file, 'utf8');
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
this.error(`Failed to read file '${flags.file}': ${error}`);
|
|
117
|
+
}
|
|
130
118
|
}
|
|
131
119
|
}
|
|
132
120
|
else if (flags.stdin) {
|
|
@@ -141,45 +129,53 @@ Job executed successfully!
|
|
|
141
129
|
else {
|
|
142
130
|
this.error('Either --file or --stdin must be specified to provide XanoScript code');
|
|
143
131
|
}
|
|
144
|
-
// Validate xanoscript is not empty
|
|
145
|
-
if (!xanoscript || xanoscript.trim().length === 0) {
|
|
132
|
+
// Validate xanoscript is not empty (only if not using URL)
|
|
133
|
+
if (!xanoscriptUrl && (!xanoscript || xanoscript.trim().length === 0)) {
|
|
146
134
|
this.error('XanoScript content is empty');
|
|
147
135
|
}
|
|
148
|
-
// Load args from JSON file
|
|
136
|
+
// Load args from JSON file/URL if provided
|
|
149
137
|
let inputArgs;
|
|
138
|
+
let inputArgsUrl;
|
|
150
139
|
if (flags.args) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
140
|
+
if (this.isUrl(flags.args)) {
|
|
141
|
+
// Pass URL directly to API
|
|
142
|
+
inputArgsUrl = flags.args;
|
|
154
143
|
}
|
|
155
|
-
|
|
156
|
-
|
|
144
|
+
else {
|
|
145
|
+
try {
|
|
146
|
+
const argsContent = fs.readFileSync(flags.args, 'utf8');
|
|
147
|
+
inputArgs = JSON.parse(argsContent);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
this.error(`Failed to read or parse args '${flags.args}': ${error}`);
|
|
151
|
+
}
|
|
157
152
|
}
|
|
158
153
|
}
|
|
159
154
|
// Construct the API URL
|
|
160
|
-
const apiUrl = `${profile.instance_origin}/api:meta/beta/
|
|
161
|
-
// Build request body
|
|
162
|
-
let requestBody;
|
|
163
|
-
let contentType;
|
|
155
|
+
const apiUrl = `${profile.instance_origin}/api:meta/beta/ephemeral/job`;
|
|
156
|
+
// Build request body
|
|
164
157
|
const formData = new FormData();
|
|
165
|
-
|
|
166
|
-
|
|
158
|
+
if (xanoscriptUrl) {
|
|
159
|
+
formData.append('doc', xanoscriptUrl);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
formData.append('doc', xanoscript);
|
|
163
|
+
}
|
|
164
|
+
if (inputArgsUrl) {
|
|
165
|
+
formData.append('args', inputArgsUrl);
|
|
166
|
+
}
|
|
167
|
+
else if (inputArgs) {
|
|
167
168
|
formData.append('args', JSON.stringify(inputArgs));
|
|
168
169
|
}
|
|
169
|
-
requestBody = formData;
|
|
170
|
-
contentType = ''; // Let fetch set the boundary
|
|
170
|
+
const requestBody = formData;
|
|
171
171
|
// Run ephemeral job via API
|
|
172
172
|
try {
|
|
173
|
-
const headers = {
|
|
174
|
-
'accept': 'application/json',
|
|
175
|
-
'Authorization': `Bearer ${profile.access_token}`,
|
|
176
|
-
};
|
|
177
|
-
if (contentType) {
|
|
178
|
-
headers['Content-Type'] = contentType;
|
|
179
|
-
}
|
|
180
173
|
const response = await fetch(apiUrl, {
|
|
181
174
|
method: 'POST',
|
|
182
|
-
headers
|
|
175
|
+
headers: {
|
|
176
|
+
'accept': 'application/json',
|
|
177
|
+
'Authorization': `Bearer ${profile.access_token}`,
|
|
178
|
+
},
|
|
183
179
|
body: requestBody,
|
|
184
180
|
});
|
|
185
181
|
if (!response.ok) {
|
|
@@ -272,6 +268,9 @@ Job executed successfully!
|
|
|
272
268
|
}
|
|
273
269
|
return tmpFile;
|
|
274
270
|
}
|
|
271
|
+
isUrl(str) {
|
|
272
|
+
return str.startsWith('http://') || str.startsWith('https://');
|
|
273
|
+
}
|
|
275
274
|
async readStdin() {
|
|
276
275
|
return new Promise((resolve, reject) => {
|
|
277
276
|
const chunks = [];
|
|
@@ -288,31 +287,6 @@ Job executed successfully!
|
|
|
288
287
|
process.stdin.resume();
|
|
289
288
|
});
|
|
290
289
|
}
|
|
291
|
-
isUrl(str) {
|
|
292
|
-
return str.startsWith('http://') || str.startsWith('https://');
|
|
293
|
-
}
|
|
294
|
-
async fetchContent(source) {
|
|
295
|
-
if (this.isUrl(source)) {
|
|
296
|
-
try {
|
|
297
|
-
const response = await fetch(source);
|
|
298
|
-
if (!response.ok) {
|
|
299
|
-
this.error(`Failed to fetch '${source}': ${response.status} ${response.statusText}`);
|
|
300
|
-
}
|
|
301
|
-
return await response.text();
|
|
302
|
-
}
|
|
303
|
-
catch (error) {
|
|
304
|
-
this.error(`Failed to fetch '${source}': ${error}`);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
try {
|
|
309
|
-
return fs.readFileSync(source, 'utf8');
|
|
310
|
-
}
|
|
311
|
-
catch (error) {
|
|
312
|
-
this.error(`Failed to read file '${source}': ${error}`);
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
290
|
loadCredentials() {
|
|
317
291
|
const configDir = path.join(os.homedir(), '.xano');
|
|
318
292
|
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
@@ -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>;
|
|
@@ -13,8 +12,7 @@ export default class EphemeralRunService extends BaseCommand {
|
|
|
13
12
|
static examples: string[];
|
|
14
13
|
run(): Promise<void>;
|
|
15
14
|
private editFile;
|
|
16
|
-
private readStdin;
|
|
17
15
|
private isUrl;
|
|
18
|
-
private
|
|
16
|
+
private readStdin;
|
|
19
17
|
private loadCredentials;
|
|
20
18
|
}
|
|
@@ -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,24 +78,16 @@ Service created successfully!
|
|
|
87
78
|
if (!profile.access_token) {
|
|
88
79
|
this.error(`Profile '${profileName}' is missing access_token`);
|
|
89
80
|
}
|
|
90
|
-
//
|
|
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
|
-
// Read XanoScript content
|
|
81
|
+
// Read XanoScript content or use URL
|
|
104
82
|
let xanoscript;
|
|
83
|
+
let xanoscriptUrl;
|
|
105
84
|
if (flags.file) {
|
|
106
|
-
|
|
107
|
-
|
|
85
|
+
if (this.isUrl(flags.file)) {
|
|
86
|
+
// Pass URL directly to API
|
|
87
|
+
xanoscriptUrl = flags.file;
|
|
88
|
+
}
|
|
89
|
+
else if (flags.edit) {
|
|
90
|
+
// If edit flag is set, copy to temp file and open in editor
|
|
108
91
|
const fileToRead = await this.editFile(flags.file);
|
|
109
92
|
xanoscript = fs.readFileSync(fileToRead, 'utf8');
|
|
110
93
|
// Clean up temp file
|
|
@@ -116,7 +99,12 @@ Service created successfully!
|
|
|
116
99
|
}
|
|
117
100
|
}
|
|
118
101
|
else {
|
|
119
|
-
|
|
102
|
+
try {
|
|
103
|
+
xanoscript = fs.readFileSync(flags.file, 'utf8');
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
this.error(`Failed to read file '${flags.file}': ${error}`);
|
|
107
|
+
}
|
|
120
108
|
}
|
|
121
109
|
}
|
|
122
110
|
else if (flags.stdin) {
|
|
@@ -131,22 +119,29 @@ Service created successfully!
|
|
|
131
119
|
else {
|
|
132
120
|
this.error('Either --file or --stdin must be specified to provide XanoScript code');
|
|
133
121
|
}
|
|
134
|
-
// Validate xanoscript is not empty
|
|
135
|
-
if (!xanoscript || xanoscript.trim().length === 0) {
|
|
122
|
+
// Validate xanoscript is not empty (only if not using URL)
|
|
123
|
+
if (!xanoscriptUrl && (!xanoscript || xanoscript.trim().length === 0)) {
|
|
136
124
|
this.error('XanoScript content is empty');
|
|
137
125
|
}
|
|
138
126
|
// Construct the API URL
|
|
139
|
-
const apiUrl = `${profile.instance_origin}/api:meta/beta/
|
|
127
|
+
const apiUrl = `${profile.instance_origin}/api:meta/beta/ephemeral/service`;
|
|
128
|
+
// Build request body
|
|
129
|
+
const formData = new FormData();
|
|
130
|
+
if (xanoscriptUrl) {
|
|
131
|
+
formData.append('doc', xanoscriptUrl);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
formData.append('doc', xanoscript);
|
|
135
|
+
}
|
|
140
136
|
// Run ephemeral service via API
|
|
141
137
|
try {
|
|
142
138
|
const response = await fetch(apiUrl, {
|
|
143
139
|
method: 'POST',
|
|
144
140
|
headers: {
|
|
145
141
|
'accept': 'application/json',
|
|
146
|
-
'Content-Type': 'text/x-xanoscript',
|
|
147
142
|
'Authorization': `Bearer ${profile.access_token}`,
|
|
148
143
|
},
|
|
149
|
-
body:
|
|
144
|
+
body: formData,
|
|
150
145
|
});
|
|
151
146
|
if (!response.ok) {
|
|
152
147
|
const errorText = await response.text();
|
|
@@ -182,6 +177,11 @@ Service created successfully!
|
|
|
182
177
|
}
|
|
183
178
|
}
|
|
184
179
|
}
|
|
180
|
+
this.log('');
|
|
181
|
+
}
|
|
182
|
+
if (result.result.metadata_api) {
|
|
183
|
+
this.log(' Metadata API:');
|
|
184
|
+
this.log(` ${result.result.metadata_api.url}`);
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
}
|
|
@@ -244,6 +244,9 @@ Service created successfully!
|
|
|
244
244
|
}
|
|
245
245
|
return tmpFile;
|
|
246
246
|
}
|
|
247
|
+
isUrl(str) {
|
|
248
|
+
return str.startsWith('http://') || str.startsWith('https://');
|
|
249
|
+
}
|
|
247
250
|
async readStdin() {
|
|
248
251
|
return new Promise((resolve, reject) => {
|
|
249
252
|
const chunks = [];
|
|
@@ -260,31 +263,6 @@ Service created successfully!
|
|
|
260
263
|
process.stdin.resume();
|
|
261
264
|
});
|
|
262
265
|
}
|
|
263
|
-
isUrl(str) {
|
|
264
|
-
return str.startsWith('http://') || str.startsWith('https://');
|
|
265
|
-
}
|
|
266
|
-
async fetchContent(source) {
|
|
267
|
-
if (this.isUrl(source)) {
|
|
268
|
-
try {
|
|
269
|
-
const response = await fetch(source);
|
|
270
|
-
if (!response.ok) {
|
|
271
|
-
this.error(`Failed to fetch '${source}': ${response.status} ${response.statusText}`);
|
|
272
|
-
}
|
|
273
|
-
return await response.text();
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
this.error(`Failed to fetch '${source}': ${error}`);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
try {
|
|
281
|
-
return fs.readFileSync(source, 'utf8');
|
|
282
|
-
}
|
|
283
|
-
catch (error) {
|
|
284
|
-
this.error(`Failed to read file '${source}': ${error}`);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
266
|
loadCredentials() {
|
|
289
267
|
const configDir = path.join(os.homedir(), '.xano');
|
|
290
268
|
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
@@ -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
|
+
}
|