{"id":28628921,"url":"https://github.com/sqliteai/sqlite-js","last_synced_at":"2026-02-10T19:10:44.395Z","repository":{"id":293005173,"uuid":"957983251","full_name":"sqliteai/sqlite-js","owner":"sqliteai","description":"Create custom SQLite functions in JavaScript. Extend your database with scalars, aggregates, window functions, and collations directly in JavaScript.","archived":false,"fork":false,"pushed_at":"2025-10-20T12:44:53.000Z","size":3201,"stargazers_count":540,"open_issues_count":0,"forks_count":11,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-01-14T04:48:03.819Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://sqlite.ai/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sqliteai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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-03-31T13:02:52.000Z","updated_at":"2026-01-11T17:45:26.000Z","dependencies_parsed_at":"2025-07-23T10:22:02.939Z","dependency_job_id":"e7409fa2-b2dd-428f-8962-d4d712c6f915","html_url":"https://github.com/sqliteai/sqlite-js","commit_stats":null,"previous_names":["sqliteai/sqlite-js"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/sqliteai/sqlite-js","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqliteai%2Fsqlite-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqliteai%2Fsqlite-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqliteai%2Fsqlite-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqliteai%2Fsqlite-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sqliteai","download_url":"https://codeload.github.com/sqliteai/sqlite-js/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqliteai%2Fsqlite-js/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29313097,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-10T17:48:59.043Z","status":"ssl_error","status_checked_at":"2026-02-10T17:45:37.240Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2025-06-12T11:01:42.272Z","updated_at":"2026-02-10T19:10:44.356Z","avatar_url":"https://github.com/sqliteai.png","language":"C","readme":"# SQLite JS\n\n**SQLite JS** is a powerful extension that brings JavaScript capabilities to SQLite. With this extension, you can create custom SQLite functions, aggregates, window functions, and collation sequences using JavaScript code, allowing for flexible and powerful data manipulation directly within your SQLite database.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Functions Overview](#functions-overview)\n- [Scalar Functions](#scalar-functions)\n- [Aggregate Functions](#aggregate-functions)\n- [Window Functions](#window-functions)\n- [Collation Sequences](#collation-sequences)\n- [Sync JavaScript Functions Across Devices](#syncing-across-devices)\n- [JavaScript Evaluation](#javascript-evaluation)\n- [Examples](#examples)\n- [Update Functions](#update-functions)\n- [Function Naming Rules](#function-naming-rules)\n- [Building from Source](#building-from-source)\n- [License](#license)\n\n## Installation\n\n### Pre-built Binaries\n\nDownload the appropriate pre-built binary for your platform from the official [Releases](https://github.com/sqliteai/sqlite-js/releases) page:\n\n- Linux: x86 and ARM\n- macOS: x86 and ARM\n- Windows: x86\n- Android\n- iOS\n\n### Loading the Extension\n\n```sql\n-- In SQLite CLI\n.load ./js\n\n-- In SQL\nSELECT load_extension('./js');\n```\n\n### Swift Package\n\nYou can [add this repository as a package dependency to your Swift project](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app#Add-a-package-dependency). After adding the package, you'll need to set up SQLite with extension loading by following steps 4 and 5 of [this guide](https://github.com/sqliteai/sqlite-extensions-guide/blob/main/platforms/ios.md#4-set-up-sqlite-with-extension-loading).\n\nHere's an example of how to use the package:\n```swift\nimport js\n\n...\n\nvar db: OpaquePointer?\nsqlite3_open(\":memory:\", \u0026db)\nsqlite3_enable_load_extension(db, 1)\nvar errMsg: UnsafeMutablePointer\u003cInt8\u003e? = nil\nsqlite3_load_extension(db, js.path, nil, \u0026errMsg)\nvar stmt: OpaquePointer?\nsqlite3_prepare_v2(db, \"SELECT js_version()\", -1, \u0026stmt, nil)\ndefer { sqlite3_finalize(stmt) }\nsqlite3_step(stmt)\nlog(\"js_version(): \\(String(cString: sqlite3_column_text(stmt, 0)))\")\nsqlite3_close(db)\n```\n\n### Android Package\n\nAdd the [following](https://central.sonatype.com/artifact/ai.sqlite/js) to your Gradle dependencies:\n\n```gradle\nimplementation 'ai.sqlite:js:1.1.12'\n```\n\nHere's an example of how to use the package:\n```java\nSQLiteCustomExtension jsExtension = new SQLiteCustomExtension(getApplicationInfo().nativeLibraryDir + \"/js\", null);\nSQLiteDatabaseConfiguration config = new SQLiteDatabaseConfiguration(\n    getCacheDir().getPath() + \"/js_test.db\",\n    SQLiteDatabase.CREATE_IF_NECESSARY | SQLiteDatabase.OPEN_READWRITE,\n    Collections.emptyList(),\n    Collections.emptyList(),\n    Collections.singletonList(jsExtension)\n);\nSQLiteDatabase db = SQLiteDatabase.openDatabase(config, null, null);\n```\n\n**Note:** Additional settings and configuration are required for a complete setup. For full implementation details, see the [complete Android example](https://github.com/sqliteai/sqlite-extensions-guide/blob/main/examples/android/README.md).\n\n## Functions Overview\n\nSQLite-JS provides several ways to extend SQLite functionality with JavaScript:\n\n| Function Type | Description |\n|---------------|-------------|\n| Scalar Functions | Process individual rows and return a single value |\n| Aggregate Functions | Process multiple rows and return a single aggregated result |\n| Window Functions | Similar to aggregates but can access the full dataset |\n| Collation Sequences | Define custom sort orders for text values |\n| JavaScript Evaluation | Directly evaluate JavaScript code within SQLite |\n\n## Scalar Functions\n\nScalar functions process one row at a time and return a single value. They are useful for data transformation, calculations, text manipulation, etc.\n\n### Usage\n\n```sql\nSELECT js_create_scalar('function_name', 'function_code');\n```\n\n### Parameters\n\n- **function_name**: The name of your custom function (see [Function Naming Rules](#function-naming-rules))\n- **function_code**: JavaScript code that defines your function. Must be in the form `function(args) { /* your code here */ }`\n\n### Example\n\n```sql\n-- Create a custom function to calculate age from birth date\nSELECT js_create_scalar('age', '(function(args) {\n  const birthDate = new Date(args[0]);\n  const today = new Date();\n  let age = today.getFullYear() - birthDate.getFullYear();\n  const m = today.getMonth() - birthDate.getMonth();\n  if (m \u003c 0 || (m === 0 \u0026\u0026 today.getDate() \u003c birthDate.getDate())) {\n    age--;\n  }\n  return age;\n})');\n\n-- Use the function\nSELECT name, age(birth_date) FROM people;\n```\n\n## Aggregate Functions\n\nAggregate functions process multiple rows and compute a single result. Examples include SUM, AVG, and COUNT in standard SQL.\n\n### Usage\n\n```sql\nSELECT js_create_aggregate('function_name', 'init_code', 'step_code', 'final_code');\n```\n\n### Parameters\n\n- **function_name**: The name of your custom aggregate function (see [Function Naming Rules](#function-naming-rules))\n- **init_code**: JavaScript code that initializes variables for the aggregation\n- **step_code**: JavaScript code that processes each row. Must be in the form `function(args) { /* your code here */ }`\n- **final_code**: JavaScript code that computes the final result. Must be in the form `function() { /* your code here */ }`\n\n### Example\n\n```sql\n-- Create a median function\nSELECT js_create_aggregate('median', \n  -- Init code: initialize an array to store values\n  'values = [];',\n  \n  -- Step code: collect values from each row\n  '(function(args) {\n    values.push(args[0]);\n  })',\n  \n  -- Final code: calculate the median\n  '(function() {\n    values.sort((a, b) =\u003e a - b);\n    const mid = Math.floor(values.length / 2);\n    if (values.length % 2 === 0) {\n      return (values[mid-1] + values[mid]) / 2;\n    } else {\n      return values[mid];\n    }\n  })'\n);\n\n-- Use the function\nSELECT median(salary) FROM employees;\n```\n\n## Window Functions\n\nWindow functions, like aggregate functions, operate on a set of rows. However, they can access all rows in the current window without collapsing them into a single output row.\n\n### Usage\n\n```sql\nSELECT js_create_window('function_name', 'init_code', 'step_code', 'final_code', 'value_code', 'inverse_code');\n```\n\n### Parameters\n\n- **function_name**: The name of your custom window function (see [Function Naming Rules](#function-naming-rules))\n- **init_code**: JavaScript code that initializes variables\n- **step_code**: JavaScript code that processes each row. Must be in the form `function(args) { /* your code here */ }`\n- **final_code**: JavaScript code that computes the final result. Must be in the form `function() { /* your code here */ }`\n- **value_code**: JavaScript code that returns the current value. Must be in the form `function() { /* your code here */ }`\n- **inverse_code**: JavaScript code that removes a row from the current window. Must be in the form `function(args) { /* your code here */ }`\n\n### Example\n\n```sql\n-- Create a moving average window function\nSELECT js_create_window('moving_avg',\n  -- Init code\n  'sum = 0; count = 0;',\n  \n  -- Step code: process each row\n  '(function(args) {\n    sum += args[0];\n    count++;\n  })',\n  \n  -- Final code: not needed for this example\n  '(function() { })',\n  \n  -- Value code: return current average\n  '(function() {\n    return count \u003e 0 ? sum / count : null;\n  })',\n  \n  -- Inverse code: remove a value from the window\n  '(function(args) {\n    sum -= args[0];\n    count--;\n  })'\n);\n\n-- Use the function\nSELECT id, value, moving_avg(value) OVER (ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) \nFROM measurements;\n```\n\n## Collation Sequences\n\nCollation sequences determine how text values are compared and sorted in SQLite. Custom collations enable advanced sorting capabilities like natural sorting, locale-specific sorting, etc.\n\n### Usage\n\n```sql\nSELECT js_create_collation('collation_name', 'collation_function');\n```\n\n### Parameters\n\n- **collation_name**: The name of your custom collation (see [Function Naming Rules](#function-naming-rules))\n- **collation_function**: JavaScript code that compares two strings. Must return a negative number if the first string is less than the second, zero if they are equal, or a positive number if the first string is greater than the second.\n\n### Example\n\n```sql\n-- Create a case-insensitive natural sort collation\nSELECT js_create_collation('natural_nocase', '(function(a, b) {\n  // Extract numbers for natural comparison\n  const splitA = a.toLowerCase().split(/(\\d+)/);\n  const splitB = b.toLowerCase().split(/(\\d+)/);\n  \n  for (let i = 0; i \u003c Math.min(splitA.length, splitB.length); i++) {\n    if (splitA[i] !== splitB[i]) {\n      if (!isNaN(splitA[i]) \u0026\u0026 !isNaN(splitB[i])) {\n        return parseInt(splitA[i]) - parseInt(splitB[i]);\n      }\n      return splitA[i].localeCompare(splitB[i]);\n    }\n  }\n  return splitA.length - splitB.length;\n})');\n\n-- Use the collation\nSELECT * FROM files ORDER BY name COLLATE natural_nocase;\n```\n\n## Syncing Across Devices\n\nWhen used with [sqlite-sync](https://github.com/sqliteai/sqlite-sync/), user-defined functions created via sqlite-js are automatically replicated across the SQLite Cloud cluster, ensuring that all connected peers share the same logic and behavior — even offline. To enable automatic persistence and sync the special `js_init_table` function must be executed.\n\n### Usage\n```sql\nSELECT js_init_table();         -- Create table if needed (no loading)\nSELECT js_init_table(1);        -- Create table and load all stored functions\n```\n\n## JavaScript Evaluation\n\nThe extension also provides a way to directly evaluate JavaScript code within SQLite queries.\n\n### Usage\n\n```sql\nSELECT js_eval('javascript_code');\n```\n\n### Parameters\n\n- **javascript_code**: Any valid JavaScript code to evaluate\n\n### Example\n\n```sql\n-- Perform a calculation\nSELECT js_eval('Math.PI * Math.pow(5, 2)');\n\n-- Format a date\nSELECT js_eval('new Date(1629381600000).toLocaleDateString()');\n```\n\n## Examples\n\n### Example 1: String Manipulation\n\n```sql\n-- Create a function to extract domain from email\nSELECT js_create_scalar('get_domain', '(function(args) {\n  const email = args[0];\n  return email.split(\"@\")[1] || null;\n})');\n\n-- Use it in a query\nSELECT email, get_domain(email) AS domain FROM users;\n```\n\n### Example 2: Statistical Aggregation\n\n```sql\n-- Create a function to calculate standard deviation\nSELECT js_create_aggregate('stddev',\n  'sum = 0; sumSq = 0; count = 0;',\n  \n  '(function(args) {\n    const val = args[0];\n    sum += val;\n    sumSq += val * val;\n    count++;\n  })',\n  \n  '(function() {\n    if (count \u003c 2) return null;\n    const variance = (sumSq - (sum * sum) / count) / (count - 1);\n    return Math.sqrt(variance);\n  })'\n);\n\n-- Use it in a query\nSELECT department, stddev(salary) FROM employees GROUP BY department;\n```\n\n### Example 3: Custom Window Function\n\n```sql\n-- Create a window function to calculate percentile within a window\nSELECT js_create_window('percentile_rank',\n  'values = [];',\n  \n  '(function(args) {\n    values.push(args[0]);\n  })',\n  \n  '(function() {\n    values.sort((a, b) =\u003e a - b);\n  })',\n  \n  '(function() {\n    const current = values[values.length - 1];\n    const rank = values.indexOf(current);\n    return (rank / (values.length - 1)) * 100;\n  })',\n  \n  '(function(args) {\n    const index = values.indexOf(args[0]);\n    if (index !== -1) {\n      values.splice(index, 1);\n    }\n  })'\n);\n\n-- Use it in a query\nSELECT name, score, \n       percentile_rank(score) OVER (ORDER BY score) \nFROM exam_results;\n```\n\n## Update Functions\n\nDue to a constraint in [SQLite](https://www3.sqlite.org/src/info/cabab62bc10568d4), it is not possible to update or redefine a user-defined function using the same database connection that was used to initially register it. To modify an existing JavaScript function, the update must be performed through a separate database connection.\n\n## Function Naming Rules\n\nFunction names must comply with SQLite identifier rules and must be unique within the database and its schema.\n\n### Unquoted Identifiers\nThese must follow typical SQL naming conventions:\n- Must begin with a letter (A-Z or a-z) or an underscore `_`\n- May contain letters, digits (0-9), and underscores `_`\n- Are case-insensitive\n- Cannot match a reserved keyword unless quoted\n\n**Examples:**\n- Valid: `identifier1`, `_temp`, `user_name`\n- Invalid: `123abc`, `select`, `identifier-name`\n\n### Quoted Identifiers\nSQLite supports delimited identifiers, which allow almost any character, as long as the identifier is properly quoted.\n\nYou can use:\n- Double quotes: `\"identifier name\"`\n- Square brackets (Microsoft-style): `[identifier name]`\n- Backticks (MySQL-style): `` `identifier name` ``\n\nThese quoting styles are interchangeable in SQLite. Inside a quoted identifier, you can include:\n- Spaces: `\"my column\"`\n- Special characters: `\"name@domain\"`, `\"price€\"`, `\"weird!name\"`\n- Reserved SQL keywords: `\"select\"`, `\"group\"`\n\nQuoted identifiers are case-sensitive.\n\n## Building from Source\n\nSee the included Makefile for building instructions:\n\n```bash\n# Build for your current platform\nmake\n\n# Build for a specific platform\nmake PLATFORM=macos\nmake PLATFORM=linux\nmake PLATFORM=windows\n\n# Install\nmake install\n```\n\n## 📦 Integrations\n\nUse SQLite-AI alongside:\n\n* **[SQLite-AI](https://github.com/sqliteai/sqlite-ai)** – on-device inference, embedding generation, and model interaction directly into your database\n* **[SQLite-Vector](https://github.com/sqliteai/sqlite-vector)** – vector search from SQL\n* **[SQLite-Sync](https://github.com/sqliteai/sqlite-sync)** – sync on-device databases with the cloud\n\n## License\n\nThis project is licensed under the [Elastic License 2.0](./LICENSE.md). You can use, copy, modify, and distribute it under the terms of the license for non-production use. For production or managed service use, please [contact SQLite Cloud, Inc](mailto:info@sqlitecloud.io) for a commercial license.\n","funding_links":[],"categories":["C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqliteai%2Fsqlite-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsqliteai%2Fsqlite-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqliteai%2Fsqlite-js/lists"}