neon 3.0.0 → 3.1.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.
Files changed (198) hide show
  1. package/README.md +54 -0
  2. package/dist/_shared/auth_selection.js +76 -79
  3. package/dist/_shared/credentials.js +166 -187
  4. package/dist/_shared/env-core/env.js +354 -517
  5. package/dist/_shared/env-core/reuse-secrets.js +159 -203
  6. package/dist/_shared/paths.js +129 -126
  7. package/dist/_shared/profiles.js +192 -242
  8. package/dist/_shared/secure_file.js +36 -38
  9. package/dist/_virtual/_rolldown/runtime.js +13 -0
  10. package/dist/analytics.js +163 -207
  11. package/dist/api.js +815 -758
  12. package/dist/auth.js +121 -141
  13. package/dist/auth_context.js +39 -53
  14. package/dist/cli.js +4 -7
  15. package/dist/commands/api.js +220 -250
  16. package/dist/commands/api_keys.js +251 -314
  17. package/dist/commands/auth.js +283 -328
  18. package/dist/commands/bootstrap.js +372 -437
  19. package/dist/commands/branches.js +304 -455
  20. package/dist/commands/bucket.js +374 -514
  21. package/dist/commands/checkout.js +213 -298
  22. package/dist/commands/config.js +573 -690
  23. package/dist/commands/connection_string.js +137 -165
  24. package/dist/commands/data_api.js +238 -260
  25. package/dist/commands/databases.js +67 -76
  26. package/dist/commands/deploy.js +31 -25
  27. package/dist/commands/dev.js +639 -719
  28. package/dist/commands/diff.js +156 -200
  29. package/dist/commands/env.js +243 -303
  30. package/dist/commands/functions.js +275 -355
  31. package/dist/commands/index.js +70 -65
  32. package/dist/commands/init.js +84 -119
  33. package/dist/commands/inspect.js +55 -55
  34. package/dist/commands/ip_allow.js +88 -120
  35. package/dist/commands/link.js +874 -1019
  36. package/dist/commands/logs.js +291 -0
  37. package/dist/commands/neon_auth.js +725 -933
  38. package/dist/commands/operations.js +34 -25
  39. package/dist/commands/orgs.js +28 -18
  40. package/dist/commands/profile.js +614 -845
  41. package/dist/commands/projects.js +313 -373
  42. package/dist/commands/psql.js +60 -58
  43. package/dist/commands/roles.js +55 -58
  44. package/dist/commands/schema_diff.js +87 -131
  45. package/dist/commands/set_context.js +34 -26
  46. package/dist/commands/snapshots.js +288 -413
  47. package/dist/commands/status.js +41 -37
  48. package/dist/commands/user.js +21 -10
  49. package/dist/commands/vpc_endpoints.js +85 -113
  50. package/dist/config.js +7 -6
  51. package/dist/config_format.js +50 -66
  52. package/dist/config_template.js +128 -157
  53. package/dist/context.js +183 -235
  54. package/dist/current_branch_fast_path.js +40 -49
  55. package/dist/dev/env.js +313 -394
  56. package/dist/dev/functions.js +54 -68
  57. package/dist/dev/inputs.js +46 -58
  58. package/dist/dev/runtime.js +135 -164
  59. package/dist/dev/websocket.js +766 -959
  60. package/dist/env.js +27 -33
  61. package/dist/env_file.js +118 -132
  62. package/dist/env_services.js +36 -38
  63. package/dist/errors.js +57 -68
  64. package/dist/functions_api.js +45 -43
  65. package/dist/help.js +189 -140
  66. package/dist/index.js +182 -257
  67. package/dist/init/agents.js +137 -118
  68. package/dist/init/auth.js +58 -68
  69. package/dist/init/bootstrap.js +325 -396
  70. package/dist/init/build_config.js +4 -2
  71. package/dist/init/detect_agent.js +56 -101
  72. package/dist/init/editors.js +35 -52
  73. package/dist/init/enrich_output.js +51 -66
  74. package/dist/init/extension.js +134 -171
  75. package/dist/init/inspect.js +179 -266
  76. package/dist/init/interactive.js +510 -622
  77. package/dist/init/neonctl.js +117 -168
  78. package/dist/init/orchestrate.js +157 -173
  79. package/dist/init/phases/auth.js +188 -202
  80. package/dist/init/phases/cleanup.js +23 -23
  81. package/dist/init/phases/db.js +251 -277
  82. package/dist/init/phases/getting_started.js +213 -223
  83. package/dist/init/phases/mcp.js +174 -224
  84. package/dist/init/phases/migrations.js +247 -248
  85. package/dist/init/phases/neon_auth.js +114 -133
  86. package/dist/init/phases/setup.js +546 -703
  87. package/dist/init/phases/skills.js +75 -86
  88. package/dist/init/phases/status.js +72 -67
  89. package/dist/init/resolve_context.js +102 -99
  90. package/dist/init/route_command.js +91 -98
  91. package/dist/init/skills.js +174 -218
  92. package/dist/init/vsix.js +77 -99
  93. package/dist/log.js +17 -16
  94. package/dist/neon_services.js +104 -129
  95. package/dist/parameters.gen.js +481 -471
  96. package/dist/pkg.js +17 -19
  97. package/dist/profile_keys.js +44 -47
  98. package/dist/psql/cli.js +44 -47
  99. package/dist/psql/command/cmd_cond.js +231 -406
  100. package/dist/psql/command/cmd_connect.js +557 -764
  101. package/dist/psql/command/cmd_copy.js +727 -983
  102. package/dist/psql/command/cmd_describe.js +1499 -1688
  103. package/dist/psql/command/cmd_format.js +733 -905
  104. package/dist/psql/command/cmd_io.js +1293 -2082
  105. package/dist/psql/command/cmd_lo.js +297 -359
  106. package/dist/psql/command/cmd_meta.js +727 -878
  107. package/dist/psql/command/cmd_misc.js +138 -172
  108. package/dist/psql/command/cmd_pipeline.js +547 -1099
  109. package/dist/psql/command/cmd_restrict.js +119 -155
  110. package/dist/psql/command/cmd_show.js +529 -688
  111. package/dist/psql/command/dispatch.js +261 -325
  112. package/dist/psql/command/inputQueue.js +35 -33
  113. package/dist/psql/command/shared.js +49 -63
  114. package/dist/psql/complete/filenames.js +90 -133
  115. package/dist/psql/complete/index.js +59 -97
  116. package/dist/psql/complete/matcher.js +236 -300
  117. package/dist/psql/complete/psqlVars.js +218 -223
  118. package/dist/psql/complete/queries.js +159 -177
  119. package/dist/psql/complete/rules.js +1493 -2299
  120. package/dist/psql/core/common.js +762 -1180
  121. package/dist/psql/core/help.js +456 -546
  122. package/dist/psql/core/mainloop.js +692 -1302
  123. package/dist/psql/core/prompt.js +391 -408
  124. package/dist/psql/core/settings.js +429 -644
  125. package/dist/psql/core/sqlHelp.js +480 -554
  126. package/dist/psql/core/startup.js +626 -815
  127. package/dist/psql/core/syncVars.js +67 -110
  128. package/dist/psql/core/variables.js +156 -278
  129. package/dist/psql/describe/formatters.js +884 -1285
  130. package/dist/psql/describe/processNamePattern.js +173 -260
  131. package/dist/psql/describe/queries.js +1368 -2403
  132. package/dist/psql/describe/versionGate.js +32 -41
  133. package/dist/psql/index.js +1414 -1927
  134. package/dist/psql/io/history.js +232 -271
  135. package/dist/psql/io/input.js +103 -108
  136. package/dist/psql/io/lineEditor/buffer.js +238 -319
  137. package/dist/psql/io/lineEditor/complete.js +135 -213
  138. package/dist/psql/io/lineEditor/filename.js +139 -148
  139. package/dist/psql/io/lineEditor/index.js +653 -870
  140. package/dist/psql/io/lineEditor/keymap.js +544 -702
  141. package/dist/psql/io/lineEditor/vt100.js +294 -341
  142. package/dist/psql/io/pgpass.js +158 -187
  143. package/dist/psql/io/pgservice.js +146 -183
  144. package/dist/psql/io/psqlrc.js +328 -403
  145. package/dist/psql/print/aligned.js +1020 -1683
  146. package/dist/psql/print/asciidoc.js +180 -214
  147. package/dist/psql/print/crosstab.js +281 -442
  148. package/dist/psql/print/csv.js +48 -70
  149. package/dist/psql/print/html.js +195 -226
  150. package/dist/psql/print/json.js +75 -88
  151. package/dist/psql/print/latex.js +291 -364
  152. package/dist/psql/print/pager.js +171 -242
  153. package/dist/psql/print/troff.js +194 -226
  154. package/dist/psql/print/unaligned.js +69 -95
  155. package/dist/psql/print/units.js +167 -169
  156. package/dist/psql/scanner/slash.js +428 -483
  157. package/dist/psql/scanner/sql.js +445 -889
  158. package/dist/psql/scanner/stringutils.js +309 -379
  159. package/dist/psql/types/index.js +2 -7
  160. package/dist/psql/types/scanner.js +25 -22
  161. package/dist/psql/wire/connection.js +2042 -2803
  162. package/dist/psql/wire/copy.js +84 -100
  163. package/dist/psql/wire/notify.js +39 -59
  164. package/dist/psql/wire/pipeline.js +305 -518
  165. package/dist/psql/wire/protocol.js +349 -417
  166. package/dist/psql/wire/sasl.js +180 -265
  167. package/dist/psql/wire/tls.js +400 -561
  168. package/dist/storage_api.js +115 -129
  169. package/dist/test_utils/fixtures.js +94 -113
  170. package/dist/test_utils/oauth_server.js +10 -7
  171. package/dist/test_utils/project_dir.js +33 -0
  172. package/dist/utils/ai_gateway_notice.js +131 -162
  173. package/dist/utils/api_enums.js +21 -28
  174. package/dist/utils/auth.js +10 -4
  175. package/dist/utils/branch_notice.js +20 -19
  176. package/dist/utils/branch_picker.js +83 -89
  177. package/dist/utils/cli_name.js +15 -12
  178. package/dist/utils/compute_units.js +20 -27
  179. package/dist/utils/config_diff.js +127 -158
  180. package/dist/utils/enrichers.js +95 -148
  181. package/dist/utils/esbuild.js +130 -189
  182. package/dist/utils/flags.js +35 -47
  183. package/dist/utils/formats.js +8 -15
  184. package/dist/utils/git_diff.js +69 -80
  185. package/dist/utils/inspect_db.js +101 -143
  186. package/dist/utils/inspect_queries.js +179 -142
  187. package/dist/utils/middlewares.js +37 -44
  188. package/dist/utils/openapi.js +87 -99
  189. package/dist/utils/package_manager.js +312 -110
  190. package/dist/utils/point_in_time.js +49 -53
  191. package/dist/utils/psql.js +89 -106
  192. package/dist/utils/service_picker.js +55 -58
  193. package/dist/utils/string.js +5 -5
  194. package/dist/utils/ui.js +38 -55
  195. package/dist/utils/write_sync.js +26 -35
  196. package/dist/utils/zip.js +4 -3
  197. package/dist/writer.js +67 -87
  198. package/package.json +7 -5
