Repository files navigation

Null-Object

A tiny runtime type-safe polymorphic noop object that substitutes for your a real implementation without side effects.

See Null Object pattern 1.

Package Status

CodecovQuality GateTechnical DebtCode SmellsSecurity Rating

min+gzip

npm bundle sizenpm bundle sizenpm downloadsLicense: MIT

Contents

Basic Usage

Install the package.

npm install @wherejuly/null-object

Null-Object:

import{nullObject}from'@wherejuly/null-object';constlogger=config.log ? realLogger : nullObject<Logger>();logger.info('User signed in');// Always safe to call any method or access property on a null-object

A bundled noop function just for convenience:

import{noop}from'@wherejuly/null-object';noop();// returns `undefined`noop(1,'a',{b: 'c'});// as well silently acccepts any arguments

Summary

It is often useful to silently replace an optional dependency, service, or plugin that is not available in some environment (e.g. stub metrics service in development and stage environments).

It is also convenient to use in test to replace dependency objects you do not want to mock but still have to provide into the SUT. Especially, the objects that have the methods to be called by the SUT.

The package provides a safe fallback for any expected object interface by returning a no-op implementation object. It enables cleaner and more robust code due to no null checks or conditional logic.

Any methods called on it are noop, including chained ones. Methods silently accept arbitrary arguments. Access any properties, including nested, silently assign to properties.

Common use cases include:

  • Optional services like logging, analytics, metrics:

    constmetrics=prod ? nullObject<Metrics>() : devMetrics;
  • Provide a noop plugin when none is installed:

    constplugin=userProvidedPlugin??nullObject<Plugin>();
  • Avoid conditional logic in consumers via default parameter:

    functioncreateHandler(callbacks: Callbacks=nullObject<Callbacks>()){callbacks.onReady();// Always callable}
  • Middleware chains:

    constmiddleware=[authMiddleware,config.enableAudit ? auditMiddleware : nullObject<Middleware>()];

Usage

The signature:

functionnullObject<T=Record<string,any>>(name?: string): T;

Call any method, chained if needed, with arbitrary arguments, access any property, including nested and do nothing. Optionally provide null-object with the actual object type to ensure type safety.

typeTSomeActualHandler={method: any;prop: any};// May come as third-party typeconstsilent=nullObject<TSomeActualHandler>();// Could also use it untyped: `const silent = nullObject()`silent.method().another('arbitrary','args',123,true);silent.prop.method('arbitrary','args',123,true).more;

Help debugging with .toString() and optional named identity.

constlogger=config.log ? realLogger : nullObject<Logger>();constname=logger.toString();// name === [NullObject]// orconstlogger=config.log ? realLogger : nullObject<Logger>('Logger');constname=logger.toString();// name === [NullObject: Logger]

Can silently accept assignments to any property including nested.

constplugin=userProvidedPlugin??nullObject<Plugin>();plugin.settings.some=true;

The Convenience noop Function

The package also provides the noop function so that you do not have to import another package for it.

noop();// returns `undefined`noop(1,'a',true,null);// Accepts arbitrary arguments without throwingfunctiononEvent(callback: ()=>void=noop){callback();// Safe to call without checking}

Maintenance

The package is written in TypeScript with the informative JSDoc blocks available on hover for public interface (e.g. in VS Code) for comfortable programmatic usage. The code is carefully crafted with TDD allowing simple extension. The project is production-ready and actively maintained.

Contributions

Filling issues, questions in Discussions are all welcome.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Footnotes

  1. Kerievsky J., Refactoring to Patterns (2004), p. 343; Fowler M., Refactoring (2018), p. 289 under "Introduce Special Case" title.

About

The tiny polymorphic noop-behavior object to stub actual objects conditionally.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Null-Object

A tiny runtime type-safe polymorphic noop object that substitutes for your a real implementation without side effects.

See Null Object pattern 1.

Package Status

CodecovQuality GateTechnical DebtCode SmellsSecurity Rating

min+gzip

npm bundle sizenpm bundle sizenpm downloadsLicense: MIT

Contents

Basic Usage

Install the package.

npm install @wherejuly/null-object

Null-Object:

import{nullObject}from'@wherejuly/null-object';constlogger=config.log ? realLogger : nullObject<Logger>();logger.info('User signed in');// Always safe to call any method or access property on a null-object

A bundled noop function just for convenience:

import{noop}from'@wherejuly/null-object';noop();// returns `undefined`noop(1,'a',{b: 'c'});// as well silently acccepts any arguments

Summary

It is often useful to silently replace an optional dependency, service, or plugin that is not available in some environment (e.g. stub metrics service in development and stage environments).

It is also convenient to use in test to replace dependency objects you do not want to mock but still have to provide into the SUT. Especially, the objects that have the methods to be called by the SUT.

The package provides a safe fallback for any expected object interface by returning a no-op implementation object. It enables cleaner and more robust code due to no null checks or conditional logic.

Any methods called on it are noop, including chained ones. Methods silently accept arbitrary arguments. Access any properties, including nested, silently assign to properties.

Common use cases include:

  • Optional services like logging, analytics, metrics:

    constmetrics=prod ? nullObject<Metrics>() : devMetrics;
  • Provide a noop plugin when none is installed:

    constplugin=userProvidedPlugin??nullObject<Plugin>();
  • Avoid conditional logic in consumers via default parameter:

    functioncreateHandler(callbacks: Callbacks=nullObject<Callbacks>()){callbacks.onReady();// Always callable}
  • Middleware chains:

    constmiddleware=[authMiddleware,config.enableAudit ? auditMiddleware : nullObject<Middleware>()];

Usage

The signature:

functionnullObject<T=Record<string,any>>(name?: string): T;

Call any method, chained if needed, with arbitrary arguments, access any property, including nested and do nothing. Optionally provide null-object with the actual object type to ensure type safety.

typeTSomeActualHandler={method: any;prop: any};// May come as third-party typeconstsilent=nullObject<TSomeActualHandler>();// Could also use it untyped: `const silent = nullObject()`silent.method().another('arbitrary','args',123,true);silent.prop.method('arbitrary','args',123,true).more;

Help debugging with .toString() and optional named identity.

constlogger=config.log ? realLogger : nullObject<Logger>();constname=logger.toString();// name === [NullObject]// orconstlogger=config.log ? realLogger : nullObject<Logger>('Logger');constname=logger.toString();// name === [NullObject: Logger]

Can silently accept assignments to any property including nested.

constplugin=userProvidedPlugin??nullObject<Plugin>();plugin.settings.some=true;

The Convenience noop Function

The package also provides the noop function so that you do not have to import another package for it.

noop();// returns `undefined`noop(1,'a',true,null);// Accepts arbitrary arguments without throwingfunctiononEvent(callback: ()=>void=noop){callback();// Safe to call without checking}

Maintenance

The package is written in TypeScript with the informative JSDoc blocks available on hover for public interface (e.g. in VS Code) for comfortable programmatic usage. The code is carefully crafted with TDD allowing simple extension. The project is production-ready and actively maintained.

Contributions

Filling issues, questions in Discussions are all welcome.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Footnotes

  1. Kerievsky J., Refactoring to Patterns (2004), p. 343; Fowler M., Refactoring (2018), p. 289 under "Introduce Special Case" title.

About

The tiny polymorphic noop-behavior object to stub actual objects conditionally.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Null-Object

A tiny runtime type-safe polymorphic noop object that substitutes for your a real implementation without side effects.

See Null Object pattern 1.

Package Status

CodecovQuality GateTechnical DebtCode SmellsSecurity Rating

min+gzip

npm bundle sizenpm bundle sizenpm downloadsLicense: MIT

Contents

Basic Usage

Install the package.

npm install @wherejuly/null-object

Null-Object:

import{nullObject}from'@wherejuly/null-object';constlogger=config.log ? realLogger : nullObject<Logger>();logger.info('User signed in');// Always safe to call any method or access property on a null-object

A bundled noop function just for convenience:

import{noop}from'@wherejuly/null-object';noop();// returns `undefined`noop(1,'a',{b: 'c'});// as well silently acccepts any arguments

Summary

It is often useful to silently replace an optional dependency, service, or plugin that is not available in some environment (e.g. stub metrics service in development and stage environments).

It is also convenient to use in test to replace dependency objects you do not want to mock but still have to provide into the SUT. Especially, the objects that have the methods to be called by the SUT.

The package provides a safe fallback for any expected object interface by returning a no-op implementation object. It enables cleaner and more robust code due to no null checks or conditional logic.

Any methods called on it are noop, including chained ones. Methods silently accept arbitrary arguments. Access any properties, including nested, silently assign to properties.

Common use cases include:

  • Optional services like logging, analytics, metrics:

    constmetrics=prod ? nullObject<Metrics>() : devMetrics;
  • Provide a noop plugin when none is installed:

    constplugin=userProvidedPlugin??nullObject<Plugin>();
  • Avoid conditional logic in consumers via default parameter:

    functioncreateHandler(callbacks: Callbacks=nullObject<Callbacks>()){callbacks.onReady();// Always callable}
  • Middleware chains:

    constmiddleware=[authMiddleware,config.enableAudit ? auditMiddleware : nullObject<Middleware>()];

Usage

The signature:

functionnullObject<T=Record<string,any>>(name?: string): T;

Call any method, chained if needed, with arbitrary arguments, access any property, including nested and do nothing. Optionally provide null-object with the actual object type to ensure type safety.

typeTSomeActualHandler={method: any;prop: any};// May come as third-party typeconstsilent=nullObject<TSomeActualHandler>();// Could also use it untyped: `const silent = nullObject()`silent.method().another('arbitrary','args',123,true);silent.prop.method('arbitrary','args',123,true).more;

Help debugging with .toString() and optional named identity.

constlogger=config.log ? realLogger : nullObject<Logger>();constname=logger.toString();// name === [NullObject]// orconstlogger=config.log ? realLogger : nullObject<Logger>('Logger');constname=logger.toString();// name === [NullObject: Logger]

Can silently accept assignments to any property including nested.

constplugin=userProvidedPlugin??nullObject<Plugin>();plugin.settings.some=true;

The Convenience noop Function

The package also provides the noop function so that you do not have to import another package for it.

noop();// returns `undefined`noop(1,'a',true,null);// Accepts arbitrary arguments without throwingfunctiononEvent(callback: ()=>void=noop){callback();// Safe to call without checking}

Maintenance

The package is written in TypeScript with the informative JSDoc blocks available on hover for public interface (e.g. in VS Code) for comfortable programmatic usage. The code is carefully crafted with TDD allowing simple extension. The project is production-ready and actively maintained.

Contributions

Filling issues, questions in Discussions are all welcome.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Footnotes

  1. Kerievsky J., Refactoring to Patterns (2004), p. 343; Fowler M., Refactoring (2018), p. 289 under "Introduce Special Case" title.

About

The tiny polymorphic noop-behavior object to stub actual objects conditionally.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Null-Object

A tiny runtime type-safe polymorphic noop object that substitutes for your a real implementation without side effects.

See Null Object pattern 1.

Package Status

CodecovQuality GateTechnical DebtCode SmellsSecurity Rating

min+gzip

npm bundle sizenpm bundle sizenpm downloadsLicense: MIT

Contents

Basic Usage

Install the package.

npm install @wherejuly/null-object

Null-Object:

import{nullObject}from'@wherejuly/null-object';constlogger=config.log ? realLogger : nullObject<Logger>();logger.info('User signed in');// Always safe to call any method or access property on a null-object

A bundled noop function just for convenience:

import{noop}from'@wherejuly/null-object';noop();// returns `undefined`noop(1,'a',{b: 'c'});// as well silently acccepts any arguments

Summary

It is often useful to silently replace an optional dependency, service, or plugin that is not available in some environment (e.g. stub metrics service in development and stage environments).

It is also convenient to use in test to replace dependency objects you do not want to mock but still have to provide into the SUT. Especially, the objects that have the methods to be called by the SUT.

The package provides a safe fallback for any expected object interface by returning a no-op implementation object. It enables cleaner and more robust code due to no null checks or conditional logic.

Any methods called on it are noop, including chained ones. Methods silently accept arbitrary arguments. Access any properties, including nested, silently assign to properties.

Common use cases include:

  • Optional services like logging, analytics, metrics:

    constmetrics=prod ? nullObject<Metrics>() : devMetrics;
  • Provide a noop plugin when none is installed:

    constplugin=userProvidedPlugin??nullObject<Plugin>();
  • Avoid conditional logic in consumers via default parameter:

    functioncreateHandler(callbacks: Callbacks=nullObject<Callbacks>()){callbacks.onReady();// Always callable}
  • Middleware chains:

    constmiddleware=[authMiddleware,config.enableAudit ? auditMiddleware : nullObject<Middleware>()];

Usage

The signature:

functionnullObject<T=Record<string,any>>(name?: string): T;

Call any method, chained if needed, with arbitrary arguments, access any property, including nested and do nothing. Optionally provide null-object with the actual object type to ensure type safety.

typeTSomeActualHandler={method: any;prop: any};// May come as third-party typeconstsilent=nullObject<TSomeActualHandler>();// Could also use it untyped: `const silent = nullObject()`silent.method().another('arbitrary','args',123,true);silent.prop.method('arbitrary','args',123,true).more;

Help debugging with .toString() and optional named identity.

constlogger=config.log ? realLogger : nullObject<Logger>();constname=logger.toString();// name === [NullObject]// orconstlogger=config.log ? realLogger : nullObject<Logger>('Logger');constname=logger.toString();// name === [NullObject: Logger]

Can silently accept assignments to any property including nested.

constplugin=userProvidedPlugin??nullObject<Plugin>();plugin.settings.some=true;

The Convenience noop Function

The package also provides the noop function so that you do not have to import another package for it.

noop();// returns `undefined`noop(1,'a',true,null);// Accepts arbitrary arguments without throwingfunctiononEvent(callback: ()=>void=noop){callback();// Safe to call without checking}

Maintenance

The package is written in TypeScript with the informative JSDoc blocks available on hover for public interface (e.g. in VS Code) for comfortable programmatic usage. The code is carefully crafted with TDD allowing simple extension. The project is production-ready and actively maintained.

Contributions

Filling issues, questions in Discussions are all welcome.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Footnotes

  1. Kerievsky J., Refactoring to Patterns (2004), p. 343; Fowler M., Refactoring (2018), p. 289 under "Introduce Special Case" title.

About

The tiny polymorphic noop-behavior object to stub actual objects conditionally.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Null-Object

A tiny runtime type-safe polymorphic noop object that substitutes for your a real implementation without side effects.

See Null Object pattern 1.

Package Status

CodecovQuality GateTechnical DebtCode SmellsSecurity Rating

min+gzip

npm bundle sizenpm bundle sizenpm downloadsLicense: MIT

Contents

Basic Usage

Install the package.

npm install @wherejuly/null-object

Null-Object:

import{nullObject}from'@wherejuly/null-object';constlogger=config.log ? realLogger : nullObject<Logger>();logger.info('User signed in');// Always safe to call any method or access property on a null-object

A bundled noop function just for convenience:

import{noop}from'@wherejuly/null-object';noop();// returns `undefined`noop(1,'a',{b: 'c'});// as well silently acccepts any arguments

Summary

It is often useful to silently replace an optional dependency, service, or plugin that is not available in some environment (e.g. stub metrics service in development and stage environments).

It is also convenient to use in test to replace dependency objects you do not want to mock but still have to provide into the SUT. Especially, the objects that have the methods to be called by the SUT.

The package provides a safe fallback for any expected object interface by returning a no-op implementation object. It enables cleaner and more robust code due to no null checks or conditional logic.

Any methods called on it are noop, including chained ones. Methods silently accept arbitrary arguments. Access any properties, including nested, silently assign to properties.

Common use cases include:

  • Optional services like logging, analytics, metrics:

    constmetrics=prod ? nullObject<Metrics>() : devMetrics;
  • Provide a noop plugin when none is installed:

    constplugin=userProvidedPlugin??nullObject<Plugin>();
  • Avoid conditional logic in consumers via default parameter:

    functioncreateHandler(callbacks: Callbacks=nullObject<Callbacks>()){callbacks.onReady();// Always callable}
  • Middleware chains:

    constmiddleware=[authMiddleware,config.enableAudit ? auditMiddleware : nullObject<Middleware>()];

Usage

The signature:

functionnullObject<T=Record<string,any>>(name?: string): T;

Call any method, chained if needed, with arbitrary arguments, access any property, including nested and do nothing. Optionally provide null-object with the actual object type to ensure type safety.

typeTSomeActualHandler={method: any;prop: any};// May come as third-party typeconstsilent=nullObject<TSomeActualHandler>();// Could also use it untyped: `const silent = nullObject()`silent.method().another('arbitrary','args',123,true);silent.prop.method('arbitrary','args',123,true).more;

Help debugging with .toString() and optional named identity.

constlogger=config.log ? realLogger : nullObject<Logger>();constname=logger.toString();// name === [NullObject]// orconstlogger=config.log ? realLogger : nullObject<Logger>('Logger');constname=logger.toString();// name === [NullObject: Logger]

Can silently accept assignments to any property including nested.

constplugin=userProvidedPlugin??nullObject<Plugin>();plugin.settings.some=true;

The Convenience noop Function

The package also provides the noop function so that you do not have to import another package for it.

noop();// returns `undefined`noop(1,'a',true,null);// Accepts arbitrary arguments without throwingfunctiononEvent(callback: ()=>void=noop){callback();// Safe to call without checking}

Maintenance

The package is written in TypeScript with the informative JSDoc blocks available on hover for public interface (e.g. in VS Code) for comfortable programmatic usage. The code is carefully crafted with TDD allowing simple extension. The project is production-ready and actively maintained.

Contributions

Filling issues, questions in Discussions are all welcome.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Footnotes

  1. Kerievsky J., Refactoring to Patterns (2004), p. 343; Fowler M., Refactoring (2018), p. 289 under "Introduce Special Case" title.

About

The tiny polymorphic noop-behavior object to stub actual objects conditionally.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Null-Object

A tiny runtime type-safe polymorphic noop object that substitutes for your a real implementation without side effects.

See Null Object pattern 1.

Package Status

CodecovQuality GateTechnical DebtCode SmellsSecurity Rating

min+gzip

npm bundle sizenpm bundle sizenpm downloadsLicense: MIT

Contents

Basic Usage

Install the package.

npm install @wherejuly/null-object

Null-Object:

import{nullObject}from'@wherejuly/null-object';constlogger=config.log ? realLogger : nullObject<Logger>();logger.info('User signed in');// Always safe to call any method or access property on a null-object

A bundled noop function just for convenience:

import{noop}from'@wherejuly/null-object';noop();// returns `undefined`noop(1,'a',{b: 'c'});// as well silently acccepts any arguments

Summary

It is often useful to silently replace an optional dependency, service, or plugin that is not available in some environment (e.g. stub metrics service in development and stage environments).

It is also convenient to use in test to replace dependency objects you do not want to mock but still have to provide into the SUT. Especially, the objects that have the methods to be called by the SUT.

The package provides a safe fallback for any expected object interface by returning a no-op implementation object. It enables cleaner and more robust code due to no null checks or conditional logic.

Any methods called on it are noop, including chained ones. Methods silently accept arbitrary arguments. Access any properties, including nested, silently assign to properties.

Common use cases include:

  • Optional services like logging, analytics, metrics:

    constmetrics=prod ? nullObject<Metrics>() : devMetrics;
  • Provide a noop plugin when none is installed:

    constplugin=userProvidedPlugin??nullObject<Plugin>();
  • Avoid conditional logic in consumers via default parameter:

    functioncreateHandler(callbacks: Callbacks=nullObject<Callbacks>()){callbacks.onReady();// Always callable}
  • Middleware chains:

    constmiddleware=[authMiddleware,config.enableAudit ? auditMiddleware : nullObject<Middleware>()];

Usage

The signature:

functionnullObject<T=Record<string,any>>(name?: string): T;

Call any method, chained if needed, with arbitrary arguments, access any property, including nested and do nothing. Optionally provide null-object with the actual object type to ensure type safety.

typeTSomeActualHandler={method: any;prop: any};// May come as third-party typeconstsilent=nullObject<TSomeActualHandler>();// Could also use it untyped: `const silent = nullObject()`silent.method().another('arbitrary','args',123,true);silent.prop.method('arbitrary','args',123,true).more;

Help debugging with .toString() and optional named identity.

constlogger=config.log ? realLogger : nullObject<Logger>();constname=logger.toString();// name === [NullObject]// orconstlogger=config.log ? realLogger : nullObject<Logger>('Logger');constname=logger.toString();// name === [NullObject: Logger]

Can silently accept assignments to any property including nested.

constplugin=userProvidedPlugin??nullObject<Plugin>();plugin.settings.some=true;

The Convenience noop Function

The package also provides the noop function so that you do not have to import another package for it.

noop();// returns `undefined`noop(1,'a',true,null);// Accepts arbitrary arguments without throwingfunctiononEvent(callback: ()=>void=noop){callback();// Safe to call without checking}

Maintenance

The package is written in TypeScript with the informative JSDoc blocks available on hover for public interface (e.g. in VS Code) for comfortable programmatic usage. The code is carefully crafted with TDD allowing simple extension. The project is production-ready and actively maintained.

Contributions

Filling issues, questions in Discussions are all welcome.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Footnotes

  1. Kerievsky J., Refactoring to Patterns (2004), p. 343; Fowler M., Refactoring (2018), p. 289 under "Introduce Special Case" title.

About

The tiny polymorphic noop-behavior object to stub actual objects conditionally.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Null-Object

A tiny runtime type-safe polymorphic noop object that substitutes for your a real implementation without side effects.

See Null Object pattern 1.

Package Status

CodecovQuality GateTechnical DebtCode SmellsSecurity Rating

min+gzip

npm bundle sizenpm bundle sizenpm downloadsLicense: MIT

Contents

Basic Usage

Install the package.

npm install @wherejuly/null-object

Null-Object:

import{nullObject}from'@wherejuly/null-object';constlogger=config.log ? realLogger : nullObject<Logger>();logger.info('User signed in');// Always safe to call any method or access property on a null-object

A bundled noop function just for convenience:

import{noop}from'@wherejuly/null-object';noop();// returns `undefined`noop(1,'a',{b: 'c'});// as well silently acccepts any arguments

Summary

It is often useful to silently replace an optional dependency, service, or plugin that is not available in some environment (e.g. stub metrics service in development and stage environments).

It is also convenient to use in test to replace dependency objects you do not want to mock but still have to provide into the SUT. Especially, the objects that have the methods to be called by the SUT.

The package provides a safe fallback for any expected object interface by returning a no-op implementation object. It enables cleaner and more robust code due to no null checks or conditional logic.

Any methods called on it are noop, including chained ones. Methods silently accept arbitrary arguments. Access any properties, including nested, silently assign to properties.

Common use cases include:

  • Optional services like logging, analytics, metrics:

    constmetrics=prod ? nullObject<Metrics>() : devMetrics;
  • Provide a noop plugin when none is installed:

    constplugin=userProvidedPlugin??nullObject<Plugin>();
  • Avoid conditional logic in consumers via default parameter:

    functioncreateHandler(callbacks: Callbacks=nullObject<Callbacks>()){callbacks.onReady();// Always callable}
  • Middleware chains:

    constmiddleware=[authMiddleware,config.enableAudit ? auditMiddleware : nullObject<Middleware>()];

Usage

The signature:

functionnullObject<T=Record<string,any>>(name?: string): T;

Call any method, chained if needed, with arbitrary arguments, access any property, including nested and do nothing. Optionally provide null-object with the actual object type to ensure type safety.

typeTSomeActualHandler={method: any;prop: any};// May come as third-party typeconstsilent=nullObject<TSomeActualHandler>();// Could also use it untyped: `const silent = nullObject()`silent.method().another('arbitrary','args',123,true);silent.prop.method('arbitrary','args',123,true).more;

Help debugging with .toString() and optional named identity.

constlogger=config.log ? realLogger : nullObject<Logger>();constname=logger.toString();// name === [NullObject]// orconstlogger=config.log ? realLogger : nullObject<Logger>('Logger');constname=logger.toString();// name === [NullObject: Logger]

Can silently accept assignments to any property including nested.

constplugin=userProvidedPlugin??nullObject<Plugin>();plugin.settings.some=true;

The Convenience noop Function

The package also provides the noop function so that you do not have to import another package for it.

noop();// returns `undefined`noop(1,'a',true,null);// Accepts arbitrary arguments without throwingfunctiononEvent(callback: ()=>void=noop){callback();// Safe to call without checking}

Maintenance

The package is written in TypeScript with the informative JSDoc blocks available on hover for public interface (e.g. in VS Code) for comfortable programmatic usage. The code is carefully crafted with TDD allowing simple extension. The project is production-ready and actively maintained.

Contributions

Filling issues, questions in Discussions are all welcome.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Footnotes

  1. Kerievsky J., Refactoring to Patterns (2004), p. 343; Fowler M., Refactoring (2018), p. 289 under "Introduce Special Case" title.

About

The tiny polymorphic noop-behavior object to stub actual objects conditionally.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Null-Object

A tiny runtime type-safe polymorphic noop object that substitutes for your a real implementation without side effects.

See Null Object pattern 1.

Package Status

CodecovQuality GateTechnical DebtCode SmellsSecurity Rating

min+gzip

npm bundle sizenpm bundle sizenpm downloadsLicense: MIT

Contents

Basic Usage

Install the package.

npm install @wherejuly/null-object

Null-Object:

import{nullObject}from'@wherejuly/null-object';constlogger=config.log ? realLogger : nullObject<Logger>();logger.info('User signed in');// Always safe to call any method or access property on a null-object

A bundled noop function just for convenience:

import{noop}from'@wherejuly/null-object';noop();// returns `undefined`noop(1,'a',{b: 'c'});// as well silently acccepts any arguments

Summary

It is often useful to silently replace an optional dependency, service, or plugin that is not available in some environment (e.g. stub metrics service in development and stage environments).

It is also convenient to use in test to replace dependency objects you do not want to mock but still have to provide into the SUT. Especially, the objects that have the methods to be called by the SUT.

The package provides a safe fallback for any expected object interface by returning a no-op implementation object. It enables cleaner and more robust code due to no null checks or conditional logic.

Any methods called on it are noop, including chained ones. Methods silently accept arbitrary arguments. Access any properties, including nested, silently assign to properties.

Common use cases include:

  • Optional services like logging, analytics, metrics:

    constmetrics=prod ? nullObject<Metrics>() : devMetrics;
  • Provide a noop plugin when none is installed:

    constplugin=userProvidedPlugin??nullObject<Plugin>();
  • Avoid conditional logic in consumers via default parameter:

    functioncreateHandler(callbacks: Callbacks=nullObject<Callbacks>()){callbacks.onReady();// Always callable}
  • Middleware chains:

    constmiddleware=[authMiddleware,config.enableAudit ? auditMiddleware : nullObject<Middleware>()];

Usage

The signature:

functionnullObject<T=Record<string,any>>(name?: string): T;

Call any method, chained if needed, with arbitrary arguments, access any property, including nested and do nothing. Optionally provide null-object with the actual object type to ensure type safety.

typeTSomeActualHandler={method: any;prop: any};// May come as third-party typeconstsilent=nullObject<TSomeActualHandler>();// Could also use it untyped: `const silent = nullObject()`silent.method().another('arbitrary','args',123,true);silent.prop.method('arbitrary','args',123,true).more;

Help debugging with .toString() and optional named identity.

constlogger=config.log ? realLogger : nullObject<Logger>();constname=logger.toString();// name === [NullObject]// orconstlogger=config.log ? realLogger : nullObject<Logger>('Logger');constname=logger.toString();// name === [NullObject: Logger]

Can silently accept assignments to any property including nested.

constplugin=userProvidedPlugin??nullObject<Plugin>();plugin.settings.some=true;

The Convenience noop Function

The package also provides the noop function so that you do not have to import another package for it.

noop();// returns `undefined`noop(1,'a',true,null);// Accepts arbitrary arguments without throwingfunctiononEvent(callback: ()=>void=noop){callback();// Safe to call without checking}

Maintenance

The package is written in TypeScript with the informative JSDoc blocks available on hover for public interface (e.g. in VS Code) for comfortable programmatic usage. The code is carefully crafted with TDD allowing simple extension. The project is production-ready and actively maintained.

Contributions

Filling issues, questions in Discussions are all welcome.

License

This project is licensed under the MIT License. See the LICENSE file for details.

Footnotes

  1. Kerievsky J., Refactoring to Patterns (2004), p. 343; Fowler M., Refactoring (2018), p. 289 under "Introduce Special Case" title.

About

The tiny polymorphic noop-behavior object to stub actual objects conditionally.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages