@livestore/sync-cf 0.4.0-dev.3 → 0.4.0-dev.6

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.
Files changed (113) hide show
  1. package/README.md +60 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/cf-worker/do/durable-object.d.ts +45 -0
  4. package/dist/cf-worker/do/durable-object.d.ts.map +1 -0
  5. package/dist/cf-worker/do/durable-object.js +154 -0
  6. package/dist/cf-worker/do/durable-object.js.map +1 -0
  7. package/dist/cf-worker/do/layer.d.ts +34 -0
  8. package/dist/cf-worker/do/layer.d.ts.map +1 -0
  9. package/dist/cf-worker/do/layer.js +68 -0
  10. package/dist/cf-worker/do/layer.js.map +1 -0
  11. package/dist/cf-worker/do/pull.d.ts +6 -0
  12. package/dist/cf-worker/do/pull.d.ts.map +1 -0
  13. package/dist/cf-worker/do/pull.js +39 -0
  14. package/dist/cf-worker/do/pull.js.map +1 -0
  15. package/dist/cf-worker/do/push.d.ts +14 -0
  16. package/dist/cf-worker/do/push.d.ts.map +1 -0
  17. package/dist/cf-worker/do/push.js +99 -0
  18. package/dist/cf-worker/do/push.js.map +1 -0
  19. package/dist/cf-worker/do/sqlite.d.ts +196 -0
  20. package/dist/cf-worker/do/sqlite.d.ts.map +1 -0
  21. package/dist/cf-worker/do/sqlite.js +27 -0
  22. package/dist/cf-worker/do/sqlite.js.map +1 -0
  23. package/dist/cf-worker/do/sync-storage.d.ts +17 -0
  24. package/dist/cf-worker/do/sync-storage.d.ts.map +1 -0
  25. package/dist/cf-worker/do/sync-storage.js +73 -0
  26. package/dist/cf-worker/do/sync-storage.js.map +1 -0
  27. package/dist/cf-worker/do/transport/do-rpc-server.d.ts +8 -0
  28. package/dist/cf-worker/do/transport/do-rpc-server.d.ts.map +1 -0
  29. package/dist/cf-worker/do/transport/do-rpc-server.js +45 -0
  30. package/dist/cf-worker/do/transport/do-rpc-server.js.map +1 -0
  31. package/dist/cf-worker/do/transport/http-rpc-server.d.ts +7 -0
  32. package/dist/cf-worker/do/transport/http-rpc-server.d.ts.map +1 -0
  33. package/dist/cf-worker/do/transport/http-rpc-server.js +24 -0
  34. package/dist/cf-worker/do/transport/http-rpc-server.js.map +1 -0
  35. package/dist/cf-worker/do/transport/ws-rpc-server.d.ts +4 -0
  36. package/dist/cf-worker/do/transport/ws-rpc-server.d.ts.map +1 -0
  37. package/dist/cf-worker/do/transport/ws-rpc-server.js +21 -0
  38. package/dist/cf-worker/do/transport/ws-rpc-server.js.map +1 -0
  39. package/dist/cf-worker/mod.d.ts +4 -2
  40. package/dist/cf-worker/mod.d.ts.map +1 -1
  41. package/dist/cf-worker/mod.js +3 -2
  42. package/dist/cf-worker/mod.js.map +1 -1
  43. package/dist/cf-worker/shared.d.ts +127 -0
  44. package/dist/cf-worker/shared.d.ts.map +1 -0
  45. package/dist/cf-worker/shared.js +26 -0
  46. package/dist/cf-worker/shared.js.map +1 -0
  47. package/dist/cf-worker/worker.d.ts +36 -21
  48. package/dist/cf-worker/worker.d.ts.map +1 -1
  49. package/dist/cf-worker/worker.js +39 -32
  50. package/dist/cf-worker/worker.js.map +1 -1
  51. package/dist/client/mod.d.ts +4 -0
  52. package/dist/client/mod.d.ts.map +1 -0
  53. package/dist/client/mod.js +4 -0
  54. package/dist/client/mod.js.map +1 -0
  55. package/dist/client/transport/do-rpc-client.d.ts +40 -0
  56. package/dist/client/transport/do-rpc-client.d.ts.map +1 -0
  57. package/dist/client/transport/do-rpc-client.js +102 -0
  58. package/dist/client/transport/do-rpc-client.js.map +1 -0
  59. package/dist/client/transport/http-rpc-client.d.ts +43 -0
  60. package/dist/client/transport/http-rpc-client.d.ts.map +1 -0
  61. package/dist/client/transport/http-rpc-client.js +87 -0
  62. package/dist/client/transport/http-rpc-client.js.map +1 -0
  63. package/dist/client/transport/ws-rpc-client.d.ts +45 -0
  64. package/dist/client/transport/ws-rpc-client.d.ts.map +1 -0
  65. package/dist/client/transport/ws-rpc-client.js +94 -0
  66. package/dist/client/transport/ws-rpc-client.js.map +1 -0
  67. package/dist/common/do-rpc-schema.d.ts +76 -0
  68. package/dist/common/do-rpc-schema.d.ts.map +1 -0
  69. package/dist/common/do-rpc-schema.js +48 -0
  70. package/dist/common/do-rpc-schema.js.map +1 -0
  71. package/dist/common/http-rpc-schema.d.ts +58 -0
  72. package/dist/common/http-rpc-schema.d.ts.map +1 -0
  73. package/dist/common/http-rpc-schema.js +37 -0
  74. package/dist/common/http-rpc-schema.js.map +1 -0
  75. package/dist/common/mod.d.ts +5 -1
  76. package/dist/common/mod.d.ts.map +1 -1
  77. package/dist/common/mod.js +4 -1
  78. package/dist/common/mod.js.map +1 -1
  79. package/dist/common/sync-message-types.d.ts +236 -0
  80. package/dist/common/sync-message-types.d.ts.map +1 -0
  81. package/dist/common/sync-message-types.js +60 -0
  82. package/dist/common/sync-message-types.js.map +1 -0
  83. package/dist/common/ws-rpc-schema.d.ts +55 -0
  84. package/dist/common/ws-rpc-schema.d.ts.map +1 -0
  85. package/dist/common/ws-rpc-schema.js +32 -0
  86. package/dist/common/ws-rpc-schema.js.map +1 -0
  87. package/package.json +7 -8
  88. package/src/cf-worker/do/durable-object.ts +241 -0
  89. package/src/cf-worker/do/layer.ts +107 -0
  90. package/src/cf-worker/do/pull.ts +64 -0
  91. package/src/cf-worker/do/push.ts +162 -0
  92. package/src/cf-worker/do/sqlite.ts +28 -0
  93. package/src/cf-worker/do/sync-storage.ts +126 -0
  94. package/src/cf-worker/do/transport/do-rpc-server.ts +82 -0
  95. package/src/cf-worker/do/transport/http-rpc-server.ts +37 -0
  96. package/src/cf-worker/do/transport/ws-rpc-server.ts +34 -0
  97. package/src/cf-worker/mod.ts +4 -2
  98. package/src/cf-worker/shared.ts +95 -0
  99. package/src/cf-worker/worker.ts +72 -63
  100. package/src/client/mod.ts +3 -0
  101. package/src/client/transport/do-rpc-client.ts +171 -0
  102. package/src/client/transport/http-rpc-client.ts +205 -0
  103. package/src/client/transport/ws-rpc-client.ts +182 -0
  104. package/src/common/do-rpc-schema.ts +54 -0
  105. package/src/common/http-rpc-schema.ts +40 -0
  106. package/src/common/mod.ts +8 -1
  107. package/src/common/sync-message-types.ts +117 -0
  108. package/src/common/ws-rpc-schema.ts +36 -0
  109. package/src/cf-worker/cf-types.ts +0 -12
  110. package/src/cf-worker/durable-object.ts +0 -478
  111. package/src/common/ws-message-types.ts +0 -114
  112. package/src/sync-impl/mod.ts +0 -1
  113. package/src/sync-impl/ws-impl.ts +0 -274
