{"id":15016819,"url":"https://github.com/rawleyfowler/slick","last_synced_at":"2025-04-09T19:42:19.863Z","repository":{"id":185146866,"uuid":"672010606","full_name":"rawleyfowler/Slick","owner":"rawleyfowler","description":"Slick: A Perl web toolkit built on technologies you already know","archived":false,"fork":false,"pushed_at":"2024-10-16T17:35:19.000Z","size":157,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-23T21:35:55.510Z","etag":null,"topics":["hacktoberfest","microservice-framework","perl","perl5","plack","plack-app","restful-webservices"],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rawleyfowler.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES","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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-28T17:19:52.000Z","updated_at":"2025-01-04T04:58:00.000Z","dependencies_parsed_at":"2024-04-16T20:56:02.660Z","dependency_job_id":"1e14850b-882c-442b-9b5a-b1f32ae69f8b","html_url":"https://github.com/rawleyfowler/Slick","commit_stats":{"total_commits":35,"total_committers":2,"mean_commits":17.5,"dds":"0.11428571428571432","last_synced_commit":"b14b5b343d66ee3e7161abe778a859a615906681"},"previous_names":["rawleyfowler/slick"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawleyfowler%2FSlick","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawleyfowler%2FSlick/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawleyfowler%2FSlick/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rawleyfowler%2FSlick/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rawleyfowler","download_url":"https://codeload.github.com/rawleyfowler/Slick/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248101027,"owners_count":21047889,"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":["hacktoberfest","microservice-framework","perl","perl5","plack","plack-app","restful-webservices"],"created_at":"2024-09-24T19:49:25.545Z","updated_at":"2025-04-09T19:42:19.841Z","avatar_url":"https://github.com/rawleyfowler.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [Slick](https://metacpan.org/pod/Slick)\n\nSlick is an Object-Oriented Perl web-framework for building performant, and easy to refactor web applications.\nSlick is built on top of [DBI](https://metacpan.org/pod/DBI), [Plack](https://metacpan.org/pod/Plack), \nand [Moo](https://metacpan.org/pod/Moo) and fits somewhere in-between the realms of Dancer and Mojo.\n\nSlick has everything you need to build a Database driven REST API, including built in support\nfor Database connections, Migrations, and Caching via Redis or Memcached. Since Slick is a Plack application,\nyou can also take advantage of swappable backends and Plack middlewares extremely simply.\n\nCurrently, Slick supports `MySQL`, `Redis`, `Memcached` and `Postgres` but there are plans to implement `Oracle` and `MS SQL Server`.\n\n## Philosophy\n\nSlick is aiming to become a \"Batteries Included\" framework for building REST API's and Micro-Services in\nPerl. This will include tooling for all sorts of Micro-Service concerns like Databases, Caching, Queues,\nUser-Agents, and much more.\n\n### Goals\n\n- [x] Database management (auto-enabled)\n- [x] Migrations (auto-enabled)\n- [ ] CLI\n- [x] Caching via Redis (optional)\n- [x] Caching via Memcached (optional)\n- [x] Sub-routine based caching for routes (optional)\n- [ ] RabbitMQ built-ins (optional)\n- [ ] AWS S3 support (optional)\n- [ ] User-Agents, including Client API exports\n- [ ] AWS SQS support (optional)\n\n*Note*: All of these features excluding database stuff will be enabled optionally at run-time.\n\n## Examples\n\n### Single File App\n```perl\nuse Slick;\n\nmy $s = Slick-\u003enew;\n\n# Both MySQL and Postgres are supported databases\n# Slick will create the correct DB object based on the connection URI\n# [{mysql,postgres,postgresql}://][user[:[password]]@]host[:port][/schema]\n$s-\u003edatabase(my_db =\u003e 'postgresql://user:password@127.0.0.1:5432/schema');\n$s-\u003edatabase(corporate_db =\u003e 'mysql://corporate:secure_password@127.0.0.1:3306/schema');\n\n$s-\u003emy_db-\u003emigration(\n\t'create_user_table', # id\n\t'CREATE TABLE user ( id SERIAL PRIMARY KEY AUTOINCREMENT, name TEXT, age INT );', #up\n\t'DROP TABLE user;' # down\n);\n\n$s-\u003emy_db-\u003emigrate_up; # Migrates all pending migrations\n\n$s-\u003eget('/users/{id}' =\u003e sub {\n    my $app = shift;\n    my $context = shift;\n\n    # Queries follow SQL::Abstract's notations\n    my $user = $app-\u003emy_db-\u003eselect_one('user', { id =\u003e $context-\u003eparam('id') });\n\n    # Render the user hashref as JSON.\n    $context-\u003ejson($user);\n});\n\n$s-\u003epost('/users' =\u003e sub {\n    my $app = shift;\n    my $context = shift;\n    \n    my $new_user = $context-\u003econtent; # Will be decoded from JSON, YAML, or URL encoded (See JSON::Tiny, YAML::Tiny, and URL::Encode)\n    \n    $app-\u003emy_db-\u003einsert('user', $new_user);\n    \n    $context-\u003ejson($new_user);\n});\n\n$s-\u003erun; # Run the application.\n```\n\nSee the examples directory for this example.\n\n### Multi-file Router App\n\n```perl\n### INSIDE lib/MyApp/ItemRouter.pm\n\npackage MyApp::ItemRouter;\n\nuse Moo;\n\nextends 'Slick::Router';\n\nmy $router = __PACKAGE__-\u003enew(base =\u003e '/items');\n\n$router-\u003eget('/{id}' =\u003e sub {\n    my ($app, $context) = @_;\n    my $item = $app-\u003eitems_db-\u003eselect_one({ id =\u003e $context-\u003eparam('id') });\n    $context-\u003ejson($item);\n});\n\n$router-\u003epost('' =\u003e sub {\n    my ($app, $context) = @_;\n    my $new_item = $context-\u003econtent;\n    \n    # Do some sort of validation\n    if (not $app-\u003eitem_validator-\u003evalidate($new_item)) {\n        $context-\u003estatus(400)-\u003ejson({ error =\u003e 'Bad Request' });\n    } \n    else {\n        $app-\u003eitems_db-\u003einsert('items', $new_item);\n        $context-\u003ejson($new_item);\n    }\n});\n\nsub router {\n    return $router;\n}\n\n1;\n\npackage main;\n\nuse 5.036;\nuse lib 'lib';\n\nuse Slick;\nuse MyApp::ItemRouter;\n\nmy $slick = Slick-\u003enew;\n\n$slick-\u003edatabase(items_db =\u003e 'sqlite://items.db');\n$slick-\u003eregister(MyApp::ItemRouter-\u003erouter);\n\n$slick-\u003erun;\n```\n\nSee the examples directory for this example.\n\n### Running with `plackup`\n\nIf you wish to use `plackup` you can change the final call to `run` to a call to `app`\n\n```perl\n$s-\u003eapp;\n```\n\nThen simply run with plackup (substitue `my_app.psgi` with whatever your app is called):\n\n```bash\nplackup -a my_app.psgi\n```\n\n### Changing PSGI backend\n\nWill run on the default [`HTTP::Server::PSGI`](https://metacpan.org/pod/HTTP::Server::PSGI).\n```perl\n$s-\u003erun;\n```\n\nor \n\nIn this example, running Slick with a [`Gazelle`](https://metacpan.org/pod/Gazelle) backend on port `8888` and address `0.0.0.0`.\n```perl\n$s-\u003erun(server =\u003e 'Plack::Handler::Gazelle', port =\u003e 8888, addr =\u003e '0.0.0.0'); \n```\n\n### Using Plack Middlewares\n\nYou can register more Plack middlewares with your application very easily!\n\n```perl\nmy $s = Slick-\u003enew;\n\n$s-\u003emiddleware('Deflater')\n  -\u003emiddleware('Session', store =\u003e 'file')\n  -\u003emiddleware('Debug', panels =\u003e [ qw(DBITrace Memory) ]);\n\n$s-\u003erun; # or $s-\u003eapp depending on if you want to use plackup.\n```\n\n## Managing Your Database(s)\n\nSlick allows you to easily connect databases to your applications.\n\n### Creating a database\n```perl\nmy $s = Slick-\u003enew;\n$s-\u003edatabase(my_postgres =\u003e 'postgresql://username:password@127.0.0.1:5432/db_name');\n```\n\n### Migrations\n\nMigrations are built using the `migration` method on `Slick::Database`. You provide 1, an ID for the migration,\n2, the runnable/happy side of the migrations, and 3, the down or reverse of the migration.\n\n```perl\n$s-\u003edatabase('my_postgres')\n  -\u003emigration('create_users_table',\n  'CREATE TABLE users ( id INT PRIMARY KEY, name TEXT, age INT );',\n  'DROP TABLE user;')\n  -\u003emigration('create_pets_table',\n  'CREATE TABLE pets ( id INT PRIMARY KEY, name TEXT, owner INT FOREIGN KEY REFERENCES users (id) );',\n  'DROP TABLE pets;');\n```\n\n### Queries\n\nQueries in Slick are built with [`SQL::Abstract`](https://metacpan.org/pod/SQL::Abstract), and most of the heavy lifting\nis done for you already!\n\n```perl\nmy $users = $s-\u003emy_postgres\n              -\u003eselect('users', [ 'id', 'name' ]); # SELECT id, name FROM users;\n\nmy $user = $s-\u003emy_postgres\n             -\u003eselect_one('users', [ 'id', 'name', 'age' ], { id =\u003e 1 }); # SELECT id, name, age FROM users WHERE id = 1;\n             \n$s-\u003emy_postgres\n  -\u003einsert('users', { name =\u003e 'Bob', age =\u003e 23 }); # INSERT INTO users (name, age) VALUES ('Bob', 23);\n  \n$s-\u003emy_postgres\n  -\u003eupdate('users', { name =\u003e 'John' }, { id =\u003e 2 }); # UPDATE users SET name = 'John' WHERE id = 2;\n```\n\nIf you can't do what you want with `SQL::Abstract` helpers, you can certainly do it with DBI!\n\n```perl\n$s-\u003edatabase('my_postgres')-\u003edbi-\u003eexecute('DROP TABLE users;');\n```\n\n## Caching\n\nSlick supports caching using [`Memcached`](https://memcached.org) or [`Redis`](https://redis.io).\n\n```perl\nuse 5.036;\n\nuse Slick;\nuse Slick::Annotation qw(cacheable);\n\nmy $s = Slick-\u003enew;\n\n# See Redis and Cache::Memcached on CPAN for arguments\n\n# Create a Redis instance\n$s-\u003ecache(\n    my_redis =\u003e type =\u003e 'redis',    # Slick Arguments\n    server   =\u003e '127.0.0.1:6379'    # Cache::Memcached arguments\n);\n\n# Create a Memcached instance\n$s-\u003ecache(\n    my_memcached =\u003e type          =\u003e 'memcached',   # Slick Arguments\n    servers      =\u003e ['127.0.0.1'] =\u003e debug =\u003e 1     # Cache::Memcached arguments\n);\n\n$s-\u003emy_redis-\u003eset( something =\u003e 'awesome' );\n\n$s-\u003eget(\n    '/foo' =\u003e sub {\n        my ( $app, $context ) = @_;\n        my $value = $app-\u003ecache('my_redis')-\u003eget('something');  # Use your cache\n        return $context-\u003etext($value);\n    }\n);\n\n# Use your cache to cache a route\n$s-\u003eget(\n    '/foobar' =\u003e cacheable(\n        'my_redis',\n        sub {\n            my ( $app, $context ) = @_;\n            return $context-\u003ejson( { foo =\u003e 'bar' } );\n        }\n    )\n);\n\n$s-\u003erun;\n```\n\n## Deployment\n\nPlease follow a standard `Plack` application deployment. Reverse-proxying your application behind\n[`NGiNX`](https://nginx.org) or [`Caddy`](https://caddyserver.com) and using [`Docker`](https://www.docker.com) can\ndrastically improve your deployment.\n\nAn example `Dockerfile` can be found in the examples directory.\n\n## Contributing\n\nSlick is open to any and all contributions.\n\n**Code Standards**:\n\n* Always format with the provided `.perltidyrc`\n* Always use `Perl::Critic` set to severity `3`\n* Unpack subroutine arguments using array-destructuring when there are 2 or more elements\n\n## License\n\nSlick is provided under the Artistic 2.0 license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frawleyfowler%2Fslick","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frawleyfowler%2Fslick","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frawleyfowler%2Fslick/lists"}