@xano/cli 0.0.21 → 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.
Files changed (107) hide show
  1. package/dist/base-command.d.ts +1 -1
  2. package/dist/base-command.js +6 -6
  3. package/dist/commands/branch/create/index.d.ts +17 -0
  4. package/dist/commands/branch/create/index.js +164 -0
  5. package/dist/commands/branch/delete/index.d.ts +18 -0
  6. package/dist/commands/branch/delete/index.js +156 -0
  7. package/dist/commands/branch/edit/index.d.ts +19 -0
  8. package/dist/commands/branch/edit/index.js +166 -0
  9. package/dist/commands/branch/get/index.d.ts +16 -0
  10. package/dist/commands/branch/get/index.js +135 -0
  11. package/dist/commands/branch/list/index.d.ts +18 -0
  12. package/dist/commands/branch/list/index.js +138 -0
  13. package/dist/commands/branch/set-live/index.d.ts +18 -0
  14. package/dist/commands/branch/set-live/index.js +155 -0
  15. package/dist/commands/function/create/index.d.ts +6 -6
  16. package/dist/commands/function/create/index.js +55 -55
  17. package/dist/commands/function/edit/index.d.ts +10 -10
  18. package/dist/commands/function/edit/index.js +155 -162
  19. package/dist/commands/function/get/index.d.ts +5 -5
  20. package/dist/commands/function/get/index.js +55 -60
  21. package/dist/commands/function/list/index.d.ts +5 -5
  22. package/dist/commands/function/list/index.js +52 -52
  23. package/dist/commands/profile/create/index.d.ts +6 -6
  24. package/dist/commands/profile/create/index.js +37 -37
  25. package/dist/commands/profile/delete/index.d.ts +2 -2
  26. package/dist/commands/profile/delete/index.js +9 -9
  27. package/dist/commands/profile/edit/index.d.ts +7 -7
  28. package/dist/commands/profile/edit/index.js +47 -47
  29. package/dist/commands/profile/get-default/index.js +1 -1
  30. package/dist/commands/profile/list/index.d.ts +2 -2
  31. package/dist/commands/profile/list/index.js +9 -9
  32. package/dist/commands/profile/me/index.d.ts +3 -3
  33. package/dist/commands/profile/me/index.js +21 -21
  34. package/dist/commands/profile/project/index.js +1 -1
  35. package/dist/commands/profile/set-default/index.js +1 -1
  36. package/dist/commands/profile/token/index.js +1 -1
  37. package/dist/commands/profile/wizard/index.d.ts +4 -4
  38. package/dist/commands/profile/wizard/index.js +118 -122
  39. package/dist/commands/run/env/delete/index.d.ts +2 -2
  40. package/dist/commands/run/env/delete/index.js +9 -9
  41. package/dist/commands/run/env/get/index.d.ts +2 -2
  42. package/dist/commands/run/env/get/index.js +10 -10
  43. package/dist/commands/run/env/list/index.d.ts +2 -2
  44. package/dist/commands/run/env/list/index.js +16 -18
  45. package/dist/commands/run/env/set/index.d.ts +2 -2
  46. package/dist/commands/run/env/set/index.js +4 -4
  47. package/dist/commands/run/exec/index.d.ts +11 -11
  48. package/dist/commands/run/exec/index.js +109 -109
  49. package/dist/commands/run/info/index.d.ts +4 -4
  50. package/dist/commands/run/info/index.js +26 -26
  51. package/dist/commands/run/projects/create/index.d.ts +3 -3
  52. package/dist/commands/run/projects/create/index.js +22 -22
  53. package/dist/commands/run/projects/delete/index.d.ts +2 -2
  54. package/dist/commands/run/projects/delete/index.js +9 -9
  55. package/dist/commands/run/projects/list/index.d.ts +2 -2
  56. package/dist/commands/run/projects/list/index.js +11 -11
  57. package/dist/commands/run/projects/update/index.d.ts +3 -3
  58. package/dist/commands/run/projects/update/index.js +20 -20
  59. package/dist/commands/run/secrets/delete/index.d.ts +2 -2
  60. package/dist/commands/run/secrets/delete/index.js +9 -9
  61. package/dist/commands/run/secrets/get/index.d.ts +2 -2
  62. package/dist/commands/run/secrets/get/index.js +10 -10
  63. package/dist/commands/run/secrets/list/index.d.ts +2 -2
  64. package/dist/commands/run/secrets/list/index.js +21 -23
  65. package/dist/commands/run/secrets/set/index.d.ts +3 -3
  66. package/dist/commands/run/secrets/set/index.js +15 -15
  67. package/dist/commands/run/sessions/delete/index.d.ts +2 -2
  68. package/dist/commands/run/sessions/delete/index.js +9 -9
  69. package/dist/commands/run/sessions/get/index.d.ts +2 -2
  70. package/dist/commands/run/sessions/get/index.js +10 -10
  71. package/dist/commands/run/sessions/list/index.d.ts +2 -2
  72. package/dist/commands/run/sessions/list/index.js +10 -10
  73. package/dist/commands/run/sessions/start/index.d.ts +2 -2
  74. package/dist/commands/run/sessions/start/index.js +10 -10
  75. package/dist/commands/run/sessions/stop/index.d.ts +2 -2
  76. package/dist/commands/run/sessions/stop/index.js +10 -10
  77. package/dist/commands/run/sink/get/index.d.ts +2 -2
  78. package/dist/commands/run/sink/get/index.js +10 -10
  79. package/dist/commands/static_host/build/create/index.d.ts +4 -4
  80. package/dist/commands/static_host/build/create/index.js +33 -33
  81. package/dist/commands/static_host/build/get/index.d.ts +4 -4
  82. package/dist/commands/static_host/build/get/index.js +20 -20
  83. package/dist/commands/static_host/build/list/index.d.ts +3 -3
  84. package/dist/commands/static_host/build/list/index.js +31 -31
  85. package/dist/commands/static_host/list/index.d.ts +3 -3
  86. package/dist/commands/static_host/list/index.js +31 -31
  87. package/dist/commands/workspace/create/index.d.ts +3 -3
  88. package/dist/commands/workspace/create/index.js +24 -24
  89. package/dist/commands/workspace/delete/index.d.ts +2 -2
  90. package/dist/commands/workspace/delete/index.js +18 -18
  91. package/dist/commands/workspace/edit/index.d.ts +5 -5
  92. package/dist/commands/workspace/edit/index.js +34 -34
  93. package/dist/commands/workspace/get/index.d.ts +2 -2
  94. package/dist/commands/workspace/get/index.js +12 -12
  95. package/dist/commands/workspace/list/index.d.ts +2 -2
  96. package/dist/commands/workspace/list/index.js +15 -15
  97. package/dist/commands/workspace/pull/index.d.ts +4 -4
  98. package/dist/commands/workspace/pull/index.js +46 -51
  99. package/dist/commands/workspace/push/index.js +3 -3
  100. package/dist/help.d.ts +1 -1
  101. package/dist/lib/base-run-command.d.ts +4 -4
  102. package/dist/lib/base-run-command.js +3 -3
  103. package/dist/lib/run-http-client.d.ts +20 -20
  104. package/dist/lib/run-http-client.js +71 -71
  105. package/dist/lib/run-types.d.ts +80 -80
  106. package/oclif.manifest.json +1336 -815
  107. package/package.json +1 -1
