@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.
Files changed (108) hide show
  1. package/dist/base-command.d.ts +1 -3
  2. package/dist/base-command.js +5 -12
  3. package/dist/commands/function/create/index.d.ts +6 -7
  4. package/dist/commands/function/create/index.js +55 -55
  5. package/dist/commands/function/edit/index.d.ts +10 -11
  6. package/dist/commands/function/edit/index.js +162 -155
  7. package/dist/commands/function/get/index.d.ts +5 -6
  8. package/dist/commands/function/get/index.js +60 -55
  9. package/dist/commands/function/list/index.d.ts +5 -6
  10. package/dist/commands/function/list/index.js +52 -52
  11. package/dist/commands/profile/create/index.d.ts +6 -6
  12. package/dist/commands/profile/create/index.js +37 -37
  13. package/dist/commands/profile/delete/index.d.ts +2 -2
  14. package/dist/commands/profile/delete/index.js +9 -9
  15. package/dist/commands/profile/edit/index.d.ts +7 -8
  16. package/dist/commands/profile/edit/index.js +48 -48
  17. package/dist/commands/profile/get-default/index.js +1 -1
  18. package/dist/commands/profile/list/index.d.ts +2 -2
  19. package/dist/commands/profile/list/index.js +9 -9
  20. package/dist/commands/profile/me/index.d.ts +3 -4
  21. package/dist/commands/profile/me/index.js +21 -21
  22. package/dist/commands/profile/project/index.js +1 -1
  23. package/dist/commands/profile/set-default/index.js +1 -1
  24. package/dist/commands/profile/token/index.js +1 -1
  25. package/dist/commands/profile/wizard/index.d.ts +4 -5
  26. package/dist/commands/profile/wizard/index.js +108 -142
  27. package/dist/commands/run/env/delete/index.d.ts +2 -3
  28. package/dist/commands/run/env/delete/index.js +10 -10
  29. package/dist/commands/run/env/get/index.d.ts +2 -3
  30. package/dist/commands/run/env/get/index.js +11 -11
  31. package/dist/commands/run/env/list/index.d.ts +2 -3
  32. package/dist/commands/run/env/list/index.js +19 -17
  33. package/dist/commands/run/env/set/index.d.ts +2 -3
  34. package/dist/commands/run/env/set/index.js +5 -5
  35. package/dist/commands/run/exec/index.d.ts +8 -19
  36. package/dist/commands/run/exec/index.js +108 -186
  37. package/dist/commands/run/info/index.d.ts +4 -5
  38. package/dist/commands/run/info/index.js +27 -27
  39. package/dist/commands/run/projects/create/index.d.ts +3 -4
  40. package/dist/commands/run/projects/create/index.js +23 -23
  41. package/dist/commands/run/projects/delete/index.d.ts +2 -3
  42. package/dist/commands/run/projects/delete/index.js +10 -10
  43. package/dist/commands/run/projects/list/index.d.ts +2 -3
  44. package/dist/commands/run/projects/list/index.js +12 -12
  45. package/dist/commands/run/projects/update/index.d.ts +3 -4
  46. package/dist/commands/run/projects/update/index.js +21 -21
  47. package/dist/commands/run/secrets/delete/index.d.ts +2 -3
  48. package/dist/commands/run/secrets/delete/index.js +10 -10
  49. package/dist/commands/run/secrets/get/index.d.ts +2 -3
  50. package/dist/commands/run/secrets/get/index.js +11 -11
  51. package/dist/commands/run/secrets/list/index.d.ts +2 -3
  52. package/dist/commands/run/secrets/list/index.js +24 -22
  53. package/dist/commands/run/secrets/set/index.d.ts +3 -4
  54. package/dist/commands/run/secrets/set/index.js +16 -16
  55. package/dist/commands/run/sessions/delete/index.d.ts +2 -3
  56. package/dist/commands/run/sessions/delete/index.js +10 -10
  57. package/dist/commands/run/sessions/get/index.d.ts +2 -3
  58. package/dist/commands/run/sessions/get/index.js +11 -11
  59. package/dist/commands/run/sessions/list/index.d.ts +2 -3
  60. package/dist/commands/run/sessions/list/index.js +11 -11
  61. package/dist/commands/run/sessions/start/index.d.ts +2 -3
  62. package/dist/commands/run/sessions/start/index.js +11 -11
  63. package/dist/commands/run/sessions/stop/index.d.ts +2 -3
  64. package/dist/commands/run/sessions/stop/index.js +11 -11
  65. package/dist/commands/run/sink/get/index.d.ts +2 -3
  66. package/dist/commands/run/sink/get/index.js +11 -11
  67. package/dist/commands/static_host/build/create/index.d.ts +4 -5
  68. package/dist/commands/static_host/build/create/index.js +33 -33
  69. package/dist/commands/static_host/build/get/index.d.ts +4 -5
  70. package/dist/commands/static_host/build/get/index.js +20 -20
  71. package/dist/commands/static_host/build/list/index.d.ts +3 -4
  72. package/dist/commands/static_host/build/list/index.js +31 -31
  73. package/dist/commands/static_host/list/index.d.ts +3 -4
  74. package/dist/commands/static_host/list/index.js +31 -31
  75. package/dist/commands/workspace/list/index.d.ts +2 -3
  76. package/dist/commands/workspace/list/index.js +15 -15
  77. package/dist/commands/workspace/pull/index.d.ts +4 -5
  78. package/dist/commands/workspace/pull/index.js +52 -47
  79. package/dist/commands/workspace/push/index.d.ts +0 -1
  80. package/dist/commands/workspace/push/index.js +4 -4
  81. package/dist/help.d.ts +1 -1
  82. package/dist/lib/base-run-command.d.ts +6 -6
  83. package/dist/lib/base-run-command.js +6 -8
  84. package/dist/lib/run-http-client.d.ts +18 -24
  85. package/dist/lib/run-http-client.js +61 -96
  86. package/dist/lib/run-types.d.ts +80 -80
  87. package/oclif.manifest.json +888 -2031
  88. package/package.json +5 -2
  89. package/dist/commands/branch/create/index.d.ts +0 -17
  90. package/dist/commands/branch/create/index.js +0 -164
  91. package/dist/commands/branch/delete/index.d.ts +0 -18
  92. package/dist/commands/branch/delete/index.js +0 -156
  93. package/dist/commands/branch/edit/index.d.ts +0 -19
  94. package/dist/commands/branch/edit/index.js +0 -166
  95. package/dist/commands/branch/get/index.d.ts +0 -16
  96. package/dist/commands/branch/get/index.js +0 -135
  97. package/dist/commands/branch/list/index.d.ts +0 -18
  98. package/dist/commands/branch/list/index.js +0 -138
  99. package/dist/commands/branch/set-live/index.d.ts +0 -18
  100. package/dist/commands/branch/set-live/index.js +0 -155
  101. package/dist/commands/workspace/create/index.d.ts +0 -14
  102. package/dist/commands/workspace/create/index.js +0 -131
  103. package/dist/commands/workspace/delete/index.d.ts +0 -20
  104. package/dist/commands/workspace/delete/index.js +0 -141
  105. package/dist/commands/workspace/edit/index.d.ts +0 -22
  106. package/dist/commands/workspace/edit/index.js +0 -176
  107. package/dist/commands/workspace/get/index.d.ts +0 -18
  108. 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
- functionId = args.function_id ? args.function_id : (await this.promptForFunctionId(profile, workspaceId));
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
- body: xanoscript,
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
- method: 'PUT',
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 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
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
- execSync(`${editor} ${tmpFile}`, { stdio: 'inherit' });
273
- }
274
- catch (error) {
275
- // Clean up temp file
276
- try {
277
- fs.unlinkSync(tmpFile);
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
- catch {
280
- // Ignore cleanup errors
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
- this.error(`Editor exited with an error: ${error}`);
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 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()}`;
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
- 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 '';
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
- throw error;
351
+ this.error(`Failed to read file '${filePath}': ${error}`);
370
352
  }
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'`);
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
- // Read credentials file
360
+ catch (error) {
361
+ this.error(`Failed to create temporary file: ${error}`);
362
+ }
363
+ // Open the editor
381
364
  try {
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;
365
+ execSync(`${editor} ${tmpFile}`, { stdio: 'inherit' });
388
366
  }
389
367
  catch (error) {
390
- this.error(`Failed to parse credentials file: ${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}`);
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
- 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
- });
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
- functionId = args.function_id ? args.function_id : (await this.promptForFunctionId(profile, workspaceId));
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
- workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
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
  }