neonctl 2.27.1 → 2.29.0
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/README.md +35 -3
- package/dist/analytics.js +52 -34
- package/dist/api.js +643 -13
- package/dist/auth.js +50 -44
- package/dist/cli.js +8 -1
- package/dist/commands/auth.js +64 -51
- package/dist/commands/bootstrap.js +115 -157
- package/dist/commands/branches.js +160 -150
- package/dist/commands/bucket.js +183 -146
- package/dist/commands/checkout.js +51 -51
- package/dist/commands/config.js +228 -82
- package/dist/commands/connection_string.js +62 -62
- package/dist/commands/data_api.js +100 -101
- package/dist/commands/databases.js +29 -26
- package/dist/commands/deploy.js +12 -12
- package/dist/commands/dev.js +114 -114
- package/dist/commands/env.js +43 -43
- package/dist/commands/functions.js +101 -104
- package/dist/commands/index.js +27 -25
- package/dist/commands/init.js +23 -22
- package/dist/commands/ip_allow.js +29 -29
- package/dist/commands/link.js +232 -182
- package/dist/commands/neon_auth.js +385 -370
- package/dist/commands/operations.js +11 -11
- package/dist/commands/orgs.js +8 -8
- package/dist/commands/projects.js +103 -101
- package/dist/commands/psql.js +31 -31
- package/dist/commands/roles.js +27 -24
- package/dist/commands/schema_diff.js +25 -26
- package/dist/commands/set_context.js +17 -17
- package/dist/commands/status.js +40 -0
- package/dist/commands/user.js +5 -5
- package/dist/commands/vpc_endpoints.js +50 -50
- package/dist/config.js +7 -7
- package/dist/config_format.js +5 -5
- package/dist/context.js +37 -14
- package/dist/current_branch_fast_path.js +55 -0
- package/dist/dev/env.js +33 -33
- package/dist/dev/functions.js +4 -4
- package/dist/dev/inputs.js +6 -6
- package/dist/dev/runtime.js +25 -25
- package/dist/env.js +14 -14
- package/dist/env_file.js +13 -13
- package/dist/errors.js +68 -5
- package/dist/functions_api.js +10 -10
- package/dist/help.js +15 -15
- package/dist/index.js +110 -107
- package/dist/log.js +2 -2
- package/dist/parameters.gen.js +14 -14
- package/dist/pkg.js +5 -5
- package/dist/psql/cli.js +4 -2
- package/dist/psql/command/cmd_cond.js +61 -61
- package/dist/psql/command/cmd_connect.js +159 -154
- package/dist/psql/command/cmd_copy.js +107 -97
- package/dist/psql/command/cmd_describe.js +368 -363
- package/dist/psql/command/cmd_format.js +276 -263
- package/dist/psql/command/cmd_io.js +269 -263
- package/dist/psql/command/cmd_lo.js +74 -66
- package/dist/psql/command/cmd_meta.js +148 -148
- package/dist/psql/command/cmd_misc.js +17 -17
- package/dist/psql/command/cmd_pipeline.js +142 -135
- package/dist/psql/command/cmd_restrict.js +25 -25
- package/dist/psql/command/cmd_show.js +183 -168
- package/dist/psql/command/dispatch.js +26 -26
- package/dist/psql/command/shared.js +14 -14
- package/dist/psql/complete/filenames.js +16 -16
- package/dist/psql/complete/index.js +4 -4
- package/dist/psql/complete/matcher.js +33 -32
- package/dist/psql/complete/psqlVars.js +173 -173
- package/dist/psql/complete/queries.js +5 -3
- package/dist/psql/complete/rules.js +900 -863
- package/dist/psql/core/common.js +136 -133
- package/dist/psql/core/help.js +343 -343
- package/dist/psql/core/mainloop.js +160 -153
- package/dist/psql/core/prompt.js +126 -123
- package/dist/psql/core/settings.js +111 -111
- package/dist/psql/core/sqlHelp.js +150 -150
- package/dist/psql/core/startup.js +211 -205
- package/dist/psql/core/syncVars.js +14 -14
- package/dist/psql/core/variables.js +24 -24
- package/dist/psql/describe/formatters.js +302 -289
- package/dist/psql/describe/processNamePattern.js +28 -28
- package/dist/psql/describe/queries.js +656 -651
- package/dist/psql/index.js +436 -411
- package/dist/psql/io/history.js +36 -36
- package/dist/psql/io/input.js +15 -15
- package/dist/psql/io/lineEditor/buffer.js +27 -25
- package/dist/psql/io/lineEditor/complete.js +15 -15
- package/dist/psql/io/lineEditor/filename.js +22 -22
- package/dist/psql/io/lineEditor/index.js +65 -62
- package/dist/psql/io/lineEditor/keymap.js +325 -318
- package/dist/psql/io/lineEditor/vt100.js +60 -60
- package/dist/psql/io/pgpass.js +18 -18
- package/dist/psql/io/pgservice.js +14 -14
- package/dist/psql/io/psqlrc.js +46 -46
- package/dist/psql/print/aligned.js +175 -166
- package/dist/psql/print/asciidoc.js +51 -51
- package/dist/psql/print/crosstab.js +34 -31
- package/dist/psql/print/csv.js +25 -22
- package/dist/psql/print/html.js +54 -54
- package/dist/psql/print/json.js +12 -12
- package/dist/psql/print/latex.js +118 -118
- package/dist/psql/print/pager.js +28 -26
- package/dist/psql/print/troff.js +48 -48
- package/dist/psql/print/unaligned.js +15 -14
- package/dist/psql/print/units.js +17 -17
- package/dist/psql/scanner/slash.js +48 -46
- package/dist/psql/scanner/sql.js +88 -84
- package/dist/psql/scanner/stringutils.js +21 -17
- package/dist/psql/types/index.js +7 -7
- package/dist/psql/types/scanner.js +8 -8
- package/dist/psql/wire/connection.js +341 -327
- package/dist/psql/wire/copy.js +7 -7
- package/dist/psql/wire/pipeline.js +26 -24
- package/dist/psql/wire/protocol.js +102 -102
- package/dist/psql/wire/sasl.js +62 -62
- package/dist/psql/wire/tls.js +79 -73
- package/dist/storage_api.js +22 -23
- package/dist/test_utils/fixtures.js +74 -41
- package/dist/test_utils/oauth_server.js +5 -5
- package/dist/utils/api_enums.js +33 -0
- package/dist/utils/branch_notice.js +5 -5
- package/dist/utils/branch_picker.js +26 -26
- package/dist/utils/compute_units.js +4 -4
- package/dist/utils/enrichers.js +28 -16
- package/dist/utils/esbuild.js +28 -28
- package/dist/utils/formats.js +1 -1
- package/dist/utils/middlewares.js +3 -3
- package/dist/utils/package_manager.js +68 -0
- package/dist/utils/point_in_time.js +12 -12
- package/dist/utils/psql.js +30 -30
- package/dist/utils/string.js +2 -2
- package/dist/utils/ui.js +9 -9
- package/dist/utils/zip.js +1 -1
- package/dist/writer.js +17 -17
- package/package.json +10 -12
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { contextBranch, readContextFile } from
|
|
3
|
-
import {
|
|
4
|
-
import { branchCreateRequest } from
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { parsePointInTime } from
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
1
|
+
import { retryOnLock } from "../api.js";
|
|
2
|
+
import { contextBranch, readContextFile } from "../context.js";
|
|
3
|
+
import { log } from "../log.js";
|
|
4
|
+
import { branchCreateRequest } from "../parameters.gen.js";
|
|
5
|
+
import { EndpointType } from "../utils/api_enums.js";
|
|
6
|
+
import { getComputeUnits } from "../utils/compute_units.js";
|
|
7
|
+
import { branchIdFromProps, branchIdResolve, fillSingleProject, } from "../utils/enrichers.js";
|
|
8
|
+
import { looksLikeBranchId, looksLikeLSN, looksLikeTimestamp, } from "../utils/formats.js";
|
|
9
|
+
import { parsePointInTime } from "../utils/point_in_time.js";
|
|
10
|
+
import { psql } from "../utils/psql.js";
|
|
11
|
+
import { writer } from "../writer.js";
|
|
12
|
+
import { parseSchemaDiffParams, schemaDiff } from "./schema_diff.js";
|
|
13
13
|
export const BRANCH_FIELDS = [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
"name",
|
|
15
|
+
"id",
|
|
16
|
+
"current_state",
|
|
17
|
+
"created_at",
|
|
18
|
+
"expires_at",
|
|
19
19
|
];
|
|
20
20
|
const BRANCH_FIELDS_RESET = [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
"name",
|
|
22
|
+
"id",
|
|
23
|
+
"default",
|
|
24
|
+
"current_state",
|
|
25
|
+
"created_at",
|
|
26
|
+
"last_reset_at",
|
|
27
27
|
];
|
|
28
|
-
export const command =
|
|
29
|
-
export const describe =
|
|
30
|
-
export const aliases = [
|
|
28
|
+
export const command = "branches";
|
|
29
|
+
export const describe = "Manage branches";
|
|
30
|
+
export const aliases = ["branch"];
|
|
31
31
|
export const builder = (argv) => argv
|
|
32
|
-
.usage(
|
|
32
|
+
.usage("$0 branches <sub-command> [options]")
|
|
33
33
|
.options({
|
|
34
|
-
|
|
35
|
-
describe:
|
|
36
|
-
type:
|
|
34
|
+
"project-id": {
|
|
35
|
+
describe: "Project ID",
|
|
36
|
+
type: "string",
|
|
37
37
|
},
|
|
38
38
|
})
|
|
39
39
|
.middleware(fillSingleProject)
|
|
@@ -41,172 +41,173 @@ export const builder = (argv) => argv
|
|
|
41
41
|
// Provide alias for analytics
|
|
42
42
|
args.branchId ?? (args.branchId = args.id);
|
|
43
43
|
})
|
|
44
|
-
.command(
|
|
45
|
-
.command(
|
|
46
|
-
name: branchCreateRequest[
|
|
44
|
+
.command("list", "List branches", (yargs) => yargs, (args) => list(args))
|
|
45
|
+
.command("create", "Create a branch", (yargs) => yargs.options({
|
|
46
|
+
name: branchCreateRequest["branch.name"],
|
|
47
47
|
parent: {
|
|
48
|
-
describe:
|
|
49
|
-
type:
|
|
48
|
+
describe: "Parent branch name or id or timestamp or LSN. Defaults to the default branch",
|
|
49
|
+
type: "string",
|
|
50
50
|
},
|
|
51
51
|
compute: {
|
|
52
|
-
describe:
|
|
53
|
-
type:
|
|
52
|
+
describe: "Create a branch with or without a compute. By default branch is created with a read-write compute. To create a branch without compute use --no-compute",
|
|
53
|
+
type: "boolean",
|
|
54
54
|
default: true,
|
|
55
55
|
},
|
|
56
56
|
type: {
|
|
57
|
-
describe:
|
|
58
|
-
type:
|
|
59
|
-
implies:
|
|
57
|
+
describe: "Type of compute to add",
|
|
58
|
+
type: "string",
|
|
59
|
+
implies: "compute",
|
|
60
60
|
default: EndpointType.ReadWrite,
|
|
61
61
|
choices: Object.values(EndpointType),
|
|
62
62
|
},
|
|
63
|
-
|
|
64
|
-
describe:
|
|
65
|
-
type:
|
|
66
|
-
implies:
|
|
63
|
+
"suspend-timeout": {
|
|
64
|
+
describe: "Duration of inactivity in seconds after which the compute endpoint is\nautomatically suspended. The value `0` means use the global default.\nThe value `-1` means never suspend. The default value is `300` seconds (5 minutes).\nThe maximum value is `604800` seconds (1 week).",
|
|
65
|
+
type: "number",
|
|
66
|
+
implies: "compute",
|
|
67
67
|
default: 0,
|
|
68
68
|
},
|
|
69
69
|
cu: {
|
|
70
70
|
describe: 'The number of Compute Units. Could be a fixed size (e.g. "2") or a range delimited by a dash (e.g. "0.5-3").',
|
|
71
|
-
type:
|
|
72
|
-
implies:
|
|
71
|
+
type: "string",
|
|
72
|
+
implies: "compute",
|
|
73
73
|
},
|
|
74
74
|
psql: {
|
|
75
|
-
type:
|
|
76
|
-
describe:
|
|
75
|
+
type: "boolean",
|
|
76
|
+
describe: "Connect to a new branch via psql",
|
|
77
77
|
default: false,
|
|
78
78
|
},
|
|
79
79
|
fallback: {
|
|
80
|
-
type:
|
|
81
|
-
describe:
|
|
80
|
+
type: "boolean",
|
|
81
|
+
describe: "Force the embedded TypeScript psql fallback (for testing)",
|
|
82
82
|
default: false,
|
|
83
83
|
hidden: true,
|
|
84
84
|
},
|
|
85
85
|
annotation: {
|
|
86
|
-
type:
|
|
86
|
+
type: "string",
|
|
87
87
|
hidden: true,
|
|
88
|
-
default:
|
|
88
|
+
default: "{}",
|
|
89
89
|
},
|
|
90
|
-
|
|
91
|
-
describe:
|
|
92
|
-
type:
|
|
90
|
+
"schema-only": {
|
|
91
|
+
describe: "Create a schema-only branch. Requires exactly one read-write compute.",
|
|
92
|
+
type: "boolean",
|
|
93
93
|
default: false,
|
|
94
94
|
},
|
|
95
|
-
|
|
96
|
-
describe:
|
|
97
|
-
type:
|
|
95
|
+
"expires-at": {
|
|
96
|
+
describe: "Set an expiration date for the branch. Accepts a date string (e.g., 2024-12-31T23:59:59Z).",
|
|
97
|
+
type: "string",
|
|
98
98
|
requiresArg: true,
|
|
99
99
|
},
|
|
100
100
|
}), (args) => create(args))
|
|
101
|
-
.command(
|
|
101
|
+
.command("reset <id|name>", "Reset a branch", (yargs) => yargs.options({
|
|
102
102
|
parent: {
|
|
103
|
-
describe:
|
|
104
|
-
type:
|
|
103
|
+
describe: "Reset to a parent branch",
|
|
104
|
+
type: "boolean",
|
|
105
105
|
default: false,
|
|
106
106
|
},
|
|
107
|
-
|
|
108
|
-
describe:
|
|
107
|
+
"preserve-under-name": {
|
|
108
|
+
describe: "Name under which to preserve the old branch",
|
|
109
109
|
},
|
|
110
110
|
}), (args) => reset(args))
|
|
111
|
-
.command(
|
|
111
|
+
.command("restore <target-id|name> <source>[@(timestamp|lsn)]", "Restores a branch to a specific point in time\n<source> can be: ^self, ^parent, or <source-branch-id|name>", (yargs) => yargs
|
|
112
112
|
// we want to show meaningful help for the command
|
|
113
113
|
// but it makes yargs to fail on parsing the command
|
|
114
114
|
// so we need to fill in the missing args manually
|
|
115
115
|
.middleware((args) => {
|
|
116
116
|
args.id = args.targetId;
|
|
117
|
-
args.pointInTime = args[
|
|
117
|
+
args.pointInTime = args["source@(timestamp"];
|
|
118
118
|
args.branchId = args.id; // for analytics
|
|
119
119
|
})
|
|
120
|
-
.usage(
|
|
120
|
+
.usage("$0 branches restore <target-id|name> <source>[@(timestamp|lsn)]")
|
|
121
121
|
.options({
|
|
122
|
-
|
|
123
|
-
describe:
|
|
122
|
+
"preserve-under-name": {
|
|
123
|
+
describe: "Name under which to preserve the old branch",
|
|
124
124
|
},
|
|
125
125
|
})
|
|
126
126
|
.example([
|
|
127
127
|
[
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
"$0 branches restore main br-source-branch-123456",
|
|
129
|
+
"Restores main to the head of the branch with id br-source-branch-123456",
|
|
130
130
|
],
|
|
131
131
|
[
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
"$0 branches restore main source@2021-01-01T00:00:00Z",
|
|
133
|
+
"Restores main to the timestamp 2021-01-01T00:00:00Z of the source branch",
|
|
134
134
|
],
|
|
135
135
|
[
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
"$0 branches restore my-branch ^self@0/123456",
|
|
137
|
+
"Restores my-branch to the LSN 0/123456 from its own history",
|
|
138
138
|
],
|
|
139
139
|
[
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
"$0 branches restore my-branch ^parent",
|
|
141
|
+
"Restore my-branch to the head of its parent branch",
|
|
142
142
|
],
|
|
143
143
|
]), (args) => restore(args))
|
|
144
|
-
.command(
|
|
145
|
-
.command(
|
|
144
|
+
.command("rename <id|name> <new-name>", "Rename a branch", (yargs) => yargs, (args) => rename(args))
|
|
145
|
+
.command("set-default <id|name>", "Set a branch as default", (yargs) => yargs, (args) => setDefault(args))
|
|
146
146
|
.command({
|
|
147
|
-
command:
|
|
148
|
-
describe:
|
|
147
|
+
command: "set-expiration <id|name>",
|
|
148
|
+
describe: "Set an expiration date for the branch",
|
|
149
149
|
builder: (yargs) => yargs.options({
|
|
150
|
-
|
|
151
|
-
describe:
|
|
152
|
-
type:
|
|
150
|
+
"expires-at": {
|
|
151
|
+
describe: "Set a expiration date for the branch. If omitted, expiration will be removed. Format [RFC3339]: 2024-12-31T23:59:59Z",
|
|
152
|
+
type: "string",
|
|
153
153
|
requiresArg: false,
|
|
154
154
|
},
|
|
155
155
|
}),
|
|
156
156
|
handler: (args) => setExpiration(args),
|
|
157
157
|
})
|
|
158
|
-
.command(
|
|
158
|
+
.command("add-compute <id|name>", "Add a compute to a branch", (yargs) => yargs.options({
|
|
159
159
|
type: {
|
|
160
|
-
type:
|
|
160
|
+
type: "string",
|
|
161
161
|
choices: Object.values(EndpointType),
|
|
162
|
-
describe:
|
|
162
|
+
describe: "Type of compute to add",
|
|
163
163
|
default: EndpointType.ReadOnly,
|
|
164
164
|
},
|
|
165
165
|
cu: {
|
|
166
166
|
describe: 'The number of Compute Units. Could be a fixed size (e.g. "2") or a range delimited by a dash (e.g. "0.5-3").',
|
|
167
|
-
type:
|
|
167
|
+
type: "string",
|
|
168
168
|
},
|
|
169
169
|
name: {
|
|
170
|
-
type:
|
|
171
|
-
describe:
|
|
170
|
+
type: "string",
|
|
171
|
+
describe: "Optional name of the compute",
|
|
172
172
|
},
|
|
173
173
|
}), (args) => addCompute(args))
|
|
174
|
-
.command(
|
|
175
|
-
.command(
|
|
174
|
+
.command("delete <id|name>", "Delete a branch", (yargs) => yargs, (args) => deleteBranch(args))
|
|
175
|
+
.command("get <id|name>", "Get a branch", (yargs) => yargs, (args) => get(args))
|
|
176
176
|
.command({
|
|
177
|
-
command:
|
|
178
|
-
aliases: [
|
|
177
|
+
command: "schema-diff [base-branch] [compare-source[@(timestamp|lsn)]]",
|
|
178
|
+
aliases: ["sd"],
|
|
179
179
|
describe: "Compare the latest schemas of any two branches, or compare a branch to its own or another branch's history.",
|
|
180
180
|
builder: (yargs) => {
|
|
181
181
|
return yargs
|
|
182
|
-
.middleware((args) => (args.compareSource =
|
|
182
|
+
.middleware((args) => (args.compareSource =
|
|
183
|
+
args["compare-source@(timestamp"]))
|
|
183
184
|
.middleware(parseSchemaDiffParams)
|
|
184
185
|
.options({
|
|
185
186
|
database: {
|
|
186
|
-
alias:
|
|
187
|
-
type:
|
|
188
|
-
description:
|
|
187
|
+
alias: "db",
|
|
188
|
+
type: "string",
|
|
189
|
+
description: "Name of the database for which the schema comparison is performed",
|
|
189
190
|
},
|
|
190
191
|
})
|
|
191
192
|
.example([
|
|
192
193
|
[
|
|
193
|
-
|
|
194
|
-
|
|
194
|
+
"$0 branches schema-diff main br-compare-branch-123456",
|
|
195
|
+
"Compares the main branch to the head of the branch with ID br-compare-branch-123456",
|
|
195
196
|
],
|
|
196
197
|
[
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
"$0 branches schema-diff main compare@2024-06-01T00:00:00Z",
|
|
199
|
+
"Compares the main branch to the state of the compare branch at timestamp 2024-06-01T00:00:00.000Z",
|
|
199
200
|
],
|
|
200
201
|
[
|
|
201
|
-
|
|
202
|
-
|
|
202
|
+
"$0 branches schema-diff my-branch ^self@0/123456",
|
|
203
|
+
"Compares my-branch to LSN 0/123456 from its own history",
|
|
203
204
|
],
|
|
204
205
|
[
|
|
205
|
-
|
|
206
|
-
|
|
206
|
+
"$0 branches schema-diff my-branch ^parent",
|
|
207
|
+
"Compares my-branch to the head of its parent branch",
|
|
207
208
|
],
|
|
208
209
|
[
|
|
209
|
-
|
|
210
|
+
"$0 branches schema-diff",
|
|
210
211
|
"If a branch is specified in 'set-context', compares this branch to its parent. Otherwise, compares the default branch to its parent.",
|
|
211
212
|
],
|
|
212
213
|
]);
|
|
@@ -227,27 +228,27 @@ const list = async (props) => {
|
|
|
227
228
|
writer(props).end(branches, {
|
|
228
229
|
fields: BRANCH_FIELDS,
|
|
229
230
|
renderColumns: {
|
|
230
|
-
expires_at: (br) => br.expires_at ||
|
|
231
|
+
expires_at: (br) => br.expires_at || "never",
|
|
231
232
|
// Word labels (not symbols) so they read clearly and match the existing `[anon]`.
|
|
232
233
|
name: (br) => {
|
|
233
234
|
const annotation = annotations[br.id];
|
|
234
235
|
const isAnon = annotation?.value.anonymized;
|
|
235
236
|
const labels = [];
|
|
236
237
|
if (br.default) {
|
|
237
|
-
labels.push(
|
|
238
|
+
labels.push("[default]");
|
|
238
239
|
}
|
|
239
240
|
if (br.protected) {
|
|
240
|
-
labels.push(
|
|
241
|
+
labels.push("[protected]");
|
|
241
242
|
}
|
|
242
243
|
if (isAnon) {
|
|
243
|
-
labels.push(
|
|
244
|
+
labels.push("[anon]");
|
|
244
245
|
}
|
|
245
246
|
if (currentBranch !== undefined &&
|
|
246
247
|
(br.id === currentBranch || br.name === currentBranch)) {
|
|
247
|
-
labels.push(
|
|
248
|
+
labels.push("[current]");
|
|
248
249
|
}
|
|
249
250
|
labels.push(br.name);
|
|
250
|
-
return labels.join(
|
|
251
|
+
return labels.join(" ");
|
|
251
252
|
},
|
|
252
253
|
},
|
|
253
254
|
});
|
|
@@ -260,7 +261,7 @@ const create = async (props) => {
|
|
|
260
261
|
if (!props.parent) {
|
|
261
262
|
const branch = branches.find((b) => b.default);
|
|
262
263
|
if (!branch) {
|
|
263
|
-
throw new Error(
|
|
264
|
+
throw new Error("No default branch found");
|
|
264
265
|
}
|
|
265
266
|
return { parent_id: branch.id };
|
|
266
267
|
}
|
|
@@ -282,27 +283,33 @@ const create = async (props) => {
|
|
|
282
283
|
// Validate schema-only branch requirements
|
|
283
284
|
if (props.schemaOnly) {
|
|
284
285
|
if (!props.compute) {
|
|
285
|
-
throw new Error(
|
|
286
|
+
throw new Error("Schema-only branches require a compute endpoint");
|
|
286
287
|
}
|
|
287
288
|
if (props.type !== EndpointType.ReadWrite) {
|
|
288
|
-
throw new Error(
|
|
289
|
+
throw new Error("Schema-only branches require a read-write compute endpoint");
|
|
289
290
|
}
|
|
290
291
|
}
|
|
291
292
|
const { data } = await retryOnLock(() => props.apiClient.createProjectBranch(props.projectId, {
|
|
292
293
|
branch: {
|
|
293
294
|
name: props.name,
|
|
294
295
|
...parentProps,
|
|
295
|
-
...(props.schemaOnly ? { init_source:
|
|
296
|
-
...(props[
|
|
297
|
-
? {
|
|
296
|
+
...(props.schemaOnly ? { init_source: "schema-only" } : {}),
|
|
297
|
+
...(props["expires-at"]
|
|
298
|
+
? {
|
|
299
|
+
expires_at: new Date(props["expires-at"]).toISOString(),
|
|
300
|
+
}
|
|
298
301
|
: {}),
|
|
299
302
|
},
|
|
300
303
|
endpoints: props.compute
|
|
301
304
|
? [
|
|
302
305
|
{
|
|
303
306
|
type: props.type,
|
|
304
|
-
suspend_timeout_seconds: props.suspendTimeout === 0
|
|
305
|
-
|
|
307
|
+
suspend_timeout_seconds: props.suspendTimeout === 0
|
|
308
|
+
? undefined
|
|
309
|
+
: props.suspendTimeout,
|
|
310
|
+
...(props.cu
|
|
311
|
+
? getComputeUnits(props.cu)
|
|
312
|
+
: undefined),
|
|
306
313
|
},
|
|
307
314
|
]
|
|
308
315
|
: [],
|
|
@@ -312,26 +319,26 @@ const create = async (props) => {
|
|
|
312
319
|
}));
|
|
313
320
|
const parent = branches.find((b) => b.id === data.branch.parent_id);
|
|
314
321
|
if (parent?.protected) {
|
|
315
|
-
log.warning(
|
|
322
|
+
log.warning("The parent branch is protected; a unique role password has been generated for the new branch.");
|
|
316
323
|
}
|
|
317
324
|
const out = writer(props);
|
|
318
325
|
out.write(data.branch, {
|
|
319
326
|
fields: BRANCH_FIELDS,
|
|
320
|
-
title:
|
|
321
|
-
emptyMessage:
|
|
327
|
+
title: "branch",
|
|
328
|
+
emptyMessage: "No branches have been found.",
|
|
322
329
|
});
|
|
323
330
|
if (data.endpoints?.length > 0) {
|
|
324
331
|
out.write(data.endpoints, {
|
|
325
|
-
fields: [
|
|
326
|
-
title:
|
|
327
|
-
emptyMessage:
|
|
332
|
+
fields: ["id", "created_at"],
|
|
333
|
+
title: "endpoints",
|
|
334
|
+
emptyMessage: "No endpoints have been found.",
|
|
328
335
|
});
|
|
329
336
|
}
|
|
330
337
|
if (data.connection_uris?.length) {
|
|
331
338
|
out.write(data.connection_uris, {
|
|
332
|
-
fields: [
|
|
333
|
-
title:
|
|
334
|
-
emptyMessage:
|
|
339
|
+
fields: ["connection_uri"],
|
|
340
|
+
title: "connection_uris",
|
|
341
|
+
emptyMessage: "No connection uris have been found",
|
|
335
342
|
});
|
|
336
343
|
}
|
|
337
344
|
out.end();
|
|
@@ -340,9 +347,9 @@ const create = async (props) => {
|
|
|
340
347
|
throw new Error(`Branch ${data.branch.id} doesn't have a connection uri`);
|
|
341
348
|
}
|
|
342
349
|
const connection_uri = data.connection_uris[0].connection_uri;
|
|
343
|
-
const psqlArgs = props[
|
|
350
|
+
const psqlArgs = props["--"];
|
|
344
351
|
await psql(connection_uri, psqlArgs, {
|
|
345
|
-
mode: props.fallback ?
|
|
352
|
+
mode: props.fallback ? "ts" : "auto",
|
|
346
353
|
});
|
|
347
354
|
}
|
|
348
355
|
};
|
|
@@ -367,9 +374,12 @@ const setDefault = async (props) => {
|
|
|
367
374
|
const deleteBranch = async (props) => {
|
|
368
375
|
const branchId = await branchIdFromProps(props);
|
|
369
376
|
const { data } = await retryOnLock(() => props.apiClient.deleteProjectBranch(props.projectId, branchId));
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
377
|
+
// A 204 (branch already gone) carries no body; only a 200 returns it.
|
|
378
|
+
if (data) {
|
|
379
|
+
writer(props).end(data.branch, {
|
|
380
|
+
fields: BRANCH_FIELDS,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
373
383
|
};
|
|
374
384
|
const get = async (props) => {
|
|
375
385
|
const branchId = await branchIdFromProps(props);
|
|
@@ -390,17 +400,17 @@ const addCompute = async (props) => {
|
|
|
390
400
|
},
|
|
391
401
|
}));
|
|
392
402
|
writer(props).end(data.endpoint, {
|
|
393
|
-
fields: [
|
|
403
|
+
fields: ["id", "host"],
|
|
394
404
|
});
|
|
395
405
|
};
|
|
396
406
|
const reset = async (props) => {
|
|
397
407
|
if (!props.parent) {
|
|
398
|
-
throw new Error(
|
|
408
|
+
throw new Error("Only resetting to parent is supported for now");
|
|
399
409
|
}
|
|
400
410
|
const branchId = await branchIdFromProps(props);
|
|
401
411
|
const { data: { branch: { parent_id }, }, } = await props.apiClient.getProjectBranch(props.projectId, branchId);
|
|
402
412
|
if (!parent_id) {
|
|
403
|
-
throw new Error(
|
|
413
|
+
throw new Error("Branch has no parent");
|
|
404
414
|
}
|
|
405
415
|
const { data } = await retryOnLock(() => props.apiClient.restoreProjectBranch(props.projectId, branchId, {
|
|
406
416
|
source_branch_id: parent_id,
|
|
@@ -423,30 +433,30 @@ const restore = async (props) => {
|
|
|
423
433
|
projectId: props.projectId,
|
|
424
434
|
api: props.apiClient,
|
|
425
435
|
});
|
|
426
|
-
log.info(`Restoring branch ${targetBranchId} to the branch ${pointInTime.branchId} ${(pointInTime.tag ===
|
|
427
|
-
(pointInTime.tag ===
|
|
428
|
-
|
|
429
|
-
|
|
436
|
+
log.info(`Restoring branch ${targetBranchId} to the branch ${pointInTime.branchId} ${(pointInTime.tag === "lsn" && "LSN " + pointInTime.lsn) ||
|
|
437
|
+
(pointInTime.tag === "timestamp" &&
|
|
438
|
+
"timestamp " + pointInTime.timestamp) ||
|
|
439
|
+
"head"}`);
|
|
430
440
|
const { data } = await retryOnLock(() => props.apiClient.restoreProjectBranch(props.projectId, targetBranchId, {
|
|
431
441
|
source_branch_id: pointInTime.branchId,
|
|
432
442
|
preserve_under_name: props.preserveUnderName || undefined,
|
|
433
|
-
...(pointInTime.tag ===
|
|
434
|
-
...(pointInTime.tag ===
|
|
443
|
+
...(pointInTime.tag === "lsn" && { source_lsn: pointInTime.lsn }),
|
|
444
|
+
...(pointInTime.tag === "timestamp" && {
|
|
435
445
|
source_timestamp: pointInTime.timestamp,
|
|
436
446
|
}),
|
|
437
447
|
}));
|
|
438
448
|
const writeInst = writer(props).write(data.branch, {
|
|
439
|
-
title:
|
|
440
|
-
fields: [
|
|
441
|
-
emptyMessage:
|
|
449
|
+
title: "Restored branch",
|
|
450
|
+
fields: ["id", "name", "last_reset_at"],
|
|
451
|
+
emptyMessage: "No branches have been restored.",
|
|
442
452
|
});
|
|
443
453
|
const parentId = data.branch.parent_id;
|
|
444
454
|
if (props.preserveUnderName && parentId) {
|
|
445
455
|
const { data } = await props.apiClient.getProjectBranch(props.projectId, parentId);
|
|
446
456
|
writeInst.write(data.branch, {
|
|
447
|
-
title:
|
|
448
|
-
fields: [
|
|
449
|
-
emptyMessage:
|
|
457
|
+
title: "Backup branch",
|
|
458
|
+
fields: ["id", "name"],
|
|
459
|
+
emptyMessage: "Backup branch has not been found.",
|
|
450
460
|
});
|
|
451
461
|
}
|
|
452
462
|
writeInst.end();
|
|
@@ -457,7 +467,7 @@ const setExpiration = async (props) => {
|
|
|
457
467
|
...props,
|
|
458
468
|
id: props.branchId,
|
|
459
469
|
});
|
|
460
|
-
const expiresAt = typeof props.expiresAt ===
|
|
470
|
+
const expiresAt = typeof props.expiresAt === "string"
|
|
461
471
|
? new Date(props.expiresAt).toISOString()
|
|
462
472
|
: null;
|
|
463
473
|
const { data } = await retryOnLock(() => props.apiClient.updateProjectBranch(props.projectId, branchId, {
|