@weapp-sqlite/devtools 0.0.0-init.0 → 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.
@@ -0,0 +1,397 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_protocol = require("./protocol-Cl3y675u.cjs");
3
+ //#region src/socket.ts
4
+ function toBinaryBytes(value) {
5
+ if (typeof ArrayBuffer !== "undefined" && value instanceof ArrayBuffer) return new Uint8Array(value);
6
+ if (typeof ArrayBuffer !== "undefined" && ArrayBuffer.isView(value)) {
7
+ const view = value;
8
+ return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
9
+ }
10
+ }
11
+ function decodeUtf8(value) {
12
+ if (typeof value === "string") return value;
13
+ const bytes = toBinaryBytes(value);
14
+ if (!bytes) return;
15
+ if (typeof TextDecoder !== "undefined") try {
16
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
17
+ } catch {
18
+ return;
19
+ }
20
+ let output = "";
21
+ for (let index = 0; index < bytes.length;) {
22
+ const first = bytes[index++] ?? -1;
23
+ if (first <= 127) {
24
+ output += String.fromCharCode(first);
25
+ continue;
26
+ }
27
+ const continuation = (count) => {
28
+ if (index + count > bytes.length) return;
29
+ let codePoint = 0;
30
+ for (let offset = 0; offset < count; offset++) {
31
+ const next = bytes[index++] ?? -1;
32
+ if ((next & 192) !== 128) return;
33
+ codePoint = codePoint << 6 | next & 63;
34
+ }
35
+ return codePoint;
36
+ };
37
+ let codePoint;
38
+ if (first >= 194 && first <= 223) {
39
+ const next = bytes[index++] ?? -1;
40
+ if ((next & 192) === 128) codePoint = (first & 31) << 6 | next & 63;
41
+ } else if (first >= 224 && first <= 239) {
42
+ const second = bytes[index++] ?? -1;
43
+ if (first === 224 && second >= 160 && second <= 191 || first === 237 && second >= 128 && second <= 159 || first !== 224 && first !== 237 && second >= 128 && second <= 191) {
44
+ const next = continuation(1);
45
+ if (next !== void 0) codePoint = (first & 15) << 12 | (second & 63) << 6 | next;
46
+ }
47
+ } else if (first >= 240 && first <= 244) {
48
+ const second = bytes[index++] ?? -1;
49
+ if (first === 240 && second >= 144 && second <= 191 || first === 244 && second >= 128 && second <= 143 || first !== 240 && first !== 244 && second >= 128 && second <= 191) {
50
+ const next = continuation(2);
51
+ if (next !== void 0) codePoint = (first & 7) << 18 | (second & 63) << 12 | next;
52
+ }
53
+ }
54
+ if (codePoint === void 0 || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343) return;
55
+ output += String.fromCodePoint(codePoint);
56
+ }
57
+ return output;
58
+ }
59
+ function createWebSocketFactory(Constructor) {
60
+ return (url, handlers) => {
61
+ let socket;
62
+ let ended = false;
63
+ let underlyingClosed = false;
64
+ function closeUnderlying() {
65
+ if (!socket || underlyingClosed) return;
66
+ underlyingClosed = true;
67
+ try {
68
+ socket.close();
69
+ } catch {}
70
+ }
71
+ function fail() {
72
+ if (ended) return;
73
+ ended = true;
74
+ closeUnderlying();
75
+ handlers.error();
76
+ }
77
+ try {
78
+ socket = new Constructor(url);
79
+ socket.addEventListener("open", () => {
80
+ if (!ended) handlers.open();
81
+ });
82
+ socket.addEventListener("message", (event) => {
83
+ if (ended) return;
84
+ const data = decodeUtf8(event.data);
85
+ if (data === void 0) {
86
+ fail();
87
+ return;
88
+ }
89
+ handlers.message(data);
90
+ });
91
+ socket.addEventListener("close", () => {
92
+ if (ended) return;
93
+ ended = true;
94
+ handlers.close();
95
+ });
96
+ socket.addEventListener("error", fail);
97
+ } catch {
98
+ fail();
99
+ }
100
+ return {
101
+ send(data) {
102
+ if (ended || !socket) return;
103
+ try {
104
+ socket.send(data);
105
+ } catch {
106
+ fail();
107
+ }
108
+ },
109
+ close() {
110
+ if (ended) return;
111
+ ended = true;
112
+ closeUnderlying();
113
+ }
114
+ };
115
+ };
116
+ }
117
+ /** 直接使用 SocketTask,不依赖浏览器全局变量或动态求值。 */
118
+ function createWeappSocketFactory(api) {
119
+ return (url, handlers) => {
120
+ let task;
121
+ let ended = false;
122
+ let underlyingClosed = false;
123
+ function closeUnderlying() {
124
+ if (!task || underlyingClosed) return;
125
+ underlyingClosed = true;
126
+ try {
127
+ task.close({
128
+ code: 1e3,
129
+ reason: "SQLite DevTools closed"
130
+ });
131
+ } catch {}
132
+ }
133
+ function fail() {
134
+ if (ended) return;
135
+ ended = true;
136
+ closeUnderlying();
137
+ handlers.error();
138
+ }
139
+ function handleMessage(event) {
140
+ if (ended) return;
141
+ const data = decodeUtf8(event.data);
142
+ if (data === void 0) {
143
+ fail();
144
+ return;
145
+ }
146
+ handlers.message(data);
147
+ }
148
+ try {
149
+ task = api.connectSocket({
150
+ url,
151
+ success: () => {},
152
+ fail
153
+ });
154
+ if (!task) throw new Error("wx.connectSocket did not return a SocketTask.");
155
+ if (ended) closeUnderlying();
156
+ else {
157
+ task.onOpen(() => {
158
+ if (!ended) handlers.open();
159
+ });
160
+ task.onMessage(handleMessage);
161
+ task.onClose(() => {
162
+ if (ended) return;
163
+ ended = true;
164
+ handlers.close();
165
+ });
166
+ task.onError(fail);
167
+ }
168
+ } catch {
169
+ fail();
170
+ }
171
+ return {
172
+ send(data) {
173
+ if (ended || !task) return;
174
+ try {
175
+ task.send({
176
+ data,
177
+ fail
178
+ });
179
+ } catch {
180
+ fail();
181
+ }
182
+ },
183
+ close() {
184
+ if (ended) return;
185
+ ended = true;
186
+ closeUnderlying();
187
+ }
188
+ };
189
+ };
190
+ }
191
+ //#endregion
192
+ //#region src/runtime.ts
193
+ function utf8ByteLength(value) {
194
+ if (typeof TextEncoder !== "undefined") return new TextEncoder().encode(value).byteLength;
195
+ let bytes = 0;
196
+ for (const character of value) {
197
+ const codePoint = character.codePointAt(0) ?? 0;
198
+ bytes += codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
199
+ }
200
+ return bytes;
201
+ }
202
+ /** 只登记和转发当前运行时的数据库,断线后不重放任何数据库操作。 */
203
+ function connectSqliteDevtoolsRuntime(options) {
204
+ if (!/^ws:\/\/(?:127\.0\.0\.1|localhost|\[::1\])(?::\d+)?\//.test(options.endpoint) || !options.token || !require_protocol.isIdentifier(options.runtime.id) || !require_protocol.isIdentifier(options.runtime.label) || !require_protocol.isIdentifier(options.runtime.platform)) throw new require_protocol.SqliteDevtoolsError("SQLITE_DEVTOOLS_INVALID_CONFIG", "SQLite DevTools requires a loopback endpoint and valid runtime identity.");
205
+ let disposed = false;
206
+ let generation = 0;
207
+ let socket;
208
+ let reconnectTimer;
209
+ let authTimer;
210
+ let sessionId;
211
+ let allowWrite = false;
212
+ let requestIds = /* @__PURE__ */ new Set();
213
+ let reconnectAttempt = 0;
214
+ let releaseVersion = 0;
215
+ let releaseInProgress;
216
+ function databases() {
217
+ const names = [...options.listDatabases()];
218
+ if (!require_protocol.validDatabaseNames(names)) throw new require_protocol.SqliteDevtoolsError("SQLITE_DEVTOOLS_INVALID_CONFIG", "SQLite DevTools database names are invalid.");
219
+ return names;
220
+ }
221
+ function send(payload) {
222
+ const text = JSON.stringify(payload);
223
+ if (utf8ByteLength(text) > 16777216) throw new require_protocol.SqliteDevtoolsError("SQLITE_DEVTOOLS_PAYLOAD_LIMIT", "SQLite DevTools message exceeds the size limit.");
224
+ socket?.send(text);
225
+ }
226
+ function disconnect(current) {
227
+ if (current !== generation) return;
228
+ generation += 1;
229
+ sessionId = void 0;
230
+ requestIds.clear();
231
+ clearTimeout(authTimer);
232
+ const previous = socket;
233
+ socket = void 0;
234
+ try {
235
+ previous?.close();
236
+ } catch {}
237
+ Promise.resolve().then(() => options.onDisconnect?.()).catch(() => {});
238
+ if (!disposed && !reconnectTimer) {
239
+ const delay = Math.min(5e3, (options.reconnectDelayMs ?? 500) * 2 ** Math.min(reconnectAttempt++, 4));
240
+ reconnectTimer = setTimeout(() => {
241
+ reconnectTimer = void 0;
242
+ connect();
243
+ }, delay);
244
+ }
245
+ }
246
+ async function receive(text, current) {
247
+ if (disposed || current !== generation) return;
248
+ try {
249
+ if (utf8ByteLength(text) > 16777216) throw new Error("Oversized message");
250
+ const message = JSON.parse(text);
251
+ if (!require_protocol.isRecord(message)) throw new Error("Invalid message");
252
+ if (message.type === "ready" && require_protocol.isIdentifier(message.sessionId) && typeof message.allowWrite === "boolean") {
253
+ if (sessionId) throw new Error("Duplicate handshake");
254
+ clearTimeout(authTimer);
255
+ sessionId = message.sessionId;
256
+ allowWrite = message.allowWrite;
257
+ reconnectAttempt = 0;
258
+ return;
259
+ }
260
+ if (message.type === "release") {
261
+ if (!sessionId || message.sessionId !== sessionId || !require_protocol.isIdentifier(message.requestId)) throw new Error("Invalid runtime release");
262
+ const requestedSession = sessionId;
263
+ ++releaseVersion;
264
+ const release = (async () => {
265
+ await options.onDisconnect?.();
266
+ })();
267
+ releaseInProgress = release;
268
+ try {
269
+ await release;
270
+ if (!disposed && current === generation && requestedSession === sessionId) send({
271
+ type: "release-result",
272
+ sessionId: requestedSession,
273
+ requestId: message.requestId,
274
+ result: {
275
+ ok: true,
276
+ value: require_protocol.encodeSqliteDevtoolsValue(void 0)
277
+ }
278
+ });
279
+ } catch (error) {
280
+ if (!disposed && current === generation && requestedSession === sessionId) send({
281
+ type: "release-result",
282
+ sessionId: requestedSession,
283
+ requestId: message.requestId,
284
+ result: {
285
+ ok: false,
286
+ error: require_protocol.serializeDevtoolsError(error)
287
+ }
288
+ });
289
+ } finally {
290
+ if (releaseInProgress === release) releaseInProgress = void 0;
291
+ }
292
+ return;
293
+ }
294
+ if (message.type !== "request" || !sessionId || message.sessionId !== sessionId || !require_protocol.isIdentifier(message.requestId)) throw new Error("Invalid runtime request");
295
+ if (requestIds.has(message.requestId) || requestIds.size >= 1e5) throw new Error("Duplicate or excessive request ids");
296
+ requestIds.add(message.requestId);
297
+ const requestId = message.requestId;
298
+ const requestedSession = sessionId;
299
+ const requestedReleaseVersion = releaseVersion;
300
+ let result;
301
+ try {
302
+ if (releaseInProgress) await releaseInProgress;
303
+ if (disposed || current !== generation || requestedSession !== sessionId || requestedReleaseVersion !== releaseVersion) return;
304
+ if (!require_protocol.isSqliteDevtoolsMethod(message.method) || message.method === "close" || !require_protocol.isIdentifier(message.databaseName) || !databases().includes(message.databaseName)) throw new require_protocol.SqliteDevtoolsError("SQLITE_DEVTOOLS_INVALID_REQUEST", "Unknown SQLite database or operation.");
305
+ if (!allowWrite && require_protocol.isSqliteDevtoolsWriteMethod(message.method)) throw new require_protocol.SqliteDevtoolsError("SQLITE_DEVTOOLS_READ_ONLY", "This SQLite DevTools session is read-only.");
306
+ const args = require_protocol.decodeSqliteDevtoolsValue(message.args);
307
+ if (!Array.isArray(args) || args.length > 8) throw new require_protocol.SqliteDevtoolsError("SQLITE_DEVTOOLS_INVALID_REQUEST", "SQLite operation arguments must be an array.");
308
+ const controller = await options.getController(message.databaseName);
309
+ if (disposed || current !== generation || requestedSession !== sessionId) return;
310
+ if (!databases().includes(message.databaseName)) throw new require_protocol.SqliteDevtoolsError("SQLITE_DEVTOOLS_DATABASE_CLOSED", "The selected SQLite database is no longer registered.");
311
+ const value = await controller[message.method].apply(controller, args);
312
+ result = {
313
+ ok: true,
314
+ value: require_protocol.encodeSqliteDevtoolsValue(value)
315
+ };
316
+ } catch (error) {
317
+ result = {
318
+ ok: false,
319
+ error: require_protocol.serializeDevtoolsError(error)
320
+ };
321
+ }
322
+ if (!disposed && current === generation && requestedSession === sessionId) send({
323
+ type: "result",
324
+ sessionId,
325
+ requestId,
326
+ result
327
+ });
328
+ } catch {
329
+ disconnect(current);
330
+ }
331
+ }
332
+ function connect() {
333
+ if (disposed) return;
334
+ const current = ++generation;
335
+ requestIds = /* @__PURE__ */ new Set();
336
+ try {
337
+ const created = options.createSocket(options.endpoint, {
338
+ open() {
339
+ queueMicrotask(() => {
340
+ if (disposed || current !== generation) return;
341
+ try {
342
+ send({
343
+ type: "hello",
344
+ protocol: 1,
345
+ token: options.token,
346
+ runtime: options.runtime,
347
+ databases: databases()
348
+ });
349
+ authTimer = setTimeout(disconnect, 5e3, current);
350
+ } catch {
351
+ disconnect(current);
352
+ }
353
+ });
354
+ },
355
+ message: (text) => {
356
+ receive(text, current);
357
+ },
358
+ close: () => disconnect(current),
359
+ error: () => disconnect(current)
360
+ });
361
+ if (disposed || current !== generation) {
362
+ try {
363
+ created.close();
364
+ } catch {}
365
+ return;
366
+ }
367
+ socket = created;
368
+ } catch {
369
+ disconnect(current);
370
+ }
371
+ }
372
+ connect();
373
+ return {
374
+ refresh() {
375
+ if (!disposed && sessionId) try {
376
+ send({
377
+ type: "databases",
378
+ sessionId,
379
+ databases: databases()
380
+ });
381
+ } catch {
382
+ disconnect(generation);
383
+ }
384
+ },
385
+ close() {
386
+ if (disposed) return;
387
+ disposed = true;
388
+ clearTimeout(reconnectTimer);
389
+ clearTimeout(authTimer);
390
+ disconnect(generation);
391
+ }
392
+ };
393
+ }
394
+ //#endregion
395
+ exports.connectSqliteDevtoolsRuntime = connectSqliteDevtoolsRuntime;
396
+ exports.createWeappSocketFactory = createWeappSocketFactory;
397
+ exports.createWebSocketFactory = createWebSocketFactory;
@@ -0,0 +1,68 @@
1
+ import { f as SqliteDevtoolsRuntime } from "./protocol-BhfjLrSe.cjs";
2
+ import { SqliteDebugController } from "@weapp-sqlite/debug";
3
+ //#region src/socket.d.ts
4
+ interface SqliteDevtoolsSocketHandlers {
5
+ readonly open: () => void;
6
+ readonly message: (data: string) => void;
7
+ readonly close: () => void;
8
+ readonly error: () => void;
9
+ }
10
+ interface SqliteDevtoolsSocket {
11
+ send: (data: string) => void;
12
+ close: () => void;
13
+ }
14
+ type SqliteDevtoolsSocketFactory = (url: string, handlers: SqliteDevtoolsSocketHandlers) => SqliteDevtoolsSocket;
15
+ interface SqliteDevtoolsWebSocket {
16
+ send: (data: string) => void;
17
+ close: () => void;
18
+ addEventListener: (type: string, listener: (event: {
19
+ data?: unknown;
20
+ }) => void) => void;
21
+ }
22
+ export declare function createWebSocketFactory(Constructor: new (url: string) => SqliteDevtoolsWebSocket): SqliteDevtoolsSocketFactory;
23
+ interface SqliteDevtoolsWeappSocketTask {
24
+ send: (options: {
25
+ data: string;
26
+ fail?: () => void;
27
+ }) => void;
28
+ close: (options: {
29
+ code: number;
30
+ reason: string;
31
+ }) => void;
32
+ onOpen: (handler: () => void) => void;
33
+ onMessage: (handler: (event: {
34
+ data: string | ArrayBuffer;
35
+ }) => void) => void;
36
+ onClose: (handler: () => void) => void;
37
+ onError: (handler: () => void) => void;
38
+ }
39
+ interface SqliteDevtoolsWeappSocketApi {
40
+ connectSocket: (options: {
41
+ url: string;
42
+ success: () => void;
43
+ fail: () => void;
44
+ }) => SqliteDevtoolsWeappSocketTask;
45
+ }
46
+ /** 直接使用 SocketTask,不依赖浏览器全局变量或动态求值。 */
47
+ export declare function createWeappSocketFactory(api: SqliteDevtoolsWeappSocketApi): SqliteDevtoolsSocketFactory;
48
+ //#endregion
49
+ //#region src/runtime.d.ts
50
+ export interface ConnectSqliteDevtoolsRuntimeOptions {
51
+ readonly endpoint: string;
52
+ readonly token: string;
53
+ readonly runtime: SqliteDevtoolsRuntime;
54
+ readonly listDatabases: () => readonly string[];
55
+ readonly getController: (databaseName: string) => SqliteDebugController | Promise<SqliteDebugController>;
56
+ readonly createSocket: SqliteDevtoolsSocketFactory;
57
+ /** Releases debug-only resources without closing application database handles. */
58
+ readonly onDisconnect?: () => void | Promise<void>;
59
+ readonly reconnectDelayMs?: number;
60
+ }
61
+ export interface SqliteDevtoolsRuntimeConnection {
62
+ refresh: () => void;
63
+ close: () => void;
64
+ }
65
+ /** 只登记和转发当前运行时的数据库,断线后不重放任何数据库操作。 */
66
+ export declare function connectSqliteDevtoolsRuntime(options: ConnectSqliteDevtoolsRuntimeOptions): SqliteDevtoolsRuntimeConnection;
67
+ //#endregion
68
+ export type { SqliteDevtoolsSocket, SqliteDevtoolsSocketFactory, SqliteDevtoolsSocketHandlers, SqliteDevtoolsWeappSocketApi, SqliteDevtoolsWeappSocketTask, SqliteDevtoolsWebSocket };
@@ -0,0 +1,68 @@
1
+ import { f as SqliteDevtoolsRuntime } from "./protocol-BhfjLrSe.mjs";
2
+ import { SqliteDebugController } from "@weapp-sqlite/debug";
3
+ //#region src/socket.d.ts
4
+ interface SqliteDevtoolsSocketHandlers {
5
+ readonly open: () => void;
6
+ readonly message: (data: string) => void;
7
+ readonly close: () => void;
8
+ readonly error: () => void;
9
+ }
10
+ interface SqliteDevtoolsSocket {
11
+ send: (data: string) => void;
12
+ close: () => void;
13
+ }
14
+ type SqliteDevtoolsSocketFactory = (url: string, handlers: SqliteDevtoolsSocketHandlers) => SqliteDevtoolsSocket;
15
+ interface SqliteDevtoolsWebSocket {
16
+ send: (data: string) => void;
17
+ close: () => void;
18
+ addEventListener: (type: string, listener: (event: {
19
+ data?: unknown;
20
+ }) => void) => void;
21
+ }
22
+ export declare function createWebSocketFactory(Constructor: new (url: string) => SqliteDevtoolsWebSocket): SqliteDevtoolsSocketFactory;
23
+ interface SqliteDevtoolsWeappSocketTask {
24
+ send: (options: {
25
+ data: string;
26
+ fail?: () => void;
27
+ }) => void;
28
+ close: (options: {
29
+ code: number;
30
+ reason: string;
31
+ }) => void;
32
+ onOpen: (handler: () => void) => void;
33
+ onMessage: (handler: (event: {
34
+ data: string | ArrayBuffer;
35
+ }) => void) => void;
36
+ onClose: (handler: () => void) => void;
37
+ onError: (handler: () => void) => void;
38
+ }
39
+ interface SqliteDevtoolsWeappSocketApi {
40
+ connectSocket: (options: {
41
+ url: string;
42
+ success: () => void;
43
+ fail: () => void;
44
+ }) => SqliteDevtoolsWeappSocketTask;
45
+ }
46
+ /** 直接使用 SocketTask,不依赖浏览器全局变量或动态求值。 */
47
+ export declare function createWeappSocketFactory(api: SqliteDevtoolsWeappSocketApi): SqliteDevtoolsSocketFactory;
48
+ //#endregion
49
+ //#region src/runtime.d.ts
50
+ export interface ConnectSqliteDevtoolsRuntimeOptions {
51
+ readonly endpoint: string;
52
+ readonly token: string;
53
+ readonly runtime: SqliteDevtoolsRuntime;
54
+ readonly listDatabases: () => readonly string[];
55
+ readonly getController: (databaseName: string) => SqliteDebugController | Promise<SqliteDebugController>;
56
+ readonly createSocket: SqliteDevtoolsSocketFactory;
57
+ /** Releases debug-only resources without closing application database handles. */
58
+ readonly onDisconnect?: () => void | Promise<void>;
59
+ readonly reconnectDelayMs?: number;
60
+ }
61
+ export interface SqliteDevtoolsRuntimeConnection {
62
+ refresh: () => void;
63
+ close: () => void;
64
+ }
65
+ /** 只登记和转发当前运行时的数据库,断线后不重放任何数据库操作。 */
66
+ export declare function connectSqliteDevtoolsRuntime(options: ConnectSqliteDevtoolsRuntimeOptions): SqliteDevtoolsRuntimeConnection;
67
+ //#endregion
68
+ export type { SqliteDevtoolsSocket, SqliteDevtoolsSocketFactory, SqliteDevtoolsSocketHandlers, SqliteDevtoolsWeappSocketApi, SqliteDevtoolsWeappSocketTask, SqliteDevtoolsWebSocket };