@supalive/core 0.1.3 → 0.1.5
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 +308 -1
- package/dist/helper-CiacMqje.d.ts +14 -0
- package/dist/helper-CiacMqje.d.ts.map +1 -0
- package/dist/helper-zdJT5FUc.js +58 -0
- package/dist/helper-zdJT5FUc.js.map +1 -0
- package/dist/index-CTyXKcq_.d.ts +1736 -0
- package/dist/index-CTyXKcq_.d.ts.map +1 -0
- package/dist/mysql-C8SN443m.d.ts +104 -0
- package/dist/mysql-C8SN443m.d.ts.map +1 -0
- package/dist/mysql-DELSRrpY.js +569 -0
- package/dist/mysql-DELSRrpY.js.map +1 -0
- package/dist/overlap-checker-CVkbbuEQ.js +187 -0
- package/dist/overlap-checker-CVkbbuEQ.js.map +1 -0
- package/dist/postgres-DE-XyNAQ.js +823 -0
- package/dist/postgres-DE-XyNAQ.js.map +1 -0
- package/dist/postgres-D_gwCHx-.d.ts +108 -0
- package/dist/postgres-D_gwCHx-.d.ts.map +1 -0
- package/dist/query-CbQLjeME.js +713 -0
- package/dist/query-CbQLjeME.js.map +1 -0
- package/dist/realtime_db-D9p2X2PH.js +246 -0
- package/dist/realtime_db-D9p2X2PH.js.map +1 -0
- package/dist/router-DlTYWpop.js +81 -0
- package/dist/router-DlTYWpop.js.map +1 -0
- package/dist/schema-SKcIWHfo.js +167 -0
- package/dist/schema-SKcIWHfo.js.map +1 -0
- package/dist/src/client/index.d.ts +2 -17
- package/dist/src/client/index.js +1151 -18
- package/dist/src/client/index.js.map +1 -1
- package/dist/src/exports/mysql.d.ts +2 -2
- package/dist/src/exports/mysql.js +2 -2
- package/dist/src/exports/postgres.d.ts +2 -2
- package/dist/src/exports/postgres.js +2 -2
- package/dist/src/exports/procedure.d.ts +3 -5
- package/dist/src/exports/procedure.js +5 -5
- package/dist/src/exports/server.d.ts +368 -2
- package/dist/src/exports/server.d.ts.map +1 -1
- package/dist/src/exports/server.js +1346 -2
- package/dist/src/exports/server.js.map +1 -1
- package/dist/src/exports/subscription-manager-worker-entry.d.ts +1 -0
- package/dist/src/exports/subscription-manager-worker-entry.js +115 -0
- package/dist/src/exports/subscription-manager-worker-entry.js.map +1 -0
- package/dist/src/exports/types.d.ts +4 -6
- package/dist/src/exports/types.js +5 -6
- package/dist/subscription-worker-BurdPO8d.js +511 -0
- package/dist/subscription-worker-BurdPO8d.js.map +1 -0
- package/dist/types_client_rpc-CIsjQQGG.js +105 -0
- package/dist/types_client_rpc-CIsjQQGG.js.map +1 -0
- package/dist/types_db-Ctf-ksoy.js +168 -0
- package/dist/types_db-Ctf-ksoy.js.map +1 -0
- package/dist/types_server-Ch56y8L3.d.ts +216 -0
- package/dist/types_server-Ch56y8L3.d.ts.map +1 -0
- package/dist/types_server-Dk6o_B7N.js +24 -0
- package/dist/types_server-Dk6o_B7N.js.map +1 -0
- package/package.json +3 -3
- package/dist/src/client/caller_client.d.ts +0 -42
- package/dist/src/client/caller_client.d.ts.map +0 -1
- package/dist/src/client/caller_client.js +0 -77
- package/dist/src/client/caller_client.js.map +0 -1
- package/dist/src/client/client.d.ts +0 -149
- package/dist/src/client/client.d.ts.map +0 -1
- package/dist/src/client/client.js +0 -308
- package/dist/src/client/client.js.map +0 -1
- package/dist/src/client/index.d.ts.map +0 -1
- package/dist/src/client/sub_key.d.ts +0 -20
- package/dist/src/client/sub_key.d.ts.map +0 -1
- package/dist/src/client/sub_key.js +0 -37
- package/dist/src/client/sub_key.js.map +0 -1
- package/dist/src/client/ws_client_manager.d.ts +0 -268
- package/dist/src/client/ws_client_manager.d.ts.map +0 -1
- package/dist/src/client/ws_client_manager.js +0 -1013
- package/dist/src/client/ws_client_manager.js.map +0 -1
- package/dist/src/config.d.ts +0 -117
- package/dist/src/config.d.ts.map +0 -1
- package/dist/src/config.js +0 -2
- package/dist/src/config.js.map +0 -1
- package/dist/src/db/bytes.d.ts +0 -4
- package/dist/src/db/bytes.d.ts.map +0 -1
- package/dist/src/db/bytes.js +0 -24
- package/dist/src/db/bytes.js.map +0 -1
- package/dist/src/db/cache.d.ts +0 -30
- package/dist/src/db/cache.d.ts.map +0 -1
- package/dist/src/db/cache.js +0 -153
- package/dist/src/db/cache.js.map +0 -1
- package/dist/src/db/codec.d.ts +0 -10
- package/dist/src/db/codec.d.ts.map +0 -1
- package/dist/src/db/codec.js +0 -73
- package/dist/src/db/codec.js.map +0 -1
- package/dist/src/db/context.d.ts +0 -28
- package/dist/src/db/context.d.ts.map +0 -1
- package/dist/src/db/context.js +0 -147
- package/dist/src/db/context.js.map +0 -1
- package/dist/src/db/db.d.ts +0 -154
- package/dist/src/db/db.d.ts.map +0 -1
- package/dist/src/db/db.js +0 -23
- package/dist/src/db/db.js.map +0 -1
- package/dist/src/db/mysql.d.ts +0 -120
- package/dist/src/db/mysql.d.ts.map +0 -1
- package/dist/src/db/mysql.js +0 -708
- package/dist/src/db/mysql.js.map +0 -1
- package/dist/src/db/postgres.d.ts +0 -116
- package/dist/src/db/postgres.d.ts.map +0 -1
- package/dist/src/db/postgres.js +0 -998
- package/dist/src/db/postgres.js.map +0 -1
- package/dist/src/db/query.d.ts +0 -174
- package/dist/src/db/query.d.ts.map +0 -1
- package/dist/src/db/query.js +0 -790
- package/dist/src/db/query.js.map +0 -1
- package/dist/src/db/query_definition.d.ts +0 -54
- package/dist/src/db/query_definition.d.ts.map +0 -1
- package/dist/src/db/query_definition.js +0 -47
- package/dist/src/db/query_definition.js.map +0 -1
- package/dist/src/db/realtime_db.d.ts +0 -19
- package/dist/src/db/realtime_db.d.ts.map +0 -1
- package/dist/src/db/realtime_db.js +0 -98
- package/dist/src/db/realtime_db.js.map +0 -1
- package/dist/src/db/schema.d.ts +0 -110
- package/dist/src/db/schema.d.ts.map +0 -1
- package/dist/src/db/schema.js +0 -47
- package/dist/src/db/schema.js.map +0 -1
- package/dist/src/db/types_client_rpc.d.ts +0 -157
- package/dist/src/db/types_client_rpc.d.ts.map +0 -1
- package/dist/src/db/types_client_rpc.js +0 -106
- package/dist/src/db/types_client_rpc.js.map +0 -1
- package/dist/src/db/types_db.d.ts +0 -236
- package/dist/src/db/types_db.d.ts.map +0 -1
- package/dist/src/db/types_db.js +0 -188
- package/dist/src/db/types_db.js.map +0 -1
- package/dist/src/exports/mysql.d.ts.map +0 -1
- package/dist/src/exports/mysql.js.map +0 -1
- package/dist/src/exports/postgres.d.ts.map +0 -1
- package/dist/src/exports/postgres.js.map +0 -1
- package/dist/src/exports/procedure.d.ts.map +0 -1
- package/dist/src/exports/procedure.js.map +0 -1
- package/dist/src/exports/types.d.ts.map +0 -1
- package/dist/src/exports/types.js.map +0 -1
- package/dist/src/helper.d.ts +0 -11
- package/dist/src/helper.d.ts.map +0 -1
- package/dist/src/helper.js +0 -45
- package/dist/src/helper.js.map +0 -1
- package/dist/src/logger.d.ts +0 -7
- package/dist/src/logger.d.ts.map +0 -1
- package/dist/src/logger.js +0 -45
- package/dist/src/logger.js.map +0 -1
- package/dist/src/router/index.d.ts +0 -4
- package/dist/src/router/index.d.ts.map +0 -1
- package/dist/src/router/index.js +0 -4
- package/dist/src/router/index.js.map +0 -1
- package/dist/src/router/procedure.d.ts +0 -204
- package/dist/src/router/procedure.d.ts.map +0 -1
- package/dist/src/router/procedure.js +0 -122
- package/dist/src/router/procedure.js.map +0 -1
- package/dist/src/router/router.d.ts +0 -88
- package/dist/src/router/router.d.ts.map +0 -1
- package/dist/src/router/router.js +0 -88
- package/dist/src/router/router.js.map +0 -1
- package/dist/src/server/hash.d.ts +0 -12
- package/dist/src/server/hash.d.ts.map +0 -1
- package/dist/src/server/hash.js +0 -20
- package/dist/src/server/hash.js.map +0 -1
- package/dist/src/server/hash.test.d.ts +0 -2
- package/dist/src/server/hash.test.d.ts.map +0 -1
- package/dist/src/server/hash.test.js +0 -43
- package/dist/src/server/hash.test.js.map +0 -1
- package/dist/src/server/index.d.ts +0 -8
- package/dist/src/server/index.d.ts.map +0 -1
- package/dist/src/server/index.js +0 -7
- package/dist/src/server/index.js.map +0 -1
- package/dist/src/server/overlap-checker.d.ts +0 -18
- package/dist/src/server/overlap-checker.d.ts.map +0 -1
- package/dist/src/server/overlap-checker.js +0 -247
- package/dist/src/server/overlap-checker.js.map +0 -1
- package/dist/src/server/sub_hash.d.ts +0 -23
- package/dist/src/server/sub_hash.d.ts.map +0 -1
- package/dist/src/server/sub_hash.js +0 -38
- package/dist/src/server/sub_hash.js.map +0 -1
- package/dist/src/server/subscription-manager-client.d.ts +0 -120
- package/dist/src/server/subscription-manager-client.d.ts.map +0 -1
- package/dist/src/server/subscription-manager-client.js +0 -207
- package/dist/src/server/subscription-manager-client.js.map +0 -1
- package/dist/src/server/subscription-manager-types.d.ts +0 -168
- package/dist/src/server/subscription-manager-types.d.ts.map +0 -1
- package/dist/src/server/subscription-manager-types.js +0 -94
- package/dist/src/server/subscription-manager-types.js.map +0 -1
- package/dist/src/server/subscription-manager-worker-entry.d.ts +0 -2
- package/dist/src/server/subscription-manager-worker-entry.d.ts.map +0 -1
- package/dist/src/server/subscription-manager-worker-entry.js +0 -127
- package/dist/src/server/subscription-manager-worker-entry.js.map +0 -1
- package/dist/src/server/subscription-manager-worker-protocol.d.ts +0 -40
- package/dist/src/server/subscription-manager-worker-protocol.d.ts.map +0 -1
- package/dist/src/server/subscription-manager-worker-protocol.js +0 -20
- package/dist/src/server/subscription-manager-worker-protocol.js.map +0 -1
- package/dist/src/server/subscription-manager.d.ts +0 -32
- package/dist/src/server/subscription-manager.d.ts.map +0 -1
- package/dist/src/server/subscription-manager.js +0 -249
- package/dist/src/server/subscription-manager.js.map +0 -1
- package/dist/src/server/subscription-manager.test.d.ts +0 -2
- package/dist/src/server/subscription-manager.test.d.ts.map +0 -1
- package/dist/src/server/subscription-manager.test.js +0 -610
- package/dist/src/server/subscription-manager.test.js.map +0 -1
- package/dist/src/server/subscription-worker.d.ts +0 -32
- package/dist/src/server/subscription-worker.d.ts.map +0 -1
- package/dist/src/server/subscription-worker.js +0 -190
- package/dist/src/server/subscription-worker.js.map +0 -1
- package/dist/src/server/supalive-server.d.ts +0 -158
- package/dist/src/server/supalive-server.d.ts.map +0 -1
- package/dist/src/server/supalive-server.js +0 -1048
- package/dist/src/server/supalive-server.js.map +0 -1
- package/dist/src/server/types_server.d.ts +0 -96
- package/dist/src/server/types_server.d.ts.map +0 -1
- package/dist/src/server/types_server.js +0 -36
- package/dist/src/server/types_server.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
//#region src/db/types_client_rpc.ts
|
|
3
|
+
const AuthMessageSchema = z.object({
|
|
4
|
+
type: z.literal("auth"),
|
|
5
|
+
data: z.record(z.string(), z.any()).optional()
|
|
6
|
+
});
|
|
7
|
+
const CallMessageSchema = z.object({
|
|
8
|
+
type: z.literal("call"),
|
|
9
|
+
id: z.string(),
|
|
10
|
+
procedure: z.string(),
|
|
11
|
+
input: z.unknown()
|
|
12
|
+
});
|
|
13
|
+
const SubscribeMessageSchema = z.object({
|
|
14
|
+
type: z.literal("subscribe"),
|
|
15
|
+
id: z.string(),
|
|
16
|
+
procedure: z.string(),
|
|
17
|
+
input: z.unknown()
|
|
18
|
+
});
|
|
19
|
+
const UnsubscribeMessageSchema = z.object({
|
|
20
|
+
type: z.literal("unsubscribe"),
|
|
21
|
+
subId: z.string()
|
|
22
|
+
});
|
|
23
|
+
const ClientMessageSchema = z.union([
|
|
24
|
+
AuthMessageSchema,
|
|
25
|
+
CallMessageSchema,
|
|
26
|
+
SubscribeMessageSchema,
|
|
27
|
+
UnsubscribeMessageSchema
|
|
28
|
+
]);
|
|
29
|
+
const ConnectedMessageSchema = z.object({
|
|
30
|
+
type: z.literal("connected"),
|
|
31
|
+
sessionId: z.string()
|
|
32
|
+
});
|
|
33
|
+
const AuthSuccessMessageSchema = z.object({
|
|
34
|
+
type: z.literal("auth:success"),
|
|
35
|
+
userId: z.string(),
|
|
36
|
+
extra: z.object().optional()
|
|
37
|
+
});
|
|
38
|
+
const AuthFailedMessageSchema = z.object({
|
|
39
|
+
type: z.literal("auth:failed"),
|
|
40
|
+
message: z.string(),
|
|
41
|
+
extra: z.record(z.string(), z.unknown()).optional()
|
|
42
|
+
});
|
|
43
|
+
const ResponseMessageSchema = z.object({
|
|
44
|
+
type: z.literal("response"),
|
|
45
|
+
id: z.string(),
|
|
46
|
+
success: z.boolean(),
|
|
47
|
+
data: z.unknown().optional(),
|
|
48
|
+
error: z.string().optional(),
|
|
49
|
+
code: z.string().optional(),
|
|
50
|
+
/**
|
|
51
|
+
* Populated by the server only for a successful `subscribe` response.
|
|
52
|
+
* Carries the canonical, server-computed subscription id so the client
|
|
53
|
+
* can route subsequent `sub:update` / `sub:gone` messages without
|
|
54
|
+
* recomputing the hash locally (which would require the wasm runtime
|
|
55
|
+
* and would not reflect server-side per-procedure `queryIdentity`
|
|
56
|
+
* overrides).
|
|
57
|
+
*/
|
|
58
|
+
subId: z.string().optional()
|
|
59
|
+
});
|
|
60
|
+
const SubscriptionUpdateMessageSchema = z.object({
|
|
61
|
+
type: z.literal("sub:update"),
|
|
62
|
+
subId: z.string(),
|
|
63
|
+
data: z.unknown(),
|
|
64
|
+
dataHash: z.string().optional()
|
|
65
|
+
});
|
|
66
|
+
/**
|
|
67
|
+
* Notifies a client that a subscription is no longer tracked on the server
|
|
68
|
+
* and will not receive further updates. Sent when, during a sub-manager
|
|
69
|
+
* recovery cycle, the registration record could not be found (e.g. another
|
|
70
|
+
* app-server instance fully unregistered the sub while we were disconnected).
|
|
71
|
+
* The client may choose to re-subscribe or surface the state to the user.
|
|
72
|
+
*/
|
|
73
|
+
const SubscriptionGoneMessageSchema = z.object({
|
|
74
|
+
type: z.literal("sub:gone"),
|
|
75
|
+
subId: z.string(),
|
|
76
|
+
reason: z.string().optional()
|
|
77
|
+
});
|
|
78
|
+
/**
|
|
79
|
+
* Server-driven liveness signal. Sent when the channel has been idle for
|
|
80
|
+
* the configured app-ping interval (default 15s) and again after every
|
|
81
|
+
* outbound message. Pure no-op for the client: receiving any message
|
|
82
|
+
* (including this one) resets the client's inactivity watchdog. The client
|
|
83
|
+
* does NOT reply.
|
|
84
|
+
*/
|
|
85
|
+
const ServerPingMessageSchema = z.object({ type: z.literal("ping") });
|
|
86
|
+
const ServerMessageSchema = z.union([
|
|
87
|
+
ConnectedMessageSchema,
|
|
88
|
+
AuthSuccessMessageSchema,
|
|
89
|
+
AuthFailedMessageSchema,
|
|
90
|
+
ResponseMessageSchema,
|
|
91
|
+
SubscriptionUpdateMessageSchema,
|
|
92
|
+
SubscriptionGoneMessageSchema,
|
|
93
|
+
ServerPingMessageSchema
|
|
94
|
+
]);
|
|
95
|
+
var AuthenticationError = class extends Error {
|
|
96
|
+
extra;
|
|
97
|
+
constructor(message, extra = {}) {
|
|
98
|
+
super(message);
|
|
99
|
+
this.extra = extra;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
//#endregion
|
|
103
|
+
export { CallMessageSchema as a, ResponseMessageSchema as c, SubscribeMessageSchema as d, SubscriptionGoneMessageSchema as f, AuthenticationError as i, ServerMessageSchema as l, UnsubscribeMessageSchema as m, AuthMessageSchema as n, ClientMessageSchema as o, SubscriptionUpdateMessageSchema as p, AuthSuccessMessageSchema as r, ConnectedMessageSchema as s, AuthFailedMessageSchema as t, ServerPingMessageSchema as u };
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=types_client_rpc-CIsjQQGG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types_client_rpc-CIsjQQGG.js","names":[],"sources":["../src/db/types_client_rpc.ts"],"sourcesContent":["import z from \"zod\";\n\nexport interface ErrorMessage {\n type: \"error\";\n id?: string;\n error: string;\n code?: string;\n}\n\n// ─── WebSocket Message Schemas ────────────────────────────────────────────────\n// Zod schemas for runtime validation of WebSocket messages\n\nexport const AuthMessageSchema = z.object({\n type: z.literal(\"auth\"),\n data: z.record(z.string(), z.any()).optional(),\n});\n\nexport const CallMessageSchema = z.object({\n type: z.literal(\"call\"),\n id: z.string(),\n procedure: z.string(),\n input: z.unknown(),\n});\n\nexport const SubscribeMessageSchema = z.object({\n type: z.literal(\"subscribe\"),\n id: z.string(),\n procedure: z.string(),\n input: z.unknown(),\n});\n\nexport const UnsubscribeMessageSchema = z.object({\n type: z.literal(\"unsubscribe\"),\n subId: z.string(),\n});\n\nexport const ClientMessageSchema = z.union([\n AuthMessageSchema,\n CallMessageSchema,\n SubscribeMessageSchema,\n UnsubscribeMessageSchema,\n]);\n\n// Infer TypeScript types from schemas\nexport type AuthMessage = z.infer<typeof AuthMessageSchema>;\nexport type CallMessage = z.infer<typeof CallMessageSchema>;\nexport type SubscribeMessage = z.infer<typeof SubscribeMessageSchema>;\nexport type UnsubscribeMessage = z.infer<typeof UnsubscribeMessageSchema>;\nexport type ClientMessage = z.infer<typeof ClientMessageSchema>;\n\n// ─── Server Message Schemas ───────────────────────────────────────────────────\n\nexport const ConnectedMessageSchema = z.object({\n type: z.literal(\"connected\"),\n sessionId: z.string(),\n});\n\nexport const AuthSuccessMessageSchema = z.object({\n type: z.literal(\"auth:success\"),\n userId: z.string(),\n extra: z.object().optional()\n});\n\nexport const AuthFailedMessageSchema = z.object({\n type: z.literal(\"auth:failed\"),\n message: z.string(),\n extra: z.record(z.string(), z.unknown()).optional()\n});\n\nexport const ResponseMessageSchema = z.object({\n type: z.literal(\"response\"),\n id: z.string(),\n success: z.boolean(),\n data: z.unknown().optional(),\n error: z.string().optional(),\n code: z.string().optional(),\n /**\n * Populated by the server only for a successful `subscribe` response.\n * Carries the canonical, server-computed subscription id so the client\n * can route subsequent `sub:update` / `sub:gone` messages without\n * recomputing the hash locally (which would require the wasm runtime\n * and would not reflect server-side per-procedure `queryIdentity`\n * overrides).\n */\n subId: z.string().optional(),\n});\n\nexport const SubscriptionUpdateMessageSchema = z.object({\n type: z.literal(\"sub:update\"),\n subId: z.string(),\n data: z.unknown(),\n dataHash: z.string().optional(),\n});\n\n/**\n * Notifies a client that a subscription is no longer tracked on the server\n * and will not receive further updates. Sent when, during a sub-manager\n * recovery cycle, the registration record could not be found (e.g. another\n * app-server instance fully unregistered the sub while we were disconnected).\n * The client may choose to re-subscribe or surface the state to the user.\n */\nexport const SubscriptionGoneMessageSchema = z.object({\n type: z.literal(\"sub:gone\"),\n subId: z.string(),\n reason: z.string().optional(),\n});\n\n/**\n * Server-driven liveness signal. Sent when the channel has been idle for\n * the configured app-ping interval (default 15s) and again after every\n * outbound message. Pure no-op for the client: receiving any message\n * (including this one) resets the client's inactivity watchdog. The client\n * does NOT reply.\n */\nexport const ServerPingMessageSchema = z.object({\n type: z.literal(\"ping\"),\n});\n\nexport const ServerMessageSchema = z.union([\n ConnectedMessageSchema,\n AuthSuccessMessageSchema,\n AuthFailedMessageSchema,\n ResponseMessageSchema,\n SubscriptionUpdateMessageSchema,\n SubscriptionGoneMessageSchema,\n ServerPingMessageSchema,\n]);\n\nexport type ConnectedMessage = z.infer<typeof ConnectedMessageSchema>;\nexport type AuthSuccessMessage = z.infer<typeof AuthSuccessMessageSchema>;\nexport type AuthFailedMessage = z.infer<typeof AuthFailedMessageSchema>;\nexport type ResponseMessage = z.infer<typeof ResponseMessageSchema>;\nexport type SubscriptionUpdateMessage = z.infer<typeof SubscriptionUpdateMessageSchema>;\nexport type SubscriptionGoneMessage = z.infer<typeof SubscriptionGoneMessageSchema>;\nexport type ServerPingMessage = z.infer<typeof ServerPingMessageSchema>;\nexport type ServerMessage = z.infer<typeof ServerMessageSchema>;\n\nexport class AuthenticationError extends Error {\n constructor(\n message: string,\n public extra: Record<string, unknown> = {},\n ) {\n super(message);\n }\n}\n\n/**\n * Helper type to check if a procedure is internal.\n */\nexport type IsInternal<T> = T extends { internal: infer I } ? (I extends true ? true : false) : false;\n\nexport interface Context {\n requestId: string;\n /** Authenticated user info */\n user: {\n userId: string;\n };\n}\n"],"mappings":";;AAYA,MAAa,oBAAoB,EAAE,OAAO;CACxC,MAAM,EAAE,QAAQ,MAAM;CACtB,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS;AAC/C,CAAC;AAED,MAAa,oBAAoB,EAAE,OAAO;CACxC,MAAM,EAAE,QAAQ,MAAM;CACtB,IAAI,EAAE,OAAO;CACb,WAAW,EAAE,OAAO;CACpB,OAAO,EAAE,QAAQ;AACnB,CAAC;AAED,MAAa,yBAAyB,EAAE,OAAO;CAC7C,MAAM,EAAE,QAAQ,WAAW;CAC3B,IAAI,EAAE,OAAO;CACb,WAAW,EAAE,OAAO;CACpB,OAAO,EAAE,QAAQ;AACnB,CAAC;AAED,MAAa,2BAA2B,EAAE,OAAO;CAC/C,MAAM,EAAE,QAAQ,aAAa;CAC7B,OAAO,EAAE,OAAO;AAClB,CAAC;AAED,MAAa,sBAAsB,EAAE,MAAM;CACzC;CACA;CACA;CACA;AACF,CAAC;AAWD,MAAa,yBAAyB,EAAE,OAAO;CAC7C,MAAM,EAAE,QAAQ,WAAW;CAC3B,WAAW,EAAE,OAAO;AACtB,CAAC;AAED,MAAa,2BAA2B,EAAE,OAAO;CAC/C,MAAM,EAAE,QAAQ,cAAc;CAC9B,QAAQ,EAAE,OAAO;CACjB,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;AAC7B,CAAC;AAED,MAAa,0BAA0B,EAAE,OAAO;CAC9C,MAAM,EAAE,QAAQ,aAAa;CAC7B,SAAS,EAAE,OAAO;CAClB,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS;AACpD,CAAC;AAED,MAAa,wBAAwB,EAAE,OAAO;CAC5C,MAAM,EAAE,QAAQ,UAAU;CAC1B,IAAI,EAAE,OAAO;CACb,SAAS,EAAE,QAAQ;CACnB,MAAM,EAAE,QAAQ,CAAC,CAAC,SAAS;CAC3B,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;CAC3B,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS;;;;;;;;;CAS1B,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;AAC7B,CAAC;AAED,MAAa,kCAAkC,EAAE,OAAO;CACtD,MAAM,EAAE,QAAQ,YAAY;CAC5B,OAAO,EAAE,OAAO;CAChB,MAAM,EAAE,QAAQ;CAChB,UAAU,EAAE,OAAO,CAAC,CAAC,SAAS;AAChC,CAAC;;;;;;;;AASD,MAAa,gCAAgC,EAAE,OAAO;CACpD,MAAM,EAAE,QAAQ,UAAU;CAC1B,OAAO,EAAE,OAAO;CAChB,QAAQ,EAAE,OAAO,CAAC,CAAC,SAAS;AAC9B,CAAC;;;;;;;;AASD,MAAa,0BAA0B,EAAE,OAAO,EAC9C,MAAM,EAAE,QAAQ,MAAM,EACxB,CAAC;AAED,MAAa,sBAAsB,EAAE,MAAM;CACzC;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAWD,IAAa,sBAAb,cAAyC,MAAM;CAGpC;CAFT,YACE,SACA,QAAwC,CAAC,GACzC;EACA,MAAM,OAAO;EAFN,KAAA,QAAA;CAGT;AACF"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { o as utf8Encode } from "./helper-zdJT5FUc.js";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
//#region src/db/types_db.ts
|
|
4
|
+
const BigIntSchema = z.string().transform((val) => BigInt(val));
|
|
5
|
+
const CompareOperatorSchema = z.enum([
|
|
6
|
+
"=",
|
|
7
|
+
"!=",
|
|
8
|
+
">",
|
|
9
|
+
">=",
|
|
10
|
+
"<",
|
|
11
|
+
"<=",
|
|
12
|
+
"like",
|
|
13
|
+
"ilike",
|
|
14
|
+
"contains",
|
|
15
|
+
"icontains",
|
|
16
|
+
"between",
|
|
17
|
+
"jsonContains",
|
|
18
|
+
"jsonContainedBy",
|
|
19
|
+
"jsonHasKey",
|
|
20
|
+
"jsonArrayContains",
|
|
21
|
+
"isNull",
|
|
22
|
+
"isNotNull"
|
|
23
|
+
]);
|
|
24
|
+
const PredicateSchema = z.lazy(() => z.union([
|
|
25
|
+
LeafPredicateSchema,
|
|
26
|
+
AndPredicateSchema,
|
|
27
|
+
OrPredicateSchema
|
|
28
|
+
]));
|
|
29
|
+
const LeafPredicateSchema = z.object({
|
|
30
|
+
"kind": z.literal("leaf"),
|
|
31
|
+
column: z.string(),
|
|
32
|
+
operator: CompareOperatorSchema,
|
|
33
|
+
value: z.unknown(),
|
|
34
|
+
value2: z.unknown().optional(),
|
|
35
|
+
raw: z.boolean().optional(),
|
|
36
|
+
path: z.string().optional(),
|
|
37
|
+
mode: z.enum(["one", "all"]).optional()
|
|
38
|
+
});
|
|
39
|
+
const AndPredicateSchema = z.object({
|
|
40
|
+
kind: z.literal("and"),
|
|
41
|
+
children: z.array(PredicateSchema)
|
|
42
|
+
});
|
|
43
|
+
const OrPredicateSchema = z.object({
|
|
44
|
+
kind: z.literal("or"),
|
|
45
|
+
children: z.array(PredicateSchema)
|
|
46
|
+
});
|
|
47
|
+
const Uint8ArraySchema = z.any().transform((val) => {
|
|
48
|
+
if (val instanceof Uint8Array) return val;
|
|
49
|
+
return bytesFromJson(val);
|
|
50
|
+
});
|
|
51
|
+
function normalizeIdToBytes(id, fromHex = false) {
|
|
52
|
+
const data = (typeof id === "number" ? String(id) : id).replace(/-/g, "");
|
|
53
|
+
if (fromHex === true) {
|
|
54
|
+
const len = data.length >>> 1;
|
|
55
|
+
const out = new Uint8Array(len);
|
|
56
|
+
for (let i = 0; i < len; i++) out[i] = parseInt(data.substring(i * 2, i * 2 + 2), 16);
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
return utf8Encode(data);
|
|
60
|
+
}
|
|
61
|
+
function normalizeToBytes(value) {
|
|
62
|
+
try {
|
|
63
|
+
return bytesFromJson(value);
|
|
64
|
+
} catch (_) {
|
|
65
|
+
return /* @__PURE__ */ new Uint8Array(0);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function bytesFromJson(value) {
|
|
69
|
+
if (value instanceof Uint8Array) return value;
|
|
70
|
+
if (Array.isArray(value)) return Uint8Array.from(value);
|
|
71
|
+
if (value && typeof value === "object" && "type" in value && value.type === "Buffer" && "data" in value) return Uint8Array.from(value.data);
|
|
72
|
+
if (typeof value === "string") return utf8Encode(value);
|
|
73
|
+
if (typeof value === "number") return utf8Encode(String(value));
|
|
74
|
+
throw new Error("Invalid buffer value");
|
|
75
|
+
}
|
|
76
|
+
const PointReadSchema = z.object({
|
|
77
|
+
kind: z.literal("point"),
|
|
78
|
+
table: z.string(),
|
|
79
|
+
id: z.string(),
|
|
80
|
+
tableId: Uint8ArraySchema,
|
|
81
|
+
expectedCommitTs: BigIntSchema.nullable().optional()
|
|
82
|
+
});
|
|
83
|
+
const RawPointReadSchema = z.object({
|
|
84
|
+
kind: z.literal("point"),
|
|
85
|
+
tableId: Uint8ArraySchema,
|
|
86
|
+
id: Uint8ArraySchema,
|
|
87
|
+
table: z.string(),
|
|
88
|
+
expectedCommitTs: BigIntSchema.nullable().optional()
|
|
89
|
+
});
|
|
90
|
+
/**
|
|
91
|
+
* Query specification for a range read (get with filters).
|
|
92
|
+
* This is the query definition, not the result.
|
|
93
|
+
*/
|
|
94
|
+
const RangeReadSchema = z.object({
|
|
95
|
+
kind: z.literal("range"),
|
|
96
|
+
table: z.string(),
|
|
97
|
+
tableId: Uint8ArraySchema,
|
|
98
|
+
predicate: PredicateSchema,
|
|
99
|
+
columns: z.array(z.string()),
|
|
100
|
+
orderBy: z.string().nullable().optional(),
|
|
101
|
+
limit: z.number().nullable().optional(),
|
|
102
|
+
offset: z.number().nullable().optional()
|
|
103
|
+
});
|
|
104
|
+
const RawRangeReadSchema = z.object({
|
|
105
|
+
kind: z.literal("range"),
|
|
106
|
+
table: z.string(),
|
|
107
|
+
tableId: Uint8ArraySchema,
|
|
108
|
+
predicate: PredicateSchema,
|
|
109
|
+
columns: z.array(z.string()),
|
|
110
|
+
orderBy: z.string().nullable().optional(),
|
|
111
|
+
limit: z.number().nullable().optional(),
|
|
112
|
+
offset: z.number().nullable().optional()
|
|
113
|
+
});
|
|
114
|
+
const ReadEntrySchema = z.union([PointReadSchema, RangeReadSchema]);
|
|
115
|
+
const RawReadEntrySchema = z.union([RawPointReadSchema, RawRangeReadSchema]);
|
|
116
|
+
const WriteOpSchema = z.enum([
|
|
117
|
+
"insert",
|
|
118
|
+
"update",
|
|
119
|
+
"delete"
|
|
120
|
+
]);
|
|
121
|
+
const WriteEntrySchema = z.object({
|
|
122
|
+
table: z.string(),
|
|
123
|
+
tableId: Uint8ArraySchema,
|
|
124
|
+
id: z.string(),
|
|
125
|
+
op: WriteOpSchema,
|
|
126
|
+
data: z.record(z.string(), z.unknown()).optional(),
|
|
127
|
+
prevData: z.record(z.string(), z.unknown()).optional(),
|
|
128
|
+
expectedCommitTs: BigIntSchema.nullable().optional()
|
|
129
|
+
});
|
|
130
|
+
const QueryCacheMetadataSchema = z.object({
|
|
131
|
+
lastSnapshotTs: BigIntSchema,
|
|
132
|
+
readSet: z.array(ReadEntrySchema)
|
|
133
|
+
});
|
|
134
|
+
const QueryCacheEntrySchema = z.object({ data: z.unknown() });
|
|
135
|
+
const CachedPgMetadataSchema = z.record(z.string(), z.record(z.string(), z.string()));
|
|
136
|
+
const NO_RETRY = {
|
|
137
|
+
maxAttempts: 1,
|
|
138
|
+
backoff: "none"
|
|
139
|
+
};
|
|
140
|
+
const DEFAULT_RETRY = {
|
|
141
|
+
maxAttempts: 12,
|
|
142
|
+
backoff: "exponential",
|
|
143
|
+
delayMs: 15
|
|
144
|
+
};
|
|
145
|
+
var OccConflictError = class OccConflictError extends Error {
|
|
146
|
+
reason;
|
|
147
|
+
conflictDetail;
|
|
148
|
+
constructor(reason, conflictDetail) {
|
|
149
|
+
super(`OCC conflict: ${reason}`);
|
|
150
|
+
this.reason = reason;
|
|
151
|
+
this.conflictDetail = conflictDetail;
|
|
152
|
+
this.name = "OccConflictError";
|
|
153
|
+
}
|
|
154
|
+
static isOccConflictError(err) {
|
|
155
|
+
if (err instanceof OccConflictError || err && typeof err === "object" && err.name === "OccConflictError") return true;
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
var OccAbortError = class extends Error {
|
|
160
|
+
constructor(message) {
|
|
161
|
+
super(message);
|
|
162
|
+
this.name = "OccAbortError";
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
//#endregion
|
|
166
|
+
export { normalizeIdToBytes as C, bytesFromJson as S, RawRangeReadSchema as _, DEFAULT_RETRY as a, WriteEntrySchema as b, OccAbortError as c, PointReadSchema as d, PredicateSchema as f, RawPointReadSchema as g, RangeReadSchema as h, CompareOperatorSchema as i, OccConflictError as l, QueryCacheMetadataSchema as m, BigIntSchema as n, LeafPredicateSchema as o, QueryCacheEntrySchema as p, CachedPgMetadataSchema as r, NO_RETRY as s, AndPredicateSchema as t, OrPredicateSchema as u, RawReadEntrySchema as v, normalizeToBytes as w, WriteOpSchema as x, ReadEntrySchema as y };
|
|
167
|
+
|
|
168
|
+
//# sourceMappingURL=types_db-Ctf-ksoy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types_db-Ctf-ksoy.js","names":[],"sources":["../src/db/types_db.ts"],"sourcesContent":["import z from \"zod\";\nimport { utf8Encode } from \"./bytes\";\n\n/** Monotonically increasing integer from global_commit_ts sequence in Postgres */\nexport type CommitTs = bigint;\n\nexport const BigIntSchema = z.string().transform((val) => BigInt(val));\n\nexport const CompareOperatorSchema = z.enum([\n \"=\", \"!=\", \">\", \">=\", \"<\", \"<=\",\n \"like\", \"ilike\", \"contains\", \"icontains\",\n \"between\",\n \"jsonContains\", \"jsonContainedBy\", \"jsonHasKey\", \"jsonArrayContains\",\n \"isNull\", \"isNotNull\"\n]);\nexport type CompareOperator = z.infer<typeof CompareOperatorSchema>;\n\n// Define the type first so z.lazy() can reference it\nexport type Predicate =\n | LeafPredicate\n | { kind: \"and\"; children: Predicate[] }\n | { kind: \"or\"; children: Predicate[] };\nexport const PredicateSchema: z.ZodType<Predicate> = z.lazy(() =>\n z.union([\n LeafPredicateSchema,\n AndPredicateSchema,\n OrPredicateSchema,\n ])\n);\n\nexport const LeafPredicateSchema = z.object({\n \"kind\": z.literal(\"leaf\"),\n column: z.string(),\n operator: CompareOperatorSchema,\n value: z.unknown(),\n value2: z.unknown().optional(),\n // For JSON ops: `true` means `value` is already in dialect-prepared form\n // (a path expression for jsonHasKey, a JSON string for the contains family)\n // and the SqlBuilder should pass it through without further escaping.\n raw: z.boolean().optional(),\n // For jsonContains/jsonContainedBy/jsonArrayContains: optional sub-path\n // into the target JSON value to scope the check (jsonpath syntax, e.g.\n // `$.\"a\".\"b\"`). Already compiled to a single string.\n path: z.string().optional(),\n // For jsonHasKey multi-path mode: when set, `value` is `string[]` (each\n // entry a jsonpath) and the predicate checks for existence of any (`one`)\n // or all (`all`) of them.\n mode: z.enum([\"one\", \"all\"]).optional(),\n});\nexport type LeafPredicate = z.infer<typeof LeafPredicateSchema>;\n\nexport const AndPredicateSchema = z.object({\n kind: z.literal(\"and\"),\n children: z.array(PredicateSchema),\n});\nexport type AndPredicate = z.infer<typeof AndPredicateSchema>;\n\nexport const OrPredicateSchema = z.object({\n kind: z.literal(\"or\"),\n children: z.array(PredicateSchema),\n});\nexport type OrPredicate = z.infer<typeof OrPredicateSchema>;\n\n/** Query specification - what was queried (used for cache key generation) */\nexport type QuerySpec = ReadEntry;\n\nconst Uint8ArraySchema = z.any().transform((val) => {\n if (val instanceof Uint8Array) return val;\n return bytesFromJson(val);\n});\n\nexport function normalizeIdToBytes(id: string | number, fromHex = false): Uint8Array {\n const idStr = typeof id === \"number\" ? String(id) : id;\n const data = idStr.replace(/-/g, \"\");\n if (fromHex === true) {\n const len = data.length >>> 1;\n const out = new Uint8Array(len);\n for (let i = 0; i < len; i++) {\n out[i] = parseInt(data.substring(i * 2, i * 2 + 2), 16);\n }\n return out;\n }\n return utf8Encode(data);\n}\n\nexport function normalizeToBytes(value: Uint8Array | unknown): Uint8Array {\n try {\n return bytesFromJson(value);\n } catch (_) {\n return new Uint8Array(0);\n }\n}\n\nexport function bytesFromJson(value: Uint8Array | unknown): Uint8Array {\n if (value instanceof Uint8Array) {\n return value;\n }\n if (Array.isArray(value)) {\n return Uint8Array.from(value as number[]);\n }\n if (value && typeof value === \"object\" && \"type\" in value && (value as any).type === \"Buffer\" && \"data\" in value) {\n return Uint8Array.from((value as any).data);\n }\n if (typeof value === \"string\") {\n return utf8Encode(value);\n }\n if (typeof value === \"number\") {\n return utf8Encode(String(value));\n }\n\n throw new Error(\"Invalid buffer value\");\n}\n\n/* \n * Query specification for a point read (find by ID).\n */\nexport const PointReadSchema = z.object({\n kind: z.literal(\"point\"),\n table: z.string(),\n id: z.string(),\n tableId: Uint8ArraySchema,\n // commit_ts of the row at read time. `null` = row didn't exist (so a later\n // insert is a conflict). `undefined` = the read was added synthetically and\n // OCC should fall back to the commit-log scan / general validator.\n expectedCommitTs: BigIntSchema.nullable().optional(),\n});\nexport type PointRead = z.infer<typeof PointReadSchema>;\n\nexport const RawPointReadSchema = z.object({\n kind: z.literal(\"point\"),\n tableId: Uint8ArraySchema,\n id: Uint8ArraySchema,\n table: z.string(),\n expectedCommitTs: BigIntSchema.nullable().optional(),\n});\nexport type RawPointRead = z.infer<typeof RawPointReadSchema>;\n\n/**\n * Query specification for a range read (get with filters).\n * This is the query definition, not the result.\n */\nexport const RangeReadSchema = z.object({\n kind: z.literal(\"range\"),\n table: z.string(),\n tableId: Uint8ArraySchema,\n predicate: PredicateSchema,\n columns: z.array(z.string()),\n orderBy: z.string().nullable().optional(),\n limit: z.number().nullable().optional(),\n offset: z.number().nullable().optional(),\n});\nexport type RangeRead = z.infer<typeof RangeReadSchema>;\n\nexport const RawRangeReadSchema = z.object({\n kind: z.literal(\"range\"),\n table: z.string(),\n tableId: Uint8ArraySchema,\n predicate: PredicateSchema,\n columns: z.array(z.string()),\n orderBy: z.string().nullable().optional(),\n limit: z.number().nullable().optional(),\n offset: z.number().nullable().optional(),\n});\nexport type RawRangeRead = z.infer<typeof RawRangeReadSchema>;\n\nexport const ReadEntrySchema = z.union([PointReadSchema, RangeReadSchema]);\nexport type ReadEntry = z.infer<typeof ReadEntrySchema>;\n\nexport const RawReadEntrySchema = z.union([RawPointReadSchema, RawRangeReadSchema]);\nexport type RawReadEntry = z.infer<typeof RawReadEntrySchema>;\n\nexport const WriteOpSchema = z.enum([\"insert\", \"update\", \"delete\"]);\nexport type WriteOp = z.infer<typeof WriteOpSchema>;\n\nexport const WriteEntrySchema = z.object({\n table: z.string(),\n tableId: Uint8ArraySchema,\n id: z.string(),\n op: WriteOpSchema,\n data: z.record(z.string(), z.unknown()).optional(),\n // Row state at beginTs, before this write. Populated server-side by\n // attachPrevDataToWriteSet for `update`/`delete`. Lets the invalidator\n // detect rows leaving a filtered result set (e.g. status changed from\n // matching to non-matching).\n prevData: z.record(z.string(), z.unknown()).optional(),\n // commit_ts the row had right before this write. Drives the CAS guard:\n // `UPDATE ... WHERE id=? AND commit_ts=expectedCommitTs`. Populated by\n // attachPrevDataToWriteSet or carried over from a prior find() in the\n // same txn. Undefined on inserts.\n expectedCommitTs: BigIntSchema.nullable().optional(),\n});\nexport type WriteEntry = z.infer<typeof WriteEntrySchema>;\n\nexport interface CommitLogEntry {\n id: Uint8Array;\n ts: bigint;\n tableId: Uint8Array;\n data: Uint8Array;\n\n _parsedData?: Record<string, unknown> | null\n}\n\nexport interface MutationResult<T> {\n result: T;\n writeSet: WriteEntry[];\n commitTs: CommitTs;\n}\n\nexport interface LiveResult<T> {\n ts: bigint,\n data: T;\n readSet: ReadEntry[];\n}\n\nexport const QueryCacheMetadataSchema = z.object({\n lastSnapshotTs: BigIntSchema,\n readSet: z.array(ReadEntrySchema),\n});\nexport type QueryCacheMetadata = z.infer<typeof QueryCacheMetadataSchema>;\n\nexport const QueryCacheEntrySchema = z.object({\n data: z.unknown(),\n});\nexport type QueryCacheEntry = z.infer<typeof QueryCacheEntrySchema>;\n\nexport const CachedPgMetadataSchema = z.record(z.string(), z.record(z.string(), z.string()));\nexport type CachedPgMetadata = z.infer<typeof CachedPgMetadataSchema>;\n\nexport interface RetryConfig {\n maxAttempts: number;\n backoff: \"none\" | \"linear\" | \"exponential\";\n delayMs?: number;\n onConflict?: (attempt: number, error: OccConflictError) => void;\n}\n\nexport const NO_RETRY: RetryConfig = { maxAttempts: 1, backoff: \"none\" };\n\nexport const DEFAULT_RETRY: RetryConfig = {\n maxAttempts: 12,\n backoff: \"exponential\",\n delayMs: 15,\n};\n\nexport class OccConflictError extends Error {\n constructor(\n public readonly reason: string,\n public readonly conflictDetail?: unknown\n ) {\n super(`OCC conflict: ${reason}`);\n this.name = \"OccConflictError\";\n }\n\n static isOccConflictError(err: unknown): boolean {\n if (err instanceof OccConflictError ||\n (err && typeof err === \"object\" && (err as { name?: string }).name === \"OccConflictError\")) {\n return true;\n }\n return false;\n }\n}\n\nexport class OccAbortError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OccAbortError\";\n }\n}"],"mappings":"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"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { Tn as CacheLayer, er as MutationResult, tt as RegisteredProcedure, wt as SupaliveDb } from "./index-CTyXKcq_.js";
|
|
2
|
+
import z from "zod";
|
|
3
|
+
import { WebSocket } from "ws";
|
|
4
|
+
import { Level } from "pino";
|
|
5
|
+
import { Redis } from "ioredis";
|
|
6
|
+
|
|
7
|
+
//#region src/config.d.ts
|
|
8
|
+
interface UpstashConfig {
|
|
9
|
+
url: string;
|
|
10
|
+
token: string;
|
|
11
|
+
redisUrl: string;
|
|
12
|
+
}
|
|
13
|
+
/** Database configuration for PostgreSQL */
|
|
14
|
+
interface PostgresConfig {
|
|
15
|
+
type: "postgres";
|
|
16
|
+
connectionString: string;
|
|
17
|
+
/** Optional max connections for the Postgres connection pool. Defaults to 10.*/
|
|
18
|
+
maxConnections?: number;
|
|
19
|
+
/** Optional min connections for the Postgres connection pool. Defaults to 1.*/
|
|
20
|
+
minConnections?: number;
|
|
21
|
+
/** Optional idle timeout for Postgres connections in milliseconds. Defaults to 30000 (30 seconds). */
|
|
22
|
+
idleTimeoutMillis?: number;
|
|
23
|
+
/** Optional connection timeout for acquiring Postgres connections in milliseconds. Defaults to 7000 (7 seconds). */
|
|
24
|
+
connectionTimeoutMillis?: number;
|
|
25
|
+
}
|
|
26
|
+
/** Database configuration for MySQL */
|
|
27
|
+
interface MySQLConfig {
|
|
28
|
+
type: "mysql";
|
|
29
|
+
connectionString: string;
|
|
30
|
+
/** Optional max connections for the MySQL connection pool. Defaults to 20.*/
|
|
31
|
+
maxConnections?: number;
|
|
32
|
+
/** Optional min connections for the MySQL connection pool. Defaults to 1.*/
|
|
33
|
+
minConnections?: number;
|
|
34
|
+
/** Optional idle timeout for MySQL connections in milliseconds. Defaults to 30000 (30 seconds). */
|
|
35
|
+
idleTimeoutMillis?: number;
|
|
36
|
+
/** Optional connection timeout for acquiring MySQL connections in milliseconds. Defaults to 7000 (7 seconds). */
|
|
37
|
+
connectionTimeoutMillis?: number;
|
|
38
|
+
/** Optional flag to queue connection requests when pool is exhausted. Defaults to true (queue requests). */
|
|
39
|
+
queueLimit?: number;
|
|
40
|
+
}
|
|
41
|
+
type DatabaseConfig = PostgresConfig | MySQLConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Configuration for the Supalive WebSocket server.
|
|
44
|
+
*/
|
|
45
|
+
interface SupaliveServerConfig<TContext = Record<string, unknown>> {
|
|
46
|
+
/** Server port (default: 3000) */
|
|
47
|
+
port?: number;
|
|
48
|
+
/** Server host (default: "0.0.0.0") */
|
|
49
|
+
host?: string;
|
|
50
|
+
cacheLayer: CacheLayer;
|
|
51
|
+
redisSubClient: Redis;
|
|
52
|
+
/**
|
|
53
|
+
* Subscription Manager WebSocket URL for RPC communication.
|
|
54
|
+
* A single sub-manager process owns all subscription state for this
|
|
55
|
+
* deployment. Internally it spawns N logical workers (configured on the
|
|
56
|
+
* sub-manager side) and routes by hash(subId) to spread CPU across them.
|
|
57
|
+
*/
|
|
58
|
+
subManagerUrl: string;
|
|
59
|
+
/** Database instance */
|
|
60
|
+
database: SupaliveDb;
|
|
61
|
+
/**
|
|
62
|
+
* Optional authentication callback.
|
|
63
|
+
* Called when client sends auth message.
|
|
64
|
+
* Return null to reject authentication.
|
|
65
|
+
*/
|
|
66
|
+
verifyAuth?: (data: Record<string, unknown>, sessionId: string) => Promise<TContext | null>;
|
|
67
|
+
/**
|
|
68
|
+
* Server context name for procedure routing.
|
|
69
|
+
* Must match the router's contextName.
|
|
70
|
+
*/
|
|
71
|
+
contextName?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Session TTL in seconds (default: 3600 = 1 hour).
|
|
74
|
+
* Sessions are kept alive while connected and expire after disconnect.
|
|
75
|
+
*/
|
|
76
|
+
sessionTtlSeconds?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Enable detailed logging.
|
|
79
|
+
*/
|
|
80
|
+
logLevel?: Level;
|
|
81
|
+
/**
|
|
82
|
+
* Extract user ID from context for cache key generation.
|
|
83
|
+
* If not provided, caching is disabled (each sub recomputes independently).
|
|
84
|
+
*/
|
|
85
|
+
getUserId?: (ctx: TContext) => string;
|
|
86
|
+
/**
|
|
87
|
+
* Cache TTL in seconds (default: 3600).
|
|
88
|
+
* How long query results are cached in Redis.
|
|
89
|
+
*/
|
|
90
|
+
cacheTtlSeconds?: number;
|
|
91
|
+
}
|
|
92
|
+
interface SubscriptionManagerConfig {
|
|
93
|
+
port: number;
|
|
94
|
+
upstash: {
|
|
95
|
+
url: string;
|
|
96
|
+
token: string;
|
|
97
|
+
redisUrl: string;
|
|
98
|
+
};
|
|
99
|
+
database: DatabaseConfig;
|
|
100
|
+
cacheTTLSeconds: number;
|
|
101
|
+
/**
|
|
102
|
+
* Number of logical workers inside the sub-manager process.
|
|
103
|
+
*
|
|
104
|
+
* Subscriptions are routed by FNV-1a(subId) % workers so that all operations
|
|
105
|
+
* for a given subId always land on the same worker (preserving the existing
|
|
106
|
+
* `instances: Set<string>` dedup). Each worker owns an independent
|
|
107
|
+
* subscriptions Map; on invalidate, all workers scan their own slice in
|
|
108
|
+
* parallel (logically — JS still runs one at a time inside one event loop,
|
|
109
|
+
* but per-worker scans are smaller so total work is split N ways).
|
|
110
|
+
*
|
|
111
|
+
* Defaults to `SUPALIVE_SUB_MANAGER_WORKERS` env var if set, else 1.
|
|
112
|
+
*/
|
|
113
|
+
workers?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Connection pool size *per worker*. If omitted, falls back to
|
|
116
|
+
* `floor(database.maxConnections / workers)` (min 1) so the total pool
|
|
117
|
+
* size stays close to the legacy single-worker configuration.
|
|
118
|
+
*/
|
|
119
|
+
maxConnectionsPerWorker?: number;
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/server/types_server.d.ts
|
|
123
|
+
type InstanceId = string;
|
|
124
|
+
type SubId = string;
|
|
125
|
+
/** Local tracking of an active subscription (per-session) */
|
|
126
|
+
interface SubscriptionEntry {
|
|
127
|
+
subId: SubId;
|
|
128
|
+
cacheKey: string;
|
|
129
|
+
subscribedTimes: number;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* A mutation that has been validated and parked on the per-session FIFO
|
|
133
|
+
* queue, waiting for the in-flight mutation on this socket to finish. Each
|
|
134
|
+
* `handleCall` for a mutation owns one of these and awaits its own
|
|
135
|
+
* resolve/reject so it can send the response.
|
|
136
|
+
*/
|
|
137
|
+
interface PendingMutation<TContext = Record<string, unknown>> {
|
|
138
|
+
procedure: RegisteredProcedure<TContext>;
|
|
139
|
+
validatedInput: unknown;
|
|
140
|
+
resolve: (result: MutationResult<unknown>) => void;
|
|
141
|
+
reject: (err: unknown) => void;
|
|
142
|
+
}
|
|
143
|
+
/** WebSocket session (runtime, with WebSocket) */
|
|
144
|
+
interface Session<TContext = Record<string, unknown>> {
|
|
145
|
+
id: string;
|
|
146
|
+
ws: WebSocket;
|
|
147
|
+
/** Auth context from verifyAuth callback */
|
|
148
|
+
serverCtx: TContext;
|
|
149
|
+
subIds: Set<string>;
|
|
150
|
+
/**
|
|
151
|
+
* Per-socket FIFO mutation queue. at most one mutation
|
|
152
|
+
* drains at a time so a single client cannot saturate the OCC retry
|
|
153
|
+
* loop or fan out concurrent commits that race the same rows.
|
|
154
|
+
*/
|
|
155
|
+
mutationQueue: PendingMutation<TContext>[];
|
|
156
|
+
mutationInFlight: boolean;
|
|
157
|
+
/** Per-socket count of currently executing actions. */
|
|
158
|
+
actionInFlight: number;
|
|
159
|
+
/**
|
|
160
|
+
* Wall-clock of the last inbound frame (text message, ws-ping, or ws-pong).
|
|
161
|
+
* Used by the per-session heartbeat to terminate sockets that have gone
|
|
162
|
+
* silent past `CLIENT_TIMEOUT_MS`.
|
|
163
|
+
*/
|
|
164
|
+
lastReceivedAt: number;
|
|
165
|
+
/**
|
|
166
|
+
* Wall-clock of the last outbound frame. Gates the idle-only app-level
|
|
167
|
+
* ping so a busy session (frequent sub:updates etc.) doesn't emit a
|
|
168
|
+
* redundant `{type:"ping"}` on every heartbeat tick.
|
|
169
|
+
*/
|
|
170
|
+
lastSentAt: number;
|
|
171
|
+
/**
|
|
172
|
+
* Per-session combined heartbeat. Single `setInterval` that handles
|
|
173
|
+
* both dead-TCP detection (ws-ping or terminate) and client-watchdog
|
|
174
|
+
* refresh (idle-only app-level ping) on each tick.
|
|
175
|
+
*/
|
|
176
|
+
heartbeatTimer: ReturnType<typeof setInterval> | null;
|
|
177
|
+
}
|
|
178
|
+
declare const RemoteSubscriptionUpdateSchema: z.ZodObject<{
|
|
179
|
+
type: z.ZodLiteral<"update">;
|
|
180
|
+
subId: z.ZodString;
|
|
181
|
+
data: z.ZodUnknown;
|
|
182
|
+
dataHash: z.ZodString;
|
|
183
|
+
originInstance: z.ZodString;
|
|
184
|
+
}, z.core.$strip>;
|
|
185
|
+
type RemoteSubscriptionUpdate = z.infer<typeof RemoteSubscriptionUpdateSchema>;
|
|
186
|
+
declare const RemoteRecomputeRaceSchema: z.ZodObject<{
|
|
187
|
+
type: z.ZodLiteral<"recompute-race">;
|
|
188
|
+
subId: z.ZodString;
|
|
189
|
+
cacheKey: z.ZodString;
|
|
190
|
+
queryName: z.ZodString;
|
|
191
|
+
args: z.ZodUnknown;
|
|
192
|
+
notifyInstances: z.ZodArray<z.ZodString>;
|
|
193
|
+
commitTs: z.ZodString;
|
|
194
|
+
originInstance: z.ZodString;
|
|
195
|
+
}, z.core.$strip>;
|
|
196
|
+
type RemoteRecomputeRace = z.infer<typeof RemoteRecomputeRaceSchema>;
|
|
197
|
+
declare const RemoteSubscriptionMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
198
|
+
type: z.ZodLiteral<"update">;
|
|
199
|
+
subId: z.ZodString;
|
|
200
|
+
data: z.ZodUnknown;
|
|
201
|
+
dataHash: z.ZodString;
|
|
202
|
+
originInstance: z.ZodString;
|
|
203
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
204
|
+
type: z.ZodLiteral<"recompute-race">;
|
|
205
|
+
subId: z.ZodString;
|
|
206
|
+
cacheKey: z.ZodString;
|
|
207
|
+
queryName: z.ZodString;
|
|
208
|
+
args: z.ZodUnknown;
|
|
209
|
+
notifyInstances: z.ZodArray<z.ZodString>;
|
|
210
|
+
commitTs: z.ZodString;
|
|
211
|
+
originInstance: z.ZodString;
|
|
212
|
+
}, z.core.$strip>], "type">;
|
|
213
|
+
type RemoteSubscriptionMessage = z.infer<typeof RemoteSubscriptionMessageSchema>;
|
|
214
|
+
//#endregion
|
|
215
|
+
export { UpstashConfig as _, RemoteSubscriptionMessage as a, RemoteSubscriptionUpdateSchema as c, SubscriptionEntry as d, DatabaseConfig as f, SupaliveServerConfig as g, SubscriptionManagerConfig as h, RemoteRecomputeRaceSchema as i, Session as l, PostgresConfig as m, PendingMutation as n, RemoteSubscriptionMessageSchema as o, MySQLConfig as p, RemoteRecomputeRace as r, RemoteSubscriptionUpdate as s, InstanceId as t, SubId as u };
|
|
216
|
+
//# sourceMappingURL=types_server-Ch56y8L3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types_server-Ch56y8L3.d.ts","names":[],"sources":["../src/config.ts","../src/server/types_server.ts"],"mappings":";;;;;;;UAKiB,aAAA;EACb,GAAA;EACA,KAAA;EACA,QAAA;AAAA;;UAIa,cAAA;EACb,IAAA;EACA,gBAAA;EANA;EAQA,cAAA;EARQ;EAWR,cAAA;EAP2B;EAU3B,iBAAA;EAV2B;EAa3B,uBAAA;AAAA;;UAIa,WAAA;EACb,IAAA;EACA,gBAAA;EANuB;EAQvB,cAAA;EAJa;EAOb,cAAA;;EAGA,iBAAA;EATA;EAYA,uBAAA;EATA;EAYA,UAAA;AAAA;AAAA,KAGQ,cAAA,GAAiB,cAAA,GAAiB,WAAW;;;AAH3C;UAQG,oBAAA,YAAgC,MAAA;EALvB;EAOtB,IAAA;EAPyB;EAUzB,IAAA;EAKA,UAAA,EAAY,UAAA;EAIZ,cAAA,EAAgB,KAAA;EAdiB;;;;;;EAsBjC,aAAA;EAaK;EAVL,QAAA,EAAU,UAAA;EAiCQ;;;;;EA1BlB,UAAA,IACI,IAAA,EAAM,MAAA,mBACN,SAAA,aACC,OAAA,CAAQ,QAAA;EA9Bb;;;;EAoCA,WAAA;EAnBA;;;;EAyBA,iBAAA;EAdI;;;EAmBJ,QAAA,GAAW,KAAA;EAXX;;;;EAiBA,SAAA,IAAa,GAAA,EAAK,QAAA;EAAA;;;;EAMlB,eAAA;AAAA;AAAA,UAGa,yBAAA;EACb,IAAA;EACA,OAAA;IAAW,GAAA;IAAa,KAAA;IAAe,QAAA;EAAA;EACvC,QAAA,EAAU,cAAc;EACxB,eAAA;EADU;;;;;AAoBa;;;;ACxI3B;;;EDkII,OAAA;EClIkB;AAEtB;;;;EDsII,uBAAA;AAAA;;;KCxIQ,UAAA;AAAA,KAEA,KAAA;;UAGK,iBAAA;EACf,KAAA,EAAO,KAAK;EACZ,QAAA;EACA,eAAA;AAAA;;;;ADPU;AAIZ;;UCYiB,eAAA,YAA2B,MAAA;EAC1C,SAAA,EAAW,mBAAA,CAAoB,QAAA;EAC/B,cAAA;EACA,OAAA,GAAU,MAAA,EAAQ,cAAA;EAClB,MAAA,GAAS,GAAA;AAAA;;UAIM,OAAA,YAAmB,MAAA;EAClC,EAAA;EACA,EAAA,EAAI,SAAA;EDLW;ECOf,SAAA,EAAW,QAAA;EACX,MAAA,EAAQ,GAAA;EDRkB;;;;;ECc1B,aAAA,EAAe,eAAA,CAAgB,QAAA;EAC/B,gBAAA;EDCE;ECCF,cAAA;EDDY;AAGd;;;;ECIE,cAAA;EDCe;;;;;ECKf,UAAA;EDoBY;;;;;ECdZ,cAAA,EAAgB,UAAA,QAAkB,WAAA;AAAA;AAAA,cAgBvB,8BAAA,EAA8B,CAAA,CAAA,SAAA;;;;;;;KAO/B,wBAAA,GAA2B,CAAA,CAAE,KAAK,QAAQ,8BAAA;AAAA,cAEzC,yBAAA,EAAyB,CAAA,CAAA,SAAA;;;;;;;;;;KAU1B,mBAAA,GAAsB,CAAA,CAAE,KAAK,QAAQ,yBAAA;AAAA,cAEpC,+BAAA,EAA+B,CAAA,CAAA,qBAAA,EAAA,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;KAIhC,yBAAA,GAA4B,CAAA,CAAE,KAAK,QAAQ,+BAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
//#region src/server/types_server.ts
|
|
3
|
+
const RemoteSubscriptionUpdateSchema = z.object({
|
|
4
|
+
type: z.literal("update"),
|
|
5
|
+
subId: z.string(),
|
|
6
|
+
data: z.unknown(),
|
|
7
|
+
dataHash: z.string(),
|
|
8
|
+
originInstance: z.string()
|
|
9
|
+
});
|
|
10
|
+
const RemoteRecomputeRaceSchema = z.object({
|
|
11
|
+
type: z.literal("recompute-race"),
|
|
12
|
+
subId: z.string(),
|
|
13
|
+
cacheKey: z.string(),
|
|
14
|
+
queryName: z.string(),
|
|
15
|
+
args: z.unknown(),
|
|
16
|
+
notifyInstances: z.array(z.string()),
|
|
17
|
+
commitTs: z.string(),
|
|
18
|
+
originInstance: z.string()
|
|
19
|
+
});
|
|
20
|
+
const RemoteSubscriptionMessageSchema = z.discriminatedUnion("type", [RemoteSubscriptionUpdateSchema, RemoteRecomputeRaceSchema]);
|
|
21
|
+
//#endregion
|
|
22
|
+
export { RemoteSubscriptionMessageSchema as n, RemoteSubscriptionUpdateSchema as r, RemoteRecomputeRaceSchema as t };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=types_server-Dk6o_B7N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types_server-Dk6o_B7N.js","names":[],"sources":["../src/server/types_server.ts"],"sourcesContent":["import type { WebSocket } from \"ws\";\nimport type { ReadEntry, MutationResult } from \"../db/types_db\";\nimport type { RegisteredProcedure } from \"../router/router\";\nimport z from \"zod\";\n\n// ─── Core Types ───────────────────────────────────────────────────────────────\n\nexport type InstanceId = string;\n\nexport type SubId = string;\n\n/** Local tracking of an active subscription (per-session) */\nexport interface SubscriptionEntry {\n subId: SubId;\n cacheKey: string;\n subscribedTimes: number;\n}\n\n/**\n * A mutation that has been validated and parked on the per-session FIFO\n * queue, waiting for the in-flight mutation on this socket to finish. Each\n * `handleCall` for a mutation owns one of these and awaits its own\n * resolve/reject so it can send the response.\n */\nexport interface PendingMutation<TContext = Record<string, unknown>> {\n procedure: RegisteredProcedure<TContext>;\n validatedInput: unknown;\n resolve: (result: MutationResult<unknown>) => void;\n reject: (err: unknown) => void;\n}\n\n/** WebSocket session (runtime, with WebSocket) */\nexport interface Session<TContext = Record<string, unknown>> {\n id: string;\n ws: WebSocket;\n /** Auth context from verifyAuth callback */\n serverCtx: TContext;\n subIds: Set<string>;\n /**\n * Per-socket FIFO mutation queue. at most one mutation\n * drains at a time so a single client cannot saturate the OCC retry\n * loop or fan out concurrent commits that race the same rows.\n */\n mutationQueue: PendingMutation<TContext>[];\n mutationInFlight: boolean;\n /** Per-socket count of currently executing actions. */\n actionInFlight: number;\n /**\n * Wall-clock of the last inbound frame (text message, ws-ping, or ws-pong).\n * Used by the per-session heartbeat to terminate sockets that have gone\n * silent past `CLIENT_TIMEOUT_MS`.\n */\n lastReceivedAt: number;\n /**\n * Wall-clock of the last outbound frame. Gates the idle-only app-level\n * ping so a busy session (frequent sub:updates etc.) doesn't emit a\n * redundant `{type:\"ping\"}` on every heartbeat tick.\n */\n lastSentAt: number;\n /**\n * Per-session combined heartbeat. Single `setInterval` that handles\n * both dead-TCP detection (ws-ping or terminate) and client-watchdog\n * refresh (idle-only app-level ping) on each tick.\n */\n heartbeatTimer: ReturnType<typeof setInterval> | null;\n}\n\n// Messages published on `sub:instance:<instanceId>` for cross-instance fan-out.\n//\n// Two variants:\n// • update — the writer (or race winner) recomputed and is pushing\n// the result; receivers forward `data` to their local\n// sessions.\n// • recompute-race — the writer does not hold the affected sub locally, so\n// it broadcasts a race hint to every instance that does\n// (`notifyInstances`). Receivers try to acquire a Redis\n// lock keyed by (subId, commitTs); the winner runs the\n// query against one of its own sessions' serverCtx and\n// publishes the resulting `update` back out. Losers\n// no-op and pick up the winner's `update` over Redis.\nexport const RemoteSubscriptionUpdateSchema = z.object({\n type: z.literal(\"update\"),\n subId: z.string(),\n data: z.unknown(),\n dataHash: z.string(),\n originInstance: z.string(),\n});\nexport type RemoteSubscriptionUpdate = z.infer<typeof RemoteSubscriptionUpdateSchema>;\n\nexport const RemoteRecomputeRaceSchema = z.object({\n type: z.literal(\"recompute-race\"),\n subId: z.string(),\n cacheKey: z.string(),\n queryName: z.string(),\n args: z.unknown(),\n notifyInstances: z.array(z.string()),\n commitTs: z.string(),\n originInstance: z.string(),\n});\nexport type RemoteRecomputeRace = z.infer<typeof RemoteRecomputeRaceSchema>;\n\nexport const RemoteSubscriptionMessageSchema = z.discriminatedUnion(\"type\", [\n RemoteSubscriptionUpdateSchema,\n RemoteRecomputeRaceSchema,\n]);\nexport type RemoteSubscriptionMessage = z.infer<typeof RemoteSubscriptionMessageSchema>;\n"],"mappings":";;AAgFA,MAAa,iCAAiC,EAAE,OAAO;CACrD,MAAM,EAAE,QAAQ,QAAQ;CACxB,OAAO,EAAE,OAAO;CAChB,MAAM,EAAE,QAAQ;CAChB,UAAU,EAAE,OAAO;CACnB,gBAAgB,EAAE,OAAO;AAC3B,CAAC;AAGD,MAAa,4BAA4B,EAAE,OAAO;CAChD,MAAM,EAAE,QAAQ,gBAAgB;CAChC,OAAO,EAAE,OAAO;CAChB,UAAU,EAAE,OAAO;CACnB,WAAW,EAAE,OAAO;CACpB,MAAM,EAAE,QAAQ;CAChB,iBAAiB,EAAE,MAAM,EAAE,OAAO,CAAC;CACnC,UAAU,EAAE,OAAO;CACnB,gBAAgB,EAAE,OAAO;AAC3B,CAAC;AAGD,MAAa,kCAAkC,EAAE,mBAAmB,QAAQ,CAC1E,gCACA,yBACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supalive/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core for supalive — reactive database framework",
|
|
6
6
|
"license": "MIT",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"access": "public"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
|
-
"build": "
|
|
58
|
+
"build": "tsdown",
|
|
59
59
|
"test": "vitest --run"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
@@ -92,4 +92,4 @@
|
|
|
92
92
|
"optional": true
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
}
|
|
95
|
+
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { AnyProcedure, InputOf, OutputOf } from "../router/procedure";
|
|
2
|
-
import { type Router } from "../router/router";
|
|
3
|
-
import type { SupaliveDb } from "../db/realtime_db";
|
|
4
|
-
import { LiveResult } from "../db/types_db";
|
|
5
|
-
export interface CallerOptions<TContext = unknown> {
|
|
6
|
-
db: SupaliveDb;
|
|
7
|
-
context?: TContext;
|
|
8
|
-
isInternal?: boolean;
|
|
9
|
-
inContext: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Create a server-side caller that bypasses HTTP/WebSocket.
|
|
13
|
-
*
|
|
14
|
-
* For in-memory calls, input validation is skipped (data is already a JS object).
|
|
15
|
-
* Query procedures also get a liveQuery() method for server-side use.
|
|
16
|
-
*/
|
|
17
|
-
export declare function createCaller<AppRouter extends Router<Record<string, AnyProcedure<TContext>>, TContext>, TContext = unknown, TProcedures extends Record<string, AnyProcedure<TContext>> = AppRouter["procedures"]>(options: CallerOptions<any>): CallerFromProcedures<TProcedures, TContext>;
|
|
18
|
-
/**
|
|
19
|
-
* Caller type from procedures (includes internal procedures).
|
|
20
|
-
* Query procedures also have liveQuery() for server-side use.
|
|
21
|
-
*/
|
|
22
|
-
export type CallerFromProcedures<TProcedures extends Record<string, AnyProcedure<TContext>>, TContext = unknown> = {
|
|
23
|
-
[K in keyof TProcedures]: TProcedures[K] extends {
|
|
24
|
-
procedureType: "query";
|
|
25
|
-
} ? {
|
|
26
|
-
query: (input: InputOf<TProcedures[K]>) => Promise<OutputOf<TProcedures[K]>>;
|
|
27
|
-
liveQuery: (input: InputOf<TProcedures[K]>) => Promise<LiveResult<OutputOf<TProcedures[K]>>>;
|
|
28
|
-
} : TProcedures[K] extends {
|
|
29
|
-
procedureType: "mutation";
|
|
30
|
-
} ? {
|
|
31
|
-
mutate: (input: InputOf<TProcedures[K]>) => Promise<OutputOf<TProcedures[K]>>;
|
|
32
|
-
} : TProcedures[K] extends {
|
|
33
|
-
procedureType: "action";
|
|
34
|
-
} ? {
|
|
35
|
-
action: (input: InputOf<TProcedures[K]>) => Promise<OutputOf<TProcedures[K]>>;
|
|
36
|
-
} : never;
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* Caller type from router.
|
|
40
|
-
*/
|
|
41
|
-
export type CallerFromRouter<TRouter extends Router<any, any>> = CallerFromProcedures<TRouter["procedures"]>;
|
|
42
|
-
//# sourceMappingURL=caller_client.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"caller_client.d.ts","sourceRoot":"","sources":["../../../src/client/caller_client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,YAAY,EAAE,OAAO,EAAe,QAAQ,EAAY,MAAM,qBAAqB,CAAC;AAC7G,OAAO,EAAsB,KAAK,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,WAAW,aAAa,CAAC,QAAQ,GAAG,OAAO;IAC7C,EAAE,EAAE,UAAU,CAAC;IACf,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CACxB,SAAS,SAAS,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,EAC1E,QAAQ,GAAG,OAAO,EAClB,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,EACtF,OAAO,EAAE,aAAa,CAAC,GAAG,CAAC,GAAG,oBAAoB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAyE1E;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,CAAC,WAAW,SAAS,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,OAAO,IAAI;KAC9G,CAAC,IAAI,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,SAAS;QAAE,aAAa,EAAE,OAAO,CAAA;KAAE,GACzE;QACE,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAChG,GACC,WAAW,CAAC,CAAC,CAAC,SAAS;QAAE,aAAa,EAAE,UAAU,CAAA;KAAE,GACpD;QAAE,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,GACjF,WAAW,CAAC,CAAC,CAAC,SAAS;QAAE,aAAa,EAAE,QAAQ,CAAA;KAAE,GAClD;QAAE,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;KAAE,GACjF,KAAK;CACV,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,oBAAoB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC"}
|