insta 0.0.56 → 0.0.57

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.
@@ -1,4 +1,5 @@
1
1
  import { ApiClient, requireProject } from '../api.js';
2
+ import { pgBadge } from './services.js';
2
3
  import { info, printJson } from '../util.js';
3
4
  /**
4
5
  * The label that names WHERE a resource runs.
@@ -21,7 +22,9 @@ export function resourceLabel(r) {
21
22
  // One `manifest` resource line. Pure, so the label is unit-tested without a network mock.
22
23
  export function resourceLine(r) {
23
24
  const where = r.ref?.url ?? r.ref?.bucket ?? r.ref?.neonProjectId ?? '';
24
- return ` - ${resourceLabel(r)} ${where} [${r.status}]`;
25
+ // Database rows only: the platform stamps ref.pgVersion on insta-db (and legacy neon) resources.
26
+ const pg = r.kind === 'insta-db' || r.kind === 'neon' ? pgBadge(r.ref?.pgVersion) : '';
27
+ return ` - ${resourceLabel(r)} ${where}${pg} [${r.status}]`;
25
28
  }
26
29
  // Agent-legible view of each environment's databases / storage / compute.
27
30
  export async function manifest(opts) {
@@ -118,10 +118,7 @@ export async function servicesAdd(type, name, opts = {}) {
118
118
  if (opts.json)
119
119
  return printJson(res.body.service);
120
120
  const svc = res.body.service;
121
- const access = svc.type === 'storage' ? ` [${svc.public ? 'public' : 'private'}]` : '';
122
- const img = svc.image ? ` running ${svc.image}${svc.port ? `:${svc.port}` : ''}` : '';
123
- const vol = svc.volume_gib ? ` vol ${svc.volume_gib}Gi at /data` : '';
124
- info(`added ${type} service ${name} on ${branch ?? 'default'} (${svc.id})${access}${svc.region ? ` ${svc.region}` : ''}${img}${vol}${svc.domain ? ` — ${svc.domain}` : ''}`);
121
+ info(serviceAddedLine(type, name, branch, svc));
125
122
  // Discoverability: the DB is directly dialable, but its DSN is deliberately absent from the
126
123
  // general `insta secrets` bundle — without this line nothing in the product says how to reach it.
127
124
  if (type === 'postgres') {
@@ -132,13 +129,32 @@ export async function servicesAdd(type, name, opts = {}) {
132
129
  }
133
130
  renderNextActions(res.body.nextActions);
134
131
  }
132
+ // The `services add` success line. Pure, so the badge's placement is unit-tested: a template string
133
+ // nothing asserts on silently loses a segment.
134
+ export function serviceAddedLine(type, name, branch, svc) {
135
+ const access = svc.type === 'storage' ? ` [${svc.public ? 'public' : 'private'}]` : '';
136
+ const img = svc.image ? ` running ${svc.image}${svc.port ? `:${svc.port}` : ''}` : '';
137
+ const vol = svc.volume_gib ? ` vol ${svc.volume_gib}Gi at /data` : '';
138
+ // The major belongs next to the connect hint: it decides which psql/pg_dump to reach for.
139
+ const pg = svc.type === 'postgres' ? pgBadge(svc.pg_version) : '';
140
+ return `added ${type} service ${name} on ${branch ?? 'default'} (${svc.id})${access}${svc.region ? ` ${svc.region}` : ''}${img}${vol}${pg}${svc.domain ? ` — ${svc.domain}` : ''}`;
141
+ }
142
+ // ` pg <major>` for a postgres row, or '' when the platform sent nothing usable. The field arrives
143
+ // as untyped API JSON: only a positive integer renders, so a malformed or nonsense value (true,
144
+ // '16', 16.4, 0, -1) can never print as a version an agent would pick tooling by.
145
+ export function pgBadge(v) {
146
+ return typeof v === 'number' && Number.isInteger(v) && v > 0 ? ` pg ${v}` : '';
147
+ }
135
148
  // Render one `services list` row. Pure, so it's unit-tested without a network mock (mirrors
136
149
  // billingLines in billing.ts). Compute rows show the running image when the platform reports one.
137
150
  export function serviceListLine(s) {
138
151
  const extra = s.type === 'compute'
139
152
  ? ` x${s.machine_count}${s.volume_gib ? ` vol ${s.volume_gib}Gi` : ''}${s.image ? ` running ${s.image}${s.port ? `:${s.port}` : ''}` : ''}`
140
153
  : ['redis', 'mysql', 'mongodb'].includes(s.type) ? ` tcp/${s.port ?? defaultDatabasePort(s.type)}${s.volume_gib ? ` vol ${s.volume_gib}Gi` : ''}`
141
- : s.type === 'storage' ? ` ${s.public ? 'public' : 'private'}` : '';
154
+ : s.type === 'storage' ? ` ${s.public ? 'public' : 'private'}`
155
+ // Postgres major, so the reader picks matching pg_dump/psql BEFORE connecting (a newer client
156
+ // dumps statements an older server cannot restore). Older platforms send no pg_version.
157
+ : s.type === 'postgres' ? pgBadge(s.pg_version) : '';
142
158
  return `${s.type}/${s.name} [${s.status}]${extra}${s.domain ? ` ${s.domain}` : ''} ${s.id}`;
143
159
  }
144
160
  export async function servicesList(opts) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "insta",
3
- "version": "0.0.56",
3
+ "version": "0.0.57",
4
4
  "type": "module",
5
5
  "description": "InstaCloud CLI — a thin client of the platform control-plane API.",
6
6
  "keywords": [