foxhound 2.0.13 → 2.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -44
- package/docs/.nojekyll +1 -0
- package/docs/README.md +63 -0
- package/docs/_sidebar.md +34 -0
- package/docs/architecture.md +104 -0
- package/docs/configuration.md +217 -0
- package/docs/cover.md +11 -0
- package/docs/dialects/README.md +61 -0
- package/docs/dialects/alasql.md +84 -0
- package/docs/dialects/mssql.md +95 -0
- package/docs/dialects/mysql.md +99 -0
- package/docs/dialects/sqlite.md +82 -0
- package/docs/filters.md +171 -0
- package/docs/index.html +39 -0
- package/docs/joins.md +101 -0
- package/docs/pagination.md +82 -0
- package/docs/query/README.md +115 -0
- package/docs/query/count.md +81 -0
- package/docs/query/create.md +66 -0
- package/docs/query/delete.md +82 -0
- package/docs/query/read.md +138 -0
- package/docs/query/update.md +56 -0
- package/docs/query-overrides.md +88 -0
- package/docs/schema.md +93 -0
- package/docs/sorting.md +80 -0
- package/package.json +3 -3
- package/source/dialects/SQLite/FoxHound-Dialect-SQLite.js +1 -1
- package/test/FoxHound-Dialect-SQLite_tests.js +4 -4
- package/test/Foxhound-Dialect-MSSQL_tests.js +1 -1
package/README.md
CHANGED
|
@@ -1,65 +1,143 @@
|
|
|
1
1
|
# FoxHound
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
3
|
+
> A fluent query generation DSL for Node.js and the browser
|
|
4
|
+
|
|
5
|
+
FoxHound is a database query builder that generates dialect-specific SQL from a single chainable API. It keeps your application code database-agnostic while producing safe, parameterized queries for MySQL, Microsoft SQL Server, SQLite, and ALASQL.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Chainable API** — every configuration method returns the query object for fluent composition
|
|
10
|
+
- **Multiple Dialects** — generate SQL for MySQL, MSSQL, SQLite, ALASQL, or plain English from the same code
|
|
11
|
+
- **Parameterized Queries** — user-supplied values are always bound as named parameters, preventing SQL injection
|
|
12
|
+
- **Schema-Aware** — automatic management of identity columns, timestamps, user stamps, and soft-delete tracking
|
|
13
|
+
- **Full CRUD + Count** — build CREATE, READ, UPDATE, DELETE, UNDELETE, and COUNT queries
|
|
14
|
+
- **Query Overrides** — underscore-style templates for custom SQL while retaining automatic parameter binding
|
|
15
|
+
- **Filtering & Sorting** — rich filter expressions with multiple operators, logical grouping, and multi-column sorting
|
|
16
|
+
- **Joins & Pagination** — INNER, LEFT, and custom joins plus dialect-aware LIMIT/OFFSET pagination
|
|
17
|
+
- **Fable Integration** — operates as a Fable service, inheriting configuration, logging, and UUID generation
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const libFable = require('fable');
|
|
23
|
+
const libFoxHound = require('foxhound');
|
|
24
|
+
|
|
25
|
+
const _Fable = new libFable({});
|
|
26
|
+
const tmpQuery = libFoxHound.new(_Fable);
|
|
27
|
+
|
|
28
|
+
tmpQuery
|
|
29
|
+
.setScope('Books')
|
|
30
|
+
.setDataElements(['Title', 'Author', 'PublishedYear'])
|
|
31
|
+
.addFilter('Genre', 'Science Fiction')
|
|
32
|
+
.addSort({Column: 'PublishedYear', Direction: 'Descending'})
|
|
33
|
+
.setCap(25)
|
|
34
|
+
.setDialect('MySQL')
|
|
35
|
+
.buildReadQuery();
|
|
36
|
+
|
|
37
|
+
console.log(tmpQuery.query.body);
|
|
38
|
+
// => SELECT `Title`, `Author`, `PublishedYear` FROM `Books`
|
|
39
|
+
// WHERE `Books`.`Genre` = :Genre_w0 ORDER BY PublishedYear DESC LIMIT 25;
|
|
40
|
+
|
|
41
|
+
console.log(tmpQuery.query.parameters);
|
|
42
|
+
// => { Genre_w0: 'Science Fiction' }
|
|
43
|
+
```
|
|
29
44
|
|
|
30
|
-
|
|
45
|
+
## Installation
|
|
31
46
|
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
```bash
|
|
48
|
+
npm install foxhound
|
|
49
|
+
```
|
|
34
50
|
|
|
35
|
-
|
|
51
|
+
## How It Works
|
|
36
52
|
|
|
53
|
+
FoxHound follows a configure-then-build pattern. You create a query instance, chain configuration methods to set the table, columns, filters, sorts, and dialect, then call a build method to generate the SQL.
|
|
37
54
|
|
|
38
|
-
1. Run this command to build this image:
|
|
39
55
|
```
|
|
40
|
-
|
|
56
|
+
Application Code
|
|
57
|
+
└── FoxHound Query
|
|
58
|
+
├── setScope('Books') → target table
|
|
59
|
+
├── addFilter('Genre', '...') → WHERE clause
|
|
60
|
+
├── addSort('Title') → ORDER BY clause
|
|
61
|
+
├── setCap(25) → LIMIT clause
|
|
62
|
+
├── setDialect('MySQL') → output format
|
|
63
|
+
└── buildReadQuery() → SQL generation
|
|
64
|
+
├── query.body → SQL string
|
|
65
|
+
└── query.parameters → bound values
|
|
41
66
|
```
|
|
42
67
|
|
|
43
|
-
|
|
68
|
+
## Dialects
|
|
69
|
+
|
|
70
|
+
| Dialect | Target | Identifier Quoting | Parameter Prefix | Pagination |
|
|
71
|
+
|---------|--------|-------------------|-----------------|------------|
|
|
72
|
+
| `MySQL` | MySQL / MariaDB | `` `backticks` `` | `:name` | `LIMIT offset, count` |
|
|
73
|
+
| `MSSQL` | Microsoft SQL Server | `[brackets]` | `@name` | `OFFSET/FETCH` |
|
|
74
|
+
| `SQLite` | SQLite 3 | `` `backticks` `` | `:name` | `LIMIT count OFFSET offset` |
|
|
75
|
+
| `ALASQL` | ALASQL (in-memory) | `` `backticks` `` | `:name` | `LIMIT count FETCH offset` |
|
|
76
|
+
| `English` | Human-readable | none | none | prose |
|
|
77
|
+
| `MeadowEndpoints` | REST URLs | none | none | query string |
|
|
78
|
+
|
|
79
|
+
## Schema Types
|
|
80
|
+
|
|
81
|
+
When a schema is attached, FoxHound automatically manages special columns:
|
|
82
|
+
|
|
83
|
+
| Type | Description |
|
|
84
|
+
|------|-------------|
|
|
85
|
+
| `AutoIdentity` | Auto-increment primary key — `NULL` on insert, skipped on update |
|
|
86
|
+
| `AutoGUID` | Automatically generated UUID on insert |
|
|
87
|
+
| `CreateDate` / `CreateIDUser` | Auto-populated on insert only |
|
|
88
|
+
| `UpdateDate` / `UpdateIDUser` | Auto-populated on insert and update |
|
|
89
|
+
| `DeleteDate` / `DeleteIDUser` | Auto-populated on soft delete |
|
|
90
|
+
| `Deleted` | Soft-delete flag — auto-filtered in reads |
|
|
91
|
+
|
|
92
|
+
## Filter Operators
|
|
93
|
+
|
|
94
|
+
| Operator | SQL | Description |
|
|
95
|
+
|----------|-----|-------------|
|
|
96
|
+
| `=` | `=` | Equals (default) |
|
|
97
|
+
| `!=` | `!=` | Not equals |
|
|
98
|
+
| `>`, `>=`, `<`, `<=` | `>`, `>=`, `<`, `<=` | Comparison |
|
|
99
|
+
| `LIKE` | `LIKE` | Pattern match |
|
|
100
|
+
| `IN`, `NOT IN` | `IN (...)`, `NOT IN (...)` | Set membership |
|
|
101
|
+
| `IS NULL`, `IS NOT NULL` | `IS NULL`, `IS NOT NULL` | Null checks |
|
|
102
|
+
| `(`, `)` | `(`, `)` | Logical grouping |
|
|
103
|
+
|
|
104
|
+
## Testing
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm test
|
|
108
|
+
npm run coverage
|
|
109
|
+
```
|
|
44
110
|
|
|
111
|
+
## Docker Development Environment
|
|
45
112
|
|
|
46
|
-
|
|
47
|
-
npm run docker-dev-build-image
|
|
48
|
-
```
|
|
113
|
+
1. Build the image:
|
|
49
114
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
docker run -it --name foxhound-dev -p 127.0.0.1:12346:8080 -v "$PWD/.config:/home/coder/.config" -v "$PWD:/home/coder/foxhound" -u "$(id -u):$(id -g)" -e "DOCKER_USER=$USER" retold/foxhound:local
|
|
115
|
+
```bash
|
|
116
|
+
npm run docker-dev-build
|
|
53
117
|
```
|
|
54
118
|
|
|
55
|
-
|
|
119
|
+
2. Run the container:
|
|
56
120
|
|
|
57
|
-
```
|
|
121
|
+
```bash
|
|
58
122
|
npm run docker-dev-run
|
|
59
123
|
```
|
|
60
124
|
|
|
61
|
-
3.
|
|
125
|
+
3. Open http://localhost:24238/ — the password is "retold"
|
|
126
|
+
|
|
127
|
+
## Documentation
|
|
128
|
+
|
|
129
|
+
Detailed documentation is available in the `docs/` folder and can be served locally:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npx docsify-cli serve docs
|
|
133
|
+
```
|
|
62
134
|
|
|
63
|
-
|
|
135
|
+
## Related Packages
|
|
64
136
|
|
|
65
|
-
|
|
137
|
+
- [fable](https://github.com/stevenvelozo/fable) — Core service framework (required dependency)
|
|
138
|
+
- [meadow](https://github.com/stevenvelozo/meadow) — Data access layer that uses FoxHound for query generation
|
|
139
|
+
- [stricture](https://github.com/stevenvelozo/stricture) — Schema definition tool that produces FoxHound-compatible schema arrays
|
|
140
|
+
- [meadow-endpoints](https://github.com/stevenvelozo/meadow-endpoints) — REST endpoint generator built on Meadow + FoxHound
|
|
141
|
+
- [meadow-connection-mysql](https://github.com/stevenvelozo/meadow-connection-mysql) — MySQL connection provider
|
|
142
|
+
- [meadow-connection-mssql](https://github.com/stevenvelozo/meadow-connection-mssql) — MSSQL connection provider
|
|
143
|
+
- [meadow-connection-sqlite](https://github.com/stevenvelozo/meadow-connection-sqlite) — SQLite connection provider
|
package/docs/.nojekyll
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# FoxHound
|
|
2
|
+
|
|
3
|
+
FoxHound is a fluent query generation DSL for Node.js and the browser. It produces dialect-specific SQL (or other query formats) from a single chainable API, keeping your application code database-agnostic while generating safe, parameterized queries.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Chainable API** — every configuration method returns the query object, so you can compose queries in a single expression
|
|
8
|
+
- **Multiple Dialects** — generate SQL for MySQL, Microsoft SQL Server, SQLite, ALASQL, or plain English, all from the same code
|
|
9
|
+
- **Parameterized Queries** — user-supplied values are always bound as named parameters, preventing SQL injection
|
|
10
|
+
- **Schema-Aware** — when a schema is provided, FoxHound automatically manages identity columns, timestamps, user stamps, and soft-delete tracking
|
|
11
|
+
- **Full CRUD + Count** — build CREATE, READ, UPDATE, DELETE, UNDELETE, and COUNT queries
|
|
12
|
+
- **Query Overrides** — supply an underscore-style template to customize query generation while still benefiting from automatic parameter binding
|
|
13
|
+
- **Filtering & Sorting** — rich filter expressions with multiple operators, logical grouping, and multi-column sorting
|
|
14
|
+
- **Joins & Pagination** — INNER, LEFT, and custom joins plus dialect-aware LIMIT/OFFSET pagination
|
|
15
|
+
- **Fable Integration** — operates as a Fable service, inheriting configuration, logging, and UUID generation
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
$ npm install foxhound
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
var libFable = require('fable');
|
|
25
|
+
var _Fable = new libFable({});
|
|
26
|
+
|
|
27
|
+
var tmpQuery = _Fable.Utility.waterfall.FoxHound;
|
|
28
|
+
// Or create a new query directly:
|
|
29
|
+
var libFoxHound = require('foxhound');
|
|
30
|
+
var tmpQuery = libFoxHound.new(_Fable);
|
|
31
|
+
|
|
32
|
+
tmpQuery.setScope('Users')
|
|
33
|
+
.setCap(20)
|
|
34
|
+
.setDialect('MySQL')
|
|
35
|
+
.buildReadQuery();
|
|
36
|
+
|
|
37
|
+
console.log(tmpQuery.query.body);
|
|
38
|
+
// => SELECT `Users`.* FROM `Users` LIMIT 20;
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## How It Works
|
|
42
|
+
|
|
43
|
+
1. **Create a Query** — instantiate via `foxhound.new(fable)` or through a Fable service
|
|
44
|
+
2. **Configure** — chain methods to set scope (table), fields, filters, sorts, joins, and pagination
|
|
45
|
+
3. **Set a Dialect** — call `.setDialect('MySQL')` (or MSSQL, SQLite, ALASQL, English)
|
|
46
|
+
4. **Build** — call a build method such as `.buildReadQuery()` to generate the SQL
|
|
47
|
+
5. **Execute** — read the generated SQL from `.query.body` and bound parameters from `.query.parameters`
|
|
48
|
+
|
|
49
|
+
## Related Packages
|
|
50
|
+
|
|
51
|
+
| Package | Purpose |
|
|
52
|
+
|---------|---------|
|
|
53
|
+
| [fable](https://github.com/stevenvelozo/fable) | Core service framework (required dependency) |
|
|
54
|
+
| [meadow](https://github.com/stevenvelozo/meadow) | Data access layer that uses FoxHound for query generation |
|
|
55
|
+
| [stricture](https://github.com/stevenvelozo/stricture) | Schema definition tool that produces FoxHound-compatible schema arrays |
|
|
56
|
+
| [meadow-endpoints](https://github.com/stevenvelozo/meadow-endpoints) | REST endpoint generator built on Meadow + FoxHound |
|
|
57
|
+
|
|
58
|
+
## Testing
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
$ npm test
|
|
62
|
+
$ npm run coverage
|
|
63
|
+
```
|
package/docs/_sidebar.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
- Getting Started
|
|
2
|
+
|
|
3
|
+
- [Introduction](/)
|
|
4
|
+
- [Architecture](architecture.md)
|
|
5
|
+
|
|
6
|
+
- Query Building
|
|
7
|
+
|
|
8
|
+
- [Query Overview](query/README.md)
|
|
9
|
+
- [Create](query/create.md)
|
|
10
|
+
- [Read](query/read.md)
|
|
11
|
+
- [Update](query/update.md)
|
|
12
|
+
- [Delete](query/delete.md)
|
|
13
|
+
- [Count](query/count.md)
|
|
14
|
+
|
|
15
|
+
- Filtering & Sorting
|
|
16
|
+
|
|
17
|
+
- [Filters](filters.md)
|
|
18
|
+
- [Sorting](sorting.md)
|
|
19
|
+
- [Joins](joins.md)
|
|
20
|
+
- [Pagination](pagination.md)
|
|
21
|
+
|
|
22
|
+
- Dialects
|
|
23
|
+
|
|
24
|
+
- [Dialects Overview](dialects/README.md)
|
|
25
|
+
- [MySQL](dialects/mysql.md)
|
|
26
|
+
- [MSSQL](dialects/mssql.md)
|
|
27
|
+
- [SQLite](dialects/sqlite.md)
|
|
28
|
+
- [ALASQL](dialects/alasql.md)
|
|
29
|
+
|
|
30
|
+
- Advanced
|
|
31
|
+
|
|
32
|
+
- [Schema Integration](schema.md)
|
|
33
|
+
- [Query Overrides](query-overrides.md)
|
|
34
|
+
- [Configuration Reference](configuration.md)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
FoxHound follows a clean separation between query configuration, dialect-specific generation, and result handling.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌─────────────────────────────────────┐
|
|
9
|
+
│ Application Code │
|
|
10
|
+
│ query.setScope('Books') │
|
|
11
|
+
│ .addFilter('Genre','Sci-Fi') │
|
|
12
|
+
│ .setDialect('MySQL') │
|
|
13
|
+
│ .buildReadQuery() │
|
|
14
|
+
└──────────────┬──────────────────────┘
|
|
15
|
+
│
|
|
16
|
+
┌──────────────▼──────────────────────┐
|
|
17
|
+
│ FoxHound Core │
|
|
18
|
+
│ - Parameters object (state) │
|
|
19
|
+
│ - Chainable configuration API │
|
|
20
|
+
│ - Dialect selection & delegation │
|
|
21
|
+
└──────────────┬──────────────────────┘
|
|
22
|
+
│
|
|
23
|
+
┌──────────────▼──────────────────────┐
|
|
24
|
+
│ Dialect Engine │
|
|
25
|
+
│ MySQL │ MSSQL │ SQLite │ ALASQL │
|
|
26
|
+
│ - Generates SQL string │
|
|
27
|
+
│ - Populates named parameters │
|
|
28
|
+
│ - Applies schema-aware logic │
|
|
29
|
+
└──────────────┬──────────────────────┘
|
|
30
|
+
│
|
|
31
|
+
┌──────────────▼──────────────────────┐
|
|
32
|
+
│ Query Output │
|
|
33
|
+
│ query.body → SQL string │
|
|
34
|
+
│ query.parameters → bound values │
|
|
35
|
+
│ query.schema → column metadata │
|
|
36
|
+
└─────────────────────────────────────┘
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Factory Pattern
|
|
40
|
+
|
|
41
|
+
FoxHound uses a factory constructor pattern. The module exports a bare constructor; you create instances by calling `.new()` with a Fable service context:
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
var libFoxHound = require('foxhound');
|
|
45
|
+
var tmpQuery = libFoxHound.new(_Fable);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Every query instance gets its own UUID and independent parameter state, so multiple queries can be built concurrently without interference.
|
|
49
|
+
|
|
50
|
+
## Parameters Object
|
|
51
|
+
|
|
52
|
+
All query state lives in a single `Parameters` object:
|
|
53
|
+
|
|
54
|
+
| Property | Type | Purpose |
|
|
55
|
+
|----------|------|---------|
|
|
56
|
+
| `scope` | String | Table or collection name |
|
|
57
|
+
| `dataElements` | Array | Column/field list |
|
|
58
|
+
| `begin` | Integer | Pagination start offset |
|
|
59
|
+
| `cap` | Integer | Maximum rows to return |
|
|
60
|
+
| `filter` | Array | Filter expression objects |
|
|
61
|
+
| `sort` | Array | Sort expression objects |
|
|
62
|
+
| `join` | Array | Join expression objects |
|
|
63
|
+
| `query` | Object | Generated query body, schema, records, and bound parameters |
|
|
64
|
+
| `queryOverride` | String | Custom query template |
|
|
65
|
+
| `indexHints` | Array | Index hints for the database engine |
|
|
66
|
+
| `userID` | Integer | The acting user (for audit stamps) |
|
|
67
|
+
| `result` | Object | Execution results (value, error, executed flag) |
|
|
68
|
+
|
|
69
|
+
## Dialect Strategy
|
|
70
|
+
|
|
71
|
+
Each dialect is a module that exports a factory function accepting a Fable instance. The returned object exposes six methods that each accept a Parameters object and return a SQL string:
|
|
72
|
+
|
|
73
|
+
- `Create(pParameters)` — INSERT statement
|
|
74
|
+
- `Read(pParameters)` — SELECT statement
|
|
75
|
+
- `Update(pParameters)` — UPDATE statement
|
|
76
|
+
- `Delete(pParameters)` — UPDATE (soft) or DELETE (hard)
|
|
77
|
+
- `Undelete(pParameters)` — UPDATE to restore soft-deleted rows
|
|
78
|
+
- `Count(pParameters)` — SELECT COUNT statement
|
|
79
|
+
|
|
80
|
+
The dialect handles all syntax differences: quoting identifiers, parameter prefixes, pagination syntax, date functions, and identity column handling.
|
|
81
|
+
|
|
82
|
+
## Chainable API
|
|
83
|
+
|
|
84
|
+
Every setter method returns `this`, enabling fluent composition:
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
tmpQuery
|
|
88
|
+
.setScope('Orders')
|
|
89
|
+
.setDataElements(['OrderID', 'Total', 'Status'])
|
|
90
|
+
.addFilter('Status', 'Pending')
|
|
91
|
+
.addSort({Column: 'Total', Direction: 'Descending'})
|
|
92
|
+
.setCap(50)
|
|
93
|
+
.setDialect('MySQL')
|
|
94
|
+
.buildReadQuery();
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Fable Integration
|
|
98
|
+
|
|
99
|
+
FoxHound depends on Fable for:
|
|
100
|
+
|
|
101
|
+
- **UUID Generation** — each query and record gets a unique identifier via `_Fable.getUUID()`
|
|
102
|
+
- **Logging** — filter, scope, and query errors are logged through `_Fable.log`
|
|
103
|
+
- **Utility Functions** — `_Fable.Utility.extend()` for parameter merging and `_Fable.Utility.template()` for query overrides
|
|
104
|
+
- **Configuration** — inherits any relevant settings from the Fable config
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Configuration Reference
|
|
2
|
+
|
|
3
|
+
This page documents all FoxHound configuration methods, properties, and their accepted values.
|
|
4
|
+
|
|
5
|
+
## Query Configuration Methods
|
|
6
|
+
|
|
7
|
+
All setter methods return `this` for chaining.
|
|
8
|
+
|
|
9
|
+
### setScope(pScope)
|
|
10
|
+
|
|
11
|
+
Set the primary table or collection for the query.
|
|
12
|
+
|
|
13
|
+
| Parameter | Type | Description |
|
|
14
|
+
|-----------|------|-------------|
|
|
15
|
+
| `pScope` | String | Table name |
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
tmpQuery.setScope('Books');
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### setDialect(pDialectName)
|
|
22
|
+
|
|
23
|
+
Set the SQL dialect for query generation.
|
|
24
|
+
|
|
25
|
+
| Parameter | Type | Values |
|
|
26
|
+
|-----------|------|--------|
|
|
27
|
+
| `pDialectName` | String | `'MySQL'`, `'MSSQL'`, `'SQLite'`, `'ALASQL'`, `'English'`, `'MeadowEndpoints'` |
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
tmpQuery.setDialect('MySQL');
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### setDataElements(pDataElements)
|
|
34
|
+
|
|
35
|
+
Set the columns to select. Pass `false` or omit to select all columns (`*`).
|
|
36
|
+
|
|
37
|
+
| Parameter | Type | Description |
|
|
38
|
+
|-----------|------|-------------|
|
|
39
|
+
| `pDataElements` | Array or String | Column name(s) |
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
tmpQuery.setDataElements(['Title', 'Author']);
|
|
43
|
+
tmpQuery.setDataElements('Title'); // Wraps in array automatically
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### setDistinct(pDistinct)
|
|
47
|
+
|
|
48
|
+
Enable or disable DISTINCT results.
|
|
49
|
+
|
|
50
|
+
| Parameter | Type | Description |
|
|
51
|
+
|-----------|------|-------------|
|
|
52
|
+
| `pDistinct` | Boolean | `true` to enable DISTINCT |
|
|
53
|
+
|
|
54
|
+
### setBegin(pBeginAmount)
|
|
55
|
+
|
|
56
|
+
Set the pagination starting offset.
|
|
57
|
+
|
|
58
|
+
| Parameter | Type | Description |
|
|
59
|
+
|-----------|------|-------------|
|
|
60
|
+
| `pBeginAmount` | Integer ≥ 0 | Zero-based row offset |
|
|
61
|
+
|
|
62
|
+
### setCap(pCapAmount)
|
|
63
|
+
|
|
64
|
+
Set the maximum number of rows to return.
|
|
65
|
+
|
|
66
|
+
| Parameter | Type | Description |
|
|
67
|
+
|-----------|------|-------------|
|
|
68
|
+
| `pCapAmount` | Integer ≥ 0 | Maximum row count |
|
|
69
|
+
|
|
70
|
+
### addFilter(pColumn, pValue, pOperator, pConnector, pParameter)
|
|
71
|
+
|
|
72
|
+
Add a filter expression.
|
|
73
|
+
|
|
74
|
+
| Parameter | Default | Description |
|
|
75
|
+
|-----------|---------|-------------|
|
|
76
|
+
| `pColumn` | *(required)* | Column name |
|
|
77
|
+
| `pValue` | *(required)* | Comparison value |
|
|
78
|
+
| `pOperator` | `'='` | Operator (`=`, `!=`, `>`, `>=`, `<`, `<=`, `LIKE`, `IN`, `NOT IN`, `IS NULL`, `IS NOT NULL`, `(`, `)`) |
|
|
79
|
+
| `pConnector` | `'AND'` | Logical connector (`AND`, `OR`, `NONE`) |
|
|
80
|
+
| `pParameter` | `pColumn` | Parameter name |
|
|
81
|
+
|
|
82
|
+
### setFilter(pFilter)
|
|
83
|
+
|
|
84
|
+
Replace the entire filter array.
|
|
85
|
+
|
|
86
|
+
| Parameter | Type | Description |
|
|
87
|
+
|-----------|------|-------------|
|
|
88
|
+
| `pFilter` | Array or Object | Filter expression(s) |
|
|
89
|
+
|
|
90
|
+
### addSort(pSort)
|
|
91
|
+
|
|
92
|
+
Add a sort expression.
|
|
93
|
+
|
|
94
|
+
| Parameter | Type | Description |
|
|
95
|
+
|-----------|------|-------------|
|
|
96
|
+
| `pSort` | String or Object | Column name or `{Column, Direction}` |
|
|
97
|
+
|
|
98
|
+
### setSort(pSort)
|
|
99
|
+
|
|
100
|
+
Replace the entire sort array.
|
|
101
|
+
|
|
102
|
+
| Parameter | Type | Description |
|
|
103
|
+
|-----------|------|-------------|
|
|
104
|
+
| `pSort` | String, Object, or Array | Sort expression(s) |
|
|
105
|
+
|
|
106
|
+
### addJoin(pTable, pFrom, pTo, pType)
|
|
107
|
+
|
|
108
|
+
Add a join expression.
|
|
109
|
+
|
|
110
|
+
| Parameter | Default | Description |
|
|
111
|
+
|-----------|---------|-------------|
|
|
112
|
+
| `pTable` | *(required)* | Table to join |
|
|
113
|
+
| `pFrom` | *(required)* | Column on join table |
|
|
114
|
+
| `pTo` | *(required)* | Column on base table |
|
|
115
|
+
| `pType` | `'INNER JOIN'` | Join type |
|
|
116
|
+
|
|
117
|
+
### setJoin(pJoin)
|
|
118
|
+
|
|
119
|
+
Replace the entire join array.
|
|
120
|
+
|
|
121
|
+
| Parameter | Type | Description |
|
|
122
|
+
|-----------|------|-------------|
|
|
123
|
+
| `pJoin` | Object or Array | Join expression(s) |
|
|
124
|
+
|
|
125
|
+
### addRecord(pRecord)
|
|
126
|
+
|
|
127
|
+
Add a record for CREATE or UPDATE operations.
|
|
128
|
+
|
|
129
|
+
| Parameter | Type | Description |
|
|
130
|
+
|-----------|------|-------------|
|
|
131
|
+
| `pRecord` | Object | Key-value pairs of column names and values |
|
|
132
|
+
|
|
133
|
+
### setIDUser(pIDUser)
|
|
134
|
+
|
|
135
|
+
Set the user ID for audit stamp columns.
|
|
136
|
+
|
|
137
|
+
| Parameter | Type | Description |
|
|
138
|
+
|-----------|------|-------------|
|
|
139
|
+
| `pIDUser` | Integer ≥ 0 | User ID |
|
|
140
|
+
|
|
141
|
+
### setDisableAutoIdentity(pFlag)
|
|
142
|
+
|
|
143
|
+
Disable automatic identity column handling.
|
|
144
|
+
|
|
145
|
+
### setDisableAutoDateStamp(pFlag)
|
|
146
|
+
|
|
147
|
+
Disable automatic timestamp generation.
|
|
148
|
+
|
|
149
|
+
### setDisableAutoUserStamp(pFlag)
|
|
150
|
+
|
|
151
|
+
Disable automatic user ID stamping.
|
|
152
|
+
|
|
153
|
+
### setDisableDeleteTracking(pFlag)
|
|
154
|
+
|
|
155
|
+
Disable soft-delete behavior.
|
|
156
|
+
|
|
157
|
+
### setLogLevel(pLogLevel)
|
|
158
|
+
|
|
159
|
+
Set the query logging verbosity.
|
|
160
|
+
|
|
161
|
+
| Level | Behavior |
|
|
162
|
+
|-------|----------|
|
|
163
|
+
| `0` | No logging (default) |
|
|
164
|
+
| `1` | Log generated queries |
|
|
165
|
+
| `2` | Log queries and non-parameterized versions |
|
|
166
|
+
| `3` | Log everything |
|
|
167
|
+
|
|
168
|
+
## Properties
|
|
169
|
+
|
|
170
|
+
| Property | Type | Access | Description |
|
|
171
|
+
|----------|------|--------|-------------|
|
|
172
|
+
| `query` | Object | get/set | The generated query (`body`, `schema`, `records`, `parameters`) |
|
|
173
|
+
| `result` | Object | get/set | Execution results (`executed`, `value`, `error`) |
|
|
174
|
+
| `parameters` | Object | get/set | Full parameters state |
|
|
175
|
+
| `dialect` | Object | get | Current dialect object |
|
|
176
|
+
| `uuid` | String | get | Unique identifier for this query |
|
|
177
|
+
| `logLevel` | Integer | get | Current log level |
|
|
178
|
+
| `indexHints` | Array | get/set | Index hints for the database engine |
|
|
179
|
+
|
|
180
|
+
## Utility Methods
|
|
181
|
+
|
|
182
|
+
### clone()
|
|
183
|
+
|
|
184
|
+
Create a new FoxHound query with the same scope, begin, cap, schema, dataElements, sorts, and filters.
|
|
185
|
+
|
|
186
|
+
```javascript
|
|
187
|
+
var tmpClone = tmpQuery.clone();
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### resetParameters()
|
|
191
|
+
|
|
192
|
+
Reset the query to its default state.
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
tmpQuery.resetParameters();
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### mergeParameters(pFromParameters)
|
|
199
|
+
|
|
200
|
+
Merge an object of parameters into the current state.
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
tmpQuery.mergeParameters({cap: 50, begin: 0});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Build Methods
|
|
207
|
+
|
|
208
|
+
| Method | Generates |
|
|
209
|
+
|--------|-----------|
|
|
210
|
+
| `buildCreateQuery()` | INSERT statement |
|
|
211
|
+
| `buildReadQuery()` | SELECT statement |
|
|
212
|
+
| `buildUpdateQuery()` | UPDATE statement |
|
|
213
|
+
| `buildDeleteQuery()` | DELETE or soft-delete UPDATE |
|
|
214
|
+
| `buildUndeleteQuery()` | Restore soft-deleted rows |
|
|
215
|
+
| `buildCountQuery()` | SELECT COUNT statement |
|
|
216
|
+
|
|
217
|
+
All build methods return `this` for chaining. The generated SQL is available at `query.body` and bound parameters at `query.parameters`.
|
package/docs/cover.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# FoxHound <small>2</small>
|
|
2
|
+
|
|
3
|
+
> A fluent query generation DSL for Node.js and the browser
|
|
4
|
+
|
|
5
|
+
- Chainable API that generates dialect-specific SQL
|
|
6
|
+
- Parameterized queries for safe, injection-free operation
|
|
7
|
+
- Schema-aware with automatic identity, timestamp, and soft-delete management
|
|
8
|
+
- Multiple dialects: MySQL, MSSQL, SQLite, ALASQL, and more
|
|
9
|
+
|
|
10
|
+
[GitHub](https://github.com/stevenvelozo/foxhound)
|
|
11
|
+
[Get Started](#foxhound)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Dialects Overview
|
|
2
|
+
|
|
3
|
+
FoxHound uses a dialect strategy pattern to generate database-specific SQL from the same query configuration. Each dialect is a self-contained module that translates FoxHound's internal parameters into the target SQL syntax.
|
|
4
|
+
|
|
5
|
+
## Available Dialects
|
|
6
|
+
|
|
7
|
+
| Dialect | Target | Identifier Quoting | Parameter Prefix | Pagination |
|
|
8
|
+
|---------|--------|-------------------|-----------------|------------|
|
|
9
|
+
| [MySQL](dialects/mysql.md) | MySQL / MariaDB | `` `backticks` `` | `:name` | `LIMIT offset, count` |
|
|
10
|
+
| [MSSQL](dialects/mssql.md) | Microsoft SQL Server | `[brackets]` | `@name` | `OFFSET n ROWS FETCH NEXT m ROWS ONLY` |
|
|
11
|
+
| [SQLite](dialects/sqlite.md) | SQLite 3 | `` `backticks` `` | `:name` | `LIMIT count OFFSET offset` |
|
|
12
|
+
| [ALASQL](dialects/alasql.md) | ALASQL (in-memory) | `` `backticks` `` | `:name` | `LIMIT count FETCH offset` |
|
|
13
|
+
| English | Human-readable | none | none | prose |
|
|
14
|
+
| MeadowEndpoints | REST URL generation | none | none | query string |
|
|
15
|
+
|
|
16
|
+
## Setting a Dialect
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
tmpQuery.setDialect('MySQL');
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If no dialect is set before building a query, FoxHound defaults to `English`.
|
|
23
|
+
|
|
24
|
+
If an invalid dialect name is passed, FoxHound logs an error and falls back to `English`.
|
|
25
|
+
|
|
26
|
+
## Dialect Interface
|
|
27
|
+
|
|
28
|
+
Every dialect exports a factory function that accepts a Fable instance and returns an object with six methods:
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
{
|
|
32
|
+
Create: function(pParameters) { ... },
|
|
33
|
+
Read: function(pParameters) { ... },
|
|
34
|
+
Update: function(pParameters) { ... },
|
|
35
|
+
Delete: function(pParameters) { ... },
|
|
36
|
+
Undelete: function(pParameters) { ... },
|
|
37
|
+
Count: function(pParameters) { ... }
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Each method receives the full Parameters object and returns a SQL string (or `false` if the query cannot be generated).
|
|
42
|
+
|
|
43
|
+
## Common Behaviors
|
|
44
|
+
|
|
45
|
+
All SQL dialects share these behaviors:
|
|
46
|
+
|
|
47
|
+
- **Parameterized values** — user data is always bound as named parameters, never interpolated
|
|
48
|
+
- **Schema-aware column management** — AutoIdentity, timestamps, user stamps, and soft-delete columns are handled automatically based on schema type annotations
|
|
49
|
+
- **Soft-delete filtering** — Read and Count queries automatically exclude rows where the `Deleted` column is `1` (when schema is present)
|
|
50
|
+
- **Query overrides** — Read and Count queries support underscore templates for custom SQL generation
|
|
51
|
+
|
|
52
|
+
## Choosing a Dialect
|
|
53
|
+
|
|
54
|
+
| Use Case | Recommended Dialect |
|
|
55
|
+
|----------|-------------------|
|
|
56
|
+
| Production MySQL/MariaDB | `MySQL` |
|
|
57
|
+
| Production SQL Server | `MSSQL` |
|
|
58
|
+
| Embedded/file-based database | `SQLite` |
|
|
59
|
+
| Browser-side or in-memory queries | `ALASQL` |
|
|
60
|
+
| Debugging/logging | `English` |
|
|
61
|
+
| REST API URL generation | `MeadowEndpoints` |
|