Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ jobs:
'mysql:8.0.23',
'mariadb:11.4',
'postgres:16.3',
'sqlite:3',
]
steps:
- uses: actions/checkout@master
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# [0.101.0](https://github.com/MrSwitch/dare/compare/v0.100.2...v0.101.0) (2026-06-14)


### Features

* **sqlite:** initial engine support ([#457](https://github.com/MrSwitch/dare/issues/457)) ([1344fb2](https://github.com/MrSwitch/dare/commit/1344fb2266d3b7cd6add8a3fbe8db7d434a36a84))

## [0.100.2](https://github.com/MrSwitch/dare/compare/v0.100.1...v0.100.2) (2026-06-14)


Expand Down
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ npm i dare --save

## Setup

Import the appropriate entry point for your database engine. The versions listed are minimum supported versions Dare has been tested against - more recent versions are expected to be backwards compatible.
Import the appropriate entry point for your database engine. The versions listed are minimum supported versions Dare has been tested against - more recent database versions are expected to be backwards compatible with the versions listed below.

| Import Path | Database Engine |
| ----------------- | ----------------------------- |
| `dare` | MySQL 8.0+, MariaDB |
| `dare/mariadb11` | MariaDB 11+ (alias of `dare`) |
| `dare/mysql80` | MySQL 8.0+ (alias of `dare`) |
| `dare/mysql57` | MySQL 5.7+, MySQL 5.6+ |
| `dare/postgres16` | PostgreSQL 16+ |
| Database Engine | Import Path |
| ----------------------------- | ----------------- |
| MySQL 8.0+, MariaDB | `dare` |
| MariaDB 11+ (alias of `dare`) | `dare/mariadb11` |
| MySQL 8.0+ (alias of `dare`) | `dare/mysql80` |
| MySQL 5.7+, MySQL 5.6+ | `dare/mysql57` |
| PostgreSQL 16+ | `dare/postgres16` |
| SQLite 3+ | `dare/sqlite3` |

## Example

Expand Down Expand Up @@ -69,6 +70,7 @@ The integration tests illustrates how a [setup of a dare instance](`./test/integ

- **MySQL** (5.6, 5.7, 8.0,...) and **MariaDB** (11) See [connection with `mysql2`](./test/integration/helpers/MySQL.js)
- **Postgres** (16+) See [connection with `pg`](./test/integration/helpers/Postgres.js)
- **SQLite** (3+) See [connection with `node:sqlite`](./test/integration/helpers/Sqlite.js)

# Methods

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dare",
"version": "0.100.2",
"version": "0.101.0",
"description": "Database to REST, REST to Database",
"type": "module",
"main": "./src/index.js",
Expand All @@ -25,6 +25,10 @@
"import": "./src/postgres16.js",
"types": "./types/src/index.d.ts"
},
"./sqlite3": {
"import": "./src/sqlite.js",
"types": "./types/src/index.d.ts"
},
"./utils/*": {
"import": "./src/utils/*.js",
"types": "./types/src/utils/*.d.ts"
Expand All @@ -40,6 +44,7 @@
"test": "npm run lint && npm run spec && ((c8 report --reporter=text-lcov | coveralls) || exit 0)",
"test:ci": "npm run lint && c8 node --test test/specs/**/*.spec.js && (c8 report --reporter=text-lcov | coveralls)",
"test:integration": "bash ./test/integration/run.sh",
"test:integration:sqlite": "DB_ENGINE=sqlite:3 bash ./test/integration/run.sh",
"spec": "c8 node --test 'test/specs/**/*.spec.js'",
"lint": "eslint ./ && npx prettier --check . && npm run check-types",
"prettier": "prettier --write --ignore-unknown .",
Expand Down
11 changes: 10 additions & 1 deletion src/format/reducer_conditions.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import unwrap_field from '../utils/unwrap_field.js';
* @param {object} options - Options object
* @param {Function} options.extract - Extract (key, value) related to nested model
* @param {string} options.sql_alias - Table SQL Alias, e.g. 'a', 'b', etc..
* @param {string} [options.sql_table] - Table name, e.g. 'users'
* @param {object} options.table_schema - Table schema
* @param {string|null} options.conditional_operators_in_value - Allowable conditional operators in value
* @param {Dare} options.dareInstance - Dare Instance
Expand All @@ -24,6 +25,7 @@ export default function reduceConditions(
{
extract,
sql_alias,
sql_table,
table_schema,
conditional_operators_in_value,
dareInstance,
Expand Down Expand Up @@ -67,6 +69,7 @@ export default function reduceConditions(
field: key,
value,
sql_alias,
sql_table,
table_schema,
operators,
conditional_operators_in_value,
Expand Down Expand Up @@ -107,6 +110,7 @@ function stripKey(key) {
* @param {string} params.field - Field name
* @param {string} params.value - Field value
* @param {string} params.sql_alias - SQL Alias
* @param {string} params.sql_table - Table name
* @param {object} params.table_schema - Table schema
* @param {string|null} params.operators - Allowable operators
* @param {string|null} params.conditional_operators_in_value - Allowable conditional operators in value
Expand All @@ -117,6 +121,7 @@ function prepCondition({
field,
value,
sql_alias,
sql_table,
table_schema,
operators = '',
conditional_operators_in_value,
Expand All @@ -142,7 +147,10 @@ function prepCondition({
// Join the fields
const sql_field_array = sql_fields.map(({sql}) => sql);

return dareInstance.fulltextSearch(sql_field_array, value, NOT);
return dareInstance.fulltextSearch(sql_field_array, value, NOT, {
sql_alias,
sql_table,
});
} else if (sql_fields.length > 1) {
/*
* Is the field an array of field names?
Expand All @@ -157,6 +165,7 @@ function prepCondition({
field,
value,
sql_alias,
sql_table,
table_schema,
operators: operators.replace('-', ''),
conditional_operators_in_value,
Expand Down
8 changes: 8 additions & 0 deletions src/format_request.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ async function format_request(options, dareInstance) {
*/
if (options.method === 'del' && !options.parent) {
options.sql_alias = options.sql_table;
} else if (
options.method === 'patch' &&
!options.parent &&
!dareInstance.applyAliasesOnUpdate
) {
options.sql_alias = options.sql_table;
} else {
/** EOF Hack */
options.sql_alias = dareInstance.get_unique_alias();
Expand Down Expand Up @@ -226,6 +232,7 @@ async function format_request(options, dareInstance) {
const arr = reduceConditions(options.filter, {
extract,
sql_alias,
sql_table: options.sql_table,
table_schema,
conditional_operators_in_value,
dareInstance,
Expand Down Expand Up @@ -289,6 +296,7 @@ async function format_request(options, dareInstance) {
const arrJoins = reduceConditions(options.join, {
extract,
sql_alias,
sql_table: options.sql_table,
table_schema,
conditional_operators_in_value,
dareInstance,
Expand Down
23 changes: 19 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import response_handler, {responseRowHandler} from './response_handler.js';
/**
* @import {Sql} from 'sql-template-tag'
*
* @typedef {`${'mysql' | 'postgres' | 'mariadb'}:${number}.${number}${string?}`} Engine
* @typedef {`${'mysql' | 'postgres' | 'mariadb' | 'sqlite'}:${number}.${number}${string?}` | `sqlite:${number}`} Engine
*
* @typedef {Pick<InternalProps, 'alias' | 'parent' | 'name' | 'skip'>} ModalHandlerExtraProps
*
Expand Down Expand Up @@ -253,6 +253,12 @@ Dare.prototype.jsonFormatValue = function jsonFormatValue(
/** @type {string} */
Dare.prototype.rowid = '_rowid';

/**
* Default value to use in INSERT statements when a column value is missing
* MySQL/MariaDB support the DEFAULT keyword, SQLite does not
*/
Dare.prototype.sql_default_value = raw('DEFAULT');

// Set the Max Limit for SELECT statements
/** @type {number} */
Dare.prototype.MAX_LIMIT = null;
Expand Down Expand Up @@ -289,6 +295,12 @@ Dare.prototype.applySubqueryOnDML = false;
*/
Dare.prototype.applyAliasesOnUpdate = true;

/**
* Apply table alias on UPDATE statement - SQLite doesn't support UPDATE tbl alias SET ...
* @type {boolean}
*/
Dare.prototype.applyTableAliasOnUpdate = true;

/**
* SQL insert suffix - Additional SQL to append to insert statements, e.g., RETURNING clause for Postgres
* @type {string | undefined}
Expand Down Expand Up @@ -351,12 +363,15 @@ Dare.prototype.getFieldKey = function getFieldKey(field, schema) {
* @param {Sql[]} sql_field_array - Array of SQL fields to apply the fulltext search to
* @param {string} value - Fulltext search string
* @param {Sql} [NOT] - Whether to negate the fulltext search
* @param {object} [context] - Additional context (sql_alias, sql_table)
* @returns {Sql} SQL condition for the fulltext search
*/
Dare.prototype.fulltextSearch = function fulltextSearch(
sql_field_array,
value,
NOT
NOT,
// eslint-disable-next-line no-unused-vars
context
) {
return SQL`${NOT}MATCH(${join(sql_field_array, ', ')}) AGAINST(${this.fulltextParser(value)} IN BOOLEAN MODE)`;
};
Expand Down Expand Up @@ -775,7 +790,7 @@ Dare.prototype.patch = async function patch(table, filter, body, options = {}) {

// Construct a db update
const sql = SQL`
UPDATE ${raw(exec)}${raw(req.sql_table)} ${raw(req.sql_alias)}
UPDATE ${raw(exec)}${raw(req.sql_table)} ${dareInstance.applyAliasesOnUpdate ? raw(req.sql_alias) : empty}
${req.sql_joins.length ? join(req.sql_joins, '\n') : empty}
SET ${sql_set}
WHERE
Expand Down Expand Up @@ -980,7 +995,7 @@ Dare.prototype.post = async function post(table, body, options = {}) {
const a = fields.map((_, index) => {
// If any of the values are missing, set them as DEFAULT
if (_data[index] === undefined) {
return raw('DEFAULT');
return dareInstance.sql_default_value;
}

// Return the prepared statement placeholder
Expand Down
Loading
Loading