@petradb/engine 1.1.0 → 1.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.
Files changed (4) hide show
  1. package/README.md +9 -264
  2. package/index.d.ts +12 -0
  3. package/main.js +86034 -46104
  4. package/package.json +2 -2
package/README.md CHANGED
@@ -1,4 +1,6 @@
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.
1
+ # @petradb/engine
2
+
3
+ A lightweight, embeddable SQL database engine for JavaScript and TypeScript. No native dependencies, no external services — just import and query. Follows PostgreSQL conventions.
2
4
 
3
5
  ## Installation
4
6
 
@@ -14,274 +16,17 @@ import { Session } from '@petradb/engine';
14
16
  const db = new Session();
15
17
 
16
18
  await db.execute(`
17
- CREATE TABLE users (
18
- id SERIAL,
19
- name TEXT NOT NULL,
20
- email TEXT,
21
- PRIMARY KEY (id)
22
- )
19
+ CREATE TABLE users (id SERIAL, name TEXT NOT NULL, email TEXT);
20
+ INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
23
21
  `);
24
22
 
25
- await db.execute("INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')");
26
- await db.execute("INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com')");
27
-
28
- const [{ rows, fields }] = await 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 Session({ rowMode: 'array' });
40
-
41
- // Or override per call
42
- const [{ rows }] = await 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
- INSERT ... ON CONFLICT (col) DO UPDATE SET ... -- upsert with EXCLUDED pseudo-table
103
- ```
104
-
105
- ### Queries
106
-
107
- ```sql
108
- SELECT, SELECT DISTINCT, WHERE, ORDER BY, LIMIT, OFFSET
109
- GROUP BY, HAVING
110
- JOIN (INNER/LEFT/RIGHT/FULL/CROSS)
111
- LATERAL joins -- correlated subqueries in FROM
112
- Subqueries, EXISTS, IN, = ANY(...)
113
- VALUES as standalone query and FROM source
114
- Column aliases: AS alias (col1, col2, ...)
115
- CASE expressions, BETWEEN, LIKE, ILIKE
116
- UNION, INTERSECT, EXCEPT
117
- OVERLAPS -- date/time range overlap test
118
- CAST(expr AS type), expr::type
119
- ```
120
-
121
- ### Constraints
122
-
123
- ```sql
124
- PRIMARY KEY, UNIQUE, NOT NULL, DEFAULT
125
- FOREIGN KEY ... REFERENCES ... ON DELETE/UPDATE (CASCADE, SET NULL, RESTRICT)
126
- ```
127
-
128
- ### Transactions
129
-
130
- ```sql
131
- BEGIN, COMMIT, ROLLBACK
132
- ```
133
-
134
- ### Prepared Statements
135
-
136
- ```sql
137
- PREPARE name AS statement -- with $1, $2, ... parameters
138
- EXECUTE name(arg1, arg2, ...)
139
- DEALLOCATE name
23
+ const [{ rows }] = await db.execute('SELECT * FROM users');
24
+ console.log(rows); // [{ id: 1, name: 'Alice', email: 'alice@example.com' }]
140
25
  ```
141
26
 
142
- ### Aggregate Functions
143
-
144
- `COUNT`, `SUM`, `AVG`, `MIN`, `MAX`, `string_agg`, `array_agg`, `bool_and`, `bool_or`, `every`, `variance`, `var_samp`, `var_pop`, `stddev`, `stddev_samp`, `stddev_pop`
145
-
146
- ### Built-in Functions
147
-
148
- **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`
149
-
150
- **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)
151
-
152
- **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`
153
-
154
- **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`
155
-
156
- **Other:** `coalesce`, `nullif`, `typeof`, `gen_random_uuid`, `octet_length`, `encode`, `decode`
157
-
158
- ## API
159
-
160
- ### `new Session(options?)`
161
-
162
- Creates a new database instance. Each instance is fully isolated.
27
+ ## Documentation
163
28
 
