@microblink/blinkid-imagecapture-in-browser-sdk
Version:
A smart image capturing library for WebAssembly-enabled browsers.
320 lines (311 loc) • 12.7 kB
JavaScript
/*! ****************************************************************************
Copyright (c) Microblink. All rights reserved.
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
***************************************************************************** */
;
Object.defineProperty(exports, '__esModule', { value: true });
/**
* Copyright (c) Microblink Ltd. All rights reserved.
*/
exports.ApiType = void 0;
(function (ApiType) {
ApiType["Cloud"] = "cloud";
ApiType["SelfHosted"] = "self-hosted";
})(exports.ApiType || (exports.ApiType = {}));
const GenericMessages = {
"GENERIC_ERROR": "There was an error during scan action.",
"UNKNOWN_ERROR": "Oops, something went wrong."
};
/**
* Copyright (c) Microblink Ltd. All rights reserved.
*/
function getSafeUrl(base, ...args) {
const impureUrl = [...args].join("/");
const pureUrl = safeReplaceAll(impureUrl, "//", "/");
const safeBase = base.endsWith("/") ? base.slice(0, -1) : base;
const endpoint = pureUrl.startsWith("/") ? pureUrl : "/" + pureUrl;
return safeBase + endpoint;
}
function safeReplaceAll(input, substr, newSubstr) {
input = input || "";
substr = substr || "";
newSubstr = newSubstr || "";
while (input.indexOf(substr) > -1) {
input = input.replace(substr, newSubstr);
}
return input;
}
function httpClient(method, url, headers, payload) {
return new Promise((resolve, reject) => {
const fetchConfiguration = {
method,
headers
};
if (payload) {
fetchConfiguration["body"] = JSON.stringify(payload);
}
window.fetch(url, fetchConfiguration)
.then((response) => {
const headerEntries = response.headers.entries();
const headers = {};
for (const entry of headerEntries) {
headers[entry[0]] = entry[1];
}
const httpResponse = {
httpStatus: response.status,
headers
};
response.text()
.then((data) => {
try {
const jsonData = JSON.parse(data);
httpResponse["data"] = jsonData;
}
catch (_a) {
httpResponse["data"] = data;
}
resolve(httpResponse);
})
.catch((error) => {
httpResponse["data"] = error;
reject(httpResponse);
});
})
.catch(error => {
reject({
httpStatus: -1,
headers: {},
data: error
});
});
});
}
function imageDataToBase64(imageData) {
const canvas = document.createElement("canvas");
canvas.width = imageData.width;
canvas.height = imageData.height;
const context = canvas.getContext("2d");
context === null || context === void 0 ? void 0 : context.putImageData(imageData, 0, 0);
return canvas.toDataURL();
}
/**
* Copyright (c) Microblink Ltd. All rights reserved.
*/
const CloudMessages = {
"API_ROLE_IS_NOT_FOUND": "API role is not found",
"AUTHORIZATION_HEADER_IS_NOT_VALID": "Authorization header is not valid",
"BAD_REQUEST": "Bad request",
"FORBIDDEN_RECOGNIZER": "Forbidden recognizer",
"IMAGE_IS_NOT_ABLE_TO_CONVERT_TO_RAW_PIXELS": "Image is not able to convert to raw pixels",
"IMAGE_IS_NOT_VALID": "Image is not valid",
"IMAGE_IS_NOT_VALID_BASE64_STRING": "Image is not valid base64 string",
"IMAGE_SIZE_IS_TOO_BIG": "Image size is too big",
"INSUFFICIENT_BALANCE": "Insufficient balance",
"INTERNAL_SERVER_ERROR": "Internal server error",
"INVALID_LICENSE_KEY": "Invalid license key",
"NOT_ALLOWED_TO_EXECUTE_REQUESTED_RECOGNIZER": "Not allowed to execute requested recognizer",
"SERVER_CANCELED_REQUEST": "Server canceled request",
"SERVER_TOO_BUSY": "Server too busy"
};
const DefaultHeaders$1 = {
"Accept": "application/json",
"Content-Type": "application/json"
};
class ServiceCloud {
constructor(apiLocation, healthcheckEndpoint, headers) {
this.apiLocation = apiLocation;
this.healthcheckEndpoint = healthcheckEndpoint;
this.headers = Object.assign(DefaultHeaders$1, headers);
// HTTP header must contain header field and value
// @see https://tools.ietf.org/html/rfc7230#section-3.2
for (const key in this.headers) {
if (!key || !this.headers[key]) {
delete this.headers[key];
}
}
}
getHealthcheckResponse() {
const requestUrl = getSafeUrl(this.apiLocation, this.healthcheckEndpoint);
return httpClient("GET", requestUrl, this.headers);
}
recognize(endpoint, payload, method = "POST") {
const requestUrl = getSafeUrl(this.apiLocation, endpoint);
return httpClient(method, requestUrl, this.headers, payload);
}
}
/**
* Copyright (c) Microblink Ltd. All rights reserved.
*/
const SelfHostedMessages = {
"API_ROLE_IS_NOT_FOUND": "API role is not found",
"AUTHORIZATION_HEADER_IS_NOT_VALID": "Authorization header is not valid",
"BAD_REQUEST": "Bad request",
"FORBIDDEN_RECOGNIZER": "Forbidden recognizer",
"IMAGE_IS_NOT_ABLE_TO_CONVERT_TO_RAW_PIXELS": "Image is not able to convert to raw pixels",
"IMAGE_IS_NOT_VALID": "Image is not valid",
"IMAGE_IS_NOT_VALID_BASE64_STRING": "Image is not valid base64 string",
"IMAGE_SIZE_IS_TOO_BIG": "Image size is too big",
"INTERNAL_SERVER_ERROR": "Internal server error",
"INVALID_LICENSE_KEY": "Invalid license key",
"NOT_ALLOWED_TO_EXECUTE_REQUESTED_RECOGNIZER": "Not allowed to execute requested recognizer",
"SERVER_CANCELED_REQUEST": "Server canceled request",
"SERVER_TOO_BUSY": "Server too busy"
};
const DefaultHeaders = {
"Accept": "application/json",
"Content-Type": "application/json"
};
class ServiceSelfHosted {
constructor(apiLocation, healthcheckEndpoint, headers) {
this.apiLocation = apiLocation;
this.healthcheckEndpoint = healthcheckEndpoint;
this.headers = Object.assign(DefaultHeaders, headers);
// HTTP header must contain header field and value
// @see https://tools.ietf.org/html/rfc7230#section-3.2
for (const key in this.headers) {
if (!key || !this.headers[key]) {
delete this.headers[key];
}
}
}
getHealthcheckResponse() {
const requestUrl = getSafeUrl(this.apiLocation, this.healthcheckEndpoint);
return httpClient("GET", requestUrl, this.headers);
}
recognize(endpoint, payload, method = "POST") {
const requestUrl = getSafeUrl(this.apiLocation, endpoint);
return httpClient(method, requestUrl, this.headers, payload);
}
}
/**
* Copyright (c) Microblink Ltd. All rights reserved.
*/
const _DEFAULT_CLOUD_LOCATION = "http://localhost";
const _DEFAULT_SELF_HOSTED_LOCATION = "http://localhost";
const _DEFAULT_HEALTHCHECK_ENDPOINT = "/v2/hc";
class Client {
/**
* Create new instance of Client service.
*
* This class requires API type and optional configuration object.
*/
constructor(type, configuration) {
if (!type) {
throw "API type is not provided!";
}
const headers = (configuration === null || configuration === void 0 ? void 0 : configuration.headers) || {};
const healthcheckEndpoint = (configuration === null || configuration === void 0 ? void 0 : configuration.healthcheckEndpoint) || _DEFAULT_HEALTHCHECK_ENDPOINT;
const customApiLocation = (configuration === null || configuration === void 0 ? void 0 : configuration.apiLocation) || "";
let apiMessages = {};
switch (type) {
case exports.ApiType.Cloud:
apiMessages = CloudMessages;
this.service = new ServiceCloud(customApiLocation || _DEFAULT_CLOUD_LOCATION, healthcheckEndpoint, headers);
break;
case exports.ApiType.SelfHosted:
apiMessages = SelfHostedMessages;
this.service = new ServiceSelfHosted(customApiLocation || _DEFAULT_SELF_HOSTED_LOCATION, healthcheckEndpoint, headers);
break;
default:
throw "Unsupported API type!";
}
this.errorMessages = Object.assign(GenericMessages, apiMessages, (configuration === null || configuration === void 0 ? void 0 : configuration.messages) || {});
}
/**
* Returns a promise which will resolve to `{ status: true }` if API service
* is available.
*
* In case of error, promise will reject and property `details` with full
* HTTP response will is added to object.
*
* Healthcheck endpoint can be configured with
* `Configuration.healthcheckEndpoint` property. If omitted, default value
* is used.
*/
getHealthcheck() {
return new Promise((resolve, reject) => {
this.service.getHealthcheckResponse()
.then((response) => {
if (response.httpStatus === 200) {
resolve({ status: true });
return;
}
reject({ status: false, response });
})
.catch((response) => {
reject({ status: false, response });
});
});
}
/**
* Extract data from image. First argument is API endpoint, while the second
* one is body which is sent with the request.
*
* This method returns a promise which will always resolve/reject to
* `ResponseRecognition` object.
*
* Promise will resolve only when data has been extracted successfuly, or
* when no data has been extracted. In every other case promise will reject.
*
* For full list of endpoints and related payloads see official
* documentation for Cloud API or Self-hosted API.
*
* @example
* client.recognize( "/v2/recognizers/blinkid-single-side", { "imageSource": imageBase64 } )
* .then( ( result: ResponseRecognition ) => console.log( result.response.data.result ) )
* .catch( ( error: ResponseRecognition ) => console.log( error.error.message ) );
*/
recognize(endpoint, payload) {
return new Promise((resolve, reject) => {
this.service.recognize(endpoint, payload)
.then((response) => {
if (response.httpStatus === 200) {
resolve({ status: true, response });
return;
}
const errorCode = response.data.code || "GENERIC_ERROR";
const recognitionResult = {
status: false,
response: response,
error: {
code: errorCode,
message: this.errorMessages[errorCode]
}
};
reject(recognitionResult);
})
.catch((response) => {
let errorCode = "UNKNOWN_ERROR";
if (response.httpStatus === -1 || (response.httpStatus % 400 < 100)) {
errorCode = "GENERIC_ERROR";
}
const recognitionResult = {
status: false,
response: response,
error: {
code: errorCode,
message: this.errorMessages[errorCode]
}
};
reject(recognitionResult);
});
});
}
/**
* Get Base64 representation of an image based on provided instance of ImageData.
*/
imageDataToBase64(imageData) {
if (!imageData) {
throw "Image data is not provided!";
}
if (!imageData.width || !imageData.height) {
throw "Image data is malformed!";
}
return imageDataToBase64(imageData);
}
}
exports.Client = Client;
exports.GenericMessages = GenericMessages;