Add memoization to expensive pure functions because the library involves a lot of computation under the hood.master
@@ -20,7 +20,9 @@ | |||||
"build-storybook": "build-storybook" | "build-storybook": "build-storybook" | ||||
}, | }, | ||||
"dependencies": { | "dependencies": { | ||||
"styled-components": "^5.1.1" | |||||
"mem": "^6.1.0", | |||||
"styled-components": "^5.1.1", | |||||
"typescript-memoize": "^1.0.0-alpha.3" | |||||
}, | }, | ||||
"peerDependencies": { | "peerDependencies": { | ||||
"react": ">=16" | "react": ">=16" | ||||
@@ -1,9 +1,10 @@ | |||||
import * as React from 'react' | import * as React from 'react' | ||||
import * as PropTypes from 'prop-types' | import * as PropTypes from 'prop-types' | ||||
import styled from 'styled-components' | import styled from 'styled-components' | ||||
import isNaturalKey from '../../services/isNaturalKey' | |||||
import getKeyWidth from '../../services/getKeyWidth' | |||||
import getKeyLeft from '../../services/getKeyLeft' | |||||
import mem from 'mem' | |||||
import isNaturalKeyUnmemoized from '../../services/isNaturalKey' | |||||
import getKeyWidthUnmemoized from '../../services/getKeyWidth' | |||||
import getKeyLeftUnmemoized from '../../services/getKeyLeft' | |||||
import generateKeys from '../../services/generateKeys' | import generateKeys from '../../services/generateKeys' | ||||
import * as DefaultAccidentalKey from '../AccidentalKey/AccidentalKey' | import * as DefaultAccidentalKey from '../AccidentalKey/AccidentalKey' | ||||
import * as DefaultNaturalKey from '../NaturalKey/NaturalKey' | import * as DefaultNaturalKey from '../NaturalKey/NaturalKey' | ||||
@@ -19,6 +20,10 @@ const Key = styled('div')({ | |||||
top: 0, | top: 0, | ||||
}) | }) | ||||
const getKeyWidth = mem(getKeyWidthUnmemoized, { cacheKey: (args) => args.join(':') }) | |||||
const getKeyLeft = mem(getKeyLeftUnmemoized, { cacheKey: (args) => args.join(':') }) | |||||
const isNaturalKey = mem(isNaturalKeyUnmemoized) | |||||
export const propTypes = { | export const propTypes = { | ||||
/** | /** | ||||
* MIDI note of the first key. | * MIDI note of the first key. | ||||
@@ -20,7 +20,7 @@ | |||||
*/ | */ | ||||
// export default [ | |||||
// export const KEY_OFFSETS = [ | |||||
// 0, // C | // 0, // C | ||||
// 3 / 7 / 5, // C# | // 3 / 7 / 5, // C# | ||||
// 1 / 7, // D | // 1 / 7, // D | ||||
@@ -36,7 +36,7 @@ | |||||
// ] | // ] | ||||
// http://datagenetics.com/blog/may32016/index.html | // http://datagenetics.com/blog/may32016/index.html | ||||
export default [ | |||||
export const KEY_OFFSETS = [ | |||||
0, // C | 0, // C | ||||
525 / 5880, // C# | 525 / 5880, // C# | ||||
1 / 7, // D | 1 / 7, // D | ||||
@@ -50,3 +50,5 @@ export default [ | |||||
(525 + 490 * 7 + 525 + 455) / 5880, // A# | (525 + 490 * 7 + 525 + 455) / 5880, // A# | ||||
6 / 7, // B | 6 / 7, // B | ||||
] | ] | ||||
export const ACCIDENTAL_KEY_TO_NATURAL_KEY_WIDTH_RATIO = 13 / 23 |
@@ -3,8 +3,8 @@ interface GenerateKeys { | |||||
} | } | ||||
const generateKeys: GenerateKeys = (startKey, endKey) => | const generateKeys: GenerateKeys = (startKey, endKey) => | ||||
Array(endKey! - startKey! + 1) | |||||
Array(endKey - startKey + 1) | |||||
.fill(0) | .fill(0) | ||||
.map((_, i) => startKey! + i) | |||||
.map((_, i) => startKey + i) | |||||
export default generateKeys | export default generateKeys |
@@ -0,0 +1,28 @@ | |||||
import mem from 'mem' | |||||
import generateKeys from './generateKeys' | |||||
import groupKeysIntoOctaves from './groupKeysIntoOctaves' | |||||
import getOctaveCompletenessUnmemoized from './getOctaveCompleteness' | |||||
const getOctaveCompleteness = mem(getOctaveCompletenessUnmemoized) | |||||
interface GetFractionalOctaveCount { | |||||
(startKey: number, endKey: number): number | |||||
} | |||||
const getFractionalOctaveCount: GetFractionalOctaveCount = (startKey, endKey) => { | |||||
const dummyKeys = generateKeys(startKey, endKey) | |||||
const keysGroupedIntoOctaves = groupKeysIntoOctaves(dummyKeys) | |||||
const octaveCompleteness = Object.entries(keysGroupedIntoOctaves) | |||||
.map<number[]>(([octave, keys]) => [(octave as unknown) as number, keys[0], keys.slice(-1)[0]]) | |||||
.reduce<Record<number, number>>( | |||||
(theOctaveCompleteness, [octave, firstKey, lastKey]) => ({ | |||||
...theOctaveCompleteness, | |||||
[octave]: getOctaveCompleteness(firstKey, lastKey), | |||||
}), | |||||
{}, | |||||
) | |||||
return Object.values(octaveCompleteness).reduce((a, b) => a + b, 0) | |||||
} | |||||
export default getFractionalOctaveCount |
@@ -1,8 +1,13 @@ | |||||
import getKeyXOffset from './getKeyXOffset' | |||||
import getOctaveCount from './getOctaveCount' | |||||
import generateKeys from './generateKeys' | |||||
import groupKeysIntoOctaves from './groupKeysIntoOctaves' | |||||
import getOctaveCompleteness from './getOctaveCompleteness' | |||||
import mem from 'mem' | |||||
import getKeyXOffsetUnmemoized from './getKeyXOffset' | |||||
import getOctaveCountUnmemoized from './getOctaveCount' | |||||
import getFractionalOctaveCountUnmemoized from './getFractionalOctaveCount' | |||||
import getKeyOctaveUnmemoized from './getKeyOctave' | |||||
const getKeyXOffset = mem(getKeyXOffsetUnmemoized) | |||||
const getOctaveCount = mem(getOctaveCountUnmemoized, { cacheKey: (args) => args.join(':') }) | |||||
const getFractionalOctaveCount = mem(getFractionalOctaveCountUnmemoized, { cacheKey: (args) => args.join(':') }) | |||||
const getKeyOctave = mem(getKeyOctaveUnmemoized) | |||||
interface GetKeyLeft { | interface GetKeyLeft { | ||||
(k: number): number | (k: number): number | ||||
@@ -13,23 +18,10 @@ interface GetKeyLeftDecorator { | |||||
} | } | ||||
const getKeyLeftDecorator: GetKeyLeftDecorator = (startKey, endKey): GetKeyLeft => (k) => { | const getKeyLeftDecorator: GetKeyLeftDecorator = (startKey, endKey): GetKeyLeft => (k) => { | ||||
const dummyKeys = generateKeys(startKey, endKey) | |||||
const keysGroupedIntoOctaves = groupKeysIntoOctaves(dummyKeys) | |||||
const octaveCompleteness = Object.entries(keysGroupedIntoOctaves) | |||||
.map<number[]>(([octave, keys]) => [(octave as unknown) as number, keys[0], keys.slice(-1)[0]]) | |||||
.reduce<Record<number, number>>( | |||||
(theOctaveCompleteness, [octave, firstKey, lastKey]) => ({ | |||||
...theOctaveCompleteness, | |||||
[octave]: getOctaveCompleteness(firstKey, lastKey), | |||||
}), | |||||
{}, | |||||
) | |||||
const fractionalOctaveCount = Object.values(octaveCompleteness).reduce((a, b) => a + b, 0) | |||||
const fractionalOctaveCount = getFractionalOctaveCount(startKey, endKey) | |||||
const octaveCount = getOctaveCount(startKey, endKey) | const octaveCount = getOctaveCount(startKey, endKey) | ||||
const startOctave = Math.floor(startKey! / 12) | |||||
const octave = Math.floor(k / 12) | |||||
const startOctave = getKeyOctave(startKey) | |||||
const octave = getKeyOctave(k) | |||||
const octaveOffset = ((100 * octaveCount) / fractionalOctaveCount / octaveCount) * (octave - startOctave) | const octaveOffset = ((100 * octaveCount) / fractionalOctaveCount / octaveCount) * (octave - startOctave) | ||||
const theKeyOffset = octaveOffset + ((100 * octaveCount) / fractionalOctaveCount / octaveCount) * getKeyXOffset(k) | const theKeyOffset = octaveOffset + ((100 * octaveCount) / fractionalOctaveCount / octaveCount) * getKeyXOffset(k) | ||||
const firstKeyOffset = ((100 * octaveCount) / fractionalOctaveCount / octaveCount) * getKeyXOffset(startKey + 12) | const firstKeyOffset = ((100 * octaveCount) / fractionalOctaveCount / octaveCount) * getKeyXOffset(startKey + 12) | ||||
@@ -0,0 +1,7 @@ | |||||
interface GetKeyOctave { | |||||
(k: number): number | |||||
} | |||||
const getKeyOctave: GetKeyOctave = (k) => Math.floor(k / 12) | |||||
export default getKeyOctave |
@@ -1,8 +1,8 @@ | |||||
import isNaturalKey from './isNaturalKey' | |||||
import groupKeysIntoOctaves from './groupKeysIntoOctaves' | |||||
import getOctaveCompleteness from './getOctaveCompleteness' | |||||
import getOctaveCount from './getOctaveCount' | |||||
import generateKeys from './generateKeys' | |||||
import mem from 'mem' | |||||
import isNaturalKeyUnmemoized from './isNaturalKey' | |||||
import getOctaveCountUnmemoized from './getOctaveCount' | |||||
import getFractionalOctaveCountUnmemoized from './getFractionalOctaveCount' | |||||
import { ACCIDENTAL_KEY_TO_NATURAL_KEY_WIDTH_RATIO } from './constants' | |||||
interface GetKeyWidth { | interface GetKeyWidth { | ||||
(k: number): number | (k: number): number | ||||
@@ -12,25 +12,19 @@ interface GetKeyWidthDecorator { | |||||
(startKey: number, endKey: number): GetKeyWidth | (startKey: number, endKey: number): GetKeyWidth | ||||
} | } | ||||
const ACCIDENTAL_KEY_TO_NATURAL_KEY_WIDTH_RATIO = 13 / 23 | |||||
const isNaturalKey = mem(isNaturalKeyUnmemoized) | |||||
const getFractionalOctaveCount = mem(getFractionalOctaveCountUnmemoized, { cacheKey: (args) => args.join(':') }) | |||||
const getOctaveCount = mem(getOctaveCountUnmemoized, { cacheKey: (args) => args.join(':') }) | |||||
const getKeyWidthDecorator: GetKeyWidthDecorator = (startKey, endKey): GetKeyWidth => (k) => { | |||||
const dummyKeys = generateKeys(startKey, endKey) | |||||
const keysGroupedIntoOctaves = groupKeysIntoOctaves(dummyKeys) | |||||
const octaveCompleteness = Object.entries(keysGroupedIntoOctaves) | |||||
.map<number[]>(([octave, keys]) => [(octave as unknown) as number, keys[0], keys.slice(-1)[0]]) | |||||
.reduce<Record<number, number>>( | |||||
(theOctaveCompleteness, [octave, firstKey, lastKey]) => ({ | |||||
...theOctaveCompleteness, | |||||
[octave]: getOctaveCompleteness(firstKey, lastKey), | |||||
}), | |||||
{}, | |||||
) | |||||
const getKeyWidthDecorator: GetKeyWidthDecorator = (startKey, endKey) => { | |||||
const getKeyWidth: GetKeyWidth = (k) => { | |||||
const fractionalOctaveCount = getFractionalOctaveCount(startKey, endKey) | |||||
const octaveCount = getOctaveCount(startKey, endKey) | |||||
const naturalKeyWidth = (100 * (octaveCount / fractionalOctaveCount)) / (octaveCount * 7) | |||||
return isNaturalKey(k) ? naturalKeyWidth : naturalKeyWidth * ACCIDENTAL_KEY_TO_NATURAL_KEY_WIDTH_RATIO | |||||
} | |||||
const fractionalOctaveCount = Object.values(octaveCompleteness).reduce((a, b) => a + b, 0) | |||||
const octaveCount = getOctaveCount(startKey, endKey) | |||||
const naturalKeyWidth = (100 * (octaveCount / fractionalOctaveCount)) / (octaveCount * 7) | |||||
return isNaturalKey(k) ? naturalKeyWidth : naturalKeyWidth * ACCIDENTAL_KEY_TO_NATURAL_KEY_WIDTH_RATIO | |||||
return mem(getKeyWidth) | |||||
} | } | ||||
export default getKeyWidthDecorator | export default getKeyWidthDecorator |
@@ -1,5 +1,11 @@ | |||||
import KEY_OFFSETS from './constants/keyOffsets' | |||||
import { KEY_OFFSETS } from './constants' | |||||
export default (k: number): number => { | |||||
interface GetKeyXOffset { | |||||
(k: number): number | |||||
} | |||||
const getKeyXOffset: GetKeyXOffset = (k) => { | |||||
return KEY_OFFSETS[k % 12] | return KEY_OFFSETS[k % 12] | ||||
} | } | ||||
export default getKeyXOffset |
@@ -1,10 +1,20 @@ | |||||
import getKeyXOffset from './getKeyXOffset' | |||||
import isNaturalKey from './isNaturalKey' | |||||
import mem from 'mem' | |||||
import getKeyXOffsetUnmemoized from './getKeyXOffset' | |||||
import isNaturalKeyUnmemoized from './isNaturalKey' | |||||
const getKeyXOffset = mem(getKeyXOffsetUnmemoized) | |||||
const isNaturalKey = mem(isNaturalKeyUnmemoized) | |||||
interface GetOctaveCompleteness { | |||||
(firstKey: number, lastKey: number): number | |||||
} | |||||
// expect firstKey and lastKey within the same octave | // expect firstKey and lastKey within the same octave | ||||
export default (firstKey: number, lastKey: number) => | |||||
const getOctaveCompleteness: GetOctaveCompleteness = (firstKey, lastKey) => | |||||
// see if there are missing higher notes | // see if there are missing higher notes | ||||
getKeyXOffset(lastKey) + | getKeyXOffset(lastKey) + | ||||
(isNaturalKey(lastKey) ? 1 / 7 : ((1 / 7) * 18) / 36) - | (isNaturalKey(lastKey) ? 1 / 7 : ((1 / 7) * 18) / 36) - | ||||
// see if there are missing lower notes | // see if there are missing lower notes | ||||
getKeyXOffset(firstKey) | getKeyXOffset(firstKey) | ||||
export default getOctaveCompleteness |
@@ -1,11 +1,12 @@ | |||||
import mem from 'mem' | |||||
import getKeyOctaveUnmemoized from './getKeyOctave' | |||||
const getKeyOctave = mem(getKeyOctaveUnmemoized) | |||||
interface GetOctaveCount { | interface GetOctaveCount { | ||||
(startKey: number, endKey: number): number | (startKey: number, endKey: number): number | ||||
} | } | ||||
const getOctaveCount: GetOctaveCount = (startKey, endKey) => { | |||||
const startOctave = Math.floor(startKey / 12) | |||||
const endOctave = Math.floor(endKey / 12) | |||||
return endOctave - startOctave + 1 | |||||
} | |||||
const getOctaveCount: GetOctaveCount = (startKey, endKey) => getKeyOctave(endKey) - getKeyOctave(startKey) + 1 | |||||
export default getOctaveCount | export default getOctaveCount |
@@ -1,4 +1,8 @@ | |||||
export default (dummyKeys: number[]): Record<number, number[]> => | |||||
interface GroupKeysIntoOctaves { | |||||
(dummyKeys: number[]): Record<number, number[]> | |||||
} | |||||
const groupKeysIntoOctaves: GroupKeysIntoOctaves = (dummyKeys) => | |||||
dummyKeys | dummyKeys | ||||
.map((k) => [k, Math.floor(k / 12)]) | .map((k) => [k, Math.floor(k / 12)]) | ||||
.reduce<Record<number, number[]>>( | .reduce<Record<number, number[]>>( | ||||
@@ -8,3 +12,5 @@ export default (dummyKeys: number[]): Record<number, number[]> => | |||||
}), | }), | ||||
{}, | {}, | ||||
) | ) | ||||
export default groupKeysIntoOctaves |
@@ -1,6 +1,10 @@ | |||||
const NATURAL_KEYS = [0, 2, 4, 5, 7, 9, 11] | const NATURAL_KEYS = [0, 2, 4, 5, 7, 9, 11] | ||||
export default (k: number): boolean => { | |||||
interface IsNaturalKey { | |||||
(k: number): boolean | |||||
} | |||||
const isNaturalKey: IsNaturalKey = (k: number): boolean => { | |||||
const type = typeof (k as unknown) | const type = typeof (k as unknown) | ||||
if ((type as string) !== 'number') { | if ((type as string) !== 'number') { | ||||
throw TypeError(`Invalid value type passed to isNaturalKey, expected 'number', got ${type}.`) | throw TypeError(`Invalid value type passed to isNaturalKey, expected 'number', got ${type}.`) | ||||
@@ -13,3 +17,5 @@ export default (k: number): boolean => { | |||||
} | } | ||||
return NATURAL_KEYS.includes(Math.floor(k) % 12) | return NATURAL_KEYS.includes(Math.floor(k) % 12) | ||||
} | } | ||||
export default isNaturalKey |
@@ -4249,6 +4249,11 @@ core-js-pure@^3.0.0, core-js-pure@^3.0.1: | |||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" | resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" | ||||
integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== | integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== | ||||
core-js@2.4.1: | |||||
version "2.4.1" | |||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" | |||||
integrity sha1-TekR5mew6ukSTjQlS1OupvxhjT4= | |||||
core-js@^1.0.0: | core-js@^1.0.0: | ||||
version "1.2.7" | version "1.2.7" | ||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" | resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" | ||||
@@ -8027,6 +8032,13 @@ makeerror@1.0.x: | |||||
dependencies: | dependencies: | ||||
tmpl "1.0.x" | tmpl "1.0.x" | ||||
map-age-cleaner@^0.1.3: | |||||
version "0.1.3" | |||||
resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" | |||||
integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== | |||||
dependencies: | |||||
p-defer "^1.0.0" | |||||
map-cache@^0.2.2: | map-cache@^0.2.2: | ||||
version "0.2.2" | version "0.2.2" | ||||
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" | resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" | ||||
@@ -8143,6 +8155,14 @@ media-typer@0.3.0: | |||||
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" | ||||
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= | integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= | ||||
mem@^6.1.0: | |||||
version "6.1.0" | |||||
resolved "https://registry.yarnpkg.com/mem/-/mem-6.1.0.tgz#846eca0bd4708a8f04b9c3f3cd769e194ae63c5c" | |||||
integrity sha512-RlbnLQgRHk5lwqTtpEkBTQ2ll/CG/iB+J4Hy2Wh97PjgZgXgWJWrFF+XXujh3UUVLvR4OOTgZzcWMMwnehlEUg== | |||||
dependencies: | |||||
map-age-cleaner "^0.1.3" | |||||
mimic-fn "^3.0.0" | |||||
memoizerific@^1.11.3: | memoizerific@^1.11.3: | ||||
version "1.11.3" | version "1.11.3" | ||||
resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" | resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" | ||||
@@ -8267,6 +8287,11 @@ mimic-fn@^2.1.0: | |||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" | ||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== | ||||
mimic-fn@^3.0.0: | |||||
version "3.1.0" | |||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" | |||||
integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== | |||||
min-document@^2.19.0: | min-document@^2.19.0: | ||||
version "2.19.0" | version "2.19.0" | ||||
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" | resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" | ||||
@@ -8832,6 +8857,11 @@ os-tmpdir@~1.0.2: | |||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" | ||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= | integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= | ||||
p-defer@^1.0.0: | |||||
version "1.0.0" | |||||
resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" | |||||
integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= | |||||
p-each-series@^1.0.0: | p-each-series@^1.0.0: | ||||
version "1.0.0" | version "1.0.0" | ||||
resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" | resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" | ||||
@@ -11740,6 +11770,13 @@ typedarray@^0.0.6: | |||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" | ||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= | integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= | ||||
typescript-memoize@^1.0.0-alpha.3: | |||||
version "1.0.0-alpha.3" | |||||
resolved "https://registry.yarnpkg.com/typescript-memoize/-/typescript-memoize-1.0.0-alpha.3.tgz#699a5415f886694a8d6e2e5451bc28a39a6bc2f9" | |||||
integrity sha1-aZpUFfiGaUqNbi5UUbwoo5prwvk= | |||||
dependencies: | |||||
core-js "2.4.1" | |||||
typescript@^3.7.3, typescript@^3.9.7: | typescript@^3.7.3, typescript@^3.9.7: | ||||
version "3.9.7" | version "3.9.7" | ||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" | ||||