{"id":22328621,"url":"https://github.com/qrailibs/fishboard","last_synced_at":"2025-03-26T06:26:06.050Z","repository":{"id":202749803,"uuid":"452948724","full_name":"qrailibs/Fishboard","owner":"qrailibs","description":"✨ JS Framework to make your JavaScript code more structured.","archived":false,"fork":false,"pushed_at":"2022-06-03T15:21:36.000Z","size":165,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-01-31T08:16:00.405Z","etag":null,"topics":["framework","javascript","oop"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qrailibs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-01-28T05:20:57.000Z","updated_at":"2023-09-27T19:50:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"68b4dcc4-beeb-4317-a1a0-5634fd5a853c","html_url":"https://github.com/qrailibs/Fishboard","commit_stats":null,"previous_names":["ultralib/fishboard","qrailibs/fishboard"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qrailibs%2FFishboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qrailibs%2FFishboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qrailibs%2FFishboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qrailibs%2FFishboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qrailibs","download_url":"https://codeload.github.com/qrailibs/Fishboard/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245600635,"owners_count":20642334,"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":["framework","javascript","oop"],"created_at":"2024-12-04T03:13:07.246Z","updated_at":"2025-03-26T06:26:06.028Z","avatar_url":"https://github.com/qrailibs.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Fishboard banner](https://github.com/Proxymal/Fishboard/blob/main/other/LOGO_BANNER.png)\n\n# About\n**Fishboard** is framework to make your JavaScript code more structured, object-oriented and easy-to-maintain. \n\n### Core features\n- [Interface](#interface)\n- [Module](#module)\n- [ModuleTests](#moduletests)\n- [Model](#model)\n- [Controller](#controller)\n- [Implementer](#implementer)\n- [Static](#static)\n- [IType](#itype)\n- [Types](#types)\n- [IConverter](#iconverter)\n- [Converters](#converters)\n- [Encapsulated](#encapsulated)\n\n### Additional features\n- [Object reflection](#object-reflection)\n- [Object metadata](#object-metadata)\n- [Array features](#array-features)\n- [String features](#string-features)\n- [Functions with history](#functions-with-history)\n- [Functions with state](#functions-with-state)\n\n### Progress\n- [x] Interface\n- [ ] Module\n- [ ] ModuleTests\n- [ ] Model\n- [ ] Controller\n- [ ] Implementer\n- [x] Static\n- [x] IType\n- [x] Types\n- [ ] IConverter\n- [ ] Converters\n- [x] Object reflection\n- [x] Object metadata\n- [ ] Array features\n- [x] String features\n- [x] Functions with history\n- [x] Functions with state\n- [x] Encapsulated\n\n# Installation\nYou can install framework via node package manager:\n```\nnpm i fishboard -d\n```\n**NOTICE**: framework is uses alot of modern JavaScript, you should use *Webpack + Babel* when you use **Fishboard** in your project.\n\n\n\n# Core features\n**Fishboard** has a bunch of features that it's implements in the JavaScript.\n\n### Interface\nEvery object-oriented programming language has *Interfaces* feature, *Interface* is abstract class with properties and methods,\ninstances of *Interface* cannot be created, but classes can inherit Interfaces and implement logic of it's properties and methods.\n**Fishboard** allows you to create interfaces:\n```js\nimport { Interface } from 'fishboard'\n\n// Interface\nclass ICar extends Interface {\n    get [Interface.$Required] () {\n        return [ 'price' ] \n    } \n}\n\n// Class that implements interface\nclass Audi extends ICar {\n    get price() { return 1_000_000 }\n}\nclass BMW extends ICar {} // Error -\u003e 'price' not implemented\n```\n\n### Module\n**Modules** - is independent collection of functions that can be auto-tested. \nExample of creating module:\n```js\nimport { Module } from 'fishboard'\n\nconst math = new Module({\n  plus: (a, b) =\u003e a + b,\n  minus: (a, b) =\u003e a - b\n})\n\nconsole.log(math.plus(10, 10)) // 20\nconsole.log(math.minus(20, 10)) // 10\n```\n\n### ModuleTests\n*Modules* is also can be tested with **ModuleTests**. \nExample of creating tests for module:\n```js\nimport { Module, ModuleTests } from 'fishboard'\n\nconst math = new Module({\n  plus: (a, b) =\u003e a + b,\n  minus: (a, b) =\u003e a - b\n})\nconst mathTests = new ModuleTests({\n  plus: (test, run) =\u003e {\n    test.IsEquals(run(1, 1), 2) // 1 + 1 = 2?\n  },\n  minus: (test, run) =\u003e {\n    test.IsEquals(run(2, 1), 1) // 2 - 1 = 1?\n  }\n}, module)\n\nconst testResults = mathTests.Test()\nconsole.log(testResults.IsSuccess) // true\n```\n\n### Model\n**Models** - is things that describes some object structure. *Models* also allows to validate if object has described structure.\nExample of creating model and validating:\n```js\nimport { Model, Types } from 'fishboard'\n\nconst UserModel = new Model({\n    id: Types.Number,\n    nickname: Types.String,\n    biography: Types.String\n})\n\nconst userJohn = {\n    id: 1,\n    nickname: 'john_2008',\n    biography: 'typical gamer'\n}\nconst userMike = {\n    id: 2,\n    nickname: 'mikegamer100',\n    biography: 1\n}\nconsole.log(UserModel.IsValid(userJohn)) // true\nconsole.log(UserModel.IsValid(userMike)) // false (biography was not string)\n```\n\nAlso you can generate random model instances(objects):\n```js\nimport { Model, Types } from 'fishboard'\n\nconst UserModel = new Model({\n    id: { Types.Number, Model.$CanBeAuto },\n    nickname: { Types.String, Model.$Required },\n    biography: { Types.String, Model.$Required }\n})\n\nconst randomUser = UserModel.RandomInstance()\nconsole.log(randomUser) // { id: 31874, nickname: 'qL9Nx*^ajD(', biography: 'KD1_d$jd(ac0+' }\n```\n\n### Controller\nIn progress\n\n### Implementer\nImplementer is special feature, allows to implement methods on models\n```js\nimport { Model, Implementer } from 'fishboard'\n\nconst UserModel = new Model({\n    id: { Types.Number, Model.$CanBeAuto },\n    nickname: { Types.String, Model.$Required },\n    biography: { Types.String, Model.$Required }\n})\n\nconst User = new Implementer(\n    UserModel, {\n    create: function (nickname, bio) {\n        // create user instance\n        const user = this.model.Instantiate({\n            id: model.$Auto,\n            nickname: nickname,\n            biography: bio\n        })\n        // validate data\n        if(this.model.IsValidInst(user)) {\n            // create user in database\n        }\n    }\n})\n\nUser.create('john2000', 'im gamer')\n\n```\n\n### Static\n**Static** - is a base class that allows you to make fully-static classes. Example:\n```js\nimport { Static } from 'fishboard'\n\nclass Props extends Static {\n    static get Version() { return '1.0.0' }\n}\n\nconsole.log(Props.Version) // 1.0.0\nnew Props() // Error: Static classes cannot be instantiated\n```\n\n### IType\n**IType** - is interface that used for basic types. You can create own type\nto validate its value. Example:\n\nWhen you inherit `IType` you should implement:\n- method `[IType.$IsValue](value)` (Should return true or false)\n\nExample of creating primitive `char` type:\n```js\nimport { IType } from 'fishboard'\n\n// Char: string with length of 1\nclass CharType extends IType {\n    IsValue(value) {\n        return typeof value == 'string' \u0026\u0026 value.length == 1\n    }\n}\n\nconst Char = new CharType()\nconsole.log(Char.IsValue('a')) // true\nconsole.log(Char.IsValue('bb')) // false\n```\n\nExample of creating `password` type (inherits `String` type):\n```js\nimport { Types } from 'fishboard'\n\n// (password length should be min: 6, max: 12)\nclass PasswordType extends (Types.String.constructor) {\n    IsValue(value) {\n        return super.IsValue(value) \u0026\u0026 value.length \u003e= 6 \u0026\u0026 value.length \u003c= 12\n    }\n}\n\nconst Password = new PasswordType()\nconsole.log(Password.IsValue('abcdfg')) // true\nconsole.log(Password.IsValue('abc')) // false\n```\n\n### Types\n**Types** - is collection of primitive types implementation over *IType* interface.\n\nTypes includes these primitives:\n- `NumberType` (*Number* primitive)\n- `BigNumberType` (*BigInt* primitive)\n- `BooleanType` (*Boolean* primitive)\n- `FunctionType` (*Function* primitive)\n- `ObjectType` (*Object* primitive)\n- `SymbolType` (*Symbol* primitive)\n- `DOMElementType` (*DOMNode* primitive)\n\n### IConverter\n**IConverter** - is *interface* that allows you to implement types converters.\n\nWhen you inherit `IConverter` you should implement:\n- property `Input` (Should return instance of `IType`)\n- property `Output` (Should return instance of `IType`)\n- method `Convert(input)` (Should return value of type `output`)\n\nExample of creating DOM node to string converter:\n```js\nimport { IConverter, Types } from 'fishboard'\n\nclass DomToStringConverter extends IConverter {\n    get Input() { return Types.DOMElement }\n    get Output() { return Types.String }\n    Convert(input) { return input.innerText }\n}\n\nconst someDomNode = document.getElementById('someNode') // Some node in HTML that have text 'Hello world'\nconsole.log(new DomToStringConverter().Convert(someDomNode)) // Hello world\n```\n\n### Converters\nIn progress\n\n\n# Additional features\n**Fishboard** also offers additional features as extensions of existing JavaScript things. All of the additional features\nwill be added to JavaScript when you will import something from `fishboard` or just write:\n```js\nimport 'fishboard'\n```\n\n### Object reflection\n`Object.GetAllProperties` - returns all of the object properties, including ones from prototypes.\n```js\nclass A { get x() { return 1 } }\nclass B extends A {}\nclass C extends B {}\n\nconsole.log(Object.GetAllProperties(new C())) // [ 'x' ]\n```\n\n### Object metadata\n**Fishboard** also allows you to use hidden property **meta** in object, that can be used to store any metadata of object.\nAvailable methods is:\n- `Object.GetMeta()`\n- `Object.SetMeta(value)`\n- `Object.IsHasMeta()`\n```js\nlet myObject = {}\nlet myMeta = { x: 100 }\n\nconsole.log(Object.IsHasMeta(myObject)) // false\nObject.SetMeta(myObject, myMeta)\nconsole.log(Object.GetMeta(myObject)) // { x: 100 }\n```\n\n### Array features\nIn progress\n\n### String features\nTo get things in strings you can use `.GetBefore`, `.GetAfter`, `.getBetween` functions. Example:\n```js\nconst myStr = 'forest,desert.jungle'\n\nconsole.log(myStr.GetBefore(',')) // forest\nconsole.log(myStr.GetAfter('.')) // jungle\nconsole.log(myStr.GetBetween(',', '.')) // desert\n```\n\n### Functions with history\nYou can easily store history of function results by running function with `.RunWithHistory(...args)`. Example: \n```js\nfunction plus(a, b) {\n    return a + b\n}\n\nconsole.log(plus.RunWithHistory(1, 1)) // 2\nconsole.log(plus.RunWithHistory(2, 2)) // 4\n\nconsole.log(plus.GetHistory())\n// [\n//      { time: '12:00:00.00', arguments: [1, 1], result: 2 }\n//      { time: '12:00:00.01', arguments: [2, 2], result: 4 }\n// ]\n```\n\n### Functions with state\nYou can also call function and store state by running function with `.RunWithState(...args)`. Example: \n```js\nfunction someFunc() {\n    // If defined 'i' in state, do a++ (Or set 0 to 'i')\n    this.state.SetValue('i', this.state.GetValue('i') + 1 || 0)\n}\n\nsomeFunc.RunWithState() // i is 0\nsomeFunc.RunWithState() // i is 1\nsomeFunc.RunWithState() // i is 2\n\nconsole.log(someFunc.GetState().GetValues()) // { i: 2 }\n```\nWhen you run function with state, it has access to `this.state` variable, which is instance of `State` class.\n`State` class has these properties and methods:\n- `.SetValue(name, value)` (Sets value in state)\n- `.GetValue(name)` (Gets value in state)\n- `.GetValues()` (Returns all values in state as object\n- `[State.$Data]` (Field with all data of state)\n\n### Encapsulated\n```js\nimport { Encapsulated, Types } from 'fishboard'\n\nconst x = new Encapsulated(Types.Number, 100)\nconsole.log(x.Value) // 100\nx.Value = '200' // Error: Cannot assign value '200' to Encapsulated of type 'Number'\nx.Value = 300\nconsole.log(x.Value) // 300\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqrailibs%2Ffishboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqrailibs%2Ffishboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqrailibs%2Ffishboard/lists"}