mirror of
https://github.com/status-im/sourcecred.git
synced 2025-02-23 09:48:14 +00:00
util: add uuid
module (#1914)
Summary: A new utility module defines an opaque UUID type. Clients can generate random UUIDs and convert them to and from strings. We roll our own module here rather than using the `uuid` NPM module because that module only exposes the 32-character hyphen-separated string form of UUID, which takes up nearly 50% more space. The usual approach these days is to use fixed-length base64 strings without padding. For instance, [YouTube video IDs are of this form][yt]. This module takes care not to generate IDs that might confuse command-line argument parsers, and tries not to generate IDs that might contain English curse words. The implementation uses isomorphic libraries for RNG and base64 conversion because the relevant Node and browser APIs are not aligned. [yt]: https://webapps.stackexchange.com/a/101153 Test Plan: Unit tests included, with full coverage. wchargin-branch: util-uuid
This commit is contained in:
parent
ba8313e4b4
commit
abbc024cbf
27
flow-typed/npm/base-64_v0.1.x.js
vendored
Normal file
27
flow-typed/npm/base-64_v0.1.x.js
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// flow-typed signature: 8c0e4b660f7fea456915de716d603d27
|
||||
// flow-typed version: c6154227d1/base-64_v0.1.x/flow_>=v0.104.x
|
||||
|
||||
declare module 'base-64' {
|
||||
declare module.exports: {
|
||||
version: string,
|
||||
/**
|
||||
* This function takes a byte string (the input parameter) and encodes it according to base64.
|
||||
* The input data must be in the form of a string containing only characters
|
||||
* in the range from U+0000 to U+00FF, each representing a binary byte with values 0x00 to 0xFF.
|
||||
* The base64.encode() function is designed to be fully compatible
|
||||
* with btoa() as described in the HTML Standard.
|
||||
* see: https://html.spec.whatwg.org/multipage/webappapis.html#dom-windowbase64-btoa
|
||||
*/
|
||||
encode(input: string): string,
|
||||
/**
|
||||
* This function takes a base64-encoded string (the input parameter) and decodes it.
|
||||
* The return value is in the form of a string containing only characters in
|
||||
* the range from U+0000 to U+00FF, each representing a binary byte with values 0x00 to 0xFF.
|
||||
* The base64.decode() function is designed to be fully compatible
|
||||
* with atob() as described in the HTML Standard.
|
||||
* see: https://html.spec.whatwg.org/multipage/webappapis.html#dom-windowbase64-atob
|
||||
*/
|
||||
decode(input: string): string,
|
||||
...
|
||||
};
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
"private": false,
|
||||
"dependencies": {
|
||||
"aphrodite": "^2.4.0",
|
||||
"base-64": "^0.1.0",
|
||||
"base64url": "^3.0.1",
|
||||
"better-sqlite3": "^7.0.0",
|
||||
"bottleneck": "^2.19.5",
|
||||
@ -23,6 +24,7 @@
|
||||
"history": "^3.3.0",
|
||||
"htmlparser2": "^4.1.0",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"isomorphic-webcrypto": "^2.3.6",
|
||||
"json-stable-stringify": "^1.0.1",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
|
126
src/util/uuid.js
Normal file
126
src/util/uuid.js
Normal file
@ -0,0 +1,126 @@
|
||||
// @flow
|
||||
|
||||
// Universally unique identifiers. As in the UUID4 spec, we use
|
||||
// uniformly random 128-bit payloads, but we represent them more
|
||||
// compactly as base64 strings (22 characters long) rather than hex
|
||||
// strings (36 characters with a bunch of hyphens). We also ensure that
|
||||
// the serialized form is clean for machine and human eyes.
|
||||
|
||||
import {encode as base64Encode, decode as base64Decode} from "base-64";
|
||||
import {getRandomValues} from "isomorphic-webcrypto";
|
||||
|
||||
import * as C from "./combo";
|
||||
|
||||
export opaque type Uuid: string = string;
|
||||
|
||||
// Any UUIDs that we generate will be purely alphanumeric and will not
|
||||
// contain consecutive pairs of certain letters. Non-alphanumeric base64
|
||||
// characters are either +/ or -_, depending on encoding. The former set
|
||||
// is not URL-safe, and the latter set is not safe for command line
|
||||
// arguments (IDs starting with hyphens) or easy legibility (consecutive
|
||||
// hyphens or underscores). Consecutive occurrences of /csfhuit/i are
|
||||
// forbidden per a heuristic given by <https://hashids.org/#cursing> to
|
||||
// avoid common English curse words.
|
||||
const _RE_UNCLEAN = /[+/\-_]|[csfhuit]{2}/i;
|
||||
|
||||
function isClean(s: string): boolean {
|
||||
return !s.match(_RE_UNCLEAN);
|
||||
}
|
||||
|
||||
// Generate an unpadded base64 string of a uniformly random 128-bit
|
||||
// payload. This may be unclean.
|
||||
function randomUuidUnchecked(): string {
|
||||
const bytes = getRandomValues(new Uint8Array(16));
|
||||
const blob = [...bytes].map((n) => String.fromCharCode(n)).join("");
|
||||
return btoa(blob).slice(0, -2); // drop "==" padding
|
||||
}
|
||||
|
||||
// Generate this many uniformly random UUIDs looking for a clean one.
|
||||
// The total failure probability drops off exponentially with each try.
|
||||
//
|
||||
// To model the probability that `randomUuidUnchecked` emits a clean ID,
|
||||
// consider a DFA with three states INIT, DANGER, and FAIL. If we ever
|
||||
// see a non-alphanumeric character, go straight to FAIL (which
|
||||
// absorbs). If we see one of the characters that must not appear twice
|
||||
// consecutively, more from INIT to DANGER or DANGER to FAIL. If we see
|
||||
// any other character, move from DANGER back to INIT. Then this is a
|
||||
// Markov chain with transitions:
|
||||
//
|
||||
// - INIT: 48/64 to INIT, 14/64 to DANGER, 2/64 to FAIL;
|
||||
// - DANGER: 48/64 to INIT, 16/64 to FAIL;
|
||||
// - FAIL: always back to FAIL.
|
||||
//
|
||||
// A 128-bit payload is base-64 encoded by 21 uniform code units plus
|
||||
// one final code unit with less entropy (only 2 bits), but for
|
||||
// simplicity we'll just model this as 22 uniform code units, which is
|
||||
// very nearly correct. Then the probability of emitting an unclean ID
|
||||
// is the probability that after 22 steps in this Markov chain starting
|
||||
// from INIT we end up at FAIL---
|
||||
//
|
||||
// $ octave --no-gui
|
||||
// >> A = [48 14 2; 48 0 16; 0 0 64] / 64;
|
||||
// >> A^22
|
||||
// ans =
|
||||
//
|
||||
// 0.15839 0.03738 0.80424
|
||||
// 0.12815 0.03024 0.84161
|
||||
// 0.00000 0.00000 1.00000
|
||||
//
|
||||
// ---which is about 80.4%. So any individual attempt is likely to fail,
|
||||
// but after five attempts the probability of total failure is only
|
||||
// 33.6%, and it drops off exponentially from there.
|
||||
const _MAX_ATTEMPTS = 1024;
|
||||
|
||||
/**
|
||||
* Generate a uniformly random clean ID.
|
||||
*/
|
||||
export function random(): Uuid {
|
||||
for (let i = 0; i < _MAX_ATTEMPTS; i++) {
|
||||
const result: string = randomUuidUnchecked();
|
||||
if (isClean(result)) {
|
||||
// Because we use rejection sampling, this is uniformly random
|
||||
// among clean IDs.
|
||||
return (result: Uuid);
|
||||
}
|
||||
}
|
||||
// This is vanishingly unlikely (p ~= 10^-97). Something is wrong.
|
||||
// istanbul ignore next
|
||||
throw new Error(
|
||||
`failed to generate clean UUID after ${_MAX_ATTEMPTS} attempts`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a serialized UUID. This is the left inverse of the trivial
|
||||
* injection from `Uuid` to `string`, and throws on invalid input.
|
||||
*/
|
||||
export function fromString(s: string): Uuid {
|
||||
if (s.endsWith("=")) {
|
||||
throw new Error("expected unpadded string: " + JSON.stringify(s));
|
||||
}
|
||||
if (s.length !== 22) {
|
||||
throw new Error("expected length-22 string: " + JSON.stringify(s));
|
||||
}
|
||||
if (!isClean(s)) {
|
||||
throw new Error(
|
||||
"unclean UUID: " + JSON.stringify(s) + JSON.stringify(_RE_UNCLEAN.exec(s))
|
||||
);
|
||||
}
|
||||
let bytes;
|
||||
try {
|
||||
bytes = base64Decode(s);
|
||||
} catch (e) {
|
||||
throw new Error("invalid base64 string: " + JSON.stringify(s));
|
||||
}
|
||||
if (base64Encode(bytes) !== s + "==") {
|
||||
// e.g., "z" === atob("eg") === atob("eh")
|
||||
throw new Error("non-canonical base64 string: " + JSON.stringify(s));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a serialized UUID. This expects to parse a JSON string value
|
||||
* with the same semantics as `fromString`.
|
||||
*/
|
||||
export const parser: C.Parser<Uuid> = C.fmap(C.string, fromString);
|
84
src/util/uuid.test.js
Normal file
84
src/util/uuid.test.js
Normal file
@ -0,0 +1,84 @@
|
||||
// @flow
|
||||
|
||||
import {random, fromString, parser, type Uuid} from "./uuid";
|
||||
|
||||
describe("util/uuid", () => {
|
||||
describe("random", () => {
|
||||
it("always returns a 22-character string that passes UUID tests", () => {
|
||||
for (let i = 0; i < 16; i++) {
|
||||
const uuid = random();
|
||||
expect(uuid).toHaveLength(22);
|
||||
expect(fromString(uuid)).toEqual(uuid);
|
||||
}
|
||||
});
|
||||
});
|
||||
describe("fromString", () => {
|
||||
function fail(input, message) {
|
||||
expect(() => fromString(input)).toThrow(message);
|
||||
}
|
||||
it("rejects the empty UUID", () => {
|
||||
fail("", 'expected length-22 string: ""');
|
||||
});
|
||||
it("rejects short UUIDs", () => {
|
||||
fail("NjRiaXRzOig", 'expected length-22 string: "NjRiaXRzOig"');
|
||||
});
|
||||
it("rejects long UUIDs", () => {
|
||||
fail(
|
||||
"MTYwIGJpdHMgaXMgdG9vIG1hbnk",
|
||||
'expected length-22 string: "MTYwIGJpdHMgaXMgdG9vIG1hbnk"'
|
||||
);
|
||||
});
|
||||
it("rejects UUIDs with 1 padding token", () => {
|
||||
fail(
|
||||
"YW55ICI9IiBzaWduIGJhZA=",
|
||||
'expected unpadded string: "YW55ICI9IiBzaWduIGJhZA="'
|
||||
);
|
||||
});
|
||||
it("rejects UUIDs with 2 padding tokens", () => {
|
||||
fail(
|
||||
"MTI4Yml0c2J1dHBhZGRlZA==",
|
||||
'expected unpadded string: "MTI4Yml0c2J1dHBhZGRlZA=="'
|
||||
);
|
||||
});
|
||||
it("rejects UUIDs with 3 padding tokens", () => {
|
||||
fail(
|
||||
"JiAzIGlzIHJpZ2h0IG91dA===",
|
||||
'expected unpadded string: "JiAzIGlzIHJpZ2h0IG91dA==="'
|
||||
);
|
||||
});
|
||||
it("rejects UUIDs with non-alphanumeric URL-safe characters", () => {
|
||||
fail("Y3J1ZWwgdHdpc3Qgb2Yg-A", 'unclean UUID: "Y3J1ZWwgdHdpc3Qgb2Yg-A"');
|
||||
});
|
||||
it("rejects strings that aren't valid base64 at all", () => {
|
||||
fail(
|
||||
"Extr@Symbol$NotGood???",
|
||||
'invalid base64 string: "Extr@Symbol$NotGood???"'
|
||||
);
|
||||
});
|
||||
it("rejects base64 strings with non-canonical final token", () => {
|
||||
fail(
|
||||
"enp6enp6enp6enp6enp6eh",
|
||||
'non-canonical base64 string: "enp6enp6enp6enp6enp6eh"'
|
||||
);
|
||||
});
|
||||
it("accepts a UUID that passes all the tests", () => {
|
||||
const input: string = "YVZhbGlkVXVpZEF0TGFzdA";
|
||||
const output: Uuid = fromString(input);
|
||||
expect(output).toEqual(input);
|
||||
});
|
||||
});
|
||||
describe("parser", () => {
|
||||
it("accepts a valid UUID", () => {
|
||||
expect(parser.parse("YVZhbGlkVXVpZEF0TGFzdA")).toEqual({
|
||||
ok: true,
|
||||
value: "YVZhbGlkVXVpZEF0TGFzdA",
|
||||
});
|
||||
});
|
||||
it("rejects an invalid UUID", () => {
|
||||
expect(parser.parse("hmm")).toEqual({
|
||||
ok: false,
|
||||
err: expect.stringContaining("length-22"),
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
173
yarn.lock
173
yarn.lock
@ -1100,6 +1100,34 @@
|
||||
"@nodelib/fs.scandir" "2.1.3"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@peculiar/asn1-schema@^2.0.1", "@peculiar/asn1-schema@^2.0.3":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.0.5.tgz#ba6c5a107eec16a23804d0176a3595837b53c0e9"
|
||||
integrity sha512-VIKJjsgMkv+yyWx3C+D4xo6/NeCg0XFBgNlavtkxELijV+aKAq53du5KkOJbeZtm1nn9CinQKny2PqL8zCfpeA==
|
||||
dependencies:
|
||||
"@types/asn1js" "^0.0.1"
|
||||
asn1js "^2.0.26"
|
||||
pvtsutils "^1.0.10"
|
||||
tslib "^1.11.1"
|
||||
|
||||
"@peculiar/json-schema@^1.1.10":
|
||||
version "1.1.10"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.10.tgz#d772b4323c9a4b5352b5ad52dc821a07b0db4877"
|
||||
integrity sha512-kbpnG9CkF1y6wwGkW7YtSA+yYK4X5uk4rAwsd1hxiaYE3Hkw2EsGlbGh/COkMLyFf+Fe830BoFiMSB3QnC/ItA==
|
||||
dependencies:
|
||||
tslib "^1.11.1"
|
||||
|
||||
"@peculiar/webcrypto@^1.0.22":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.1.1.tgz#4c7498e4861878e299ef058bce1208a4d063d0ff"
|
||||
integrity sha512-Bu2XgOvzirnLcojZYs4KQ8hOLf2ETpa0NL6btQt5NgsAwctI6yVkzgYP+EcG7Mm579RBP+V0LM5rXyMlTVx23A==
|
||||
dependencies:
|
||||
"@peculiar/asn1-schema" "^2.0.3"
|
||||
"@peculiar/json-schema" "^1.1.10"
|
||||
pvtsutils "^1.0.10"
|
||||
tslib "^1.11.2"
|
||||
webcrypto-core "^1.1.0"
|
||||
|
||||
"@sinonjs/commons@^1.7.0":
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.7.2.tgz#505f55c74e0272b43f6c52d81946bed7058fc0e2"
|
||||
@ -1114,6 +1142,13 @@
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@types/asn1js@^0.0.1":
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/asn1js/-/asn1js-0.0.1.tgz#ef8b9f9708cb1632a1c3a9cd27717caabe793bc2"
|
||||
integrity sha1-74uflwjLFjKhw6nNJ3F8qr55O8I=
|
||||
dependencies:
|
||||
"@types/pvutils" "*"
|
||||
|
||||
"@types/babel__core@^7.1.7":
|
||||
version "7.1.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.7.tgz#1dacad8840364a57c98d0dd4855c6dd3752c6b89"
|
||||
@ -1213,6 +1248,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.0.tgz#dc85454b953178cc6043df5208b9e949b54a3bc4"
|
||||
integrity sha512-/rM+sWiuOZ5dvuVzV37sUuklsbg+JPOP8d+nNFlo2ZtfpzPiPvh1/gc8liWOLBqe+sR+ZM7guPaIcTt6UZTo7Q==
|
||||
|
||||
"@types/pvutils@*":
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/pvutils/-/pvutils-0.0.2.tgz#e21684962cfa58ac920fd576d90556032dc86009"
|
||||
integrity sha512-CgQAm7pjyeF3Gnv78ty4RBVIfluB+Td+2DR8iPaU0prF18pkzptHHP+DoKPfpsJYknKsVZyVsJEu5AuGgAqQ5w==
|
||||
|
||||
"@types/stack-utils@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
|
||||
@ -1230,6 +1270,22 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@unimodules/core@*":
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@unimodules/core/-/core-5.3.0.tgz#c425e59b1f9c1e2c91b235b6192e5f622a47d833"
|
||||
integrity sha512-uGpkYE2zI0F1LTv+p6drzCHAZo8UFITxedHUH6pjWQBHdpTtae5cU7l3F/CzQ4WYU6SWhkzaB90/Ydf3DNTuLw==
|
||||
dependencies:
|
||||
compare-versions "^3.4.0"
|
||||
|
||||
"@unimodules/react-native-adapter@*":
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@unimodules/react-native-adapter/-/react-native-adapter-5.4.0.tgz#6639a2b6df74806bc886933c99bb18408e54f7f0"
|
||||
integrity sha512-2c3hDWzfBAyDWNCkBziyXphmxRZvZ5J8oSMLRDohvj6DnQiHvnlgr/A4oberkjPSEve5fN4GA+eybcJrec08AA==
|
||||
dependencies:
|
||||
invariant "^2.2.4"
|
||||
lodash "^4.5.0"
|
||||
prop-types "^15.6.1"
|
||||
|
||||
"@webassemblyjs/ast@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
|
||||
@ -1684,6 +1740,11 @@ asap@^2.0.3, asap@~2.0.3, asap@~2.0.6:
|
||||
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
|
||||
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
|
||||
|
||||
asmcrypto.js@^0.22.0:
|
||||
version "0.22.0"
|
||||
resolved "https://registry.yarnpkg.com/asmcrypto.js/-/asmcrypto.js-0.22.0.tgz#38fc1440884d802c7bd37d1d23c2b26a5cd5d2d2"
|
||||
integrity sha512-usgMoyXjMbx/ZPdzTSXExhMPur2FTdz/Vo5PVx2gIaBcdAAJNOFlsdgqveM8Cff7W0v+xrf9BwjOV26JSAF9qA==
|
||||
|
||||
asn1.js@^4.0.0:
|
||||
version "4.10.1"
|
||||
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
|
||||
@ -1700,6 +1761,13 @@ asn1@~0.2.3:
|
||||
dependencies:
|
||||
safer-buffer "~2.1.0"
|
||||
|
||||
asn1js@^2.0.26:
|
||||
version "2.0.26"
|
||||
resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-2.0.26.tgz#0a6d435000f556a96c6012969d9704d981b71251"
|
||||
integrity sha512-yG89F0j9B4B0MKIcFyWWxnpZPLaNTjCj4tkE3fjbAoo0qmpGw0PYYqSbX/4ebnd9Icn8ZgK4K1fvDyEtW1JYtQ==
|
||||
dependencies:
|
||||
pvutils latest
|
||||
|
||||
assert-plus@1.0.0, assert-plus@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
|
||||
@ -1775,6 +1843,20 @@ axobject-query@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.1.2.tgz#2bdffc0371e643e5f03ba99065d5179b9ca79799"
|
||||
integrity sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ==
|
||||
|
||||
b64-lite@^1.3.1, b64-lite@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/b64-lite/-/b64-lite-1.4.0.tgz#e62442de11f1f21c60e38b74f111ac0242283d3d"
|
||||
integrity sha512-aHe97M7DXt+dkpa8fHlCcm1CnskAHrJqEfMI0KN7dwqlzml/aUe1AGt6lk51HzrSfVD67xOso84sOpr+0wIe2w==
|
||||
dependencies:
|
||||
base-64 "^0.1.0"
|
||||
|
||||
b64u-lite@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/b64u-lite/-/b64u-lite-1.1.0.tgz#a581b7df94cbd4bed7cbb19feae816654f0b1bf0"
|
||||
integrity sha512-929qWGDVCRph7gQVTC6koHqQIpF4vtVaSbwLltFQo44B1bYUquALswZdBKFfrJCPEnsCOvWkJsPdQYZ/Ukhw8A==
|
||||
dependencies:
|
||||
b64-lite "^1.4.0"
|
||||
|
||||
babel-code-frame@6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
|
||||
@ -1887,7 +1969,12 @@ balanced-match@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
base64-js@^1.0.2:
|
||||
base-64@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb"
|
||||
integrity sha1-eAqZyE59YAJgNhURxId2E78k9rs=
|
||||
|
||||
base64-js@*, base64-js@^1.0.2, base64-js@^1.3.0:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
|
||||
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
|
||||
@ -2532,6 +2619,11 @@ commonmark@^0.29.1:
|
||||
minimist "~1.2.0"
|
||||
string.prototype.repeat "^0.2.0"
|
||||
|
||||
compare-versions@^3.4.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62"
|
||||
integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==
|
||||
|
||||
component-emitter@^1.2.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
||||
@ -3875,6 +3967,13 @@ expect@^26.0.1:
|
||||
jest-message-util "^26.0.1"
|
||||
jest-regex-util "^26.0.0"
|
||||
|
||||
expo-random@*:
|
||||
version "8.2.1"
|
||||
resolved "https://registry.yarnpkg.com/expo-random/-/expo-random-8.2.1.tgz#dafb19b3dcc8c7a74939c5c33a769ff5371ab289"
|
||||
integrity sha512-5qcR00xMONKXy6QyNWOcslD0Ka6FYE+5wDLxeG6sZYakBMZ+7CZqXIHU56z2oY3ZjrA6sqy5mJcj1naNOweHMw==
|
||||
dependencies:
|
||||
base64-js "^1.3.0"
|
||||
|
||||
express@^4.17.1:
|
||||
version "4.17.1"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
|
||||
@ -5315,6 +5414,24 @@ isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1:
|
||||
node-fetch "^1.0.1"
|
||||
whatwg-fetch ">=0.10.0"
|
||||
|
||||
isomorphic-webcrypto@^2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/isomorphic-webcrypto/-/isomorphic-webcrypto-2.3.6.tgz#2bd183557186268ff0898affaef2b21f29e64db7"
|
||||
integrity sha512-d1prB3b0UMWOao5DK3+O2Dr5ZJCakzB5Q+2kCWNkNuM9ln7VB8TSw2SwUjbnErzg7cgsYja+VPQaeBtXEojpew==
|
||||
dependencies:
|
||||
"@peculiar/webcrypto" "^1.0.22"
|
||||
asmcrypto.js "^0.22.0"
|
||||
b64-lite "^1.3.1"
|
||||
b64u-lite "^1.0.1"
|
||||
msrcrypto "^1.5.6"
|
||||
str2buf "^1.3.0"
|
||||
webcrypto-shim "^0.1.4"
|
||||
optionalDependencies:
|
||||
"@unimodules/core" "*"
|
||||
"@unimodules/react-native-adapter" "*"
|
||||
expo-random "*"
|
||||
react-native-securerandom "^0.1.1"
|
||||
|
||||
isstream@~0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
@ -6142,7 +6259,7 @@ lodash.throttle@^4.1.1:
|
||||
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||
|
||||
"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5, lodash@^4.3.0, lodash@~4.17.4:
|
||||
"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@~4.17.4:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
@ -6485,6 +6602,11 @@ ms@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
msrcrypto@^1.5.6:
|
||||
version "1.5.8"
|
||||
resolved "https://registry.yarnpkg.com/msrcrypto/-/msrcrypto-1.5.8.tgz#be419be4945bf134d8af52e9d43be7fa261f4a1c"
|
||||
integrity sha512-ujZ0TRuozHKKm6eGbKHfXef7f+esIhEckmThVnz7RNyiOJd7a6MXj2JGBoL9cnPDW+JMG16MoTUh5X+XXjI66Q==
|
||||
|
||||
multicast-dns-service-types@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"
|
||||
@ -7414,7 +7536,7 @@ prop-types-exact@^1.2.0:
|
||||
object.assign "^4.1.0"
|
||||
reflect.ownkeys "^0.2.0"
|
||||
|
||||
prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
@ -7498,6 +7620,18 @@ punycode@^2.1.0, punycode@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
pvtsutils@^1.0.10:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.0.10.tgz#157d0fcb853f570d32e0f8788179f3057eacdf38"
|
||||
integrity sha512-8ZKQcxnZKTn+fpDh7wL4yKax5fdl3UJzT8Jv49djZpB/dzPxacyN1Sez90b6YLdOmvIr9vaySJ5gw4aUA1EdSw==
|
||||
dependencies:
|
||||
tslib "^1.10.0"
|
||||
|
||||
pvutils@latest:
|
||||
version "1.0.17"
|
||||
resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.0.17.tgz#ade3c74dfe7178944fe44806626bd2e249d996bf"
|
||||
integrity sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==
|
||||
|
||||
qs@6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||
@ -7671,6 +7805,13 @@ react-markdown@^4.3.1:
|
||||
unist-util-visit "^1.3.0"
|
||||
xtend "^4.0.1"
|
||||
|
||||
react-native-securerandom@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-native-securerandom/-/react-native-securerandom-0.1.1.tgz#f130623a412c338b0afadedbc204c5cbb8bf2070"
|
||||
integrity sha1-8TBiOkEsM4sK+t7bwgTFy7i/IHA=
|
||||
dependencies:
|
||||
base64-js "*"
|
||||
|
||||
react-resize-detector@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-2.3.0.tgz#57bad1ae26a28a62a2ddb678ba6ffdf8fa2b599c"
|
||||
@ -8726,6 +8867,11 @@ stealthy-require@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
|
||||
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
|
||||
|
||||
str2buf@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/str2buf/-/str2buf-1.3.0.tgz#a4172afff4310e67235178e738a2dbb573abead0"
|
||||
integrity sha512-xIBmHIUHYZDP4HyoXGHYNVmxlXLXDrtFHYT0eV6IOdEj3VO9ccaF1Ejl9Oq8iFjITllpT8FhaXb4KsNmw+3EuA==
|
||||
|
||||
stream-browserify@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
|
||||
@ -9218,6 +9364,11 @@ trough@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406"
|
||||
integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==
|
||||
|
||||
tslib@^1.10.0, tslib@^1.11.1, tslib@^1.11.2:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
|
||||
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
|
||||
|
||||
tslib@^1.9.0:
|
||||
version "1.11.2"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.2.tgz#9c79d83272c9a7aaf166f73915c9667ecdde3cc9"
|
||||
@ -9616,6 +9767,22 @@ wbuf@^1.1.0, wbuf@^1.7.3:
|
||||
dependencies:
|
||||
minimalistic-assert "^1.0.0"
|
||||
|
||||
webcrypto-core@^1.1.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.1.2.tgz#c522a9e5596688f2b6bb19e2d336f68efa8bdd57"
|
||||
integrity sha512-LxM/dTcXr/ZnwwKLox0tGEOIqvP7KIJ4Hk/fFPX20tr1EgqTmpEFZinmu4FzoGVbs6e4jI1priQKCDrOBD3L6w==
|
||||
dependencies:
|
||||
"@peculiar/asn1-schema" "^2.0.1"
|
||||
"@peculiar/json-schema" "^1.1.10"
|
||||
asn1js "^2.0.26"
|
||||
pvtsutils "^1.0.10"
|
||||
tslib "^1.11.2"
|
||||
|
||||
webcrypto-shim@^0.1.4:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/webcrypto-shim/-/webcrypto-shim-0.1.5.tgz#13e34a010ccc544edecfe8a2642204502841bcf0"
|
||||
integrity sha512-mE+E00gulvbLjHaAwl0kph60oOLQRsKyivEFgV9DMM/3Y05F1vZvGq12hAcNzHRnYxyEOABBT/XMtwGSg5xA7A==
|
||||
|
||||
webidl-conversions@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
|
||||
|
Loading…
x
Reference in New Issue
Block a user