@xano/cli 0.0.20 → 0.0.22
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 -1
- package/dist/base-command.js +6 -6
- package/dist/commands/branch/create/index.d.ts +17 -0
- package/dist/commands/branch/create/index.js +164 -0
- package/dist/commands/branch/delete/index.d.ts +18 -0
- package/dist/commands/branch/delete/index.js +156 -0
- package/dist/commands/branch/edit/index.d.ts +19 -0
- package/dist/commands/branch/edit/index.js +166 -0
- package/dist/commands/branch/get/index.d.ts +16 -0
- package/dist/commands/branch/get/index.js +135 -0
- package/dist/commands/branch/list/index.d.ts +18 -0
- package/dist/commands/branch/list/index.js +138 -0
- package/dist/commands/branch/set-live/index.d.ts +18 -0
- package/dist/commands/branch/set-live/index.js +155 -0
- package/dist/commands/function/create/index.d.ts +6 -6
- package/dist/commands/function/create/index.js +55 -55
- package/dist/commands/function/edit/index.d.ts +10 -10
- package/dist/commands/function/edit/index.js +155 -162
- package/dist/commands/function/get/index.d.ts +5 -5
- package/dist/commands/function/get/index.js +55 -60
- package/dist/commands/function/list/index.d.ts +5 -5
- 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 -7
- package/dist/commands/profile/edit/index.js +47 -47
- 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 -3
- 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 -4
- package/dist/commands/profile/wizard/index.js +118 -122
- package/dist/commands/run/env/delete/index.d.ts +2 -2
- package/dist/commands/run/env/delete/index.js +9 -9
- package/dist/commands/run/env/get/index.d.ts +2 -2
- package/dist/commands/run/env/get/index.js +10 -10
- package/dist/commands/run/env/list/index.d.ts +2 -2
- package/dist/commands/run/env/list/index.js +16 -18
- package/dist/commands/run/env/set/index.d.ts +2 -2
- package/dist/commands/run/env/set/index.js +4 -4
- package/dist/commands/run/exec/index.d.ts +11 -11
- package/dist/commands/run/exec/index.js +109 -109
- package/dist/commands/run/info/index.d.ts +4 -4
- package/dist/commands/run/info/index.js +26 -26
- package/dist/commands/run/projects/create/index.d.ts +3 -3
- package/dist/commands/run/projects/create/index.js +22 -22
- package/dist/commands/run/projects/delete/index.d.ts +2 -2
- package/dist/commands/run/projects/delete/index.js +9 -9
- package/dist/commands/run/projects/list/index.d.ts +2 -2
- package/dist/commands/run/projects/list/index.js +11 -11
- package/dist/commands/run/projects/update/index.d.ts +3 -3
- package/dist/commands/run/projects/update/index.js +20 -20
- package/dist/commands/run/secrets/delete/index.d.ts +2 -2
- package/dist/commands/run/secrets/delete/index.js +9 -9
- package/dist/commands/run/secrets/get/index.d.ts +2 -2
- package/dist/commands/run/secrets/get/index.js +10 -10
- package/dist/commands/run/secrets/list/index.d.ts +2 -2
- package/dist/commands/run/secrets/list/index.js +21 -23
- package/dist/commands/run/secrets/set/index.d.ts +3 -3
- package/dist/commands/run/secrets/set/index.js +15 -15
- package/dist/commands/run/sessions/delete/index.d.ts +2 -2
- package/dist/commands/run/sessions/delete/index.js +9 -9
- package/dist/commands/run/sessions/get/index.d.ts +2 -2
- package/dist/commands/run/sessions/get/index.js +10 -10
- package/dist/commands/run/sessions/list/index.d.ts +2 -2
- package/dist/commands/run/sessions/list/index.js +10 -10
- package/dist/commands/run/sessions/start/index.d.ts +2 -2
- package/dist/commands/run/sessions/start/index.js +10 -10
- package/dist/commands/run/sessions/stop/index.d.ts +2 -2
- package/dist/commands/run/sessions/stop/index.js +10 -10
- package/dist/commands/run/sink/get/index.d.ts +2 -2
- package/dist/commands/run/sink/get/index.js +10 -10
- package/dist/commands/static_host/build/create/index.d.ts +4 -4
- package/dist/commands/static_host/build/create/index.js +33 -33
- package/dist/commands/static_host/build/get/index.d.ts +4 -4
- package/dist/commands/static_host/build/get/index.js +20 -20
- package/dist/commands/static_host/build/list/index.d.ts +3 -3
- package/dist/commands/static_host/build/list/index.js +31 -31
- package/dist/commands/static_host/list/index.d.ts +3 -3
- package/dist/commands/static_host/list/index.js +31 -31
- package/dist/commands/workspace/create/index.d.ts +14 -0
- package/dist/commands/workspace/create/index.js +131 -0
- package/dist/commands/workspace/delete/index.d.ts +20 -0
- package/dist/commands/workspace/delete/index.js +141 -0
- package/dist/commands/workspace/edit/index.d.ts +22 -0
- package/dist/commands/workspace/edit/index.js +176 -0
- package/dist/commands/workspace/get/index.d.ts +18 -0
- package/dist/commands/workspace/get/index.js +136 -0
- package/dist/commands/workspace/list/index.d.ts +2 -2
- package/dist/commands/workspace/list/index.js +15 -15
- package/dist/commands/workspace/pull/index.d.ts +4 -4
- package/dist/commands/workspace/pull/index.js +46 -51
- package/dist/commands/workspace/push/index.js +3 -3
- package/dist/help.d.ts +1 -1
- package/dist/lib/base-run-command.d.ts +4 -4
- package/dist/lib/base-run-command.js +3 -3
- package/dist/lib/run-http-client.d.ts +21 -21
- package/dist/lib/run-http-client.js +72 -72
- package/dist/lib/run-types.d.ts +80 -80
- package/oclif.manifest.json +1633 -791
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import * as yaml from 'js-yaml';
|
|
2
4
|
import { execSync } from 'node:child_process';
|
|
3
5
|
import * as fs from 'node:fs';
|
|
4
6
|
import * as os from 'node:os';
|
|
5
7
|
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,45 +13,6 @@ 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
|
-
};
|
|
55
16
|
static description = 'Edit a function in a workspace';
|
|
56
17
|
static examples = [
|
|
57
18
|
`$ xano function:edit 163
|
|
@@ -100,6 +61,45 @@ Name: my_function
|
|
|
100
61
|
}
|
|
101
62
|
`,
|
|
102
63
|
];
|
|
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,12 +138,7 @@ Name: my_function
|
|
|
138
138
|
}
|
|
139
139
|
// If function_id is not provided, prompt user to select from list
|
|
140
140
|
let functionId;
|
|
141
|
-
|
|
142
|
-
functionId = args.function_id;
|
|
143
|
-
}
|
|
144
|
-
else {
|
|
145
|
-
functionId = await this.promptForFunctionId(profile, workspaceId);
|
|
146
|
-
}
|
|
141
|
+
functionId = args.function_id ? args.function_id : (await this.promptForFunctionId(profile, workspaceId));
|
|
147
142
|
// Read XanoScript content
|
|
148
143
|
let xanoscript;
|
|
149
144
|
if (flags.file) {
|
|
@@ -195,20 +190,20 @@ Name: my_function
|
|
|
195
190
|
}
|
|
196
191
|
// Construct the API URL
|
|
197
192
|
const queryParams = new URLSearchParams({
|
|
198
|
-
publish: flags.publish ? 'true' : 'false',
|
|
199
193
|
include_xanoscript: 'false',
|
|
194
|
+
publish: flags.publish ? 'true' : 'false',
|
|
200
195
|
});
|
|
201
196
|
const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/function/${functionId}?${queryParams.toString()}`;
|
|
202
197
|
// Update function via API
|
|
203
198
|
try {
|
|
204
199
|
const response = await fetch(apiUrl, {
|
|
205
|
-
|
|
200
|
+
body: xanoscript,
|
|
206
201
|
headers: {
|
|
207
202
|
'accept': 'application/json',
|
|
208
|
-
'Content-Type': 'text/x-xanoscript',
|
|
209
203
|
'Authorization': `Bearer ${profile.access_token}`,
|
|
204
|
+
'Content-Type': 'text/x-xanoscript',
|
|
210
205
|
},
|
|
211
|
-
|
|
206
|
+
method: 'PUT',
|
|
212
207
|
});
|
|
213
208
|
if (!response.ok) {
|
|
214
209
|
const errorText = await response.text();
|
|
@@ -239,41 +234,54 @@ Name: my_function
|
|
|
239
234
|
}
|
|
240
235
|
}
|
|
241
236
|
}
|
|
242
|
-
async
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
237
|
+
async editFile(filePath) {
|
|
238
|
+
// Get the EDITOR environment variable
|
|
239
|
+
const editor = process.env.EDITOR || process.env.VISUAL;
|
|
240
|
+
if (!editor) {
|
|
241
|
+
this.error('No editor configured. Please set the EDITOR or VISUAL environment variable.\n' +
|
|
242
|
+
'Example: export EDITOR=vim');
|
|
243
|
+
}
|
|
244
|
+
// Validate editor executable exists
|
|
247
245
|
try {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
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
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return '';
|
|
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');
|
|
273
256
|
}
|
|
274
257
|
catch (error) {
|
|
275
|
-
|
|
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
|
|
271
|
+
try {
|
|
272
|
+
execSync(`${editor} ${tmpFile}`, { stdio: 'inherit' });
|
|
276
273
|
}
|
|
274
|
+
catch (error) {
|
|
275
|
+
// Clean up temp file
|
|
276
|
+
try {
|
|
277
|
+
fs.unlinkSync(tmpFile);
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// Ignore cleanup errors
|
|
281
|
+
}
|
|
282
|
+
this.error(`Editor exited with an error: ${error}`);
|
|
283
|
+
}
|
|
284
|
+
return tmpFile;
|
|
277
285
|
}
|
|
278
286
|
async editFunctionContent(xanoscript) {
|
|
279
287
|
// Get the EDITOR environment variable
|
|
@@ -327,70 +335,60 @@ Name: my_function
|
|
|
327
335
|
throw new Error(`Failed to read edited file: ${error}`);
|
|
328
336
|
}
|
|
329
337
|
}
|
|
330
|
-
async
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
'Example: export EDITOR=vim');
|
|
336
|
-
}
|
|
337
|
-
// Validate editor executable exists
|
|
338
|
-
try {
|
|
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;
|
|
338
|
+
async fetchFunctionCode(profile, workspaceId, functionId) {
|
|
339
|
+
const queryParams = new URLSearchParams({
|
|
340
|
+
include_xanoscript: 'true',
|
|
341
|
+
});
|
|
342
|
+
const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/function/${functionId}?${queryParams.toString()}`;
|
|
347
343
|
try {
|
|
348
|
-
|
|
344
|
+
const response = await fetch(apiUrl, {
|
|
345
|
+
headers: {
|
|
346
|
+
'accept': 'application/json',
|
|
347
|
+
'Authorization': `Bearer ${profile.access_token}`,
|
|
348
|
+
},
|
|
349
|
+
method: 'GET',
|
|
350
|
+
});
|
|
351
|
+
if (!response.ok) {
|
|
352
|
+
const errorText = await response.text();
|
|
353
|
+
throw new Error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
|
|
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 '';
|
|
349
367
|
}
|
|
350
368
|
catch (error) {
|
|
351
|
-
|
|
352
|
-
}
|
|
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');
|
|
369
|
+
throw error;
|
|
359
370
|
}
|
|
360
|
-
|
|
361
|
-
|
|
371
|
+
}
|
|
372
|
+
loadCredentials() {
|
|
373
|
+
const configDir = path.join(os.homedir(), '.xano');
|
|
374
|
+
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
375
|
+
// Check if credentials file exists
|
|
376
|
+
if (!fs.existsSync(credentialsPath)) {
|
|
377
|
+
this.error(`Credentials file not found at ${credentialsPath}\n` +
|
|
378
|
+
`Create a profile using 'xano profile:create'`);
|
|
362
379
|
}
|
|
363
|
-
//
|
|
380
|
+
// Read credentials file
|
|
364
381
|
try {
|
|
365
|
-
|
|
382
|
+
const fileContent = fs.readFileSync(credentialsPath, 'utf8');
|
|
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;
|
|
366
388
|
}
|
|
367
389
|
catch (error) {
|
|
368
|
-
|
|
369
|
-
try {
|
|
370
|
-
fs.unlinkSync(tmpFile);
|
|
371
|
-
}
|
|
372
|
-
catch {
|
|
373
|
-
// Ignore cleanup errors
|
|
374
|
-
}
|
|
375
|
-
this.error(`Editor exited with an error: ${error}`);
|
|
390
|
+
this.error(`Failed to parse credentials file: ${error}`);
|
|
376
391
|
}
|
|
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
|
-
});
|
|
394
392
|
}
|
|
395
393
|
async promptForFunctionId(profile, workspaceId) {
|
|
396
394
|
try {
|
|
@@ -398,18 +396,18 @@ Name: my_function
|
|
|
398
396
|
const queryParams = new URLSearchParams({
|
|
399
397
|
include_draft: 'false',
|
|
400
398
|
include_xanoscript: 'false',
|
|
399
|
+
order: 'desc',
|
|
401
400
|
page: '1',
|
|
402
401
|
per_page: '50',
|
|
403
402
|
sort: 'created_at',
|
|
404
|
-
order: 'desc',
|
|
405
403
|
});
|
|
406
404
|
const listUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/function?${queryParams.toString()}`;
|
|
407
405
|
const response = await fetch(listUrl, {
|
|
408
|
-
method: 'GET',
|
|
409
406
|
headers: {
|
|
410
407
|
'accept': 'application/json',
|
|
411
408
|
'Authorization': `Bearer ${profile.access_token}`,
|
|
412
409
|
},
|
|
410
|
+
method: 'GET',
|
|
413
411
|
});
|
|
414
412
|
if (!response.ok) {
|
|
415
413
|
const errorText = await response.text();
|
|
@@ -441,10 +439,10 @@ Name: my_function
|
|
|
441
439
|
// Prompt user to select a function
|
|
442
440
|
const answer = await inquirer.prompt([
|
|
443
441
|
{
|
|
444
|
-
type: 'list',
|
|
445
|
-
name: 'functionId',
|
|
446
|
-
message: 'Select a function to edit:',
|
|
447
442
|
choices,
|
|
443
|
+
message: 'Select a function to edit:',
|
|
444
|
+
name: 'functionId',
|
|
445
|
+
type: 'list',
|
|
448
446
|
},
|
|
449
447
|
]);
|
|
450
448
|
return answer.functionId;
|
|
@@ -458,25 +456,20 @@ Name: my_function
|
|
|
458
456
|
}
|
|
459
457
|
}
|
|
460
458
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
return parsed;
|
|
477
|
-
}
|
|
478
|
-
catch (error) {
|
|
479
|
-
this.error(`Failed to parse credentials file: ${error}`);
|
|
480
|
-
}
|
|
459
|
+
async readStdin() {
|
|
460
|
+
return new Promise((resolve, reject) => {
|
|
461
|
+
const chunks = [];
|
|
462
|
+
process.stdin.on('data', (chunk) => {
|
|
463
|
+
chunks.push(chunk);
|
|
464
|
+
});
|
|
465
|
+
process.stdin.on('end', () => {
|
|
466
|
+
resolve(Buffer.concat(chunks).toString('utf8'));
|
|
467
|
+
});
|
|
468
|
+
process.stdin.on('error', (error) => {
|
|
469
|
+
reject(error);
|
|
470
|
+
});
|
|
471
|
+
// Resume stdin if it was paused
|
|
472
|
+
process.stdin.resume();
|
|
473
|
+
});
|
|
481
474
|
}
|
|
482
475
|
}
|
|
@@ -3,17 +3,17 @@ 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[];
|
|
6
8
|
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>;
|
|
11
13
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
14
|
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
15
|
};
|
|
14
|
-
static description: string;
|
|
15
|
-
static examples: string[];
|
|
16
16
|
run(): Promise<void>;
|
|
17
|
-
private promptForFunctionId;
|
|
18
17
|
private loadCredentials;
|
|
18
|
+
private promptForFunctionId;
|
|
19
19
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Args, Flags } from '@oclif/core';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import * as yaml from 'js-yaml';
|
|
2
4
|
import * as fs from 'node:fs';
|
|
3
5
|
import * as os from 'node:os';
|
|
4
6
|
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,31 +12,6 @@ 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
|
-
};
|
|
40
15
|
static description = 'Get a specific function from a workspace';
|
|
41
16
|
static examples = [
|
|
42
17
|
`$ xano function:get 145 -w 40
|
|
@@ -76,6 +51,31 @@ function yo {
|
|
|
76
51
|
}
|
|
77
52
|
`,
|
|
78
53
|
];
|
|
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,12 +110,7 @@ function yo {
|
|
|
110
110
|
}
|
|
111
111
|
// If function_id is not provided, prompt user to select from list
|
|
112
112
|
let functionId;
|
|
113
|
-
|
|
114
|
-
functionId = args.function_id;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
functionId = await this.promptForFunctionId(profile, workspaceId);
|
|
118
|
-
}
|
|
113
|
+
functionId = args.function_id ? args.function_id : (await this.promptForFunctionId(profile, workspaceId));
|
|
119
114
|
// Build query parameters
|
|
120
115
|
// Automatically set include_xanoscript to true if output format is xs
|
|
121
116
|
const includeXanoscript = flags.output === 'xs' ? true : flags.include_xanoscript;
|
|
@@ -128,11 +123,11 @@ function yo {
|
|
|
128
123
|
// Fetch function from the API
|
|
129
124
|
try {
|
|
130
125
|
const response = await fetch(apiUrl, {
|
|
131
|
-
method: 'GET',
|
|
132
126
|
headers: {
|
|
133
127
|
'accept': 'application/json',
|
|
134
128
|
'Authorization': `Bearer ${profile.access_token}`,
|
|
135
129
|
},
|
|
130
|
+
method: 'GET',
|
|
136
131
|
});
|
|
137
132
|
if (!response.ok) {
|
|
138
133
|
const errorText = await response.text();
|
|
@@ -189,24 +184,45 @@ function yo {
|
|
|
189
184
|
}
|
|
190
185
|
}
|
|
191
186
|
}
|
|
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
|
+
}
|
|
192
208
|
async promptForFunctionId(profile, workspaceId) {
|
|
193
209
|
try {
|
|
194
210
|
// Fetch list of functions
|
|
195
211
|
const queryParams = new URLSearchParams({
|
|
196
212
|
include_draft: 'false',
|
|
197
213
|
include_xanoscript: 'false',
|
|
214
|
+
order: 'desc',
|
|
198
215
|
page: '1',
|
|
199
216
|
per_page: '50',
|
|
200
217
|
sort: 'created_at',
|
|
201
|
-
order: 'desc',
|
|
202
218
|
});
|
|
203
219
|
const listUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/function?${queryParams.toString()}`;
|
|
204
220
|
const response = await fetch(listUrl, {
|
|
205
|
-
method: 'GET',
|
|
206
221
|
headers: {
|
|
207
222
|
'accept': 'application/json',
|
|
208
223
|
'Authorization': `Bearer ${profile.access_token}`,
|
|
209
224
|
},
|
|
225
|
+
method: 'GET',
|
|
210
226
|
});
|
|
211
227
|
if (!response.ok) {
|
|
212
228
|
const errorText = await response.text();
|
|
@@ -238,10 +254,10 @@ function yo {
|
|
|
238
254
|
// Prompt user to select a function
|
|
239
255
|
const answer = await inquirer.prompt([
|
|
240
256
|
{
|
|
241
|
-
type: 'list',
|
|
242
|
-
name: 'functionId',
|
|
243
|
-
message: 'Select a function:',
|
|
244
257
|
choices,
|
|
258
|
+
message: 'Select a function:',
|
|
259
|
+
name: 'functionId',
|
|
260
|
+
type: 'list',
|
|
245
261
|
},
|
|
246
262
|
]);
|
|
247
263
|
return answer.functionId;
|
|
@@ -255,25 +271,4 @@ function yo {
|
|
|
255
271
|
}
|
|
256
272
|
}
|
|
257
273
|
}
|
|
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
|
-
}
|
|
279
274
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
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[];
|
|
4
6
|
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>;
|
|
9
11
|
page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
12
|
per_page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
13
|
sort: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
|
|
14
|
+
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
15
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
16
|
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
17
|
};
|
|
16
|
-
static description: string;
|
|
17
|
-
static examples: string[];
|
|
18
18
|
run(): Promise<void>;
|
|
19
19
|
private loadCredentials;
|
|
20
20
|
}
|