neon 7.0.2 → 7.0.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.
- package/dist/commands/api.js +1 -1
- package/dist/commands/bootstrap.js +3 -3
- package/dist/commands/branches.js +140 -41
- package/dist/commands/bucket.js +1 -1
- package/dist/commands/config.js +1 -1
- package/dist/commands/dev.js +1 -1
- package/dist/commands/ip_allow.js +1 -1
- package/dist/commands/manifest.js +316 -0
- package/dist/commands/mcp.js +2 -2
- package/dist/commands/plugins.js +3 -3
- package/dist/commands/profile.js +1 -1
- package/dist/commands/projects.js +1 -1
- package/dist/commands/schema_diff.js +29 -10
- package/dist/commands/skills.js +3 -3
- package/dist/human_table.js +5 -2
- package/dist/index.js +3 -2
- package/dist/init/mode.js +1 -1
- package/dist/init/run.js +5 -5
- package/dist/init/tooling.js +1 -1
- package/dist/init/wizard.js +3 -3
- package/dist/mcp/install.js +1 -1
- package/dist/mcp/mint.js +1 -1
- package/dist/plugins/targets.js +1 -1
- package/dist/test_utils/fixtures.js +8 -1
- package/dist/update_notifier.js +1 -1
- package/dist/utils/enrichers.js +40 -7
- package/dist/utils/point_in_time.js +4 -4
- package/dist/writer.js +8 -5
- package/package.json +6 -3
package/dist/commands/api.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
2
|
-
import { describeOperation, getEndpoints, loadSpec } from "../utils/openapi.js";
|
|
3
2
|
import { writer } from "../writer.js";
|
|
3
|
+
import { describeOperation, getEndpoints, loadSpec } from "../utils/openapi.js";
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
5
5
|
import { resolve } from "node:path";
|
|
6
6
|
import YAML from "yaml";
|
|
@@ -4,13 +4,13 @@ import { log } from "../log.js";
|
|
|
4
4
|
import { recordCommandSuccessExtras, recordScaffoldedTemplate } from "../analytics.js";
|
|
5
5
|
import { getCliName } from "../utils/cli_name.js";
|
|
6
6
|
import { helpCsv, helpEpilogue } from "../utils/help_text.js";
|
|
7
|
+
import { coerceAgentFlag } from "../utils/agent_flag.js";
|
|
8
|
+
import { assertNamedAgentTooling, chooseYesAgentTooling, initPluginAgents, initSkillsMcpAgents, postScaffoldActions, projectContextFile, resolveNamedAgents } from "../init/plan.js";
|
|
9
|
+
import { formatInstallCommand, inferPackageManager, installArgs, installedPackageManagers, resolvePackageManager, runCommand } from "../utils/package_manager.js";
|
|
7
10
|
import { writer } from "../writer.js";
|
|
8
11
|
import { FALLBACK_TEMPLATES, ensureTargetUsable, fetchTemplates, findTemplate, scaffoldTemplate, templateIds } from "../init/bootstrap.js";
|
|
9
12
|
import { agentSetupDoneLabel, formatInitDone, printInitBanner, printInitDone, shouldPrintInitBanner } from "../init/chrome.js";
|
|
10
|
-
import { formatInstallCommand, inferPackageManager, installArgs, installedPackageManagers, resolvePackageManager, runCommand } from "../utils/package_manager.js";
|
|
11
13
|
import { runAuthenticatedLink } from "../init/link.js";
|
|
12
|
-
import { coerceAgentFlag } from "../utils/agent_flag.js";
|
|
13
|
-
import { assertNamedAgentTooling, chooseYesAgentTooling, initPluginAgents, initSkillsMcpAgents, postScaffoldActions, projectContextFile, resolveNamedAgents } from "../init/plan.js";
|
|
14
14
|
import { formatTemplateTitle } from "../init/template_title.js";
|
|
15
15
|
import { pickAgentSetupInteractively, pickInitLinkInteractively } from "../init/wizard.js";
|
|
16
16
|
import { runAgentTooling } from "../init/tooling.js";
|
|
@@ -2,15 +2,16 @@ import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
|
2
2
|
import { log } from "../log.js";
|
|
3
3
|
import { retryOnLock } from "../api.js";
|
|
4
4
|
import { contextBranch, readContextFile } from "../context.js";
|
|
5
|
+
import { branchCreateRequest } from "../parameters.gen.js";
|
|
5
6
|
import { writer } from "../writer.js";
|
|
6
7
|
import { EndpointType } from "../utils/api_enums.js";
|
|
7
8
|
import { looksLikeBranchId, looksLikeLSN, looksLikeTimestamp } from "../utils/formats.js";
|
|
8
|
-
import { branchIdFromProps,
|
|
9
|
-
import { branchCreateRequest } from "../parameters.gen.js";
|
|
9
|
+
import { branchIdFromProps, fillSingleProject, resolveBranchFromProps } from "../utils/enrichers.js";
|
|
10
10
|
import { getComputeUnits } from "../utils/compute_units.js";
|
|
11
11
|
import { psql } from "../utils/psql.js";
|
|
12
12
|
import { parsePointInTime } from "../utils/point_in_time.js";
|
|
13
13
|
import { parseSchemaDiffParams, schemaDiff } from "./schema_diff.js";
|
|
14
|
+
import chalk from "chalk";
|
|
14
15
|
//#region src/commands/branches.ts
|
|
15
16
|
var branches_exports = /* @__PURE__ */ __exportAll({
|
|
16
17
|
BRANCH_FIELDS: () => BRANCH_FIELDS,
|
|
@@ -27,14 +28,64 @@ const BRANCH_FIELDS = [
|
|
|
27
28
|
"expires_at",
|
|
28
29
|
"created_at"
|
|
29
30
|
];
|
|
30
|
-
const BRANCH_FIELDS_RESET = [
|
|
31
|
+
const BRANCH_FIELDS_RESET = [...BRANCH_FIELDS, "last_reset_at"];
|
|
32
|
+
const BRANCH_DETAIL_FIELDS = [
|
|
31
33
|
"name",
|
|
32
34
|
"id",
|
|
33
|
-
"
|
|
35
|
+
"parent_id",
|
|
34
36
|
"current_state",
|
|
37
|
+
"expires_at",
|
|
35
38
|
"created_at",
|
|
36
|
-
"
|
|
39
|
+
"created_by",
|
|
40
|
+
"last_reset_at",
|
|
41
|
+
"logical_size"
|
|
37
42
|
];
|
|
43
|
+
/**
|
|
44
|
+
* The branch `.neon` pins, by name (preferred) or id, when `.neon` links this same project;
|
|
45
|
+
* a `--project-id` pointing elsewhere makes its branch not current.
|
|
46
|
+
*/
|
|
47
|
+
const currentBranchOf = (props) => {
|
|
48
|
+
const context = readContextFile(props.contextFile);
|
|
49
|
+
return context.projectId === props.projectId ? contextBranch(context) : void 0;
|
|
50
|
+
};
|
|
51
|
+
const branchNameCell = (br, labels) => {
|
|
52
|
+
const tags = [];
|
|
53
|
+
if (br.default) tags.push(chalk.cyan("[default]"));
|
|
54
|
+
if (br.protected) tags.push(chalk.yellow("[protected]"));
|
|
55
|
+
if (labels.annotations?.[br.id]?.value.anonymized) tags.push(chalk.dim("[anon]"));
|
|
56
|
+
if (labels.current !== void 0 && (br.id === labels.current || br.name === labels.current)) tags.push(chalk.green("[current]"));
|
|
57
|
+
tags.push(br.name);
|
|
58
|
+
return tags.join(" ");
|
|
59
|
+
};
|
|
60
|
+
const stateCell = (state) => {
|
|
61
|
+
if (!state) return "";
|
|
62
|
+
if (state === "ready") return chalk.green(state);
|
|
63
|
+
if (state === "init" || state === "resetting") return chalk.yellow(state);
|
|
64
|
+
return chalk.dim(state);
|
|
65
|
+
};
|
|
66
|
+
const formatBytes = (bytes) => {
|
|
67
|
+
const units = [
|
|
68
|
+
"bytes",
|
|
69
|
+
"KiB",
|
|
70
|
+
"MiB",
|
|
71
|
+
"GiB",
|
|
72
|
+
"TiB"
|
|
73
|
+
];
|
|
74
|
+
let value = bytes;
|
|
75
|
+
let unit = 0;
|
|
76
|
+
while (value >= 1024 && unit < units.length - 1) {
|
|
77
|
+
value /= 1024;
|
|
78
|
+
unit++;
|
|
79
|
+
}
|
|
80
|
+
return unit === 0 ? `${bytes} bytes` : `${value.toFixed(1)} ${units[unit]}`;
|
|
81
|
+
};
|
|
82
|
+
const branchColumns = (labels) => ({
|
|
83
|
+
name: (br) => branchNameCell(br, labels),
|
|
84
|
+
current_state: (br) => stateCell(br.current_state),
|
|
85
|
+
expires_at: (br) => br.expires_at || "never",
|
|
86
|
+
created_by: (br) => br.created_by?.name ?? "",
|
|
87
|
+
logical_size: (br) => br.logical_size === void 0 ? "" : formatBytes(br.logical_size)
|
|
88
|
+
});
|
|
38
89
|
const command = "branches";
|
|
39
90
|
const describe = "Manage branches";
|
|
40
91
|
const aliases = ["branch"];
|
|
@@ -171,22 +222,12 @@ const handler = (args) => {
|
|
|
171
222
|
};
|
|
172
223
|
const list = async (props) => {
|
|
173
224
|
const { data: { branches, annotations } } = await props.apiClient.listProjectBranches({ projectId: props.projectId });
|
|
174
|
-
const currentBranch = contextBranch(readContextFile(props.contextFile));
|
|
175
225
|
writer(props).end(branches, {
|
|
176
226
|
fields: BRANCH_FIELDS,
|
|
177
|
-
renderColumns: {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const labels = [];
|
|
182
|
-
if (br.default) labels.push("[default]");
|
|
183
|
-
if (br.protected) labels.push("[protected]");
|
|
184
|
-
if (isAnon) labels.push("[anon]");
|
|
185
|
-
if (currentBranch !== void 0 && (br.id === currentBranch || br.name === currentBranch)) labels.push("[current]");
|
|
186
|
-
labels.push(br.name);
|
|
187
|
-
return labels.join(" ");
|
|
188
|
-
}
|
|
189
|
-
}
|
|
227
|
+
renderColumns: branchColumns({
|
|
228
|
+
annotations,
|
|
229
|
+
current: currentBranchOf(props)
|
|
230
|
+
})
|
|
190
231
|
});
|
|
191
232
|
};
|
|
192
233
|
const create = async (props) => {
|
|
@@ -237,16 +278,20 @@ const create = async (props) => {
|
|
|
237
278
|
out.write(data.branch, {
|
|
238
279
|
fields: BRANCH_FIELDS,
|
|
239
280
|
title: "branch",
|
|
240
|
-
|
|
281
|
+
humanTitle: "Branch",
|
|
282
|
+
emptyMessage: "No branches have been found.",
|
|
283
|
+
renderColumns: branchColumns({ current: currentBranchOf(props) })
|
|
241
284
|
});
|
|
242
285
|
if (writeEndpoints) out.write(endpoints, {
|
|
243
286
|
fields: ["id", "created_at"],
|
|
244
287
|
title: "endpoints",
|
|
288
|
+
humanTitle: "Compute",
|
|
245
289
|
emptyMessage: "No endpoints have been found."
|
|
246
290
|
});
|
|
247
291
|
if (writeUris) out.write(connectionUris, {
|
|
248
292
|
fields: ["connection_uri"],
|
|
249
293
|
title: "connection_uris",
|
|
294
|
+
humanTitle: "Connection string",
|
|
250
295
|
emptyMessage: "No connection uris have been found"
|
|
251
296
|
});
|
|
252
297
|
}
|
|
@@ -259,24 +304,54 @@ const create = async (props) => {
|
|
|
259
304
|
}
|
|
260
305
|
};
|
|
261
306
|
const rename = async (props) => {
|
|
262
|
-
const branchId = await
|
|
307
|
+
const { branchId, listing } = await resolveBranchFromProps(props);
|
|
263
308
|
const { data } = await retryOnLock(() => props.apiClient.updateProjectBranch(props.projectId, branchId, { branch: { name: props.newName } }));
|
|
264
|
-
writer(props).end(data.branch, {
|
|
309
|
+
writer(props).end(data.branch, {
|
|
310
|
+
fields: BRANCH_FIELDS,
|
|
311
|
+
renderColumns: branchColumns({
|
|
312
|
+
annotations: listing?.annotations,
|
|
313
|
+
current: currentBranchOf(props)
|
|
314
|
+
})
|
|
315
|
+
});
|
|
265
316
|
};
|
|
266
317
|
const setDefault = async (props) => {
|
|
267
|
-
const branchId = await
|
|
318
|
+
const { branchId, listing } = await resolveBranchFromProps(props);
|
|
268
319
|
const { data } = await retryOnLock(() => props.apiClient.setDefaultProjectBranch(props.projectId, branchId));
|
|
269
|
-
writer(props).end(data.branch, {
|
|
320
|
+
writer(props).end(data.branch, {
|
|
321
|
+
fields: BRANCH_FIELDS,
|
|
322
|
+
renderColumns: branchColumns({
|
|
323
|
+
annotations: listing?.annotations,
|
|
324
|
+
current: currentBranchOf(props)
|
|
325
|
+
})
|
|
326
|
+
});
|
|
270
327
|
};
|
|
271
328
|
const deleteBranch = async (props) => {
|
|
272
|
-
const branchId = await
|
|
329
|
+
const { branchId, listing } = await resolveBranchFromProps(props);
|
|
273
330
|
const { data } = await retryOnLock(() => props.apiClient.deleteProjectBranch(props.projectId, branchId));
|
|
274
|
-
if (data) writer(props).end(data.branch, {
|
|
331
|
+
if (data) writer(props).end(data.branch, {
|
|
332
|
+
fields: BRANCH_FIELDS,
|
|
333
|
+
renderColumns: branchColumns({
|
|
334
|
+
annotations: listing?.annotations,
|
|
335
|
+
current: currentBranchOf(props)
|
|
336
|
+
})
|
|
337
|
+
});
|
|
275
338
|
};
|
|
276
339
|
const get = async (props) => {
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
340
|
+
const resolved = await resolveBranchFromProps(props);
|
|
341
|
+
let branch = resolved.branch;
|
|
342
|
+
let annotations = resolved.listing?.annotations;
|
|
343
|
+
if (!branch) {
|
|
344
|
+
const { data } = await props.apiClient.getProjectBranch(props.projectId, resolved.branchId);
|
|
345
|
+
branch = data.branch;
|
|
346
|
+
annotations = data.annotation ? { [data.branch.id]: data.annotation } : void 0;
|
|
347
|
+
}
|
|
348
|
+
writer(props).end(branch, {
|
|
349
|
+
fields: BRANCH_DETAIL_FIELDS,
|
|
350
|
+
renderColumns: branchColumns({
|
|
351
|
+
annotations,
|
|
352
|
+
current: currentBranchOf(props)
|
|
353
|
+
})
|
|
354
|
+
});
|
|
280
355
|
};
|
|
281
356
|
const addCompute = async (props) => {
|
|
282
357
|
const branchId = await branchIdFromProps(props);
|
|
@@ -291,34 +366,50 @@ const addCompute = async (props) => {
|
|
|
291
366
|
};
|
|
292
367
|
const reset = async (props) => {
|
|
293
368
|
if (!props.parent) throw new Error("Only resetting to parent is supported for now");
|
|
294
|
-
const branchId = await
|
|
295
|
-
const
|
|
369
|
+
const { branchId, branch, listing } = await resolveBranchFromProps(props);
|
|
370
|
+
const parent_id = branch?.parent_id ?? (await props.apiClient.getProjectBranch(props.projectId, branchId)).data.branch.parent_id;
|
|
296
371
|
if (!parent_id) throw new Error("Branch has no parent");
|
|
297
372
|
const { data } = await retryOnLock(() => props.apiClient.restoreProjectBranch(props.projectId, branchId, {
|
|
298
373
|
source_branch_id: parent_id,
|
|
299
374
|
preserve_under_name: props.preserveUnderName || void 0
|
|
300
375
|
}));
|
|
301
|
-
writer(props).end(data.branch, {
|
|
376
|
+
writer(props).end(data.branch, {
|
|
377
|
+
fields: BRANCH_FIELDS_RESET,
|
|
378
|
+
renderColumns: branchColumns({
|
|
379
|
+
annotations: listing?.annotations,
|
|
380
|
+
current: currentBranchOf(props)
|
|
381
|
+
})
|
|
382
|
+
});
|
|
302
383
|
};
|
|
303
384
|
const restore = async (props) => {
|
|
304
|
-
const targetBranchId = await
|
|
305
|
-
|
|
385
|
+
const { branchId: targetBranchId, branch: targetBranch, listing } = await resolveBranchFromProps({
|
|
386
|
+
apiClient: props.apiClient,
|
|
306
387
|
projectId: props.projectId,
|
|
307
|
-
|
|
388
|
+
id: props.id
|
|
308
389
|
});
|
|
309
390
|
const pointInTime = await parsePointInTime({
|
|
310
391
|
pointInTime: props.pointInTime,
|
|
311
392
|
targetBranchId,
|
|
312
393
|
projectId: props.projectId,
|
|
313
|
-
api: props.apiClient
|
|
394
|
+
api: props.apiClient,
|
|
395
|
+
branches: listing?.branches,
|
|
396
|
+
targetBranch
|
|
314
397
|
});
|
|
315
|
-
|
|
398
|
+
if (props.output === "table") {
|
|
399
|
+
const nameOf = (id) => listing?.branches.find((b) => b.id === id)?.name ?? id;
|
|
400
|
+
const point = pointInTime.tag === "lsn" ? `LSN ${pointInTime.lsn} of` : pointInTime.tag === "timestamp" ? `timestamp ${pointInTime.timestamp} of` : "the head of";
|
|
401
|
+
log.info(`Restoring ${nameOf(targetBranchId)} to ${point} ${nameOf(pointInTime.branchId)}`);
|
|
402
|
+
} else log.info(`Restoring branch ${targetBranchId} to the branch ${pointInTime.branchId} ${pointInTime.tag === "lsn" && "LSN " + pointInTime.lsn || pointInTime.tag === "timestamp" && "timestamp " + pointInTime.timestamp || "head"}`);
|
|
316
403
|
const { data } = await retryOnLock(() => props.apiClient.restoreProjectBranch(props.projectId, targetBranchId, {
|
|
317
404
|
source_branch_id: pointInTime.branchId,
|
|
318
405
|
preserve_under_name: props.preserveUnderName || void 0,
|
|
319
406
|
...pointInTime.tag === "lsn" && { source_lsn: pointInTime.lsn },
|
|
320
407
|
...pointInTime.tag === "timestamp" && { source_timestamp: pointInTime.timestamp }
|
|
321
408
|
}));
|
|
409
|
+
const labels = {
|
|
410
|
+
annotations: listing?.annotations,
|
|
411
|
+
current: currentBranchOf(props)
|
|
412
|
+
};
|
|
322
413
|
const writeInst = writer(props).write(data.branch, {
|
|
323
414
|
title: "Restored branch",
|
|
324
415
|
fields: [
|
|
@@ -326,7 +417,8 @@ const restore = async (props) => {
|
|
|
326
417
|
"name",
|
|
327
418
|
"last_reset_at"
|
|
328
419
|
],
|
|
329
|
-
emptyMessage: "No branches have been restored."
|
|
420
|
+
emptyMessage: "No branches have been restored.",
|
|
421
|
+
renderColumns: branchColumns(labels)
|
|
330
422
|
});
|
|
331
423
|
const parentId = data.branch.parent_id;
|
|
332
424
|
if (props.preserveUnderName && parentId) {
|
|
@@ -334,19 +426,26 @@ const restore = async (props) => {
|
|
|
334
426
|
writeInst.write(data.branch, {
|
|
335
427
|
title: "Backup branch",
|
|
336
428
|
fields: ["id", "name"],
|
|
337
|
-
emptyMessage: "Backup branch has not been found."
|
|
429
|
+
emptyMessage: "Backup branch has not been found.",
|
|
430
|
+
renderColumns: branchColumns(labels)
|
|
338
431
|
});
|
|
339
432
|
}
|
|
340
433
|
writeInst.end();
|
|
341
434
|
};
|
|
342
435
|
const setExpiration = async (props) => {
|
|
343
|
-
const branchId = await
|
|
436
|
+
const { branchId, listing } = await resolveBranchFromProps({
|
|
344
437
|
...props,
|
|
345
438
|
id: props.branchId
|
|
346
439
|
});
|
|
347
440
|
const expiresAt = typeof props.expiresAt === "string" ? new Date(props.expiresAt).toISOString() : null;
|
|
348
441
|
const { data } = await retryOnLock(() => props.apiClient.updateProjectBranch(props.projectId, branchId, { branch: { expires_at: expiresAt } }));
|
|
349
|
-
writer(props).end(data.branch, {
|
|
442
|
+
writer(props).end(data.branch, {
|
|
443
|
+
fields: BRANCH_FIELDS,
|
|
444
|
+
renderColumns: branchColumns({
|
|
445
|
+
annotations: listing?.annotations,
|
|
446
|
+
current: currentBranchOf(props)
|
|
447
|
+
})
|
|
448
|
+
});
|
|
350
449
|
};
|
|
351
450
|
//#endregion
|
|
352
451
|
export { BRANCH_FIELDS, aliases, builder, command, describe, handler, branches_exports as t };
|
package/dist/commands/bucket.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
2
2
|
import { log } from "../log.js";
|
|
3
3
|
import { isNeonApiError, retryOnLock } from "../api.js";
|
|
4
|
+
import { createProjectBranchBucket, deleteProjectBranchBucket, deleteProjectBranchBucketObject, deleteProjectBranchBucketObjectsByPrefix, getProjectBranchBucketObject, listProjectBranchBucketObjects, listProjectBranchBuckets, presignUpload } from "../storage_api.js";
|
|
4
5
|
import { writer } from "../writer.js";
|
|
5
6
|
import { branchIdFromProps, fillSingleProject } from "../utils/enrichers.js";
|
|
6
|
-
import { createProjectBranchBucket, deleteProjectBranchBucket, deleteProjectBranchBucketObject, deleteProjectBranchBucketObjectsByPrefix, getProjectBranchBucketObject, listProjectBranchBucketObjects, listProjectBranchBuckets, presignUpload } from "../storage_api.js";
|
|
7
7
|
import { createReadStream, createWriteStream } from "node:fs";
|
|
8
8
|
import { basename } from "node:path";
|
|
9
9
|
import { stat, unlink } from "node:fs/promises";
|
package/dist/commands/config.js
CHANGED
|
@@ -10,12 +10,12 @@ import { editNeonConfig } from "../config_edit.js";
|
|
|
10
10
|
import { toNeonConfigView } from "../config_format.js";
|
|
11
11
|
import { declaredNeonServices } from "../config_services.js";
|
|
12
12
|
import { loadEnvFileIntoProcess } from "../env_file.js";
|
|
13
|
+
import { formatInstallCommand, installArgs, resolvePackageManager, runCommand } from "../utils/package_manager.js";
|
|
13
14
|
import { writer } from "../writer.js";
|
|
14
15
|
import { fillSingleProject, resolveBranchRef } from "../utils/enrichers.js";
|
|
15
16
|
import { assertAiGatewayProvisionable, warnAiGateway } from "../utils/ai_gateway_notice.js";
|
|
16
17
|
import { announceTargetBranch } from "../utils/branch_notice.js";
|
|
17
18
|
import { renderAppliedChanges, renderBranchSettingConflicts, renderCustomDomainFollowup } from "../utils/config_diff.js";
|
|
18
|
-
import { formatInstallCommand, installArgs, resolvePackageManager, runCommand } from "../utils/package_manager.js";
|
|
19
19
|
import { bundleEntry } from "../utils/esbuild.js";
|
|
20
20
|
import { readGitContext } from "../utils/git.js";
|
|
21
21
|
import { resolveHookEnv, runDeployAfterHook, runDeployBeforeHook } from "../utils/hooks.js";
|
package/dist/commands/dev.js
CHANGED
|
@@ -13,8 +13,8 @@ import { existsSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs"
|
|
|
13
13
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
14
14
|
import { fileURLToPath } from "node:url";
|
|
15
15
|
import chalk from "chalk";
|
|
16
|
-
import { bundleAsIs, describeNativeFinding, findUndeclaredNativePackages, resolveEsbuildEntry } from "@neon/config-runtime";
|
|
17
16
|
import { spawn, spawnSync } from "node:child_process";
|
|
17
|
+
import { bundleAsIs, describeNativeFinding, findUndeclaredNativePackages, resolveEsbuildEntry } from "@neon/config-runtime";
|
|
18
18
|
import { once } from "node:events";
|
|
19
19
|
import { createServer } from "node:net";
|
|
20
20
|
//#region src/commands/dev.ts
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
2
2
|
import { log } from "../log.js";
|
|
3
3
|
import { getCliName } from "../utils/cli_name.js";
|
|
4
|
+
import { projectUpdateRequest } from "../parameters.gen.js";
|
|
4
5
|
import { writer } from "../writer.js";
|
|
5
6
|
import { fillSingleProject } from "../utils/enrichers.js";
|
|
6
|
-
import { projectUpdateRequest } from "../parameters.gen.js";
|
|
7
7
|
//#region src/commands/ip_allow.ts
|
|
8
8
|
var ip_allow_exports = /* @__PURE__ */ __exportAll({
|
|
9
9
|
builder: () => builder,
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { getCliName } from "../utils/cli_name.js";
|
|
2
|
+
import { Parser } from "yargs/helpers";
|
|
3
|
+
//#region src/commands/manifest.ts
|
|
4
|
+
/**
|
|
5
|
+
* Every top-level command, in help order, with the metadata yargs needs to list and route it.
|
|
6
|
+
* A command's module (and everything it imports) loads only when yargs selects that command,
|
|
7
|
+
* so `neon --help` and `neon projects list` don't pay for `init`, `dev`, or `psql`.
|
|
8
|
+
*
|
|
9
|
+
* `command`, `aliases`, and `describe` must equal the module's own exports; `manifest.test.ts`
|
|
10
|
+
* enforces that. `load` uses a literal specifier so bundlers can see and package each chunk.
|
|
11
|
+
*/
|
|
12
|
+
const commandManifest = [
|
|
13
|
+
{
|
|
14
|
+
command: "auth",
|
|
15
|
+
aliases: ["login"],
|
|
16
|
+
describe: "Sign in with a browser. See --help for API keys and profiles",
|
|
17
|
+
load: () => import("./auth.js")
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
command: "profile",
|
|
21
|
+
aliases: ["profiles"],
|
|
22
|
+
describe: "Manage named sets of Neon credentials",
|
|
23
|
+
load: () => import("./profile.js")
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
command: "api-keys",
|
|
27
|
+
aliases: ["api-key"],
|
|
28
|
+
describe: "Manage API keys",
|
|
29
|
+
load: () => import("./api_keys.js")
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
command: "api [path]",
|
|
33
|
+
describe: "Call any Neon API route directly (authenticated passthrough)",
|
|
34
|
+
load: () => import("./api.js")
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
command: "me",
|
|
38
|
+
describe: "Show current user",
|
|
39
|
+
load: () => import("./user.js")
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
command: "orgs",
|
|
43
|
+
aliases: ["org"],
|
|
44
|
+
describe: "Manage organizations",
|
|
45
|
+
load: () => import("./orgs.js")
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
command: "projects",
|
|
49
|
+
aliases: ["project"],
|
|
50
|
+
describe: "Manage projects",
|
|
51
|
+
load: () => import("./projects.js")
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
command: "ip-allow",
|
|
55
|
+
describe: "Manage IP Allow",
|
|
56
|
+
load: () => import("./ip_allow.js")
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
command: "vpc",
|
|
60
|
+
describe: "Manage VPC endpoints and project VPC restrictions",
|
|
61
|
+
load: () => import("./vpc_endpoints.js")
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
command: "neon-auth",
|
|
65
|
+
describe: "Manage Neon Auth",
|
|
66
|
+
load: () => import("./neon_auth.js")
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
command: "branches",
|
|
70
|
+
aliases: ["branch"],
|
|
71
|
+
describe: "Manage branches",
|
|
72
|
+
load: () => import("./branches.js")
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
command: "databases",
|
|
76
|
+
aliases: ["database", "db"],
|
|
77
|
+
describe: "Manage databases",
|
|
78
|
+
load: () => import("./databases.js")
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
command: "roles",
|
|
82
|
+
aliases: ["role"],
|
|
83
|
+
describe: "Manage roles",
|
|
84
|
+
load: () => import("./roles.js")
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
command: "operations",
|
|
88
|
+
aliases: ["operation"],
|
|
89
|
+
describe: "Manage operations",
|
|
90
|
+
load: () => import("./operations.js")
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
command: "logs",
|
|
94
|
+
describe: "Query branch logs",
|
|
95
|
+
load: () => import("./logs.js")
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
command: "snapshots",
|
|
99
|
+
aliases: ["snapshot"],
|
|
100
|
+
describe: "Manage snapshots",
|
|
101
|
+
load: () => import("./snapshots.js")
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
command: "inspect",
|
|
105
|
+
aliases: ["inspection"],
|
|
106
|
+
describe: "Inspect a branch's Postgres health and configuration",
|
|
107
|
+
load: () => import("./inspect.js")
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
command: "connection-string [branch]",
|
|
111
|
+
aliases: ["cs"],
|
|
112
|
+
describe: "Get connection string",
|
|
113
|
+
load: () => import("./connection_string.js")
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
command: "psql [branch]",
|
|
117
|
+
describe: "Connect to a database via psql",
|
|
118
|
+
load: () => import("./psql.js")
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
command: "set-context",
|
|
122
|
+
describe: `Deprecated: use \`${getCliName()} link\`. Set the .neon context (raw write).`,
|
|
123
|
+
load: () => import("./set_context.js")
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
command: "checkout [id|name]",
|
|
127
|
+
describe: "Pin a branch in the local context (.neon) so subsequent commands target it",
|
|
128
|
+
load: () => import("./checkout.js")
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
command: "git",
|
|
132
|
+
aliases: [],
|
|
133
|
+
describe: "Sync the checked-out Neon branch to your git branch (Preview)",
|
|
134
|
+
load: () => import("./git.js")
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
command: "link",
|
|
138
|
+
describe: "Link the current directory to a Neon project",
|
|
139
|
+
load: () => import("./link.js")
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
command: "open",
|
|
143
|
+
describe: "Open the linked project in the Neon Console",
|
|
144
|
+
load: () => import("./open.js")
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
command: "claim",
|
|
148
|
+
aliases: ["claimable"],
|
|
149
|
+
describe: "Create and claim temporary Neon projects",
|
|
150
|
+
load: () => import("./claim.js")
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
command: "init",
|
|
154
|
+
describe: "Set up coding agents and this directory for Neon. -y is Recommended. -y with Custom flags applies those answers without prompts.",
|
|
155
|
+
load: () => import("./init.js")
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
command: "mcp",
|
|
159
|
+
describe: "Install the Neon MCP server into coding agents",
|
|
160
|
+
load: () => import("./mcp.js")
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
command: "plugins",
|
|
164
|
+
aliases: ["plugin"],
|
|
165
|
+
describe: "Install the Neon plugin into coding agents",
|
|
166
|
+
load: () => import("./plugins.js")
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
command: "skills",
|
|
170
|
+
aliases: ["skill"],
|
|
171
|
+
describe: "Install Neon agent skills into coding agents",
|
|
172
|
+
load: () => import("./skills.js")
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
command: "ask",
|
|
176
|
+
describe: "Ask a question about Neon",
|
|
177
|
+
load: () => import("./ask.js")
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
command: "data-api",
|
|
181
|
+
describe: "Manage the Neon Data API for a database",
|
|
182
|
+
load: () => import("./data_api.js")
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
command: "functions",
|
|
186
|
+
aliases: ["function"],
|
|
187
|
+
describe: "Manage Neon Functions",
|
|
188
|
+
load: () => import("./functions.js")
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
command: "triggers",
|
|
192
|
+
aliases: ["trigger"],
|
|
193
|
+
describe: "Manage function triggers",
|
|
194
|
+
load: () => import("./triggers.js")
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
command: "credentials",
|
|
198
|
+
aliases: ["credential"],
|
|
199
|
+
describe: "Manage branch credentials",
|
|
200
|
+
load: () => import("./credentials.js")
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
command: "dev",
|
|
204
|
+
describe: "Run Neon Functions locally with a dev server",
|
|
205
|
+
load: () => import("./dev.js")
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
command: "diff [compare-branch]",
|
|
209
|
+
describe: "Show a git-style schema diff between the current branch and another branch",
|
|
210
|
+
load: () => import("./diff.js")
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
command: "config",
|
|
214
|
+
describe: "Manage a branch with a neon.ts policy",
|
|
215
|
+
load: () => import("./config.js")
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
command: "status",
|
|
219
|
+
describe: "Show the branch's live Neon state (alias of `config status`)",
|
|
220
|
+
load: () => import("./status.js")
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
command: "deploy",
|
|
224
|
+
describe: "Apply a neon.ts policy to a branch (alias for `config apply`)",
|
|
225
|
+
load: () => import("./deploy.js")
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
command: "env",
|
|
229
|
+
describe: "Manage a branch's Neon env variables locally",
|
|
230
|
+
load: () => import("./env.js")
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
command: "buckets",
|
|
234
|
+
aliases: ["bucket"],
|
|
235
|
+
describe: "Manage branch object-storage buckets and their objects",
|
|
236
|
+
load: () => import("./bucket.js")
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
command: "bootstrap [directory]",
|
|
240
|
+
describe: "Scaffold a new project from a Neon starter template, then install agent tooling and link a Neon project",
|
|
241
|
+
load: () => import("./bootstrap.js")
|
|
242
|
+
}
|
|
243
|
+
];
|
|
244
|
+
const COMPLETION_COMMAND = "completion";
|
|
245
|
+
const COMPLETION_FLAG = "--get-yargs-completions";
|
|
246
|
+
const verbOf = (entry) => entry.command.split(" ")[0];
|
|
247
|
+
const entryByName = new Map(commandManifest.flatMap((entry) => [verbOf(entry), ...entry.aliases ?? []].map((name) => [name, entry])));
|
|
248
|
+
/**
|
|
249
|
+
* The command yargs 17 will run for these top-level positionals: it walks them in order,
|
|
250
|
+
* skips `completion`, runs the first one that names a command, and stops at the first one
|
|
251
|
+
* that doesn't (`kRunYargsParserAndExecuteCommands` in yargs-factory.js).
|
|
252
|
+
*/
|
|
253
|
+
const selectCommand = (positionals) => {
|
|
254
|
+
const first = positionals.find((p) => String(p) !== COMPLETION_COMMAND);
|
|
255
|
+
return first === void 0 ? void 0 : entryByName.get(String(first));
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* The command whose builder yargs 17 runs to complete `--get-yargs-completions <words>`: the
|
|
259
|
+
* first word that is a command's canonical name, at any position; aliases don't count there
|
|
260
|
+
* (`defaultCompletion` in completion.js looks words up in the handler map, keyed by name).
|
|
261
|
+
*/
|
|
262
|
+
const selectCompletionCommand = (words) => words.map((word) => commandManifest.find((entry) => verbOf(entry) === word)).find((entry) => entry);
|
|
263
|
+
function assertHasGetOptions(argv) {
|
|
264
|
+
if (!("getOptions" in argv) || typeof argv.getOptions !== "function") throw new Error("yargs no longer exposes getOptions(); update preloadCommand for the installed yargs");
|
|
265
|
+
}
|
|
266
|
+
const loaded = /* @__PURE__ */ new Map();
|
|
267
|
+
/**
|
|
268
|
+
* Import the module of the command yargs is about to run, before it runs, so its builder can
|
|
269
|
+
* stay synchronous. Parses argv with yargs' own parser and the top-level options yargs will
|
|
270
|
+
* use, so an option value that happens to be a command name (`--api-key projects`) can't
|
|
271
|
+
* change the answer.
|
|
272
|
+
*/
|
|
273
|
+
const preloadCommand = async (cli, args) => {
|
|
274
|
+
const doubleDash = args.indexOf("--");
|
|
275
|
+
const completionAt = (doubleDash === -1 ? args : args.slice(0, doubleDash)).indexOf(COMPLETION_FLAG);
|
|
276
|
+
let entry;
|
|
277
|
+
if (completionAt >= 0) entry = selectCompletionCommand(args.slice(completionAt + 1));
|
|
278
|
+
else {
|
|
279
|
+
assertHasGetOptions(cli);
|
|
280
|
+
const options = cli.getOptions();
|
|
281
|
+
const { argv } = Parser.detailed([...args], {
|
|
282
|
+
...options,
|
|
283
|
+
configuration: {
|
|
284
|
+
...options?.configuration,
|
|
285
|
+
"populate--": true,
|
|
286
|
+
"parse-positional-numbers": false
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
entry = selectCommand(argv._);
|
|
290
|
+
}
|
|
291
|
+
if (entry && !loaded.has(entry)) loaded.set(entry, await entry.load());
|
|
292
|
+
return entry;
|
|
293
|
+
};
|
|
294
|
+
/**
|
|
295
|
+
* The manifest as yargs command modules. The builder is synchronous when `preloadCommand`
|
|
296
|
+
* already imported the module, which is every invocation it predicts correctly. A mispredicted
|
|
297
|
+
* command still runs, because yargs 17 awaits a builder's promise when it runs a command; shell
|
|
298
|
+
* completion does not await it, so a mispredicted completion lists no subcommands.
|
|
299
|
+
*/
|
|
300
|
+
const lazyCommands = commandManifest.map((entry) => ({
|
|
301
|
+
command: entry.command,
|
|
302
|
+
aliases: entry.aliases,
|
|
303
|
+
describe: entry.describe,
|
|
304
|
+
builder: (argv) => {
|
|
305
|
+
const mod = loaded.get(entry);
|
|
306
|
+
return mod ? mod.builder(argv) : entry.load().then((m) => {
|
|
307
|
+
loaded.set(entry, m);
|
|
308
|
+
return m.builder(argv);
|
|
309
|
+
});
|
|
310
|
+
},
|
|
311
|
+
handler: async (args) => {
|
|
312
|
+
return (loaded.get(entry) ?? await entry.load()).handler?.(args);
|
|
313
|
+
}
|
|
314
|
+
}));
|
|
315
|
+
//#endregion
|
|
316
|
+
export { commandManifest, lazyCommands, preloadCommand, selectCommand, selectCompletionCommand };
|
package/dist/commands/mcp.js
CHANGED
|
@@ -4,11 +4,11 @@ import { readContextFile } from "../context.js";
|
|
|
4
4
|
import { recordCommandSuccessExtras } from "../analytics.js";
|
|
5
5
|
import { getCliName } from "../utils/cli_name.js";
|
|
6
6
|
import { helpCsv, helpEpilogue } from "../utils/help_text.js";
|
|
7
|
+
import { NEON_MCP_CATEGORIES, NEON_MCP_URL, existingNeonApiKey, installNeonMcpServer, neonMcpUrl, parseMcpCategories, trackedProjectMcpConfig } from "../mcp/install.js";
|
|
8
|
+
import { mcpInstallableAgents, resolveInstallTargets } from "../mcp/targets.js";
|
|
7
9
|
import { writer } from "../writer.js";
|
|
8
10
|
import { noPassthrough, single } from "../utils/flags.js";
|
|
9
11
|
import { AGENT_MCP_SKIP_MESSAGE } from "../init/copy.js";
|
|
10
|
-
import { NEON_MCP_CATEGORIES, NEON_MCP_URL, existingNeonApiKey, installNeonMcpServer, neonMcpUrl, parseMcpCategories, trackedProjectMcpConfig } from "../mcp/install.js";
|
|
11
|
-
import { mcpInstallableAgents, resolveInstallTargets } from "../mcp/targets.js";
|
|
12
12
|
import { mintMcpApiKey, mintedKeyRevokeCommand, withdrawMintedKey } from "../mcp/mint.js";
|
|
13
13
|
import { canPickAgentsInteractively, skippableAgentPicker } from "../utils/agent_picker.js";
|
|
14
14
|
import { resolveMcpPlan } from "../mcp/plan.js";
|
package/dist/commands/plugins.js
CHANGED
|
@@ -2,13 +2,13 @@ import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
|
2
2
|
import { log } from "../log.js";
|
|
3
3
|
import { recordCommandSuccessExtras } from "../analytics.js";
|
|
4
4
|
import { helpCsv, helpEpilogue } from "../utils/help_text.js";
|
|
5
|
-
import { writer } from "../writer.js";
|
|
6
|
-
import { noPassthrough } from "../utils/flags.js";
|
|
7
|
-
import { AGENT_PLUGIN_SKIP_MESSAGE } from "../init/copy.js";
|
|
8
5
|
import { getAgentDisplayName } from "../mcp/agents.js";
|
|
9
6
|
import { NEON_MCP_URL } from "../mcp/install.js";
|
|
10
7
|
import "../init/agents.js";
|
|
11
8
|
import { pluginsInstallableAgents } from "../plugins/targets.js";
|
|
9
|
+
import { writer } from "../writer.js";
|
|
10
|
+
import { noPassthrough } from "../utils/flags.js";
|
|
11
|
+
import { AGENT_PLUGIN_SKIP_MESSAGE } from "../init/copy.js";
|
|
12
12
|
import { canPickAgentsInteractively, skippableAgentPicker } from "../utils/agent_picker.js";
|
|
13
13
|
import { resolvePluginsPlan } from "../plugins/plan.js";
|
|
14
14
|
import { NEON_PLUGIN_NAME, PLUGIN_SKILLS, PLUGIN_SOURCE, neonPluginsRetryCommand, pluginsAddArgs, runPluginsCli } from "../plugins/run.js";
|
package/dist/commands/profile.js
CHANGED
|
@@ -11,10 +11,10 @@ import { auth, revokeToken } from "../auth.js";
|
|
|
11
11
|
import { t as credentialInputs } from "../_chunks/auth_selection-pitMFzDe.js";
|
|
12
12
|
import { readOutgoingCredential, retirePreviousCredential, revokeTokenSet, withdrawKey } from "../retire_credential.js";
|
|
13
13
|
import { authFlow, usableCredential } from "./auth.js";
|
|
14
|
+
import { identityFromAuthDetails, isApiKeyMethod, mintedKeyName, notAnApiKeyMessage } from "../profile_keys.js";
|
|
14
15
|
import { writer } from "../writer.js";
|
|
15
16
|
import { noPassthrough, single } from "../utils/flags.js";
|
|
16
17
|
import { orgIdForProject } from "./api_keys.js";
|
|
17
|
-
import { identityFromAuthDetails, isApiKeyMethod, mintedKeyName, notAnApiKeyMessage } from "../profile_keys.js";
|
|
18
18
|
import { existsSync, readFileSync, rmSync } from "node:fs";
|
|
19
19
|
import { isAbsolute, relative } from "node:path";
|
|
20
20
|
import prompts from "prompts";
|
|
@@ -4,8 +4,8 @@ import { log } from "../log.js";
|
|
|
4
4
|
import { isNeonApiError, messageFromBody } from "../api.js";
|
|
5
5
|
import { updateContextFile } from "../context.js";
|
|
6
6
|
import { getCliName } from "../utils/cli_name.js";
|
|
7
|
-
import { writer } from "../writer.js";
|
|
8
7
|
import { projectCreateRequest, projectUpdateRequest } from "../parameters.gen.js";
|
|
8
|
+
import { writer } from "../writer.js";
|
|
9
9
|
import { getComputeUnits } from "../utils/compute_units.js";
|
|
10
10
|
import { psql } from "../utils/psql.js";
|
|
11
11
|
import prompts from "prompts";
|
|
@@ -2,7 +2,7 @@ import { log } from "../log.js";
|
|
|
2
2
|
import { isNeonApiError, messageFromBody } from "../api.js";
|
|
3
3
|
import { sendError } from "../analytics.js";
|
|
4
4
|
import { writer } from "../writer.js";
|
|
5
|
-
import {
|
|
5
|
+
import { listAllProjectBranchesWithAnnotations, resolveBranchFromProps } from "../utils/enrichers.js";
|
|
6
6
|
import { parsePointInTime } from "../utils/point_in_time.js";
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
import { createPatch } from "diff";
|
|
@@ -15,12 +15,14 @@ const COLORS = {
|
|
|
15
15
|
};
|
|
16
16
|
const schemaDiff = async (props) => {
|
|
17
17
|
props.branch = props.baseBranch || props.branch;
|
|
18
|
-
const baseBranch = await
|
|
18
|
+
const { branchId: baseBranch, branch: baseBranchData, listing } = await resolveBranchFromProps(props, props.branchListing);
|
|
19
19
|
let pointInTime = await parsePointInTime({
|
|
20
20
|
pointInTime: props.compareSource,
|
|
21
21
|
targetBranchId: baseBranch,
|
|
22
22
|
projectId: props.projectId,
|
|
23
|
-
api: props.apiClient
|
|
23
|
+
api: props.apiClient,
|
|
24
|
+
branches: listing?.branches,
|
|
25
|
+
targetBranch: baseBranchData
|
|
24
26
|
});
|
|
25
27
|
const comparingWithParent = props.compareSource.startsWith("^parent");
|
|
26
28
|
let baseBranchPoint = {
|
|
@@ -32,21 +34,35 @@ const schemaDiff = async (props) => {
|
|
|
32
34
|
if (props.database) {
|
|
33
35
|
const database = baseDatabases.find((db) => db.name === props.database);
|
|
34
36
|
if (!database) throw new Error(`Database ${props.database} does not exist in base branch ${baseBranch}`);
|
|
35
|
-
const
|
|
36
|
-
writer(props).text(colorize(patch));
|
|
37
|
+
const diff = await createSchemaDiff(baseBranchPoint, pointInTime, database, props);
|
|
38
|
+
writer(props).text(colorize(diff.patch));
|
|
39
|
+
reportUnchanged(diff, [baseBranchPoint, pointInTime], database, props, listing);
|
|
37
40
|
return;
|
|
38
41
|
}
|
|
39
42
|
await Promise.all(baseDatabases.map(async (database) => {
|
|
40
|
-
const
|
|
41
|
-
writer(props).text(colorize(patch));
|
|
43
|
+
const diff = await createSchemaDiff(baseBranchPoint, pointInTime, database, props);
|
|
44
|
+
writer(props).text(colorize(diff.patch));
|
|
45
|
+
reportUnchanged(diff, [baseBranchPoint, pointInTime], database, props, listing);
|
|
42
46
|
}));
|
|
43
47
|
};
|
|
48
|
+
/** The patch alone is two header lines when nothing differs, which reads like missing output. */
|
|
49
|
+
const reportUnchanged = (diff, [base, compare], database, props, listing) => {
|
|
50
|
+
if (!diff.unchanged || props.output !== "table") return;
|
|
51
|
+
const label = (point) => {
|
|
52
|
+
const name = listing?.branches.find((b) => b.id === point.branchId)?.name ?? point.branchId;
|
|
53
|
+
return point.tag === "lsn" ? `${name} at ${point.lsn}` : point.tag === "timestamp" ? `${name} at ${point.timestamp}` : name;
|
|
54
|
+
};
|
|
55
|
+
log.info(`No schema differences for database ${database.name} between ${label(base)} and ${label(compare)}.`);
|
|
56
|
+
};
|
|
44
57
|
const fetchDatabases = async (branch, props) => {
|
|
45
58
|
return props.apiClient.listProjectBranchDatabases(props.projectId, branch).then((response) => response.data.databases);
|
|
46
59
|
};
|
|
47
60
|
const createSchemaDiff = async (baseBranch, pointInTime, database, props) => {
|
|
48
61
|
const [baseSchema, compareSchema] = await Promise.all([fetchSchema(baseBranch, database, props), fetchSchema(pointInTime, database, props)]);
|
|
49
|
-
return
|
|
62
|
+
return {
|
|
63
|
+
patch: createPatch(`Database: ${database.name}`, baseSchema, compareSchema, generateHeader(baseBranch), generateHeader(pointInTime)),
|
|
64
|
+
unchanged: baseSchema === compareSchema
|
|
65
|
+
};
|
|
50
66
|
};
|
|
51
67
|
const fetchSchema = async (pointInTime, database, props) => {
|
|
52
68
|
try {
|
|
@@ -68,6 +84,7 @@ const colorize = (patch) => {
|
|
|
68
84
|
return patch.replace(/^([^\n]+)\n([^\n]+)\n/m, "").replace(/^-.*/gm, colorizer("removed")).replace(/^\+.*/gm, colorizer("added")).replace(/^@@.+@@.*/gm, colorizer("section"));
|
|
69
85
|
};
|
|
70
86
|
const colorizer = (colorId) => {
|
|
87
|
+
if (process.env.NO_COLOR) return (line) => line;
|
|
71
88
|
const color = COLORS[colorId];
|
|
72
89
|
return (line) => color(line);
|
|
73
90
|
};
|
|
@@ -92,11 +109,13 @@ const parseSchemaDiffParams = async (props) => {
|
|
|
92
109
|
props.compareSource = props.baseBranch;
|
|
93
110
|
props.baseBranch = props.branch;
|
|
94
111
|
} else if (props.branch) {
|
|
95
|
-
|
|
112
|
+
props.branchListing = await listAllProjectBranchesWithAnnotations(props.apiClient, props.projectId);
|
|
113
|
+
if (props.branchListing.branches.find((b) => b.id === props.branch || b.name === props.branch)?.parent_id == void 0) throw new Error(`No branch specified. Your context branch (${props.branch}) has no parent, so no comparison is possible.`);
|
|
96
114
|
log.info(`No branches specified. Comparing your context branch '${props.branch}' with its parent`);
|
|
97
115
|
props.compareSource = "^parent";
|
|
98
116
|
} else {
|
|
99
|
-
|
|
117
|
+
props.branchListing = await listAllProjectBranchesWithAnnotations(props.apiClient, props.projectId);
|
|
118
|
+
if (props.branchListing.branches.find((b) => b.default)?.parent_id == void 0) throw new Error("No branch specified. Include a base branch or add a set-context branch to continue. Your default branch has no parent, so no comparison is possible.");
|
|
100
119
|
log.info(`No branches specified. Comparing default branch with its parent`);
|
|
101
120
|
props.compareSource = "^parent";
|
|
102
121
|
}
|
package/dist/commands/skills.js
CHANGED
|
@@ -2,12 +2,12 @@ import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
|
|
|
2
2
|
import { log } from "../log.js";
|
|
3
3
|
import { recordCommandSuccessExtras } from "../analytics.js";
|
|
4
4
|
import { helpCsv, helpEpilogue } from "../utils/help_text.js";
|
|
5
|
-
import { writer } from "../writer.js";
|
|
6
|
-
import { noPassthrough } from "../utils/flags.js";
|
|
7
|
-
import { AGENT_SKILLS_SKIP_MESSAGE } from "../init/copy.js";
|
|
8
5
|
import { getAgentDisplayName } from "../mcp/agents.js";
|
|
9
6
|
import "../init/agents.js";
|
|
10
7
|
import { mappedSkillsAgentNames, skillsInstallableAgents } from "../skills/targets.js";
|
|
8
|
+
import { writer } from "../writer.js";
|
|
9
|
+
import { noPassthrough } from "../utils/flags.js";
|
|
10
|
+
import { AGENT_SKILLS_SKIP_MESSAGE } from "../init/copy.js";
|
|
11
11
|
import { canPickAgentsInteractively, skippableAgentPicker } from "../utils/agent_picker.js";
|
|
12
12
|
import { skillsHelpValues, skillsYesHelp } from "../skills/catalog.js";
|
|
13
13
|
import { confirmSkillsUpdate } from "../skills/wizard.js";
|
package/dist/human_table.js
CHANGED
|
@@ -22,8 +22,11 @@ function parseColumns(value) {
|
|
|
22
22
|
if (!Number.isFinite(n) || n <= 0) return;
|
|
23
23
|
return n;
|
|
24
24
|
}
|
|
25
|
+
function stripAnsi(s) {
|
|
26
|
+
return s.replace(ANSI_RE, "");
|
|
27
|
+
}
|
|
25
28
|
function displayWidth(s) {
|
|
26
|
-
const plain = s
|
|
29
|
+
const plain = stripAnsi(s);
|
|
27
30
|
let width = 0;
|
|
28
31
|
for (const char of plain) {
|
|
29
32
|
const code = char.codePointAt(0);
|
|
@@ -203,4 +206,4 @@ function charWidth(code) {
|
|
|
203
206
|
return 1;
|
|
204
207
|
}
|
|
205
208
|
//#endregion
|
|
206
|
-
export { displayWidth, formatHumanChunk, parseColumns, resolveOutputWidth };
|
|
209
|
+
export { displayWidth, formatHumanChunk, parseColumns, resolveOutputWidth, stripAnsi };
|
package/dist/index.js
CHANGED
|
@@ -12,8 +12,8 @@ import { getCliName } from "./utils/cli_name.js";
|
|
|
12
12
|
import { ensureAuth } from "./commands/auth.js";
|
|
13
13
|
import { recoverFrom401 } from "./auth_recovery.js";
|
|
14
14
|
import { UsageError, failOnUsageError, isBareParentCommand, showHelp, showUsageErrorHelp } from "./help.js";
|
|
15
|
+
import { lazyCommands, preloadCommand } from "./commands/manifest.js";
|
|
15
16
|
import { rewriteUnknownAgentArg } from "./init/plan.js";
|
|
16
|
-
import commands_default from "./commands/index.js";
|
|
17
17
|
import { recoverFromSSO } from "./sso_recovery.js";
|
|
18
18
|
import { notifyIfUpdateAvailable } from "./update_notifier.js";
|
|
19
19
|
import { fillInArgs, resolveApiKeyFromEnv } from "./utils/middlewares.js";
|
|
@@ -128,7 +128,7 @@ builder = builder.scriptName(pkg_default.name).locale("en").usage("$0 <command>
|
|
|
128
128
|
if (args.help) await showHelp(builder);
|
|
129
129
|
}, true).middleware(async (args) => {
|
|
130
130
|
if (args._.length === 1 && !NO_SUBCOMMANDS_VERBS.includes(args._[0]) || args._.length > 1 && isBareParentCommand(builder, args._)) await showHelp(builder);
|
|
131
|
-
}).middleware(ensureAuth).middleware(enrichFromContext).middleware(analyticsMiddleware).command(
|
|
131
|
+
}).middleware(ensureAuth).middleware(enrichFromContext).middleware(analyticsMiddleware).command(lazyCommands).strictCommands().version(pkg_default.version).group("version", "Global options:").alias("version", "v").completion().scriptName(getCliName()).epilog("For more information, visit https://neon.com/docs/reference/neon-cli").wrap(null).fail(failOnUsageError);
|
|
132
132
|
async function handleError(msg, err, canRetry) {
|
|
133
133
|
if (process.argv.some((arg) => arg === "--help" || arg === "-h")) {
|
|
134
134
|
await showHelp(builder);
|
|
@@ -194,6 +194,7 @@ async function handleError(msg, err, canRetry) {
|
|
|
194
194
|
(async () => {
|
|
195
195
|
let attempts = 0;
|
|
196
196
|
const MAX_ATTEMPTS = 2;
|
|
197
|
+
await preloadCommand(builder, hideBin(process.argv));
|
|
197
198
|
while (attempts < MAX_ATTEMPTS) try {
|
|
198
199
|
const args = await builder.argv;
|
|
199
200
|
trackEvent("cli_command_success", commandSuccessProperties(args));
|
package/dist/init/mode.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { NON_TTY_AGENT_SETUP, NO_AGENT_SETUP_CONFLICT } from "./copy.js";
|
|
2
1
|
import { INIT_NEEDS_YES_OR_TERMINAL } from "./plan.js";
|
|
2
|
+
import { NON_TTY_AGENT_SETUP, NO_AGENT_SETUP_CONFLICT } from "./copy.js";
|
|
3
3
|
//#region src/init/mode.ts
|
|
4
4
|
const hasInitMcpFlags = (input) => input.mcpConfigLocation !== void 0 || input.mcpAuth !== void 0 || input.mcpProjectScoped === true;
|
|
5
5
|
const hasSkillsFlag = (skills) => skills !== void 0 && skills.length > 0;
|
package/dist/init/run.js
CHANGED
|
@@ -8,16 +8,16 @@ import { readLinkedClaimableCredentials } from "../claimable/state.js";
|
|
|
8
8
|
import { getCliName } from "../utils/cli_name.js";
|
|
9
9
|
import { deprecatedServiceMessage, parseServices, servicesFlagValue } from "../neon_services.js";
|
|
10
10
|
import { CONFIG_INIT_NONE_MEANS, CONFIG_INIT_SERVICES, CONFIG_INIT_UNAVAILABLE } from "../config_template.js";
|
|
11
|
-
import { CANCELLED_BODY, CLAIMABLE_ACCOUNT_FLAGS, CLAIMABLE_ALREADY_LINKED, CLAIMABLE_MCP_API_KEY, CLAIMABLE_NO_LINK, MCP_SCOPED_NEEDS_PROJECT, NON_TTY_LINK_NEEDS_AUTH, NO_AGENTS_FALLBACK_STATUS, PROGRESS, YES_LINK_NEEDS_AUTH, claimableNext, claimableThenServicesNext, envPullFailedNext, existingConfigNext, extraServicesNext, installFailedNext, mcpConfigLocationSkipped, mcpConfigLocationUnavailable, namedAgentsUnavailable, skippedLinkNext, unattendedUnauthedNext } from "./copy.js";
|
|
12
|
-
import { agentsRowValue, configRowValue, formatInitDone, headingForKind, printInitBanner, printInitDone, printInitProgress, projectRowValue, shouldPrintInitBanner } from "./chrome.js";
|
|
13
|
-
import { inferPackageManager, resolvePackageManager } from "../utils/package_manager.js";
|
|
14
|
-
import { ConfigInstallFailed, hasNeonConfigFile, initCmd, neonConfigFilename } from "../commands/config.js";
|
|
15
|
-
import { runAuthenticatedLink } from "./link.js";
|
|
16
11
|
import { getAgentDisplayName } from "../mcp/agents.js";
|
|
17
12
|
import { mcpInstallableAgents } from "../mcp/targets.js";
|
|
18
13
|
import { missingPluginsCommands, pluginsInstallableAgents } from "../plugins/targets.js";
|
|
19
14
|
import { skillsInstallableAgents } from "../skills/targets.js";
|
|
20
15
|
import { FALLBACK_SKILLS_AGENTS, assertNamedAgentTooling, funnelAgentSetup, planInitToolingSteps, recommendedTooling, resolveNamedAgents, splitInitTooling } from "./plan.js";
|
|
16
|
+
import { inferPackageManager, resolvePackageManager } from "../utils/package_manager.js";
|
|
17
|
+
import { CANCELLED_BODY, CLAIMABLE_ACCOUNT_FLAGS, CLAIMABLE_ALREADY_LINKED, CLAIMABLE_MCP_API_KEY, CLAIMABLE_NO_LINK, MCP_SCOPED_NEEDS_PROJECT, NON_TTY_LINK_NEEDS_AUTH, NO_AGENTS_FALLBACK_STATUS, PROGRESS, YES_LINK_NEEDS_AUTH, claimableNext, claimableThenServicesNext, envPullFailedNext, existingConfigNext, extraServicesNext, installFailedNext, mcpConfigLocationSkipped, mcpConfigLocationUnavailable, namedAgentsUnavailable, skippedLinkNext, unattendedUnauthedNext } from "./copy.js";
|
|
18
|
+
import { agentsRowValue, configRowValue, formatInitDone, headingForKind, printInitBanner, printInitDone, printInitProgress, projectRowValue, shouldPrintInitBanner } from "./chrome.js";
|
|
19
|
+
import { ConfigInstallFailed, hasNeonConfigFile, initCmd, neonConfigFilename } from "../commands/config.js";
|
|
20
|
+
import { runAuthenticatedLink } from "./link.js";
|
|
21
21
|
import { pullInitEnv } from "./auth.js";
|
|
22
22
|
import { InitCancelled, raceSigint, restoreCursor } from "./cancelled.js";
|
|
23
23
|
import { pickAgentSetupInteractively, pickInitAgentsInteractively, pickInitConfigInteractively, pickInitMcpAuthInteractively, pickInitMcpConfigLocationInteractively, pickInitModeInteractively, pickInitPackageManagerInteractively, pickInitProjectSetupInteractively, pickInitServicesInteractively, pickInitSkillsInteractively } from "./wizard.js";
|
package/dist/init/tooling.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { log } from "../log.js";
|
|
2
2
|
import { getCliName } from "../utils/cli_name.js";
|
|
3
|
-
import { PROGRESS } from "./copy.js";
|
|
4
3
|
import { assertNamedAgentTooling, chooseYesAgentTooling, collectYesAgents, initYesSupportedAgents, noDetectedAgentsMessage, planAgentSteps, planToolingSteps, planYesAgentSteps, resolveInitAgentSetup } from "./plan.js";
|
|
4
|
+
import { PROGRESS } from "./copy.js";
|
|
5
5
|
import { detectAgent } from "./detect_host.js";
|
|
6
6
|
import { AgentSelectionSkipped, canPickAgentsInteractively } from "../utils/agent_picker.js";
|
|
7
7
|
import { mcpInstallError, reportMcpInstall } from "../commands/mcp.js";
|
package/dist/init/wizard.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { CONFIG_INIT_SERVICES } from "../config_template.js";
|
|
2
|
-
import { AGENT_DETECTED_DESCRIPTION, AGENT_MCP_PICKER_MESSAGE, AGENT_MCP_SKIP_MESSAGE, AGENT_OTHER_DESCRIPTION, AGENT_PICKER_MESSAGE, AGENT_PLUGIN_SKIP_MESSAGE, AGENT_SETUP_MESSAGE, AGENT_SETUP_PLUGIN_DESCRIPTION, AGENT_SETUP_PLUGIN_TITLE, AGENT_SETUP_SKILLS_DESCRIPTION, AGENT_SETUP_SKILLS_TITLE, AGENT_SETUP_SKIP_DESCRIPTION, AGENT_SETUP_SKIP_TITLE, AGENT_SKILLS_PICKER_MESSAGE, AGENT_SKILLS_SKIP_MESSAGE, CONFIG_CONFIRM_HINT, CONFIG_CONFIRM_MESSAGE, MCP_AUTH_API_KEY_DESCRIPTION, MCP_AUTH_API_KEY_TITLE, MCP_AUTH_MESSAGE, MCP_AUTH_OAUTH_DESCRIPTION, MCP_AUTH_OAUTH_TITLE, MCP_SCOPE_GLOBAL_DESCRIPTION, MCP_SCOPE_GLOBAL_TITLE, MCP_SCOPE_MESSAGE, MCP_SCOPE_PROJECT_DESCRIPTION, MCP_SCOPE_PROJECT_TITLE, MODE_CUSTOM_DESCRIPTION, MODE_CUSTOM_TITLE, MODE_MESSAGE, MODE_RECOMMENDED_DESCRIPTION, MODE_RECOMMENDED_TITLE, PACKAGE_MANAGER_MESSAGE, PROJECT_SETUP_CLAIMABLE_DESCRIPTION, PROJECT_SETUP_CLAIMABLE_TITLE, PROJECT_SETUP_LINK_DESCRIPTION, PROJECT_SETUP_LINK_TITLE, PROJECT_SETUP_MESSAGE, SERVICES_HINT, SERVICES_MESSAGE, SKILLS_PICKER_MESSAGE, agentMissingCommandDescription } from "./copy.js";
|
|
3
|
-
import { installedPackageManagers } from "../utils/package_manager.js";
|
|
4
|
-
import { POSTGRES_SERVICE_CHOICE, keepPostgresSelected } from "../utils/service_picker.js";
|
|
5
2
|
import { getAgentDisplayName, listMcpAgentIds } from "../mcp/agents.js";
|
|
6
3
|
import { INIT_NEEDS_YES_OR_TERMINAL } from "./plan.js";
|
|
4
|
+
import { installedPackageManagers } from "../utils/package_manager.js";
|
|
5
|
+
import { AGENT_DETECTED_DESCRIPTION, AGENT_MCP_PICKER_MESSAGE, AGENT_MCP_SKIP_MESSAGE, AGENT_OTHER_DESCRIPTION, AGENT_PICKER_MESSAGE, AGENT_PLUGIN_SKIP_MESSAGE, AGENT_SETUP_MESSAGE, AGENT_SETUP_PLUGIN_DESCRIPTION, AGENT_SETUP_PLUGIN_TITLE, AGENT_SETUP_SKILLS_DESCRIPTION, AGENT_SETUP_SKILLS_TITLE, AGENT_SETUP_SKIP_DESCRIPTION, AGENT_SETUP_SKIP_TITLE, AGENT_SKILLS_PICKER_MESSAGE, AGENT_SKILLS_SKIP_MESSAGE, CONFIG_CONFIRM_HINT, CONFIG_CONFIRM_MESSAGE, MCP_AUTH_API_KEY_DESCRIPTION, MCP_AUTH_API_KEY_TITLE, MCP_AUTH_MESSAGE, MCP_AUTH_OAUTH_DESCRIPTION, MCP_AUTH_OAUTH_TITLE, MCP_SCOPE_GLOBAL_DESCRIPTION, MCP_SCOPE_GLOBAL_TITLE, MCP_SCOPE_MESSAGE, MCP_SCOPE_PROJECT_DESCRIPTION, MCP_SCOPE_PROJECT_TITLE, MODE_CUSTOM_DESCRIPTION, MODE_CUSTOM_TITLE, MODE_MESSAGE, MODE_RECOMMENDED_DESCRIPTION, MODE_RECOMMENDED_TITLE, PACKAGE_MANAGER_MESSAGE, PROJECT_SETUP_CLAIMABLE_DESCRIPTION, PROJECT_SETUP_CLAIMABLE_TITLE, PROJECT_SETUP_LINK_DESCRIPTION, PROJECT_SETUP_LINK_TITLE, PROJECT_SETUP_MESSAGE, SERVICES_HINT, SERVICES_MESSAGE, SKILLS_PICKER_MESSAGE, agentMissingCommandDescription } from "./copy.js";
|
|
6
|
+
import { POSTGRES_SERVICE_CHOICE, keepPostgresSelected } from "../utils/service_picker.js";
|
|
7
7
|
import { canPickAgentsInteractively, pickAgentsInteractively } from "../utils/agent_picker.js";
|
|
8
8
|
import { NEON_SKILL_CATALOG, listSkillIds } from "../skills/catalog.js";
|
|
9
9
|
import { InitCancelled, restoreCursorVisibilityOnAbort } from "./cancelled.js";
|
package/dist/mcp/install.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { chmodSync, existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { basename, dirname, join } from "node:path";
|
|
3
|
-
import { execFileSync } from "node:child_process";
|
|
4
3
|
import { agents, upsertServer } from "add-mcp";
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
5
|
//#region src/mcp/install.ts
|
|
6
6
|
const NEON_MCP_URL = "https://mcp.neon.tech/mcp";
|
|
7
7
|
const NEON_MCP_NAME = "Neon";
|
package/dist/mcp/mint.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { log } from "../log.js";
|
|
2
2
|
import { isNeonApiError } from "../api.js";
|
|
3
3
|
import { getCliName } from "../utils/cli_name.js";
|
|
4
|
-
import { orgIdForProject } from "../commands/api_keys.js";
|
|
5
4
|
import { mintedKeyName } from "../profile_keys.js";
|
|
5
|
+
import { orgIdForProject } from "../commands/api_keys.js";
|
|
6
6
|
//#region src/mcp/mint.ts
|
|
7
7
|
const cannotMintMessage = "This CLI credential cannot mint API keys. Organization and project-scoped keys cannot create other keys. Sign in with `neon auth` or pass a personal API key.";
|
|
8
8
|
function mintedKeyRevokeCommand(key) {
|
package/dist/plugins/targets.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { detectInstalledAgents, listMcpAgentIds, tryResolveAddMcpAgentId, uniqueAgentIds } from "../mcp/agents.js";
|
|
2
2
|
import "../init/agents.js";
|
|
3
3
|
import { delimiter, dirname, join, resolve } from "node:path";
|
|
4
|
-
import which from "which";
|
|
5
4
|
import { detectProjectAgents } from "add-mcp";
|
|
5
|
+
import which from "which";
|
|
6
6
|
//#region src/plugins/targets.ts
|
|
7
7
|
const CLAUDE_CODE = { target: "claude-code" };
|
|
8
8
|
const PLUGINS_TARGET_BY_TYPE = {
|
|
@@ -26,8 +26,15 @@ const reserveClosedPort = () => new Promise((resolve, reject) => {
|
|
|
26
26
|
const test = test$1.extend({
|
|
27
27
|
runMockServer: async ({}, use) => {
|
|
28
28
|
let startedServer;
|
|
29
|
-
await use(async (mockDir) => {
|
|
29
|
+
await use(async (mockDir, onRequest) => {
|
|
30
30
|
const app = express();
|
|
31
|
+
if (onRequest) app.use((req, _res, next) => {
|
|
32
|
+
onRequest({
|
|
33
|
+
method: req.method,
|
|
34
|
+
path: req.path
|
|
35
|
+
});
|
|
36
|
+
next();
|
|
37
|
+
});
|
|
31
38
|
app.use(express.json());
|
|
32
39
|
app.use("/", emocks(join(process.cwd(), "mocks", mockDir), { "404": (_req, res) => res.status(404).send({ message: "Not Found" }) }));
|
|
33
40
|
const server = await new Promise((resolve) => {
|
package/dist/update_notifier.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isCi } from "./env.js";
|
|
2
2
|
import { log } from "./log.js";
|
|
3
|
-
import { detectCliInstallMethod, recommendedCliUpgradeCommand } from "./utils/package_manager.js";
|
|
4
3
|
import { writeJsonFile } from "./utils/json_file.js";
|
|
5
4
|
import { showNotice } from "./notices.js";
|
|
5
|
+
import { detectCliInstallMethod, recommendedCliUpgradeCommand } from "./utils/package_manager.js";
|
|
6
6
|
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
7
7
|
import { basename, dirname, join } from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
package/dist/utils/enrichers.js
CHANGED
|
@@ -7,8 +7,9 @@ const BRANCHES_LIST_LIMIT = 100;
|
|
|
7
7
|
* Branch list pages cap at 100. A name stored in `.neon` can live on a later
|
|
8
8
|
* page, so resolution has to walk `pagination.next` before treating it as missing.
|
|
9
9
|
*/
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
const listAllProjectBranchesWithAnnotations = async (apiClient, projectId) => {
|
|
11
|
+
const branches = [];
|
|
12
|
+
const annotations = {};
|
|
12
13
|
let cursor;
|
|
13
14
|
while (true) {
|
|
14
15
|
const { data } = await apiClient.listProjectBranches({
|
|
@@ -16,16 +17,21 @@ const listAllProjectBranches = async (apiClient, projectId) => {
|
|
|
16
17
|
limit: BRANCHES_LIST_LIMIT,
|
|
17
18
|
cursor
|
|
18
19
|
});
|
|
19
|
-
|
|
20
|
+
branches.push(...data.branches);
|
|
21
|
+
Object.assign(annotations, data.annotations);
|
|
20
22
|
cursor = data.pagination?.next;
|
|
21
23
|
if (!cursor || data.branches.length === 0) break;
|
|
22
24
|
}
|
|
23
|
-
return
|
|
25
|
+
return {
|
|
26
|
+
branches,
|
|
27
|
+
annotations
|
|
28
|
+
};
|
|
24
29
|
};
|
|
25
|
-
const
|
|
30
|
+
const listAllProjectBranches = async (apiClient, projectId) => (await listAllProjectBranchesWithAnnotations(apiClient, projectId)).branches;
|
|
31
|
+
const branchIdResolve = async ({ branch, apiClient, projectId, branches: listed }) => {
|
|
26
32
|
branch = branch.toString();
|
|
27
33
|
if (looksLikeBranchId(branch)) return branch;
|
|
28
|
-
const branches = await listAllProjectBranches(apiClient, projectId);
|
|
34
|
+
const branches = listed ?? await listAllProjectBranches(apiClient, projectId);
|
|
29
35
|
const branchData = branches.find((b) => b.name === branch);
|
|
30
36
|
if (!branchData) throw new Error(`Branch ${branch} not found.\nAvailable branches: ${branches.map((b) => b.name).join(", ")}`);
|
|
31
37
|
return branchData.id;
|
|
@@ -45,6 +51,33 @@ const branchIdFromProps = async (props) => {
|
|
|
45
51
|
props.branchId = await getBranchIdFromProps(props);
|
|
46
52
|
return props.branchId;
|
|
47
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* {@link branchIdFromProps}, plus whatever the resolution already fetched: a name or the
|
|
56
|
+
* default branch is resolved from a listing, so the branch object and the listing come back
|
|
57
|
+
* with the id and callers need not fetch them again. An explicit `br-…` id is not listed.
|
|
58
|
+
*/
|
|
59
|
+
const resolveBranchFromProps = async (props, known) => {
|
|
60
|
+
const ref = typeof props.branch === "string" ? props.branch : props.id;
|
|
61
|
+
const explicit = ref ? String(ref) : void 0;
|
|
62
|
+
if (explicit !== void 0 && looksLikeBranchId(explicit)) {
|
|
63
|
+
props.branchId = explicit;
|
|
64
|
+
const branch = known?.branches.find((b) => b.id === explicit);
|
|
65
|
+
return branch ? {
|
|
66
|
+
branchId: explicit,
|
|
67
|
+
branch,
|
|
68
|
+
listing: known
|
|
69
|
+
} : { branchId: explicit };
|
|
70
|
+
}
|
|
71
|
+
const listing = known ?? await listAllProjectBranchesWithAnnotations(props.apiClient, props.projectId);
|
|
72
|
+
const branch = explicit === void 0 ? listing.branches.find((b) => b.default) : listing.branches.find((b) => b.name === explicit);
|
|
73
|
+
if (!branch) throw new Error(explicit === void 0 ? "No default branch found" : `Branch ${explicit} not found.\nAvailable branches: ${listing.branches.map((b) => b.name).join(", ")}`);
|
|
74
|
+
props.branchId = branch.id;
|
|
75
|
+
return {
|
|
76
|
+
branchId: branch.id,
|
|
77
|
+
branch,
|
|
78
|
+
listing
|
|
79
|
+
};
|
|
80
|
+
};
|
|
48
81
|
const resolveBranchRef = async (props) => {
|
|
49
82
|
const branch = typeof props.branch === "string" ? props.branch : props.id;
|
|
50
83
|
const branches = await listAllProjectBranches(props.apiClient, props.projectId);
|
|
@@ -130,4 +163,4 @@ const fillSingleOrg = async (props) => {
|
|
|
130
163
|
};
|
|
131
164
|
};
|
|
132
165
|
//#endregion
|
|
133
|
-
export { branchIdFromProps, branchIdResolve, fillSingleOrg, fillSingleProject, listAllProjectBranches, resolveBranchRef, resolveSingleDatabase };
|
|
166
|
+
export { branchIdFromProps, branchIdResolve, fillSingleOrg, fillSingleProject, listAllProjectBranches, listAllProjectBranchesWithAnnotations, resolveBranchFromProps, resolveBranchRef, resolveSingleDatabase };
|
|
@@ -28,19 +28,19 @@ const parsePITBranch = (input) => {
|
|
|
28
28
|
}
|
|
29
29
|
return result;
|
|
30
30
|
};
|
|
31
|
-
const parsePointInTime = async ({ pointInTime, targetBranchId, projectId, api }) => {
|
|
31
|
+
const parsePointInTime = async ({ pointInTime, targetBranchId, projectId, api, branches, targetBranch }) => {
|
|
32
32
|
const parsedPIT = parsePITBranch(pointInTime);
|
|
33
33
|
let branchId = "";
|
|
34
34
|
if (parsedPIT.branch === "^self") branchId = targetBranchId;
|
|
35
35
|
else if (parsedPIT.branch === "^parent") {
|
|
36
|
-
const
|
|
37
|
-
const { parent_id: parentId } = data.branch;
|
|
36
|
+
const parentId = (targetBranch?.id === targetBranchId ? targetBranch : (await api.getProjectBranch(projectId, targetBranchId)).data.branch).parent_id;
|
|
38
37
|
if (parentId == null) throw new PointInTimeParseError("Branch has no parent");
|
|
39
38
|
branchId = parentId;
|
|
40
39
|
} else branchId = await branchIdResolve({
|
|
41
40
|
branch: parsedPIT.branch,
|
|
42
41
|
projectId,
|
|
43
|
-
apiClient: api
|
|
42
|
+
apiClient: api,
|
|
43
|
+
branches
|
|
44
44
|
});
|
|
45
45
|
delete parsedPIT.branch;
|
|
46
46
|
return {
|
package/dist/writer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isCi } from "./env.js";
|
|
2
2
|
import { toSnakeCase } from "./utils/string.js";
|
|
3
|
-
import { formatHumanChunk, resolveOutputWidth } from "./human_table.js";
|
|
3
|
+
import { formatHumanChunk, resolveOutputWidth, stripAnsi } from "./human_table.js";
|
|
4
4
|
import YAML from "yaml";
|
|
5
5
|
//#region src/writer.ts
|
|
6
6
|
const writeYaml = (chunks) => {
|
|
@@ -11,17 +11,20 @@ const writeJson = (chunks) => {
|
|
|
11
11
|
return json === void 0 ? json : `${json}\n`;
|
|
12
12
|
};
|
|
13
13
|
const writeTable = (chunks, out, width) => {
|
|
14
|
+
const noColor = Boolean(process.env.NO_COLOR);
|
|
14
15
|
chunks.forEach(({ data, config }, i) => {
|
|
15
|
-
|
|
16
|
+
const title = config.humanTitle ?? config.title;
|
|
17
|
+
const text = formatHumanChunk({
|
|
16
18
|
data,
|
|
17
19
|
fields: config.fields,
|
|
18
|
-
title
|
|
20
|
+
title,
|
|
19
21
|
emptyMessage: config.emptyMessage,
|
|
20
22
|
renderColumns: config.renderColumns,
|
|
21
23
|
width,
|
|
22
24
|
colorTitle: !isCi(),
|
|
23
|
-
leadingBlank: i > 0 && Boolean(
|
|
24
|
-
})
|
|
25
|
+
leadingBlank: i > 0 && Boolean(title)
|
|
26
|
+
});
|
|
27
|
+
out.write(noColor ? stripAnsi(text) : text);
|
|
25
28
|
});
|
|
26
29
|
};
|
|
27
30
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.4",
|
|
4
4
|
"description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
"yaml": "^2.9.0",
|
|
65
65
|
"yargs": "17.7.2",
|
|
66
66
|
"yoctocolors": "^2.1.2",
|
|
67
|
+
"@neon/config-runtime": "1.7.3",
|
|
67
68
|
"@neon/config": "1.8.3",
|
|
68
|
-
"@neon/sdk": "7.0.0"
|
|
69
|
-
"@neon/config-runtime": "1.7.3"
|
|
69
|
+
"@neon/sdk": "7.0.0"
|
|
70
70
|
},
|
|
71
71
|
"optionalDependencies": {
|
|
72
72
|
"@napi-rs/keyring": "1.3.0",
|
|
@@ -134,6 +134,9 @@
|
|
|
134
134
|
"test": "pnpm --filter neonctl... build && vitest run",
|
|
135
135
|
"test:ci": "pnpm build && vitest run",
|
|
136
136
|
"test:e2e": "pnpm build && vitest run --config vitest.e2e.config.ts",
|
|
137
|
+
"test:perf": "pnpm --filter neon... build && vitest run src/perf_budget.test.ts",
|
|
138
|
+
"perf": "tsx scripts/perf/perf.ts",
|
|
139
|
+
"perf:ci-report": "tsx scripts/perf/ci-report.ts",
|
|
137
140
|
"test:conformance": "vitest run --config tests/psql-conformance/vitest.config.ts"
|
|
138
141
|
}
|
|
139
142
|
}
|