@xano/cli 0.0.65 → 0.0.66
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 +25 -0
- package/dist/base-command.d.ts +25 -0
- package/dist/base-command.js +53 -11
- package/dist/commands/auth/index.d.ts +2 -0
- package/dist/commands/auth/index.js +23 -16
- package/dist/commands/function/edit/index.js +17 -18
- package/dist/commands/function/get/index.js +11 -11
- package/dist/commands/profile/create/index.d.ts +1 -0
- package/dist/commands/profile/create/index.js +10 -0
- package/dist/commands/profile/edit/index.d.ts +2 -0
- package/dist/commands/profile/edit/index.js +23 -1
- package/dist/commands/profile/list/index.js +3 -0
- package/dist/commands/profile/wizard/index.d.ts +2 -0
- package/dist/commands/profile/wizard/index.js +23 -12
- package/dist/commands/release/export/index.js +14 -13
- package/dist/commands/tenant/backup/export/index.js +4 -2
- package/dist/commands/workspace/git/pull/index.js +2 -2
- package/oclif.manifest.json +1264 -1224
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ import * as yaml from 'js-yaml';
|
|
|
5
5
|
import * as fs from 'node:fs';
|
|
6
6
|
import * as os from 'node:os';
|
|
7
7
|
import * as path from 'node:path';
|
|
8
|
+
import { buildUserAgent } from '../../../base-command.js';
|
|
8
9
|
export default class ProfileWizard extends Command {
|
|
9
10
|
static description = 'Create a new profile configuration using an interactive wizard';
|
|
10
11
|
static examples = [
|
|
@@ -19,6 +20,12 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
19
20
|
`,
|
|
20
21
|
];
|
|
21
22
|
static flags = {
|
|
23
|
+
insecure: Flags.boolean({
|
|
24
|
+
char: 'k',
|
|
25
|
+
default: false,
|
|
26
|
+
description: 'Skip TLS certificate verification (for self-signed certificates)',
|
|
27
|
+
required: false,
|
|
28
|
+
}),
|
|
22
29
|
name: Flags.string({
|
|
23
30
|
char: 'n',
|
|
24
31
|
description: 'Profile name (skip prompt if provided)',
|
|
@@ -33,6 +40,10 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
33
40
|
};
|
|
34
41
|
async run() {
|
|
35
42
|
const { flags } = await this.parse(ProfileWizard);
|
|
43
|
+
if (flags.insecure) {
|
|
44
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
45
|
+
this.warn('TLS certificate verification is disabled (insecure mode)');
|
|
46
|
+
}
|
|
36
47
|
this.log('Welcome to the Xano Profile Wizard!');
|
|
37
48
|
this.log('');
|
|
38
49
|
try {
|
|
@@ -163,6 +174,7 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
163
174
|
access_token: accessToken,
|
|
164
175
|
account_origin: flags.origin,
|
|
165
176
|
branch,
|
|
177
|
+
...(flags.insecure && { insecure: true }),
|
|
166
178
|
instance_origin: selectedInstance.origin,
|
|
167
179
|
name: profileName,
|
|
168
180
|
workspace,
|
|
@@ -178,12 +190,16 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
178
190
|
throw error;
|
|
179
191
|
}
|
|
180
192
|
}
|
|
193
|
+
getHeaders(accessToken) {
|
|
194
|
+
return {
|
|
195
|
+
'User-Agent': buildUserAgent(this.config.version),
|
|
196
|
+
accept: 'application/json',
|
|
197
|
+
...(accessToken && { Authorization: `Bearer ${accessToken}` }),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
181
200
|
async fetchBranches(accessToken, origin, workspaceId) {
|
|
182
201
|
const response = await fetch(`${origin}/api:meta/workspace/${workspaceId}/branch`, {
|
|
183
|
-
headers:
|
|
184
|
-
accept: 'application/json',
|
|
185
|
-
Authorization: `Bearer ${accessToken}`,
|
|
186
|
-
},
|
|
202
|
+
headers: this.getHeaders(accessToken),
|
|
187
203
|
method: 'GET',
|
|
188
204
|
});
|
|
189
205
|
if (!response.ok) {
|
|
@@ -215,10 +231,7 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
215
231
|
}
|
|
216
232
|
async fetchInstances(accessToken, origin) {
|
|
217
233
|
const response = await fetch(`${origin}/api:meta/instance`, {
|
|
218
|
-
headers:
|
|
219
|
-
accept: 'application/json',
|
|
220
|
-
Authorization: `Bearer ${accessToken}`,
|
|
221
|
-
},
|
|
234
|
+
headers: this.getHeaders(accessToken),
|
|
222
235
|
method: 'GET',
|
|
223
236
|
});
|
|
224
237
|
if (!response.ok) {
|
|
@@ -254,10 +267,7 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
254
267
|
}
|
|
255
268
|
async fetchWorkspaces(accessToken, origin) {
|
|
256
269
|
const response = await fetch(`${origin}/api:meta/workspace`, {
|
|
257
|
-
headers:
|
|
258
|
-
accept: 'application/json',
|
|
259
|
-
Authorization: `Bearer ${accessToken}`,
|
|
260
|
-
},
|
|
270
|
+
headers: this.getHeaders(accessToken),
|
|
261
271
|
method: 'GET',
|
|
262
272
|
});
|
|
263
273
|
if (!response.ok) {
|
|
@@ -333,6 +343,7 @@ Profile 'production' created successfully at ~/.xano/credentials.yaml
|
|
|
333
343
|
instance_origin: profile.instance_origin,
|
|
334
344
|
...(profile.workspace && { workspace: profile.workspace }),
|
|
335
345
|
...(profile.branch && { branch: profile.branch }),
|
|
346
|
+
...(profile.insecure && { insecure: true }),
|
|
336
347
|
};
|
|
337
348
|
// Set as default if requested
|
|
338
349
|
if (setAsDefault) {
|
|
@@ -3,7 +3,7 @@ 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
|
-
import BaseCommand from '../../../base-command.js';
|
|
6
|
+
import BaseCommand, { buildUserAgent } from '../../../base-command.js';
|
|
7
7
|
export default class ReleaseExport extends BaseCommand {
|
|
8
8
|
static args = {
|
|
9
9
|
release_name: Args.string({
|
|
@@ -64,8 +64,8 @@ Downloaded release 'v1.0' to ./release-v1.0.tar.gz
|
|
|
64
64
|
try {
|
|
65
65
|
const response = await this.verboseFetch(exportUrl, {
|
|
66
66
|
headers: {
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
accept: 'application/json',
|
|
68
|
+
Authorization: `Bearer ${profile.access_token}`,
|
|
69
69
|
},
|
|
70
70
|
method: 'GET',
|
|
71
71
|
}, flags.verbose, profile.access_token);
|
|
@@ -73,7 +73,7 @@ Downloaded release 'v1.0' to ./release-v1.0.tar.gz
|
|
|
73
73
|
const errorText = await response.text();
|
|
74
74
|
this.error(`API request failed with status ${response.status}: ${response.statusText}\n${errorText}`);
|
|
75
75
|
}
|
|
76
|
-
const exportLink = await response.json();
|
|
76
|
+
const exportLink = (await response.json());
|
|
77
77
|
if (!exportLink.src) {
|
|
78
78
|
this.error('API did not return a download URL');
|
|
79
79
|
}
|
|
@@ -81,7 +81,9 @@ Downloaded release 'v1.0' to ./release-v1.0.tar.gz
|
|
|
81
81
|
const safeFilename = releaseName.replaceAll(/[^\w.-]/g, '_');
|
|
82
82
|
const outputPath = flags.output || `release-${safeFilename}.tar.gz`;
|
|
83
83
|
const resolvedPath = path.resolve(outputPath);
|
|
84
|
-
const downloadResponse = await fetch(exportLink.src
|
|
84
|
+
const downloadResponse = await fetch(exportLink.src, {
|
|
85
|
+
headers: { 'User-Agent': buildUserAgent(this.config.version) },
|
|
86
|
+
});
|
|
85
87
|
if (!downloadResponse.ok) {
|
|
86
88
|
this.error(`Failed to download release: ${downloadResponse.status} ${downloadResponse.statusText}`);
|
|
87
89
|
}
|
|
@@ -126,8 +128,7 @@ Downloaded release 'v1.0' to ./release-v1.0.tar.gz
|
|
|
126
128
|
const configDir = path.join(os.homedir(), '.xano');
|
|
127
129
|
const credentialsPath = path.join(configDir, 'credentials.yaml');
|
|
128
130
|
if (!fs.existsSync(credentialsPath)) {
|
|
129
|
-
this.error(`Credentials file not found at ${credentialsPath}\n` +
|
|
130
|
-
`Create a profile using 'xano profile create'`);
|
|
131
|
+
this.error(`Credentials file not found at ${credentialsPath}\n` + `Create a profile using 'xano profile create'`);
|
|
131
132
|
}
|
|
132
133
|
try {
|
|
133
134
|
const fileContent = fs.readFileSync(credentialsPath, 'utf8');
|
|
@@ -145,8 +146,8 @@ Downloaded release 'v1.0' to ./release-v1.0.tar.gz
|
|
|
145
146
|
const listUrl = `${profile.instance_origin}/api:meta/workspace/${workspaceId}/release`;
|
|
146
147
|
const response = await this.verboseFetch(listUrl, {
|
|
147
148
|
headers: {
|
|
148
|
-
|
|
149
|
-
|
|
149
|
+
accept: 'application/json',
|
|
150
|
+
Authorization: `Bearer ${profile.access_token}`,
|
|
150
151
|
},
|
|
151
152
|
method: 'GET',
|
|
152
153
|
}, verbose, profile.access_token);
|
|
@@ -154,15 +155,15 @@ Downloaded release 'v1.0' to ./release-v1.0.tar.gz
|
|
|
154
155
|
const errorText = await response.text();
|
|
155
156
|
this.error(`Failed to list releases: ${response.status} ${response.statusText}\n${errorText}`);
|
|
156
157
|
}
|
|
157
|
-
const data = await response.json();
|
|
158
|
+
const data = (await response.json());
|
|
158
159
|
const releases = Array.isArray(data)
|
|
159
160
|
? data
|
|
160
|
-
:
|
|
161
|
+
: data && typeof data === 'object' && 'items' in data && Array.isArray(data.items)
|
|
161
162
|
? data.items
|
|
162
163
|
: [];
|
|
163
|
-
const match = releases.find(r => r.name === releaseName);
|
|
164
|
+
const match = releases.find((r) => r.name === releaseName);
|
|
164
165
|
if (!match) {
|
|
165
|
-
const available = releases.map(r => r.name).join(', ');
|
|
166
|
+
const available = releases.map((r) => r.name).join(', ');
|
|
166
167
|
this.error(`Release '${releaseName}' not found.${available ? ` Available releases: ${available}` : ''}`);
|
|
167
168
|
}
|
|
168
169
|
return match.id;
|
|
@@ -3,7 +3,7 @@ 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
|
-
import BaseCommand from '../../../../base-command.js';
|
|
6
|
+
import BaseCommand, { buildUserAgent } from '../../../../base-command.js';
|
|
7
7
|
export default class TenantBackupExport extends BaseCommand {
|
|
8
8
|
static args = {
|
|
9
9
|
tenant_name: Args.string({
|
|
@@ -84,7 +84,9 @@ Downloaded backup #10 to ./tenant-t1234-abcd-xyz1-backup-10.tar.gz
|
|
|
84
84
|
// Step 2: Download the file
|
|
85
85
|
const outputPath = flags.output || `tenant-${tenantName}-backup-${backupId}.tar.gz`;
|
|
86
86
|
const resolvedPath = path.resolve(outputPath);
|
|
87
|
-
const downloadResponse = await fetch(exportLink.src
|
|
87
|
+
const downloadResponse = await fetch(exportLink.src, {
|
|
88
|
+
headers: { 'User-Agent': buildUserAgent(this.config.version) },
|
|
89
|
+
});
|
|
88
90
|
if (!downloadResponse.ok) {
|
|
89
91
|
this.error(`Failed to download backup: ${downloadResponse.status} ${downloadResponse.statusText}`);
|
|
90
92
|
}
|
|
@@ -4,7 +4,7 @@ import * as fs from 'node:fs';
|
|
|
4
4
|
import * as os from 'node:os';
|
|
5
5
|
import * as path from 'node:path';
|
|
6
6
|
import snakeCase from 'lodash.snakecase';
|
|
7
|
-
import BaseCommand from '../../../../base-command.js';
|
|
7
|
+
import BaseCommand, { buildUserAgent } from '../../../../base-command.js';
|
|
8
8
|
import { buildApiGroupFolderResolver, parseDocument } from '../../../../utils/document-parser.js';
|
|
9
9
|
export default class GitPull extends BaseCommand {
|
|
10
10
|
static args = {
|
|
@@ -175,7 +175,7 @@ export default class GitPull extends BaseCommand {
|
|
|
175
175
|
const apiUrl = `https://api.github.com/repos/${owner}/${repo}/tarball/${tarballRef}`;
|
|
176
176
|
const headers = {
|
|
177
177
|
Accept: 'application/vnd.github+json',
|
|
178
|
-
'User-Agent':
|
|
178
|
+
'User-Agent': buildUserAgent(this.config.version),
|
|
179
179
|
};
|
|
180
180
|
if (token) {
|
|
181
181
|
headers.Authorization = `Bearer ${token}`;
|