{"_id":"@allnulled/controlled-function","_rev":"2-4043e893afec3d662f5fb4250ec5b0fa","name":"@allnulled/controlled-function","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.1":{"name":"@allnulled/controlled-function","version":"1.0.1","keywords":[],"author":{"name":"allnulled"},"license":"WTFPL","_id":"@allnulled/controlled-function@1.0.1","maintainers":[{"name":"allnulled","email":"todosanulados@gmail.com"}],"dist":{"shasum":"0ad1f7160ee98d5134f57f19b057804cc1b4a60c","tarball":"https://registry.npmjs.org/@allnulled/controlled-function/-/controlled-function-1.0.1.tgz","fileCount":5,"integrity":"sha512-yd4J9QkNyAq7X7TaT7OEa6Gva32XEk3Om39cv4f1MrKtVVXvJvH1w79mmTIcW1XgMeO8FFGigAqKLw0sEOSADg==","signatures":[{"sig":"MEYCIQCnK7rpYLpVUOwth587XWwlF4P4NuWVw6jjhui/X5W32QIhAMTcRFI+AXTR2k7PkZpeLLB1ObrmBnYLVxU+x9BybTbU","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":5065},"main":"controlled-function.js","gitHead":"56c7270b497b9414570abb131d9f6c60c8fa3fb1","scripts":{"test":"npx mocha test.js"},"_npmUser":{"name":"allnulled","email":"todosanulados@gmail.com"},"_npmVersion":"9.6.7","description":"API to return values through 1 outter function scope.","directories":{},"_nodeVersion":"18.17.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/controlled-function_1.0.1_1735381843380_0.3044908632226737","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@allnulled/controlled-function","version":"1.0.2","keywords":[],"author":{"name":"allnulled"},"license":"WTFPL","_id":"@allnulled/controlled-function@1.0.2","maintainers":[{"name":"allnulled","email":"todosanulados@gmail.com"}],"dist":{"shasum":"781bd622242c4a703e77c80ab18c9b3df8b836df","tarball":"https://registry.npmjs.org/@allnulled/controlled-function/-/controlled-function-1.0.2.tgz","fileCount":5,"integrity":"sha512-hg/LULp1bOhsZF3ariv8140P/aqLvB+YR548CYEVGTLpQ+GIGORwsWgLxndiCBMnZH8SpPLh54btrKSoczAYBQ==","signatures":[{"sig":"MEUCIQD4484eDWn4efid56OCV1MTGuOe930oi7KWFi4cg0n6xAIgEokgfAKP8IOyk304dj5wNSM9k5iivdwd2GzQBh9Qk7s=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":15565},"main":"controlled-function.js","gitHead":"f87e1f7d2b590fb025927ecb37464e60a253a08c","scripts":{"test":"npx mocha test.js"},"_npmUser":{"name":"allnulled","email":"todosanulados@gmail.com"},"_npmVersion":"9.6.7","description":"API to return values through 1 outter function scope.","directories":{},"_nodeVersion":"18.17.1","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/controlled-function_1.0.2_1735402582086_0.9888334399130929","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@allnulled/controlled-function","version":"1.0.3","description":"API to return values through 1 outter function scope.","main":"controlled-function.js","scripts":{"test":"npx mocha test.js"},"keywords":[],"author":{"name":"allnulled"},"license":"WTFPL","gitHead":"c0940c54ea7c2fdb1c174541e393795186afce7f","_id":"@allnulled/controlled-function@1.0.3","_nodeVersion":"18.17.1","_npmVersion":"9.6.7","dist":{"integrity":"sha512-pIsMfBY4MLrSmG7uKbzJSXhR9OAiVB5QVefLvMxd+xkjYIPYh08cGO9G+S9tN/Pzdnp5u9YZhPxkd4BS0WXbxA==","shasum":"b2e8e7b1bd004307fa6c5a95e9f6fa32c026f378","tarball":"https://registry.npmjs.org/@allnulled/controlled-function/-/controlled-function-1.0.3.tgz","fileCount":5,"unpackedSize":15713,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCYwJgJbuDMagch3Y6DDOA0pJ0fatn50aBU/QCTXH1/jwIhAO2kZx/dBBt20l7if1uGZhn3wJb3FnB/7ZnFnjF6rQLM"}]},"_npmUser":{"name":"allnulled","email":"todosanulados@gmail.com"},"directories":{},"maintainers":[{"name":"allnulled","email":"todosanulados@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/controlled-function_1.0.3_1735402815070_0.2930292552293494"},"_hasShrinkwrap":false}},"time":{"created":"2024-12-28T10:30:43.251Z","modified":"2024-12-28T16:20:15.438Z","1.0.1":"2024-12-28T10:30:43.595Z","1.0.2":"2024-12-28T16:16:22.277Z","1.0.3":"2024-12-28T16:20:15.242Z"},"author":{"name":"allnulled"},"license":"WTFPL","keywords":[],"description":"API to return values through 1 outter function scope.","maintainers":[{"name":"allnulled","email":"todosanulados@gmail.com"}],"readme":"# controlled-function\n\nAPI to return values through 1 outter function scope.\n\nAllows both:\n\n  - The **trascendent condition/if** pattern\n  - The **stuck loop/while** pattern, easying the **coliving combination** of others like:\n     - The **energetical while** pattern, like a being.\n     - The **timed-out while** pattern, like a shortcircuit.\n     - Probably others.\n\n## Installation\n\n```sh\nnpm i -s @allnulled/controlled-function\n```\n\n## Importation\n\nIn node.js:\n\n```js\nrequire(\"@allnulled/controlled-function\");\n```\n\nIn browser:\n\n```html\n<script src=\"node_modules/@allnulled/controlled-function/controlled-function.js\"></script>\n```\n\n## Why interests?\n\nThe thing is to be able to create **trascendent conditions** and **energetical loops**.\n\n## How?\n\nEl `ReturnControl` permite emitir un (signo de) `return` al controlador desde dentro del pipeo.\n\nEl `MutateControl` permite cambiar el estado del controlador (`ReturnController`) desde dentro del pipeo.\n\nEl `controller.hook(fn)` permite apendizar un middleware que el controlador (`ReturnController`) procesará después de cada step del pipeo.\n\nEl `controller.pipe(outputId, pipeNames)` lo que hace es:\n\n - Si algún step de la tubería returna un `MutateControl`, altera su propio `controller.properties` consecuentemente.\n - Si algún step de la tubería retorna un `ReturnControl`: devuelve `true`.\n    - Establece el valor del `ReturnControl` en la `controller.results[outputId]`. Para recuperarlo, `controller.solved(outputId)`.\n    - Devuelve `true`\n - Si no, devuelve `false`.\n\n### The TRASCENDENT-IF pattern\n\nEsto nos permite patrones como:\n\n\n```js\nconst id = \"output\";\nconst functions = {\n    stepOne() {\n        console.log(\"step 1\");\n    },\n    stepTwo() {\n        console.log(\"step 2\");\n        return new ReturnControl(\"Broken in step 2\");\n    },\n    stepThree() {\n        console.log(\"this is not gonna happen\");\n    }\n};\nconst names = [\"stepOne\", \"stepTwo\", \"stepThree];\ncontrol.reset().load(functions);\n// This sentence gives the functions to emit TRASCENDENT RETURNS in TRASCENDENT CONDITIONS:\nif(control.pipe(id, names)) return control.solved(id);\n```\n\nDe esta forma podemos rápidamente traspasar un `return` de una subllamada a la función que la llama.\n\nPodemos crear **condiciones supertrascendentes** con **retornos trascendentes**. Porque trascienden la función de arriba.\n\n### The STUCK-WHILE pattern\n\n```js\ncontrol.reset();\n// Iniciamos en 100 punto de energía:\ncontrol.prop({ cycles: 100 });\ncontrol.hook(c => {\n    if(c.properties.cycles === 0) {\n        // Implementamos la ley de no-energía:\n        return new ReturnControl(\"No more cycles\");\n    }\n});\ncontrol.load({\n    step1(c) {\n        return new MutateControl(c => {\n            return {\n                // Restamos 1 punto de energía en el step1:\n                cycles: c.properties.cicles - 1\n            };\n        });\n    }\n});\nwhile(!control.pipe(\"output\", [\"step1\"])) {\n    // @Intercycle code.\n}\n```\n\nDe esta forma, podemos crear **bucles energéticos**. Energéticos porque funcionan con energía, si la energía se agota, y tiene una ley implementada (que tienes que implementar, pueden ser energéticos o de otros tipos) para ello, el controlador mismo dejará de retornar `false` porque no ha habido **retornos trascendentes**, y retornará `true`, lo que rompería los bucles o desencadenaría los condicionales\n\n\n\n**NOTA:** Cuidado, en el ejemplo llamamos `control` al `controller` porque es más lógico desde fuera de ámbito.\n\n```js\nconst { ReturnController, ReturnControl, MutateControl } = ControlledFunction;\nconst controlledFunction = function () {\n\n  // Creando instancia:\n  const control = new ReturnController();\n\n  // Inicializando el estado:\n  control.reset();\n  \n  // Inicializando las propiedades:\n  control.prop({\n    cicles: 100\n  });\n  \n  // Inicializando el middleware de energía:\n  control.hook(c => {\n    if(c.properties.cicles === 0) {\n      return new ReturnControl(\"No more cicles\");\n    }\n  });\n  \n  // Inicializando funciones:\n  control.load({\n    step1() {\n      return new MutateControl(c => {\n        return {\n          cicles: c.properties.cicles - 1\n        };\n      });\n    },\n  });\n  \n  // Y luego puedes hacer así para crear artefactos con alcance limitado de vida:\n  let index = 0;\n  Ciclo_de_vida_en_repeticiones: {\n    while(!control.pipe(\"output\", [\"step1\"])) {\n      // @TOINJECT: intercycle code\n      console.log(\"Round: \" + (++index));\n    }\n  }\n\n  console.log(\"Finished cicles\");\n};\nconsole.log(controlledFunction());\n```\n\nWhat is happening here?\n\n1. `new ReturnController`. We create the basic instance of the API.\n2. `reset`. We unnecessarily reset `properties` and `results` of the instance.\n3. `prop`. We overwrite the `control.properties` object with new data.\n4. `hook`. This is a law. We push a function in `control.middlewares` so every time a pipe step is finished, this function is going to be called (unless a previous hook returns a `new ReturnControl` instance). You are also provided with `prehook` to prepend a middleware.\n5. `load`. This is the knowledge. Map of known functions. This way, we ensure *modularity* and *functional flatening*.\n6. `while + !control.pipe`. This expression is key. We say `until no energy` or `while energy`, then `keep steping` + `in loop`. This is the definition of life, more or less. That is why that expression is the key.\n\n\n\n\n## Usage\n\nThis is the test provided in source:\n\n```js\nrequire(__dirname + \"/controlled-function.js\");\n\ndescribe(\"ControlledFunction API Test\", function() {\n  \n  it(\"can work as expected with ReturnControl class\", async function() {\n    const { ReturnController, ReturnControl } = ControlledFunction;\n    const controlledFunction = function () {\n      const control = new ReturnController();\n      // Reseteando y cargando un nuevo conjunto de funciones\n      const knowledge = {\n        step1() {\n          return console.log(\"Happens 2!\");\n        },\n        step2() {\n          return new ReturnControl('step 2 Resolved');\n        },\n        step3() {\n          return console.log(\"No happens!\");\n        },\n        stepA() {\n          return console.log(\"Happens 5!\");\n        },\n        stepB() {\n          return new ReturnControl('step B Resolved');\n        },\n        stepC() {\n          return console.log(\"No happens!\");\n        }\n      };\n      control.reset().load(knowledge);\n      // Pasareleamos por los pipes usando la misma instancia para invocar y para acceder:\n      const output1 = (function() {\n        console.log(\"Happens 1!\");\n        if (control.pipe(\"output\", [\"step1\", \"step2\", \"step3\"])) {\n          return control.solved(\"output\");\n        }\n        console.log(\"No happens!\");\n      })();\n\n      if(output1 === \"step 2 Resolved\") {\n        console.log(\"Happens 3!\");\n      }\n\n      const output2 = (function() {\n        console.log(\"Happens 4!\");\n        if(control.pipe(\"output2\", [\"stepA\", \"stepB\", \"stepC\"])) {\n          return control.solved(\"output2\");\n        }\n        console.log(\"No happens!\");\n      })();\n\n      if(output2 === \"step B Resolved\") {\n        console.log(\"Happens 6!\");\n      }\n    };\n    controlledFunction();\n  });\n  \n  it(\"can work as expected with MutateControl class\", async function() {\n    const { ReturnController, ReturnControl, MutateControl } = ControlledFunction;\n    const controlledFunction = function () {\n      const control = new ReturnController();\n      // Inicializando el estado:\n      control.reset();\n      // Inicializando las propiedades:\n      control.prop({\n        cicles: 100\n      });\n      // Inicializando el middleware de energía:\n      control.hook(c => {\n        if(c.properties.cicles === 0) {\n          return new ReturnControl(\"No more cicles\");\n        }\n      });\n      // Inicializando funciones:\n      control.load({\n        step1() {\n          return new MutateControl(c => {\n            return {\n              cicles: c.properties.cicles - 1\n            };\n          });\n        },\n      });\n      let index = 0;\n      Ciclo_de_vida_en_repeticiones: {\n        while(!control.pipe(\"output\", [\"step1\"])) {\n          // @TOINJECT: intercycle code\n          console.log(\"Round: \" + (++index));\n        }\n      }\n      console.log(\"Finished cicles\");\n    };\n    console.log(controlledFunction());\n  });\n\n});\n```\n\n\n## Conclusion\n\nLet's see in the future. But I found this pattern useful because combining only 2 middlewares, I can get these 2 artifacts, from the basic `ReturnControl` API + the `MutateControl` API. The `MutateControl` API can be powerfull with `controller.hooks`, I think.","readmeFilename":"README.md"}