package/dist/index.js CHANGED
@@ -1,267 +1,192 @@
1
- import yargs from "yargs";
2
- import { hideBin } from "yargs/helpers";
3
- import { analyticsMiddleware, closeAnalytics, getAnalyticsEventProperties, initAnalyticsClientMiddleware, sendError, trackEvent, } from "./analytics.js";
1
+ import { log } from "./log.js";
2
+ import pkg_default from "./pkg.js";
4
3
  import { isNeonApiError, messageFromBody } from "./api.js";
5
- import { defaultClientID } from "./auth.js";
6
- import { authFailureMessage, credentialsToClearOn401, getAuthContext, } from "./auth_context.js";
7
- import { deleteCredentialsAt, ensureAuth } from "./commands/auth.js";
8
- import commands from "./commands/index.js";
9
- import { defaultDir, ensureConfigDir } from "./config.js";
4
+ import { defaultDir } from "./_shared/paths.js";
5
+ import { ensureConfigDir } from "./config.js";
6
+ import { authFailureMessage, credentialsToClearOn401, getAuthContext } from "./auth_context.js";
10
7
  import { currentContextFile, enrichFromContext } from "./context.js";
11
- import { isNetworkError, matchErrorCode, NETWORK_ERROR_MESSAGE, } from "./errors.js";
12
- import { showHelp } from "./help.js";
13
- import { log } from "./log.js";
14
- import pkg from "./pkg.js";
8
+ import { analyticsMiddleware, closeAnalytics, getAnalyticsEventProperties, initAnalyticsClientMiddleware, sendError, trackEvent } from "./analytics.js";
9
+ import { NETWORK_ERROR_MESSAGE, isNetworkError, matchErrorCode } from "./errors.js";
10
+ import { defaultClientID } from "./auth.js";
15
11
  import { getCliName } from "./utils/cli_name.js";
