{"id":32861504,"url":"https://github.com/c0m371/restsql","last_synced_at":"2026-01-20T16:56:48.494Z","repository":{"id":323037529,"uuid":"1065403357","full_name":"c0m371/RestSQL","owner":"c0m371","description":"RestSQL: A lightweight .NET tool that turns SQL queries (defined in YAML) into ready-to-run REST endpoints. Works standalone or as a library, supports transactions, nested JSON output, and multiple database providers.","archived":false,"fork":false,"pushed_at":"2025-11-07T18:16:46.000Z","size":89,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-07T19:14:48.512Z","etag":null,"topics":["asp-net-core","csharp","database","dotnet","generation","mysql","oracle","postgresql","rest-api","sql","sqlite","sqlserver","yaml"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/c0m371.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,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-27T16:51:41.000Z","updated_at":"2025-11-07T18:16:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/c0m371/RestSQL","commit_stats":null,"previous_names":["c0m371/restsql"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/c0m371/RestSQL","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c0m371%2FRestSQL","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c0m371%2FRestSQL/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c0m371%2FRestSQL/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c0m371%2FRestSQL/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/c0m371","download_url":"https://codeload.github.com/c0m371/RestSQL/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c0m371%2FRestSQL/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":283418034,"owners_count":26832617,"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-11-08T02:00:06.281Z","response_time":57,"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":["asp-net-core","csharp","database","dotnet","generation","mysql","oracle","postgresql","rest-api","sql","sqlite","sqlserver","yaml"],"created_at":"2025-11-08T21:01:21.633Z","updated_at":"2026-01-20T16:56:48.488Z","avatar_url":"https://github.com/c0m371.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RestSQL \n|        |                                                                                                          |\n|--------|:--------------------------------------------------------------------------------------------------------:|\n| Nuget  | [![Nuget](https://img.shields.io/nuget/v/Comet1.RestSQL)](https://www.nuget.org/packages/Comet1.RestSQL) |\n| Docker | [![Docker](https://img.shields.io/docker/v/cometone/restsql)](https://hub.docker.com/r/cometone/restsql) |\n\n\nRestSQL is a lightweight **.NET tool** that turns SQL queries (defined in **YAML**) into ready-to-run **REST endpoints**. Works standalone or as a library, supports transactions, nested JSON output, multiple database providers, and **OAuth 2.0/OpenID Connect (OIDC) authentication**.\n\n## Getting Started\n\nThere are two ways to use RestSQL:\n\n### 1. Standalone API (Using RestSQL.Api)\n\n#### Build from source\n\nThe simplest way to get started is using the pre-built API project:\n\n1. Clone the repository\n2. Configure your `appsettings.json`:\n\n```json\n{\n  \"RestSQL\": {\n    \"ConfigFolder\": \"path/to/your/yaml/configs\"\n  },\n  \"Serilog\": {\n    \"MinimumLevel\": {\n      \"Default\": \"Information\"\n    },\n    \"WriteTo\": [\n      {\n        \"Name\": \"Console\"\n      }\n    ]\n  }\n}\n```\n\n3. Run the project:\n\n```sh\ncd src/RestSQL.Api\ndotnet run\n```\n\n#### Alternatively, use docker \n[![Docker](https://img.shields.io/docker/v/cometone/restsql)](https://hub.docker.com/r/cometone/restsql)\n\n\nSet the `RestSQL:ConfigFolder` key using the environment variable name `RestSQL__ConfigFolder` (double underscore maps to a colon in ASP.NET configuration).\n\nExample Docker run (mount local configs and set env):\n\n```sh\ndocker run --rm -p 7017:8080 \\\n  -v $(pwd)/my-yaml-configs:/app/config \\\n  -e RestSQL__ConfigFolder=/app/config \\\n  cometone/restsql:latest\n```\n\nRunning inside containers: connection string tips\n\nWhen your API runs inside Docker, the database host in connection strings must be reachable from the container. A few common patterns:\n\n- Docker Desktop (Windows/macOS): use `host.docker.internal` to reach services running on the host machine. Example Postgres connection string:\n\n  `Host=host.docker.internal;Port=5432;Database=mydb;Username=user;Password=pass`\n\n- Linux Docker (host.docker.internal): older Docker engines on Linux don't provide `host.docker.internal` by default. You can add it at container startup with `--add-host` (Docker 20.10+ with host-gateway):\n\n  ```sh\n  docker run --add-host=host.docker.internal:host-gateway \\\n    -e RestSQL__ConfigFolder=/app/config \\\n    -v $(pwd)/my-yaml-configs:/app/config \\\n    cometone/restsql:latest\n  ```\n\n### 2. Library Usage (Adding to Existing Project)\n\nAdd RestSQL to your ASP.NET Core project:\n\n```csharp\n// Program.cs\nbuilder.Services.AddRestSQL(builder.Configuration);\n\n// Configure middleware\napp.UseRestSQL(builder.Configuration);\n```\n\nEither link the project via the source code, or use Nuget  \n![NuGet Version](https://img.shields.io/nuget/v/Comet1.RestSQL)\n\n## Configuration\n\nRestSQL uses YAML files for configuration. You need two main configuration sections:\n\n1. connections - Database connection definitions\n2. endpoints - Endpoint definitions\n\nYou can split these across files as you see fit, they will be merged.\nA single file is also fine. \n\n### Database Connections\n\nDefine your database connections under connections:\n\n```yaml\nconnections:\n  postgres1:\n    type: PostgreSQL\n    connectionString: \"Host=localhost;Database=mydb;Username=user;Password=pass\"\n  mysql1:\n    type: MySql\n    connectionString: \"Server=localhost;Database=mydb;User=user;Password=pass\"\n  oracle1:\n    type: Oracle\n    connectionString: \"Data Source=localhost:1521/XEPDB1;User Id=system;Password=pass\"\n  sqlserver1:\n    type: SqlServer\n    connectionString: \"Server=localhost;Database=mydb;User=sa;Password=pass;TrustServerCertificate=True\"\n  sqlite1:\n    type: Sqlite\n    connectionString: \"Data Source=local.db\"\n```\n\n### Authentication Configuration\n\nFor secured endpoints, define your OIDC/OAuth 2.0 configuration globally under `authentication`. This section is **optional**.\n\n```yaml\nauthentication:\n  authority: https://auth.example.com/\n  audience: https://api.example.com\n  scopes:\n    - write:posts\n```\n\n### Endpoint Configuration\n\nDefine REST endpoints. Endpoints can include optional authorization settings.\nSee section \"Example blog API\" below.\n\n## Example Blog API\n\nLet's look at a complete blog post API example:\n\n```yaml\nconnections:\n  blog:\n    type: PostgreSQL\n    connectionString: \"Host=localhost;Database=restsql_blog;Username=restsql_blog;Password=restsql_blog\"\n\nendpoints:\n  # Get all posts with tags\n  - path: /api/posts\n    method: GET\n    statusCode: 200\n    sqlQueries:\n      posts:\n        connectionName: blog\n        sql: \u003e\n          select id post_id, title, description, creation_date, username\n          from posts;\n      tags: \u0026tagsQuery\n        connectionName: blog\n        sql: \u003e\n          select *\n          from tags;\n    outputStructure:\n      type: Object\n      isArray: true\n      queryName: posts\n      fields: \u0026postFields\n        - { type: Long, name: id, columnName: post_id }\n        - { type: String, name: title, columnName: title }\n        - { type: String, name: description, columnName: description }\n        - { type: String, name: username, columnName: username }\n        - { type: String, name: creationDate, columnName: creation_date }\n        - type: string\n          isArray: true\n          name: tags\n          queryName: tags\n          columnName: tag\n          linkColumn: post_id\n      \n  # Get specific post\n  - path: /api/posts/{id}\n    method: GET\n    statusCode: 200\n    statusCodeOnEmptyResult: 404\n    sqlQueries:\n      posts:\n        connectionName: blog\n        sql: \u003e\n          select id post_id, title, description, creation_date, username\n          from posts\n          where id = :id::int;\n      tags: \u0026tagsQuery\n        connectionName: blog\n        sql: \u003e\n          select *\n          from tags;\n    outputStructure:\n      type: Object\n      isArray: true\n      queryName: posts\n      fields: *postFields\n\n  # Create new post, and return the created post\n  # Requires authorization\n  - path: /api/posts\n    method: POST\n    statusCode: 200\n    authorize: true                 # Requires a valid JWT bearer token\n    authorizationScope: write:posts # Token must contain this scope claim\n    writeOperations:\n      - connectionName: blog\n        sql: \u003e\n          insert into posts (title, description, creation_date, username)\n          values (:title, :description, current_timestamp, :username)\n          returning id;\n        bodyType: Object\n        outputCaptures:\n          - columnName: id\n            parameterName: post_id\n    sqlQueries:\n      posts:\n        connectionName: blog\n        sql: \u003e\n          select id post_id, title, description, creation_date, username\n          from posts\n          where id = @post_id;\n      tags: *tagsQuery\n    outputStructure:\n      type: Object\n      queryName: posts\n      fields: *postFields\n```\n\n### Making Requests\n\nGet posts:\n```sh\nGET /api/posts\n\nResponse:\n[\n  {\n    \"id\": 1,\n    \"title\": \"The Joys of Async/Await\",\n    \"description\": \"A deep dive into non-blocking operations in C#.\",\n    \"creationDate\": \"2025-10-25T15:03:04\",\n    \"username\": \"alice_codes\",\n    \"tags\": [\"C#\", \"Async\"]\n  }\n]\n```\n\nCreate post (with Authorization):\nYou must include an `Authorization: Bearer \u003ctoken\u003e` header where the token grants the `write:posts` scope.\n\n```sh\nPOST /api/posts\nAuthorization: Bearer \u003cJWT_TOKEN_WITH_WRITE:POSTS_SCOPE\u003e\n\n{\n  \"title\": \"PostgreSQL vs MySQL\",\n  \"description\": \"A performance comparison\",\n  \"username\": \"bob_devs\"\n}\n\nResponse:\n{\n  \"id\": 2,\n  \"title\": \"PostgreSQL vs MySQL\",\n  \"description\": \"A performance comparison\",\n  \"username\": \"bob_devs\",\n  \"creationDate\": \"06/11/2025 10:30:41\",\n  \"tags\": []\n}\n```\n\nGet specific post:\n```sh\nGET /api/posts/2\n\nResponse:\n[\n  {\n    \"id\": 2,\n    \"title\": \"PostgreSQL vs MySQL: A Performance Review\",\n    \"description\": \"Comparing the speed and features of two popular databases.\",\n    \"username\": \"alice_codes\",\n    \"creationDate\": \"22/10/2025 22:00:00\",\n    \"tags\": [\n      \"PostgreSQL\",\n      \"Database\"\n    ]\n  }\n]\n```\n\n## Advanced Features\n\n### Output Structure Transformation\n\nYou can define complex nested JSON structures.\nQueries can be linked through a linkColumn.\n\n```yaml\n    sqlQueries:\n      posts:\n        connectionName: blog\n        sql: \u003e\n          select id post_id, title, description, creation_date, username\n          from posts;\n      tags:\n        connectionName: blog\n        sql: \u003e\n          select *\n          from tags;\n    outputStructure:\n      type: Object\n      isArray: true\n      queryName: posts\n      fields:\n        - { type: Long, name: id, columnName: post_id }\n        - { type: String, name: title, columnName: title }\n        - { type: String, name: description, columnName: description }\n        - { type: String, name: username, columnName: username }\n        - { type: String, name: creationDate, columnName: creation_date }\n        - type: string\n          isArray: true\n          name: tags\n          queryName: tags\n          columnName: tag\n          linkColumn: post_id\n```\n\n### Parameter Capture\n\nCapture output from write operations:\n\n```yaml\nwriteOperations:\n  - connectionName: postgres1\n    sql: \"INSERT INTO posts ... RETURNING id\"\n    outputCaptures:\n      - columnName: id\n        parameterName: postId\n  - connectionName: postgres1\n    sql: \"INSERT INTO tags (post_id, tag) VALUES (@postId, @tag)\"\n```\n\n### Transaction Support\n\nMultiple write operations are automatically wrapped in a transaction:\n\n```yaml\nwriteOperations:\n  - connectionName: postgres1\n    sql: \"INSERT INTO posts ...\"\n  - connectionName: postgres1\n    sql: \"INSERT INTO tags ...\"  # Rolled back if posts insert fails\n```\n\n### Parameter Binding\n\n- Route parameters: `{id}` in path\n- Query parameters: `?search=term`\n- Request body: JSON object or value\n\n## Development Setup\n\n1. Clone the repository\n2. Install .NET 9.0 SDK\n3. Run tests:\n\n```sh\ndotnet test\n```\n\nNote that docker should be running to be able to run the integration tests with test containers.\n\n4. Start the API:\n\n```sh\ncd src/RestSQL.Api\ndotnet run\n```\n\nFor more examples, check out the integration tests in the `tests/RestSQL.IntegrationTests` directory.\n\n## Supported Databases\n\n- PostgreSQL\n- SQL Server\n- MySQL\n- Oracle\n- SQLite\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc0m371%2Frestsql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fc0m371%2Frestsql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc0m371%2Frestsql/lists"}