neon 8.0.0 → 8.0.1
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/analytics.js +13 -4
- package/dist/utils/psql.js +34 -33
- package/package.json +4 -4
package/dist/analytics.js
CHANGED
|
@@ -149,12 +149,21 @@ const analyticsMiddleware = async (args) => {
|
|
|
149
149
|
context: { direct: true }
|
|
150
150
|
});
|
|
151
151
|
};
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
let closing;
|
|
153
|
+
/**
|
|
154
|
+
* Close the client and flush queued events. Later calls share the first flush: the psql
|
|
155
|
+
* launcher starts one while psql runs, and a second `closeAndFlush` would only make the SDK
|
|
156
|
+
* warn about overlapping flushes.
|
|
157
|
+
*/
|
|
158
|
+
const closeAnalytics = (opts) => {
|
|
159
|
+
if (!client) return Promise.resolve();
|
|
160
|
+
if (!closing) {
|
|
154
161
|
log.debug("Flushing CLI analytics");
|
|
155
|
-
|
|
156
|
-
|
|
162
|
+
closing = client.closeAndFlush(opts).then(() => {
|
|
163
|
+
log.debug("Flushed CLI analytics");
|
|
164
|
+
});
|
|
157
165
|
}
|
|
166
|
+
return closing;
|
|
158
167
|
};
|
|
159
168
|
const getErrorAnalyticsEventContext = (_args) => ({
|
|
160
169
|
version: pkg_default.version,
|
package/dist/utils/psql.js
CHANGED
|
@@ -4,7 +4,7 @@ import which from "which";
|
|
|
4
4
|
import { spawn } from "child_process";
|
|
5
5
|
//#region src/utils/psql.ts
|
|
6
6
|
const FALLBACK_ENV = "NEONCTL_PSQL_FALLBACK";
|
|
7
|
-
/**
|
|
7
|
+
/** Cap on the analytics flush, counted from when psql launches. */
|
|
8
8
|
const ANALYTICS_FLUSH_TIMEOUT_MS = 3e3;
|
|
9
9
|
/**
|
|
10
10
|
* Decide which psql implementation will run, and why. The PATH probe is
|
|
@@ -45,59 +45,60 @@ const planPsql = async (opts) => {
|
|
|
45
45
|
nativePath
|
|
46
46
|
};
|
|
47
47
|
};
|
|
48
|
-
/**
|
|
49
|
-
* Record which psql implementation is about to run, then flush analytics.
|
|
50
|
-
*
|
|
51
|
-
* Both exec paths below call `process.exit()`, which short-circuits the
|
|
52
|
-
* main loop's `closeAnalytics()` — so without flushing here the event (and
|
|
53
|
-
* any earlier queued events, e.g. `CLI Started`) would be dropped. The
|
|
54
|
-
* flush is bounded by {@link ANALYTICS_FLUSH_TIMEOUT_MS} so a slow or
|
|
55
|
-
* unreachable analytics endpoint can't stall the psql launch. No-ops when
|
|
56
|
-
* analytics is disabled (`--analytics false`), since the client is absent.
|
|
57
|
-
*/
|
|
58
|
-
const reportPsqlInvocation = async (plan) => {
|
|
59
|
-
trackEvent("psql_invoked", {
|
|
60
|
-
implementation: plan.implementation,
|
|
61
|
-
reason: plan.reason,
|
|
62
|
-
nativeAvailable: plan.nativeAvailable
|
|
63
|
-
});
|
|
64
|
-
await closeAnalytics({ timeout: ANALYTICS_FLUSH_TIMEOUT_MS });
|
|
65
|
-
};
|
|
66
48
|
const execNative = async (binary, connection_uri, args) => {
|
|
67
|
-
log.info(
|
|
49
|
+
log.info(`${connectionSummary(connection_uri, args)}; launching psql...`);
|
|
68
50
|
const child = spawn(binary, [connection_uri, ...args], { stdio: "inherit" });
|
|
69
51
|
for (const signame of ["SIGINT", "SIGTERM"]) process.on(signame, (code) => {
|
|
70
52
|
if (!child.killed && code !== null) child.kill(code);
|
|
71
53
|
});
|
|
72
|
-
return new Promise((
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
73
55
|
child.on("exit", (code) => {
|
|
74
|
-
|
|
56
|
+
resolve(code === null ? 1 : code);
|
|
75
57
|
});
|
|
76
58
|
child.on("error", reject);
|
|
77
59
|
});
|
|
78
60
|
};
|
|
79
61
|
const execTs = async (connection_uri, args) => {
|
|
80
|
-
log.info(
|
|
62
|
+
log.info(`${connectionSummary(connection_uri, args)}; launching embedded psql (TypeScript)...`);
|
|
81
63
|
const { runPsql } = await import("../psql/index.js");
|
|
82
|
-
|
|
64
|
+
return runPsql([connection_uri, ...args], {
|
|
83
65
|
stdin: process.stdin,
|
|
84
66
|
stdout: process.stdout,
|
|
85
67
|
stderr: process.stderr
|
|
86
68
|
});
|
|
87
|
-
|
|
69
|
+
};
|
|
70
|
+
const GENERIC_CONNECTING = "Connecting to the database";
|
|
71
|
+
const connectionSummary = (connection_uri, args = []) => {
|
|
72
|
+
if (args.length > 0) return GENERIC_CONNECTING;
|
|
73
|
+
try {
|
|
74
|
+
const url = new URL(connection_uri);
|
|
75
|
+
const part = (value) => decodeURIComponent(value).replace(/[\u0000-\u001f\u007f]/g, "");
|
|
76
|
+
const database = part(url.pathname.replace(/^\//, ""));
|
|
77
|
+
const role = part(url.username);
|
|
78
|
+
if (!database || !role || !url.host) return GENERIC_CONNECTING;
|
|
79
|
+
return `Neon connection: ${database} as ${role} on ${url.host}`;
|
|
80
|
+
} catch {
|
|
81
|
+
return GENERIC_CONNECTING;
|
|
82
|
+
}
|
|
88
83
|
};
|
|
89
84
|
const psql = async (connection_uri, args = [], opts = {}) => {
|
|
90
85
|
const plan = await planPsql(opts);
|
|
91
|
-
|
|
86
|
+
trackEvent("psql_invoked", {
|
|
87
|
+
implementation: plan.implementation,
|
|
88
|
+
reason: plan.reason,
|
|
89
|
+
nativeAvailable: plan.nativeAvailable
|
|
90
|
+
});
|
|
91
|
+
const flushed = closeAnalytics({ timeout: ANALYTICS_FLUSH_TIMEOUT_MS });
|
|
92
|
+
let code;
|
|
92
93
|
if (plan.implementation === "ts") {
|
|
93
94
|
if (plan.reason === "fallback_no_native") log.info("psql binary not found on PATH; falling back to embedded TypeScript psql");
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
if (plan.nativePath === null) {
|
|
95
|
+
code = await execTs(connection_uri, args);
|
|
96
|
+
} else if (plan.nativePath === null) {
|
|
97
97
|
log.error(`psql is not available in the PATH`);
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
98
|
+
code = 1;
|
|
99
|
+
} else code = await execNative(plan.nativePath, connection_uri, args);
|
|
100
|
+
await flushed;
|
|
101
|
+
process.exit(code);
|
|
101
102
|
};
|
|
102
103
|
//#endregion
|
|
103
|
-
export { psql };
|
|
104
|
+
export { connectionSummary, psql };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neon",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.1",
|
|
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/
|
|
67
|
+
"@neon/config": "1.8.3",
|
|
68
68
|
"@neon/config-runtime": "1.7.3",
|
|
69
|
-
"@neon/
|
|
69
|
+
"@neon/sdk": "7.0.0"
|
|
70
70
|
},
|
|
71
71
|
"optionalDependencies": {
|
|
72
72
|
"@napi-rs/keyring": "1.3.0",
|
|
@@ -100,8 +100,8 @@
|
|
|
100
100
|
"typescript": "^5.9.0",
|
|
101
101
|
"vitest": "^3.0.9",
|
|
102
102
|
"@neon-internals/cli-core": "0.0.0",
|
|
103
|
-
"@neon-internals/env-core": "0.0.26",
|
|
104
103
|
"@neon/e2e-harness": "0.0.0",
|
|
104
|
+
"@neon-internals/env-core": "0.0.26",
|
|
105
105
|
"@neon/functions": "0.11.0"
|
|
106
106
|
},
|
|
107
107
|
"publishConfig": {
|