12
+ import { showHelp } from "./help.js";
13
+ import { deleteCredentialsAt, ensureAuth } from "./commands/auth.js";
14
+ import commands_default from "./commands/index.js";
16
15
  import { fillInArgs, resolveApiKeyFromEnv } from "./utils/middlewares.js";
16
+ import yargs from "yargs";
17
+ import { hideBin } from "yargs/helpers";
18
+ //#region src/index.ts
17
19
  const NO_SUBCOMMANDS_VERBS = [
18
- // `api <path>` has a handler but no subcommands (like `status`), so the
19
- // help-fallback middleware must not intercept a bare `neon api /projects`.
20
- "api",
21
- // aliases
22
- "auth",
23
- "login",
24
- "me",
25
- // aliases
26
- "cs",
27
- "connection-string",
28
- "psql",
29
- "set-context",
30
- "checkout",
31
- "link",
32
- "init",
33
- "dev",
34
- "deploy",
35
- // `diff <compare-branch>` has a handler but no subcommands (like `status`),
36
- // so the help-fallback middleware must not intercept a bare `neon diff main`.
37
- "diff",
38
- "bootstrap",
39
- // alias of `config status`
40
- "status",
20
+ "api",
21
+ "auth",
22
+ "login",
23
+ "me",
24
+ "cs",
25
+ "connection-string",
26
+ "psql",
27
+ "set-context",
28
+ "checkout",
29
+ "link",
30
+ "init",
31
+ "dev",
32
+ "deploy",
33
+ "diff",
34
+ "bootstrap",
35
+ "status"
41
36
  ];
