@xano/cli 0.0.26 → 0.0.28

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 +6 -4
  100. package/dist/commands/workspace/pull/index.js +123 -63
  101. package/dist/commands/workspace/push/index.d.ts +2 -0
  102. package/dist/commands/workspace/push/index.js +16 -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 +2041 -843
  110. 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,16 +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;
13
+ private fetchRunProjects;
14
+ private fetchWorkspaces;
14
15
  private getDefaultProfileName;
15
16
  private saveProfile;
16
17
  }
@@ -1,23 +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
+ import { DEFAULT_RUN_BASE_URL } from '../../../lib/run-http-client.js';
7
8
  export default class ProfileWizard extends Command {
8
- static flags = {
9
- name: Flags.string({
10
- char: 'n',
11
- description: 'Profile name (skip prompt if provided)',
12
- required: false,
13
- }),
14
- origin: Flags.string({
15
- char: 'o',
16
- description: 'Xano instance origin URL',
17
- required: false,
18
- default: 'https://app.xano.com',
19
- }),
20
- };
21
9
  static description = 'Create a new profile configuration using an interactive wizard';
22
10
  static examples = [
23
11
  `$ xano profile:wizard
@@ -30,6 +18,19 @@ Welcome to the Xano Profile Wizard!
30
18
  Profile 'production' created successfully at ~/.xano/credentials.yaml
31
19
  `,
32
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
+ };
33
34
  async run() {
34
35
  const { flags } = await this.parse(ProfileWizard);
35
36
  this.log('Welcome to the Xano Profile Wizard!');
@@ -38,11 +39,11 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
38
39
  // Step 1: Get access token
39
40
  const { accessToken } = await inquirer.prompt([
40
41
  {
41
- type: 'password',
42
- name: 'accessToken',
43
- message: 'Enter your access token',
44
42
  mask: '',
45
- validate: (input) => {
43
+ message: 'Enter your access token',
44
+ name: 'accessToken',
45
+ type: 'password',
46
+ validate(input) {
46
47
  if (!input || input.trim() === '') {
47
48
  return 'Access token cannot be empty';
48
49
  }
@@ -67,13 +68,13 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
67
68
  this.log('');
68
69
  const { instanceId } = await inquirer.prompt([
69
70
  {
70
- type: 'list',
71
- name: 'instanceId',
72
- message: 'Select an instance',
73
71
  choices: instances.map((inst) => ({
74
72
  name: `${inst.name} (${inst.display})`,
75
73
  value: inst.id,
76
74
  })),
75
+ message: 'Select an instance',
76
+ name: 'instanceId',
77
+ type: 'list',
77
78
  },
78
79
  ]);
79
80
  const selectedInstance = instances.find((inst) => inst.id === instanceId);
@@ -81,11 +82,11 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
81
82
  const defaultProfileName = flags.name || this.getDefaultProfileName();
82
83
  const { profileName } = await inquirer.prompt([
83
84
  {
84
- type: 'input',
85
- name: 'profileName',
86
- message: 'Profile name',
87
85
  default: defaultProfileName,
88
- validate: (input) => {
86
+ message: 'Profile name',
87
+ name: 'profileName',
88
+ type: 'input',
89
+ validate(input) {
89
90
  if (!input || input.trim() === '') {
90
91
  return 'Profile name cannot be empty';
91
92
  }
@@ -112,9 +113,6 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
112
113
  this.log('');
113
114
  const { selectedWorkspace } = await inquirer.prompt([
114
115
  {
115
- type: 'list',
116
- name: 'selectedWorkspace',
117
- message: 'Select a workspace (or skip to use default)',
118
116
  choices: [
119
117
  { name: '(Skip workspace)', value: '' },
120
118
  ...workspaces.map((ws) => ({
@@ -122,6 +120,9 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
122
120
  value: ws.id,
123
121
  })),
124
122
  ],
123
+ message: 'Select a workspace (or skip to use default)',
124
+ name: 'selectedWorkspace',
125
+ type: 'list',
125
126
  },
126
127
  ]);
127
128
  workspace = selectedWorkspace || undefined;
@@ -142,18 +143,16 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
142
143
  this.log('');
143
144
  const { selectedBranch } = await inquirer.prompt([
144
145
  {
145
- type: 'list',
146
- name: 'selectedBranch',
147
- message: 'Select a branch',
148
146
  choices: [
149
147
  { name: '(Skip and use live branch)', value: '' },
150
- ...branches.map((br) => {
151
- return {
152
- name: br.label,
153
- value: br.id,
154
- };
155
- }),
148
+ ...branches.map((br) => ({
149
+ name: br.label,
150
+ value: br.id,
151
+ })),
156
152
  ],
153
+ message: 'Select a branch',
154
+ name: 'selectedBranch',
155
+ type: 'list',
157
156
  },
158
157
  ]);
159
158
  branch = selectedBranch || undefined;
@@ -173,33 +172,50 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
173
172
  this.log('');
174
173
  const { selectedProject } = await inquirer.prompt([
175
174
  {
176
- type: 'list',
177
- name: 'selectedProject',
178
- message: 'Select a project',
179
175
  choices: [
180
176
  { name: '(Skip project)', value: '' },
181
- ...projects.map((proj) => {
182
- return {
183
- name: proj.name,
184
- value: proj.id,
185
- };
186
- }),
177
+ ...projects.map((proj) => ({
178
+ name: proj.name,
179
+ value: proj.id,
180
+ })),
187
181
  ],
182
+ message: 'Select a project',
183
+ name: 'selectedProject',
184
+ type: 'list',
188
185
  },
189
186
  ]);
190
187
  project = selectedProject || undefined;
191
188
  }
192
189
  }
193
190
  }
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
+ }
194
210
  // Save profile
195
211
  await this.saveProfile({
196
- name: profileName,
197
- account_origin: flags.origin,
198
- instance_origin: selectedInstance.origin,
199
212
  access_token: accessToken,
200
- workspace,
213
+ account_origin: flags.origin,
201
214
  branch,
215
+ instance_origin: selectedInstance.origin,
216
+ name: profileName,
202
217
  project,
218
+ workspace,
203
219
  }, true);
204
220
  this.log('');
205
221
  this.log(`✓ Profile '${profileName}' created successfully!`);
@@ -212,13 +228,48 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
212
228
  throw error;
213
229
  }
214
230
  }
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
+ }
215
266
  async fetchInstances(accessToken, origin) {
216
267
  const response = await fetch(`${origin}/api:meta/instance`, {
217
- method: 'GET',
218
268
  headers: {
219
269
  accept: 'application/json',
220
270
  Authorization: `Bearer ${accessToken}`,
221
271
  },
272
+ method: 'GET',
222
273
  });
223
274
  if (!response.ok) {
224
275
  if (response.status === 401) {
@@ -231,9 +282,9 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
231
282
  // Assuming the API returns an array or object with instances
232
283
  if (Array.isArray(data)) {
233
284
  return data.map((inst) => ({
285
+ display: inst.display,
234
286
  id: inst.id || inst.name,
235
287
  name: inst.name,
236
- display: inst.display,
237
288
  origin: new URL(inst.meta_api).origin,
238
289
  }));
239
290
  }
@@ -242,22 +293,23 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
242
293
  const instances = data.instances || data.data || [];
243
294
  if (Array.isArray(instances)) {
244
295
  return instances.map((inst) => ({
296
+ display: inst.display,
245
297
  id: inst.id || inst.name,
246
298
  name: inst.name,
247
- display: inst.display,
248
299
  origin: new URL(inst.meta_api).origin,
249
300
  }));
250
301
  }
251
302
  }
252
303
  return [];
253
304
  }
254
- async fetchWorkspaces(accessToken, origin) {
255
- const response = await fetch(`${origin}/api:meta/workspace`, {
256
- method: 'GET',
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}`, {
257
308
  headers: {
258
309
  accept: 'application/json',
259
310
  Authorization: `Bearer ${accessToken}`,
260
311
  },
312
+ method: 'GET',
261
313
  });
262
314
  if (!response.ok) {
263
315
  if (response.status === 401) {
@@ -266,33 +318,34 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
266
318
  throw new Error(`API request failed with status ${response.status}`);
267
319
  }
268
320
  const data = (await response.json());
269
- // Transform API response to Workspace format
270
- // Assuming the API returns an array or object with workspaces
321
+ // Transform API response to Project format
322
+ // Assuming the API returns an array or object with projects
271
323
  if (Array.isArray(data)) {
272
- return data.map((ws) => ({
273
- id: ws.id || ws.name,
274
- name: ws.name,
324
+ return data.map((proj) => ({
325
+ id: proj.id || proj.name,
326
+ name: proj.name,
275
327
  }));
276
328
  }
277
- // If it's an object, try to extract workspaces
329
+ // If it's an object, try to extract projects
278
330
  if (data && typeof data === 'object') {
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,
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,
284
336
  }));
285
337
  }
286
338
  }
287
339
  return [];
288
340
  }
289
- async fetchBranches(accessToken, origin, workspaceId) {
290
- const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/branch`, {
291
- method: 'GET',
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`, {
292
344
  headers: {
293
- accept: 'application/json',
294
345
  Authorization: `Bearer ${accessToken}`,
346
+ 'Content-Type': 'application/json',
295
347
  },
348
+ method: 'GET',
296
349
  });
297
350
  if (!response.ok) {
298
351
  if (response.status === 401) {
@@ -301,34 +354,15 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
301
354
  throw new Error(`API request failed with status ${response.status}`);
302
355
  }
303
356
  const data = (await response.json());
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 [];
357
+ return Array.isArray(data) ? data : [];
323
358
  }
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',
359
+ async fetchWorkspaces(accessToken, origin) {
360
+ const response = await fetch(`${origin}/api:meta/workspace`, {
328
361
  headers: {
329
362
  accept: 'application/json',
330
363
  Authorization: `Bearer ${accessToken}`,
331
364
  },
365
+ method: 'GET',
332
366
  });
333
367
  if (!response.ok) {
334
368
  if (response.status === 401) {
@@ -337,21 +371,21 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
337
371
  throw new Error(`API request failed with status ${response.status}`);
338
372
  }
339
373
  const data = (await response.json());
340
- // Transform API response to Project format
341
- // Assuming the API returns an array or object with projects
374
+ // Transform API response to Workspace format
375
+ // Assuming the API returns an array or object with workspaces
342
376
  if (Array.isArray(data)) {
343
- return data.map((proj) => ({
344
- id: proj.id || proj.name,
345
- name: proj.name,
377
+ return data.map((ws) => ({
378
+ id: ws.id || ws.name,
379
+ name: ws.name,
346
380
  }));
347
381
  }
348
- // If it's an object, try to extract projects
382
+ // If it's an object, try to extract workspaces
349
383
  if (data && typeof data === 'object') {
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,
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,
355
389
  }));
356
390
  }
357
391
  }
@@ -392,15 +426,15 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
392
426
  credentials = parsed;
393
427
  }
394
428
  }
395
- catch (error) {
429
+ catch {
396
430
  // Continue with empty credentials if parse fails
397
431
  }
398
432
  }
399
433
  // Add or update the profile
400
434
  credentials.profiles[profile.name] = {
435
+ access_token: profile.access_token,
401
436
  account_origin: profile.account_origin,
402
437
  instance_origin: profile.instance_origin,
403
- access_token: profile.access_token,
404
438
  ...(profile.workspace && { workspace: profile.workspace }),
405
439
  ...(profile.branch && { branch: profile.branch }),
406
440
  ...(profile.project && { project: profile.project }),
@@ -3,11 +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>;
11
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
12
  };
10
- static description: string;
11
- static examples: string[];
12
13
  run(): Promise<void>;
13
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,10 +17,19 @@ 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
32
- await this.initRunCommandWithProject(flags.profile);
32
+ await this.initRunCommandWithProject(flags.profile, flags.verbose);
33
33
  // Confirm deletion unless --force is used
34
34
  if (!flags.force) {
35
35
  const readline = await import('node:readline');
@@ -3,11 +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>;
11
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
12
  };
10
- static description: string;
11
- static examples: string[];
12
13
  run(): Promise<void>;
13
14
  }