@xano/cli 0.0.11 → 0.0.12

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.
@@ -2,7 +2,6 @@ import BaseCommand from '../../../../base-command.js';
2
2
  export default class EphemeralRunJob extends BaseCommand {
3
3
  static args: {};
4
4
  static flags: {
5
- workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
6
5
  file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
6
  stdin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
7
  edit: import("@oclif/core/interfaces").BooleanFlag<boolean>;
@@ -9,11 +9,6 @@ export default class EphemeralRunJob extends BaseCommand {
9
9
  static args = {};
10
10
  static flags = {
11
11
  ...BaseCommand.baseFlags,
12
- workspace: Flags.string({
13
- char: 'w',
14
- description: 'Workspace ID (optional if set in profile)',
15
- required: false,
16
- }),
17
12
  file: Flags.string({
18
13
  char: 'f',
19
14
  description: 'Path or URL to file containing XanoScript code',
@@ -47,32 +42,28 @@ export default class EphemeralRunJob extends BaseCommand {
47
42
  required: false,
48
43
  }),
49
44
  };
50
- static description = 'Run an ephemeral job in a workspace';
45
+ static description = 'Run an ephemeral job';
51
46
  static examples = [
52
- `$ xano ephemeral:run:job -w 1 -f script.xs
53
- Job executed successfully!
54
- ...
55
- `,
56
47
  `$ xano ephemeral:run:job -f script.xs
57
48
  Job executed successfully!
58
49
  ...
59
50
  `,
60
- `$ xano ephemeral:run:job -w 1 -f script.xs --edit
51
+ `$ xano ephemeral:run:job -f script.xs --edit
61
52
  # Opens script.xs in $EDITOR, then runs job with edited content
62
53
  Job executed successfully!
63
54
  ...
64
55
  `,
65
- `$ cat script.xs | xano ephemeral:run:job -w 1 --stdin
56
+ `$ cat script.xs | xano ephemeral:run:job --stdin
66
57
  Job executed successfully!
67
58
  ...
68
59
  `,
69
- `$ xano ephemeral:run:job -w 1 -f script.xs -o json
60
+ `$ xano ephemeral:run:job -f script.xs -o json
70
61
  {
71
62
  "job": { "id": 1, "run": { "id": 1 } },
72
63
  "result": { ... }
73
64
  }
74
65
  `,
75
- `$ xano ephemeral:run:job -w 1 -f script.xs -a args.json
66
+ `$ xano ephemeral:run:job -f script.xs -a args.json
76
67
  # Runs job with input arguments from args.json
77
68
  Job executed successfully!
78
69
  ...
@@ -97,19 +88,6 @@ Job executed successfully!
97
88
  if (!profile.access_token) {
98
89
  this.error(`Profile '${profileName}' is missing access_token`);
99
90
  }
100
- // Determine workspace_id from flag or profile
101
- let workspaceId;
102
- if (flags.workspace) {
103
- workspaceId = flags.workspace;
104
- }
105
- else if (profile.workspace) {
106
- workspaceId = profile.workspace;
107
- }
108
- else {
109
- this.error(`Workspace ID is required. Either:\n` +
110
- ` 1. Provide it as a flag: xano ephemeral:run:job -w <workspace_id>\n` +
111
- ` 2. Set it in your profile using: xano profile:edit ${profileName} -w <workspace_id>`);
112
- }
113
91
  // Read XanoScript content or use URL
114
92
  let xanoscript;
115
93
  let xanoscriptUrl;
@@ -174,7 +152,7 @@ Job executed successfully!
174
152
  }
175
153
  }
176
154
  // Construct the API URL
177
- const apiUrl = `${profile.instance_origin}/api:meta/beta/workspace/${workspaceId}/ephemeral/job`;
155
+ const apiUrl = `${profile.instance_origin}/api:meta/beta/ephemeral/job`;
178
156
  // Build request body
179
157
  const formData = new FormData();
180
158
  if (xanoscriptUrl) {
@@ -2,7 +2,6 @@ import BaseCommand from '../../../../base-command.js';
2
2
  export default class EphemeralRunService extends BaseCommand {
3
3
  static args: {};
4
4
  static flags: {
5
- workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
6
5
  file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
6
  stdin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
7
  edit: import("@oclif/core/interfaces").BooleanFlag<boolean>;
@@ -9,11 +9,6 @@ export default class EphemeralRunService extends BaseCommand {
9
9
  static args = {};
10
10
  static flags = {
11
11
  ...BaseCommand.baseFlags,
12
- workspace: Flags.string({
13
- char: 'w',
14
- description: 'Workspace ID (optional if set in profile)',
15
- required: false,
16
- }),
17
12
  file: Flags.string({
18
13
  char: 'f',
19
14
  description: 'Path or URL to file containing XanoScript code',
@@ -42,26 +37,22 @@ export default class EphemeralRunService extends BaseCommand {
42
37
  options: ['summary', 'json'],
43
38
  }),
44
39
  };
45
- static description = 'Run an ephemeral service in a workspace';
40
+ static description = 'Run an ephemeral service';
46
41
  static examples = [
47
- `$ xano ephemeral:run:service -w 1 -f service.xs
48
- Service created successfully!
49
- ...
50
- `,
51
42
  `$ xano ephemeral:run:service -f service.xs
52
43
  Service created successfully!
53
44
  ...
54
45
  `,
55
- `$ xano ephemeral:run:service -w 1 -f service.xs --edit
46
+ `$ xano ephemeral:run:service -f service.xs --edit
56
47
  # Opens service.xs in $EDITOR, then creates service with edited content
57
48
  Service created successfully!
58
49
  ...
59
50
  `,
60
- `$ cat service.xs | xano ephemeral:run:service -w 1 --stdin
51
+ `$ cat service.xs | xano ephemeral:run:service --stdin
61
52
  Service created successfully!
62
53
  ...
63
54
  `,
64
- `$ xano ephemeral:run:service -w 1 -f service.xs -o json
55
+ `$ xano ephemeral:run:service -f service.xs -o json
65
56
  {
66
57
  "service": { "id": 1 },
67
58
  ...
@@ -87,19 +78,6 @@ Service created successfully!
87
78
  if (!profile.access_token) {
88
79
  this.error(`Profile '${profileName}' is missing access_token`);
89
80
  }
90
- // Determine workspace_id from flag or profile
91
- let workspaceId;
92
- if (flags.workspace) {
93
- workspaceId = flags.workspace;
94
- }
95
- else if (profile.workspace) {
96
- workspaceId = profile.workspace;
97
- }
98
- else {
99
- this.error(`Workspace ID is required. Either:\n` +
100
- ` 1. Provide it as a flag: xano ephemeral:run:service -w <workspace_id>\n` +
101
- ` 2. Set it in your profile using: xano profile:edit ${profileName} -w <workspace_id>`);
102
- }
103
81
  // Read XanoScript content or use URL
104
82
  let xanoscript;
105
83
  let xanoscriptUrl;
@@ -146,7 +124,7 @@ Service created successfully!
146
124
  this.error('XanoScript content is empty');
147
125
  }
148
126
  // Construct the API URL
149
- const apiUrl = `${profile.instance_origin}/api:meta/beta/workspace/${workspaceId}/ephemeral/service`;
127
+ const apiUrl = `${profile.instance_origin}/api:meta/beta/ephemeral/service`;
150
128
  // Build request body
151
129
  const formData = new FormData();
152
130
  if (xanoscriptUrl) {
@@ -1,7 +1,7 @@
1
- import { Command } from '@oclif/core';
2
- export default class ProfileEdit extends Command {
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class ProfileEdit extends BaseCommand {
3
3
  static args: {
4
- name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
4
+ name: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
5
5
  };
6
6
  static flags: {
7
7
  account_origin: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -11,6 +11,7 @@ export default class ProfileEdit extends Command {
11
11
  branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
12
  'remove-workspace': import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
13
  'remove-branch': import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
15
  };
15
16
  static description: string;
16
17
  static examples: string[];
@@ -1,16 +1,18 @@
1
- import { Args, Command, Flags } from '@oclif/core';
1
+ import { Args, Flags } from '@oclif/core';
2
2
  import * as fs from 'node:fs';
3
3
  import * as os from 'node:os';
4
4
  import * as path from 'node:path';
5
5
  import * as yaml from 'js-yaml';
6
- export default class ProfileEdit extends Command {
6
+ import BaseCommand from '../../../base-command.js';
7
+ export default class ProfileEdit extends BaseCommand {
7
8
  static args = {
8
9
  name: Args.string({
9
- description: 'Profile name to edit',
10
- required: true,
10
+ description: 'Profile name to edit (uses default profile if not specified)',
11
+ required: false,
11
12
  }),
12
13
  };
13
14
  static flags = {
15
+ ...BaseCommand.baseFlags,
14
16
  account_origin: Flags.string({
15
17
  char: 'a',
16
18
  description: 'Update account origin URL',
@@ -49,21 +51,26 @@ export default class ProfileEdit extends Command {
49
51
  };
50
52
  static description = 'Edit an existing profile configuration';
51
53
  static examples = [
54
+ `$ xano profile:edit --access_token new_token123
55
+ Profile 'default' updated successfully at ~/.xano/credentials.yaml
56
+ `,
52
57
  `$ xano profile:edit production --access_token new_token123
53
58
  Profile 'production' updated successfully at ~/.xano/credentials.yaml
54
59
  `,
55
60
  `$ xano profile:edit staging -i https://new-staging-instance.xano.com -t new_token456
56
61
  Profile 'staging' updated successfully at ~/.xano/credentials.yaml
57
62
  `,
58
- `$ xano profile:edit dev -w new-workspace -b new-branch
59
- Profile 'dev' updated successfully at ~/.xano/credentials.yaml
63
+ `$ xano profile:edit -b new-branch
64
+ Profile 'default' updated successfully at ~/.xano/credentials.yaml
60
65
  `,
61
- `$ xano profile:edit dev --remove-workspace
62
- Profile 'dev' updated successfully at ~/.xano/credentials.yaml
66
+ `$ xano profile:edit --remove-branch
67
+ Profile 'default' updated successfully at ~/.xano/credentials.yaml
63
68
  `,
64
69
  ];
65
70
  async run() {
66
71
  const { args, flags } = await this.parse(ProfileEdit);
72
+ // Use provided name or default profile
73
+ const profileName = args.name || this.getDefaultProfile();
67
74
  const configDir = path.join(os.homedir(), '.xano');
68
75
  const credentialsPath = path.join(configDir, 'credentials.yaml');
69
76
  // Check if credentials file exists
@@ -84,11 +91,11 @@ Profile 'dev' updated successfully at ~/.xano/credentials.yaml
84
91
  this.error(`Failed to parse credentials file: ${error}`);
85
92
  }
86
93
  // Check if profile exists
87
- if (!(args.name in credentials.profiles)) {
88
- this.error(`Profile '${args.name}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}`);
94
+ if (!(profileName in credentials.profiles)) {
95
+ this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}`);
89
96
  }
90
97
  // Get the existing profile
91
- const existingProfile = credentials.profiles[args.name];
98
+ const existingProfile = credentials.profiles[profileName];
92
99
  // Check if any flags were provided
93
100
  const hasFlags = flags.account_origin || flags.instance_origin || flags.access_token ||
94
101
  flags.workspace || flags.branch || flags['remove-workspace'] || flags['remove-branch'];
@@ -111,7 +118,7 @@ Profile 'dev' updated successfully at ~/.xano/credentials.yaml
111
118
  if (flags['remove-branch']) {
112
119
  delete updatedProfile.branch;
113
120
  }
114
- credentials.profiles[args.name] = updatedProfile;
121
+ credentials.profiles[profileName] = updatedProfile;
115
122
  // Write the updated credentials back to the file
116
123
  try {
117
124
  const yamlContent = yaml.dump(credentials, {
@@ -120,7 +127,7 @@ Profile 'dev' updated successfully at ~/.xano/credentials.yaml
120
127
  noRefs: true,
121
128
  });
122
129
  fs.writeFileSync(credentialsPath, yamlContent, 'utf8');
123
- this.log(`Profile '${args.name}' updated successfully at ${credentialsPath}`);
130
+ this.log(`Profile '${profileName}' updated successfully at ${credentialsPath}`);
124
131
  }
125
132
  catch (error) {
126
133
  this.error(`Failed to write credentials file: ${error}`);
@@ -0,0 +1,12 @@
1
+ import BaseCommand from '../../../base-command.js';
2
+ export default class ProfileMe 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
+ private formatKey;
12
+ }
@@ -0,0 +1,146 @@
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 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
+ static description = 'Get information about the currently authenticated user';
19
+ static examples = [
20
+ `$ xano profile:me
21
+ User Information:
22
+ ID: 1
23
+ Name: John Doe
24
+ Email: john@example.com
25
+ `,
26
+ `$ xano profile:me --profile production
27
+ User Information:
28
+ ID: 42
29
+ Name: Admin User
30
+ Email: admin@example.com
31
+ `,
32
+ `$ xano profile:me --output json
33
+ {
34
+ "id": 1,
35
+ "name": "John Doe",
36
+ "email": "john@example.com"
37
+ }
38
+ `,
39
+ ];
40
+ async run() {
41
+ const { flags } = await this.parse(ProfileMe);
42
+ // Get profile name (default or from flag/env)
43
+ const profileName = flags.profile || this.getDefaultProfile();
44
+ // Load credentials
45
+ const credentials = this.loadCredentials();
46
+ // Get the profile configuration
47
+ if (!(profileName in credentials.profiles)) {
48
+ this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}\n` +
49
+ `Create a profile using 'xano profile:create'`);
50
+ }
51
+ const profile = credentials.profiles[profileName];
52
+ // Validate required fields
53
+ if (!profile.instance_origin) {
54
+ this.error(`Profile '${profileName}' is missing instance_origin`);
55
+ }
56
+ if (!profile.access_token) {
57
+ this.error(`Profile '${profileName}' is missing access_token`);
58
+ }
59
+ // Construct the API URL
60
+ const apiUrl = `${profile.instance_origin}/api:meta/auth/me`;
61
+ // Fetch user info from the API
62
+ try {
63
+ const response = await fetch(apiUrl, {
64
+ method: 'GET',
65
+ headers: {
66
+ 'accept': 'application/json',
67
+ 'Authorization': `Bearer ${profile.access_token}`,
68
+ },
69
+ });
70
+ if (!response.ok) {
71
+ const errorText = await response.text();
72
+ this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
73
+ }
74
+ const data = await response.json();
75
+ // Output results
76
+ if (flags.output === 'json') {
77
+ this.log(JSON.stringify(data, null, 2));
78
+ }
79
+ else {
80
+ // summary format
81
+ this.log('User Information:');
82
+ if (data.id !== undefined) {
83
+ this.log(` ID: ${data.id}`);
84
+ }
85
+ if (data.name) {
86
+ this.log(` Name: ${data.name}`);
87
+ }
88
+ if (data.email) {
89
+ this.log(` Email: ${data.email}`);
90
+ }
91
+ if (data.created_at) {
92
+ const date = new Date(data.created_at * 1000);
93
+ this.log(` Created: ${date.toISOString()}`);
94
+ }
95
+ // Display any other fields that aren't already shown
96
+ const knownFields = ['id', 'name', 'email', 'created_at'];
97
+ for (const [key, value] of Object.entries(data)) {
98
+ if (!knownFields.includes(key) && value !== null && value !== undefined) {
99
+ if (typeof value === 'object') {
100
+ this.log(` ${this.formatKey(key)}: ${JSON.stringify(value)}`);
101
+ }
102
+ else {
103
+ this.log(` ${this.formatKey(key)}: ${value}`);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ catch (error) {
110
+ if (error instanceof Error) {
111
+ this.error(`Failed to fetch user info: ${error.message}`);
112
+ }
113
+ else {
114
+ this.error(`Failed to fetch user info: ${String(error)}`);
115
+ }
116
+ }
117
+ }
118
+ loadCredentials() {
119
+ const configDir = path.join(os.homedir(), '.xano');
120
+ const credentialsPath = path.join(configDir, 'credentials.yaml');
121
+ // Check if credentials file exists
122
+ if (!fs.existsSync(credentialsPath)) {
123
+ this.error(`Credentials file not found at ${credentialsPath}\n` +
124
+ `Create a profile using 'xano profile:create'`);
125
+ }
126
+ // Read credentials file
127
+ try {
128
+ const fileContent = fs.readFileSync(credentialsPath, 'utf8');
129
+ const parsed = yaml.load(fileContent);
130
+ if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
131
+ this.error('Credentials file has invalid format.');
132
+ }
133
+ return parsed;
134
+ }
135
+ catch (error) {
136
+ this.error(`Failed to parse credentials file: ${error}`);
137
+ }
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
+ }