42
37
  let builder = yargs(hideBin(process.argv));
43
- builder = builder
44
- .scriptName(pkg.name)
45
- .locale("en")
46
- .usage("$0 <command> [options]")
47
- .parserConfiguration({
48
- "populate--": true,
49
- })
50
- .help()
51
- .option("output", {
52
- alias: "o",
53
- group: "Global options:",
54
- describe: "Set output format",
55
- type: "string",
56
- choices: ["json", "yaml", "table"],
57
- default: "table",
58
- })
59
- .option("api-host", {
60
- describe: "The API host",
61
- hidden: true,
62
- default: process.env.NEON_API_HOST ?? "https://console.neon.tech/api/v2",
63
- })
64
- // Setup config directory
65
- .option("config-dir", {
66
- describe: "Path to config directory",
67
- group: "Global options:",
68
- type: "string",
69
- default: defaultDir,
70
- })
71
- .option("profile", {
72
- describe: "Named credentials to use, from profiles.json (default: NEON_PROFILE, else DEFAULT)",
73
- group: "Global options:",
74
- type: "string",
75
- })
76
- .option("force-auth", {
77
- describe: "Force authentication",
78
- type: "boolean",
79
- hidden: true,
80
- default: false,
81
- })
82
- .middleware(ensureConfigDir)
83
- .options({
84
- "oauth-host": {
85
- description: "URL to Neon OAuth host",
86
- hidden: true,
87
- default: process.env.NEON_OAUTH_HOST ?? "https://oauth2.neon.tech",
88
- },
89
- "client-id": {
90
- description: "OAuth client id",
91
- hidden: true,
92
- type: "string",
93
- default: defaultClientID,
94
- },
95
- "api-key": {
96
- describe: "API key",
97
- group: "Global options:",
98
- type: "string",
99
- // Take the next token as the value even when it looks like an option, so
100
- // `--api-key -` binds the dash rather than being read as a command of its own.
101
- // `profile create` gives `-` its meaning; everywhere else it is just a value.
102
- nargs: 1,
103
- // The default must never be the value of NEON_API_KEY: yargs renders an
104
- // option's default into every help screen, so that printed the user's key
105
- // verbatim on `neon --help`. `resolveApiKeyFromEnv` reads the env var
106
- // instead, and `defaultDescription` names it in help without its value.
107
- default: "",
108
- defaultDescription: "NEON_API_KEY",
109
- },
110
- apiClient: {
111
- hidden: true,
112
- coerce: (v) => v,
113
- default: null,
114
- },
115
- "context-file": {
116
- describe: "Context file",
117
- type: "string",
118
- default: currentContextFile,
119
- },
120
- color: {
121
- group: "Global options:",
122
- describe: "Colorize the output. Example: --no-color, --color false",
123
- type: "boolean",
124
- default: true,
125
- },
126
- analytics: {
127
- describe: "Manage analytics. Example: --no-analytics, --analytics false",
128
- group: "Global options:",
129
- type: "boolean",
130
- default: true,
131
- },
132
- })
133
- .middleware((args) => {
134
- fillInArgs(args);
135
- }, true)
136
- .middleware(resolveApiKeyFromEnv, true)
137
- .middleware(initAnalyticsClientMiddleware, true)
138
- .help(false)
139
- .group("help", "Global options:")
140
- .option("help", {
141
- describe: "Show help",
142
- type: "boolean",
143
- default: false,
144
- })
145
- .alias("help", "h")
146
- .middleware(async (args) => {
147
- if (args.help ||
148
- (args._.length === 1 &&
149
- !NO_SUBCOMMANDS_VERBS.includes(args._[0]))) {
150
- await showHelp(builder);
151
- }
152
- })
153
- .middleware(ensureAuth)
154
- .middleware(enrichFromContext)
155
- .middleware(analyticsMiddleware)
156
- .command(commands)
157
- .strictCommands()
158
- .version(pkg.version)
159
- .group("version", "Global options:")
160
- .alias("version", "v")
161
- .completion()
162
- .scriptName(getCliName())
163
- .epilog("For more information, visit https://neon.com/docs/reference/neon-cli")
164
- .wrap(null)
165
- .fail(false);
38
+ builder = builder.scriptName(pkg_default.name).locale("en").usage("$0 <command> [options]").parserConfiguration({ "populate--": true }).help().option("output", {
39
+ alias: "o",
40
+ group: "Global options:",
41
+ describe: "Set output format",
42
+ type: "string",
43
+ choices: [
44
+ "json",
45
+ "yaml",
46
+ "table"
47
+ ],
48
+ default: "table"
49
+ }).option("api-host", {
50
+ describe: "The API host",
51
+ hidden: true,
52
+ default: process.env.NEON_API_HOST ?? "https://console.neon.tech/api/v2"
53
+ }).option("config-dir", {
54
+ describe: "Path to config directory",
55
+ group: "Global options:",
56
+ type: "string",
57
+ default: defaultDir
58
+ }).option("profile", {
59
+ describe: "Named credentials to use, from profiles.json (default: NEON_PROFILE, else DEFAULT)",
60
+ group: "Global options:",
61
+ type: "string"
62
+ }).option("force-auth", {
63
+ describe: "Force authentication",
64
+ type: "boolean",
65
+ hidden: true,
66
+ default: false
67
+ }).middleware(ensureConfigDir).options({
68
+ "oauth-host": {
69
+ description: "URL to Neon OAuth host",
70
+ hidden: true,
71
+ default: process.env.NEON_OAUTH_HOST ?? "https://oauth2.neon.tech"
72
+ },
73
+ "client-id": {
74
+ description: "OAuth client id",
75
+ hidden: true,
76
+ type: "string",
77
+ default: defaultClientID
78
+ },
79
+ "api-key": {
80
+ describe: "API key",
81
+ group: "Global options:",
82
+ type: "string",
83
+ nargs: 1,
84
+ default: "",
85
+ defaultDescription: "NEON_API_KEY"
86
+ },
87
+ apiClient: {
88
+ hidden: true,
89
+ coerce: (v) => v,
90
+ default: null
91
+ },
92
+ "context-file": {
93
+ describe: "Context file",
94
+ type: "string",
95
+ default: currentContextFile
96
+ },
97
+ color: {
98
+ group: "Global options:",
99
+ describe: "Colorize the output. Example: --no-color, --color false",
100
+ type: "boolean",
101
+ default: true
102
+ },
103
+ analytics: {
104
+ describe: "Manage analytics. Example: --no-analytics, --analytics false",
105
+ group: "Global options:",
106
+ type: "boolean",
107
+ default: true
108
+ }
109
+ }).middleware((args) => {
110
+ fillInArgs(args);
111
+ }, true).middleware(resolveApiKeyFromEnv, true).middleware(initAnalyticsClientMiddleware, true).help(false).group("help", "Global options:").option("help", {
112
+ describe: "Show help",
113
+ type: "boolean",
114
+ default: false
115
+ }).alias("help", "h").middleware(async (args) => {
116
+ if (args.help || args._.length === 1 && !NO_SUBCOMMANDS_VERBS.includes(args._[0])) await showHelp(builder);
117
+ }).middleware(ensureAuth).middleware(enrichFromContext).middleware(analyticsMiddleware).command(commands_default).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(false);
166
118
  async function handleError(msg, err) {
167
- if (process.argv.some((arg) => arg === "--help" || arg === "-h")) {
168
- await showHelp(builder);
169
- process.exit(0);
170
- }
171
- // Log stack trace if available
172
- if (err instanceof Error && err.stack) {
173
- log.debug("Stack: %s", err.stack);
174
- }
175
- // A connection-level failure (no response ever reached us) reads as a cryptic
176
- // `fetch failed` from the @neon/sdk / global `fetch` path. Detect it first and
177
- // swap in one clear "check your connection" hint. We deliberately do not retry
178
- // here: re-running the whole command could re-trigger a non-idempotent step
179
- // (e.g. project create), so retries belong at the request layer.
180
- if (isNetworkError(err)) {
181
- log.error(NETWORK_ERROR_MESSAGE);
182
- const error = err instanceof Error ? err : new Error(NETWORK_ERROR_MESSAGE);
183
- sendError(error, "NETWORK_ERROR");
184
- return false;
185
- }
186
- if (isNeonApiError(err)) {
187
- if (err.code === "ECONNABORTED") {
188
- log.error("Request timed out");
189
- sendError(err, "REQUEST_TIMEOUT");
190
- return false;
191
- }
192
- else if (err.status === 401) {
193
- sendError(err, "AUTH_FAILED");
194
- const context = getAuthContext();
195
- const staleCredentials = credentialsToClearOn401(context);
196
- // The request was authorized with a key rather than a refreshable token — one the
197
- // user supplied, or one stored in a profile. Either way there is nothing to clear
198
- // and nothing to retry, since the same key would just be rejected again. Deleting
199
- // a profile's key would destroy the only copy of a credential that cannot be
200
- // refreshed, so the message says what to re-run instead.
201
- if (staleCredentials === null) {
202
- log.error(authFailureMessage(context));
203
- return false;
204
- }
205
- log.info("Authentication failed, deleting credentials...");
206
- try {
207
- deleteCredentialsAt(staleCredentials);
208
- return true; // Allow retry for auth failures
209
- }
210
- catch (deleteErr) {
211
- log.debug("Failed to delete credentials: %s", deleteErr instanceof Error
212
- ? deleteErr.message
213
- : "unknown error");
214
- return false;
215
- }
216
- }
217
- else {
218
- const serverMessage = messageFromBody(err.data);
219
- if (serverMessage) {
220
- log.error(serverMessage);
221
- }
222
- log.debug("status: %d %s | path: %s", err.status, err.statusText, err.requestPath);
223
- sendError(err, "API_ERROR");
224
- return false;
225
- }
226
- }
227
- else {
228
- const error = err instanceof Error ? err : new Error(msg || "Unknown error");
229
- sendError(error, matchErrorCode(error.message));
230
- log.error(error.message);
231
- return false;
232
- }
119
+ if (process.argv.some((arg) => arg === "--help" || arg === "-h")) {
120
+ await showHelp(builder);
121
+ process.exit(0);
122
+ }
123
+ if (err instanceof Error && err.stack) log.debug("Stack: %s", err.stack);
124
+ if (isNetworkError(err)) {
125
+ log.error(NETWORK_ERROR_MESSAGE);
126
+ const error = err instanceof Error ? err : new Error(NETWORK_ERROR_MESSAGE);
127
+ sendError(error, "NETWORK_ERROR");
128
+ return false;
129
+ }
130
+ if (isNeonApiError(err)) if (err.code === "ECONNABORTED") {
131
+ log.error("Request timed out");
132
+ sendError(err, "REQUEST_TIMEOUT");
133
+ return false;
134
+ } else if (err.status === 401) {
135
+ sendError(err, "AUTH_FAILED");
136
+ const context = getAuthContext();
137
+ const staleCredentials = credentialsToClearOn401(context);
138
+ if (staleCredentials === null) {
139
+ log.error(authFailureMessage(context));
140
+ return false;
141
+ }
142
+ log.info("Authentication failed, deleting credentials...");
143
+ try {
144
+ deleteCredentialsAt(staleCredentials);
145
+ return true;
146
+ } catch (deleteErr) {
147
+ log.debug("Failed to delete credentials: %s", deleteErr instanceof Error ? deleteErr.message : "unknown error");
148
+ return false;
149
+ }
150
+ } else {
151
+ const serverMessage = messageFromBody(err.data);
152
+ if (serverMessage) log.error(serverMessage);
153
+ log.debug("status: %d %s | path: %s", err.status, err.statusText, err.requestPath);
154
+ sendError(err, "API_ERROR");
155
+ return false;
156
+ }
157
+ else {
158
+ const error = err instanceof Error ? err : new Error(msg || "Unknown error");
159
+ sendError(error, matchErrorCode(error.message));
160
+ log.error(error.message);
161
+ return false;
162
+ }
233
163
  }
