neonctl 1.23.3 → 1.24.2
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/callback.html +134 -40
- package/commands/branches.js +40 -0
- package/commands/branches.test.js +14 -0
- package/commands/set_context.js +1 -3
- package/commands/set_context.test.js +24 -1
- package/context.js +1 -1
- package/index.js +10 -2
- package/package.json +8 -4
- package/test_utils/test_cli_command.js +7 -1
- package/utils/formats.js +1 -1
- package/utils/formats.test.js +32 -0
package/callback.html
CHANGED
|
@@ -1,45 +1,139 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8"
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
5
|
<title>Neon</title>
|
|
6
|
-
<style>
|
|
7
|
-
body,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
6
|
+
<style>
|
|
7
|
+
body,
|
|
8
|
+
html {
|
|
9
|
+
width: 100%;
|
|
10
|
+
height: 100%;
|
|
11
|
+
margin: 0;
|
|
12
|
+
text-align: center;
|
|
13
|
+
font-family: 'Open Sans', sans-serif;
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
align-items: center;
|
|
18
|
+
background-color: #ffffff;
|
|
19
|
+
color: #2d374c;
|
|
20
|
+
}
|
|
21
|
+
@media (prefers-color-scheme: dark) {
|
|
22
|
+
body,
|
|
23
|
+
html {
|
|
24
|
+
background-color: #191919;
|
|
25
|
+
color: #bfbfbf;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
.logo {
|
|
29
|
+
display: inline-block;
|
|
30
|
+
width: 100px;
|
|
31
|
+
height: 100px;
|
|
32
|
+
margin: 0 auto;
|
|
33
|
+
}
|
|
34
|
+
svg {
|
|
35
|
+
overflow: visible;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
38
|
+
</head>
|
|
39
|
+
<body>
|
|
38
40
|
<div class="logo">
|
|
39
|
-
<svg
|
|
41
|
+
<svg
|
|
42
|
+
id="eBsErktH1941"
|
|
43
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
44
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
45
|
+
viewBox="0 0 42 42"
|
|
46
|
+
shape-rendering="geometricPrecision"
|
|
47
|
+
text-rendering="geometricPrecision"
|
|
48
|
+
>
|
|
49
|
+
<style>
|
|
50
|
+
<![CDATA[#eBsErktH1945 {animation: eBsErktH1945__fl 3000ms linear infinite normal forwards}@keyframes eBsErktH1945__fl { 0% {filter: drop-shadow(0px 0px 0px #5cff61)} 13.666667% {filter: drop-shadow(0px 0px 0px #5cff61)} 15% {filter: drop-shadow(0px 0px 4.242641px #5cff61)} 34% {filter: drop-shadow(0px 0px 4.242641px #5cff61)} 34.333333% {filter: drop-shadow(0px 0px 0px #5cff61)} 37.333333% {filter: drop-shadow(0px 0px 0px #5cff61)} 37.666667% {filter: drop-shadow(0px 0px 4.242641px #5cff61)} 43.666667% {filter: drop-shadow(0px 0px 4.242641px #5cff61)} 44% {filter: drop-shadow(0px 0px 0px #5cff61)} 47% {filter: drop-shadow(0px 0px 0px #5cff61)} 47.333333% {filter: drop-shadow(0px 0px 4.242641px #5cff61)} 51% {filter: drop-shadow(0px 0px 4.242641px #5cff61)} 51.333333% {filter: drop-shadow(0px 0px 0px #5cff61)} 53.666667% {filter: drop-shadow(0px 0px 0px #5cff61)} 54% {filter: drop-shadow(0px 0px 4.242641px #5cff61)} 100% {filter: drop-shadow(0px 0px 4.242641px #5cff61)}} #eBsErktH1946 {animation: eBsErktH1946__fl 3000ms linear infinite normal forwards}@keyframes eBsErktH1946__fl { 0% {filter: drop-shadow(0px 0px 0px #5cff61)} 13.666667% {filter: drop-shadow(0px 0px 0px #5cff61)} 15% {filter: drop-shadow(0px 0px 2.828427px #5cff61)} 34% {filter: drop-shadow(0px 0px 2.828427px #5cff61)} 34.333333% {filter: drop-shadow(0px 0px 0px #5cff61)} 37.333333% {filter: drop-shadow(0px 0px 0px #5cff61)} 37.666667% {filter: drop-shadow(0px 0px 2.828427px #5cff61)} 43.666667% {filter: drop-shadow(0px 0px 2.828427px #5cff61)} 44% {filter: drop-shadow(0px 0px 0px #5cff61)} 47% {filter: drop-shadow(0px 0px 0px #5cff61)} 47.333333% {filter: drop-shadow(0px 0px 2.828427px #5cff61)} 51% {filter: drop-shadow(0px 0px 2.828427px #5cff61)} 51.333333% {filter: drop-shadow(0px 0px 0px #5cff61)} 53.666667% {filter: drop-shadow(0px 0px 0px #5cff61)} 54% {filter: drop-shadow(0px 0px 2.828427px #5cff61)} 100% {filter: drop-shadow(0px 0px 2.828427px #5cff61)}} #eBsErktH1947 {animation: eBsErktH1947__fl 3000ms linear infinite normal forwards}@keyframes eBsErktH1947__fl { 0% {filter: drop-shadow(0px 0px 0px #5cff61)} 13.666667% {filter: drop-shadow(0px 0px 0px #5cff61)} 15% {filter: drop-shadow(0px 0px 1.414214px #5cff61)} 34% {filter: drop-shadow(0px 0px 1.414214px #5cff61)} 34.333333% {filter: drop-shadow(0px 0px 0px #5cff61)} 37.333333% {filter: drop-shadow(0px 0px 0px #5cff61)} 37.666667% {filter: drop-shadow(0px 0px 1.414214px #5cff61)} 43.666667% {filter: drop-shadow(0px 0px 1px #5cff61)} 44% {filter: drop-shadow(0px 0px 0px #5cff61)} 47% {filter: drop-shadow(0px 0px 0px #5cff61)} 47.333333% {filter: drop-shadow(0px 0px 1.414214px #5cff61)} 51% {filter: drop-shadow(0px 0px 1.414214px #5cff61)} 51.333333% {filter: drop-shadow(0px 0px 0px #5cff61)} 53.666667% {filter: drop-shadow(0px 0px 0px #5cff61)} 54% {filter: drop-shadow(0px 0px 1.414214px #5cff61)} 100% {filter: drop-shadow(0px 0px 1.414214px #5cff61)}}]]>
|
|
51
|
+
</style>
|
|
52
|
+
<defs>
|
|
53
|
+
<linearGradient
|
|
54
|
+
id="eBsErktH1943-fill"
|
|
55
|
+
x1="36"
|
|
56
|
+
y1="36"
|
|
57
|
+
x2="4.345"
|
|
58
|
+
y2="0"
|
|
59
|
+
spreadMethod="pad"
|
|
60
|
+
gradientUnits="userSpaceOnUse"
|
|
61
|
+
gradientTransform="translate(0 0)"
|
|
62
|
+
>
|
|
63
|
+
<stop id="eBsErktH1943-fill-0" offset="0%" stop-color="#b9ffb3" />
|
|
64
|
+
<stop
|
|
65
|
+
id="eBsErktH1943-fill-1"
|
|
66
|
+
offset="100%"
|
|
67
|
+
stop-color="rgba(185,255,179,0)"
|
|
68
|
+
/>
|
|
69
|
+
</linearGradient>
|
|
70
|
+
<linearGradient
|
|
71
|
+
id="eBsErktH1944-fill"
|
|
72
|
+
x1="36"
|
|
73
|
+
y1="36"
|
|
74
|
+
x2="14.617"
|
|
75
|
+
y2="27.683"
|
|
76
|
+
spreadMethod="pad"
|
|
77
|
+
gradientUnits="userSpaceOnUse"
|
|
78
|
+
gradientTransform="translate(0 0)"
|
|
79
|
+
>
|
|
80
|
+
<stop
|
|
81
|
+
id="eBsErktH1944-fill-0"
|
|
82
|
+
offset="0%"
|
|
83
|
+
stop-color="rgba(26,26,26,0.9)"
|
|
84
|
+
/>
|
|
85
|
+
<stop
|
|
86
|
+
id="eBsErktH1944-fill-1"
|
|
87
|
+
offset="100%"
|
|
88
|
+
stop-color="rgba(26,26,26,0)"
|
|
89
|
+
/>
|
|
90
|
+
</linearGradient>
|
|
91
|
+
</defs>
|
|
92
|
+
<path
|
|
93
|
+
d="M0,6.207c0-1.646199.65395-3.224973,1.817988-4.389012C2.982026,0.65395,4.560801,0,6.207,0h23.586c1.646199,0,3.224973.65395,4.389012,1.817988s1.817988,2.742813,1.817988,4.389012v20.06c0,3.546-4.488,5.085-6.664,2.286l-6.805-8.754v10.615c0,3.085063-2.500937,5.586-5.586,5.586h-10.738c-1.646199,0-3.224973-.65395-4.389012-1.817988s-1.817988-2.742813-1.817988-4.389012L0,6.207ZM6.207,4.966c-.686,0-1.241.555-1.241,1.24v23.587c0,.686.555,1.242,1.24,1.242h10.925c.343,0,.434-.278.434-.621v-14.234c0-3.547,4.488-5.086,6.665-2.286l6.805,8.753v-16.44c0-.686.064-1.241-.621-1.241h-24.207Z"
|
|
94
|
+
transform="translate(3 3)"
|
|
95
|
+
clip-rule="evenodd"
|
|
96
|
+
fill="#12fff7"
|
|
97
|
+
fill-rule="evenodd"
|
|
98
|
+
/>
|
|
99
|
+
<path
|
|
100
|
+
d="M0,6.207c0-1.646199.65395-3.224973,1.817988-4.389012C2.982026,0.65395,4.560801,0,6.207,0h23.586c1.646199,0,3.224973.65395,4.389012,1.817988s1.817988,2.742813,1.817988,4.389012v20.06c0,3.546-4.488,5.085-6.664,2.286l-6.805-8.754v10.615c0,3.085063-2.500937,5.586-5.586,5.586h-10.738c-1.646199,0-3.224973-.65395-4.389012-1.817988s-1.817988-2.742813-1.817988-4.389012L0,6.207ZM6.207,4.966c-.686,0-1.241.555-1.241,1.24v23.587c0,.686.555,1.242,1.24,1.242h10.925c.343,0,.434-.278.434-.621v-14.234c0-3.547,4.488-5.086,6.665-2.286l6.805,8.753v-16.44c0-.686.064-1.241-.621-1.241h-24.207Z"
|
|
101
|
+
transform="translate(3 3)"
|
|
102
|
+
clip-rule="evenodd"
|
|
103
|
+
fill="url(#eBsErktH1943-fill)"
|
|
104
|
+
fill-rule="evenodd"
|
|
105
|
+
/>
|
|
106
|
+
<path
|
|
107
|
+
d="M0,6.207c0-1.646199.65395-3.224973,1.817988-4.389012C2.982026,0.65395,4.560801,0,6.207,0h23.586c1.646199,0,3.224973.65395,4.389012,1.817988s1.817988,2.742813,1.817988,4.389012v20.06c0,3.546-4.488,5.085-6.664,2.286l-6.805-8.754v10.615c0,3.085063-2.500937,5.586-5.586,5.586h-10.738c-1.646199,0-3.224973-.65395-4.389012-1.817988s-1.817988-2.742813-1.817988-4.389012L0,6.207ZM6.207,4.966c-.686,0-1.241.555-1.241,1.24v23.587c0,.686.555,1.242,1.24,1.242h10.925c.343,0,.434-.278.434-.621v-14.234c0-3.547,4.488-5.086,6.665-2.286l6.805,8.753v-16.44c0-.686.064-1.241-.621-1.241h-24.207Z"
|
|
108
|
+
transform="translate(3 3)"
|
|
109
|
+
clip-rule="evenodd"
|
|
110
|
+
fill="url(#eBsErktH1944-fill)"
|
|
111
|
+
fill-rule="evenodd"
|
|
112
|
+
/>
|
|
113
|
+
<path
|
|
114
|
+
id="eBsErktH1945"
|
|
115
|
+
style="filter: drop-shadow(0px 0px 0px #5cff61)"
|
|
116
|
+
d="M29.793,0c1.646199,0,3.224973.65395,4.389012,1.817988s1.817988,2.742813,1.817988,4.389012v20.06c0,3.546-4.488,5.085-6.664,2.286l-6.805-8.754v10.615c0,3.085063-2.500937,5.586-5.586,5.586.342417,0,.62-.277583.62-.62v-19.2c0-3.547,4.488-5.086,6.665-2.286l6.805,8.753v-21.406c0-.685-.556-1.241-1.242-1.241Z"
|
|
117
|
+
transform="translate(3 3)"
|
|
118
|
+
fill="#b9ffb3"
|
|
119
|
+
/>
|
|
120
|
+
<path
|
|
121
|
+
id="eBsErktH1946"
|
|
122
|
+
style="filter: drop-shadow(0px 0px 0px #5cff61)"
|
|
123
|
+
d="M29.793,0c1.646199,0,3.224973.65395,4.389012,1.817988s1.817988,2.742813,1.817988,4.389012v20.06c0,3.546-4.488,5.085-6.664,2.286l-6.805-8.754v10.615c0,3.085063-2.500937,5.586-5.586,5.586.342417,0,.62-.277583.62-.62v-19.2c0-3.547,4.488-5.086,6.665-2.286l6.805,8.753v-21.406c0-.685-.556-1.241-1.242-1.241Z"
|
|
124
|
+
transform="translate(3 3)"
|
|
125
|
+
fill="#b9ffb3"
|
|
126
|
+
/>
|
|
127
|
+
<path
|
|
128
|
+
id="eBsErktH1947"
|
|
129
|
+
style="filter: drop-shadow(0px 0px 0px #5cff61)"
|
|
130
|
+
d="M29.793,0c1.646199,0,3.224973.65395,4.389012,1.817988s1.817988,2.742813,1.817988,4.389012v20.06c0,3.546-4.488,5.085-6.664,2.286l-6.805-8.754v10.615c0,3.085063-2.500937,5.586-5.586,5.586.342417,0,.62-.277583.62-.62v-19.2c0-3.547,4.488-5.086,6.665-2.286l6.805,8.753v-21.406c0-.685-.556-1.241-1.242-1.241Z"
|
|
131
|
+
transform="translate(3 3)"
|
|
132
|
+
fill="#b9ffb3"
|
|
133
|
+
/>
|
|
134
|
+
</svg>
|
|
40
135
|
</div>
|
|
41
136
|
<h1>Thank you for using Neon</h1>
|
|
42
|
-
<p>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
</body>
|
|
137
|
+
<p>You may close this page now</p>
|
|
138
|
+
</body>
|
|
139
|
+
</html>
|
package/commands/branches.js
CHANGED
|
@@ -12,6 +12,13 @@ const BRANCH_FIELDS = [
|
|
|
12
12
|
'created_at',
|
|
13
13
|
'updated_at',
|
|
14
14
|
];
|
|
15
|
+
const BRANCH_FIELDS_RESET = [
|
|
16
|
+
'id',
|
|
17
|
+
'name',
|
|
18
|
+
'primary',
|
|
19
|
+
'created_at',
|
|
20
|
+
'last_reset_at',
|
|
21
|
+
];
|
|
15
22
|
export const command = 'branches';
|
|
16
23
|
export const describe = 'Manage branches';
|
|
17
24
|
export const aliases = ['branch'];
|
|
@@ -56,6 +63,16 @@ export const builder = (argv) => argv
|
|
|
56
63
|
default: false,
|
|
57
64
|
},
|
|
58
65
|
}), async (args) => await create(args))
|
|
66
|
+
.command('reset <id|name>', 'Reset a branch', (yargs) => yargs.options({
|
|
67
|
+
parent: {
|
|
68
|
+
describe: 'Reset to a parent branch',
|
|
69
|
+
type: 'boolean',
|
|
70
|
+
default: false,
|
|
71
|
+
},
|
|
72
|
+
'preserve-under-name': {
|
|
73
|
+
describe: 'Name under which to preserve the old branch',
|
|
74
|
+
},
|
|
75
|
+
}), async (args) => await reset(args))
|
|
59
76
|
.command('rename <id|name> <new-name>', 'Rename a branch', (yargs) => yargs, async (args) => await rename(args))
|
|
60
77
|
.command('set-primary <id|name>', 'Set a branch as primary', (yargs) => yargs, async (args) => await setPrimary(args))
|
|
61
78
|
.command('add-compute <id|name>', 'Add a compute to a branch', (yargs) => yargs.options({
|
|
@@ -194,3 +211,26 @@ const addCompute = async (props) => {
|
|
|
194
211
|
fields: ['id', 'host'],
|
|
195
212
|
});
|
|
196
213
|
};
|
|
214
|
+
const reset = async (props) => {
|
|
215
|
+
if (!props.parent) {
|
|
216
|
+
throw new Error('Only resetting to parent is supported for now');
|
|
217
|
+
}
|
|
218
|
+
const branchId = await branchIdFromProps(props);
|
|
219
|
+
const { data: { branch }, } = await props.apiClient.getProjectBranch(props.projectId, branchId);
|
|
220
|
+
if (!branch.parent_id) {
|
|
221
|
+
throw new Error('Branch has no parent');
|
|
222
|
+
}
|
|
223
|
+
const { data } = await retryOnLock(() => props.apiClient.request({
|
|
224
|
+
method: 'POST',
|
|
225
|
+
path: `/projects/${props.projectId}/branches/${branch.id}/reset`,
|
|
226
|
+
body: {
|
|
227
|
+
source_branch_id: branch.parent_id,
|
|
228
|
+
preserve_under_name: props.preserveUnderName || undefined,
|
|
229
|
+
},
|
|
230
|
+
}));
|
|
231
|
+
const resultBranch = data.branch;
|
|
232
|
+
writer(props).end(resultBranch, {
|
|
233
|
+
// need to reset types until we expose reset api
|
|
234
|
+
fields: BRANCH_FIELDS_RESET,
|
|
235
|
+
});
|
|
236
|
+
};
|
|
@@ -250,4 +250,18 @@ describe('branches', () => {
|
|
|
250
250
|
snapshot: true,
|
|
251
251
|
},
|
|
252
252
|
});
|
|
253
|
+
testCliCommand({
|
|
254
|
+
name: 'reset branch to parent',
|
|
255
|
+
args: [
|
|
256
|
+
'branches',
|
|
257
|
+
'reset',
|
|
258
|
+
'test_branch',
|
|
259
|
+
'--project-id',
|
|
260
|
+
'test',
|
|
261
|
+
'--parent',
|
|
262
|
+
],
|
|
263
|
+
expected: {
|
|
264
|
+
snapshot: true,
|
|
265
|
+
},
|
|
266
|
+
});
|
|
253
267
|
});
|
package/commands/set_context.js
CHANGED
|
@@ -2,9 +2,7 @@ import { updateContextFile } from '../context.js';
|
|
|
2
2
|
import { branchIdFromProps } from '../utils/enrichers.js';
|
|
3
3
|
export const command = 'set-context';
|
|
4
4
|
export const describe = 'Set the current context';
|
|
5
|
-
export const builder = (argv) => argv
|
|
6
|
-
.usage('$0 set-context [options]')
|
|
7
|
-
.options({
|
|
5
|
+
export const builder = (argv) => argv.usage('$0 set-context [options]').options({
|
|
8
6
|
'project-id': {
|
|
9
7
|
describe: 'Project ID',
|
|
10
8
|
type: 'string',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { tmpdir } from 'node:os';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { rmSync } from 'node:fs';
|
|
3
|
+
import { rmSync, writeFileSync } from 'node:fs';
|
|
4
4
|
import { afterAll, describe } from '@jest/globals';
|
|
5
5
|
import { testCliCommand } from '../test_utils/test_cli_command';
|
|
6
6
|
const CONTEXT_FILE = join(tmpdir(), `neon_${Date.now()}`);
|
|
@@ -26,5 +26,28 @@ describe('set_context', () => {
|
|
|
26
26
|
snapshot: true,
|
|
27
27
|
},
|
|
28
28
|
});
|
|
29
|
+
const overrideContextFile = join(tmpdir(), `neon_override_ctx_${Date.now()}`);
|
|
30
|
+
testCliCommand({
|
|
31
|
+
name: 'get branch id overrides context set branch',
|
|
32
|
+
before: async () => {
|
|
33
|
+
writeFileSync(overrideContextFile, JSON.stringify({
|
|
34
|
+
projectId: 'test',
|
|
35
|
+
branchId: 'br-cloudy-branch-12345678',
|
|
36
|
+
}));
|
|
37
|
+
},
|
|
38
|
+
after: async () => {
|
|
39
|
+
rmSync(overrideContextFile);
|
|
40
|
+
},
|
|
41
|
+
args: [
|
|
42
|
+
'branches',
|
|
43
|
+
'get',
|
|
44
|
+
'br-sunny-branch-123456',
|
|
45
|
+
'--context-file',
|
|
46
|
+
overrideContextFile,
|
|
47
|
+
],
|
|
48
|
+
expected: {
|
|
49
|
+
snapshot: true,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
29
52
|
});
|
|
30
53
|
});
|
package/context.js
CHANGED
package/index.js
CHANGED
|
@@ -25,7 +25,13 @@ import { isAxiosError } from 'axios';
|
|
|
25
25
|
import { matchErrorCode } from './errors.js';
|
|
26
26
|
import { showHelp } from './help.js';
|
|
27
27
|
import { currentContextFile, enrichFromContext } from './context.js';
|
|
28
|
-
const NO_SUBCOMMANDS_VERBS = [
|
|
28
|
+
const NO_SUBCOMMANDS_VERBS = [
|
|
29
|
+
'auth',
|
|
30
|
+
'me',
|
|
31
|
+
'cs',
|
|
32
|
+
'connection-string',
|
|
33
|
+
'set-context',
|
|
34
|
+
];
|
|
29
35
|
let builder = yargs(hideBin(process.argv));
|
|
30
36
|
builder = builder
|
|
31
37
|
.scriptName(pkg.name)
|
|
@@ -101,7 +107,9 @@ builder = builder
|
|
|
101
107
|
})
|
|
102
108
|
.alias('help', 'h')
|
|
103
109
|
.middleware(async (args) => {
|
|
104
|
-
if (args.help ||
|
|
110
|
+
if (args.help ||
|
|
111
|
+
(args._.length === 1 &&
|
|
112
|
+
!NO_SUBCOMMANDS_VERBS.includes(args._[0]))) {
|
|
105
113
|
await showHelp(builder);
|
|
106
114
|
}
|
|
107
115
|
})
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"url": "git@github.com:neondatabase/neonctl.git"
|
|
6
6
|
},
|
|
7
7
|
"type": "module",
|
|
8
|
-
"version": "1.
|
|
8
|
+
"version": "1.24.2",
|
|
9
9
|
"description": "CLI tool for NeonDB Cloud management",
|
|
10
10
|
"main": "index.js",
|
|
11
11
|
"author": "NeonDB",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"lint-staged": "^13.0.3",
|
|
45
45
|
"oauth2-mock-server": "^6.0.0",
|
|
46
46
|
"pkg": "^5.8.1",
|
|
47
|
-
"prettier": "^
|
|
47
|
+
"prettier": "^3.1.0",
|
|
48
48
|
"rollup": "^3.26.2",
|
|
49
49
|
"semantic-release": "^21.0.2",
|
|
50
50
|
"strip-ansi": "^7.1.0",
|
|
@@ -85,14 +85,18 @@
|
|
|
85
85
|
},
|
|
86
86
|
"scripts": {
|
|
87
87
|
"watch": "tsc --watch",
|
|
88
|
-
"lint": "tsc --noEmit && eslint src --ext .ts",
|
|
88
|
+
"lint": "tsc --noEmit && eslint src --ext .ts && prettier --check .",
|
|
89
89
|
"build": "npm run generateParams && npm run clean && tsc && cp src/*.html package*.json README.md ./dist",
|
|
90
90
|
"clean": "rm -rf dist",
|
|
91
91
|
"generateParams": "node --loader ts-node/esm ./generateOptionsFromSpec.ts",
|
|
92
92
|
"start": "node src/index.js",
|
|
93
|
-
"test": "node --experimental-vm-modules node_modules/.bin/jest"
|
|
93
|
+
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
94
|
+
"prepare": "test -d .git && husky install || true"
|
|
94
95
|
},
|
|
95
96
|
"lint-staged": {
|
|
97
|
+
".{cjs,js,json,md,html}": [
|
|
98
|
+
"prettier --write"
|
|
99
|
+
],
|
|
96
100
|
"*.ts": [
|
|
97
101
|
"eslint --cache --fix",
|
|
98
102
|
"prettier --write"
|
|
@@ -4,13 +4,19 @@ import { join } from 'node:path';
|
|
|
4
4
|
import { log } from '../log.js';
|
|
5
5
|
import strip from 'strip-ansi';
|
|
6
6
|
import { runMockServer } from './mock_server.js';
|
|
7
|
-
export const testCliCommand = ({ args, name, expected, mockDir = 'main', }) => {
|
|
7
|
+
export const testCliCommand = ({ args, name, expected, before, after, mockDir = 'main', }) => {
|
|
8
8
|
let server;
|
|
9
9
|
describe(name, () => {
|
|
10
10
|
beforeAll(async () => {
|
|
11
|
+
if (before) {
|
|
12
|
+
await before();
|
|
13
|
+
}
|
|
11
14
|
server = await runMockServer(mockDir);
|
|
12
15
|
});
|
|
13
16
|
afterAll(async () => {
|
|
17
|
+
if (after) {
|
|
18
|
+
await after();
|
|
19
|
+
}
|
|
14
20
|
return new Promise((resolve) => {
|
|
15
21
|
server.close(() => {
|
|
16
22
|
resolve();
|
package/utils/formats.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const HAIKU_REGEX = /^[a-z]+-[a-z]
|
|
1
|
+
const HAIKU_REGEX = /^[a-z]+-[a-z]+-[a-z0-9]+$/;
|
|
2
2
|
export const looksLikeBranchId = (branch) => branch.startsWith('br-') && HAIKU_REGEX.test(branch.substring(3));
|
|
3
3
|
const LSN_REGEX = /^[a-fA-F0-9]{1,8}\/[a-fA-F0-9]{1,8}$/;
|
|
4
4
|
export const looksLikeLSN = (lsn) => LSN_REGEX.test(lsn);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { test, describe, expect } from '@jest/globals';
|
|
2
|
+
import { looksLikeBranchId, looksLikeLSN, looksLikeTimestamp } from './formats';
|
|
3
|
+
describe('branch formats', () => {
|
|
4
|
+
test('branch name', () => {
|
|
5
|
+
expect(looksLikeBranchId('master')).toBe(false);
|
|
6
|
+
});
|
|
7
|
+
test('initial short', () => {
|
|
8
|
+
expect(looksLikeBranchId('br-flower-sunshine-123456')).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
test('update 1, longer version', () => {
|
|
11
|
+
expect(looksLikeBranchId('br-flower-sunshine-12345678')).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
test('update 2, includes region', () => {
|
|
14
|
+
expect(looksLikeBranchId('br-bold-recipe-a13oexw7')).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
describe('timestamp formats', () => {
|
|
18
|
+
test('valid', () => {
|
|
19
|
+
expect(looksLikeTimestamp('2021-03-13T19:47:33.000Z')).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
test('invalid', () => {
|
|
22
|
+
expect(looksLikeTimestamp('branch_name')).toBe(false);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe('LSN formats', () => {
|
|
26
|
+
test('valid', () => {
|
|
27
|
+
expect(looksLikeLSN('0/1F56000')).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
test('invalid', () => {
|
|
30
|
+
expect(looksLikeLSN('branch_name')).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
});
|