164
- | Option | Type | Default | Description |
165
- |--------|------|---------|-------------|
166
- | `rowMode` | `'object' \| 'array'` | `'object'` | Default row format for SELECT results |
167
-
168
- ### `db.execute(sql, options?)`
169
-
170
- Executes one or more SQL statements separated by `;`. Returns a promise that resolves to an array of results.
171
-
172
- | Option | Type | Default | Description |
173
- |--------|------|---------|-------------|
174
- | `rowMode` | `'object' \| 'array'` | constructor default | Row format for this call |
175
-
176
- ### `db.prepare(sql)`
177
-
178
- Creates a prepared statement with `$1`, `$2`, ... parameter placeholders. Returns a statement object with an `execute(params, options?)` method.
179
-
180
- ```javascript
181
- const stmt = db.prepare('SELECT * FROM users WHERE id = $1');
182
- const [{ rows }] = await stmt.execute([42]);
183
-
184
- // With options
185
- const [{ rows }] = await stmt.execute([42], { rowMode: 'array' });
186
- ```
187
-
188
- ### Result Types
189
-
190
- Every result has a `command` field for easy discrimination:
191
-
192
- ```typescript
193
- // DDL
194
- { command: 'create table', table: string }
195
- { command: 'drop table', table: string }
196
- { command: 'create type', type: string }
197
- { command: 'drop type', type: string }
198
- { command: 'create index', index: string }
199
- { command: 'drop index', index: string }
200
- { command: 'truncate table', table: string }
201
- { command: 'alter table' }
202
-
203
- // DML
204
- { command: 'insert', result: Record<string, any>, rows: T[], fields: FieldInfo[] }
205
- { command: 'select', rows: T[], fields: { name: string, dataType: string }[] }
206
- { command: 'update', rowCount: number }
207
- { command: 'delete', rowCount: number }
208
-
209
- // Transactions
210
- { command: 'begin' }
211
- { command: 'commit' }
212
- { command: 'rollback' }
213
-
214
- // Prepared statements
215
- { command: 'prepare', name: string }
216
- { command: 'deallocate', name: string }
217
- ```
218
-
219
- ### Value Mapping
220
-
221
- | SQL Type | JavaScript Type |
222
- |----------|----------------|
223
- | INT, BIGINT, DOUBLE, NUMERIC | `number` |
224
- | TEXT, CHAR, VARCHAR | `string` |
225
- | BOOLEAN | `boolean` |
226
- | UUID | `string` |
227
- | TIMESTAMP | `Date` |
228
- | ENUM | `string` (label) |
229
- | JSON array | `Array` |
230
- | JSON object | `Object` |
231
- | NULL | `null` |
232
-
233
- ## TypeScript
234
-
235
- Full type definitions are included. Use discriminated unions to narrow result types:
236
-
237
- ```typescript
238
- import { Session, ExecuteResult } from '@petradb/engine';
239
-
240
- const db = new Session();
241
- const results: ExecuteResult[] = await db.execute('SELECT * FROM users');
242
-
243
- for (const result of results) {
244
- if (result.command === 'select') {
245
- // result.rows and result.fields are typed here
246
- }
247
- }
248
- ```
249
-
250
- ## Example
251
-
252
- ```javascript
253
- import { Session } from '@petradb/engine';
254
-
255
- const db = new Session();
256
-
257
- await db.execute(`
258
- CREATE TYPE status AS ENUM ('active', 'inactive');
259
- CREATE TABLE products (
260
- id SERIAL,
261
- name TEXT NOT NULL,
262
- price NUMERIC(10,2),
263
- status status DEFAULT 'active',
264
- tags JSON,
265
- created_at TIMESTAMP,
266
- PRIMARY KEY (id)
267
- )
268
- `);
269
-
270
- await db.execute(`
271
- INSERT INTO products (name, price, tags, created_at) VALUES
272
- ('Laptop', 999.99, '["electronics", "computers"]', '2025-01-15 10:30:00');
273
- INSERT INTO products (name, price, tags, created_at) VALUES
274
- ('Coffee', 4.50, '["food", "organic"]', '2025-01-16 08:00:00')
275
- `);
276
-
277
- const [{ rows }] = await db.execute(`
278
- SELECT name, price FROM products
279
- WHERE price > 10
280
- ORDER BY price DESC
281
- `);
282
-
283
- console.log(rows); // [{ name: 'Laptop', price: 999.99 }]
284
- ```
29
+ Full documentation, SQL reference, and API details are available at **[petradb.dev](https://petradb.dev)**.
285
30
 
286
31
  ## License
287
32
 
package/index.d.ts CHANGED
@@ -50,6 +50,16 @@ export interface AlterTableResult {
50
50
  command: 'alter table';
51
51
  }
52
52
 
53
+ export interface CreateViewResult {
54
+ command: 'create view';
55
+ view: string;
56
+ }
57
+
58
+ export interface DropViewResult {
59
+ command: 'drop view';
60
+ view: string;
61
+ }
62
+
53
63
  export interface PrepareResult {
54
64
  command: 'prepare';
55
65
  name: string;
@@ -104,6 +114,8 @@ export type ExecuteResult =
104
114
  | DropIndexResult
105
115
  | TruncateTableResult
106
116
  | AlterTableResult
117
+ | CreateViewResult
118
+ | DropViewResult
107
119
  | InsertResult
108
120
  | SelectResult
109
121
  | UpdateResult