@attlaz/client 1.114.0 → 1.115.2
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/Http/ClientError.d.ts +8 -0
- package/dist/Http/ClientError.js +20 -3
- package/dist/Http/HttpClient.js +4 -2
- package/dist/Http/HttpClientResponse.d.ts +7 -2
- package/dist/Http/HttpClientResponse.js +7 -2
- package/dist/Http/Transport/DirectTransport.d.ts +1 -1
- package/dist/Http/Transport/ITransport.d.ts +1 -1
- package/dist/Http/Transport/OAuthClient.d.ts +1 -1
- package/dist/Http/Transport/OAuthClient.js +5 -2
- package/dist/Service/Endpoint.d.ts +2 -2
- package/dist/Service/Endpoint.js +11 -4
- package/dist/Service/StorageEndpoint.d.ts +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -3
|
@@ -2,6 +2,14 @@ export declare class ClientError extends Error {
|
|
|
2
2
|
httpStatus: number | null;
|
|
3
3
|
message: string;
|
|
4
4
|
response: unknown;
|
|
5
|
+
/**
|
|
6
|
+
* The error this one was built from, when it wraps another (see {@link fromError}).
|
|
7
|
+
*
|
|
8
|
+
* Declared here rather than relying on the built-in `Error.cause`: that is ES2022 and this
|
|
9
|
+
* package compiles against es2017 so it still runs in older browsers. Assigning the property
|
|
10
|
+
* works on any engine, and a modern one treats it as the standard field.
|
|
11
|
+
*/
|
|
12
|
+
cause?: unknown;
|
|
5
13
|
constructor(message: string, httpErrorCode?: number | null);
|
|
6
14
|
/**
|
|
7
15
|
* Type guard: true when `error` is a ClientError (or a subclass such as ApiError). Use it to
|
package/dist/Http/ClientError.js
CHANGED
|
@@ -3,6 +3,14 @@ export class ClientError extends Error {
|
|
|
3
3
|
httpStatus = null;
|
|
4
4
|
message;
|
|
5
5
|
response;
|
|
6
|
+
/**
|
|
7
|
+
* The error this one was built from, when it wraps another (see {@link fromError}).
|
|
8
|
+
*
|
|
9
|
+
* Declared here rather than relying on the built-in `Error.cause`: that is ES2022 and this
|
|
10
|
+
* package compiles against es2017 so it still runs in older browsers. Assigning the property
|
|
11
|
+
* works on any engine, and a modern one treats it as the standard field.
|
|
12
|
+
*/
|
|
13
|
+
cause;
|
|
6
14
|
constructor(message, httpErrorCode = null) {
|
|
7
15
|
super(message);
|
|
8
16
|
this.message = message;
|
|
@@ -36,13 +44,22 @@ export class ClientError extends Error {
|
|
|
36
44
|
return error;
|
|
37
45
|
}
|
|
38
46
|
// The transport uses fetch, which throws TypeError on network failures (DNS, refused
|
|
39
|
-
// connection, TLS, etc.).
|
|
40
|
-
//
|
|
47
|
+
// connection, TLS, etc.). That case keeps its own wording: "Service not available" says
|
|
48
|
+
// more to a caller than fetch's own "Failed to fetch".
|
|
49
|
+
//
|
|
50
|
+
// Anything else is unexpected, and its message is the only description of what actually
|
|
51
|
+
// went wrong — so it is carried through rather than replaced. This used to read
|
|
52
|
+
// 'Unknown error', which cost a production outage: a ReferenceError from a Node-only
|
|
53
|
+
// global in the browser reached the user as "Unknown error" with nothing naming Buffer,
|
|
54
|
+
// and the console showed the same for every failed call.
|
|
41
55
|
const clientError = error instanceof TypeError
|
|
42
56
|
? new ClientError('Service not available', HttpStatus.HTTP_UNAVAILABLE)
|
|
43
|
-
: new ClientError('Unknown error', HttpStatus.HTTP_INTERNAL_SERVER_ERROR);
|
|
57
|
+
: new ClientError(error.message === '' ? 'Unknown error' : error.message, HttpStatus.HTTP_INTERNAL_SERVER_ERROR);
|
|
44
58
|
clientError.name = error.name;
|
|
45
59
|
clientError.stack = error.stack;
|
|
60
|
+
// The original survives as `cause`, so a handler can inspect the real error even where the
|
|
61
|
+
// message has been rewritten — the TypeError branch above being exactly that case.
|
|
62
|
+
clientError.cause = error;
|
|
46
63
|
return clientError;
|
|
47
64
|
}
|
|
48
65
|
static byStatus(statusCode, statusText) {
|
package/dist/Http/HttpClient.js
CHANGED
|
@@ -33,7 +33,7 @@ export class HttpClient {
|
|
|
33
33
|
clientError.response = {
|
|
34
34
|
status: rawResponse.status,
|
|
35
35
|
statusText,
|
|
36
|
-
data: JSON.parse(
|
|
36
|
+
data: JSON.parse(await rawResponse.text()),
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
catch {
|
|
@@ -49,7 +49,9 @@ export class HttpClient {
|
|
|
49
49
|
// endpoint supplies a parser, a blob read wants the bytes — so sniffing the content type
|
|
50
50
|
// here would be a second, weaker answer to a question already answered. It was also
|
|
51
51
|
// lossy: the old `text()` fallback UTF-8-decoded binary, turning 10 bytes into 16.
|
|
52
|
-
|
|
52
|
+
//
|
|
53
|
+
// Uint8Array, not Buffer: this runs in the browser too, where Buffer does not exist.
|
|
54
|
+
httpResponse.body = new Uint8Array(await rawResponse.arrayBuffer());
|
|
53
55
|
return httpResponse;
|
|
54
56
|
}
|
|
55
57
|
catch (error) {
|
|
@@ -2,15 +2,20 @@ import { Headers } from './Data/Headers.js';
|
|
|
2
2
|
/**
|
|
3
3
|
* A response as it came off the wire. `body` is always bytes — the transport does not interpret,
|
|
4
4
|
* because the caller already knows what it asked for. Use `getJson()` or `getBytes()` to say which.
|
|
5
|
+
*
|
|
6
|
+
* Bytes are a `Uint8Array`, never a `Buffer`: this package runs in the browser as well as in Node,
|
|
7
|
+
* and `Buffer` is a Node global that simply does not exist there — the same reason `Utils` uses
|
|
8
|
+
* `btoa`/`atob`. A `Buffer` IS a `Uint8Array`, so Node callers can still wrap one without a copy
|
|
9
|
+
* (`Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength)`) when they want its methods.
|
|
5
10
|
*/
|
|
6
11
|
export declare class HttpClientResponse {
|
|
7
12
|
status: number;
|
|
8
13
|
statusText: string;
|
|
9
|
-
body:
|
|
14
|
+
body: Uint8Array | null;
|
|
10
15
|
headers: Headers;
|
|
11
16
|
constructor(status: number, statusText: string);
|
|
12
17
|
/** The raw bytes, empty when the response had no body. */
|
|
13
|
-
getBytes():
|
|
18
|
+
getBytes(): Uint8Array;
|
|
14
19
|
/**
|
|
15
20
|
* The body parsed as JSON, or null when there was none — a 204 and a DELETE that answers empty
|
|
16
21
|
* are normal, and `JSON.parse('')` throws.
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A response as it came off the wire. `body` is always bytes — the transport does not interpret,
|
|
3
3
|
* because the caller already knows what it asked for. Use `getJson()` or `getBytes()` to say which.
|
|
4
|
+
*
|
|
5
|
+
* Bytes are a `Uint8Array`, never a `Buffer`: this package runs in the browser as well as in Node,
|
|
6
|
+
* and `Buffer` is a Node global that simply does not exist there — the same reason `Utils` uses
|
|
7
|
+
* `btoa`/`atob`. A `Buffer` IS a `Uint8Array`, so Node callers can still wrap one without a copy
|
|
8
|
+
* (`Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength)`) when they want its methods.
|
|
4
9
|
*/
|
|
5
10
|
export class HttpClientResponse {
|
|
6
11
|
status;
|
|
@@ -13,7 +18,7 @@ export class HttpClientResponse {
|
|
|
13
18
|
}
|
|
14
19
|
/** The raw bytes, empty when the response had no body. */
|
|
15
20
|
getBytes() {
|
|
16
|
-
return this.body ??
|
|
21
|
+
return this.body ?? new Uint8Array(0);
|
|
17
22
|
}
|
|
18
23
|
/**
|
|
19
24
|
* The body parsed as JSON, or null when there was none — a 204 and a DELETE that answers empty
|
|
@@ -24,6 +29,6 @@ export class HttpClientResponse {
|
|
|
24
29
|
if (bytes.length === 0) {
|
|
25
30
|
return null;
|
|
26
31
|
}
|
|
27
|
-
return JSON.parse(
|
|
32
|
+
return JSON.parse(new TextDecoder().decode(bytes));
|
|
28
33
|
}
|
|
29
34
|
}
|
|
@@ -32,7 +32,7 @@ export declare class DirectTransport implements ITransport {
|
|
|
32
32
|
private parseErrorHandler;
|
|
33
33
|
constructor(defaultBaseUrl: string, sessionPayload: string, sessionSignature: string, routes?: DirectTransportRoute[]);
|
|
34
34
|
request<T>(action: string, parameters?: Parameters, method?: string, _signWithOauthToken?: boolean): Promise<T>;
|
|
35
|
-
requestBytes(action: string, parameters?: Parameters, method?: string, _signWithOauthToken?: boolean, headers?: Record<string, string>): Promise<
|
|
35
|
+
requestBytes(action: string, parameters?: Parameters, method?: string, _signWithOauthToken?: boolean, headers?: Record<string, string>): Promise<Uint8Array>;
|
|
36
36
|
private resolveClient;
|
|
37
37
|
isDebugEnabled(): boolean;
|
|
38
38
|
setParseErrorHandler(handler: ParseErrorHandler | null): void;
|
|
@@ -8,7 +8,7 @@ export type ParseErrorHandler = (message: string, context: Record<string, unknow
|
|
|
8
8
|
export interface ITransport {
|
|
9
9
|
request: <T>(action: string, parameters: Parameters, method: string, signWithOauthToken: boolean) => Promise<T>;
|
|
10
10
|
/** The response bytes, undecoded — for resources a JSON round trip would inflate or destroy. */
|
|
11
|
-
requestBytes: (action: string, parameters: Parameters, method: string, signWithOauthToken: boolean, headers?: Record<string, string>) => Promise<
|
|
11
|
+
requestBytes: (action: string, parameters: Parameters, method: string, signWithOauthToken: boolean, headers?: Record<string, string>) => Promise<Uint8Array>;
|
|
12
12
|
isDebugEnabled: () => boolean;
|
|
13
13
|
reportParseError: (message: string, context: Record<string, unknown>) => void;
|
|
14
14
|
setParseErrorHandler: (handler: ParseErrorHandler | null) => void;
|
|
@@ -52,7 +52,7 @@ export declare class OAuthClient implements ITransport {
|
|
|
52
52
|
* Like `request`, but asks for and returns the raw bytes. For a resource that has a binary
|
|
53
53
|
* representation — a stored item — where decoding would destroy it.
|
|
54
54
|
*/
|
|
55
|
-
requestBytes(action: string, parameters?: Parameters, method?: string, signWithOauthToken?: boolean, headers?: Record<string, string>): Promise<
|
|
55
|
+
requestBytes(action: string, parameters?: Parameters, method?: string, signWithOauthToken?: boolean, headers?: Record<string, string>): Promise<Uint8Array>;
|
|
56
56
|
request<T>(action: string, parameters?: Parameters, method?: string, signWithOauthToken?: boolean): Promise<T>;
|
|
57
57
|
isAuthenticated(): boolean;
|
|
58
58
|
getToken(): OAuthClientToken | null;
|
|
@@ -395,9 +395,12 @@ export class OAuthClient {
|
|
|
395
395
|
requestData.setHeader('Attlaz-API-Version', this.version);
|
|
396
396
|
}
|
|
397
397
|
if ((method === 'POST' || method === 'DELETE' || method === 'PUT' || method === 'PATCH') && parameters !== null && parameters !== undefined) {
|
|
398
|
-
//
|
|
398
|
+
// Raw bytes are the payload, not something to serialise. Stringifying them yields
|
|
399
399
|
// {"type":"Buffer","data":[…]} — larger than the bytes and not what any reader expects.
|
|
400
|
-
|
|
400
|
+
// Tested with instanceof rather than Buffer.isBuffer: Buffer is a Node global and this
|
|
401
|
+
// package runs in the browser, where naming it at all is a ReferenceError. A Buffer is
|
|
402
|
+
// a Uint8Array, so this still catches one.
|
|
403
|
+
if (parameters instanceof Uint8Array) {
|
|
401
404
|
requestData.body = parameters;
|
|
402
405
|
requestData.setHeader('Content-Type', 'application/octet-stream');
|
|
403
406
|
}
|
|
@@ -16,12 +16,12 @@ export declare abstract class Endpoint {
|
|
|
16
16
|
private formatParameters;
|
|
17
17
|
private formatKey;
|
|
18
18
|
/** Raw response bytes for this action — see `ITransport.requestBytes`. */
|
|
19
|
-
requestBytes(action: string, parameters?: Parameters, method?: string, signWithOauthToken?: boolean, headers?: Record<string, string>): Promise<
|
|
19
|
+
requestBytes(action: string, parameters?: Parameters, method?: string, signWithOauthToken?: boolean, headers?: Record<string, string>): Promise<Uint8Array>;
|
|
20
20
|
/**
|
|
21
21
|
* Send raw bytes as the request body. Metadata rides headers because the body IS the value —
|
|
22
22
|
* there is no envelope left to put it in.
|
|
23
23
|
*/
|
|
24
|
-
requestBinary(action: string, value:
|
|
24
|
+
requestBinary(action: string, value: Uint8Array, headers?: Record<string, string>): Promise<void>;
|
|
25
25
|
requestCollection<T>(action: string | QueryString, parser: (input: any) => T, parameters?: Parameters, method?: string, signWithOauthToken?: boolean): Promise<CollectionResult<T>>;
|
|
26
26
|
requestObject<T>(action: string | QueryString, parameters: Parameters | undefined, parser: (input: Record<string, any>) => T, method?: string, signWithOauthToken?: boolean): Promise<ObjectResult<T>>;
|
|
27
27
|
private toApiError;
|
package/dist/Service/Endpoint.js
CHANGED
|
@@ -168,10 +168,17 @@ export class Endpoint {
|
|
|
168
168
|
}
|
|
169
169
|
return apiError;
|
|
170
170
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
// Not a ClientError at all — a bug in this client or in a dependency, rather than anything
|
|
172
|
+
// the API said. Its message is carried through and the original attached as `cause`:
|
|
173
|
+
// replacing both with 'Unknown Error' is what made a browser-only ReferenceError
|
|
174
|
+
// undiagnosable from the console during a production outage.
|
|
175
|
+
const apiError = new ApiError(error instanceof Error && error.message !== '' ? error.message : 'Unknown Error', HttpStatus.HTTP_INTERNAL_SERVER_ERROR);
|
|
176
|
+
if (error instanceof Error) {
|
|
177
|
+
apiError.name = error.name;
|
|
178
|
+
apiError.stack = error.stack;
|
|
179
|
+
}
|
|
180
|
+
apiError.cause = error;
|
|
181
|
+
return apiError;
|
|
175
182
|
}
|
|
176
183
|
parseCollection(rawData, parser) {
|
|
177
184
|
const data = [];
|
|
@@ -25,7 +25,7 @@ export declare class StorageEndpoint extends Endpoint {
|
|
|
25
25
|
* ("do I already have these bytes?") costs headers rather than the whole object.
|
|
26
26
|
*/
|
|
27
27
|
hasItem(projectEnvironmentId: string, storageType: StorageType, bucketKey: string, storageItemKey: string): Promise<boolean>;
|
|
28
|
-
getItemBytes(projectEnvironmentId: string, storageType: StorageType, bucketKey: string, storageItemKey: string): Promise<
|
|
28
|
+
getItemBytes(projectEnvironmentId: string, storageType: StorageType, bucketKey: string, storageItemKey: string): Promise<Uint8Array>;
|
|
29
29
|
/**
|
|
30
30
|
* Store raw bytes. Metadata travels as headers, since the body is the value.
|
|
31
31
|
*
|
|
@@ -33,7 +33,7 @@ export declare class StorageEndpoint extends Endpoint {
|
|
|
33
33
|
* response `Content-Type`, and without it an image is delivered as `application/octet-stream`,
|
|
34
34
|
* which downloads rather than renders.
|
|
35
35
|
*/
|
|
36
|
-
setItemBytes(projectEnvironmentId: string, storageType: StorageType, bucketKey: string, storageItemKey: string, value:
|
|
36
|
+
setItemBytes(projectEnvironmentId: string, storageType: StorageType, bucketKey: string, storageItemKey: string, value: Uint8Array, expiration?: Date | null, contentType?: string | null): Promise<void>;
|
|
37
37
|
setItem(projectEnvironmentId: string, storageType: StorageType, bucketKey: string, storageItem: StorageItem): Promise<StorageItem>;
|
|
38
38
|
deleteItem(projectEnvironmentId: string, storageType: StorageType, bucketKey: string, storageItemKey: string): Promise<boolean>;
|
|
39
39
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "1.
|
|
1
|
+
export declare const VERSION = "1.115.2";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "1.
|
|
1
|
+
export const VERSION = "1.115.2";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@attlaz/client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.115.2",
|
|
4
4
|
"description": "Javascript Client to access Attlaz API",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
|
-
"url": "git+https://
|
|
23
|
+
"url": "git+https://github.com/Attlaz-Platform/JS-Client.git"
|
|
24
24
|
},
|
|
25
25
|
"homepage": "https://attlaz.com",
|
|
26
26
|
"keywords": [
|
|
@@ -49,7 +49,6 @@
|
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public",
|
|
52
|
-
"cache": "~/.npm",
|
|
53
52
|
"registry": "https://registry.npmjs.org"
|
|
54
53
|
},
|
|
55
54
|
"devDependencies": {
|