234
- void (async () => {
235
- // Main loop with max 2 attempts (initial + 1 retry):
236
- let attempts = 0;
237
- const MAX_ATTEMPTS = 2;
238
- while (attempts < MAX_ATTEMPTS) {
239
- try {
240
- const args = await builder.argv;
241
- // Send analytics for a successful attempt
242
- trackEvent("cli_command_success", {
243
- ...getAnalyticsEventProperties(args),
244
- projectId: args.projectId,
245
- branchId: args.branchId,
246
- accountId: args.accountId,
247
- authMethod: args.authMethod,
248
- authData: args.authData,
249
- });
250
- if (args._.length === 0 || args.help) {
251
- await showHelp(builder);
252
- process.exit(0);
253
- }
254
- await closeAnalytics();
255
- break;
256
- }
257
- catch (err) {
258
- attempts++;
259
- const shouldRetry = await handleError("", err);
260
- if (!shouldRetry || attempts >= MAX_ATTEMPTS) {
261
- await closeAnalytics();
262
- process.exit(1);
263
- }
264
- // If shouldRetry is true and we haven't hit max attempts, loop continues
265
- }
266
- }
164
+ (async () => {
165
+ let attempts = 0;
166
+ const MAX_ATTEMPTS = 2;
167
+ while (attempts < MAX_ATTEMPTS) try {
168
+ const args = await builder.argv;
169
+ trackEvent("cli_command_success", {
170
+ ...getAnalyticsEventProperties(args),
171
+ projectId: args.projectId,
172
+ branchId: args.branchId,
173
+ accountId: args.accountId,
174
+ authMethod: args.authMethod,
175
+ authData: args.authData
176
+ });
177
+ if (args._.length === 0 || args.help) {
178
+ await showHelp(builder);
179
+ process.exit(0);
180
+ }
181
+ await closeAnalytics();
182
+ break;
183
+ } catch (err) {
184
+ attempts++;
185
+ if (!await handleError("", err) || attempts >= MAX_ATTEMPTS) {
186
+ await closeAnalytics();
187
+ process.exit(1);
188
+ }
189
+ }
267
190
  })();
191
+ //#endregion
192
+ export {};