@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
@@ -8,6 +8,6 @@ export default abstract class BaseCommand extends Command {
8
8
  profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
9
  verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
10
  };
11
- protected getProfile(): string | undefined;
12
11
  protected getDefaultProfile(): string;
12
+ protected getProfile(): string | undefined;
13
13
  }
@@ -1,8 +1,8 @@
1
1
  import { Command, 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
  export default class BaseCommand extends Command {
7
7
  static baseFlags = {
8
8
  profile: Flags.string({
@@ -13,18 +13,14 @@ export default class BaseCommand extends Command {
13
13
  }),
14
14
  verbose: Flags.boolean({
15
15
  char: 'v',
16
+ default: false,
16
17
  description: 'Show detailed request/response information',
17
18
  env: 'XANO_VERBOSE',
18
19
  required: false,
19
- default: false,
20
20
  }),
21
21
  };
22
22
  // Override the flags property to include baseFlags
23
23
  static flags = BaseCommand.baseFlags;
24
- // Helper method to get the profile flag value
25
- getProfile() {
26
- return this.flags?.profile;
27
- }
28
24
  // Helper method to get the default profile from credentials file
29
25
  getDefaultProfile() {
30
26
  try {
@@ -44,4 +40,8 @@ export default class BaseCommand extends Command {
44
40
  return 'default';
45
41
  }
46
42
  }
43
+ // Helper method to get the profile flag value
44
+ getProfile() {
45
+ return this.flags?.profile;
46
+ }
47
47
  }
@@ -0,0 +1,17 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class BranchCreate extends BaseCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ color: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ label: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ source: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ workspace: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ private loadCredentials;
17
+ }
@@ -0,0 +1,164 @@
1
+ import { Flags } from '@oclif/core';
2
+ import * as yaml from 'js-yaml';
3
+ import * as fs from 'node:fs';
4
+ import * as os from 'node:os';
5
+ import * as path from 'node:path';
6
+ import BaseCommand from '../../../base-command.js';
7
+ export default class BranchCreate extends BaseCommand {
8
+ static description = 'Create a new branch by cloning from an existing branch';
9
+ static examples = [
10
+ `$ xano branch create --label dev
11
+ Created branch: dev
12
+ Cloned from: v1
13
+ `,
14
+ `$ xano branch create -l feature-auth -s dev -d "Authentication feature"
15
+ Created branch: feature-auth
16
+ Cloned from: dev
17
+ Description: Authentication feature
18
+ `,
19
+ `$ xano branch create --label staging --color "#ebc346" --output json
20
+ {
21
+ "created_at": "2024-02-11T10:00:00Z",
22
+ "label": "staging",
23
+ "backup": false,
24
+ "live": false
25
+ }
26
+ `,
27
+ ];
28
+ static flags = {
29
+ ...BaseCommand.baseFlags,
30
+ color: Flags.string({
31
+ char: 'c',
32
+ description: 'Color hex code for the branch (e.g., "#ebc346")',
33
+ required: false,
34
+ }),
35
+ description: Flags.string({
36
+ char: 'd',
37
+ description: 'Description for the new branch',
38
+ required: false,
39
+ }),
40
+ label: Flags.string({
41
+ char: 'l',
42
+ description: 'Label for the new branch',
43
+ required: true,
44
+ }),
45
+ output: Flags.string({
46
+ char: 'o',
47
+ default: 'summary',
48
+ description: 'Output format',
49
+ options: ['summary', 'json'],
50
+ required: false,
51
+ }),
52
+ source: Flags.string({
53
+ char: 's',
54
+ default: 'v1',
55
+ description: 'Source branch to clone from (defaults to "v1")',
56
+ required: false,
57
+ }),
58
+ workspace: Flags.integer({
59
+ char: 'w',
60
+ description: 'Workspace ID (uses profile workspace if not provided)',
61
+ required: false,
62
+ }),
63
+ };
64
+ async run() {
65
+ const { flags } = await this.parse(BranchCreate);
66
+ // Get profile name (default or from flag/env)
67
+ const profileName = flags.profile || this.getDefaultProfile();
68
+ // Load credentials
69
+ const credentials = this.loadCredentials();
70
+ // Get the profile configuration
71
+ if (!(profileName in credentials.profiles)) {
72
+ this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}\n` +
73
+ `Create a profile using 'xano profile create'`);
74
+ }
75
+ const profile = credentials.profiles[profileName];
76
+ // Validate required fields
77
+ if (!profile.instance_origin) {
78
+ this.error(`Profile '${profileName}' is missing instance_origin`);
79
+ }
80
+ if (!profile.access_token) {
81
+ this.error(`Profile '${profileName}' is missing access_token`);
82
+ }
83
+ // Get workspace ID from flag or profile
84
+ const workspaceId = flags.workspace || profile.workspace;
85
+ if (!workspaceId) {
86
+ this.error('No workspace ID provided. Either use --workspace flag or set one in your profile.\n' +
87
+ 'Usage: xano branch create --label <label> [--workspace <workspace_id>]');
88
+ }
89
+ // Build request body
90
+ const body = {
91
+ label: flags.label,
92
+ source_branch: flags.source,
93
+ };
94
+ if (flags.description) {
95
+ body.description = flags.description;
96
+ }
97
+ if (flags.color) {
98
+ body.color = flags.color;
99
+ }
100
+ // Construct the API URL
101
+ const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/branch`;
102
+ // Create branch via the API
103
+ try {
104
+ const response = await fetch(apiUrl, {
105
+ body: JSON.stringify(body),
106
+ headers: {
107
+ 'accept': 'application/json',
108
+ 'Authorization': `Bearer ${profile.access_token}`,
109
+ 'content-type': 'application/json',
110
+ },
111
+ method: 'POST',
112
+ });
113
+ if (!response.ok) {
114
+ const errorText = await response.text();
115
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
116
+ }
117
+ const branch = await response.json();
118
+ // Output results
119
+ if (flags.output === 'json') {
120
+ this.log(JSON.stringify(branch, null, 2));
121
+ }
122
+ else {
123
+ // summary format
124
+ this.log(`Created branch: ${branch.label}`);
125
+ this.log(` Cloned from: ${flags.source}`);
126
+ if (flags.description) {
127
+ this.log(` Description: ${flags.description}`);
128
+ }
129
+ if (flags.color) {
130
+ this.log(` Color: ${flags.color}`);
131
+ }
132
+ }
133
+ }
134
+ catch (error) {
135
+ if (error instanceof Error) {
136
+ this.error(`Failed to create branch: ${error.message}`);
137
+ }
138
+ else {
139
+ this.error(`Failed to create branch: ${String(error)}`);
140
+ }
141
+ }
142
+ }
143
+ loadCredentials() {
144
+ const configDir = path.join(os.homedir(), '.xano');
145
+ const credentialsPath = path.join(configDir, 'credentials.yaml');
146
+ // Check if credentials file exists
147
+ if (!fs.existsSync(credentialsPath)) {
148
+ this.error(`Credentials file not found at ${credentialsPath}\n` +
149
+ `Create a profile using 'xano profile create'`);
150
+ }
151
+ // Read credentials file
152
+ try {
153
+ const fileContent = fs.readFileSync(credentialsPath, 'utf8');
154
+ const parsed = yaml.load(fileContent);
155
+ if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
156
+ this.error('Credentials file has invalid format.');
157
+ }
158
+ return parsed;
159
+ }
160
+ catch (error) {
161
+ this.error(`Failed to parse credentials file: ${error}`);
162
+ }
163
+ }
164
+ }
@@ -0,0 +1,18 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class BranchDelete extends BaseCommand {
3
+ static args: {
4
+ branch_label: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
+ workspace: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ };
15
+ run(): Promise<void>;
16
+ private confirm;
17
+ private loadCredentials;
18
+ }
@@ -0,0 +1,156 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import * as yaml from 'js-yaml';
3
+ import * as fs from 'node:fs';
4
+ import * as os from 'node:os';
5
+ import * as path from 'node:path';
6
+ import BaseCommand from '../../../base-command.js';
7
+ export default class BranchDelete extends BaseCommand {
8
+ static args = {
9
+ branch_label: Args.string({
10
+ description: 'Branch label to delete (cannot delete "v1" or the live branch)',
11
+ required: true,
12
+ }),
13
+ };
14
+ static description = 'Delete a branch (cannot delete "v1" or the live branch)';
15
+ static examples = [
16
+ `$ xano branch delete feature-old
17
+ Are you sure you want to delete branch 'feature-old'? This action cannot be undone. (y/N) y
18
+ Deleted branch: feature-old
19
+ `,
20
+ `$ xano branch delete dev --force
21
+ Deleted branch: dev
22
+ `,
23
+ `$ xano branch delete staging -f -o json
24
+ {
25
+ "deleted": true,
26
+ "branch_label": "staging"
27
+ }
28
+ `,
29
+ ];
30
+ static flags = {
31
+ ...BaseCommand.baseFlags,
32
+ force: Flags.boolean({
33
+ char: 'f',
34
+ default: false,
35
+ description: 'Skip confirmation prompt',
36
+ required: false,
37
+ }),
38
+ output: Flags.string({
39
+ char: 'o',
40
+ default: 'summary',
41
+ description: 'Output format',
42
+ options: ['summary', 'json'],
43
+ required: false,
44
+ }),
45
+ workspace: Flags.integer({
46
+ char: 'w',
47
+ description: 'Workspace ID (uses profile workspace if not provided)',
48
+ required: false,
49
+ }),
50
+ };
51
+ async run() {
52
+ const { args, flags } = await this.parse(BranchDelete);
53
+ // Get profile name (default or from flag/env)
54
+ const profileName = flags.profile || this.getDefaultProfile();
55
+ // Load credentials
56
+ const credentials = this.loadCredentials();
57
+ // Get the profile configuration
58
+ if (!(profileName in credentials.profiles)) {
59
+ this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}\n` +
60
+ `Create a profile using 'xano profile create'`);
61
+ }
62
+ const profile = credentials.profiles[profileName];
63
+ // Validate required fields
64
+ if (!profile.instance_origin) {
65
+ this.error(`Profile '${profileName}' is missing instance_origin`);
66
+ }
67
+ if (!profile.access_token) {
68
+ this.error(`Profile '${profileName}' is missing access_token`);
69
+ }
70
+ // Get workspace ID from flag or profile
71
+ const workspaceId = flags.workspace || profile.workspace;
72
+ if (!workspaceId) {
73
+ this.error('No workspace ID provided. Either use --workspace flag or set one in your profile.\n' +
74
+ 'Usage: xano branch delete <branch_label> [--workspace <workspace_id>]');
75
+ }
76
+ const branchLabel = args.branch_label;
77
+ // Warn about protected branches
78
+ if (branchLabel === 'v1') {
79
+ this.error('Cannot delete the "v1" branch. This is the default branch and cannot be removed.');
80
+ }
81
+ // Confirmation prompt unless --force is used
82
+ if (!flags.force) {
83
+ const confirmed = await this.confirm(`Are you sure you want to delete branch '${branchLabel}'? This action cannot be undone.`);
84
+ if (!confirmed) {
85
+ this.log('Deletion cancelled.');
86
+ return;
87
+ }
88
+ }
89
+ // Construct the API URL
90
+ const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/branch/${encodeURIComponent(branchLabel)}`;
91
+ // Delete branch via the API
92
+ try {
93
+ const response = await fetch(apiUrl, {
94
+ headers: {
95
+ 'accept': 'application/json',
96
+ 'Authorization': `Bearer ${profile.access_token}`,
97
+ },
98
+ method: 'DELETE',
99
+ });
100
+ if (!response.ok) {
101
+ const errorText = await response.text();
102
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
103
+ }
104
+ // Output results
105
+ if (flags.output === 'json') {
106
+ this.log(JSON.stringify({ branch_label: branchLabel, deleted: true }, null, 2));
107
+ }
108
+ else {
109
+ this.log(`Deleted branch: ${branchLabel}`);
110
+ }
111
+ }
112
+ catch (error) {
113
+ if (error instanceof Error) {
114
+ this.error(`Failed to delete branch: ${error.message}`);
115
+ }
116
+ else {
117
+ this.error(`Failed to delete branch: ${String(error)}`);
118
+ }
119
+ }
120
+ }
121
+ async confirm(message) {
122
+ // Use readline for simple yes/no confirmation
123
+ const readline = await import('node:readline');
124
+ const rl = readline.createInterface({
125
+ input: process.stdin,
126
+ output: process.stdout,
127
+ });
128
+ return new Promise((resolve) => {
129
+ rl.question(`${message} (y/N) `, (answer) => {
130
+ rl.close();
131
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
132
+ });
133
+ });
134
+ }
135
+ loadCredentials() {
136
+ const configDir = path.join(os.homedir(), '.xano');
137
+ const credentialsPath = path.join(configDir, 'credentials.yaml');
138
+ // Check if credentials file exists
139
+ if (!fs.existsSync(credentialsPath)) {
140
+ this.error(`Credentials file not found at ${credentialsPath}\n` +
141
+ `Create a profile using 'xano profile create'`);
142
+ }
143
+ // Read credentials file
144
+ try {
145
+ const fileContent = fs.readFileSync(credentialsPath, 'utf8');
146
+ const parsed = yaml.load(fileContent);
147
+ if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
148
+ this.error('Credentials file has invalid format.');
149
+ }
150
+ return parsed;
151
+ }
152
+ catch (error) {
153
+ this.error(`Failed to parse credentials file: ${error}`);
154
+ }
155
+ }
156
+ }
@@ -0,0 +1,19 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class BranchEdit extends BaseCommand {
3
+ static args: {
4
+ branch_label: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ color: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ label: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ workspace: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ run(): Promise<void>;
18
+ private loadCredentials;
19
+ }
@@ -0,0 +1,166 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import * as yaml from 'js-yaml';
3
+ import * as fs from 'node:fs';
4
+ import * as os from 'node:os';
5
+ import * as path from 'node:path';
6
+ import BaseCommand from '../../../base-command.js';
7
+ export default class BranchEdit extends BaseCommand {
8
+ static args = {
9
+ branch_label: Args.string({
10
+ description: 'Branch label to edit (cannot edit "v1" label)',
11
+ required: true,
12
+ }),
13
+ };
14
+ static description = 'Update an existing branch (cannot update "v1" label)';
15
+ static examples = [
16
+ `$ xano branch edit dev --label development
17
+ Updated branch: development
18
+ `,
19
+ `$ xano branch edit feature-auth -l feature-authentication --color "#ff5733"
20
+ Updated branch: feature-authentication
21
+ Color: #ff5733
22
+ `,
23
+ `$ xano branch edit staging --description "Staging environment" -o json
24
+ {
25
+ "created_at": "2024-02-10T09:15:00Z",
26
+ "label": "staging",
27
+ "backup": false
28
+ }
29
+ `,
30
+ ];
31
+ static flags = {
32
+ ...BaseCommand.baseFlags,
33
+ color: Flags.string({
34
+ char: 'c',
35
+ description: 'New color hex code for the branch (e.g., "#ff5733")',
36
+ required: false,
37
+ }),
38
+ description: Flags.string({
39
+ char: 'd',
40
+ description: 'New description for the branch',
41
+ required: false,
42
+ }),
43
+ label: Flags.string({
44
+ char: 'l',
45
+ description: 'New label for the branch',
46
+ required: false,
47
+ }),
48
+ output: Flags.string({
49
+ char: 'o',
50
+ default: 'summary',
51
+ description: 'Output format',
52
+ options: ['summary', 'json'],
53
+ required: false,
54
+ }),
55
+ workspace: Flags.integer({
56
+ char: 'w',
57
+ description: 'Workspace ID (uses profile workspace if not provided)',
58
+ required: false,
59
+ }),
60
+ };
61
+ async run() {
62
+ const { args, flags } = await this.parse(BranchEdit);
63
+ // Get profile name (default or from flag/env)
64
+ const profileName = flags.profile || this.getDefaultProfile();
65
+ // Load credentials
66
+ const credentials = this.loadCredentials();
67
+ // Get the profile configuration
68
+ if (!(profileName in credentials.profiles)) {
69
+ this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}\n` +
70
+ `Create a profile using 'xano profile create'`);
71
+ }
72
+ const profile = credentials.profiles[profileName];
73
+ // Validate required fields
74
+ if (!profile.instance_origin) {
75
+ this.error(`Profile '${profileName}' is missing instance_origin`);
76
+ }
77
+ if (!profile.access_token) {
78
+ this.error(`Profile '${profileName}' is missing access_token`);
79
+ }
80
+ // Get workspace ID from flag or profile
81
+ const workspaceId = flags.workspace || profile.workspace;
82
+ if (!workspaceId) {
83
+ this.error('No workspace ID provided. Either use --workspace flag or set one in your profile.\n' +
84
+ 'Usage: xano branch edit <branch_label> [--workspace <workspace_id>]');
85
+ }
86
+ const branchLabel = args.branch_label;
87
+ // Build request body - only include fields that were specified
88
+ const body = {};
89
+ if (flags.label !== undefined) {
90
+ body.label = flags.label;
91
+ }
92
+ if (flags.description !== undefined) {
93
+ body.description = flags.description;
94
+ }
95
+ if (flags.color !== undefined) {
96
+ body.color = flags.color;
97
+ }
98
+ // Check if at least one field is being updated
99
+ if (Object.keys(body).length === 0) {
100
+ this.error('No fields specified to update. Use --label, --description, or --color flags.\n' +
101
+ 'Example: xano branch edit dev --label development');
102
+ }
103
+ // Construct the API URL
104
+ const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/branch/${encodeURIComponent(branchLabel)}`;
105
+ // Update branch via the API
106
+ try {
107
+ const response = await fetch(apiUrl, {
108
+ body: JSON.stringify(body),
109
+ headers: {
110
+ 'accept': 'application/json',
111
+ 'Authorization': `Bearer ${profile.access_token}`,
112
+ 'content-type': 'application/json',
113
+ },
114
+ method: 'PUT',
115
+ });
116
+ if (!response.ok) {
117
+ const errorText = await response.text();
118
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
119
+ }
120
+ const branch = await response.json();
121
+ // Output results
122
+ if (flags.output === 'json') {
123
+ this.log(JSON.stringify(branch, null, 2));
124
+ }
125
+ else {
126
+ // summary format
127
+ this.log(`Updated branch: ${branch.label}`);
128
+ if (flags.description) {
129
+ this.log(` Description: ${flags.description}`);
130
+ }
131
+ if (flags.color) {
132
+ this.log(` Color: ${flags.color}`);
133
+ }
134
+ }
135
+ }
136
+ catch (error) {
137
+ if (error instanceof Error) {
138
+ this.error(`Failed to update branch: ${error.message}`);
139
+ }
140
+ else {
141
+ this.error(`Failed to update branch: ${String(error)}`);
142
+ }
143
+ }
144
+ }
145
+ loadCredentials() {
146
+ const configDir = path.join(os.homedir(), '.xano');
147
+ const credentialsPath = path.join(configDir, 'credentials.yaml');
148
+ // Check if credentials file exists
149
+ if (!fs.existsSync(credentialsPath)) {
150
+ this.error(`Credentials file not found at ${credentialsPath}\n` +
151
+ `Create a profile using 'xano profile create'`);
152
+ }
153
+ // Read credentials file
154
+ try {
155
+ const fileContent = fs.readFileSync(credentialsPath, 'utf8');
156
+ const parsed = yaml.load(fileContent);
157
+ if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
158
+ this.error('Credentials file has invalid format.');
159
+ }
160
+ return parsed;
161
+ }
162
+ catch (error) {
163
+ this.error(`Failed to parse credentials file: ${error}`);
164
+ }
165
+ }
166
+ }
@@ -0,0 +1,16 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class BranchGet extends BaseCommand {
3
+ static args: {
4
+ branch_label: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
+ workspace: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ };
14
+ run(): Promise<void>;
15
+ private loadCredentials;
16
+ }