@somewhere-tech/cli 0.31.2 → 0.31.3
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/commands/deploy.js +15 -11
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.js +23 -11
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/errors.js +9 -2
- package/dist/commands/errors.js.map +1 -1
- package/dist/commands/logs.js +9 -2
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/open.js +9 -5
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/project.js +113 -0
- package/dist/commands/project.js.map +1 -1
- package/dist/commands/promote.js +45 -1
- package/dist/commands/promote.js.map +1 -1
- package/dist/commands/rollback.js +12 -1
- package/dist/commands/rollback.js.map +1 -1
- package/dist/commands/status.js +19 -3
- package/dist/commands/status.js.map +1 -1
- package/dist/lib/allowed-origins.js +41 -0
- package/dist/lib/allowed-origins.js.map +1 -0
- package/dist/lib/project-ref.js +34 -0
- package/dist/lib/project-ref.js.map +1 -0
- package/dist/lib/promote-handoff.js +72 -0
- package/dist/lib/promote-handoff.js.map +1 -0
- package/dist/lib/surface-counts.js +87 -0
- package/dist/lib/surface-counts.js.map +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -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.trim()];
|
|
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,IAAI,EAAE,CAAC,CAAC;IAC/B,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"}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@somewhere-tech/cli",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@somewhere-tech/cli",
|
|
9
|
-
"version": "0.31.
|
|
9
|
+
"version": "0.31.3",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"@modelcontextprotocol/sdk",
|
|
12
12
|
"chokidar",
|