@mikeci/pos-replay-protocol 0.0.0-stage → 0.2.1
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 +8 -2
- package/dist/codec.d.ts +12 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +222 -0
- package/dist/codec.js.map +1 -0
- package/dist/fixture.d.ts +6 -0
- package/dist/fixture.d.ts.map +1 -0
- package/dist/fixture.js +93 -0
- package/dist/fixture.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/mask.d.ts +12 -0
- package/dist/mask.d.ts.map +1 -0
- package/dist/mask.js +18 -0
- package/dist/mask.js.map +1 -0
- package/dist/sanitize.d.ts +13 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +49 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/scene.d.ts +27 -0
- package/dist/scene.d.ts.map +1 -0
- package/dist/scene.js +94 -0
- package/dist/scene.js.map +1 -0
- package/dist/types.d.ts +105 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +25 -3
package/README.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @mikeci/pos-replay-protocol
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Hợp đồng session replay dùng chung cho SDK, collector và player. `protocolVersion` hiện tại là `1`. Player từ chối bản ghi có version cao hơn.
|
|
4
|
+
|
|
5
|
+
Chunk bắt đầu bằng một record `snapshot`. `patch` cập nhật hoặc xóa node. `interaction` ghi tap hoặc scroll. `privacy_boundary` chặn nội dung nhạy cảm. `lifecycle` ghi background, foreground, đổi tài khoản hoặc khoảng trống.
|
|
6
|
+
|
|
7
|
+
`encodeChunk` gắn checksum SHA-256 của JSON đã sắp khóa, không gồm chính checksum. Cùng nội dung luôn ra cùng checksum. Payload bị sửa sẽ không qua `decodeChunk`.
|
|
8
|
+
|
|
9
|
+
Tọa độ node là tương đối với `parentId`. Ô `input` và component có tên nhạy cảm được đổi text thành `••••` trước khi ra khỏi thiết bị.
|
package/dist/codec.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ReplayChunk, type ReplayNode } from "./types.js";
|
|
2
|
+
export declare function stableJson(value: unknown): string;
|
|
3
|
+
/** SHA-256 dùng khi runtime không có Web Crypto, ví dụ Hermes. */
|
|
4
|
+
export declare function sha256Fallback(text: string): string;
|
|
5
|
+
export declare function sha256Hex(text: string): Promise<string>;
|
|
6
|
+
export declare function chunkWithoutChecksum(chunk: ReplayChunk): ReplayChunk;
|
|
7
|
+
export declare function checksumChunk(chunk: ReplayChunk): Promise<string>;
|
|
8
|
+
export declare function validateNode(node: ReplayNode): string[];
|
|
9
|
+
export declare function validateChunk(chunk: ReplayChunk): string[];
|
|
10
|
+
export declare function encodeChunk(chunk: ReplayChunk): Promise<ReplayChunk>;
|
|
11
|
+
export declare function decodeChunk(input: unknown): Promise<ReplayChunk>;
|
|
12
|
+
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmF,KAAK,WAAW,EAAE,KAAK,UAAU,EAAqB,MAAM,YAAY,CAAC;AAmBnK,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEjD;AA4BD,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAkDnD;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW7D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,CAIpE;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAEvE;AAYD,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,CAUvD;AAyBD,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,EAAE,CAe1D;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAK1E;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAStE"}
|
package/dist/codec.js
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { MAX_CHUNK_BYTES, MAX_NODES, MAX_RECORDS, MAX_TEXT, NODE_TYPES, PROTOCOL_VERSION } from "./types.js";
|
|
2
|
+
const NODE_KEYS = new Set([
|
|
3
|
+
"id",
|
|
4
|
+
"parentId",
|
|
5
|
+
"type",
|
|
6
|
+
"bounds",
|
|
7
|
+
"zIndex",
|
|
8
|
+
"clipsChildren",
|
|
9
|
+
"text",
|
|
10
|
+
"assetId",
|
|
11
|
+
"state",
|
|
12
|
+
"style",
|
|
13
|
+
"componentId",
|
|
14
|
+
"contentId",
|
|
15
|
+
"contentVersion",
|
|
16
|
+
"masked",
|
|
17
|
+
]);
|
|
18
|
+
export function stableJson(value) {
|
|
19
|
+
return JSON.stringify(sortValue(value));
|
|
20
|
+
}
|
|
21
|
+
function sortValue(value) {
|
|
22
|
+
if (Array.isArray(value))
|
|
23
|
+
return value.map(sortValue);
|
|
24
|
+
if (!value || typeof value !== "object")
|
|
25
|
+
return value;
|
|
26
|
+
const source = value;
|
|
27
|
+
const out = {};
|
|
28
|
+
for (const key of Object.keys(source).sort()) {
|
|
29
|
+
if (source[key] !== undefined)
|
|
30
|
+
out[key] = sortValue(source[key]);
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
const SHA_K = [
|
|
35
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
36
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
37
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
38
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
39
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
40
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
41
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
42
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
43
|
+
];
|
|
44
|
+
function rotr(value, bits) {
|
|
45
|
+
return (value >>> bits) | (value << (32 - bits));
|
|
46
|
+
}
|
|
47
|
+
/** SHA-256 dùng khi runtime không có Web Crypto, ví dụ Hermes. */
|
|
48
|
+
export function sha256Fallback(text) {
|
|
49
|
+
const bytes = [...new TextEncoder().encode(text)];
|
|
50
|
+
const bitLength = bytes.length * 8;
|
|
51
|
+
bytes.push(0x80);
|
|
52
|
+
while (bytes.length % 64 !== 56)
|
|
53
|
+
bytes.push(0);
|
|
54
|
+
const high = Math.floor(bitLength / 0x100000000);
|
|
55
|
+
const low = bitLength >>> 0;
|
|
56
|
+
for (let shift = 24; shift >= 0; shift -= 8)
|
|
57
|
+
bytes.push((high >>> shift) & 0xff);
|
|
58
|
+
for (let shift = 24; shift >= 0; shift -= 8)
|
|
59
|
+
bytes.push((low >>> shift) & 0xff);
|
|
60
|
+
const hash = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19];
|
|
61
|
+
const words = new Array(64);
|
|
62
|
+
for (let offset = 0; offset < bytes.length; offset += 64) {
|
|
63
|
+
for (let index = 0; index < 16; index += 1) {
|
|
64
|
+
const start = offset + index * 4;
|
|
65
|
+
words[index] = ((bytes[start] ?? 0) << 24) | ((bytes[start + 1] ?? 0) << 16) | ((bytes[start + 2] ?? 0) << 8) | (bytes[start + 3] ?? 0);
|
|
66
|
+
}
|
|
67
|
+
for (let index = 16; index < 64; index += 1) {
|
|
68
|
+
const start = words[index - 15] ?? 0;
|
|
69
|
+
const end = words[index - 2] ?? 0;
|
|
70
|
+
const small = rotr(start, 7) ^ rotr(start, 18) ^ (start >>> 3);
|
|
71
|
+
const large = rotr(end, 17) ^ rotr(end, 19) ^ (end >>> 10);
|
|
72
|
+
words[index] = ((words[index - 16] ?? 0) + small + (words[index - 7] ?? 0) + large) >>> 0;
|
|
73
|
+
}
|
|
74
|
+
let [a, b, c, d, e, f, g, h] = hash;
|
|
75
|
+
for (let index = 0; index < 64; index += 1) {
|
|
76
|
+
const sum1 = rotr(e ?? 0, 6) ^ rotr(e ?? 0, 11) ^ rotr(e ?? 0, 25);
|
|
77
|
+
const choice = ((e ?? 0) & (f ?? 0)) ^ (~(e ?? 0) & (g ?? 0));
|
|
78
|
+
const temp1 = (((h ?? 0) + sum1 + choice + (SHA_K[index] ?? 0) + (words[index] ?? 0)) >>> 0);
|
|
79
|
+
const sum0 = rotr(a ?? 0, 2) ^ rotr(a ?? 0, 13) ^ rotr(a ?? 0, 22);
|
|
80
|
+
const majority = ((a ?? 0) & (b ?? 0)) ^ ((a ?? 0) & (c ?? 0)) ^ ((b ?? 0) & (c ?? 0));
|
|
81
|
+
const temp2 = (sum0 + majority) >>> 0;
|
|
82
|
+
h = g;
|
|
83
|
+
g = f;
|
|
84
|
+
f = e;
|
|
85
|
+
e = ((d ?? 0) + temp1) >>> 0;
|
|
86
|
+
d = c;
|
|
87
|
+
c = b;
|
|
88
|
+
b = a;
|
|
89
|
+
a = (temp1 + temp2) >>> 0;
|
|
90
|
+
}
|
|
91
|
+
hash[0] = ((hash[0] ?? 0) + (a ?? 0)) >>> 0;
|
|
92
|
+
hash[1] = ((hash[1] ?? 0) + (b ?? 0)) >>> 0;
|
|
93
|
+
hash[2] = ((hash[2] ?? 0) + (c ?? 0)) >>> 0;
|
|
94
|
+
hash[3] = ((hash[3] ?? 0) + (d ?? 0)) >>> 0;
|
|
95
|
+
hash[4] = ((hash[4] ?? 0) + (e ?? 0)) >>> 0;
|
|
96
|
+
hash[5] = ((hash[5] ?? 0) + (f ?? 0)) >>> 0;
|
|
97
|
+
hash[6] = ((hash[6] ?? 0) + (g ?? 0)) >>> 0;
|
|
98
|
+
hash[7] = ((hash[7] ?? 0) + (h ?? 0)) >>> 0;
|
|
99
|
+
}
|
|
100
|
+
return hash.map((word) => (word ?? 0).toString(16).padStart(8, "0")).join("");
|
|
101
|
+
}
|
|
102
|
+
export async function sha256Hex(text) {
|
|
103
|
+
const subtle = globalThis.crypto?.subtle;
|
|
104
|
+
if (subtle?.digest) {
|
|
105
|
+
try {
|
|
106
|
+
const digest = await subtle.digest("SHA-256", new TextEncoder().encode(text));
|
|
107
|
+
return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return sha256Fallback(text);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return sha256Fallback(text);
|
|
114
|
+
}
|
|
115
|
+
export function chunkWithoutChecksum(chunk) {
|
|
116
|
+
const copy = { ...chunk };
|
|
117
|
+
delete copy.checksum;
|
|
118
|
+
return copy;
|
|
119
|
+
}
|
|
120
|
+
export async function checksumChunk(chunk) {
|
|
121
|
+
return sha256Hex(stableJson(chunkWithoutChecksum(chunk)));
|
|
122
|
+
}
|
|
123
|
+
function boundsOk(value) {
|
|
124
|
+
if (!value || typeof value !== "object")
|
|
125
|
+
return false;
|
|
126
|
+
const box = value;
|
|
127
|
+
return ["x", "y", "width", "height"].every((key) => typeof box[key] === "number" && Number.isFinite(box[key]));
|
|
128
|
+
}
|
|
129
|
+
function unknownKeys(value, allowed) {
|
|
130
|
+
return Object.keys(value).filter((key) => !allowed.has(key));
|
|
131
|
+
}
|
|
132
|
+
export function validateNode(node) {
|
|
133
|
+
const issues = [];
|
|
134
|
+
const extra = unknownKeys(node, NODE_KEYS);
|
|
135
|
+
if (extra.length)
|
|
136
|
+
issues.push(`unknown node fields: ${extra.join(",")}`);
|
|
137
|
+
if (!node.id)
|
|
138
|
+
issues.push("node id required");
|
|
139
|
+
if (node.parentId !== null && typeof node.parentId !== "string")
|
|
140
|
+
issues.push("parentId must be string or null");
|
|
141
|
+
if (!NODE_TYPES.includes(node.type))
|
|
142
|
+
issues.push(`unknown node type ${node.type}`);
|
|
143
|
+
if (!boundsOk(node.bounds))
|
|
144
|
+
issues.push("bounds invalid");
|
|
145
|
+
if (node.text && node.text.length > MAX_TEXT)
|
|
146
|
+
issues.push("text too long");
|
|
147
|
+
return issues;
|
|
148
|
+
}
|
|
149
|
+
const RECORD_TYPES = new Set(["snapshot", "patch", "interaction", "lifecycle", "viewport", "privacy_boundary"]);
|
|
150
|
+
const LIFECYCLE_KINDS = new Set(["background", "foreground", "account_changed", "gap"]);
|
|
151
|
+
function validateRecord(record, index) {
|
|
152
|
+
const issues = [];
|
|
153
|
+
const type = record.type;
|
|
154
|
+
if (typeof type !== "string" || !RECORD_TYPES.has(type)) {
|
|
155
|
+
issues.push(`record ${index} unknown type ${String(type)}`);
|
|
156
|
+
return issues;
|
|
157
|
+
}
|
|
158
|
+
if (!Number.isInteger(record.seq) || record.seq < 0)
|
|
159
|
+
issues.push(`record ${index} seq`);
|
|
160
|
+
if (!Number.isFinite(record.offsetMs) || record.offsetMs < 0)
|
|
161
|
+
issues.push(`record ${index} offset`);
|
|
162
|
+
if (record.type === "snapshot" || record.type === "patch") {
|
|
163
|
+
const nodes = record.type === "snapshot" ? record.nodes : record.upserts;
|
|
164
|
+
if (!Array.isArray(nodes) || nodes.length > MAX_NODES)
|
|
165
|
+
issues.push("too many nodes");
|
|
166
|
+
else
|
|
167
|
+
for (const node of nodes)
|
|
168
|
+
issues.push(...validateNode(node));
|
|
169
|
+
}
|
|
170
|
+
if (record.type === "interaction" && record.kind !== "tap" && record.kind !== "scroll")
|
|
171
|
+
issues.push("interaction kind");
|
|
172
|
+
if (record.type === "lifecycle" && !LIFECYCLE_KINDS.has(record.kind))
|
|
173
|
+
issues.push("lifecycle kind");
|
|
174
|
+
if (record.type === "privacy_boundary" && typeof record.blocked !== "boolean")
|
|
175
|
+
issues.push("privacy blocked");
|
|
176
|
+
return issues;
|
|
177
|
+
}
|
|
178
|
+
export function validateChunk(chunk) {
|
|
179
|
+
const issues = [];
|
|
180
|
+
if (chunk.protocolVersion > PROTOCOL_VERSION)
|
|
181
|
+
issues.push("unsupported protocol version");
|
|
182
|
+
if (!chunk.protocolVersion || chunk.protocolVersion < 1)
|
|
183
|
+
issues.push("protocol version required");
|
|
184
|
+
if (!chunk.replayId || !chunk.segmentId || !chunk.chunkId || !chunk.sessionId)
|
|
185
|
+
issues.push("identity required");
|
|
186
|
+
if (!Number.isInteger(chunk.chunkSequence) || chunk.chunkSequence < 0)
|
|
187
|
+
issues.push("chunk sequence");
|
|
188
|
+
if (chunk.endOffsetMs < chunk.startOffsetMs)
|
|
189
|
+
issues.push("offset range");
|
|
190
|
+
if (!chunk.viewport || chunk.viewport.width <= 0 || chunk.viewport.height <= 0)
|
|
191
|
+
issues.push("viewport");
|
|
192
|
+
if (!Array.isArray(chunk.records) || chunk.records.length > MAX_RECORDS)
|
|
193
|
+
issues.push("records");
|
|
194
|
+
chunk.records.forEach((record, index) => issues.push(...validateRecord(record, index)));
|
|
195
|
+
const hasKeyframe = chunk.records.some((record) => record.type === "snapshot");
|
|
196
|
+
if (!hasKeyframe)
|
|
197
|
+
issues.push("chunk requires a snapshot keyframe");
|
|
198
|
+
// Độ dài không phụ thuộc thứ tự khóa, nên dùng JSON.stringify (nhanh hơn nhiều so với stableJson sắp xếp khóa).
|
|
199
|
+
if (JSON.stringify(chunk).length > MAX_CHUNK_BYTES)
|
|
200
|
+
issues.push("chunk too large");
|
|
201
|
+
return issues;
|
|
202
|
+
}
|
|
203
|
+
export async function encodeChunk(chunk) {
|
|
204
|
+
const issues = validateChunk(chunk);
|
|
205
|
+
if (issues.length)
|
|
206
|
+
throw Object.assign(new Error(issues[0] ?? "invalid chunk"), { issues });
|
|
207
|
+
const checksum = await checksumChunk(chunk);
|
|
208
|
+
return { ...chunk, checksum };
|
|
209
|
+
}
|
|
210
|
+
export async function decodeChunk(input) {
|
|
211
|
+
const chunk = input;
|
|
212
|
+
const issues = validateChunk(chunk);
|
|
213
|
+
if (issues.length)
|
|
214
|
+
throw Object.assign(new Error(issues[0] ?? "invalid chunk"), { issues, statusCode: 400 });
|
|
215
|
+
if (chunk.checksum) {
|
|
216
|
+
const expected = await checksumChunk(chunk);
|
|
217
|
+
if (expected !== chunk.checksum)
|
|
218
|
+
throw Object.assign(new Error("checksum_mismatch"), { statusCode: 400 });
|
|
219
|
+
}
|
|
220
|
+
return chunk;
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=codec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAwD,MAAM,YAAY,CAAC;AAEnK,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,IAAI;IACJ,UAAU;IACV,MAAM;IACN,QAAQ;IACR,QAAQ;IACR,eAAe;IACf,MAAM;IACN,SAAS;IACT,OAAO;IACP,OAAO;IACP,aAAa;IACb,WAAW;IACX,gBAAgB;IAChB,QAAQ;CACT,CAAC,CAAC;AAEH,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC7C,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,KAAK,GAAG;IACZ,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;IAC9F,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;IAC9F,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;IAC9F,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;IAC9F,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;IAC9F,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;IAC9F,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;IAC9F,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;CAC/F,CAAC;AAEF,SAAS,IAAI,CAAC,KAAa,EAAE,IAAY;IACvC,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACnC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,OAAO,KAAK,CAAC,MAAM,GAAG,EAAE,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,WAAW,CAAC,CAAC;IACjD,MAAM,GAAG,GAAG,SAAS,KAAK,CAAC,CAAC;IAC5B,KAAK,IAAI,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACjF,KAAK,IAAI,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IAChF,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IAC9G,MAAM,KAAK,GAAG,IAAI,KAAK,CAAS,EAAE,CAAC,CAAC;IACpC,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;QACzD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,CAAC,CAAC;YACjC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1I,CAAC;QACD,KAAK,IAAI,KAAK,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC;YAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC;YAC3D,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5F,CAAC;QACD,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;QACpC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YACnE,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9D,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;YAC7F,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YACnE,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACvF,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YACtC,CAAC,GAAG,CAAC,CAAC;YACN,CAAC,GAAG,CAAC,CAAC;YACN,CAAC,GAAG,CAAC,CAAC;YACN,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC,GAAG,CAAC,CAAC;YACN,CAAC,GAAG,CAAC,CAAC;YACN,CAAC,GAAG,CAAC,CAAC;YACN,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY;IAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC;IACzC,IAAI,MAAM,EAAE,MAAM,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAC9E,OAAO,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChG,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAkB;IACrD,MAAM,IAAI,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;IAC1B,OAAO,IAAI,CAAC,QAAQ,CAAC;IACrB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAkB;IACpD,OAAO,SAAS,CAAC,UAAU,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAW,CAAC,CAAC,CAAC;AAC3H,CAAC;AAED,SAAS,WAAW,CAAC,KAA8B,EAAE,OAAoB;IACvE,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,WAAW,CAAC,IAA0C,EAAE,SAAS,CAAC,CAAC;IACjF,IAAI,KAAK,CAAC,MAAM;QAAE,MAAM,CAAC,IAAI,CAAC,wBAAwB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACzE,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC9C,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAChH,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACnF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC1D,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC3E,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAChH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;AAExF,SAAS,cAAc,CAAC,MAAoB,EAAE,KAAa;IACzD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAI,MAA6B,CAAC,IAAI,CAAC;IACjD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,iBAAiB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5D,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC;IACxF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,QAAQ,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC;IACpG,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;QACzE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS;YAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;;YAChF,KAAK,MAAM,IAAI,IAAI,KAAK;gBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ;QAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACxH,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACpG,IAAI,MAAM,CAAC,IAAI,KAAK,kBAAkB,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC9G,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAkB;IAC9C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,CAAC,eAAe,GAAG,gBAAgB;QAAE,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;IAC1F,IAAI,CAAC,KAAK,CAAC,eAAe,IAAI,KAAK,CAAC,eAAe,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAClG,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAChH,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACrG,IAAI,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,aAAa;QAAE,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACzE,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,WAAW;QAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACxF,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAC/E,IAAI,CAAC,WAAW;QAAE,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;IACpE,gHAAgH;IAChH,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,eAAe;QAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACnF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAkB;IAClD,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,MAAM;QAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5C,OAAO,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAc;IAC9C,MAAM,KAAK,GAAG,KAAoB,CAAC;IACnC,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,MAAM;QAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7G,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,QAAQ,KAAK,KAAK,CAAC,QAAQ;YAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5G,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ReplayChunk, ReplayNode } from "./types.js";
|
|
2
|
+
export declare function homeNodes(): ReplayNode[];
|
|
3
|
+
export declare function pickTicketNodes(): ReplayNode[];
|
|
4
|
+
export declare function checkoutNodes(): ReplayNode[];
|
|
5
|
+
export declare function sampleRecording(): ReplayChunk[];
|
|
6
|
+
//# sourceMappingURL=fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture.d.ts","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAS1D,wBAAgB,SAAS,IAAI,UAAU,EAAE,CAwBxC;AAED,wBAAgB,eAAe,IAAI,UAAU,EAAE,CAM9C;AAED,wBAAgB,aAAa,IAAI,UAAU,EAAE,CAc5C;AAED,wBAAgB,eAAe,IAAI,WAAW,EAAE,CAuC/C"}
|
package/dist/fixture.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { PROTOCOL_VERSION } from "./types.js";
|
|
2
|
+
const viewport = { width: 390, height: 844, pixelRatio: 2 };
|
|
3
|
+
function node(partial) {
|
|
4
|
+
return partial;
|
|
5
|
+
}
|
|
6
|
+
export function homeNodes() {
|
|
7
|
+
return [
|
|
8
|
+
node({ id: "root", parentId: null, type: "view", bounds: { x: 0, y: 0, width: 390, height: 844 }, style: { backgroundColor: "#ffffff" } }),
|
|
9
|
+
node({
|
|
10
|
+
id: "banner",
|
|
11
|
+
parentId: "root",
|
|
12
|
+
type: "view",
|
|
13
|
+
componentId: "home.jackpot_banner",
|
|
14
|
+
contentId: "jackpot-1",
|
|
15
|
+
contentVersion: "1",
|
|
16
|
+
bounds: { x: 16, y: 120, width: 358, height: 140 },
|
|
17
|
+
style: { backgroundColor: "#e8eefc", borderRadius: 16 },
|
|
18
|
+
}),
|
|
19
|
+
node({ id: "banner-title", parentId: "banner", type: "text", bounds: { x: 16, y: 24, width: 300, height: 32 }, text: "Jackpot 12 tỷ" }),
|
|
20
|
+
node({
|
|
21
|
+
id: "buy",
|
|
22
|
+
parentId: "root",
|
|
23
|
+
type: "button",
|
|
24
|
+
componentId: "home.buy_ticket",
|
|
25
|
+
bounds: { x: 16, y: 290, width: 180, height: 48 },
|
|
26
|
+
text: "Chọn vé",
|
|
27
|
+
style: { backgroundColor: "#1d4ed8", color: "#ffffff", borderRadius: 12 },
|
|
28
|
+
}),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
export function pickTicketNodes() {
|
|
32
|
+
return [
|
|
33
|
+
node({ id: "root", parentId: null, type: "view", bounds: { x: 0, y: 0, width: 390, height: 844 }, style: { backgroundColor: "#ffffff" } }),
|
|
34
|
+
node({ id: "list", parentId: "root", type: "scroll", bounds: { x: 0, y: 80, width: 390, height: 700 } }),
|
|
35
|
+
node({ id: "row", parentId: "list", type: "button", componentId: "ticket.row", contentId: "mega-01", bounds: { x: 16, y: 8, width: 358, height: 64 }, text: "Mega 6/45" }),
|
|
36
|
+
];
|
|
37
|
+
}
|
|
38
|
+
export function checkoutNodes() {
|
|
39
|
+
return [
|
|
40
|
+
node({ id: "root", parentId: null, type: "view", bounds: { x: 0, y: 0, width: 390, height: 844 }, style: { backgroundColor: "#ffffff" } }),
|
|
41
|
+
node({ id: "title", parentId: "root", type: "text", bounds: { x: 16, y: 80, width: 300, height: 32 }, text: "Thanh toán" }),
|
|
42
|
+
node({ id: "error", parentId: "root", type: "text", bounds: { x: 16, y: 140, width: 340, height: 28 }, text: "Không đủ số dư" }),
|
|
43
|
+
node({
|
|
44
|
+
id: "phone",
|
|
45
|
+
parentId: "root",
|
|
46
|
+
type: "input",
|
|
47
|
+
componentId: "checkout.otp",
|
|
48
|
+
bounds: { x: 16, y: 200, width: 240, height: 44 },
|
|
49
|
+
text: "123456",
|
|
50
|
+
}),
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
export function sampleRecording() {
|
|
54
|
+
return [
|
|
55
|
+
{
|
|
56
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
57
|
+
replayId: "replay-1",
|
|
58
|
+
segmentId: "segment-1",
|
|
59
|
+
chunkId: "chunk-1",
|
|
60
|
+
chunkSequence: 0,
|
|
61
|
+
sessionId: "session-1",
|
|
62
|
+
screenInstanceId: "home-1",
|
|
63
|
+
startOffsetMs: 0,
|
|
64
|
+
endOffsetMs: 1_200,
|
|
65
|
+
viewport,
|
|
66
|
+
records: [
|
|
67
|
+
{ type: "snapshot", seq: 1, offsetMs: 0, nodes: homeNodes() },
|
|
68
|
+
{ type: "interaction", seq: 2, offsetMs: 400, kind: "scroll", targetId: "root", scrollX: 0, scrollY: 80 },
|
|
69
|
+
{ type: "interaction", seq: 3, offsetMs: 900, kind: "tap", targetId: "buy", actionId: "act-buy", x: 40, y: 20 },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
74
|
+
replayId: "replay-1",
|
|
75
|
+
segmentId: "segment-1",
|
|
76
|
+
chunkId: "chunk-3",
|
|
77
|
+
chunkSequence: 2,
|
|
78
|
+
sessionId: "session-1",
|
|
79
|
+
screenInstanceId: "checkout-1",
|
|
80
|
+
startOffsetMs: 12_000,
|
|
81
|
+
endOffsetMs: 13_000,
|
|
82
|
+
viewport,
|
|
83
|
+
records: [
|
|
84
|
+
{ type: "lifecycle", seq: 1, offsetMs: 12_000, kind: "gap" },
|
|
85
|
+
{ type: "snapshot", seq: 2, offsetMs: 12_000, nodes: checkoutNodes() },
|
|
86
|
+
{ type: "patch", seq: 3, offsetMs: 12_400, upserts: [{ id: "error", parentId: "root", type: "text", bounds: { x: 16, y: 140, width: 340, height: 28 }, text: "Đã thanh toán" }], removedIds: [] },
|
|
87
|
+
{ type: "privacy_boundary", seq: 4, offsetMs: 12_600, blocked: true, reason: "otp" },
|
|
88
|
+
{ type: "lifecycle", seq: 5, offsetMs: 12_800, kind: "background" },
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixture.js","sourceRoot":"","sources":["../src/fixture.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { MAX_CHUNK_BYTES, MAX_NODES, MAX_RECORDS, MAX_TEXT, NODE_TYPES, PROTOCOL_VERSION, } from "./types.js";
|
|
2
|
+
export type { InteractionRecord, LifecycleRecord, PatchRecord, PrivacyBoundaryRecord, ReplayBounds, ReplayChunk, ReplayNode, ReplayNodeType, ReplayRecord, ReplayViewport, SnapshotRecord, ViewportRecord, } from "./types.js";
|
|
3
|
+
export { checksumChunk, decodeChunk, encodeChunk, sha256Fallback, stableJson, validateChunk, validateNode } from "./codec.js";
|
|
4
|
+
export { maskNode, maskText, shouldMask } from "./mask.js";
|
|
5
|
+
export { sanitizeChunk, scrubText } from "./sanitize.js";
|
|
6
|
+
export { applyRecord, applyRecords, cloneScene, emptyScene, placeNodes, recordsUntil, sceneNodes, type PlacedNode, type Scene } from "./scene.js";
|
|
7
|
+
export { checkoutNodes, homeNodes, pickTicketNodes, sampleRecording } from "./fixture.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,SAAS,EACT,WAAW,EACX,QAAQ,EACR,UAAU,EACV,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9H,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAClJ,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { MAX_CHUNK_BYTES, MAX_NODES, MAX_RECORDS, MAX_TEXT, NODE_TYPES, PROTOCOL_VERSION, } from "./types.js";
|
|
2
|
+
export { checksumChunk, decodeChunk, encodeChunk, sha256Fallback, stableJson, validateChunk, validateNode } from "./codec.js";
|
|
3
|
+
export { maskNode, maskText, shouldMask } from "./mask.js";
|
|
4
|
+
export { sanitizeChunk, scrubText } from "./sanitize.js";
|
|
5
|
+
export { applyRecord, applyRecords, cloneScene, emptyScene, placeNodes, recordsUntil, sceneNodes } from "./scene.js";
|
|
6
|
+
export { checkoutNodes, homeNodes, pickTicketNodes, sampleRecording } from "./fixture.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,SAAS,EACT,WAAW,EACX,QAAQ,EACR,UAAU,EACV,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAepB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9H,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAA+B,MAAM,YAAY,CAAC;AAClJ,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/mask.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReplayNode, ReplayNodeType } from "./types.js";
|
|
2
|
+
export declare function shouldMask(type: ReplayNodeType, hints?: {
|
|
3
|
+
secure?: boolean;
|
|
4
|
+
analyticsMask?: boolean;
|
|
5
|
+
componentId?: string;
|
|
6
|
+
}): boolean;
|
|
7
|
+
export declare function maskText(text: string | undefined, masked: boolean): string | undefined;
|
|
8
|
+
export declare function maskNode(node: ReplayNode, hints?: {
|
|
9
|
+
secure?: boolean;
|
|
10
|
+
analyticsMask?: boolean;
|
|
11
|
+
}): ReplayNode;
|
|
12
|
+
//# sourceMappingURL=mask.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask.d.ts","sourceRoot":"","sources":["../src/mask.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI7D,wBAAgB,UAAU,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAIzI;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGtF;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,UAAU,CAGhH"}
|
package/dist/mask.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const SENSITIVE = /otp|password|passwd|pin|cvv|token|bank|card|cccd|secret/i;
|
|
2
|
+
export function shouldMask(type, hints = {}) {
|
|
3
|
+
if (hints.secure || hints.analyticsMask)
|
|
4
|
+
return true;
|
|
5
|
+
if (type === "input")
|
|
6
|
+
return true;
|
|
7
|
+
return SENSITIVE.test(hints.componentId ?? "");
|
|
8
|
+
}
|
|
9
|
+
export function maskText(text, masked) {
|
|
10
|
+
if (!text)
|
|
11
|
+
return text;
|
|
12
|
+
return masked ? "••••" : text;
|
|
13
|
+
}
|
|
14
|
+
export function maskNode(node, hints = {}) {
|
|
15
|
+
const masked = Boolean(node.masked) || shouldMask(node.type, { ...hints, componentId: node.componentId });
|
|
16
|
+
return { ...node, masked, text: maskText(node.text, masked) };
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=mask.js.map
|
package/dist/mask.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mask.js","sourceRoot":"","sources":["../src/mask.ts"],"names":[],"mappings":"AAEA,MAAM,SAAS,GAAG,0DAA0D,CAAC;AAE7E,MAAM,UAAU,UAAU,CAAC,IAAoB,EAAE,QAA6E,EAAE;IAC9H,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC;IACrD,IAAI,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAwB,EAAE,MAAe;IAChE,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAgB,EAAE,QAAuD,EAAE;IAClG,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAC1G,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ReplayChunk } from "./types.js";
|
|
2
|
+
/** Thay mọi đoạn giống dữ liệu cá nhân (email, số điện thoại, số thẻ, CCCD) bằng ••••. */
|
|
3
|
+
export declare function scrubText(text: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Lớp phòng thủ thứ hai ở phía máy chủ: áp lại mask cho input/secure và quét dữ liệu cá nhân trong chữ,
|
|
6
|
+
* kể cả khi SDK cũ hoặc bị lỗi đã để lọt. Trả về chunk mới (không sửa đối tượng đầu vào) và cờ `changed`.
|
|
7
|
+
* Checksum cũ không còn đúng nếu `changed`; người gọi phải tính lại bằng `checksumChunk`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function sanitizeChunk(chunk: ReplayChunk): {
|
|
10
|
+
chunk: ReplayChunk;
|
|
11
|
+
changed: boolean;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=sanitize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAA4B,MAAM,YAAY,CAAC;AAYxE,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI9C;AAqBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAI1F"}
|
package/dist/sanitize.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { shouldMask } from "./mask.js";
|
|
2
|
+
const MASKED = "••••";
|
|
3
|
+
// Không dùng lookbehind: package này cũng được bundle vào SDK chạy trên Hermes.
|
|
4
|
+
const PATTERNS = [
|
|
5
|
+
/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g, // email
|
|
6
|
+
/\b\d(?:[ -]?\d){12,18}\b/g, // số thẻ, tài khoản, CCCD (13-19 chữ số, có thể ngăn bằng khoảng trắng hoặc gạch)
|
|
7
|
+
/(?:\+84|\b84|\b0)[\s.-]?\d{2,3}[\s.-]?\d{3}[\s.-]?\d{3,4}\b/g, // số điện thoại Việt Nam
|
|
8
|
+
/\b\d{12}\b/g, // CCCD 12 số liền
|
|
9
|
+
];
|
|
10
|
+
/** Thay mọi đoạn giống dữ liệu cá nhân (email, số điện thoại, số thẻ, CCCD) bằng ••••. */
|
|
11
|
+
export function scrubText(text) {
|
|
12
|
+
let out = text;
|
|
13
|
+
for (const pattern of PATTERNS)
|
|
14
|
+
out = out.replace(pattern, MASKED);
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
function cleanNode(node) {
|
|
18
|
+
const masked = Boolean(node.masked) || shouldMask(node.type, { componentId: node.componentId });
|
|
19
|
+
if (masked) {
|
|
20
|
+
if (node.masked === true && (node.text === undefined || node.text === MASKED))
|
|
21
|
+
return node;
|
|
22
|
+
const { text: _text, ...rest } = node;
|
|
23
|
+
return { ...rest, masked: true, ...(node.text ? { text: MASKED } : {}) };
|
|
24
|
+
}
|
|
25
|
+
if (!node.text)
|
|
26
|
+
return node;
|
|
27
|
+
const text = scrubText(node.text);
|
|
28
|
+
return text === node.text ? node : { ...node, text };
|
|
29
|
+
}
|
|
30
|
+
function cleanRecord(record) {
|
|
31
|
+
if (record.type === "snapshot")
|
|
32
|
+
return { ...record, nodes: record.nodes.map(cleanNode) };
|
|
33
|
+
if (record.type === "patch")
|
|
34
|
+
return { ...record, upserts: record.upserts.map(cleanNode) };
|
|
35
|
+
if (record.type === "privacy_boundary" && record.reason)
|
|
36
|
+
return { ...record, reason: scrubText(record.reason) };
|
|
37
|
+
return record;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Lớp phòng thủ thứ hai ở phía máy chủ: áp lại mask cho input/secure và quét dữ liệu cá nhân trong chữ,
|
|
41
|
+
* kể cả khi SDK cũ hoặc bị lỗi đã để lọt. Trả về chunk mới (không sửa đối tượng đầu vào) và cờ `changed`.
|
|
42
|
+
* Checksum cũ không còn đúng nếu `changed`; người gọi phải tính lại bằng `checksumChunk`.
|
|
43
|
+
*/
|
|
44
|
+
export function sanitizeChunk(chunk) {
|
|
45
|
+
const records = chunk.records.map(cleanRecord);
|
|
46
|
+
const changed = JSON.stringify(records) !== JSON.stringify(chunk.records);
|
|
47
|
+
return { chunk: changed ? { ...chunk, records } : chunk, changed };
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=sanitize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGvC,MAAM,MAAM,GAAG,MAAM,CAAC;AAEtB,gFAAgF;AAChF,MAAM,QAAQ,GAAa;IACzB,iDAAiD,EAAE,QAAQ;IAC3D,2BAA2B,EAAE,kFAAkF;IAC/G,8DAA8D,EAAE,yBAAyB;IACzF,aAAa,EAAE,kBAAkB;CAClC,CAAC;AAEF,0FAA0F;AAC1F,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IAAI,GAAG,GAAG,IAAI,CAAC;IACf,KAAK,MAAM,OAAO,IAAI,QAAQ;QAAE,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACnE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS,CAAC,IAAgB;IACjC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IAChG,IAAI,MAAM,EAAE,CAAC;QACX,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3F,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACtC,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;IAC3E,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAC5B,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC;AACvD,CAAC;AAED,SAAS,WAAW,CAAC,MAAoB;IACvC,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;IACzF,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;IAC1F,IAAI,MAAM,CAAC,IAAI,KAAK,kBAAkB,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IAChH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAkB;IAC9C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1E,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;AACrE,CAAC"}
|
package/dist/scene.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { InteractionRecord, ReplayNode, ReplayRecord } from "./types.js";
|
|
2
|
+
export interface Scene {
|
|
3
|
+
nodes: Map<string, ReplayNode>;
|
|
4
|
+
order: string[];
|
|
5
|
+
blocked: boolean;
|
|
6
|
+
gap: boolean;
|
|
7
|
+
scroll: {
|
|
8
|
+
targetId: string;
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
} | null;
|
|
12
|
+
taps: InteractionRecord[];
|
|
13
|
+
}
|
|
14
|
+
export declare function emptyScene(): Scene;
|
|
15
|
+
/** Áp một record vào cảnh (sửa tại chỗ). Hàm lõi của `applyRecords` và của con trỏ thời gian trong player. */
|
|
16
|
+
export declare function applyRecord(scene: Scene, record: ReplayRecord): Scene;
|
|
17
|
+
export declare function applyRecords(scene: Scene, records: ReplayRecord[]): Scene;
|
|
18
|
+
/** Bản sao độc lập của cảnh. Node là bất biến nên chỉ sao chép các cấu trúc chứa chúng. */
|
|
19
|
+
export declare function cloneScene(scene: Scene): Scene;
|
|
20
|
+
export declare function sceneNodes(scene: Scene): ReplayNode[];
|
|
21
|
+
export interface PlacedNode extends ReplayNode {
|
|
22
|
+
absX: number;
|
|
23
|
+
absY: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function placeNodes(nodes: ReplayNode[]): PlacedNode[];
|
|
26
|
+
export declare function recordsUntil(records: ReplayRecord[], offsetMs: number): ReplayRecord[];
|
|
27
|
+
//# sourceMappingURL=scene.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE9E,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC/B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC1D,IAAI,EAAE,iBAAiB,EAAE,CAAC;CAC3B;AAED,wBAAgB,UAAU,IAAI,KAAK,CAElC;AAOD,8GAA8G;AAC9G,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,GAAG,KAAK,CAiCrE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,KAAK,CAIzE;AAED,2FAA2F;AAC3F,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAS9C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,EAAE,CAKrD;AAED,MAAM,WAAW,UAAW,SAAQ,UAAU;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAa5D;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAEtF"}
|
package/dist/scene.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export function emptyScene() {
|
|
2
|
+
return { nodes: new Map(), order: [], blocked: false, gap: false, scroll: null, taps: [] };
|
|
3
|
+
}
|
|
4
|
+
function remember(scene, node) {
|
|
5
|
+
if (!scene.nodes.has(node.id))
|
|
6
|
+
scene.order.push(node.id);
|
|
7
|
+
scene.nodes.set(node.id, node);
|
|
8
|
+
}
|
|
9
|
+
/** Áp một record vào cảnh (sửa tại chỗ). Hàm lõi của `applyRecords` và của con trỏ thời gian trong player. */
|
|
10
|
+
export function applyRecord(scene, record) {
|
|
11
|
+
if (record.type === "lifecycle" && record.kind === "gap") {
|
|
12
|
+
scene.nodes.clear();
|
|
13
|
+
scene.order = [];
|
|
14
|
+
scene.gap = true;
|
|
15
|
+
return scene;
|
|
16
|
+
}
|
|
17
|
+
if (record.type === "privacy_boundary") {
|
|
18
|
+
scene.blocked = record.blocked;
|
|
19
|
+
if (record.blocked) {
|
|
20
|
+
for (const [id, node] of scene.nodes)
|
|
21
|
+
scene.nodes.set(id, { ...node, text: node.type === "input" || node.masked ? "••••" : node.text, masked: node.masked });
|
|
22
|
+
}
|
|
23
|
+
return scene;
|
|
24
|
+
}
|
|
25
|
+
// Đang bị che: chỉ snapshot mới được áp (để thoát khỏi trạng thái che); interaction và patch bị bỏ.
|
|
26
|
+
if (scene.blocked && (record.type === "interaction" || record.type === "patch"))
|
|
27
|
+
return scene;
|
|
28
|
+
if (record.type === "snapshot") {
|
|
29
|
+
scene.nodes.clear();
|
|
30
|
+
scene.order = [];
|
|
31
|
+
scene.gap = false;
|
|
32
|
+
for (const node of record.nodes)
|
|
33
|
+
remember(scene, node);
|
|
34
|
+
}
|
|
35
|
+
else if (record.type === "patch") {
|
|
36
|
+
if (record.removedIds.length > 0) {
|
|
37
|
+
const gone = new Set(record.removedIds);
|
|
38
|
+
for (const id of gone)
|
|
39
|
+
scene.nodes.delete(id);
|
|
40
|
+
scene.order = scene.order.filter((id) => !gone.has(id));
|
|
41
|
+
}
|
|
42
|
+
for (const node of record.upserts)
|
|
43
|
+
remember(scene, node);
|
|
44
|
+
}
|
|
45
|
+
else if (record.type === "interaction") {
|
|
46
|
+
if (record.kind === "scroll")
|
|
47
|
+
scene.scroll = { targetId: record.targetId, x: record.scrollX ?? 0, y: record.scrollY ?? 0 };
|
|
48
|
+
if (record.kind === "tap")
|
|
49
|
+
scene.taps.push(record);
|
|
50
|
+
}
|
|
51
|
+
return scene;
|
|
52
|
+
}
|
|
53
|
+
export function applyRecords(scene, records) {
|
|
54
|
+
const ordered = [...records].sort((left, right) => left.seq - right.seq || left.offsetMs - right.offsetMs);
|
|
55
|
+
for (const record of ordered)
|
|
56
|
+
applyRecord(scene, record);
|
|
57
|
+
return scene;
|
|
58
|
+
}
|
|
59
|
+
/** Bản sao độc lập của cảnh. Node là bất biến nên chỉ sao chép các cấu trúc chứa chúng. */
|
|
60
|
+
export function cloneScene(scene) {
|
|
61
|
+
return {
|
|
62
|
+
nodes: new Map(scene.nodes),
|
|
63
|
+
order: scene.order.slice(),
|
|
64
|
+
blocked: scene.blocked,
|
|
65
|
+
gap: scene.gap,
|
|
66
|
+
scroll: scene.scroll,
|
|
67
|
+
taps: scene.taps.slice(),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function sceneNodes(scene) {
|
|
71
|
+
return scene.order.flatMap((id) => {
|
|
72
|
+
const node = scene.nodes.get(id);
|
|
73
|
+
return node ? [node] : [];
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
export function placeNodes(nodes) {
|
|
77
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
78
|
+
const placed = new Map();
|
|
79
|
+
const visit = (node) => {
|
|
80
|
+
const cached = placed.get(node.id);
|
|
81
|
+
if (cached)
|
|
82
|
+
return cached;
|
|
83
|
+
const parent = node.parentId ? byId.get(node.parentId) : undefined;
|
|
84
|
+
const origin = parent ? visit(parent) : { absX: 0, absY: 0 };
|
|
85
|
+
const next = { ...node, absX: origin.absX + node.bounds.x, absY: origin.absY + node.bounds.y };
|
|
86
|
+
placed.set(node.id, next);
|
|
87
|
+
return next;
|
|
88
|
+
};
|
|
89
|
+
return nodes.map(visit);
|
|
90
|
+
}
|
|
91
|
+
export function recordsUntil(records, offsetMs) {
|
|
92
|
+
return records.filter((record) => record.offsetMs <= offsetMs).sort((left, right) => left.seq - right.seq);
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=scene.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scene.js","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
export declare const PROTOCOL_VERSION = 1;
|
|
2
|
+
export declare const NODE_TYPES: readonly ["view", "text", "button", "input", "image", "scroll", "modal", "placeholder"];
|
|
3
|
+
export type ReplayNodeType = (typeof NODE_TYPES)[number];
|
|
4
|
+
export interface ReplayBounds {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ReplayNode {
|
|
11
|
+
id: string;
|
|
12
|
+
parentId: string | null;
|
|
13
|
+
type: ReplayNodeType;
|
|
14
|
+
bounds: ReplayBounds;
|
|
15
|
+
zIndex?: number;
|
|
16
|
+
clipsChildren?: boolean;
|
|
17
|
+
text?: string;
|
|
18
|
+
assetId?: string;
|
|
19
|
+
state?: {
|
|
20
|
+
selected?: boolean;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
loading?: boolean;
|
|
23
|
+
};
|
|
24
|
+
style?: {
|
|
25
|
+
backgroundColor?: string;
|
|
26
|
+
color?: string;
|
|
27
|
+
fontSize?: number;
|
|
28
|
+
borderRadius?: number;
|
|
29
|
+
};
|
|
30
|
+
componentId?: string;
|
|
31
|
+
contentId?: string;
|
|
32
|
+
contentVersion?: string;
|
|
33
|
+
masked?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface SnapshotRecord {
|
|
36
|
+
type: "snapshot";
|
|
37
|
+
seq: number;
|
|
38
|
+
offsetMs: number;
|
|
39
|
+
nodes: ReplayNode[];
|
|
40
|
+
}
|
|
41
|
+
export interface PatchRecord {
|
|
42
|
+
type: "patch";
|
|
43
|
+
seq: number;
|
|
44
|
+
offsetMs: number;
|
|
45
|
+
upserts: ReplayNode[];
|
|
46
|
+
removedIds: string[];
|
|
47
|
+
}
|
|
48
|
+
export interface InteractionRecord {
|
|
49
|
+
type: "interaction";
|
|
50
|
+
seq: number;
|
|
51
|
+
offsetMs: number;
|
|
52
|
+
kind: "tap" | "scroll";
|
|
53
|
+
targetId: string;
|
|
54
|
+
actionId?: string;
|
|
55
|
+
x?: number;
|
|
56
|
+
y?: number;
|
|
57
|
+
scrollX?: number;
|
|
58
|
+
scrollY?: number;
|
|
59
|
+
}
|
|
60
|
+
export interface LifecycleRecord {
|
|
61
|
+
type: "lifecycle";
|
|
62
|
+
seq: number;
|
|
63
|
+
offsetMs: number;
|
|
64
|
+
kind: "background" | "foreground" | "account_changed" | "gap";
|
|
65
|
+
}
|
|
66
|
+
export interface ViewportRecord {
|
|
67
|
+
type: "viewport";
|
|
68
|
+
seq: number;
|
|
69
|
+
offsetMs: number;
|
|
70
|
+
width: number;
|
|
71
|
+
height: number;
|
|
72
|
+
pixelRatio: number;
|
|
73
|
+
}
|
|
74
|
+
export interface PrivacyBoundaryRecord {
|
|
75
|
+
type: "privacy_boundary";
|
|
76
|
+
seq: number;
|
|
77
|
+
offsetMs: number;
|
|
78
|
+
blocked: boolean;
|
|
79
|
+
reason?: string;
|
|
80
|
+
}
|
|
81
|
+
export type ReplayRecord = SnapshotRecord | PatchRecord | InteractionRecord | LifecycleRecord | ViewportRecord | PrivacyBoundaryRecord;
|
|
82
|
+
export interface ReplayViewport {
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
pixelRatio: number;
|
|
86
|
+
}
|
|
87
|
+
export interface ReplayChunk {
|
|
88
|
+
protocolVersion: number;
|
|
89
|
+
replayId: string;
|
|
90
|
+
segmentId: string;
|
|
91
|
+
chunkId: string;
|
|
92
|
+
chunkSequence: number;
|
|
93
|
+
sessionId: string;
|
|
94
|
+
screenInstanceId?: string;
|
|
95
|
+
startOffsetMs: number;
|
|
96
|
+
endOffsetMs: number;
|
|
97
|
+
viewport: ReplayViewport;
|
|
98
|
+
records: ReplayRecord[];
|
|
99
|
+
checksum?: string;
|
|
100
|
+
}
|
|
101
|
+
export declare const MAX_NODES = 400;
|
|
102
|
+
export declare const MAX_RECORDS = 800;
|
|
103
|
+
export declare const MAX_TEXT = 240;
|
|
104
|
+
export declare const MAX_CHUNK_BYTES: number;
|
|
105
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const PROTOCOL_VERSION = 1;
|
|
2
|
+
export const NODE_TYPES = ["view", "text", "button", "input", "image", "scroll", "modal", "placeholder"];
|
|
3
|
+
export const MAX_NODES = 400;
|
|
4
|
+
export const MAX_RECORDS = 800;
|
|
5
|
+
export const MAX_TEXT = 240;
|
|
6
|
+
export const MAX_CHUNK_BYTES = 256 * 1024;
|
|
7
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAU,CAAC;AAqHlH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,CAAC;AAC7B,MAAM,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAC/B,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAC;AAC5B,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,GAAG,IAAI,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikeci/pos-replay-protocol",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Shared session replay protocol: nodes, records, chunks, checksums.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"registry": "https://registry.npmjs.org/",
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"typescript": "^5.7.2"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc -p tsconfig.build.json"
|
|
27
|
+
}
|
|
6
28
|
}
|