openbase-js 0.1.2 → 0.1.3
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/index.cjs +156 -0
- package/index.js +3 -0
- package/package.json +1 -1
package/index.cjs
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// ─── Query Builder ────────────────────────────────────────────────────────────
|
|
2
|
+
|
|
3
|
+
class QueryBuilder {
|
|
4
|
+
constructor(baseUrl, apiKey, dbName, table) {
|
|
5
|
+
this._baseUrl = baseUrl;
|
|
6
|
+
this._apiKey = apiKey;
|
|
7
|
+
this._dbName = dbName;
|
|
8
|
+
this._table = table;
|
|
9
|
+
this._filters = {};
|
|
10
|
+
this._columns = '*';
|
|
11
|
+
this._limitVal = null;
|
|
12
|
+
this._single = false;
|
|
13
|
+
this._operation = 'select';
|
|
14
|
+
this._insertData = null;
|
|
15
|
+
this._updateData = null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
select(columns = '*') {
|
|
19
|
+
this._columns = columns;
|
|
20
|
+
this._operation = 'select';
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
eq(column, value) {
|
|
25
|
+
this._filters[column] = value;
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
limit(n) {
|
|
30
|
+
this._limitVal = n;
|
|
31
|
+
return this;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
single() {
|
|
35
|
+
this._single = true;
|
|
36
|
+
this._limitVal = 1;
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
insert(data) {
|
|
41
|
+
this._operation = 'insert';
|
|
42
|
+
this._insertData = data;
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
update(data) {
|
|
47
|
+
this._operation = 'update';
|
|
48
|
+
this._updateData = data;
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
delete() {
|
|
53
|
+
this._operation = 'delete';
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_buildSQL() {
|
|
58
|
+
let sql = '';
|
|
59
|
+
|
|
60
|
+
if (this._operation === 'select') {
|
|
61
|
+
sql = `SELECT ${this._columns} FROM "${this._table}"`;
|
|
62
|
+
const whereParts = Object.entries(this._filters).map(([col, val]) =>
|
|
63
|
+
typeof val === 'string' ? `"${col}" = '${val}'` : `"${col}" = ${val}`
|
|
64
|
+
);
|
|
65
|
+
if (whereParts.length) sql += ` WHERE ${whereParts.join(' AND ')}`;
|
|
66
|
+
if (this._limitVal) sql += ` LIMIT ${this._limitVal}`;
|
|
67
|
+
|
|
68
|
+
} else if (this._operation === 'insert') {
|
|
69
|
+
const cols = Object.keys(this._insertData).map(c => `"${c}"`).join(', ');
|
|
70
|
+
const vals = Object.values(this._insertData).map(v =>
|
|
71
|
+
typeof v === 'string' ? `'${v.replace(/'/g, "''")}'` : v
|
|
72
|
+
).join(', ');
|
|
73
|
+
sql = `INSERT INTO "${this._table}" (${cols}) VALUES (${vals}) RETURNING *`;
|
|
74
|
+
|
|
75
|
+
} else if (this._operation === 'update') {
|
|
76
|
+
const setClauses = Object.entries(this._updateData).map(([col, val]) =>
|
|
77
|
+
typeof val === 'string' ? `"${col}" = '${val.replace(/'/g, "''")}'` : `"${col}" = ${val}`
|
|
78
|
+
).join(', ');
|
|
79
|
+
const whereParts = Object.entries(this._filters).map(([col, val]) =>
|
|
80
|
+
typeof val === 'string' ? `"${col}" = '${val}'` : `"${col}" = ${val}`
|
|
81
|
+
);
|
|
82
|
+
sql = `UPDATE "${this._table}" SET ${setClauses}`;
|
|
83
|
+
if (whereParts.length) sql += ` WHERE ${whereParts.join(' AND ')}`;
|
|
84
|
+
sql += ` RETURNING *`;
|
|
85
|
+
|
|
86
|
+
} else if (this._operation === 'delete') {
|
|
87
|
+
const whereParts = Object.entries(this._filters).map(([col, val]) =>
|
|
88
|
+
typeof val === 'string' ? `"${col}" = '${val}'` : `"${col}" = ${val}`
|
|
89
|
+
);
|
|
90
|
+
sql = `DELETE FROM "${this._table}"`;
|
|
91
|
+
if (whereParts.length) sql += ` WHERE ${whereParts.join(' AND ')}`;
|
|
92
|
+
sql += ` RETURNING *`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return sql;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async _buildAndRun() {
|
|
99
|
+
const sql = this._buildSQL();
|
|
100
|
+
try {
|
|
101
|
+
const res = await fetch(`${this._baseUrl}/query`, {
|
|
102
|
+
method: 'POST',
|
|
103
|
+
headers: {
|
|
104
|
+
'Content-Type': 'application/json',
|
|
105
|
+
'Authorization': `Bearer ${this._apiKey}`,
|
|
106
|
+
},
|
|
107
|
+
body: JSON.stringify({ sql, db_name: this._dbName }),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const json = await res.json();
|
|
111
|
+
const { data, error } = json;
|
|
112
|
+
if (error) return { data: null, error };
|
|
113
|
+
if (this._single) return { data: data[0] || null, error: null };
|
|
114
|
+
return { data, error: null };
|
|
115
|
+
} catch (err) {
|
|
116
|
+
return { data: null, error: err.message };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
then(resolve, reject) {
|
|
121
|
+
return this._buildAndRun().then(resolve, reject);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ─── Client ───────────────────────────────────────────────────────────────────
|
|
126
|
+
|
|
127
|
+
class OpenbaseClient {
|
|
128
|
+
constructor(baseUrl, apiKey, dbName) {
|
|
129
|
+
this._baseUrl = baseUrl.replace(/\/$/, '');
|
|
130
|
+
this._apiKey = apiKey;
|
|
131
|
+
this._dbName = dbName;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
from(table) {
|
|
135
|
+
return new QueryBuilder(this._baseUrl, this._apiKey, this._dbName, table);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ─── Factory ──────────────────────────────────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
function createClient(baseUrl, apiKey, dbName) {
|
|
142
|
+
if (!baseUrl) throw new Error('[openbase] Missing baseUrl. Pass your backend URL as the first argument.');
|
|
143
|
+
if (!apiKey) throw new Error('[openbase] Missing apiKey. Pass your anon or service key as the second argument.');
|
|
144
|
+
if (!dbName) throw new Error('[openbase] Missing dbName. Pass your database name as the third argument.');
|
|
145
|
+
return new OpenbaseClient(baseUrl, apiKey, dbName);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (typeof module !== 'undefined') {
|
|
149
|
+
module.exports = { createClient };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (typeof window !== 'undefined') {
|
|
153
|
+
window.openbase = { createClient };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = { createClient };
|
package/index.js
CHANGED
|
@@ -139,6 +139,9 @@ class OpenbaseClient {
|
|
|
139
139
|
// ─── Factory ──────────────────────────────────────────────────────────────────
|
|
140
140
|
|
|
141
141
|
function createClient(baseUrl, apiKey, dbName) {
|
|
142
|
+
if (!baseUrl) throw new Error('[openbase] Missing baseUrl. Pass your backend URL as the first argument.');
|
|
143
|
+
if (!apiKey) throw new Error('[openbase] Missing apiKey. Pass your anon or service key as the second argument.');
|
|
144
|
+
if (!dbName) throw new Error('[openbase] Missing dbName. Pass your database name as the third argument.');
|
|
142
145
|
return new OpenbaseClient(baseUrl, apiKey, dbName);
|
|
143
146
|
}
|
|
144
147
|
|