@wowsql/sdk 3.4.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/CHANGELOG.md +296 -0
- package/LICENSE +22 -0
- package/README.md +990 -0
- package/dist/auth.d.ts +160 -0
- package/dist/auth.js +320 -0
- package/dist/errors.d.ts +5 -0
- package/dist/errors.js +12 -0
- package/dist/index.d.ts +180 -0
- package/dist/index.js +264 -0
- package/dist/schema.d.ts +58 -0
- package/dist/schema.js +116 -0
- package/dist/storage.d.ts +395 -0
- package/dist/storage.js +404 -0
- package/package.json +65 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WowSQL TypeScript SDK
|
|
4
|
+
* Official client library for WowSQL REST API v2
|
|
5
|
+
*
|
|
6
|
+
* @version 2.0.0
|
|
7
|
+
* @license MIT
|
|
8
|
+
* @see https://github.com/wowsql/wowsql
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
22
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
|
+
};
|
|
24
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
25
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.QueryBuilder = exports.Table = exports.WowSQLClient = void 0;
|
|
29
|
+
const axios_1 = __importDefault(require("axios"));
|
|
30
|
+
const errors_1 = require("./errors");
|
|
31
|
+
// ==================== Main Client ====================
|
|
32
|
+
class WowSQLClient {
|
|
33
|
+
constructor(config) {
|
|
34
|
+
// Build base URL
|
|
35
|
+
const protocol = config.secure !== false ? 'https' : 'http';
|
|
36
|
+
if (config.projectUrl.startsWith('http://') || config.projectUrl.startsWith('https://')) {
|
|
37
|
+
this.baseUrl = config.projectUrl;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const domain = config.baseDomain || 'wowsql.com';
|
|
41
|
+
// If it already contains the base domain, don't append it again
|
|
42
|
+
if (config.projectUrl.includes(`.${domain}`) || config.projectUrl.endsWith(domain)) {
|
|
43
|
+
this.baseUrl = `${protocol}://${config.projectUrl}`;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// Just a project slug, append domain
|
|
47
|
+
this.baseUrl = `${protocol}://${config.projectUrl}.${domain}`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Create axios instance
|
|
51
|
+
this.client = axios_1.default.create({
|
|
52
|
+
baseURL: `${this.baseUrl}/api/v2`,
|
|
53
|
+
headers: {
|
|
54
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
55
|
+
'Content-Type': 'application/json',
|
|
56
|
+
},
|
|
57
|
+
timeout: config.timeout || 30000,
|
|
58
|
+
});
|
|
59
|
+
// Add error interceptor
|
|
60
|
+
this.client.interceptors.response.use((response) => response, (error) => {
|
|
61
|
+
if (error.response) {
|
|
62
|
+
const errorData = error.response.data;
|
|
63
|
+
const errorMessage = errorData?.detail || errorData?.message || error.message;
|
|
64
|
+
throw new errors_1.WOWSQLError(errorMessage, error.response.status, errorData);
|
|
65
|
+
}
|
|
66
|
+
throw new errors_1.WOWSQLError(error.message);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get a table interface for fluent API
|
|
71
|
+
*/
|
|
72
|
+
table(tableName) {
|
|
73
|
+
return new Table(this.client, tableName);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* List all tables in the database
|
|
77
|
+
*/
|
|
78
|
+
async listTables() {
|
|
79
|
+
const response = await this.client.get('/tables');
|
|
80
|
+
return response.data.tables;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get table schema
|
|
84
|
+
*/
|
|
85
|
+
async getTableSchema(tableName) {
|
|
86
|
+
const response = await this.client.get(`/tables/${tableName}/schema`);
|
|
87
|
+
return response.data;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Execute raw SQL query (read-only for safety)
|
|
91
|
+
*/
|
|
92
|
+
async query(sql) {
|
|
93
|
+
const response = await this.client.post('/query', { sql });
|
|
94
|
+
return response.data.results || response.data;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Health check
|
|
98
|
+
*/
|
|
99
|
+
async health() {
|
|
100
|
+
const response = await this.client.get('/health');
|
|
101
|
+
return response.data;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.WowSQLClient = WowSQLClient;
|
|
105
|
+
// ==================== Table Class ====================
|
|
106
|
+
class Table {
|
|
107
|
+
constructor(client, tableName) {
|
|
108
|
+
this.client = client;
|
|
109
|
+
this.tableName = tableName;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Query records with filters and pagination
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* const users = await client.table('users')
|
|
116
|
+
* .select(['id', 'name', 'email'])
|
|
117
|
+
* .filter({ column: 'age', operator: 'gt', value: 18 })
|
|
118
|
+
* .order('created_at', 'desc')
|
|
119
|
+
* .limit(10)
|
|
120
|
+
* .get();
|
|
121
|
+
*/
|
|
122
|
+
select(columns) {
|
|
123
|
+
return new QueryBuilder(this.client, this.tableName).select(columns);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Query with filter
|
|
127
|
+
*/
|
|
128
|
+
filter(filter) {
|
|
129
|
+
return new QueryBuilder(this.client, this.tableName).filter(filter);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get all records (with optional limit)
|
|
133
|
+
*/
|
|
134
|
+
async get(options) {
|
|
135
|
+
return new QueryBuilder(this.client, this.tableName).get(options);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get a single record by ID
|
|
139
|
+
*/
|
|
140
|
+
async getById(id) {
|
|
141
|
+
const response = await this.client.get(`/${this.tableName}/${id}`);
|
|
142
|
+
return response.data;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Create a new record
|
|
146
|
+
*/
|
|
147
|
+
async create(data) {
|
|
148
|
+
const response = await this.client.post(`/${this.tableName}`, data);
|
|
149
|
+
return response.data;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Update a record by ID
|
|
153
|
+
*/
|
|
154
|
+
async update(id, data) {
|
|
155
|
+
const response = await this.client.patch(`/${this.tableName}/${id}`, data);
|
|
156
|
+
return response.data;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Delete a record by ID
|
|
160
|
+
*/
|
|
161
|
+
async delete(id) {
|
|
162
|
+
const response = await this.client.delete(`/${this.tableName}/${id}`);
|
|
163
|
+
return response.data;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
exports.Table = Table;
|
|
167
|
+
// ==================== Query Builder ====================
|
|
168
|
+
class QueryBuilder {
|
|
169
|
+
constructor(client, tableName) {
|
|
170
|
+
this.client = client;
|
|
171
|
+
this.tableName = tableName;
|
|
172
|
+
this.options = {};
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Select specific columns
|
|
176
|
+
*/
|
|
177
|
+
select(columns) {
|
|
178
|
+
this.options.select = Array.isArray(columns) ? columns.join(',') : columns;
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Add filter condition
|
|
183
|
+
*/
|
|
184
|
+
filter(filter) {
|
|
185
|
+
if (!this.options.filter) {
|
|
186
|
+
this.options.filter = [];
|
|
187
|
+
}
|
|
188
|
+
if (Array.isArray(this.options.filter)) {
|
|
189
|
+
this.options.filter.push(filter);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
this.options.filter = [this.options.filter, filter];
|
|
193
|
+
}
|
|
194
|
+
return this;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Order by column
|
|
198
|
+
*/
|
|
199
|
+
order(column, direction = 'asc') {
|
|
200
|
+
this.options.order = column;
|
|
201
|
+
this.options.orderDirection = direction;
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Limit number of results
|
|
206
|
+
*/
|
|
207
|
+
limit(limit) {
|
|
208
|
+
this.options.limit = limit;
|
|
209
|
+
return this;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Skip records (pagination)
|
|
213
|
+
*/
|
|
214
|
+
offset(offset) {
|
|
215
|
+
this.options.offset = offset;
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Execute query
|
|
220
|
+
*/
|
|
221
|
+
async get(additionalOptions) {
|
|
222
|
+
const finalOptions = { ...this.options, ...additionalOptions };
|
|
223
|
+
// Build query parameters
|
|
224
|
+
const params = {};
|
|
225
|
+
if (finalOptions.select) {
|
|
226
|
+
params.select = finalOptions.select;
|
|
227
|
+
}
|
|
228
|
+
if (finalOptions.filter) {
|
|
229
|
+
const filters = Array.isArray(finalOptions.filter)
|
|
230
|
+
? finalOptions.filter
|
|
231
|
+
: [finalOptions.filter];
|
|
232
|
+
params.filter = filters
|
|
233
|
+
.map((f) => `${f.column}.${f.operator}.${f.value}`)
|
|
234
|
+
.join(',');
|
|
235
|
+
}
|
|
236
|
+
if (finalOptions.order) {
|
|
237
|
+
params.order = finalOptions.order;
|
|
238
|
+
params.order_direction = finalOptions.orderDirection || 'asc';
|
|
239
|
+
}
|
|
240
|
+
if (finalOptions.limit !== undefined) {
|
|
241
|
+
params.limit = finalOptions.limit;
|
|
242
|
+
}
|
|
243
|
+
if (finalOptions.offset !== undefined) {
|
|
244
|
+
params.offset = finalOptions.offset;
|
|
245
|
+
}
|
|
246
|
+
const response = await this.client.get(`/${this.tableName}`, { params });
|
|
247
|
+
return response.data;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Get first record
|
|
251
|
+
*/
|
|
252
|
+
async first() {
|
|
253
|
+
const result = await this.limit(1).get();
|
|
254
|
+
return result.data[0] || null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
exports.QueryBuilder = QueryBuilder;
|
|
258
|
+
// ==================== Exports ====================
|
|
259
|
+
// Re-export storage SDK
|
|
260
|
+
__exportStar(require("./storage"), exports);
|
|
261
|
+
__exportStar(require("./auth"), exports);
|
|
262
|
+
__exportStar(require("./schema"), exports);
|
|
263
|
+
__exportStar(require("./errors"), exports);
|
|
264
|
+
exports.default = WowSQLClient;
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema management client for WowSQL.
|
|
3
|
+
* Requires SERVICE ROLE key.
|
|
4
|
+
*/
|
|
5
|
+
export interface ColumnDefinition {
|
|
6
|
+
name: string;
|
|
7
|
+
type: string;
|
|
8
|
+
auto_increment?: boolean;
|
|
9
|
+
unique?: boolean;
|
|
10
|
+
nullable?: boolean;
|
|
11
|
+
default?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface CreateTableOptions {
|
|
14
|
+
tableName: string;
|
|
15
|
+
columns: ColumnDefinition[];
|
|
16
|
+
primaryKey?: string;
|
|
17
|
+
indexes?: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface AlterTableOptions {
|
|
20
|
+
tableName: string;
|
|
21
|
+
operation: 'add_column' | 'drop_column' | 'modify_column' | 'rename_column';
|
|
22
|
+
columnName?: string;
|
|
23
|
+
columnType?: string;
|
|
24
|
+
newColumnName?: string;
|
|
25
|
+
nullable?: boolean;
|
|
26
|
+
default?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare class WowSQLSchema {
|
|
29
|
+
private baseUrl;
|
|
30
|
+
private serviceKey;
|
|
31
|
+
/**
|
|
32
|
+
* Initialize schema client.
|
|
33
|
+
*
|
|
34
|
+
* ⚠️ IMPORTANT: Requires SERVICE ROLE key, not anonymous key!
|
|
35
|
+
*
|
|
36
|
+
* @param projectUrl - Project URL (e.g., "https://myproject.wowsql.com")
|
|
37
|
+
* @param serviceKey - SERVICE ROLE key (not anonymous key!)
|
|
38
|
+
*/
|
|
39
|
+
constructor(projectUrl: string, serviceKey: string);
|
|
40
|
+
/**
|
|
41
|
+
* Create a new table.
|
|
42
|
+
*/
|
|
43
|
+
createTable(options: CreateTableOptions): Promise<any>;
|
|
44
|
+
/**
|
|
45
|
+
* Alter an existing table.
|
|
46
|
+
*/
|
|
47
|
+
alterTable(options: AlterTableOptions): Promise<any>;
|
|
48
|
+
/**
|
|
49
|
+
* Drop a table.
|
|
50
|
+
*
|
|
51
|
+
* ⚠️ WARNING: This operation cannot be undone!
|
|
52
|
+
*/
|
|
53
|
+
dropTable(tableName: string, cascade?: boolean): Promise<any>;
|
|
54
|
+
/**
|
|
55
|
+
* Execute raw SQL for schema operations.
|
|
56
|
+
*/
|
|
57
|
+
executeSQL(sql: string): Promise<any>;
|
|
58
|
+
}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Schema management client for WowSQL.
|
|
4
|
+
* Requires SERVICE ROLE key.
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.WowSQLSchema = void 0;
|
|
8
|
+
class WowSQLSchema {
|
|
9
|
+
/**
|
|
10
|
+
* Initialize schema client.
|
|
11
|
+
*
|
|
12
|
+
* ⚠️ IMPORTANT: Requires SERVICE ROLE key, not anonymous key!
|
|
13
|
+
*
|
|
14
|
+
* @param projectUrl - Project URL (e.g., "https://myproject.wowsql.com")
|
|
15
|
+
* @param serviceKey - SERVICE ROLE key (not anonymous key!)
|
|
16
|
+
*/
|
|
17
|
+
constructor(projectUrl, serviceKey) {
|
|
18
|
+
this.baseUrl = projectUrl.replace(/\/$/, '');
|
|
19
|
+
this.serviceKey = serviceKey;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create a new table.
|
|
23
|
+
*/
|
|
24
|
+
async createTable(options) {
|
|
25
|
+
const url = `${this.baseUrl}/api/v2/schema/tables`;
|
|
26
|
+
const response = await fetch(url, {
|
|
27
|
+
method: 'POST',
|
|
28
|
+
headers: {
|
|
29
|
+
'Authorization': `Bearer ${this.serviceKey}`,
|
|
30
|
+
'Content-Type': 'application/json'
|
|
31
|
+
},
|
|
32
|
+
body: JSON.stringify({
|
|
33
|
+
table_name: options.tableName,
|
|
34
|
+
columns: options.columns,
|
|
35
|
+
primary_key: options.primaryKey,
|
|
36
|
+
indexes: options.indexes
|
|
37
|
+
})
|
|
38
|
+
});
|
|
39
|
+
if (response.status === 403) {
|
|
40
|
+
throw new Error('Schema operations require a SERVICE ROLE key. ' +
|
|
41
|
+
'You are using an anonymous key which cannot modify database schema.');
|
|
42
|
+
}
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
const error = await response.json();
|
|
45
|
+
throw new Error(`Failed to create table: ${error.detail || response.statusText}`);
|
|
46
|
+
}
|
|
47
|
+
return response.json();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Alter an existing table.
|
|
51
|
+
*/
|
|
52
|
+
async alterTable(options) {
|
|
53
|
+
const url = `${this.baseUrl}/api/v2/schema/tables/${options.tableName}`;
|
|
54
|
+
const response = await fetch(url, {
|
|
55
|
+
method: 'PATCH',
|
|
56
|
+
headers: {
|
|
57
|
+
'Authorization': `Bearer ${this.serviceKey}`,
|
|
58
|
+
'Content-Type': 'application/json'
|
|
59
|
+
},
|
|
60
|
+
body: JSON.stringify(options)
|
|
61
|
+
});
|
|
62
|
+
if (response.status === 403) {
|
|
63
|
+
throw new Error('Schema operations require a SERVICE ROLE key.');
|
|
64
|
+
}
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
const error = await response.json();
|
|
67
|
+
throw new Error(`Failed to alter table: ${error.detail || response.statusText}`);
|
|
68
|
+
}
|
|
69
|
+
return response.json();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Drop a table.
|
|
73
|
+
*
|
|
74
|
+
* ⚠️ WARNING: This operation cannot be undone!
|
|
75
|
+
*/
|
|
76
|
+
async dropTable(tableName, cascade = false) {
|
|
77
|
+
const url = `${this.baseUrl}/api/v2/schema/tables/${tableName}?cascade=${cascade}`;
|
|
78
|
+
const response = await fetch(url, {
|
|
79
|
+
method: 'DELETE',
|
|
80
|
+
headers: {
|
|
81
|
+
'Authorization': `Bearer ${this.serviceKey}`
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
if (response.status === 403) {
|
|
85
|
+
throw new Error('Schema operations require a SERVICE ROLE key.');
|
|
86
|
+
}
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
const error = await response.json();
|
|
89
|
+
throw new Error(`Failed to drop table: ${error.detail || response.statusText}`);
|
|
90
|
+
}
|
|
91
|
+
return response.json();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Execute raw SQL for schema operations.
|
|
95
|
+
*/
|
|
96
|
+
async executeSQL(sql) {
|
|
97
|
+
const url = `${this.baseUrl}/api/v2/schema/execute`;
|
|
98
|
+
const response = await fetch(url, {
|
|
99
|
+
method: 'POST',
|
|
100
|
+
headers: {
|
|
101
|
+
'Authorization': `Bearer ${this.serviceKey}`,
|
|
102
|
+
'Content-Type': 'application/json'
|
|
103
|
+
},
|
|
104
|
+
body: JSON.stringify({ sql })
|
|
105
|
+
});
|
|
106
|
+
if (response.status === 403) {
|
|
107
|
+
throw new Error('Schema operations require a SERVICE ROLE key.');
|
|
108
|
+
}
|
|
109
|
+
if (!response.ok) {
|
|
110
|
+
const error = await response.json();
|
|
111
|
+
throw new Error(`Failed to execute SQL: ${error.detail || response.statusText}`);
|
|
112
|
+
}
|
|
113
|
+
return response.json();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.WowSQLSchema = WowSQLSchema;
|