dobo-sqlite3 2.2.0

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.
@@ -0,0 +1,13 @@
1
+ github: ardhi
2
+ patreon: bajoframework
3
+ #open_collective: # Replace with a single Open Collective username
4
+ #ko_fi: # Replace with a single Ko-fi username
5
+ #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
6
+ #community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
7
+ #liberapay: # Replace with a single Liberapay username
8
+ #issuehunt: # Replace with a single IssueHunt username
9
+ #lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
10
+ #polar: # Replace with a single Polar username
11
+ #buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
12
+ #thanks_dev: # Replace with a single thanks.dev username
13
+ custom: ["https://www.paypal.com/ncp/payment/EWLERL7SCUU64"]
@@ -0,0 +1,24 @@
1
+ name: 'Repo Lockdown'
2
+
3
+ on:
4
+ #issues:
5
+ #types: opened
6
+ pull_request_target:
7
+ types: opened
8
+ #schedule:
9
+ #- cron: '* */6 * * *'
10
+
11
+ permissions:
12
+ #issues: write
13
+ pull-requests: write
14
+
15
+ jobs:
16
+ action:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: dessant/repo-lockdown@v4
20
+ with:
21
+ pr-comment: >
22
+ This repository does not accept pull requests,
23
+ see the README.md for details.
24
+ skip-closed-pr-comment: true
@@ -0,0 +1,45 @@
1
+ {
2
+ "plugins": ["plugins/markdown", "jsdoc-plugin-intersection"],
3
+ "opts": {
4
+ "encoding": "utf8",
5
+ "recurse": true,
6
+ "verbose": true,
7
+ "destination": "./docs",
8
+ "template": "node_modules/clean-jsdoc-theme",
9
+ "readme": "./docs/static/home.md",
10
+ "theme_opts": {
11
+ "default_theme": "light",
12
+ "display-module-header": true,
13
+ "title": "DoboKnex API",
14
+ "homepageTitle": "DoboKnex API",
15
+ "sections": ["Classes", "Events", "Modules", "Global"],
16
+ "menu": [{
17
+ "title": "NPM",
18
+ "link": "https://www.npmjs.com/package/dobo-knex"
19
+ }, {
20
+ "title": "Github",
21
+ "link": "https://github.com/ardhi/dobo-knex"
22
+ }, {
23
+ "title": "Dobo",
24
+ "link": "https://dobo.bajo.app/"
25
+ }, {
26
+ "title": "Bajo",
27
+ "link": "https://bajo.app/"
28
+ }]
29
+ }
30
+ },
31
+ "source": {
32
+ "include": ["."],
33
+ "includePattern": ".+\\.js(doc|x)?$",
34
+ "exclude": ["node_modules", "docs", "test"]
35
+ },
36
+ "markdown": {
37
+ "hardwrap": false,
38
+ "idInHeadings": true
39
+ },
40
+ "sourceType": "module",
41
+ "templates": {
42
+ "cleverLinks": false,
43
+ "monospaceLinks": false
44
+ }
45
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ardhi Lukianto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # dobo-sqlite3
2
+
3
+ ![GitHub package.json version](https://img.shields.io/github/package-json/v/ardhi/dobo-sqlite3) ![NPM Version](https://img.shields.io/npm/v/dobo-sqlite3)
4
+
5
+ > <br />**Attention**: I do NOT accept any pull request at the moment, thanks! ([Why?](wiki/CONTRIBUTING.md))<br /><br />
6
+
7
+ SQLite3 driver for [Dobo](https://github.com/ardhi/dobo)
8
+
9
+ ## Installation
10
+
11
+ Goto your ```{appDir}``` and run the following command in your terminal:
12
+
13
+ ```bash
14
+ $ npm install dobo dobo-knex dobo-sqlite3
15
+ ```
16
+
17
+ And enable the plugin by adding ```dobo```, ```dobo-knex``` and ```dobo-sqlite3``` to the plugin list in either the ```$dataDir/config/.plugins``` file or the ```bajo.plugins``` array within your ```package.json``` file
18
+
19
+ ## Documentations
20
+
21
+ - [Config Object](wiki/CONFIG.md)
22
+ - [Supported Drivers](wiki/SUPPORTED-DRIVERS.md)
23
+ - [API](https://ardhi.github.io/dobo-sqlite3)
24
+ - [Contributing](wiki/CONTRIBUTING.md)
25
+
26
+ ## Hire Me
27
+
28
+ If you have a Bajo Framework-based project and need a professional service or assistance, please <a href="https://github.com/ardhi#professional-service">click here</a>. I'd be happy to work on it at a competitive price and with fast turnaround!
29
+
30
+ ## Support Me
31
+
32
+ Please support me using the channels below. Your donation will motivate me to work faster and more diligently on future development.
33
+
34
+ <a href="https://github.com/sponsors/ardhi">
35
+ <img src="https://img.shields.io/badge/Github-slategrey?style=flat&logo=github" height="50">
36
+ </a>
37
+ <a href="https://www.patreon.com/bajoframework">
38
+ <img src="https://img.shields.io/badge/Patreon-f2c3b2?style=flat&logo=patreon" height="50">
39
+ </a>
40
+ <a href="https://www.paypal.com/ncp/payment/EWLERL7SCUU64">
41
+ <img src="https://img.shields.io/badge/Paypal-blue?style=flat&logo=paypal" height="50">
42
+ </a>
43
+
44
+ <p>
45
+ <div><img alt="bc1qwtv78cwp9ef8hnqaw84fxg5856l0pggqe32g6f" src="docs/static/bitcoin.jpeg" width="150" height="150" /><br>Bitcoin</div>
46
+ </p>
47
+
48
+ ## License
49
+
50
+ [MIT](LICENSE)
@@ -0,0 +1,145 @@
1
+ import path from 'path'
2
+
3
+ async function sqlite3DriverFactory () {
4
+ const { DoboKnexDriver } = this.app.baseClass
5
+ const { uniq } = this.app.lib._
6
+
7
+ class DoboSqlite3Driver extends DoboKnexDriver {
8
+ constructor (plugin, name, options) {
9
+ super(plugin, name, options)
10
+ this.dialect = 'sqlite3'
11
+ this.adapter = 'sqlite3'
12
+ this.options = {
13
+ useNullAsDefault: true
14
+ }
15
+ }
16
+
17
+ async sanitizeConnection (item) {
18
+ await super.sanitizeConnection(item)
19
+ const { fs } = this.app.lib
20
+ const { getPluginDataDir } = this.app.bajo
21
+ const { isString, isEmpty } = this.app.lib._
22
+ if (!isString(item.filename)) this.plugin.fatal('keyIsRequired%s%s%s', 'filename', this.plugin.t('connection'), item.name, { payload: item })
23
+ if (item.filename === ':memory:') this.memory = true
24
+ else {
25
+ let file = item.filename
26
+ if (file.indexOf('/') === -1) {
27
+ file = `${getPluginDataDir('dobo')}/db/${file}`
28
+ const ext = path.extname(file)
29
+ if (isEmpty(ext)) file += '.sqlite3'
30
+ fs.ensureDirSync(path.dirname(file))
31
+ } else {
32
+ if (file.indexOf('{appDir}') > -1) file = file.replace('{appDir}', this.app.dir)
33
+ if (file.indexOf('{dataDir}') > -1) file = file.replace('{dataDir}', this.app.bajo.dir.data)
34
+ if (file.indexOf('{tmpDir}') > -1) file = file.replace('{tmpDir}', this.app.bajo.dir.tmp)
35
+ }
36
+ item.filename = file
37
+ }
38
+ }
39
+
40
+ async connect (connection, noRebuild) {
41
+ await super.connect(connection, noRebuild)
42
+ if (!this.memory) return
43
+ const models = this.plugin.getModelsByConnection(connection.name)
44
+ for (const model of models) {
45
+ await model.build()
46
+ await model.loadFixtures()
47
+ }
48
+ }
49
+
50
+ async buildModel (model, options = {}) {
51
+ await super.buildModel(model, options)
52
+ const fullTexts = model.indexes.filter(idx => idx.type === 'fulltext')
53
+ if (fullTexts.length === 0) return
54
+
55
+ const client = model.connection.client
56
+ function getCols () {
57
+ const columns = []
58
+ for (const idx of fullTexts) {
59
+ columns.push(...idx.fields)
60
+ }
61
+ return uniq(columns)
62
+ }
63
+
64
+ function printCols (prefix) {
65
+ let cols = [...getCols()]
66
+ if (prefix) cols = cols.map(c => `${prefix}.${c}`)
67
+ return cols.join(', ')
68
+ }
69
+
70
+ const columns = getCols().join(', ')
71
+ const stmtSchema = `
72
+ CREATE VIRTUAL TABLE ${model.name}_fts USING fts5 (
73
+ ${printCols()}, content = '${model.name}', content_rowid = '${this.idField.name}'
74
+ );
75
+ `
76
+ const stmtTriggerInsert = `
77
+ CREATE TRIGGER ${model.name}_fts_insert AFTER INSERT ON ${model.name}
78
+ BEGIN
79
+ INSERT INTO ${model.name}_fts (rowid, ${columns}) VALUES (new.id, ${printCols('new')});
80
+ END;
81
+ `
82
+ const stmtTriggerDelete = `
83
+ CREATE TRIGGER ${model.name}_fts_delete AFTER DELETE ON ${model.name}
84
+ BEGIN
85
+ INSERT INTO ${model.name}_fts (${model.name}_fts, rowid, ${columns}) VALUES ('delete', old.id, ${printCols('old')});
86
+ END;
87
+ `
88
+
89
+ const stmtTriggerUpdate = `
90
+ CREATE TRIGGER ${model.name}_fts_update AFTER UPDATE ON ${model.name}
91
+ BEGIN
92
+ INSERT INTO ${model.name}_fts (${model.name}_fts, rowid, ${columns}) VALUES ('delete', old.id, ${printCols('old')});
93
+ INSERT INTO ${model.name}_fts (rowid, ${columns}) VALUES (new.id, ${printCols('new')});
94
+ END;
95
+ `
96
+ await client.raw(stmtSchema)
97
+ await client.raw(stmtTriggerInsert)
98
+ await client.raw(stmtTriggerDelete)
99
+ await client.raw(stmtTriggerUpdate)
100
+ }
101
+
102
+ async dropModel (model, options = {}) {
103
+ await super.dropModel(model, options)
104
+ const client = model.connection.client
105
+ const fulltexts = model.indexes.filter(idx => idx.type === 'fulltext')
106
+ if (fulltexts.length > 0) await client.schema.dropTable(`${model.name}_fts`)
107
+ }
108
+
109
+ _reformHistogram ({ type, item, group, aggregates, field }) {
110
+ const aggs = []
111
+ for (const agg of aggregates) {
112
+ aggs.push(`${agg}(${agg === 'count' ? '*' : field}) as ${agg}`)
113
+ }
114
+ switch (type) {
115
+ case 'daily': {
116
+ item.sql = item.sql.replace('*', `strftime('%Y-%m-%d', substr(${group}, 1, 10), 'auto') as date, ${aggs.join(', ')}`)
117
+ const start = item.sql.indexOf(' order by ')
118
+ const end = item.sql.indexOf(' limit ')
119
+ // const order = item.sql.slice(start, end)
120
+ item.sql = item.sql.splice(start, end - start, '')
121
+ // item.sql = item.sql.replace('limit ', `group by strftime('%Y', substr(${group}, 1, 10), 'auto'), strftime('%m', substr(${group}, 1, 10), 'auto'), strftime('%d', substr(${group}, 1, 10), 'auto') ${order} limit `)
122
+ item.sql = item.sql.replace('limit ', 'group by date limit ')
123
+ break
124
+ }
125
+ case 'monthly': {
126
+ item.sql = item.sql.replace('*', `strftime('%Y-%m', substr(${group}, 1, 10), 'auto') as month, ${aggs.join(', ')}`)
127
+ // item.sql = item.sql.replace('limit ', `group by strftime('%Y', substr(${group}, 1, 10), 'auto'), strftime('%m', substr(${group}, 1, 10), 'auto') limit `)
128
+ item.sql = item.sql.replace('limit ', 'group by month limit ')
129
+ break
130
+ }
131
+ case 'yearly': {
132
+ item.sql = item.sql.replace('*', `cast(strftime('%Y', substr(${group}, 1, 10), 'auto') as integer) as year, ${aggs.join(', ')}`)
133
+ // item.sql = item.sql.replace('limit ', `group by strftime('%Y', substr(${group}, 1, 10), 'auto') limit `)
134
+ item.sql = item.sql.replace('limit ', 'group by year limit ')
135
+ break
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ this.app.DoboSqlite3Driver = DoboSqlite3Driver
142
+ return DoboSqlite3Driver
143
+ }
144
+
145
+ export default sqlite3DriverFactory
package/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Plugin factory
3
+ *
4
+ * @param {string} pkgName - NPM package name
5
+ * @returns {class}
6
+ */
7
+ async function factory (pkgName) {
8
+ const me = this
9
+
10
+ /**
11
+ * DoboSqlite3 class
12
+ *
13
+ * @class
14
+ */
15
+ class DoboSqlite3 extends this.app.baseClass.Base {
16
+ constructor () {
17
+ super(pkgName, me.app)
18
+ this.config = {
19
+ options: {
20
+ compileSqlOnError: false
21
+ }
22
+ }
23
+ }
24
+ }
25
+ return DoboSqlite3
26
+ }
27
+
28
+ export default factory
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "dobo-sqlite3",
3
+ "version": "2.2.0",
4
+ "description": "SQLite3 driver for Dobo",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "build-doc": "jsdoc -c .jsdoc.conf.json",
8
+ "test": "mocha"
9
+ },
10
+ "type": "module",
11
+ "bajo": {
12
+ "type": "plugin",
13
+ "alias": "dbsqlite3",
14
+ "dependencies": ["dobo", "dobo-knex"]
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/ardhi/dobo-sqlite3.git"
19
+ },
20
+ "keywords": [
21
+ "sqlite3",
22
+ "sql",
23
+ "dobo",
24
+ "db",
25
+ "driver",
26
+ "bajo",
27
+ "framework",
28
+ "modular"
29
+ ],
30
+ "author": "Ardhi Lukianto <ardhi@lukianto.com>",
31
+ "license": "MIT",
32
+ "bugs": {
33
+ "url": "https://github.com/ardhi/dobo-sqlite3/issues"
34
+ },
35
+ "homepage": "https://github.com/ardhi/dobo-sqlite3#readme",
36
+ "dependencies": {
37
+ "sqlite3": "^5.1.7"
38
+ },
39
+ "devDependencies": {
40
+ "clean-jsdoc-theme": "^4.3.0",
41
+ "jsdoc-plugin-intersection": "^1.0.4"
42
+ }
43
+ }
@@ -0,0 +1,5 @@
1
+ # Changes
2
+
3
+ ## 2025-12-22
4
+
5
+ - First port SQLite3 driver as independent plugin
package/wiki/CONFIG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Config Object
2
+
3
+
4
+ ## Dobo's connection object
5
+
6
+ These SQLite3 connection objects should be used as your **Dobo connection** object's array written in your ```{dataDir}/config/dobo.json```, NOT in ```{dataDir}/config/doboSqlite3.json```.
7
+
8
+ | Key Name | Type | Default | Description |
9
+ | ------- | ---- | ----- | ----------- |
10
+ | ```name``` | ```string``` | ```default``` | Connection name |
11
+ | ```type``` | ```string``` || Connection's driver type. See below |
12
+ | ```connection``` | ```object``` || Connection details |
13
+ | &nbsp;&nbsp;&nbsp;&nbsp;```filename``` | ```string``` || Path to database file |
14
+ | &nbsp;&nbsp;&nbsp;&nbsp;```...``` ||| See knex *connection* config |
15
+ | ```useNullAsDefault``` | ```boolean``` | ```true``` | See knex options |
16
+ | ```...``` ||| See knex options |
17
+
18
+ Directory to database file, if not specifed, defaults to ```{dataDir}/plugins/dobo/db/{filename}```
19
+
20
+ if ```{filename}``` is ```:memory:```, it turns on SQLite3 memory database
21
+
22
+ Directory tokens are supported, it will be replaced by its respected values if any are found:
23
+ - ```{appDir}```
24
+ - ```{dataDir}```
25
+ - ```{tmpDir}```
@@ -0,0 +1,5 @@
1
+ # Contributing
2
+
3
+ Thanks very much to everyone who wants to join as a contributor, but I have committed to devoting 100% of my time to this project. Therefore, I'm currently unable to accept pull requests from anyone until the project is large enough for me to manage it independently.
4
+
5
+ However, I am available if you encounter any bugs that require immediate fixes. Please report your issues in a GitHub issue, and I'll try to address them promptly. I'm also open to criticism and suggestions for improvements or requests for new features.
@@ -0,0 +1,73 @@
1
+ # Supported Drivers
2
+
3
+ By default, [Knex](https://knexjs.org) support the following databases:
4
+
5
+ - [PostgreSQL](https://www.postgresql.org), [CockrouchDB](https://www.cockroachlabs.com) and [Amazon Redshift](https://aws.amazon.com/redshift) through [pg](https://github.com/brianc/node-postgres) adapter.
6
+ - [MySQL](https://www.mysql.com) and [MariaDB](https://mariadb.org) through [mysql](https://github.com/felixge/node-mysql) adapter.
7
+ - [SQLite3](https://sqlite.org) through [sqlite3](https://github.com/mapbox/node-sqlite3) adapter.
8
+ - [MSSQL](https://www.microsoft.com/en-us/sql-server) through [tedious](https://github.com/tediousjs/tedious) adapter.
9
+
10
+ In addition to those listed above, Dobo Knex also supports the following databases with some custom patches to ensure they work as smoothly as it possible:
11
+
12
+ - [Manticoresearch](https://github.com/manticoresoftware/manticoresearch) through [mysql](https://github.com/felixge/node-mysql) adapter.
13
+
14
+ ## Example MySQL
15
+
16
+ - Package install:
17
+
18
+ ```bash
19
+ $ npm install mysql dobo dobo-knex
20
+ ```
21
+ - ```{dataDir}/config/.plugins``` file:
22
+
23
+ ```txt
24
+ ...
25
+ dobo
26
+ dobo-knex
27
+ ...
28
+ ```
29
+ - ```{dataDir}/config/dobo.json``` file:
30
+
31
+ ```json
32
+ {
33
+ "connections": [{
34
+ "name": "default",
35
+ "type": "dbknex:mysql",
36
+ "connection": {
37
+ "host": "localhost",
38
+ "user": "myuser",
39
+ "password": "mypassword",
40
+ "database": "mydb"
41
+ }
42
+ }]
43
+ }
44
+ ```
45
+
46
+ ## Example SQLite3
47
+
48
+ - Package install:
49
+
50
+ ```bash
51
+ $ npm install sqlite3 dobo dobo-knex
52
+ ```
53
+ - ```{dataDir}/config/.plugins``` file:
54
+
55
+ ```txt
56
+ ...
57
+ dobo
58
+ dobo-knex
59
+ ...
60
+ ```
61
+ - ```{dataDir}/config/dobo.json``` file:
62
+
63
+ ```json
64
+ {
65
+ "connections": [{
66
+ "name": "default",
67
+ "type": "dbknex:sqlite3",
68
+ "connection": {
69
+ "filename": "mydatabase.sqlite3"
70
+ }
71
+ }]
72
+ }
73
+ ```