{"id":18687643,"url":"https://github.com/junosuarez/cut","last_synced_at":"2025-11-08T02:30:36.549Z","repository":{"id":6663074,"uuid":"7907698","full_name":"junosuarez/cut","owner":"junosuarez","description":"node module: Aspect-oriented (AOP) helper for sync or async code","archived":false,"fork":false,"pushed_at":"2013-01-30T04:27:44.000Z","size":120,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-02-15T16:46:16.766Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/junosuarez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-01-30T04:19:41.000Z","updated_at":"2016-09-10T19:01:25.000Z","dependencies_parsed_at":"2022-07-31T03:38:48.029Z","dependency_job_id":null,"html_url":"https://github.com/junosuarez/cut","commit_stats":null,"previous_names":["agilediagnosis/cut"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junosuarez%2Fcut","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junosuarez%2Fcut/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junosuarez%2Fcut/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/junosuarez%2Fcut/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/junosuarez","download_url":"https://codeload.github.com/junosuarez/cut/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239545771,"owners_count":19656847,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T10:33:40.452Z","updated_at":"2025-11-08T02:30:36.508Z","avatar_url":"https://github.com/junosuarez.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cut\nAspect-oriented (AOP) helper for sync or async code\n\n## installation\n\n    $ npm install cut\n\n## about\n\nWrap a function to extend its behavior before and/or after\nit is called (See http://en.wikipedia.org/wiki/Aspect-oriented_programming)\n\nThis is useful, for example, to add logging, tracking, to modify its output,\nor for other orthogonal concerns to maintain Single Responsibility.\n\n`cut` is named after the term pointcut. Think of this as a way to cut into\na location in your program and modify behavior - in this case, around a\nfunction.\n\nBy building up chains of functionality around a function, you can more easily\nre-use code for validation, policy, logging, etc - and reconfigure it at\nruntime.\n\n## usage\n\n    var cut = require('cut')\n\nlet's start with a basic identify function, which will return\nit's argument:\n\n    var targetFn = function (val) { return val }\n\n    targetFn(true)\n    // =\u003e true\n\n    var fn = cut(targetFn)\n\nnow, we can add functionality before or after the targetFn's callsite\n`cut` returns a function\nwith two additional properties: a `before` array and an `after` array\n\nlet's add some behavior to run before targetFn\n\n    fn.before.push(function(args, next) {\n      console.log('We\\'re calling targetFn with these arguments:', args)\n      next(args)\n    })\n\nnow when we call fn, it will log first before calling targetFn\n\n    fn(true)\n    // We're calling targetFn with these arguments: [true]\n    // =\u003e true\n\nlet's add another piece of advice to modify the arguments:\n\n    var invert = function (args, next) { args[0] = !args[0]; next(args) }\n\nsince before advice is called in array index order, we unshift\nto prepend to the `before` array\n\n    fn.before.unshift(invert)\n\n    fn(true)\n    // We're calling targetFn with these arguments: [false]\n    // =\u003e false\n\nnow let's modify the return value:\n\n    var stringify = function (obj) { return obj.toString() }\n    var shout = function (str) { return str.toUpperCase() }\n\n    fn.after.push(stringify, shout)\n\n    fn(true)\n    // We're calling targetFn with these arguments: [false]\n    // =\u003e \"FALSE\"\n\nfinally, we want to add a guard so `targetFn` is only called\nwith boolean arguments\n\n    fn.before.unshift(function (args, next) {\n      if (typeof args[0] !== 'boolean') return;\n      next(args);\n    })\n\n    fn('true')\n    // undefined\n\nsince `'true'` is a string, the advice never called `next` and the\ncall chain was aborted before calling `targetFn` or any of the\nsubsequent advice\n\n    fn(true)\n    // We're calling targetFn with these arguments: [false]\n    // =\u003e \"FALSE\"\n\n\nAs you can see, `cut` gives you a powerful and easy way to compose, modify,\nand re-use behaviors to modify and control your programs.\n\n\n## api\nthe functions and behaviors use with `cut` are called `advice`.\n\n** before advice **\n\n    function(args, next) : void\n\nEach before advice is called in serial, with each advice passing the original\nor modified arguments to the `next` callback. When all before advice has been\nrun, the target function is invoked with the arguments passed by the last\nadvice.\n\nBefore advice can intercept the target function from being called (for example,\nin advice implementing authorization policy) by simply not calling `next`\n\nNote, `args` is a proper Array, rather than an `arguments` object.\n\nSince `next` is a callback, before advice can be implemented synchronously\nor async.\n\n** after advice **\n\n    function(val, args) : val\n\nIf the target function is called and returns normally, the after advice is\ncalled in serial. `val` is the return value of the previous advice or the\ntarget function, and `args` is an Array of the arguments that the target\nfunction was called with. The return value of the after advice is passed to\nthe next after advice or used as the overall return value, in turn.\n\nIf you wish to use after advice asynchronously, promises must be used as of\nthis version.\n\n** sealed **\n\n    cut(fn).sealed\n\nWhen `cut` is called, the resulting function has its before and after arrays\nexposed. If you want to pass a function somewhere else in your program without\nallowing modification of the advice, `sealed` is a function which applies the\nadvice without exposing those properties.\n\n\n## contributors\n\njden \u003cjason@denizac.org\u003e @leJDen\n\nPlease submit pull requests and issues through github.\n\n## license\n\nMIT\n(c) 2013 Agile Diagnosis, Inc.\nsee LICENSE.md","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjunosuarez%2Fcut","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjunosuarez%2Fcut","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjunosuarez%2Fcut/lists"}