@possumtech/sqlrite 0.1.2 → 0.1.5

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
+ # sqlrite Contributor Code of Conduct
2
+
3
+ sqlrite is an open source project and not a community. It exists to perform the
4
+ technical goals outlined in the readme and implemented in the codebase. All
5
+ contributions are equally welcome, except from those who reject the premise that
6
+ Sqlrite is an open source project and not a community.
7
+
8
+ Those seeking a "community" are encouraged to reach out to a local church,
9
+ mosque, temple, synagogue, or local civic organization, at your discretion, for
10
+ community support. sqlrite does not support or endorse any cause or campaign.
11
+
12
+ Conversations on the platform are to pertain to the project. All other topics
13
+ are unwelcome.
@@ -0,0 +1 @@
1
+ Contributions are welcome, and I will do my best to work with you on any workflow, coding style, or other issues that may arise.
package/README.md CHANGED
@@ -47,7 +47,7 @@ them all.
47
47
 
48
48
  There are three types of "chunk" one can add to a `.sql` file:
49
49
 
50
- 1. **INIT**: A transaction that is executed when the database is first created.
50
+ 1. **INIT**: A transaction that is executed when the module is instantiated.
51
51
  This is where you should create your tables, for example.
52
52
 
53
53
  2. **EXEC**: A transaction that can be executed at any time. For example,
@@ -55,7 +55,36 @@ This is where you should create your tables, for example.
55
55
  not prepared statements, like maintaining your database.
56
56
 
57
57
  3. **PREP**: A prepared statement that can be executed at any time. This is
58
- where you should put your queries.
58
+ where you should put your queries. After declaring a prepared statement, you can
59
+ then run it with either the `.all({})`, `.get({})` or `.run({})` methods, as per
60
+ the native sqlite API.
61
+
62
+ | Method | Description |
63
+ |------------|-------------------------------------------------------|
64
+ | `.all({})` | Returns all rows that match the query. |
65
+ | `.get({})` | Returns the first row that matches the query. |
66
+ | `.run({})` | Executes the query and returns the (optional) result. |
67
+
68
+ ### Synchronous/Asynchronous
69
+
70
+ The native sqlite module currently only supports synchronous operations. This
71
+ can pose a performance issue in some common cases. Sqlrite addresses this by
72
+ allowing one to run one's queries asynchronously by appending `.async`:
73
+
74
+ For example, instead of:
75
+
76
+ **Synchronous**
77
+
78
+ ```js
79
+ console.log(sql.getPositions.all());
80
+ ```
81
+
82
+ **Asynchronous**
83
+
84
+ ```js
85
+ sql.async.getPositions.all().then((positions) => console.log(positions));
86
+ ```
87
+
59
88
 
60
89
  **Example SQL File**
61
90
 
@@ -83,6 +112,9 @@ END TRANSACTION;
83
112
  INSERT INTO employees (name, position, salary)
84
113
  VALUES ($name, $position, $salary);
85
114
 
115
+ -- PREP: getPositions
116
+ SELECT name, position FROM employees;
117
+
86
118
  -- PREP: getHighestPaidEmployee
87
119
  SELECT name FROM employees ORDER BY salary DESC LIMIT 1;
88
120
  ```
@@ -101,32 +133,53 @@ sql.addEmployee.run({ name: "Jill", position: "CIO", salary: 49996 });
101
133
 
102
134
  const employee = sql.getHighestPaidEmployee.get();
103
135
 
136
+ assert(employee?.name === "John", "The highest paid employee should be John");
137
+
138
+ sql.async.getPositions.all().then((positions) => console.log(positions));
139
+
104
140
  console.log(`The highest paid employee is ${employee.name}.`);
105
141
 
106
142
  sql.deleteTable();
107
-
108
143
  ```
109
144
 
110
145
  ## Installation
111
146
 
112
- Navigate to your project directory and run the following command:
147
+ 1. Navigate to your project directory and run the following command:
113
148
 
114
149
  ```bash
115
150
  npm install @possumtech/sqlrite
116
151
  ```
117
152
 
153
+ 2. Then create a `sql` directory in your project directory. This is where you
154
+ will put your SQL files.
155
+
156
+ ```bash
157
+ mkdir sql
158
+ cd sql
159
+ touch exampleFile.sql
160
+ ```
161
+
118
162
  ## Configuration
119
163
 
120
164
  ```js
121
- import sqlrite from "sqlrite";
165
+ import SqlRite from "@possumtech/sqlrite";
122
166
 
123
- const sql = new sqlrite(options = {
124
- // Custom SQLite database file path.
125
- path: ":memory:",
167
+ const sql = new SqlRite({
168
+ // SQLite database file path.
169
+ path: ":memory:",
126
170
 
127
- // Path to your SQL directory.
128
- dir: "./sql",
171
+ // Path to your SQL directory.
172
+ dir: "sql/",
129
173
  });
130
174
  ```
