Skip to content

Instantly share code, notes, and snippets.

@Kynako
Created September 23, 2021 03:44
Show Gist options
  • Save Kynako/3b7a8b2ddc49a91f2fa30790a22bd322 to your computer and use it in GitHub Desktop.
Save Kynako/3b7a8b2ddc49a91f2fa30790a22bd322 to your computer and use it in GitHub Desktop.
Generate classes that can use method chaining from built-in classes.
/*
# Usage
const chainable = importModule('chainable')
// generate a class that can use method chaining.
const ChainableAlert = chainable('Alert')
// construct instance
const alert = new ChainableAlert()
.setTitle('Title')
.setMessage('Message')
.addAction('Action1')
.addAction('Action2')
.addCancelAction('CancelAction1')
.addDestructiveAction('DestructiveAction1')
await alert.present()
*/
const INFO = {
'Alert': {
value: Alert,
voidReturnerNames: [
'addAction',
'addCancelAction',
'addDestructiveAction'
],
writablePropNames: [
'title',
'message'
]
},
'Request': {
value: Request,
voidReturnerNames: [
'addFileToMultipart',
'addFileDataToMultipart',
'addImageToMultipart',
'addParameterToMultipart'
],
writablePropNames: [
'url',
'method',
'headers',
'body',
'timeoutInterval',
'onRedirect',
'allowInsecureRequest'
]
}
}
/*
* - lowerCamelCase -> UpperCamelCase
* - set `setProp(prop)` functon
* - make functions that return void return self
*/
function lowerCamelToUpperCamel(string){
const firstChar = string.slice(0, 1),
restChar = string.slice(-(string.length - 1));
return [ firstChar.toUpperCase(), restChar ].join('');
};
/*
* set setProp(prop)
*/
function setSetPropMethod(propName, Child, Parent){
const methodName = 'set' + lowerCamelToUpperCamel(propName);
Child.prototype[methodName] = function (arg) {
this[propName] = arg;
return this;
};
}
/*
* set selfReturnMethod
*/
function setSelfReturnMethod(methodName, Child, Parent){
Child.prototype[methodName] = function (...args){
Parent.prototype[methodName].call(this, ...args);
return this;
};
};
/*
* main
*/
function generateChainableClass(className) {
const targetClassInfo = INFO[className]
const {
value: BaseClass,
voidReturnerNames,
writablePropNames
} = targetClassInfo
// Inherits from BaseClass
const ChainableClass = class extends BaseClass {
constructor(...args) {
super(...args);
};
static name = 'Chainable' + className;
};
// list of methods that return void
// -> let these methods return this
voidReturnerNames.forEach(methodName => {
setSelfReturnMethod(
methodName,
ChainableClass,
BaseClass
);
});
// list of properties that is writable
// -> `setTheProperty(theProperty)
writablePropNames.forEach(propName => {
setSetPropMethod(
propName,
ChainableClass,
BaseClass
);
});
return ChainableClass;
}
module.exports = generateChainableClass;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment