insta 0.0.54 → 0.0.56
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/dist/api.js +6 -3
- package/dist/commands/feedback.js +2 -13
- package/dist/commands/services.js +6 -4
- package/dist/commands/template.js +7 -5
- package/dist/index.js +7 -19
- package/dist/version.js +14 -0
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { readGlobal, writeGlobal, readProject, writeProject } from './config.js';
|
|
4
4
|
import { autoResolveProject, promptChoice } from './resolve-project.js';
|
|
5
5
|
import { die } from './util.js';
|
|
6
|
+
import { USER_AGENT } from './version.js';
|
|
6
7
|
export class ApiError extends Error {
|
|
7
8
|
status;
|
|
8
9
|
body;
|
|
@@ -24,8 +25,10 @@ export function storeApiKeyCredential(cfg, token, user) {
|
|
|
24
25
|
}
|
|
25
26
|
export class ApiClient {
|
|
26
27
|
cfg;
|
|
27
|
-
|
|
28
|
+
fetchImpl;
|
|
29
|
+
constructor(cfg, fetchImpl = fetch) {
|
|
28
30
|
this.cfg = cfg;
|
|
31
|
+
this.fetchImpl = fetchImpl;
|
|
29
32
|
}
|
|
30
33
|
static async load() { return new ApiClient(await readGlobal()); }
|
|
31
34
|
get apiUrl() { return this.cfg.apiUrl; }
|
|
@@ -70,10 +73,10 @@ export class ApiClient {
|
|
|
70
73
|
return r;
|
|
71
74
|
}
|
|
72
75
|
async fetch(method, path, body, auth) {
|
|
73
|
-
const headers = { 'Content-Type': 'application/json', 'Insta-Hints': '1' };
|
|
76
|
+
const headers = { 'Content-Type': 'application/json', 'Insta-Hints': '1', 'User-Agent': USER_AGENT };
|
|
74
77
|
if (auth && this.cfg.accessToken)
|
|
75
78
|
headers.Authorization = `Bearer ${this.cfg.accessToken}`;
|
|
76
|
-
const res = await
|
|
79
|
+
const res = await this.fetchImpl(this.apiUrl + path, {
|
|
77
80
|
method,
|
|
78
81
|
headers,
|
|
79
82
|
body: body === undefined ? undefined : JSON.stringify(body),
|
|
@@ -14,6 +14,7 @@ import { readGlobal, readProject } from '../config.js';
|
|
|
14
14
|
import { envForApiUrl } from '../env.js';
|
|
15
15
|
import { info, printJson, CliCancel } from '../util.js';
|
|
16
16
|
import { clean } from '../redact.js';
|
|
17
|
+
import { cliVersion } from '../version.js';
|
|
17
18
|
export const TYPES = ['bug', 'feature-request', 'friction', 'other'];
|
|
18
19
|
export const COMPONENTS = ['cli', 'mcp', 'platform', 'skills', 'docs', 'other'];
|
|
19
20
|
export const SEVERITIES = ['blocker', 'major', 'minor'];
|
|
@@ -42,18 +43,6 @@ const FEEDBACK_INGEST_TOKEN = process.env.INSTA_FEEDBACK_TOKEN || 'insta-feedbac
|
|
|
42
43
|
// An expired deadline is reported as UNCONFIRMED, not failed — the report may well be stored.
|
|
43
44
|
const FEEDBACK_TIMEOUT_MS = 15_000;
|
|
44
45
|
const MAX_FILE_BYTES = 256 * 1024;
|
|
45
|
-
function resolveCliVersion() {
|
|
46
|
-
// Same resolution as index.ts: the standalone binary bakes INSTA_CLI_VERSION via --define;
|
|
47
|
-
// npm/node reads the installed package.json next to dist/.
|
|
48
|
-
if (process.env.INSTA_CLI_VERSION)
|
|
49
|
-
return process.env.INSTA_CLI_VERSION;
|
|
50
|
-
try {
|
|
51
|
-
return JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8')).version;
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return '0.0.0';
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
46
|
function requireEnum(value, allowed, flag) {
|
|
58
47
|
if (!allowed.includes(value)) {
|
|
59
48
|
throw new Error(`${flag} must be one of: ${allowed.join(', ')}`);
|
|
@@ -206,7 +195,7 @@ export async function feedback(opts, deps = {}) {
|
|
|
206
195
|
// transport-failure shapes) instead of guard()'s plaintext stderr line.
|
|
207
196
|
let payload;
|
|
208
197
|
try {
|
|
209
|
-
payload = await buildPayload(opts, { cliVersion: deps.cliVersion ??
|
|
198
|
+
payload = await buildPayload(opts, { cliVersion: deps.cliVersion ?? cliVersion() });
|
|
210
199
|
}
|
|
211
200
|
catch (e) {
|
|
212
201
|
if (!opts.json)
|
|
@@ -16,11 +16,13 @@ export function assertServiceName(name) {
|
|
|
16
16
|
if (!SERVICE_NAME_RE.test(name))
|
|
17
17
|
throw new Error('service name must be lower-kebab (a-z, 0-9, -)');
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
const MAX_COMPUTE_REPLICAS = 10;
|
|
20
|
+
// Parse a replica count inside the compute plane's current safety ceiling.
|
|
20
21
|
export function parseCount(raw) {
|
|
21
22
|
const n = Number(raw);
|
|
22
|
-
if (!Number.isInteger(n) || n < 1)
|
|
23
|
-
throw new Error(`count must be
|
|
23
|
+
if (!Number.isInteger(n) || n < 1 || n > MAX_COMPUTE_REPLICAS) {
|
|
24
|
+
throw new Error(`count must be an integer between 1 and ${MAX_COMPUTE_REPLICAS}, got: ${raw}`);
|
|
25
|
+
}
|
|
24
26
|
return n;
|
|
25
27
|
}
|
|
26
28
|
// Parse a TCP port. Junk fails here rather than reaching the API as NaN (the parseCpu lesson).
|
|
@@ -216,7 +218,7 @@ export async function servicesScale(type, name, number, region, _opts) {
|
|
|
216
218
|
return;
|
|
217
219
|
if (_opts.json)
|
|
218
220
|
return printJson(res.body.service);
|
|
219
|
-
info(`scaled compute ${name} to ${machineCount}
|
|
221
|
+
info(`scaled compute ${name} to ${machineCount} replica(s)${region ? ` in ${region}` : ''}`);
|
|
220
222
|
}
|
|
221
223
|
// insta services upgrade <compute|postgres> <name> <new-spec>
|
|
222
224
|
export async function servicesUpgrade(type, name, spec, _opts) {
|
|
@@ -14,11 +14,13 @@ import { MANIFEST_FILE, collectManifestVariables, loadTemplateManifest } from '.
|
|
|
14
14
|
export function templateListLines(templates) {
|
|
15
15
|
if (!templates.length)
|
|
16
16
|
return ['(no templates published yet)'];
|
|
17
|
-
const head = ['CODE', 'VERSION', 'CATEGORY', '
|
|
17
|
+
const head = ['CODE', 'VERSION', 'CATEGORY', 'PROJECTS', 'SUCCESS', 'NAME'];
|
|
18
18
|
const numeric = [false, false, false, true, true, false];
|
|
19
19
|
const rows = templates.map((t) => [
|
|
20
20
|
t.code, t.version ?? '', t.category ?? '-',
|
|
21
|
-
String(t.
|
|
21
|
+
String(t.totalProjects ?? 0),
|
|
22
|
+
// null = nothing has concluded yet; the platform never sends 0 for that.
|
|
23
|
+
t.successRate == null ? '-' : `${t.successRate}%`,
|
|
22
24
|
t.tagline ? `${t.name} — ${t.tagline}` : (t.name ?? ''),
|
|
23
25
|
]);
|
|
24
26
|
const widths = head.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
|
|
@@ -148,12 +150,12 @@ export async function resolveVariables(vars, given, opts = {}) {
|
|
|
148
150
|
return values;
|
|
149
151
|
}
|
|
150
152
|
// The platform's machine-readable "you forgot these" answer to the POST (error=missing_variables,
|
|
151
|
-
// missing: [{name, key, description}]
|
|
152
|
-
//
|
|
153
|
+
// missing: [{name, key, description}]) — turned back into promptable variables. null = some other
|
|
154
|
+
// error, not ours to interpret.
|
|
153
155
|
export function missingVariablesFrom(body) {
|
|
154
156
|
if ((body?.error ?? body?.code) !== 'missing_variables')
|
|
155
157
|
return null;
|
|
156
|
-
const list = body?.missing ??
|
|
158
|
+
const list = body?.missing ?? [];
|
|
157
159
|
if (!Array.isArray(list))
|
|
158
160
|
return [];
|
|
159
161
|
return list.map((v) => ({ name: String(v.name ?? v.key ?? v), required: true, description: v.description }));
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
3
2
|
import { Command } from 'commander';
|
|
4
3
|
import { ApiError } from './api.js';
|
|
5
4
|
import { CliCancel, CliExit, fail, relayedExitCode } from './util.js';
|
|
6
5
|
import { trackCommand } from './telemetry.js';
|
|
6
|
+
import { cliVersion } from './version.js';
|
|
7
7
|
import * as auth from './commands/auth.js';
|
|
8
8
|
import * as envCmd_ from './commands/env.js';
|
|
9
9
|
import { ENV_NAMES } from './env.js';
|
|
@@ -52,7 +52,7 @@ const guard = (fn) => async (...a) => {
|
|
|
52
52
|
}
|
|
53
53
|
await trackCommand(a[a.length - 1], a.slice(0, -2), {
|
|
54
54
|
error, durationMs: Date.now() - started, exitCode: Number(process.exitCode ?? 0), childExitCode: relayedExitCode(),
|
|
55
|
-
},
|
|
55
|
+
}, cliVersion());
|
|
56
56
|
};
|
|
57
57
|
const program = new Command();
|
|
58
58
|
// Positional options: some command groups (e.g. `secrets`, `billing`) declare a flag (like
|
|
@@ -63,19 +63,7 @@ const program = new Command();
|
|
|
63
63
|
// group's own options only match before the subcommand name, so occurrences after it are matched
|
|
64
64
|
// against the subcommand's own (identically-named) option instead.
|
|
65
65
|
program.enablePositionalOptions();
|
|
66
|
-
|
|
67
|
-
// the installed package.json (npm/node — ../package.json sits beside dist/) → 0.0.0.
|
|
68
|
-
function resolveVersion() {
|
|
69
|
-
if (process.env.INSTA_CLI_VERSION)
|
|
70
|
-
return process.env.INSTA_CLI_VERSION;
|
|
71
|
-
try {
|
|
72
|
-
return JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
|
|
73
|
-
}
|
|
74
|
-
catch {
|
|
75
|
-
return '0.0.0';
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
program.name('insta').description('InstaCloud CLI — manage projects, branches, secrets, deploys').version(resolveVersion());
|
|
66
|
+
program.name('insta').description('InstaCloud CLI — manage projects, branches, secrets, deploys').version(cliVersion());
|
|
79
67
|
// ---- auth ----
|
|
80
68
|
program.command('login').description('Log in — bare: sign in from your browser (any account type); or --email <email> + password, --oauth <github|google>, --device (headless), --api-key <insta_…> (headless, durable token)')
|
|
81
69
|
.option('--email <email>', 'account email (email + password login)')
|
|
@@ -160,7 +148,7 @@ svc.command('rename <type> <name> <new-name>').description('Rename a service and
|
|
|
160
148
|
.action(guard((type, name, newName, o) => services.servicesRename(type, name, newName, o)));
|
|
161
149
|
svc.command('set-access <type> <name> <access>').description('Set a storage service bucket access mode (access: public|private)')
|
|
162
150
|
.option('--json').action(guard((type, name, access, o) => services.servicesSetAccess(type, name, access, o)));
|
|
163
|
-
svc.command('scale <type> <name> <number> [region]').description('Set a compute service
|
|
151
|
+
svc.command('scale <type> <name> <number> [region]').description('Set a compute service same-region replica count from 1 to 10 (paid plans only)')
|
|
164
152
|
.option('--json').option('--branch <branch>', 'branch (default: current)').action(guard((type, name, number, region, o) => services.servicesScale(type, name, number, region, o)));
|
|
165
153
|
svc.command('upgrade <type> <name> <spec>').description('Change a compute service spec (paid plans only). Postgres upgrades are rejected by the platform — use `insta db limits` instead')
|
|
166
154
|
.option('--json').option('--branch <branch>', 'branch (default: current)').action(guard((type, name, spec, o) => services.servicesUpgrade(type, name, spec, o)));
|
|
@@ -366,10 +354,10 @@ program.command('feedback')
|
|
|
366
354
|
.action(guard((o) => feedbackCmd.feedback(o)));
|
|
367
355
|
// ---- self-update ----
|
|
368
356
|
program.command('upgrade').description('Update the insta CLI to the latest release (binary or npm install)')
|
|
369
|
-
.action(guard(() => selfUpdate.upgrade(
|
|
357
|
+
.action(guard(() => selfUpdate.upgrade(cliVersion())));
|
|
370
358
|
program.command('autoupdate [mode]').description('Show or set auto-update: on | off (default: on while pre-1.0)')
|
|
371
359
|
.action(guard((mode) => selfUpdate.autoupdate(mode)));
|
|
372
|
-
program.command('__update-check', { hidden: true }).action(guard(() => selfUpdate.backgroundCheck(
|
|
373
|
-
selfUpdate.maybeUpdate(
|
|
360
|
+
program.command('__update-check', { hidden: true }).action(guard(() => selfUpdate.backgroundCheck(cliVersion())));
|
|
361
|
+
selfUpdate.maybeUpdate(cliVersion(), process.argv);
|
|
374
362
|
program.parseAsync(computeArgv);
|
|
375
363
|
//# sourceMappingURL=index.js.map
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
// bun build --define bakes INSTA_CLI_VERSION into the standalone binary, which has no package.json to read.
|
|
3
|
+
export function cliVersion() {
|
|
4
|
+
if (process.env.INSTA_CLI_VERSION)
|
|
5
|
+
return process.env.INSTA_CLI_VERSION;
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return '0.0.0';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export const USER_AGENT = `insta-cli/${cliVersion()}`;
|
|
14
|
+
//# sourceMappingURL=version.js.map
|