@@ -0,0 +1,127 @@
1
+ import type { InvalidPullError, InvalidPushError } from '@livestore/common';
2
+ import type { CfTypes } from '@livestore/common-cf';
3
+ import { Effect, type Option, Schema } from '@livestore/utils/effect';
4
+ import { SearchParamsSchema, SyncMessage } from '../common/mod.ts';
5
+ export interface Env {
6
+ /** Eventlog database */
7
+ DB: CfTypes.D1Database;
8
+ ADMIN_SECRET: string;
9
+ }
10
+ export type MakeDurableObjectClassOptions = {
11
+ onPush?: (message: SyncMessage.PushRequest, context: {
12
+ storeId: StoreId;
13
+ payload?: Schema.JsonValue;
14
+ }) => Effect.SyncOrPromiseOrEffect<void>;
15
+ onPushRes?: (message: SyncMessage.PushAck | InvalidPushError) => Effect.SyncOrPromiseOrEffect<void>;
16
+ onPull?: (message: SyncMessage.PullRequest, context: {
17
+ storeId: StoreId;
18
+ payload?: Schema.JsonValue;
19
+ }) => Effect.SyncOrPromiseOrEffect<void>;
20
+ onPullRes?: (message: SyncMessage.PullResponse | InvalidPullError) => Effect.SyncOrPromiseOrEffect<void>;
21
+ /**
22
+ * Enabled transports for sync backend
23
+ * - `http`: HTTP JSON-RPC
24
+ * - `ws`: WebSocket
25
+ * - `do-rpc`: Durable Object RPC calls (only works in combination with `@livestore/adapter-cf`)
26
+ *
27
+ * @default Set(['http', 'ws', 'do-rpc'])
28
+ */
29
+ enabledTransports?: Set<'http' | 'ws' | 'do-rpc'>;
30
+ otel?: {
31
+ baseUrl?: string;
32
+ serviceName?: string;
33
+ };
34
+ };
35
+ export type StoreId = string;
36
+ export type DurableObjectId = string;
37
+ /**
38
+ * Needs to be bumped when the storage format changes (e.g. eventlogTable schema changes)
39
+ *
40
+ * Changing this version number will lead to a "soft reset".
41
+ */
42
+ export declare const PERSISTENCE_FORMAT_VERSION = 7;
43
+ export declare const DEFAULT_SYNC_DURABLE_OBJECT_NAME = "SYNC_BACKEND_DO";
44
+ export declare const encodeOutgoingMessage: (a: {
45
+ readonly backendId: string;
46
+ readonly batch: readonly {
47
+ readonly metadata: Option.Option<{
48
+ readonly createdAt: string;
49
+ readonly _tag: "SyncMessage.SyncMetadata";
50
+ }>;
51
+ readonly eventEncoded: {
52
+ readonly name: string;
53
+ readonly args: any;
54
+ readonly seqNum: any;
55
+ readonly parentSeqNum: any;
56
+ readonly clientId: string;
57
+ readonly sessionId: string;
58
+ };
59
+ }[];
60
+ readonly pageInfo: {
61
+ readonly _tag: "MoreUnknown";
62
+ } | {
63
+ readonly _tag: "MoreKnown";
64
+ readonly remaining: number;
65
+ } | {
66
+ readonly _tag: "NoMore";
67
+ };
68
+ } | {} | {
69
+ readonly _tag: "SyncMessage.Pong";
70
+ } | {
71
+ readonly _tag: "SyncMessage.AdminResetRoomResponse";
72
+ } | {
73
+ readonly info: {
74
+ readonly durableObjectId: string;
75
+ };
76
+ readonly _tag: "SyncMessage.AdminInfoResponse";
77
+ }, overrideOptions?: import("effect/SchemaAST").ParseOptions) => string;
78
+ export declare const encodeIncomingMessage: (a: {
79
+ readonly cursor: Option.Option<{
80
+ readonly backendId: string;
81
+ readonly eventSequenceNumber: number & import("effect/Brand").Brand<"GlobalEventSequenceNumber">;
82
+ }>;
83
+ } | {
84
+ readonly backendId: Option.Option<string>;
85
+ readonly batch: readonly {
86
+ readonly name: string;
87
+ readonly args: any;
88
+ readonly seqNum: any;
89
+ readonly parentSeqNum: any;
90
+ readonly clientId: string;
91
+ readonly sessionId: string;
92
+ }[];
93
+ } | {
94
+ readonly _tag: "SyncMessage.Ping";
95
+ } | {
96
+ readonly _tag: "SyncMessage.AdminResetRoomRequest";
97
+ readonly adminSecret: string;
98
+ } | {
99
+ readonly _tag: "SyncMessage.AdminInfoRequest";
100
+ readonly adminSecret: string;
101
+ }, overrideOptions?: import("effect/SchemaAST").ParseOptions) => string;
102
+ export declare const getSyncRequestSearchParams: (request: CfTypes.Request) => Option.Option<typeof SearchParamsSchema.Type>;
103
+ export declare const PULL_CHUNK_SIZE = 100;
104
+ export type RpcSubscription = {
105
+ storeId: StoreId;
106
+ payload?: Schema.JsonValue;
107
+ subscribedAt: number;
108
+ /** Effect RPC request ID */
109
+ requestId: string;
110
+ callerContext: {
111
+ bindingName: string;
112
+ durableObjectId: string;
113
+ };
114
+ };
115
+ /**
116
+ * Durable Object interface supporting the DO RPC protocol for DO <> DO syncing.
117
+ */
118
+ export interface SyncBackendRpcInterface {
119
+ __DURABLE_OBJECT_BRAND: never;
120
+ rpc(payload: Uint8Array): Promise<Uint8Array | CfTypes.ReadableStream>;
121
+ }
122
+ export declare const WebSocketAttachmentSchema: Schema.transform<Schema.SchemaClass<unknown, string, never>, Schema.Struct<{
123
+ storeId: typeof Schema.String;
124
+ payload: Schema.optional<Schema.Schema<Schema.JsonValue, Schema.JsonValue, never>>;
125
+ pullRequestIds: Schema.Array$<typeof Schema.String>;
126
+ }>>;
127
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/cf-worker/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,EAAa,MAAM,yBAAyB,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAElE,MAAM,WAAW,GAAG;IAClB,wBAAwB;IACxB,EAAE,EAAE,OAAO,CAAC,UAAU,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,CAAC,EAAE,CACP,OAAO,EAAE,WAAW,CAAC,WAAW,EAChC,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,SAAS,CAAA;KAAE,KACtD,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;IACvC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,GAAG,gBAAgB,KAAK,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;IACnG,MAAM,CAAC,EAAE,CACP,OAAO,EAAE,WAAW,CAAC,WAAW,EAChC,OAAO,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC,SAAS,CAAA;KAAE,KACtD,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;IACvC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,YAAY,GAAG,gBAAgB,KAAK,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAA;IAGxG;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAA;IAEjD,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,OAAO,GAAG,MAAM,CAAA;AAC5B,MAAM,MAAM,eAAe,GAAG,MAAM,CAAA;AAEpC;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAA;AAE3C,eAAO,MAAM,gCAAgC,oBAAoB,CAAA;AAEjE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uEAA0E,CAAA;AAC5G,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;uEAA0E,CAAA;AAE5G,eAAO,MAAM,0BAA0B,GAAI,SAAS,OAAO,CAAC,OAAO,KAAG,MAAM,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,IAAI,CAMjH,CAAA;AAED,eAAO,MAAM,eAAe,MAAM,CAAA;AAGlC,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,SAAS,CAAA;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,eAAe,EAAE,MAAM,CAAA;KACxB,CAAA;CACF,CAAA;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,sBAAsB,EAAE,KAAK,CAAA;IAC7B,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;CACvE;AAED,eAAO,MAAM,yBAAyB;;;;GAQrC,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { Effect, Schema, UrlParams } from '@livestore/utils/effect';
2
+ import { SearchParamsSchema, SyncMessage } from "../common/mod.js";
3
+ /**
4
+ * Needs to be bumped when the storage format changes (e.g. eventlogTable schema changes)
5
+ *
6
+ * Changing this version number will lead to a "soft reset".
7
+ */
8
+ export const PERSISTENCE_FORMAT_VERSION = 7;
9
+ export const DEFAULT_SYNC_DURABLE_OBJECT_NAME = 'SYNC_BACKEND_DO';
10
+ export const encodeOutgoingMessage = Schema.encodeSync(Schema.parseJson(SyncMessage.BackendToClientMessage));
11
+ export const encodeIncomingMessage = Schema.encodeSync(Schema.parseJson(SyncMessage.ClientToBackendMessage));
12
+ export const getSyncRequestSearchParams = (request) => {
13
+ const url = new URL(request.url);
14
+ const urlParams = UrlParams.fromInput(url.searchParams);
15
+ const paramsResult = UrlParams.schemaStruct(SearchParamsSchema)(urlParams).pipe(Effect.option, Effect.runSync);
16
+ return paramsResult;
17
+ };
18
+ export const PULL_CHUNK_SIZE = 100;
19
+ export const WebSocketAttachmentSchema = Schema.parseJson(Schema.Struct({
20
+ // Same across all websocket connections
21
+ storeId: Schema.String,
22
+ // Different for each websocket connection
23
+ payload: Schema.optional(Schema.JsonValue),
24
+ pullRequestIds: Schema.Array(Schema.String),
25
+ }));
26
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/cf-worker/shared.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAe,MAAM,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAwClE;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAA;AAE3C,MAAM,CAAC,MAAM,gCAAgC,GAAG,iBAAiB,CAAA;AAEjE,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAAA;AAC5G,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAAA;AAE5G,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,OAAwB,EAAiD,EAAE;IACpH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAChC,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;IACvD,MAAM,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IAE9G,OAAO,YAAY,CAAA;AACrB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAA;AAuBlC,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,SAAS,CACvD,MAAM,CAAC,MAAM,CAAC;IACZ,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;IAC1C,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;CAC5C,CAAC,CACH,CAAA"}
@@ -1,8 +1,8 @@
1
- import type * as CfWorker from '@cloudflare/workers-types';
2
1
  import type { Schema } from '@livestore/utils/effect';
