@xano/cli 0.0.2

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 (49) hide show
  1. package/README.md +1200 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +5 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +5 -0
  6. package/dist/base-command.d.ts +11 -0
  7. package/dist/base-command.js +40 -0
  8. package/dist/commands/ephemeral/run/job/index.d.ts +19 -0
  9. package/dist/commands/ephemeral/run/job/index.js +318 -0
  10. package/dist/commands/ephemeral/run/service/index.d.ts +18 -0
  11. package/dist/commands/ephemeral/run/service/index.js +286 -0
  12. package/dist/commands/function/create/index.d.ts +18 -0
  13. package/dist/commands/function/create/index.js +280 -0
  14. package/dist/commands/function/edit/index.d.ts +24 -0
  15. package/dist/commands/function/edit/index.js +482 -0
  16. package/dist/commands/function/get/index.d.ts +18 -0
  17. package/dist/commands/function/get/index.js +279 -0
  18. package/dist/commands/function/list/index.d.ts +19 -0
  19. package/dist/commands/function/list/index.js +208 -0
  20. package/dist/commands/profile/create/index.d.ts +17 -0
  21. package/dist/commands/profile/create/index.js +123 -0
  22. package/dist/commands/profile/delete/index.d.ts +14 -0
  23. package/dist/commands/profile/delete/index.js +124 -0
  24. package/dist/commands/profile/edit/index.d.ts +18 -0
  25. package/dist/commands/profile/edit/index.js +129 -0
  26. package/dist/commands/profile/get-default/index.d.ts +6 -0
  27. package/dist/commands/profile/get-default/index.js +44 -0
  28. package/dist/commands/profile/list/index.d.ts +10 -0
  29. package/dist/commands/profile/list/index.js +115 -0
  30. package/dist/commands/profile/set-default/index.d.ts +9 -0
  31. package/dist/commands/profile/set-default/index.js +63 -0
  32. package/dist/commands/profile/wizard/index.d.ts +15 -0
  33. package/dist/commands/profile/wizard/index.js +350 -0
  34. package/dist/commands/static_host/build/create/index.d.ts +18 -0
  35. package/dist/commands/static_host/build/create/index.js +194 -0
  36. package/dist/commands/static_host/build/get/index.d.ts +16 -0
  37. package/dist/commands/static_host/build/get/index.js +165 -0
  38. package/dist/commands/static_host/build/list/index.d.ts +17 -0
  39. package/dist/commands/static_host/build/list/index.js +192 -0
  40. package/dist/commands/static_host/list/index.d.ts +15 -0
  41. package/dist/commands/static_host/list/index.js +187 -0
  42. package/dist/commands/workspace/list/index.d.ts +11 -0
  43. package/dist/commands/workspace/list/index.js +154 -0
  44. package/dist/help.d.ts +20 -0
  45. package/dist/help.js +26 -0
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.js +1 -0
  48. package/oclif.manifest.json +1370 -0
  49. package/package.json +79 -0
