@ikatec/digisac-api-sdk 3.1.0 → 4.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.
- package/README.md +71 -9
- package/dist/apis/authHistory/AuthHistoryApi.cjs +3 -9
- package/dist/apis/authHistory/AuthHistoryApi.cjs.map +1 -1
- package/dist/apis/authHistory/AuthHistoryApi.d.ts +3 -4
- package/dist/apis/authHistory/AuthHistoryApi.d.ts.map +1 -1
- package/dist/apis/authHistory/AuthHistoryApi.mjs +3 -7
- package/dist/apis/authHistory/AuthHistoryApi.mjs.map +1 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.cjs +2 -5
- package/dist/apis/clientFeedback/ClientFeedbackApi.cjs.map +1 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts +2 -4
- package/dist/apis/clientFeedback/ClientFeedbackApi.d.ts.map +1 -1
- package/dist/apis/clientFeedback/ClientFeedbackApi.mjs +3 -5
- package/dist/apis/clientFeedback/ClientFeedbackApi.mjs.map +1 -1
- package/dist/apis/contacts/ContactsApi.cjs +2 -2
- package/dist/apis/contacts/ContactsApi.cjs.map +1 -1
- package/dist/apis/contacts/ContactsApi.mjs +2 -2
- package/dist/apis/contacts/ContactsApi.mjs.map +1 -1
- package/dist/apis/me/MeApi.cjs +2 -5
- package/dist/apis/me/MeApi.cjs.map +1 -1
- package/dist/apis/me/MeApi.d.ts +2 -4
- package/dist/apis/me/MeApi.d.ts.map +1 -1
- package/dist/apis/me/MeApi.mjs +3 -5
- package/dist/apis/me/MeApi.mjs.map +1 -1
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.cjs +3 -9
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.cjs.map +1 -1
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.d.ts +3 -4
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.d.ts.map +1 -1
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.mjs +3 -7
- package/dist/apis/serviceAccessManagement/ServiceAccessManagementApi.mjs.map +1 -1
- package/dist/apis/stickerUsers/StickerUsersApi.cjs +3 -9
- package/dist/apis/stickerUsers/StickerUsersApi.cjs.map +1 -1
- package/dist/apis/stickerUsers/StickerUsersApi.d.ts +3 -4
- package/dist/apis/stickerUsers/StickerUsersApi.d.ts.map +1 -1
- package/dist/apis/stickerUsers/StickerUsersApi.mjs +3 -7
- package/dist/apis/stickerUsers/StickerUsersApi.mjs.map +1 -1
- package/dist/apis/terms/TermsApi.cjs +3 -12
- package/dist/apis/terms/TermsApi.cjs.map +1 -1
- package/dist/apis/terms/TermsApi.d.ts +2 -4
- package/dist/apis/terms/TermsApi.d.ts.map +1 -1
- package/dist/apis/terms/TermsApi.mjs +3 -10
- package/dist/apis/terms/TermsApi.mjs.map +1 -1
- package/dist/apis/transcripts/TranscriptsApi.cjs +2 -5
- package/dist/apis/transcripts/TranscriptsApi.cjs.map +1 -1
- package/dist/apis/transcripts/TranscriptsApi.d.ts +2 -4
- package/dist/apis/transcripts/TranscriptsApi.d.ts.map +1 -1
- package/dist/apis/transcripts/TranscriptsApi.mjs +3 -5
- package/dist/apis/transcripts/TranscriptsApi.mjs.map +1 -1
- package/dist/core/ApiClient.d.ts +3 -0
- package/dist/core/ApiClient.d.ts.map +1 -1
- package/dist/core/ArchivableCrudApi.cjs +0 -2
- package/dist/core/ArchivableCrudApi.cjs.map +1 -1
- package/dist/core/ArchivableCrudApi.d.ts.map +1 -1
- package/dist/core/ArchivableCrudApi.mjs +0 -2
- package/dist/core/ArchivableCrudApi.mjs.map +1 -1
- package/dist/core/BaseApi.cjs +34 -0
- package/dist/core/BaseApi.cjs.map +1 -0
- package/dist/core/BaseApi.d.ts +20 -0
- package/dist/core/BaseApi.d.ts.map +1 -0
- package/dist/core/BaseApi.mjs +33 -0
- package/dist/core/BaseApi.mjs.map +1 -0
- package/dist/core/BaseApiClient.cjs +29 -57
- package/dist/core/BaseApiClient.cjs.map +1 -1
- package/dist/core/BaseApiClient.d.ts +8 -11
- package/dist/core/BaseApiClient.d.ts.map +1 -1
- package/dist/core/BaseApiClient.mjs +31 -57
- package/dist/core/BaseApiClient.mjs.map +1 -1
- package/dist/core/BaseCrudApi.cjs +6 -16
- package/dist/core/BaseCrudApi.cjs.map +1 -1
- package/dist/core/BaseCrudApi.d.ts +3 -2
- package/dist/core/BaseCrudApi.d.ts.map +1 -1
- package/dist/core/BaseCrudApi.mjs +6 -14
- package/dist/core/BaseCrudApi.mjs.map +1 -1
- package/dist/core/bindMethods.cjs +24 -0
- package/dist/core/bindMethods.cjs.map +1 -0
- package/dist/core/bindMethods.d.ts +7 -0
- package/dist/core/bindMethods.d.ts.map +1 -0
- package/dist/core/bindMethods.mjs +22 -0
- package/dist/core/bindMethods.mjs.map +1 -0
- package/dist/core/errors.cjs +192 -0
- package/dist/core/errors.cjs.map +1 -0
- package/dist/core/errors.d.ts +117 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.mjs +177 -0
- package/dist/core/errors.mjs.map +1 -0
- package/dist/core/index.cjs +18 -2
- package/dist/core/index.d.ts +6 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.mjs +4 -2
- package/dist/core/queryString.cjs +22 -0
- package/dist/core/queryString.cjs.map +1 -0
- package/dist/core/queryString.d.ts +14 -0
- package/dist/core/queryString.d.ts.map +1 -0
- package/dist/core/queryString.mjs +18 -0
- package/dist/core/queryString.mjs.map +1 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/withQueryFormat.cjs +42 -0
- package/dist/core/withQueryFormat.cjs.map +1 -0
- package/dist/core/withQueryFormat.d.ts +10 -0
- package/dist/core/withQueryFormat.d.ts.map +1 -0
- package/dist/core/withQueryFormat.mjs +40 -0
- package/dist/core/withQueryFormat.mjs.map +1 -0
- package/dist/index.cjs +18 -2
- package/dist/index.mjs +4 -2
- package/package.json +1 -1
- package/src/apis/authHistory/AuthHistoryApi.test.ts +1 -1
- package/src/apis/authHistory/AuthHistoryApi.ts +10 -10
- package/src/apis/campaigns/CampaignsApi.test.ts +1 -1
- package/src/apis/clientFeedback/ClientFeedbackApi.ts +5 -7
- package/src/apis/contacts/ContactsApi.test.ts +1 -1
- package/src/apis/contacts/ContactsApi.ts +2 -2
- package/src/apis/me/MeApi.ts +2 -8
- package/src/apis/messages/MessagesApi.test.ts +2 -2
- package/src/apis/queryFormat.test.ts +198 -0
- package/src/apis/serviceAccessManagement/ServiceAccessManagementApi.test.ts +2 -2
- package/src/apis/serviceAccessManagement/ServiceAccessManagementApi.ts +10 -10
- package/src/apis/stickerUsers/StickerUsersApi.test.ts +1 -1
- package/src/apis/stickerUsers/StickerUsersApi.ts +7 -10
- package/src/apis/terms/TermsApi.ts +3 -12
- package/src/apis/transcripts/TranscriptsApi.ts +2 -7
- package/src/core/ApiClient.ts +4 -0
- package/src/core/ArchivableCrudApi.ts +0 -2
- package/src/core/BaseApi.test.ts +164 -0
- package/src/core/BaseApi.ts +32 -0
- package/src/core/BaseApiClient.test.ts +193 -22
- package/src/core/BaseApiClient.ts +44 -85
- package/src/core/BaseCrudApi.test-d.ts +57 -0
- package/src/core/BaseCrudApi.test.ts +252 -31
- package/src/core/BaseCrudApi.ts +14 -14
- package/src/core/bindMethods.ts +26 -0
- package/src/core/errors.test-d.ts +14 -0
- package/src/core/errors.test.ts +389 -0
- package/src/core/errors.ts +284 -0
- package/src/core/index.ts +21 -2
- package/src/core/queryString.test.ts +71 -0
- package/src/core/queryString.ts +30 -0
- package/src/core/types.ts +5 -0
- package/src/core/withQueryFormat.test.ts +136 -0
- package/src/core/withQueryFormat.ts +47 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseApiClient.cjs","names":[],"sources":["../../src/core/BaseApiClient.ts"],"sourcesContent":["import type { ApiClient, HttpMethod } from './ApiClient'\
|
|
1
|
+
{"version":3,"file":"BaseApiClient.cjs","names":["DEFAULT_QUERY_FORMAT","ApiConnectionError","ApiError"],"sources":["../../src/core/BaseApiClient.ts"],"sourcesContent":["import type { ApiClient, HttpMethod } from './ApiClient'\nimport { ApiConnectionError, ApiError } from './errors'\nimport { DEFAULT_QUERY_FORMAT, type QueryFormat } from './queryString'\n\nexport interface BaseApiClientOptions {\n /** How list/get queries are serialized in the URL. Defaults to `'json'`. */\n queryFormat?: QueryFormat\n}\n\nexport class BaseApiClient implements ApiClient {\n protected readonly baseUrl: string\n protected accessToken: string | null = null\n public readonly queryFormat: QueryFormat\n\n constructor(baseUrl: string, accessToken?: string, options: BaseApiClientOptions = {}) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.accessToken = accessToken || null\n this.queryFormat = options.queryFormat ?? DEFAULT_QUERY_FORMAT\n }\n\n setAccessToken(accessToken: string): this {\n this.accessToken = accessToken\n return this\n }\n\n async request<TResponse = unknown, TBody = unknown>(\n method: HttpMethod,\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n const url = `${this.baseUrl}/${endpoint.replace(/^\\//, '')}`\n const init: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...(this.accessToken && { Authorization: `Bearer ${this.accessToken}` }),\n ...headers,\n },\n ...(body !== undefined && { body: JSON.stringify(body) }),\n }\n\n let response: Response\n try {\n response = await fetch(url, init)\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n throw new ApiConnectionError(`Request to ${method} ${url} failed: ${reason}`, {\n cause: error,\n })\n }\n\n return this.handleResponse<TResponse>(response)\n }\n\n protected async handleResponse<TResponse>(response: Response): Promise<TResponse> {\n if (!response.ok) {\n throw ApiError.fromResponse(\n response.status,\n response.statusText,\n response.headers,\n await this.readErrorBody(response),\n )\n }\n\n // 204 No Content never has a body; short-circuit before reading the stream.\n if (response.status === 204) {\n return undefined as unknown as TResponse\n }\n\n // Read body as text once and treat an empty body as \"no content\" regardless of\n // Content-Type. Servers sometimes return 200 with Content-Type: application/json\n // and an empty body (e.g. POST endpoints whose framework keeps the default JSON\n // content-type even when nothing is written). `response.json()` would throw\n // \"Unexpected end of input\" in that case.\n const text = await response.text()\n if (!text) {\n return undefined as unknown as TResponse\n }\n\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n if (isJson) {\n return JSON.parse(text) as TResponse\n }\n\n try {\n return JSON.parse(text) as TResponse\n } catch {\n return text as unknown as TResponse\n }\n }\n\n /** Reads an error body: parsed JSON when possible, the raw text otherwise, `undefined` when empty. */\n protected async readErrorBody(response: Response): Promise<unknown> {\n let text: string\n try {\n text = await response.text()\n } catch {\n return undefined\n }\n if (!text) {\n return undefined\n }\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n }\n\n get<TResponse = unknown>(endpoint: string, headers?: Record<string, string>): Promise<TResponse> {\n return this.request<TResponse>('GET', endpoint, undefined, headers)\n }\n\n post<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('POST', endpoint, body, headers)\n }\n\n put<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PUT', endpoint, body, headers)\n }\n\n patch<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PATCH', endpoint, body, headers)\n }\n\n delete<TResponse = unknown>(\n endpoint: string,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse>('DELETE', endpoint, undefined, headers)\n }\n}\n"],"mappings":";;;;;AASA,IAAa,gBAAb,MAAgD;CAC9C,AAAmB;CACnB,AAAU,cAA6B;CACvC,AAAgB;CAEhB,YAAY,SAAiB,aAAsB,UAAgC,EAAE,EAAE;AACrF,OAAK,UAAU,QAAQ,QAAQ,OAAO,GAAG;AACzC,OAAK,cAAc,eAAe;AAClC,OAAK,cAAc,QAAQ,eAAeA;;CAG5C,eAAe,aAA2B;AACxC,OAAK,cAAc;AACnB,SAAO;;CAGT,MAAM,QACJ,QACA,UACA,MACA,SACoB;EACpB,MAAM,MAAM,GAAG,KAAK,QAAQ,GAAG,SAAS,QAAQ,OAAO,GAAG;EAC1D,MAAM,OAAoB;GACxB;GACA,SAAS;IACP,gBAAgB;IAChB,GAAI,KAAK,eAAe,EAAE,eAAe,UAAU,KAAK,eAAe;IACvE,GAAG;IACJ;GACD,GAAI,SAAS,UAAa,EAAE,MAAM,KAAK,UAAU,KAAK,EAAE;GACzD;EAED,IAAI;AACJ,MAAI;AACF,cAAW,MAAM,MAAM,KAAK,KAAK;WAC1B,OAAO;AAEd,SAAM,IAAIC,uCAAmB,cAAc,OAAO,GAAG,IAAI,WAD1C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACS,EAC5E,OAAO,OACR,CAAC;;AAGJ,SAAO,KAAK,eAA0B,SAAS;;CAGjD,MAAgB,eAA0B,UAAwC;AAChF,MAAI,CAAC,SAAS,GACZ,OAAMC,6BAAS,aACb,SAAS,QACT,SAAS,YACT,SAAS,SACT,MAAM,KAAK,cAAc,SAAS,CACnC;AAIH,MAAI,SAAS,WAAW,IACtB;EAQF,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,MAAI,CAAC,KACH;AAMF,MAHoB,SAAS,QAAQ,IAAI,eAAe,EAC5B,SAAS,mBAAmB,IAAI,MAG1D,QAAO,KAAK,MAAM,KAAK;AAGzB,MAAI;AACF,UAAO,KAAK,MAAM,KAAK;UACjB;AACN,UAAO;;;;CAKX,MAAgB,cAAc,UAAsC;EAClE,IAAI;AACJ,MAAI;AACF,UAAO,MAAM,SAAS,MAAM;UACtB;AACN;;AAEF,MAAI,CAAC,KACH;AAEF,MAAI;AACF,UAAO,KAAK,MAAM,KAAK;UACjB;AACN,UAAO;;;CAIX,IAAyB,UAAkB,SAAsD;AAC/F,SAAO,KAAK,QAAmB,OAAO,UAAU,QAAW,QAAQ;;CAGrE,KACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,QAAQ,UAAU,MAAM,QAAQ;;CAGxE,IACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,OAAO,UAAU,MAAM,QAAQ;;CAGvE,MACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,SAAS,UAAU,MAAM,QAAQ;;CAGzE,OACE,UACA,SACoB;AACpB,SAAO,KAAK,QAAmB,UAAU,UAAU,QAAW,QAAQ"}
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import type { ApiClient, HttpMethod } from './ApiClient';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
export declare class ApiError extends Error {
|
|
8
|
-
readonly errorClass?: string | undefined;
|
|
9
|
-
readonly status?: number | undefined;
|
|
10
|
-
readonly validationErrors: ValidationError[] | null;
|
|
11
|
-
constructor(message: string, errorClass?: string, status?: number, validationErrors?: ValidationError[] | null);
|
|
2
|
+
import { type QueryFormat } from './queryString';
|
|
3
|
+
export interface BaseApiClientOptions {
|
|
4
|
+
/** How list/get queries are serialized in the URL. Defaults to `'json'`. */
|
|
5
|
+
queryFormat?: QueryFormat;
|
|
12
6
|
}
|
|
13
7
|
export declare class BaseApiClient implements ApiClient {
|
|
14
8
|
protected readonly baseUrl: string;
|
|
15
9
|
protected accessToken: string | null;
|
|
16
|
-
|
|
10
|
+
readonly queryFormat: QueryFormat;
|
|
11
|
+
constructor(baseUrl: string, accessToken?: string, options?: BaseApiClientOptions);
|
|
17
12
|
setAccessToken(accessToken: string): this;
|
|
18
13
|
request<TResponse = unknown, TBody = unknown>(method: HttpMethod, endpoint: string, body?: TBody, headers?: Record<string, string>): Promise<TResponse>;
|
|
19
14
|
protected handleResponse<TResponse>(response: Response): Promise<TResponse>;
|
|
15
|
+
/** Reads an error body: parsed JSON when possible, the raw text otherwise, `undefined` when empty. */
|
|
16
|
+
protected readErrorBody(response: Response): Promise<unknown>;
|
|
20
17
|
get<TResponse = unknown>(endpoint: string, headers?: Record<string, string>): Promise<TResponse>;
|
|
21
18
|
post<TResponse = unknown, TBody = unknown>(endpoint: string, body?: TBody, headers?: Record<string, string>): Promise<TResponse>;
|
|
22
19
|
put<TResponse = unknown, TBody = unknown>(endpoint: string, body?: TBody, headers?: Record<string, string>): Promise<TResponse>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseApiClient.d.ts","sourceRoot":"","sources":["../../src/core/BaseApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExD,
|
|
1
|
+
{"version":3,"file":"BaseApiClient.d.ts","sourceRoot":"","sources":["../../src/core/BaseApiClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExD,OAAO,EAAwB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAA;AAEtE,MAAM,WAAW,oBAAoB;IACnC,4EAA4E;IAC5E,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED,qBAAa,aAAc,YAAW,SAAS;IAC7C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IAClC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAO;IAC3C,SAAgB,WAAW,EAAE,WAAW,CAAA;gBAE5B,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB;IAMrF,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAKnC,OAAO,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EAChD,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;cAyBL,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAuCjF,sGAAsG;cACtF,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBnE,GAAG,CAAC,SAAS,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAIhG,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EACvC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB,GAAG,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB,KAAK,CAAC,SAAS,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB,MAAM,CAAC,SAAS,GAAG,OAAO,EACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;CAGtB"}
|
|
@@ -1,47 +1,15 @@
|
|
|
1
|
+
import { ApiConnectionError, ApiError } from "./errors.mjs";
|
|
2
|
+
import { DEFAULT_QUERY_FORMAT } from "./queryString.mjs";
|
|
3
|
+
|
|
1
4
|
//#region src/core/BaseApiClient.ts
|
|
2
|
-
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
|
-
/**
|
|
4
|
-
* Flattens the Digisac `errors` object into `ValidationError[]` — one entry per message, with
|
|
5
|
-
* `path` = `<location>.<field>` (e.g. `body.name`) and `code` = the rule type (e.g. `required`).
|
|
6
|
-
* Returns `null` when the body carries no field errors.
|
|
7
|
-
*/
|
|
8
|
-
function parseValidationErrors(errors) {
|
|
9
|
-
if (!isRecord(errors)) return null;
|
|
10
|
-
const parsed = [];
|
|
11
|
-
for (const [location, fields] of Object.entries(errors)) {
|
|
12
|
-
if (!isRecord(fields)) continue;
|
|
13
|
-
for (const [field, detail] of Object.entries(fields)) {
|
|
14
|
-
const messages = Array.isArray(detail?.messages) ? detail.messages.map(String) : [];
|
|
15
|
-
const types = Array.isArray(detail?.types) ? detail.types.map(String) : [];
|
|
16
|
-
messages.forEach((message, index) => {
|
|
17
|
-
parsed.push({
|
|
18
|
-
path: `${location}.${field}`,
|
|
19
|
-
message,
|
|
20
|
-
code: types[index] ?? types[0] ?? ""
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return parsed.length ? parsed : null;
|
|
26
|
-
}
|
|
27
|
-
var ApiError = class extends Error {
|
|
28
|
-
errorClass;
|
|
29
|
-
status;
|
|
30
|
-
validationErrors;
|
|
31
|
-
constructor(message, errorClass, status, validationErrors = null) {
|
|
32
|
-
super(message);
|
|
33
|
-
this.name = "ApiError";
|
|
34
|
-
this.errorClass = errorClass;
|
|
35
|
-
this.status = status;
|
|
36
|
-
this.validationErrors = validationErrors;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
5
|
var BaseApiClient = class {
|
|
40
6
|
baseUrl;
|
|
41
7
|
accessToken = null;
|
|
42
|
-
|
|
8
|
+
queryFormat;
|
|
9
|
+
constructor(baseUrl, accessToken, options = {}) {
|
|
43
10
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
44
11
|
this.accessToken = accessToken || null;
|
|
12
|
+
this.queryFormat = options.queryFormat ?? DEFAULT_QUERY_FORMAT;
|
|
45
13
|
}
|
|
46
14
|
setAccessToken(accessToken) {
|
|
47
15
|
this.accessToken = accessToken;
|
|
@@ -49,7 +17,7 @@ var BaseApiClient = class {
|
|
|
49
17
|
}
|
|
50
18
|
async request(method, endpoint, body, headers) {
|
|
51
19
|
const url = `${this.baseUrl}/${endpoint.replace(/^\//, "")}`;
|
|
52
|
-
const
|
|
20
|
+
const init = {
|
|
53
21
|
method,
|
|
54
22
|
headers: {
|
|
55
23
|
"Content-Type": "application/json",
|
|
@@ -57,26 +25,17 @@ var BaseApiClient = class {
|
|
|
57
25
|
...headers
|
|
58
26
|
},
|
|
59
27
|
...body !== void 0 && { body: JSON.stringify(body) }
|
|
60
|
-
}
|
|
28
|
+
};
|
|
29
|
+
let response;
|
|
30
|
+
try {
|
|
31
|
+
response = await fetch(url, init);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
throw new ApiConnectionError(`Request to ${method} ${url} failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
34
|
+
}
|
|
61
35
|
return this.handleResponse(response);
|
|
62
36
|
}
|
|
63
37
|
async handleResponse(response) {
|
|
64
|
-
if (!response.ok)
|
|
65
|
-
const isJson = response.headers.get("Content-Type")?.includes("application/json") ?? false;
|
|
66
|
-
let errorMessage = `HTTP Error ${response.status}: ${response.statusText}`;
|
|
67
|
-
let errorClass;
|
|
68
|
-
let validationErrors = null;
|
|
69
|
-
if (isJson) try {
|
|
70
|
-
const errorText = await response.text();
|
|
71
|
-
if (errorText) {
|
|
72
|
-
const errorData = JSON.parse(errorText);
|
|
73
|
-
errorMessage = errorData.message || errorData.error || errorMessage;
|
|
74
|
-
errorClass = errorData.error;
|
|
75
|
-
validationErrors = errorData.validationErrors ?? parseValidationErrors(errorData.errors);
|
|
76
|
-
}
|
|
77
|
-
} catch {}
|
|
78
|
-
throw new ApiError(errorMessage, errorClass, response.status, validationErrors);
|
|
79
|
-
}
|
|
38
|
+
if (!response.ok) throw ApiError.fromResponse(response.status, response.statusText, response.headers, await this.readErrorBody(response));
|
|
80
39
|
if (response.status === 204) return;
|
|
81
40
|
const text = await response.text();
|
|
82
41
|
if (!text) return;
|
|
@@ -87,6 +46,21 @@ var BaseApiClient = class {
|
|
|
87
46
|
return text;
|
|
88
47
|
}
|
|
89
48
|
}
|
|
49
|
+
/** Reads an error body: parsed JSON when possible, the raw text otherwise, `undefined` when empty. */
|
|
50
|
+
async readErrorBody(response) {
|
|
51
|
+
let text;
|
|
52
|
+
try {
|
|
53
|
+
text = await response.text();
|
|
54
|
+
} catch {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (!text) return;
|
|
58
|
+
try {
|
|
59
|
+
return JSON.parse(text);
|
|
60
|
+
} catch {
|
|
61
|
+
return text;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
90
64
|
get(endpoint, headers) {
|
|
91
65
|
return this.request("GET", endpoint, void 0, headers);
|
|
92
66
|
}
|
|
@@ -105,5 +79,5 @@ var BaseApiClient = class {
|
|
|
105
79
|
};
|
|
106
80
|
|
|
107
81
|
//#endregion
|
|
108
|
-
export {
|
|
82
|
+
export { BaseApiClient };
|
|
109
83
|
//# sourceMappingURL=BaseApiClient.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseApiClient.mjs","names":[],"sources":["../../src/core/BaseApiClient.ts"],"sourcesContent":["import type { ApiClient, HttpMethod } from './ApiClient'\
|
|
1
|
+
{"version":3,"file":"BaseApiClient.mjs","names":[],"sources":["../../src/core/BaseApiClient.ts"],"sourcesContent":["import type { ApiClient, HttpMethod } from './ApiClient'\nimport { ApiConnectionError, ApiError } from './errors'\nimport { DEFAULT_QUERY_FORMAT, type QueryFormat } from './queryString'\n\nexport interface BaseApiClientOptions {\n /** How list/get queries are serialized in the URL. Defaults to `'json'`. */\n queryFormat?: QueryFormat\n}\n\nexport class BaseApiClient implements ApiClient {\n protected readonly baseUrl: string\n protected accessToken: string | null = null\n public readonly queryFormat: QueryFormat\n\n constructor(baseUrl: string, accessToken?: string, options: BaseApiClientOptions = {}) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.accessToken = accessToken || null\n this.queryFormat = options.queryFormat ?? DEFAULT_QUERY_FORMAT\n }\n\n setAccessToken(accessToken: string): this {\n this.accessToken = accessToken\n return this\n }\n\n async request<TResponse = unknown, TBody = unknown>(\n method: HttpMethod,\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n const url = `${this.baseUrl}/${endpoint.replace(/^\\//, '')}`\n const init: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...(this.accessToken && { Authorization: `Bearer ${this.accessToken}` }),\n ...headers,\n },\n ...(body !== undefined && { body: JSON.stringify(body) }),\n }\n\n let response: Response\n try {\n response = await fetch(url, init)\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n throw new ApiConnectionError(`Request to ${method} ${url} failed: ${reason}`, {\n cause: error,\n })\n }\n\n return this.handleResponse<TResponse>(response)\n }\n\n protected async handleResponse<TResponse>(response: Response): Promise<TResponse> {\n if (!response.ok) {\n throw ApiError.fromResponse(\n response.status,\n response.statusText,\n response.headers,\n await this.readErrorBody(response),\n )\n }\n\n // 204 No Content never has a body; short-circuit before reading the stream.\n if (response.status === 204) {\n return undefined as unknown as TResponse\n }\n\n // Read body as text once and treat an empty body as \"no content\" regardless of\n // Content-Type. Servers sometimes return 200 with Content-Type: application/json\n // and an empty body (e.g. POST endpoints whose framework keeps the default JSON\n // content-type even when nothing is written). `response.json()` would throw\n // \"Unexpected end of input\" in that case.\n const text = await response.text()\n if (!text) {\n return undefined as unknown as TResponse\n }\n\n const contentType = response.headers.get('Content-Type')\n const isJson = contentType?.includes('application/json') ?? false\n\n if (isJson) {\n return JSON.parse(text) as TResponse\n }\n\n try {\n return JSON.parse(text) as TResponse\n } catch {\n return text as unknown as TResponse\n }\n }\n\n /** Reads an error body: parsed JSON when possible, the raw text otherwise, `undefined` when empty. */\n protected async readErrorBody(response: Response): Promise<unknown> {\n let text: string\n try {\n text = await response.text()\n } catch {\n return undefined\n }\n if (!text) {\n return undefined\n }\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n }\n\n get<TResponse = unknown>(endpoint: string, headers?: Record<string, string>): Promise<TResponse> {\n return this.request<TResponse>('GET', endpoint, undefined, headers)\n }\n\n post<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('POST', endpoint, body, headers)\n }\n\n put<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PUT', endpoint, body, headers)\n }\n\n patch<TResponse = unknown, TBody = unknown>(\n endpoint: string,\n body?: TBody,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>('PATCH', endpoint, body, headers)\n }\n\n delete<TResponse = unknown>(\n endpoint: string,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.request<TResponse>('DELETE', endpoint, undefined, headers)\n }\n}\n"],"mappings":";;;;AASA,IAAa,gBAAb,MAAgD;CAC9C,AAAmB;CACnB,AAAU,cAA6B;CACvC,AAAgB;CAEhB,YAAY,SAAiB,aAAsB,UAAgC,EAAE,EAAE;AACrF,OAAK,UAAU,QAAQ,QAAQ,OAAO,GAAG;AACzC,OAAK,cAAc,eAAe;AAClC,OAAK,cAAc,QAAQ,eAAe;;CAG5C,eAAe,aAA2B;AACxC,OAAK,cAAc;AACnB,SAAO;;CAGT,MAAM,QACJ,QACA,UACA,MACA,SACoB;EACpB,MAAM,MAAM,GAAG,KAAK,QAAQ,GAAG,SAAS,QAAQ,OAAO,GAAG;EAC1D,MAAM,OAAoB;GACxB;GACA,SAAS;IACP,gBAAgB;IAChB,GAAI,KAAK,eAAe,EAAE,eAAe,UAAU,KAAK,eAAe;IACvE,GAAG;IACJ;GACD,GAAI,SAAS,UAAa,EAAE,MAAM,KAAK,UAAU,KAAK,EAAE;GACzD;EAED,IAAI;AACJ,MAAI;AACF,cAAW,MAAM,MAAM,KAAK,KAAK;WAC1B,OAAO;AAEd,SAAM,IAAI,mBAAmB,cAAc,OAAO,GAAG,IAAI,WAD1C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACS,EAC5E,OAAO,OACR,CAAC;;AAGJ,SAAO,KAAK,eAA0B,SAAS;;CAGjD,MAAgB,eAA0B,UAAwC;AAChF,MAAI,CAAC,SAAS,GACZ,OAAM,SAAS,aACb,SAAS,QACT,SAAS,YACT,SAAS,SACT,MAAM,KAAK,cAAc,SAAS,CACnC;AAIH,MAAI,SAAS,WAAW,IACtB;EAQF,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,MAAI,CAAC,KACH;AAMF,MAHoB,SAAS,QAAQ,IAAI,eAAe,EAC5B,SAAS,mBAAmB,IAAI,MAG1D,QAAO,KAAK,MAAM,KAAK;AAGzB,MAAI;AACF,UAAO,KAAK,MAAM,KAAK;UACjB;AACN,UAAO;;;;CAKX,MAAgB,cAAc,UAAsC;EAClE,IAAI;AACJ,MAAI;AACF,UAAO,MAAM,SAAS,MAAM;UACtB;AACN;;AAEF,MAAI,CAAC,KACH;AAEF,MAAI;AACF,UAAO,KAAK,MAAM,KAAK;UACjB;AACN,UAAO;;;CAIX,IAAyB,UAAkB,SAAsD;AAC/F,SAAO,KAAK,QAAmB,OAAO,UAAU,QAAW,QAAQ;;CAGrE,KACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,QAAQ,UAAU,MAAM,QAAQ;;CAGxE,IACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,OAAO,UAAU,MAAM,QAAQ;;CAGvE,MACE,UACA,MACA,SACoB;AACpB,SAAO,KAAK,QAA0B,SAAS,UAAU,MAAM,QAAQ;;CAGzE,OACE,UACA,SACoB;AACpB,SAAO,KAAK,QAAmB,UAAU,UAAU,QAAW,QAAQ"}
|
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const
|
|
3
|
-
let qs = require("qs");
|
|
4
|
-
qs = require_chunk.__toESM(qs);
|
|
2
|
+
const require_core_BaseApi = require('./BaseApi.cjs');
|
|
5
3
|
|
|
6
4
|
//#region src/core/BaseCrudApi.ts
|
|
7
|
-
var BaseCrudApi = class {
|
|
8
|
-
client;
|
|
5
|
+
var BaseCrudApi = class extends require_core_BaseApi.BaseApi {
|
|
9
6
|
basePath;
|
|
10
7
|
constructor(client, basePath) {
|
|
11
|
-
|
|
8
|
+
super(client);
|
|
12
9
|
this.basePath = basePath.replace(/\/$/, "");
|
|
13
|
-
this.getMany = this.getMany.bind(this);
|
|
14
|
-
this.getOne = this.getOne.bind(this);
|
|
15
|
-
this.getById = this.getById.bind(this);
|
|
16
|
-
this.create = this.create.bind(this);
|
|
17
|
-
this.updateById = this.updateById.bind(this);
|
|
18
|
-
this.deleteById = this.deleteById.bind(this);
|
|
19
10
|
}
|
|
20
11
|
getMany(query, headers) {
|
|
21
|
-
const queryString =
|
|
12
|
+
const queryString = this.toQueryString(query);
|
|
22
13
|
return this.client.get(`${this.basePath}${queryString}`, headers);
|
|
23
14
|
}
|
|
24
15
|
/**
|
|
@@ -31,15 +22,14 @@ var BaseCrudApi = class {
|
|
|
31
22
|
...query,
|
|
32
23
|
limit: 1,
|
|
33
24
|
paginate: false
|
|
34
|
-
}, headers))[0] ?? null;
|
|
25
|
+
}, headers))?.[0] ?? null;
|
|
35
26
|
}
|
|
36
27
|
/**
|
|
37
28
|
* Returns a single resource by ID.
|
|
38
29
|
* @permissions $resourceName.view
|
|
39
30
|
*/
|
|
40
31
|
getById(id, query, headers) {
|
|
41
|
-
|
|
42
|
-
return this.client.get(`${this.basePath}/${id}${queryString}`, headers);
|
|
32
|
+
return this.client.get(`${this.basePath}/${id}${this.toQueryString(query)}`, headers);
|
|
43
33
|
}
|
|
44
34
|
/**
|
|
45
35
|
* Creates a new resource.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseCrudApi.cjs","names":[],"sources":["../../src/core/BaseCrudApi.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"BaseCrudApi.cjs","names":["BaseApi"],"sources":["../../src/core/BaseCrudApi.ts"],"sourcesContent":["import type { ApiClient } from './ApiClient'\nimport { BaseApi } from './BaseApi'\nimport type { CrudApi, GetByIdQuery, ListQuery, Paginated } from './types'\nexport type {\n WhereClause,\n IncludeItem,\n ListQuery,\n GetByIdQuery,\n Paginated,\n HasGetMany,\n HasGetById,\n HasCreate,\n HasUpdateById,\n HasDeleteById,\n CrudApi,\n} from './types'\n\nexport class BaseCrudApi<\n TResponse,\n TCreate,\n TUpdate = TCreate,\n TQuery extends ListQuery<TResponse> = ListQuery<TResponse>,\n>\n extends BaseApi\n implements CrudApi<TResponse, TCreate, TUpdate, TQuery>\n{\n public readonly basePath: string\n\n constructor(client: ApiClient, basePath: string) {\n super(client)\n this.basePath = basePath.replace(/\\/$/, '')\n }\n\n getMany(\n query: TQuery & { paginate: false },\n headers?: Record<string, string>,\n ): Promise<TResponse[]>\n getMany(\n query?: TQuery & { paginate?: true },\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse>>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]> {\n const queryString = this.toQueryString(query)\n return this.client.get<Paginated<TResponse> | TResponse[]>(\n `${this.basePath}${queryString}`,\n headers,\n )\n }\n\n /**\n * Returns the first resource matching the query, or `null` when none match.\n * Convenience over `getMany` with `limit: 1`.\n * @permissions $resourceName.view\n */\n async getOne(query?: TQuery, headers?: Record<string, string>): Promise<TResponse | null> {\n const results = await this.getMany(\n { ...query, limit: 1, paginate: false } as TQuery & { paginate: false },\n headers,\n )\n // An empty response body resolves to `undefined`.\n return results?.[0] ?? null\n }\n\n /**\n * Returns a single resource by ID.\n * @permissions $resourceName.view\n */\n getById(\n id: string,\n query?: GetByIdQuery<TResponse>,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.client.get<TResponse>(`${this.basePath}/${id}${this.toQueryString(query)}`, headers)\n }\n\n /**\n * Creates a new resource.\n * @permissions $resourceName.create\n */\n create(body: TCreate, headers?: Record<string, string>): Promise<TResponse> {\n return this.client.post<TResponse, TCreate>(this.basePath, body, headers)\n }\n\n /**\n * Updates an existing resource by ID.\n * @permissions $resourceName.update\n */\n updateById(id: string, body: TUpdate, headers?: Record<string, string>): Promise<TResponse> {\n return this.client.put<TResponse, TUpdate>(`${this.basePath}/${id}`, body, headers)\n }\n\n /**\n * Deletes a resource by ID.\n * @permissions $resourceName.delete\n */\n deleteById(id: string, headers?: Record<string, string>): Promise<TResponse> {\n return this.client.delete<TResponse>(`${this.basePath}/${id}`, headers)\n }\n}\n"],"mappings":";;;;AAiBA,IAAa,cAAb,cAMUA,6BAEV;CACE,AAAgB;CAEhB,YAAY,QAAmB,UAAkB;AAC/C,QAAM,OAAO;AACb,OAAK,WAAW,SAAS,QAAQ,OAAO,GAAG;;CAe7C,QACE,OACA,SAC6C;EAC7C,MAAM,cAAc,KAAK,cAAc,MAAM;AAC7C,SAAO,KAAK,OAAO,IACjB,GAAG,KAAK,WAAW,eACnB,QACD;;;;;;;CAQH,MAAM,OAAO,OAAgB,SAA6D;AAMxF,UALgB,MAAM,KAAK,QACzB;GAAE,GAAG;GAAO,OAAO;GAAG,UAAU;GAAO,EACvC,QACD,IAEgB,MAAM;;;;;;CAOzB,QACE,IACA,OACA,SACoB;AACpB,SAAO,KAAK,OAAO,IAAe,GAAG,KAAK,SAAS,GAAG,KAAK,KAAK,cAAc,MAAM,IAAI,QAAQ;;;;;;CAOlG,OAAO,MAAe,SAAsD;AAC1E,SAAO,KAAK,OAAO,KAAyB,KAAK,UAAU,MAAM,QAAQ;;;;;;CAO3E,WAAW,IAAY,MAAe,SAAsD;AAC1F,SAAO,KAAK,OAAO,IAAwB,GAAG,KAAK,SAAS,GAAG,MAAM,MAAM,QAAQ;;;;;;CAOrF,WAAW,IAAY,SAAsD;AAC3E,SAAO,KAAK,OAAO,OAAkB,GAAG,KAAK,SAAS,GAAG,MAAM,QAAQ"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ApiClient } from './ApiClient';
|
|
2
|
+
import { BaseApi } from './BaseApi';
|
|
2
3
|
import type { CrudApi, GetByIdQuery, ListQuery, Paginated } from './types';
|
|
3
4
|
export type { WhereClause, IncludeItem, ListQuery, GetByIdQuery, Paginated, HasGetMany, HasGetById, HasCreate, HasUpdateById, HasDeleteById, CrudApi, } from './types';
|
|
4
|
-
export declare class BaseCrudApi<TResponse, TCreate, TUpdate = TCreate, TQuery extends ListQuery<TResponse> = ListQuery<TResponse>> implements CrudApi<TResponse, TCreate, TUpdate, TQuery> {
|
|
5
|
-
readonly client: ApiClient;
|
|
5
|
+
export declare class BaseCrudApi<TResponse, TCreate, TUpdate = TCreate, TQuery extends ListQuery<TResponse> = ListQuery<TResponse>> extends BaseApi implements CrudApi<TResponse, TCreate, TUpdate, TQuery> {
|
|
6
6
|
readonly basePath: string;
|
|
7
7
|
constructor(client: ApiClient, basePath: string);
|
|
8
8
|
getMany(query: TQuery & {
|
|
@@ -11,6 +11,7 @@ export declare class BaseCrudApi<TResponse, TCreate, TUpdate = TCreate, TQuery e
|
|
|
11
11
|
getMany(query?: TQuery & {
|
|
12
12
|
paginate?: true;
|
|
13
13
|
}, headers?: Record<string, string>): Promise<Paginated<TResponse>>;
|
|
14
|
+
getMany(query?: TQuery, headers?: Record<string, string>): Promise<Paginated<TResponse> | TResponse[]>;
|
|
14
15
|
/**
|
|
15
16
|
* Returns the first resource matching the query, or `null` when none match.
|
|
16
17
|
* Convenience over `getMany` with `limit: 1`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseCrudApi.d.ts","sourceRoot":"","sources":["../../src/core/BaseCrudApi.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"BaseCrudApi.d.ts","sourceRoot":"","sources":["../../src/core/BaseCrudApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAC1E,YAAY,EACV,WAAW,EACX,WAAW,EACX,SAAS,EACT,YAAY,EACZ,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,aAAa,EACb,aAAa,EACb,OAAO,GACR,MAAM,SAAS,CAAA;AAEhB,qBAAa,WAAW,CACtB,SAAS,EACT,OAAO,EACP,OAAO,GAAG,OAAO,EACjB,MAAM,SAAS,SAAS,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,CAE1D,SAAQ,OACR,YAAW,OAAO,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC;IAEvD,SAAgB,QAAQ,EAAE,MAAM,CAAA;gBAEpB,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM;IAK/C,OAAO,CACL,KAAK,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,KAAK,CAAA;KAAE,EACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,EAAE,CAAC;IACvB,OAAO,CACL,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,EAAE,IAAI,CAAA;KAAE,EACpC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CACL,KAAK,CAAC,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,SAAS,EAAE,CAAC;IAY9C;;;;OAIG;IACG,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IASzF;;;OAGG;IACH,OAAO,CACL,EAAE,EAAE,MAAM,EACV,KAAK,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,EAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,SAAS,CAAC;IAIrB;;;OAGG;IACH,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAI3E;;;OAGG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;IAI3F;;;OAGG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;CAG7E"}
|
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { BaseApi } from "./BaseApi.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/core/BaseCrudApi.ts
|
|
4
|
-
var BaseCrudApi = class {
|
|
5
|
-
client;
|
|
4
|
+
var BaseCrudApi = class extends BaseApi {
|
|
6
5
|
basePath;
|
|
7
6
|
constructor(client, basePath) {
|
|
8
|
-
|
|
7
|
+
super(client);
|
|
9
8
|
this.basePath = basePath.replace(/\/$/, "");
|
|
10
|
-
this.getMany = this.getMany.bind(this);
|
|
11
|
-
this.getOne = this.getOne.bind(this);
|
|
12
|
-
this.getById = this.getById.bind(this);
|
|
13
|
-
this.create = this.create.bind(this);
|
|
14
|
-
this.updateById = this.updateById.bind(this);
|
|
15
|
-
this.deleteById = this.deleteById.bind(this);
|
|
16
9
|
}
|
|
17
10
|
getMany(query, headers) {
|
|
18
|
-
const queryString =
|
|
11
|
+
const queryString = this.toQueryString(query);
|
|
19
12
|
return this.client.get(`${this.basePath}${queryString}`, headers);
|
|
20
13
|
}
|
|
21
14
|
/**
|
|
@@ -28,15 +21,14 @@ var BaseCrudApi = class {
|
|
|
28
21
|
...query,
|
|
29
22
|
limit: 1,
|
|
30
23
|
paginate: false
|
|
31
|
-
}, headers))[0] ?? null;
|
|
24
|
+
}, headers))?.[0] ?? null;
|
|
32
25
|
}
|
|
33
26
|
/**
|
|
34
27
|
* Returns a single resource by ID.
|
|
35
28
|
* @permissions $resourceName.view
|
|
36
29
|
*/
|
|
37
30
|
getById(id, query, headers) {
|
|
38
|
-
|
|
39
|
-
return this.client.get(`${this.basePath}/${id}${queryString}`, headers);
|
|
31
|
+
return this.client.get(`${this.basePath}/${id}${this.toQueryString(query)}`, headers);
|
|
40
32
|
}
|
|
41
33
|
/**
|
|
42
34
|
* Creates a new resource.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseCrudApi.mjs","names":[],"sources":["../../src/core/BaseCrudApi.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"BaseCrudApi.mjs","names":[],"sources":["../../src/core/BaseCrudApi.ts"],"sourcesContent":["import type { ApiClient } from './ApiClient'\nimport { BaseApi } from './BaseApi'\nimport type { CrudApi, GetByIdQuery, ListQuery, Paginated } from './types'\nexport type {\n WhereClause,\n IncludeItem,\n ListQuery,\n GetByIdQuery,\n Paginated,\n HasGetMany,\n HasGetById,\n HasCreate,\n HasUpdateById,\n HasDeleteById,\n CrudApi,\n} from './types'\n\nexport class BaseCrudApi<\n TResponse,\n TCreate,\n TUpdate = TCreate,\n TQuery extends ListQuery<TResponse> = ListQuery<TResponse>,\n>\n extends BaseApi\n implements CrudApi<TResponse, TCreate, TUpdate, TQuery>\n{\n public readonly basePath: string\n\n constructor(client: ApiClient, basePath: string) {\n super(client)\n this.basePath = basePath.replace(/\\/$/, '')\n }\n\n getMany(\n query: TQuery & { paginate: false },\n headers?: Record<string, string>,\n ): Promise<TResponse[]>\n getMany(\n query?: TQuery & { paginate?: true },\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse>>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]>\n getMany(\n query?: TQuery,\n headers?: Record<string, string>,\n ): Promise<Paginated<TResponse> | TResponse[]> {\n const queryString = this.toQueryString(query)\n return this.client.get<Paginated<TResponse> | TResponse[]>(\n `${this.basePath}${queryString}`,\n headers,\n )\n }\n\n /**\n * Returns the first resource matching the query, or `null` when none match.\n * Convenience over `getMany` with `limit: 1`.\n * @permissions $resourceName.view\n */\n async getOne(query?: TQuery, headers?: Record<string, string>): Promise<TResponse | null> {\n const results = await this.getMany(\n { ...query, limit: 1, paginate: false } as TQuery & { paginate: false },\n headers,\n )\n // An empty response body resolves to `undefined`.\n return results?.[0] ?? null\n }\n\n /**\n * Returns a single resource by ID.\n * @permissions $resourceName.view\n */\n getById(\n id: string,\n query?: GetByIdQuery<TResponse>,\n headers?: Record<string, string>,\n ): Promise<TResponse> {\n return this.client.get<TResponse>(`${this.basePath}/${id}${this.toQueryString(query)}`, headers)\n }\n\n /**\n * Creates a new resource.\n * @permissions $resourceName.create\n */\n create(body: TCreate, headers?: Record<string, string>): Promise<TResponse> {\n return this.client.post<TResponse, TCreate>(this.basePath, body, headers)\n }\n\n /**\n * Updates an existing resource by ID.\n * @permissions $resourceName.update\n */\n updateById(id: string, body: TUpdate, headers?: Record<string, string>): Promise<TResponse> {\n return this.client.put<TResponse, TUpdate>(`${this.basePath}/${id}`, body, headers)\n }\n\n /**\n * Deletes a resource by ID.\n * @permissions $resourceName.delete\n */\n deleteById(id: string, headers?: Record<string, string>): Promise<TResponse> {\n return this.client.delete<TResponse>(`${this.basePath}/${id}`, headers)\n }\n}\n"],"mappings":";;;AAiBA,IAAa,cAAb,cAMU,QAEV;CACE,AAAgB;CAEhB,YAAY,QAAmB,UAAkB;AAC/C,QAAM,OAAO;AACb,OAAK,WAAW,SAAS,QAAQ,OAAO,GAAG;;CAe7C,QACE,OACA,SAC6C;EAC7C,MAAM,cAAc,KAAK,cAAc,MAAM;AAC7C,SAAO,KAAK,OAAO,IACjB,GAAG,KAAK,WAAW,eACnB,QACD;;;;;;;CAQH,MAAM,OAAO,OAAgB,SAA6D;AAMxF,UALgB,MAAM,KAAK,QACzB;GAAE,GAAG;GAAO,OAAO;GAAG,UAAU;GAAO,EACvC,QACD,IAEgB,MAAM;;;;;;CAOzB,QACE,IACA,OACA,SACoB;AACpB,SAAO,KAAK,OAAO,IAAe,GAAG,KAAK,SAAS,GAAG,KAAK,KAAK,cAAc,MAAM,IAAI,QAAQ;;;;;;CAOlG,OAAO,MAAe,SAAsD;AAC1E,SAAO,KAAK,OAAO,KAAyB,KAAK,UAAU,MAAM,QAAQ;;;;;;CAO3E,WAAW,IAAY,MAAe,SAAsD;AAC1F,SAAO,KAAK,OAAO,IAAwB,GAAG,KAAK,SAAS,GAAG,MAAM,MAAM,QAAQ;;;;;;CAOrF,WAAW,IAAY,SAAsD;AAC3E,SAAO,KAAK,OAAO,OAAkB,GAAG,KAAK,SAAS,GAAG,MAAM,QAAQ"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
//#region src/core/bindMethods.ts
|
|
4
|
+
/**
|
|
5
|
+
* Binds every method of `instance`'s class chain (up to `Object.prototype`) to `instance`, as own
|
|
6
|
+
* properties, so methods keep working when destructured (`const { getMany } = api`). The most
|
|
7
|
+
* derived implementation wins; getters, setters and `constructor` are skipped.
|
|
8
|
+
*/
|
|
9
|
+
function bindMethods(instance) {
|
|
10
|
+
const target = instance;
|
|
11
|
+
const bound = /* @__PURE__ */ new Set();
|
|
12
|
+
for (let prototype = Object.getPrototypeOf(instance); prototype && prototype !== Object.prototype; prototype = Object.getPrototypeOf(prototype)) for (const key of Reflect.ownKeys(prototype)) {
|
|
13
|
+
if (key === "constructor" || bound.has(key)) continue;
|
|
14
|
+
const { value } = Object.getOwnPropertyDescriptor(prototype, key);
|
|
15
|
+
if (typeof value === "function") {
|
|
16
|
+
target[key] = value.bind(instance);
|
|
17
|
+
bound.add(key);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.bindMethods = bindMethods;
|
|
24
|
+
//# sourceMappingURL=bindMethods.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bindMethods.cjs","names":[],"sources":["../../src/core/bindMethods.ts"],"sourcesContent":["/**\n * Binds every method of `instance`'s class chain (up to `Object.prototype`) to `instance`, as own\n * properties, so methods keep working when destructured (`const { getMany } = api`). The most\n * derived implementation wins; getters, setters and `constructor` are skipped.\n */\nexport function bindMethods(instance: object): void {\n const target = instance as Record<PropertyKey, unknown>\n const bound = new Set<PropertyKey>()\n\n for (\n let prototype: object | null = Object.getPrototypeOf(instance);\n prototype && prototype !== Object.prototype;\n prototype = Object.getPrototypeOf(prototype)\n ) {\n for (const key of Reflect.ownKeys(prototype)) {\n if (key === 'constructor' || bound.has(key)) {\n continue\n }\n const { value } = Object.getOwnPropertyDescriptor(prototype, key) as PropertyDescriptor\n if (typeof value === 'function') {\n target[key] = value.bind(instance)\n bound.add(key)\n }\n }\n }\n}\n"],"mappings":";;;;;;;;AAKA,SAAgB,YAAY,UAAwB;CAClD,MAAM,SAAS;CACf,MAAM,wBAAQ,IAAI,KAAkB;AAEpC,MACE,IAAI,YAA2B,OAAO,eAAe,SAAS,EAC9D,aAAa,cAAc,OAAO,WAClC,YAAY,OAAO,eAAe,UAAU,CAE5C,MAAK,MAAM,OAAO,QAAQ,QAAQ,UAAU,EAAE;AAC5C,MAAI,QAAQ,iBAAiB,MAAM,IAAI,IAAI,CACzC;EAEF,MAAM,EAAE,UAAU,OAAO,yBAAyB,WAAW,IAAI;AACjE,MAAI,OAAO,UAAU,YAAY;AAC/B,UAAO,OAAO,MAAM,KAAK,SAAS;AAClC,SAAM,IAAI,IAAI"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binds every method of `instance`'s class chain (up to `Object.prototype`) to `instance`, as own
|
|
3
|
+
* properties, so methods keep working when destructured (`const { getMany } = api`). The most
|
|
4
|
+
* derived implementation wins; getters, setters and `constructor` are skipped.
|
|
5
|
+
*/
|
|
6
|
+
export declare function bindMethods(instance: object): void;
|
|
7
|
+
//# sourceMappingURL=bindMethods.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bindMethods.d.ts","sourceRoot":"","sources":["../../src/core/bindMethods.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAoBlD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/core/bindMethods.ts
|
|
2
|
+
/**
|
|
3
|
+
* Binds every method of `instance`'s class chain (up to `Object.prototype`) to `instance`, as own
|
|
4
|
+
* properties, so methods keep working when destructured (`const { getMany } = api`). The most
|
|
5
|
+
* derived implementation wins; getters, setters and `constructor` are skipped.
|
|
6
|
+
*/
|
|
7
|
+
function bindMethods(instance) {
|
|
8
|
+
const target = instance;
|
|
9
|
+
const bound = /* @__PURE__ */ new Set();
|
|
10
|
+
for (let prototype = Object.getPrototypeOf(instance); prototype && prototype !== Object.prototype; prototype = Object.getPrototypeOf(prototype)) for (const key of Reflect.ownKeys(prototype)) {
|
|
11
|
+
if (key === "constructor" || bound.has(key)) continue;
|
|
12
|
+
const { value } = Object.getOwnPropertyDescriptor(prototype, key);
|
|
13
|
+
if (typeof value === "function") {
|
|
14
|
+
target[key] = value.bind(instance);
|
|
15
|
+
bound.add(key);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
export { bindMethods };
|
|
22
|
+
//# sourceMappingURL=bindMethods.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bindMethods.mjs","names":[],"sources":["../../src/core/bindMethods.ts"],"sourcesContent":["/**\n * Binds every method of `instance`'s class chain (up to `Object.prototype`) to `instance`, as own\n * properties, so methods keep working when destructured (`const { getMany } = api`). The most\n * derived implementation wins; getters, setters and `constructor` are skipped.\n */\nexport function bindMethods(instance: object): void {\n const target = instance as Record<PropertyKey, unknown>\n const bound = new Set<PropertyKey>()\n\n for (\n let prototype: object | null = Object.getPrototypeOf(instance);\n prototype && prototype !== Object.prototype;\n prototype = Object.getPrototypeOf(prototype)\n ) {\n for (const key of Reflect.ownKeys(prototype)) {\n if (key === 'constructor' || bound.has(key)) {\n continue\n }\n const { value } = Object.getOwnPropertyDescriptor(prototype, key) as PropertyDescriptor\n if (typeof value === 'function') {\n target[key] = value.bind(instance)\n bound.add(key)\n }\n }\n }\n}\n"],"mappings":";;;;;;AAKA,SAAgB,YAAY,UAAwB;CAClD,MAAM,SAAS;CACf,MAAM,wBAAQ,IAAI,KAAkB;AAEpC,MACE,IAAI,YAA2B,OAAO,eAAe,SAAS,EAC9D,aAAa,cAAc,OAAO,WAClC,YAAY,OAAO,eAAe,UAAU,CAE5C,MAAK,MAAM,OAAO,QAAQ,QAAQ,UAAU,EAAE;AAC5C,MAAI,QAAQ,iBAAiB,MAAM,IAAI,IAAI,CACzC;EAEF,MAAM,EAAE,UAAU,OAAO,yBAAyB,WAAW,IAAI;AACjE,MAAI,OAAO,UAAU,YAAY;AAC/B,UAAO,OAAO,MAAM,KAAK,SAAS;AAClC,SAAM,IAAI,IAAI"}
|