diff --git a/package.json b/package.json index 93f9d208..3b65d16b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "zeed", "type": "module", - "version": "0.13.13", + "version": "0.13.14", "description": "🌱 Simple foundation library", "author": { "name": "Dirk Holtwick", diff --git a/src/common/data/index.ts b/src/common/data/index.ts index 0c2644c8..6be9a49e 100644 --- a/src/common/data/index.ts +++ b/src/common/data/index.ts @@ -4,8 +4,8 @@ export * from './bin' export * from './camelcase' export * from './convert' export * from './datauri' -export * from './day' export * from './day-legacy' +export * from './day' export * from './decimal' export * from './deep' export * from './diff' @@ -21,7 +21,8 @@ export * from './regexp' export * from './rounding' export * from './sortable' export * from './sorted' +export * from './string-deburr' export * from './url' export * from './utils' +export * from './wordlist' export * from './xrx' -export * from './string-deburr' diff --git a/src/common/data/wordlist.spec.ts b/src/common/data/wordlist.spec.ts new file mode 100644 index 00000000..b9a8b522 --- /dev/null +++ b/src/common/data/wordlist.spec.ts @@ -0,0 +1,17 @@ +import { UInt8ArrayToWords } from "./wordlist" + +describe("wordlist.spec", () => { + it("should match", async () => { + const wordsOdd = 'aardvark absurd accrue acme adrift adult afflict ahead aimless Algol allow alone ammo ancient apple artist assume Athens atlas Aztec baboon backfield backward basalt beaming bedlamp beehive beeswax befriend Belfast berserk billiard bison blackjack blockade blowtorch bluebird bombast bookshelf brackish breadline breakup brickyard briefcase Burbank button buzzard cement chairlift chatter checkup chisel choking chopper Christmas clamshell classic classroom cleanup clockwork cobra commence concert cowbell crackdown cranky crowfoot crucial crumpled crusade cubic deadbolt deckhand dogsled dosage dragnet drainage dreadful drifter dropper drumbeat drunken Dupont dwelling eating edict egghead eightball endorse endow enlist erase escape exceed eyeglass eyetooth facial fallout flagpole flatfoot flytrap fracture fragile framework freedom frighten gazelle Geiger Glasgow glitter glucose goggles goldfish gremlin guidance hamlet highchair hockey hotdog indoors indulge inverse involve island Janus jawbone keyboard kickoff kiwi klaxon lockup merit minnow miser Mohawk mural music Neptune newborn nightbird obtuse offload oilfield optic orca payday peachy pheasant physique playhouse Pluto preclude prefer preshrunk printer profile prowler pupil puppy python quadrant quiver quota ragtime ratchet rebirth reform regain reindeer rematch repay retouch revenge reward rhythm ringbolt robust rocker ruffled sawdust scallion scenic scorecard Scotland seabird select sentence shadow showgirl skullcap skydive slingshot slothful slowdown snapline snapshot snowcap snowslide solo spaniel spearhead spellbind spheroid spigot spindle spoilage spyglass stagehand stagnate stairway standard stapler steamship stepchild sterling stockman stopwatch stormy sugar surmount suspense swelter tactics talon tapeworm tempest tiger tissue tonic tracker transit trauma treadmill Trojan trouble tumor tunnel tycoon umpire uncut unearth unwind uproot upset upshot vapor village virus Vulcan waffle wallet watchword wayside willow woodlark Zulu' + const wordsEven = 'adroitness adviser aggregate alkali almighty amulet amusement antenna applicant Apollo armistice article asteroid Atlantic atmosphere autopsy Babylon backwater barbecue belowground bifocals bodyguard borderline bottomless Bradbury Brazilian breakaway Burlington businessman butterfat Camelot candidate cannonball Capricorn caravan caretaker celebrate cellulose certify chambermaid Cherokee Chicago clergyman coherence combustion commando company component concurrent confidence conformist congregate consensus consulting corporate corrosion councilman crossover cumbersome customer Dakota decadence December decimal designing detector detergent determine dictator dinosaur direction disable disbelief disruptive distortion divisive document embezzle enchanting enrollment enterprise equation equipment escapade Eskimo everyday examine existence exodus fascinate filament finicky forever fortitude frequency gadgetry Galveston getaway glossary gossamer graduate gravity guitarist hamburger Hamilton handiwork hazardous headwaters hemisphere hesitate hideaway holiness hurricane hydraulic impartial impetus inception indigo inertia infancy inferno informant insincere insurgent integrate intention inventive Istanbul Jamaica Jupiter leprosy letterhead liberty maritime matchmaker maverick Medusa megaton microscope microwave midsummer millionaire miracle misnomer molasses molecule Montana monument mosquito narrative nebula newsletter Norwegian October Ohio onlooker opulent Orlando outfielder Pacific pandemic pandora paperweight paragon paragraph paramount passenger pedigree Pegasus penetrate perceptive performance pharmacy phonetic photograph pioneer pocketful politeness positive potato processor prophecy provincial proximate puberty publisher pyramid quantity racketeer rebellion recipe recover repellent replica reproduce resistor responsive retraction retrieval retrospect revenue revival revolver Sahara sandalwood sardonic Saturday savagery scavenger sensation sociable souvenir specialist speculate stethoscope stupendous supportive surrender suspicious sympathy tambourine telephone therapist tobacco tolerance tomorrow torpedo tradition travesty trombonist truncated typewriter ultimate undaunted underfoot unicorn unify universe unravel upcoming vacancy vagabond versatile vertigo Virginia visitor vocalist voyager warranty Waterloo whimsical Wichita Wilmington Wyoming yesteryear Yucatan' + + expect(wordsOdd.split(' ')).toHaveLength(256) + expect(wordsEven.split(' ')).toHaveLength(256) + + // console.log('const wordsOdd = ' + JSON.stringify(wordsOdd.split(' '))) + // console.log('const wordsEven = ' + JSON.stringify(wordsEven.split(' '))) + + expect(UInt8ArrayToWords(new Uint8Array([1,2,255,254]), '-', ' / ')).toMatchInlineSnapshot('"absurd-aggregate / Zulu-yesteryear"') + expect(UInt8ArrayToWords(new Uint8Array([1,2,88]), '-', ' / ')).toMatchInlineSnapshot('"absurd-aggregate / endorse"') + }) +}) \ No newline at end of file diff --git a/src/common/data/wordlist.ts b/src/common/data/wordlist.ts new file mode 100644 index 00000000..096c30d7 --- /dev/null +++ b/src/common/data/wordlist.ts @@ -0,0 +1,9 @@ +// PGP Word List from https://web.mit.edu/network/pgpfone/manual/index.html#PGP000062 +// See https://en.wikipedia.org/wiki/PGP_word_list + +const wordsOdd = ['aardvark', 'absurd', 'accrue', 'acme', 'adrift', 'adult', 'afflict', 'ahead', 'aimless', 'Algol', 'allow', 'alone', 'ammo', 'ancient', 'apple', 'artist', 'assume', 'Athens', 'atlas', 'Aztec', 'baboon', 'backfield', 'backward', 'basalt', 'beaming', 'bedlamp', 'beehive', 'beeswax', 'befriend', 'Belfast', 'berserk', 'billiard', 'bison', 'blackjack', 'blockade', 'blowtorch', 'bluebird', 'bombast', 'bookshelf', 'brackish', 'breadline', 'breakup', 'brickyard', 'briefcase', 'Burbank', 'button', 'buzzard', 'cement', 'chairlift', 'chatter', 'checkup', 'chisel', 'choking', 'chopper', 'Christmas', 'clamshell', 'classic', 'classroom', 'cleanup', 'clockwork', 'cobra', 'commence', 'concert', 'cowbell', 'crackdown', 'cranky', 'crowfoot', 'crucial', 'crumpled', 'crusade', 'cubic', 'deadbolt', 'deckhand', 'dogsled', 'dosage', 'dragnet', 'drainage', 'dreadful', 'drifter', 'dropper', 'drumbeat', 'drunken', 'Dupont', 'dwelling', 'eating', 'edict', 'egghead', 'eightball', 'endorse', 'endow', 'enlist', 'erase', 'escape', 'exceed', 'eyeglass', 'eyetooth', 'facial', 'fallout', 'flagpole', 'flatfoot', 'flytrap', 'fracture', 'fragile', 'framework', 'freedom', 'frighten', 'gazelle', 'Geiger', 'Glasgow', 'glitter', 'glucose', 'goggles', 'goldfish', 'gremlin', 'guidance', 'hamlet', 'highchair', 'hockey', 'hotdog', 'indoors', 'indulge', 'inverse', 'involve', 'island', 'Janus', 'jawbone', 'keyboard', 'kickoff', 'kiwi', 'klaxon', 'lockup', 'merit', 'minnow', 'miser', 'Mohawk', 'mural', 'music', 'Neptune', 'newborn', 'nightbird', 'obtuse', 'offload', 'oilfield', 'optic', 'orca', 'payday', 'peachy', 'pheasant', 'physique', 'playhouse', 'Pluto', 'preclude', 'prefer', 'preshrunk', 'printer', 'profile', 'prowler', 'pupil', 'puppy', 'python', 'quadrant', 'quiver', 'quota', 'ragtime', 'ratchet', 'rebirth', 'reform', 'regain', 'reindeer', 'rematch', 'repay', 'retouch', 'revenge', 'reward', 'rhythm', 'ringbolt', 'robust', 'rocker', 'ruffled', 'sawdust', 'scallion', 'scenic', 'scorecard', 'Scotland', 'seabird', 'select', 'sentence', 'shadow', 'showgirl', 'skullcap', 'skydive', 'slingshot', 'slothful', 'slowdown', 'snapline', 'snapshot', 'snowcap', 'snowslide', 'solo', 'spaniel', 'spearhead', 'spellbind', 'spheroid', 'spigot', 'spindle', 'spoilage', 'spyglass', 'stagehand', 'stagnate', 'stairway', 'standard', 'stapler', 'steamship', 'stepchild', 'sterling', 'stockman', 'stopwatch', 'stormy', 'sugar', 'surmount', 'suspense', 'swelter', 'tactics', 'talon', 'tapeworm', 'tempest', 'tiger', 'tissue', 'tonic', 'tracker', 'transit', 'trauma', 'treadmill', 'Trojan', 'trouble', 'tumor', 'tunnel', 'tycoon', 'umpire', 'uncut', 'unearth', 'unwind', 'uproot', 'upset', 'upshot', 'vapor', 'village', 'virus', 'Vulcan', 'waffle', 'wallet', 'watchword', 'wayside', 'willow', 'woodlark', 'Zulu'] +const wordsEven = ['adroitness', 'adviser', 'aggregate', 'alkali', 'almighty', 'amulet', 'amusement', 'antenna', 'applicant', 'Apollo', 'armistice', 'article', 'asteroid', 'Atlantic', 'atmosphere', 'autopsy', 'Babylon', 'backwater', 'barbecue', 'belowground', 'bifocals', 'bodyguard', 'borderline', 'bottomless', 'Bradbury', 'Brazilian', 'breakaway', 'Burlington', 'businessman', 'butterfat', 'Camelot', 'candidate', 'cannonball', 'Capricorn', 'caravan', 'caretaker', 'celebrate', 'cellulose', 'certify', 'chambermaid', 'Cherokee', 'Chicago', 'clergyman', 'coherence', 'combustion', 'commando', 'company', 'component', 'concurrent', 'confidence', 'conformist', 'congregate', 'consensus', 'consulting', 'corporate', 'corrosion', 'councilman', 'crossover', 'cumbersome', 'customer', 'Dakota', 'decadence', 'December', 'decimal', 'designing', 'detector', 'detergent', 'determine', 'dictator', 'dinosaur', 'direction', 'disable', 'disbelief', 'disruptive', 'distortion', 'divisive', 'document', 'embezzle', 'enchanting', 'enrollment', 'enterprise', 'equation', 'equipment', 'escapade', 'Eskimo', 'everyday', 'examine', 'existence', 'exodus', 'fascinate', 'filament', 'finicky', 'forever', 'fortitude', 'frequency', 'gadgetry', 'Galveston', 'getaway', 'glossary', 'gossamer', 'graduate', 'gravity', 'guitarist', 'hamburger', 'Hamilton', 'handiwork', 'hazardous', 'headwaters', 'hemisphere', 'hesitate', 'hideaway', 'holiness', 'hurricane', 'hydraulic', 'impartial', 'impetus', 'inception', 'indigo', 'inertia', 'infancy', 'inferno', 'informant', 'insincere', 'insurgent', 'integrate', 'intention', 'inventive', 'Istanbul', 'Jamaica', 'Jupiter', 'leprosy', 'letterhead', 'liberty', 'maritime', 'matchmaker', 'maverick', 'Medusa', 'megaton', 'microscope', 'microwave', 'midsummer', 'millionaire', 'miracle', 'misnomer', 'molasses', 'molecule', 'Montana', 'monument', 'mosquito', 'narrative', 'nebula', 'newsletter', 'Norwegian', 'October', 'Ohio', 'onlooker', 'opulent', 'Orlando', 'outfielder', 'Pacific', 'pandemic', 'pandora', 'paperweight', 'paragon', 'paragraph', 'paramount', 'passenger', 'pedigree', 'Pegasus', 'penetrate', 'perceptive', 'performance', 'pharmacy', 'phonetic', 'photograph', 'pioneer', 'pocketful', 'politeness', 'positive', 'potato', 'processor', 'prophecy', 'provincial', 'proximate', 'puberty', 'publisher', 'pyramid', 'quantity', 'racketeer', 'rebellion', 'recipe', 'recover', 'repellent', 'replica', 'reproduce', 'resistor', 'responsive', 'retraction', 'retrieval', 'retrospect', 'revenue', 'revival', 'revolver', 'Sahara', 'sandalwood', 'sardonic', 'Saturday', 'savagery', 'scavenger', 'sensation', 'sociable', 'souvenir', 'specialist', 'speculate', 'stethoscope', 'stupendous', 'supportive', 'surrender', 'suspicious', 'sympathy', 'tambourine', 'telephone', 'therapist', 'tobacco', 'tolerance', 'tomorrow', 'torpedo', 'tradition', 'travesty', 'trombonist', 'truncated', 'typewriter', 'ultimate', 'undaunted', 'underfoot', 'unicorn', 'unify', 'universe', 'unravel', 'upcoming', 'vacancy', 'vagabond', 'versatile', 'vertigo', 'Virginia', 'visitor', 'vocalist', 'voyager', 'warranty', 'Waterloo', 'whimsical', 'Wichita', 'Wilmington', 'Wyoming', 'yesteryear', 'Yucatan'] + +export function UInt8ArrayToWords(bytes: Uint8Array, sepPair = ' ', sepGroup = ' '): string { + return Array.from(bytes).map((byte, pos) => pos % 2 === 0 ? wordsOdd[byte] + sepPair : wordsEven[byte] + sepGroup).join('').slice(0, -(bytes.length % 2 ? sepPair : sepGroup).length) +} diff --git a/src/common/dispose-defer.ts b/src/common/dispose-defer.ts index 64235701..fbf3160e 100644 --- a/src/common/dispose-defer.ts +++ b/src/common/dispose-defer.ts @@ -26,7 +26,7 @@ function callDisposer(disposable: Disposer): Promise | void { return result } -interface UseDisposeConfig { +export interface UseDisposeConfig { name?: string log?: LoggerInterface } @@ -108,11 +108,6 @@ export function useDispose(config?: string | UseDisposeConfig | LoggerInterface) isDisposed() { return tracked.length <= 0 }, - - // Utils - // timeout: (fn: DisposerFunction, timeout = 0) => track(useTimeout(fn, timeout)), - // interval: (fn: DisposerFunction, interval = 0) => track(useInterval(fn, interval)), - // on: (emitter: any, eventName: string, fn: (ev?: any) => void, ...args: any[]) => track(useEventListener(emitter, eventName, fn, ...args)), }) } diff --git a/src/common/dispose-utils.ts b/src/common/dispose-utils.ts index 488aed15..eb95577d 100644 --- a/src/common/dispose-utils.ts +++ b/src/common/dispose-utils.ts @@ -1,5 +1,8 @@ +import type { UseDisposeConfig } from './dispose-defer' +import { useDispose } from './dispose-defer' import type { DisposerFunction } from './dispose-types' import { promisify } from './exec' +import type { LoggerInterface } from './log/log-base' export function useTimeout( fn: DisposerFunction, @@ -66,3 +69,36 @@ export function useEventListener( emitter.removeEventListener(eventName, fn, ...args) } } + +export function useEventListenerOnce( + emitter: any, + eventName: string, + fn: (ev?: any) => void, + ...args: any[] +): DisposerFunction { + if (emitter == null) + return () => { } + if (emitter.on) + emitter.once(eventName, fn, ...args) + else if (emitter.addEventListener) + emitter.addEventListener(eventName, fn, ...args) + return () => { + if (emitter.off) + emitter.off(eventName, fn, ...args) + else if (emitter.removeEventListener) + emitter.removeEventListener(eventName, fn, ...args) + } +} + +/** Like useDispose but with shorthands for emitter and timers */ +export function useDisposeWithUtils(config?: string | UseDisposeConfig | LoggerInterface) { + const dispose = useDispose(config) + Object.assign(dispose, { + timeout: (fn: DisposerFunction, timeout = 0) => dispose.add(useTimeout(fn, timeout)), + interval: (fn: DisposerFunction, interval = 0) => dispose.add(useInterval(fn, interval)), + intervalPause: (fn: DisposerFunction, interval = 0) => dispose.add(useIntervalPause(fn, interval)), + on: (emitter: any, eventName: string, fn: (ev?: any) => void, ...args: any[]) => dispose.add(useEventListener(emitter, eventName, fn, ...args)), + once: (emitter: any, eventName: string, fn: (ev?: any) => void, ...args: any[]) => dispose.add(useEventListenerOnce(emitter, eventName, fn, ...args)), + }) + return dispose +}