@xano/cli 0.0.25 → 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 (110) 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 +849 -2027
  88. package/package.json +3 -1
  89. package/dist/commands/auth/index.d.ts +0 -21
  90. package/dist/commands/auth/index.js +0 -533
  91. package/dist/commands/branch/create/index.d.ts +0 -17
  92. package/dist/commands/branch/create/index.js +0 -164
  93. package/dist/commands/branch/delete/index.d.ts +0 -18
  94. package/dist/commands/branch/delete/index.js +0 -156
  95. package/dist/commands/branch/edit/index.d.ts +0 -19
  96. package/dist/commands/branch/edit/index.js +0 -166
  97. package/dist/commands/branch/get/index.d.ts +0 -16
  98. package/dist/commands/branch/get/index.js +0 -135
  99. package/dist/commands/branch/list/index.d.ts +0 -18
  100. package/dist/commands/branch/list/index.js +0 -138
  101. package/dist/commands/branch/set-live/index.d.ts +0 -18
  102. package/dist/commands/branch/set-live/index.js +0 -155
  103. package/dist/commands/workspace/create/index.d.ts +0 -14
  104. package/dist/commands/workspace/create/index.js +0 -131
  105. package/dist/commands/workspace/delete/index.d.ts +0 -20
  106. package/dist/commands/workspace/delete/index.js +0 -141
  107. package/dist/commands/workspace/edit/index.d.ts +0 -22
  108. package/dist/commands/workspace/edit/index.js +0 -176
  109. package/dist/commands/workspace/get/index.d.ts +0 -18
  110. package/dist/commands/workspace/get/index.js +0 -136
@@ -1,10 +1,20 @@
1
1
  import { Flags } from '@oclif/core';
2
- import * as yaml from 'js-yaml';
3
2
  import * as fs from 'node:fs';
4
3
  import * as os from 'node:os';
5
4
  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
+ };
8
18
  static description = 'Get information about the currently authenticated user';
