bisonbase 0.0.0-stage → 0.1.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.
- package/README.md +112 -2
- package/dist/auth.d.ts +16 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +75 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +149 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +478 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +12 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +34 -0
- package/dist/react.js.map +1 -0
- package/dist/schema.d.ts +22 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +57 -0
- package/dist/schema.js.map +1 -0
- package/dist/sql.d.ts +29 -0
- package/dist/sql.d.ts.map +1 -0
- package/dist/sql.js +203 -0
- package/dist/sql.js.map +1 -0
- package/dist/table.d.ts +20 -0
- package/dist/table.d.ts.map +1 -0
- package/dist/table.js +30 -0
- package/dist/table.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/values.d.ts +10 -0
- package/dist/values.d.ts.map +1 -0
- package/dist/values.js +109 -0
- package/dist/values.js.map +1 -0
- package/package.json +48 -4
- package/src/auth.ts +90 -0
- package/src/client.ts +551 -0
- package/src/index.ts +29 -0
- package/src/react.tsx +56 -0
- package/src/schema.ts +67 -0
- package/src/sql.ts +204 -0
- package/src/table.ts +48 -0
- package/src/types.ts +87 -0
- package/src/values.ts +99 -0
package/dist/schema.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Bringing a per-user database in line with the tables the app declares: create missing
|
|
2
|
+
// tables, add new columns, and refuse anything that would change or drop existing data.
|
|
3
|
+
import { addColumnSql, createTableSql, SQL_TYPES } from "./sql.js";
|
|
4
|
+
/** The database's tables don't match the app's and can't be changed to match safely. */
|
|
5
|
+
export class SchemaError extends Error {
|
|
6
|
+
name = 'SchemaError';
|
|
7
|
+
}
|
|
8
|
+
/** The statements that bring `server` in line with `tables`. Throws SchemaError if that's unsafe. */
|
|
9
|
+
export function migrationSql(tables, server, db) {
|
|
10
|
+
const existing = new Map(server.tables.map((t) => [t.name.toLowerCase(), t]));
|
|
11
|
+
const statements = [];
|
|
12
|
+
const fail = (table, msg) => {
|
|
13
|
+
throw new SchemaError(`Table "${table}" in ${db}: ${msg}`);
|
|
14
|
+
};
|
|
15
|
+
for (const table of tables) {
|
|
16
|
+
const found = existing.get(table.name.toLowerCase());
|
|
17
|
+
if (!found) {
|
|
18
|
+
statements.push(createTableSql(table));
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (found.type !== 'table')
|
|
22
|
+
fail(table.name, `the database has a ${found.type} with this name`);
|
|
23
|
+
const cols = new Map(found.columns.map((c) => [c.name.toLowerCase(), c]));
|
|
24
|
+
const id = cols.get('id');
|
|
25
|
+
if (!id || !id.pk || id.type.toUpperCase() !== 'INTEGER') {
|
|
26
|
+
fail(table.name, 'it exists but has no "id INTEGER PRIMARY KEY" column, so it wasn\'t created by this library');
|
|
27
|
+
}
|
|
28
|
+
if (found.columns.filter((c) => c.pk).length > 1)
|
|
29
|
+
fail(table.name, 'it has a composite primary key');
|
|
30
|
+
for (const col of table.columns) {
|
|
31
|
+
const have = cols.get(col.name.toLowerCase());
|
|
32
|
+
const want = SQL_TYPES[col.type];
|
|
33
|
+
if (!have) {
|
|
34
|
+
if (!col.nullable && !col.default) {
|
|
35
|
+
fail(table.name, `new column "${col.name}" needs a default (or make it nullable) so existing rows get a value`);
|
|
36
|
+
}
|
|
37
|
+
statements.push(addColumnSql(table, col));
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (have.type.toUpperCase() !== want) {
|
|
41
|
+
fail(table.name, `column "${col.name}" is ${have.type || 'untyped'} in the database but declared as ${col.type}; changing a column's type isn't supported`);
|
|
42
|
+
}
|
|
43
|
+
if (have.not_null === col.nullable) {
|
|
44
|
+
const [was, now] = have.not_null ? ['NOT NULL', 'nullable'] : ['nullable', 'not nullable'];
|
|
45
|
+
fail(table.name, `column "${col.name}" is ${was} in the database but declared ${now}; changing that isn't supported`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const have of found.columns) {
|
|
49
|
+
const name = have.name.toLowerCase();
|
|
50
|
+
if (name !== 'id' && !table.columns.some((c) => c.name.toLowerCase() === name)) {
|
|
51
|
+
fail(table.name, `column "${have.name}" is in the database but not declared; removing columns isn't supported because it would lose data. Declare it again`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return statements;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/sql.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ColumnDef, TableDef } from './table.ts';
|
|
2
|
+
import type { ColumnType, Wire } from './types.ts';
|
|
3
|
+
export interface Statement {
|
|
4
|
+
sql: string;
|
|
5
|
+
params: Wire[];
|
|
6
|
+
}
|
|
7
|
+
export declare const quote: (name: string) => string;
|
|
8
|
+
export declare const SQL_TYPES: Record<ColumnType, string>;
|
|
9
|
+
/** A default value as an SQL literal (DEFAULT clauses can't take parameters). */
|
|
10
|
+
export declare function literal(col: ColumnDef, value: unknown): string;
|
|
11
|
+
/** A column definition for CREATE TABLE or ALTER TABLE ADD COLUMN. */
|
|
12
|
+
export declare function columnSql(col: ColumnDef): string;
|
|
13
|
+
export declare function createTableSql(table: TableDef): string;
|
|
14
|
+
export declare function addColumnSql(table: TableDef, col: ColumnDef): string;
|
|
15
|
+
/** A WHERE clause (including the keyword, or empty) and its parameters. */
|
|
16
|
+
export declare function whereSql(table: TableDef, where: object | number | undefined, params: Wire[]): string;
|
|
17
|
+
export interface SelectSpec {
|
|
18
|
+
where?: object | number;
|
|
19
|
+
orderBy?: string | readonly string[];
|
|
20
|
+
limit?: number;
|
|
21
|
+
offset?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function selectSql(table: TableDef, opts?: SelectSpec): Statement;
|
|
24
|
+
/** INSERT one row, filling in defaults here so the code's defaults win over the database's. */
|
|
25
|
+
export declare function insertSql(table: TableDef, row: Record<string, unknown>): Statement;
|
|
26
|
+
/** UPDATE matching rows, or null when there's nothing to set. */
|
|
27
|
+
export declare function updateSql(table: TableDef, where: object | number, changes: Record<string, unknown>): Statement | null;
|
|
28
|
+
export declare function deleteSql(table: TableDef, where: object | number): Statement;
|
|
29
|
+
//# sourceMappingURL=sql.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAElD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,IAAI,EAAE,CAAA;CACf;AAED,eAAO,MAAM,KAAK,GAAI,MAAM,MAAM,WAAsC,CAAA;AAExE,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAOhD,CAAA;AAWD,iFAAiF;AACjF,wBAAgB,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAO9D;AAED,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAKhD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAGtD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,MAAM,CAEpE;AAYD,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAyCpG;AAsBD,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAE,UAAe,GAAG,SAAS,CAgB3E;AAED,+FAA+F;AAC/F,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAsBlF;AAED,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,CAarH;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG5E"}
|
package/dist/sql.js
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// Compiles structured operations (select / insert / update / delete) to SQL with quoted
|
|
2
|
+
// identifiers and bound parameters. Nothing outside this file and schema.ts writes SQL, so
|
|
3
|
+
// these operations can later move to a server-side relational API without changing callers.
|
|
4
|
+
import { encode } from "./values.js";
|
|
5
|
+
export const quote = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
6
|
+
export const SQL_TYPES = {
|
|
7
|
+
text: 'TEXT',
|
|
8
|
+
integer: 'INTEGER',
|
|
9
|
+
real: 'REAL',
|
|
10
|
+
boolean: 'BOOLEAN',
|
|
11
|
+
blob: 'BLOB',
|
|
12
|
+
json: 'JSON',
|
|
13
|
+
};
|
|
14
|
+
const ID = { name: 'id', type: 'integer', nullable: false };
|
|
15
|
+
function column(table, name) {
|
|
16
|
+
if (name === 'id')
|
|
17
|
+
return ID;
|
|
18
|
+
const col = table.byName.get(name);
|
|
19
|
+
if (!col)
|
|
20
|
+
throw new Error(`Table "${table.name}" has no column "${name}"`);
|
|
21
|
+
return col;
|
|
22
|
+
}
|
|
23
|
+
/** A default value as an SQL literal (DEFAULT clauses can't take parameters). */
|
|
24
|
+
export function literal(col, value) {
|
|
25
|
+
const wire = encode(col.type, col.nullable, value, col.name);
|
|
26
|
+
if (wire === null)
|
|
27
|
+
return 'NULL';
|
|
28
|
+
if (typeof wire === 'number')
|
|
29
|
+
return String(wire);
|
|
30
|
+
if (typeof wire === 'string')
|
|
31
|
+
return `'${wire.replaceAll("'", "''")}'`;
|
|
32
|
+
const hex = Array.from(atob(wire.$base64), (c) => c.charCodeAt(0).toString(16).padStart(2, '0')).join('');
|
|
33
|
+
return `X'${hex}'`;
|
|
34
|
+
}
|
|
35
|
+
/** A column definition for CREATE TABLE or ALTER TABLE ADD COLUMN. */
|
|
36
|
+
export function columnSql(col) {
|
|
37
|
+
let sql = `${quote(col.name)} ${SQL_TYPES[col.type]}`;
|
|
38
|
+
if (!col.nullable)
|
|
39
|
+
sql += ' NOT NULL';
|
|
40
|
+
if (col.default)
|
|
41
|
+
sql += ` DEFAULT ${literal(col, col.default.value)}`;
|
|
42
|
+
return sql;
|
|
43
|
+
}
|
|
44
|
+
export function createTableSql(table) {
|
|
45
|
+
const cols = [`"id" INTEGER PRIMARY KEY`, ...table.columns.map(columnSql)];
|
|
46
|
+
return `CREATE TABLE IF NOT EXISTS ${quote(table.name)} (${cols.join(', ')})`;
|
|
47
|
+
}
|
|
48
|
+
export function addColumnSql(table, col) {
|
|
49
|
+
return `ALTER TABLE ${quote(table.name)} ADD COLUMN ${columnSql(col)}`;
|
|
50
|
+
}
|
|
51
|
+
const allColumns = (table) => ['id', ...table.columns.map((c) => c.name)].map(quote).join(', ');
|
|
52
|
+
const OPS = { $ne: '<>', $lt: '<', $lte: '<=', $gt: '>', $gte: '>=' };
|
|
53
|
+
function isOps(value) {
|
|
54
|
+
if (typeof value !== 'object' || value === null || value instanceof Uint8Array || Array.isArray(value))
|
|
55
|
+
return false;
|
|
56
|
+
const keys = Object.keys(value);
|
|
57
|
+
return keys.length > 0 && keys.every((k) => k.startsWith('$'));
|
|
58
|
+
}
|
|
59
|
+
/** A WHERE clause (including the keyword, or empty) and its parameters. */
|
|
60
|
+
export function whereSql(table, where, params) {
|
|
61
|
+
if (where === undefined)
|
|
62
|
+
return '';
|
|
63
|
+
if (typeof where === 'number')
|
|
64
|
+
where = { id: where };
|
|
65
|
+
const terms = [];
|
|
66
|
+
for (const [name, cond] of Object.entries(where)) {
|
|
67
|
+
const col = column(table, name);
|
|
68
|
+
const q = quote(name);
|
|
69
|
+
if (cond === undefined)
|
|
70
|
+
throw new Error(`where.${name} is undefined; leave it out or use null`);
|
|
71
|
+
if (!isOps(cond)) {
|
|
72
|
+
if (cond === null)
|
|
73
|
+
terms.push(`${q} IS NULL`);
|
|
74
|
+
else {
|
|
75
|
+
terms.push(`${q} = ?`);
|
|
76
|
+
params.push(encode(col.type, col.nullable, cond, name));
|
|
77
|
+
}
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
for (const [op, value] of Object.entries(cond)) {
|
|
81
|
+
if (value === undefined)
|
|
82
|
+
continue;
|
|
83
|
+
if (op === '$in') {
|
|
84
|
+
if (!Array.isArray(value))
|
|
85
|
+
throw new Error(`where.${name}.$in must be an array`);
|
|
86
|
+
if (value.length === 0) {
|
|
87
|
+
terms.push('0');
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
terms.push(`${q} IN (${value.map(() => '?').join(', ')})`);
|
|
91
|
+
for (const v of value)
|
|
92
|
+
params.push(encode(col.type, col.nullable, v, name));
|
|
93
|
+
}
|
|
94
|
+
else if (op === '$ne' && value === null) {
|
|
95
|
+
terms.push(`${q} IS NOT NULL`);
|
|
96
|
+
}
|
|
97
|
+
else if (op === '$ne') {
|
|
98
|
+
// Like JavaScript's !==, NULL counts as different from any value.
|
|
99
|
+
terms.push(`${q} IS NOT ?`);
|
|
100
|
+
params.push(encode(col.type, col.nullable, value, name));
|
|
101
|
+
}
|
|
102
|
+
else if (OPS[op]) {
|
|
103
|
+
terms.push(`${q} ${OPS[op]} ?`);
|
|
104
|
+
params.push(encode(col.type, col.nullable, value, name));
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
throw new Error(`Unknown operator where.${name}.${op}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return terms.length ? ` WHERE ${terms.join(' AND ')}` : '';
|
|
112
|
+
}
|
|
113
|
+
function orderSql(table, orderBy) {
|
|
114
|
+
if (orderBy === undefined)
|
|
115
|
+
return '';
|
|
116
|
+
const items = typeof orderBy === 'string' ? [orderBy] : orderBy;
|
|
117
|
+
if (items.length === 0)
|
|
118
|
+
return '';
|
|
119
|
+
const parts = items.map((item) => {
|
|
120
|
+
const [name, dir = 'asc', ...rest] = item.trim().split(/\s+/);
|
|
121
|
+
const d = dir.toLowerCase();
|
|
122
|
+
if (rest.length || (d !== 'asc' && d !== 'desc'))
|
|
123
|
+
throw new Error(`Bad orderBy "${item}"; use "column" or "column desc"`);
|
|
124
|
+
column(table, name);
|
|
125
|
+
return `${quote(name)} ${d.toUpperCase()}`;
|
|
126
|
+
});
|
|
127
|
+
return ` ORDER BY ${parts.join(', ')}`;
|
|
128
|
+
}
|
|
129
|
+
function count(name, n) {
|
|
130
|
+
if (n === undefined)
|
|
131
|
+
return false;
|
|
132
|
+
if (!Number.isSafeInteger(n) || n < 0)
|
|
133
|
+
throw new Error(`${name} must be a non-negative integer`);
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
export function selectSql(table, opts = {}) {
|
|
137
|
+
const params = [];
|
|
138
|
+
let sql = `SELECT ${allColumns(table)} FROM ${quote(table.name)}`;
|
|
139
|
+
sql += whereSql(table, opts.where, params);
|
|
140
|
+
sql += orderSql(table, opts.orderBy);
|
|
141
|
+
const hasLimit = count('limit', opts.limit);
|
|
142
|
+
const hasOffset = count('offset', opts.offset);
|
|
143
|
+
if (hasLimit || hasOffset) {
|
|
144
|
+
sql += ' LIMIT ?';
|
|
145
|
+
params.push(hasLimit ? opts.limit : -1);
|
|
146
|
+
}
|
|
147
|
+
if (hasOffset) {
|
|
148
|
+
sql += ' OFFSET ?';
|
|
149
|
+
params.push(opts.offset);
|
|
150
|
+
}
|
|
151
|
+
return { sql, params };
|
|
152
|
+
}
|
|
153
|
+
/** INSERT one row, filling in defaults here so the code's defaults win over the database's. */
|
|
154
|
+
export function insertSql(table, row) {
|
|
155
|
+
for (const name of Object.keys(row))
|
|
156
|
+
column(table, name);
|
|
157
|
+
const names = [];
|
|
158
|
+
const params = [];
|
|
159
|
+
if (row.id !== undefined) {
|
|
160
|
+
names.push('id');
|
|
161
|
+
params.push(encode('integer', false, row.id, 'id'));
|
|
162
|
+
}
|
|
163
|
+
for (const col of table.columns) {
|
|
164
|
+
let value = row[col.name];
|
|
165
|
+
if (value === undefined) {
|
|
166
|
+
if (col.default)
|
|
167
|
+
value = col.default.value;
|
|
168
|
+
else if (col.nullable)
|
|
169
|
+
value = null;
|
|
170
|
+
else
|
|
171
|
+
throw new Error(`Missing value for column "${col.name}" of table "${table.name}"`);
|
|
172
|
+
}
|
|
173
|
+
names.push(col.name);
|
|
174
|
+
params.push(encode(col.type, col.nullable, value, col.name));
|
|
175
|
+
}
|
|
176
|
+
const sql = names.length
|
|
177
|
+
? `INSERT INTO ${quote(table.name)} (${names.map(quote).join(', ')}) VALUES (${names.map(() => '?').join(', ')})`
|
|
178
|
+
: `INSERT INTO ${quote(table.name)} DEFAULT VALUES`;
|
|
179
|
+
return { sql: `${sql} RETURNING ${allColumns(table)}`, params };
|
|
180
|
+
}
|
|
181
|
+
/** UPDATE matching rows, or null when there's nothing to set. */
|
|
182
|
+
export function updateSql(table, where, changes) {
|
|
183
|
+
const params = [];
|
|
184
|
+
const sets = [];
|
|
185
|
+
for (const [name, value] of Object.entries(changes)) {
|
|
186
|
+
if (value === undefined)
|
|
187
|
+
continue;
|
|
188
|
+
if (name === 'id')
|
|
189
|
+
throw new Error("A row's id can't be changed");
|
|
190
|
+
const col = column(table, name);
|
|
191
|
+
sets.push(`${quote(name)} = ?`);
|
|
192
|
+
params.push(encode(col.type, col.nullable, value, name));
|
|
193
|
+
}
|
|
194
|
+
if (sets.length === 0)
|
|
195
|
+
return null;
|
|
196
|
+
const sql = `UPDATE ${quote(table.name)} SET ${sets.join(', ')}${whereSql(table, where, params)}`;
|
|
197
|
+
return { sql, params };
|
|
198
|
+
}
|
|
199
|
+
export function deleteSql(table, where) {
|
|
200
|
+
const params = [];
|
|
201
|
+
return { sql: `DELETE FROM ${quote(table.name)}${whereSql(table, where, params)}`, params };
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=sql.js.map
|
package/dist/sql.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql.js","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"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"}
|
package/dist/table.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ColumnType, Columns } from './types.ts';
|
|
2
|
+
export interface ColumnDef {
|
|
3
|
+
name: string;
|
|
4
|
+
type: ColumnType;
|
|
5
|
+
nullable: boolean;
|
|
6
|
+
/** Present when the column has a default. */
|
|
7
|
+
default?: {
|
|
8
|
+
value: unknown;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export interface TableDef {
|
|
12
|
+
name: string;
|
|
13
|
+
/** Every column except `id`, in declaration order. */
|
|
14
|
+
columns: ColumnDef[];
|
|
15
|
+
byName: Map<string, ColumnDef>;
|
|
16
|
+
}
|
|
17
|
+
/** Check that a table or column name is a plain identifier. */
|
|
18
|
+
export declare function checkName(kind: string, name: string): void;
|
|
19
|
+
export declare function parseTable(name: string, columns: Columns): TableDef;
|
|
20
|
+
//# sourceMappingURL=table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAEjE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAA;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,sDAAsD;IACtD,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CAC/B;AAKD,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAK1D;AAcD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,QAAQ,CAKnE"}
|
package/dist/table.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// A table's columns, normalized from the spec passed to createTable.
|
|
2
|
+
const TYPES = ['text', 'integer', 'real', 'boolean', 'blob', 'json'];
|
|
3
|
+
const IDENT = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
4
|
+
/** Check that a table or column name is a plain identifier. */
|
|
5
|
+
export function checkName(kind, name) {
|
|
6
|
+
if (!IDENT.test(name)) {
|
|
7
|
+
throw new Error(`${kind} name "${name}" must be letters, digits and underscores, not starting with a digit`);
|
|
8
|
+
}
|
|
9
|
+
if (name.toLowerCase().startsWith('sqlite_'))
|
|
10
|
+
throw new Error(`${kind} name "${name}" is reserved by SQLite`);
|
|
11
|
+
}
|
|
12
|
+
function parseColumn(name, spec) {
|
|
13
|
+
checkName('Column', name);
|
|
14
|
+
if (name.toLowerCase() === 'id')
|
|
15
|
+
throw new Error('Every table gets an "id" column automatically; don\'t declare one');
|
|
16
|
+
const [base, hasDefault, value] = Array.isArray(spec) ? [spec[0], true, spec[1]] : [spec, false, undefined];
|
|
17
|
+
const nullable = base.endsWith('?');
|
|
18
|
+
const type = (nullable ? base.slice(0, -1) : base);
|
|
19
|
+
if (!TYPES.includes(type)) {
|
|
20
|
+
throw new Error(`Column "${name}" has unknown type "${base}"; use one of ${TYPES.join(', ')}`);
|
|
21
|
+
}
|
|
22
|
+
return { name, type, nullable, ...(hasDefault ? { default: { value } } : {}) };
|
|
23
|
+
}
|
|
24
|
+
export function parseTable(name, columns) {
|
|
25
|
+
checkName('Table', name);
|
|
26
|
+
const defs = Object.entries(columns).map(([col, spec]) => parseColumn(col, spec));
|
|
27
|
+
const byName = new Map(defs.map((c) => [c.name, c]));
|
|
28
|
+
return { name, columns: defs, byName };
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","sourceRoot":"","sources":["../src/table.ts"],"names":[],"mappings":"AAAA,qEAAqE;AAmBrE,MAAM,KAAK,GAA0B,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAC3F,MAAM,KAAK,GAAG,0BAA0B,CAAA;AAExC,+DAA+D;AAC/D,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IAClD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,UAAU,IAAI,sEAAsE,CAAC,CAAA;IAC9G,CAAC;IACD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,UAAU,IAAI,yBAAyB,CAAC,CAAA;AAC/G,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,IAAgB;IACjD,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IACzB,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAA;IACrH,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAc,EAAE,KAAK,EAAE,SAAS,CAAC,CAAA;IACrH,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;IACnC,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAe,CAAA;IAChE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,uBAAuB,IAAI,iBAAiB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChG,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;AAChF,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,OAAgB;IACvD,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IACxB,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAA;IACjF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACxC,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/** The column types a table can declare. */
|
|
2
|
+
export type ColumnType = 'text' | 'integer' | 'real' | 'boolean' | 'blob' | 'json';
|
|
3
|
+
/** Any value that survives JSON.stringify / JSON.parse. */
|
|
4
|
+
export type Json = string | number | boolean | null | readonly Json[] | {
|
|
5
|
+
readonly [key: string]: Json;
|
|
6
|
+
};
|
|
7
|
+
interface TypeMap {
|
|
8
|
+
text: string;
|
|
9
|
+
integer: number;
|
|
10
|
+
real: number;
|
|
11
|
+
boolean: boolean;
|
|
12
|
+
blob: Uint8Array;
|
|
13
|
+
json: Json;
|
|
14
|
+
}
|
|
15
|
+
/** `"text"`, or `"text?"` for a nullable column. */
|
|
16
|
+
type BaseSpec = ColumnType | `${ColumnType}?`;
|
|
17
|
+
type ValueOfBase<B> = B extends `${infer T extends ColumnType}?` ? TypeMap[T] | null : B extends ColumnType ? TypeMap[B] : never;
|
|
18
|
+
/** `[type, default]`: the default must have the column's type. */
|
|
19
|
+
type WithDefault<B> = B extends BaseSpec ? readonly [B, ValueOfBase<B>] : never;
|
|
20
|
+
/**
|
|
21
|
+
* A column: `"text"`, `"text?"` (nullable), or `["boolean", false]` (with a default).
|
|
22
|
+
* Nullable columns and columns with a default are optional on insert.
|
|
23
|
+
*/
|
|
24
|
+
export type ColumnSpec = BaseSpec | WithDefault<BaseSpec>;
|
|
25
|
+
/** The columns passed to `createTable`. `id` is added automatically. */
|
|
26
|
+
export type Columns = {
|
|
27
|
+
readonly [name: string]: ColumnSpec;
|
|
28
|
+
};
|
|
29
|
+
type BaseOf<S> = S extends readonly [infer B, unknown] ? B : S;
|
|
30
|
+
/** The TypeScript type of a column's values. */
|
|
31
|
+
export type ValueOf<S> = ValueOfBase<BaseOf<S>>;
|
|
32
|
+
type Simplify<T> = {
|
|
33
|
+
[K in keyof T]: T[K];
|
|
34
|
+
} & {};
|
|
35
|
+
type OptionalKeys<C> = {
|
|
36
|
+
[K in keyof C]: C[K] extends readonly unknown[] ? K : C[K] extends `${string}?` ? K : never;
|
|
37
|
+
}[keyof C];
|
|
38
|
+
/** A row as read from a table with these columns. */
|
|
39
|
+
export type RowFor<C> = Simplify<{
|
|
40
|
+
id: number;
|
|
41
|
+
} & {
|
|
42
|
+
-readonly [K in keyof C]: ValueOf<C[K]>;
|
|
43
|
+
}>;
|
|
44
|
+
/** What `insert` takes: nullable columns and columns with a default may be left out. */
|
|
45
|
+
export type InsertFor<C> = Simplify<{
|
|
46
|
+
id?: number;
|
|
47
|
+
} & {
|
|
48
|
+
-readonly [K in Exclude<keyof C, OptionalKeys<C>>]: ValueOf<C[K]>;
|
|
49
|
+
} & {
|
|
50
|
+
-readonly [K in OptionalKeys<C>]?: ValueOf<C[K]>;
|
|
51
|
+
}>;
|
|
52
|
+
/** What `update` takes: any subset of the columns. */
|
|
53
|
+
export type UpdateFor<C> = Simplify<{
|
|
54
|
+
-readonly [K in keyof C]?: ValueOf<C[K]>;
|
|
55
|
+
}>;
|
|
56
|
+
/** Comparisons other than equality, e.g. `{ start: { $gte: from, $lt: to } }`. */
|
|
57
|
+
export interface Ops<T> {
|
|
58
|
+
$ne?: T;
|
|
59
|
+
$lt?: T;
|
|
60
|
+
$lte?: T;
|
|
61
|
+
$gt?: T;
|
|
62
|
+
$gte?: T;
|
|
63
|
+
$in?: readonly T[];
|
|
64
|
+
}
|
|
65
|
+
/** Rows match when every listed column matches. `null` matches NULL. */
|
|
66
|
+
export type Where<R> = {
|
|
67
|
+
[K in keyof R]?: R[K] | Ops<R[K]>;
|
|
68
|
+
};
|
|
69
|
+
/** A column name, optionally followed by `" asc"` or `" desc"`. */
|
|
70
|
+
export type OrderBy<R> = (keyof R & string) | `${keyof R & string} ${'asc' | 'desc'}`;
|
|
71
|
+
export interface SelectOptions<R> {
|
|
72
|
+
where?: Where<R>;
|
|
73
|
+
orderBy?: OrderBy<R> | readonly OrderBy<R>[];
|
|
74
|
+
limit?: number;
|
|
75
|
+
offset?: number;
|
|
76
|
+
}
|
|
77
|
+
/** A value as sent to or returned by the bisonbase API. */
|
|
78
|
+
export type Wire = string | number | null | {
|
|
79
|
+
$base64: string;
|
|
80
|
+
};
|
|
81
|
+
export {};
|
|
82
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qDAAqD"}
|
package/dist/values.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ColumnType, Wire } from './types.ts';
|
|
2
|
+
export declare function toBase64(bytes: Uint8Array): string;
|
|
3
|
+
export declare function fromBase64(b64: string): Uint8Array;
|
|
4
|
+
/** Convert a column value to its wire form, checking its type. `column` names it in errors. */
|
|
5
|
+
export declare function encode(type: ColumnType, nullable: boolean, value: unknown, column: string): Wire;
|
|
6
|
+
/** Convert a wire value read from a column back to its TypeScript form. */
|
|
7
|
+
export declare function decode(type: ColumnType, value: Wire): unknown;
|
|
8
|
+
/** Convert a value used in raw SQL (`db.sql`) to its wire form. */
|
|
9
|
+
export declare function encodeParam(value: unknown): Wire;
|
|
10
|
+
//# sourceMappingURL=values.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../src/values.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAElD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAMlD;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAKlD;AAmBD,+FAA+F;AAC/F,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CA+BhG;AAED,2EAA2E;AAC3E,wBAAgB,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,GAAG,OAAO,CAa7D;AAED,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAUhD"}
|
package/dist/values.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Converting values between their TypeScript form and what the API sends over the wire:
|
|
2
|
+
// booleans are stored as 0/1, blobs travel as {"$base64": ...}, json is stored as text.
|
|
3
|
+
export function toBase64(bytes) {
|
|
4
|
+
let s = '';
|
|
5
|
+
for (let i = 0; i < bytes.length; i += 0x8000) {
|
|
6
|
+
s += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
|
|
7
|
+
}
|
|
8
|
+
return btoa(s);
|
|
9
|
+
}
|
|
10
|
+
export function fromBase64(b64) {
|
|
11
|
+
const s = atob(b64);
|
|
12
|
+
const bytes = new Uint8Array(s.length);
|
|
13
|
+
for (let i = 0; i < s.length; i++)
|
|
14
|
+
bytes[i] = s.charCodeAt(i);
|
|
15
|
+
return bytes;
|
|
16
|
+
}
|
|
17
|
+
/** Describe a value for an error message. */
|
|
18
|
+
function describe(value) {
|
|
19
|
+
if (value === null)
|
|
20
|
+
return 'null';
|
|
21
|
+
if (value instanceof Uint8Array)
|
|
22
|
+
return 'Uint8Array';
|
|
23
|
+
if (Array.isArray(value))
|
|
24
|
+
return 'array';
|
|
25
|
+
return typeof value;
|
|
26
|
+
}
|
|
27
|
+
const EXPECTED = {
|
|
28
|
+
text: 'a string',
|
|
29
|
+
integer: 'an integer',
|
|
30
|
+
real: 'a finite number',
|
|
31
|
+
boolean: 'a boolean',
|
|
32
|
+
blob: 'a Uint8Array',
|
|
33
|
+
json: 'a JSON value',
|
|
34
|
+
};
|
|
35
|
+
/** Convert a column value to its wire form, checking its type. `column` names it in errors. */
|
|
36
|
+
export function encode(type, nullable, value, column) {
|
|
37
|
+
const bad = () => new TypeError(`Column "${column}" expects ${EXPECTED[type]}${nullable ? ' or null' : ''}, got ${describe(value)}`);
|
|
38
|
+
if (value === undefined)
|
|
39
|
+
throw bad();
|
|
40
|
+
if (value === null) {
|
|
41
|
+
if (nullable)
|
|
42
|
+
return null;
|
|
43
|
+
if (type === 'json')
|
|
44
|
+
return 'null';
|
|
45
|
+
throw bad();
|
|
46
|
+
}
|
|
47
|
+
switch (type) {
|
|
48
|
+
case 'text':
|
|
49
|
+
if (typeof value !== 'string')
|
|
50
|
+
throw bad();
|
|
51
|
+
return value;
|
|
52
|
+
case 'integer':
|
|
53
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value))
|
|
54
|
+
throw bad();
|
|
55
|
+
return value;
|
|
56
|
+
case 'real':
|
|
57
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
58
|
+
throw bad();
|
|
59
|
+
return value;
|
|
60
|
+
case 'boolean':
|
|
61
|
+
if (typeof value !== 'boolean')
|
|
62
|
+
throw bad();
|
|
63
|
+
return value ? 1 : 0;
|
|
64
|
+
case 'blob':
|
|
65
|
+
if (!(value instanceof Uint8Array))
|
|
66
|
+
throw bad();
|
|
67
|
+
return { $base64: toBase64(value) };
|
|
68
|
+
case 'json': {
|
|
69
|
+
const text = JSON.stringify(value);
|
|
70
|
+
if (text === undefined)
|
|
71
|
+
throw bad();
|
|
72
|
+
return text;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Convert a wire value read from a column back to its TypeScript form. */
|
|
77
|
+
export function decode(type, value) {
|
|
78
|
+
if (value === null)
|
|
79
|
+
return null;
|
|
80
|
+
switch (type) {
|
|
81
|
+
case 'boolean':
|
|
82
|
+
return value !== 0 && value !== '0' && value !== '';
|
|
83
|
+
case 'blob':
|
|
84
|
+
return typeof value === 'object' ? fromBase64(value.$base64) : new TextEncoder().encode(String(value));
|
|
85
|
+
case 'json':
|
|
86
|
+
// SQLite may have stored numeric JSON as a number (the column has numeric affinity).
|
|
87
|
+
return typeof value === 'string' ? JSON.parse(value) : value;
|
|
88
|
+
default:
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Convert a value used in raw SQL (`db.sql`) to its wire form. */
|
|
93
|
+
export function encodeParam(value) {
|
|
94
|
+
if (value === null || typeof value === 'string')
|
|
95
|
+
return value;
|
|
96
|
+
if (typeof value === 'number') {
|
|
97
|
+
if (!Number.isFinite(value))
|
|
98
|
+
throw new TypeError(`SQL parameter must be finite, got ${value}`);
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
if (typeof value === 'boolean')
|
|
102
|
+
return value ? 1 : 0;
|
|
103
|
+
if (value instanceof Uint8Array)
|
|
104
|
+
return { $base64: toBase64(value) };
|
|
105
|
+
if (value === undefined)
|
|
106
|
+
throw new TypeError('SQL parameter is undefined');
|
|
107
|
+
return JSON.stringify(value);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=values.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.js","sourceRoot":"","sources":["../src/values.ts"],"names":[],"mappings":"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"}
|