Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

NOTICE: replaced byhttps://github.com/fluents/chain-able

NotificationsYou must be signed in to change notification settings

fliphub/flipchain

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NPM versionMIT Licensefliphubflipfamfluent

core chaining library, heavily based onwebpack-chain, but not webpack-specific.

🏰 benefits

writing an api using flipchain means writing a single fluent api, but getting 3 apis as a result!

  • 🍉 rehydratable configurations
  • ⛓ fluent chainable api
  • 🍦 object configs that are easily merged deep

🌊 what?

fluent

imagine there are 2 people by the water, & the goal is to make 10 splashes.

as with most skills, you get better at skipping rocks the more that you do it.a lot of people cannot skip rocks, or they do not like to skip rocks, but they can still throw rocks and make a splash. think of this like non-fluent/vanilla-calls

Chain.prop()Chain.longer()Chain.intoSomeShapes()

or throwing a really huge rock into the water, and getting the splashes to make more splashes.

Chain.from({prop:null,longer:null,intoSomeShapes:null,})

pebblesusing method chaining looks similar to skipping rocks

Chain.prop().longer().intoSomeShapes()

writing an application with a fluent interface allows people to use it all three ways, and you only have to write it one way.

📘 examples

👋 intro

constChainedMap=require('./ChainedMapExtendable')classEasyFluentextendsChainedMap{constructor(parent){super(parent)// extend a list of strings for easy chainable methodsthis.extend(['eh'])// same as .extend,// but when called with no arguments,// default is used (`true` in this case)// third param is optionally a prefix for inversified// for example, `no` => `noCanada()` for inverse valuethis.extendPrefixed(['canada'],true,'no')}// if more advanced data changes are needed// or if the syntax is preferred for use with typescript or flowtype// .set, .get, .has are availableigloo(igloo){this.set('igloo',igloo)returnthis}toConfig(){returnthis.entries()}}// {igloo: 'fire', canada: false, eh: 'moose'}constconfig=newEasyFluent().igloo('fire').noCanada().eh('moose').toConfig()// this is == configconsthydrated=newEasyFluent().from(config).toConfig()// canada is now trueconstmerged=newEasyFluent().merge(config).merge({canada:true}).toConfig()

🕳🏊 advanced

constChainedMap=require('./ChainedMapExtendable')constChainedSet=require('./ChainedSet')classAdvancedextendsChainedMap{staticinit(parent){returnnewAdvanced(parent)}constructor(parent){super(parent)this.list=newChainedSet(this)this.extend(['eh'])this.extendWith(['canada'],true)}addName(name){this.list.add(name)returnthis}igloo(igloo){this.set('igloo',igloo)returnthis}toConfig(){returnObject.assign(this.entries(),{list:this.list.values().map(name=>name),})}// since we have additional data that is not simple key value// we do additional (albeit easy) steps to rehydratefrom(obj){super.from(obj)Object.keys(obj).forEach(key=>{constval=obj[key]switch(key){case'list':returnval.filter(name=>name).forEach(name=>this.addName(name))}})returnthis}// same with `from`// we do additional simple steps to merge in listsmerge(obj){Object.keys(obj).filter(key=>obj[key]).forEach(key=>{constval=obj[key]switch(key){case'list':returnval.filter(name=>name).forEach(v=>this.addName(v))}})// built-in merging// can use `.mergeReal` to merge only `real` values// and `.merge` to merge anysuper.merge(obj)returnthis}}constchain=Advanced.init().igloo('brr').canada().eh('eh!').addName('thing one').addName('thing two')// true, `eh!`chain.has('igloo')chain.get('eh')constresult=chain.toConfig()consthydrated=Advanced.init().from(result).toConfig()constmerged=Advanced.init().merge(hydrated).merge({igloo:'whaaaat'})// can use toConfig,// and safely continue editing `merged`// with a snapshot of the object data saved as `mergedResult`constmergedResult=merged.toConfig()// hydrated === result === {//   igloo: 'brr',//   canada: 'canada',//   eh: 'eh!',//   list: [ 'thing one', 'thing two' ]// }// merged === {//   igloo: 'whaaaat',//   canada: 'canada',//   eh: 'eh!',//   list: [ 'thing one', 'thing two' ]// }

🌊 types

🌐 api

  • every chain has.className for easy debugging
  • every chain has this.parent
  • and this.parent is hidden on inspection by🕵🗜 inspector-gadget for easier debugging

ChainedSet

  • Set
  • prepend => this
  • clear => this
  • delete => this
  • values => array of entries
  • has => boolean
  • merge => merge an object into the chain
  • when => conditional instance callback

ChainedMap

extendAlias

  • (methodsToAlias: Array<string>, methodToAlias: string, [thisArg])
  • alias a list of methods
  • @returnsthis

from

  • (obj: Object)
  • checks each property of the object
  • calls the chains accordingly
  • rehydrates a chain from an object

other

  • decorateParent (usingchildparent)
  • clear() => this // clearsAll
  • delete(key) => this
  • entries => {keysAndValues}
  • values => Object.values
  • get(key) => entry
  • has(key) => boolean
  • set(key, val) => this
if key is an array, merge in the value,
usually should use ChainedSet for this
  • concat(key, val) => this
  • append(key, val) => this
merging
  • mergeReal(obj) => this // only merges non-undefined values
  • merge(obj) => this
  • clean => this
  • when => conditional instance callback

🔗 links & more

chainMapTill

lets you chain until the required keys are set via chains, or if they are passed in, then it auto returnsparent

chainedMapExtendable

  • has chains with.extends able to usedefault values when calling it
  • also can addprefixes (defaultno) so if you usecache defaulttrue, it can addnoCache which does the inverse
  • set up for being chains of chains when you add a few decorating chains dynamically

📝🌊 TODO

// using `izz` to validate types when settingthis.extendType(['str'],'string')

[8]ページ先頭

©2009-2025 Movatter.jp