175
+
176
+ You will almost certainly wish to replace the `path` with a path to your
177
+ database file. Otherwise, the database will be created in memory and lost when
178
+ the process ends.
179
+
180
+ ```js
181
+ const sql = new SqlRite({ path: "path/to/your/database.sqlite3" });
182
+ ```
183
+
131
184
  Additional arguments will be passed to the options object of the native sqlite
132
185
  module.
package/SqlRite.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { Database, DatabaseSync, Statement } from 'node:sqlite';
2
+
3
+ interface SqlRiteOptions {
4
+ path?: string;
5
+ dir?: string;
6
+ }
7
+
8
+ interface SqlRiteAsyncPreparedStatements {
9
+ all: (params?: Record<string, any>) => Promise<any[]>;
10
+ get: (params?: Record<string, any>) => Promise<any>;
11
+ run: (params?: Record<string, any>) => Promise<void>;
12
+ }
13
+
14
+ interface SqlRiteAsyncMethods {
15
+ [key: string]: (() => Promise<void>) | SqlRiteAsyncPreparedStatements;
16
+ }
17
+
18
+ export default class SqlRite {
19
+ constructor(options?: SqlRiteOptions);
20
+ async: SqlRiteAsyncMethods;
21
+ [key: string]: (() => void) | Statement | SqlRiteAsyncMethods | any;
22
+ }
package/SqlRite.js CHANGED
@@ -16,22 +16,43 @@ export default class SqlRite {
16
16
  const files = fs.readdirSync(dir);
17
17
  const code = files.map((f) => fs.readFileSync(dir + f, "utf8")).join("");
18
18
 
19
+ this.async = {};
20
+
19
21
  const chunks =
20
22
  /-- (?<chunk>(?<type>INIT|EXEC|PREP): (?<name>\w+)\n(?<sql>.*?))($|(?=-- (INIT|EXEC|PREP):))/gs;
21
23
 
24
+ const initChunks = [];
25
+ const execChunks = [];
26
+ const prepChunks = [];
27
+
22
28
  for (const chunk of code.matchAll(chunks)) {
23
29
  const { type, name, sql } = chunk.groups;
24
- switch (type) {
25
- case "INIT":
26
- db.exec(sql);
27
- break;
28
- case "EXEC":
29
- this[name] = () => db.exec(sql);
30
- break;
31
- case "PREP":
32
- this[name] = db.prepare(sql);
33
- break;
34
- }
30
+
31
+ if (type === "INIT") initChunks.push(chunk.groups);
32
+ if (type === "EXEC") execChunks.push(chunk.groups);
33
+ if (type === "PREP") prepChunks.push(chunk.groups);
35
34
  }
35
+
36
+ initChunks.forEach((init) => db.exec(init.sql));
37
+
38
+ execChunks.forEach((exec) => {
39
+ this[exec.name] = () => db.exec(exec.sql);
40
+ this.async[exec.name] = async () => db.exec(exec.sql);
41
+ });
42
+
43
+ prepChunks.forEach((prep) => {
44
+ this[prep.name] = db.prepare(prep.sql);
45
+
46
+ this.async[prep.name] = {};
47
+
48
+ this.async[prep.name].all = async (params = {}) =>
49
+ this[prep.name].all(params);
50
+
51
+ this.async[prep.name].get = async (params = {}) =>
52
+ this[prep.name].get(params);
53
+
54
+ this.async[prep.name].run = async (params = {}) =>
55
+ this[prep.name].run(params);
56
+ });
36
57
  }
37
58
  }
package/biome.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "files": {
9
9
  "ignoreUnknown": false,
10
- "ignore": []
10
+ "ignore": ["SqlRite.d.ts", "package.json", "package-lock.json"]
11
11
  },
12
12
  "formatter": {
13
13
  "enabled": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@possumtech/sqlrite",
3
- "version": "0.1.2",
3
+ "version": "0.1.5",
4
4
  "description": "SQL Done Right",
5
5
  "keywords": [
6
6
  "node",
package/sql/test.sql CHANGED
@@ -21,5 +21,8 @@ END TRANSACTION;
21
21
  INSERT INTO employees (name, position, salary)
22
22
  VALUES ($name, $position, $salary);
23
23
 
24
+ -- PREP: getPositions
25
+ SELECT name, position FROM employees;
26
+
24
27
  -- PREP: getHighestPaidEmployee
25
28
  SELECT name FROM employees ORDER BY salary DESC LIMIT 1;
package/test/test.js CHANGED
@@ -12,6 +12,8 @@ const employee = sql.getHighestPaidEmployee.get();
12
12
 
13
13
  assert(employee?.name === "John", "The highest paid employee should be John");
14
14
 
15
+ sql.async.getPositions.all().then((positions) => console.log(positions));
16
+
15
17
  console.log(`The highest paid employee is ${employee.name}.`);
16
18
 
17
19
  sql.deleteTable();