UNPKG

@microblink/blinkid-imagecapture-in-browser-sdk

Version:

A smart image capturing library for WebAssembly-enabled browsers.

320 lines (311 loc) 12.7 kB
/*! **************************************************************************** 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. ***************************************************************************** */ 'use strict'; 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;