@petradb/engine 1.0.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.
Files changed (4) hide show
  1. package/README.md +287 -0
  2. package/index.d.ts +118 -0
  3. package/main.js +137674 -0
  4. package/package.json +36 -0
package/README.md ADDED
@@ -0,0 +1,287 @@
1
+ A lightweight, in-memory SQL database for JavaScript and TypeScript. No native dependencies, no external services — just import and query. Follows PostgreSQL conventions for SQL syntax, identifier handling, and type casting.
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ npm install @petradb/engine
7
+ ```
8
+
9
+ ## Quick Start
10
+
11
+ ```javascript
12
+ import { ConnectSQL } from '@petradb/engine';
13
+
14
+ const db = new ConnectSQL();
15
+
16
+ db.execute(`
17
+ CREATE TABLE users (
18
+ id SERIAL,
19
+ name TEXT NOT NULL,
20
+ email TEXT,
21
+ PRIMARY KEY (id)
22
+ )
23
+ `);
24
+
25
+ db.execute("INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')");
26
+ db.execute("INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com')");
27
+
28
+ const [{ rows, fields }] = db.execute('SELECT * FROM users');
29
+ // rows: [{ id: 1, name: 'Alice', email: 'alice@example.com' }, ...]
30
+ // fields: [{ name: 'id', dataType: 'serial' }, { name: 'name', dataType: 'text' }, ...]
31
+ ```
32
+
33
+ ## Row Modes
34
+
35
+ By default, SELECT rows are returned as objects keyed by column name. Use `rowMode: 'array'` for positional arrays instead.
36
+
37
+ ```javascript
38
+ // Set default for all queries
39
+ const db = new ConnectSQL({ rowMode: 'array' });
40
+
41
+ // Or override per call
42
+ const [{ rows }] = db.execute('SELECT id, name FROM users', { rowMode: 'array' });
43
+ // rows: [[1, 'Alice'], [2, 'Bob']]
44
+ ```
45
+
46
+ ## SQL Compatibility
47
+
48
+ PetraDB follows PostgreSQL conventions:
49
+
50
+ - **Case-insensitive keywords** — `SELECT`, `select`, and `Select` are equivalent
51
+ - **Unquoted identifier folding** — identifiers fold to lowercase (`CREATE TABLE Users` → table name `users`)
52
+ - **Double-quoted identifiers** — preserve case (`"MixedCase"` stays as-is)
53
+ - **String escaping** — doubled single quotes (`'it''s'`) and E-strings (`E'it\'s'`)
54
+ - **Operators** — both `!=` and `<>` for not-equal
55
+ - **Type casting** — `::` operator and `CAST(expr AS type)`
56
+
57
+ ## Supported SQL
58
+
59
+ ### Data Types
60
+
61
+ | Type | Description |
62
+ |------|-------------|
63
+ | `SMALLINT` | 16-bit integer |
64
+ | `INT` / `INTEGER` | 32-bit integer |
65
+ | `BIGINT` | 64-bit integer |
66
+ | `SMALLSERIAL` / `SERIAL` / `BIGSERIAL` | Auto-incrementing integers |
67
+ | `DOUBLE` / `FLOAT` / `REAL` | Double-precision float |
68
+ | `NUMERIC(p, s)` / `DECIMAL(p, s)` | Fixed-precision decimal |
69
+ | `TEXT` | Variable-length string |
70
+ | `CHAR(n)` | Fixed-length string |
71
+ | `VARCHAR(n)` | Variable-length string (max n chars) |
72
+ | `BOOLEAN` | True/false |
73
+ | `DATE` / `TIME` / `TIMESTAMP` | Date and time types |
74
+ | `TIMESTAMP WITH TIME ZONE` | Timezone-aware timestamp |
75
+ | `INTERVAL` | Duration |
76
+ | `UUID` | UUID (use `DEFAULT gen_random_uuid()`) |
77
+ | `JSON` / `JSONB` | JSON objects and arrays |
78
+ | `BYTEA` | Binary data |
79
+ | `ENUM` | Custom enumerated types |
80
+ | `INT[]`, `TEXT[]`, etc. | Typed arrays |
81
+
82
+ ### DDL
83
+
84
+ ```sql
85
+ CREATE TABLE, CREATE TABLE IF NOT EXISTS
86
+ DROP TABLE, DROP TABLE IF EXISTS
87
+ ALTER TABLE (ADD/DROP/RENAME COLUMN, ADD CONSTRAINT, etc.)
88
+ CREATE TYPE ... AS ENUM, DROP TYPE
89
+ CREATE INDEX, CREATE UNIQUE INDEX, DROP INDEX
90
+ TRUNCATE TABLE
91
+ ```
92
+
93
+ ### DML
94
+
95
+ ```sql
96
+ INSERT INTO ... VALUES
97
+ INSERT INTO ... SELECT -- insert from a query
98
+ UPDATE ... SET ... WHERE
99
+ UPDATE ... SET ... FROM ... -- bulk update with join semantics
100
+ DELETE FROM ... WHERE
101
+ TRUNCATE TABLE -- fast table reset, resets serial sequences
102
+ ```
103
+
104
+ ### Queries
105
+
106
+ ```sql
107
+ SELECT, SELECT DISTINCT, WHERE, ORDER BY, LIMIT, OFFSET
108
+ GROUP BY, HAVING
109
+ JOIN (INNER/LEFT/RIGHT/FULL/CROSS)
110
+ LATERAL joins -- correlated subqueries in FROM
111
+ Subqueries, EXISTS, IN, = ANY(...)
112
+ VALUES as standalone query and FROM source
113
+ Column aliases: AS alias (col1, col2, ...)
114
+ CASE expressions, BETWEEN, LIKE, ILIKE
115
+ UNION, INTERSECT, EXCEPT
116
+ OVERLAPS -- date/time range overlap test
117
+ CAST(expr AS type), expr::type
118
+ ```
119
+
120
+ ### Constraints
121
+
122
+ ```sql
123
+ PRIMARY KEY, UNIQUE, NOT NULL, DEFAULT
124
+ FOREIGN KEY ... REFERENCES ... ON DELETE/UPDATE (CASCADE, SET NULL, RESTRICT)
125
+ ```
126
+
127
+ ### Transactions
128
+
129
+ ```sql
130
+ BEGIN, COMMIT, ROLLBACK
131
+ ```
132
+
133
+ ### Prepared Statements
134
+
135
+ ```sql
136
+ PREPARE name AS statement -- with $1, $2, ... parameters
137
+ EXECUTE name(arg1, arg2, ...)
138
+ DEALLOCATE name
139
+ ```
140
+
141
+ ### Aggregate Functions
142
+
143
+ `COUNT`, `SUM`, `AVG`, `MIN`, `MAX`, `string_agg`, `array_agg`, `bool_and`, `bool_or`, `every`, `variance`, `var_samp`, `var_pop`, `stddev`, `stddev_samp`, `stddev_pop`
144
+
145
+ ### Built-in Functions
146
+
147
+ **Text:** `lower`, `upper`, `initcap`, `length`, `trim`, `ltrim`, `rtrim`, `btrim`, `substring`, `left`, `right`, `lpad`, `rpad`, `replace`, `translate`, `concat`, `concat_ws`, `repeat`, `reverse`, `position`, `split_part`, `ascii`, `chr`, `regexp_replace`, `regexp_match`, `starts_with`, `ends_with`
148
+
149
+ **Numeric:** `abs`, `ceil`, `floor`, `round`, `trunc`, `sign`, `mod`, `%`, `power`, `sqrt`, `cbrt`, `exp`, `ln`, `log10`, `log`, `pi`, `degrees`, `radians`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `atan2`, `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh`, `div`, `factorial`, `gcd`, `lcm`, `random`, `greatest`, `least`, `&` (AND), `|` (OR), `#` (XOR), `~` (NOT), `<<` (shift left), `>>` (shift right)
150
+
151
+ **Date/Time:** `now`, `current_date`, `current_time`, `date_part`, `EXTRACT`, `date_trunc`, `make_date`, `make_time`, `make_timestamp`, `make_interval`, `age`, `to_char`, `to_date`, `to_timestamp`, `to_number`, `isfinite`
152
+
153
+ **Array:** `array_length`, `array_append`, `array_prepend`, `array_concat`, `array_cat`, `array_slice`, `array_remove`, `array_replace`, `array_position`, `array_distinct`, `array_lower`, `array_upper`, `array_ndims`, `cardinality`, `string_to_array`, `array_to_string`
154
+
155
+ **Other:** `coalesce`, `nullif`, `typeof`, `gen_random_uuid`, `octet_length`, `encode`, `decode`
156
+
157
+ ## API
158
+
159
+ ### `new ConnectSQL(options?)`
160
+
161
+ Creates a new database instance. Each instance is fully isolated.
162
+
163
+ | Option | Type | Default | Description |
164
+ |--------|------|---------|-------------|
165
+ | `rowMode` | `'object' \| 'array'` | `'object'` | Default row format for SELECT results |
166
+
167
+ ### `db.execute(sql, options?)`
168
+
169
+ Executes one or more SQL statements separated by `;`. Returns an array of results.
170
+
171
+ | Option | Type | Default | Description |
172
+ |--------|------|---------|-------------|
173
+ | `rowMode` | `'object' \| 'array'` | constructor default | Row format for this call |
174
+
175
+ ### `db.prepare(sql)`
176
+
177
+ Creates a prepared statement with `$1`, `$2`, ... parameter placeholders. Returns a statement object with an `execute(params, options?)` method.
178
+
179
+ ```javascript
180
+ const stmt = db.prepare('SELECT * FROM users WHERE id = $1');
181
+ const [{ rows }] = stmt.execute([42]);
182
+
183
+ // With options
184
+ const [{ rows }] = stmt.execute([42], { rowMode: 'array' });
185
+ ```
186
+
187
+ ### Result Types
188
+
189
+ Every result has a `command` field for easy discrimination:
190
+
191
+ ```typescript
192
+ // DDL
193
+ { command: 'create table', table: string }
194
+ { command: 'drop table', table: string }
195
+ { command: 'create type', type: string }
196
+ { command: 'drop type', type: string }
197
+ { command: 'create index', index: string }
198
+ { command: 'drop index', index: string }
199
+ { command: 'truncate table', table: string }
200
+ { command: 'alter table' }
201
+
202
+ // DML
203
+ { command: 'insert', result: Record<string, any> }
204
+ { command: 'select', rows: T[], fields: { name: string, dataType: string }[] }
205
+ { command: 'update', rows: number }
206
+ { command: 'delete', rows: number }
207
+
208
+ // Transactions
209
+ { command: 'begin' }
210
+ { command: 'commit' }
211
+ { command: 'rollback' }
212
+
213
+ // Prepared statements
214
+ { command: 'prepare', name: string }
215
+ { command: 'deallocate', name: string }
216
+ ```
217
+
218
+ ### Value Mapping
219
+
220
+ | SQL Type | JavaScript Type |
221
+ |----------|----------------|
222
+ | INT, BIGINT, DOUBLE, NUMERIC | `number` |
223
+ | TEXT, CHAR, VARCHAR | `string` |
224
+ | BOOLEAN | `boolean` |
225
+ | UUID | `string` |
226
+ | TIMESTAMP | `Date` |
227
+ | ENUM | `string` (label) |
228
+ | JSON array | `Array` |
229
+ | JSON object | `Object` |
230
+ | NULL | `null` |
231
+
232
+ ## TypeScript
233
+
234
+ Full type definitions are included. Use discriminated unions to narrow result types:
235
+
236
+ ```typescript
237
+ import { ConnectSQL, ExecuteResult } from '@petradb/engine';
238
+
239
+ const db = new ConnectSQL();
240
+ const results: ExecuteResult[] = db.execute('SELECT * FROM users');
241
+
242
+ for (const result of results) {
243
+ if (result.command === 'select') {
244
+ // result.rows and result.fields are typed here
245
+ }
246
+ }
247
+ ```
248
+
249
+ ## Example
250
+
251
+ ```javascript
252
+ import { ConnectSQL } from '@petradb/engine';
253
+
254
+ const db = new ConnectSQL();
255
+
256
+ db.execute(`
257
+ CREATE TYPE status AS ENUM ('active', 'inactive');
258
+ CREATE TABLE products (
259
+ id SERIAL,
260
+ name TEXT NOT NULL,
261
+ price NUMERIC(10,2),
262
+ status status DEFAULT 'active',
263
+ tags JSON,
264
+ created_at TIMESTAMP,
265
+ PRIMARY KEY (id)
266
+ )
267
+ `);
268
+
269
+ db.execute(`
270
+ INSERT INTO products (name, price, tags, created_at) VALUES
271
+ ('Laptop', 999.99, '["electronics", "computers"]', '2025-01-15 10:30:00');
272
+ INSERT INTO products (name, price, tags, created_at) VALUES
273
+ ('Coffee', 4.50, '["food", "organic"]', '2025-01-16 08:00:00')
274
+ `);
275
+
276
+ const [{ rows }] = db.execute(`
277
+ SELECT name, price FROM products
278
+ WHERE price > 10
279
+ ORDER BY price DESC
280
+ `);
281
+
282
+ console.log(rows); // [{ name: 'Laptop', price: 999.99 }]
283
+ ```
284
+
285
+ ## License
286
+
287
+ [ISC](https://opensource.org/licenses/ISC)
package/index.d.ts ADDED
@@ -0,0 +1,118 @@
1
+ export interface ConnectSQLOptions {
2
+ rowMode?: 'object' | 'array';
3
+ }
4
+
5
+ export interface ExecuteOptions {
6
+ rowMode?: 'object' | 'array';
7
+ }
8
+
9
+ export interface FieldInfo {
10
+ name: string;
11
+ dataType: string;
12
+ }
13
+
14
+ export interface CreateTableResult {
15
+ command: 'create table';
16
+ table: string;
17
+ }
18
+
19
+ export interface DropTableResult {
20
+ command: 'drop table';
21
+ table: string;
22
+ }
23
+
24
+ export interface CreateTypeResult {
25
+ command: 'create type';
26
+ type: string;
27
+ }
28
+
29
+ export interface DropTypeResult {
30
+ command: 'drop type';
31
+ type: string;
32
+ }
33
+
34
+ export interface CreateIndexResult {
35
+ command: 'create index';
36
+ index: string;
37
+ }
38
+
39
+ export interface DropIndexResult {
40
+ command: 'drop index';
41
+ index: string;
42
+ }
43
+
44
+ export interface TruncateTableResult {
45
+ command: 'truncate table';
46
+ table: string;
47
+ }
48
+
49
+ export interface AlterTableResult {
50
+ command: 'alter table';
51
+ }
52
+
53
+ export interface PrepareResult {
54
+ command: 'prepare';
55
+ name: string;
56
+ }
57
+
58
+ export interface DeallocateResult {
59
+ command: 'deallocate';
60
+ name: string;
61
+ }
62
+
63
+ export interface BeginResult {
64
+ command: 'begin';
65
+ }
66
+
67
+ export interface CommitResult {
68
+ command: 'commit';
69
+ }
70
+
71
+ export interface RollbackResult {
72
+ command: 'rollback';
73
+ }
74
+
75
+ export interface InsertResult {
76
+ command: 'insert';
77
+ result: Record<string, any>;
78
+ }
79
+
80
+ export interface SelectResult<T = Record<string, any>> {
81
+ command: 'select';
82
+ rows: T[];
83
+ fields: FieldInfo[];
84
+ }
85
+
86
+ export interface UpdateResult {
87
+ command: 'update';
88
+ rows: number;
89
+ }
90
+
91
+ export interface DeleteResult {
92
+ command: 'delete';
93
+ rows: number;
94
+ }
95
+
96
+ export type ExecuteResult =
97
+ | CreateTableResult
98
+ | DropTableResult
99
+ | CreateTypeResult
100
+ | DropTypeResult
101
+ | CreateIndexResult
102
+ | DropIndexResult
103
+ | TruncateTableResult
104
+ | AlterTableResult
105
+ | InsertResult
106
+ | SelectResult
107
+ | UpdateResult
108
+ | DeleteResult
109
+ | PrepareResult
110
+ | DeallocateResult
111
+ | BeginResult
112
+ | CommitResult
113
+ | RollbackResult;
114
+
115
+ export class ConnectSQL {
116
+ constructor(options?: ConnectSQLOptions);
117
+ execute(sql: string, options?: ExecuteOptions): ExecuteResult[];
118
+ }