@@ -0,0 +1,165 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import * as fs from 'node:fs';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import * as yaml from 'js-yaml';
6
+ import BaseCommand from '../../../../base-command.js';
7
+ export default class StaticHostBuildGet extends BaseCommand {
8
+ static args = {
9
+ static_host: Args.string({
10
+ description: 'Static Host name',
11
+ required: true,
12
+ }),
13
+ build_id: Args.string({
14
+ description: 'Build ID',
15
+ required: true,
16
+ }),
17
+ };
18
+ static flags = {
19
+ ...BaseCommand.baseFlags,
20
+ workspace: Flags.string({
21
+ char: 'w',
22
+ description: 'Workspace ID (optional if set in profile)',
23
+ required: false,
24
+ }),
25
+ output: Flags.string({
26
+ char: 'o',
27
+ description: 'Output format',
28
+ required: false,
29
+ default: 'summary',
30
+ options: ['summary', 'json'],
31
+ }),
32
+ };
33
+ static description = 'Get details of a specific build for a static host';
34
+ static examples = [
35
+ `$ xano static_host:build:get default 52
36
+ Build Details:
37
+ ID: 52
38
+ Name: v1.0.0
39
+ Status: completed
40
+ `,
41
+ `$ xano static_host:build:get default 52 -w 40
42
+ Build Details:
43
+ ID: 52
44
+ Name: v1.0.0
45
+ Status: completed
46
+ `,
47
+ `$ xano static_host:build:get myhost 123 --profile production
48
+ Build Details:
49
+ ID: 123
50
+ Name: production-build
51
+ `,
52
+ `$ xano static_host:build:get default 52 -o json
53
+ {
54
+ "id": 52,
55
+ "name": "v1.0.0",
56
+ "status": "completed"
57
+ }
58
+ `,
59
+ ];
60
+ async run() {
61
+ const { args, flags } = await this.parse(StaticHostBuildGet);
62
+ // Get profile name (default or from flag/env)
63
+ const profileName = flags.profile || this.getDefaultProfile();
64
+ // Load credentials
65
+ const credentials = this.loadCredentials();
66
+ // Get the profile configuration
67
+ if (!(profileName in credentials.profiles)) {
68
+ this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}\n` +
69
+ `Create a profile using 'xano profile:create'`);
70
+ }
71
+ const profile = credentials.profiles[profileName];
72
+ // Validate required fields
73
+ if (!profile.instance_origin) {
74
+ this.error(`Profile '${profileName}' is missing instance_origin`);
75
+ }
76
+ if (!profile.access_token) {
77
+ this.error(`Profile '${profileName}' is missing access_token`);
78
+ }
79
+ // Determine workspace_id from flag or profile
80
+ let workspaceId;
81
+ if (flags.workspace) {
82
+ workspaceId = flags.workspace;
83
+ }
84
+ else if (profile.workspace) {
85
+ workspaceId = profile.workspace;
86
+ }
87
+ else {
88
+ this.error(`Workspace ID is required. Either:\n` +
89
+ ` 1. Provide it as a flag: xano static_host:build:get <static_host> <build_id> -w <workspace_id>\n` +
90
+ ` 2. Set it in your profile using: xano profile:edit ${profileName} -w <workspace_id>`);
91
+ }
92
+ // Construct the API URL
93
+ const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/static_host/${args.static_host}/build/${args.build_id}`;
94
+ // Fetch build from the API
95
+ try {
96
+ const response = await fetch(apiUrl, {
97
+ method: 'GET',
98
+ headers: {
99
+ 'accept': 'application/json',
100
+ 'Authorization': `Bearer ${profile.access_token}`,
101
+ },
102
+ });
103
+ if (!response.ok) {
104
+ const errorText = await response.text();
105
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
106
+ }
107
+ const build = await response.json();
108
+ // Validate response
109
+ if (!build || typeof build !== 'object') {
110
+ this.error('Unexpected API response format');
111
+ }
112
+ // Output results
113
+ if (flags.output === 'json') {
114
+ this.log(JSON.stringify(build, null, 2));
115
+ }
116
+ else {
117
+ // summary format
118
+ this.log('Build Details:');
119
+ this.log(`ID: ${build.id}`);
120
+ this.log(`Name: ${build.name}`);
121
+ if (build.description) {
122
+ this.log(`Description: ${build.description}`);
123
+ }
124
+ if (build.status) {
125
+ this.log(`Status: ${build.status}`);
126
+ }
127
+ if (build.created_at) {
128
+ this.log(`Created: ${build.created_at}`);
129
+ }
130
+ if (build.updated_at) {
131
+ this.log(`Updated: ${build.updated_at}`);
132
+ }
133
+ }
134
+ }
135
+ catch (error) {
136
+ if (error instanceof Error) {
137
+ this.error(`Failed to fetch build: ${error.message}`);
138
+ }
139
+ else {
140
+ this.error(`Failed to fetch build: ${String(error)}`);
141
+ }
142
+ }
143
+ }
144
+ loadCredentials() {
145
+ const configDir = path.join(os.homedir(), '.xano');
146
+ const credentialsPath = path.join(configDir, 'credentials.yaml');
147
+ // Check if credentials file exists
148
+ if (!fs.existsSync(credentialsPath)) {
149
+ this.error(`Credentials file not found at ${credentialsPath}\n` +
150
+ `Create a profile using 'xano profile:create'`);
151
+ }
152
+ // Read credentials file
153
+ try {
154
+ const fileContent = fs.readFileSync(credentialsPath, 'utf8');
155
+ const parsed = yaml.load(fileContent);
156
+ if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
157
+ this.error('Credentials file has invalid format.');
158
+ }
159
+ return parsed;
160
+ }
161
+ catch (error) {
162
+ this.error(`Failed to parse credentials file: ${error}`);
163
+ }
164
+ }
165
+ }
@@ -0,0 +1,17 @@
1
+ import BaseCommand from '../../../../base-command.js';
2
+ export default class StaticHostBuildList extends BaseCommand {
3
+ static args: {
4
+ static_host: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static flags: {
7
+ workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
9
+ page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
10
+ per_page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
11
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ };
13
+ static description: string;
14
+ static examples: string[];
15
+ run(): Promise<void>;
16
+ private loadCredentials;
17
+ }
@@ -0,0 +1,192 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import * as fs from 'node:fs';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import * as yaml from 'js-yaml';
6
+ import BaseCommand from '../../../../base-command.js';
7
+ export default class StaticHostBuildList extends BaseCommand {
8
+ static args = {
9
+ static_host: Args.string({
10
+ description: 'Static Host name',
11
+ required: true,
12
+ }),
13
+ };
14
+ static flags = {
15
+ ...BaseCommand.baseFlags,
16
+ workspace: Flags.string({
17
+ char: 'w',
18
+ description: 'Workspace ID (optional if set in profile)',
19
+ required: false,
20
+ }),
21
+ output: Flags.string({
22
+ char: 'o',
23
+ description: 'Output format',
24
+ required: false,
25
+ default: 'summary',
26
+ options: ['summary', 'json'],
27
+ }),
28
+ page: Flags.integer({
29
+ description: 'Page number for pagination',
30
+ required: false,
31
+ default: 1,
32
+ }),
33
+ per_page: Flags.integer({
34
+ description: 'Number of results per page',
35
+ required: false,
36
+ default: 50,
37
+ }),
38
+ };
39
+ static description = 'List all builds for a static host';
40
+ static examples = [
41
+ `$ xano static_host:build:list default -w 40
42
+ Available builds:
43
+ - v1.0.0 (ID: 1) - Status: completed
44
+ - v1.0.1 (ID: 2) - Status: pending
45
+ `,
46
+ `$ xano static_host:build:list myhost --profile production
47
+ Available builds:
48
+ - production (ID: 1) - Status: completed
49
+ - staging (ID: 2) - Status: completed
50
+ `,
51
+ `$ xano static_host:build:list default -w 40 --output json
52
+ [
53
+ {
54
+ "id": 1,
55
+ "name": "v1.0.0",
56
+ "status": "completed"
57
+ }
58
+ ]
59
+ `,
60
+ `$ xano static_host:build:list default -p staging -o json --page 2
61
+ [
62
+ {
63
+ "id": 3,
64
+ "name": "v1.0.2"
65
+ }
66
+ ]
67
+ `,
68
+ ];
69
+ async run() {
70
+ const { args, flags } = await this.parse(StaticHostBuildList);
71
+ // Get profile name (default or from flag/env)
72
+ const profileName = flags.profile || this.getDefaultProfile();
73
+ // Load credentials
74
+ const credentials = this.loadCredentials();
75
+ // Get the profile configuration
76
+ if (!(profileName in credentials.profiles)) {
77
+ this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}\n` +
78
+ `Create a profile using 'xano profile:create'`);
79
+ }
80
+ const profile = credentials.profiles[profileName];
81
+ // Validate required fields
82
+ if (!profile.instance_origin) {
83
+ this.error(`Profile '${profileName}' is missing instance_origin`);
84
+ }
85
+ if (!profile.access_token) {
86
+ this.error(`Profile '${profileName}' is missing access_token`);
87
+ }
88
+ // Determine workspace_id from flag or profile
89
+ let workspaceId;
90
+ if (flags.workspace) {
91
+ workspaceId = flags.workspace;
92
+ }
93
+ else if (profile.workspace) {
94
+ workspaceId = profile.workspace;
95
+ }
96
+ else {
97
+ this.error(`Workspace ID is required. Either:\n` +
98
+ ` 1. Provide it as a flag: xano static_host:build:list <static_host> -w <workspace_id>\n` +
99
+ ` 2. Set it in your profile using: xano profile:edit ${profileName} -w <workspace_id>`);
100
+ }
101
+ // Build query parameters
102
+ const queryParams = new URLSearchParams({
103
+ page: flags.page.toString(),
104
+ });
105
+ // Only add per_page if it's not the default value
106
+ if (flags.per_page !== 50) {
107
+ queryParams.append('per_page', flags.per_page.toString());
108
+ }
109
+ // Construct the API URL
110
+ const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/static_host/${args.static_host}/build?${queryParams.toString()}`;
111
+ // Fetch builds from the API
112
+ try {
113
+ const response = await fetch(apiUrl, {
114
+ method: 'GET',
115
+ headers: {
116
+ 'accept': 'application/json',
117
+ 'Authorization': `Bearer ${profile.access_token}`,
118
+ },
119
+ });
120
+ if (!response.ok) {
121
+ const errorText = await response.text();
122
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
123
+ }
124
+ const data = await response.json();
125
+ // Handle different response formats
126
+ let builds;
127
+ if (Array.isArray(data)) {
128
+ builds = data;
129
+ }
130
+ else if (data && typeof data === 'object' && 'builds' in data && Array.isArray(data.builds)) {
131
+ builds = data.builds;
132
+ }
133
+ else if (data && typeof data === 'object' && 'items' in data && Array.isArray(data.items)) {
134
+ builds = data.items;
135
+ }
136
+ else {
137
+ this.error('Unexpected API response format');
138
+ }
139
+ // Output results
140
+ if (flags.output === 'json') {
141
+ this.log(JSON.stringify(builds, null, 2));
142
+ }
143
+ else {
144
+ // summary format
145
+ if (builds.length === 0) {
146
+ this.log('No builds found');
147
+ }
148
+ else {
149
+ this.log('Available builds:');
150
+ for (const build of builds) {
151
+ if (build.id !== undefined) {
152
+ const statusInfo = build.status ? ` - Status: ${build.status}` : '';
153
+ this.log(` - ${build.name} (ID: ${build.id})${statusInfo}`);
154
+ }
155
+ else {
156
+ this.log(` - ${build.name}`);
157
+ }
158
+ }
159
+ }
160
+ }
161
+ }
162
+ catch (error) {
163
+ if (error instanceof Error) {
164
+ this.error(`Failed to fetch builds: ${error.message}`);
165
+ }
166
+ else {
167
+ this.error(`Failed to fetch builds: ${String(error)}`);
168
+ }
169
+ }
170
+ }
171
+ loadCredentials() {
172
+ const configDir = path.join(os.homedir(), '.xano');
173
+ const credentialsPath = path.join(configDir, 'credentials.yaml');
174
+ // Check if credentials file exists
175
+ if (!fs.existsSync(credentialsPath)) {
176
+ this.error(`Credentials file not found at ${credentialsPath}\n` +
177
+ `Create a profile using 'xano profile:create'`);
178
+ }
179
+ // Read credentials file
180
+ try {
181
+ const fileContent = fs.readFileSync(credentialsPath, 'utf8');
182
+ const parsed = yaml.load(fileContent);
183
+ if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
184
+ this.error('Credentials file has invalid format.');
185
+ }
186
+ return parsed;
187
+ }
188
+ catch (error) {
189
+ this.error(`Failed to parse credentials file: ${error}`);
190
+ }
191
+ }
192
+ }
@@ -0,0 +1,15 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class StaticHostList extends BaseCommand {
3
+ static args: {};
4
+ static flags: {
5
+ workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
6
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
7
+ page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
8
+ per_page: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
9
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ static description: string;
12
+ static examples: string[];
13
+ run(): Promise<void>;
14
+ private loadCredentials;
15
+ }
@@ -0,0 +1,187 @@
1
+ import { Flags } from '@oclif/core';
2
+ import * as fs from 'node:fs';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import * as yaml from 'js-yaml';
6
+ import BaseCommand from '../../../base-command.js';
7
+ export default class StaticHostList extends BaseCommand {
8
+ static args = {};
9
+ static flags = {
10
+ ...BaseCommand.baseFlags,
11
+ workspace: Flags.string({
12
+ char: 'w',
13
+ description: 'Workspace ID (optional if set in profile)',
14
+ required: false,
15
+ }),
16
+ output: Flags.string({
17
+ char: 'o',
18
+ description: 'Output format',
19
+ required: false,
20
+ default: 'summary',
21
+ options: ['summary', 'json'],
22
+ }),
23
+ page: Flags.integer({
24
+ description: 'Page number for pagination',
25
+ required: false,
26
+ default: 1,
27
+ }),
28
+ per_page: Flags.integer({
29
+ description: 'Number of results per page',
30
+ required: false,
31
+ default: 50,
32
+ }),
33
+ };
34
+ static description = 'List all static hosts in a workspace from the Xano Metadata API';
35
+ static examples = [
36
+ `$ xano static_host:list -w 40
37
+ Available static hosts:
38
+ - my-static-host (ID: 1)
39
+ - another-host (ID: 2)
40
+ `,
41
+ `$ xano static_host:list --profile production
42
+ Available static hosts:
43
+ - my-static-host (ID: 1)
44
+ - another-host (ID: 2)
45
+ `,
46
+ `$ xano static_host:list -w 40 --output json
47
+ [
48
+ {
49
+ "id": 1,
50
+ "name": "my-static-host",
51
+ "domain": "example.com"
52
+ }
53
+ ]
54
+ `,
55
+ `$ xano static_host:list -p staging -o json --page 2
56
+ [
57
+ {
58
+ "id": 3,
59
+ "name": "static-host-3"
60
+ }
61
+ ]
62
+ `,
63
+ ];
64
+ async run() {
65
+ const { flags } = await this.parse(StaticHostList);
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
+ // Determine workspace_id from flag or profile
84
+ let workspaceId;
85
+ if (flags.workspace) {
86
+ workspaceId = flags.workspace;
87
+ }
88
+ else if (profile.workspace) {
89
+ workspaceId = profile.workspace;
90
+ }
91
+ else {
92
+ this.error(`Workspace ID is required. Either:\n` +
93
+ ` 1. Provide it as a flag: xano static_host:list -w <workspace_id>\n` +
94
+ ` 2. Set it in your profile using: xano profile:edit ${profileName} -w <workspace_id>`);
95
+ }
96
+ // Build query parameters
97
+ const queryParams = new URLSearchParams({
98
+ page: flags.page.toString(),
99
+ });
100
+ // Only add per_page if it's not the default value
101
+ if (flags.per_page !== 50) {
102
+ queryParams.append('per_page', flags.per_page.toString());
103
+ }
104
+ // Construct the API URL
105
+ const apiUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/static_host?${queryParams.toString()}`;
106
+ // Fetch static hosts from the API
107
+ try {
108
+ const response = await fetch(apiUrl, {
109
+ method: 'GET',
110
+ headers: {
111
+ 'accept': 'application/json',
112
+ 'Authorization': `Bearer ${profile.access_token}`,
113
+ },
114
+ });
115
+ if (!response.ok) {
116
+ const errorText = await response.text();
117
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
118
+ }
119
+ const data = await response.json();
120
+ // Handle different response formats
121
+ let staticHosts;
122
+ if (Array.isArray(data)) {
123
+ staticHosts = data;
124
+ }
125
+ else if (data && typeof data === 'object' && 'static_hosts' in data && Array.isArray(data.static_hosts)) {
126
+ staticHosts = data.static_hosts;
127
+ }
128
+ else if (data && typeof data === 'object' && 'items' in data && Array.isArray(data.items)) {
129
+ staticHosts = data.items;
130
+ }
131
+ else {
132
+ this.error('Unexpected API response format');
133
+ }
134
+ // Output results
135
+ if (flags.output === 'json') {
136
+ this.log(JSON.stringify(staticHosts, null, 2));
137
+ }
138
+ else {
139
+ // summary format
140
+ if (staticHosts.length === 0) {
141
+ this.log('No static hosts found');
142
+ }
143
+ else {
144
+ this.log('Available static hosts:');
145
+ for (const host of staticHosts) {
146
+ if (host.id !== undefined) {
147
+ const domainInfo = host.domain ? ` - ${host.domain}` : '';
148
+ this.log(` - ${host.name} (ID: ${host.id})${domainInfo}`);
149
+ }
150
+ else {
151
+ this.log(` - ${host.name}`);
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+ catch (error) {
158
+ if (error instanceof Error) {
159
+ this.error(`Failed to fetch static hosts: ${error.message}`);
160
+ }
161
+ else {
162
+ this.error(`Failed to fetch static hosts: ${String(error)}`);
163
+ }
164
+ }
165
+ }
166
+ loadCredentials() {
167
+ const configDir = path.join(os.homedir(), '.xano');
168
+ const credentialsPath = path.join(configDir, 'credentials.yaml');
169
+ // Check if credentials file exists
170
+ if (!fs.existsSync(credentialsPath)) {
171
+ this.error(`Credentials file not found at ${credentialsPath}\n` +
172
+ `Create a profile using 'xano profile:create'`);
173
+ }
174
+ // Read credentials file
175
+ try {
176
+ const fileContent = fs.readFileSync(credentialsPath, 'utf8');
177
+ const parsed = yaml.load(fileContent);
178
+ if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
179
+ this.error('Credentials file has invalid format.');
180
+ }
181
+ return parsed;
182
+ }
183
+ catch (error) {
184
+ this.error(`Failed to parse credentials file: ${error}`);
185
+ }
186
+ }
187
+ }
@@ -0,0 +1,11 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class WorkspaceList extends BaseCommand {
3
+ static flags: {
4
+ output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
5
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ run(): Promise<void>;
10
+ private loadCredentials;
11
+ }