@neon/sdk 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{LICENSE.md → LICENSE} +27 -3
- package/README.md +22 -1
- package/dist/neon/errors.d.ts +25 -2
- package/dist/neon/errors.d.ts.map +1 -1
- package/dist/neon/errors.js +60 -5
- package/dist/neon/errors.js.map +1 -1
- package/package.json +3 -2
package/{LICENSE.md → LICENSE}
RENAMED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
# Apache License 2.0
|
|
2
1
|
|
|
3
|
-
|
|
2
|
+
Apache License
|
|
4
3
|
Version 2.0, January 2004
|
|
5
4
|
http://www.apache.org/licenses/
|
|
6
5
|
|
|
@@ -175,4 +174,29 @@
|
|
|
175
174
|
incurred by, or claims asserted against, such Contributor by reason
|
|
176
175
|
of your accepting any such warranty or additional liability.
|
|
177
176
|
|
|
178
|
-
END OF TERMS AND CONDITIONS
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -83,7 +83,7 @@ The `error` channel carries a typed hierarchy (all `Error` subclasses with a `ki
|
|
|
83
83
|
| `NeonRateLimitError` | `"rate_limit"` | (429, after retries) |
|
|
84
84
|
| `NeonOperationError` | `"operation"` | `operationId`, `status` — an awaited operation failed |
|
|
85
85
|
| `NeonTimeoutError` | `"timeout"` | readiness/wait deadline exceeded |
|
|
86
|
-
| `NeonNetworkError` | `"network"` | transport failure (no response) |
|
|
86
|
+
| `NeonNetworkError` | `"network"` | `reason` — transport failure (no response) |
|
|
87
87
|
| `NeonError` | `"client"` | SDK-side errors (e.g. ambiguous connection-string selection) |
|
|
88
88
|
|
|
89
89
|
```ts
|
|
@@ -91,6 +91,27 @@ const { error } = await neon.branches.get(pid, "nope");
|
|
|
91
91
|
if (error?.kind === "not_found") { /* … */ }
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
Branch on `kind` rather than `name` or `message`. `name` is a stable string literal on every
|
|
95
|
+
class, so it survives bundling, but `message` is not a contract.
|
|
96
|
+
|
|
97
|
+
`NeonNetworkError.reason` carries the most specific reason the platform gave — an `errno`
|
|
98
|
+
code such as `ECONNRESET` when one is available, otherwise the innermost non-empty message.
|
|
99
|
+
It is also interpolated into `message`, so transport faults are distinguishable in logs and
|
|
100
|
+
error trackers instead of collapsing onto one string:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const { error } = await neon.projects.get(id);
|
|
104
|
+
if (error?.kind === "network") {
|
|
105
|
+
error.reason; // "ECONNRESET"
|
|
106
|
+
error.message; // 'Network error: no response received from the Neon API (ECONNRESET).'
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Validating ids and other path parameters before passing them in is the caller's
|
|
111
|
+
responsibility. An empty path parameter builds a URL with an empty segment, which the Neon
|
|
112
|
+
API answers with a redirect rather than a `400`; that can surface as a `"network"` error
|
|
113
|
+
rather than anything that names the argument.
|
|
114
|
+
|
|
94
115
|
## Pagination
|
|
95
116
|
|
|
96
117
|
Cursor-paginated `list()` methods return a lazy `Paginated<T>`:
|
package/dist/neon/errors.d.ts
CHANGED
|
@@ -6,7 +6,14 @@
|
|
|
6
6
|
* it.
|
|
7
7
|
*/
|
|
8
8
|
type NeonErrorKind = "api" | "not_found" | "auth" | "rate_limit" | "operation" | "timeout" | "network" | "client";
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Base class for every error the ergonomic layer produces.
|
|
11
|
+
*
|
|
12
|
+
* Every subclass assigns `this.name` as a string literal rather than reading it from the
|
|
13
|
+
* constructor. Bundlers rename classes, so deriving the name at runtime leaves consumers
|
|
14
|
+
* of a minified build with errors called `s` and `r` — unreadable in logs and impossible
|
|
15
|
+
* to group on in an error tracker.
|
|
16
|
+
*/
|
|
10
17
|
declare class NeonError extends Error {
|
|
11
18
|
readonly kind: NeonErrorKind;
|
|
12
19
|
constructor(message: string, kind: NeonErrorKind, options?: {
|
|
@@ -63,10 +70,26 @@ declare class NeonTimeoutError extends NeonError {
|
|
|
63
70
|
}
|
|
64
71
|
/** A transport-level failure (DNS, connection, abort) — no HTTP response received. */
|
|
65
72
|
declare class NeonNetworkError extends NeonError {
|
|
73
|
+
/**
|
|
74
|
+
* The most specific reason the platform gave for the failure — an `errno` code such as
|
|
75
|
+
* `ECONNRESET` when one is available, otherwise the innermost non-empty message. Read
|
|
76
|
+
* this instead of matching on {@link message}.
|
|
77
|
+
*/
|
|
78
|
+
readonly reason: string;
|
|
66
79
|
constructor(message: string, options?: {
|
|
67
80
|
cause?: unknown;
|
|
81
|
+
reason?: string;
|
|
68
82
|
});
|
|
69
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Walk a transport failure's `cause` chain for the most specific description available.
|
|
86
|
+
*
|
|
87
|
+
* `fetch` reports every transport fault as `TypeError: fetch failed` and puts the real
|
|
88
|
+
* reason underneath, sometimes several levels down and sometimes with an empty message and
|
|
89
|
+
* only an `errno` code. Without this, a DNS failure, a reset connection and a redirect the
|
|
90
|
+
* client refused to follow all produce the same sentence.
|
|
91
|
+
*/
|
|
92
|
+
declare function describeTransportFailure(error: unknown): string;
|
|
70
93
|
/**
|
|
71
94
|
* Build the right {@link NeonError} subclass from a raw client result. `error` is the
|
|
72
95
|
* decoded error body (Neon `GeneralError`); `response` is present unless the failure was
|
|
@@ -74,5 +97,5 @@ declare class NeonNetworkError extends NeonError {
|
|
|
74
97
|
*/
|
|
75
98
|
declare function toNeonError(error: unknown, response: Response | undefined): NeonError;
|
|
76
99
|
//#endregion
|
|
77
|
-
export { NeonApiError, NeonAuthError, NeonError, NeonErrorKind, NeonNetworkError, NeonNotFoundError, NeonOperationError, NeonRateLimitError, NeonTimeoutError, toNeonError };
|
|
100
|
+
export { NeonApiError, NeonAuthError, NeonError, NeonErrorKind, NeonNetworkError, NeonNotFoundError, NeonOperationError, NeonRateLimitError, NeonTimeoutError, describeTransportFailure, toNeonError };
|
|
78
101
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/neon/errors.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/neon/errors.ts"],"mappings":";;AAUA;AAkBA;AAAuB;AACP;AAIR;AALuB,KAlBnB,aAAA,GAkBmB,KAAA,GAAA,WAAA,GAAA,MAAA,GAAA,YAAA,GAAA,WAAA,GAAA,SAAA,GAAA,SAAA,GAAA,QAAA;AAAK;AAepC;AAA0B;AAQL;AAOX;AAII;AAnBoB;AAAS;AAkC9B,cAjDA,SAAA,SAAkB,KAAA,CAiDA;EAAA,SAAA,IAAA,EAhDf,aAgDe;EAGM,WAAA,CAAA,OAAA,EAAA,MAAA,EAAA,IAAA,EA/C7B,aA+C6B,EAAA,OAHE,CAGF,EAAA;IAA7B,KAAA,CAAA,EAAA,OAAA;EAH+B,CAAA;AAAY;AAWnD;AAA2B,cA7Cd,YAAA,SAAqB,SAAA,CA6CP;EAGU;EAA7B,SAAA,MAAA,EAAA,MAAA;EAH2B;EAAY,SAAA,IAAA,CAAA,EAAA,MAAA;EAWlC;EAAmB,SAAA,SAAA,CAAA,EAAA,MAAA;EAGK;EAA7B,SAAA,QAAA,CAAA,EAnDa,QAmDb;EAHgC;EAAY,SAAA,IAAA,EAAA,OAAA;EAWvC,WAAA,CAAA,OAAA,EAAmB,MAAA,EAAA,IAAA,EAAQ;IAkB3B,IAAA,CAAA,EAtEH,aAsEoB;IAQjB,MAAA,EAAA,MAAA;IA4CG,IAAA,CAAA,EAAA,MAAA;IAsBA,SAAA,CAAW,EAAA,MAAA;IAAA,QAAA,CAAA,EA5Ib,QA4Ia;IAEhB,IAAA,CAAA,EAAA,OAAA;EACR,CAAA;AAAS;;cAhIC,iBAAA,SAA0B,YAAA;qCAG/B,6BAA6B;;;cAQxB,aAAA,SAAsB,YAAA;qCAG3B,6BAA6B;;;cAQxB,kBAAA,SAA2B,YAAA;qCAGhC,6BAA6B;;;cAQxB,kBAAA,SAA2B,SAAS;;;;;;;;;;;cAkBpC,gBAAA,SAAyB,SAAS;;;;cAQlC,gBAAA,SAAyB,SAAS;;;;;;;;;;;;;;;;;;;;iBA4C/B,wBAAA;;;;;;iBAsBA,WAAA,2BAEL,uBACR"}
|
package/dist/neon/errors.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
//#region src/neon/errors.ts
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Typed error hierarchy surfaced on the `error` channel of every ergonomic call (and
|
|
4
|
+
* thrown when `throwOnError` is set). All are `Error` subclasses with a `kind`
|
|
5
|
+
* discriminant, so the same value works whether you read it from `{ error }` or `catch`
|
|
6
|
+
* it.
|
|
7
|
+
*/
|
|
8
|
+
/** Used when a transport failure carries neither an `errno` code nor any message. */
|
|
9
|
+
const UNKNOWN_TRANSPORT_REASON = "cause unavailable";
|
|
10
|
+
/**
|
|
11
|
+
* Base class for every error the ergonomic layer produces.
|
|
12
|
+
*
|
|
13
|
+
* Every subclass assigns `this.name` as a string literal rather than reading it from the
|
|
14
|
+
* constructor. Bundlers rename classes, so deriving the name at runtime leaves consumers
|
|
15
|
+
* of a minified build with errors called `s` and `r` — unreadable in logs and impossible
|
|
16
|
+
* to group on in an error tracker.
|
|
17
|
+
*/
|
|
3
18
|
var NeonError = class extends Error {
|
|
4
19
|
kind;
|
|
5
20
|
constructor(message, kind, options) {
|
|
6
21
|
super(message, options);
|
|
7
|
-
this.name =
|
|
22
|
+
this.name = "NeonError";
|
|
8
23
|
this.kind = kind;
|
|
9
24
|
}
|
|
10
25
|
};
|
|
@@ -22,6 +37,7 @@ var NeonApiError = class extends NeonError {
|
|
|
22
37
|
body;
|
|
23
38
|
constructor(message, init) {
|
|
24
39
|
super(message, init.kind ?? "api");
|
|
40
|
+
this.name = "NeonApiError";
|
|
25
41
|
this.status = init.status;
|
|
26
42
|
this.code = init.code;
|
|
27
43
|
this.requestId = init.requestId;
|
|
@@ -36,6 +52,7 @@ var NeonNotFoundError = class extends NeonApiError {
|
|
|
36
52
|
...init,
|
|
37
53
|
kind: "not_found"
|
|
38
54
|
});
|
|
55
|
+
this.name = "NeonNotFoundError";
|
|
39
56
|
}
|
|
40
57
|
};
|
|
41
58
|
/** 401/403 — the API key is missing, invalid, or lacks permission. */
|
|
@@ -45,6 +62,7 @@ var NeonAuthError = class extends NeonApiError {
|
|
|
45
62
|
...init,
|
|
46
63
|
kind: "auth"
|
|
47
64
|
});
|
|
65
|
+
this.name = "NeonAuthError";
|
|
48
66
|
}
|
|
49
67
|
};
|
|
50
68
|
/** 429 — rate limited (after retries, if enabled, were exhausted). */
|
|
@@ -54,6 +72,7 @@ var NeonRateLimitError = class extends NeonApiError {
|
|
|
54
72
|
...init,
|
|
55
73
|
kind: "rate_limit"
|
|
56
74
|
});
|
|
75
|
+
this.name = "NeonRateLimitError";
|
|
57
76
|
}
|
|
58
77
|
};
|
|
59
78
|
/** An awaited Neon operation ended in a non-success terminal state. */
|
|
@@ -64,6 +83,7 @@ var NeonOperationError = class extends NeonError {
|
|
|
64
83
|
status;
|
|
65
84
|
constructor(message, init) {
|
|
66
85
|
super(message, "operation");
|
|
86
|
+
this.name = "NeonOperationError";
|
|
67
87
|
this.operationId = init.operationId;
|
|
68
88
|
this.status = init.status;
|
|
69
89
|
}
|
|
@@ -72,12 +92,21 @@ var NeonOperationError = class extends NeonError {
|
|
|
72
92
|
var NeonTimeoutError = class extends NeonError {
|
|
73
93
|
constructor(message) {
|
|
74
94
|
super(message, "timeout");
|
|
95
|
+
this.name = "NeonTimeoutError";
|
|
75
96
|
}
|
|
76
97
|
};
|
|
77
98
|
/** A transport-level failure (DNS, connection, abort) — no HTTP response received. */
|
|
78
99
|
var NeonNetworkError = class extends NeonError {
|
|
100
|
+
/**
|
|
101
|
+
* The most specific reason the platform gave for the failure — an `errno` code such as
|
|
102
|
+
* `ECONNRESET` when one is available, otherwise the innermost non-empty message. Read
|
|
103
|
+
* this instead of matching on {@link message}.
|
|
104
|
+
*/
|
|
105
|
+
reason;
|
|
79
106
|
constructor(message, options) {
|
|
80
|
-
super(message, "network", options);
|
|
107
|
+
super(message, "network", { cause: options?.cause });
|
|
108
|
+
this.name = "NeonNetworkError";
|
|
109
|
+
this.reason = options?.reason ?? UNKNOWN_TRANSPORT_REASON;
|
|
81
110
|
}
|
|
82
111
|
};
|
|
83
112
|
function readApiErrorBody(body) {
|
|
@@ -89,12 +118,38 @@ function readApiErrorBody(body) {
|
|
|
89
118
|
return out;
|
|
90
119
|
}
|
|
91
120
|
/**
|
|
121
|
+
* Walk a transport failure's `cause` chain for the most specific description available.
|
|
122
|
+
*
|
|
123
|
+
* `fetch` reports every transport fault as `TypeError: fetch failed` and puts the real
|
|
124
|
+
* reason underneath, sometimes several levels down and sometimes with an empty message and
|
|
125
|
+
* only an `errno` code. Without this, a DNS failure, a reset connection and a redirect the
|
|
126
|
+
* client refused to follow all produce the same sentence.
|
|
127
|
+
*/
|
|
128
|
+
function describeTransportFailure(error) {
|
|
129
|
+
const seen = /* @__PURE__ */ new Set();
|
|
130
|
+
let current = error;
|
|
131
|
+
let deepestMessage;
|
|
132
|
+
while (current instanceof Error && !seen.has(current)) {
|
|
133
|
+
seen.add(current);
|
|
134
|
+
if ("code" in current && typeof current.code === "string") return current.code;
|
|
135
|
+
if (current.message) deepestMessage = current.message;
|
|
136
|
+
current = current.cause;
|
|
137
|
+
}
|
|
138
|
+
return deepestMessage ?? UNKNOWN_TRANSPORT_REASON;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
92
141
|
* Build the right {@link NeonError} subclass from a raw client result. `error` is the
|
|
93
142
|
* decoded error body (Neon `GeneralError`); `response` is present unless the failure was
|
|
94
143
|
* transport-level.
|
|
95
144
|
*/
|
|
96
145
|
function toNeonError(error, response) {
|
|
97
|
-
if (!response)
|
|
146
|
+
if (!response) {
|
|
147
|
+
const reason = describeTransportFailure(error);
|
|
148
|
+
return new NeonNetworkError(`Network error: no response received from the Neon API (${reason}).`, {
|
|
149
|
+
cause: error,
|
|
150
|
+
reason
|
|
151
|
+
});
|
|
152
|
+
}
|
|
98
153
|
const parsed = readApiErrorBody(error);
|
|
99
154
|
const status = response.status;
|
|
100
155
|
const message = parsed.message ?? `Neon API request failed with status ${status}.`;
|
|
@@ -111,6 +166,6 @@ function toNeonError(error, response) {
|
|
|
111
166
|
return new NeonApiError(message, init);
|
|
112
167
|
}
|
|
113
168
|
//#endregion
|
|
114
|
-
export { NeonApiError, NeonAuthError, NeonError, NeonNetworkError, NeonNotFoundError, NeonOperationError, NeonRateLimitError, NeonTimeoutError, toNeonError };
|
|
169
|
+
export { NeonApiError, NeonAuthError, NeonError, NeonNetworkError, NeonNotFoundError, NeonOperationError, NeonRateLimitError, NeonTimeoutError, describeTransportFailure, toNeonError };
|
|
115
170
|
|
|
116
171
|
//# sourceMappingURL=errors.js.map
|
package/dist/neon/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":[],"sources":["../../src/neon/errors.ts"],"sourcesContent":["/**\n * Typed error hierarchy surfaced on the `error` channel of every ergonomic call (and\n * thrown when `throwOnError` is set). All are `Error` subclasses with a `kind`\n * discriminant, so the same value works whether you read it from `{ error }` or `catch`\n * it.\n */\n\nexport type NeonErrorKind =\n\t| \"api\"\n\t| \"not_found\"\n\t| \"auth\"\n\t| \"rate_limit\"\n\t| \"operation\"\n\t| \"timeout\"\n\t| \"network\"\n\t| \"client\";\n\n
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../../src/neon/errors.ts"],"sourcesContent":["/**\n * Typed error hierarchy surfaced on the `error` channel of every ergonomic call (and\n * thrown when `throwOnError` is set). All are `Error` subclasses with a `kind`\n * discriminant, so the same value works whether you read it from `{ error }` or `catch`\n * it.\n */\n\n/** Used when a transport failure carries neither an `errno` code nor any message. */\nconst UNKNOWN_TRANSPORT_REASON = \"cause unavailable\";\n\nexport type NeonErrorKind =\n\t| \"api\"\n\t| \"not_found\"\n\t| \"auth\"\n\t| \"rate_limit\"\n\t| \"operation\"\n\t| \"timeout\"\n\t| \"network\"\n\t| \"client\";\n\n/**\n * Base class for every error the ergonomic layer produces.\n *\n * Every subclass assigns `this.name` as a string literal rather than reading it from the\n * constructor. Bundlers rename classes, so deriving the name at runtime leaves consumers\n * of a minified build with errors called `s` and `r` — unreadable in logs and impossible\n * to group on in an error tracker.\n */\nexport class NeonError extends Error {\n\treadonly kind: NeonErrorKind;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tkind: NeonErrorKind,\n\t\toptions?: { cause?: unknown },\n\t) {\n\t\tsuper(message, options);\n\t\tthis.name = \"NeonError\";\n\t\tthis.kind = kind;\n\t}\n}\n\n/** A non-2xx HTTP response from the Neon API. */\nexport class NeonApiError extends NeonError {\n\t/** HTTP status code. */\n\treadonly status: number;\n\t/** Machine-readable Neon error code (`GeneralError.code`), when present. */\n\treadonly code?: string;\n\t/** Neon request id (`X-Request-Id` / `GeneralError.request_id`), when present. */\n\treadonly requestId?: string;\n\t/** The raw response, when one was received. */\n\treadonly response?: Response;\n\t/** The parsed error body, as returned by the API. */\n\treadonly body: unknown;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tinit: {\n\t\t\tkind?: NeonErrorKind;\n\t\t\tstatus: number;\n\t\t\tcode?: string;\n\t\t\trequestId?: string;\n\t\t\tresponse?: Response;\n\t\t\tbody?: unknown;\n\t\t},\n\t) {\n\t\tsuper(message, init.kind ?? \"api\");\n\t\tthis.name = \"NeonApiError\";\n\t\tthis.status = init.status;\n\t\tthis.code = init.code;\n\t\tthis.requestId = init.requestId;\n\t\tthis.response = init.response;\n\t\tthis.body = init.body;\n\t}\n}\n\n/** 404 — the resource does not exist. */\nexport class NeonNotFoundError extends NeonApiError {\n\tconstructor(\n\t\tmessage: string,\n\t\tinit: ConstructorParameters<typeof NeonApiError>[1],\n\t) {\n\t\tsuper(message, { ...init, kind: \"not_found\" });\n\t\tthis.name = \"NeonNotFoundError\";\n\t}\n}\n\n/** 401/403 — the API key is missing, invalid, or lacks permission. */\nexport class NeonAuthError extends NeonApiError {\n\tconstructor(\n\t\tmessage: string,\n\t\tinit: ConstructorParameters<typeof NeonApiError>[1],\n\t) {\n\t\tsuper(message, { ...init, kind: \"auth\" });\n\t\tthis.name = \"NeonAuthError\";\n\t}\n}\n\n/** 429 — rate limited (after retries, if enabled, were exhausted). */\nexport class NeonRateLimitError extends NeonApiError {\n\tconstructor(\n\t\tmessage: string,\n\t\tinit: ConstructorParameters<typeof NeonApiError>[1],\n\t) {\n\t\tsuper(message, { ...init, kind: \"rate_limit\" });\n\t\tthis.name = \"NeonRateLimitError\";\n\t}\n}\n\n/** An awaited Neon operation ended in a non-success terminal state. */\nexport class NeonOperationError extends NeonError {\n\t/** The id of the operation that failed. */\n\treadonly operationId: string;\n\t/** The terminal status reported by the API (`failed` / `error` / `cancelled`). */\n\treadonly status: string;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tinit: { operationId: string; status: string },\n\t) {\n\t\tsuper(message, \"operation\");\n\t\tthis.name = \"NeonOperationError\";\n\t\tthis.operationId = init.operationId;\n\t\tthis.status = init.status;\n\t}\n}\n\n/** Waiting for operations to finish exceeded the configured timeout. */\nexport class NeonTimeoutError extends NeonError {\n\tconstructor(message: string) {\n\t\tsuper(message, \"timeout\");\n\t\tthis.name = \"NeonTimeoutError\";\n\t}\n}\n\n/** A transport-level failure (DNS, connection, abort) — no HTTP response received. */\nexport class NeonNetworkError extends NeonError {\n\t/**\n\t * The most specific reason the platform gave for the failure — an `errno` code such as\n\t * `ECONNRESET` when one is available, otherwise the innermost non-empty message. Read\n\t * this instead of matching on {@link message}.\n\t */\n\treadonly reason: string;\n\n\tconstructor(\n\t\tmessage: string,\n\t\toptions?: { cause?: unknown; reason?: string },\n\t) {\n\t\tsuper(message, \"network\", { cause: options?.cause });\n\t\tthis.name = \"NeonNetworkError\";\n\t\tthis.reason = options?.reason ?? UNKNOWN_TRANSPORT_REASON;\n\t}\n}\n\ninterface ApiErrorBody {\n\tmessage?: string;\n\tcode?: string;\n\trequest_id?: string;\n}\n\nfunction readApiErrorBody(body: unknown): ApiErrorBody {\n\tif (typeof body !== \"object\" || body === null) return {};\n\tconst out: ApiErrorBody = {};\n\tif (\"message\" in body && typeof body.message === \"string\")\n\t\tout.message = body.message;\n\tif (\"code\" in body && typeof body.code === \"string\") out.code = body.code;\n\tif (\"request_id\" in body && typeof body.request_id === \"string\") {\n\t\tout.request_id = body.request_id;\n\t}\n\treturn out;\n}\n\n/**\n * Walk a transport failure's `cause` chain for the most specific description available.\n *\n * `fetch` reports every transport fault as `TypeError: fetch failed` and puts the real\n * reason underneath, sometimes several levels down and sometimes with an empty message and\n * only an `errno` code. Without this, a DNS failure, a reset connection and a redirect the\n * client refused to follow all produce the same sentence.\n */\nexport function describeTransportFailure(error: unknown): string {\n\tconst seen = new Set<unknown>();\n\tlet current: unknown = error;\n\tlet deepestMessage: string | undefined;\n\n\twhile (current instanceof Error && !seen.has(current)) {\n\t\tseen.add(current);\n\t\tif (\"code\" in current && typeof current.code === \"string\") {\n\t\t\treturn current.code;\n\t\t}\n\t\tif (current.message) deepestMessage = current.message;\n\t\tcurrent = current.cause;\n\t}\n\n\treturn deepestMessage ?? UNKNOWN_TRANSPORT_REASON;\n}\n\n/**\n * Build the right {@link NeonError} subclass from a raw client result. `error` is the\n * decoded error body (Neon `GeneralError`); `response` is present unless the failure was\n * transport-level.\n */\nexport function toNeonError(\n\terror: unknown,\n\tresponse: Response | undefined,\n): NeonError {\n\tif (!response) {\n\t\tconst reason = describeTransportFailure(error);\n\t\treturn new NeonNetworkError(\n\t\t\t`Network error: no response received from the Neon API (${reason}).`,\n\t\t\t{ cause: error, reason },\n\t\t);\n\t}\n\n\tconst parsed = readApiErrorBody(error);\n\tconst status = response.status;\n\tconst message =\n\t\tparsed.message ?? `Neon API request failed with status ${status}.`;\n\tconst init = {\n\t\tstatus,\n\t\tcode: parsed.code,\n\t\trequestId:\n\t\t\tparsed.request_id ??\n\t\t\tresponse.headers.get(\"x-request-id\") ??\n\t\t\tundefined,\n\t\tresponse,\n\t\tbody: error,\n\t};\n\n\tif (status === 404) return new NeonNotFoundError(message, init);\n\tif (status === 401 || status === 403)\n\t\treturn new NeonAuthError(message, init);\n\tif (status === 429) return new NeonRateLimitError(message, init);\n\treturn new NeonApiError(message, init);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neon/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "The official TypeScript SDK for the Neon API, generated from Neon's OpenAPI specification. A modern, fetch-based replacement for @neondatabase/api-client.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -52,7 +52,8 @@
|
|
|
52
52
|
"console-fail-test": "0.5.0",
|
|
53
53
|
"tsdown": "^0.14.1",
|
|
54
54
|
"typescript": "^5.9.0",
|
|
55
|
-
"vitest": "^3.0.9"
|
|
55
|
+
"vitest": "^3.0.9",
|
|
56
|
+
"@neon/e2e-harness": "0.0.0"
|
|
56
57
|
},
|
|
57
58
|
"engines": {
|
|
58
59
|
"node": ">=20.19.0"
|