@xano/cli 0.0.26 → 0.0.27

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.
Files changed (110) hide show
  1. package/dist/base-command.d.ts +3 -1
  2. package/dist/base-command.js +12 -5
  3. package/dist/commands/auth/index.d.ts +21 -0
  4. package/dist/commands/auth/index.js +533 -0
  5. package/dist/commands/branch/create/index.d.ts +17 -0
  6. package/dist/commands/branch/create/index.js +164 -0
  7. package/dist/commands/branch/delete/index.d.ts +18 -0
  8. package/dist/commands/branch/delete/index.js +156 -0
  9. package/dist/commands/branch/edit/index.d.ts +19 -0
  10. package/dist/commands/branch/edit/index.js +166 -0
  11. package/dist/commands/branch/get/index.d.ts +16 -0
  12. package/dist/commands/branch/get/index.js +135 -0
  13. package/dist/commands/branch/list/index.d.ts +18 -0
  14. package/dist/commands/branch/list/index.js +138 -0
  15. package/dist/commands/branch/set-live/index.d.ts +18 -0
  16. package/dist/commands/branch/set-live/index.js +155 -0
  17. package/dist/commands/function/create/index.d.ts +7 -6
  18. package/dist/commands/function/create/index.js +55 -55
  19. package/dist/commands/function/edit/index.d.ts +11 -10
  20. package/dist/commands/function/edit/index.js +155 -162
  21. package/dist/commands/function/get/index.d.ts +6 -5
  22. package/dist/commands/function/get/index.js +55 -60
  23. package/dist/commands/function/list/index.d.ts +6 -5
  24. package/dist/commands/function/list/index.js +52 -52
  25. package/dist/commands/profile/create/index.d.ts +6 -6
  26. package/dist/commands/profile/create/index.js +37 -37
  27. package/dist/commands/profile/delete/index.d.ts +2 -2
  28. package/dist/commands/profile/delete/index.js +9 -9
  29. package/dist/commands/profile/edit/index.d.ts +8 -7
  30. package/dist/commands/profile/edit/index.js +48 -48
  31. package/dist/commands/profile/get-default/index.js +1 -1
  32. package/dist/commands/profile/list/index.d.ts +2 -2
  33. package/dist/commands/profile/list/index.js +9 -9
  34. package/dist/commands/profile/me/index.d.ts +4 -3
  35. package/dist/commands/profile/me/index.js +21 -21
  36. package/dist/commands/profile/project/index.js +1 -1
  37. package/dist/commands/profile/set-default/index.js +1 -1
  38. package/dist/commands/profile/token/index.js +1 -1
  39. package/dist/commands/profile/wizard/index.d.ts +5 -4
  40. package/dist/commands/profile/wizard/index.js +142 -108
  41. package/dist/commands/run/env/delete/index.d.ts +3 -2
  42. package/dist/commands/run/env/delete/index.js +10 -10
  43. package/dist/commands/run/env/get/index.d.ts +3 -2
  44. package/dist/commands/run/env/get/index.js +11 -11
  45. package/dist/commands/run/env/list/index.d.ts +3 -2
  46. package/dist/commands/run/env/list/index.js +17 -19
  47. package/dist/commands/run/env/set/index.d.ts +3 -2
  48. package/dist/commands/run/env/set/index.js +5 -5
  49. package/dist/commands/run/exec/index.d.ts +19 -8
  50. package/dist/commands/run/exec/index.js +186 -108
  51. package/dist/commands/run/info/index.d.ts +5 -4
  52. package/dist/commands/run/info/index.js +27 -27
  53. package/dist/commands/run/projects/create/index.d.ts +4 -3
  54. package/dist/commands/run/projects/create/index.js +23 -23
  55. package/dist/commands/run/projects/delete/index.d.ts +3 -2
  56. package/dist/commands/run/projects/delete/index.js +10 -10
  57. package/dist/commands/run/projects/list/index.d.ts +3 -2
  58. package/dist/commands/run/projects/list/index.js +12 -12
  59. package/dist/commands/run/projects/update/index.d.ts +4 -3
  60. package/dist/commands/run/projects/update/index.js +21 -21
  61. package/dist/commands/run/secrets/delete/index.d.ts +3 -2
  62. package/dist/commands/run/secrets/delete/index.js +10 -10
  63. package/dist/commands/run/secrets/get/index.d.ts +3 -2
  64. package/dist/commands/run/secrets/get/index.js +11 -11
  65. package/dist/commands/run/secrets/list/index.d.ts +3 -2
  66. package/dist/commands/run/secrets/list/index.js +22 -24
  67. package/dist/commands/run/secrets/set/index.d.ts +4 -3
  68. package/dist/commands/run/secrets/set/index.js +16 -16
  69. package/dist/commands/run/sessions/delete/index.d.ts +3 -2
  70. package/dist/commands/run/sessions/delete/index.js +10 -10
  71. package/dist/commands/run/sessions/get/index.d.ts +3 -2
  72. package/dist/commands/run/sessions/get/index.js +11 -11
  73. package/dist/commands/run/sessions/list/index.d.ts +3 -2
  74. package/dist/commands/run/sessions/list/index.js +11 -11
  75. package/dist/commands/run/sessions/start/index.d.ts +3 -2
  76. package/dist/commands/run/sessions/start/index.js +11 -11
  77. package/dist/commands/run/sessions/stop/index.d.ts +3 -2
  78. package/dist/commands/run/sessions/stop/index.js +11 -11
  79. package/dist/commands/run/sink/get/index.d.ts +3 -2
  80. package/dist/commands/run/sink/get/index.js +11 -11
  81. package/dist/commands/static_host/build/create/index.d.ts +5 -4
  82. package/dist/commands/static_host/build/create/index.js +33 -33
  83. package/dist/commands/static_host/build/get/index.d.ts +5 -4
  84. package/dist/commands/static_host/build/get/index.js +20 -20
  85. package/dist/commands/static_host/build/list/index.d.ts +4 -3
  86. package/dist/commands/static_host/build/list/index.js +31 -31
  87. package/dist/commands/static_host/list/index.d.ts +4 -3
  88. package/dist/commands/static_host/list/index.js +31 -31
  89. package/dist/commands/workspace/create/index.d.ts +14 -0
  90. package/dist/commands/workspace/create/index.js +131 -0
  91. package/dist/commands/workspace/delete/index.d.ts +20 -0
  92. package/dist/commands/workspace/delete/index.js +141 -0
  93. package/dist/commands/workspace/edit/index.d.ts +22 -0
  94. package/dist/commands/workspace/edit/index.js +176 -0
  95. package/dist/commands/workspace/get/index.d.ts +18 -0
  96. package/dist/commands/workspace/get/index.js +136 -0
  97. package/dist/commands/workspace/list/index.d.ts +3 -2
  98. package/dist/commands/workspace/list/index.js +15 -15
  99. package/dist/commands/workspace/pull/index.d.ts +5 -4
  100. package/dist/commands/workspace/pull/index.js +113 -64
  101. package/dist/commands/workspace/push/index.d.ts +1 -0
  102. package/dist/commands/workspace/push/index.js +5 -5
  103. package/dist/help.d.ts +1 -1
  104. package/dist/lib/base-run-command.d.ts +6 -6
  105. package/dist/lib/base-run-command.js +8 -6
  106. package/dist/lib/run-http-client.d.ts +24 -18
  107. package/dist/lib/run-http-client.js +96 -61
  108. package/dist/lib/run-types.d.ts +80 -80
  109. package/oclif.manifest.json +1963 -785
  110. 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
- if (args.function_id) {
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
- method: 'PUT',
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
- body: xanoscript,
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 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()}`;
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
- 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}`);
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
- throw 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
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 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
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
- originalContent = fs.readFileSync(filePath, 'utf8');
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
- this.error(`Failed to read file '${filePath}': ${error}`);
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
- catch (error) {
361
- this.error(`Failed to create temporary file: ${error}`);
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
- // Open the editor
380
+ // Read credentials file
364
381
  try {
365
- execSync(`${editor} ${tmpFile}`, { stdio: 'inherit' });
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
- // 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}`);
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
- 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
- }
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,16 +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>;
14
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
15
  };
13
- static description: string;
14
- static examples: string[];
15
16
  run(): Promise<void>;
16
- private promptForFunctionId;
17
17
  private loadCredentials;
18
+ private promptForFunctionId;
18
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
- if (args.function_id) {
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,19 +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
- order: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
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>;
16
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
17
  };
15
- static description: string;
16
- static examples: string[];
17
18
  run(): Promise<void>;
18
19
  private loadCredentials;
19
20
  }