{"id":13878506,"url":"https://github.com/dphaener/kanji","last_synced_at":"2025-08-26T14:33:36.184Z","repository":{"id":56879873,"uuid":"101511687","full_name":"dphaener/kanji","owner":"dphaener","description":"A strongly typed GraphQL API framework","archived":false,"fork":false,"pushed_at":"2017-10-26T03:09:01.000Z","size":71,"stargazers_count":11,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-21T19:07:38.567Z","etag":null,"topics":["api-server","functional","graphql","graphql-api","graphql-ruby","graphql-server","type-safety","type-system"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/dphaener.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}},"created_at":"2017-08-26T20:33:46.000Z","updated_at":"2023-03-25T16:28:14.000Z","dependencies_parsed_at":"2022-08-20T11:40:33.262Z","dependency_job_id":null,"html_url":"https://github.com/dphaener/kanji","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/dphaener/kanji","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphaener%2Fkanji","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphaener%2Fkanji/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphaener%2Fkanji/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphaener%2Fkanji/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dphaener","download_url":"https://codeload.github.com/dphaener/kanji/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dphaener%2Fkanji/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271871440,"owners_count":24836927,"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","status":"online","status_checked_at":"2025-08-24T02:00:11.135Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["api-server","functional","graphql","graphql-api","graphql-ruby","graphql-server","type-safety","type-system"],"created_at":"2024-08-06T08:01:51.722Z","updated_at":"2025-08-26T14:33:36.137Z","avatar_url":"https://github.com/dphaener.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"[![Gem Version](https://badge.fury.io/rb/kanji-web.svg)](https://badge.fury.io/rb/kanji-web)\n[![Code Climate](https://codeclimate.com/github/dphaener/kanji/badges/gpa.svg)](https://codeclimate.com/github/dphaener/kanji)\n[![CircleCI](https://circleci.com/gh/dphaener/kanji.svg?style=svg)](https://circleci.com/gh/dphaener/kanji)\n[![Coverage Status](https://coveralls.io/repos/github/dphaener/kanji/badge.svg?branch=master)](https://coveralls.io/github/dphaener/kanji?branch=master)\n\n# Kanji\n\n## Overview\n\n### A micro, GraphQL based, strongly typed, API only web framework\n\nKanji is based on a type system. The overall application architecture is\nheavily inspired by [dry-web-roda](https://github.com/dry-rb/dry-web-roda).\nEverything in the application is [container based](https://github.com/dry-rb/dry-container),\nand the GraphQL API is inferred by creating types.\n\nCurrently Kanji supports only a Postgres database, so if you don't have Postgres\ninstalled get to it and let's get started!\n\n## Getting Started\n\n### Install the gem\n\n```bash\n$ gem install kanji-web\n```\n\nThis will install a global executable `kanji`. Let's start a new project:\n\n```bash\n$ kanji new todo\n```\n\nThis will create a bunch of files in a folder called `todo`. It's a good start,\nbut the application really won't be usable until you create your first type\nand add it to your GraphQL schema, so let's create our first type:\n\n```bash\n$ kanji g type User email:string name:string\n```\n\nThis will generate a database migration, a new type, and a\nrepository(did I mention Kanji uses ROM?) to be used for accessing your data.\n\nThis also adds the mutations for the user to you root mutation type located\nat: `app/mutation_type.rb`.\n\nNext ensure that the database is created, and run the migration:\n\n```bash\n$ rake db:create \u0026\u0026 rake db:migrate\n```\n\nGreat, now you have a `users` table in your database!\n\nNext we're going to want to add a field to our base query type. Open up your\nquery definition at `app/query_type.rb` and add the following.\n\n```rb\nfield :users do\n  type -\u003e { types[Types::User[:graphql_type]] }\n  description \"All of the users in this app\"\n\n  resolve -\u003e (obj, args, ctx) { Types::User[:repo].all }\nend\n```\n\nNext you'll want to open up your main schema file and uncomment the query and\nmutation type declarations. This file is at `app/schema.rb`.\n\nThat's it! You now have a GraphQL API with a root node that you can\nquery and the basic `create`, `update`, and `destroy` mutations.\n\nLet's start the server and play with the API:\n\n```bash\n$ kanji s\n```\n\nThis will start a server on `localhost:9393`. Visit `localhost:9393/graphiql`\nand play around with the API!\n\n## Types\n\nTypes are the foundation for everything that is done in Kanji. When you create\na type and define it's attributes a lot of stuff happens under the covers.\nBecause everything is container based, when you create a type it is a container\nand it exposes a few things that you can use in the application.\n\n### value_object\n\nAn instance of this is returned when you fetch a row or rows from the database. It is\nan immutable value object that does nothing but store the values and give you\naccessors. It can be resolved from the container like so:\n```ruby\nTypes::User[:value_object]\n```\nThis object is typically not needed in regular development. It is used by the\nrepository to resolve database values.\n\n### graphql_type\n\nThis is the graphql definition that is used in your graphql schemas. You can\nsee from above that we used it when defining our root `users` field.\n\n### schema\n\nThis is a dry-validation schema that can be used to validate and manipulate\nincoming data before persisting to the database.\n\n### repo\n\nThis is the repository that is associated with the type. The definition lives\nin the `app/repositories` folder, and is generated when you use the command\nline type generator. It allows you to read/mutate data in the database.\n\n## Repositories\n\nYour repositories are what defines how you interact with data in the database.\nAll repositories inherit from `Kanji::Repository` and give you a few default\nconvenience methods: `create`, `update`, `destroy`, and `all`.\n\nBeyond this, it is up to you to add methods that fetch/persist data as needed\nby your application domain. The `Kanji::Repository` class exposes the `relation`\nmethod that can be used to interact with the database. I.E. -\n\n```ruby\nmodule Repositories\n  class Users \u003c Kanji::Repository[:users]\n    def find_by_id(id)\n      relation.where(id: id).one\n    end\n  end\nend\n```\n\n### create\n\nThe create method takes a params hash of all required attributes and creates\na new row in the database, returning an instance of the value_object for that\ntype.\n\n### update\n\nSimilar to the create method, but also requires the primary key.\n\n### destroy\n\nTakes the primary key as the only argument and returns the same object that\nwas deleted from the database.\n\n### all\n\nReturns all of the records for this table.\n\n### relation\n\nA convenience method that allows you to run queries on the table for this particular\ntype.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdphaener%2Fkanji","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdphaener%2Fkanji","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdphaener%2Fkanji/lists"}