@@ -1,20 +1,10 @@
1
1
  import { Flags } from '@oclif/core';
2
+ import * as yaml from 'js-yaml';
2
3
  import * as fs from 'node:fs';
3
4
  import * as os from 'node:os';
4
5
  import * as path from 'node:path';
5
- import * as yaml from 'js-yaml';
6
6
  import BaseCommand from '../../../base-command.js';
7
7
  export default class ProfileMe extends BaseCommand {
8
- static flags = {
9
- ...BaseCommand.baseFlags,
10
- output: Flags.string({
11
- char: 'o',
12
- description: 'Output format',
13
- required: false,
14
- default: 'summary',
15
- options: ['summary', 'json'],
16
- }),
17
- };
18
8
  static description = 'Get information about the currently authenticated user';
19
9
  static examples = [
20
10
  `$ xano profile:me
@@ -37,6 +27,16 @@ User Information:
37
27
  }
38
28
  `,
39
29
  ];
30
+ static flags = {
31
+ ...BaseCommand.baseFlags,
32
+ output: Flags.string({
33
+ char: 'o',
34
+ default: 'summary',
35
+ description: 'Output format',
36
+ options: ['summary', 'json'],
37
+ required: false,
38
+ }),
39
+ };
40
40
  async run() {
41
41
  const { flags } = await this.parse(ProfileMe);
42
42
  // Get profile name (default or from flag/env)
@@ -61,11 +61,11 @@ User Information:
61
61
  // Fetch user info from the API
62
62
  try {
63
63
  const response = await fetch(apiUrl, {
64
- method: 'GET',
65
64
  headers: {
66
65
  'accept': 'application/json',
67
66
  'Authorization': `Bearer ${profile.access_token}`,
68
67
  },
68
+ method: 'GET',
69
69
  });
70
70
  if (!response.ok) {
71
71
  const errorText = await response.text();
@@ -93,9 +93,9 @@ User Information:
93
93
  this.log(` Created: ${date.toISOString()}`);
94
94
  }
95
95
  // Display any other fields that aren't already shown
96
- const knownFields = ['id', 'name', 'email', 'created_at'];
96
+ const knownFields = new Set(['created_at', 'email', 'id', 'name']);
97
97
  for (const [key, value] of Object.entries(data)) {
98
- if (!knownFields.includes(key) && value !== null && value !== undefined) {
98
+ if (!knownFields.has(key) && value !== null && value !== undefined) {
99
99
  if (typeof value === 'object') {
100
100
  this.log(` ${this.formatKey(key)}: ${JSON.stringify(value)}`);
101
101
  }
@@ -115,6 +115,13 @@ User Information:
115
115
  }
116
116
  }
117
117
  }
118
+ formatKey(key) {
119
+ // Convert snake_case to Title Case
120
+ return key
121
+ .split('_')
122
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
123
+ .join(' ');
124
+ }
118
125
  loadCredentials() {
119
126
  const configDir = path.join(os.homedir(), '.xano');
120
127
  const credentialsPath = path.join(configDir, 'credentials.yaml');
@@ -136,11 +143,4 @@ User Information:
136
143
  this.error(`Failed to parse credentials file: ${error}`);
137
144
  }
138
145
  }
139
- formatKey(key) {
140
- // Convert snake_case to Title Case
141
- return key
142
- .split('_')
143
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
144
- .join(' ');
145
- }
146
146
  }
@@ -1,8 +1,8 @@
1
1
  import { Command } from '@oclif/core';
2
+ import * as yaml from 'js-yaml';
2
3
  import * as fs from 'node:fs';
3
4
  import * as os from 'node:os';
4
5
  import * as path from 'node:path';
5
- import * as yaml from 'js-yaml';
6
6
  export default class ProfileProject extends Command {
7
7
  static description = 'Print the project for the default profile';
8
8
  static examples = [
@@ -1,8 +1,8 @@
1
1
  import { Args, Command } from '@oclif/core';
2
+ import * as yaml from 'js-yaml';
2
3
  import * as fs from 'node:fs';
3
4
  import * as os from 'node:os';
4
5
  import * as path from 'node:path';
5
- import * as yaml from 'js-yaml';
6
6
  export default class ProfileSetDefault extends Command {
7
7
  static args = {
8
8
  name: Args.string({
@@ -1,8 +1,8 @@
1
1
  import { Command } from '@oclif/core';
2
+ import * as yaml from 'js-yaml';
2
3
  import * as fs from 'node:fs';
3
4
  import * as os from 'node:os';
4
5
  import * as path from 'node:path';
5
- import * as yaml from 'js-yaml';
6
6
  export default class ProfileToken extends Command {
7
7
  static description = 'Print the access token for the default profile';
8
8
  static examples = [
@@ -1,17 +1,17 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class ProfileWizard extends Command {
3
+ static description: string;
4
+ static examples: string[];
3
5
  static flags: {
4
6
  name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
5
7
  origin: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
6
8
  };
7
- static description: string;
8
- static examples: string[];
9
9
  run(): Promise<void>;
10
- private fetchInstances;
11
- private fetchWorkspaces;
12
10
  private fetchBranches;
11
+ private fetchInstances;
13
12
  private fetchProjects;
14
13
  private fetchRunProjects;
14
+ private fetchWorkspaces;
15
15
  private getDefaultProfileName;
16
16
  private saveProfile;
17
17
  }
@@ -1,24 +1,11 @@
1
1
  import { Command, 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 { DEFAULT_RUN_BASE_URL } from '../../../lib/run-http-client.js';
8
8
  export default class ProfileWizard extends Command {
9
- static flags = {
10
- name: Flags.string({
11
- char: 'n',
12
- description: 'Profile name (skip prompt if provided)',
13
- required: false,
14
- }),
15
- origin: Flags.string({
16
- char: 'o',
17
- description: 'Xano instance origin URL',
18
- required: false,
19
- default: 'https://app.xano.com',
20
- }),
21
- };
22
9
  static description = 'Create a new profile configuration using an interactive wizard';
23
10
  static examples = [
24
11
  `$ xano profile:wizard
@@ -31,6 +18,19 @@ Welcome to the Xano Profile Wizard!
31
18
  Profile 'production' created successfully at ~/.xano/credentials.yaml
32
19
  `,
33
20
  ];
21
+ static flags = {
22
+ name: Flags.string({
23
+ char: 'n',
24
+ description: 'Profile name (skip prompt if provided)',
25
+ required: false,
26
+ }),
27
+ origin: Flags.string({
28
+ char: 'o',
29
+ default: 'https://app.xano.com',
30
+ description: 'Xano instance origin URL',
31
+ required: false,
32
+ }),
33
+ };
34
34
  async run() {
35
35
  const { flags } = await this.parse(ProfileWizard);
36
36
  this.log('Welcome to the Xano Profile Wizard!');
@@ -39,11 +39,11 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
39
39
  // Step 1: Get access token
40
40
  const { accessToken } = await inquirer.prompt([
41
41
  {
42
- type: 'password',
43
- name: 'accessToken',
44
- message: 'Enter your access token',
45
42
  mask: '',
46
- validate: (input) => {
43
+ message: 'Enter your access token',
44
+ name: 'accessToken',
45
+ type: 'password',
46
+ validate(input) {
47
47
  if (!input || input.trim() === '') {
48
48
  return 'Access token cannot be empty';
49
49
  }
@@ -68,13 +68,13 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
68
68
  this.log('');
69
69
  const { instanceId } = await inquirer.prompt([
70
70
  {
71
- type: 'list',
72
- name: 'instanceId',
73
- message: 'Select an instance',
74
71
  choices: instances.map((inst) => ({
75
72
  name: `${inst.name} (${inst.display})`,
76
73
  value: inst.id,
77
74
  })),
75
+ message: 'Select an instance',
76
+ name: 'instanceId',
77
+ type: 'list',
78
78
  },
79
79
  ]);
80
80
  const selectedInstance = instances.find((inst) => inst.id === instanceId);
@@ -82,11 +82,11 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
82
82
  const defaultProfileName = flags.name || this.getDefaultProfileName();
83
83
  const { profileName } = await inquirer.prompt([
84
84
  {
85
- type: 'input',
86
- name: 'profileName',
87
- message: 'Profile name',
88
85
  default: defaultProfileName,
89
- validate: (input) => {
86
+ message: 'Profile name',
87
+ name: 'profileName',
88
+ type: 'input',
89
+ validate(input) {
90
90
  if (!input || input.trim() === '') {
91
91
  return 'Profile name cannot be empty';
92
92
  }
@@ -113,9 +113,6 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
113
113
  this.log('');
114
114
  const { selectedWorkspace } = await inquirer.prompt([
115
115
  {
116
- type: 'list',
117
- name: 'selectedWorkspace',
118
- message: 'Select a workspace (or skip to use default)',
119
116
  choices: [
120
117
  { name: '(Skip workspace)', value: '' },
121
118
  ...workspaces.map((ws) => ({
@@ -123,6 +120,9 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
123
120
  value: ws.id,
124
121
  })),
125
122
  ],
123
+ message: 'Select a workspace (or skip to use default)',
124
+ name: 'selectedWorkspace',
125
+ type: 'list',
126
126
  },
127
127
  ]);
128
128
  workspace = selectedWorkspace || undefined;
@@ -143,18 +143,16 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
143
143
  this.log('');
144
144
  const { selectedBranch } = await inquirer.prompt([
145
145
  {
146
- type: 'list',
147
- name: 'selectedBranch',
148
- message: 'Select a branch',
149
146
  choices: [
150
147
  { name: '(Skip and use live branch)', value: '' },
151
- ...branches.map((br) => {
152
- return {
153
- name: br.label,
154
- value: br.id,
155
- };
156
- }),
148
+ ...branches.map((br) => ({
149
+ name: br.label,
150
+ value: br.id,
151
+ })),
157
152
  ],
153
+ message: 'Select a branch',
154
+ name: 'selectedBranch',
155
+ type: 'list',
158
156
  },
159
157
  ]);
160
158
  branch = selectedBranch || undefined;
@@ -174,18 +172,16 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
174
172
  this.log('');
175
173
  const { selectedProject } = await inquirer.prompt([
176
174
  {
177
- type: 'list',
178
- name: 'selectedProject',
179
- message: 'Select a project',
180
175
  choices: [
181
176
  { name: '(Skip project)', value: '' },
182
- ...projects.map((proj) => {
183
- return {
184
- name: proj.name,
185
- value: proj.id,
186
- };
187
- }),
177
+ ...projects.map((proj) => ({
178
+ name: proj.name,
179
+ value: proj.id,
180
+ })),
188
181
  ],
182
+ message: 'Select a project',
183
+ name: 'selectedProject',
184
+ type: 'list',
189
185
  },
190
186
  ]);
191
187
  project = selectedProject || undefined;
@@ -213,13 +209,13 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
213
209
  }
214
210
  // Save profile
215
211
  await this.saveProfile({
216
- name: profileName,
217
- account_origin: flags.origin,
218
- instance_origin: selectedInstance.origin,
219
212
  access_token: accessToken,
220
- workspace,
213
+ account_origin: flags.origin,
221
214
  branch,
215
+ instance_origin: selectedInstance.origin,
216
+ name: profileName,
222
217
  project,
218
+ workspace,
223
219
  }, true);
224
220
  this.log('');
225
221
  this.log(`✓ Profile '${profileName}' created successfully!`);
@@ -232,52 +228,13 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
232
228
  throw error;
233
229
  }
234
230
  }
235
- async fetchInstances(accessToken, origin) {
236
- const response = await fetch(`${origin}/api:meta/instance`, {
237
- method: 'GET',
231
+ async fetchBranches(accessToken, origin, workspaceId) {
232
+ const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/branch`, {
238
233
  headers: {
239
234
  accept: 'application/json',
240
235
  Authorization: `Bearer ${accessToken}`,
241
236
  },
242
- });
243
- if (!response.ok) {
244
- if (response.status === 401) {
245
- throw new Error('Unauthorized. Please check your access token.');
246
- }
247
- throw new Error(`API request failed with status ${response.status}`);
248
- }
249
- const data = (await response.json());
250
- // Transform API response to Instance format
251
- // Assuming the API returns an array or object with instances
252
- if (Array.isArray(data)) {
253
- return data.map((inst) => ({
254
- id: inst.id || inst.name,
255
- name: inst.name,
256
- display: inst.display,
257
- origin: new URL(inst.meta_api).origin,
258
- }));
259
- }
260
- // If it's an object, try to extract instances
261
- if (data && typeof data === 'object') {
262
- const instances = data.instances || data.data || [];
263
- if (Array.isArray(instances)) {
264
- return instances.map((inst) => ({
265
- id: inst.id || inst.name,
266
- name: inst.name,
267
- display: inst.display,
268
- origin: new URL(inst.meta_api).origin,
269
- }));
270
- }
271
- }
272
- return [];
273
- }
274
- async fetchWorkspaces(accessToken, origin) {
275
- const response = await fetch(`${origin}/api:meta/workspace`, {
276
237
  method: 'GET',
277
- headers: {
278
- accept: 'application/json',
279
- Authorization: `Bearer ${accessToken}`,
280
- },
281
238
  });
282
239
  if (!response.ok) {
283
240
  if (response.status === 401) {
@@ -286,33 +243,33 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
286
243
  throw new Error(`API request failed with status ${response.status}`);
287
244
  }
288
245
  const data = (await response.json());
289
- // Transform API response to Workspace format
290
- // Assuming the API returns an array or object with workspaces
246
+ // Transform API response to Branch format
247
+ // Assuming the API returns an array or object with branches
291
248
  if (Array.isArray(data)) {
292
- return data.map((ws) => ({
293
- id: ws.id || ws.name,
294
- name: ws.name,
249
+ return data.map((br) => ({
250
+ id: br.id || br.label,
251
+ label: br.label,
295
252
  }));
296
253
  }
297
- // If it's an object, try to extract workspaces
254
+ // If it's an object, try to extract branches
298
255
  if (data && typeof data === 'object') {
299
- const workspaces = data.workspaces || data.data || [];
300
- if (Array.isArray(workspaces)) {
301
- return workspaces.map((ws) => ({
302
- id: ws.id || ws.name,
303
- name: ws.name,
256
+ const branches = data.branches || data.data || [];
257
+ if (Array.isArray(branches)) {
258
+ return branches.map((br) => ({
259
+ id: br.id || br.name,
260
+ label: br.label,
304
261
  }));
305
262
  }
306
263
  }
307
264
  return [];
308
265
  }
309
- async fetchBranches(accessToken, origin, workspaceId) {
310
- const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/branch`, {
311
- method: 'GET',
266
+ async fetchInstances(accessToken, origin) {
267
+ const response = await fetch(`${origin}/api:meta/instance`, {
312
268
  headers: {
313
269
  accept: 'application/json',
314
270
  Authorization: `Bearer ${accessToken}`,
315
271
  },
272
+ method: 'GET',
316
273
  });
317
274
  if (!response.ok) {
318
275
  if (response.status === 401) {
@@ -321,21 +278,25 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
321
278
  throw new Error(`API request failed with status ${response.status}`);
322
279
  }
323
280
  const data = (await response.json());
324
- // Transform API response to Branch format
325
- // Assuming the API returns an array or object with branches
281
+ // Transform API response to Instance format
282
+ // Assuming the API returns an array or object with instances
326
283
  if (Array.isArray(data)) {
327
- return data.map((br) => ({
328
- id: br.id || br.label,
329
- label: br.label,
284
+ return data.map((inst) => ({
285
+ display: inst.display,
286
+ id: inst.id || inst.name,
287
+ name: inst.name,
288
+ origin: new URL(inst.meta_api).origin,
330
289
  }));
331
290
  }
332
- // If it's an object, try to extract branches
291
+ // If it's an object, try to extract instances
333
292
  if (data && typeof data === 'object') {
334
- const branches = data.branches || data.data || [];
335
- if (Array.isArray(branches)) {
336
- return branches.map((br) => ({
337
- id: br.id || br.name,
338
- label: br.label,
293
+ const instances = data.instances || data.data || [];
294
+ if (Array.isArray(instances)) {
295
+ return instances.map((inst) => ({
296
+ display: inst.display,
297
+ id: inst.id || inst.name,
298
+ name: inst.name,
299
+ origin: new URL(inst.meta_api).origin,
339
300
  }));
340
301
  }
341
302
  }
@@ -344,11 +305,11 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
344
305
  async fetchProjects(accessToken, origin, workspaceId, branchId) {
345
306
  const branchParam = branchId ? `?branch=${branchId}` : '';
346
307
  const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/project${branchParam}`, {
347
- method: 'GET',
348
308
  headers: {
349
309
  accept: 'application/json',
350
310
  Authorization: `Bearer ${accessToken}`,
351
311
  },
312
+ method: 'GET',
352
313
  });
353
314
  if (!response.ok) {
354
315
  if (response.status === 401) {
@@ -380,11 +341,11 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
380
341
  async fetchRunProjects(accessToken, runBaseUrl = DEFAULT_RUN_BASE_URL) {
381
342
  const baseUrl = runBaseUrl.endsWith('/') ? runBaseUrl.slice(0, -1) : runBaseUrl;
382
343
  const response = await fetch(`${baseUrl}/api:run/project`, {
383
- method: 'GET',
384
344
  headers: {
385
- 'Content-Type': 'application/json',
386
345
  Authorization: `Bearer ${accessToken}`,
346
+ 'Content-Type': 'application/json',
387
347
  },
348
+ method: 'GET',
388
349
  });
389
350
  if (!response.ok) {
390
351
  if (response.status === 401) {
@@ -395,6 +356,41 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
395
356
  const data = (await response.json());
396
357
  return Array.isArray(data) ? data : [];
397
358
  }
359
+ async fetchWorkspaces(accessToken, origin) {
360
+ const response = await fetch(`${origin}/api:meta/workspace`, {
361
+ headers: {
362
+ accept: 'application/json',
363
+ Authorization: `Bearer ${accessToken}`,
364
+ },
365
+ method: 'GET',
366
+ });
367
+ if (!response.ok) {
368
+ if (response.status === 401) {
369
+ throw new Error('Unauthorized. Please check your access token.');
370
+ }
371
+ throw new Error(`API request failed with status ${response.status}`);
372
+ }
373
+ const data = (await response.json());
374
+ // Transform API response to Workspace format
375
+ // Assuming the API returns an array or object with workspaces
376
+ if (Array.isArray(data)) {
377
+ return data.map((ws) => ({
378
+ id: ws.id || ws.name,
379
+ name: ws.name,
380
+ }));
381
+ }
382
+ // If it's an object, try to extract workspaces
383
+ if (data && typeof data === 'object') {
384
+ const workspaces = data.workspaces || data.data || [];
385
+ if (Array.isArray(workspaces)) {
386
+ return workspaces.map((ws) => ({
387
+ id: ws.id || ws.name,
388
+ name: ws.name,
389
+ }));
390
+ }
391
+ }
392
+ return [];
393
+ }
398
394
  getDefaultProfileName() {
399
395
  try {
400
396
  const configDir = path.join(os.homedir(), '.xano');
@@ -430,15 +426,15 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
430
426
  credentials = parsed;
431
427
  }
432
428
  }
433
- catch (error) {
429
+ catch {
434
430
  // Continue with empty credentials if parse fails
435
431
  }
436
432
  }
437
433
  // Add or update the profile
438
434
  credentials.profiles[profile.name] = {
435
+ access_token: profile.access_token,
439
436
  account_origin: profile.account_origin,
440
437
  instance_origin: profile.instance_origin,
441
- access_token: profile.access_token,
442
438
  ...(profile.workspace && { workspace: profile.workspace }),
443
439
  ...(profile.branch && { branch: profile.branch }),
444
440
  ...(profile.project && { project: profile.project }),
@@ -3,12 +3,12 @@ export default class RunEnvDelete extends BaseRunCommand {
3
3
  static args: {
4
4
  name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
5
  };
6
+ static description: string;
7
+ static examples: string[];
6
8
  static flags: {
7
9
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
10
  profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
11
  verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
12
  };
11
- static description: string;
12
- static examples: string[];
13
13
  run(): Promise<void>;
14
14
  }
@@ -7,15 +7,6 @@ export default class RunEnvDelete extends BaseRunCommand {
7
7
  required: true,
8
8
  }),
9
9
  };
10
- static flags = {
11
- ...BaseRunCommand.baseFlags,
12
- force: Flags.boolean({
13
- char: 'f',
14
- description: 'Skip confirmation prompt',
15
- required: false,
16
- default: false,
17
- }),
18
- };
19
10
  static description = 'Delete an environment variable';
20
11
  static examples = [
21
12
  `$ xano run env delete API_KEY
@@ -26,6 +17,15 @@ Environment variable 'API_KEY' deleted successfully!
26
17
  Environment variable 'API_KEY' deleted successfully!
27
18
  `,
28
19
  ];
20
+ static flags = {
21
+ ...BaseRunCommand.baseFlags,
22
+ force: Flags.boolean({
23
+ char: 'f',
24
+ default: false,
25
+ description: 'Skip confirmation prompt',
26
+ required: false,
27
+ }),
28
+ };
29
29
  async run() {
30
30
  const { args, flags } = await this.parse(RunEnvDelete);
31
31
  // Initialize with project required
@@ -3,12 +3,12 @@ export default class RunEnvGet extends BaseRunCommand {
3
3
  static args: {
4
4
  name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
5
  };
6
+ static description: string;
7
+ static examples: string[];
6
8
  static flags: {
7
9
  output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
10
  profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
11
  verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
12
  };
11
- static description: string;
12
- static examples: string[];
13
13
  run(): Promise<void>;
14
14
  }
@@ -7,16 +7,6 @@ export default class RunEnvGet extends BaseRunCommand {
7
7
  required: true,
8
8
  }),
9
9
  };
10
- static flags = {
11
- ...BaseRunCommand.baseFlags,
12
- output: Flags.string({
13
- char: 'o',
14
- description: 'Output format',
15
- required: false,
16
- default: 'value',
17
- options: ['value', 'json'],
18
- }),
19
- };
20
10
  static description = 'Get an environment variable value';
21
11
  static examples = [
22
12
  `$ xano run env get API_KEY
@@ -26,6 +16,16 @@ my-secret-api-key
26
16
  { "name": "API_KEY", "value": "my-secret-api-key" }
27
17
  `,
28
18
  ];
19
+ static flags = {
20
+ ...BaseRunCommand.baseFlags,
21
+ output: Flags.string({
22
+ char: 'o',
23
+ default: 'value',
24
+ description: 'Output format',
25
+ options: ['value', 'json'],
26
+ required: false,
27
+ }),
28
+ };
29
29
  async run() {
30
30
  const { args, flags } = await this.parse(RunEnvGet);
31
31
  // Initialize with project required
@@ -1,12 +1,12 @@
1
1
  import BaseRunCommand from '../../../../lib/base-run-command.js';
2
2
  export default class RunEnvList extends BaseRunCommand {
3
3
  static args: {};
4
+ static description: string;
5
+ static examples: string[];
4
6
  static flags: {
5
7
  output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
6
8
  profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
9
  verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
10
  };
9
- static description: string;
10
- static examples: string[];
11
11
  run(): Promise<void>;
12
12
  }