@verdocs/js-sdk
Version:
Isomorphic JS/TS SDK providing types and API wrappers for the Verdocs platform for Node and browser clients
1 lines • 263 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../src/Lists.ts","../src/Utils/Colors.ts","../src/Utils/DateTime.ts","../src/Utils/Entitlements.ts","../src/Utils/Fields.ts","../src/Utils/Files.ts","../src/Utils/Locales.ts","../src/Utils/Strings.ts","../src/Utils/Primitives.ts","../src/Utils/Token.ts","../src/Utils/globalThis.js","../src/Users/Auth.ts","../src/Users/Notifications.ts","../src/Users/Profiles.ts","../src/VerdocsEndpoint.ts","../src/Envelopes/Envelopes.ts","../src/Envelopes/Initials.ts","../src/Envelopes/KBA.ts","../src/Envelopes/Recipients.ts","../src/Envelopes/Permissions.ts","../src/Envelopes/Signatures.ts","../src/Organizations/ApiKeys.ts","../src/Organizations/Contacts.ts","../src/Organizations/Groups.ts","../src/Organizations/Invitations.ts","../src/Organizations/Members.ts","../src/Organizations/Organizations.ts","../src/Organizations/Webhooks.ts","../src/Sessions/Permissions.ts","../src/Templates/Actions.ts","../src/Templates/Fields.ts","../src/Templates/Permissions.ts","../src/Templates/Roles.ts","../src/Templates/Stars.ts","../src/Templates/Tags.ts","../src/Templates/Templates.ts","../src/Templates/TemplateDocuments.ts","../src/Templates/Validators.ts"],"sourcesContent":["import type {TFieldType} from './BaseTypes';\n\nexport const FIELD_TYPES: TFieldType[] = [\n 'textbox',\n 'signature',\n 'initial',\n 'date',\n 'dropdown',\n 'timestamp',\n /** @deprecated. Use `textbox` with multiLine set to > 1 */\n 'textarea',\n 'checkbox',\n 'radio',\n 'attachment',\n 'payment',\n];\n\nexport const DEFAULT_FIELD_WIDTHS: Record<TFieldType, number> = {\n signature: 71,\n initial: 71,\n date: 75,\n timestamp: 130,\n textbox: 150,\n textarea: 150,\n checkbox: 14,\n radio: 14,\n dropdown: 85,\n attachment: 24,\n payment: 24,\n};\n\nexport const DEFAULT_FIELD_HEIGHTS: Record<TFieldType, number> = {\n signature: 36,\n initial: 36,\n date: 15,\n timestamp: 15,\n textbox: 15,\n textarea: 41,\n checkbox: 14,\n radio: 14,\n dropdown: 20,\n attachment: 24,\n payment: 24,\n};\n\nexport const WEBHOOK_EVENTS = [\n 'envelope_created',\n 'envelope_completed',\n 'envelope_canceled',\n\n 'template_created',\n 'template_updated',\n 'template_deleted',\n 'template_used',\n];\n\nexport const ALL_PERMISSIONS = [\n // TODO: Are these permissions still relevant?\n // 'member:view',\n // 'org:create',\n // 'org:view',\n // 'org:list',\n // 'org:transfer',\n\n 'template:creator:create:public',\n 'template:creator:create:org',\n 'template:creator:create:personal',\n 'template:creator:delete',\n 'template:creator:visibility',\n 'template:member:read',\n 'template:member:write',\n 'template:member:delete',\n 'template:member:visibility',\n 'owner:add',\n 'owner:remove',\n 'admin:add',\n 'admin:remove',\n 'member:view',\n 'member:add',\n 'member:remove',\n 'org:create',\n 'org:view',\n 'org:update',\n 'org:delete',\n 'org:transfer',\n 'org:list',\n 'envelope:create',\n 'envelope:cancel',\n 'envelope:view',\n];\n","import type {TRole} from '../Sessions';\n\n/**\n * Given a `rgba(r,g,b,a)` string value, returns the hex equivalent, dropping the alpha channel.\n */\nexport function getRGB(rgba: string) {\n const rgbNumbers = rgba.replace('rgba(', '').replace(')', '').split(',');\n const rgbObject = {\n red: +rgbNumbers[0],\n green: +rgbNumbers[1],\n blue: +rgbNumbers[2],\n alpha: +rgbNumbers[3],\n };\n const alpha = 1 - rgbObject.alpha;\n const red = Math.round((rgbObject.alpha * (rgbObject.red / 255) + alpha) * 255);\n const green = Math.round((rgbObject.alpha * (rgbObject.green / 255) + alpha) * 255);\n const blue = Math.round((rgbObject.alpha * (rgbObject.blue / 255) + alpha) * 255);\n return '#' + rgbToHex(red) + rgbToHex(green) + rgbToHex(blue);\n}\n\n/**\n * Given an RGB string value, returns the hex equivalent.\n */\nfunction rgbToHex(rgb: number) {\n const hex = rgb.toString(16);\n if (hex.length < 2) {\n return '0' + hex;\n }\n return hex;\n}\n\n/**\n * Given a signer role index, return the color code for that signer.\n */\nexport function getRGBA(roleIndex: number) {\n switch (roleIndex % 10) {\n case 0:\n return roleIndex === 0 ? 'rgba(255, 193, 7, 0.4)' : 'rgba(134, 134, 134, 0.3)'; // #FFE69C\n case 1:\n return 'rgba(156, 39, 176, .4)'; // '#E3C3E9'\n case 2:\n return 'rgba(33, 150, 243, .4)'; // '#C1E1FB'\n case 3:\n return 'rgba(220, 231, 117, 0.3)';\n case 4:\n return 'rgba(121, 134, 203, 0.3)';\n case 5:\n return 'rgba(77, 182, 172, 0.3)';\n case 6:\n return 'rgba(255, 202, 165, 0.3)';\n case 7:\n return 'rgba(2, 247, 190, 0.3)';\n case 8:\n return 'rgba(255, 138, 101, 0.3)';\n case 9:\n return 'rgba(82, 255, 79, 0.3)';\n default:\n return 'rgba(229, 115, 155, 0.3)';\n }\n}\n\n/**\n * Given a role name, return a color code for it. This works by computing a hash code so the specific color returned\n * is not specified explicitly, but will be the same for every call with the same input value.\n */\nexport function nameToRGBA(str: string) {\n if (!!str) {\n const validNum = parseInt(str.slice(-1), 10);\n if (!isNaN(validNum)) {\n str += (validNum * 99).toString();\n }\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n // tslint:disable-next-line:no-bitwise\n hash = str.charCodeAt(i) + ((hash << 5) - hash);\n }\n hash = Math.round(hash / 1.3);\n // tslint:disable-next-line:no-bitwise\n const c = (hash & 0x00ffff08).toString(16).toUpperCase();\n const hex = '#' + '00000'.substring(0, 6 - c.length) + c;\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex) as any[];\n const color = {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16),\n };\n return `rgba(${color.r}, ${color.g}, ${color.b}, 0.2)`;\n }\n}\n\n/**\n * Helper function to obtain a color code given a role name given various possible inputs.\n */\nexport function getRoleColor(name: string, roles: TRole[], index?: number) {\n if (index) {\n return getRGBA(index);\n } else if (roles && roles.length > 0) {\n const roleIndex = roles.findIndex((role) => role === name);\n if (roleIndex > -1) {\n return getRGBA(roleIndex);\n } else {\n return nameToRGBA(name);\n }\n } else {\n return nameToRGBA(name);\n }\n}\n","const YEAR = 365 * 24 * 60 * 60;\n// const MONTH = 30 * 24 * 60 * 60;\nconst WEEK = 7 * 24 * 60 * 60;\nconst DAY = 24 * 60 * 60;\nconst HOUR = 60 * 60;\nconst MINUTE = 60;\n\nexport const formatShortTimeAgo = (val: any) => {\n if (val === undefined || val === null) {\n return '';\n }\n\n let dateInput;\n if (typeof val === 'string' || typeof val === 'number') {\n dateInput = new Date(val);\n } else if (typeof val === 'object') {\n dateInput = val;\n } else {\n return '';\n }\n\n const timeDiff = Math.floor((new Date().getTime() - dateInput.getTime()) / 1000);\n if (timeDiff >= YEAR) {\n return Math.floor(timeDiff / YEAR) + 'Y';\n }\n // if (timeDiff >= MONTH) {\n // return Math.floor(timeDiff / MONTH) + 'M';\n // }\n if (timeDiff >= WEEK) {\n return Math.floor(timeDiff / WEEK) + 'W';\n }\n if (timeDiff >= DAY) {\n return Math.floor(timeDiff / DAY) + 'D';\n }\n if (timeDiff >= HOUR) {\n return Math.floor(timeDiff / HOUR) + 'H';\n }\n if (timeDiff >= MINUTE) {\n return Math.floor(timeDiff / MINUTE) + 'M';\n }\n\n return `${timeDiff}S`;\n};\n","import {TEntitlement} from '../BaseTypes';\nimport {IEntitlement} from '../Models';\n\nexport const collapseEntitlements = (entitlements: IEntitlement[]) => {\n const now = new Date();\n const activeEntitlements: Partial<Record<TEntitlement, IEntitlement>> = {};\n\n entitlements.forEach((entitlement) => {\n const start = new Date(entitlement.starts_at);\n const end = new Date(entitlement.ends_at);\n if (now >= start && now <= end && !activeEntitlements[entitlement.feature]) {\n activeEntitlements[entitlement.feature] = entitlement;\n }\n });\n\n return activeEntitlements;\n};\n","import {IEnvelopeField, ITemplateField} from '../Models';\n\nexport function getRTop(y: number, fieldHeight: number, iTextHeight: number, yRatio: number) {\n return iTextHeight - (y + fieldHeight) * yRatio;\n}\n\nexport function getRLeft(x: number, ratio: number) {\n return x * ratio;\n}\n\nexport function getRValue(y: number, ratio: number) {\n return y * ratio;\n}\n\nexport function blobToBase64(image: Blob) {\n const fileReader = new FileReader();\n return new Promise((resolve, reject) => {\n fileReader.onerror = () => {\n reject(new DOMException('Problem reading blob.'));\n };\n\n fileReader.onload = () => {\n resolve(fileReader.result);\n };\n\n fileReader.readAsDataURL(image);\n });\n}\n\nexport function rescale(r: number, n: number): number {\n return r * n;\n}\n\n/**\n * Utility function to sort fields by page, then by Y coordinate, then by X coordinate.\n * NOTE: This function mutates the input array.\n */\nexport function sortFields(fields: ITemplateField[] | IEnvelopeField[]) {\n fields.sort((a, b) => {\n const aPage = a.page || 0;\n const bPage = b.page || 0;\n const aX = a.x || 0;\n const aY = (a.y || 0) + (a.height || 0);\n const bX = b.x || 0;\n const bY = (b.y || 0) + (b.height || 0);\n\n if (aPage !== bPage) {\n return aPage - bPage;\n }\n\n // NOTE: Logic looks a little strange X vs Y. It's because we go top down,\n // left to right. But Y coordinates are inverted in PDFs. The reason for\n // the division is because no human makes perfect templates and frequently\n // two fields on the \"same line\" will be slightly offset vertically.\n const divaY = Math.floor(aY / 5);\n const divbY = Math.floor(bY / 5);\n if (divaY !== divbY) {\n return divbY - divaY;\n }\n\n return aX - bX;\n });\n\n return fields;\n}\n","import type {IFileWithData} from './Types';\n\n/**\n * Given a File, extract the file's content as a base64 encoded data URL. The response will have a prefix that\n * includes the MIME type of the file, e.g. \"data:image/jpeg;base64,iVBORw0K......\"\n */\nexport const fileToDataUrl = (file: File): Promise<IFileWithData> =>\n new Promise((resolve, reject) => {\n const reader = new FileReader();\n\n reader.onload = () =>\n resolve({\n lastModified: file.lastModified,\n size: file.size,\n type: file.type,\n name: file.name,\n data: reader.result as string,\n });\n\n reader.onerror = reject;\n\n if (file) {\n reader.readAsDataURL(file);\n } else {\n reject(new Error('Invalid file'));\n }\n });\n\n/**\n * Trigger a download dialog to save a blob as a file on disk.\n */\nexport const downloadBlob = (blob: Blob, name = 'file.pdf') => {\n const blobUrl = URL.createObjectURL(blob);\n const link = document.createElement('a');\n\n link.href = blobUrl;\n link.download = name;\n document.body.appendChild(link);\n\n link.dispatchEvent(\n new MouseEvent('click', {\n bubbles: true,\n cancelable: true,\n view: window,\n }),\n );\n\n document.body.removeChild(link);\n};\n","import type {ICountry} from './Types';\n\nexport const Countries: ICountry[] = [\n {code: '+7 840', name: 'Abkhazia', value: '+7'},\n {code: '+93', name: 'Afghanistan', value: '+93'},\n {code: '+355', name: 'Albania', value: '+355'},\n {code: '+213', name: 'Algeria', value: '+213'},\n {code: '+1', name: 'American Samoa', value: '+1'},\n {code: '+376', name: 'Andorra', value: '+376'},\n {code: '+244', name: 'Angola', value: '+244'},\n {code: '+1', name: 'Anguilla', value: '+1'},\n {code: '+1', name: 'Antigua and Barbuda', value: '+1'},\n {code: '+54', name: 'Argentina', value: '+54'},\n {code: '+374', name: 'Armenia', value: '+374'},\n {code: '+297', name: 'Aruba', value: '+297'},\n {code: '+247', name: 'Ascension', value: '+247'},\n {code: '+61', name: 'Australia', value: '+61'},\n {code: '+672', name: 'Australian External Territories', value: '+672'},\n {code: '+43', name: 'Austria', value: '+43'},\n {code: '+994', name: 'Azerbaijan', value: '+994'},\n {code: '+1', name: 'Bahamas', value: '+1'},\n {code: '+973', name: 'Bahrain', value: '+973'},\n {code: '+880', name: 'Bangladesh', value: '+880'},\n {code: '+1', name: 'Barbados', value: '+1'},\n {code: '+1', name: 'Barbuda', value: '+1'},\n {code: '+375', name: 'Belarus', value: '+375'},\n {code: '+32', name: 'Belgium', value: '+32'},\n {code: '+501', name: 'Belize', value: '+501'},\n {code: '+229', name: 'Benin', value: '+229'},\n {code: '+1', name: 'Bermuda', value: '+1'},\n {code: '+975', name: 'Bhutan', value: '+975'},\n {code: '+591', name: 'Bolivia', value: '+591'},\n {code: '+387', name: 'Bosnia and Herzegovina', value: '+387'},\n {code: '+267', name: 'Botswana', value: '+267'},\n {code: '+55', name: 'Brazil', value: '+55'},\n {code: '+246', name: 'British Indian Ocean Territory', value: '+246'},\n {code: '+1', name: 'British Virgin Islands', value: '+1'},\n {code: '+673', name: 'Brunei', value: '+673'},\n {code: '+359', name: 'Bulgaria', value: '+359'},\n {code: '+226', name: 'Burkina Faso', value: '+226'},\n {code: '+257', name: 'Burundi', value: '+257'},\n {code: '+855', name: 'Cambodia', value: '+855'},\n {code: '+237', name: 'Cameroon', value: '+237'},\n {code: '+1', name: 'Canada', value: '+1'},\n {code: '+238', name: 'Cape Verde', value: '+238'},\n {code: '+1', name: 'Cayman Islands', value: '+1'},\n {code: '+236', name: 'Central African Republic', value: '+236'},\n {code: '+235', name: 'Chad', value: '+235'},\n {code: '+56', name: 'Chile', value: '+56'},\n {code: '+86', name: 'China', value: '+86'},\n {code: '+61', name: 'Christmas Island', value: '+61'},\n {code: '+61', name: 'Cocos-Keeling Islands', value: '+61'},\n {code: '+57', name: 'Colombia', value: '+57'},\n {code: '+269', name: 'Comoros', value: '+269'},\n {code: '+242', name: 'Congo', value: '+242'},\n {code: '+243', name: 'Congo, Dem. Rep. of (Zaire)', value: '+243'},\n {code: '+682', name: 'Cook Islands', value: '+682'},\n {code: '+506', name: 'Costa Rica', value: '+506'},\n {code: '+385', name: 'Croatia', value: '+385'},\n {code: '+53', name: 'Cuba', value: '+53'},\n {code: '+599', name: 'Curacao', value: '+599'},\n {code: '+537', name: 'Cyprus', value: '+537'},\n {code: '+420', name: 'Czech Republic', value: '+420'},\n {code: '+45', name: 'Denmark', value: '+45'},\n {code: '+246', name: 'Diego Garcia', value: '+246'},\n {code: '+253', name: 'Djibouti', value: '+253'},\n {code: '+1', name: 'Dominica', value: '+1'},\n {code: '+1', name: 'Dominican Republic', value: '+1'},\n {code: '+670', name: 'East Timor', value: '+670'},\n {code: '+56', name: 'Easter Island', value: '+56'},\n {code: '+593', name: 'Ecuador', value: '+593'},\n {code: '+20', name: 'Egypt', value: '+20'},\n {code: '+503', name: 'El Salvador', value: '+503'},\n {code: '+240', name: 'Equatorial Guinea', value: '+240'},\n {code: '+291', name: 'Eritrea', value: '+291'},\n {code: '+372', name: 'Estonia', value: '+372'},\n {code: '+251', name: 'Ethiopia', value: '+251'},\n {code: '+500', name: 'Falkland Islands', value: '+500'},\n {code: '+298', name: 'Faroe Islands', value: '+298'},\n {code: '+679', name: 'Fiji', value: '+679'},\n {code: '+358', name: 'Finland', value: '+358'},\n {code: '+33', name: 'France', value: '+33'},\n {code: '+596', name: 'Martinique', value: '+596'},\n {code: '+594', name: 'French Guiana', value: '+594'},\n {code: '+689', name: 'French Polynesia', value: '+689'},\n {code: '+241', name: 'Gabon', value: '+241'},\n {code: '+220', name: 'Gambia', value: '+220'},\n {code: '+995', name: 'Georgia', value: '+995'},\n {code: '+49', name: 'Germany', value: '+49'},\n {code: '+233', name: 'Ghana', value: '+233'},\n {code: '+350', name: 'Gibraltar', value: '+350'},\n {code: '+30', name: 'Greece', value: '+30'},\n {code: '+299', name: 'Greenland', value: '+299'},\n {code: '+1', name: 'Grenada', value: '+1'},\n {code: '+590', name: 'Guadeloupe', value: '+590'},\n {code: '+1', name: 'Guam', value: '+1'},\n {code: '+502', name: 'Guatemala', value: '+502'},\n {code: '+224', name: 'Guinea', value: '+224'},\n {code: '+245', name: 'Guinea-Bissau', value: '+245'},\n {code: '+595', name: 'Guyana', value: '+595'},\n {code: '+509', name: 'Haiti', value: '+509'},\n {code: '+504', name: 'Honduras', value: '+504'},\n {code: '+852', name: 'Hong Kong SAR China', value: '+852'},\n {code: '+36', name: 'Hungary', value: '+36'},\n {code: '+354', name: 'Iceland', value: '+354'},\n {code: '+91', name: 'India', value: '+91'},\n {code: '+62', name: 'Indonesia', value: '+62'},\n {code: '+98', name: 'Iran', value: '+98'},\n {code: '+964', name: 'Iraq', value: '+964'},\n {code: '+353', name: 'Ireland', value: '+353'},\n {code: '+972', name: 'Israel', value: '+972'},\n {code: '+39', name: 'Italy', value: '+39'},\n {code: '+225', name: 'Ivory Coast', value: '+225'},\n {code: '+1', name: 'Jamaica', value: '+1'},\n {code: '+81', name: 'Japan', value: '+81'},\n {code: '+962', name: 'Jordan', value: '+962'},\n {code: '+77', name: 'Kazakhstan', value: '+7'},\n {code: '+254', name: 'Kenya', value: '+254'},\n {code: '+686', name: 'Kiribati', value: '+686'},\n {code: '+965', name: 'Kuwait', value: '+965'},\n {code: '+996', name: 'Kyrgyzstan', value: '+996'},\n {code: '+856', name: 'Laos', value: '+856'},\n {code: '+371', name: 'Latvia', value: '+371'},\n {code: '+961', name: 'Lebanon', value: '+961'},\n {code: '+266', name: 'Lesotho', value: '+266'},\n {code: '+231', name: 'Liberia', value: '+231'},\n {code: '+218', name: 'Libya', value: '+218'},\n {code: '+423', name: 'Liechtenstein', value: '+423'},\n {code: '+370', name: 'Lithuania', value: '+370'},\n {code: '+352', name: 'Luxembourg', value: '+352'},\n {code: '+853', name: 'Macau SAR China', value: '+853'},\n {code: '+389', name: 'Macedonia', value: '+389'},\n {code: '+261', name: 'Madagascar', value: '+261'},\n {code: '+265', name: 'Malawi', value: '+265'},\n {code: '+60', name: 'Malaysia', value: '+60'},\n {code: '+960', name: 'Maldives', value: '+960'},\n {code: '+223', name: 'Mali', value: '+223'},\n {code: '+356', name: 'Malta', value: '+356'},\n {code: '+692', name: 'Marshall Islands', value: '+692'},\n {code: '+596', name: 'Martinique', value: '+596'},\n {code: '+222', name: 'Mauritania', value: '+222'},\n {code: '+230', name: 'Mauritius', value: '+230'},\n {code: '+262', name: 'Mayotte or Réunion', value: '+262'},\n {code: '+52', name: 'Mexico', value: '+52'},\n {code: '+691', name: 'Micronesia', value: '+691'},\n {code: '+1', name: 'Midway Island', value: '+1'},\n {code: '+373', name: 'Moldova', value: '+373'},\n {code: '+377', name: 'Monaco', value: '+377'},\n {code: '+976', name: 'Mongolia', value: '+976'},\n {code: '+382', name: 'Montenegro', value: '+382'},\n {code: '+1', name: 'Montserrat', value: '+1'},\n {code: '+212', name: 'Morocco', value: '+212'},\n {code: '+95', name: 'Myanmar', value: '+95'},\n {code: '+264', name: 'Namibia', value: '+264'},\n {code: '+674', name: 'Nauru', value: '+674'},\n {code: '+977', name: 'Nepal', value: '+977'},\n {code: '+31', name: 'Netherlands', value: '+31'},\n {code: '+599', name: 'Netherlands Antilles', value: '+599'},\n {code: '+1', name: 'Nevis', value: '+1'},\n {code: '+687', name: 'New Caledonia', value: '+687'},\n {code: '+64', name: 'New Zealand', value: '+64'},\n {code: '+505', name: 'Nicaragua', value: '+505'},\n {code: '+227', name: 'Niger', value: '+227'},\n {code: '+234', name: 'Nigeria', value: '+234'},\n {code: '+683', name: 'Niue', value: '+683'},\n {code: '+672', name: 'Norfolk Island', value: '+672'},\n {code: '+850', name: 'North Korea', value: '+850'},\n {code: '+1', name: 'Northern Mariana Islands', value: '+1'},\n {code: '+47', name: 'Norway', value: '+47'},\n {code: '+968', name: 'Oman', value: '+968'},\n {code: '+92', name: 'Pakistan', value: '+92'},\n {code: '+680', name: 'Palau', value: '+680'},\n {code: '+970', name: 'Palestinian Territory', value: '+970'},\n {code: '+507', name: 'Panama', value: '+507'},\n {code: '+675', name: 'Papua New Guinea', value: '+675'},\n {code: '+595', name: 'Paraguay', value: '+595'},\n {code: '+51', name: 'Peru', value: '+51'},\n {code: '+63', name: 'Philippines', value: '+63'},\n {code: '+48', name: 'Poland', value: '+48'},\n {code: '+351', name: 'Portugal', value: '+351'},\n {code: '+1', name: 'Puerto Rico', value: '+1'},\n {code: '+974', name: 'Qatar', value: '+974'},\n {code: '+40', name: 'Romania', value: '+40'},\n {code: '+7', name: 'Russia', value: '+7'},\n {code: '+250', name: 'Rwanda', value: '+250'},\n {code: '508', name: 'Saint Pierre and Miquelon', value: '508'},\n {code: '+685', name: 'Samoa', value: '+685'},\n {code: '+378', name: 'San Marino', value: '+378'},\n {code: '+966', name: 'Saudi Arabia', value: '+966'},\n {code: '+221', name: 'Senegal', value: '+221'},\n {code: '+381', name: 'Serbia', value: '+381'},\n {code: '+248', name: 'Seychelles', value: '+248'},\n {code: '+232', name: 'Sierra Leone', value: '+232'},\n {code: '+65', name: 'Singapore', value: '+65'},\n {code: '+421', name: 'Slovakia', value: '+421'},\n {code: '+386', name: 'Slovenia', value: '+386'},\n {code: '+677', name: 'Solomon Islands', value: '+677'},\n {code: '+27', name: 'South Africa', value: '+27'},\n {code: '+500', name: 'South Georgia and the South Sandwich Islands', value: '+500'},\n {code: '+82', name: 'South Korea', value: '+82'},\n {code: '+34', name: 'Spain', value: '+34'},\n {code: '+94', name: 'Sri Lanka', value: '+94'},\n {code: '+249', name: 'Sudan', value: '+249'},\n {code: '+597', name: 'Suriname', value: '+597'},\n {code: '+268', name: 'Swaziland', value: '+268'},\n {code: '+46', name: 'Sweden', value: '+46'},\n {code: '+41', name: 'Switzerland', value: '+41'},\n {code: '+963', name: 'Syria', value: '+963'},\n {code: '+886', name: 'Taiwan', value: '+886'},\n {code: '+992', name: 'Tajikistan', value: '+992'},\n {code: '+255', name: 'Tanzania', value: '+255'},\n {code: '+66', name: 'Thailand', value: '+66'},\n {code: '+670', name: 'Timor Leste', value: '+670'},\n {code: '+228', name: 'Togo', value: '+228'},\n {code: '+690', name: 'Tokelau', value: '+690'},\n {code: '+676', name: 'Tonga', value: '+676'},\n {code: '+1', name: 'Trinidad and Tobago', value: '+1'},\n {code: '+216', name: 'Tunisia', value: '+216'},\n {code: '+90', name: 'Turkey', value: '+90'},\n {code: '+993', name: 'Turkmenistan', value: '+993'},\n {code: '+1', name: 'Turks and Caicos Islands', value: '+1'},\n {code: '+688', name: 'Tuvalu', value: '+688'},\n {code: '+1', name: 'U.S. Virgin Islands', value: '+1'},\n {code: '+256', name: 'Uganda', value: '+256'},\n {code: '+380', name: 'Ukraine', value: '+380'},\n {code: '+971', name: 'United Arab Emirates', value: '+971'},\n {code: '+44', name: 'United Kingdom', value: '+44'},\n {code: '+1', name: 'United States', value: '+1'},\n {code: '+598', name: 'Uruguay', value: '+598'},\n {code: '+998', name: 'Uzbekistan', value: '+998'},\n {code: '+678', name: 'Vanuatu', value: '+678'},\n {code: '+58', name: 'Venezuela', value: '+58'},\n {code: '+84', name: 'Vietnam', value: '+84'},\n {code: '+1', name: 'Wake Island', value: '+1'},\n {code: '+681', name: 'Wallis and Futuna', value: '+681'},\n {code: '+967', name: 'Yemen', value: '+967'},\n {code: '+260', name: 'Zambia', value: '+260'},\n {code: '+255', name: 'Zanzibar', value: '+255'},\n {code: '+263', name: 'Zimbabwe', value: '+263'},\n];\n\nexport function getCountryByCode(code: string): ICountry | null {\n const found = Countries.find((country) => country.code === code);\n if (found) return found;\n\n if (isFrenchGuiana(code)) {\n return {code: '+594', name: 'French Guiana', value: '+594'};\n } else if (isGuadeloupe(code)) {\n return {code: '+590', name: 'Guadeloupe', value: '+590'};\n } else if (isMartinique(code)) {\n return {code: '+596', name: 'Martinique', value: '+596'};\n } else if (isMayotte(code)) {\n return {code: '+262', name: 'Mayotte or Réunion', value: '+262'};\n }\n\n return null;\n}\n\nexport function isFrenchGuiana(code: string) {\n return '+594' === code.substring(0, 4);\n}\n\nexport function isGuadeloupe(code: string) {\n return '+590' === code.substring(0, 4);\n}\n\nexport function isMartinique(code: string) {\n return '+596' === code.substring(0, 4);\n}\n\nexport function isMayotte(code: string) {\n return '+262' === code.substring(0, 4);\n}\n\nexport function getPlusOneCountry(code: string) {\n let info: ICountry | null = null;\n switch (code.substring(0, 5)) {\n case '+1684':\n info = {code: '+1', name: 'American Samoa', value: '+1'};\n break;\n case '+1264':\n info = {code: '+1', name: 'Anguilla', value: '+1'};\n break;\n case '+1268':\n info = {code: '+1', name: 'Antigua and Barbuda', value: '+1'};\n break;\n case '+1242':\n info = {code: '+1', name: 'Bahamas', value: '+1'};\n break;\n case '+1246':\n info = {code: '+1', name: 'Barbados', value: '+1'};\n break;\n case '+1441':\n info = {code: '+1', name: 'Bermuda', value: '+1'};\n break;\n case '+1284':\n info = {code: '+1', name: 'British Virgin Islands', value: '+1'};\n break;\n case '+1':\n info = {code: '+1', name: '', value: '+1'};\n break;\n default:\n break;\n }\n return info;\n}\n\nexport function isCanada(code: string) {\n const canadianAreaCodes = [\n '403',\n '587',\n '780',\n '825',\n '604',\n '250',\n '778',\n '236',\n '204',\n '431',\n '506',\n '709',\n '867',\n '782',\n '902',\n '867',\n '548',\n '705',\n '365',\n '613',\n '807',\n '226',\n '289',\n '437',\n '519',\n '647',\n '905',\n '249',\n '343',\n '416',\n '902',\n '782',\n '450',\n '418',\n '579',\n '873',\n '367',\n '514',\n '581',\n '819',\n '438',\n '639',\n '306',\n '867',\n ];\n const areaCode = code.substring(0, 5);\n return canadianAreaCodes.findIndex((x) => '+1' + x === areaCode) > -1;\n}\n\nexport function isAmericanSamoa(code: string) {\n return code.substring(0, 5) === '+1684';\n}\n\nexport function isDominicanRepublic(code: string) {\n return '+1809' === code.substring(0, 5) || '+1829' === code.substring(0, 5) || '+1849' === code.substring(0, 5);\n}\n\nexport function isPuertoRico(code: string) {\n return code.substring(0, 5) === '+' || code.substring(0, 5) === '+';\n}\n\n// need to finish\nexport function getMatchingCountry(code: string, substrings: number) {\n const toMatch = code.substring(0, substrings);\n return Countries.filter((c) => c.code === toMatch).length;\n}\n\n// const e164Regex = new RegExp(/\\+[1-9]\\d{6,14}/g);\n\n// export function simpleE164Validator(code: string) {\n// return (code !== null && code.length < 16 && code.length > 6 && e164Regex.test(code)) || code === '' || code === null;\n// }\n","/**\n * Capitalize the first letter of a string.\n */\nexport const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);\n\n/**\n * Convert a phone-number-like string to E164 format.\n * @see https://46elks.com/kb/e164\n */\nexport const convertToE164 = (input: string) => {\n // \"(212) 555-1212\" => +12125551212\n // \"+46766861004\" => \"+46766861004\"\n // \"212-555-1212\" => +12125551212\n // \"212.555.1212\" => +12125551212\n // \"212 555 1212\" => +12125551212\n\n let temp = (input || '').trim();\n // If we are already prefixed, assume the user did it deliberately and attempt to use what they entered. We also short-circuit blanks.\n if (!temp || temp.startsWith('+')) {\n return temp;\n }\n\n // Remove any spaces, parenthesis or other punctuation.\n temp = temp.replace(/[^0-9]/g, '');\n\n // If the number begins with a zero, remove the leading zero. Do not combine this with the previous step because it needs to be removed\n // whether it's the actual first character e.g. `0(5)` or just the first digit e.g. `(05`.\n temp = temp.replace(/^0/g, '');\n\n // Prepend the country code and +. We're assuming US in this case given the target demographic. Users in other countries would/should be\n // already entering a prefix so they'd shortcut out of this routine via the + prefix check.\n return `+1${temp}`;\n};\n\n// Generate a random string of a given length. This is NOT cryptographically strong. It is meant for light-duty\n// uses such as assigning IDs to DOM elements.\nexport const randomString = (length: number) =>\n Math.random()\n .toString(36)\n .substring(2, 2 + length + 1);\n","import type {IProfile} from '../Models';\nimport {capitalize} from './Strings';\n\n/**\n * Create an array containing a sequence of integers, e.g. [START, START+1, START+2, ...] This is frequently useful\n * in rendering operations when there is no source array to .map() across.\n */\nexport const integerSequence = (start: number, count: number): number[] =>\n Array(count)\n .fill(1)\n .map((_, index) => index + start);\n\n/**\n * Format a profile's full name\n */\nexport const formatFullName = (source?: {first_name?: string | null; last_name?: string | null; [key: string]: any} | null) =>\n `${capitalize(source?.first_name || '')} ${capitalize(source?.last_name || '')}`.trim();\n\n/**\n * Format a profile's initials\n */\nexport const formatInitials = (profile?: IProfile) =>\n profile ? `${capitalize(profile.first_name).charAt(0)} ${capitalize(profile.last_name).charAt(0)}` : '--';\n\n/**\n * Generate suggested initials for a full name, e.g. \"John Doe\" will yield \"JD\".\n */\nexport const fullNameToInitials = (name: string) =>\n name\n .split(' ')\n .map((word) => word[0])\n .join('');\n","/* tslint:disable:no-bitwise */\n\nimport type {TSession} from '../Sessions';\n\nconst b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n// Regular expression to check formal correctness of base64 encoded strings\nconst b64re = /^(?:[A-Za-z\\d+\\/]{4})*?(?:[A-Za-z\\d+\\/]{2}(?:==)?|[A-Za-z\\d+\\/]{3}=?)?$/;\n\n/**\n * Simplified, Node/Browser-safe alternative to atob() for base64 decoding.\n * Modified from https://github.com/MaxArt2501/base64-js/blob/master/base64.js\n */\nexport const AtoB = (str: string) => {\n // atob can work with strings with whitespaces, even inside the encoded part,\n // but only \\t, \\n, \\f, \\r and ' ', which can be stripped.\n str = String(str).replace(/[\\t\\n\\f\\r ]+/g, '');\n if (!b64re.test(str)) throw new TypeError(\"Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.\");\n\n // Adding the padding if missing, for semplicity\n str += '=='.slice(2 - (str.length & 3));\n let bitmap;\n let result = '';\n let r1;\n let r2;\n let i = 0;\n\n for (; i < str.length; ) {\n bitmap =\n (b64.indexOf(str.charAt(i++)) << 18) |\n (b64.indexOf(str.charAt(i++)) << 12) |\n ((r1 = b64.indexOf(str.charAt(i++))) << 6) |\n (r2 = b64.indexOf(str.charAt(i++)));\n\n result +=\n r1 === 64\n ? String.fromCharCode((bitmap >> 16) & 255)\n : r2 === 64\n ? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255)\n : String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255, bitmap & 255);\n }\n return result;\n};\n\n/**\n * Decode the body of a JWT. This helper may allow front-end applications to avoid a dependency on `jsonwebtoken` in\n * many cases. Note that this should only be used for true JWTs. Opaque tokens will cause this to throw.\n */\nexport const decodeJWTBody = (token: string) => JSON.parse(AtoB((token || '').split('.')[1] || ''));\n\n/**\n * Decode the body of an Verdocs access token. Note that raw tokens contain namespaced fields, e.g.\n * `https://verdocs.com/profile_id`. To make these tokens easier to use in front-end code, this name-spacing\n * will be removed. Note that user and signing sessions have different access token formats. The calling\n * application should distinguish between the two based on the context of the authenticated session, or by\n * the presence of the `document_id` field, which will only be present for signing sessions.\n */\nexport const decodeAccessTokenBody = (token: string): TSession => {\n let decoded: any;\n try {\n decoded = decodeJWTBody(token) as TSession;\n if (decoded === null) {\n return null;\n }\n } catch (e) {\n return null;\n }\n\n return decoded;\n};\n","// This file provides a polyfill for managing globals in both NodeJS and browser environments. This is\n// an anti-pattern we'd hoped to avoid, but we have several projects dependending on one common library\n// (this js-sdk) and we want that library to provide a common endpoint to all callers (so authentication\n// tokens only need to be tracked in one place). The trouble is, one of those libraries is based on\n// StencilJS and is compiling its modules into Web Components. Because of how module resolution works,\n// when those Components load js-sdk they get a separate instance. Without messy options like having to\n// pass raw data from the caller to each Component, or pass around references to a common Endpoint, they\n// have no way to access authenticated sessions unless we make the Endpoint a true global.\n//\n// @credit https://github.com/medikoo/es5-ext/blob/master/global.js\n// @credit https://mathiasbynens.be/notes/globalthis\n\nvar naiveFallback = function () {\n if (typeof self === 'object' && self) return self;\n if (typeof window === 'object' && window) return window;\n throw new Error('Unable to resolve global `this`');\n};\n\nmodule.exports = (function () {\n if (this) return this;\n\n // Unexpected strict mode (may happen if e.g. bundled into ESM module)\n\n // Fallback to standard globalThis if available\n if (typeof globalThis === 'object' && globalThis) return globalThis;\n\n // Thanks @mathiasbynens -> https://mathiasbynens.be/notes/globalthis\n // In all ES5+ engines global object inherits from Object.prototype\n // (if you approached one that doesn't please report)\n try {\n Object.defineProperty(Object.prototype, '__global__', {\n get: function () {\n return this;\n },\n configurable: true,\n });\n } catch (error) {\n // Unfortunate case of updates to Object.prototype being restricted\n // via preventExtensions, seal or freeze\n return naiveFallback();\n }\n try {\n // Safari case (window.__global__ works, but __global__ does not)\n if (!__global__) return naiveFallback();\n return __global__;\n } finally {\n delete Object.prototype.__global__;\n }\n})();\n","import {IAuthenticateResponse, IChangePasswordRequest, IChangePasswordResponse, IVerifyEmailRequest} from './Types';\nimport {VerdocsEndpoint} from '../VerdocsEndpoint';\nimport {IUser} from '../Models';\n\nexport interface IROPCRequest {\n grant_type: 'password';\n username: string;\n password: string;\n client_id?: string;\n scope?: string;\n}\n\nexport interface IClientCredentialsRequest {\n grant_type: 'client_credentials';\n client_id: string;\n client_secret: string;\n scope?: string;\n}\n\nexport interface IRefreshTokenRequest {\n grant_type: 'refresh_token';\n refresh_token: string;\n client_id?: string;\n scope?: string;\n}\n\nexport type TAuthenticationRequest = IROPCRequest | IClientCredentialsRequest | IRefreshTokenRequest;\n\n/**\n * Authenticate to Verdocs.\n *\n * ```typescript\n * import {authenticate, VerdocsEndpoint} from '@verdocs/js-sdk';\n *\n * // Client-side call, suitable for Web and mobile apps:\n * const {access_token} = await Auth.authenticate({ username: 'test@test.com', password: 'PASSWORD', grant_type:'password' });\n * VerdocsEndpoint.getDefault().setAuthToken(access_token);\n *\n * // Server-side call, suitable for server apps. NEVER EXPOSE client_secret IN FRONT-END CODE:\n * const {access_token} = await Auth.authenticate({ client_id: '...', client_secret: '...', grant_type:'client_credentials' });\n * VerdocsEndpoint.getDefault().setAuthToken(access_token);\n * ```\n *\n * @group Authentication\n * @api POST /v2/oauth2/token Authenticate\n * @apiBody string(enum: 'client_credentials'|'refresh_token'|'password') grant_type The type of grant to request. API callers should nearly always use 'client_credentials'.\n * @apiBody string(format: 'uuid') client_id? If grant_type is client_credentials or refresh_token, the client ID of the API key to use.\n * @apiBody string(format: 'uuid') client_secret? If grant_type is client_credentials, the secret key of the API key to use.\n * @apiBody string username? If grant_type is password, the username to authenticate with.\n * @apiBody string password? If grant_type is password, the password to authenticate with.\n * @apiBody string password? If grant_type is password, the password to authenticate with.\n * @apiBody string scope? Optional scope to limit the auth token to. Do not specify this unless you are instructed to by a Verdocs Support rep.\n * @apiSuccess IAuthenticateResponse . The detailed metadata for the envelope requested\n */\nexport const authenticate = (endpoint: VerdocsEndpoint, params: TAuthenticationRequest) =>\n endpoint.api //\n .post<IAuthenticateResponse>('/v2/oauth2/token', params)\n .then((r) => r.data);\n\n/**\n * If called before the session expires, this will refresh the caller's session and tokens.\n *\n * ```typescript\n * import {Auth, VerdocsEndpoint} from '@verdocs/js-sdk';\n *\n * const {accessToken} = await Auth.refreshTokens();\n * VerdocsEndpoint.setAuthToken(accessToken);\n * ```\n */\nexport const refreshToken = (endpoint: VerdocsEndpoint, refreshToken: string) =>\n authenticate(endpoint, {grant_type: 'refresh_token', refresh_token: refreshToken});\n\n/**\n * Update the caller's password when the old password is known (typically for logged-in users).\n *\n * ```typescript\n * import {changePassword} from '@verdocs/js-sdk';\n *\n * const {status, message} = await changePassword({ old_password, new_password });\n * if (status !== 'OK') {\n * window.alert(`Password reset error: ${message}`);\n * }\n * ```\n *\n * @group Authentication\n * @api POST /v2/users/change-password Change the caller's password\n * @apiBody string old_password Current password for the caller\n * @apiBody string new_password New password to set for the caller. Must meet strength requirements.\n * @apiSuccess string . Success\n */\nexport const changePassword = (endpoint: VerdocsEndpoint, params: IChangePasswordRequest) =>\n endpoint.api //\n .post<IChangePasswordResponse>('/v2/users/change-password', params)\n .then((r) => r.data);\n\n/**\n * Request a password reset, when the old password is not known (typically in login forms).\n *\n * ```typescript\n * import {resetPassword} from '@verdocs/js-sdk';\n *\n * const {success} = await resetPassword({ email });\n * if (status !== 'OK') {\n * window.alert(`Please check your email for instructions on how to reset your password.`);\n * }\n *\n * // Collect code and new password from the user, then call:\n *\n * const {success} = await resetPassword({ email, code, new_password });\n * if (status !== 'OK') {\n * window.alert(`Please check your verification code and try again.`);\n * }\n * ```\n *\n * @group Authentication\n * @api POST /v2/users/reset-password Reset a password for a user\n * @apiBody string email Email address for the user account\n * @apiBody string code? To initiate a reset request, omit this field. To complete it, provide the emailed code received by the user.\n * @apiBody string new_password? To initiate a reset request, omit this field. To complete it, provide the new password the user wishes to use.\n * @apiSuccess string . Success\n */\nexport const resetPassword = (endpoint: VerdocsEndpoint, params: {email: string; code?: string; new_password?: string}) =>\n endpoint.api //\n .post<{success: boolean}>('/v2/users/reset-password', params)\n .then((r) => r.data);\n\n/**\n * Resend the email verification request if the email or token are unknown. Instead, an accessToken\n * may be supplied through which the user will be identified. This is intended to be used in post-signup\n * cases where the user is \"partially\" authenticated (has a session, but is not yet verified).\n *\n * ```typescript\n * import {resendVerification} from '@verdocs/js-sdk';\n *\n * const result = await resendVerification();\n * ```\n *\n * @group Authentication\n * @api POST /v2/users/verify Resend an email verification request for a \"partially\" authenticated user (authenticated, but not yet verified)\n * @apiSuccess string . Success\n */\nexport const resendVerification = (endpoint: VerdocsEndpoint, accessToken?: string) =>\n endpoint.api //\n .post<{result: 'done'}>('/v2/users/resend-verification', {}, accessToken ? {headers: {Authorization: `Bearer ${accessToken}`}} : {})\n .then((r) => r.data);\n\n/**\n * Resend the email verification request if the user is unauthenticated, but the email and token are known.\n * Used if the token is valid but has expired.\n *\n * ```typescript\n * import {resendVerification} from '@verdocs/js-sdk';\n *\n * const result = await resendVerification();\n * ```\n *\n * @group Authentication\n * @api POST /v2/users/verify Resend the email verification request if both the email and token are known. Used if the token is valid but has expired.\n * @apiSuccess IAuthenticateResponse . Updated authentication details\n */\nexport const verifyEmail = (endpoint: VerdocsEndpoint, params: IVerifyEmailRequest) =>\n endpoint.api //\n .post<IAuthenticateResponse>('/v2/users/verify', params)\n .then((r) => r.data);\n\n/**\n * Get the caller's current user record.\n *\n * @group Authentication\n * @api GET /v2/users/me Get the caller's user record.\n * @apiSuccess IUser . User record\n */\nexport const getMyUser = (endpoint: VerdocsEndpoint) =>\n endpoint.api //\n .get<IUser>('/v2/users/me')\n .then((r) => r.data);\n","import {VerdocsEndpoint} from '../VerdocsEndpoint';\n\nexport const getNotifications = async (endpoint: VerdocsEndpoint) =>\n endpoint.api //\n .get('/v2/notifications')\n .then((r) => r.data);\n","import type {IAuthenticateResponse, IUpdateProfileRequest, ICreateProfileRequest} from './Types';\nimport {VerdocsEndpoint} from '../VerdocsEndpoint';\nimport type {IProfile} from '../Models';\n\n/**\n * Get the caller's available profiles. The current profile will be marked with `current: true`.\n *\n * ```typescript\n * import {getProfiles} from '@verdocs/js-sdk';\n *\n * const profiles = await getProfiles();\n * ```\n *\n * @group Profiles\n * @api GET /v2/profiles Get the caller's profiles\n * @apiDescription A user may have multiple profiles, one for each organization of which they are a member. Only one profile may be \"current\" at a time.\n * @apiSuccess array(items: IProfile) . The caller's profiles\n */\nexport const getProfiles = (endpoint: VerdocsEndpoint) =>\n endpoint.api //\n .get<IProfile[]>('/v2/profiles')\n .then((r) => r.data);\n\n/**\n * Get the caller's current profile. This is just a convenience accessor that calls `getProfiles()`\n * and returns the first `current: true` entry.\n *\n * ```typescript\n * import {getCurrentProfile} from '@verdocs/js-sdk';\n *\n * const profiles = await getCurrentProfile(VerdocsEndpoint.getDefault());\n * ```\n */\nexport const getCurrentProfile = (endpoint: VerdocsEndpoint) =>\n endpoint.api //\n .get<IProfile[]>('/v2/profiles')\n .then((r) => (r.data || []).find((profile) => profile.current));\n\n/**\n * Switch the caller's \"current\" profile. The current profile is used for permissions checking\n * and profile_id field settings for most operations in Verdocs. It is important to select the\n * appropropriate profile before calling other API functions.\n *\n * ```typescript\n * import {switchProfile} from '@verdocs/js-sdk';\n *\n * const newProfile = await switchProfile(VerdocsEndpoint.getDefault(), 'PROFILEID');\n * ```\n *\n * @group Profiles\n * @api POST /v2/profiles/:profile_id/switch Change the \"current\" profile for the caller\n * @apiSuccess IAuthenticateResponse . New authentication credentials\n */\nexport const switchProfile = (endpoint: VerdocsEndpoint, profileId: string) =>\n endpoint.api //\n .post<IAuthenticateResponse>(`/v2/profiles/${profileId}/switch`)\n .then((r) => r.data);\n\n/**\n * Update a profile. For future expansion, the profile ID to update is required, but currently\n * this must also be the \"current\" profile for the caller.\n *\n * ```typescript\n * import {updateProfile} from '@verdocs/js-sdk/Users';\n *\n * const newProfile = await updateProfile(VerdocsEndpoint.getDefault(), 'PROFILEID');\n * ```\n *\n * @group Profiles\n * @api PATCH /v2/profiles/:profile_id Update a profile\n * @apiBody string first_name? First name\n * @apiBody string last_name? Last name\n * @apiBody string phone? Phone number\n * @apiBody array(items:TPermission) permissions? New permissions to directly apply to the profile\n * @apiBody array(items:TRole) roles? New roles to assign to the profile\n * @apiSuccess IProfile . The updated profile\n */\nexport const updateProfile = (endpoint: VerdocsEndpoint, profileId: string, params: IUpdateProfileRequest) =>\n endpoint.api //\n .patch<IProfile>(`/v2/profiles/${profileId}`, params)\n .then((r) => r.data);\n\n/**\n * Delete a profile. If the requested profile is the caller's curent profile, the next\n * available profile will be selected.\n *\n * ```typescript\n * import {deleteProfile} from '@verdocs/js-sdk';\n *\n * await deleteProfile(VerdocsEndpoint.getDefault(), 'PROFILEID');\n * ```\n *\n * @group Profiles\n * @api DELETE /v2/profiles/:profile_id Delete a profile\n * @apiSuccess IAuthenticateResponse . New session tokens for the next available profile for the caller, or null if none.\n */\nexport const deleteProfile = (endpoint: VerdocsEndpoint, profileId: string) =>\n endpoint.api //\n .delete<IAuthenticateResponse | {status: 'OK'; message: 'Your last profile has been deleted. You are now logged out.'}>(\n `/v2/profiles/${profileId}`,\n )\n .then((r) => r.data);\n\n/**\n * Create a new profile. Note that there are two registration paths for creation:\n * - Get invited to an organization, by an admin or owner of that org.\n * - Created a new organization. The caller will become the first owner of the new org.\n *\n * This endpoint is for the second path, so an organization name is required. It is NOT\n * required to be unique because it is very common for businesses to have the same names,\n * without conflicting (e.g. \"Delta\" could be Delta Faucet or Delta Airlines).\n *\n * The new profile will automatically be set as the user's \"current\" profile, and new\n * session tokens will be returned to the caller. However, the caller's email may not yet\n * be verified. In that case, the caller will not yet be able to call other endpoints in\n * the Verdocs API. The caller will need to check their email for a verification code,\n * which should be submitted via the `verifyEmail` endpoint.\n *\n * ```typescript\n * import {createProfile} from '@verdocs/js-sdk';\n *\n * const newSession = await createProfile(VerdocsEndpoint.getDefault(), {\n * orgName: 'NEW ORG', email: 'a@b.com', password: '12345678', firstName: 'FIRST', lastName: 'LAST'\n * });\n * ```\n */\nexport const createProfile = (endpoint: VerdocsEndpoint, params: ICreateProfileRequest) =>\n endpoint.api //\n .post<IAuthenticateResponse>('/v2/profiles', params)\n .then((r) => r.data);\n\n/**\n * Update the caller's profile photo. This can only be called for the user's \"current\" profile.\n *\n * ```typescript\n * import {uploadProfilePhoto} from '@verdocs/js-sdk';\n *\n * await uploadProfilePhoto((VerdocsEndpoint.getDefault(), profileId, file);\n * ```\n *\n * @group Profiles\n * @api PATCH /v2/templates/:template_id Change a profile's photo\n * @apiBody string(format:binary) file File to upload\n * @apiSuccess IProfile . The updated profile\n */\nexport const updateProfilePhoto = (\n endpoint: VerdocsEndpoint,\n profileId: string,\n file: File,\n onUploadProgress?: (percent: number, loadedBytes: number, totalBytes: number) => void,\n) => {\n const formData = new FormData();\n formData.append('picture', file, file.name);\n\n return endpoint.api //\n .patch<IProfile>(`/v2/profiles/${profileId}`, formData, {\n timeout: 120000,\n onUploadProgress: (event) => {\n const total = event.total || 1;\n const loaded = event.loaded || 0;\n onUploadProgress?.(Math.floor((loaded * 100) / (total || 1)), loaded, total || 1);\n },\n })\n .then((r) => r.data);\n};\n","import axios, {AxiosInstance} from 'axios';\nimport {TSession, TSessionType} from './Sessions';\nimport {decodeAccessTokenBody, randomString} from './Utils';\nimport globalThis from './Utils/globalThis';\nimport {getCurrentProfile} from './Users';\nimport {IProfile} from './Models';\n\n// @credit https://derickbailey.com/2016/03/09/creating-a-true-singleton-in-node-js-with-es6-symbols/\n// Also see globalThis for comments about why we're doing this in the first place.\nconst ENDPOINT_KEY = Symbol.for('verdocs-default-endpoint');\n\nconst BETA_ORIGINS = ['https://beta.verdocs.com', 'https://stage.verdocs.com', 'http://localhost:6006', 'http://localhost:5173'];\n\nconst requestLogger = (r: any) => {\n // tslint:disable-next-line\n console.debug(`[JS-SDK] ${r.method.toUpperCase()} ${r.baseURL}${r.url}`, r.data ? JSON.stringify(r.data) : '');\n return r;\n};\n\nexport type TEnvironment = '' | 'beta';\n\nexport type TSessionChangedListener =