@somewhere-tech/cli 0.31.2 → 0.31.4

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.
@@ -0,0 +1,72 @@
1
+ /**
2
+ * The promote command the CLI hands back, and the two things it must say after
3
+ * a promote lands.
4
+ *
5
+ * Both come out of the same parity run:
6
+ *
7
+ * - The printed promote command could not be run in the shell that printed it.
8
+ * `somewhere preview` and `somewhere status` printed
9
+ * `somewhere promote <session> <preview>`; `somewhere promote` then refuses
10
+ * that exact command with "Refusing to promote without confirmation in a
11
+ * non-interactive shell" — so the one context where the hosted loop is the
12
+ * only way to see the app (an agent, a script, a piped terminal) is the one
13
+ * context where the CLI's own output does not work.
14
+ *
15
+ * - Promotion moved the app and said nothing about the data. Preview rows stay
16
+ * in the preview database; that isolation is the point, but a developer who
17
+ * is not told rediscovers it by opening an empty production page and
18
+ * repeating the whole acceptance pass.
19
+ *
20
+ * Pure so both directions can be fixtured without a network or a terminal.
21
+ */
22
+ /**
23
+ * The promote command for a given shell.
24
+ *
25
+ * Non-interactive: one line, with `--yes`, because there is nobody to answer a
26
+ * prompt and a command that cannot run is not a handoff.
27
+ *
28
+ * Interactive: the plain command first — a person at a keyboard should get the
29
+ * confirmation, not be handed an unattended promote they did not ask for — and
30
+ * the `--yes` form named after it, so the same output is still useful when it
31
+ * is scrolled back to from a script.
32
+ */
33
+ export function promoteCommands(args) {
34
+ const base = `somewhere promote ${args.previewSessionId} ${args.previewId}`;
35
+ if (!args.interactive)
36
+ return [`${base} --yes`];
37
+ return [base, `${base} --yes`];
38
+ }
39
+ /** The single command to print when only one line fits. Always runnable here. */
40
+ export function promoteCommandForShell(args) {
41
+ const commands = promoteCommands(args);
42
+ return commands[0];
43
+ }
44
+ /** The label for each printed variant, so two lines are not two mysteries. */
45
+ export function promoteCommandLines(args) {
46
+ const commands = promoteCommands(args);
47
+ if (commands.length === 1)
48
+ return [`promote command: \`${commands[0]}\``];
49
+ return [
50
+ `promote command: \`${commands[0]}\``,
51
+ `without the confirmation (scripts, agents): \`${commands[1]}\``,
52
+ ];
53
+ }
54
+ /**
55
+ * What a developer needs to know about their data the moment production
56
+ * changes.
57
+ *
58
+ * The platform is adding a field that says this in its own words; when it
59
+ * sends one, that wins, so the sentence can be corrected without waiting for a
60
+ * CLI release. Until then the CLI says it from what it already knows, because
61
+ * a line that waits on a deploy is a line nobody reads.
62
+ */
63
+ export function promotedDataNotes(platformNote) {
64
+ if (typeof platformNote === 'string' && platformNote.trim()) {
65
+ return [platformNote];
66
+ }
67
+ return [
68
+ 'Only the app was promoted. Rows you created while previewing stayed in the preview database — production is serving the data it already had.',
69
+ 'Open production and check it end to end, and seed anything it needs, before you call this shipped.',
70
+ ];
71
+ }
72
+ //# sourceMappingURL=promote-handoff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promote-handoff.js","sourceRoot":"","sources":["../../src/lib/promote-handoff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,IAI/B;IACC,MAAM,IAAI,GAAG,qBAAqB,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;IAC5E,IAAI,CAAC,IAAI,CAAC,WAAW;QAAE,OAAO,CAAC,GAAG,IAAI,QAAQ,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,sBAAsB,CAAC,IAItC;IACC,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,mBAAmB,CAAC,IAInC;IACC,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,sBAAsB,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC1E,OAAO;QACL,sBAAsB,QAAQ,CAAC,CAAC,CAAC,IAAI;QACrC,iDAAiD,QAAQ,CAAC,CAAC,CAAC,IAAI;KACjE,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAsB;IACtD,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5D,OAAO,CAAC,YAAY,CAAC,CAAC;IACxB,CAAC;IACD,OAAO;QACL,8IAA8I;QAC9I,oGAAoG;KACrG,CAAC;AACJ,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * How many files, said the same way everywhere.
3
+ *
4
+ * One project used to get three different answers out of one CLI: `somewhere
5
+ * deploy` said "2 static file(s) + 1 function(s)", `somewhere preview` said
6
+ * "Synced 3 files" with the function invisible inside the number, and
7
+ * `somewhere promote` said "3 files + functions" with the count of functions
8
+ * replaced by the word. A developer reading all three cannot tell whether the
9
+ * app grew, whether the function shipped, or which number to trust — which is
10
+ * exactly what happened in the parity run that produced this module.
11
+ *
12
+ * The shape, everywhere: `3 static files + 1 function`. Two nouns, two
13
+ * numbers, no parenthesised plurals.
14
+ *
15
+ * The counting rule, everywhere: static = the pages, scripts, styles and
16
+ * assets that make up the site; functions = the api/ handlers, counted
17
+ * separately because they are the half a boolean used to hide. It is the same
18
+ * split the project itself reports, so the CLI's number and the project's
19
+ * number are the same number.
20
+ *
21
+ * Pure and dependency-free so both directions can be fixtured without a
22
+ * network.
23
+ */
24
+ /** A count with its noun, singular or plural — never `file(s)`. */
25
+ function plural(count, one, many) {
26
+ return `${count} ${count === 1 ? one : many}`;
27
+ }
28
+ /**
29
+ * The one phrase. Renders as many of the two halves as are actually known:
30
+ *
31
+ * { staticFiles: 3, functions: 1 } → `3 static files + 1 function`
32
+ * { staticFiles: 3, functions: 0 } → `3 static files`
33
+ * { staticFiles: 1, functions: 2 } → `1 static file + 2 functions`
34
+ * { staticFiles: 3, functions: 'some' } → `3 static files + functions`
35
+ * { staticFiles: null, functions: 1 } → `1 function`
36
+ * { staticFiles: null, functions: null} → `Files`
37
+ *
38
+ * A zero function count prints nothing rather than "+ 0 functions": a static
39
+ * site saying it has no backend on every line is noise, and the absence is
40
+ * already the answer.
41
+ */
42
+ export function formatPublishSurface(counts) {
43
+ const parts = [];
44
+ if (counts.staticFiles !== null) {
45
+ parts.push(plural(counts.staticFiles, 'static file', 'static files'));
46
+ }
47
+ if (counts.functions === 'some') {
48
+ parts.push('functions');
49
+ }
50
+ else if (typeof counts.functions === 'number') {
51
+ // Zero is suppressed only as a TAIL: "3 static files + 0 functions" is
52
+ // noise on a static site, but a functions-only deploy that moved nothing
53
+ // still has to say so rather than fall through to a bare noun.
54
+ if (counts.functions > 0 || parts.length === 0) {
55
+ parts.push(plural(counts.functions, 'function', 'functions'));
56
+ }
57
+ }
58
+ if (parts.length === 0)
59
+ return 'Files';
60
+ return parts.join(' + ');
61
+ }
62
+ /**
63
+ * Count a collected publish surface the way the project does.
64
+ *
65
+ * Binary assets are static files — an image is as much part of the site as the
66
+ * page that shows it, and splitting them out is an implementation detail of how
67
+ * the CLI reads them off disk, not something a developer asked about.
68
+ */
69
+ export function countPublishSurface(collected) {
70
+ return {
71
+ staticFiles: Object.keys(collected.files).length + Object.keys(collected.binaryFiles ?? {}).length,
72
+ functions: Object.keys(collected.functions ?? {}).length,
73
+ };
74
+ }
75
+ /**
76
+ * A count the platform sent, when it sent one. Anything that is not a finite
77
+ * number is not a count — `null` (unknown) is honest and renders as an absence,
78
+ * where `0` would be a claim.
79
+ */
80
+ export function countFromResponse(value) {
81
+ if (typeof value === 'number' && Number.isFinite(value))
82
+ return value;
83
+ if (Array.isArray(value))
84
+ return value.length;
85
+ return null;
86
+ }
87
+ //# sourceMappingURL=surface-counts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface-counts.js","sourceRoot":"","sources":["../../src/lib/surface-counts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAYH,mEAAmE;AACnE,SAAS,MAAM,CAAC,KAAa,EAAE,GAAW,EAAE,IAAY;IACtD,OAAO,GAAG,KAAK,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA4B;IAC/D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC;SAAM,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QAChD,uEAAuE;QACvE,yEAAyE;QACzE,+DAA+D;QAC/D,IAAI,MAAM,CAAC,SAAS,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACvC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAInC;IACC,OAAO;QACL,WAAW,EACT,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,MAAM;QACvF,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM;KACzD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,MAAM,CAAC;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@somewhere-tech/cli",
3
- "version": "0.31.2",
3
+ "version": "0.31.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@somewhere-tech/cli",
9
- "version": "0.31.2",
9
+ "version": "0.31.4",
10
10
  "bundleDependencies": [
11
11
  "@modelcontextprotocol/sdk",
12
12
  "chokidar",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@somewhere-tech/cli",
3
- "version": "0.31.2",
3
+ "version": "0.31.4",
4
4
  "description": "CLI for somewhere.tech — auth, projects, deploy, pull, promote, db, logs, env, MCP bridge.",
5
5
  "keywords": [
6
6
  "somewhere",