@frogfish/k2db-api 1.0.10
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/index.d.ts +134 -0
- package/dist/index.js +210 -0
- package/dist/index.js.map +1 -0
- package/package.json +33 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { ServiceError } from '@frogfish/k2error';
|
|
2
|
+
|
|
3
|
+
interface K2ClientOptions {
|
|
4
|
+
baseUrl: string;
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
fetch?: typeof fetch;
|
|
7
|
+
headers?: Record<string, string>;
|
|
8
|
+
}
|
|
9
|
+
interface RequestOptions {
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
scope?: string;
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
}
|
|
15
|
+
interface CreateResult {
|
|
16
|
+
id: string;
|
|
17
|
+
created: boolean;
|
|
18
|
+
}
|
|
19
|
+
interface UpdateResult {
|
|
20
|
+
updated: number;
|
|
21
|
+
}
|
|
22
|
+
interface RestoreResult {
|
|
23
|
+
restored: number;
|
|
24
|
+
}
|
|
25
|
+
interface CountResult {
|
|
26
|
+
count: number;
|
|
27
|
+
}
|
|
28
|
+
interface SearchRequest {
|
|
29
|
+
filter?: Record<string, unknown>;
|
|
30
|
+
params?: Record<string, unknown>;
|
|
31
|
+
skip?: number;
|
|
32
|
+
limit?: number;
|
|
33
|
+
}
|
|
34
|
+
interface AggregateRequest {
|
|
35
|
+
criteria: Record<string, unknown>[];
|
|
36
|
+
skip?: number;
|
|
37
|
+
limit?: number;
|
|
38
|
+
}
|
|
39
|
+
interface CountRequest {
|
|
40
|
+
criteria?: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
interface BulkUpdateRequest<TValues extends Record<string, unknown>> {
|
|
43
|
+
criteria: Record<string, unknown>;
|
|
44
|
+
values: Partial<TValues>;
|
|
45
|
+
}
|
|
46
|
+
interface RestoreRequest {
|
|
47
|
+
criteria: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
interface VersionedUpdateRequest<TData extends Record<string, unknown>> {
|
|
50
|
+
data: Partial<TData>;
|
|
51
|
+
replace?: boolean;
|
|
52
|
+
maxVersions?: number;
|
|
53
|
+
}
|
|
54
|
+
interface VersionInfo<TData extends Record<string, unknown>> {
|
|
55
|
+
version: number;
|
|
56
|
+
timestamp: string;
|
|
57
|
+
data: TData;
|
|
58
|
+
}
|
|
59
|
+
interface VersionedUpdateResult {
|
|
60
|
+
version: number;
|
|
61
|
+
updated: number;
|
|
62
|
+
}
|
|
63
|
+
interface IndexRequest {
|
|
64
|
+
indexSpec: Record<string, unknown>;
|
|
65
|
+
options?: Record<string, unknown>;
|
|
66
|
+
}
|
|
67
|
+
interface ReadyOk {
|
|
68
|
+
status: 'ready';
|
|
69
|
+
}
|
|
70
|
+
interface ReadyNotOk {
|
|
71
|
+
status: 'not-ready';
|
|
72
|
+
databases: string[];
|
|
73
|
+
}
|
|
74
|
+
interface HealthOk {
|
|
75
|
+
status: 'ok';
|
|
76
|
+
}
|
|
77
|
+
declare class K2ApiError extends Error {
|
|
78
|
+
status: number;
|
|
79
|
+
body: unknown;
|
|
80
|
+
constructor(message: string, status: number, body: unknown);
|
|
81
|
+
}
|
|
82
|
+
interface ProblemDetailsPayload {
|
|
83
|
+
type?: string;
|
|
84
|
+
title?: string;
|
|
85
|
+
status?: number;
|
|
86
|
+
detail?: string;
|
|
87
|
+
trace?: string;
|
|
88
|
+
chain?: ErrorChainItem[];
|
|
89
|
+
}
|
|
90
|
+
interface ErrorChainItem {
|
|
91
|
+
error: ServiceError;
|
|
92
|
+
error_description: string;
|
|
93
|
+
stage?: string;
|
|
94
|
+
at: number;
|
|
95
|
+
}
|
|
96
|
+
declare class K2DbApiClient {
|
|
97
|
+
private baseUrl;
|
|
98
|
+
private apiKey;
|
|
99
|
+
private fetchImpl;
|
|
100
|
+
private defaultHeaders;
|
|
101
|
+
constructor(options: K2ClientOptions);
|
|
102
|
+
health(options?: RequestOptions): Promise<HealthOk>;
|
|
103
|
+
ready(options?: RequestOptions): Promise<ReadyOk | ReadyNotOk>;
|
|
104
|
+
create<TDoc extends Record<string, unknown>>(collection: string, document: Partial<TDoc>, options?: RequestOptions): Promise<CreateResult>;
|
|
105
|
+
getById<TDoc extends Record<string, unknown>>(collection: string, id: string, options?: RequestOptions): Promise<TDoc>;
|
|
106
|
+
patchById<TDoc extends Record<string, unknown>>(collection: string, id: string, updates: Partial<TDoc>, options?: RequestOptions): Promise<UpdateResult>;
|
|
107
|
+
deleteById(collection: string, id: string, options?: RequestOptions): Promise<void>;
|
|
108
|
+
patchCollection<TDoc extends Record<string, unknown>>(collection: string, payload: BulkUpdateRequest<TDoc>, options?: RequestOptions): Promise<UpdateResult>;
|
|
109
|
+
search<TDoc extends Record<string, unknown>>(collection: string, payload?: SearchRequest, options?: RequestOptions): Promise<TDoc[]>;
|
|
110
|
+
aggregate<TDoc extends Record<string, unknown>>(collection: string, payload: AggregateRequest, options?: RequestOptions): Promise<TDoc[]>;
|
|
111
|
+
count(collection: string, payload?: CountRequest, options?: RequestOptions): Promise<CountResult>;
|
|
112
|
+
restore(collection: string, payload: RestoreRequest, options?: RequestOptions): Promise<RestoreResult>;
|
|
113
|
+
getVersions<TDoc extends Record<string, unknown>>(collection: string, id: string, query?: {
|
|
114
|
+
skip?: number;
|
|
115
|
+
limit?: number;
|
|
116
|
+
}, options?: RequestOptions): Promise<Array<VersionInfo<TDoc>>>;
|
|
117
|
+
patchVersions<TDoc extends Record<string, unknown>>(collection: string, id: string, payload: VersionedUpdateRequest<TDoc>, options?: RequestOptions): Promise<VersionedUpdateResult[]>;
|
|
118
|
+
revertVersion(collection: string, id: string, version: number, options?: RequestOptions): Promise<UpdateResult>;
|
|
119
|
+
adminDeleteCollection(collection: string, options?: RequestOptions): Promise<void>;
|
|
120
|
+
adminDeleteById(collection: string, id: string, options?: RequestOptions): Promise<void>;
|
|
121
|
+
adminCreateIndexes(collection: string, payload: IndexRequest, options?: RequestOptions): Promise<{
|
|
122
|
+
message: string;
|
|
123
|
+
}>;
|
|
124
|
+
adminCreateHistoryIndexes(collection: string, payload?: Record<string, unknown>, options?: RequestOptions): Promise<{
|
|
125
|
+
message: string;
|
|
126
|
+
}>;
|
|
127
|
+
private request;
|
|
128
|
+
private tryRehydrateK2Error;
|
|
129
|
+
private parseServiceError;
|
|
130
|
+
private buildUrl;
|
|
131
|
+
private buildHeaders;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export { type AggregateRequest, type BulkUpdateRequest, type CountRequest, type CountResult, type CreateResult, type ErrorChainItem, type HealthOk, type IndexRequest, K2ApiError, type K2ClientOptions, K2DbApiClient, type ProblemDetailsPayload, type ReadyNotOk, type ReadyOk, type RequestOptions, type RestoreRequest, type RestoreResult, type SearchRequest, type UpdateResult, type VersionInfo, type VersionedUpdateRequest, type VersionedUpdateResult };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// src/k2db-client.ts
|
|
2
|
+
import { K2Error, ServiceError } from "@frogfish/k2error";
|
|
3
|
+
var K2ApiError = class extends Error {
|
|
4
|
+
status;
|
|
5
|
+
body;
|
|
6
|
+
constructor(message, status, body) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "K2ApiError";
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.body = body;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
var K2DbApiClient = class {
|
|
14
|
+
baseUrl;
|
|
15
|
+
apiKey;
|
|
16
|
+
fetchImpl;
|
|
17
|
+
defaultHeaders;
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
20
|
+
this.apiKey = options.apiKey;
|
|
21
|
+
this.fetchImpl = options.fetch ?? globalThis.fetch;
|
|
22
|
+
this.defaultHeaders = options.headers;
|
|
23
|
+
}
|
|
24
|
+
async health(options = {}) {
|
|
25
|
+
return this.request("GET", "/health", { ...options, authOptional: true });
|
|
26
|
+
}
|
|
27
|
+
async ready(options = {}) {
|
|
28
|
+
return this.request("GET", "/ready", { ...options, authOptional: true });
|
|
29
|
+
}
|
|
30
|
+
async create(collection, document, options = {}) {
|
|
31
|
+
return this.request("POST", `/v1/${encodeURIComponent(collection)}`, {
|
|
32
|
+
...options,
|
|
33
|
+
body: document
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async getById(collection, id, options = {}) {
|
|
37
|
+
return this.request("GET", `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}`, options);
|
|
38
|
+
}
|
|
39
|
+
async patchById(collection, id, updates, options = {}) {
|
|
40
|
+
return this.request("PATCH", `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}`, {
|
|
41
|
+
...options,
|
|
42
|
+
body: updates
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async deleteById(collection, id, options = {}) {
|
|
46
|
+
await this.request("DELETE", `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}`, options);
|
|
47
|
+
}
|
|
48
|
+
async patchCollection(collection, payload, options = {}) {
|
|
49
|
+
return this.request("PATCH", `/v1/${encodeURIComponent(collection)}`, {
|
|
50
|
+
...options,
|
|
51
|
+
body: payload
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async search(collection, payload = {}, options = {}) {
|
|
55
|
+
return this.request("POST", `/v1/${encodeURIComponent(collection)}/search`, {
|
|
56
|
+
...options,
|
|
57
|
+
body: payload
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async aggregate(collection, payload, options = {}) {
|
|
61
|
+
return this.request("POST", `/v1/${encodeURIComponent(collection)}/aggregate`, {
|
|
62
|
+
...options,
|
|
63
|
+
body: payload
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async count(collection, payload = {}, options = {}) {
|
|
67
|
+
return this.request("POST", `/v1/${encodeURIComponent(collection)}/count`, {
|
|
68
|
+
...options,
|
|
69
|
+
body: payload
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async restore(collection, payload, options = {}) {
|
|
73
|
+
return this.request("POST", `/v1/${encodeURIComponent(collection)}/restore`, {
|
|
74
|
+
...options,
|
|
75
|
+
body: payload
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
async getVersions(collection, id, query = {}, options = {}) {
|
|
79
|
+
return this.request("GET", `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}/versions`, {
|
|
80
|
+
...options,
|
|
81
|
+
query
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
async patchVersions(collection, id, payload, options = {}) {
|
|
85
|
+
return this.request("PATCH", `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}/versions`, {
|
|
86
|
+
...options,
|
|
87
|
+
body: payload
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async revertVersion(collection, id, version, options = {}) {
|
|
91
|
+
return this.request(
|
|
92
|
+
"POST",
|
|
93
|
+
`/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}/versions/${encodeURIComponent(String(version))}/revert`,
|
|
94
|
+
options
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
async adminDeleteCollection(collection, options = {}) {
|
|
98
|
+
await this.request("DELETE", `/v1/admin/${encodeURIComponent(collection)}`, options);
|
|
99
|
+
}
|
|
100
|
+
async adminDeleteById(collection, id, options = {}) {
|
|
101
|
+
await this.request("DELETE", `/v1/admin/${encodeURIComponent(collection)}/${encodeURIComponent(id)}`, options);
|
|
102
|
+
}
|
|
103
|
+
async adminCreateIndexes(collection, payload, options = {}) {
|
|
104
|
+
return this.request("POST", `/v1/admin/${encodeURIComponent(collection)}/indexes`, {
|
|
105
|
+
...options,
|
|
106
|
+
body: payload
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async adminCreateHistoryIndexes(collection, payload = {}, options = {}) {
|
|
110
|
+
return this.request("POST", `/v1/admin/${encodeURIComponent(collection)}/history-indexes`, {
|
|
111
|
+
...options,
|
|
112
|
+
body: payload
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async request(method, path, options) {
|
|
116
|
+
const url = this.buildUrl(path, options.query);
|
|
117
|
+
const headers = this.buildHeaders(options);
|
|
118
|
+
const init = {
|
|
119
|
+
method,
|
|
120
|
+
headers
|
|
121
|
+
};
|
|
122
|
+
if (options.signal) {
|
|
123
|
+
init.signal = options.signal;
|
|
124
|
+
}
|
|
125
|
+
if (options.body !== void 0) {
|
|
126
|
+
init.body = JSON.stringify(options.body);
|
|
127
|
+
}
|
|
128
|
+
const res = await this.fetchImpl(url, init);
|
|
129
|
+
if (res.status === 204) {
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
133
|
+
const isJson = contentType.includes("application/json") || contentType.includes("application/problem+json");
|
|
134
|
+
const payload = isJson ? await res.json() : await res.text();
|
|
135
|
+
if (!res.ok) {
|
|
136
|
+
if (isJson) {
|
|
137
|
+
const k2err = this.tryRehydrateK2Error(payload, res.status);
|
|
138
|
+
if (k2err) {
|
|
139
|
+
throw k2err;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const message = typeof payload === "string" && payload ? payload : `Request failed: ${res.status}`;
|
|
143
|
+
throw new K2ApiError(message, res.status, payload);
|
|
144
|
+
}
|
|
145
|
+
return payload;
|
|
146
|
+
}
|
|
147
|
+
tryRehydrateK2Error(payload, status) {
|
|
148
|
+
if (!payload || typeof payload !== "object") return null;
|
|
149
|
+
const problem = payload;
|
|
150
|
+
const errorId = this.parseServiceError(problem.type);
|
|
151
|
+
if (!errorId && !problem.detail) return null;
|
|
152
|
+
const err = new K2Error(
|
|
153
|
+
errorId ?? ServiceError.SERVICE_ERROR,
|
|
154
|
+
problem.detail ?? `Request failed: ${status}`,
|
|
155
|
+
problem.trace
|
|
156
|
+
);
|
|
157
|
+
if (typeof problem.status === "number" && Number.isFinite(problem.status)) {
|
|
158
|
+
err.code = problem.status;
|
|
159
|
+
} else {
|
|
160
|
+
err.code = status;
|
|
161
|
+
}
|
|
162
|
+
if (Array.isArray(problem.chain)) {
|
|
163
|
+
err.chain = problem.chain;
|
|
164
|
+
}
|
|
165
|
+
return err;
|
|
166
|
+
}
|
|
167
|
+
parseServiceError(typeValue) {
|
|
168
|
+
if (!typeValue || typeof typeValue !== "string") return void 0;
|
|
169
|
+
const prefix = "urn:service-error:";
|
|
170
|
+
if (!typeValue.startsWith(prefix)) return void 0;
|
|
171
|
+
const id = typeValue.slice(prefix.length);
|
|
172
|
+
if (!id) return void 0;
|
|
173
|
+
const values = Object.values(ServiceError);
|
|
174
|
+
return values.includes(id) ? id : void 0;
|
|
175
|
+
}
|
|
176
|
+
buildUrl(path, query) {
|
|
177
|
+
const base = `${this.baseUrl}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
178
|
+
if (!query || Object.keys(query).length === 0) return base;
|
|
179
|
+
const params = new URLSearchParams();
|
|
180
|
+
for (const [key, value] of Object.entries(query)) {
|
|
181
|
+
if (value === void 0 || value === null) continue;
|
|
182
|
+
params.set(key, String(value));
|
|
183
|
+
}
|
|
184
|
+
const qs = params.toString();
|
|
185
|
+
return qs ? `${base}?${qs}` : base;
|
|
186
|
+
}
|
|
187
|
+
buildHeaders(options) {
|
|
188
|
+
const headers = {
|
|
189
|
+
accept: "application/json",
|
|
190
|
+
...this.defaultHeaders,
|
|
191
|
+
...options.headers
|
|
192
|
+
};
|
|
193
|
+
if (options.body !== void 0) {
|
|
194
|
+
headers["content-type"] = "application/json";
|
|
195
|
+
}
|
|
196
|
+
if (options.scope) {
|
|
197
|
+
headers["x-scope"] = options.scope;
|
|
198
|
+
}
|
|
199
|
+
const apiKey = options.apiKey ?? this.apiKey;
|
|
200
|
+
if (apiKey && !options.authOptional) {
|
|
201
|
+
headers.authorization = apiKey.startsWith("ApiKey ") ? apiKey : `ApiKey ${apiKey}`;
|
|
202
|
+
}
|
|
203
|
+
return headers;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
export {
|
|
207
|
+
K2ApiError,
|
|
208
|
+
K2DbApiClient
|
|
209
|
+
};
|
|
210
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/k2db-client.ts"],"sourcesContent":["import { K2Error, ServiceError } from '@frogfish/k2error'\n\nexport interface K2ClientOptions {\n baseUrl: string\n apiKey?: string\n fetch?: typeof fetch\n headers?: Record<string, string>\n}\n\nexport interface RequestOptions {\n apiKey?: string\n scope?: string\n headers?: Record<string, string>\n signal?: AbortSignal\n}\n\nexport interface CreateResult {\n id: string\n created: boolean\n}\n\nexport interface UpdateResult {\n updated: number\n}\n\nexport interface RestoreResult {\n restored: number\n}\n\nexport interface CountResult {\n count: number\n}\n\nexport interface SearchRequest {\n filter?: Record<string, unknown>\n params?: Record<string, unknown>\n skip?: number\n limit?: number\n}\n\nexport interface AggregateRequest {\n criteria: Record<string, unknown>[]\n skip?: number\n limit?: number\n}\n\nexport interface CountRequest {\n criteria?: Record<string, unknown>\n}\n\nexport interface BulkUpdateRequest<TValues extends Record<string, unknown>> {\n criteria: Record<string, unknown>\n values: Partial<TValues>\n}\n\nexport interface RestoreRequest {\n criteria: Record<string, unknown>\n}\n\nexport interface VersionedUpdateRequest<TData extends Record<string, unknown>> {\n data: Partial<TData>\n replace?: boolean\n maxVersions?: number\n}\n\nexport interface VersionInfo<TData extends Record<string, unknown>> {\n version: number\n timestamp: string\n data: TData\n}\n\nexport interface VersionedUpdateResult {\n version: number\n updated: number\n}\n\nexport interface IndexRequest {\n indexSpec: Record<string, unknown>\n options?: Record<string, unknown>\n}\n\nexport interface ReadyOk {\n status: 'ready'\n}\n\nexport interface ReadyNotOk {\n status: 'not-ready'\n databases: string[]\n}\n\nexport interface HealthOk {\n status: 'ok'\n}\n\nexport class K2ApiError extends Error {\n status: number\n body: unknown\n\n constructor(message: string, status: number, body: unknown) {\n super(message)\n this.name = 'K2ApiError'\n this.status = status\n this.body = body\n }\n}\n\nexport interface ProblemDetailsPayload {\n type?: string\n title?: string\n status?: number\n detail?: string\n trace?: string\n chain?: ErrorChainItem[]\n}\n\nexport interface ErrorChainItem {\n error: ServiceError\n error_description: string\n stage?: string\n at: number\n}\n\nexport class K2DbApiClient {\n private baseUrl: string\n private apiKey: string | undefined\n private fetchImpl: typeof fetch\n private defaultHeaders: Record<string, string> | undefined\n\n constructor(options: K2ClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/+$/, '')\n this.apiKey = options.apiKey\n this.fetchImpl = options.fetch ?? globalThis.fetch\n this.defaultHeaders = options.headers\n }\n\n async health(options: RequestOptions = {}): Promise<HealthOk> {\n return this.request('GET', '/health', { ...options, authOptional: true })\n }\n\n async ready(options: RequestOptions = {}): Promise<ReadyOk | ReadyNotOk> {\n return this.request('GET', '/ready', { ...options, authOptional: true })\n }\n\n async create<TDoc extends Record<string, unknown>>(\n collection: string,\n document: Partial<TDoc>,\n options: RequestOptions = {}\n ): Promise<CreateResult> {\n return this.request('POST', `/v1/${encodeURIComponent(collection)}`, {\n ...options,\n body: document,\n })\n }\n\n async getById<TDoc extends Record<string, unknown>>(\n collection: string,\n id: string,\n options: RequestOptions = {}\n ): Promise<TDoc> {\n return this.request('GET', `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}`, options)\n }\n\n async patchById<TDoc extends Record<string, unknown>>(\n collection: string,\n id: string,\n updates: Partial<TDoc>,\n options: RequestOptions = {}\n ): Promise<UpdateResult> {\n return this.request('PATCH', `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}`, {\n ...options,\n body: updates,\n })\n }\n\n async deleteById(\n collection: string,\n id: string,\n options: RequestOptions = {}\n ): Promise<void> {\n await this.request('DELETE', `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}`, options)\n }\n\n async patchCollection<TDoc extends Record<string, unknown>>(\n collection: string,\n payload: BulkUpdateRequest<TDoc>,\n options: RequestOptions = {}\n ): Promise<UpdateResult> {\n return this.request('PATCH', `/v1/${encodeURIComponent(collection)}`, {\n ...options,\n body: payload,\n })\n }\n\n async search<TDoc extends Record<string, unknown>>(\n collection: string,\n payload: SearchRequest = {},\n options: RequestOptions = {}\n ): Promise<TDoc[]> {\n return this.request('POST', `/v1/${encodeURIComponent(collection)}/search`, {\n ...options,\n body: payload,\n })\n }\n\n async aggregate<TDoc extends Record<string, unknown>>(\n collection: string,\n payload: AggregateRequest,\n options: RequestOptions = {}\n ): Promise<TDoc[]> {\n return this.request('POST', `/v1/${encodeURIComponent(collection)}/aggregate`, {\n ...options,\n body: payload,\n })\n }\n\n async count(\n collection: string,\n payload: CountRequest = {},\n options: RequestOptions = {}\n ): Promise<CountResult> {\n return this.request('POST', `/v1/${encodeURIComponent(collection)}/count`, {\n ...options,\n body: payload,\n })\n }\n\n async restore(\n collection: string,\n payload: RestoreRequest,\n options: RequestOptions = {}\n ): Promise<RestoreResult> {\n return this.request('POST', `/v1/${encodeURIComponent(collection)}/restore`, {\n ...options,\n body: payload,\n })\n }\n\n async getVersions<TDoc extends Record<string, unknown>>(\n collection: string,\n id: string,\n query: { skip?: number; limit?: number } = {},\n options: RequestOptions = {}\n ): Promise<Array<VersionInfo<TDoc>>> {\n return this.request('GET', `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}/versions`, {\n ...options,\n query,\n })\n }\n\n async patchVersions<TDoc extends Record<string, unknown>>(\n collection: string,\n id: string,\n payload: VersionedUpdateRequest<TDoc>,\n options: RequestOptions = {}\n ): Promise<VersionedUpdateResult[]> {\n return this.request('PATCH', `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}/versions`, {\n ...options,\n body: payload,\n })\n }\n\n async revertVersion(\n collection: string,\n id: string,\n version: number,\n options: RequestOptions = {}\n ): Promise<UpdateResult> {\n return this.request(\n 'POST',\n `/v1/${encodeURIComponent(collection)}/${encodeURIComponent(id)}/versions/${encodeURIComponent(String(version))}/revert`,\n options\n )\n }\n\n async adminDeleteCollection(\n collection: string,\n options: RequestOptions = {}\n ): Promise<void> {\n await this.request('DELETE', `/v1/admin/${encodeURIComponent(collection)}`, options)\n }\n\n async adminDeleteById(\n collection: string,\n id: string,\n options: RequestOptions = {}\n ): Promise<void> {\n await this.request('DELETE', `/v1/admin/${encodeURIComponent(collection)}/${encodeURIComponent(id)}`, options)\n }\n\n async adminCreateIndexes(\n collection: string,\n payload: IndexRequest,\n options: RequestOptions = {}\n ): Promise<{ message: string }> {\n return this.request('POST', `/v1/admin/${encodeURIComponent(collection)}/indexes`, {\n ...options,\n body: payload,\n })\n }\n\n async adminCreateHistoryIndexes(\n collection: string,\n payload: Record<string, unknown> = {},\n options: RequestOptions = {}\n ): Promise<{ message: string }> {\n return this.request('POST', `/v1/admin/${encodeURIComponent(collection)}/history-indexes`, {\n ...options,\n body: payload,\n })\n }\n\n private async request<T>(\n method: string,\n path: string,\n options: RequestOptions & {\n body?: unknown\n query?: Record<string, unknown>\n authOptional?: boolean\n }\n ): Promise<T> {\n const url = this.buildUrl(path, options.query)\n const headers = this.buildHeaders(options)\n const init: RequestInit = {\n method,\n headers,\n }\n if (options.signal) {\n init.signal = options.signal\n }\n if (options.body !== undefined) {\n init.body = JSON.stringify(options.body)\n }\n\n const res = await this.fetchImpl(url, init)\n\n if (res.status === 204) {\n return undefined as T\n }\n\n const contentType = res.headers.get('content-type') ?? ''\n const isJson = contentType.includes('application/json') || contentType.includes('application/problem+json')\n const payload = isJson ? await res.json() : await res.text()\n\n if (!res.ok) {\n if (isJson) {\n const k2err = this.tryRehydrateK2Error(payload, res.status)\n if (k2err) {\n throw k2err\n }\n }\n\n const message = typeof payload === 'string' && payload ? payload : `Request failed: ${res.status}`\n throw new K2ApiError(message, res.status, payload)\n }\n\n return payload as T\n }\n\n private tryRehydrateK2Error(payload: unknown, status: number): K2Error | null {\n if (!payload || typeof payload !== 'object') return null\n\n const problem = payload as ProblemDetailsPayload\n const errorId = this.parseServiceError(problem.type)\n if (!errorId && !problem.detail) return null\n\n const err = new K2Error(\n errorId ?? ServiceError.SERVICE_ERROR,\n problem.detail ?? `Request failed: ${status}`,\n problem.trace\n )\n\n if (typeof problem.status === 'number' && Number.isFinite(problem.status)) {\n err.code = problem.status\n } else {\n err.code = status\n }\n\n if (Array.isArray(problem.chain)) {\n err.chain = problem.chain\n }\n\n return err\n }\n\n private parseServiceError(typeValue: string | undefined): ServiceError | undefined {\n if (!typeValue || typeof typeValue !== 'string') return undefined\n const prefix = 'urn:service-error:'\n if (!typeValue.startsWith(prefix)) return undefined\n const id = typeValue.slice(prefix.length)\n if (!id) return undefined\n const values = Object.values(ServiceError) as string[]\n return values.includes(id) ? (id as ServiceError) : undefined\n }\n\n private buildUrl(path: string, query?: Record<string, unknown>): string {\n const base = `${this.baseUrl}${path.startsWith('/') ? '' : '/'}${path}`\n if (!query || Object.keys(query).length === 0) return base\n\n const params = new URLSearchParams()\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) continue\n params.set(key, String(value))\n }\n\n const qs = params.toString()\n return qs ? `${base}?${qs}` : base\n }\n\n private buildHeaders(options: RequestOptions & { body?: unknown; authOptional?: boolean }): Record<string, string> {\n const headers: Record<string, string> = {\n accept: 'application/json',\n ...this.defaultHeaders,\n ...options.headers,\n }\n\n if (options.body !== undefined) {\n headers['content-type'] = 'application/json'\n }\n\n if (options.scope) {\n headers['x-scope'] = options.scope\n }\n\n const apiKey = options.apiKey ?? this.apiKey\n if (apiKey && !options.authOptional) {\n headers.authorization = apiKey.startsWith('ApiKey ') ? apiKey : `ApiKey ${apiKey}`\n }\n\n return headers\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@frogfish/k2db-api",
|
|
3
|
+
"version": "1.0.10",
|
|
4
|
+
"description": "K2DB API client",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=20"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup --config tsup.config.ts"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@frogfish/k2error": "^3.0.1"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"tsup": "^8.5.1",
|
|
31
|
+
"typescript": "^5.9.3"
|
|
32
|
+
}
|
|
33
|
+
}
|