UNPKG

@sphereon/oid4vci-common

Version:

OpenID 4 Verifiable Credential Issuance Common Types

168 lines • 7.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getURIComponentsAsArray = exports.decodeJsonProperties = exports.convertURIToJsonObject = exports.convertJsonToURI = void 0; const types_1 = require("../types"); /** * @type {(json: {[s:string]: never} | ArrayLike<never> | string | object, opts?: EncodeJsonAsURIOpts)} encodes a Json object into a URI * @param { {[s:string]: never} | ArrayLike<never> | string | object } json * @param {EncodeJsonAsURIOpts} [opts] Option to encode json as uri * - urlTypeProperties: a list of properties of which the value is a URL * - arrayTypeProperties: a list of properties which are an array */ // /* eslint-disable @typescript-eslint/no-explicit-any */ function convertJsonToURI(json, opts) { var _a, _b; if (typeof json === 'string') { return convertJsonToURI(JSON.parse(json), opts); } const results = []; function encodeAndStripWhitespace(key) { return encodeURIComponent(key.replace(' ', '')); } let components; if (((opts === null || opts === void 0 ? void 0 : opts.version) && opts.version > types_1.OpenId4VCIVersion.VER_1_0_08 && !opts.mode) || (opts === null || opts === void 0 ? void 0 : opts.mode) === types_1.JsonURIMode.JSON_STRINGIFY) { // v11 changed from encoding every param to a encoded json object with a credential_offer param key components = encodeAndStripWhitespace(JSON.stringify(json)); } else { // version 8 or lower, or mode is x-form-www-urlencoded for (const [key, value] of Object.entries(json)) { if (!value) { continue; } //Skip properties that are not of URL type if (!((_a = opts === null || opts === void 0 ? void 0 : opts.uriTypeProperties) === null || _a === void 0 ? void 0 : _a.includes(key))) { results.push(`${key}=${value}`); continue; } if (((_b = opts === null || opts === void 0 ? void 0 : opts.arrayTypeProperties) === null || _b === void 0 ? void 0 : _b.includes(key)) && Array.isArray(value)) { results.push(value.map((v) => `${encodeAndStripWhitespace(key)}=${customEncodeURIComponent(v, /\./g)}`).join('&')); continue; } const isBool = typeof value == 'boolean'; const isNumber = typeof value == 'number'; const isString = typeof value == 'string'; let encoded; if (isBool || isNumber) { encoded = `${encodeAndStripWhitespace(key)}=${value}`; } else if (isString) { encoded = `${encodeAndStripWhitespace(key)}=${customEncodeURIComponent(value, /\./g)}`; } else { encoded = `${encodeAndStripWhitespace(key)}=${customEncodeURIComponent(JSON.stringify(value), /\./g)}`; } results.push(encoded); } components = results.join('&'); } if (opts === null || opts === void 0 ? void 0 : opts.baseUrl) { if (opts.baseUrl.endsWith('=')) { if (opts.param) { throw Error('Cannot combine param with an url ending in ='); } return `${opts.baseUrl}${components}`; } else if (!opts.baseUrl.includes('?')) { return `${opts.baseUrl}?${opts.param ? opts.param + '=' : ''}${components}`; } else if (opts.baseUrl.endsWith('?')) { return `${opts.baseUrl}${opts.param ? opts.param + '=' : ''}${components}`; } else { return `${opts.baseUrl}${opts.param ? '&' + opts.param : ''}=${components}`; } } return components; } exports.convertJsonToURI = convertJsonToURI; /** * @type {(uri: string, opts?: DecodeURIAsJsonOpts): unknown} convertURIToJsonObject converts an URI into a Json object decoding its properties * @param {string} uri * @param {DecodeURIAsJsonOpts} [opts] * - requiredProperties: the required properties * - arrayTypeProperties: properties that can show up more that once * @returns JSON object */ function convertURIToJsonObject(uri, opts) { var _a; if (!uri || ((opts === null || opts === void 0 ? void 0 : opts.requiredProperties) && !((_a = opts.requiredProperties) === null || _a === void 0 ? void 0 : _a.every((p) => uri.includes(p))))) { throw new Error(types_1.BAD_PARAMS); } const uriComponents = getURIComponentsAsArray(uri, opts === null || opts === void 0 ? void 0 : opts.arrayTypeProperties); return decodeJsonProperties(uriComponents); } exports.convertURIToJsonObject = convertURIToJsonObject; function decodeJsonProperties(parts) { const result = {}; for (const key in parts) { const value = parts[key]; if (!value) { continue; } if (Array.isArray(value)) { result[decodeURIComponent(key)] = value.map((v) => decodeURIComponent(v)); continue; } const isBool = typeof value == 'boolean'; const isNumber = typeof value == 'number'; const isString = typeof value == 'string'; const isObject = typeof value == 'object'; if (isBool || isNumber) { result[decodeURIComponent(key)] = value; } else if (isString) { const decoded = decodeURIComponent(value); if (decoded.startsWith('{') && decoded.endsWith('}')) { result[decodeURIComponent(key)] = JSON.parse(decoded); } else { result[decodeURIComponent(key)] = decoded; } } else if (isObject) { result[decodeURIComponent(key)] = decodeJsonProperties(value); } } return result; } exports.decodeJsonProperties = decodeJsonProperties; /** * @function get URI Components as Array * @param {string} uri uri * @param {string[]} [arrayTypes] array of string containing array like keys */ function getURIComponentsAsArray(uri, arrayTypes) { const parts = uri.includes('?') ? uri.split('?')[1] : uri.includes('://') ? uri.split('://')[1] : uri; const json = []; const dict = parts.split('&'); for (const entry of dict) { const pair = entry.split('='); const p0 = pair[0]; const p1 = pair[1]; if (arrayTypes === null || arrayTypes === void 0 ? void 0 : arrayTypes.includes(p0)) { const key = json[p0]; if (Array.isArray(key)) { key.push(p1); } else { json[p0] = [p1]; } continue; } json[p0] = p1; } return json; } exports.getURIComponentsAsArray = getURIComponentsAsArray; /** * @function customEncodeURIComponent is used to encode chars that are not encoded by default * @param searchValue The pattern/regexp to find the char(s) to be encoded * @param uriComponent query string */ function customEncodeURIComponent(uriComponent, searchValue) { // -_.!~*'() are not escaped because they are considered safe. // Add them to the regex as you need return encodeURIComponent(uriComponent).replace(searchValue, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`); } //# sourceMappingURL=Encoding.js.map