Current status of ccm-apiclient-commons. Trying to figure best way for zero dependencies and supporting browsers and node environments
parent
01444aa09e
commit
cdde8ce67a
|
|
@ -61,6 +61,12 @@
|
|||
"integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "12.12.50",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.50.tgz",
|
||||
"integrity": "sha512-5ImO01Fb8YsEOYpV+aeyGYztcYcjGsBvN4D7G5r1ef2cuQOpymjWNQi5V0rKHE6PC2ru3HkoUr/Br2/8GUA84w==",
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.6.0.tgz",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.12.50",
|
||||
"@typescript-eslint/eslint-plugin": "^3.6.0",
|
||||
"@typescript-eslint/parser": "^3.6.0",
|
||||
"eslint": "^7.4.0",
|
||||
|
|
|
|||
|
|
@ -1,2 +1,155 @@
|
|||
import http from "http";
|
||||
import { AnyARecord } from "dns";
|
||||
|
||||
export * from "./entities";
|
||||
export * from "./RequestInitProvider";
|
||||
export * from "./RequestInitProvider";
|
||||
|
||||
export interface LibreCcmApiClient {
|
||||
get(
|
||||
endpoint: string,
|
||||
searchParams: Record<string, string>
|
||||
): Promise<ApiResponse>;
|
||||
post(
|
||||
endpoint: string,
|
||||
searchParams: Record<string, string>,
|
||||
body: unknown
|
||||
): Promise<Response>;
|
||||
put(endpoint: string, body: Record<string, unknown>): Promise<Response>;
|
||||
delete(endpoint: string): Promise<Response>;
|
||||
head(endpoint: string): Promise<Response>;
|
||||
options(endpoint: string): Promise<Response>;
|
||||
}
|
||||
|
||||
export interface ApiResponse {
|
||||
status: number;
|
||||
statusText: string;
|
||||
json(): Promise<Record<string, unknown>>;
|
||||
blob(): Promise<Blob>;
|
||||
text(): Promise<string>
|
||||
}
|
||||
|
||||
export interface ApiError {
|
||||
status: number;
|
||||
statusText: string;
|
||||
method: "get" | "post" | "put" | "delete" | "head" | "option";
|
||||
message: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export function buildUrl(base: string, endpoint: string, searchParams?: Record<string, string>): string {
|
||||
const url = new URL(base);
|
||||
url.pathname = endpoint;
|
||||
if (searchParams) {
|
||||
const urlSearchParams: URLSearchParams = new URLSearchParams();
|
||||
for (const key in searchParams) {
|
||||
urlSearchParams.append(key, searchParams[key]);
|
||||
}
|
||||
url.search = urlSearchParams.toString();
|
||||
}
|
||||
|
||||
return url.href;
|
||||
}
|
||||
|
||||
export function buildEmbeddedApiClient(): LibreCcmApiClient {
|
||||
if (!document) {
|
||||
throw "document global variable is not available. Please use the buildRemoteApiClient.";
|
||||
}
|
||||
const baseUrl = new URL(document.documentURI);
|
||||
baseUrl.hash = "";
|
||||
baseUrl.password = "";
|
||||
baseUrl.pathname = "";
|
||||
baseUrl.search = "";
|
||||
baseUrl.username = "";
|
||||
|
||||
return new EmbeddedApiClient(baseUrl.href, {
|
||||
credentials: "include",
|
||||
mode: "same-origin",
|
||||
});
|
||||
}
|
||||
|
||||
class FetchResponse implements ApiResponse {
|
||||
readonly status: number;
|
||||
readonly statusText: string;
|
||||
#response: Response;
|
||||
|
||||
constructor(response: Response) {
|
||||
this.status = response.status;
|
||||
this.statusText = response.statusText;
|
||||
this.#response = response;
|
||||
}
|
||||
|
||||
json(): Promise<Record<string, unknown>> {
|
||||
return this.#response.json();
|
||||
}
|
||||
|
||||
blob(): Promise<Blob> {
|
||||
return this.#response.blob();
|
||||
}
|
||||
|
||||
text(): Promise<string> {
|
||||
return this.#response.text();
|
||||
}
|
||||
}
|
||||
|
||||
class EmbeddedApiClient implements LibreCcmApiClient {
|
||||
#baseUrl: string;
|
||||
#fetchOptions: RequestInit;
|
||||
|
||||
constructor(baseUrl: string, fetchOptions: RequestInit) {
|
||||
this.#baseUrl = baseUrl;
|
||||
this.#fetchOptions = fetchOptions;
|
||||
}
|
||||
|
||||
async get(
|
||||
endpoint: string,
|
||||
searchParams?: Record<string, string>
|
||||
): Promise<ApiResponse> {
|
||||
const fetchOptions: RequestInit = {};
|
||||
Object.assign(fetchOptions, this.#fetchOptions);
|
||||
fetchOptions.method = "get";
|
||||
|
||||
const url = buildUrl(this.#baseUrl, endpoint, searchParams);
|
||||
try {
|
||||
const response = await fetch(url, this.#fetchOptions);
|
||||
if (response.ok) {
|
||||
return new FetchResponse(response);
|
||||
} else {
|
||||
throw {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
method: "get",
|
||||
message: "Received an error from the API endpoint. ",
|
||||
url
|
||||
}
|
||||
}
|
||||
} catch(err) {
|
||||
throw `Failed to execute GET on ${url}: ${err}`;
|
||||
}
|
||||
}
|
||||
|
||||
async post(
|
||||
endpoint: string,
|
||||
searchParams: Record<string, string>,
|
||||
body: unknown
|
||||
): Promise<Response> {
|
||||
throw "Not implemented yet";
|
||||
}
|
||||
|
||||
put(endpoint: string, body: Record<string, unknown>): Promise<Response> {
|
||||
throw "Not implemented yet";
|
||||
}
|
||||
|
||||
delete(endpoint: string): Promise<Response> {
|
||||
throw "Not implemented yet";
|
||||
}
|
||||
|
||||
head(endpoint: string): Promise<Response> {
|
||||
throw "Not implemented yet";
|
||||
}
|
||||
|
||||
options(endpoint: string): Promise<Response> {
|
||||
throw "Not implemented yet";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue