├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── bin └── levelmeup ├── data ├── horse_js.json ├── keywise.json ├── node_0.8_commits.dat ├── sowpods_2.dat ├── sowpods_3.dat ├── sowpods_4.dat ├── sowpods_endhooks_2.dat ├── sowpods_endhooks_3.dat ├── sowpods_fronthooks_2.dat └── sowpods_fronthooks_3.dat ├── docs ├── level.html ├── leveldown.html ├── levelup.html ├── multilevel.html └── sublevel.html ├── exercises ├── all_your_base │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── basics_batch │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── basics_get │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── basics_put │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── get_your_level_on │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── horse_js_count │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── horse_js_tweets │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── keywise │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── multilevel │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── short_scrabble_words │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── streaming │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js └── sublevel │ ├── exercise.js │ ├── problem.en.md │ ├── problem.ja.md │ └── solution.js ├── i18n ├── en.json ├── help │ ├── en.md │ └── ja.md └── ja.json ├── levelmeup.js ├── levelmeup.png ├── lib ├── exercise.js ├── formatDiff.js ├── generate.js ├── gibberish.js └── read-db.js ├── package-lock.json ├── package.json ├── scripts └── fetch_horse.js └── test ├── all_your_base ├── invalid_01.js ├── invalid_02.js └── valid_01.js ├── basics_batch ├── invalid_01.js ├── valid_01.js ├── valid_02.js ├── valid_03.js └── valid_04.js ├── basics_get ├── invalid_01.js ├── invalid_02.js └── valid_01.js ├── basics_put ├── invalid_01.js ├── valid_01.js └── valid_02.js ├── get_your_level_on ├── invalid_01.js ├── invalid_02.js ├── invalid_03.js ├── invalid_04.js ├── invalid_05.js ├── invalid_06.js ├── invalid_07.js └── valid_01.js ├── horse_js_count ├── invalid_01.js └── valid_01.js ├── horse_js_tweets ├── invalid_01.js └── valid_01.js ├── keywise ├── invalid_01.js ├── valid_01.js ├── valid_02.js └── valid_03.js ├── multilevel ├── invalid_01.js └── valid_01.js ├── short_scrabble_words ├── invalid_01.js ├── invalid_02.js ├── invalid_03.js ├── invalid_04.js ├── invalid_05.js ├── invalid_06.js └── valid_01.js ├── streaming ├── invalid_01.js └── valid_01.js └── sublevel ├── invalid_01.js ├── invalid_02.js ├── valid_01.js └── valid_02.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | horse_js.csv 3 | horse.js -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | levelmeup.png 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '4' 4 | - '5' 5 | - '6' 6 | - '7' 7 | sudo: false 8 | env: 9 | - CXX=g++-4.8 10 | addons: 11 | apt: 12 | sources: 13 | - ubuntu-toolchain-r-test 14 | packages: 15 | - g++-4.8 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | ## [1.0.1](https://github.com/workshopper/levelmeup/compare/v1.0.0...v1.0.1) (2017-11-24) 7 | 8 | 9 | ### Bug Fixes 10 | 11 | * **docs:** The code snippets in basic_get didn't fit the solution ([00dc8c9](https://github.com/workshopper/levelmeup/commit/00dc8c9)) 12 | * **exercise:** Multilevel explanation wasn't up-to-date with the current verification logic ([ccce5cf](https://github.com/workshopper/levelmeup/commit/ccce5cf)) 13 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright (c) 2013-2015 levelmeup contributors 5 | --------------------------------------- 6 | 7 | *levelmeup contributors listed at * 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Level Me Up Scotty! 2 | 3 | **An intro to Node.js databases via a set of self-guided workshops.** 4 | 5 | [![NPM](https://nodei.co/npm/levelmeup.png?downloads=true&stars=true)](https://nodei.co/npm/levelmeup/) [![NPM](https://nodei.co/npm-dl/levelmeup.png?months=3)](https://nodei.co/npm/levelmeup/) 6 | [![Build Status](https://travis-ci.org/workshopper/levelmeup.svg?branch=master)](https://travis-ci.org/workshopper/levelmeup) 7 | 8 | ![Level Me Up Scotty!](https://github.com/rvagg/levelmeup/raw/master/levelmeup.png) 9 | 10 | 1. Run `[sudo] npm install levelmeup -g` 11 | 1. Run `levelmeup` 12 | 1. **.. profit!** 13 | 14 | levelmeup will run through a series of Node.js databases workshops. Starting with the basic operations of [LevelUP](https://github.com/Level/levelup) and moving on to more advanced exercises. 15 | 16 | ### Contributors 17 | 18 | levelmeup is proudly brought to you by the following Node.js database hackers: 19 | 20 | *<Your name here>* 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
Rod VaggGitHub/rvaggTwitter/@rvagg
Eugene WareGitHub/eugenewareTwitter/@eugeneware
James HallidayGitHub/substackTwitter/@substack
Jake VerbatenGitHub/raynosTwitter/@raynos
Julian GruberGitHub/juliangruberTwitter/@juliangruber
Robert KowalskiGitHub/robertkowalskiTwitter/@robinson_k
Lars-Magnus SkogGitHub/ralphtheninja
31 | 32 | **levelmeup** builds on the **[workshopper](https://github.com/rvagg/workshopper)** framework which is also used by **[learnyounode](https://github.com/rvagg/learnyounode)** (Learn You Node.js For Much Win), a basic introduction to Node.js workshop application. 33 | 34 | ## License 35 | 36 | **levelmeup** is Copyright (c) 2013-2015 Rod Vagg [@rvagg](https://twitter.com/rvagg) and licenced under the MIT licence. All rights not explicitly granted in the MIT license are reserved. See the included `LICENSE.md` file for more details. 37 | 38 | **levelmeup** builds on the excellent work by [@substack](https://github.com/substack) and [@maxogden](https://github.com/maxogden) who created **[stream-adventure](https://github.com/substack/stream-adventure)** which serves as the original foundation for **levelmeup**. 39 | -------------------------------------------------------------------------------- /bin/levelmeup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../levelmeup').execute(process.argv.slice(2)) 4 | -------------------------------------------------------------------------------- /data/keywise.json: -------------------------------------------------------------------------------- 1 | [{"type":"user","name":"maxogden"} 2 | ,{"type":"repo","name":"mux-demux","user":"dominictarr"} 3 | ,{"type":"user","name":"juliangruber"} 4 | ,{"type":"repo","name":"multilevel","user":"juliangruber"} 5 | ,{"type":"repo","name":"voxel-engine","user":"maxogden"} 6 | ,{"type":"user","name":"rvagg"} 7 | ,{"type":"repo","name":"leveldown","user":"rvagg"} 8 | ,{"type":"repo","name":"level-sublevel","user":"dominictarr"} 9 | ,{"type":"repo","name":"level-merkle","user":"dominictarr"} 10 | ,{"type":"repo","name":"levelup","user":"rvagg"} 11 | ,{"type":"repo","name":"concat-stream","user":"maxogden"} 12 | ,{"type":"repo","name":"through","user":"dominictarr"} 13 | ,{"type":"user","name":"dominictarr"}] 14 | -------------------------------------------------------------------------------- /data/node_0.8_commits.dat: -------------------------------------------------------------------------------- 1 | v0.8.0 2012.06.25, Version 0.8.0 (stable) 2 | v0.8.1 2012.06.29, Version 0.8.1 (stable) 3 | v0.8.10 2012.09.25, Version 0.8.10 (Stable) 4 | v0.8.11 2012.09.27, Version 0.8.11 (Stable) 5 | v0.8.12 2012.10.12, Version 0.8.12 (Stable) 6 | v0.8.13 2012.10.25, Version 0.8.13 (Stable) 7 | v0.8.14 2012.10.25, Version 0.8.14 (Stable) 8 | v0.8.15 2012.11.26, Version 0.8.15 (Stable) 9 | v0.8.16 2012.12.13, Version 0.8.16 (Stable) 10 | v0.8.17 2012.01.09, Version 0.8.17 (Stable) 11 | v0.8.18 2013.01.18, Version 0.8.18 (Stable) 12 | v0.8.19 2013.02.06, Version 0.8.19 (Stable) 13 | v0.8.2 2012.07.09, Version 0.8.2 (Stable) 14 | v0.8.20 2013.02.15, Version 0.8.20 (Stable) 15 | v0.8.21 2013.02.25, Version 0.8.21 (Stable) 16 | v0.8.22 2013.03.07, Version 0.8.22 (Stable) 17 | v0.8.23 2013.04.09, Version 0.8.23 (maintenance) 18 | v0.8.24 2013.06.04, Version 0.8.24 (maintenance) 19 | v0.8.25 2013.06.13, Version 0.8.25 (maintenance) 20 | v0.8.3 2012.07.19, Version 0.8.3 (Stable) 21 | v0.8.4 2012.07.25, Version 0.8.4 (Stable) 22 | v0.8.5 2012.08.02, Version 0.8.5 (Stable) 23 | v0.8.6 2012.08.07, Version 0.8.6 (Stable) 24 | v0.8.7 2012.08.15, Version 0.8.7 (Stable) 25 | v0.8.8 2012.08.22, Version 0.8.8 (Stable) 26 | v0.8.9 2012.09.11, Version 0.8.9 (Stable) 27 | -------------------------------------------------------------------------------- /data/sowpods_2.dat: -------------------------------------------------------------------------------- 1 | AA AB AD AE AG AH AI AL AM AN AR AS AT AW AX AY BA BE BI BO BY CH DA DE DI DO EA ED EE EF EH EL EM EN ER ES ET EX FA FY GI GO GU HA HE HI HM HO ID IF IN IO IS IT JO KA KO KY LA LI LO MA ME MI MM MO MU MY NA NE NO NU NY OB OD OE OF OH OI OM ON OO OP OR OS OU OW OX OY PA PE PH PI PO QI RE SH SI SO ST TA TE TI TO UG UH UM UN UP UR US UT WE WO XI XU YA YE YO YU ZO -------------------------------------------------------------------------------- /data/sowpods_3.dat: -------------------------------------------------------------------------------- 1 | AAH AAL ABA ABB ABO ABY ACE ACH ACT ADD ADO ADZ AFF AFT AGA 2 | AGE AGO AHA AIA AID AIL AIM AIN AIR AIT AKE ALA ALB ALE ALL 3 | ALP ALT AMA AMI AMP AMU ANA AND ANE ANI ANN ANT ANY APE APT 4 | ARB ARC ARD ARE ARF ARK ARM ART ARY ASH ASK ASP ASS ATE ATT AUF AUK AVA AVE AVO AWA AWE AWL AWN AXE AYE AYU AZO BAA BAC BAD BAG BAH BAL BAM BAN BAP BAR BAT BAY BED BEE BEG BEL BEN BET BEY BEZ BIB BID BIG BIN BIO BIT BIZ BOA BOB BOD 5 | BOG BOH BOK BON BOO BOP BOR BOT BOW BOX BOY BRA BRO BRR BUB 6 | BUD BUG BUM BUN BUR BUS BUT BUY BYE BYS CAB CAD CAM CAN CAP CAR CAT CAW CAY CEE CEL CEP CHA CHE CHI 7 | CID CIG CIS CIT CLY COB COD COG COL CON COO COP COR COS COT 8 | COW COX COY COZ CRU CRY CUB CUD CUE CUM CUP CUR CUT CUZ CWM 9 | DAB DAD DAE DAG DAH DAK DAL DAM DAN DAP DAW DAY DEB DEE DEF 10 | DEI DEL DEN DEV DEW DEX DEY DIB DID DIE DIG DIM DIN DIP DIT 11 | DIV DOB DOC DOD DOE DOG DOH DOL DOM DON DOO DOP DOR DOT DOW 12 | DRY DSO DUB DUD DUE DUG DUI DUN DUO DUP DUX DYE DZO EAN EAR EAT EAU EBB ECH ECU EDH EEK EEL EEN EFF EFT EGG 13 | EGO EIK EKE ELD ELF ELK ELL ELM ELT EME EMF EMU END ENE ENG EON ERA ERE ERF ERG ERK ERN ERR ESS EST ETA ETH EUK EVE EWE 14 | EWK EWT EYE FAB FAD FAG FAH FAN FAP FAR FAT FAW FAX FAY FED FEE FEH FEM FEN FER FET FEU FEW FEY FEZ FIB FID FIE FIG FIL FIN FIR FIT 15 | FIX FIZ FLU FLY FOB FOE FOG FOH FON FOP FOR FOU FOX FOY FRA 16 | FRO FRY FUB FUD FUG FUM FUN FUR 17 | GAB GAD GAE GAG GAL GAM GAN GAP GAR GAS GAT GAU GAY GED GEE 18 | GEL GEM GEN GEO GET GEY GHI GIB GID GIE GIF GIG GIN GIO GIP 19 | GIT GJU GNU GOA GOB GOD GOE GON GOO GOR GOT GOV GOX GOY GUB 20 | GUE GUL GUM GUN GUP GUR GUT GUV GUY GYM GYP HAD HAE HAG HAH HAJ HAM HAN HAO HAP HAT HAW HAY HEH HEM HEN 21 | HEP HER HET HEW HEX HEY HIC HID HIE HIM HIN HIP HIT HMM HOA 22 | HOB HOC HOD HOE HOG HOH HOI HON HOO HOP HOT HOW HOX HOY HUB 23 | HUE HUG HUH HUI HUM HUN HUP HUT HYE HYP ICE ICH ICK ICY IDE IFF ILK ILL IMP INK INN ION IRE IRK ISH 24 | ISM ISO ITA IVY 25 | JAB JAG JAK JAM JAP JAR JAW JAY JEE JET JEU JEW JIB JIG JIN JIZ JOB JOE JOG JOR JOT JOW JOY JUD JUG JUN JUS JUT KAB KAE KAF KAI KAM KAT KAW KAY KEA KEB KED KEF KEG KEN KEP KET KEX KEY KHI KID KIF KIN KIP KIR KIT KOA KOB KOI KON KOP KOR KOS KOW KUE KYE KYU 26 | LAB LAC LAD LAG LAH LAM LAP LAR LAT LAV LAW LAX LAY LEA LED LEE LEG LEI LEK LEP LES LET LEU LEV LEW LEX LEY LEZ LIB LID LIE LIG LIN LIP LIT LOB LOD LOG LOO LOP LOR LOT LOW LOX LOY 27 | LUD LUG LUM LUR LUV LUX LUZ LYE LYM MAA MAC MAD MAE MAG MAK MAL MAM MAN MAP MAR MAT MAW MAX MAY 28 | MED MEG MEL MEM MEN MET MEU MEW MHO MIB MID MIG MIL MIM MIR 29 | MIX MIZ MNA MOA MOB MOC MOD MOE MOG MOI MOL MOM MON MOO MOP 30 | MOR MOT MOU MOW MOY MOZ MUD MUG MUM MUN MUT MUX NAB NAE NAG NAH NAM NAN NAP NAT NAW NAY NEB NED NEE NEF NEK 31 | NEP NET NEW NIB NID NIE NIL NIM NIP NIS NIT NIX NOB NOD NOG 32 | NOH NOM NON NOO NOR NOT NOW NOX NOY NTH NUB NUN NUR NUT NYE 33 | NYS OAF OAK OAR OAT OBA OBE OBI OBO OCA OCH ODA ODD ODE OFF OFT 34 | OHM OHO OIK OIL OKA OKE OLD OLE OLM ONE OOF OOH OOM OON OOP 35 | OOR OOT OPE OPT ORA ORB ORC ORD ORE ORF ORT OSE OUD OUK OUP 36 | OUR OUT OVA OWE OWL OWN OWT OXO OXY OYE PAC PAD PAH PAL PAM PAN PAP PAR PAT PAW PAX PAY PEA PEC PED 37 | PEE PEG PEH PEN PEP PER PET PEW PHI PHO PHT PIA PIC PIE PIG PIN PIP PIR PIT PIU PIX PLY POA POD POH POI POL POM POO POP 38 | POT POW POX POZ PRE PRO PRY PSI PST PUB PUD PUG PUH PUL PUN 39 | PUP PUR PUS PUT PUY PYA PYE PYX QAT QUA RAD RAG RAH RAI RAJ RAM RAN RAP RAS RAT RAW RAX RAY REB REC 40 | RED REE REF REG REH REI REM REN REP RES RET REV REW REX REZ RHO RHY RIA RIB RID RIF RIG RIM RIN RIP RIT RIZ ROB ROC ROD 41 | ROE ROK ROM ROO ROT ROW RUB RUC RUD RUE RUG RUM RUN RUT RYA RYE SAB SAC SAD SAE SAG SAI SAL SAM SAN SAP SAR SAT SAU SAW SAX 42 | SAY SAZ SEA SEC SED SEE SEG SEI SEL SEN SER SET SEW SEX SEY 43 | SEZ SHA SHE SHH SHY SIB SIC SIM SIN SIP SIR SIS SIT SIX SKA 44 | SKI SKY SLY SMA SNY SOB SOC SOD SOG SOH SOL SON SOP SOT SOU 45 | SOV SOW SOX SOY SPA SPY SRI STY SUB SUD SUE SUI SUK SUM SUN SUP SUQ SUR SUS SWY SYE SYN TAB TAD TAE TAG TAI TAJ TAK TAM TAN TAO TAP TAR TAT TAU TAV 46 | TAW TAX TAY TEA TED TEE TEF TEG TEL TEN TET TEW THE THO THY 47 | TIC TID TIE TIG TIL TIN TIP TIT TOC TOD TOE TOG TOM TON TOO 48 | TOP TOR TOT TOW TOY TRY TSK TUB TUG TUI TUM TUN TUP TUT TUX 49 | TWA TWO TWP TYE TYG UDO UDS UEY UFO UGH UKE ULE ULU UMM UMP UNI UPO URB URD URE 50 | URN USE UTA UTE UTU UVA VAC VAE VAN VAR VAS VAT VAU VAV VAW VEE VEG VET VEX VIA VID 51 | VIE VIG VIM VIN VIS VLY VOE VOL VOR VOW VOX VUG VUM WAB WAD WAE WAG WAN WAP WAR WAS WAT WAW WAX WAY WEB WED WEE 52 | WEM WEN WET WEX WEY WHA WHO WHY WIG WIN WIS WIT WIZ WOE WOG 53 | WOK WON WOO WOP WOT WOW WOX WRY WUD WUS WYE WYN 54 | YAH YAK YAM YAP YAR YAW YAY YEA YEH YEN YEP YES YET YEW YEX YGO YID YIN YIP YOB YOD YOK YOM YON YOU YOW YUG YUK YUM YUP ZAG ZAP ZAX ZEA ZED ZEE ZEK ZEL ZEX ZHO ZIG ZIN ZIP ZIT ZIZ 55 | ZOA ZOO ZUZ -------------------------------------------------------------------------------- /data/sowpods_4.dat: -------------------------------------------------------------------------------- 1 | AAHS AALS ABAC ABAS ABBA ABBE ABBS ABED ABET ABID ABLE ABLY ABOS ABRI ABUT ABYE ABYS ACED ACER ACES ACHE ACHY ACID ACME ACNE ACRE ACTA ACTS ACYL ADAW ADDS ADIT ADOS ADRY ADZE AEON AERO AERY AESC AFAR AFFY AFRO AGAR AGAS AGED AGEE AGEN AGES AGHA AGIN AGIO AGLY AGMA AGOG AGON AGUE AHED AHEM AHOY AIAS AIDE AIDS AILS AIMS AINE AINS AIRN AIRS AIRT AIRY AITS AITU AJAR AJEE AKED AKEE AKES AKIN ALAE ALAN ALAP ALAR ALAS ALAY ALBA ALBE ALBS ALEC ALEE ALEF ALES ALEW ALFA ALGA ALIF ALIT ALKY ALLS ALLY ALMA ALME ALMS ALOD ALOE ALOW ALPS ALSO ALTO ALTS ALUM AMAH AMAS AMBO AMEN AMIA AMID AMIE AMIN AMIR AMIS AMLA AMMO AMOK AMPS AMUS AMYL ANAL ANAN ANAS ANCE ANDS ANES ANEW ANGA ANIL ANIS ANKH ANNA ANNO ANNS ANOA ANON ANOW ANSA ANTA ANTE ANTI ANTS ANUS APAY APED APER APES APEX APOD APSE APTS AQUA ARAK ARAR ARBA ARBS ARCH ARCO ARCS ARDS AREA ARED AREG ARES ARET AREW ARFS ARIA ARID ARIL ARIS ARKS ARLE ARMS ARMY ARNA AROW ARSE ARTS ARTY ARUM ARVO ARYL ASAR ASCI ASEA ASHY ASKS ASPS ATAP ATES ATMA ATOC ATOK ATOM ATOP AUFS AUKS AULA AULD AUNE AUNT AURA AUTO AVAL AVAS AVER AVES AVID AVOS AVOW AWAY AWDL AWED AWEE AWES AWLS AWNS AWNY AWOL AWRY AXAL AXED AXEL AXES AXIL AXIS AXLE AXON AYAH AYES AYIN AYRE AYUS AZAN AZON AZYM 2 | BAAL BAAS BABA BABE BABU BABY BACH BACK BACS BADE BADS BAEL BAFF BAFT BAGS BAHT BAIL BAIT BAJU BAKE BALD BALE BALK BALL BALM BALS BALU BAMS BANC BAND BANE BANG BANI BANK BANS BANT BAPS BAPU BARB BARD BARE BARF BARK BARM BARN BARP BARS BASE BASH BASK BASS BAST BATE BATH BATS BATT BAUD BAUK BAUR BAWD BAWL BAWN BAWR BAYE BAYS BAYT BEAD BEAK BEAM BEAN BEAR BEAT BEAU BECK BEDE BEDS BEDU BEEF BEEN BEEP BEER BEES BEET BEGO BEGS BEIN BELL BELS BELT BEMA BEND BENE BENI BENJ BENS BENT BERE BERG BERK BERM BEST BETA BETE BETH BETS BEVY BEYS BHEL BHUT BIAS BIBB BIBS BICE BIDE BIDS BIEN BIER BIFF BIGA BIGG BIGS BIKE BILE BILK BILL BIMA BIND BINE BING BINK BINS BINT BIOG BIOS BIRD BIRK BIRL BIRR BISE BISH BISK BITE BITO BITS BITT BIZE BLAB BLAD BLAE BLAG BLAH BLAM BLAT BLAW BLAY BLEB BLED BLEE BLET BLEW BLEY BLIN BLIP BLOB BLOC BLOT BLOW BLUB BLUE BLUR BOAK BOAR BOAS BOAT BOBA BOBS BOCK BODE BODS BODY BOFF BOGS BOGY BOHS BOIL BOKE BOKO BOKS BOLA BOLD BOLE BOLL BOLO BOLT BOMA BOMB BONA BOND BONE BONG BONK BONY BOOB BOOH BOOK BOOL BOOM BOON BOOR BOOS BOOT BOPS BORA BORD BORE BORN BORS BORT BOSH BOSK BOSS BOTA BOTH BOTS BOTT BOUK BOUN BOUT BOWL BOWR BOWS BOXY BOYG BOYO BOYS BOZO BRAD BRAE BRAG BRAN BRAS BRAT BRAW BRAY BRED BREE BREN BRER BREW BRIE BRIG BRIM BRIN BRIO BRIS BRIT BROD BROG BROO BROS BROW BRRR BRUT BUAT BUBA BUBO BUBS BUCK BUDO BUDS BUFF BUFO BUGS BUHL BUHR BUIK BUKE BULB BULK BULL BUMF BUMP BUMS BUNA BUND BUNG BUNK BUNN BUNS BUNT BUOY BURA BURD BURG BURK BURL BURN BURP BURR BURS BURY BUSH BUSK BUSS BUST BUSY BUTE BUTS BUTT BUYS BUZZ BYES BYKE BYRE BYRL BYTE 3 | CABA CABS CACA CADE CADI CADS CAFE CAFF CAGE CAGY CAID CAIN CAKE CAKY CALF CALK CALL CALM CALO CALP CALX CAME CAMP CAMS CANE CANG CANN CANS CANT CANY CAPA CAPE CAPH CAPI CAPO CAPS CARB CARD CARE CARK CARL CARN CARP CARR CARS CART CASA CASE CASH CASK CAST CATE CATS CAUF CAUK CAUL CAUM CAUP CAVE CAVY CAWK CAWS CAYS CEAS CECA CEDE CEDI CEES CEIL CELL CELS CELT CENS CENT CEPE CEPS CERE CERO CERT CESS CETE CHAD CHAI CHAL CHAM CHAO CHAP CHAR CHAS CHAT CHAW CHAY CHEF CHER CHEW CHEZ CHIA CHIC CHID CHIK CHIN CHIP CHIS CHIT CHIV CHIZ CHOC CHON CHOP CHOU CHOW CHUB CHUG CHUM CHUT CIAO CIDE CIDS CIEL CIGS CILL CINE CION CIRE CIRL CIST CITE CITO CITS CITY CIVE CLAD CLAG CLAM CLAN CLAP CLAT CLAW CLAY CLEF CLEG CLEM CLEW CLIP CLOD CLOG CLON CLOP CLOT CLOU CLOW CLOY CLUB CLUE COAL COAT COAX COBB COBS COCA COCH COCK COCO CODA CODE CODS COED COFF COFT COGS COHO COIF COIL COIN COIR COIT COKE COKY COLA COLD COLE COLL COLS COLT COLY COMA COMB COME COMP COMS COND CONE CONF CONI CONK CONN CONS CONY COOF COOK COOL COOM COON COOP COOS COOT COPE COPS COPY CORD CORE CORF CORK CORM CORN CORS CORY COSE COSH COSS COST COSY COTE COTH COTS COTT COUP COUR COVE COWL COWP COWS COWY COXA COXY COYS COZE COZY CRAB CRAG CRAM CRAN CRAP CRAW CRED CREE CREW CRIB CRIM CRIS CRIT CROC CROP CROW CRUD CRUE CRUS CRUX CUBE CUBS CUDS CUED CUES CUFF CUIF CUIT CUKE CULL CULM CULT CUNT CUPS CURB CURD CURE CURF CURL CURN CURR CURS CURT CUSH CUSK CUSP CUSS CUTE CUTS CWMS CYAN CYMA CYME CYST CYTE CZAR 4 | DABS DACE DADA DADO DADS DAES DAFF DAFT DAGO DAGS DAHL DAHS DAIS DAKS DALE DALI DALS DALT DAME DAMN DAMP DAMS DANG DANK DANS DANT DAPS DARB DARE DARG DARI DARK DARN DART DASH DATA DATE DATO DAUB DAUD DAUR DAUT DAVY DAWD DAWK DAWN DAWS DAWT DAYS DAZE DEAD DEAF DEAL DEAN DEAR DEAW DEBS DEBT DECK DECO DEED DEEK DEEM DEEN DEEP DEER DEES DEET DEEV DEFI DEFT DEFY DEID DEIL DEKE DELE DELF DELI DELL DELS DELT DEME DEMO DEMY DENE DENS DENT DENY DERE DERM DERN DERV DESK DEUS DEVA DEVS DEWS DEWY DEXY DEYS DHAK DHAL DHOL DHOW DIAL DIBS DICE DICH DICK DICT DIDO DIDY DIEB DIED DIEL DIES DIET DIGS DIKA DIKE DILL DIME DIMS DINE DING DINK DINO DINS DINT DIOL DIPS DIPT DIRE DIRK DIRL DIRT DISA DISC DISH DISK DISS DITA DITE DITS DITT DITZ DIVA DIVE DIVI DIVS DIXI DIXY DJIN DOAB DOAT DOBS DOBY DOCK DOCS DODO DODS DOEK DOEN DOER DOES DOFF DOGE DOGS DOGY DOHS DOIT DOJO DOLE DOLL DOLS DOLT DOME DOMS DOMY DONA DONE DONG DONS DOOB DOOK DOOL DOOM DOOR DOOS DOPA DOPE DOPS DOPY DORE DORK DORM DORP DORR DORS DORT DORY DOSE DOSH DOSS DOST DOTE DOTH DOTS DOTY DOUC DOUM DOUP DOUR DOUT DOUX DOVE DOWD DOWF DOWL DOWN DOWP DOWS DOWT DOXY DOZE DOZY DRAB DRAD DRAG DRAM DRAP DRAT DRAW DRAY DREE DREG DREK DREW DREY DRIB DRIP DROP DROW DRUB DRUG DRUM DRYS DSOS DUAD DUAL DUAN DUAR DUBS DUCE DUCI DUCK DUCT DUDE DUDS DUED DUEL DUES DUET DUFF DUGS DUIT DUKE DULE DULL DULY DUMA DUMB DUMP DUNE DUNG DUNK DUNS DUNT DUOS DUPE DUPS DURA DURE DURN DURO DURR DUSH DUSK DUST DUTY DWAM DYAD DYED DYER DYES DYKE DYNE DZHO DZOS 5 | EACH EALE EANS EARD EARL EARN EARS EASE EAST EASY EATH EATS EAUS EAUX EAVE EBBS EBON ECAD ECCE ECCO ECHE ECHO ECHT ECOD ECRU ECUS EDDO EDDY EDGE EDGY EDHS EDIT EECH EELS EELY EERY EEVN EFFS EFTS EGAD EGAL EGER EGGS EGGY EGIS EGMA EGOS EHED EIDE EIKS EILD EINE EKED EKES EKKA ELAN ELDS ELFS ELHI ELKS ELLS ELMS ELMY ELSE ELTS EMES EMEU EMFS EMIC EMIR EMIT EMMA EMUS EMYD EMYS ENDS ENES ENEW ENGS ENOL ENOW ENVY EOAN EONS EORL EPEE EPHA EPIC EPOS ERAS ERED ERES ERGO ERGS ERIC ERKS ERNE ERNS EROS ERRS ERST ESES ESKY ESNE ESPY ESSE ESTS ETAS ETAT ETCH ETEN ETHE ETHS ETIC ETNA ETUI EUGE EUGH EUKS EUOI EURO EVEN EVER EVES EVET EVIL EVOE EWER EWES EWKS EWTS EXAM EXEC EXES EXIT EXON EXPO EXUL EYAS EYED EYEN EYER EYES EYNE EYOT EYRA EYRE EYRY 6 | FACE FACT FADE FADO FADS FADY FAFF FAGS FAHS FAIK FAIL FAIN FAIR FAIX FAKE FALL FALX FAME FAND FANE FANG FANK FANO FANS FARD FARE FARL FARM FARO FARS FART FASH FAST FATE FATS FAUN FAUX FAVA FAVE FAWN FAWS FAYS FAZE FEAL FEAR FEAT FECK FEDS FEED FEEL FEER FEES FEET FEGS FEHM FEHS FEIS FELL FELT FEME FEMS FEND FENI FENS FENT FEOD FERE FERM FERN FESS FEST FETA FETE FETS FETT FEUD FEUS FEYS FIAR FIAT FIBS FICE FICO FIDO FIDS FIEF FIER FIFE FIGO FIGS FIKE FIKY FILA FILE FILL FILM FILO FILS FIND FINE FINI FINK FINO FINS FIRE FIRK FIRM FIRN FIRS FISC FISH FISK FIST FITS FITT FIVE FIXT FIZZ FLAB FLAG FLAK FLAM FLAN FLAP FLAT FLAW FLAX FLAY FLEA FLED FLEE FLEG FLEW FLEX FLEY FLIC FLIP FLIT FLIX FLOC FLOE FLOG FLOP FLOR FLOW FLUB FLUE FLUS FLUX FOAL FOAM FOBS FOCI FOEN FOES FOGS FOGY FOHN FOHS FOID FOIL FOIN FOLD FOLK FOND FONE FONS FONT FOOD FOOL FOOT FOPS FORA FORB FORD FORE FORK FORM FORT FOSS FOUD FOUL FOUR FOUS FOWL FOXY FOYS FOZY FRAB FRAE FRAG FRAP FRAS FRAT FRAU FRAY FREE FRET FRIG FRIS FRIT FRIZ FROE FROG FROM FROW FRUG FUBS FUCI FUCK FUDS FUEL FUFF FUGS FUGU FUJI FULL FUME FUMS FUMY FUND FUNG FUNK FUNS FURL FURR FURS FURY FUSC FUSE FUSS FUST FUTZ FUZE FUZZ FYCE FYKE FYLE FYRD 7 | GABS GABY GADE GADI GADS GAED GAEN GAES GAFF GAGA GAGE GAGS GAID GAIN GAIR GAIT GAJO GALA GALE GALL GALS GAMA GAMB GAME GAMP GAMS GAMY GANE GANG GANT GAOL GAPE GAPO GAPS GAPY GARB GARE GARS GART GASH GASP GAST GATE GATH GATS GAUD GAUM GAUN GAUP GAUR GAUS GAVE GAWD GAWK GAWP GAYS GAZE GAZY GEAL GEAN GEAR GEAT GECK GEDS GEED GEEK GEEP GEES GEEZ GEIT GELD GELS GELT GEMS GENA GENE GENS GENT GENU GEOS GERE GERM GEST GETA GETS GEUM GHAT GHEE GHIS GIBE GIBS GIDS GIED GIEN GIES GIFT GIGA GIGS GILA GILD GILL GILT GIMP GING GINK GINN GINS GIOS GIPS GIRD GIRL GIRN GIRO GIRR GIRT GISM GIST GITE GITS GIVE GIZZ GJUS GLAD GLAM GLED GLEE GLEG GLEI GLEN GLEY GLIA GLIB GLID GLIM GLIT GLOB GLOM GLOP GLOW GLUE GLUG GLUM GLUT GNAR GNAT GNAW GNUS GOAD GOAF GOAL GOAS GOAT GOBO GOBS GOBY GODS GOEL GOER GOES GOEY GOFF GOGO GOLD GOLE GOLF GOLP GONE GONG GONK GONS GOOD GOOF GOOK GOLL GOON GOOP GOOR GOOS GORE GORM GORP GORY GOSH GOUK GOUT GOVS GOWD GOWF GOWL GOWN GOYS GRAB GRAD GRAM GRAN GRAT GRAY GREE GREN GREW GREY GRID GRIG GRIM GRIN GRIP GRIS GRIT GROG GROT GROW GRUB GRUE GRUM GUAN GUAR GUBS GUCK GUDE GUES GUFF GUGA GUID GULA GULE GULF GULL GULP GULS GULY GUMP GUMS GUNK GUNS GUPS GURL GURN GURS GURU GUSH GUST GUTS GUVS GUYS GYAL GYBE GYMP GYMS GYNY GYPS GYRE GYRI GYRO GYTE GYVE 8 | HAAF HAAR HABU HACK HADE HADJ HADS HAED HAEM HAEN HAES HAET HAFF HAFT HAGG HAGS HAHA HAHS HAIK HAIL HAIN HAIR HAJI HAJJ HAKA HAKE HALE HALF HALL HALM HALO HALT HAME HAMS HAND HANG HANK HANT HAPS HARD HARE HARK HARL HARM HARN HARO HARP HART HASH HASK HASP HAST HATE HATH HATS HAUD HAUL HAUT HAVE HAWK HAWM HAWS HAYS HAZE HAZY HEAD HEAL HEAP HEAR HEAT HEBE HECH HECK HEED HEEL HEFT HEHS HEID HEIL HEIR HELD HELE HELL HELM HELP HELO HEME HEMP HEMS HEND HENS HENT HEPS HEPT HERB HERD HERE HERL HERM HERN HERO HERS HERY HESP HEST HETE HETH HETS HEWN HEWS HEYS HICK HIED HIES HIGH HIKE HILA HILD HILI HILL HILT HIND HING HINS HINT HIPS HIPT HIRE HISH HISN HISS HIST HITS HIVE HIYA HIZZ HOAR HOAS HOAX HOBO HOBS HOCK HODS HOED HOER HOES HOGG HOGH HOGS HOHS HOIK HOKE HOKI HOLD HOLE HOLK HOLM HOLP HOLS HOLT HOLY HOME HOMO HOMY HOND HONE HONG HONK HONS HOOD HOOF HOOK HOON HOOP HOOT HOPE HOPS HORA HORE HORN HORS HOSE HOSS HOST HOTE HOTS HOUF HOUR HOUT HOVE HOWE HOWF HOWK HOWL HOWS HOYA HUBS HUCK HUED HUER HUES HUFF HUGE HUGS HUGY HUIA HUIC HUIS HULA HULE HULK HULL HUMA HUMF HUMP HUMS HUNG HUNH HUNK HUNS HUNT HUPS HURL HURT HUSK HUSO HUSS HUTS HWAN HWYL HYED HYEN HYES HYKE HYLA HYLE HYMN HYPE HYPO HYPS HYTE 9 | IAMB IBEX IBIS ICED ICER ICES ICHS ICKY ICON IDEA IDEE IDEM IDES IDLE IDLY IDOL IDYL IFFY IGAD IGLU IKAT IKON ILEA ILEX ILIA ILKA ILKS ILLS ILLY IMAM IMID IMMY IMPI IMPS INBY INCH INFO INGO INIA INKS INKY INLY INRO INTI INTO IONS IOTA IRED IRES IRID IRIS IRKS IRON ISBA ISLE ISMS ISOS ITAS ITCH ITEM IURE IWIS IXIA IZAR 10 | JABS JACK JADE JAGG JAGS JAIL JAKE JAKS JAMB JAMS JANE JANN JAPE JAPS JARK JARL JARS JASP JASS JASY JATO JAUK JAUP JAVA JAWS JAYS JAZY JAZZ JEAN JEAT JEED JEEL JEEP JEER JEES JEEZ JEFE JEFF JEHU JELL JEON JERK JESS JEST JETE JETS JEUX JEWS JIAO JIBB JIBE JIBS JIFF JIGS JILL JILT JIMP JINK JINN JINS JINX JIRD JISM JIVE JIZZ JOBE JOBS JOCK JOCO JOES JOEY JOGS JOHN JOIN JOKE JOKY JOLE JOLL JOLT JOMO JOOK JORS JOSH JOSS JOTA JOTS JOUK JOUR JOWL JOWS JOYS JUBA JUDO JUDS JUDY JUGA JUGS JUJU JUKE JUMP JUNK JUPE JURA JURE JURY JUST JUTE JUTS JUVE JYNX 11 | KAAS KABS KADE KADI KAED KAES KAFS KAGO KAGU KAID KAIE KAIF KAIL KAIM KAIN KAIS KAKA KAKI KALE KALI KAMA KAME KAMI KANA KANE KANG KANS KANT KAON KAPA KAPH KARA KARN KART KATA KATI KATS KAVA KAWS KAYO KAYS KAZI KBAR KEAS KEBS KECK KEDS KEEF KEEK KEEL KEEN KEEP KEET KEFS KEGS KEIR KELL KELP KELT KEMB KEMP KENO KENS KENT KEPI KEPS KEPT KERB KERF KERN KESH KEST KETA KETO KETS KEYS KHAF KHAN KHAT KHET KHIS KHOR KHUD KIBE KICK KIDS KIEF KIER KIFS KIKE KILD KILL KILN KILO KILP KILT KINA KIND KINE KING KINK KINO KINS KIPE KIPP KIPS KIRK KIRN KIRS KISH KISS KIST KITE KITH KITS KIVA KIWI KNAG KNAP KNAR KNEE KNEW KNIT KNOB KNOP KNOT KNOW KNUB KNUR KNUT KOAN KOAS KOBO KOBS KOEL KOFF KOHL KOLA KOLO KOND KONK KONS KOOK KOPH KOPS KORA KORE KORS KOSS KOTO KOWS KRAB KRIS KSAR KUDO KUDU KUES KUKU KURI KURU KVAS KYAK KYAR KYAT KYLE KYND KYNE KYTE KYUS 12 | LABS LACE LACK LACS LACY LADE LADS LADY LAER LAGS LAHS LAIC LAID LAIK LAIN LAIR LAKE LAKH LAKY LALL LAMA LAMB LAME LAMP LAMS LANA LAND LANE LANG LANK LANT LANX LAPS LARD LARE LARI LARK LARN LARS LASE LASH LASS LAST LATE LATH LATI LATS LAUD LAUF LAVA LAVE LAVS LAWK LAWN LAWS LAYS LAZE LAZO LAZY LEAD LEAF LEAK LEAL LEAM LEAN LEAP LEAR LEAS LEAT LECH LEED LEEK LEEP LEER LEES LEET LEFT LEGS LEHR LEIR LEIS LEKE LEKS LEKU LEME LEND LENG LENO LENS LENT LEPS LEPT LERE LERP LESS LEST LETS LEUD LEVA LEVE LEVO LEVY LEWD LEYS LEZZ LIAR LIBS LICE LICH LICK LIDO LIDS LIED LIEF LIEN LIER LIES LIEU LIFE LIFT LIGS LIKE LILL LILO LILT LILY LIMA LIMB LIME LIMN LIMO LIMP LIMY LIND LINE LING LINK LINN LINO LINS LINT LINY LION LIPS LIRA LIRI LIRK LISK LISP LIST LITE LITH LITS LITU LIVE LOAD LOAF LOAM LOAN LOBE LOBI LOBO LOBS LOCA LOCH LOCI LOCK LOCO LODE LODS LOFT LOGE LOGO LOGS LOGY LOID LOIN LOIR LOKE LOLL LOMA LOME LONE LONG LOOF LOOK LOOM LOON LOOP LOOR LOOS LOOT LOPE LOPS LORD LORE LORN LORY LOSE LOSH LOSS LOST LOTA LOTE LOTH LOTI LOTO LOTS LOUD LOUN LOUP LOUR LOUT LOVE LOWE LOWN LOWS LOWT LOYS LUAU LUBE LUCE LUCK LUDE LUDO LUDS LUES LUFF LUGE LUGS LUIT LUKE LULL LULU LUMP LUMS LUNA LUNE LUNG LUNK LUNT LUNY LURE LURK LURS LUSH LUSK LUST LUTE LUTZ LUVS LUXE LWEI LYAM LYES LYME LYMS LYNE LYNX LYRE LYSE LYTE 13 | MAAR MAAS MABE MACE MACH MACK MACS MADE MADS MAES MAGE MAGG MAGI MAGS MAID MAIK MAIL MAIM MAIN MAIR MAKE MAKO MAKS MALE MALI MALL MALM MALS MALT MAMA MAMS MANA MAND MANE MANG MANI MANO MANS MANY MAPS MARA MARC MARD MARE MARG MARK MARL MARM MARS MART MARY MASA MASE MASH MASK MASS MAST MASU MATE MATH MATS MATT MATY MAUD MAUL MAUN MAUT MAWK MAWN MAWR MAWS MAXI MAYA MAYO MAYS MAZE MAZY MEAD MEAL MEAN MEAT MEED MEEK MEER MEET MEGA MEGS MEIN MELA MELD MELL MELS MELT MEME MEMO MEMS MEND MENE MENG MENO MENT MENU MEOU MEOW MERC MERE MERI MERK MERL MESA MESE MESH MESS META METE METH METS MEUS MEVE MEWL MEWS MEZE MHOS MIBS MICA MICE MICK MICO MIDI MIDS MIEN MIFF MIGG MIGS MIKE MILD MILE MILK MILL MILO MILS MILT MIME MINE MINA MIND MINE MING MINI MINK MINO MINT MINX MINY MIRE MIRI MIRK MIRS MIRV MIRY MISE MISO MISS MIST MITE MITT MITY MIXT MIXY MIZZ MNAS MOAN MOAS MOAT MOBS MOCH MOCK MOCS MODE MODI MODS MOES MOGS MOHR MOIL MOIT MOJO MOKE MOKI MOKO MOLA MOLD MOLE MOLL MOLS MOLT MOLY MOMI MOMS MONA MONG MONK MONO MONS MONY MOOD MOOI MOOK MOOL MOON MOOP MOOR MOOS MOOT MOPE MOPS MOPY MORA MORE MORN MORS MORT MOSE MOSK MOSS MOST MOTE MOTH MOTS MOTT MOTU MOUE MOUP MOUS MOVE MOWA MOWN MOWS MOXA MOYA MOYL MOYS MOZE MOZO MOZZ MUCH MUCK MUDS MUFF MUGG MUGS MUID MUIL MUIR MULE MULL MUMM MUMP MUMS MUMU MUNS MUNT MUNI MUON MURA MURE MURK MURL MURR MUSE MUSH MUSK MUSO MUSS MUST MUTE MUTI MUTS MUTT MYAL MYNA MYTH MZEE 14 | NAAM NAAN NABE NABK NABS NACH NADA NAFF NAGA NAGS NAIF NAIK NAIL NAIN NALA NAME NAMS NANA NANS NAOI NAOS NAPA NAPE NAPS NARC NARD NARE NARK NARY NATS NAVE NAVY NAYS NAZE NAZI NEAL NEAP NEAR NEAT NEBS NECK NEDS NEED NEEM NEEP NEFS NEIF NEKS NEMA NEMN NENE NEON NEPS NERD NERK NESH NESS NEST NETE NETS NETT NEUK NEUM NEVE NEVI NEWS NEWT NEXT NIBS NICE NICK NIDE NIDI NIDS NIED NIEF NIES NIFE NIFF NIGH NILL NILS NIMB NIMS NINE NIPA NIPS NIRL NISI NITE NITS NIXE NIXY NOBS NOCK NODE NODI NODS NOEL NOES NOGG NOGS NOIL NOIR NOLE NOLL NOLO NOMA NOME NOMS NONA NONE NONG NOOK NOON NOOP NOPE NORI NORK NORM NOSE NOSH NOSY NOTA NOTE NOTT NOUL NOUN NOUP NOUS NOUT NOVA NOWL NOWN NOWS NOWT NOWY NOYS NUBS NUDE NUFF NUKE NULL NUMB NUNS NURD NURL NURR NURS NUTS NYAS NYED NYES 15 | OAFS OAKS OAKY OARS OARY OAST OATH OATS OBAS OBES OBEY OBIA OBIS OBIT OBOE OBOL OBOS OCAS OCHE OCTA ODAL ODAS ODDS ODEA ODES ODIC ODOR ODSO ODYL OFAY OFFS OGAM OGEE OGLE OGRE OHED OHIA OHMS OHOS OIKS OILS OILY OINK OINT OKAS OKAY OKEH OKES OKRA OKTA OLDS OLDY OLEA OLEO OLES OLID OLIO OLLA OLMS OLPE OMBU OMEN OMER OMIT ONCE ONER ONES ONLY ONST ONTO ONYX OOFS OOHS OOMS OONS OONT OOPS OOSE OOSY OOTS OOZE OOZY OPAH OPAL OPEN OPPO OPTS OPUS ORAD ORAL ORBS ORBY ORCA ORCS ORDO ORDS ORES ORFE ORGY ORLE ORRA ORTS ORYX ORZO OSAR OSES OSSA OTIC OTTO OUCH OUDS OUKS OULD OULK OUPH OUPS OURN OURS OUST OUTS OUZO OVAL OVEN OVER OVUM OWED OWES OWLS OWLY OWNS OWRE OWSE OWTS OXEN OXER OXES OXID OXIM OYER OYES OYEZ 16 | PACA PACE PACK PACO PACS PACT PACY PADI PADS PAGE PAHS PAID PAIK PAIL PAIN PAIR PAIS PALE PALL PALM PALP PALS PALY PAMS PAND PANE PANG PANS PANT PAPA PAPE PAPS PARA PARD PARE PARK PARP PARR PARS PART PASE PASH PASS PAST PATE PATH PATS PATY PAUA PAUL PAVE PAWA PAWK PAWL PAWN PAWS PAYS PEAG PEAK PEAL PEAN PEAR PEAS PEAT PEBA PECH PECK PECS PEDS PEED PEEK PEEL PEEN PEEP PEER PEES PEGH PEGS PEHS PEIN PEKE PELA PELE PELF PELT PEND PENE PENI PENK PENS PENT PEON PEPO PEPS PERE PERI PERK PERM PERT PERV PESO PEST PETS PEWS PFFT PFUI PHAT PHEW PHIS PHIZ PHOH PHON PHOS PHOT PHUT PIAL PIAN PIAS PICA PICE PICK PICS PIED PIER PIES PIET PIKA PIKI PILA PILE PILI PILL PILY PIMA PIMP PINA PINE PING PINK PINS PINY PION PIOY PIPA PIPE PIPI PIPS PIPY PIRL PIRN PIRS PISE PISH PISO PITA PITH PITS PITY PIUM PIXY PIZE PLAN PLAP PLAT PLAY PLEA PLEB PLED PLEW PLIE PLIM PLOD PLOP PLOT PLOW PLOY PLUG PLUM PLUS POAS POCK POCO POEM POET POGO POGY POIS POKE POKY POLE POLK POLL POLO POLS POLT POLY POMP POMS POND PONE PONG PONK PONS PONT PONY POOD POOF POOH POOK POOL POON POOP POOR POOS POOT POPE POPS PORE PORK PORN PORT PORY POSE POSH POSS POST POSY POTE POTS POTT POUF POUK POUR POUT POWN POWS POXY POZZ PRAD PRAM PRAO PRAT PRAU PRAY PREE PREP PREX PREY PREZ PRIG PRIM PROA PROD PROF PROG PROM PROO PROP PROS PROW PRUH PRYS PSIS PSST PUBS PUCE PUDS PUDU PUER PUFF PUGH PUGS PUIR PUJA PUKE PUKU PULA PULE PULI PULK PULL PULP PULS PULU PULY PUMA PUMP PUMY PUNA PUNG PUNK PUNS PUNT PUNY PUPA PUPS PURE PURI PURL PURR PURS PUSH PUSS PUTS PUTT PUTZ PUYS PYAS PYAT PYES PYET PYIC PYIN PYNE PYOT PYRE PYRO 17 | QADI QAID QATS QOPH QUAD QUAG QUAI QUAT QUAY QUEP QUEY QUID QUIM QUIN QUIP QUIT QUIZ QUOD QUOP 18 | RABI RACA RACE RACH RACK RACY RADE RADS RAFF RAFT RAGA RAGE RAGG RAGI RAGS RAHS RAIA RAID RAIK RAIL RAIN RAIS RAIT RAJA RAKE RAKI RAKU RALE RAMI RAMP RAMS RANA RAND RANG RANI RANK RANT RAPE RAPS RAPT RARE RASE RASH RASP RAST RATA RATE RATH RATO RATS RATU RAUN RAVE RAWN RAWS RAYA RAYS RAZE RAZZ READ REAK REAL REAM REAN REAP REAR REBS RECK RECS REDD REDE REDO REDS REED REEF REEK REEL REEN REES REFS REFT REGO REGS REHS REIF REIK REIN REIS REKE RELY REMS REND RENS RENT RENY REPO REPP REPS REST RETE RETS REVS REWS RHEA RHOS RHUS RIAL RIAS RIBS RICE RICH RICK RIDE RIDS RIEL RIEM RIFE RIFF RIFS RIFT RIGG RIGS RILE RILL RIMA RIME RIMU RIMY RIND RINE RING RINK RINS RIOT RIPE RIPP RIPS RIPT RISE RISK RITE RITS RITT RITZ RIVA RIVE RIVO RIZA ROAD ROAM ROAN ROAR ROBE ROBS ROCK ROCS RODE RODS ROED ROES ROIL ROIN ROJI ROKE ROKS ROKY ROLE ROLF ROMA ROMP ROMS RONE RONG RONT ROOD ROOF ROOK ROOM ROON ROOP ROOS ROOT ROPY RORE RORT RORY ROSE ROST ROSY ROTA ROTE ROTI ROTL ROTO ROTS ROUE ROUM ROUP ROUT ROUX ROVE ROWS ROWT RUBE RUBS RUBY RUCK RUCS RUDD RUDE RUED RUER RUES RUFF RUGA RUGS RUIN RUKH RULE RULY RUME RUMP RUMS RUND RUNE RUNG RUNS RUNT RURP RURU RUSA RUSE RUSH RUSK RUST RUTH RUTS RYAL RYAS RYES RYFE RYKE RYND RYOT RYPE 19 | SABE SABS SACK SACS SADE SADI SAFE SAGA SAGE SAGO SAGS SAGY SAIC SAID SAIL SAIM SAIN SAIR SAIS SAKE SAKI SALE SALL SALP SALS SALT SAMA SAME SAMP SAND SANE SANG SANK SANS SANT SAPS SARD SARI SARK SARS SASH SASS SATE SATI SAUL SAUT SAVE SAWN SAWS SAYS SCAB SCAD SCAG SCAM SCAN SCAR SCAT SCAW SCOG SCOP SCOT SCOW SCRY SCUD SCUG SCUL SCUM SCUP SCUR SCUT SCYE SEAL SEAM SEAN SEAR SEAS SEAT SECO SECS SECT SEED SEEK SEEL SEEM SEEN SEEP SEER SEES SEGO SEGS SEIF SEIK SEIL SEIR SEIS SEKT SELD SELE SELF SELL SELS SEME SENA SEND SENE SENS SENT SEPS SEPT SERA SERE SERF SERK SERR SERS SESE SESS SETA SETS SETT SEWN SEWS SEXT SEXY SEYS SHAD SHAG SHAH SHAM SHAN SHAT SHAW SHAY SHEA SHED SHES SHET SHEW SHIM SHIN SHIP SHIR SHIT SHIV SHMO SHOD SHOE SHOG SHOO SHOP SHOT SHOW SHRI SHUL SHUN SHUT SHWA SIAL SIBB SIBS SICE SICH SICK SICS SIDA SIDE SIEN SIFT SIGH SIGN SIJO SIKA SIKE SILD SILE SILK SILL SILO SILT SIMA SIMI SIMP SIMS SIND SINE SING SINH SINK SINS SIPE SIPS SIRE SIRI SIRS SISS SIST SITE SITH SITS SIZE SIZY SKAG SKAS SKAT SKAW SKEE SKEG SKEO SKEP SKER SKEW SKID SKIM SKIN SKIO SKIP SKIS SKIT SKOL SKRY SKUA SKUG SKYR SLAB SLAE SLAG SLAM SLAP SLAT SLAW SLAY SLED SLEE SLEW SLEY SLID SLIM SLIP SLIT SLOB SLOE SLOG SLOP SLOT SLOW SLUB SLUE SLUG SLUM SLUR SLUT SMEE SMEW SMIR SMIT SMOG SMUG SMUR SMUT SNAB SNAG SNAP SNAR SNAW SNEB SNED SNEE SNIB SNIG SNIP SNIT SNOB SNOD SNOG SNOT SNOW SNUB SNUG SNYE SOAK SOAP SOAR SOBS SOCA SOCK SOCS SODA SODS SOFT SOGS SOHO SOHS SOIL SOJA SOKE SOLA SOLD SOLE SOLI SOLO SOLS SOMA SONE SONG SONS SOOK SOOM SOON SOOP SOOT SOPH SOPS SORA SORB SORD SORE SORN SORT SOSS SOTH SOTS SOUK SOUL SOUM SOUP SOUR SOUS SOUT SOVS SOWF SOWM SOWN SOWP SOWS SOYA SOYS SPAE SPAG SPAM SPAN SPAR SPAS SPAT SPAW SPAY SPEC SPED SPEK SPET SPEW SPIC SPIE SPIK SPIN SPIT SPIV SPOT SPRY SPUD SPUN SPUR SRIS STAB STAG STAP STAR STAT STAW STAY STED STEM STEN STEP STET STEW STEY STIE STIR STOA STOB STOP STOT STOW STUB STUD STUM STUN SUBA SUBS SUCH SUCK SUDD SUDS SUED SUER SUES SUET SUGH SUID SUIT SUKH SULK SULU SUMO SUMP SUMS SUNG SUNK SUNN SUNS SUPE SUPS SUQS SURA SURD SURF SUSS SWAB SWAD SWAG SWAM SWAN SWAP SWAT SWAY SWEE SWEY SWIG SWIM SWIZ SWOB SWOP SWOT SWUM SYBO SYCE SYED SYEN SYES SYKE SYLI SYNC SYND SYNE SYPE SYPH 20 | TABI TABS TABU TACE TACH TACK TACO TACT TADS TAED TAEL TAES TAGS TAHA TAHR TAIL TAIN TAIS TAIT TAKA TAKE TAKI TAKS TAKY TALA TALC TALE TALI TALK TALL TAME TAMP TAMS TANA TANE TANG TANH TANK TANS TAOS TAPA TAPE TAPS TAPU TARA TARE TARN TARO TARP TARS TART TASH TASK TASS TATE TATH TATS TATT TATU TAUS TAUT TAVA TAVS TAWA TAWS TAWT TAXA TAXI TAYS TEAD TEAK TEAL TEAM TEAR TEAS TEAT TECH TEDS TEDY TEED TEEL TEEM TEEN TEER TEES TEFF TEFS TEGG TEGS TEGU TEHR TEIL TELA TELD TELE TELL TELS TELT TEMP TEMS TEND TENE TENS TENT TEPA TERF TERM TERN TEST TETE TETH TETS TEXT THAE THAN THAR THAT THAW THEE THEM THEN THEW THEY THIG THIN THIO THIS THON THOU THRO THRU THUD THUG THUS TIAR TICE TICH TICK TICS TIDE TIDY TIED TIER TIES TIFF TIFT TIGE TIGS TIKA TIKE TIKI TILE TILL TILS TIME TIND TINE TING TINK TINS TINT TINY TIPI TIPS TIPT TIRE TIRL TIRO TITE TITI TITS TIVY TIZZ TOAD TOBY TOCK TOCO TOCS TODS TODY TOEA TOED TOEY TOFF TOFT TOFU TOGA TOGE TOGS TOHO TOIL TOIT TOKE TOKO TOLA TOLD TOLL TOLT TOLU TOMB TOME TOMS TONE TONG TONK TONS TONY TOOK TOOL TOOM TOOT TOPE TOPH TOPI TOPS TORA TORC TORE TORI TORN TORO TORR TORS TORT TOSA TOSE TOSH TOSS TOST TOTE TOTS TOUK TOUN TOUR TOUT TOWN TOWS TOWT TOYO TOYS TOZE TRAD TRAM TRAP TRAT TRAY TREE TREF TREK TRES TRET TREW TREZ TRIE TRIG TRIM TRIN TRIO TRIP TROD TROG TRON TROP TROT TROW TROY TRUG TRYE TRYP TSAR TSKS TUAN TUBA TUBA TUBS TUCK TUFA TUFF TUFT TUGS TULE TUMP TUMS TUNA TUND TUNE TUNG TUNS TUNY TUPS TURD TURF TURK TURM TURN TUSH TUSK TUTS TUTU TUZZ TWAE TWAL TWAS TWAT TWAY TWEE TWIG TWIN TWIT TWOS TYDE TYED TYEE TYER TYES TYGS TYKE TYMP TYND TYNE TYPE TYPO TYPP TYPY TYRE TYRO TYTE TZAR 21 | UDAL UDOS UEYS UFOS UGHS UGLI UGLY UKES ULAN ULES ULEX ULNA ULUS ULVA UMBO UMPH UMPS UNAI UNAU UNBE UNCE UNCI UNCO UNDE UNDO UNDY UNIS UNIT UNTO UPAS UPBY UPDO UPGO UPON UPSY URAO URBS URDE URDS URDY UREA URES URGE URIC URNS URSA URUS URVA USED USER USES UTAS UTES UTIS UTUS UVAE UVAS UVEA 22 | VACS VADE VAES VAGI VAIL VAIN VAIR VALE VALI VAMP VANE VANG VANS VANT VARA VARE VARS VARY VASA VASE VAST VATS VATU VAUS VAUT VAVS VAWS VEAL VEEP VEER VEES VEGA VEHM VEIL VEIN VELA VELD VELE VELL VENA VEND VENT VERA VERB VERS VERT VERY VEST VETO VETS VEXT VIAE VIAL VIAS VIBE VIBS VICE VIDE VIDS VIED VIER VIES VIEW VIGA VIGS VILD VILE VILL VIMS VINA VINE VINO VINS VINT VINY VIOL VIRE VIRL VISA VISE VITA VITE VIVA VIVE VIVO VIZY VLEI VOAR VOES VOID VOLA VOLE VOLK VOLS VOLT VORS VOTE VOWS VRIL VROW VUGG VUGH VUGS VULN VUMS 23 | WABS WACK WADD WADE WADI WADS WADT WADY WAES WAFF WAFT WAGE WAGS WAID WAIF WAIL WAIN WAIR WAIT WAKA WAKE WAKF WALD WALE WALI WALK WALL WALY WAME WAND WANE WANG WANK WANS WANT WANY WAPS WAQF WARD WARE WARK WARM WARN WARP WARS WART WARY WASE WASH WASM WASP WAST WATE WATS WATT WAUK WAUL WAUR WAVE WAVY WAWE WAWL WAWS WAXY WAYS WEAK WEAL WEAN WEAR WEBS WEDS WEED WEEK WEEL WEEM WEEN WEEP WEER WEES WEET WEFT WEID WEIL WEIR WEKA WELD WELK WELL WELT WEMB WEMS WEND WENS WENT WEPT WERE WERT WEST WETA WETS WEXE WEYS WHAM WHAP WHAT WHEE WHEN WHET WHEW WHEY WHID WHIG WHIM WHIN WHIP WHIR WHIT WHIZ WHOA WHOM WHOP WHOT WHOW WHYS WICE WICH WICK WIDE WIEL WIFE WIGS WILD WILE WILI WILL WILT WILY WIMP WIND WINE WING WINK WINN WINO WINS WINY WIPE WIRE WIRY WISE WISH WISP WISS WIST WITE WITH WITS WIVE WOAD WOCK WOES WOGS WOKE WOKS WOLD WOLF WOMB WONK WONS WONT WOOD WOOF WOOL WOON WOOS WOOT WOPS WORD WORE WORK WORM WORN WORT WOST WOTS WOVE WOWF WOWS WRAP WREN WRIT WUDS WULL WUSS WYCH WYES WYLE WYND WYNN WYNS WYTE 24 | XYST 25 | YACK YAFF YAGI YAHS YAKS YALD YALE YAMS YANG YANK YAPP YAPS YARD YARE YARN YARR YATE YAUD YAUP YAWL YAWN YAWP YAWS YAWY YAYS YBET YEAD YEAH YEAN YEAR YEAS YECH YEDE YEED YEGG YELD YELK YELL YELM YELP YELT YENS YEPS YERD YERK YESK YEST YETI YETT YEUK YEVE YEWS YGOE YIDS YIKE YILL YINS YIPE YIPS YIRD YIRK YIRR YITE YLEM YLKE YMPE YMPT YOBS YOCK YODE YODH YODS YOGA YOGH YOGI YOKE YOKS YOLD YOLK YOMP YOND YONI YONT YOOF YORE YORK YOUK YOUR YOWE YOWL YOWS YUAN YUCA YUCH YUFT YUGA YUGS YUKE YUKO YUKS YUKY YULE YUMP YUNX YUPS YURT YWIS 26 | ZACK ZAGS ZANY ZAPS ZARF ZATI ZEAL ZEAS ZEBU ZEDS ZEES ZEIN ZEKS ZELS ZERK ZERO ZEST ZETA ZEZE ZHOS ZIFF ZIGS ZILA ZILL ZIMB ZINC ZINE ZING ZINS ZIPS ZITE ZITI ZITS ZIZZ ZEBO ZOBU ZOEA ZOIC ZONA ZONE ZONK ZOOM ZOON ZOOS ZOPP ZORI ZOUK ZULU ZUPA ZURF ZYGA ZYME -------------------------------------------------------------------------------- /data/sowpods_endhooks_2.dat: -------------------------------------------------------------------------------- 1 | AA AAH AAL 2 | AB ABA ABB ABO ABY AD ADZ 3 | AE AG AGA AH AHA 4 | AI AIA AIN AIT 5 | AL ALA ALB ALP ALT AM AMA AMI AMP AMU 6 | AN ANA ANE ANI ANN AR ARB ARD ARF ARY 7 | AS AT ATT 8 | AW AWA AWL AWN 9 | AX AY AYU BA BAA BAH BAL BAM BAP BE BEL BEN BEY BEZ BI BIO BIZ BO BOD BOH BOK BON BOP BOR BOT BY CH CHA CHE CHI DA DAE DAH DAK DAL DAN DAP DAW DE DEB DEE DEF DEI DEL DEV DEX DEY DI DIB DIT DIV DO DOC DOD DOH DOL DOM DOO DOP DOR DOW EA EAN EAU 10 | ED EDH EE EEK EEN EF EFF EFT 11 | EH EL ELD ELL ELT 12 | EM EME EMF 13 | EN ENE ENG ER ERE ERF ERG ERK ERN 14 | ES ESS EST ET ETA ETH EX FA FAB FAH FAP FAW FAY FY GI GIB GID GIE GIF GIO GIP GIT GO GOA GOE GON GOO GOR GOV GOX GOY GU GUB GUE GUL GUP GUR GUV HA HAE HAH HAJ HAN HAO HAP HAW 15 | HE HEH HEP HET HEY 16 | HI HIC HIE HIN HO HOA HOB HOC HOD HOH HOI HON HOO HOX HOY HM HMM ID IDE 17 | IF IFF IN IO IS ISH ISM ISO 18 | IT ITA JO JOE JOR JOW KA KAB KAE KAF KAI KAM KAT KAW KAY 19 | KO KOA KOB KOI KON KOP KOR KOS KOW 20 | KY KYE KYU LA LAB LAC LAH LAM LAR LAT LAV 21 | LI LIB LIG LIN LO LOO LOR LOX LOY MA MAA MAC MAE MAG MAK MAL MAM MAW MAX 22 | ME MED MEG MEL MEM MEU MEW 23 | MI MIB MIG MIL MIM MIR MIZ 24 | MM MO MOA MOD MOC MOE MOG MOI MOL MOM MON MOR MOT MOU MOY MOZ MU MUN MUT MUX MY NA NAE NAH NAM NAN NAT NAW NAY 25 | NE NEB NED NEE NEF NEK NEP 26 | NO NOB NOG NOH NOM NON NOO NOX NOY NU NUB NUR 27 | NY NYE OB OBA OBE OBI OBO OD ODA OE OF OFT 28 | OH OHM OHO 29 | OI OIK OM ON OO OOF OOH OOM OON OOP OOR OOT OP OPE OR ORA ORC ORD ORF ORT OS OSE OU OUD OUK OUP OW OWT OX OXO OXY OY OYE PA PAC PAH PAM PAP PAX PE PEC PED PEE PEH PH PHI PHO PHT PI PIA PIC PIR PIU PIX PO POA POH POI POL POM POO POW POZ QI RE REB REC REE REF REG REH REI REM REN REP RES RET REV REW REX REZ SH SHA SHH SI SIB SIC SIM SO SOC SOG SOH SOL SOP SOT SOU SOV SOX SOY ST TA TAD TAE TAI TAJ TAK TAM TAO TAT TAU TAV TAW TAY TE TED TEF TEG TEL TET TEW TI TIC TID TIG TIL TO TOC TOD TOM TOR UG UGH UH UM UMM UMP UN UNI UP UPO UR URB URD URE US UT UTA UTE UTU WE WEM WEN WEX WEY WO WOK WOP WOT WOX XI XU YA YAH YAR YAW YAY YE YEA YEH YEP YEW YEX YO YOB YOD YOK YOM YON YOW YU YUG YUK YUM YUP ZO ZOA -------------------------------------------------------------------------------- /data/sowpods_endhooks_3.dat: -------------------------------------------------------------------------------- 1 | ABA ABAC 2 | ABB ABBA ABBE 3 | ABY ABYE 4 | ACE ACER 5 | ACH ACHY 6 | ACT ACTA 7 | ADZ ADZE 8 | AFF AFFY 9 | AGE AGEE AGEN AGER 10 | AGO AGOG AGON 11 | AID AIDE 12 | AIN AINE 13 | AIR AIRN AIRT AIRY 14 | AIT AITU 15 | AKE AKEE 16 | ALB ALBA ALBE 17 | ALA ALAE ALAN ALAP ALAR ALAY 18 | ALE ALEC ALEE ALEF ALEW 19 | ALT ALTO 20 | AMA AMAH 21 | AMI AMIA AMIE AMIN AMIR 22 | ANE ANEW 23 | ANN ANNO 24 | ANT ANTA ANTI 25 | APE APER 26 | ARC ARCO 27 | ARE ARED AREG ARET AREW 28 | ARS ARSE 29 | ART ARTY 30 | ARY ARYL 31 | ASH ASHY 32 | AVA AVAL 33 | AVE AVER 34 | AWE AWEE 35 | AWN AWNY 36 | AZO AZON 37 | BAD BADE 38 | BAH BAHT 39 | BAL BALE BALK BALM BALU 40 | BAN BANC BANI BANT 41 | BAP BAPU 42 | BAR BARD BARF BARM BARP 43 | BAS BAST 44 | BAT BATE BATT 45 | BAY BAYE BAYT 46 | BED BEDE BEDU 47 | BEG BEGO 48 | BEN BENE BENI BENJ 49 | BET BETE BETH 50 | BIG BIGA BIGG 51 | BIN BINE BING BINK BINT 52 | BIO BIOG 53 | BIS BISE BISH BISK 54 | BIT BITO BITT 55 | BIZ BIZE 56 | BOB BOBA 57 | BOD BODE 58 | BOG BOGY 59 | BOK BOKE BOKO 60 | BON BONA BONK BONY 61 | BOO BOOB BOOL BOOR 62 | BOR BORA BORD BORT 63 | BOS BOSH BOSK 64 | BOT BOTA BOTT 65 | BOW BOWR 66 | BOX BOXY 67 | BRA BRAD BRAE BRAW 68 | BRO BROD BROO BROG 69 | BRR BRRR 70 | BUB BUBA BUBO 71 | BUD BUDO 72 | BUM BUMF 73 | BUN BUND BUNN BUNT 74 | BUR BURA BURD BURG BURK BURL 75 | BUS BUSK BUSS 76 | BUT BUTE 77 | CAB CABA 78 | CAD CADE CADI 79 | CAN CANG CANN CANY 80 | CAP CAPA CAPH CAPI CAPO 81 | CAR CARB CARK CARL CARN CARR 82 | CAT CATE 83 | CAW CAWK 84 | CEL CELT 85 | CEP CEPE 86 | CHA CHAD CHAI CHAL CHAM CHAO CHAW CHAY 87 | CHE CHER CHEZ 88 | CHI CHIA CHID CHIK CHIV CHIZ 89 | CIS CIST 90 | CIT CITO 91 | COB COBB 92 | COD CODA 93 | COL COLA COLE COLL COLY 94 | CON COND CONK CONI CONN CONY 95 | COO COOF COOM COON 96 | COR CORF CORM CORY 97 | COS COSE COSH COSS 98 | COT COTE COTH COTT 99 | COW COWP COWY 100 | COX COXA COXY 101 | COZ COZE COZY 102 | CUR CURD CURF CURN CURR 103 | DAD DADA DADO 104 | DAG DAGO 105 | DAH DAHL 106 | DAL DALI DALT 107 | DAN DANG DANT 108 | DAW DAWD DAWK DAWT 109 | DEE DEEK DEEN DEET DEEV 110 | DEF DEFI 111 | DEI DEID DEIL 112 | DEL DELE DELF DELI DELT 113 | DEV DEVA 114 | DEW DEWY 115 | DEX DEXY 116 | DID DIDO DIDY 117 | DIE DIEB DIEL 118 | DIN DINK 119 | DIP DIPT 120 | DIS DISA DISS 121 | DIT DITA DITE DITT DITZ 122 | DIV DIVA DIVI 123 | DOB DOBY 124 | DOD DODO 125 | DOE DOEK DOEN DOER 126 | DOG DOGE DOGY 127 | DOL DOLE 128 | DOM DOMY 129 | DON DONA 130 | DOO DOOB DOOK DOOL 131 | DOP DOPA DOPY 132 | DOR DORE DORK DORM DORP DORR DORT DORY 133 | DOS DOSH DOSS DOST 134 | DOT DOTH DOTY 135 | DOW DOWD DOWF DOWL DOWP DOWT 136 | DUI DUIT 137 | DUN DUNK DUNT 138 | DYE DYER 139 | EAR EARD 140 | EAT EATH 141 | EAU EAUX 142 | ECH ECHE ECHT 143 | EEL EELY 144 | EGG EGGY 145 | ELM ELMY 146 | EME EMEU 147 | ENE ENEW 148 | ERG ERGO 149 | ERN ERNE 150 | ERS ERST 151 | ESS ESSE 152 | ETA ETAT 153 | ETH ETHE 154 | EYE EYEN EYER 155 | FAD FADO FADY 156 | FAN FAND FANE FANK FANO 157 | FAR FARD FARO FARL FART 158 | FAS FASH 159 | FEE FEER 160 | FEM FEME 161 | FEN FENI FENT 162 | FER FERE FERM 163 | FET FETA FETT 164 | FID FIDO 165 | FIE FIEF 166 | FIG FIGO 167 | FIL FILA FILO 168 | FIN FINI FINK FINO 169 | FIR FIRK FIRN 170 | FIT FITT 171 | FIX FIXT 172 | FLU FLUB FLUE 173 | FOE FOEN 174 | FOG FOGY 175 | FOH FOHN 176 | FON FONE 177 | FOR FORA FORB 178 | FOU FOUD 179 | FOX FOXY 180 | FRA FRAB FRAE FRAG FRAP FRAT FRAU 181 | FRO FROE FROW 182 | FUG FUGU 183 | FUM FUMY 184 | FUN FUNG FUNK 185 | FUR FURL FURR 186 | GAB GABY 187 | GAE GAED GAEN 188 | GAD GADE GADI 189 | GAG GAGA GAGE 190 | GAM GAMA GAMB GAMP GAMY 191 | GAN GANE 192 | GAP GAPO GAPY 193 | GAR GARB GARE GART 194 | GAS GAST 195 | GAT GATH 196 | GAU GAUD GAUM GAUN GAUP GAUR 197 | GEE GEEK GEEP GEEZ 198 | GEL GELD GELT 199 | GEN GENA GENE GENU 200 | GET GETA 201 | GIB GIBE 202 | GIE GIEN 203 | GIG GIGA 204 | GIN GING GINK GINN 205 | GIS GISM 206 | GIT GITE 207 | GOB GOBO GOBY 208 | GOE GOEL GOER GOEY 209 | GON GONK 210 | GOO GOOK GOOL GOON GOOP GOOR 211 | GOR GORM GORP GORY 212 | GOS GOSH 213 | GUL GULE GULY 214 | GUM GUMP 215 | GUN GUNK 216 | GUR GURL GURN GURU 217 | GYM GYMP 218 | HAD HADE HADJ 219 | HAE HAEM HAEN HAET 220 | HAG HAGG 221 | HAJ HAJI 222 | HAM HAME 223 | HAN HANK HANT 224 | HAS HASK HASP HAST 225 | HAT HATH 226 | HAW HAWM 227 | HEM HEME 228 | HEN HEND HENT 229 | HEP HEPT 230 | HER HERL HERM HERN HERY 231 | HES HESP HEST 232 | HET HETE HETH 233 | HEW HEWN 234 | HIN HING 235 | HIP HIPT 236 | HIS HISH HISN HIST 237 | HOA HOAR 238 | HOC HOCK 239 | HOE HOER 240 | HOG HOGG HOGH 241 | HON HOND HONG 242 | HOO HOON 243 | HOS HOSS 244 | HOT HOTE 245 | HOW HOWE HOWF HOWK 246 | HOY HOYA 247 | HUE HUED HUER 248 | HUG HUGY 249 | HUI HUIA HUIC 250 | HUM HUMA HUMF 251 | HUN HUNH 252 | HYE HYEN 253 | HYP HYPO 254 | ICE ICER 255 | ICK ICKY 256 | IDE IDEE IDEM 257 | IFF IFFY 258 | ILK ILKA 259 | ILL ILLY 260 | IMP IMPI 261 | INK INKY 262 | JAG JAGG 263 | JAK JAKE 264 | JAM JAMB 265 | JAP JAPE 266 | JAR JARK JARL 267 | JEE JEEL JEEP JEEZ 268 | JET JETE 269 | JEU JEUX 270 | JIB JIBB JIBE 271 | JIN JINK JINN JINX 272 | JOB JOBE 273 | JOE JOEY 274 | JOT JOTA 275 | JUD JUDY 276 | JUG JUGA 277 | KAI KAID KAIE KAIF KAIL KAIM KAIN 278 | KAM KAMA KAME KAMI 279 | KAT KATA KATI 280 | KAY KAYO 281 | KEN KENO KENT 282 | KEP KEPI 283 | KET KETA KETO 284 | KIN KINA KINE KINO 285 | KIP KIPE KIPP 286 | KIR KIRN 287 | KOA KOAN 288 | KOB KOBO 289 | KON KOND 290 | KOP KOPH 291 | KOR KORE 292 | KOS KOSS 293 | LAC LACY 294 | LAD LADE 295 | LAR LARE LARI LARN 296 | LAS LASE 297 | LAT LATH LATI 298 | LAV LAVE 299 | LAW LAWK 300 | LEA LEAL LEAM LEAR LEAT 301 | LEE LEEP LEET 302 | LEI LEIR 303 | LEK LEKE LEKU 304 | LEP LEPT 305 | LES LEST 306 | LEU LEUD 307 | LEV LEVA LEVE LEVO 308 | LEW LEWD 309 | LID LIDO 310 | LIE LIEF LIEN LIER LIEU 311 | LIN LIND LING LINO LINN LINY 312 | LIS LISK 313 | LIT LITE LITH LITU 314 | LOB LOBI LOBO 315 | LOG LOGE LOGO LOGY 316 | LOO LOOF LOON LOOR 317 | LOR LORE LORN LORY 318 | LOS LOSH 319 | LOT LOTA LOTE LOTH LOTI LOTO 320 | LOW LOWE LOWN LOWT 321 | LUD LUDE LUDO 322 | LUX LUXE 323 | LYM LYME 324 | MAA MAAR 325 | MAC MACH MACK 326 | MAG MAGE MAGG MAGI 327 | MAK MAKO 328 | MAL MALI MALM 329 | MAM MAMA 330 | MAN MANA MAND MANG MANI MANO 331 | MAR MARA MARC MARD MARG MARL MARM MARY 332 | MAS MASA MASE MASU 333 | MAT MATT MATY 334 | MAW MAWK MAWN MAWR 335 | MAX MAXI 336 | MAY MAYA MAYO 337 | MEG MEGA 338 | MEL MELA MELD MELL 339 | MEN MENE MENG MENO MENT 340 | MES MESA MESE 341 | MET META METH 342 | MEW MEWL 343 | MID MIDI 344 | MEM MEMO 345 | MIG MIGG 346 | MIL MILO MILT 347 | MIR MIRI MIRK MIRV MIRY 348 | MIS MISE MISO 349 | MIX MIXT MIXY 350 | MOC MOCH 351 | MOD MODI 352 | MOI MOIL MOIT 353 | MOL MOLA MOLD MOLL MOLT MOLY 354 | MOM MOME MOMI 355 | MON MONA MONO MONG MONY 356 | MOO MOOI MOOK MOOL MOOP 357 | MOP MOPY 358 | MOR MORA MORN MORT 359 | MOS MOSE MOSK 360 | MOT MOTE MOTT MOTU 361 | MOU MOUE 362 | MOW MOWA 363 | MOY MOYA MOYL 364 | MOZ MOZE MOZO 365 | MUG MUGG 366 | MUM MUMP MUMU 367 | MUN MUNI MUNT 368 | MUS MUSO MUSS 369 | MUT MUTI MUTT 370 | NAB NABE NABK 371 | NAG NAGA 372 | NAN NANA 373 | NAP NAPA 374 | NEE NEEM NEEP 375 | NET NETE 376 | NID NIDE NIDI 377 | NIE NIEF 378 | NIL NILL 379 | NIM NIMB 380 | NIP NIPA 381 | NIS NISI 382 | NIT NITE 383 | NIX NIXE NIXY 384 | NOD NODI 385 | NOG NOGG 386 | NOM NOMA NOME 387 | NON NONA NONG 388 | NOO NOOP 389 | NOR NORI NORK 390 | NOS NOSH 391 | NOT NOTA NOTT 392 | NOW NOWL NOWN NOWT NOWY 393 | NUR NURD NURL NURR 394 | OAK OAKY 395 | OAR OARY 396 | OBI OBIA OBIT 397 | OBO OBOL 398 | ODA ODAL 399 | ODE ODEA 400 | ODS ODSO 401 | OKE OKEH 402 | ORC ORCA 403 | OLD OLDY 404 | OLE OLEA OLEO 405 | ONE ONER 406 | ONS ONST 407 | OON OONT 408 | OOS OOSE OOSY 409 | ORA ORAD 410 | ORB ORBY 411 | ORD ORDO 412 | ORF ORFE 413 | OUP OUPH 414 | OUR OURN 415 | OWE OWER 416 | OWL OWLY 417 | OYE OYER OYES OYEZ 418 | PAC PACA PACO PACY 419 | PAD PADI 420 | PAL PALL PALP PALY 421 | PAN PAND 422 | PAP PAPA PAPE 423 | PAR PARA PARD PARP PARR 424 | PAS PASE PASH 425 | PAT PATE PATY 426 | PAW PAWA PAWK PAWL 427 | PEA PEAG PEAN 428 | PEC PECH 429 | PEE PEEN 430 | PEG PEGH 431 | PEN PENE PENI PENK 432 | PEP PEPO 433 | PER PERE PERI PERN PERT PERV 434 | PES PESO 435 | PHI PHIZ 436 | PHO PHON PHOT 437 | PIA PIAL PIAN 438 | PIC PICA PICE 439 | PIE PIET 440 | PIN PINA PINY 441 | PIP PIPA PIPI PIPY 442 | PIR PIRL PIRN 443 | PIS PISE PISH PISO PISS 444 | PIT PITA 445 | PIU PIUM 446 | PIX PIXY 447 | POL POLK POLO POLT POLY 448 | POM POME 449 | POO POOD POOF POOH POOK POON POOP POOT 450 | POP POPE 451 | POS POSS POSY 452 | POT POTE POTT 453 | POW POWN 454 | POX POXY 455 | PRE PREE PREP PREX PREZ 456 | PRO PROA PROB PROG PROM PROO PROW 457 | PRY PRYS 458 | PUG PUGH 459 | PUL PULA PULE PULI PULK PULY 460 | PUN PUNA PUNG 461 | PUP PUPA 462 | PUR PURI PURL 463 | PUS PUSS 464 | PUT PUTZ 465 | PYA PYAT 466 | QUA QUAG QUAI QUAT 467 | RAD RADE 468 | RAG RAGA RAGG RAGI 469 | RAI RAIK RAIT 470 | RAJ RAJA 471 | RAM RAMI 472 | RAN RANA RANI 473 | RAS RASE RAST 474 | RAT RATA RATH RATO RATU 475 | RAW RAWN 476 | RAY RAYA 477 | REC RECK 478 | RED REDD REDE REDO 479 | REE REEN 480 | REF REFT 481 | REI REIF REIK 482 | REN REND RENY 483 | REP REPO REPP 484 | RES RESH 485 | RET RETE 486 | RIA RIAL 487 | RIF RIFF 488 | RIG RIGG 489 | RIM RIMA RIME RIMU RIMY 490 | RIN RINE 491 | RIP RIPP RIPT 492 | RIT RITT RITZ 493 | RIZ RIZA 494 | ROC ROCH 495 | ROE ROED 496 | ROK ROKE ROKY 497 | ROM ROMA 498 | ROO ROON ROOP 499 | ROT ROTA ROTE ROTI ROTO ROTL 500 | ROW ROWT 501 | RUB RUBE RUBY 502 | RUD RUDD 503 | RUE RUER 504 | RUG RUGA 505 | RUM RUME 506 | RUN RUND RUNE 507 | RUT RUTH 508 | RYA RYAL 509 | SAB SABE 510 | SAD SADE SADI 511 | SAG SAGO SAGY 512 | SAI SAIC SAIM SAIN SAIR 513 | SAL SALL SALP 514 | SAM SAMA SAMP 515 | SAN SANT 516 | SAR SARD SARI SARK 517 | SAT SATE SATI 518 | SAU SAUL SAUT 519 | SEA SEAN SEAR 520 | SEC SECO 521 | SEE SEEL SEER 522 | SEG SEGO 523 | SEI SEIF SEIK SEIL SEIR 524 | SEL SELD SELE 525 | SEN SENA SENE 526 | SER SERA SERE SERF SERK 527 | SET SETA SETT 528 | SEX SEXT 529 | SHA SHAN SHAT SHAW SHAY 530 | SHE SHEA SHET SHEW 531 | SIB SIBB 532 | SIC SICE SICH 533 | SIM SIMA SIMI SIMP 534 | SIN SIND SINE SINH 535 | SIP SIPE 536 | SIS SISS SIST 537 | SIT SITH 538 | SKA SKAG SKAT 539 | SKI SKIO 540 | SKY SKYR 541 | SOC SOCA 542 | SOH SOHO 543 | SOL SOLA SOLI 544 | SON SONE 545 | SOP SOPH 546 | SOS SOSS 547 | SOT SOTH 548 | SOU SOUM SOUT 549 | SOW SOWF SOWL SOWM SOWP 550 | SOY SOYA 551 | SPA SPAE SPAG SPAR SPAW SPAY SPAZ 552 | SUB SUBA 553 | SUD SUDD 554 | SUE SUER SUET 555 | SUI SUID 556 | SUK SUKH 557 | SUM SUMO 558 | SUN SUNN 559 | SUP SUPE 560 | SUR SURA SURD 561 | SUS SUSS 562 | SYE SYEN 563 | SYN SYNC SYND SYNE 564 | TAB TABI TABU 565 | TAE TAEL 566 | TAI TAIN TAIT 567 | TAK TAKA TAKI TAKY 568 | TAM TAMP 569 | TAN TANA TANE TANH 570 | TAP TAPA TAPU 571 | TAR TARA TARN TARO TARP 572 | TAS TASH TASS 573 | TAT TATE TATH TATT TATU 574 | TAV TAVA 575 | TAW TAWA TAWT 576 | TAX TAXA 577 | TEA TEAD 578 | TED TEDY 579 | TEE TEEL TEEN TEER 580 | TEF TEFF 581 | TEG TEGG TEGU 582 | TEL TELA TELD TELE TELT 583 | TEN TENE 584 | TET TETE TETH 585 | THE THEW 586 | THO THON THOU 587 | TIC TICH 588 | TIG TIGE 589 | TIN TIND TING TINK 590 | TIP TIPI TIPT 591 | TIT TITE TITI 592 | TOC TOCK TOCO 593 | TOD TODY 594 | TOE TOEA TOEY 595 | TOG TOGE 596 | TOM TOME 597 | TON TONK TONY 598 | TOO TOOM TOON 599 | TOP TOPE TOPH TOPI 600 | TOR TORI TORO TORR TORT TORY 601 | TOW TOWT TOWY 602 | TOY TOYO 603 | TRY TRYE TRYP 604 | TUM TUMP 605 | TUN TUND TUNG TUNY 606 | TUT TUTU 607 | TWA TWAE TWAL TWAY 608 | TYE TYEE TYER 609 | ULE ULEX 610 | UPS UPSY 611 | URD URDE URDY 612 | URE UREA 613 | UVA UVAE 614 | VAN VANG VANT 615 | VAR VARA VARE 616 | VAS VASA 617 | VAT VATU 618 | VAU VAUT 619 | VEE VEEP 620 | VEG VEGA 621 | VEX VEXT 622 | VIA VIAE 623 | VID VIDE 624 | VIE VIER 625 | VIG VIGA 626 | VIN VINA VINO VINT VINY 627 | VIS VISE 628 | VOL VOLA VOLE 629 | VUG VUGG VUGH 630 | WAD WADD WADI WADT WADY 631 | WAN WANG WANY 632 | WAR WARK 633 | WAS WASE WASM WAST 634 | WAT WATE 635 | WAW WAWE WAWL 636 | WAX WAXY 637 | WEE WEEL WEEM WEEN WEER WEET 638 | WEM WEMB 639 | WET WETA 640 | WEX WEXE 641 | WHA WHAM 642 | WHO WHOA WHOT WHOW 643 | WIN WINN WINO WINY 644 | WIS WISS WIST 645 | WIT WITE 646 | WON WONK WONT 647 | WOO WOON WOOT 648 | WOS WOST 649 | WOW WOWF 650 | WUS WUSS 651 | WYN WYND WYNN 652 | YAP YAPP 653 | YAR YARE YARR 654 | YAW YAWL YAWP YAWY 655 | YEA YEAD YEAH YEAN 656 | YES YESK YEST 657 | YET YETI YETT 658 | YGO YGOE 659 | YIP YIPE 660 | YOD YODE YODH 661 | YON YOND YONI YONT 662 | YOU YOUK 663 | YOW YOWE YOWL 664 | YUG YUGA 665 | YUK YUKE YUKO YUKY 666 | YUM YUMP 667 | ZIT ZITE ZITI -------------------------------------------------------------------------------- /data/sowpods_fronthooks_2.dat: -------------------------------------------------------------------------------- 1 | AA BAA MAA 2 | AB FAB GAB KAB LAB SAB WAB AD RAD TAD 3 | AE DAE GAE HAE KAE MAE NAE SAE TAE VAE WAE 4 | AG MAG AH AAH BAH DAH FAH HAH LAH NAH PAH RAH YAH AI KAI RAI SAI TAI 5 | AL AAL BAL DAL GAL MAL SAL AM BAM CAM GAM KAM LAM MAM NAM PAM SAM TAM 6 | AN DAN EAN GAN HAN NAN SAN AR GAR LAR SAR VAR YAR 7 | AS RAS VAS 8 | AT GAT KAT LAT NAT QAT TAT WAT 9 | AW CAW DAW FAW HAW KAW MAW NAW TAW VAW WAW YAW 10 | AX MAX PAX RAX SAX ZAX 11 | AY CAY FAY JAY KAY NAY TAY YAY BA ABA OBA 12 | BE OBE 13 | BI OBI 14 | BO ABO OBO 15 | BY ABY CH ACH ECH ICH OCH DA ODA 16 | DE IDE 17 | DI DO UDO EA KEA LEA YEA ZEA 18 | ED GED KED MED NED PED SED TED ZED 19 | EE CEE DEE GEE JEE LEE NEE PEE REE VEE ZEE EF DEF KEF NEF REF TEF EH FEH HEH PEH REH YEH EL BEL CEL DEL GEL MEL SEL TEL ZEL 20 | EM FEM MEM REM WEM 21 | EN BEN EEN GEN KEN REN SEN WEN ER FER SER 22 | ES LES 23 | ET FET HET KET RET TET 24 | EX DEX KEX LEX REX WEX YEX ZEX FA FY GI GO YGO 25 | GU HA AHA CHA SHA WHA 26 | HE CHE 27 | HI CHI GHI KHI PHI 28 | HM OHM 29 | HO MHO OHO PHO RHO THO ZHO ID CID FID GID NID TID VID YID 30 | IF GIF KIF RIF 31 | IN AIN HIN JIN LIN RIN VIN YIN ZIN 32 | IO BIO GIO 33 | IS CIS NIS VIS WIS 34 | IT AIT CIT DIT GIT NIT RIT ZIT JO KA OKA SKA 35 | KO KY LA ALA 36 | LI LO MA AMA SMA 37 | ME EME 38 | MI AMI 39 | MM HMM UMM 40 | MO MU AMU 41 | MY NA ANA MNA 42 | NE ANE ENE 43 | NO NU GNU 44 | NY SNY OB HOB KOB NOB YOB 45 | OD BOD DOD HOD MOD TOD YOD 46 | OE GOE JOE MOE ROE VOE 47 | OF OOF 48 | OH BOH DOH FOH HOH NOH OOH POH SOH 49 | OI HOI KOI MOI POI 50 | OM DOM MOM NOM OOM POM ROM TOM YOM 51 | ON BON FON GON HON ION KON MON NON OON VON YON 52 | OO DOO GOO HOO LOO NOO POO ROO 53 | OP BOP DOP KOP OOP SOP WOP 54 | OR BOR COR DOR GOR JOR KOR LOR MOR OOR TOR VOR 55 | OS COS 56 | OU FOU MOU SOU 57 | OW DOW JOW KOW POW YOW 58 | OX COX GOX HOX LOX NOX SOX VOX WOX 59 | OY FOY GOY HOY LOY MOY NOY SOY PA PE OPE 60 | PH PI PO UPO QI RE ERE PRE URE SH ISH 61 | SI PSI 62 | SO DSO ISO 63 | ST EST PST TA ETA ITA UTA 64 | TE UTE 65 | TI TO UG FUG VUG YUG 66 | UH PUH HUH 67 | UM CUM FUM LUM TUM VUM YUM 68 | UN DUN HUN JUN MUN TUN 69 | UP DUP GUP HUP OUP SUP TUP YUP 70 | UR BUR GUR LUR NUR PUR SUR 71 | US JUS PUS SUS WUS 72 | UT MUT WE WO XI XU YA PYA RYA 73 | YE HYE KYE LYE NYE OYE PYE SYE TYE WYE 74 | YO YU AYU KYU ZO AZO DZO -------------------------------------------------------------------------------- /data/sowpods_fronthooks_3.dat: -------------------------------------------------------------------------------- 1 | AAL BAAL 2 | AAS KAAS 3 | ABA BABA CABA 4 | ABY GABY 5 | ACE DACE TACE 6 | ACH BACH MACH NACH RACH TACH 7 | ADD WADD 8 | ADO DADO FADO 9 | AFF BAFF CAFF DAFF GAFF HAFF NAFF RAFF WAFF YAFF 10 | AFT BAFT HAFT 11 | AGA GAGA NAGA RAGA 12 | AGE GAGE MAGE 13 | AGO DAGO KAGO SAGO 14 | AHA HAHA TAHA 15 | AIA RAIA 16 | AID CAID GAID KAID QAID WAID 17 | AIL KAIL VAIL AIM KAIM SAIM 18 | AIN CAIN FAIN HAIN KAIN LAIN NAIN SAIN TAIN WAIN 19 | AIR GAIR MAIR SAIR VAIR WAIR 20 | AIS DAIS PAIS 21 | AIT RAIT TAIT 22 | AKE HAKE JAKE 23 | ALA NALA TALA 24 | ALE BALE EALE HALE KALE RALE VALE WALE YALE 25 | ALL LALL PALL SALL 26 | ALP CALP PALP SALP 27 | ALT DALT 28 | AMA GAMA LAMA MAMA SAMA 29 | AMI KAMI RAMI 30 | AMP GAMP SAMP TAMP VAMP 31 | ANA KANA LANA MANA NANA RANA TANA 32 | AND FAND MAND PAND ANE FANE GANE JANE TANE 33 | ANI BANI MANI RANI 34 | ANN CANN JANN 35 | ANT BANT DANT GANT HANT KANT LANT SANT VANT 36 | APE JAPE PAPE APT RAPT 37 | ARB CARB DARB GARB 38 | ARC MARC NARC 39 | ARD BARD EARD FARD MARD NARD PARD SARD 40 | ARE GARE LARE NARE VARE YARE 41 | ARF BARF ZARF 42 | ARK CARK JARK NARK SARK WARK 43 | ARM BARM MARM 44 | ART FART GART HART KART 45 | ARY MARY NARY OARY 46 | ASH FASH PASH TASH 47 | ASK HASK 48 | ASP HASP JASP 49 | ASS JASS SASS TASS 50 | ATE BATE CATE PATE SATE TATE WATE YATE 51 | ATT BATT MATT TATT 52 | AUF CAUF LAUF 53 | AUK BAUK CAUK JAUK WAUK 54 | AVA FAVA JAVA KAVA TAVA 55 | AVE EAVE FAVE LAVE NAVE 56 | AWA PAWA TAWA 57 | AWE WAWE 58 | AWL PAWL WAWL YAWL 59 | AWN BAWN MAWN RAWN 60 | AYE BAYE 61 | AZO LAZO 62 | BAR KBAR 63 | BED ABED 64 | BET ABET YBET 65 | BIT OBIT 66 | BON EBON 67 | BUT ABUT 68 | BYE ABYE 69 | CAD ECAD SCAD 70 | CAW SCAW 71 | CHE ECHE OCHE 72 | COD ECOD 73 | COG SCOG 74 | CON ICON 75 | COP SCOP 76 | COT SCOT 77 | COW SCOW 78 | CRU ECRU 79 | CRY SCRY 80 | CUD SCUD 81 | CUP SCUP 82 | CUR SCUR 83 | CUT SCUT 84 | DAL ODAL UDAL 85 | DAW ADAW 86 | DEE IDEE 87 | DIT ADIT 88 | DOR ODOR 89 | DRY ADRY 90 | DSO ODSO 91 | EAN GEAN PEAN REAN SEAN YEAN EAR LEAR SEAR 92 | EAS CEAS 93 | EAT GEAT JEAT LEAT 94 | EAU BEAU 95 | ECH EECH HECH LECH PECH TECH YECH ECO DECO SECO 96 | EEK DEEK GEEK 97 | EEL JEEL SEEL TEEL WEEL EEN DEEN PEEN REEN TEEN WEEN 98 | EFF JEFF TEFF 99 | EFT HEFT REFT WEFT 100 | EGG TEGG YEGG 101 | EGO BEGO SEGO REGO 102 | EIK REIK SEIK 103 | EKE DEKE LEKE PEKE REKE 104 | ELD GELD MELD SELD TELD VELD YELD 105 | ELF DELF PELF 106 | ELK WELK YELK 107 | ELL JELL KELL MELL PELL VELL 108 | ELM YELM 109 | ELT CELT DELT GELT KELT TELT YELT 110 | EME DEME FEME HEME LEME SEME TEME EMS TEMS 111 | END HEND REND 112 | ENE BENE DENE GENE MENE NENE PENE SENE TENE 113 | ENG LENG MENG 114 | ENS CENS LENS 115 | EON AEON JEON PEON 116 | ERA SERA VERA 117 | ERE BERE CERE DERE FERE GERE LERE PERE SERE 118 | ERF KERF SERF TERF 119 | ERG BERG 120 | ERK BERK MERK NERK SERK YERK ZERK 121 | ERN DERN HERN KERN PERN TERN 122 | ERR SERR 123 | ERS VERS 124 | ESS CESS FESS JESS NESS SESS 125 | EST FEST GEST HEST KEST LEST YEST 126 | ETA FETA GETA KETA META SETA WETA 127 | ETH BETH HETH METH TETH 128 | EUK NEUK YEUK EVE LEVE MEVE NEVE YEVE 129 | EWT NEWT 130 | FAY OFAY 131 | FRO AFRO 132 | GAD EGAD IGAD 133 | GAL EGAL 134 | GAM OGAM 135 | GAR AGAR 136 | GEE AGEE OGEE 137 | GEN AGEN 138 | GIN AGIN 139 | GIO AGIO GIS EGIS GOE YGOE GON AGON GUE AGUE HAD CHAD SHAD 140 | HAE THAE HAH SHAH HAM CHAM WHAM 141 | HAN KHAN SHAN 142 | HAO CHAO HAP WHAP 143 | HAT GHAT KHAT PHAT SHAT 144 | HAW CHAW SHAW 145 | HAY CHAY SHAY 146 | HEM AHEM 147 | HER CHER 148 | HET KHET SHET WHET 149 | HEW PHEW SHEW THEW WHEW 150 | HIC CHIC 151 | HID CHID WHID 152 | HIM SHIM 153 | HIN WHIN 154 | HIT SHIT WHIT 155 | HOA WHOA 156 | HOC CHOC 157 | HOD SHOD 158 | HOG SHOG 159 | HOH PHOH 160 | HON CHON PHON THON 161 | HOP WHOP 162 | HOT PHOT WHOT 163 | HOW DHOW WHOW 164 | HOY AHOY 165 | HUB CHUB 166 | HUG CHUG 167 | HUT BHUT CHUT PHUT 168 | ICE BICE PICE FICE SICE WICE 169 | ICK MICK 170 | ICY RICY 171 | ICH DICH LICH SICH TICH WICH IDE AIDE EIDE NIDE VIDE 172 | IFF BIFF JIFF MIFF NIFF RIFF ZIFF 173 | ILK BILK 174 | ILL CILL JILL LILL NILL RILL VILL YILL ZILL 175 | IMP GIMP JIMP SIMP 176 | INK BINK DINK FINK GINK JINK OINK TINK 177 | INN GINN JINN LINN WINN 178 | ION CION PION 179 | IRE CIRE LIRE VIRE 180 | IRK BIRK DIRK FIRK LIRK MIRK YIRK 181 | ISH BISH HISH KISH PISH 182 | ISM GISM JISM 183 | ISO MISO PISO 184 | ITA DITA PITA VITA 185 | IVY TIVY 186 | JEE AJEE 187 | JIN DJIN 188 | KAT IKAT SKAT 189 | KAW SKAW 190 | KAY OKAY 191 | KEG SKEG 192 | KEP SKEP 193 | KON IKON 194 | LAB BLAB 195 | LAD BLAD 196 | LAG BLAG 197 | LAH BLAH 198 | LAM BLAM FLAM GLAM 199 | LAP ALAP PLAP 200 | LAR ALAR 201 | LAT BLAT CLAT PLAT 202 | LAX FLAX 203 | LAW BLAW SLAW 204 | LAY ALAY BLAY FLAY 205 | LEA ILEA OLEA 206 | LED GLED PLED 207 | LEE ALEE BLEE SLEE 208 | LEG CLEG FLEG GLEG 209 | LEI GLEI VLEI 210 | LET BLET 211 | LEW ALEW CLEW PLEW SLEW 212 | LEX ILEX ULEX 213 | LEY BLEY FLEY GLEY SLEY 214 | LID GLID OLID 215 | LIE PLIE 216 | LIN BLIN 217 | LIP BLIP 218 | LIT ALIT GLIT 219 | LOB GLOB 220 | LOP CLOP GLOP 221 | LOR FLOR 222 | LOW ALOW CLOW PLOW 223 | LOY CLOY 224 | LUG GLUG 225 | LUM ALUM GLUM 226 | MAM IMAM 227 | MEU EMEU 228 | MEW SMEW 229 | MID IMID 230 | MIR AMIR EMIR SMIR 231 | NAB SNAB 232 | NAG KNAG 233 | NAN ANAN 234 | NAP KNAP 235 | NAT GNAT 236 | NAW SNAW 237 | NEB SNEB 238 | NED SNED 239 | NEE SNEE 240 | NEW ANEW ENEW 241 | NIB SNIB 242 | NIL ANIL 243 | NIT SNIT 244 | NOD SNOD 245 | NOG SNOG 246 | NON ANON 247 | NOW ANOW ENOW 248 | NUB KNUB 249 | NUR KNUR 250 | NUS ANUS 251 | NUT KNUT 252 | NYE SNYE 253 | OAF GOAF 254 | OAK BOAK 255 | OAR HOAR VOAR 256 | OAT DOAT 257 | OBA BOBA 258 | OBI LOBI 259 | OBO GOBO KOBO LOBO ZOBO 260 | OCA COCA LOCA SOCA 261 | OCH LOCH MOCH ROCH 262 | ODE BODE LODE YODE 263 | OES NOES 264 | OFF BOFF COFF DOFF GOFF KOFF 265 | OFT COFT TOFT 266 | OHO COHO SOHO TOHO 267 | OIK HOIK 268 | OIL MOIL NOIL ROIL 269 | OKE BOKE COKE HOKE LOKE MOKE ROKE SOKE 270 | OLD MOLD WOLD YOLD 271 | OLE BOLE COLE DOLE GOLE JOLE NOLE TOLE VOLE 272 | OLM HOLM 273 | OMS COMS 274 | ONE FONE PONE RONE SONE 275 | ONS PONS 276 | OOF COOF LOOF POOF YOOF 277 | OOH BOOH POOH 278 | OOM COOM SOOM TOOM 279 | OON COON GOON HOON LOON POON ROON TOON WOON 280 | OOP GOOP MOOP NOOP POOP ROOP SOOP YOOP 281 | OOR BOOR GOOR LOOR 282 | OOT POOT WOOT 283 | OPE NOPE POPE TOPE 284 | ORA BORA FORA HORA KORA MORA SORA TORA 285 | ORB FORB SORB 286 | ORC TORC 287 | ORD BORD SORD 288 | ORE DORE HORE KORE RORE YORE 289 | ORF CORF 290 | ORS HORS 291 | ORT BORT DORT MORT TORT WORT 292 | OSE COSE MOSE TOSE 293 | OUD FOUD 294 | OUK BOUK GOUK JOUK POUK SOUK TOUK YOUK ZOUK 295 | OUP DOUP LOUP MOUP NOUP ROUP 296 | OUR COUR JOUR LOUR 297 | OUT DOUT HOUT NOUT SOUT 298 | OVA NOVA 299 | OWE HOWE LOWE YOWE 300 | OWL DOWL GOWL NOWL SOWL YOWL 301 | OWN LOWN NOWN POWN 302 | OWT DOWT LOWT NOWT ROWT TOWT 303 | OXY BOXY COXY DOXY FOXY POXY 304 | PAH OPAH 305 | PAR SPAR 306 | PAS UPAS 307 | PAW SPAW 308 | PAY APAY SPAY 309 | PEC SPEC 310 | PER APER 311 | PET SPET 312 | PIC SPIC 313 | PIE SPIE 314 | POD APOD 315 | POS EPOS 316 | PRY SPRY 317 | PUS OPUS 318 | QUA AQUA 319 | RAD BRAD DRAD GRAD ORAD PRAD TRAD 320 | RAG FRAG 321 | RAN CRAN GRAN 322 | RAP DRAP FRAP 323 | RAT DRAT GRAT FRAT PRAT TRAT 324 | RAW BRAW 325 | RAY BRAY 326 | RED ARED CRED 327 | REE BREE CREE DREE GREE PREE 328 | REF TREF 329 | REG AREG DREG 330 | REN BREN GREN 331 | REP PREP 332 | RES TRES 333 | RET ARET TRET 334 | REW AREW TREW 335 | REX PREX 336 | REZ PREZ TREZ 337 | RIA ARIA 338 | RIB DRIB 339 | RID IRID 340 | RIG FRIG GRIG PRIG TRIG 341 | RIM CRIM 342 | RIN BRIN TRIN 343 | RIT BRIT CRIT FRIT 344 | RIZ FRIZ 345 | ROB PROB 346 | ROD BROD 347 | ROE FROE 348 | ROM PROM 349 | ROO BROO PROO 350 | ROT GROT 351 | ROW AROW DROW FROW PROW TROW VROW 352 | RUB DRUB 353 | RUD CRUD 354 | RUE GRUE 355 | RUG FRUG TRUG 356 | RUM ARUM GRUM 357 | RUT BRUT 358 | RYE TRYE 359 | SAR ASAR KSAR OSAR TSAR 360 | SEA ASEA 361 | SHY ASHY 362 | SKY ESKY 363 | SPY ESPY 364 | TAP ATAP STAP 365 | TAT ETAT STAT 366 | TAW STAW 367 | TED STED 368 | TEN ETEN STEN 369 | TET STET 370 | THE ETHE 371 | TIC ETIC OTIC 372 | TIE STIE 373 | TIS UTIS 374 | TOC ATOC 375 | TOP ATOP 376 | TOT STOT 377 | TUI ETUI 378 | TUM STUM 379 | UDO BUDO KUDO LUDO 380 | UEY QUEY 381 | UFO BUFO 382 | UGH EUGH PUGH SUGH VUGH 383 | UKE BUKE CUKE JUKE LUKE NUKE 384 | ULE DULE GULE HULE PULE TULE YULE 385 | ULU LULU PULU SULU ZULU 386 | UMP GUMP MUMP TUMP YUMP 387 | URD BURD CURD NURD SURD TURD 388 | URE DURE IURE JURE MURE 389 | URN CURN DURN GURN OURN 390 | UTU TUTU 391 | VAE UVAE 392 | VAS KVAS 393 | VET EVET 394 | VOE EVOE 395 | VUM OVUM 396 | WAD SWAD 397 | WAE TWAE 398 | WAN HWAN 399 | WAT TWAT 400 | WAY TWAY 401 | WEE AWEE SWEE TWEE 402 | WEY SWEY 403 | WIS IWIS YWIS 404 | WIZ SWIZ 405 | WOP SWOP 406 | WOT SWOT 407 | WRY AWRY 408 | YAH AYAH 409 | YAM LYAM 410 | YAR KYAR 411 | YEN EYEN HYEN SYEN 412 | YES OYES 413 | YET PYET 414 | YIN AYIN PYIN 415 | ZEE MZEE 416 | ZHO DZHO -------------------------------------------------------------------------------- /docs/level.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Level 7 | 8 | 9 | 10 | 310 | 311 | 312 |
313 |

Level

314 |

LevelDB Logo

315 |

Fast & simple storage - a Node.js-style LevelDB wrapper**

316 |

NPM NPM

317 |

This is a convenience package that bundles the current release of LevelUP and LevelDOWN and exposes LevelUP on its export.

318 |

Use this package to avoid having to explicitly install LevelDOWN when you just want plain old LevelDB from LevelUP.

319 |
var level = require('level')
320 | 
321 | // 1) Create our database, supply location and options.
322 | //    This will create or open the underlying LevelDB store.
323 | var db = level('./mydb')
324 | 
325 | // 2) put a key & value
326 | db.put('name', 'Level', function (err) {
327 |   if (err) return console.log('Ooops!', err) // some kind of I/O error
328 | 
329 |   // 3) fetch by key
330 |   db.get('name', function (err, value) {
331 |     if (err) return console.log('Ooops!', err) // likely the key was not found
332 | 
333 |     // ta da!
334 |     console.log('name=' + value)
335 |   })
336 | })
337 | 
338 | 339 |

See LevelUP and LevelDOWN for more details.

340 |

341 |

Contributing

342 |

Level is an OPEN Open Source Project. This means that:

343 |
344 |

Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.

345 |
346 |

See the CONTRIBUTING.md file for more details.

347 |

Contributors

348 |

Level, including LevelUP & LevelDOWN, is only possible due to the excellent work of the following contributors:

349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 |
Rod VaggGitHub/rvaggTwitter/@rvagg
John ChesleyGitHub/cheslesTwitter/@chesles
Jake VerbatenGitHub/raynosTwitter/@raynos2
Dominic TarrGitHub/dominictarrTwitter/@dominictarr
Max OgdenGitHub/maxogdenTwitter/@maxogden
Lars-Magnus SkogGitHub/ralphtheninjaTwitter/@ralphtheninja
David BjörklundGitHub/keslaTwitter/@david_bjorklund
Julian GruberGitHub/juliangruberTwitter/@juliangruber
Paolo FragomeniGitHub/hij1nxTwitter/@hij1nx
Anton WhalleyGitHub/No9Twitter/@antonwhalley
Matteo CollinaGitHub/mcollinaTwitter/@matteocollina
Pedro TeixeiraGitHub/pgteTwitter/@pgte
363 | 364 | 365 |

366 |

Licence & copyright

367 |

Copyright (c) 2012-2013 Level contributors (listed above).

368 |

Level is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.

369 |
370 |
371 | 372 | -------------------------------------------------------------------------------- /docs/leveldown.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | LevelDOWN 7 | 8 | 9 | 10 | 310 | 311 | 312 |
313 |

LevelDOWN

314 |

LevelDB Logo

315 |

A Low-level Node.js LevelDB binding

316 |

Build Status

317 |

NPM

318 |

LevelDOWN was extracted from LevelUP and now serves as a stand-alone binding for LevelDB.

319 |

It is strongly recommended that you use LevelUP in preference to LevelDOWN unless you have measurable performance reasons to do so. LevelUP is optimised for usability and safety. Although we are working to improve the safety of the LevelDOWN interface it is still easy to crash your Node process if you don't do things in just the right way.

320 |

See the section on safety below for details of known unsafe operations with LevelDOWN.

321 |

322 |

Tested & supported platforms

323 |
    324 |
  • Linux (including ARM platforms such as Raspberry Pi and Kindle!)
  • 325 |
  • Mac OS
  • 326 |
  • Solaris (SmartOS & Nodejitsu)
  • 327 |
  • Windows
      328 |
    • Node 0.10 and above only, see issue #5 for more info
    • 329 |
    • See installation instructions for node-gyp dependencies here, you'll need these (free) components from Microsoft to compile and run any native Node add-on in Windows.
    • 330 |
    331 |
  • 332 |
333 |

334 |

API

335 | 351 |
352 |

353 |

leveldown(location)

354 |

leveldown() returns a new LevelDOWN instance. location is a String pointing to the LevelDB location to be opened.

355 |
356 |

357 |

leveldown#open([options, ]callback)

358 |

open() is an instance method on an existing database object.

359 |

The callback function will be called with no arguments when the database has been successfully opened, or with a single error argument if the open operation failed for any reason.

360 |

options

361 |

The optional options argument may contain:

362 |
    363 |
  • 'createIfMissing' (boolean, default: true): If true, will initialise an empty database at the specified location if one doesn't already exist. If false and a database doesn't exist you will receive an error in your open() callback and your database won't open.

    364 |
  • 365 |
  • 'errorIfExists' (boolean, default: false): If true, you will receive an error in your open() callback if the database exists at the specified location.

    366 |
  • 367 |
  • 'compression' (boolean, default: true): If true, all compressible data will be run through the Snappy compression algorithm before being stored. Snappy is very fast and shouldn't gain much speed by disabling so leave this on unless you have good reason to turn it off.

    368 |
  • 369 |
  • 'cacheSize' (number, default: `8 1024 1024` = 8MB): The size (in bytes) of the in-memory LRU cache with frequently used uncompressed block contents.

    370 |
  • 371 |
372 |

Advanced options

373 |

The following options are for advanced performance tuning. Modify them only if you can prove actual benefit for your particular application.

374 |
    375 |
  • 'writeBufferSize' (number, default: `4 1024 1024` = 4MB): The maximum size (in bytes) of the log (in memory and stored in the .log file on disk). Beyond this size, LevelDB will convert the log data to the first level of sorted table files. From the LevelDB documentation:
  • 376 |
377 |
378 |

Larger values increase performance, especially during bulk loads. Up to two write buffers may be held in memory at the same time, so you may wish to adjust this parameter to control memory usage. Also, a larger write buffer will result in a longer recovery time the next time the database is opened.

379 |
380 |
    381 |
  • 'blockSize' (number, default 4096 = 4K): The approximate size of the blocks that make up the table files. The size related to uncompressed data (hence "approximate"). Blocks are indexed in the table file and entry-lookups involve reading an entire block and parsing to discover the required entry.

    382 |
  • 383 |
  • 'maxOpenFiles' (number, default: 1000): The maximum number of files that LevelDB is allowed to have open at a time. If your data store is likely to have a large working set, you may increase this value to prevent file descriptor churn. To calculate the number of files required for your working set, divide your total data by 2MB, as each table file is a maximum of 2MB.

    384 |
  • 385 |
  • 'blockRestartInterval' (number, default: 16): The number of entries before restarting the "delta encoding" of keys within blocks. Each "restart" point stores the full key for the entry, between restarts, the common prefix of the keys for those entries is omitted. Restarts are similar to the concept of keyframs in video encoding and are used to minimise the amount of space required to store keys. This is particularly helpful when using deep namespacing / prefixing in your keys.

    386 |
  • 387 |
388 |
389 |

390 |

leveldown#close(callback)

391 |

close() is an instance method on an existing database object. The underlying LevelDB database will be closed and the callback function will be called with no arguments if the operation is successful or with a single error argument if the operation failed for any reason.

392 |
393 |

394 |

leveldown#put(key, value[, options], callback)

395 |

put() is an instance method on an existing database object, used to store new entries, or overwrite existing entries in the LevelDB store.

396 |

The key and value objects may either be Strings or Node.js Buffer objects and cannot be undefined or null. Other object types are converted to JavaScript Strings with the toString() method and the resulting String may not be a zero-length. A richer set of data-types are catered for in LevelUP.

397 |

options

398 |

The only property currently available on the options object is 'sync' (boolean, default: false). If you provide a 'sync' value of true in your options object, LevelDB will perform a synchronous write of the data; although the operation will be asynchronous as far as Node is concerned. Normally, LevelDB passes the data to the operating system for writing and returns immediately, however a synchronous write will use fsync() or equivalent so your callback won't be triggered until the data is actually on disk. Synchronous filesystem writes are significantly slower than asynchronous writes but if you want to be absolutely sure that the data is flushed then you can use 'sync': true.

399 |

The callback function will be called with no arguments if the operation is successful or with a single error argument if the operation failed for any reason.

400 |
401 |

402 |

leveldown#get(key[, options], callback)

403 |

get() is an instance method on an existing database object, used to fetch individual entries from the LevelDB store.

404 |

The key object may either be a String or a Node.js Buffer object and cannot be undefined or null. Other object types are converted to JavaScript Strings with the toString() method and the resulting String may not be a zero-length. A richer set of data-types are catered for in LevelUP.

405 |

options

406 |

The optional options object may contain:

407 |
    408 |
  • 'fillCache' (boolean, default: true): LevelDB will by default fill the in-memory LRU Cache with data from a call to get. Disabling this is done by setting fillCache to false.

    409 |
  • 410 |
  • 'asBuffer' (boolean, default: true): Used to determine whether to return the value of the entry as a String or a Node.js Buffer object. Note that converting from a Buffer to a String incurs a cost so if you need a String (and the value can legitimately become a UFT8 string) then you should fetch it as one with asBuffer: true and you'll avoid this conversion cost.

    411 |
  • 412 |
413 |

The callback function will be called with a single error if the operation failed for any reason. If successful the first argument will be null and the second argument will be the value as a String or Buffer depending on the asBuffer option.

414 |
415 |

416 |

leveldown#del(key[, options], callback)

417 |

del() is an instance method on an existing database object, used to delete entries from the LevelDB store.

418 |

The key object may either be a String or a Node.js Buffer object and cannot be undefined or null. Other object types are converted to JavaScript Strings with the toString() method and the resulting String may not be a zero-length. A richer set of data-types are catered for in LevelUP.

419 |

options

420 |

The only property currently available on the options object is 'sync' (boolean, default: false). See leveldown#put() for details about this option.

421 |

The callback function will be called with no arguments if the operation is successful or with a single error argument if the operation failed for any reason.

422 |
423 |

424 |

leveldown#batch(operations[, options], callback)

425 |

batch() is an instance method on an existing database object. Used for very fast bulk-write operations (both put and delete). The operations argument should be an Array containing a list of operations to be executed sequentially, although as a whole they are performed as an atomic operation inside LevelDB. Each operation is contained in an object having the following properties: type, key, value, where the type is either 'put' or 'del'. In the case of 'del' the 'value' property is ignored. Any entries with a 'key' of null or undefined will cause an error to be returned on the callback and any 'type': 'put' entry with a 'value' of null or undefined will return an error. See LevelUP for full documentation on how this works in practice.

426 |

options

427 |

The only property currently available on the options object is 'sync' (boolean, default: false). See leveldown#put() for details about this option.

428 |

The callback function will be called with no arguments if the operation is successful or with a single error argument if the operation failed for any reason.

429 |
430 |

431 |

leveldown#approximateSize(start, end, callback)

432 |

approximateSize() is an instance method on an existing database object. Used to get the approximate number of bytes of file system space used by the range [start..end). The result may not include recently written data.

433 |

The start and end parameters may be either String or Node.js Buffer objects representing keys in the LevelDB store.

434 |

The callback function will be called with no arguments if the operation is successful or with a single error argument if the operation failed for any reason.

435 |
436 |

437 |

leveldown#getProperty(property)

438 |

getProperty can be used to get internal details from LevelDB. When issued with a valid property string, a readable string will be returned (this method is synchronous).

439 |

Currently, the only valid properties are:

440 |
    441 |
  • 'leveldb.num-files-at-levelN': return the number of files at level N, where N is an integer representing a valid level (e.g. "0").

    442 |
  • 443 |
  • 'leveldb.stats': returns a multi-line string describing statistics about LevelDB's internal operation.

    444 |
  • 445 |
  • 'leveldb.sstables': returns a multi-line string describing all of the sstables that make up contents of the current database.

    446 |
  • 447 |
448 |
449 |

450 |

leveldown#iterator([options])

451 |

iterator() is an instance method on an existing database object. It returns a new Iterator instance.

452 |

options

453 |

The optional options object may contain:

454 |
    455 |
  • 'start': the key you wish to start the read at. By default it will start at the beginning of the store. Note that the start doesn't have to be an actual key that exists, LevelDB will simply find the next key, greater than the key you provide.

    456 |
  • 457 |
  • 'end': the key you wish to end the read on. By default it will continue until the end of the store. Again, the end doesn't have to be an actual key as an (inclusive) <=-type operation is performed to detect the end. You can also use the destroy() method instead of supplying an 'end' parameter to achieve the same effect.

    458 |
  • 459 |
  • 'reverse' (boolean, default: false): a boolean, set to true if you want the stream to go in reverse order. Beware that due to the way LevelDB works, a reverse seek will be slower than a forward seek.

    460 |
  • 461 |
  • 'keys' (boolean, default: true): whether the callback to the next() method should receive a non-null key. There is a small efficiency gain if you ultimately don't care what the keys are as they don't need to be converted and copied into JavaScript.

    462 |
  • 463 |
  • 'values' (boolean, default: true): whether the callback to the next() method should receive a non-null value. There is a small efficiency gain if you ultimately don't care what the values are as they don't need to be converted and copied into JavaScript.

    464 |
  • 465 |
  • 'limit' (number, default: -1): limit the number of results collected by this iterator. This number represents a maximum number of results and may not be reached if you get to the end of the store or your 'end' value first. A value of -1 means there is no limit.

    466 |
  • 467 |
  • 'fillCache' (boolean, default: false): wheather LevelDB's LRU-cache should be filled with data read.

    468 |
  • 469 |
  • 'keyAsBuffer' (boolean, default: true): Used to determine whether to return the key of each entry as a String or a Node.js Buffer object. Note that converting from a Buffer to a String incurs a cost so if you need a String (and the value can legitimately become a UFT8 string) then you should fetch it as one.

    470 |
  • 471 |
  • 'valueAsBuffer' (boolean, default: true): Used to determine whether to return the value of each entry as a String or a Node.js Buffer object.

    472 |
  • 473 |
474 |
475 |

476 |

iterator#next(callback)

477 |

next() is an instance method on an existing iterator object, used to increment the underlying LevelDB iterator and return the entry at that location.

478 |

the callback function will be called with no arguments in any of the following situations:

479 |
    480 |
  • the iterator comes to the end of the store
  • 481 |
  • the end key has been reached; or
  • 482 |
  • the limit has been reached
  • 483 |
484 |

Otherwise, the callback function will be called with the following 3 arguments:

485 |
    486 |
  • error - any error that occurs while incrementing the iterator.
  • 487 |
  • key - either a String or a Node.js Buffer object depending on the keyAsBuffer argument when the iterator() was called.
  • 488 |
  • value - either a String or a Node.js Buffer object depending on the valueAsBuffer argument when the iterator() was called.
  • 489 |
490 |
491 |

492 |

iterator#end(callback)

493 |

end() is an instance method on an existing iterator object. The underlying LevelDB iterator will be deleted and the callback function will be called with no arguments if the operation is successful or with a single error argument if the operation failed for any reason.

494 |
495 |

496 |

leveldown.destroy(location, callback)

497 |

destroy() is used to completely remove an existing LevelDB database directory. You can use this function in place of a full directory rm if you want to be sure to only remove LevelDB-related files. If the directory only contains LevelDB files, the directory itself will be removed as well. If there are additional, non-LevelDB files in the directory, those files, and the directory, will be left alone.

498 |

The callback will be called when the destroy operation is complete, with a possible error argument.

499 |

500 |

leveldown.repair(location, callback)

501 |

repair() can be used to attempt a restoration of a damaged LevelDB store. From the LevelDB documentation:

502 |
503 |

If a DB cannot be opened, you may attempt to call this method to resurrect as much of the contents of the database as possible. Some data may be lost, so be careful when calling this function on a database that contains important information.

504 |
505 |

You will find information on the repair operation in the LOG file inside the store directory.

506 |

A repair() can also be used to perform a compaction of the LevelDB log into table files.

507 |

The callback will be called when the repair operation is complete, with a possible error argument.

508 |

509 |

Safety

510 |

Database state

511 |

Currently LevelDOWN does not track the state of the underlying LevelDB instance. This means that calling open() on an already open database may result in an error. Likewise, calling any other operation on a non-open database may result in an error.

512 |

LevelUP currently tracks and manages state and will prevent out-of-state operations from being send to LevelDOWN. If you use LevelDOWN directly then you must track and manage state for yourself.

513 |

514 |

Getting support

515 |

There are multiple ways you can find help in using LevelDB in Node.js:

516 |
    517 |
  • IRC: you'll find an active group of LevelUP users in the ##leveldb channel on Freenode, including most of the contributors to this project.
  • 518 |
  • Mailing list: there is an active Node.js LevelDB Google Group.
  • 519 |
  • GitHub: you're welcome to open an issue here on this GitHub repository if you have a question.
  • 520 |
521 |

522 |

Contributing

523 |

LevelDOWN is an OPEN Open Source Project. This means that:

524 |
525 |

Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.

526 |
527 |

See the CONTRIBUTING.md file for more details.

528 |

Contributors

529 |

LevelDOWN is only possible due to the excellent work of the following contributors:

530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 |
Rod VaggGitHub/rvaggTwitter/@rvagg
John ChesleyGitHub/cheslesTwitter/@chesles
Jake VerbatenGitHub/raynosTwitter/@raynos2
Dominic TarrGitHub/dominictarrTwitter/@dominictarr
Max OgdenGitHub/maxogdenTwitter/@maxogden
Lars-Magnus SkogGitHub/ralphtheninjaTwitter/@ralphtheninja
David BjörklundGitHub/keslaTwitter/@david_bjorklund
Julian GruberGitHub/juliangruberTwitter/@juliangruber
Paolo FragomeniGitHub/hij1nxTwitter/@hij1nx
Anton WhalleyGitHub/No9Twitter/@antonwhalley
Matteo CollinaGitHub/mcollinaTwitter/@matteocollina
Pedro TeixeiraGitHub/pgteTwitter/@pgte
544 | 545 |

Windows

546 |

A large portion of the Windows support comes from code by Krzysztof Kowalczyk @kjk, see his Windows LevelDB port here. If you're using LevelUP on Windows, you should give him your thanks!

547 |

548 |

Licence & copyright

549 |

Copyright (c) 2012-2013 LevelDOWN contributors (listed above).

550 |

LevelDOWN is licensed under an MIT +no-false-attribs license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details.

551 |

LevelDOWN builds on the excellent work of the LevelDB and Snappy teams from Google and additional contributors. LevelDB and Snappy are both issued under the New BSD Licence.

552 |
553 |
554 | 555 | -------------------------------------------------------------------------------- /docs/sublevel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | level-sublevel 7 | 8 | 9 | 10 | 310 | 311 | 312 |
313 |

level-sublevel

314 |

Separate sections of levelup, with hooks!

315 |

build status

316 |

This module allows you to create seperate sections of a 317 | levelup database, 318 | kinda like tables in an sql database, but evented, and ranged, 319 | for real-time changing data.

320 |

Stability

321 |

Unstable: Expect patches and features, possible api changes.

322 |

This is module is working well, but may change in the future as it's use is futher explored.

323 |

Example

324 |
var LevelUp = require('levelup')
325 | var Sublevel = require('level-sublevel')
326 | 
327 | var db = Sublevel(LevelUp('/tmp/sublevel-example'))
328 | var sub = db.sublevel('stuff')
329 | 
330 | //put a key into the main levelup
331 | db.put(key, value, function () {
332 | 
333 | })
334 | 
335 | //put a key into the sub-section!
336 | sub.put(key2, value, function () {
337 | 
338 | })
339 | 
340 | 341 |

Sublevel prefixes each subsection so that it will not collide 342 | with the outer db when saving or reading!

343 |

Hooks

344 |

Hooks are specially built into Sublevel so that you can 345 | do all sorts of clever stuff, like generating views or 346 | logs when records are inserted!

347 |

Records added via hooks will be atomically with the triggering change.

348 |

Hooks Example

349 |

Whenever a record is inserted, 350 | save an index to it by the time it was inserted.

351 |
var sub = db.sublevel('SEQ')
352 | 
353 | db.pre(function (ch, add) {
354 |   add({
355 |     key: ''+Date.now(), 
356 |     value: ch.key, 
357 |     type: 'put',
358 |     prefix: sub //NOTE pass the destination db to add
359 |                //and the value will end up in that subsection!
360 |   })
361 | })
362 | 
363 | db.put('key', 'VALUE', function (err) {
364 | 
365 |   //read all the records inserted by the hook!
366 | 
367 |   sub.createReadStream()
368 |     .on('data', console.log)
369 | 
370 | })
371 | 
372 | 373 |

Notice that sub is the second argument to add, 374 | which tells the hook to save the new record in the sub section.

375 |

Batches

376 |

In sublevel batches also support a prefix: subdb property, 377 | if set, this row will be inserted into that database section, 378 | instead of the current section.

379 |
var sub1 = db.sublevel('SUB_1')
380 | var sub2 = db.sublevel('SUM_2')
381 | 
382 | sub.batch([
383 |   {key: 'key', value: 'Value', type: 'put'},
384 |   {key: 'key', value: 'Value', type: 'put', prefix: sub2},
385 | ], function (err) {...})
386 | 
387 | 388 |

License

389 |

MIT

390 |
391 |
392 | 393 | -------------------------------------------------------------------------------- /exercises/all_your_base/exercise.js: -------------------------------------------------------------------------------- 1 | var sample = require('lodash.sample') 2 | var values = [ 3 | [ 'BASE', 'US' ], 4 | [ 'LANDS AND POSESSIONS', 'VIKINGS OF WESTERN NORWAY' ], 5 | [ 'INDEPENDENCE', 'KING HENRY VIII' ], 6 | [ 'INTERNET COMMUNICATIONS', 'THE NSA' ], 7 | [ 'TICKS', 'LIBUV' ] 8 | ] 9 | 10 | module.exports = require('../../lib/exercise')({ 11 | dir: __dirname, 12 | init: function () { 13 | var value = sample(values) 14 | return { 15 | prepare: function (db, callback) { 16 | setImmediate(callback) 17 | }, 18 | exec: function (dir, mod, callback) { 19 | if (typeof mod !== 'function') { 20 | throw String('{error.mod.not_function}') 21 | } 22 | if (mod.length < 3) { 23 | throw String('{error.mod.not_long_enough}') 24 | } 25 | mod(value[0], value[1], callback) 26 | } 27 | } 28 | } 29 | }) 30 | -------------------------------------------------------------------------------- /exercises/all_your_base/problem.en.md: -------------------------------------------------------------------------------- 1 | To get into the rhythm, let's do a simple _hello world_. 2 | 3 | Write a Node module with three arguments: 4 | 5 | ```javascript 6 | module.exports = function (X, Y, callback) { 7 | /* your code here */ 8 | callback(error, result) 9 | } 10 | ``` 11 | 12 | This module should use **X** and **Y** and call the `callback` with the 13 | following result: 14 | 15 | ALL YOUR {X} ARE BELONG TO {Y} 16 | 17 | Where `X` and `Y` are filled in with the arguments. When you have completed 18 | your program, you can run it in the test environment with: 19 | 20 | {appname} run program.js 21 | 22 | And once you are happy that it is correct then run: 23 | 24 | {appname} verify program.js 25 | 26 | And your submission will be verified for correctness. After you have 27 | a correct solution, run **`{appname}`** again and select the next problem! 28 | -------------------------------------------------------------------------------- /exercises/all_your_base/problem.ja.md: -------------------------------------------------------------------------------- 1 | 簡単な_hello world_でリズムに乗りましょう。 2 | 3 | 3つの引数を取るNodeモジュールを書きましょう。 4 | 5 | ```javascript 6 | module.exports = function (X, Y, callback) { 7 | /* your code here */ 8 | callback(error, result) 9 | } 10 | ``` 11 | 12 | **X**と**Y**を使い、Callbackを下記のような結果を使って実行 13 | するようにして下さい。 14 | 15 | ALL YOUR {X} ARE BELONG TO {Y} 16 | 17 | 上記の中で、`X`と`Y`はそれぞれ引数の値で置き換えて下さい。 18 | プログラムが出来たら実行してみましょう。以下のコマンドを使って 19 | テスト環境で実行することができます。 20 | 21 | {appname} run program.js 22 | 23 | もし結果に問題が無ければ、以下を実行しましょう。 24 | 25 | {appname} verify program.js 26 | 27 | 正しいかどうか、検証が行われます。もし正解なら再度**`{appname}`**を 28 | 実行して次の課題に取り組みましょう! 29 | -------------------------------------------------------------------------------- /exercises/all_your_base/solution.js: -------------------------------------------------------------------------------- 1 | module.exports = function (X, Y, callback) { 2 | callback(null, 'ALL YOUR ' + X + ' ARE BELONG TO ' + Y) 3 | } 4 | -------------------------------------------------------------------------------- /exercises/basics_batch/exercise.js: -------------------------------------------------------------------------------- 1 | var gibberish = require('../../lib/gibberish') 2 | var generate = require('../../lib/generate') 3 | 4 | module.exports = require('../../lib/exercise')({ 5 | dir: __dirname, 6 | init: function () { 7 | var del = generate(5 + (Math.random() * 20 | 0)) 8 | var mod = generate(5 + (Math.random() * 20 | 0)) 9 | var put = generate(5 + (Math.random() * 20 | 0)) 10 | var ops = [] 11 | Object.keys(del).forEach(function (key) { 12 | ops.push({ 13 | type: 'put', 14 | key: key, 15 | value: del[key] 16 | }) 17 | }) 18 | Object.keys(mod).forEach(function (key) { 19 | ops.push({ 20 | type: 'put', 21 | key: key, 22 | value: gibberish() 23 | }) 24 | put[key] = mod[key] 25 | }) 26 | 27 | var changes = { 28 | del: Object.keys(del), 29 | put: put 30 | } 31 | return { 32 | prepare: function (db, callback) { 33 | db.batch(ops, callback) 34 | }, 35 | exec: function (dir, mod, callback) { 36 | if (typeof mod !== 'function') { 37 | throw String('{error.mod.not_function}') 38 | } 39 | if (mod.length < 3) { 40 | throw String('{error.mod.not_long_enough}') 41 | } 42 | mod(dir, changes, function () { 43 | require('../../lib/read-db')(dir, 'utf8', callback) 44 | }) 45 | } 46 | } 47 | } 48 | }) 49 | -------------------------------------------------------------------------------- /exercises/basics_batch/problem.en.md: -------------------------------------------------------------------------------- 1 | Write a program that opens a LevelDB data-store using **`level`** and reads a few keys. 2 | 3 | Your program should be written as Node.js module with 3 arguments. 4 | 5 | ```javascript 6 | module.exports = function (databaseDir, changes, callback) { 7 | // your code... 8 | callback(error, values) 9 | } 10 | ``` 11 | 12 | `changes` is an Object that contains a `del` property with an array of keys to 13 | delete. It also contains a `put` property with an object that contains keys 14 | and values to add to the leveldb. 15 | 16 | For example: 17 | 18 | ``` 19 | { 20 | del: [ '@darachennis' ], 21 | put: { 22 | '@izs': 'Isaac Z. Schlueter', 23 | '@tmpvar': 'Elijah Insua', 24 | '@mrbruning': 'Max Bruning' 25 | } 26 | } 27 | ``` 28 | 29 | In this case, you have 3 new entries to add, mapping twitter handles 30 | to real names, and one entry to remove. 31 | 32 | You are encouraged to use the `batch()` method for this exercise. A 33 | _batch_ operation is an atomic, and efficient mechanism for 34 | performing multiple writes (put and delete). 35 | 36 | --- 37 | 38 | ## Hints: 39 | 40 | The `batch()` method has two forms: 41 | 42 | ### The `Array` form 43 | 44 | The `Array` form lets you provide an array containing your operations 45 | followed by an optional callback. The array must contain objects of the 46 | form: 47 | 48 | ```javascript 49 | { type: 'put', key: 'foo', value: 'bar' } 50 | ``` 51 | 52 | or: 53 | 54 | ```javascript 55 | { type: 'del', key: 'foo' } 56 | ``` 57 | 58 | ### The _chained form_ 59 | 60 | The chained form is closer to the way that LevelDB exposes its batch 61 | operation. Calling `batch()` with no arguments returns a `Batch` object 62 | that you can use to build your complete set of writes and then submit when 63 | ready. It has the following methods: 64 | 65 | ```javascript 66 | batch.put('key', 'value') 67 | batch.del('key') 68 | batch.write(callback) 69 | ``` 70 | 71 | You can't use the chained form of batch until the LevelUP instance is 72 | _"ready"_, you can determine this by either providing a callback to the 73 | main `level()` function or by listening to a "ready" event on the 74 | resulting LevelUP object. See the LevelUP documentation for more details. 75 | 76 | ### Atomicity 77 | Batch writes are "atomic" in that either all writes succeed or they all fail. 78 | If you receive an error on your callback then you can safely assume that your 79 | whole batch failed. 80 | 81 | To get output for debugging when running `{appname} run program.js` 82 | you should use console.error instead of console.log. 83 | -------------------------------------------------------------------------------- /exercises/basics_batch/problem.ja.md: -------------------------------------------------------------------------------- 1 | **`level`**をつかって、LevelDBのデータストアをオープンし、いくつかのエントリを 2 | 更新するモジュールを書きましょう。 3 | 4 | 3つの引数を取るNodeモジュールとしてプログラムを書いて下さい。 5 | 6 | ```javascript 7 | module.exports = function (databaseDir, changes, callback) { 8 | // your code... 9 | callback(error, values) 10 | } 11 | ``` 12 | `changes`はデータベースに対する変更内容を持ったオブジェクトです。 13 | `del`プロパティは削除対象キーの配列です。 14 | `put`プロパティは追加対象のキーと値を持つオブジェクトです。 15 | 16 | 例えば: 17 | 18 | ``` 19 | { 20 | del: [ '@darachennis' ], 21 | put: { 22 | '@izs': 'Isaac Z. Schlueter', 23 | '@tmpvar': 'Elijah Insua', 24 | '@mrbruning': 'Max Bruning' 25 | } 26 | } 27 | ``` 28 | 29 | この場合、あなたは3つの新しいエントリ(Twitterハンドルと実名のマップ)を 30 | 追加し、1つのエントリを削除する必要があります。 31 | 32 | このエクササイズでは`batch()`メソッドを使うと良いでしょう。_batch_ 33 | オペレーションはアトミックで、複数回の書き込み(追加・削除)を行うのに効率的な 34 | メカニズムです。 35 | 36 | --- 37 | 38 | ## ヒント: 39 | 40 | `batch()`メソッドは2つの形式を持っています。 41 | 42 | ### 配列形式 43 | 44 | 配列形式では、必要なオペレーション配列にして渡します。オプションで 45 | callbackを渡すことも出来ます。配列の各要素は以下の様な形式のオブジェクト 46 | となります。 47 | 48 | ```javascript 49 | { type: 'put', key: 'foo', value: 'bar' } 50 | ``` 51 | 52 | あるいは、 53 | 54 | ```javascript 55 | { type: 'del', key: 'foo' } 56 | ``` 57 | 58 | ### チェーン形式 59 | 60 | チェーン系式はLevelDBが提供するバッチオペレーションにより近いものと 61 | なっています。`batch()`を引数無しでコールすると、`Batch`オブジェクトが 62 | 返されます。そのオブジェクトを使用することで一連の書き込みオペレー 63 | ションを構築し、サブミットすることが出来ます。このオブジェクトは以下の 64 | ようなメソッドを持っています。 65 | 66 | ```javascript 67 | batch.put('key', 'value') 68 | batch.del('key') 69 | batch.write(callback) 70 | ``` 71 | 72 | LevelUPインスタンスが_"ready"_となるまで、チェーン系式のバッチは使用 73 | できません。_"ready"_はcallbackをメインの`level()`関数に渡す、あるいは 74 | "ready"イベントをListenすることで判定することが出来ます。詳しい情報は 75 | LevelUPドキュメントを参照して下さい。 76 | 77 | ### アトミック性 78 | 79 | バッチの書き込みはアトミックで、全ての書き込みが成功するか、全て失敗 80 | するかのどちらかです。もしcallbackがエラーを受け取った場合は、全ての 81 | 書き込みが失敗したとみなして問題ありません。 82 | 83 | デバッグで`levelmeup run program.js`を使用しますが、その際に出力を見たい 84 | 場合はconsole.logではなく、console.errorを使用して下さい。 85 | -------------------------------------------------------------------------------- /exercises/basics_batch/solution.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, changes, callback) { 4 | var db = level(databaseDir) 5 | var error 6 | db.on('error', function (err) { 7 | error = err 8 | }) 9 | var ops = changes.del.map(function (key) { 10 | return { 11 | type: 'del', 12 | key: key 13 | } 14 | }).concat(Object.keys(changes.put).map(function (key) { 15 | return { 16 | type: 'put', 17 | key: key, 18 | value: changes.put[key] 19 | } 20 | })) 21 | db.batch(ops, function (err) { 22 | if (err) { 23 | error = err 24 | } 25 | db.close(function (err) { 26 | callback(error || err) 27 | }) 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /exercises/basics_get/exercise.js: -------------------------------------------------------------------------------- 1 | var gibberish = require('../../lib/gibberish') 2 | 3 | module.exports = require('../../lib/exercise')({ 4 | dir: __dirname, 5 | init: function () { 6 | var ops = [] 7 | for (var i = 0; i < 10; ++i) { 8 | ops.push({ 9 | type: 'put', 10 | key: 'key' + Math.floor(Math.random() * (i === 1 ? 10 : 100)), 11 | value: gibberish() 12 | }) 13 | } 14 | return { 15 | prepare: function (db, callback) { 16 | db.batch(ops, callback) 17 | }, 18 | exec: function (dir, mod, callback) { 19 | if (typeof mod !== 'function') { 20 | throw String('{error.mod.not_function}') 21 | } 22 | if (mod.length < 2) { 23 | throw String('{error.mod.not_long_enough}') 24 | } 25 | mod(dir, callback) 26 | } 27 | } 28 | } 29 | }) 30 | -------------------------------------------------------------------------------- /exercises/basics_get/problem.en.md: -------------------------------------------------------------------------------- 1 | Write a module with one argument that opens a LevelDB data-store using 2 | **`level`**. 3 | 4 | The store will contain up to 10 entries with keys in the form: 5 | 6 | 'key' + i 7 | 8 | Where _'i'_ is an integer between 0 and 100. 9 | 10 | You must find those entries and return them in the callback as an, ordered 11 | by _'i'_, ascending. Your module could look like: 12 | 13 | ```javascript 14 | module.exports = function (databaseDir, callback) { 15 | var result = [] 16 | // your code... 17 | result.push() 18 | // more code... 19 | callback(null, result) 20 | } 21 | ``` 22 | 23 | The full path to the data-store will be provided to your program as 24 | the first argument. 25 | 26 | --- 27 | 28 | ## Hints: 29 | 30 | When you perform a `.get()` operation, if the entry does not exist 31 | your callback will receive an error object as the first argument. 32 | 33 | It is also possible to receive I/O errors but you can differentiate 34 | a `NotFoundError` by checking `err.type == 'NotFoundError'` or by 35 | checking for a `err.notFound` boolean. 36 | 37 | Using `.get()` is recommended for this exercise but if you're tempted 38 | to use a ReadStream to solve this problem, beware that the sorting 39 | may be a problem. 40 | -------------------------------------------------------------------------------- /exercises/basics_get/problem.ja.md: -------------------------------------------------------------------------------- 1 | **`level`**をつかって、LevelDBのデータストアをオープンし、エントリを 2 | 探しだすモジュールを書きましょう。 3 | 4 | このデータストアは10個のエントリをもち、それぞれ以下の形式のキーに関連 5 | 付けられています。 6 | 7 | key[X] 8 | 9 | ここで_'[X]'_は0から100までの整数です。 10 | 11 | これらのエントリを探し、一つのリストを作成し、コールバックに渡してください。 12 | そのリストは_'[X]'_で昇順にソートされていなければなりません。あたなの作る 13 | モジュールは下記のようなものになるでしょう。 14 | 15 | ```javascript 16 | module.exports = function (databaseDir, callback) { 17 | var result = [] 18 | // your code... 19 | result.push() 20 | // more code... 21 | callback(null, result) 22 | } 23 | ``` 24 | 25 | データストアのディレクトリへの絶対パスは第1引数として渡されます。 26 | 27 | --- 28 | 29 | ## ヒント: 30 | 31 | `.get()`メソッドを実行した時に対象エントリが存在していなかった場合、 32 | callbackの第1引数にはエラーオブジェクトが渡されます。 33 | 34 | I/Oエラーが渡される可能性もありますが、`NotFoundError`かどうかは 35 | 以下の2通りの方法で判別することが出来ます。 36 | 37 | * `err.type == 'NotFoundError'`をチェックする 38 | * `err.notFound`のBool値をチェックする 39 | 40 | 41 | `.get()`メソッドを使用することを推奨します。ReadStreamを使用する 42 | 場合はソートの問題に注意して下さい。 43 | -------------------------------------------------------------------------------- /exercises/basics_get/solution.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, callback) { 4 | var db = level(databaseDir) 5 | var error 6 | db.on('error', function (err) { 7 | error = err 8 | }) 9 | var result = [] 10 | 11 | var fetchNext = function fetchNext (i) { 12 | var key = 'key' + i 13 | db.get(key, function (err, value) { 14 | if (err) { 15 | if (!err.notFound) { 16 | error = err 17 | } 18 | } else { 19 | result.push(value) 20 | } 21 | 22 | if (i < 100 && !error) { 23 | fetchNext(i + 1) 24 | } else { 25 | db.close(function (err) { 26 | callback(error || err, result) 27 | }) 28 | } 29 | }) 30 | } 31 | fetchNext(0) 32 | } 33 | -------------------------------------------------------------------------------- /exercises/basics_put/exercise.js: -------------------------------------------------------------------------------- 1 | var generate = require('../../lib/generate') 2 | 3 | module.exports = require('../../lib/exercise')({ 4 | dir: __dirname, 5 | init: function () { 6 | var data = generate(5 + (Math.random() * 20 | 0)) 7 | return { 8 | prepare: function (db, callback) { 9 | callback() 10 | }, 11 | exec: function (dir, mod, callback) { 12 | if (typeof mod !== 'function') { 13 | throw String('{error.mod.not_function}') 14 | } 15 | if (mod.length < 3) { 16 | throw String('{error.mod.not_long_enough}') 17 | } 18 | mod(dir, data, function () { 19 | require('../../lib/read-db')(dir, 'utf8', callback) 20 | }) 21 | } 22 | } 23 | } 24 | }) 25 | -------------------------------------------------------------------------------- /exercises/basics_put/problem.en.md: -------------------------------------------------------------------------------- 1 | Write a module that opens a LevelDB data-store using **`level`**. 2 | 3 | Your module should be written as Node.js module with 3 arguments. 4 | 5 | ```javascript 6 | module.exports = function (databaseDir, obj, callback) { 7 | // your code... 8 | callback(error) 9 | } 10 | ``` 11 | 12 | The second argument contains an object. **put** each property of the 13 | object as key and value into a level store. 14 | 15 | Your solution will be verified by reading the data-store and checking 16 | against the object that was provided to you. 17 | 18 | --- 19 | 20 | ## Hints: 21 | 22 | The `put()` method in LevelUP is very simple, you just need to supply 23 | the key and value. An optional callback may be passed if you need 24 | to know when the data has been committed to the store or to 25 | properly catch any errors (otherwise errors will be thrown): 26 | 27 | ```javascript 28 | var db = level('/path/to/db/') 29 | db.put('foo', 'bar', function (err) { 30 | if (err) { 31 | return callback(error) 32 | } 33 | }) 34 | ``` 35 | 36 | You may also call `db.close()` after all your callbacks have returned, 37 | however this is optional as the data-store will be automatically 38 | closed when your program exits. An open LevelDB store will not keep 39 | your program running indefinitely. 40 | 41 | To get output for debugging when running `levelmeup run program.js` 42 | you should use console.error instead of console.log. 43 | -------------------------------------------------------------------------------- /exercises/basics_put/problem.ja.md: -------------------------------------------------------------------------------- 1 | **`level`**をつかって、LevelDBのデータストアをオープンし、エントリを 2 | **`put`**するモジュールを書きましょう。 3 | 4 | 3つの引数を取るNodeモジュールとしてプログラムを書いて下さい。 5 | 6 | ```javascript 7 | module.exports = function (databaseDir, obj, callback) { 8 | // your code... 9 | callback(error) 10 | } 11 | ``` 12 | 13 | 第2引数にはオブジェクトが渡されます。オブジェクトのプロパティをそれぞれキーと値 14 | としてlevelのデータストアに**put**して下さい。 15 | 16 | プログラムの検証時には、更新されたデータストアの値とオブジェクトのプロパティが 17 | 比較されます。 18 | 19 | --- 20 | 21 | ## ヒント: 22 | 23 | LevelUPの`put()`メソッドはとてもシンプルで、キーと値を渡すだけで使えます。 24 | オプションでCallbackを渡すこともできます。Callbackを渡すことで、データの 25 | コミットが完了したことを知ることが出来ます。あるいは、エラーをcatchすることが 26 | 出来ます。(CatchしなければErrorはthrowされてしまいます) 27 | 28 | ```javascript 29 | var db = level('/path/to/db/') 30 | db.put('foo', 'bar', function (err) { 31 | if (err) { 32 | return callback(error) 33 | } 34 | }) 35 | ``` 36 | 37 | 全てのcallbackが終了すれば、あなたは`db.close()`も実行するかもしれません。 38 | プログラムの実行が終了すればデータストアは自動的にクローズされるので、この 39 | 関数の実行はオプショナルです。オープンしたままのLevelDBのデータストアが 40 | 存在したとしても、あなたのプログラムが無限ループに陥ることはありません。 41 | 42 | デバッグで`levelmeup run program.js`を使用しますが、その際に出力を見たい 43 | 場合はconsole.logではなく、console.errorを使用して下さい。 44 | -------------------------------------------------------------------------------- /exercises/basics_put/solution.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, obj, callback) { 4 | var db = level(databaseDir) 5 | var error 6 | 7 | for (var key in obj) { 8 | db.put(key, obj[key]) 9 | } 10 | db.on('error', function (err) { 11 | error = err 12 | }) 13 | db.close(function (err) { 14 | callback(error || err) 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /exercises/get_your_level_on/exercise.js: -------------------------------------------------------------------------------- 1 | var sample = require('lodash.sample') 2 | var values = [ 3 | 'You have been LEVELED UP!', 4 | 'A LEVEL UP for you!', 5 | 'More LEVELS for you!', 6 | 'Your LEVEL has gone UP!', 7 | 'One LEVEL for you!', 8 | 'LEVELS and LEVELS for you!', 9 | 'Another one has a LEVEL!', 10 | 'LEVEL increased!', 11 | 'You have got another LEVEL!', 12 | 'Your LEVEL was just a raised!', 13 | "Hey you've made it to the next LEVEL!", 14 | 'You are a LEVEL explorer!', 15 | 'Here is a bag of LEVELS!', 16 | 'LEVELED you up for the win!' 17 | ] 18 | 19 | module.exports = require('../../lib/exercise')({ 20 | dir: __dirname, 21 | init: function () { 22 | var key = 'levelmeup_' + Date.now().toString(32) + '_' + (Math.random() * 1000 | 0) 23 | var value = sample(values) 24 | return { 25 | prepare: function (db, callback) { 26 | db.put(key, value) 27 | setImmediate(callback) 28 | }, 29 | exec: function (dir, mod, callback) { 30 | if (typeof mod !== 'function') { 31 | throw String('{error.mod.not_function}') 32 | } 33 | if (mod.length < 3) { 34 | throw String('{error.mod.not_long_enough}') 35 | } 36 | mod(dir, key, callback) 37 | } 38 | } 39 | } 40 | }) 41 | -------------------------------------------------------------------------------- /exercises/get_your_level_on/problem.en.md: -------------------------------------------------------------------------------- 1 | Write a program that opens a **`level`** directory and reads a key from it. 2 | 3 | Your program should be written as Node.js module with 3 arguments. 4 | 5 | ```javascript 6 | module.exports = function (databaseDir, key, callback) { 7 | // your code... 8 | callback(error, value) 9 | } 10 | ``` 11 | 12 | The `database_dir` contains the data to be read by the `leveldb`. Your program 13 | should then retrieve the value of `key` and pass it to the callback. 14 | 15 | _Note: You have to close the database before returning the key!_ 16 | 17 | --- 18 | 19 | ## Hints 20 | 21 | **`level`** is a package that bundles both **`levelup`**, the Node-friendly 22 | data-store API and **`leveldown`**, the low-level LevelDB binding. 23 | 24 | Read more about Level and LevelUP: http://npmjs.com/levelup 25 | 26 | Or off-line on your local filesystem: 27 | 28 | {rootdir}/docs/levelup.html 29 | 30 | You will need to `npm install level` to get started with this 31 | exercise. 32 | 33 | If you don't have an Internet connection, simply make a `node_modules` 34 | directory and copy the following directory into it: 35 | 36 | {rootdir}/node_modules/level/ 37 | 38 | You can open an existing data-store, or create a new one, by invoking 39 | `level()` and passing in a path to a directory. The function returns 40 | a new _LevelUP_ instance. 41 | 42 | All LevelUP methods are asynchronous. To _get_ a value out of 43 | the data-store, use the `.get(key, callback)` method: 44 | 45 | ```javascript 46 | var level = require('level') 47 | var db = level('/path/to/db/') 48 | db.get('foo', function (err, value) { 49 | console.log('foo =', value) 50 | }) 51 | ``` 52 | -------------------------------------------------------------------------------- /exercises/get_your_level_on/problem.ja.md: -------------------------------------------------------------------------------- 1 | **`level`**ディレクトリを開いて、そこからキーを読みだすプログラム 2 | を作りましょう。 3 | 4 | 3つの引数を取るNodeモジュールとしてプログラムを書いて下さい。 5 | 6 | ```javascript 7 | module.exports = function (databaseDir, key, callback) { 8 | // your code... 9 | callback(error, value) 10 | } 11 | ``` 12 | 13 | `database_dir`は`leveldb`のデータを持ったディレクトリです。 14 | `key`の値をLevelDBから取り出し、その値をcallbackに渡してください。 15 | 16 | _注意: キーの値を返す前に、データベースをクローズする必要があります!_ 17 | 18 | --- 19 | 20 | ## ヒント 21 | 22 | **`level`**パッケージはNodeフレンドリな **`levelup`**と、低レベルな 23 | LevelDBバインディングである**`leveldown`**の両方を含んでいます。 24 | 25 | LevelとLevelUPについての詳しい情報はここを読んで下さい。: http://npmjs.com/levelup 26 | 27 | オフラインで参照する場合は、あなたのPCの以下のパスを参照して下さい。 28 | 29 | {rootdir}/docs/levelup.html 30 | 31 | このエクササイズを始める前に、 `npm install level`を実行する必要が 32 | あります。 33 | 34 | もしインターネットに接続されていないのであれば、`node_modules` 35 | ディレクトリを作成し、そこに以下のディレクトリをコピーして下さい。 36 | 37 | {rootdir}/node_modules/level/ 38 | 39 | `level()`をディレクトリのパスを指定して実行することで、既存の 40 | データベースを開く、あるいは新たにデータベースを作ることが出来ます。 41 | この関数は_LevelUP_インスタンスを新たに作成して返します。 42 | 43 | 全てのLevelUPメソッドは非同期です。データストアから値を取得するときは、 44 | `.get(key, callback)`メソッドを使用して下さい。 45 | 46 | ```javascript 47 | var level = require('level') 48 | var db = level('/path/to/db/') 49 | db.get('foo', function (err, value) { 50 | console.log('foo =', value) 51 | }) 52 | ``` 53 | -------------------------------------------------------------------------------- /exercises/get_your_level_on/solution.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (dir, key, callback) { 4 | var db = level(dir) 5 | db.get(key, function (error, value) { 6 | db.close(function (err) { 7 | callback(error || err, value) 8 | }) 9 | }) 10 | } 11 | -------------------------------------------------------------------------------- /exercises/horse_js_count/exercise.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../../lib/exercise')({ 2 | dir: __dirname, 3 | init: function () { 4 | var horseJs = require('../../data/horse_js.json') 5 | var start = new Date(horseJs[0].key) 6 | var end = new Date(horseJs[horseJs.length - 1].key) 7 | var newDate = function () { 8 | var mark = new Date(start.getTime() + Math.floor(Math.random() * (end.getTime() - start.getTime()))) 9 | return mark.getFullYear() + '-' + (mark.getUTCMonth() < 9 ? '0' : '') + (mark.getUTCMonth() + 1) + '-' + (mark.getUTCDate() < 9 ? '0' : '') + (mark.getUTCDate() + 1) 10 | } 11 | var startDates = [newDate(), newDate(), newDate(), newDate()] 12 | return { 13 | prepare: function (db, callback) { 14 | db.batch(horseJs, callback) 15 | }, 16 | exec: function (dbDir, mod, callback) { 17 | if (typeof mod !== 'function') { 18 | throw String('{error.mod.not_function}') 19 | } 20 | if (mod.length < 3) { 21 | throw String('{error.mod.not_long_enough}') 22 | } 23 | var dates = startDates.concat() 24 | var result = [] 25 | var next = function () { 26 | mod(dbDir, dates.shift(), function (err, data) { 27 | result.push(data) 28 | if (dates.length === 0 || err) { 29 | callback(err, result) 30 | } else { 31 | next() 32 | } 33 | }) 34 | } 35 | next() 36 | } 37 | } 38 | } 39 | }) 40 | -------------------------------------------------------------------------------- /exercises/horse_js_count/problem.en.md: -------------------------------------------------------------------------------- 1 | You have been provided with a rich and valuable data-set that you 2 | need to provide a simple query interface to. 3 | 4 | In this exercise you will be given a LevelDB store that contains 5 | over 2,000 tweets from [@horse_js](https://twitter.com/horse_js). 6 | Your job is to query this dataset and return the number of tweets 7 | that occur from a given date to the _end_ of the data set. 8 | 9 | Each entry is a single tweet. The key is the exact time that the 10 | tweet was sent, in standard ISO date format (i.e. the format 11 | generated by the `Date` object's `toISOString()` method.) The value 12 | of the entry is simply a String representing the tweet's content. 13 | 14 | Write a **module** that exports a single function that 15 | accepts three arguments: an instance of an existing LevelUP database, 16 | a date string, of the form `YYYY-MM-DD` and a callback function. 17 | 18 | The first argument returned on the callback should be an Error if one 19 | occurred or null. The second argument, if there was no error, should 20 | be an integer, representing the number of tweets since that date. 21 | 22 | Your solution will be checked against the official solution to ensure 23 | that your query is targeting the exact range (see details below). 24 | The output will include the number of "streamed entries". 25 | 26 | --- 27 | 28 | ## Hints: 29 | 30 | Use this boilerplate to get started with your module file: 31 | 32 | ```javascript 33 | module.exports = function (databaseDir, date, callback) { 34 | // .. your code here 35 | callback(error, tweetCount) 36 | } 37 | ``` 38 | 39 | The ISO date format will always sort lexicographically, which means 40 | that our tweets appear in date/time order in our data store without 41 | any special work required on your part. 42 | 43 | In this exercise, you will need to use the `createReadStream()` 44 | method but you will need to restrict the range of entries to just the 45 | data you need, i.e. you must perform a "range query". 46 | 47 | By default, the range is the whole store, but you can narrow it down 48 | to a start and/or end key. For this exercise you want to start at 49 | a particular date and continue to the end of the store. 50 | 51 | Some of the power of range queries comes from the fact that your 52 | start and end keys need not even exist. If your start key does not 53 | exist then the data will start from the entry with a key that 54 | would come next in the sorted order. 55 | 56 | When you call `createReadStream()`, provide an options object with 57 | the property 'gte' (greater than or equal). The value of this property can simply be the 58 | original date string since YYYY-MM-DD is how the ISO format starts 59 | and this will make the ReadStream jump to the first key that begins 60 | with that prefix, i.e. the first tweet on that day. 61 | 62 | ```javascript 63 | db.createReadStream({ gte: '...' })... 64 | ``` 65 | 66 | The rest of the solution will involve incrementing a counter for each 67 | 'data' event you receive and then returning the total count as the 68 | second argument on the callback. 69 | -------------------------------------------------------------------------------- /exercises/horse_js_count/problem.ja.md: -------------------------------------------------------------------------------- 1 | とても有益なデータベースが与えられるので、それに対する簡単なクエリインターフェースを 2 | 作らなくてはなりません。 3 | 4 | このエクササイズでは[@horse_js](https://twitter.com/horse_js)から2000以上の 5 | ツイートを保存したLevelDBのデータを使用します。 6 | データベースから指定した日付以降のツイートの数を取り出すのが課題です。 7 | 8 | エントリにツイートが1つずつ保存されています。ツイートが投稿された日時がキーになっています。 9 | 日時はISO形式で保存されています。 10 | (例えば`Date`オブジェクトの`toISOString()`メソッドによって作られたような形式です。) 11 | エントリの値はツイートの内容を表す文字列です。 12 | 13 | 引数を3つ取る関数を1つだけエクスポートした**module**を作成してください。 14 | 1つ目の引数はLevelUPデータベースインスタンスのディレクトリパス、2つ目の引数は`YYYY-MM-DD`形式の日付の文字列、 15 | 3つ目の引数はコールバック関数です。 16 | 17 | コールバック関数の最初の引数はエラーまたはnullを持つようにしてください。 18 | 2つ目の引数には指定した日付以降に投稿されたツイート数を表す整数を持つようにしてください。 19 | 20 | あなたの解答が正確な範囲(詳細は以下)を対象にしているかチェックされます。 21 | 22 | --- 23 | 24 | ## ヒント 25 | 26 | 以下のboilerplateを利用してみましょう。 27 | 28 | ```javascript 29 | module.exports = function (databaseDir, date, callback) { 30 | // .. your code here 31 | callback(error, tweetCount) 32 | } 33 | ``` 34 | 35 | ISO形式の日時フォーマットは常に辞書順で並んでおり、 36 | 特別な操作をしなくとも、データストアの中でツイートは日付・時間の順番で現れます。 37 | 38 | このエクササイズでは、`createReadStream()`メソッドを使用します。 39 | しかし、エントリは必要な範囲のみに絞らなければなりません。 40 | 41 | デフォルトでは全てのデータストアが対象範囲となりますが、startキーとendキー、 42 | またはどちらか1つを使用して範囲を絞ることができます。 43 | このエクササイズでは指定した日付からデータストアの最後までのツイートに 44 | 範囲を限定したいと思うでしょう。 45 | 46 | この範囲指定のクエリが強力なのは、指定したstartキーとendキーがデータストアに 47 | 存在していなくても良い、という点にあります。 48 | startキーが存在していない場合、ソートされた順番においてstartキーの次に現れる 49 | キーからデータが始まります。 50 | 51 | `createReadStream()`をコールする際、'start'プロパティを持つオブジェクトを引数に設定してください。 52 | このプロパティの値はシンプルにISO形式で始まるYYYY-MM-DDの文字列にすることができます。 53 | そうすることで、その文字列を接辞頭に持つ最初のキー、例えばその日の最初のツイート、へReadStreamオブジェクトはジャンプします。 54 | 55 | ```javascript 56 | db.createReadStream({ start: '...' })... 57 | ``` 58 | 59 | 最後に取得した'data'の数を数えて、その総数をコールバック関数の2つ目の引数に設定して終了してください。 60 | -------------------------------------------------------------------------------- /exercises/horse_js_count/solution.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (dir, date, callback) { 3 | var db = level(dir) 4 | var tweets = 0 5 | var error 6 | db.createReadStream({ gte: date }) 7 | .on('data', function (data) { 8 | tweets++ 9 | }) 10 | .on('error', function (err) { 11 | error = err 12 | }) 13 | .on('end', function () { 14 | db.close(function (err) { 15 | callback(error || err, tweets) 16 | }) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /exercises/horse_js_tweets/exercise.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../../lib/exercise')({ 2 | dir: __dirname, 3 | init: function () { 4 | var horseJs = require('../../data/horse_js.json') 5 | var start = new Date(horseJs[0].key) 6 | var end = new Date(horseJs[horseJs.length - 1].key) 7 | var newDate = function () { 8 | var mark = new Date(start.getTime() + Math.floor(Math.random() * (end.getTime() - start.getTime()))) 9 | return mark.getFullYear() + '-' + (mark.getUTCMonth() < 9 ? '0' : '') + (mark.getUTCMonth() + 1) + '-' + (mark.getUTCDate() < 9 ? '0' : '') + (mark.getUTCDate() + 1) 10 | } 11 | var startDates = [ '2013-06-01', newDate(), '2013-07-11', newDate() ] 12 | return { 13 | prepare: function (db, callback) { 14 | db.batch(horseJs, callback) 15 | }, 16 | exec: function (dbDir, mod, callback) { 17 | if (typeof mod !== 'function') { 18 | throw String('{error.mod.not_function}') 19 | } 20 | if (mod.length < 3) { 21 | throw String('{error.mod.not_long_enough}') 22 | } 23 | var dates = startDates.concat() 24 | var result = [] 25 | var next = function () { 26 | mod(dbDir, dates.shift(), function (err, data) { 27 | result.push(data) 28 | if (dates.length === 0 || err) { 29 | callback(err, result) 30 | } else { 31 | next() 32 | } 33 | }) 34 | } 35 | next() 36 | } 37 | } 38 | } 39 | }) 40 | -------------------------------------------------------------------------------- /exercises/horse_js_tweets/problem.en.md: -------------------------------------------------------------------------------- 1 | In this exercise you will be provided with a LevelDB store that 2 | contains over 2,000 tweets from [@horse_js](https://twitter.com/horse_js). 3 | Your job is to query this data set for tweets that were made on a particular 4 | date. 5 | 6 | Each entry is a single tweet. The key is the exact time that the 7 | tweet was sent, in standard ISO date format (i.e. the format 8 | generated by the Date object's `toISOString()` method.) The value 9 | of the entry is simply a String representing the tweet's content. 10 | 11 | Write a **module** that exports a single function that 12 | accepts three arguments: an instance of the levelup database, a date string, of 13 | the form YYYY-MM-DD and a callback function. 14 | 15 | The first argument to the callback should be an Error if one occurred 16 | or null. 17 | 18 | The second argument, if there was no error, should be an 19 | **array where each element is the String text of a tweet**. 20 | 21 | The array should contain ordered tweets for the **single day** given 22 | as the first argument to your function. You must not return tweets 23 | for any other day. 24 | 25 | Your solution will be checked against the official solution to ensure 26 | that your query is targeting the exact range (see details below). 27 | The output will include the number of "streamed entries". 28 | 29 | --- 30 | ## Hints: 31 | 32 | The ISO date format will always sort lexicographically, which means 33 | that our tweets appear in date/time order in our data store without 34 | any special work on our part. 35 | 36 | In this exercise, you will need to use the `createReadStream()` 37 | method but you will need to restrict the range of entries to just the 38 | data you need, i.e. you must perform a "range query". 39 | 40 | By default the range is the whole store, but you can narrow it down 41 | to a start and/or end key. For this exercise you want to start at 42 | the first tweet on the given day and end at the last tweet of that 43 | day. 44 | 45 | Some of the power of range queries comes from the fact that your 46 | start and end keys need not even exist. If your start key does not 47 | exist then the data will start from the entry with a key that 48 | would come next in the sorted order. If your end key does not exist 49 | then your query will end at the entry with a key that would come 50 | before your end key in sorted order. 51 | 52 | To target a range, you supply an options object to 53 | `createReadStream()` with `gte` (greater than or equal) and/or `lte` (less than 54 | or equal) properties that define your range keys: 55 | 56 | ```javascript 57 | db.createReadStream({ gte: 'bar', lte: 'foo' })... 58 | ``` 59 | 60 | Keep in mind that since your range keys need not exist you only need 61 | to supply any prefix of the keys you are looking for, e.g. `2010` 62 | will jump to the first key starting with `2010`, which might end up 63 | matching `2010-09-04T03:51:30.929Z`. 64 | 65 | Because the `lte` key of your range will be inclusive, you will need 66 | to create a pseudo-key that would match only the keys you want. 67 | Consider that if you used a `gte` of `2010` and `lte` of `2011` you would 68 | get all entries that start with both `2010` and `2011`. The idiomatic 69 | way _(but not the only way)_ to do this with LevelUP is to append `'\xff'` 70 | to the end of your key, this is the last ASCII character. So, `gte` 71 | of `2010` and `lte` of `2010\xff` would only match keys starting with 72 | `2010`. 73 | -------------------------------------------------------------------------------- /exercises/horse_js_tweets/problem.ja.md: -------------------------------------------------------------------------------- 1 | このエクササイズでは[@horse_js](https://twitter.com/horse_js)から2000以上の 2 | ツイートを保存したLevelDBのデータを使用します。 3 | ある特定の日付に投稿されたツイートを取得するクエリを投げるのが課題です。 4 | 5 | エントリにツイートが1つずつ保存されています。ツイートが投稿された日時がキーになっています。 6 | 日時はISO形式で保存されています。 7 | (例えば`Date`オブジェクトの`toISOString()`メソッドによって作られたような形式です。) 8 | エントリの値はツイートの内容を表す文字列です。 9 | 10 | 引数を3つ取る関数を1つだけエクスポートした**module**を作成してください。 11 | 1つ目の引数はLevelUPデータベースインスタンスのディレクトリパス、2つ目の引数は`YYYY-MM-DD`形式の日付の文字列、 12 | 3つ目の引数はコールバック関数です。 13 | 14 | コールバック関数の最初の引数はエラーまたはnullを持つようにしてください。 15 | 16 | 2つ目の引数には**ツイートのテキストが要素の配列**を持つようにしてください。 17 | 18 | 1つ目の引数として与えられる**1日**のツイートを配列は含んでいなければいけません。 19 | 他の日付のツイートを返してはいけません。 20 | 21 | あなたの解答が正解な範囲(詳細は以下)を対象にしているかチェックされます。 22 | 23 | --- 24 | ## ヒント: 25 | 26 | ISO形式の日時フォーマットは常に辞書順で並んでおり、 27 | 特別な操作をしなくとも、データストアの中でツイートは日付・時間の順番で現れます。 28 | 29 | このエクササイズでは、`createReadStream()`メソッドを使用します。 30 | しかし、エントリは必要な範囲のみに絞らなければなりません。 31 | 32 | デフォルトでは全てのデータストアを範囲としますが、startキーとendキー、 33 | またはどちらか1つを使用して範囲を絞ることができます。 34 | このエクササイズでは指定した日付の最初から最後までのツイートを 35 | 対象にしたいと思うでしょう。 36 | 37 | この範囲指定のクエリが強力なのは、指定したstartキーとendキーがデータストアに 38 | 存在していなくても良い、という点にあります。 39 | startキーが存在していない場合、ソートされた順番においてstartキーの次に現れる 40 | キーからデータが始まります。 41 | endキーが存在していない場合、ソートされた順番においてendキーの前に現れるキーで 42 | データが終了します。 43 | 44 | 範囲を絞るために'start'と'end'またはどちらか1つプロパティを持つオブジェクトを`createReadStream()`の引数に設定してください。 45 | 46 | ```javascript 47 | db.createReadStream({ start: 'bar', end: 'foo' })... 48 | ``` 49 | 50 | 指定する範囲の両キーが存在する必要はなく、見つけたいキーの接頭辞の指定さえあれば良い、 51 | という点を忘れないで下さい。 52 | 例えば、`2010`は`2010`から始まる最初のキーへジャンプします。それは`2010-09-04T03:51:30.929Z`にマッチするという結果になるかもしれません。 53 | 54 | 範囲指定クエリの結果は、`end`キーそのもののエントリが含まれるので、所望のキーだけに 55 | マッチする擬似キーを作成する必要があります。 56 | もし`start`に`2010`、`end`に`2011`を使用する場合、`2010`と`2011`の両方から始まるすべてのエントリを取得します。 57 | LevelUPを使用してこれを実現する(唯一ではないが)慣用的な方法は`'\xff'`をキーの最後に付加することです。 58 | これは最後のASCII文字を意味します。ですから、`2010`の`start`と `2010\xff` の`end`は`2010`から始まるキーにだけマッチします。 59 | -------------------------------------------------------------------------------- /exercises/horse_js_tweets/solution.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, day, callback) { 3 | var tweets = [] 4 | var db = level(databaseDir) 5 | var error 6 | db.createReadStream({ gte: day, lte: day + '\xff' }) 7 | .on('data', function (data) { 8 | tweets.push(data.value) 9 | }) 10 | .on('error', function (err) { 11 | error = err 12 | }) 13 | .on('end', function () { 14 | db.close(function (err) { 15 | callback(error || err, tweets) 16 | }) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /exercises/keywise/exercise.js: -------------------------------------------------------------------------------- 1 | var keywiseFileName = require.resolve('../../data/keywise.json') 2 | 3 | module.exports = require('../../lib/exercise')({ 4 | dir: __dirname, 5 | init: function () { 6 | return { 7 | prepare: function (db, callback) { 8 | callback() 9 | }, 10 | exec: function (dbDir, mod, callback) { 11 | if (typeof mod !== 'function') { 12 | throw String('{error.mod.not_function}') 13 | } 14 | if (mod.length < 3) { 15 | throw String('{error.mod.not_long_enough}') 16 | } 17 | mod(dbDir, keywiseFileName, function () { 18 | require('../../lib/read-db')(dbDir, 'json', callback) 19 | }) 20 | } 21 | } 22 | } 23 | }) 24 | -------------------------------------------------------------------------------- /exercises/keywise/problem.en.md: -------------------------------------------------------------------------------- 1 | Write a **module** that exports a single function that 2 | accepts three arguments: an instance of an existing LevelUP database, 3 | a file path that points to a JSON file and a callback function. 4 | 5 | ## The **module** should 6 | 7 | Write a module that reads in a JSON file containing mappings of 8 | usernames to their GitHub repositories and store them in a LevelUP 9 | data-store such that they can be searched. 10 | 11 | Your first command-line argument will be the full path to the LevelUP 12 | store where you need to write the data. 13 | 14 | You will be given the path to a JSON file as the second command-line 15 | argument, you can use `require(jsonPath)` to load and parse 16 | it into a JavaScript object. 17 | 18 | The JSON file is an array with two kinds of rows, some are users: 19 | 20 | ```javascript 21 | { 22 | type: "user", 23 | name: "maxogden" 24 | } 25 | ``` 26 | 27 | And some are repositories: 28 | 29 | ```javascript 30 | { 31 | type: "repo", 32 | name: "mux-demux", 33 | user: "dominictarr" 34 | } 35 | ``` 36 | 37 | You must write all of the entries in this file to the data-store. 38 | 39 | Open the data-store and write data with `!` as a delimiter such that 40 | the verify script will be able to read the **repos for each user** by 41 | doing the following range query: 42 | 43 | ```javascript 44 | db.createReadStream({ 45 | start: 'rvagg!', 46 | end: 'rvagg!~' 47 | }) 48 | ``` 49 | 50 | The user data should also be fetchable with: 51 | 52 | ```javascript 53 | db.get('rvagg', function (err, user) { ... }) 54 | ``` 55 | 56 | The value of each entry of the data-store should be the same as the 57 | original JSON object from the data file. 58 | 59 | --- 60 | 61 | ## Hints: 62 | 63 | To simplify the use of JSON here you can open your LevelUP store 64 | with the option: `valueEncoding: 'json'`, i.e. 65 | 66 | ```javascript 67 | var db = level(databaseDir, { valueEncoding: 'json' }) 68 | ``` 69 | 70 | You can then write values as objects directly to the store without 71 | having to do a JSON conversion yourself. This also means that read 72 | operations will receive a recomposed object. 73 | 74 | To get output for debugging when running `levelmeup run program.js` 75 | you should use console.error instead of console.log. 76 | -------------------------------------------------------------------------------- /exercises/keywise/problem.ja.md: -------------------------------------------------------------------------------- 1 | 引数を3つ取る関数を1つだけエクスポートした**module**を作成してください。 2 | 引数はLevelUPデータベースのインスタンスが存在するディレクトリ、JSONファイルのファイルパス、 3 | コールバック関数となっています。 4 | 5 | ## **module**の仕様 6 | 7 | GitHubリポジトリとユーザーネームのマッピングが書かれたJSONファイルを読み出し、 8 | それらのデータを検索できるようにLevelUPデータストアに保存するモジュールを書きましょう。 9 | 10 | 1つ目のコマンドライン引数はデータを書き込むLevelUPデータベースのパスになります。 11 | 12 | 2つ目のコマンドライン引数はJSONファイルへのパスになります。JSONを読み込みJavascriptオブジェクトに変換するために 13 | `require(JSONファイルのパス)`が使えます。 14 | 15 | JSONファイルは2種類の行を持つ配列です。1つはユーザーです。 16 | 17 | ```javascript 18 | { 19 | type: "user", 20 | name: "maxogden" 21 | } 22 | ``` 23 | 24 | もう1つはリポジトリです。 25 | 26 | ```javascript 27 | { 28 | type: "repo", 29 | name: "mux-demux", 30 | user: "dominictarr" 31 | } 32 | ``` 33 | 34 | このファイルのすべてのエントリをデータストアに書き込まなければいけません。 35 | 36 | データストアを開き、`!`を区切り文字としてデータを書き込んでください。そうすることで検証用スクリプトは 37 | 以下の範囲問い合わせを実行し、**各ユーザーのリポジトリ**を読み込むことができます。 38 | 39 | ```javascript 40 | db.createReadStream({ 41 | start: 'rvagg!', 42 | end: 'rvagg!~' 43 | }) 44 | ``` 45 | 46 | ユーザーデータは以下の方法で取得できるようにして下さい。 47 | 48 | ```javascript 49 | db.get('rvagg', function (err, user) { ... }) 50 | ``` 51 | 52 | データストアの各エントリの値はファイルから取得したオリジナルのJSONオブジェクトと同じでなけれななりません。 53 | 54 | --- 55 | 56 | ## ヒント: 57 | 58 | JSONの扱いを簡単にするために、`valueEncoding: 'json'`のオプションを使用しLevelUPストアを 59 | 開くことができます。以下は例です。 60 | 61 | ```javascript 62 | var db = level(databaseDir, { valueEncoding: 'json' }) 63 | ``` 64 | 65 | こうすることでオブジェクトをデータとして直接ストアに書き込むことが出来、自分でJSONデータの 66 | 変換をする必要が無くなります。 67 | これは同様に、読み込み処理は再構成されたオブジェクトを受け取ることを意味します。 68 | 69 | `levelmeup run program.js`を実行する時にデバッグ用の出力を取得したい場合は、 70 | console.logの代わりにconsole.errorを使用してください。 71 | -------------------------------------------------------------------------------- /exercises/keywise/solution.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, keywiseFile, callback) { 4 | var db = level(databaseDir, { valueEncoding: 'json' }) 5 | var data = require(keywiseFile) 6 | 7 | var operations = data.map(function (row) { 8 | var key 9 | if (row.type === 'user') { 10 | key = row.name 11 | } else if (row.type === 'repo') { 12 | key = row.user + '!' + row.name 13 | } 14 | return { 15 | type: 'put', 16 | key: key, 17 | value: row 18 | } 19 | }) 20 | 21 | db.batch(operations, function (error) { 22 | db.close(function (err) { 23 | callback(error || err) 24 | }) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /exercises/multilevel/exercise.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | var net = require('net') 3 | var multilevel = require('multilevel') 4 | 5 | module.exports = require('../../lib/exercise')({ 6 | dir: __dirname, 7 | init: function () { 8 | return { 9 | prepare: function (db, callback) { 10 | db.put('multilevelmeup', '`Twas brillig, and the slithy toves\n\tDid gyre and gimble in the wabe:\nAll mimsy were the borogoves,\n\tAnd the mome raths outgrabe.', callback) 11 | }, 12 | exec: function (dbDir, mod, callback) { 13 | if (typeof mod !== 'function') { 14 | throw String('{error.mod.not_function}') 15 | } 16 | if (mod.length < 1) { 17 | throw String('{error.mod.not_long_enough}') 18 | } 19 | var db = level(dbDir) 20 | var server = net 21 | .createServer(function (con) { 22 | con.pipe(multilevel.server(db)).pipe(con) 23 | }) 24 | .listen(4545, function (conn) { 25 | mod(function (error, data) { 26 | server.close(function () { 27 | db.close(function (err) { 28 | callback(error || err, data) 29 | }) 30 | }) 31 | }) 32 | }) 33 | } 34 | } 35 | } 36 | }) 37 | -------------------------------------------------------------------------------- /exercises/multilevel/problem.en.md: -------------------------------------------------------------------------------- 1 | Write a module that uses multilevel to fetch a value from a server 2 | running on your computer. 3 | 4 | Create a TCP connection with the core `net` module to port **4545** 5 | on localhost. Pipe this connection through a multilevel RPC stream and 6 | back to the connection. Your code should look like: 7 | 8 | ```javascript 9 | var multilevel = require('multilevel') 10 | var net = require('net') 11 | 12 | module.exports = function (callback) { 13 | var db = multilevel.client() 14 | var connection = net.connect(4545) 15 | connection.pipe(db.createRpcStream()).pipe(connection) 16 | 17 | // your code ... 18 | callback(null, value) 19 | } 20 | ``` 21 | 22 | You will then have a `db` object that you can interact with like a 23 | LevelUP object. 24 | 25 | Fetch the value from the data store with the key `multilevelmeup` 26 | and return it to the provided callback. 27 | 28 | **You must close the connection using `connection.end(..)` after you 29 | have fetched the value but before you execute the callback!** 30 | 31 | --- 32 | 33 | ## Hints: 34 | 35 | Read more about multilevel here: 36 | 37 | http://npmjs.com/multilevel 38 | 39 | Or off-line on your local filesystem: 40 | 41 | {rootdir}/docs/multilevel.html 42 | 43 | You will need to `npm install multilevel` to get started with this 44 | exercise. 45 | 46 | If you don't have an Internet connection, simply make a `node_modules` 47 | directory and copy the following directory into it: 48 | 49 | {rootdir}/node_modules/multilevel/ 50 | -------------------------------------------------------------------------------- /exercises/multilevel/problem.ja.md: -------------------------------------------------------------------------------- 1 | あなたのコンピューター上で動くサーバーから値を取得するためにmultilevelを使用するモジュールを 2 | 書いてください。 3 | 4 | ローカルホスト上でポート番号**4545**を使用する`net`モジュールを使用してTCPコネクションを作成してください。 5 | このコネクションをmultilevelのRPCストリームにパイプでつなぎ、コネクションに返してください。 6 | 以下のようなコードになるでしょう。 7 | 8 | ```javascript 9 | var multilevel = require('multilevel') 10 | var net = require('net') 11 | 12 | module.exports = function (callback) { 13 | var db = multilevel.client() 14 | var connection = net.connect(4545) 15 | connection.pipe(db.createRpcStream()).pipe(connection) 16 | 17 | // あなたのコード ... 18 | callback(null, value) 19 | } 20 | ``` 21 | 22 | `db`オブジェクトはLevelUPオブジェクトのように使用できるものになります。 23 | 24 | `multilevelmeup`というキーを使用してデータストアから値を取得し、 25 | コールバックに渡してください。 26 | 27 | **値を取得した後コールバックを呼ぶ前に必ずコネクションを 28 | `connection.end(..)`で閉じてください!** 29 | 30 | --- 31 | 32 | ## ヒント: 33 | 34 | multilevelに関しての詳細は以下のページで読めます。 35 | 36 | http://npmjs.com/multilevel 37 | 38 | または以下に配置されているローカルのファイルからオフラインでも読めます。 39 | 40 | {rootdir}/docs/multilevel.html 41 | 42 | このエクササイズを始めるために`npm install multilevel`を実行しなければいけません。 43 | 44 | インターネットに接続できない場合、`node_modules`というディレクトリを作成し以下のディレクトリを作成した 45 | ディレクトリ内にコピーしてください。 46 | 47 | {rootdir}/node_modules/multilevel/ 48 | -------------------------------------------------------------------------------- /exercises/multilevel/solution.js: -------------------------------------------------------------------------------- 1 | var multilevel = require('multilevel') 2 | var net = require('net') 3 | 4 | module.exports = function (callback) { 5 | var db = multilevel.client() 6 | var con = net.connect(4545) 7 | con.pipe(db.createRpcStream()).pipe(con) 8 | 9 | db.get('multilevelmeup', function (err, value) { 10 | con.end(function () { 11 | callback(err, value) 12 | }) 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /exercises/short_scrabble_words/exercise.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var through2 = require('through2') 4 | var sample = require('lodash.sample') 5 | var level = require('level') 6 | 7 | function loadWords (file) { 8 | return fs.readFileSync(path.join(__dirname, '../../data/', file), 'utf8').split(/\s|\n/g) 9 | } 10 | 11 | var twoLetter = loadWords('sowpods_2.dat') 12 | var threeLetter = loadWords('sowpods_3.dat') 13 | var fourLetter = loadWords('sowpods_4.dat') 14 | var words = [] 15 | .concat(twoLetter) 16 | .concat(threeLetter) 17 | .concat(fourLetter) 18 | .filter(Boolean) 19 | 20 | module.exports = require('../../lib/exercise')({ 21 | dir: __dirname, 22 | init: function () { 23 | var queries = [ 24 | sample(twoLetter).substr(0, 1) + '*', 25 | sample(twoLetter), 26 | sample(threeLetter).substr(0, 1) + '**', 27 | sample(threeLetter).substr(0, 2) + '*', 28 | sample(threeLetter), 29 | sample(fourLetter).substr(0, 1) + '***', 30 | sample(fourLetter).substr(0, 2) + '**', 31 | sample(fourLetter).substr(0, 3) + '*', 32 | sample(fourLetter), 33 | 'NODE' 34 | ] 35 | return { 36 | prepare: function (db, callback) { 37 | callback() 38 | }, 39 | exec: function (dbDir, mod, callback) { 40 | if (typeof mod !== 'object') { 41 | throw String('{error.mod.not_object}') 42 | } 43 | if (typeof mod.init !== 'function') { 44 | throw String('{error.mod.init_missing}') 45 | } 46 | if (typeof mod.query !== 'function') { 47 | throw String('{error.mod.query_missing}') 48 | } 49 | var db = level(dbDir) 50 | mod.init(db, words, function (error) { 51 | if (error) { 52 | return db.close(callback.bind(null, error)) 53 | } 54 | var _createReadStream = db.createReadStream 55 | db.createReadStream = function () { 56 | return _createReadStream.apply(db, arguments).pipe(through2({ objectMode: true }, 57 | function (chunk, enc, callback) { 58 | result.count += 1 59 | callback(null, chunk) 60 | } 61 | )) 62 | } 63 | var result 64 | var runQueries = queries.concat() 65 | var next = function () { 66 | var query = runQueries.shift() 67 | result = { 68 | data: {}, 69 | count: 0 70 | } 71 | mod.query(db, query, function (err, data) { 72 | if (!err) { 73 | result.data[query] = data 74 | } 75 | if (err || runQueries.length === 0) { 76 | return db.close(callback.bind(null, err, result)) 77 | } 78 | next() 79 | }) 80 | } 81 | next() 82 | }) 83 | } 84 | } 85 | } 86 | }) 87 | -------------------------------------------------------------------------------- /exercises/short_scrabble_words/problem.en.md: -------------------------------------------------------------------------------- 1 | Write a module that stores valid 2, 3 and 4 character Scrabble words 2 | and is able to retrieve them according to basic prefix-queries. 3 | 4 | Your module should export an `init()` function that accepts 3 5 | arguments: a LevelUP `db` object for an empty database, an array of 6 | 2, 3 and 4 character Scrabble words and callback that you must call 7 | once you have finished initialising the database. 8 | 9 | Your module should also export a `query()` method that also accepts 10 | 3 arguments: a LevelUP `db` object (the same store that you 11 | initialised with `init()`), a `word` string containing the query, and 12 | a callback that you must call with two arguments. The first argument 13 | should be null, or an error object if one occurred. The second 14 | argument should be an array of all the words in the database which 15 | match the query. 16 | 17 | Here is a boilerplate module that you can extend for your solution: 18 | 19 | ```javascript 20 | module.exports.init = function (db, words, callback) { 21 | // insert each word in the words array here 22 | // then call `callback()` when you are done inserting words 23 | } 24 | 25 | module.exports.query = function (db, word, callback) { 26 | // `word` may have '*' chars to denote single-letter wildcards 27 | // call callback(err, results) with an array of matching words 28 | } 29 | ``` 30 | 31 | The `word` query may be a complete word, e.g. 'RUN', or a prefix of a 32 | word with `*` characters filling in the blanks, e.g. `RU*` or `R**`. 33 | The `.length` will tell you how long the word should be, your results 34 | should only include words of that length. The `*` characters are 35 | wild-cards that can match any character. 36 | 37 | For simplicity, the wild-cards will only be on the **end** of a query. 38 | You will always be given either a complete word or a word prefix. You 39 | must limit your results to words of the same length and with the same 40 | prefix. 41 | 42 | Your solution will be tested against the official solution, you must 43 | use a ReadStream that **only** returns the exact words that your query 44 | needs to match, and no more. 45 | 46 | --- 47 | 48 | ## Hints: 49 | 50 | This exercise is about coming up with a key schema that is going to be 51 | useful for retrieving results according to the queries you can expect. 52 | You will need to come up with a key structure that will let you limit 53 | your search to only words of the correct number of characters without 54 | including words that have a different number of characters. 55 | 56 | Your `init()` function should translate words into appropriate keys, 57 | and your `query()` function should be able to translate a query into 58 | a `start` and `end` for your ReadStream. 59 | -------------------------------------------------------------------------------- /exercises/short_scrabble_words/problem.ja.md: -------------------------------------------------------------------------------- 1 | 2、3、4文字のスクラブルワードを保存するモジュールを作成します。 2 | また、基本的なprefix(接頭辞)クエリにしたがって保存した言葉を取り出せる 3 | ようにします。 4 | 5 | > 〜〜〜 スクラブル 〜〜〜 6 | > アルファベットの書かれたコマを並べて単語を作るボードゲーム 7 | > クロスワードパズル的要素がある 8 | > ウィキペディア → https://ja.wikipedia.org/wiki/スクラブル 9 | 10 | 3つの引数を持つ`init()`関数がエクスポートされたモジュールを書いてください。 11 | 1つ目の引数は空のデータベースのLevelUP`db`オブジェクト、2つ目の引数は2、3、4文字のスクラブルワードの配列、 12 | 最後の引数はデータベースを初期化した後に実行するコールバックです。 13 | 14 | さらに、3つの引数を持つ`query()`関数もエクスポートして下さい。 15 | 1つ目の引数は`init()`関数で初期化されたデータベースと同じ`db`オブジェクト、 16 | 2つ目の引数はクエリ文字列、最後の引数は2つの引数を持つコールバック関数です。 17 | コールバック関数の最初の引数はnullまたはエラーが発生した場合のエラーオブジェクトです。 18 | コールバック関数の2つ目の引数はクエリに合致するデータベース内のすべての単語の配列です。 19 | 20 | 以下のボイラープレートを拡張して答えを書いてください。 21 | 22 | ```javascript 23 | module.exports.init = function (db, words, callback) { 24 | // words配列の各ワードをここで書き込む 25 | // 全ての単語の書き込みが終われば、callbackを実行 26 | } 27 | 28 | module.exports.query = function (db, word, callback) { 29 | // `word`は'*'を含む文字列。'*'は1文字をあわらすワイルドカード 30 | // callback(err, results)を一致した単語の配列を設定して実行 31 | } 32 | ``` 33 | 34 | `word`に設定するクエリは'RUN'のような完全な単語、または`RU*`や`R**`のように 35 | 前方一致のための接頭辞と`*`を組み合わせた単語でなければいけません。 36 | `.length`で目的の単語の文字数を知ることが出来、その文字数の単語のみを含む 37 | 結果を返さなければいけません。 38 | `*`はいかなる文字にもマッチするワイルドカードです。 39 | 40 | 簡単のため、ワイルドカードはクエリの**最後**にのみ付加します。 41 | 常に完全一致の単語または接頭辞のどちらかを与えられます。 42 | 同じ文字数で同じ接頭辞を持つ単語のみ結果としてください。 43 | 44 | あなたの解答はオフィシャルな解答に対してテストされます。 45 | ReadStreamを使い、問い合わせクエリに正確にマッチする結果**だけ**を返し、それ以上は返さないでください。 46 | 47 | --- 48 | 49 | ## ヒント: 50 | 51 | あなたが想定するクエリにしたがって結果を抽出する際に役立つであろうキースキーマを 52 | 考えだす、ということがこのエクササイズの目的になります。 53 | 対象外の文字数を持つ単語を含めずに、目的の文字数の単語だけを検索できるキー構造を 54 | を導きださなければいけません。 55 | 56 | `init()`関数は単語を適切なキーに変換し、 57 | `query()`関数はクエリをReadStreamの適切な`start`と`end`に変換するように 58 | してください。 59 | -------------------------------------------------------------------------------- /exercises/short_scrabble_words/solution.js: -------------------------------------------------------------------------------- 1 | module.exports.init = function (db, words, callback) { 2 | var batch = words.map(function (word) { 3 | // length-prefixed keys, separated by a '!' so we 4 | // can query by length 5 | var key = word.length + '!' + word 6 | return { type: 'put', key: key, value: word } 7 | }) 8 | db.batch(batch, callback) 9 | } 10 | 11 | module.exports.query = function (db, word, callback) { 12 | var words = [] 13 | var key = word.length + '!' + word.replace(/\*/g, '') 14 | var error 15 | db.createReadStream({ start: key, end: key + '\xff' }) 16 | .on('data', function (data) { 17 | words.push(data.value) 18 | }) 19 | .on('error', function (err) { 20 | error = err 21 | }) 22 | .on('end', function () { 23 | callback(error, words) 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /exercises/streaming/exercise.js: -------------------------------------------------------------------------------- 1 | var generate = require('../../lib/generate') 2 | var isStream = require('is-stream') 3 | 4 | module.exports = require('../../lib/exercise')({ 5 | dir: __dirname, 6 | init: function () { 7 | var data = generate(5 + (Math.random() * 20 | 0)) 8 | var ops = [] 9 | 10 | Object.keys(data).forEach(function (key) { 11 | ops.push({ 12 | type: 'put', 13 | key: key, 14 | value: data[key] 15 | }) 16 | }) 17 | return { 18 | prepare: function (db, callback) { 19 | db.batch(ops, callback) 20 | }, 21 | exec: function (dir, mod, callback) { 22 | if (typeof mod !== 'function') { 23 | throw String('{error.mod.not_function}') 24 | } 25 | if (mod.length < 1) { 26 | throw String('{error.mod.not_long_enough}') 27 | } 28 | var result = mod(dir) 29 | if (!isStream(result)) { 30 | throw String('{error.result_no_stream}') 31 | } 32 | var data = [] 33 | var error 34 | result.on('data', function (entry) { 35 | data.push(entry) 36 | }) 37 | result.on('error', function (err) { 38 | error = err 39 | }) 40 | result.on('end', function () { 41 | callback(error, data) 42 | }) 43 | } 44 | } 45 | } 46 | }) 47 | -------------------------------------------------------------------------------- /exercises/streaming/problem.en.md: -------------------------------------------------------------------------------- 1 | Write a program that opens a LevelDB data-store using **`level`** and reads a 2 | few keys. 3 | 4 | Your program should be written as Node.js module with 1 argument that returns 5 | a stream. 6 | 7 | ```javascript 8 | module.exports = function (databaseDir) { 9 | var resultStream 10 | // your code... 11 | return resultStream 12 | } 13 | ``` 14 | 15 | 16 | The resulting stream should be transformed to a stream of strings with one chunk per entry formatted as `{key}={value}`. 17 | 18 | --- 19 | 20 | ## Hints: 21 | 22 | Since you don't know what the keys are in this exercise you can't 23 | use `get()`. Instead, you'll need to query the data store using 24 | a ReadStream. 25 | 26 | The `createReadStream()` method creates a standard Node object- 27 | stream where each chunk, or `data` event, is an entry in the data 28 | store. Each data object has both `key` and `value` properties for 29 | the entry. 30 | 31 | You can therefore stream the entire contents of the data store with: 32 | 33 | ```javascript 34 | db.createReadStream().on('data', function (data) { 35 | // data.key and data.value 36 | }) 37 | ``` 38 | 39 | There is still the need to `.close` the database after the stream has 40 | ended! 41 | 42 | You can use `through2` to process the stream. 43 | 44 | npm i through2 45 | 46 | or if you have no connection to 47 | 48 | file://{rootdir}/node_modules/through2 49 | 50 | Also note that the 'error' event may also be emitted if there is an 51 | I/O error. 52 | -------------------------------------------------------------------------------- /exercises/streaming/problem.ja.md: -------------------------------------------------------------------------------- 1 | **`level`**をつかって、LevelDBのデータストアをオープンし、エントリを 2 | 全て取り出すモジュールを書きましょう。 3 | 4 | 引数を1つだけ取り、ストリームを返すNodeモジュールとしてプログラムを 5 | 書いて下さい。 6 | 7 | ```javascript 8 | module.exports = function (databaseDir) { 9 | var resultStream 10 | // your code... 11 | return resultStream 12 | } 13 | ``` 14 | 15 | LevelDB中のエントリをそれぞれ`{key}={value}`の形式でチャンクに分けた 16 | ストリームを作成して下さい。 17 | 18 | --- 19 | 20 | ## ヒント: 21 | 22 | 今回はキーが分からない状態ですので、`get()`を使うことは出来ません。 23 | その代わり、ReadStreamを使ってデータストアに問い合わせることになります。 24 | 25 | `createReadStream()`メソッドはNodeの標準的なオブジェクトストリームを 26 | 作成します。このオブジェクトストリームのチャンク(あるいはデータイベント) 27 | はLevelDBのデータストアの各エントリとなります。データオブジェクトはエントリ 28 | に対応する`key`プロパティと`value`プロバティを持ちます。 29 | 30 | あなたは以下のようなコードでデータストアの全コンテンツのストリームを 31 | 作成することが出来ます。 32 | 33 | ```javascript 34 | db.createReadStream().on('data', function (data) { 35 | // data.key and data.value 36 | }) 37 | ``` 38 | 39 | ストリームが終了したあと、データベースを`.close`する必要があることを 40 | 忘れないで下さい! 41 | 42 | `through2`を使用すると良いでしょう。 43 | 44 | npm i through2 45 | 46 | もしオフラインであれば、以下のパスのものを使用して下さい。 47 | 48 | file://{rootdir}/node_modules/through2 49 | 50 | I/Oエラーにより'error'イベントが発生する可能性があることに注意して下さい。 51 | -------------------------------------------------------------------------------- /exercises/streaming/solution.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | var through2 = require('through2') 3 | 4 | module.exports = function (databaseDir) { 5 | var db = level(databaseDir) 6 | return db.createReadStream() 7 | .pipe(through2({objectMode: true}, function (data, enc, next) { 8 | this.push(data.key + '=' + data.value) 9 | next() 10 | }, function (next) { 11 | db.close(next) 12 | })) 13 | } 14 | -------------------------------------------------------------------------------- /exercises/sublevel/exercise.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../../lib/exercise')({ 2 | dir: __dirname, 3 | init: function () { 4 | return { 5 | prepare: function (db, callback) { 6 | callback() 7 | }, 8 | exec: function (dbDir, mod, callback) { 9 | if (typeof mod !== 'function') { 10 | throw String('{error.mod.not_function}') 11 | } 12 | if (mod.length < 2) { 13 | throw String('{error.mod.not_long_enough}') 14 | } 15 | mod(dbDir, function () { 16 | require('../../lib/read-db')(dbDir, 'utf8', callback) 17 | }) 18 | } 19 | } 20 | } 21 | }) 22 | -------------------------------------------------------------------------------- /exercises/sublevel/problem.en.md: -------------------------------------------------------------------------------- 1 | Sometimes you just need a clean namespace to fill up with junk without 2 | worrying about conflicting with existing keys in use. 3 | 4 | You can use **sublevel** for creating clean namespaces! 5 | 6 | You can extend a db handle to use sublevel by doing: 7 | 8 | ```javascript 9 | var db = sub(level(...)) 10 | ``` 11 | 12 | Then you can call `db.sublevel()` to make a new sublevel. 13 | 14 | Just call `db.sublevel()` with a name and you get an object that acts 15 | just like a normal db handle except it lives in a namespace: 16 | 17 | ```javascript 18 | var wizards = db.sublevel('wizards') 19 | ``` 20 | 21 | To level up on this adventure, you will get a database path as the 22 | first module argument. Create 2 sublevels, one called "robots" 23 | and the other called "dinosaurs". 24 | 25 | For each sublevel, create a key called "slogan". Set the _slogan_ for 26 | the dinosaurs sublevel to `'rawr'` and set the _slogan_ for the robots 27 | sublevel to `'beep boop'`. 28 | 29 | --- 30 | 31 | # Hints: 32 | 33 | Read more about sublevel here: 34 | 35 | http://npmjs.com/level-sublevel 36 | 37 | Or off-line on your local filesystem: 38 | 39 | {appDir}/docs/sublevel.html 40 | 41 | You will need to `npm install level-sublevel` to get started with this 42 | exercise. 43 | 44 | If you don't have an Internet connection, simply make a `node_modules` 45 | directory and copy the following directory into it: 46 | 47 | {appDir}/node_modules/level-sublevel/ 48 | 49 | To get output for debugging when running `{appname} run program.js` 50 | you should use console.error instead of console.log. 51 | -------------------------------------------------------------------------------- /exercises/sublevel/problem.ja.md: -------------------------------------------------------------------------------- 1 | 使用中のキーとの衝突を気にせずジャンクを埋めつくせるような、クリーンな名前空間が 2 | たまに必要になります。 3 | 4 | クリーンな名前空間を作成するために**sublevel**を使用できます。 5 | 6 | 以下のようにsublevelを使用するためにデータベースハンドルを拡張できます。 7 | 8 | ```javascript 9 | var db = sub(level(...)) 10 | ``` 11 | 12 | その後、`db.sublevel()`を呼び出すことで新しいsublevelを作成できます。 13 | 14 | `db.sublevel()`を名前渡して呼ぶだけで、通常のデータベースハンドルと 15 | (ある名前空間内に存在しているということ以外は)同じように振る舞う 16 | オブジェクトを取得することができます。 17 | 18 | ```javascript 19 | var wizards = db.sublevel('wizards') 20 | ``` 21 | 22 | このアドベンチャーでレベルアップするために、1つ目の引数としてデータ 23 | ベースのパスを受け取ります。 24 | 2つのsublevelを作成してください。1つは"robots"という名前で、 25 | もう1つは"dinosaurs"という名前です。 26 | 27 | 各sublevelのために"slogan"と言う名のキーを作成してください。 28 | dinosaursと呼ばれるsublevelの _slogan_ を`'rawr'`に設定し、 29 | robotsと呼ばれるsublevelの _slogan_ を`'beep boop'`に設定してください。 30 | 31 | --- 32 | 33 | # ヒント: 34 | 35 | sublevelに関しての詳細は以下のページで読めます。 36 | 37 | http://npmjs.com/level-sublevel 38 | 39 | または以下に配置されているローカルのファイルからオフラインでも読めます。 40 | 41 | {appDir}/docs/sublevel.html 42 | 43 | このエクササイズを始めるために`npm install level-sublevel`を実行しなければいけません。 44 | 45 | インターネットに接続できない場合、`node_modules`というディレクトリを作成し以下のディレクトリを作成した 46 | ディレクトリ内にコピーしてください。 47 | 48 | {appdir}/node_modules/level-sublevel/ 49 | 50 | デバッグのために`{appname} run program.js`を実行して出力を取得するために、 51 | console.logの代わりにconsole.errorを使用してください。 52 | -------------------------------------------------------------------------------- /exercises/sublevel/solution.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, callback) { 3 | var sub = require('level-sublevel') 4 | var db = sub(level(databaseDir)) 5 | var error 6 | db.on('error', function (err) { 7 | error = err 8 | }) 9 | 10 | var robots = db.sublevel('robots') 11 | robots.put('slogan', 'beep boop') 12 | 13 | var dinosaurs = db.sublevel('dinosaurs') 14 | dinosaurs.put('slogan', 'rawr') 15 | 16 | db.close(function (err) { 17 | callback(error || err) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "LEVEL ME UP SCOTTY!", 3 | "subtitle": "Learn You Some Node.js Databases", 4 | "exercise": { 5 | "all_your_base": "ALL YOUR BASE", 6 | "get_your_level_on": "Get Your Level On!", 7 | "basics_get": "Basics: GET", 8 | "basics_put": "Basics: PUT", 9 | "basics_batch": "Basics: BATCH", 10 | "streaming": "Streaming", 11 | "horse_js_count": "@horse_js Count", 12 | "horse_js_tweets": "@horse_js Tweets", 13 | "keywise": "Keywise", 14 | "short_scrabble_words": "Short Scrabble Words", 15 | "sublevel": "Sublevel", 16 | "multilevel": "Multilevel" 17 | }, 18 | "diff": { 19 | "unexpected": "Unexpected property", 20 | "missing": "Missing", 21 | "expected": "Expected", 22 | "expected_tobe": "to be", 23 | "expected_got": "but got" 24 | }, 25 | "error": { 26 | "mod": { 27 | "broken": "An error occured while loading the module", 28 | "not_long_enough": "The module doesn't have enough arguments, it has to look like:\n\n function (db, key, callback) {...}", 29 | "not_function": "The module doesn't return a function", 30 | "unexpected": "An error occured while executing the module", 31 | "not_object": "The module doesn't return an object", 32 | "init_missing": "'init' is not a function", 33 | "query_missing": "'query' is not a function" 34 | }, 35 | "timeout": "Timeout: The module didn't respond after 10 seconds.", 36 | "not_same": "The output of the module doesn't match the expected output", 37 | "db": { 38 | "not_closed": "The database directory is still locked!\n\nClose it with `db.close(function () {})`" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /i18n/help/en.md: -------------------------------------------------------------------------------- 1 | # Having trouble with a {appname} exercise? 2 | 3 | A team of expert helper elves is eagerly waiting to assist you in 4 | mastering the basics of Node.js, or Level* / Node Databases in 5 | particular, simply go to: 6 | 7 | https://github.com/nodeschool/discussions/issues 8 | 9 | and add a **New Issue** and let us know what you're having trouble 10 | with. There are no __dumb__ questions! You may be 11 | redirected to one of the support channels below, depending on how 12 | complex your question is. 13 | 14 | If you have a specific question about LevelUP or one of the level* 15 | packages used in {appname}, you could consider one of the following 16 | support channels instead: 17 | 18 | - Visit ##leveldb on Freenode IRC 19 | - Submit your question to the Node.js Level* Google Group: 20 | https://groups.google.com/forum/#!forum/node-levelup 21 | - Open a new issue @ https://github.com/workshopper/node-levelup 22 | 23 | # Found a bug with {appname} or just want to contribute? 24 | 25 | The official repository for {appname} is: 26 | 27 | https://github.com/workshopper/levelmeup/ 28 | 29 | Feel free to file a bug report or (preferably) a pull request. 30 | -------------------------------------------------------------------------------- /i18n/help/ja.md: -------------------------------------------------------------------------------- 1 | # {appname} の課題で問題がありましたか? 2 | 3 | あなたがNode.jsの基本、あるいはLevel* / Node データベースを 4 | マスターすることに関して、エキスパート達が「是非サポートしたい!」 5 | と待っています。 6 | 以下のURLに行ってみましょう。 7 | 8 | https://github.com/nodeschool/discussions/issues 9 | 10 | **New Issue**を追加して、あなたが直面している問題を教えて下さい。 11 | 意味のない質問なんてありません! 12 | 込み入った質問の場合、下の方に記載されているチャンネルのどこかに 13 | 質問が転送されるかもしれません。 14 | 15 | もしあなたの質問がLevelUP、あるいは{appname}で使われている 16 | level*パッケージ特有のものであれば、以下のサポートチャンネルの 17 | 何れかを使うことを検討してみて下さい。 18 | 19 | - Freenode IRCの ##leveldb を訪れてみて下さい。 20 | - Node.js Level* Google Groupに質問してみて下さい。: 21 | https://groups.google.com/forum/#!forum/node-levelup 22 | - https://github.com/workshopper/node-levelup にIssueを作ってみて下さい。 23 | 24 | # {appname} のバグを見つけた、あるいは貢献して見たい場合 25 | 26 | {appname} の公式レポジトリは以下です。 27 | 28 | https://github.com/workshopper/levelmeup/ 29 | 30 | 気軽にバグレポートを下さい。 31 | プルリクエストでもOKです。(こっちの方がいい!) 32 | -------------------------------------------------------------------------------- /i18n/ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "LEVEL ME UP SCOTTY!", 3 | "subtitle": "Node.jsでのデータベースについて", 4 | "exercise": { 5 | "all_your_base": "ALL YOUR BASE", 6 | "get_your_level_on": "Get Your Level On!", 7 | "basics_get": "基礎: GET", 8 | "basics_put": "基礎: PUT", 9 | "basics_batch": "基礎: BATCH", 10 | "streaming": "ストリーミング", 11 | "horse_js_count": "@horse_js カウント", 12 | "horse_js_tweets": "@horse_js ツイート", 13 | "keywise": "キー的な話", 14 | "short_scrabble_words": "スクラブルワード", 15 | "sublevel": "Sublevel", 16 | "multilevel": "Multilevel" 17 | }, 18 | "error": { 19 | "mod": { 20 | "broken": "モジュールのロード中にエラーが発生しました", 21 | "not_long_enough": "モジュールの引数の数が不足しています。以下の形式にして下さい。\n\n function (db, key, callback) {...}", 22 | "not_function": "モジュールが関数を返していません", 23 | "unexpected": "モジュールの実行中にエラーが発生しました", 24 | "not_object": "モジュールがオブジェクトを返していません", 25 | "init_missing": "'init'関数がありません", 26 | "query_missing": "'query'関数がありません" 27 | }, 28 | "timeout": "タイムアウト: 10秒以上モジュールから反応がありません", 29 | "not_same": "モジュールの出力が期待する結果と一致しません", 30 | "db": { 31 | "not_closed": "データベースディレクトリがロックされたままです!\n\n`db.close(function () {})`を使ってクローズして下さい。" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /levelmeup.js: -------------------------------------------------------------------------------- 1 | var workshopper = require('workshopper-adventure') 2 | var levelMeUp = workshopper({ 3 | appDir: __dirname, 4 | menu: { 5 | bg: 'green' 6 | }, 7 | languages: ['en', 'ja'], 8 | header: require('workshopper-adventure/default/header'), 9 | footer: require('workshopper-adventure/default/footer'), 10 | fail: require('workshopper-adventure/default/fail'), 11 | pass: require('workshopper-adventure/default/pass'), 12 | help: { 13 | file: './i18n/help/{lang}.md' 14 | } 15 | }) 16 | 17 | levelMeUp.addAll([ 18 | 'all_your_base', 19 | 'get_your_level_on', 20 | 'basics_get', 21 | 'basics_put', 22 | 'basics_batch', 23 | 'streaming', 24 | 'horse_js_count', 25 | 'horse_js_tweets', 26 | 'keywise', 27 | 'short_scrabble_words', 28 | 'sublevel', 29 | 'multilevel' 30 | ]) 31 | 32 | module.exports = levelMeUp 33 | -------------------------------------------------------------------------------- /levelmeup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/workshopper/levelmeup/b4462bfb522fc7ad45b189a060a6e2b4908c2d89/levelmeup.png -------------------------------------------------------------------------------- /lib/exercise.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var os = require('os') 3 | var level = require('level') 4 | var rimraf = require('rimraf') 5 | var deepDiff = require('deep-diff') 6 | var execModule = require('exec-module') 7 | var formatDiff = require('./formatDiff') 8 | 9 | function setupDb (name) { 10 | // eslint-disable-next-line node/no-deprecated-api 11 | var dir = path.join(os.tmpdir ? os.tmpdir() : os.tmpDir(), '~levelmeup_' + name + '_' + process.pid) 12 | rimraf.sync(dir) 13 | return dir 14 | } 15 | 16 | function exec (opts, file, callback) { 17 | var dbDir = setupDb('1') 18 | execModule(file, { 19 | setUp: function (file, opt, callback) { 20 | var db = level(dbDir) 21 | opts.prepare(db, function (err) { 22 | if (err) { 23 | return callback(err) 24 | } 25 | db.close(callback) 26 | }) 27 | }, 28 | exec: function (file, opt, mod, callback) { 29 | opts.exec(dbDir, mod, callback) 30 | }, 31 | timeout: 5000, 32 | tearDown: function (file, opt, err, data, callback) { 33 | var db = level(dbDir, function (err) { 34 | if (err && err.type === 'OpenError') { 35 | return callback(new Error(file + '\n\n{error.db.not_closed}')) 36 | } else if (err) { 37 | return callback(new Error(file + '\n\n{error.mod.unexpected}:\n\n```\n' + ((err && err.stack) || err) + '\n```')) 38 | } 39 | db.close(function () { 40 | try { 41 | rimraf.sync(dbDir) 42 | } catch (e) { 43 | // eat rimraf errors 44 | } 45 | callback(null, data) 46 | }) 47 | }) 48 | } 49 | }, callback) 50 | } 51 | 52 | module.exports = function (opt) { 53 | return { 54 | problem: { 55 | file: path.join(opt.dir, 'problem.{lang}.md') 56 | }, 57 | solution: { 58 | file: path.join(opt.dir, 'solution.js'), 59 | type: 'js' 60 | }, 61 | verify: function (args, callback) { 62 | var cmd = opt.init() 63 | var finish = function (err) { 64 | if (err) { 65 | callback(null, false, err) 66 | } 67 | callback(null, true) 68 | } 69 | exec(cmd, path.join(opt.dir, 'solution.js'), function (err, data) { 70 | if (err) { 71 | return finish('Error in this workshopper!\n\n```\n' + err.stack + '\n```') 72 | } 73 | exec(cmd, path.resolve(process.cwd(), args[0]), function (err, data2) { 74 | if (err) { 75 | return finish('```\n' + err.stack + '\n```') 76 | } 77 | var diffs = deepDiff(data, data2) 78 | if (diffs === undefined) { 79 | return finish() 80 | } 81 | try { 82 | finish('{error.not_same}:\n' + formatDiff(diffs)) 83 | } catch (e) { 84 | console.log(e) 85 | } 86 | }) 87 | }) 88 | }, 89 | run: function (args, callback) { 90 | var cmd = opt.init() 91 | exec(cmd, path.resolve(process.cwd(), args[0]), function (err, data) { 92 | if (err) { 93 | return callback(err, false) 94 | } 95 | console.log(JSON.stringify(data, null, 2)) 96 | callback(null, true) 97 | }) 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /lib/formatDiff.js: -------------------------------------------------------------------------------- 1 | function formatNew (diff) { 2 | return '{diff.unexpected}: ' + diff.path.join('.') 3 | } 4 | 5 | function formatDeleted (diff) { 6 | return '{diff.missing}: ' + diff.path.join('.') 7 | } 8 | 9 | function formatEdited (diff) { 10 | return '{diff.expected} `' + (diff.path.join('.') || 'result') + '` {diff.expected_tobe} \n\n```\n' + JSON.stringify(diff.lhs, null, 2) + '\n```\n{diff.expected_got}\n```\n' + JSON.stringify(diff.rhs, null, 2) + '```\n\n' 11 | } 12 | 13 | function formatArray (diff) { 14 | diff.item.path = [diff.path.join('.') + '[' + diff.index + ']'] 15 | return formatChange(diff.item) 16 | } 17 | 18 | function formatChange (diff) { 19 | if (!diff.path) { 20 | diff.path = [] 21 | } 22 | if (diff.kind === 'N') { 23 | return formatNew(diff) 24 | } 25 | if (diff.kind === 'D') { 26 | return formatDeleted(diff) 27 | } 28 | if (diff.kind === 'E') { 29 | return formatEdited(diff) 30 | } 31 | if (diff.kind === 'A') { 32 | return formatArray(diff) 33 | } 34 | return '' 35 | } 36 | 37 | function formatChanges (changes) { 38 | return changes.map(formatChange).join('\n') 39 | } 40 | 41 | module.exports = function (diffs) { 42 | return '\n\n' + formatChanges(diffs) + '\n' 43 | } 44 | -------------------------------------------------------------------------------- /lib/generate.js: -------------------------------------------------------------------------------- 1 | var gibberish = require('./gibberish') 2 | 3 | module.exports = function (i) { 4 | var key = 'level_' + Date.now().toString(32) + '_' + (Math.random() * 1000 | 0) 5 | var data = {} 6 | while (i-- > 0) { 7 | data[key + i] = gibberish() 8 | } 9 | return data 10 | } 11 | -------------------------------------------------------------------------------- /lib/gibberish.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | module.exports = require('echomunge/dir2gibberish').bind(null, path.join(__dirname, '../node_modules/level/')) 3 | -------------------------------------------------------------------------------- /lib/read-db.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (dir, valueEncoding, callback) { 4 | level(dir, { valueEncoding: valueEncoding }, function (err, db) { 5 | if (err) { 6 | if (err.type === 'OpenError') { 7 | return callback(new Error(dir + '\n\n{error.db.not_closed}')) 8 | } else { 9 | return callback(new Error(dir + '\n\n{error.mod.unexpected}:\n\n```\n' + ((err && err.stack) || err) + '\n```')) 10 | } 11 | } 12 | var result = {} 13 | var stream = db.readStream() 14 | var error 15 | stream.on('data', function (entry) { 16 | result[entry.key] = entry.value 17 | }) 18 | stream.on('error', function (err) { 19 | error = err 20 | }) 21 | stream.on('end', function () { 22 | db.close(function (err) { 23 | callback(error || err, result) 24 | }) 25 | }) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "levelmeup", 3 | "version": "1.0.1", 4 | "description": "Level Me Up Scotty! An intro to Node.js databases via a set of self-guided workshops.", 5 | "author": "Rod Vagg (https://github.com/rvagg)", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/workshopper/levelmeup.git" 9 | }, 10 | "scripts": { 11 | "test": "standard && workshopper-adventure-test", 12 | "fetch-horse": "./scripts/fetch_horse.js", 13 | "lint": "standard", 14 | "release": "./node_modules/.bin/standard-version" 15 | }, 16 | "contributors": [ 17 | "Rod Vagg (https://github.com/rvagg)", 18 | "Eugene Ware (https://github.com/eugeneware)", 19 | "James Halliday (https://github.com/substack)", 20 | "Jake Verbaten (https://github.com/raynos)", 21 | "Julian Gruber (https://github.com/juliangruber)", 22 | "Robert Kowalski (https://github.com/robertkowalski)", 23 | "Lars-Magnus Skog (https://github.com/ralphtheninja)", 24 | "Martin Heidegger (https://github.com/martinheidegger)", 25 | "Masashi Hirano (https://github.com/shisama)", 26 | "Akihito Takeuchi (https://github.com/akihito-takeuchi)" 27 | ], 28 | "license": "MIT", 29 | "dependencies": { 30 | "deep-diff": "^0.3.8", 31 | "echomunge": "~0.2.0", 32 | "exec-module": "^2.0.0", 33 | "is-stream": "^1.1.0", 34 | "level": "^2.0.1", 35 | "level-sublevel": "^6.6.1", 36 | "lodash.sample": "^4.2.1", 37 | "multilevel": "^7.3.0", 38 | "rimraf": "^2.6.2", 39 | "through2": "^2.0.3", 40 | "workshopper-adventure": "^6.0.3" 41 | }, 42 | "devDependencies": { 43 | "standard": "^10.0.3", 44 | "standard-version": "^4.2.0", 45 | "twitter": "^1.7.1", 46 | "workshopper-adventure-test": "^1.1.2" 47 | }, 48 | "bin": { 49 | "levelmeup": "./bin/levelmeup" 50 | }, 51 | "preferGlobal": true 52 | } 53 | -------------------------------------------------------------------------------- /scripts/fetch_horse.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var Twitter = require('twitter') 3 | var client = new Twitter({ 4 | consumer_key: process.env.CONSUMER_KEY, 5 | consumer_secret: process.env.CONSUMER_SECRET, 6 | access_token_key: process.env.TOKEN_KEY, 7 | access_token_secret: process.env.TOKEN_SECRET 8 | }) 9 | 10 | var all = [] 11 | var fs = require('fs') 12 | var path = require('path') 13 | var out = fs.createWriteStream(path.join(__dirname, '..', 'data', 'horse_js.json')) 14 | 15 | console.log('Loading all tweets from @horse_js') 16 | out.write('[\n') 17 | function more (formerId) { 18 | client.get('statuses/user_timeline', {screen_name: 'horse_js', count: 200, max_id: formerId}, function (error, tweets) { 19 | if (error) { 20 | if (error.length === 1 && error[0].code === 215) { 21 | console.log('Authentication Incorrect, please set following environment variables:') 22 | console.log('- CONSUMER_KEY') 23 | console.log('- CONSUMER_SECRET') 24 | console.log('- TOKEN_KEY') 25 | console.log('- TOKEN_SECRET') 26 | } else { 27 | console.log('Error: ') 28 | console.log(error) 29 | } 30 | process.exit(1) 31 | } 32 | console.log('Found tweets: ' + all.length + '〜' + (all.length + tweets.length)) 33 | tweets.forEach(function (tweet, nr) { 34 | if (!tweet.retweeted) { 35 | if (nr !== 0 || all.length !== 0) { 36 | out.write(',\n') 37 | } 38 | out.write(JSON.stringify({ 39 | type: 'put', 40 | key: new Date(tweet.created_at).toISOString(), 41 | value: tweet.text 42 | })) 43 | } 44 | }) 45 | all = all.concat(tweets) 46 | if (all.length < 5000 && tweets.length > 0) { 47 | var id = tweets[tweets.length - 1].id 48 | console.log('Continuing from ' + id) 49 | more(id) 50 | } else { 51 | out.write('\n]') 52 | out.end() 53 | } 54 | }) 55 | } 56 | 57 | more() 58 | -------------------------------------------------------------------------------- /test/all_your_base/invalid_01.js: -------------------------------------------------------------------------------- 1 | module.exports = function (x, y, cb) { 2 | cb(null, 'ALL YOUR ' + y + ' ARE BELONG TO ' + x) 3 | } 4 | -------------------------------------------------------------------------------- /test/all_your_base/invalid_02.js: -------------------------------------------------------------------------------- 1 | module.exports = function (x, y, cb) { 2 | cb(null, 'all your ' + x + ' are belong to ' + y) 3 | } 4 | -------------------------------------------------------------------------------- /test/all_your_base/valid_01.js: -------------------------------------------------------------------------------- 1 | module.exports = function (x, y, cb) { 2 | cb(null, 'ALL YOUR ' + x + ' ARE BELONG TO ' + y) 3 | } 4 | -------------------------------------------------------------------------------- /test/basics_batch/invalid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, input, callback) { 4 | var db = level(databaseDir, function () { 5 | Object.keys(input.put).forEach(function (key) { 6 | db.put(key, input.put[key]) 7 | }) 8 | input.del.forEach(db.del.bind(db)) 9 | db.close(callback) 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /test/basics_batch/valid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, input, callback) { 4 | var db = level(databaseDir, function () { 5 | var batch = db.batch() 6 | Object.keys(input.put).forEach(function (key) { 7 | batch.put(key, input.put[key]) 8 | }) 9 | input.del.forEach(function (key) { 10 | batch.del(key) 11 | }) 12 | batch.write(function () { 13 | db.close(callback) 14 | }) 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /test/basics_batch/valid_02.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, input, callback) { 4 | var db = level(databaseDir, function () { 5 | var putKeys = Object.keys(input.put) 6 | var nextPut = function () { 7 | var key = putKeys.pop() 8 | db.put(key, input.put[key], function () { 9 | if (putKeys.length === 0) { 10 | db.close(callback) 11 | } else { 12 | nextPut() 13 | } 14 | }) 15 | } 16 | var nextDel = function () { 17 | var key = input.del.pop() 18 | db.del(key, function () { 19 | if (input.del.length === 0) { 20 | nextPut() 21 | } else { 22 | nextDel() 23 | } 24 | }) 25 | } 26 | nextDel() 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /test/basics_batch/valid_03.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, input, callback) { 4 | var db = level(databaseDir, function () { 5 | Object.keys(input.put).forEach(function (key) { 6 | db.put(key, input.put[key]) 7 | }) 8 | input.del.forEach(function (key) { 9 | db.del(key) 10 | }) 11 | db.close(callback) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /test/basics_batch/valid_04.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, input, callback) { 4 | var db = level(databaseDir, function () { 5 | var batch = db.batch() 6 | Object.keys(input.put).forEach(function (key) { 7 | batch.put(key, input.put[key]) 8 | }) 9 | input.del.forEach(batch.del.bind(batch)) 10 | batch.write(function () { 11 | db.close(callback) 12 | }) 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /test/basics_get/invalid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (dir, callback) { 4 | var db = level(dir) 5 | var result = [] 6 | var fetchNext = function (i) { 7 | db.get('key' + i, function (err, data) { 8 | if (err) { 9 | throw err 10 | } 11 | 12 | result.push(data) 13 | 14 | if (i === 100) { 15 | return db.close(callback.bind(null, null, result)) 16 | } 17 | 18 | fetchNext(i + 1) 19 | }) 20 | } 21 | fetchNext(0) 22 | } 23 | -------------------------------------------------------------------------------- /test/basics_get/invalid_02.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (dir, callback) { 4 | var db = level(dir) 5 | var result = [] 6 | var fetchNext = function (i) { 7 | db.get('key' + i, function (err, data) { 8 | if (!err) { 9 | result.unshift(data) 10 | } 11 | 12 | if (i === 100) { 13 | return db.close(callback.bind(null, null, result)) 14 | } 15 | 16 | fetchNext(i + 1) 17 | }) 18 | } 19 | fetchNext(0) 20 | } 21 | -------------------------------------------------------------------------------- /test/basics_get/valid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (dir, callback) { 4 | var db = level(dir) 5 | var result = [] 6 | var fetchNext = function (i) { 7 | db.get('key' + i, function (err, data) { 8 | if (!err) { 9 | result.unshift(data) 10 | } 11 | 12 | if (i === 0) { 13 | return db.close(callback.bind(null, null, result)) 14 | } 15 | 16 | fetchNext(i - 1) 17 | }) 18 | } 19 | fetchNext(100) 20 | } 21 | -------------------------------------------------------------------------------- /test/basics_put/invalid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, obj, callback) { 3 | var db = level(databaseDir) 4 | db.put('a', 'b') // additional put 5 | for (var key in obj) { 6 | db.put(key, obj[key]) 7 | } 8 | db.close(callback) 9 | } 10 | -------------------------------------------------------------------------------- /test/basics_put/valid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, obj, callback) { 3 | var db = level(databaseDir) 4 | Object.keys(obj).forEach(function (key) { 5 | db.put(key, obj[key]) 6 | }) 7 | db.close(callback) 8 | } 9 | -------------------------------------------------------------------------------- /test/basics_put/valid_02.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, obj, callback) { 3 | var db = level(databaseDir) 4 | var keys = Object.keys(obj) 5 | var next = function () { 6 | var key = keys.shift() 7 | db.put(key, obj[key], function () { 8 | if (keys.length === 0) { 9 | return db.close(callback) 10 | } 11 | next() 12 | }) 13 | } 14 | next() 15 | } 16 | -------------------------------------------------------------------------------- /test/get_your_level_on/invalid_01.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/get_your_level_on/invalid_02.js: -------------------------------------------------------------------------------- 1 | throw new Error('1') 2 | -------------------------------------------------------------------------------- /test/get_your_level_on/invalid_03.js: -------------------------------------------------------------------------------- 1 | module.exports = function (db, key, callback) {} 2 | -------------------------------------------------------------------------------- /test/get_your_level_on/invalid_04.js: -------------------------------------------------------------------------------- 1 | module.exports = function (db, key, callback) { 2 | throw new Error('abcd') 3 | } 4 | -------------------------------------------------------------------------------- /test/get_your_level_on/invalid_05.js: -------------------------------------------------------------------------------- 1 | module.exports = function (db, key, callback) { 2 | setImmediate(function () { 3 | throw new Error('def') 4 | }) 5 | } 6 | -------------------------------------------------------------------------------- /test/get_your_level_on/invalid_06.js: -------------------------------------------------------------------------------- 1 | module.exports = function (dir, key, callback) { 2 | setTimeout(function () { 3 | callback(null, { 4 | dir: dir, 5 | key: key 6 | }) 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /test/get_your_level_on/invalid_07.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, key, callback) { 4 | var db = level(databaseDir) 5 | db.get(key, function (err, value) { 6 | if (err) { 7 | return callback(err) 8 | } 9 | db.close(function () { 10 | callback(null, 'abcd') 11 | }) 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /test/get_your_level_on/valid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, key, callback) { 4 | var db = level(databaseDir) 5 | var error 6 | db.get(key, function (err, value) { 7 | if (err) { 8 | error = err 9 | } 10 | db.close(function (err) { 11 | callback(error || err, value) 12 | }) 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /test/horse_js_count/invalid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, date, callback) { 3 | var db = level(databaseDir, function () { 4 | var stream = db.createReadStream({start: date}) 5 | var i = 1 6 | var error 7 | stream.on('data', function () { 8 | i++ 9 | }) 10 | stream.on('error', function (err) { 11 | error = err 12 | }) 13 | stream.on('end', function () { 14 | db.close(function (err) { 15 | callback(error || err, i) 16 | }) 17 | }) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /test/horse_js_count/valid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, date, callback) { 3 | var db = level(databaseDir, function () { 4 | var stream = db.createReadStream({start: date}) 5 | var i = 0 6 | var error 7 | stream.on('data', function () { 8 | i++ 9 | }) 10 | stream.on('error', function (err) { 11 | error = err 12 | }) 13 | stream.on('end', function () { 14 | db.close(function (err) { 15 | callback(error || err, i) 16 | }) 17 | }) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /test/horse_js_tweets/invalid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, day, callback) { 3 | var db = level(databaseDir) 4 | var stream = db.createReadStream({ 5 | start: day, 6 | end: day 7 | }) 8 | var result = [] 9 | var error 10 | stream.on('data', function (data) { 11 | result.push(data.value) 12 | }) 13 | stream.on('error', function (err) { 14 | error = err 15 | }) 16 | stream.on('end', function () { 17 | db.close(function (err) { 18 | callback(error || err, result) 19 | }) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /test/horse_js_tweets/valid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, day, callback) { 3 | var db = level(databaseDir) 4 | var stream = db.createReadStream({ 5 | start: day, 6 | end: day + '\xff' 7 | }) 8 | var result = [] 9 | var error 10 | stream.on('data', function (data) { 11 | result.push(data.value) 12 | }) 13 | stream.on('error', function (err) { 14 | error = err 15 | }) 16 | stream.on('end', function () { 17 | db.close(function (err) { 18 | callback(error || err, result) 19 | }) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /test/keywise/invalid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, keywiseFile, callback) { 4 | var db = level(databaseDir, { valueEncoding: 'utf8' }) 5 | db.batch(require(keywiseFile).map(function (row) { 6 | var key = row.name 7 | if (row.type === 'repo') { 8 | key = row.user + '!' + key 9 | } 10 | return { 11 | type: 'put', 12 | key: key, 13 | value: row 14 | } 15 | }), function (error) { 16 | db.close(function (err) { 17 | callback(error || err) 18 | }) 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /test/keywise/valid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, keywiseFile, callback) { 4 | var db = level(databaseDir, { valueEncoding: 'json' }) 5 | db.batch(require(keywiseFile).map(function (row) { 6 | var key = row.name 7 | if (row.type === 'repo') { 8 | key = row.user + '!' + key 9 | } 10 | return { 11 | type: 'put', 12 | key: key, 13 | value: row 14 | } 15 | }), function (error) { 16 | db.close(function (err) { 17 | callback(error || err) 18 | }) 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /test/keywise/valid_02.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, keywiseFile, callback) { 4 | var db = level(databaseDir) 5 | db.batch(require(keywiseFile).map(function (row) { 6 | var key = row.name 7 | if (row.type === 'repo') { 8 | key = row.user + '!' + key 9 | } 10 | return { 11 | type: 'put', 12 | key: key, 13 | value: JSON.stringify(row) 14 | } 15 | }), function (error) { 16 | db.close(function (err) { 17 | callback(error || err) 18 | }) 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /test/keywise/valid_03.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | 3 | module.exports = function (databaseDir, keywiseFile, callback) { 4 | var db = level(databaseDir) 5 | db.batch(require(keywiseFile).map(function (row) { 6 | var key = row.name 7 | if (row.type === 'repo') { 8 | key = row.user + '!' + key 9 | } 10 | return { 11 | type: 'put', 12 | key: key, 13 | value: JSON.stringify(row) 14 | } 15 | }), function (error) { 16 | db.close(function (err) { 17 | callback(error || err) 18 | }) 19 | }) 20 | } 21 | -------------------------------------------------------------------------------- /test/multilevel/invalid_01.js: -------------------------------------------------------------------------------- 1 | var multilevel = require('multilevel') 2 | var net = require('net') 3 | 4 | module.exports = function (callback) { 5 | var db = multilevel.client() 6 | var con = net.connect(4545) 7 | con.pipe(db.createRpcStream()).pipe(con) 8 | 9 | db.get('multilevelmeup', function (err, value) { 10 | con.end(callback.bind(null, err, value + 1)) 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /test/multilevel/valid_01.js: -------------------------------------------------------------------------------- 1 | var multilevel = require('multilevel') 2 | var net = require('net') 3 | 4 | module.exports = function (callback) { 5 | var db = multilevel.client() 6 | var con = net.connect(4545) 7 | con.pipe(db.createRpcStream()).pipe(con) 8 | 9 | db.get('multilevelmeup', function (err, value) { 10 | con.end(callback.bind(null, err, value)) 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /test/short_scrabble_words/invalid_01.js: -------------------------------------------------------------------------------- 1 | module.exports = function () {} 2 | -------------------------------------------------------------------------------- /test/short_scrabble_words/invalid_02.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /test/short_scrabble_words/invalid_03.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | init: 1 3 | } 4 | -------------------------------------------------------------------------------- /test/short_scrabble_words/invalid_04.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | init: function () {} 3 | } 4 | -------------------------------------------------------------------------------- /test/short_scrabble_words/invalid_05.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | init: function () {}, 3 | query: 1 4 | } 5 | -------------------------------------------------------------------------------- /test/short_scrabble_words/invalid_06.js: -------------------------------------------------------------------------------- 1 | module.exports.init = function (db, words, callback) { 2 | var batch = words.map(function (word) { 3 | // length-prefixed keys, separated by a '!' so we 4 | // can query by length 5 | var key = word.length + '!' + word 6 | return { type: 'put', key: key, value: word } 7 | }) 8 | db.batch(batch, callback) 9 | } 10 | 11 | module.exports.query = function (db, word, callback) { 12 | var words = [] 13 | var key = word.length + '!' + word 14 | var error 15 | db.createReadStream({ start: key, end: key + '\xff' }) 16 | .on('data', function (data) { 17 | words.push(data.key) 18 | }) 19 | .on('error', function (err) { 20 | error = err 21 | }) 22 | .on('end', function () { 23 | callback(error, words) 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /test/short_scrabble_words/valid_01.js: -------------------------------------------------------------------------------- 1 | module.exports.init = function (db, words, callback) { 2 | var batch = words.map(function (word) { 3 | return { type: 'put', key: word.length + '!' + word, value: word } 4 | }) 5 | db.batch(batch, callback) 6 | } 7 | 8 | module.exports.query = function (db, word, callback) { 9 | var words = [] 10 | var key = word.length + '!' + word.replace(/\*/g, '') 11 | var error 12 | db.createReadStream({ start: key, end: key + '\xff' }) 13 | .on('data', function (data) { 14 | words.push(data.value) 15 | }) 16 | .on('error', function (err) { 17 | error = err 18 | }) 19 | .on('end', function () { 20 | callback(error, words) 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /test/streaming/invalid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | var Readable = require('stream').Readable 3 | module.exports = function (databaseDir) { 4 | var db = level(databaseDir) 5 | var stream = db.createReadStream() 6 | var result = new Readable() 7 | result.setEncoding('utf8') 8 | result._read = function (size) {} 9 | stream.on('data', function (data) { 10 | result.push(data.key + ' = ' + data.value) 11 | }) 12 | stream.on('end', function () { 13 | db.close(function () { 14 | result.push(null) 15 | }) 16 | }) 17 | stream.on('error', function (err) { 18 | result.emit('error', err) 19 | }) 20 | return result 21 | } 22 | -------------------------------------------------------------------------------- /test/streaming/valid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | var Readable = require('stream').Readable 3 | module.exports = function (databaseDir) { 4 | var db = level(databaseDir) 5 | var stream = db.createReadStream() 6 | var result = new Readable() 7 | result.setEncoding('utf8') 8 | result._read = function (size) {} 9 | stream.on('data', function (data) { 10 | result.push(data.key + '=' + data.value) 11 | }) 12 | stream.on('end', function () { 13 | db.close(function () { 14 | result.push(null) 15 | }) 16 | }) 17 | stream.on('error', function (err) { 18 | result.emit('error', err) 19 | }) 20 | return result 21 | } 22 | -------------------------------------------------------------------------------- /test/sublevel/invalid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, callback) { 3 | var db = require('level-sublevel')(level(databaseDir)) 4 | db.sublevel('robots').put('slogan', 'beep boop!') 5 | db.sublevel('dinosaurs').put('slogan', 'rawr') 6 | db.close(callback) 7 | } 8 | -------------------------------------------------------------------------------- /test/sublevel/invalid_02.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, callback) { 3 | var db = require('level-sublevel')(level(databaseDir)) 4 | var robots = db.sublevel('robots') 5 | var dinosaurs = db.sublevel('dinosaurs') 6 | 7 | ;[robots, dinosaurs].map(function (lev, i) { 8 | lev.put('slogan', i === 1 ? 'rawr' : 'beep boop') 9 | }) 10 | setImmediate(callback) 11 | } 12 | -------------------------------------------------------------------------------- /test/sublevel/valid_01.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, callback) { 3 | var db = require('level-sublevel')(level(databaseDir)) 4 | db.sublevel('robots').put('slogan', 'beep boop') 5 | db.sublevel('dinosaurs').put('slogan', 'rawr') 6 | db.close(callback) 7 | } 8 | -------------------------------------------------------------------------------- /test/sublevel/valid_02.js: -------------------------------------------------------------------------------- 1 | var level = require('level') 2 | module.exports = function (databaseDir, callback) { 3 | var db = level(databaseDir) 4 | db.put('!robots!slogan', 'beep boop') 5 | db.put('!dinosaurs!slogan', 'rawr') 6 | db.close(callback) 7 | } 8 | --------------------------------------------------------------------------------