3
- import type { Env } from './durable-object.ts';
2
+ import type { CfTypes, SearchParams } from '../common/mod.ts';
3
+ import { type Env } from './shared.ts';
4
4
  export declare namespace HelperTypes {
5
- type AnyDON = CfWorker.DurableObjectNamespace<undefined>;
5
+ type AnyDON = CfTypes.DurableObjectNamespace<undefined>;
6
6
  type DOKeys<T> = {
7
7
  [K in keyof T]-?: T[K] extends AnyDON ? K : never;
8
8
  }[keyof T];
@@ -15,18 +15,18 @@ export declare namespace HelperTypes {
15
15
  * type PlatformEnv = {
16
16
  * DB: D1Database
17
17
  * ADMIN_TOKEN: string
18
- * WEBSOCKET_SERVER: DurableObjectNamespace<WebSocketServer>
18
+ * SYNC_BACKEND_DO: DurableObjectNamespace<SyncBackendDO>
19
19
  * }
20
20
  * export default makeWorker<PlatformEnv>({
21
- * durableObject: { name: "WEBSOCKET_SERVER" },
22
- * // ^ (property) name?: "WEBSOCKET_SERVER" | undefined
21
+ * durableObject: { name: "SYNC_BACKEND_DO" },
22
+ * // ^ (property) name?: "SYNC_BACKEND_DO" | undefined
23
23
  * });
24
24
  */
25
25
  export type ExtractDurableObjectKeys<TEnv = Env> = DOKeys<NonBuiltins<TEnv>> extends never ? string : DOKeys<NonBuiltins<TEnv>>;
26
26
  export {};
27
27
  }
28
- export type CFWorker<TEnv extends Env = Env, _T extends CfWorker.Rpc.DurableObjectBranded | undefined = undefined> = {
29
- fetch: <CFHostMetada = unknown>(request: CfWorker.Request<CFHostMetada>, env: TEnv, ctx: CfWorker.ExecutionContext) => Promise<CfWorker.Response>;
28
+ export type CFWorker<TEnv extends Env = Env, _T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined> = {
29
+ fetch: <CFHostMetada = unknown>(request: CfTypes.Request<CFHostMetada>, env: TEnv, ctx: CfTypes.ExecutionContext) => Promise<CfTypes.Response>;
30
30
  };
31
31
  export type MakeWorkerOptions<TEnv extends Env = Env> = {
32
32
  /**
@@ -43,14 +43,14 @@ export type MakeWorkerOptions<TEnv extends Env = Env> = {
43
43
  /**
44
44
  * Needs to match the binding name from the wrangler config
45
45
  *
46
- * @default 'WEBSOCKET_SERVER'
46
+ * @default 'SYNC_BACKEND_DO'
47
47
  */
48
48
  name?: HelperTypes.ExtractDurableObjectKeys<TEnv>;
49
49
  };
50
50
  };
51
- export declare const makeWorker: <TEnv extends Env = Env, TDurableObjectRpc extends CfWorker.Rpc.DurableObjectBranded | undefined = undefined>(options?: MakeWorkerOptions<TEnv>) => CFWorker<TEnv, TDurableObjectRpc>;
51
+ export declare const makeWorker: <TEnv extends Env = Env, TDurableObjectRpc extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>(options?: MakeWorkerOptions<TEnv>) => CFWorker<TEnv, TDurableObjectRpc>;
52
52
  /**
53
- * Handles `/websocket` endpoint.
53
+ * Handles `/sync` endpoint.
54
54
  *
55
55
  * @example
56
56
  * ```ts
@@ -63,23 +63,38 @@ export declare const makeWorker: <TEnv extends Env = Env, TDurableObjectRpc exte
63
63
  *
64
64
  * export default {
65
65
  * fetch: async (request, env, ctx) => {
66
- * if (request.url.endsWith('/websocket')) {
67
- * return handleWebSocket(request, env, ctx, { headers: {}, validatePayload })
66
+ * const requestParamsResult = getSyncRequestSearchParams(request)
67
+ *
68
+ * // Is LiveStore sync request
69
+ * if (requestParamsResult._tag === 'Some') {
70
+ * return handleSyncRequest({
71
+ * request,
72
+ * searchParams: requestParamsResult.value,
73
+ * env,
74
+ * ctx,
75
+ * options: { headers: {}, validatePayload }
76
+ * })
68
77
  * }
69
78
  *
70
79
  * return new Response('Invalid path', { status: 400 })
71
- * return new Response('Invalid path', { status: 400 })
72
80
  * }
73
81
  * }
74
82
  * ```
75
83
  *
76
84
  * @throws {UnexpectedError} If the payload is invalid
77
85
  */
78
- export declare const handleWebSocket: <TEnv extends Env = Env, TDurableObjectRpc extends CfWorker.Rpc.DurableObjectBranded | undefined = undefined, CFHostMetada = unknown>(request: CfWorker.Request<CFHostMetada>, env: TEnv, _ctx: CfWorker.ExecutionContext, options?: {
79
- headers?: CfWorker.HeadersInit;
80
- durableObject?: MakeWorkerOptions<TEnv>["durableObject"];
81
- validatePayload?: (payload: Schema.JsonValue | undefined, context: {
82
- storeId: string;
83
- }) => void | Promise<void>;
84
- }) => Promise<CfWorker.Response>;
86
+ export declare const handleSyncRequest: <TEnv extends Env = Env, TDurableObjectRpc extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined, CFHostMetada = unknown>({ request, searchParams, env, options, }: {
87
+ request: CfTypes.Request<CFHostMetada>;
88
+ searchParams: SearchParams;
89
+ env: TEnv;
90
+ /** Only there for type-level reasons */
91
+ ctx: CfTypes.ExecutionContext;
92
+ options?: {
93
+ headers?: CfTypes.HeadersInit;
94
+ durableObject?: MakeWorkerOptions<TEnv>["durableObject"];
95
+ validatePayload?: (payload: Schema.JsonValue | undefined, context: {
96
+ storeId: string;
97
+ }) => void | Promise<void>;
98
+ };
99
+ }) => Promise<CfTypes.Response>;
85
100
  //# sourceMappingURL=worker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/cf-worker/worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/cf-worker/worker.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,10 @@
1
1
  import { UnexpectedError } from '@livestore/common';
2
- import { Effect, UrlParams } from '@livestore/utils/effect';
3
- import { SearchParamsSchema } from "../common/mod.js";
2
+ import { Effect } from '@livestore/utils/effect';
3
+ import { DEFAULT_SYNC_DURABLE_OBJECT_NAME, getSyncRequestSearchParams } from "./shared.js";
4
4
  export const makeWorker = (options = {}) => {
5
5
  return {
6
6
  fetch: async (request, env, _ctx) => {
7
7
  const url = new URL(request.url);
8
- await new Promise((resolve) => setTimeout(resolve, 500));
9
- if (request.method === 'GET' && url.pathname === '/') {
10
- return new Response('Info: WebSocket sync backend endpoint for @livestore/sync-cf.', {
11
- status: 200,
12
- headers: { 'Content-Type': 'text/plain' },
13
- });
14
- }
15
8
  const corsHeaders = options.enableCORS
16
9
  ? {
17
10
  'Access-Control-Allow-Origin': '*',
@@ -25,11 +18,26 @@ export const makeWorker = (options = {}) => {
25
18
  headers: corsHeaders,
26
19
  });
27
20
  }
28
- if (url.pathname.endsWith('/websocket')) {
29
- return handleWebSocket(request, env, _ctx, {
30
- headers: corsHeaders,
31
- validatePayload: options.validatePayload,
32
- durableObject: options.durableObject,
21
+ const requestParamsResult = getSyncRequestSearchParams(request);
22
+ // Check if this is a sync request first, before showing info message
23
+ if (requestParamsResult._tag === 'Some') {
24
+ return handleSyncRequest({
25
+ request,
26
+ searchParams: requestParamsResult.value,
27
+ env,
28
+ ctx: _ctx,
29
+ options: {
30
+ headers: corsHeaders,
31
+ validatePayload: options.validatePayload,
32
+ durableObject: options.durableObject,
33
+ },
34
+ });
35
+ }
36
+ // Only show info message for GET requests to / without sync parameters
37
+ if (request.method === 'GET' && url.pathname === '/') {
38
+ return new Response('Info: Sync backend endpoint for @livestore/sync-cf.', {
39
+ status: 200,
40
+ headers: { 'Content-Type': 'text/plain' },
33
41
  });
34
42
  }
35
43
  console.error('Invalid path', url.pathname);
@@ -45,7 +53,7 @@ export const makeWorker = (options = {}) => {
45
53
  };
46
54
  };
47
55
  /**
48
- * Handles `/websocket` endpoint.
56
+ * Handles `/sync` endpoint.
49
57
  *
50
58
  * @example
51
59
  * ```ts
@@ -58,29 +66,28 @@ export const makeWorker = (options = {}) => {
58
66
  *
59
67
  * export default {
60
68
  * fetch: async (request, env, ctx) => {
61
- * if (request.url.endsWith('/websocket')) {
62
- * return handleWebSocket(request, env, ctx, { headers: {}, validatePayload })
69
+ * const requestParamsResult = getSyncRequestSearchParams(request)
70
+ *
71
+ * // Is LiveStore sync request
72
+ * if (requestParamsResult._tag === 'Some') {
73
+ * return handleSyncRequest({
74
+ * request,
75
+ * searchParams: requestParamsResult.value,
76
+ * env,
77
+ * ctx,
78
+ * options: { headers: {}, validatePayload }
79
+ * })
63
80
  * }
64
81
  *
65
82
  * return new Response('Invalid path', { status: 400 })
66
- * return new Response('Invalid path', { status: 400 })
67
83
  * }
68
84
  * }
69
85
  * ```
70
86
  *
71
87
  * @throws {UnexpectedError} If the payload is invalid
72
88
  */
73
- export const handleWebSocket = (request, env, _ctx, options = {}) => Effect.gen(function* () {
74
- const url = new URL(request.url);
75
- const urlParams = UrlParams.fromInput(url.searchParams);
76
- const paramsResult = yield* UrlParams.schemaStruct(SearchParamsSchema)(urlParams).pipe(Effect.either);
77
- if (paramsResult._tag === 'Left') {
78
- return new Response(`Invalid search params: ${paramsResult.left.toString()}`, {
79
- status: 500,
80
- headers: options?.headers,
81
- });
82
- }
83
- const { storeId, payload } = paramsResult.right;
89
+ export const handleSyncRequest = ({ request, searchParams, env, options = {}, }) => Effect.gen(function* () {
90
+ const { storeId, payload, transport } = searchParams;
84
91
  if (options.validatePayload !== undefined) {
85
92
  const result = yield* Effect.promise(async () => options.validatePayload(payload, { storeId })).pipe(UnexpectedError.mapToUnexpectedError, Effect.either);
86
93
  if (result._tag === 'Left') {
@@ -88,7 +95,7 @@ export const handleWebSocket = (request, env, _ctx, options = {}) => Effect.gen(
88
95
  return new Response(result.left.toString(), { status: 400, headers: options.headers });
89
96
  }
90
97
  }
91
- const durableObjectName = options.durableObject?.name ?? 'WEBSOCKET_SERVER';
98
+ const durableObjectName = options.durableObject?.name ?? DEFAULT_SYNC_DURABLE_OBJECT_NAME;
92
99
  if (!(durableObjectName in env)) {
93
100
  return new Response(`Failed dependency: Required Durable Object binding '${durableObjectName}' not available`, {
94
101
  status: 424,
@@ -98,14 +105,14 @@ export const handleWebSocket = (request, env, _ctx, options = {}) => Effect.gen(
98
105
  const durableObjectNamespace = env[durableObjectName];
99
106
  const id = durableObjectNamespace.idFromName(storeId);
100
107
  const durableObject = durableObjectNamespace.get(id);
108
+ // Handle WebSocket upgrade request
101
109
  const upgradeHeader = request.headers.get('Upgrade');
102
- if (!upgradeHeader || upgradeHeader !== 'websocket') {
110
+ if (transport === 'ws' && (upgradeHeader === null || upgradeHeader !== 'websocket')) {
103
111
  return new Response('Durable Object expected Upgrade: websocket', {
104
112
  status: 426,
105
113
  headers: options?.headers,
106
114
  });
107
115
  }
108
- // Cloudflare Durable Object type clashing with lib.dom Response type, which is why we need the casts here.
109
116
  return yield* Effect.promise(() => durableObject.fetch(request));
110
117
  }).pipe(Effect.tapCauseLogPretty, Effect.runPromise);
111
118
  //# sourceMappingURL=worker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/cf-worker/worker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/cf-worker/worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './transport/do-rpc-client.ts';
2
+ export * from './transport/http-rpc-client.ts';
3
+ export * from './transport/ws-rpc-client.ts';
4
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/client/mod.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,8BAA8B,CAAA"}
@@ -0,0 +1,4 @@
1
+ export * from "./transport/do-rpc-client.js";
2
+ export * from "./transport/http-rpc-client.js";
3
+ export * from "./transport/ws-rpc-client.js";
4
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.js","sourceRoot":"","sources":["../../src/client/mod.ts"],"names":[],"mappings":"AAAA,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,8BAA8B,CAAA"}
@@ -0,0 +1,40 @@
1
+ import { SyncBackend } from '@livestore/common';
2
+ import { type CfTypes } from '@livestore/common-cf';
3
+ import type { SyncBackendRpcInterface } from '../../cf-worker/shared.ts';
4
+ import type { SyncMetadata } from '../../common/sync-message-types.ts';
5
+ export interface SyncBackendRpcStub extends CfTypes.DurableObjectStub, SyncBackendRpcInterface {
6
+ }
7
+ export interface DoRpcSyncOptions {
8
+ /** Durable Object stub that implements the SyncDoRpc interface */
9
+ syncBackendStub: SyncBackendRpcStub;
10
+ /** Information about this DurableObject instance so the Sync DO instance can call back to this instance */
11
+ durableObjectContext: {
12
+ /** See `wrangler.toml` for the binding name */
13
+ bindingName: string;
14
+ /** `state.id.toString()` in the DO */
15
+ durableObjectId: string;
16
+ };
17
+ }
18
+ /**
19
+ * Creates a sync backend that uses Durable Object RPC to communicate with the sync backend.
20
+ *
21
+ * Used internally by `@livestore/adapter-cf` to connect to the sync backend.
22
+ */
23
+ export declare const makeDoRpcSync: ({ syncBackendStub, durableObjectContext }: DoRpcSyncOptions) => SyncBackend.SyncBackendConstructor<SyncMetadata>;
24
+ /**
25
+ *
26
+ * ```ts
27
+ * import { DurableObject } from 'cloudflare:workers'
28
+ * import { ClientDoWithRpcCallback } from '@livestore/common-cf'
29
+ *
30
+ * export class MyDurableObject extends DurableObject implements ClientDoWithRpcCallback {
31
+ * // ...
32
+ *
33
+ * async syncUpdateRpc(payload: RpcMessage.ResponseChunkEncoded) {
34
+ * return handleSyncUpdateRpc(payload)
35
+ * }
36
+ * }
37
+ * ```
38
+ */
39
+ export declare const handleSyncUpdateRpc: (payload: unknown) => Promise<void>;
40
+ //# sourceMappingURL=do-rpc-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"do-rpc-client.d.ts","sourceRoot":"","sources":["../../../src/client/transport/do-rpc-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,WAAW,EAAmB,MAAM,mBAAmB,CAAA;AACpG,OAAO,EAAE,KAAK,OAAO,EAA8B,MAAM,sBAAsB,CAAA;AAc/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AAGxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AAEtE,MAAM,WAAW,kBAAmB,SAAQ,OAAO,CAAC,iBAAiB,EAAE,uBAAuB;CAAG;AAMjG,MAAM,WAAW,gBAAgB;IAC/B,kEAAkE;IAClE,eAAe,EAAE,kBAAkB,CAAA;IACnC,2GAA2G;IAC3G,oBAAoB,EAAE;QACpB,+CAA+C;QAC/C,WAAW,EAAE,MAAM,CAAA;QACnB,sCAAsC;QACtC,eAAe,EAAE,MAAM,CAAA;KACxB,CAAA;CACF;AAED;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACvB,2CAA2C,gBAAgB,KAAG,WAAW,CAAC,sBAAsB,CAAC,YAAY,CA0FnD,CAAA;AAE7D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAS,OAAO,kBAckD,CAAA"}
@@ -0,0 +1,102 @@
1
+ import { InvalidPullError, InvalidPushError, SyncBackend, UnexpectedError } from '@livestore/common';
2
+ import { layerProtocolDurableObject } from '@livestore/common-cf';
3
+ import { omit, shouldNeverHappen } from '@livestore/utils';
4
+ import { Effect, identity, Layer, Mailbox, Option, RpcClient, RpcSerialization, Schema, Stream, SubscriptionRef, } from '@livestore/utils/effect';
5
+ import { SyncDoRpc } from "../../common/do-rpc-schema.js";
6
+ import { SyncMessage } from "../../common/mod.js";
7
+ const requestIdMailboxMap = new Map();
8
+ /**
9
+ * Creates a sync backend that uses Durable Object RPC to communicate with the sync backend.
10
+ *
11
+ * Used internally by `@livestore/adapter-cf` to connect to the sync backend.
12
+ */
13
+ export const makeDoRpcSync = ({ syncBackendStub, durableObjectContext }) => ({ storeId, payload }) => Effect.gen(function* () {
14
+ const isConnected = yield* SubscriptionRef.make(true);
15
+ const ProtocolLive = layerProtocolDurableObject({
16
+ callRpc: (payload) => syncBackendStub.rpc(payload),
17
+ callerContext: durableObjectContext,
18
+ }).pipe(Layer.provide(RpcSerialization.layerJson));
19
+ const context = yield* Layer.build(ProtocolLive);
20
+ const rpcClient = yield* RpcClient.make(SyncDoRpc).pipe(Effect.provide(context));
21
+ // Nothing to do here
22
+ const connect = Effect.void;
23
+ const backendIdHelper = yield* SyncBackend.makeBackendIdHelper;
24
+ const pull = (cursor, options) => rpcClient.SyncDoRpc.Pull({
25
+ cursor: cursor.pipe(Option.map((a) => ({
26
+ eventSequenceNumber: a.eventSequenceNumber,
27
+ backendId: backendIdHelper.get().pipe(Option.getOrThrow),
28
+ }))),
29
+ storeId,
30
+ rpcContext: options?.live ? { callerContext: durableObjectContext } : undefined,
31
+ }).pipe(options?.live
32
+ ? Stream.concatWithLastElement((res) => Effect.gen(function* () {
33
+ if (res._tag === 'None')
34
+ return shouldNeverHappen('There should at least be a no-more page info response');
35
+ const mailbox = yield* Mailbox.make().pipe(Effect.acquireRelease((mailbox) => mailbox.shutdown));
36
+ requestIdMailboxMap.set(res.value.rpcRequestId, mailbox);
37
+ return Mailbox.toStream(mailbox);
38
+ }).pipe(Stream.unwrapScoped))
39
+ : identity, Stream.tap((res) => backendIdHelper.lazySet(res.backendId)), Stream.map((res) => omit(res, ['backendId'])), Stream.mapError((cause) => (cause._tag === 'InvalidPullError' ? cause : InvalidPullError.make({ cause }))), Stream.withSpan('rpc-sync-client:pull'));
40
+ const push = (batch) => Effect.gen(function* () {
41
+ if (batch.length === 0) {
42
+ return;
43
+ }
44
+ yield* rpcClient.SyncDoRpc.Push({ batch, storeId, backendId: backendIdHelper.get() });
45
+ }).pipe(Effect.mapError((cause) => cause._tag === 'InvalidPushError'
46
+ ? cause
47
+ : InvalidPushError.make({ cause: new UnexpectedError({ cause }) })), Effect.withSpan('rpc-sync-client:push'));
48
+ const ping = rpcClient.SyncDoRpc.Ping({
49
+ storeId,
50
+ payload,
51
+ }).pipe(UnexpectedError.mapToUnexpectedError, Effect.withSpan('rpc-sync-client:ping'));
52
+ return SyncBackend.of({
53
+ connect,
54
+ isConnected,
55
+ pull,
56
+ push,
57
+ ping,
58
+ metadata: {
59
+ name: 'rpc-sync-client',
60
+ description: 'Cloudflare Durable Object RPC Sync Client',
61
+ protocol: 'rpc',
62
+ storeId,
63
+ },
64
+ supports: {
65
+ pullPageInfoKnown: true,
66
+ pullLive: true,
67
+ },
68
+ });
69
+ }).pipe(Effect.withSpan('rpc-sync-client:makeDoRpcSync'));
70
+ /**
71
+ *
72
+ * ```ts
73
+ * import { DurableObject } from 'cloudflare:workers'
74
+ * import { ClientDoWithRpcCallback } from '@livestore/common-cf'
75
+ *
76
+ * export class MyDurableObject extends DurableObject implements ClientDoWithRpcCallback {
77
+ * // ...
78
+ *
79
+ * async syncUpdateRpc(payload: RpcMessage.ResponseChunkEncoded) {
80
+ * return handleSyncUpdateRpc(payload)
81
+ * }
82
+ * }
83
+ * ```
84
+ */
85
+ export const handleSyncUpdateRpc = (payload) => Effect.gen(function* () {
86
+ const decodedPayload = yield* Schema.decodeUnknown(ResponseChunkEncoded)(payload);
87
+ const decoded = yield* Schema.decodeUnknown(SyncMessage.PullResponse)(decodedPayload.values[0]);
88
+ const pullStreamMailbox = requestIdMailboxMap.get(decodedPayload.requestId);
89
+ if (pullStreamMailbox === undefined) {
90
+ // Case: DO was hibernated, so we need to manually update the store
91
+ yield* Effect.log(`No mailbox found for ${decodedPayload.requestId}`);
92
+ }
93
+ else {
94
+ // Case: DO was still alive, so the existing `pull` will pick up the new events
95
+ yield* pullStreamMailbox.offer(decoded);
96
+ }
97
+ }).pipe(Effect.withSpan('rpc-sync-client:rpcCallback'), Effect.tapCauseLogPretty, Effect.runPromise);
98
+ const ResponseChunkEncoded = Schema.Struct({
99
+ requestId: Schema.String,
100
+ values: Schema.Array(Schema.Any),
101
+ });
102
+ //# sourceMappingURL=do-rpc-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"do-rpc-client.js","sourceRoot":"","sources":["../../../src/client/transport/do-rpc-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACpG,OAAO,EAAgB,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EACL,MAAM,EACN,QAAQ,EACR,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,gBAAgB,EAChB,MAAM,EACN,MAAM,EACN,eAAe,GAChB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAOjD,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAiE,CAAA;AAcpG;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GACxB,CAAC,EAAE,eAAe,EAAE,oBAAoB,EAAoB,EAAoD,EAAE,CAClH,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CACvB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAErD,MAAM,YAAY,GAAG,0BAA0B,CAAC;QAC9C,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC;QAClD,aAAa,EAAE,oBAAoB;KACpC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAA;IAElD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IAEhD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAEhF,qBAAqB;IACrB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAA;IAE3B,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAA;IAE9D,MAAM,IAAI,GAAkD,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAC9E,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC,IAAI,CACjB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjB,mBAAmB,EAAE,CAAC,CAAC,mBAAmB;YAC1C,SAAS,EAAE,eAAe,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;SACzD,CAAC,CAAC,CACJ;QACD,OAAO;QACP,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,oBAAoB,EAAE,CAAC,CAAC,CAAC,SAAS;KAChF,CAAC,CAAC,IAAI,CACL,OAAO,EAAE,IAAI;QACX,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,GAAG,EAAE,EAAE,CACnC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;gBACrB,OAAO,iBAAiB,CAAC,uDAAuD,CAAC,CAAA;YAEnF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAA4B,CAAC,IAAI,CAClE,MAAM,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CACrD,CAAA;YAED,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;YAExD,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAC7B;QACH,CAAC,CAAC,QAAQ,EACZ,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAC3D,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAC7C,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAC1G,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CACxC,CAAA;IAEH,MAAM,IAAI,GAA2D,CAAC,KAAK,EAAE,EAAE,CAC7E,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAM;QACR,CAAC;QAED,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IACvF,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CACxB,KAAK,CAAC,IAAI,KAAK,kBAAkB;QAC/B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CACrE,EACD,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CACxC,CAAA;IAEH,MAAM,IAAI,GAA2D,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC;QAC5F,OAAO;QACP,OAAO;KACR,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,oBAAoB,EAAE,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,CAAA;IAEtF,OAAO,WAAW,CAAC,EAAE,CAAC;QACpB,OAAO;QACP,WAAW;QACX,IAAI;QACJ,IAAI;QACJ,IAAI;QACJ,QAAQ,EAAE;YACR,IAAI,EAAE,iBAAiB;YACvB,WAAW,EAAE,2CAA2C;YACxD,QAAQ,EAAE,KAAK;YACf,OAAO;SACR;QACD,QAAQ,EAAE;YACR,iBAAiB,EAAE,IAAI;YACvB,QAAQ,EAAE,IAAI;SACf;KACF,CAAC,CAAA;AACJ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC,CAAA;AAE7D;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAgB,EAAE,EAAE,CACtD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,CAAA;IACjF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAA;IAEhG,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAA;IAE3E,IAAI,iBAAiB,KAAK,SAAS,EAAE,CAAC;QACpC,mEAAmE;QACnE,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,wBAAwB,cAAc,CAAC,SAAS,EAAE,CAAC,CAAA;IACvE,CAAC;SAAM,CAAC;QACN,+EAA+E;QAC/E,KAAK,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACzC,CAAC;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,6BAA6B,CAAC,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,UAAU,CAAC,CAAA;AAEtG,MAAM,oBAAoB,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;CACjC,CAAC,CAAA"}