@xano/cli 0.0.65 → 0.0.67
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 +29 -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 +44 -22
- 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/profile/workspace/set/index.d.ts +11 -0
- package/dist/commands/profile/workspace/set/index.js +87 -0
- 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 +1368 -1281
- package/package.json +1 -1
|
@@ -27,6 +27,12 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
27
27
|
`,
|
|
28
28
|
`$ xano profile:edit --remove-branch
|
|
29
29
|
Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
30
|
+
`,
|
|
31
|
+
`$ xano profile:edit --insecure
|
|
32
|
+
Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
33
|
+
`,
|
|
34
|
+
`$ xano profile:edit --remove-insecure
|
|
35
|
+
Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
30
36
|
`,
|
|
31
37
|
];
|
|
32
38
|
static flags = {
|
|
@@ -46,6 +52,11 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
46
52
|
description: 'Update branch name',
|
|
47
53
|
required: false,
|
|
48
54
|
}),
|
|
55
|
+
insecure: Flags.boolean({
|
|
56
|
+
default: false,
|
|
57
|
+
description: 'Enable insecure mode (skip TLS certificate verification)',
|
|
58
|
+
required: false,
|
|
59
|
+
}),
|
|
49
60
|
instance_origin: Flags.string({
|
|
50
61
|
char: 'i',
|
|
51
62
|
description: 'Update instance origin URL',
|
|
@@ -56,6 +67,11 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
56
67
|
description: 'Remove branch from profile',
|
|
57
68
|
required: false,
|
|
58
69
|
}),
|
|
70
|
+
'remove-insecure': Flags.boolean({
|
|
71
|
+
default: false,
|
|
72
|
+
description: 'Remove insecure mode from profile',
|
|
73
|
+
required: false,
|
|
74
|
+
}),
|
|
59
75
|
'remove-workspace': Flags.boolean({
|
|
60
76
|
default: false,
|
|
61
77
|
description: 'Remove workspace from profile',
|
|
@@ -102,8 +118,10 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
102
118
|
flags.access_token ||
|
|
103
119
|
flags.workspace ||
|
|
104
120
|
flags.branch ||
|
|
121
|
+
flags.insecure ||
|
|
105
122
|
flags['remove-workspace'] ||
|
|
106
|
-
flags['remove-branch']
|
|
123
|
+
flags['remove-branch'] ||
|
|
124
|
+
flags['remove-insecure'];
|
|
107
125
|
if (!hasFlags) {
|
|
108
126
|
this.error('No fields specified to update. Use at least one flag to edit the profile.');
|
|
109
127
|
}
|
|
@@ -115,6 +133,7 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
115
133
|
...(flags.access_token !== undefined && { access_token: flags.access_token }),
|
|
116
134
|
...(flags.workspace !== undefined && { workspace: flags.workspace }),
|
|
117
135
|
...(flags.branch !== undefined && { branch: flags.branch }),
|
|
136
|
+
...(flags.insecure && { insecure: true }),
|
|
118
137
|
};
|
|
119
138
|
// Handle removal flags
|
|
120
139
|
if (flags['remove-workspace']) {
|
|
@@ -123,6 +142,9 @@ Profile 'default' updated successfully at ~/.xano/credentials.yaml
|
|
|
123
142
|
if (flags['remove-branch']) {
|
|
124
143
|
delete updatedProfile.branch;
|
|
125
144
|
}
|
|
145
|
+
if (flags['remove-insecure']) {
|
|
146
|
+
delete updatedProfile.insecure;
|
|
147
|
+
}
|
|
126
148
|
credentials.profiles[profileName] = updatedProfile;
|
|
127
149
|
// Write the updated credentials back to the file
|
|
128
150
|
try {
|
|
@@ -3,10 +3,12 @@ export default class ProfileWizard extends Command {
|
|
|
3
3
|
static description: string;
|
|
4
4
|
static examples: string[];
|
|
5
5
|
static flags: {
|
|
6
|
+
insecure: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
6
7
|
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
8
|
origin: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
9
|
};
|
|
9
10
|
run(): Promise<void>;
|
|
11
|
+
private getHeaders;
|
|
10
12
|
private fetchBranches;
|
|
11
13
|
private fetchInstances;
|
|
12
14
|
private fetchWorkspaces;
|
|
@@ -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) {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import BaseCommand from '../../../../base-command.js';
|
|
2
|
+
export default class ProfileWorkspaceSet extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
profile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
private fetchWorkspaces;
|
|
11
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
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, { buildUserAgent } from '../../../../base-command.js';
|
|
7
|
+
export default class ProfileWorkspaceSet extends BaseCommand {
|
|
8
|
+
static description = 'Interactively select a workspace for a profile';
|
|
9
|
+
static examples = [
|
|
10
|
+
`$ xano profile workspace set
|
|
11
|
+
Fetching workspaces...
|
|
12
|
+
? Select a workspace: My Workspace
|
|
13
|
+
Workspace updated to 'My Workspace' (abc123) on profile 'default'
|
|
14
|
+
`,
|
|
15
|
+
`$ xano profile workspace set -p production
|
|
16
|
+
Fetching workspaces...
|
|
17
|
+
? Select a workspace: Production API
|
|
18
|
+
Workspace updated to 'Production API' (xyz789) on profile 'production'
|
|
19
|
+
`,
|
|
20
|
+
];
|
|
21
|
+
static flags = {
|
|
22
|
+
...BaseCommand.baseFlags,
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { flags } = await this.parse(ProfileWorkspaceSet);
|
|
26
|
+
const profileName = flags.profile || this.getDefaultProfile();
|
|
27
|
+
const credentials = this.loadCredentialsFile();
|
|
28
|
+
if (!credentials) {
|
|
29
|
+
this.error("Credentials file not found. Create a profile first using 'xano auth'.");
|
|
30
|
+
}
|
|
31
|
+
if (!(profileName in credentials.profiles)) {
|
|
32
|
+
this.error(`Profile '${profileName}' not found. Available profiles: ${Object.keys(credentials.profiles).join(', ')}`);
|
|
33
|
+
}
|
|
34
|
+
const profile = credentials.profiles[profileName];
|
|
35
|
+
this.log('Fetching workspaces...');
|
|
36
|
+
const workspaces = await this.fetchWorkspaces(profile.access_token, profile.instance_origin);
|
|
37
|
+
if (workspaces.length === 0) {
|
|
38
|
+
this.error('No workspaces found on this instance.');
|
|
39
|
+
}
|
|
40
|
+
const { selectedWorkspace } = await inquirer.prompt([
|
|
41
|
+
{
|
|
42
|
+
choices: workspaces.map((ws) => ({
|
|
43
|
+
name: String(ws.id) === String(profile.workspace) ? `${ws.name} (current)` : ws.name,
|
|
44
|
+
value: ws.id,
|
|
45
|
+
})),
|
|
46
|
+
message: 'Select a workspace',
|
|
47
|
+
name: 'selectedWorkspace',
|
|
48
|
+
type: 'select',
|
|
49
|
+
},
|
|
50
|
+
]);
|
|
51
|
+
profile.workspace = selectedWorkspace;
|
|
52
|
+
credentials.profiles[profileName] = profile;
|
|
53
|
+
const credentialsPath = path.join(os.homedir(), '.xano', 'credentials.yaml');
|
|
54
|
+
const yamlContent = yaml.dump(credentials, {
|
|
55
|
+
indent: 2,
|
|
56
|
+
lineWidth: -1,
|
|
57
|
+
noRefs: true,
|
|
58
|
+
});
|
|
59
|
+
fs.writeFileSync(credentialsPath, yamlContent, 'utf8');
|
|
60
|
+
const selected = workspaces.find((ws) => ws.id === selectedWorkspace);
|
|
61
|
+
this.log(`Workspace updated to '${selected?.name}' (${selectedWorkspace}) on profile '${profileName}'`);
|
|
62
|
+
}
|
|
63
|
+
async fetchWorkspaces(accessToken, origin) {
|
|
64
|
+
const response = await fetch(`${origin}/api:meta/workspace`, {
|
|
65
|
+
headers: {
|
|
66
|
+
'User-Agent': buildUserAgent(this.config.version),
|
|
67
|
+
accept: 'application/json',
|
|
68
|
+
Authorization: `Bearer ${accessToken}`,
|
|
69
|
+
},
|
|
70
|
+
method: 'GET',
|
|
71
|
+
});
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
if (response.status === 401) {
|
|
74
|
+
this.error('Unauthorized. Your access token may be expired. Re-authenticate with "xano auth".');
|
|
75
|
+
}
|
|
76
|
+
this.error(`Failed to fetch workspaces (status ${response.status})`);
|
|
77
|
+
}
|
|
78
|
+
const data = (await response.json());
|
|
79
|
+
if (Array.isArray(data)) {
|
|
80
|
+
return data.map((ws) => ({
|
|
81
|
+
id: ws.id || ws.name,
|
|
82
|
+
name: ws.name,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -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}`;
|