@wowsql/sdk 3.6.0 → 3.8.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 +1293 -699
- package/dist/auth.d.ts +114 -0
- package/dist/auth.js +246 -1
- package/dist/errors.d.ts +9 -0
- package/dist/errors.js +22 -1
- package/dist/index.d.ts +135 -0
- package/dist/index.js +259 -0
- package/dist/schema.d.ts +165 -13
- package/dist/schema.js +208 -79
- package/dist/storage.d.ts +138 -322
- package/dist/storage.js +181 -270
- package/package.json +1 -1
package/dist/schema.js
CHANGED
|
@@ -1,116 +1,245 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Schema
|
|
4
|
-
* Requires SERVICE ROLE key.
|
|
3
|
+
* WowSQL Schema SDK - DDL operations for PostgreSQL.
|
|
4
|
+
* Requires a SERVICE ROLE key (wowsql_service_...).
|
|
5
|
+
*
|
|
6
|
+
* @version 3.0.0
|
|
7
|
+
* @license MIT
|
|
5
8
|
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
6
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.WowSQLSchema = void 0;
|
|
13
|
+
exports.WowSQLSchema = exports.SchemaPermissionError = void 0;
|
|
14
|
+
const axios_1 = __importDefault(require("axios"));
|
|
15
|
+
const errors_1 = require("./errors");
|
|
16
|
+
Object.defineProperty(exports, "SchemaPermissionError", { enumerable: true, get: function () { return errors_1.SchemaPermissionError; } });
|
|
17
|
+
// ==================== Schema Client ====================
|
|
8
18
|
class WowSQLSchema {
|
|
9
19
|
/**
|
|
10
20
|
* Initialize schema client.
|
|
11
21
|
*
|
|
12
|
-
*
|
|
22
|
+
* Requires a SERVICE ROLE key. Anonymous keys cannot perform DDL operations.
|
|
13
23
|
*
|
|
14
|
-
* @
|
|
15
|
-
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const schema = new WowSQLSchema({
|
|
27
|
+
* projectUrl: 'myproject',
|
|
28
|
+
* serviceKey: 'wowsql_service_...'
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* await schema.createTable({
|
|
32
|
+
* tableName: 'products',
|
|
33
|
+
* columns: [
|
|
34
|
+
* { name: 'id', type: 'SERIAL', auto_increment: true },
|
|
35
|
+
* { name: 'name', type: 'VARCHAR(255)', nullable: false },
|
|
36
|
+
* { name: 'price', type: 'NUMERIC(10,2)', default: '0' },
|
|
37
|
+
* { name: 'tags', type: 'TEXT[]' },
|
|
38
|
+
* { name: 'metadata', type: 'JSONB', default: "'{}'" },
|
|
39
|
+
* { name: 'created_at', type: 'TIMESTAMPTZ', default: 'CURRENT_TIMESTAMP' }
|
|
40
|
+
* ],
|
|
41
|
+
* primaryKey: 'id',
|
|
42
|
+
* indexes: ['name']
|
|
43
|
+
* });
|
|
44
|
+
* ```
|
|
16
45
|
*/
|
|
17
|
-
constructor(
|
|
18
|
-
|
|
19
|
-
|
|
46
|
+
constructor(config, serviceKey) {
|
|
47
|
+
if (typeof config === 'string') {
|
|
48
|
+
this.baseUrl = config.replace(/\/$/, '');
|
|
49
|
+
if (!this.baseUrl.startsWith('http')) {
|
|
50
|
+
this.baseUrl = `https://${this.baseUrl}`;
|
|
51
|
+
}
|
|
52
|
+
this.client = axios_1.default.create({
|
|
53
|
+
baseURL: `${this.baseUrl}/api/v2/schema`,
|
|
54
|
+
headers: {
|
|
55
|
+
'Authorization': `Bearer ${serviceKey}`,
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
},
|
|
58
|
+
timeout: 30000,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const protocol = config.secure !== false ? 'https' : 'http';
|
|
63
|
+
if (config.projectUrl.startsWith('http://') || config.projectUrl.startsWith('https://')) {
|
|
64
|
+
this.baseUrl = config.projectUrl.replace(/\/+$/, '');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const domain = config.baseDomain || 'wowsql.com';
|
|
68
|
+
if (config.projectUrl.includes(`.${domain}`) || config.projectUrl.endsWith(domain)) {
|
|
69
|
+
this.baseUrl = `${protocol}://${config.projectUrl}`;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this.baseUrl = `${protocol}://${config.projectUrl}.${domain}`;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
this.client = axios_1.default.create({
|
|
76
|
+
baseURL: `${this.baseUrl}/api/v2/schema`,
|
|
77
|
+
headers: {
|
|
78
|
+
'Authorization': `Bearer ${config.serviceKey}`,
|
|
79
|
+
'Content-Type': 'application/json',
|
|
80
|
+
},
|
|
81
|
+
timeout: config.timeout || 30000,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
this.client.interceptors.response.use((response) => response, (error) => {
|
|
85
|
+
if (error.response) {
|
|
86
|
+
const data = error.response.data;
|
|
87
|
+
const message = data?.detail || data?.message || error.message;
|
|
88
|
+
if (error.response.status === 403) {
|
|
89
|
+
throw new errors_1.SchemaPermissionError(message, 403, data);
|
|
90
|
+
}
|
|
91
|
+
throw new errors_1.WOWSQLError(message, error.response.status, data);
|
|
92
|
+
}
|
|
93
|
+
throw new errors_1.WOWSQLError(error.message);
|
|
94
|
+
});
|
|
20
95
|
}
|
|
21
96
|
/**
|
|
22
|
-
* Create a new table.
|
|
97
|
+
* Create a new table with PostgreSQL column types.
|
|
98
|
+
*
|
|
99
|
+
* Supported PostgreSQL types: SERIAL, BIGSERIAL, VARCHAR(n), TEXT, INT, BIGINT,
|
|
100
|
+
* BOOLEAN, NUMERIC(p,s), REAL, DOUBLE PRECISION, TIMESTAMPTZ, DATE, TIME,
|
|
101
|
+
* UUID, JSONB, TEXT[], INT[], BYTEA, etc.
|
|
23
102
|
*/
|
|
24
103
|
async createTable(options) {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
})
|
|
104
|
+
const response = await this.client.post('/tables', {
|
|
105
|
+
table_name: options.tableName,
|
|
106
|
+
columns: options.columns,
|
|
107
|
+
primary_key: options.primaryKey,
|
|
108
|
+
indexes: options.indexes,
|
|
38
109
|
});
|
|
39
|
-
|
|
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();
|
|
110
|
+
return response.data;
|
|
48
111
|
}
|
|
49
112
|
/**
|
|
50
113
|
* Alter an existing table.
|
|
114
|
+
*
|
|
115
|
+
* Operations:
|
|
116
|
+
* - `add_column`: Add a new column
|
|
117
|
+
* - `drop_column`: Remove a column
|
|
118
|
+
* - `modify_column`: Change column type/constraints (PostgreSQL ALTER COLUMN ... TYPE)
|
|
119
|
+
* - `rename_column`: Rename a column
|
|
51
120
|
*/
|
|
52
121
|
async alterTable(options) {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
122
|
+
const response = await this.client.patch(`/tables/${options.tableName}`, {
|
|
123
|
+
table_name: options.tableName,
|
|
124
|
+
operation: options.operation,
|
|
125
|
+
column_name: options.columnName,
|
|
126
|
+
column_type: options.columnType,
|
|
127
|
+
new_column_name: options.newColumnName,
|
|
128
|
+
nullable: options.nullable,
|
|
129
|
+
default: options.default,
|
|
61
130
|
});
|
|
62
|
-
|
|
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();
|
|
131
|
+
return response.data;
|
|
70
132
|
}
|
|
71
133
|
/**
|
|
72
134
|
* Drop a table.
|
|
73
135
|
*
|
|
74
|
-
*
|
|
136
|
+
* WARNING: This operation cannot be undone!
|
|
137
|
+
*
|
|
138
|
+
* @param tableName - Table to drop
|
|
139
|
+
* @param cascade - If true, also drops dependent objects (foreign keys, views, etc.)
|
|
75
140
|
*/
|
|
76
141
|
async dropTable(tableName, cascade = false) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
method: 'DELETE',
|
|
80
|
-
headers: {
|
|
81
|
-
'Authorization': `Bearer ${this.serviceKey}`
|
|
82
|
-
}
|
|
142
|
+
const response = await this.client.delete(`/tables/${tableName}`, {
|
|
143
|
+
params: { cascade },
|
|
83
144
|
});
|
|
84
|
-
|
|
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();
|
|
145
|
+
return response.data;
|
|
92
146
|
}
|
|
93
147
|
/**
|
|
94
148
|
* Execute raw SQL for schema operations.
|
|
149
|
+
*
|
|
150
|
+
* Only DDL statements are allowed: CREATE TABLE, ALTER TABLE, DROP TABLE,
|
|
151
|
+
* CREATE INDEX, DROP INDEX, CREATE EXTENSION, CREATE TYPE, ALTER TYPE,
|
|
152
|
+
* CREATE SEQUENCE, ALTER SEQUENCE, DROP SEQUENCE.
|
|
153
|
+
*
|
|
154
|
+
* @param sql - SQL DDL statement
|
|
95
155
|
*/
|
|
96
156
|
async executeSQL(sql) {
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
157
|
+
const response = await this.client.post('/execute', { sql });
|
|
158
|
+
return response.data;
|
|
159
|
+
}
|
|
160
|
+
// ==================== Convenience Methods ====================
|
|
161
|
+
/**
|
|
162
|
+
* Add a column to an existing table.
|
|
163
|
+
*/
|
|
164
|
+
async addColumn(tableName, columnName, columnType, options) {
|
|
165
|
+
return this.alterTable({
|
|
166
|
+
tableName,
|
|
167
|
+
operation: 'add_column',
|
|
168
|
+
columnName,
|
|
169
|
+
columnType,
|
|
170
|
+
nullable: options?.nullable,
|
|
171
|
+
default: options?.default,
|
|
105
172
|
});
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Drop a column from a table.
|
|
176
|
+
*/
|
|
177
|
+
async dropColumn(tableName, columnName) {
|
|
178
|
+
return this.alterTable({
|
|
179
|
+
tableName,
|
|
180
|
+
operation: 'drop_column',
|
|
181
|
+
columnName,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Rename a column in a table.
|
|
186
|
+
*/
|
|
187
|
+
async renameColumn(tableName, oldName, newName) {
|
|
188
|
+
return this.alterTable({
|
|
189
|
+
tableName,
|
|
190
|
+
operation: 'rename_column',
|
|
191
|
+
columnName: oldName,
|
|
192
|
+
newColumnName: newName,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Modify a column's type or constraints.
|
|
197
|
+
*/
|
|
198
|
+
async modifyColumn(tableName, columnName, columnType, options) {
|
|
199
|
+
return this.alterTable({
|
|
200
|
+
tableName,
|
|
201
|
+
operation: 'modify_column',
|
|
202
|
+
columnName,
|
|
203
|
+
columnType,
|
|
204
|
+
nullable: options?.nullable,
|
|
205
|
+
default: options?.default,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Create an index using raw SQL.
|
|
210
|
+
*
|
|
211
|
+
* @param tableName - Table to index
|
|
212
|
+
* @param columnNames - Column(s) to include in the index
|
|
213
|
+
* @param options - Index options
|
|
214
|
+
*/
|
|
215
|
+
async createIndex(tableName, columnNames, options) {
|
|
216
|
+
const cols = Array.isArray(columnNames) ? columnNames : [columnNames];
|
|
217
|
+
const indexName = options?.name || `idx_${tableName}_${cols.join('_')}`;
|
|
218
|
+
const unique = options?.unique ? 'UNIQUE ' : '';
|
|
219
|
+
const using = options?.using ? ` USING ${options.using}` : '';
|
|
220
|
+
const colList = cols.map(c => `"${c}"`).join(', ');
|
|
221
|
+
const sql = `CREATE ${unique}INDEX IF NOT EXISTS "${indexName}" ON "${tableName}"${using} (${colList})`;
|
|
222
|
+
return this.executeSQL(sql);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* List all tables in the database.
|
|
226
|
+
* Uses the v2 tables endpoint (GET /api/v2/tables).
|
|
227
|
+
*/
|
|
228
|
+
async listTables() {
|
|
229
|
+
const response = await this.client.get('/tables', {
|
|
230
|
+
baseURL: `${this.baseUrl}/api/v2`,
|
|
231
|
+
});
|
|
232
|
+
return response.data.tables;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get the schema for a specific table.
|
|
236
|
+
* Uses the v2 tables endpoint (GET /api/v2/tables/{name}/schema).
|
|
237
|
+
*/
|
|
238
|
+
async getTableSchema(tableName) {
|
|
239
|
+
const response = await this.client.get(`/tables/${tableName}/schema`, {
|
|
240
|
+
baseURL: `${this.baseUrl}/api/v2`,
|
|
241
|
+
});
|
|
242
|
+
return response.data;
|
|
114
243
|
}
|
|
115
244
|
}
|
|
116
245
|
exports.WowSQLSchema = WowSQLSchema;
|