@xano/cli 0.0.24 → 0.0.26
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/base-command.d.ts +1 -3
- package/dist/base-command.js +5 -12
- package/dist/commands/function/create/index.d.ts +6 -7
- package/dist/commands/function/create/index.js +55 -55
- package/dist/commands/function/edit/index.d.ts +10 -11
- package/dist/commands/function/edit/index.js +162 -155
- package/dist/commands/function/get/index.d.ts +5 -6
- package/dist/commands/function/get/index.js +60 -55
- package/dist/commands/function/list/index.d.ts +5 -6
- package/dist/commands/function/list/index.js +52 -52
- package/dist/commands/profile/create/index.d.ts +6 -6
- package/dist/commands/profile/create/index.js +37 -37
- package/dist/commands/profile/delete/index.d.ts +2 -2
- package/dist/commands/profile/delete/index.js +9 -9
- package/dist/commands/profile/edit/index.d.ts +7 -8
- package/dist/commands/profile/edit/index.js +48 -48
- package/dist/commands/profile/get-default/index.js +1 -1
- package/dist/commands/profile/list/index.d.ts +2 -2
- package/dist/commands/profile/list/index.js +9 -9
- package/dist/commands/profile/me/index.d.ts +3 -4
- package/dist/commands/profile/me/index.js +21 -21
- package/dist/commands/profile/project/index.js +1 -1
- package/dist/commands/profile/set-default/index.js +1 -1
- package/dist/commands/profile/token/index.js +1 -1
- package/dist/commands/profile/wizard/index.d.ts +4 -5
- package/dist/commands/profile/wizard/index.js +108 -142
- package/dist/commands/run/env/delete/index.d.ts +2 -3
- package/dist/commands/run/env/delete/index.js +10 -10
- package/dist/commands/run/env/get/index.d.ts +2 -3
- package/dist/commands/run/env/get/index.js +11 -11
- package/dist/commands/run/env/list/index.d.ts +2 -3
- package/dist/commands/run/env/list/index.js +19 -17
- package/dist/commands/run/env/set/index.d.ts +2 -3
- package/dist/commands/run/env/set/index.js +5 -5
- package/dist/commands/run/exec/index.d.ts +8 -19
- package/dist/commands/run/exec/index.js +108 -186
- package/dist/commands/run/info/index.d.ts +4 -5
- package/dist/commands/run/info/index.js +27 -27
- package/dist/commands/run/projects/create/index.d.ts +3 -4
- package/dist/commands/run/projects/create/index.js +23 -23
- package/dist/commands/run/projects/delete/index.d.ts +2 -3
- package/dist/commands/run/projects/delete/index.js +10 -10
- package/dist/commands/run/projects/list/index.d.ts +2 -3
- package/dist/commands/run/projects/list/index.js +12 -12
- package/dist/commands/run/projects/update/index.d.ts +3 -4
- package/dist/commands/run/projects/update/index.js +21 -21
- package/dist/commands/run/secrets/delete/index.d.ts +2 -3
- package/dist/commands/run/secrets/delete/index.js +10 -10
- package/dist/commands/run/secrets/get/index.d.ts +2 -3
- package/dist/commands/run/secrets/get/index.js +11 -11
- package/dist/commands/run/secrets/list/index.d.ts +2 -3
- package/dist/commands/run/secrets/list/index.js +24 -22
- package/dist/commands/run/secrets/set/index.d.ts +3 -4
- package/dist/commands/run/secrets/set/index.js +16 -16
- package/dist/commands/run/sessions/delete/index.d.ts +2 -3
- package/dist/commands/run/sessions/delete/index.js +10 -10
- package/dist/commands/run/sessions/get/index.d.ts +2 -3
- package/dist/commands/run/sessions/get/index.js +11 -11
- package/dist/commands/run/sessions/list/index.d.ts +2 -3
- package/dist/commands/run/sessions/list/index.js +11 -11
- package/dist/commands/run/sessions/start/index.d.ts +2 -3
- package/dist/commands/run/sessions/start/index.js +11 -11
- package/dist/commands/run/sessions/stop/index.d.ts +2 -3
- package/dist/commands/run/sessions/stop/index.js +11 -11
- package/dist/commands/run/sink/get/index.d.ts +2 -3
- package/dist/commands/run/sink/get/index.js +11 -11
- package/dist/commands/static_host/build/create/index.d.ts +4 -5
- package/dist/commands/static_host/build/create/index.js +33 -33
- package/dist/commands/static_host/build/get/index.d.ts +4 -5
- package/dist/commands/static_host/build/get/index.js +20 -20
- package/dist/commands/static_host/build/list/index.d.ts +3 -4
- package/dist/commands/static_host/build/list/index.js +31 -31
- package/dist/commands/static_host/list/index.d.ts +3 -4
- package/dist/commands/static_host/list/index.js +31 -31
- package/dist/commands/workspace/list/index.d.ts +2 -3
- package/dist/commands/workspace/list/index.js +15 -15
- package/dist/commands/workspace/pull/index.d.ts +4 -5
- package/dist/commands/workspace/pull/index.js +52 -47
- package/dist/commands/workspace/push/index.d.ts +0 -1
- package/dist/commands/workspace/push/index.js +4 -4
- package/dist/help.d.ts +1 -1
- package/dist/lib/base-run-command.d.ts +6 -6
- package/dist/lib/base-run-command.js +6 -8
- package/dist/lib/run-http-client.d.ts +18 -24
- package/dist/lib/run-http-client.js +61 -96
- package/dist/lib/run-types.d.ts +80 -80
- package/oclif.manifest.json +888 -2031
- package/package.json +5 -2
- package/dist/commands/branch/create/index.d.ts +0 -17
- package/dist/commands/branch/create/index.js +0 -164
- package/dist/commands/branch/delete/index.d.ts +0 -18
- package/dist/commands/branch/delete/index.js +0 -156
- package/dist/commands/branch/edit/index.d.ts +0 -19
- package/dist/commands/branch/edit/index.js +0 -166
- package/dist/commands/branch/get/index.d.ts +0 -16
- package/dist/commands/branch/get/index.js +0 -135
- package/dist/commands/branch/list/index.d.ts +0 -18
- package/dist/commands/branch/list/index.js +0 -138
- package/dist/commands/branch/set-live/index.d.ts +0 -18
- package/dist/commands/branch/set-live/index.js +0 -155
- package/dist/commands/workspace/create/index.d.ts +0 -14
- package/dist/commands/workspace/create/index.js +0 -131
- package/dist/commands/workspace/delete/index.d.ts +0 -20
- package/dist/commands/workspace/delete/index.js +0 -141
- package/dist/commands/workspace/edit/index.d.ts +0 -22
- package/dist/commands/workspace/edit/index.js +0 -176
- package/dist/commands/workspace/get/index.d.ts +0 -18
- package/dist/commands/workspace/get/index.js +0 -136
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
|
-
import * as yaml from 'js-yaml';
|
|
4
2
|
import { execSync } from 'node:child_process';
|
|
5
3
|
import * as fs from 'node:fs';
|
|
6
4
|
import * as os from 'node:os';
|
|
7
5
|
import * as path from 'node:path';
|
|
6
|
+
import * as yaml from 'js-yaml';
|
|
7
|
+
import inquirer from 'inquirer';
|
|
8
8
|
import BaseCommand from '../../../base-command.js';
|
|
9
9
|
export default class FunctionEdit extends BaseCommand {
|
|
10
10
|
static args = {
|
|
@@ -13,6 +13,45 @@ export default class FunctionEdit extends BaseCommand {
|
|
|
13
13
|
required: false,
|
|
14
14
|
}),
|
|
15
15
|
};
|
|
16
|
+
static flags = {
|
|
17
|
+
...BaseCommand.baseFlags,
|
|
18
|
+
workspace: Flags.string({
|
|
19
|
+
char: 'w',
|
|
20
|
+
description: 'Workspace ID (optional if set in profile)',
|
|
21
|
+
required: false,
|
|
22
|
+
}),
|
|
23
|
+
file: Flags.string({
|
|
24
|
+
char: 'f',
|
|
25
|
+
description: 'Path to file containing XanoScript code',
|
|
26
|
+
required: false,
|
|
27
|
+
exclusive: ['stdin'],
|
|
28
|
+
}),
|
|
29
|
+
stdin: Flags.boolean({
|
|
30
|
+
char: 's',
|
|
31
|
+
description: 'Read XanoScript code from stdin',
|
|
32
|
+
required: false,
|
|
33
|
+
default: false,
|
|
34
|
+
exclusive: ['file'],
|
|
35
|
+
}),
|
|
36
|
+
edit: Flags.boolean({
|
|
37
|
+
char: 'e',
|
|
38
|
+
description: 'Open file in editor before updating function (requires --file)',
|
|
39
|
+
required: false,
|
|
40
|
+
default: false,
|
|
41
|
+
}),
|
|
42
|
+
publish: Flags.boolean({
|
|
43
|
+
description: 'Publish the function after editing',
|
|
44
|
+
required: false,
|
|
45
|
+
default: true,
|
|
46
|
+
}),
|
|
47
|
+
output: Flags.string({
|
|
48
|
+
char: 'o',
|
|
49
|
+
description: 'Output format',
|
|
50
|
+
required: false,
|
|
51
|
+
default: 'summary',
|
|
52
|
+
options: ['summary', 'json'],
|
|
53
|
+
}),
|
|
54
|
+
};
|
|
16
55
|
static description = 'Edit a function in a workspace';
|
|
17
56
|
static examples = [
|
|
18
57
|
`$ xano function:edit 163
|
|
@@ -61,45 +100,6 @@ Name: my_function
|
|
|
61
100
|
}
|
|
62
101
|
`,
|
|
63
102
|
];
|
|
64
|
-
static flags = {
|
|
65
|
-
...BaseCommand.baseFlags,
|
|
66
|
-
edit: Flags.boolean({
|
|
67
|
-
char: 'e',
|
|
68
|
-
default: false,
|
|
69
|
-
description: 'Open file in editor before updating function (requires --file)',
|
|
70
|
-
required: false,
|
|
71
|
-
}),
|
|
72
|
-
file: Flags.string({
|
|
73
|
-
char: 'f',
|
|
74
|
-
description: 'Path to file containing XanoScript code',
|
|
75
|
-
exclusive: ['stdin'],
|
|
76
|
-
required: false,
|
|
77
|
-
}),
|
|
78
|
-
output: Flags.string({
|
|
79
|
-
char: 'o',
|
|
80
|
-
default: 'summary',
|
|
81
|
-
description: 'Output format',
|
|
82
|
-
options: ['summary', 'json'],
|
|
83
|
-
required: false,
|
|
84
|
-
}),
|
|
85
|
-
publish: Flags.boolean({
|
|
86
|
-
default: true,
|
|
87
|
-
description: 'Publish the function after editing',
|
|
88
|
-
required: false,
|
|
89
|
-
}),
|
|
90
|
-
stdin: Flags.boolean({
|
|
91
|
-
char: 's',
|
|
92
|
-
default: false,
|
|
93
|
-
description: 'Read XanoScript code from stdin',
|
|
94
|
-
exclusive: ['file'],
|
|
95
|
-
required: false,
|
|
96
|
-
}),
|
|
97
|
-
workspace: Flags.string({
|
|
98
|
-
char: 'w',
|
|
99
|
-
description: 'Workspace ID (optional if set in profile)',
|
|
100
|
-
required: false,
|
|
101
|
-
}),
|
|
102
|
-
};
|
|
103
103
|
async run() {
|
|
104
104
|
const { args, flags } = await this.parse(FunctionEdit);
|
|
105
105
|
// Get profile name (default or from flag/env)
|
|
@@ -138,7 +138,12 @@ Name: my_function
|
|
|
138
138
|
}
|
|
139
139
|
// If function_id is not provided, prompt user to select from list
|
|
140
140
|
let functionId;
|
|
141
|
-
|
|
141
|
+
if (args.function_id) {
|
|
142
|
+
functionId = args.function_id;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
functionId = await this.promptForFunctionId(profile, workspaceId);
|
|
146
|
+
}
|
|
142
147
|
// Read XanoScript content
|
|
143
148
|
let xanoscript;
|
|
144
149
|
if (flags.file) {
|
|
@@ -190,20 +195,20 @@ Name: my_function
|
|
|
190
195
|
}
|
|
191
196
|
// Construct the API URL
|
|
192
197
|
const queryParams = new URLSearchParams({
|
|
193
|
-
include_xanoscript: 'false',
|
|
194
198
|
publish: flags.publish ? 'true' : 'false',
|
|
199
|
+
include_xanoscript: 'false',
|
|
195
200
|
});
|
|
196
201
|
const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/function/${functionId}?${queryParams.toString()}`;
|
|
197
202
|
// Update function via API
|
|
198
203
|
try {
|
|
199
204
|
const response = await fetch(apiUrl, {
|
|
200
|
-
|
|
205
|
+
method: 'PUT',
|
|
201
206
|
headers: {
|
|
202
207
|
'accept': 'application/json',
|
|
203
|
-
'Authorization': `Bearer ${profile.access_token}`,
|
|
204
208
|
'Content-Type': 'text/x-xanoscript',
|
|
209
|
+
'Authorization': `Bearer ${profile.access_token}`,
|
|
205
210
|
},
|
|
206
|
-
|
|
211
|
+
body: xanoscript,
|
|
207
212
|
});
|
|
208
213
|
if (!response.ok) {
|
|
209
214
|
const errorText = await response.text();
|
|
@@ -234,54 +239,41 @@ Name: my_function
|
|
|
234
239
|
}
|
|
235
240
|
}
|
|
236
241
|
}
|
|
237
|
-
async
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
'Example: export EDITOR=vim');
|
|
243
|
-
}
|
|
244
|
-
// Validate editor executable exists
|
|
245
|
-
try {
|
|
246
|
-
execSync(`which ${editor.split(' ')[0]}`, { stdio: 'ignore' });
|
|
247
|
-
}
|
|
248
|
-
catch {
|
|
249
|
-
this.error(`Editor '${editor}' not found. Please set EDITOR to a valid editor.\n` +
|
|
250
|
-
'Example: export EDITOR=vim');
|
|
251
|
-
}
|
|
252
|
-
// Read the original file
|
|
253
|
-
let originalContent;
|
|
254
|
-
try {
|
|
255
|
-
originalContent = fs.readFileSync(filePath, 'utf8');
|
|
256
|
-
}
|
|
257
|
-
catch (error) {
|
|
258
|
-
this.error(`Failed to read file '${filePath}': ${error}`);
|
|
259
|
-
}
|
|
260
|
-
// Create a temporary file with the same extension
|
|
261
|
-
const ext = path.extname(filePath);
|
|
262
|
-
const tmpFile = path.join(os.tmpdir(), `xano-edit-${Date.now()}${ext}`);
|
|
263
|
-
// Copy content to temp file
|
|
264
|
-
try {
|
|
265
|
-
fs.writeFileSync(tmpFile, originalContent, 'utf8');
|
|
266
|
-
}
|
|
267
|
-
catch (error) {
|
|
268
|
-
this.error(`Failed to create temporary file: ${error}`);
|
|
269
|
-
}
|
|
270
|
-
// Open the editor
|
|
242
|
+
async fetchFunctionCode(profile, workspaceId, functionId) {
|
|
243
|
+
const queryParams = new URLSearchParams({
|
|
244
|
+
include_xanoscript: 'true',
|
|
245
|
+
});
|
|
246
|
+
const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/function/${functionId}?${queryParams.toString()}`;
|
|
271
247
|
try {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
248
|
+
const response = await fetch(apiUrl, {
|
|
249
|
+
method: 'GET',
|
|
250
|
+
headers: {
|
|
251
|
+
'accept': 'application/json',
|
|
252
|
+
'Authorization': `Bearer ${profile.access_token}`,
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
if (!response.ok) {
|
|
256
|
+
const errorText = await response.text();
|
|
257
|
+
throw new Error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
|
|
278
258
|
}
|
|
279
|
-
|
|
280
|
-
|
|
259
|
+
const result = await response.json();
|
|
260
|
+
// Handle xanoscript as an object with status and value
|
|
261
|
+
if (result.xanoscript) {
|
|
262
|
+
if (result.xanoscript.status === 'ok' && result.xanoscript.value !== undefined) {
|
|
263
|
+
return result.xanoscript.value;
|
|
264
|
+
}
|
|
265
|
+
else if (typeof result.xanoscript === 'string') {
|
|
266
|
+
return result.xanoscript;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
throw new Error(`Invalid xanoscript format: ${JSON.stringify(result.xanoscript)}`);
|
|
270
|
+
}
|
|
281
271
|
}
|
|
282
|
-
|
|
272
|
+
return '';
|
|
273
|
+
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
throw error;
|
|
283
276
|
}
|
|
284
|
-
return tmpFile;
|
|
285
277
|
}
|
|
286
278
|
async editFunctionContent(xanoscript) {
|
|
287
279
|
// Get the EDITOR environment variable
|
|
@@ -335,60 +327,70 @@ Name: my_function
|
|
|
335
327
|
throw new Error(`Failed to read edited file: ${error}`);
|
|
336
328
|
}
|
|
337
329
|
}
|
|
338
|
-
async
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
330
|
+
async editFile(filePath) {
|
|
331
|
+
// Get the EDITOR environment variable
|
|
332
|
+
const editor = process.env.EDITOR || process.env.VISUAL;
|
|
333
|
+
if (!editor) {
|
|
334
|
+
this.error('No editor configured. Please set the EDITOR or VISUAL environment variable.\n' +
|
|
335
|
+
'Example: export EDITOR=vim');
|
|
336
|
+
}
|
|
337
|
+
// Validate editor executable exists
|
|
343
338
|
try {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
const result = await response.json();
|
|
356
|
-
// Handle xanoscript as an object with status and value
|
|
357
|
-
if (result.xanoscript) {
|
|
358
|
-
if (result.xanoscript.status === 'ok' && result.xanoscript.value !== undefined) {
|
|
359
|
-
return result.xanoscript.value;
|
|
360
|
-
}
|
|
361
|
-
if (typeof result.xanoscript === 'string') {
|
|
362
|
-
return result.xanoscript;
|
|
363
|
-
}
|
|
364
|
-
throw new Error(`Invalid xanoscript format: ${JSON.stringify(result.xanoscript)}`);
|
|
365
|
-
}
|
|
366
|
-
return '';
|
|
339
|
+
execSync(`which ${editor.split(' ')[0]}`, { stdio: 'ignore' });
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
this.error(`Editor '${editor}' not found. Please set EDITOR to a valid editor.\n` +
|
|
343
|
+
'Example: export EDITOR=vim');
|
|
344
|
+
}
|
|
345
|
+
// Read the original file
|
|
346
|
+
let originalContent;
|
|
347
|
+
try {
|
|
348
|
+
originalContent = fs.readFileSync(filePath, 'utf8');
|
|
367
349
|
}
|
|
368
350
|
catch (error) {
|
|
369
|
-
|
|
351
|
+
this.error(`Failed to read file '${filePath}': ${error}`);
|
|
370
352
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
this.error(`Credentials file not found at ${credentialsPath}\n` +
|
|
378
|
-
`Create a profile using 'xano profile:create'`);
|
|
353
|
+
// Create a temporary file with the same extension
|
|
354
|
+
const ext = path.extname(filePath);
|
|
355
|
+
const tmpFile = path.join(os.tmpdir(), `xano-edit-${Date.now()}${ext}`);
|
|
356
|
+
// Copy content to temp file
|
|
357
|
+
try {
|
|
358
|
+
fs.writeFileSync(tmpFile, originalContent, 'utf8');
|
|
379
359
|
}
|
|
380
|
-
|
|
360
|
+
catch (error) {
|
|
361
|
+
this.error(`Failed to create temporary file: ${error}`);
|
|
362
|
+
}
|
|
363
|
+
// Open the editor
|
|
381
364
|
try {
|
|
382
|
-
|
|
383
|
-
const parsed = yaml.load(fileContent);
|
|
384
|
-
if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
|
|
385
|
-
this.error('Credentials file has invalid format.');
|
|
386
|
-
}
|
|
387
|
-
return parsed;
|
|
365
|
+
execSync(`${editor} ${tmpFile}`, { stdio: 'inherit' });
|
|
388
366
|
}
|
|
389
367
|
catch (error) {
|
|
390
|
-
|
|
368
|
+
// Clean up temp file
|
|
369
|
+
try {
|
|
370
|
+
fs.unlinkSync(tmpFile);
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
// Ignore cleanup errors
|
|
374
|
+
}
|
|
375
|
+
this.error(`Editor exited with an error: ${error}`);
|
|
391
376
|
}
|
|
377
|
+
return tmpFile;
|
|
378
|
+
}
|
|
379
|
+
async readStdin() {
|
|
380
|
+
return new Promise((resolve, reject) => {
|
|
381
|
+
const chunks = [];
|
|
382
|
+
process.stdin.on('data', (chunk) => {
|
|
383
|
+
chunks.push(chunk);
|
|
384
|
+
});
|
|
385
|
+
process.stdin.on('end', () => {
|
|
386
|
+
resolve(Buffer.concat(chunks).toString('utf8'));
|
|
387
|
+
});
|
|
388
|
+
process.stdin.on('error', (error) => {
|
|
389
|
+
reject(error);
|
|
390
|
+
});
|
|
391
|
+
// Resume stdin if it was paused
|
|
392
|
+
process.stdin.resume();
|
|
393
|
+
});
|
|
392
394
|
}
|
|
393
395
|
async promptForFunctionId(profile, workspaceId) {
|
|
394
396
|
try {
|
|
@@ -396,18 +398,18 @@ Name: my_function
|
|
|
396
398
|
const queryParams = new URLSearchParams({
|
|
397
399
|
include_draft: 'false',
|
|
398
400
|
include_xanoscript: 'false',
|
|
399
|
-
order: 'desc',
|
|
400
401
|
page: '1',
|
|
401
402
|
per_page: '50',
|
|
402
403
|
sort: 'created_at',
|
|
404
|
+
order: 'desc',
|
|
403
405
|
});
|
|
404
406
|
const listUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/function?${queryParams.toString()}`;
|
|
405
407
|
const response = await fetch(listUrl, {
|
|
408
|
+
method: 'GET',
|
|
406
409
|
headers: {
|
|
407
410
|
'accept': 'application/json',
|
|
408
411
|
'Authorization': `Bearer ${profile.access_token}`,
|
|
409
412
|
},
|
|
410
|
-
method: 'GET',
|
|
411
413
|
});
|
|
412
414
|
if (!response.ok) {
|
|
413
415
|
const errorText = await response.text();
|
|
@@ -439,10 +441,10 @@ Name: my_function
|
|
|
439
441
|
// Prompt user to select a function
|
|
440
442
|
const answer = await inquirer.prompt([
|
|
441
443
|
{
|
|
442
|
-
choices,
|
|
443
|
-
message: 'Select a function to edit:',
|
|
444
|
-
name: 'functionId',
|
|
445
444
|
type: 'list',
|
|
445
|
+
name: 'functionId',
|
|
446
|
+
message: 'Select a function to edit:',
|
|
447
|
+
choices,
|
|
446
448
|
},
|
|
447
449
|
]);
|
|
448
450
|
return answer.functionId;
|
|
@@ -456,20 +458,25 @@ Name: my_function
|
|
|
456
458
|
}
|
|
457
459
|
}
|
|
458
460
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
461
|
+
loadCredentials() {
|
|
462
|
+
const configDir = path.join(os.homedir(), '.xano');
|
|
463
|
+
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
464
|
+
// Check if credentials file exists
|
|
465
|
+
if (!fs.existsSync(credentialsPath)) {
|
|
466
|
+
this.error(`Credentials file not found at ${credentialsPath}\n` +
|
|
467
|
+
`Create a profile using 'xano profile:create'`);
|
|
468
|
+
}
|
|
469
|
+
// Read credentials file
|
|
470
|
+
try {
|
|
471
|
+
const fileContent = fs.readFileSync(credentialsPath, 'utf8');
|
|
472
|
+
const parsed = yaml.load(fileContent);
|
|
473
|
+
if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
|
|
474
|
+
this.error('Credentials file has invalid format.');
|
|
475
|
+
}
|
|
476
|
+
return parsed;
|
|
477
|
+
}
|
|
478
|
+
catch (error) {
|
|
479
|
+
this.error(`Failed to parse credentials file: ${error}`);
|
|
480
|
+
}
|
|
474
481
|
}
|
|
475
482
|
}
|
|
@@ -3,17 +3,16 @@ export default class FunctionGet extends BaseCommand {
|
|
|
3
3
|
static args: {
|
|
4
4
|
function_id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
5
5
|
};
|
|
6
|
-
static description: string;
|
|
7
|
-
static examples: string[];
|
|
8
6
|
static flags: {
|
|
7
|
+
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
|
+
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
9
|
include_draft: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
include_xanoscript: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
11
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
12
|
};
|
|
13
|
+
static description: string;
|
|
14
|
+
static examples: string[];
|
|
16
15
|
run(): Promise<void>;
|
|
17
|
-
private loadCredentials;
|
|
18
16
|
private promptForFunctionId;
|
|
17
|
+
private loadCredentials;
|
|
19
18
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
|
-
import * as yaml from 'js-yaml';
|
|
4
2
|
import * as fs from 'node:fs';
|
|
5
3
|
import * as os from 'node:os';
|
|
6
4
|
import * as path from 'node:path';
|
|
5
|
+
import * as yaml from 'js-yaml';
|
|
6
|
+
import inquirer from 'inquirer';
|
|
7
7
|
import BaseCommand from '../../../base-command.js';
|
|
8
8
|
export default class FunctionGet extends BaseCommand {
|
|
9
9
|
static args = {
|
|
@@ -12,6 +12,31 @@ export default class FunctionGet extends BaseCommand {
|
|
|
12
12
|
required: false,
|
|
13
13
|
}),
|
|
14
14
|
};
|
|
15
|
+
static flags = {
|
|
16
|
+
...BaseCommand.baseFlags,
|
|
17
|
+
workspace: Flags.string({
|
|
18
|
+
char: 'w',
|
|
19
|
+
description: 'Workspace ID (optional if set in profile)',
|
|
20
|
+
required: false,
|
|
21
|
+
}),
|
|
22
|
+
output: Flags.string({
|
|
23
|
+
char: 'o',
|
|
24
|
+
description: 'Output format',
|
|
25
|
+
required: false,
|
|
26
|
+
default: 'summary',
|
|
27
|
+
options: ['summary', 'json', 'xs'],
|
|
28
|
+
}),
|
|
29
|
+
include_draft: Flags.boolean({
|
|
30
|
+
description: 'Include draft version',
|
|
31
|
+
required: false,
|
|
32
|
+
default: false,
|
|
33
|
+
}),
|
|
34
|
+
include_xanoscript: Flags.boolean({
|
|
35
|
+
description: 'Include XanoScript in response',
|
|
36
|
+
required: false,
|
|
37
|
+
default: false,
|
|
38
|
+
}),
|
|
39
|
+
};
|
|
15
40
|
static description = 'Get a specific function from a workspace';
|
|
16
41
|
static examples = [
|
|
17
42
|
`$ xano function:get 145 -w 40
|
|
@@ -51,31 +76,6 @@ function yo {
|
|
|
51
76
|
}
|
|
52
77
|
`,
|
|
53
78
|
];
|
|
54
|
-
static flags = {
|
|
55
|
-
...BaseCommand.baseFlags,
|
|
56
|
-
include_draft: Flags.boolean({
|
|
57
|
-
default: false,
|
|
58
|
-
description: 'Include draft version',
|
|
59
|
-
required: false,
|
|
60
|
-
}),
|
|
61
|
-
include_xanoscript: Flags.boolean({
|
|
62
|
-
default: false,
|
|
63
|
-
description: 'Include XanoScript in response',
|
|
64
|
-
required: false,
|
|
65
|
-
}),
|
|
66
|
-
output: Flags.string({
|
|
67
|
-
char: 'o',
|
|
68
|
-
default: 'summary',
|
|
69
|
-
description: 'Output format',
|
|
70
|
-
options: ['summary', 'json', 'xs'],
|
|
71
|
-
required: false,
|
|
72
|
-
}),
|
|
73
|
-
workspace: Flags.string({
|
|
74
|
-
char: 'w',
|
|
75
|
-
description: 'Workspace ID (optional if set in profile)',
|
|
76
|
-
required: false,
|
|
77
|
-
}),
|
|
78
|
-
};
|
|
79
79
|
async run() {
|
|
80
80
|
const { args, flags } = await this.parse(FunctionGet);
|
|
81
81
|
// Get profile name (default or from flag/env)
|
|
@@ -110,7 +110,12 @@ function yo {
|
|
|
110
110
|
}
|
|
111
111
|
// If function_id is not provided, prompt user to select from list
|
|
112
112
|
let functionId;
|
|
113
|
-
|
|
113
|
+
if (args.function_id) {
|
|
114
|
+
functionId = args.function_id;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
functionId = await this.promptForFunctionId(profile, workspaceId);
|
|
118
|
+
}
|
|
114
119
|
// Build query parameters
|
|
115
120
|
// Automatically set include_xanoscript to true if output format is xs
|
|
116
121
|
const includeXanoscript = flags.output === 'xs' ? true : flags.include_xanoscript;
|
|
@@ -123,11 +128,11 @@ function yo {
|
|
|
123
128
|
// Fetch function from the API
|
|
124
129
|
try {
|
|
125
130
|
const response = await fetch(apiUrl, {
|
|
131
|
+
method: 'GET',
|
|
126
132
|
headers: {
|
|
127
133
|
'accept': 'application/json',
|
|
128
134
|
'Authorization': `Bearer ${profile.access_token}`,
|
|
129
135
|
},
|
|
130
|
-
method: 'GET',
|
|
131
136
|
});
|
|
132
137
|
if (!response.ok) {
|
|
133
138
|
const errorText = await response.text();
|
|
@@ -184,45 +189,24 @@ function yo {
|
|
|
184
189
|
}
|
|
185
190
|
}
|
|
186
191
|
}
|
|
187
|
-
loadCredentials() {
|
|
188
|
-
const configDir = path.join(os.homedir(), '.xano');
|
|
189
|
-
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
190
|
-
// Check if credentials file exists
|
|
191
|
-
if (!fs.existsSync(credentialsPath)) {
|
|
192
|
-
this.error(`Credentials file not found at ${credentialsPath}\n` +
|
|
193
|
-
`Create a profile using 'xano profile:create'`);
|
|
194
|
-
}
|
|
195
|
-
// Read credentials file
|
|
196
|
-
try {
|
|
197
|
-
const fileContent = fs.readFileSync(credentialsPath, 'utf8');
|
|
198
|
-
const parsed = yaml.load(fileContent);
|
|
199
|
-
if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
|
|
200
|
-
this.error('Credentials file has invalid format.');
|
|
201
|
-
}
|
|
202
|
-
return parsed;
|
|
203
|
-
}
|
|
204
|
-
catch (error) {
|
|
205
|
-
this.error(`Failed to parse credentials file: ${error}`);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
192
|
async promptForFunctionId(profile, workspaceId) {
|
|
209
193
|
try {
|
|
210
194
|
// Fetch list of functions
|
|
211
195
|
const queryParams = new URLSearchParams({
|
|
212
196
|
include_draft: 'false',
|
|
213
197
|
include_xanoscript: 'false',
|
|
214
|
-
order: 'desc',
|
|
215
198
|
page: '1',
|
|
216
199
|
per_page: '50',
|
|
217
200
|
sort: 'created_at',
|
|
201
|
+
order: 'desc',
|
|
218
202
|
});
|
|
219
203
|
const listUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/function?${queryParams.toString()}`;
|
|
220
204
|
const response = await fetch(listUrl, {
|
|
205
|
+
method: 'GET',
|
|
221
206
|
headers: {
|
|
222
207
|
'accept': 'application/json',
|
|
223
208
|
'Authorization': `Bearer ${profile.access_token}`,
|
|
224
209
|
},
|
|
225
|
-
method: 'GET',
|
|
226
210
|
});
|
|
227
211
|
if (!response.ok) {
|
|
228
212
|
const errorText = await response.text();
|
|
@@ -254,10 +238,10 @@ function yo {
|
|
|
254
238
|
// Prompt user to select a function
|
|
255
239
|
const answer = await inquirer.prompt([
|
|
256
240
|
{
|
|
257
|
-
choices,
|
|
258
|
-
message: 'Select a function:',
|
|
259
|
-
name: 'functionId',
|
|
260
241
|
type: 'list',
|
|
242
|
+
name: 'functionId',
|
|
243
|
+
message: 'Select a function:',
|
|
244
|
+
choices,
|
|
261
245
|
},
|
|
262
246
|
]);
|
|
263
247
|
return answer.functionId;
|
|
@@ -271,4 +255,25 @@ function yo {
|
|
|
271
255
|
}
|
|
272
256
|
}
|
|
273
257
|
}
|
|
258
|
+
loadCredentials() {
|
|
259
|
+
const configDir = path.join(os.homedir(), '.xano');
|
|
260
|
+
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
261
|
+
// Check if credentials file exists
|
|
262
|
+
if (!fs.existsSync(credentialsPath)) {
|
|
263
|
+
this.error(`Credentials file not found at ${credentialsPath}\n` +
|
|
264
|
+
`Create a profile using 'xano profile:create'`);
|
|
265
|
+
}
|
|
266
|
+
// Read credentials file
|
|
267
|
+
try {
|
|
268
|
+
const fileContent = fs.readFileSync(credentialsPath, 'utf8');
|
|
269
|
+
const parsed = yaml.load(fileContent);
|
|
270
|
+
if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
|
|
271
|
+
this.error('Credentials file has invalid format.');
|
|
272
|
+
}
|
|
273
|
+
return parsed;
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
this.error(`Failed to parse credentials file: ${error}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
274
279
|
}
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import BaseCommand from '../../../base-command.js';
|
|
2
2
|
export default class FunctionList extends BaseCommand {
|
|
3
3
|
static args: {};
|
|
4
|
-
static description: string;
|
|
5
|
-
static examples: string[];
|
|
6
4
|
static flags: {
|
|
5
|
+
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
6
|
+
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
7
|
include_draft: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
8
|
include_xanoscript: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
-
order: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
-
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
9
|
page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
10
|
per_page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
11
|
sort: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
-
|
|
12
|
+
order: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
13
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
-
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
14
|
};
|
|
15
|
+
static description: string;
|
|
16
|
+
static examples: string[];
|
|
18
17
|
run(): Promise<void>;
|
|
19
18
|
private loadCredentials;
|
|
20
19
|
}
|