@xano/cli 0.0.14 → 0.0.16
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.
- package/README.md +115 -14
- package/dist/commands/profile/create/index.d.ts +2 -0
- package/dist/commands/profile/create/index.js +15 -0
- package/dist/commands/profile/edit/index.d.ts +6 -0
- package/dist/commands/profile/edit/index.js +50 -1
- package/dist/commands/profile/list/index.js +5 -0
- package/dist/commands/profile/project/index.d.ts +6 -0
- package/dist/commands/profile/project/index.js +54 -0
- package/dist/commands/profile/token/index.d.ts +6 -0
- package/dist/commands/profile/token/index.js +54 -0
- package/dist/commands/profile/wizard/index.d.ts +2 -0
- package/dist/commands/profile/wizard/index.js +108 -0
- package/dist/commands/run/env/delete/index.d.ts +13 -0
- package/dist/commands/run/env/delete/index.js +65 -0
- package/dist/commands/run/env/get/index.d.ts +13 -0
- package/dist/commands/run/env/get/index.js +52 -0
- package/dist/commands/run/env/list/index.d.ts +11 -0
- package/dist/commands/run/env/list/index.js +58 -0
- package/dist/commands/run/env/set/index.d.ts +13 -0
- package/dist/commands/run/env/set/index.js +51 -0
- package/dist/commands/{ephemeral/run/job → run/exec}/index.d.ts +4 -3
- package/dist/commands/run/exec/index.js +353 -0
- package/dist/commands/{ephemeral/run/service → run/info}/index.d.ts +3 -5
- package/dist/commands/run/info/index.js +160 -0
- package/dist/commands/run/projects/create/index.d.ts +13 -0
- package/dist/commands/run/projects/create/index.js +75 -0
- package/dist/commands/run/projects/delete/index.d.ts +13 -0
- package/dist/commands/run/projects/delete/index.js +65 -0
- package/dist/commands/run/projects/list/index.d.ts +12 -0
- package/dist/commands/run/projects/list/index.js +66 -0
- package/dist/commands/run/projects/update/index.d.ts +15 -0
- package/dist/commands/run/projects/update/index.js +86 -0
- package/dist/commands/run/secrets/delete/index.d.ts +13 -0
- package/dist/commands/run/secrets/delete/index.js +65 -0
- package/dist/commands/run/secrets/get/index.d.ts +13 -0
- package/dist/commands/run/secrets/get/index.js +52 -0
- package/dist/commands/run/secrets/list/index.d.ts +11 -0
- package/dist/commands/run/secrets/list/index.js +62 -0
- package/dist/commands/run/secrets/set/index.d.ts +15 -0
- package/dist/commands/run/secrets/set/index.js +74 -0
- package/dist/commands/run/sessions/delete/index.d.ts +13 -0
- package/dist/commands/run/sessions/delete/index.js +65 -0
- package/dist/commands/run/sessions/get/index.d.ts +13 -0
- package/dist/commands/run/sessions/get/index.js +72 -0
- package/dist/commands/run/sessions/list/index.d.ts +12 -0
- package/dist/commands/run/sessions/list/index.js +64 -0
- package/dist/commands/run/sessions/start/index.d.ts +13 -0
- package/dist/commands/run/sessions/start/index.js +56 -0
- package/dist/commands/run/sessions/stop/index.d.ts +13 -0
- package/dist/commands/run/sessions/stop/index.js +56 -0
- package/dist/commands/run/sink/get/index.d.ts +13 -0
- package/dist/commands/run/sink/get/index.js +63 -0
- package/dist/commands/workspace/pull/index.d.ts +28 -0
- package/dist/commands/workspace/pull/index.js +238 -0
- package/dist/commands/workspace/push/index.d.ts +19 -0
- package/dist/commands/workspace/push/index.js +163 -0
- package/dist/lib/base-run-command.d.ts +42 -0
- package/dist/lib/base-run-command.js +75 -0
- package/dist/lib/run-http-client.d.ts +58 -0
- package/dist/lib/run-http-client.js +136 -0
- package/dist/lib/run-types.d.ts +226 -0
- package/dist/lib/run-types.js +5 -0
- package/oclif.manifest.json +1470 -218
- package/package.json +1 -1
- package/dist/commands/ephemeral/run/job/index.js +0 -311
- package/dist/commands/ephemeral/run/service/index.js +0 -287
package/README.md
CHANGED
|
@@ -23,24 +23,27 @@ npm install -g @xano/cli
|
|
|
23
23
|
xano workspace:list
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
3.
|
|
26
|
+
3. Execute XanoScript code:
|
|
27
27
|
```bash
|
|
28
|
-
xano
|
|
28
|
+
xano run exec -f script.xs
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
## Commands
|
|
32
32
|
|
|
33
33
|
### Profile Management
|
|
34
34
|
|
|
35
|
-
Profiles store your Xano credentials and default workspace settings.
|
|
35
|
+
Profiles store your Xano credentials and default workspace/project settings.
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
# Create a profile interactively
|
|
38
|
+
# Create a profile interactively (auto-fetches run projects)
|
|
39
39
|
xano profile:wizard
|
|
40
40
|
|
|
41
41
|
# Create a profile manually
|
|
42
42
|
xano profile:create myprofile -i https://instance.xano.com -t <access_token>
|
|
43
43
|
|
|
44
|
+
# Create a profile with workspace and project
|
|
45
|
+
xano profile:create myprofile -i https://instance.xano.com -t <access_token> -w my-workspace -j my-project
|
|
46
|
+
|
|
44
47
|
# List profiles
|
|
45
48
|
xano profile:list
|
|
46
49
|
xano profile:list --details
|
|
@@ -49,12 +52,17 @@ xano profile:list --details
|
|
|
49
52
|
xano profile:set-default myprofile
|
|
50
53
|
|
|
51
54
|
# Edit a profile
|
|
52
|
-
xano profile:edit myprofile -w 123
|
|
55
|
+
xano profile:edit myprofile -w 123 # Set default workspace
|
|
56
|
+
xano profile:edit myprofile -j my-project # Set default project
|
|
57
|
+
xano profile:edit myprofile --run-project <id> # Set run project for xano run commands
|
|
58
|
+
xano profile:edit myprofile --remove-run-project # Remove run project
|
|
53
59
|
|
|
54
60
|
# Delete a profile
|
|
55
61
|
xano profile:delete myprofile
|
|
56
62
|
```
|
|
57
63
|
|
|
64
|
+
The `profile:wizard` command automatically fetches your run projects and sets the first one as the default for `xano run` commands.
|
|
65
|
+
|
|
58
66
|
### Workspaces
|
|
59
67
|
|
|
60
68
|
```bash
|
|
@@ -84,18 +92,99 @@ xano function:edit 145 -f new.xs # Update from file
|
|
|
84
92
|
xano function:edit 145 --publish # Publish after editing
|
|
85
93
|
```
|
|
86
94
|
|
|
87
|
-
###
|
|
95
|
+
### Xano Run
|
|
96
|
+
|
|
97
|
+
Execute XanoScript code and manage projects, sessions, environment variables, and secrets.
|
|
98
|
+
|
|
99
|
+
#### Executing Code
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Execute XanoScript (job or service)
|
|
103
|
+
xano run exec -f script.xs
|
|
104
|
+
xano run exec -f https://example.com/script.xs # From URL
|
|
105
|
+
xano run exec -f script.xs -a args.json # With input arguments (file)
|
|
106
|
+
xano run exec -f script.xs -a https://ex.com/args.json # With input arguments (URL)
|
|
107
|
+
xano run exec -f script.xs --edit # Edit in $EDITOR first
|
|
108
|
+
xano run exec -f script.xs --env API_KEY=secret # With env overrides
|
|
109
|
+
cat script.xs | xano run exec --stdin # From stdin
|
|
110
|
+
|
|
111
|
+
# Get document info (type, inputs, env vars)
|
|
112
|
+
xano run info -f script.xs
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Projects
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# List projects
|
|
119
|
+
xano run projects list
|
|
120
|
+
|
|
121
|
+
# Create a project
|
|
122
|
+
xano run projects create -n "My Project"
|
|
123
|
+
xano run projects create -n "My Project" -d "Description"
|
|
124
|
+
|
|
125
|
+
# Update a project
|
|
126
|
+
xano run projects update <project-id> -n "New Name"
|
|
127
|
+
xano run projects update <project-id> -d "New description"
|
|
128
|
+
|
|
129
|
+
# Delete a project
|
|
130
|
+
xano run projects delete <project-id>
|
|
131
|
+
xano run projects delete <project-id> --force # Skip confirmation
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### Sessions
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# List sessions
|
|
138
|
+
xano run sessions list
|
|
139
|
+
|
|
140
|
+
# Get session details
|
|
141
|
+
xano run sessions get <session-id>
|
|
142
|
+
|
|
143
|
+
# Start/stop a session
|
|
144
|
+
xano run sessions start <session-id>
|
|
145
|
+
xano run sessions stop <session-id>
|
|
146
|
+
|
|
147
|
+
# Delete a session
|
|
148
|
+
xano run sessions delete <session-id>
|
|
149
|
+
xano run sessions delete <session-id> --force # Skip confirmation
|
|
150
|
+
|
|
151
|
+
# Get sink data for a completed session
|
|
152
|
+
xano run sink get <session-id>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### Environment Variables
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# List environment variable keys
|
|
159
|
+
xano run env list
|
|
160
|
+
|
|
161
|
+
# Set an environment variable
|
|
162
|
+
xano run env set API_KEY my-secret-key
|
|
163
|
+
|
|
164
|
+
# Get an environment variable value
|
|
165
|
+
xano run env get API_KEY
|
|
166
|
+
|
|
167
|
+
# Delete an environment variable
|
|
168
|
+
xano run env delete API_KEY
|
|
169
|
+
xano run env delete API_KEY --force # Skip confirmation
|
|
170
|
+
```
|
|
88
171
|
|
|
89
|
-
|
|
172
|
+
#### Secrets
|
|
90
173
|
|
|
91
174
|
```bash
|
|
92
|
-
#
|
|
93
|
-
xano
|
|
94
|
-
|
|
95
|
-
|
|
175
|
+
# List secrets
|
|
176
|
+
xano run secrets list
|
|
177
|
+
|
|
178
|
+
# Set a secret
|
|
179
|
+
xano run secrets set docker-registry -t dockerconfigjson -v '{"auths":{...}}' -r ghcr.io
|
|
180
|
+
xano run secrets set service-key -t service-account-token -v 'token-value'
|
|
96
181
|
|
|
97
|
-
#
|
|
98
|
-
xano
|
|
182
|
+
# Get a secret value
|
|
183
|
+
xano run secrets get docker-registry
|
|
184
|
+
|
|
185
|
+
# Delete a secret
|
|
186
|
+
xano run secrets delete docker-registry
|
|
187
|
+
xano run secrets delete docker-registry --force # Skip confirmation
|
|
99
188
|
```
|
|
100
189
|
|
|
101
190
|
### Static Hosts
|
|
@@ -126,7 +215,19 @@ All commands support these options:
|
|
|
126
215
|
|
|
127
216
|
## Configuration
|
|
128
217
|
|
|
129
|
-
Profiles are stored in `~/.xano/credentials.yaml
|
|
218
|
+
Profiles are stored in `~/.xano/credentials.yaml`:
|
|
219
|
+
|
|
220
|
+
```yaml
|
|
221
|
+
profiles:
|
|
222
|
+
default:
|
|
223
|
+
account_origin: https://app.xano.com
|
|
224
|
+
instance_origin: https://instance.xano.com
|
|
225
|
+
access_token: <token>
|
|
226
|
+
workspace: <workspace_id>
|
|
227
|
+
branch: <branch_id>
|
|
228
|
+
run_project: <run_project_id> # Used by xano run commands
|
|
229
|
+
default: default
|
|
230
|
+
```
|
|
130
231
|
|
|
131
232
|
## Help
|
|
132
233
|
|
|
@@ -9,6 +9,8 @@ export default class ProfileCreate extends Command {
|
|
|
9
9
|
access_token: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
11
|
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
run_base_url: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
14
|
default: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
15
|
};
|
|
14
16
|
static description: string;
|
|
@@ -36,6 +36,16 @@ export default class ProfileCreate extends Command {
|
|
|
36
36
|
description: 'Branch name',
|
|
37
37
|
required: false,
|
|
38
38
|
}),
|
|
39
|
+
project: Flags.string({
|
|
40
|
+
char: 'j',
|
|
41
|
+
description: 'Project name',
|
|
42
|
+
required: false,
|
|
43
|
+
}),
|
|
44
|
+
run_base_url: Flags.string({
|
|
45
|
+
char: 'r',
|
|
46
|
+
description: 'Xano Run API base URL (default: https://app.xano.com/)',
|
|
47
|
+
required: false,
|
|
48
|
+
}),
|
|
39
49
|
default: Flags.boolean({
|
|
40
50
|
description: 'Set this profile as the default',
|
|
41
51
|
required: false,
|
|
@@ -52,6 +62,9 @@ Profile 'staging' created successfully at ~/.xano/credentials.yaml
|
|
|
52
62
|
`,
|
|
53
63
|
`$ xano profile:create dev -i https://dev-instance.xano.com -t token789 -w my-workspace -b feature-branch
|
|
54
64
|
Profile 'dev' created successfully at ~/.xano/credentials.yaml
|
|
65
|
+
`,
|
|
66
|
+
`$ xano profile:create dev -i https://dev-instance.xano.com -t token789 -w my-workspace -b feature-branch -j my-project
|
|
67
|
+
Profile 'dev' created successfully at ~/.xano/credentials.yaml
|
|
55
68
|
`,
|
|
56
69
|
`$ xano profile:create production --account_origin https://account.xano.com --instance_origin https://instance.xano.com --access_token token123 --default
|
|
57
70
|
Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
@@ -93,6 +106,8 @@ Default profile set to 'production'
|
|
|
93
106
|
access_token: flags.access_token,
|
|
94
107
|
...(flags.workspace && { workspace: flags.workspace }),
|
|
95
108
|
...(flags.branch && { branch: flags.branch }),
|
|
109
|
+
...(flags.project && { project: flags.project }),
|
|
110
|
+
...(flags.run_base_url && { run_base_url: flags.run_base_url }),
|
|
96
111
|
};
|
|
97
112
|
// Set default if flag is provided
|
|
98
113
|
if (flags.default) {
|
|
@@ -9,8 +9,14 @@ export default class ProfileEdit extends BaseCommand {
|
|
|
9
9
|
access_token: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
10
|
workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
11
|
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'run-project': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
14
|
'remove-workspace': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
15
|
'remove-branch': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
+
'remove-project': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
17
|
+
'remove-run-project': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
18
|
+
run_base_url: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
'remove-run-base-url': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
20
|
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
21
|
};
|
|
16
22
|
static description: string;
|
|
@@ -38,6 +38,15 @@ export default class ProfileEdit extends BaseCommand {
|
|
|
38
38
|
description: 'Update branch name',
|
|
39
39
|
required: false,
|
|
40
40
|
}),
|
|
41
|
+
project: Flags.string({
|
|
42
|
+
char: 'j',
|
|
43
|
+
description: 'Update project name',
|
|
44
|
+
required: false,
|
|
45
|
+
}),
|
|
46
|
+
'run-project': Flags.string({
|
|
47
|
+
description: 'Update run project ID (for xano run commands)',
|
|
48
|
+
required: false,
|
|
49
|
+
}),
|
|
41
50
|
'remove-workspace': Flags.boolean({
|
|
42
51
|
description: 'Remove workspace from profile',
|
|
43
52
|
required: false,
|
|
@@ -48,6 +57,26 @@ export default class ProfileEdit extends BaseCommand {
|
|
|
48
57
|
required: false,
|
|
49
58
|
default: false,
|
|
50
59
|
}),
|
|
60
|
+
'remove-project': Flags.boolean({
|
|
61
|
+
description: 'Remove project from profile',
|
|
62
|
+
required: false,
|
|
63
|
+
default: false,
|
|
64
|
+
}),
|
|
65
|
+
'remove-run-project': Flags.boolean({
|
|
66
|
+
description: 'Remove run project from profile',
|
|
67
|
+
required: false,
|
|
68
|
+
default: false,
|
|
69
|
+
}),
|
|
70
|
+
run_base_url: Flags.string({
|
|
71
|
+
char: 'r',
|
|
72
|
+
description: 'Update Xano Run API base URL',
|
|
73
|
+
required: false,
|
|
74
|
+
}),
|
|
75
|
+
'remove-run-base-url': Flags.boolean({
|
|
76
|
+
description: 'Remove run_base_url from profile (use default)',
|
|
77
|
+
required: false,
|
|
78
|
+
default: false,
|
|
79
|
+
}),
|
|
51
80
|
};
|
|
52
81
|
static description = 'Edit an existing profile configuration';
|
|
53
82
|
static examples = [
|
|
@@ -65,6 +94,12 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
65
94
|
`,
|
|
66
95
|
`$ xano profile:edit --remove-branch
|
|
67
96
|
Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
97
|
+
`,
|
|
98
|
+
`$ xano profile:edit -j my-project
|
|
99
|
+
Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
100
|
+
`,
|
|
101
|
+
`$ xano profile:edit --remove-project
|
|
102
|
+
Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
68
103
|
`,
|
|
69
104
|
];
|
|
70
105
|
async run() {
|
|
@@ -98,7 +133,9 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
98
133
|
const existingProfile = credentials.profiles[profileName];
|
|
99
134
|
// Check if any flags were provided
|
|
100
135
|
const hasFlags = flags.account_origin || flags.instance_origin || flags.access_token ||
|
|
101
|
-
flags.workspace || flags.branch || flags['
|
|
136
|
+
flags.workspace || flags.branch || flags.project || flags['run-project'] || flags.run_base_url ||
|
|
137
|
+
flags['remove-workspace'] || flags['remove-branch'] || flags['remove-project'] ||
|
|
138
|
+
flags['remove-run-project'] || flags['remove-run-base-url'];
|
|
102
139
|
if (!hasFlags) {
|
|
103
140
|
this.error('No fields specified to update. Use at least one flag to edit the profile.');
|
|
104
141
|
}
|
|
@@ -110,6 +147,9 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
110
147
|
...(flags.access_token !== undefined && { access_token: flags.access_token }),
|
|
111
148
|
...(flags.workspace !== undefined && { workspace: flags.workspace }),
|
|
112
149
|
...(flags.branch !== undefined && { branch: flags.branch }),
|
|
150
|
+
...(flags.project !== undefined && { project: flags.project }),
|
|
151
|
+
...(flags['run-project'] !== undefined && { run_project: flags['run-project'] }),
|
|
152
|
+
...(flags.run_base_url !== undefined && { run_base_url: flags.run_base_url }),
|
|
113
153
|
};
|
|
114
154
|
// Handle removal flags
|
|
115
155
|
if (flags['remove-workspace']) {
|
|
@@ -118,6 +158,15 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
118
158
|
if (flags['remove-branch']) {
|
|
119
159
|
delete updatedProfile.branch;
|
|
120
160
|
}
|
|
161
|
+
if (flags['remove-project']) {
|
|
162
|
+
delete updatedProfile.project;
|
|
163
|
+
}
|
|
164
|
+
if (flags['remove-run-project']) {
|
|
165
|
+
delete updatedProfile.run_project;
|
|
166
|
+
}
|
|
167
|
+
if (flags['remove-run-base-url']) {
|
|
168
|
+
delete updatedProfile.run_base_url;
|
|
169
|
+
}
|
|
121
170
|
credentials.profiles[profileName] = updatedProfile;
|
|
122
171
|
// Write the updated credentials back to the file
|
|
123
172
|
try {
|
|
@@ -30,6 +30,7 @@ Profile: default
|
|
|
30
30
|
Access Token: ***...***
|
|
31
31
|
Workspace: my-workspace
|
|
32
32
|
Branch: main
|
|
33
|
+
Project: my-project
|
|
33
34
|
|
|
34
35
|
Profile: production
|
|
35
36
|
Account Origin: https://account.xano.com
|
|
@@ -45,6 +46,7 @@ Profile: default
|
|
|
45
46
|
Access Token: ***...***
|
|
46
47
|
Workspace: my-workspace
|
|
47
48
|
Branch: main
|
|
49
|
+
Project: my-project
|
|
48
50
|
`,
|
|
49
51
|
];
|
|
50
52
|
async run() {
|
|
@@ -93,6 +95,9 @@ Profile: default
|
|
|
93
95
|
if (profile.branch) {
|
|
94
96
|
this.log(` Branch: ${profile.branch}`);
|
|
95
97
|
}
|
|
98
|
+
if (profile.project) {
|
|
99
|
+
this.log(` Project: ${profile.project}`);
|
|
100
|
+
}
|
|
96
101
|
this.log(''); // Empty line between profiles
|
|
97
102
|
}
|
|
98
103
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Command } 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
|
+
export default class ProfileProject extends Command {
|
|
7
|
+
static description = 'Print the project for the default profile';
|
|
8
|
+
static examples = [
|
|
9
|
+
`$ xano profile:project
|
|
10
|
+
my-project-id
|
|
11
|
+
`,
|
|
12
|
+
`$ xano profile:project | pbcopy
|
|
13
|
+
# Copies the project to clipboard on macOS
|
|
14
|
+
`,
|
|
15
|
+
];
|
|
16
|
+
async run() {
|
|
17
|
+
const configDir = path.join(os.homedir(), '.xano');
|
|
18
|
+
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
19
|
+
// Check if credentials file exists
|
|
20
|
+
if (!fs.existsSync(credentialsPath)) {
|
|
21
|
+
this.error(`Credentials file not found at ${credentialsPath}. Create a profile first using 'profile:create'.`);
|
|
22
|
+
}
|
|
23
|
+
// Read credentials file
|
|
24
|
+
let credentials;
|
|
25
|
+
try {
|
|
26
|
+
const fileContent = fs.readFileSync(credentialsPath, 'utf8');
|
|
27
|
+
const parsed = yaml.load(fileContent);
|
|
28
|
+
if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
|
|
29
|
+
this.error('Credentials file has invalid format.');
|
|
30
|
+
}
|
|
31
|
+
credentials = parsed;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
this.error(`Failed to parse credentials file: ${error}`);
|
|
35
|
+
}
|
|
36
|
+
// Get the default profile name
|
|
37
|
+
const defaultProfileName = credentials.default;
|
|
38
|
+
if (!defaultProfileName) {
|
|
39
|
+
this.error("No default profile set. Set one using 'profile:set-default <name>'.");
|
|
40
|
+
}
|
|
41
|
+
// Check if the default profile exists
|
|
42
|
+
if (!(defaultProfileName in credentials.profiles)) {
|
|
43
|
+
this.error(`Default profile '${defaultProfileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}`);
|
|
44
|
+
}
|
|
45
|
+
const profile = credentials.profiles[defaultProfileName];
|
|
46
|
+
// Get and display the project
|
|
47
|
+
if (profile.project) {
|
|
48
|
+
this.log(profile.project);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.error(`Profile '${defaultProfileName}' does not have a project set. Set one using 'profile:edit -j <project>'.`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Command } 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
|
+
export default class ProfileToken extends Command {
|
|
7
|
+
static description = 'Print the access token for the default profile';
|
|
8
|
+
static examples = [
|
|
9
|
+
`$ xano profile:token
|
|
10
|
+
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|
11
|
+
`,
|
|
12
|
+
`$ xano profile:token | pbcopy
|
|
13
|
+
# Copies the token to clipboard on macOS
|
|
14
|
+
`,
|
|
15
|
+
];
|
|
16
|
+
async run() {
|
|
17
|
+
const configDir = path.join(os.homedir(), '.xano');
|
|
18
|
+
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
19
|
+
// Check if credentials file exists
|
|
20
|
+
if (!fs.existsSync(credentialsPath)) {
|
|
21
|
+
this.error(`Credentials file not found at ${credentialsPath}. Create a profile first using 'profile:create'.`);
|
|
22
|
+
}
|
|
23
|
+
// Read credentials file
|
|
24
|
+
let credentials;
|
|
25
|
+
try {
|
|
26
|
+
const fileContent = fs.readFileSync(credentialsPath, 'utf8');
|
|
27
|
+
const parsed = yaml.load(fileContent);
|
|
28
|
+
if (!parsed || typeof parsed !== 'object' || !('profiles' in parsed)) {
|
|
29
|
+
this.error('Credentials file has invalid format.');
|
|
30
|
+
}
|
|
31
|
+
credentials = parsed;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
this.error(`Failed to parse credentials file: ${error}`);
|
|
35
|
+
}
|
|
36
|
+
// Get the default profile name
|
|
37
|
+
const defaultProfileName = credentials.default;
|
|
38
|
+
if (!defaultProfileName) {
|
|
39
|
+
this.error("No default profile set. Set one using 'profile:set-default <name>'.");
|
|
40
|
+
}
|
|
41
|
+
// Check if the default profile exists
|
|
42
|
+
if (!(defaultProfileName in credentials.profiles)) {
|
|
43
|
+
this.error(`Default profile '${defaultProfileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}`);
|
|
44
|
+
}
|
|
45
|
+
const profile = credentials.profiles[defaultProfileName];
|
|
46
|
+
// Get and display the access token
|
|
47
|
+
if (profile.access_token) {
|
|
48
|
+
this.log(profile.access_token);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
this.error(`Profile '${defaultProfileName}' does not have an access token.`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -4,6 +4,7 @@ import * as os from 'node:os';
|
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import * as yaml from 'js-yaml';
|
|
6
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
9
|
static flags = {
|
|
9
10
|
name: Flags.string({
|
|
@@ -96,6 +97,7 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
96
97
|
// Step 5: Workspace selection
|
|
97
98
|
let workspace;
|
|
98
99
|
let branch;
|
|
100
|
+
let project;
|
|
99
101
|
// Fetch workspaces from the selected instance
|
|
100
102
|
this.log('');
|
|
101
103
|
this.log('Fetching available workspaces...');
|
|
@@ -157,8 +159,56 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
157
159
|
]);
|
|
158
160
|
branch = selectedBranch || undefined;
|
|
159
161
|
}
|
|
162
|
+
// Step 6: Project selection
|
|
163
|
+
this.log('');
|
|
164
|
+
this.log('Fetching available projects...');
|
|
165
|
+
let projects = [];
|
|
166
|
+
try {
|
|
167
|
+
projects = await this.fetchProjects(accessToken, selectedInstance.origin, workspace, branch);
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
this.warn(`Failed to fetch projects: ${error instanceof Error ? error.message : String(error)}`);
|
|
171
|
+
}
|
|
172
|
+
// If projects were fetched, let user select one
|
|
173
|
+
if (projects.length > 0) {
|
|
174
|
+
this.log('');
|
|
175
|
+
const { selectedProject } = await inquirer.prompt([
|
|
176
|
+
{
|
|
177
|
+
type: 'list',
|
|
178
|
+
name: 'selectedProject',
|
|
179
|
+
message: 'Select a project',
|
|
180
|
+
choices: [
|
|
181
|
+
{ name: '(Skip project)', value: '' },
|
|
182
|
+
...projects.map((proj) => {
|
|
183
|
+
return {
|
|
184
|
+
name: proj.name,
|
|
185
|
+
value: proj.id,
|
|
186
|
+
};
|
|
187
|
+
}),
|
|
188
|
+
],
|
|
189
|
+
},
|
|
190
|
+
]);
|
|
191
|
+
project = selectedProject || undefined;
|
|
192
|
+
}
|
|
160
193
|
}
|
|
161
194
|
}
|
|
195
|
+
// Step 7: Fetch run projects and auto-select the first one
|
|
196
|
+
let runProject;
|
|
197
|
+
this.log('');
|
|
198
|
+
this.log('Fetching available run projects...');
|
|
199
|
+
try {
|
|
200
|
+
const runProjects = await this.fetchRunProjects(accessToken);
|
|
201
|
+
if (runProjects.length > 0) {
|
|
202
|
+
runProject = runProjects[0].id;
|
|
203
|
+
this.log(`✓ Found ${runProjects.length} run project(s). Using "${runProjects[0].name}" as default.`);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
this.log('No run projects found. You can create one later with "xano run projects create".');
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Silently ignore - run_project will remain undefined
|
|
211
|
+
}
|
|
162
212
|
// Save profile
|
|
163
213
|
await this.saveProfile({
|
|
164
214
|
name: profileName,
|
|
@@ -167,6 +217,8 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
167
217
|
access_token: accessToken,
|
|
168
218
|
workspace,
|
|
169
219
|
branch,
|
|
220
|
+
project,
|
|
221
|
+
run_project: runProject,
|
|
170
222
|
}, true);
|
|
171
223
|
this.log('');
|
|
172
224
|
this.log(`✓ Profile '${profileName}' created successfully!`);
|
|
@@ -288,6 +340,60 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
288
340
|
}
|
|
289
341
|
return [];
|
|
290
342
|
}
|
|
343
|
+
async fetchProjects(accessToken, origin, workspaceId, branchId) {
|
|
344
|
+
const branchParam = branchId ? `?branch=${branchId}` : '';
|
|
345
|
+
const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/project${branchParam}`, {
|
|
346
|
+
method: 'GET',
|
|
347
|
+
headers: {
|
|
348
|
+
accept: 'application/json',
|
|
349
|
+
Authorization: `Bearer ${accessToken}`,
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
if (!response.ok) {
|
|
353
|
+
if (response.status === 401) {
|
|
354
|
+
throw new Error('Unauthorized. Please check your access token.');
|
|
355
|
+
}
|
|
356
|
+
throw new Error(`API request failed with status ${response.status}`);
|
|
357
|
+
}
|
|
358
|
+
const data = (await response.json());
|
|
359
|
+
// Transform API response to Project format
|
|
360
|
+
// Assuming the API returns an array or object with projects
|
|
361
|
+
if (Array.isArray(data)) {
|
|
362
|
+
return data.map((proj) => ({
|
|
363
|
+
id: proj.id || proj.name,
|
|
364
|
+
name: proj.name,
|
|
365
|
+
}));
|
|
366
|
+
}
|
|
367
|
+
// If it's an object, try to extract projects
|
|
368
|
+
if (data && typeof data === 'object') {
|
|
369
|
+
const projects = data.projects || data.data || [];
|
|
370
|
+
if (Array.isArray(projects)) {
|
|
371
|
+
return projects.map((proj) => ({
|
|
372
|
+
id: proj.id || proj.name,
|
|
373
|
+
name: proj.name,
|
|
374
|
+
}));
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return [];
|
|
378
|
+
}
|
|
379
|
+
async fetchRunProjects(accessToken, runBaseUrl = DEFAULT_RUN_BASE_URL) {
|
|
380
|
+
const baseUrl = runBaseUrl.endsWith('/') ? runBaseUrl.slice(0, -1) : runBaseUrl;
|
|
381
|
+
const response = await fetch(`${baseUrl}/api:run/project`, {
|
|
382
|
+
method: 'GET',
|
|
383
|
+
headers: {
|
|
384
|
+
'Content-Type': 'application/json',
|
|
385
|
+
Authorization: `Bearer ${accessToken}`,
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
if (!response.ok) {
|
|
389
|
+
if (response.status === 401) {
|
|
390
|
+
throw new Error('Unauthorized. Please check your access token.');
|
|
391
|
+
}
|
|
392
|
+
throw new Error(`API request failed with status ${response.status}`);
|
|
393
|
+
}
|
|
394
|
+
const data = (await response.json());
|
|
395
|
+
return Array.isArray(data) ? data : [];
|
|
396
|
+
}
|
|
291
397
|
getDefaultProfileName() {
|
|
292
398
|
try {
|
|
293
399
|
const configDir = path.join(os.homedir(), '.xano');
|
|
@@ -334,6 +440,8 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
334
440
|
access_token: profile.access_token,
|
|
335
441
|
...(profile.workspace && { workspace: profile.workspace }),
|
|
336
442
|
...(profile.branch && { branch: profile.branch }),
|
|
443
|
+
...(profile.project && { project: profile.project }),
|
|
444
|
+
...(profile.run_project && { run_project: profile.run_project }),
|
|
337
445
|
};
|
|
338
446
|
// Set as default if requested
|
|
339
447
|
if (setAsDefault) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import BaseRunCommand from '../../../../lib/base-run-command.js';
|
|
2
|
+
export default class RunEnvDelete extends BaseRunCommand {
|
|
3
|
+
static args: {
|
|
4
|
+
name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static flags: {
|
|
7
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
static description: string;
|
|
11
|
+
static examples: string[];
|
|
12
|
+
run(): Promise<void>;
|
|
13
|
+
}
|