9
19
  static examples = [
10
20
  `$ xano profile:me
@@ -27,16 +37,6 @@ User Information:
27
37
  }
28
38
  `,
29
39
  ];
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',
64
65
  headers: {
65
66
  'accept': 'application/json',
66
67
  'Authorization': `Bearer ${profile.access_token}`,
67
68
  },
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 = new Set(['created_at', 'email', 'id', 'name']);
96
+ const knownFields = ['id', 'name', 'email', 'created_at'];
97
97
  for (const [key, value] of Object.entries(data)) {
98
- if (!knownFields.has(key) && value !== null && value !== undefined) {
98
+ if (!knownFields.includes(key) && value !== null && value !== undefined) {
99
99
  if (typeof value === 'object') {
100
100
  this.log(` ${this.formatKey(key)}: ${JSON.stringify(value)}`);
101
101
  }
@@ -115,13 +115,6 @@ 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
- }
125
118
  loadCredentials() {
126
119
  const configDir = path.join(os.homedir(), '.xano');
127
120
  const credentialsPath = path.join(configDir, 'credentials.yaml');
@@ -143,4 +136,11 @@ User Information:
143
136
  this.error(`Failed to parse credentials file: ${error}`);
144
137
  }
145
138
  }
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';
3
2
  import * as fs from 'node:fs';
4
3
  import * as os from 'node:os';
5
4
  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';
3
2
  import * as fs from 'node:fs';
4
3
  import * as os from 'node:os';
5
4
  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';
3
2
  import * as fs from 'node:fs';
4
3
  import * as os from 'node:os';
5
4
  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,16 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class ProfileWizard extends Command {
3
- static description: string;
4
- static examples: string[];
5
3
  static flags: {
6
4
  name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
5
  origin: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
8
6
  };
7
+ static description: string;
8
+ static examples: string[];
9
9
  run(): Promise<void>;
10
- private fetchBranches;
11
10
  private fetchInstances;
12
- private fetchProjects;
13
- private fetchRunProjects;
14
11
  private fetchWorkspaces;
12
+ private fetchBranches;
13
+ private fetchProjects;
15
14
  private getDefaultProfileName;
16
15
  private saveProfile;
17
16
  }
@@ -1,23 +1,10 @@
1
1
  import { Command, 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';
7
- import { DEFAULT_RUN_BASE_URL } from '../../../lib/run-http-client.js';
5
+ import * as yaml from 'js-yaml';
6
+ import inquirer from 'inquirer';
8
7
  export default class ProfileWizard extends Command {
9
- static description = 'Create a new profile configuration using an interactive wizard';
10
- static examples = [
11
- `$ xano profile:wizard
12
- Welcome to the Xano Profile Wizard!
13
- ? Enter your access token: ***...***
14
- ? Select an instance:
15
- > Production (https://app.xano.com)
16
- Staging (https://staging.xano.com)
17
- ? Profile name: production
18
- Profile 'production' created successfully at ~/.xano/credentials.yaml
19
- `,
20
- ];
21
8
  static flags = {
22
9
  name: Flags.string({
23
10
  char: 'n',
@@ -26,11 +13,23 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
26
13
  }),
27
14
  origin: Flags.string({
28
15
  char: 'o',
29
- default: 'https://app.xano.com',
30
16
  description: 'Xano instance origin URL',
31
17
  required: false,
18
+ default: 'https://app.xano.com',
32
19
  }),
33
20
  };
21
+ static description = 'Create a new profile configuration using an interactive wizard';
22
+ static examples = [
23
+ `$ xano profile:wizard
24
+ Welcome to the Xano Profile Wizard!
25
+ ? Enter your access token: ***...***
26
+ ? Select an instance:
27
+ > Production (https://app.xano.com)
28
+ Staging (https://staging.xano.com)
29
+ ? Profile name: production
30
+ Profile 'production' created successfully at ~/.xano/credentials.yaml
31
+ `,
32
+ ];
34
33
  async run() {
35
34
  const { flags } = await this.parse(ProfileWizard);
36
35
  this.log('Welcome to the Xano Profile Wizard!');
@@ -39,11 +38,11 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
39
38
  // Step 1: Get access token
40
39
  const { accessToken } = await inquirer.prompt([
41
40
  {
42
- mask: '',
43
- message: 'Enter your access token',
44
- name: 'accessToken',
45
41
  type: 'password',
46
- validate(input) {
42
+ name: 'accessToken',
43
+ message: 'Enter your access token',
44
+ mask: '',
45
+ validate: (input) => {
47
46
  if (!input || input.trim() === '') {
48
47
  return 'Access token cannot be empty';
49
48
  }
@@ -68,13 +67,13 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
68
67
  this.log('');
69
68
  const { instanceId } = await inquirer.prompt([
70
69
  {
70
+ type: 'list',
71
+ name: 'instanceId',
72
+ message: 'Select an instance',
71
73
  choices: instances.map((inst) => ({
72
74
  name: `${inst.name} (${inst.display})`,
73
75
  value: inst.id,
74
76
  })),
75
- message: 'Select an instance',
76
- name: 'instanceId',
77
- type: 'list',
78
77
  },
79
78
  ]);
80
79
  const selectedInstance = instances.find((inst) => inst.id === instanceId);
@@ -82,11 +81,11 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
82
81
  const defaultProfileName = flags.name || this.getDefaultProfileName();
83
82
  const { profileName } = await inquirer.prompt([
84
83
  {
85
- default: defaultProfileName,
86
- message: 'Profile name',
87
- name: 'profileName',
88
84
  type: 'input',
89
- validate(input) {
85
+ name: 'profileName',
86
+ message: 'Profile name',
87
+ default: defaultProfileName,
88
+ validate: (input) => {
90
89
  if (!input || input.trim() === '') {
91
90
  return 'Profile name cannot be empty';
92
91
  }
@@ -113,6 +112,9 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
113
112
  this.log('');
114
113
  const { selectedWorkspace } = await inquirer.prompt([
115
114
  {
115
+ type: 'list',
116
+ name: 'selectedWorkspace',
117
+ message: 'Select a workspace (or skip to use default)',
116
118
  choices: [
117
119
  { name: '(Skip workspace)', value: '' },
118
120
  ...workspaces.map((ws) => ({
@@ -120,9 +122,6 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
120
122
  value: ws.id,
121
123
  })),
122
124
  ],
123
- message: 'Select a workspace (or skip to use default)',
124
- name: 'selectedWorkspace',
125
- type: 'list',
126
125
  },
127
126
  ]);
128
127
  workspace = selectedWorkspace || undefined;
@@ -143,16 +142,18 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
143
142
  this.log('');
144
143
  const { selectedBranch } = await inquirer.prompt([
145
144
  {
145
+ type: 'list',
146
+ name: 'selectedBranch',
147
+ message: 'Select a branch',
146
148
  choices: [
147
149
  { name: '(Skip and use live branch)', value: '' },
148
- ...branches.map((br) => ({
149
- name: br.label,
150
- value: br.id,
151
- })),
150
+ ...branches.map((br) => {
151
+ return {
152
+ name: br.label,
153
+ value: br.id,
154
+ };
155
+ }),
152
156
  ],
153
- message: 'Select a branch',
154
- name: 'selectedBranch',
155
- type: 'list',
156
157
  },
157
158
  ]);
158
159
  branch = selectedBranch || undefined;
@@ -172,50 +173,33 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
172
173
  this.log('');
173
174
  const { selectedProject } = await inquirer.prompt([
174
175
  {
176
+ type: 'list',
177
+ name: 'selectedProject',
178
+ message: 'Select a project',
175
179
  choices: [
176
180
  { name: '(Skip project)', value: '' },
177
- ...projects.map((proj) => ({
178
- name: proj.name,
179
- value: proj.id,
180
- })),
181
+ ...projects.map((proj) => {
182
+ return {
183
+ name: proj.name,
184
+ value: proj.id,
185
+ };
186
+ }),
181
187
  ],
182
- message: 'Select a project',
183
- name: 'selectedProject',
184
- type: 'list',
185
188
  },
186
189
  ]);
187
190
  project = selectedProject || undefined;
188
191
  }
189
192
  }
190
193
  }
191
- // Step 7: Fetch run projects and auto-select the first one if no project was selected
192
- this.log('');
193
- this.log('Fetching available run projects...');
194
- try {
195
- const runProjects = await this.fetchRunProjects(accessToken);
196
- if (runProjects.length > 0) {
197
- // Use run project if no metadata project was selected
198
- if (!project) {
199
- project = runProjects[0].id;
200
- }
201
- this.log(`✓ Found ${runProjects.length} run project(s). Using "${runProjects[0].name}" as default.`);
202
- }
203
- else {
204
- this.log('No run projects found. You can create one later with "xano run projects create".');
205
- }
206
- }
207
- catch {
208
- // Silently ignore - project will remain undefined
209
- }
210
194
  // Save profile
211
195
  await this.saveProfile({
212
- access_token: accessToken,
196
+ name: profileName,
213
197
  account_origin: flags.origin,
214
- branch,
215
198
  instance_origin: selectedInstance.origin,
216
- name: profileName,
217
- project,
199
+ access_token: accessToken,
218
200
  workspace,
201
+ branch,
202
+ project,
219
203
  }, true);
220
204
  this.log('');
221
205
  this.log(`✓ Profile '${profileName}' created successfully!`);
@@ -228,48 +212,13 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
228
212
  throw error;
229
213
  }
230
214
  }
231
- async fetchBranches(accessToken, origin, workspaceId) {
232
- const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/branch`, {
233
- headers: {
234
- accept: 'application/json',
235
- Authorization: `Bearer ${accessToken}`,
236
- },
237
- method: 'GET',
238
- });
239
- if (!response.ok) {
240
- if (response.status === 401) {
241
- throw new Error('Unauthorized. Please check your access token.');
242
- }
243
- throw new Error(`API request failed with status ${response.status}`);
244
- }
245
- const data = (await response.json());
246
- // Transform API response to Branch format
247
- // Assuming the API returns an array or object with branches
248
- if (Array.isArray(data)) {
249
- return data.map((br) => ({
250
- id: br.id || br.label,
251
- label: br.label,
252
- }));
253
- }
254
- // If it's an object, try to extract branches
255
- if (data && typeof data === 'object') {
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,
261
- }));
262
- }
263
- }
264
- return [];
265
- }
266
215
  async fetchInstances(accessToken, origin) {
267
216
  const response = await fetch(`${origin}/api:meta/instance`, {
217
+ method: 'GET',
268
218
  headers: {
269
219
  accept: 'application/json',
270
220
  Authorization: `Bearer ${accessToken}`,
271
221
  },
272
- method: 'GET',
273
222
  });
274
223
  if (!response.ok) {
275
224
  if (response.status === 401) {
@@ -282,9 +231,9 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
282
231
  // Assuming the API returns an array or object with instances
283
232
  if (Array.isArray(data)) {
284
233
  return data.map((inst) => ({
285
- display: inst.display,
286
234
  id: inst.id || inst.name,
287
235
  name: inst.name,
236
+ display: inst.display,
288
237
  origin: new URL(inst.meta_api).origin,
289
238
  }));
290
239
  }
@@ -293,23 +242,22 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
293
242
  const instances = data.instances || data.data || [];
294
243
  if (Array.isArray(instances)) {
295
244
  return instances.map((inst) => ({
296
- display: inst.display,
297
245
  id: inst.id || inst.name,
298
246
  name: inst.name,
247
+ display: inst.display,
299
248
  origin: new URL(inst.meta_api).origin,
300
249
  }));
301
250
  }
302
251
  }
303
252
  return [];
304
253
  }
305
- async fetchProjects(accessToken, origin, workspaceId, branchId) {
306
- const branchParam = branchId ? `?branch=${branchId}` : '';
307
- const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/project${branchParam}`, {
254
+ async fetchWorkspaces(accessToken, origin) {
255
+ const response = await fetch(`${origin}/api:meta/workspace`, {
256
+ method: 'GET',
308
257
  headers: {
309
258
  accept: 'application/json',
310
259
  Authorization: `Bearer ${accessToken}`,
311
260
  },
312
- method: 'GET',
313
261
  });
314
262
  if (!response.ok) {
315
263
  if (response.status === 401) {
@@ -318,34 +266,33 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
318
266
  throw new Error(`API request failed with status ${response.status}`);
319
267
  }
320
268
  const data = (await response.json());
321
- // Transform API response to Project format
322
- // Assuming the API returns an array or object with projects
269
+ // Transform API response to Workspace format
270
+ // Assuming the API returns an array or object with workspaces
323
271
  if (Array.isArray(data)) {
324
- return data.map((proj) => ({
325
- id: proj.id || proj.name,
326
- name: proj.name,
272
+ return data.map((ws) => ({
273
+ id: ws.id || ws.name,
274
+ name: ws.name,
327
275
  }));
328
276
  }
329
- // If it's an object, try to extract projects
277
+ // If it's an object, try to extract workspaces
330
278
  if (data && typeof data === 'object') {
331
- const projects = data.projects || data.data || [];
332
- if (Array.isArray(projects)) {
333
- return projects.map((proj) => ({
334
- id: proj.id || proj.name,
335
- name: proj.name,
279
+ const workspaces = data.workspaces || data.data || [];
280
+ if (Array.isArray(workspaces)) {
281
+ return workspaces.map((ws) => ({
282
+ id: ws.id || ws.name,
283
+ name: ws.name,
336
284
  }));
337
285
  }
338
286
  }
339
287
  return [];
340
288
  }
341
- async fetchRunProjects(accessToken, runBaseUrl = DEFAULT_RUN_BASE_URL) {
342
- const baseUrl = runBaseUrl.endsWith('/') ? runBaseUrl.slice(0, -1) : runBaseUrl;
343
- const response = await fetch(`${baseUrl}/api:run/project`, {
289
+ async fetchBranches(accessToken, origin, workspaceId) {
290
+ const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/branch`, {
291
+ method: 'GET',
344
292
  headers: {
293
+ accept: 'application/json',
345
294
  Authorization: `Bearer ${accessToken}`,
346
- 'Content-Type': 'application/json',
347
295
  },
348
- method: 'GET',
349
296
  });
350
297
  if (!response.ok) {
351
298
  if (response.status === 401) {
@@ -354,15 +301,34 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
354
301
  throw new Error(`API request failed with status ${response.status}`);
355
302
  }
356
303
  const data = (await response.json());
357
- return Array.isArray(data) ? data : [];
304
+ // Transform API response to Branch format
305
+ // Assuming the API returns an array or object with branches
306
+ if (Array.isArray(data)) {
307
+ return data.map((br) => ({
308
+ id: br.id || br.label,
309
+ label: br.label,
310
+ }));
311
+ }
312
+ // If it's an object, try to extract branches
313
+ if (data && typeof data === 'object') {
314
+ const branches = data.branches || data.data || [];
315
+ if (Array.isArray(branches)) {
316
+ return branches.map((br) => ({
317
+ id: br.id || br.name,
318
+ label: br.label,
319
+ }));
320
+ }
321
+ }
322
+ return [];
358
323
  }
359
- async fetchWorkspaces(accessToken, origin) {
360
- const response = await fetch(`${origin}/api:meta/workspace`, {
324
+ async fetchProjects(accessToken, origin, workspaceId, branchId) {
325
+ const branchParam = branchId ? `?branch=${branchId}` : '';
326
+ const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/project${branchParam}`, {
327
+ method: 'GET',
361
328
  headers: {
362
329
  accept: 'application/json',
363
330
  Authorization: `Bearer ${accessToken}`,
364
331
  },
365
- method: 'GET',
366
332
  });
367
333
  if (!response.ok) {
368
334
  if (response.status === 401) {
@@ -371,21 +337,21 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
371
337
  throw new Error(`API request failed with status ${response.status}`);
372
338
  }
373
339
  const data = (await response.json());
374
- // Transform API response to Workspace format
375
- // Assuming the API returns an array or object with workspaces
340
+ // Transform API response to Project format
341
+ // Assuming the API returns an array or object with projects
376
342
  if (Array.isArray(data)) {
377
- return data.map((ws) => ({
378
- id: ws.id || ws.name,
379
- name: ws.name,
343
+ return data.map((proj) => ({
344
+ id: proj.id || proj.name,
345
+ name: proj.name,
380
346
  }));
381
347
  }
382
- // If it's an object, try to extract workspaces
348
+ // If it's an object, try to extract projects
383
349
  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,
350
+ const projects = data.projects || data.data || [];
351
+ if (Array.isArray(projects)) {
352
+ return projects.map((proj) => ({
353
+ id: proj.id || proj.name,
354
+ name: proj.name,
389
355
  }));
390
356
  }
391
357
  }
@@ -426,15 +392,15 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
426
392
  credentials = parsed;
427
393
  }
428
394
  }
429
- catch {
395
+ catch (error) {
430
396
  // Continue with empty credentials if parse fails
431
397
  }
432
398
  }
433
399
  // Add or update the profile
434
400
  credentials.profiles[profile.name] = {
435
- access_token: profile.access_token,
436
401
  account_origin: profile.account_origin,
437
402
  instance_origin: profile.instance_origin,
403
+ access_token: profile.access_token,
438
404
  ...(profile.workspace && { workspace: profile.workspace }),
439
405
  ...(profile.branch && { branch: profile.branch }),
440
406
  ...(profile.project && { project: profile.project }),
@@ -3,12 +3,11 @@ 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[];
8
6
  static flags: {
9
7
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
8
  profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
- verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
9
  };
10
+ static description: string;
11
+ static examples: string[];
13
12
  run(): Promise<void>;
14
13
  }
@@ -7,6 +7,15 @@ 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
+ };
10
19
  static description = 'Delete an environment variable';
11
20
  static examples = [
12
21
  `$ xano run env delete API_KEY
@@ -17,19 +26,10 @@ Environment variable 'API_KEY' deleted successfully!
17
26
  Environment variable 'API_KEY' deleted successfully!
18
27
  `,
19
28
  ];
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
32
- await this.initRunCommandWithProject(flags.profile, flags.verbose);
32
+ await this.initRunCommandWithProject(flags.profile);
33
33
  // Confirm deletion unless --force is used
34
34
  if (!flags.force) {
35
35
  const readline = await import('node:readline');
@@ -3,12 +3,11 @@ 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[];
8
6
  static flags: {
9
7
  output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
8
  profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
- verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
9
  };
10
+ static description: string;
11
+ static examples: string[];
13
12
  run(): Promise<void>;
14
13
  }