insta 0.0.52 → 0.0.53

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.
@@ -26,12 +26,15 @@ export function templateListLines(templates) {
26
26
  }
27
27
  // The info endpoint may list services as an array or keep the manifest's map shape — render both.
28
28
  export function normalizeInfoServices(raw) {
29
- if (Array.isArray(raw)) {
30
- return raw.map((s) => ({ name: s.name ?? '?', type: s.type, port: s.port, volumeGib: s.volumeGib ?? s.volume?.size }));
31
- }
32
- if (raw && typeof raw === 'object') {
33
- return Object.entries(raw).map(([name, s]) => ({ name, type: s?.type, port: s?.port, volumeGib: s?.volumeGib ?? s?.volume?.size }));
34
- }
29
+ const one = (name, s) => ({
30
+ name, type: s?.type, port: s?.port,
31
+ volumeGib: s?.volumeGib ?? s?.volume?.size,
32
+ volume: s?.volume === true || s?.volumeGib != null || s?.volume?.size != null,
33
+ });
34
+ if (Array.isArray(raw))
35
+ return raw.map((s) => one(s?.name ?? '?', s));
36
+ if (raw && typeof raw === 'object')
37
+ return Object.entries(raw).map(([name, s]) => one(name, s));
35
38
  return [];
36
39
  }
37
40
  // Variables may arrive as one array with a `required` flag, or pre-grouped {required, optional}
@@ -64,7 +67,10 @@ export function templateInfoLines(t, bold = (s) => s) {
64
67
  const services = normalizeInfoServices(t.services);
65
68
  if (services.length) {
66
69
  const summary = services.map((s) => {
67
- const bits = [s.type && s.type !== 'compute' ? s.type : undefined, s.port ? `port ${s.port}` : undefined, s.volumeGib ? `${s.volumeGib}Gi volume` : undefined].filter(Boolean);
70
+ // A size only when the registry still carries one: a manifest names no size any more, so
71
+ // "persistent /data" is all there is to say until the service exists.
72
+ const disk = s.volumeGib ? `${s.volumeGib}Gi volume` : s.volume ? 'persistent /data' : undefined;
73
+ const bits = [s.type && s.type !== 'compute' ? s.type : undefined, s.port ? `port ${s.port}` : undefined, disk].filter(Boolean);
68
74
  return `${s.name}${bits.length ? ` (${bits.join(', ')})` : ''}`;
69
75
  });
70
76
  lines.push(`services (${services.length}): ${summary.join(', ')}`);
@@ -103,8 +103,16 @@ export function validateManifest(m) {
103
103
  problems.push(`${where}: web services must declare a healthcheck path`);
104
104
  if (svc.healthcheck && !String(svc.healthcheck).startsWith('/'))
105
105
  problems.push(`${where}: healthcheck must be an absolute path (start with /)`);
106
- if (svc.volume !== undefined && (!Number.isInteger(svc.volume?.size) || svc.volume.size < 1)) {
107
- problems.push(`${where}: volume.size must be a whole Gi ≥ 1, got: ${svc.volume?.size}`);
106
+ // Sizing is the platform's, capped for the org's plan (insta-platform#357). Same answers the
107
+ // publish endpoint gives, said here so an author does not upload to find out. Read as unknown:
108
+ // the type above admits only what is SUPPORTED, and the document is a cast over YAML.parse, so
109
+ // a refused shape arrives as a value that type does not describe.
110
+ const authored = svc;
111
+ if (authored.volume !== undefined && authored.volume !== true) {
112
+ problems.push(`${where}: the volume size is the platform's to choose — declare 'volume: true'`);
113
+ }
114
+ if (authored.spec !== undefined) {
115
+ problems.push(`${where}: compute size is the platform's to choose — remove spec`);
108
116
  }
109
117
  const env = svc.env ?? {};
110
118
  for (const group of ['fixed', 'generated', 'required', 'optional']) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "insta",
3
- "version": "0.0.52",
3
+ "version": "0.0.53",
4
4
  "type": "module",
5
5
  "description": "InstaCloud CLI — a thin client of the platform control-plane API.",
6
6
  "keywords": [