@faable/sdk-base 1.1.3 → 1.2.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/dist/FaableApi.d.ts +18 -3
- package/dist/FaableApi.d.ts.map +1 -1
- package/dist/FaableApi.js +1 -1
- package/dist/auth/apikey.d.ts +1 -1
- package/dist/auth/apikey.d.ts.map +1 -1
- package/dist/auth/client_credentials/client_credentials.d.ts +1 -1
- package/dist/auth/client_credentials/client_credentials.d.ts.map +1 -1
- package/dist/auth/client_credentials/store.d.ts +1 -1
- package/dist/auth/client_credentials/store.d.ts.map +1 -1
- package/dist/fetcher/fetcher_axios.d.ts +2 -2
- package/dist/fetcher/fetcher_axios.d.ts.map +1 -1
- package/dist/fetcher/fetcher_axios.js +48 -1
- package/dist/helpers/FaableApiError.d.ts +1 -1
- package/dist/helpers/FaableApiError.d.ts.map +1 -1
- package/dist/helpers/paginator.d.ts +1 -1
- package/dist/helpers/paginator.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/FaableApi.d.ts
CHANGED
|
@@ -1,12 +1,27 @@
|
|
|
1
|
-
import { AuthInterface } from "./types/AuthInterface.js";
|
|
2
|
-
import { Fetcher, FetcherCreateParams } from "./fetcher/Fetcher.js";
|
|
3
|
-
import { Paginator, PaginatorOptions } from "./helpers/paginator.js";
|
|
1
|
+
import type { AuthInterface } from "./types/AuthInterface.js";
|
|
2
|
+
import type { Fetcher, FetcherCreateParams } from "./fetcher/Fetcher.js";
|
|
3
|
+
import type { Paginator, PaginatorOptions } from "./helpers/paginator.js";
|
|
4
4
|
export type ApiParams = {
|
|
5
5
|
baseURL?: string;
|
|
6
6
|
fetcher?: FetcherCreateParams;
|
|
7
7
|
auth?: AuthInterface<any, any>;
|
|
8
8
|
debug?: boolean;
|
|
9
9
|
paginator?: Partial<PaginatorOptions>;
|
|
10
|
+
/**
|
|
11
|
+
* Opt-in in-memory ETag cache for GET requests. When enabled, the fetcher
|
|
12
|
+
* remembers each GET's `ETag` and replays it as `If-None-Match`; a `304 Not
|
|
13
|
+
* Modified` reuses the previously parsed body instead of re-downloading it.
|
|
14
|
+
* Correctness relies on the server changing the ETag whenever the resource
|
|
15
|
+
* changes (no client-side invalidation needed — a write bumps the server
|
|
16
|
+
* ETag, so the next GET gets a fresh `200`). Off by default.
|
|
17
|
+
*
|
|
18
|
+
* `true` uses the default cap; pass `{ maxEntries }` to size the bounded LRU
|
|
19
|
+
* for the client's key cardinality (e.g. a controller polling many apps +
|
|
20
|
+
* deployments wants a larger cap than a one-shot script).
|
|
21
|
+
*/
|
|
22
|
+
etagCache?: boolean | {
|
|
23
|
+
maxEntries?: number;
|
|
24
|
+
};
|
|
10
25
|
};
|
|
11
26
|
export declare abstract class FaableApi<Params extends ApiParams = ApiParams> {
|
|
12
27
|
fetcher: Fetcher;
|
package/dist/FaableApi.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FaableApi.d.ts","sourceRoot":"","sources":["../src/FaableApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"FaableApi.d.ts","sourceRoot":"","sources":["../src/FaableApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAGzE,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1E,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,IAAI,CAAC,EAAE,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACtC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG;QAAE,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C,CAAC;AAEF,8BAAsB,SAAS,CAAC,MAAM,SAAS,SAAS,GAAG,SAAS;IAClE,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;IAC/B,SAAS,aAAa,MAAM,CAAC,EAAE,MAAM;IAMrC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,QAAQ,MAAM,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,MAAM,GAAG,GAAG,EACtE,IAAI,EAAE,CAAC,EACP,MAAM,CAAC,EAAE,MAAM,GACd,YAAY,CAAC,CAAC,CAAC;CAInB"}
|
package/dist/FaableApi.js
CHANGED
package/dist/auth/apikey.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StrategyInterface } from "../types/StrategyInterface.js";
|
|
1
|
+
import type { StrategyInterface } from "../types/StrategyInterface.js";
|
|
2
2
|
export type ApikeyAuthParams = Partial<[apikey: string]>;
|
|
3
3
|
export declare const createApikeyAuth: StrategyInterface<ApikeyAuthParams>;
|
|
4
4
|
//# sourceMappingURL=apikey.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apikey.d.ts","sourceRoot":"","sources":["../../src/auth/apikey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"apikey.d.ts","sourceRoot":"","sources":["../../src/auth/apikey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAGvE,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEzD,eAAO,MAAM,gBAAgB,EAAE,iBAAiB,CAAC,gBAAgB,CAoBhE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client_credentials.d.ts","sourceRoot":"","sources":["../../../src/auth/client_credentials/client_credentials.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"client_credentials.d.ts","sourceRoot":"","sources":["../../../src/auth/client_credentials/client_credentials.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAK1E,KAAK,MAAM,GAAG;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAWrE,eAAO,MAAM,uBAAuB,EAAE,iBAAiB,CACrD,2BAA2B,CAgG5B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/auth/client_credentials/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/auth/client_credentials/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE5D,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,gBAAgB,eAAe,iBAAiB;kCAStB,yBAAyB;kBAPlD,yBAAyB;aAC9B,MAAM;;;kBADD,yBAAyB;aAC9B,MAAM;;CAkBd,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fetcher } from "./Fetcher.js";
|
|
2
|
-
import { ApiParams } from "../FaableApi.js";
|
|
1
|
+
import type { Fetcher } from "./Fetcher.js";
|
|
2
|
+
import type { ApiParams } from "../FaableApi.js";
|
|
3
3
|
export declare const fetcher_axios: (params?: ApiParams) => Fetcher;
|
|
4
4
|
//# sourceMappingURL=fetcher_axios.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetcher_axios.d.ts","sourceRoot":"","sources":["../../src/fetcher/fetcher_axios.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAiB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"fetcher_axios.d.ts","sourceRoot":"","sources":["../../src/fetcher/fetcher_axios.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAiB,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAiBjD,eAAO,MAAM,aAAa,YAAY,SAAS,KAAQ,OA0HtD,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import axios from "axios";
|
|
1
|
+
import axios, { AxiosError } from "axios";
|
|
2
2
|
import { FaableApiError } from "../helpers/FaableApiError.js";
|
|
3
3
|
const handleErrorInterceptor = async (e) => {
|
|
4
4
|
if (!e.isAxiosError) {
|
|
@@ -32,13 +32,60 @@ export const fetcher_axios = (params = {}) => {
|
|
|
32
32
|
}
|
|
33
33
|
return res;
|
|
34
34
|
}, handleErrorInterceptor);
|
|
35
|
+
// Opt-in in-memory ETag cache (per fetcher instance). Keyed by url + params
|
|
36
|
+
// so each list cursor / expanded GET caches independently. Server-driven
|
|
37
|
+
// invalidation only — a changed resource changes its ETag, so the
|
|
38
|
+
// conditional request returns a fresh 200 instead of 304.
|
|
39
|
+
//
|
|
40
|
+
// Bounded LRU: a long-lived client keeps minting distinct keys (e.g. a new
|
|
41
|
+
// `GET /deployment/:id` per deploy), so an unbounded map would leak. The Map
|
|
42
|
+
// preserves insertion order; every access re-inserts its key (moving it to
|
|
43
|
+
// the most-recent end) and inserts past the cap evict the least-recently-used
|
|
44
|
+
// (oldest) entry.
|
|
45
|
+
const etagOpt = params.etagCache;
|
|
46
|
+
const etagEnabled = etagOpt === true || (typeof etagOpt === "object" && etagOpt !== null);
|
|
47
|
+
const ETAG_CACHE_MAX = (typeof etagOpt === "object" && etagOpt?.maxEntries) || 1000;
|
|
48
|
+
const etagCache = new Map();
|
|
49
|
+
const etagKey = (url, p) => `${url}::${p ? JSON.stringify(p) : ""}`;
|
|
50
|
+
const etagTouch = (key, entry) => {
|
|
51
|
+
etagCache.delete(key);
|
|
52
|
+
etagCache.set(key, entry);
|
|
53
|
+
if (etagCache.size > ETAG_CACHE_MAX) {
|
|
54
|
+
etagCache.delete(etagCache.keys().next().value);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
35
57
|
return {
|
|
36
58
|
get: async (url, config) => {
|
|
59
|
+
if (!etagEnabled) {
|
|
60
|
+
const res = await instance.request({
|
|
61
|
+
method: "GET",
|
|
62
|
+
url,
|
|
63
|
+
...config,
|
|
64
|
+
});
|
|
65
|
+
return res.data;
|
|
66
|
+
}
|
|
67
|
+
const key = etagKey(url, config?.params);
|
|
68
|
+
const cached = etagCache.get(key);
|
|
37
69
|
const res = await instance.request({
|
|
38
70
|
method: "GET",
|
|
39
71
|
url,
|
|
40
72
|
...config,
|
|
73
|
+
headers: {
|
|
74
|
+
...config?.headers,
|
|
75
|
+
...(cached ? { "If-None-Match": cached.etag } : {}),
|
|
76
|
+
},
|
|
77
|
+
// Accept 304 so axios resolves (instead of routing it through the
|
|
78
|
+
// error interceptor) and we can serve the cached body.
|
|
79
|
+
validateStatus: (s) => (s >= 200 && s < 300) || s === 304,
|
|
41
80
|
});
|
|
81
|
+
if (res.status === 304 && cached) {
|
|
82
|
+
etagTouch(key, cached); // mark as recently used
|
|
83
|
+
return cached.data;
|
|
84
|
+
}
|
|
85
|
+
const etag = res.headers?.etag;
|
|
86
|
+
if (etag) {
|
|
87
|
+
etagTouch(key, { etag, data: res.data });
|
|
88
|
+
}
|
|
42
89
|
return res.data;
|
|
43
90
|
},
|
|
44
91
|
delete: async (url, config) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FetcherResponse } from "../fetcher/Fetcher.js";
|
|
1
|
+
import type { FetcherResponse } from "../fetcher/Fetcher.js";
|
|
2
2
|
type Status = "not-found" | "created" | "ok" | "unauthorized" | "bad-request" | "internal-server-error" | "service-unavailable" | "bad-gateway";
|
|
3
3
|
export declare const build_error_message: (message?: string, response?: FetcherResponse) => string;
|
|
4
4
|
export declare class FaableApiError extends Error {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FaableApiError.d.ts","sourceRoot":"","sources":["../../src/helpers/FaableApiError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"FaableApiError.d.ts","sourceRoot":"","sources":["../../src/helpers/FaableApiError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,KAAK,MAAM,GACP,WAAW,GACX,SAAS,GACT,IAAI,GACJ,cAAc,GACd,aAAa,GACb,uBAAuB,GACvB,qBAAqB,GACrB,aAAa,CAAC;AAYlB,eAAO,MAAM,mBAAmB,aACpB,MAAM,aACL,eAAe,WAO3B,CAAC;AAEF,qBAAa,cAAe,SAAQ,KAAK;IACvC,gBAAgB,UAAQ;IACxB,QAAQ,CAAC,EAAE,eAAe,CAAC;gBACf,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,eAAe;IAOxD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAI/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paginator.d.ts","sourceRoot":"","sources":["../../src/helpers/paginator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"paginator.d.ts","sourceRoot":"","sources":["../../src/helpers/paginator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAG3E,MAAM,WAAW,IAAI,CAAC,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,CAAC,EAAE,CAAC;CACd;AACD,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AAE1D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,eAAO,MAAM,cAAc,YAChB,OAAO,YACN,OAAO,CAAC,gBAAgB,CAAC,MAO3B,CAAC,OAAO,oBAAoB;;;oBAoCX;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;CAWhE,CAAC"}
|