{"id":15696843,"url":"https://github.com/western/wirtualbox","last_synced_at":"2025-10-25T14:10:08.435Z","repository":{"id":81872912,"uuid":"200070827","full_name":"western/wirtualbox","owner":"western","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-14T19:39:04.000Z","size":611,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"dev","last_synced_at":"2025-03-27T00:54:57.481Z","etag":null,"topics":["perl","psgi"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/western.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-01T14:58:17.000Z","updated_at":"2025-01-14T19:39:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"f49a3049-0fa1-4275-9774-d56fcdf08600","html_url":"https://github.com/western/wirtualbox","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/western%2Fwirtualbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/western%2Fwirtualbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/western%2Fwirtualbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/western%2Fwirtualbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/western","download_url":"https://codeload.github.com/western/wirtualbox/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248689382,"owners_count":21145923,"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":["perl","psgi"],"created_at":"2024-10-03T19:10:11.929Z","updated_at":"2025-10-25T14:10:08.365Z","avatar_url":"https://github.com/western.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WB (temporary work name)\n##### WB is a yet another [small] [editable] [mobility] perl web [PSGI] framework with [predeclared behaviour]\n##### Inspired by [ruby rails] [perl Catalyst] [perl Mojo]\n##### Small - all current version code contained in several packages:\n* DB\n* File - Class support for upload files\n* Model - Control of /lib/Model\n* ModelCore - Base class for all models\n* Request\n* Response\n* Router - Main work class\n* Template\n* Util\n##### Editable - get any version of code, integrate and gain full control\n##### Mobility - do not any install\n##### PSGI - Perl Web Server Gateway Interface specification\n##### Predeclared behaviour - some behaviours dictated from framework\n## Fast start\n* get repository `https://github.com/western/wirtualbox`\n* run `make` command - developer environment start for default 8090 port\n* run `make run` - start daemon for default 8090 port\n* run `make kill` - kill daemon\n## Routing\nSystem support follow requests on low level:\n* ` get( '/path/to/' =\u003e 'Package::Full::Name::and_his_action' ) `\n* ` post( '/path/to/' =\u003e 'Package::Full::Name::and_his_action' ) `\n### Special\n* root - declare action for `root \"/\"` request\n* resource\n* scope - combine some sources with location\n### Resource\nResource is a automatic generator for all source methods REST support\nExample, resource 'namething' make:\n* GET `/namething/new` for `Namething::new` sub\n* POST `/namething` - `Namething::create`\n* GET `/namething/:id/edit` - ```Namething::edit```\n* GET `/namething/:id/del` - ```Namething::del```\n* POST `/namething/:id` - ```Namething::update```\n* GET `/namething/:id` - ```Namething::show```\n* GET `/namething/` - ```Namething::index```\n\n##### Example 1: simple source file with root and /auth requests\n```perl\n# app.pl code source\n\nuse lib 'lib';\nuse WB::Router qw(:def); # export some functions\n\nmy $app = sub {\n    \n    WB::Router-\u003enew(\n        env =\u003e shift,\n        template_engine =\u003e 'HTML::Template',\n        secret =\u003e '0IkJmbamAN@cboU\u0026hHJxtruU1cI!5Lf4',\n    )-\u003edispatch(\n        root 'Page::index',\n        get(  '/auth' =\u003e 'Auth::index' ),\n    );\n};\n\n```\n###### This code generate next two services:\n* / - will work with ```/lib/Controller/Page.pm```\n* /auth - with ```/lib/Controller/Auth.pm```\n\n##### Example 2: routing with extended options\n```perl\n# app.pl code source\n\nuse lib 'lib';\nuse WB::Router qw(:def); # export some functions\n\nmy $app = sub {\n    \n    WB::Router-\u003enew(\n        env =\u003e shift,\n        template_engine =\u003e 'HTML::Template',\n        secret =\u003e '0IkJmbamAN@cboU\u0026hHJxtruU1cI!5Lf4',\n    )-\u003edispatch(\n        root 'Page::index',\n        \n        get(  '/auth'        =\u003e 'Auth::index' ),\n        post( '/auth/login'  =\u003e 'Auth::login' ),\n        get(  '/auth/logout' =\u003e 'Auth::logout' ),\n        \n        get('/admin' =\u003e 'Admin::Page::index'),\n        \n        scope('/admin' =\u003e [\n            \n            get('/vm/:uuid' =\u003e 'Admin::Vm::show'),\n            get('/vm/new' =\u003e 'Admin::Vm::new'),\n            \n            resource 'photo',\n            \n            scope('/admin/inside' =\u003e [\n                \n                resource 'doc',\n            ]),\n        ]),    \n    );\n};\n\n```\n###### Code support for:\n* get / - will work with ```/lib/Controller/Page.pm```\n* get /auth - ```/lib/Controller/Auth.pm```\n* post /auth/login\n* get /auth/logout - 'Auth::logout' if you declare \"one package name and one action\" - path is /lib/Controller/Auth\n* get /admin - ```/lib/Admin/Page.pm``` - 'Admin::Page::index' if you set \"several package names Admin::Page:: and one action\" - path is ```/lib/Admin/Page.pm```\n* get /admin/vm/:uuid - 'Admin::Vm::show' with param 'uuid' ( $args-\u003e{uuid} )\n* get /admin/vm/new - 'Admin::Vm::new'\n* resource 'photo' - make several actions. See Resource next.\n* /admin/inside/ + /doc/ resource\n## Controller\nCommon code of controller:\n```perl\n# file /lib/Controller/Photo.pm\npackage Controller::Photo;\n\nuse utf8;\nuse WB::Util qw(:def);\n\n1;\n```\nFull controller source:\n```perl\n# file /lib/Controller/Photo.pm\npackage Controller::Photo;\n\nuse utf8;\nuse WB::Util qw(:def);\n\nrequired 'App::auth_required'; # Controller::App with action \"auth_required\"\ntemplate_layout 'admin';       # main template\n\nsub new {\n    my($self, $r, $args) = @_;\n}\n\nsub create {\n    my($self, $r, $args) = @_;\n}\n\nsub edit {\n    my($self, $r, $args) = @_;\n}\n\nsub del {\n    my($self, $r, $args) = @_;\n}\n\nsub update {\n    my($self, $r, $args) = @_;\n}\n\nsub show {\n    my($self, $r, $args) = @_;\n}\n\nsub index {\n    my($self, $r, $args) = @_;\n}\n\n1;\n```\n\n### Action arguments\n\napp.pl\n```perl\n\nget('/photo/some/:uuid' =\u003e 'Photo::some_change'),\n\n```\n\nController:\n```perl\n# file /lib/Controller/Photo.pm\npackage Controller::Photo;\n\nuse utf8;\nuse WB::Util qw(:def);\n\nsub some_change {\n    my($self, $r, $args) = @_;\n    \n    warn $args-\u003e{uuid};\n    \n}\n```\n\n### Templates\n\nBy default you can create only package empty. And templates will be use.\n\n```perl\n# file /lib/Controller/Photo.pm\npackage Controller::Photo;\n\nuse utf8;\nuse WB::Util qw(:def);\n\nsub some_change {\n    my($self, $r, $args) = @_;\n    \n    # by default, system get find /template/Controller/Photo/some_change.html\n    # and 'main' layout\n    $r-\u003eresponse-\u003etemplate_args(\n        head_title =\u003e 'some title of page',\n    );\n}\n```\n\nController:\n```perl\n# file /lib/Controller/Photo.pm\npackage Controller::Photo;\n\nuse utf8;\nuse WB::Util qw(:def);\n\ntemplate_layout 'admin';  # main template\n#template_layout 'none';  # continue without main template\n# if you do not set template_layout, system set by default 'main'\n\n# define   /photo/some/:uuid\n# and call /photo/some/111-222-333\nsub some_change {\n    my($self, $r, $args) = @_;\n    \n    if ( $args-\u003e{uuid} ) {\n        \n        # by default, system get find /template/Controller/Photo/some_change.html\n        $r-\u003eresponse-\u003etemplate_args(\n            list       =\u003e [1, 2, 3],\n            uuid       =\u003e $args-\u003e{uuid},\n            head_title =\u003e 'some title of page',\n        );\n        \n        # but you can change template file\n        $r-\u003eresponse-\u003etemplate_file(\n            'template_file', 'template_layout'\n        );\n    }\n}\n```\n\nSend json data:\n```perl\n# file /lib/Controller/Photo.pm\npackage Controller::Photo;\n\nuse utf8;\nuse WB::Util qw(:def);\n\nsub some_change {\n    my($self, $r, $args) = @_;\n    \n    if ( $args-\u003e{uuid} ) {\n        \n        # send content-type: application/json;charset=utf-8\n        # and json data\n        $r-\u003eresponse-\u003ejson({\n            name1 =\u003e 'xtra',\n            val2  =\u003e 95,\n        });\n    }\n}\n```\n## Model\n### Model example\n```perl\n\npackage Model::Article;\n\nuse base WB::ModelCore;\n\n__PACKAGE__-\u003econfig( table_name =\u003e 'articles' );\n\n__PACKAGE__-\u003econfig( define_type =\u003e {\n    'articles.body'  =\u003e 'Wysiwyg',\n    'articles.title' =\u003e 'Edit',\n});\n\n__PACKAGE__-\u003ebelong_to( user_id =\u003e 'users.id' );\n__PACKAGE__-\u003ehas_many( id =\u003e 'comments.article_id' );\n1;\n\n```\n```perl\n\npackage Model::User;\n\nuse base WB::ModelCore;\n\n__PACKAGE__-\u003econfig( table_name =\u003e 'users' );\n\n1;\n\n```\n### Model call\n```perl\nsub index {\n    my($self, $r, $args) = @_;\n    \n    # get database handle\n    $r-\u003emodel-\u003edb;\n    # or\n    $r-\u003emodel-\u003eArticle-\u003edb;\n    # select * from articles\n    $r-\u003emodel-\u003eArticle-\u003elist;\n    # get value registered from first row\n    $r-\u003emodel-\u003eArticle-\u003elist-\u003e[0]-\u003e{registered}-\u003evalue;\n    \n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'users' )-\u003elist-\u003e[0];\n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'left users' )-\u003elist-\u003e[0];\n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'left users' =\u003e 'articles.user_id = users.xx' )-\u003elist-\u003e[0];\n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'comments' )-\u003elist-\u003e[0];\n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'left comments' )-\u003elist-\u003e[0];\n    \n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'users' )-\u003elist()-\u003e[0];\n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'users' )-\u003elist-\u003e[0];\n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'users' )-\u003elist( -flat =\u003e 1 )-\u003e[0];\n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'users' )-\u003elist( -data =\u003e 1 )-\u003e[0];\n    # $r-\u003emodel-\u003eArticle-\u003ejoin( 'users' )-\u003elist( -data =\u003e 1 );\n}\n```\n\n## WB Type\n### WB Type simple\n\n```perl\npackage WB::Type::Int;\n\nuse base WB::Type::Basement;\n\n1;\n\n```\n\n### WB Type extend\n\n```perl\n\npackage WB::Type::Wysiwyg;\n\nuse base WB::Type::Text;\n\nsub value {\n    my $self  = shift;\n    my $value = shift;\n    \n    $self-\u003e{value} = $value if ( defined $value );\n    \n    '[['.$self-\u003e{value}.']]';\n}\n\n1;\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwestern%2Fwirtualbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwestern%2Fwirtualbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwestern%2Fwirtualbox/lists"}