{"id":19392077,"url":"https://github.com/j3lte/deno-soda","last_synced_at":"2026-05-02T22:33:19.224Z","repository":{"id":152777074,"uuid":"627031954","full_name":"j3lte/deno-soda","owner":"j3lte","description":"SODA (Socrata) Client for Deno/Node","archived":false,"fork":false,"pushed_at":"2023-12-06T22:40:28.000Z","size":89,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-07T13:20:06.940Z","etag":null,"topics":["deno","nodejs","open-data","query-builder","query-builders","socrata","soda","typescript"],"latest_commit_sha":null,"homepage":"https://deno.land/x/soda","language":"TypeScript","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/j3lte.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}},"created_at":"2023-04-12T16:37:05.000Z","updated_at":"2024-12-06T13:57:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"cb423411-7b9e-4816-b35b-04e43989d747","html_url":"https://github.com/j3lte/deno-soda","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j3lte%2Fdeno-soda","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j3lte%2Fdeno-soda/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j3lte%2Fdeno-soda/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/j3lte%2Fdeno-soda/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/j3lte","download_url":"https://codeload.github.com/j3lte/deno-soda/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240557486,"owners_count":19820360,"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":["deno","nodejs","open-data","query-builder","query-builders","socrata","soda","typescript"],"created_at":"2024-11-10T10:30:23.246Z","updated_at":"2026-05-02T22:33:14.201Z","avatar_url":"https://github.com/j3lte.png","language":"TypeScript","funding_links":["https://www.buymeacoffee.com/j3lte"],"categories":[],"sub_categories":[],"readme":"# SODA Query\n\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/j3lte/deno-soda?style=for-the-badge)](https://github.com/j3lte/deno-soda/releases/latest \"GitHub release (latest by date)\")\n[![NPM Version](https://img.shields.io/npm/v/soda-query?style=for-the-badge)](https://www.npmjs.com/package/soda-query \"NPM Version\")\n[![GitHub Release Date](https://img.shields.io/github/release-date/j3lte/deno-soda?style=for-the-badge)](https://github.com/j3lte/deno-soda/releases/latest \"GitHub Release Date\")\n![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/j3lte/deno-soda?style=for-the-badge)\n[![GitHub](https://img.shields.io/github/license/j3lte/deno-soda?style=for-the-badge)](https://github.com/j3lte/deno-soda/blob/main/LICENSE \"GitHub License\")\n[![GitHub last commit](https://img.shields.io/github/last-commit/j3lte/deno-soda?style=for-the-badge)](https://github.com/j3lte/deno-soda/commits/main \"GitHub last commit\")\n[![GitHub issues](https://img.shields.io/github/issues/j3lte/deno-soda?style=for-the-badge)](https://github.com/j3lte/deno-soda/issues \"Github Issues\")\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/j3lte/deno-soda/main.yml?branch=main\u0026style=for-the-badge)](https://github.com/j3lte/deno-soda/actions/workflows/main.yml \"GitHub Workflow Status\")\n[![Codecov](https://img.shields.io/codecov/c/github/j3lte/deno-soda?style=for-the-badge\u0026token=F9CAI1FCMX)](https://codecov.io/gh/j3lte/deno-soda \"Codecov\")\n[![Deno docs](https://img.shields.io/badge/Deno-Docs-blue?style=for-the-badge)](https://doc.deno.land/https/deno.land/x/soda/mod.ts \"Deno docs\")\n\nSODA ([Socrata](https://dev.socrata.com/)) Query Client for Deno \u0026 NodeJS.\n\n## Table of Contents\n\n- [SODA Query](#soda-query)\n  - [Table of Contents](#table-of-contents)\n  - [Features](#features)\n  - [Installation](#installation)\n  - [Example](#example)\n    - [Plain query](#plain-query)\n    - [SQL Builder](#sql-builder)\n    - [SodaQuery](#sodaquery)\n  - [Querying data](#querying-data)\n    - [Select](#select)\n    - [Where](#where)\n    - [Field](#field)\n    - [Order](#order)\n    - [Group](#group)\n  - [Development](#development)\n  - [License](#license)\n\n## Features\n\n- Create SODA queries\n- Use SODA queries to fetch from Socrata Open Data API\n- Build complex queries with ease, in a functional way\n- SQL Builder, inspired by [sql-builder](https://deno.land/x/sql_builder)\n\n\u003e _**Note:** This client is only for fetching data from Socrata Open Data API. It does not support creating, updating or deleting data._\n\n## Installation\n\nDeno:\n\n```ts\nimport { SodaQuery } from \"https://deno.land/x/soda/mod.ts\";\n```\n\nNode: (`npm i soda-query`)\n\n```ts\nimport { SodaQuery } from \"soda-query\";\n```\n\n## Example\n\n### Plain query\n\nThe `SodaQuery` class accepts plain strings in its methods:\n\n```ts\nimport { SodaQuery } from \"https://deno.land/x/soda/mod.ts\";\n\nconst DOMAIN = \"data.cityofnewyork.us\";\nconst DATASET = \"erm2-nwe9\";\n\nconst { data, error } = await new SodaQuery(DOMAIN).withDataset(DATASET)\n  .select(\"agency\", \"borough\", \"complaint_type\")\n  .where(\"complaint_type\", \"LIKE\", \"Noise%\")\n  .where(\"created_date\", \"\u003e\", \"2019-01-01T00:00:00.000\")\n  .where(\"created_date\", \"\u003c\", \"2020-01-01T00:00:00.000\")\n  .orderBy(\"created_date DESC\")\n  .limit(10)\n  .execute();\n```\n\n### SQL Builder\n\nYou can also use the SQL Builder to create your queries:\n\n```ts\nimport { Order, SodaQuery, Where } from \"https://deno.land/x/soda/mod.ts\";\n\nconst DOMAIN = \"data.cityofnewyork.us\";\nconst DATASET = \"erm2-nwe9\";\n\n// Using the SQL Builder\nconst { data, error } = await new SodaQuery(DOMAIN).withDataset(DATASET)\n  .select(\"agency\", \"borough\", \"complaint_type\")\n  .where(\n    Where.and(\n      Where.like(\"complaint_type\", \"Noise%\"),\n      Where.gt(\"created_date\", \"2019-01-01T00:00:00.000\"),\n      Where.lt(\"created_date\", \"2020-01-01T00:00:00.000\"),\n    ),\n  )\n  .orderBy(Order.by(\"created_date\").desc)\n  .limit(10)\n  .execute();\n```\n\n### SodaQuery\n\nYou can create a new SodaQuery instance by passing a domain and optionally an authOptions object and an options object.\n\n```ts\nimport { createQueryWithDataset, SodaQuery } from \"https://deno.land/x/soda/mod.ts\";\n\nconst query = new SodaQuery(\"data.organization.com\").withDataset(\"dataset-id\");\n// Same thing:\n\nconst query = createQueryWithDataset(\"data.organization.com\", \"dataset-id\");\n```\n\n## Querying data\n\n\u003e **Note:** Most methods return the instance of SodaQuery. This means that you can chain methods together.\n\n### Select\n\nA `Select` object can be used to transform the data returned by the query.\n\n```ts\nimport { Select, SodaQuery } from \"https://deno.land/x/soda/mod.ts\";\n\nconst query = new SodaQuery(\"data.organization.com\").withDataset(\"dataset-id\");\n\n// Selecting columns\nquery.select(\n  //...Select objects\n);\n\n// Just a column:\nSelect(\"column_name\");\n\n// Select all:\nSelect(); // or Select(\"*\")\n\n// Select with alias:\nSelect(\"column_name\").as(\"alias\");\n\n// Select with function:\nSelect(\"column_name\").count().as(\"counted\");\nSelect(\"column_name\").avg();\nSelect(\"column_name\").sum();\n```\n\nSee all methods in [`\u003cSelectImpl\u003e`](https://deno.land/x/soda/mod.ts?s=SelectImpl) interface.\n\n### Where\n\nA `Where` object can be used to filter the data returned by the query. It uses static methods to create the `Where` object.\n\n```ts\nimport { SodaQuery, Where } from \"https://deno.land/x/soda/mod.ts\";\n\nconst query = new SodaQuery(\"data.organization.com\").withDataset(\"dataset-id\");\n\n// Filtering data\nquery.where(\n  //...Where objects\n);\n\n// Eq\nWhere.eq(\"column_name\", \"value\");\n\n// null\nWhere.isNull(\"column_name\");\nWhere.isNotNull(\"column_name\");\n\n// Combined\nWhere.and(\n  Where.eq(\"column_name\", \"value\"),\n  Where.or(\n    Where.eq(\"column_name\", \"value\"),\n    Where.eq(\"column_name\", \"value\"),\n  ),\n);\n```\n\nSee all methods in [`\u003cWhere\u003e`](https://deno.land/x/soda/mod.ts?s=Where) interface.\n\n### Field\n\nYou can use the `Field` method that returns a `FieldImpl` object, which can be used to ensure type safety when using the `Select` and `Where` methods.\n\nIt uses the `DataType` enum to tell what type of data the field is.\n\nDataTypes:\n\n| DataType | String representation | Socrata Type | Notes |\n| --- | --- | --- | --- |\n| `Checkbox` | `\"checkbox\"` | [Checkbox](https://dev.socrata.com/docs/datatypes/checkbox.html) | |\n| `FixedTimestamp` | `\"fixed_timestamp\"` | [Fixed Timestamp](https://dev.socrata.com/docs/datatypes/fixed_timestamp.html) | |\n| `FloatingTimestamp` | `\"floating_timestamp\"` | [Floating Timestamp](https://dev.socrata.com/docs/datatypes/floating_timestamp.html) | |\n| `Line` | `\"line\"` | [Line](https://dev.socrata.com/docs/datatypes/line.html) | |\n| `Location` | `\"location\"` | [Location](https://dev.socrata.com/docs/datatypes/location.html) | |\n| `MultiLine` | `\"multiline\"` | [MultiLine](https://dev.socrata.com/docs/datatypes/multiline.html) | |\n| `MultiPoint` | `\"multipoint\"` | [MultiPoint](https://dev.socrata.com/docs/datatypes/mulitpoint.html) | |\n| `MultiPolygon` | `\"multipolygon\"` | [MultiPolygon](https://dev.socrata.com/docs/datatypes/multipolygon.html) | |\n| `Number` | `\"number\"` | [Number](https://dev.socrata.com/docs/datatypes/number.html) | |\n| `Point` | `\"point\"` | [Point](https://dev.socrata.com/docs/datatypes/point.html) | |\n| `Polygon` | `\"polygon\"` | [Polygon](https://dev.socrata.com/docs/datatypes/polygon.html) | |\n| `Text` | `\"text\"` | [Text](https://dev.socrata.com/docs/datatypes/text.html) | |\n| `URL` | `\"url\"` | [URL](https://dev.socrata.com/docs/datatypes/url.html) | |\n| `ROWIdentifier` | `\"row_identifier\"` | - | _Special tag that is only used internally, for the ':id' column._ |\n| `Unknown` | `\"_unknown\"` | - | _Default type for a field, does not check types_ |\n\nThese Datatypes can be used to define your fields:\n\n```ts\nimport { Field, DataType } from \"https://deno.land/x/soda/mod.ts\";\n\n// Just a field, will be of type FieldImpl\u003cDataType.Unknown\u003e\nconst field = Field(\"column_name\");\n\n// Field with type\nconst field = Field(\"column_name\", DataType.Text);\n```\n\nIf you define your fields like that instead of using strings, you can use the `Select` and `Where` methods with type safety:\n\n```ts\nimport { Select, SodaQuery, Field, Where } from \"https://deno.land/x/soda/mod.ts\";\n\nconst query = new SodaQuery(\"data.organization.com\").withDataset(\"dataset-id\");\n\n// This works fine\nquery.select(\n  Select(Field(\"column_name\", DataType.Text)).as(\"alias\"),\n);\n\n// This will throw an error, as you cannot use `avg` on a text field\nquery.select(\n  Select(Field(\"column_name\", DataType.Text)).avg(),\n);\n```\n\n### Order\n\nA `Order` object can be used to order the data returned by the query.\n\n```ts\nimport { Order, SodaQuery } from \"https://deno.land/x/soda/mod.ts\";\n\nconst query = new SodaQuery(\"...\");\n\n// Ordering data\nquery.order(\n  Order.by(\"column_name\").asc(),\n  Order.by(\"column_name2\").desc(),\n);\n```\n\n### Group\n\nYou can use `groupBy` to group the data returned by the query.\n\n```ts\nquery.groupBy(\n  \"column_name\",\n  \"column_name2\",\n);\n\n// Or with Fields\nquery.groupBy(\n  Field(\"column_name\", DataType.Text),\n  Field(\"column_name2\", DataType.Number),\n);\n```\n\n## Development\n\nTODO:\n\n- Add `case` method\n- Missing undocemented functions (investigate [this doc](https://dev.socrata.com/docs/transforms/))\n- Improve docs (JSDoc categories etc)\n\n## License\n\n[MIT](LICENSE)\n\n---\n\n[![\"Buy Me A Coffee\"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/j3lte)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj3lte%2Fdeno-soda","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fj3lte%2Fdeno-soda","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fj3lte%2Fdeno-soda/lists"}