mcard-js 2.1.48 → 2.1.49

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 (37) hide show
  1. package/dist/AbstractSqlEngine-DKka6XjT.d.cts +451 -0
  2. package/dist/AbstractSqlEngine-DKka6XjT.d.ts +451 -0
  3. package/dist/CardCollection-ZQ3G3Q3A.js +10 -0
  4. package/dist/IndexedDBEngine-BWXAB46W.js +12 -0
  5. package/dist/LLMRuntime-PH3MOQ2Y.js +17 -0
  6. package/dist/LambdaRuntime-YH74FHIW.js +19 -0
  7. package/dist/Loader-WZXYG4GE.js +12 -0
  8. package/dist/NetworkRuntime-S4DZCGVN.js +1598 -0
  9. package/dist/OllamaProvider-SPGO5Z5E.js +9 -0
  10. package/dist/chunk-3FFEA2XK.js +149 -0
  11. package/dist/chunk-7AXRV7NS.js +112 -0
  12. package/dist/chunk-HIVVDGE5.js +497 -0
  13. package/dist/chunk-KVZYFZJ5.js +427 -0
  14. package/dist/chunk-NGTY4P6A.js +275 -0
  15. package/dist/chunk-OUW2SUGM.js +368 -0
  16. package/dist/chunk-QKH3N62B.js +2360 -0
  17. package/dist/chunk-QPVEUPMU.js +299 -0
  18. package/dist/chunk-VYDZR4ZD.js +364 -0
  19. package/dist/chunk-XJZOEM5F.js +903 -0
  20. package/dist/chunk-Z7EFXSTO.js +217 -0
  21. package/dist/index.browser.cjs +37 -1
  22. package/dist/index.browser.d.cts +20 -2
  23. package/dist/index.browser.d.ts +20 -2
  24. package/dist/index.browser.js +10 -6
  25. package/dist/index.cjs +618 -146
  26. package/dist/index.d.cts +723 -4
  27. package/dist/index.d.ts +723 -4
  28. package/dist/index.js +527 -89
  29. package/dist/storage/SqliteNodeEngine.cjs +7 -1
  30. package/dist/storage/SqliteNodeEngine.d.cts +1 -1
  31. package/dist/storage/SqliteNodeEngine.d.ts +1 -1
  32. package/dist/storage/SqliteNodeEngine.js +3 -3
  33. package/dist/storage/SqliteWasmEngine.cjs +7 -1
  34. package/dist/storage/SqliteWasmEngine.d.cts +1 -1
  35. package/dist/storage/SqliteWasmEngine.d.ts +1 -1
  36. package/dist/storage/SqliteWasmEngine.js +3 -3
  37. package/package.json +1 -1
@@ -0,0 +1,903 @@
1
+ // src/model/hash/algorithms/LocalSHA256.ts
2
+ async function computeHash(content) {
3
+ let contentStr;
4
+ if (typeof content === "string") {
5
+ contentStr = content;
6
+ } else {
7
+ contentStr = JSON.stringify(content);
8
+ }
9
+ const encoder = new TextEncoder();
10
+ const data = encoder.encode(contentStr);
11
+ const hashBuffer = await crypto.subtle.digest("SHA-256", data);
12
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
13
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
14
+ return hashHex;
15
+ }
16
+
17
+ // src/monads/Reader.ts
18
+ var Reader = class _Reader {
19
+ constructor(run) {
20
+ this.run = run;
21
+ }
22
+ /**
23
+ * Lift a pure value into Reader
24
+ */
25
+ static pure(value) {
26
+ return new _Reader((_) => value);
27
+ }
28
+ /**
29
+ * Get the environment
30
+ */
31
+ static ask() {
32
+ return new _Reader((env) => env);
33
+ }
34
+ /**
35
+ * Monadic bind (flatMap)
36
+ */
37
+ bind(fn) {
38
+ return new _Reader((env) => {
39
+ const value = this.run(env);
40
+ return fn(value).run(env);
41
+ });
42
+ }
43
+ /**
44
+ * Map over the result
45
+ */
46
+ map(fn) {
47
+ return this.bind((value) => _Reader.pure(fn(value)));
48
+ }
49
+ /**
50
+ * Execute the Reader logic with an environment
51
+ */
52
+ evaluate(env) {
53
+ return this.run(env);
54
+ }
55
+ };
56
+
57
+ // src/monads/Writer.ts
58
+ var Writer = class _Writer {
59
+ constructor(run) {
60
+ this.run = run;
61
+ }
62
+ /**
63
+ * Lift a pure value into Writer (empty log)
64
+ */
65
+ static pure(value) {
66
+ return new _Writer(() => [value, []]);
67
+ }
68
+ /**
69
+ * Write to log
70
+ */
71
+ static tell(log) {
72
+ return new _Writer(() => [void 0, log]);
73
+ }
74
+ /**
75
+ * Monadic bind
76
+ */
77
+ bind(fn) {
78
+ return new _Writer(() => {
79
+ const [val1, log1] = this.run();
80
+ const writer2 = fn(val1);
81
+ const [val2, log2] = writer2.evaluate();
82
+ return [val2, [...log1, ...log2]];
83
+ });
84
+ }
85
+ /**
86
+ * Map
87
+ */
88
+ map(fn) {
89
+ return this.bind((val) => _Writer.pure(fn(val)));
90
+ }
91
+ /**
92
+ * Run the writer
93
+ */
94
+ evaluate() {
95
+ return this.run();
96
+ }
97
+ };
98
+
99
+ // src/monads/State.ts
100
+ var State = class _State {
101
+ constructor(run) {
102
+ this.run = run;
103
+ }
104
+ /**
105
+ * Lift pure value
106
+ */
107
+ static pure(value) {
108
+ return new _State((state) => [value, state]);
109
+ }
110
+ /**
111
+ * Get current state
112
+ */
113
+ static get() {
114
+ return new _State((state) => [state, state]);
115
+ }
116
+ /**
117
+ * Set new state
118
+ */
119
+ static put(newState) {
120
+ return new _State((_) => [void 0, newState]);
121
+ }
122
+ /**
123
+ * Monadic bind
124
+ */
125
+ bind(fn) {
126
+ return new _State((state) => {
127
+ const [val, newState] = this.run(state);
128
+ return fn(val).run(newState);
129
+ });
130
+ }
131
+ /**
132
+ * Map
133
+ */
134
+ map(fn) {
135
+ return this.bind((val) => _State.pure(fn(val)));
136
+ }
137
+ /**
138
+ * Execute state transition
139
+ */
140
+ evaluate(initialState) {
141
+ return this.run(initialState);
142
+ }
143
+ };
144
+
145
+ // src/ptr/LensProtocol.ts
146
+ var LensProtocol = class {
147
+ static idCounter = 0;
148
+ /**
149
+ * Create an execute request
150
+ */
151
+ static createExecuteRequest(pcard_hash, target_hash, context) {
152
+ return {
153
+ jsonrpc: "2.0",
154
+ id: ++this.idCounter,
155
+ method: "pcard.execute",
156
+ params: { pcard_hash, target_hash, context }
157
+ };
158
+ }
159
+ /**
160
+ * Create a verify request
161
+ */
162
+ static createVerifyRequest(pcard_hash, target_hash, context) {
163
+ return {
164
+ jsonrpc: "2.0",
165
+ id: ++this.idCounter,
166
+ method: "pcard.verify",
167
+ params: { pcard_hash, target_hash, context }
168
+ };
169
+ }
170
+ /**
171
+ * Create a reveal request
172
+ */
173
+ static createRevealRequest(card_hash, aspect) {
174
+ return {
175
+ jsonrpc: "2.0",
176
+ id: ++this.idCounter,
177
+ method: "lens.reveal",
178
+ params: { card_hash, aspect }
179
+ };
180
+ }
181
+ /**
182
+ * Create a system status request
183
+ */
184
+ static createStatusRequest() {
185
+ return {
186
+ jsonrpc: "2.0",
187
+ id: ++this.idCounter,
188
+ method: "system.status"
189
+ };
190
+ }
191
+ /**
192
+ * Create a system health request
193
+ */
194
+ static createHealthRequest() {
195
+ return {
196
+ jsonrpc: "2.0",
197
+ id: ++this.idCounter,
198
+ method: "system.health"
199
+ };
200
+ }
201
+ /**
202
+ * Create a success response
203
+ */
204
+ static createSuccessResponse(id, result) {
205
+ return { jsonrpc: "2.0", id, result };
206
+ }
207
+ /**
208
+ * Create an error response
209
+ */
210
+ static createErrorResponse(id, code, message, data) {
211
+ return { jsonrpc: "2.0", id, error: { code, message, data } };
212
+ }
213
+ /**
214
+ * Parse a JSON-RPC response
215
+ */
216
+ static parseResponse(response) {
217
+ if (response.error) {
218
+ throw new Error(`JSON-RPC Error ${response.error.code}: ${response.error.message}`);
219
+ }
220
+ return response.result;
221
+ }
222
+ };
223
+ var ErrorCodes = {
224
+ PARSE_ERROR: -32700,
225
+ INVALID_REQUEST: -32600,
226
+ METHOD_NOT_FOUND: -32601,
227
+ INVALID_PARAMS: -32602,
228
+ INTERNAL_ERROR: -32603,
229
+ // Custom PTR errors
230
+ EXECUTION_ERROR: -32e3,
231
+ VERIFICATION_FAILED: -32001,
232
+ TIMEOUT: -32002
233
+ };
234
+
235
+ // src/ptr/common_types.ts
236
+ var VerificationStatus = /* @__PURE__ */ ((VerificationStatus2) => {
237
+ VerificationStatus2["PENDING"] = "pending";
238
+ VerificationStatus2["VERIFIED"] = "verified";
239
+ VerificationStatus2["FAILED"] = "failed";
240
+ VerificationStatus2["SKIPPED"] = "skipped";
241
+ return VerificationStatus2;
242
+ })(VerificationStatus || {});
243
+ var PreconditionViolation = class extends Error {
244
+ pcardHash;
245
+ inputHash;
246
+ detail;
247
+ constructor(pcardHash, inputHash, detail = "") {
248
+ const msg = `PreconditionViolation: PCard ${pcardHash.substring(0, 16)} rejected input ${inputHash.substring(0, 16)}${detail ? ` \u2014 ${detail}` : ""}`;
249
+ super(msg);
250
+ this.name = "PreconditionViolation";
251
+ this.pcardHash = pcardHash;
252
+ this.inputHash = inputHash;
253
+ this.detail = detail;
254
+ }
255
+ };
256
+ var PostconditionViolation = class extends Error {
257
+ pcardHash;
258
+ outputRepr;
259
+ detail;
260
+ constructor(pcardHash, outputRepr, detail = "") {
261
+ const msg = `PostconditionViolation: PCard ${pcardHash.substring(0, 16)} postcondition failed for output ${outputRepr.substring(0, 64)}${detail ? ` \u2014 ${detail}` : ""}`;
262
+ super(msg);
263
+ this.name = "PostconditionViolation";
264
+ this.pcardHash = pcardHash;
265
+ this.outputRepr = outputRepr;
266
+ this.detail = detail;
267
+ }
268
+ };
269
+
270
+ // src/ptr/browser/storage/MCardStore.ts
271
+ import { openDB } from "idb";
272
+
273
+ // src/ptr/browser/constants.ts
274
+ var MCARD_DB_NAME = "mcard-store";
275
+ var MCARD_DB_VERSION = 8;
276
+
277
+ // src/ptr/browser/storage/MCardStore.ts
278
+ var MCardStore = class {
279
+ dbPromise;
280
+ constructor(dbName = MCARD_DB_NAME) {
281
+ this.dbPromise = openDB(dbName, MCARD_DB_VERSION, {
282
+ upgrade(db, oldVersion, newVersion, transaction) {
283
+ const existingStoreNames = Array.from(db.objectStoreNames);
284
+ const rawDb = db;
285
+ if (existingStoreNames.includes("mcards")) rawDb.deleteObjectStore("mcards");
286
+ if (existingStoreNames.includes("handles")) rawDb.deleteObjectStore("handles");
287
+ let cardStore;
288
+ if (!db.objectStoreNames.contains("card")) {
289
+ cardStore = db.createObjectStore("card", { keyPath: "hash" });
290
+ } else {
291
+ cardStore = transaction.objectStore("card");
292
+ }
293
+ if (!cardStore.indexNames.contains("by_g_time")) {
294
+ cardStore.createIndex("by_g_time", "g_time");
295
+ }
296
+ let registryStore;
297
+ if (!db.objectStoreNames.contains("handle_registry")) {
298
+ registryStore = db.createObjectStore("handle_registry", { keyPath: "handle" });
299
+ } else {
300
+ registryStore = transaction.objectStore("handle_registry");
301
+ }
302
+ if (!registryStore.indexNames.contains("by_current_hash")) {
303
+ registryStore.createIndex("by_current_hash", "current_hash");
304
+ }
305
+ if (!registryStore.indexNames.contains("by_updated_at")) {
306
+ registryStore.createIndex("by_updated_at", "updated_at");
307
+ }
308
+ let historyStore;
309
+ if (!db.objectStoreNames.contains("handle_history")) {
310
+ historyStore = db.createObjectStore("handle_history", { keyPath: "id", autoIncrement: true });
311
+ } else {
312
+ historyStore = transaction.objectStore("handle_history");
313
+ }
314
+ if (!historyStore.indexNames.contains("by_handle")) {
315
+ historyStore.createIndex("by_handle", "handle");
316
+ }
317
+ if (!historyStore.indexNames.contains("by_previous_hash")) {
318
+ historyStore.createIndex("by_previous_hash", "previous_hash");
319
+ }
320
+ if (!historyStore.indexNames.contains("by_changed_at")) {
321
+ historyStore.createIndex("by_changed_at", "changed_at");
322
+ }
323
+ if (!db.objectStoreNames.contains("schema_version")) {
324
+ const versionStore = db.createObjectStore("schema_version", { keyPath: "version" });
325
+ versionStore.add({
326
+ version: "3.0.2",
327
+ applied_at: (/* @__PURE__ */ new Date()).toISOString(),
328
+ description: "Monadic Core Schema (Strict Compliance)"
329
+ });
330
+ }
331
+ }
332
+ });
333
+ }
334
+ // ═══════════════════════════════════════════════════════════════
335
+ // CARD OPERATIONS
336
+ // ═══════════════════════════════════════════════════════════════
337
+ async putCard(hash, content) {
338
+ const db = await this.dbPromise;
339
+ const g_time = (/* @__PURE__ */ new Date()).toISOString();
340
+ await db.put("card", {
341
+ hash,
342
+ content,
343
+ g_time
344
+ });
345
+ }
346
+ async getCard(hash) {
347
+ const db = await this.dbPromise;
348
+ return db.get("card", hash);
349
+ }
350
+ // ═══════════════════════════════════════════════════════════════
351
+ // HANDLE OPERATIONS (Transaction-safe)
352
+ // ═══════════════════════════════════════════════════════════════
353
+ async setHandle(handle, newHash) {
354
+ const db = await this.dbPromise;
355
+ const tx = db.transaction(["handle_registry", "handle_history"], "readwrite");
356
+ const registry = tx.objectStore("handle_registry");
357
+ const history = tx.objectStore("handle_history");
358
+ const now = (/* @__PURE__ */ new Date()).toISOString();
359
+ const existing = await registry.get(handle);
360
+ if (existing) {
361
+ await history.add({
362
+ handle,
363
+ previous_hash: existing.current_hash,
364
+ changed_at: now
365
+ });
366
+ await registry.put({
367
+ handle,
368
+ current_hash: newHash,
369
+ created_at: existing.created_at,
370
+ updated_at: now
371
+ });
372
+ } else {
373
+ await registry.put({
374
+ handle,
375
+ current_hash: newHash,
376
+ created_at: now,
377
+ updated_at: now
378
+ });
379
+ }
380
+ await tx.done;
381
+ }
382
+ async resolveHandle(handle) {
383
+ const db = await this.dbPromise;
384
+ const tx = db.transaction(["handle_registry", "card"], "readonly");
385
+ const registry = tx.objectStore("handle_registry");
386
+ const entry = await registry.get(handle);
387
+ if (!entry) return void 0;
388
+ const cardStore = tx.objectStore("card");
389
+ return cardStore.get(entry.current_hash);
390
+ }
391
+ // ═══════════════════════════════════════════════════════════════
392
+ // QUERY HELPERS (using Indices)
393
+ // ═══════════════════════════════════════════════════════════════
394
+ async getHandleHistory(handle) {
395
+ const db = await this.dbPromise;
396
+ return db.getAllFromIndex("handle_history", "by_handle", handle);
397
+ }
398
+ async getHandlesByHash(hash) {
399
+ const db = await this.dbPromise;
400
+ return db.getAllFromIndex("handle_registry", "by_current_hash", hash);
401
+ }
402
+ // ═══════════════════════════════════════════════════════════════
403
+ // UI HELPERS (For Browser Demo - keeping these for compatibility but implementing via new methods where possible)
404
+ // ═══════════════════════════════════════════════════════════════
405
+ async getAllCards() {
406
+ const db = await this.dbPromise;
407
+ return db.getAll("card");
408
+ }
409
+ async getAllHandles() {
410
+ const db = await this.dbPromise;
411
+ return db.getAll("handle_registry");
412
+ }
413
+ async getAllHistory() {
414
+ const db = await this.dbPromise;
415
+ return db.getAll("handle_history");
416
+ }
417
+ };
418
+
419
+ // src/ptr/browser/network/WebSocketClient.ts
420
+ var WebSocketClient = class {
421
+ ws = null;
422
+ url;
423
+ messageHandler = null;
424
+ reconnectInterval = 3e3;
425
+ constructor(url) {
426
+ this.url = url;
427
+ }
428
+ connect() {
429
+ console.log(`[BrowserPTR] Connecting to ${this.url}`);
430
+ this.ws = new WebSocket(this.url);
431
+ this.ws.onopen = () => {
432
+ console.log("[BrowserPTR] WebSocket connected");
433
+ };
434
+ this.ws.onmessage = (event) => {
435
+ try {
436
+ const data = JSON.parse(event.data);
437
+ if (this.messageHandler) {
438
+ this.messageHandler(data);
439
+ }
440
+ } catch (e) {
441
+ console.error("[BrowserPTR] Failed to parse message:", e);
442
+ }
443
+ };
444
+ this.ws.onclose = () => {
445
+ console.log("[BrowserPTR] WebSocket closed. Reconnecting...");
446
+ this.ws = null;
447
+ setTimeout(() => this.connect(), this.reconnectInterval);
448
+ };
449
+ this.ws.onerror = (error) => {
450
+ console.error("[BrowserPTR] WebSocket error:", error);
451
+ };
452
+ }
453
+ setMessageHandler(handler) {
454
+ this.messageHandler = handler;
455
+ }
456
+ send(data) {
457
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
458
+ this.ws.send(JSON.stringify(data));
459
+ } else {
460
+ console.warn("[BrowserPTR] WebSocket not ready. Message dropped:", data);
461
+ }
462
+ }
463
+ };
464
+
465
+ // src/ptr/browser/worker/ServiceWorkerPTR.ts
466
+ var ServiceWorkerPTR = class {
467
+ store;
468
+ ws;
469
+ constructor(serverUrl, wasmUrl, storeName = MCARD_DB_NAME) {
470
+ this.store = new MCardStore(storeName);
471
+ this.ws = new WebSocketClient(serverUrl);
472
+ this.ws.setMessageHandler(this.onMeshMessage.bind(this));
473
+ }
474
+ start() {
475
+ this.ws.connect();
476
+ self.addEventListener("message", (event) => {
477
+ const typedEvent = event;
478
+ if (typedEvent.data) {
479
+ if (typedEvent.data.type === "clm_execute") {
480
+ this.handleLocalRequest(typedEvent);
481
+ } else if (typedEvent.data.type === "EXECUTE_CLM") {
482
+ this.handleDirectExecution(typedEvent);
483
+ }
484
+ }
485
+ });
486
+ console.log("[ServiceWorkerPTR] Started");
487
+ }
488
+ getStore() {
489
+ return this.store;
490
+ }
491
+ async onMeshMessage(msg) {
492
+ console.log("[ServiceWorkerPTR] Received from mesh:", msg);
493
+ if (!msg || typeof msg !== "object" || Array.isArray(msg)) {
494
+ return;
495
+ }
496
+ const meshMessage = msg;
497
+ if (meshMessage.type === "clm_execute") {
498
+ await this.executeCLM(meshMessage.clm_hash || "", meshMessage.input_hash || "", meshMessage.request_id || "");
499
+ } else if (meshMessage.type === "clm_result") {
500
+ const clients = await self.clients.matchAll();
501
+ for (const client of clients) {
502
+ client.postMessage(meshMessage);
503
+ }
504
+ }
505
+ }
506
+ async handleLocalRequest(event) {
507
+ const { clm_hash, input_hash, request_id } = event.data;
508
+ console.log("[ServiceWorkerPTR] Local request:", request_id);
509
+ this.ws.send({
510
+ type: "clm_execute",
511
+ clm_hash,
512
+ input_hash,
513
+ request_id,
514
+ origin: "browser"
515
+ });
516
+ }
517
+ async handleDirectExecution(event) {
518
+ const { code } = event.data;
519
+ const port = event.ports[0];
520
+ console.log("[ServiceWorkerPTR] Direct Execution Request");
521
+ try {
522
+ const input = { content: { count: 0 } };
523
+ const result = await this.executeJavaScript(code || "", input, {});
524
+ if (port) {
525
+ port.postMessage({
526
+ result,
527
+ logs: ["[ServiceWorkerPTR] Executed successfully (Client Mode)"]
528
+ });
529
+ }
530
+ } catch (e) {
531
+ const error = e;
532
+ console.error("[ServiceWorkerPTR] Execution error:", e);
533
+ if (port) {
534
+ port.postMessage({
535
+ logs: [`[ServiceWorkerPTR] Error: ${error.message || String(e)}`]
536
+ });
537
+ }
538
+ }
539
+ }
540
+ async executeCLM(clmHash, inputHash, requestId) {
541
+ console.log(`[ServiceWorkerPTR] Executing CLM ${clmHash} with input ${inputHash}`);
542
+ const input = await this.store.getCard(inputHash);
543
+ try {
544
+ const code = clmHash.includes("return") ? clmHash : "return input.content.count + 1;";
545
+ const result = await this.executeJavaScript(code, input || { content: { count: 0 } }, {});
546
+ const resultHash = `sha256:result_${requestId}`;
547
+ await this.store.putCard(resultHash, this.toStoredContent(result));
548
+ this.ws.send({
549
+ type: "clm_result",
550
+ request_id: requestId,
551
+ output_hash: resultHash,
552
+ success: true
553
+ });
554
+ } catch (e) {
555
+ const error = e;
556
+ console.error("[ServiceWorkerPTR] Execution error:", e);
557
+ this.ws.send({
558
+ type: "clm_result",
559
+ request_id: requestId,
560
+ output_hash: "",
561
+ success: false,
562
+ error: error.message || String(e)
563
+ });
564
+ }
565
+ }
566
+ // --- Execution Logic Ported from SandboxWorker ---
567
+ async executeJavaScript(code, input, context) {
568
+ try {
569
+ const fn = new Function("input", "context", code);
570
+ return fn(input, context || {});
571
+ } catch (e) {
572
+ throw e;
573
+ }
574
+ }
575
+ // Pyodide support placeholder
576
+ // Implementing full Pyodide loading requires handling caching and CDN usage
577
+ // similar to SandboxWorker.ts but adapted for ServiceWorker environment.
578
+ async executePython(code, input, context) {
579
+ throw new Error("Python execution not fully implemented yet in ServiceWorkerPTR");
580
+ }
581
+ toStoredContent(value) {
582
+ if (typeof value === "string" || value instanceof Uint8Array) {
583
+ return value;
584
+ }
585
+ if (value && typeof value === "object") {
586
+ return value;
587
+ }
588
+ return { value };
589
+ }
590
+ };
591
+
592
+ // src/ptr/FaroSidecar.ts
593
+ import {
594
+ initializeFaro,
595
+ getWebInstrumentations
596
+ } from "@grafana/faro-web-sdk";
597
+ import { TracingInstrumentation } from "@grafana/faro-web-tracing";
598
+ var FaroSidecar = class _FaroSidecar {
599
+ static instance = null;
600
+ faro = null;
601
+ constructor() {
602
+ }
603
+ /**
604
+ * Get the singleton instance of FaroSidecar
605
+ */
606
+ static getInstance() {
607
+ if (!_FaroSidecar.instance) {
608
+ _FaroSidecar.instance = new _FaroSidecar();
609
+ }
610
+ return _FaroSidecar.instance;
611
+ }
612
+ /**
613
+ * Initialize the Faro SDK
614
+ *
615
+ * @param config Configuration options
616
+ * @returns The initialized Faro instance or null if not in a browser environment
617
+ */
618
+ initialize(config) {
619
+ if (typeof window === "undefined") {
620
+ console.warn("[FaroSidecar] Not initializing Grafana Faro: Non-browser environment detected.");
621
+ return null;
622
+ }
623
+ if (this.faro) {
624
+ console.warn("[FaroSidecar] Grafana Faro is already initialized.");
625
+ return this.faro;
626
+ }
627
+ const {
628
+ url,
629
+ apiKey,
630
+ appName,
631
+ appVersion,
632
+ enableTracing = true,
633
+ namespace = "ptr_runtime",
634
+ additionalInstrumentations = []
635
+ } = config;
636
+ const instrumentations = [
637
+ ...getWebInstrumentations(),
638
+ ...additionalInstrumentations
639
+ ];
640
+ if (enableTracing) {
641
+ instrumentations.push(new TracingInstrumentation());
642
+ }
643
+ const faroOptions = {
644
+ url,
645
+ apiKey,
646
+ app: {
647
+ name: appName,
648
+ version: appVersion,
649
+ namespace
650
+ },
651
+ instrumentations
652
+ };
653
+ try {
654
+ this.faro = initializeFaro(faroOptions);
655
+ console.log(`[FaroSidecar] Grafana Faro initialized for ${appName}@${appVersion}`);
656
+ this.faro.api.pushLog([`PTR Observability Sidecar started for ${appName}`]);
657
+ } catch (error) {
658
+ console.error("[FaroSidecar] Failed to initialize Grafana Faro:", error);
659
+ }
660
+ return this.faro;
661
+ }
662
+ /**
663
+ * Get the underlying Faro instance
664
+ */
665
+ getFaro() {
666
+ return this.faro;
667
+ }
668
+ /**
669
+ * Manually push an error to Faro
670
+ */
671
+ pushError(error, context) {
672
+ if (this.faro) {
673
+ this.faro.api.pushError(error, { context });
674
+ }
675
+ }
676
+ /**
677
+ * Manually push a log message to Faro
678
+ */
679
+ pushLog(message, context) {
680
+ if (this.faro) {
681
+ this.faro.api.pushLog([message], { context });
682
+ }
683
+ }
684
+ /**
685
+ * Push a custom event
686
+ */
687
+ pushEvent(name, attributes) {
688
+ if (this.faro) {
689
+ this.faro.api.pushEvent(name, attributes);
690
+ }
691
+ }
692
+ };
693
+
694
+ // src/model/validators/BaseValidator.ts
695
+ var ValidationError = class extends Error {
696
+ constructor(message) {
697
+ super(message);
698
+ this.name = "ValidationError";
699
+ }
700
+ };
701
+ var BaseValidator = class {
702
+ };
703
+
704
+ // src/model/validators/TextValidator.ts
705
+ var TextValidator = class _TextValidator extends BaseValidator {
706
+ static TEXT_MIME_TYPES = /* @__PURE__ */ new Set([
707
+ "text/plain",
708
+ "application/json",
709
+ "application/xml",
710
+ "text/xml",
711
+ "image/svg+xml",
712
+ "text/html",
713
+ "text/markdown"
714
+ ]);
715
+ canValidate(mimeType) {
716
+ return _TextValidator.TEXT_MIME_TYPES.has(mimeType);
717
+ }
718
+ validate(content, mimeType) {
719
+ const textContent = this.ensureString(content);
720
+ if (mimeType === "text/plain") {
721
+ this.validatePlainText(textContent);
722
+ } else if (mimeType === "application/json") {
723
+ this.validateJson(textContent);
724
+ } else if (["application/xml", "text/xml", "image/svg+xml"].includes(mimeType)) {
725
+ this.validateXml(textContent);
726
+ }
727
+ }
728
+ ensureString(content) {
729
+ if (typeof content === "string") {
730
+ return content;
731
+ }
732
+ return new TextDecoder().decode(content);
733
+ }
734
+ validatePlainText(content) {
735
+ const trimmed = content.trim();
736
+ if (!trimmed) {
737
+ throw new ValidationError("Invalid content: empty text");
738
+ }
739
+ if (trimmed.length < 3) {
740
+ throw new ValidationError("Invalid content: too short");
741
+ }
742
+ if (!/\s/.test(content)) {
743
+ if (content.split(/\s+/).length === 1 && content.length > 20) {
744
+ throw new ValidationError("Invalid content: likely not plain text");
745
+ }
746
+ }
747
+ }
748
+ validateJson(content) {
749
+ try {
750
+ const lines = content.split("\n");
751
+ if (lines.some((line) => line.trim().startsWith("//"))) {
752
+ throw new ValidationError("Invalid JSON content: contains comments");
753
+ }
754
+ JSON.parse(content);
755
+ } catch (e) {
756
+ if (e instanceof ValidationError) throw e;
757
+ throw new ValidationError("Invalid JSON content");
758
+ }
759
+ }
760
+ validateXml(content) {
761
+ const trimmed = content.trim();
762
+ if (!trimmed.startsWith("<") || !trimmed.endsWith(">")) {
763
+ throw new ValidationError("Invalid XML content");
764
+ }
765
+ }
766
+ };
767
+
768
+ // src/model/validators/BinaryValidator.ts
769
+ var BinaryValidator = class _BinaryValidator extends BaseValidator {
770
+ static BINARY_MIME_TYPES = /* @__PURE__ */ new Set([
771
+ "image/png",
772
+ "image/jpeg",
773
+ "image/gif",
774
+ "image/bmp",
775
+ "application/pdf",
776
+ "application/zip",
777
+ "video/mp4",
778
+ "audio/wav",
779
+ "application/octet-stream"
780
+ ]);
781
+ canValidate(mimeType) {
782
+ return _BinaryValidator.BINARY_MIME_TYPES.has(mimeType) || mimeType.startsWith("image/") || mimeType.startsWith("audio/") || mimeType.startsWith("video/");
783
+ }
784
+ validate(content, mimeType) {
785
+ const contentBytes = this.ensureBytes(content);
786
+ if (mimeType.startsWith("image/")) {
787
+ this.validateImage(contentBytes, mimeType);
788
+ } else if (mimeType === "application/pdf") {
789
+ this.validatePdf(contentBytes);
790
+ } else if (mimeType === "application/zip") {
791
+ this.validateZip(contentBytes);
792
+ }
793
+ }
794
+ ensureBytes(content) {
795
+ if (content instanceof Uint8Array) {
796
+ return content;
797
+ }
798
+ return new TextEncoder().encode(content);
799
+ }
800
+ validateImage(content, mimeType) {
801
+ if (mimeType === "image/png" && content.length <= 8) {
802
+ throw new ValidationError("Invalid PNG content: truncated file");
803
+ } else if (mimeType === "image/jpeg" && content.length <= 3) {
804
+ throw new ValidationError("Invalid JPEG content: truncated file");
805
+ } else if (mimeType === "image/gif" && content.length <= 6) {
806
+ throw new ValidationError("Invalid GIF content: truncated file");
807
+ }
808
+ const signatures = {
809
+ "image/png": "89504e470d0a1a0a",
810
+ // \x89PNG\r\n\x1a\n
811
+ "image/jpeg": "ffd8ff",
812
+ // \xff\xd8\xff
813
+ "image/gif": "47494638"
814
+ // GIF8
815
+ };
816
+ if (signatures[mimeType]) {
817
+ const expectedSig = signatures[mimeType];
818
+ const currentHex = this.toHex(content.slice(0, expectedSig.length / 2));
819
+ if (!currentHex.startsWith(expectedSig) && currentHex !== expectedSig) {
820
+ throw new ValidationError(`Invalid ${mimeType} content: missing proper header`);
821
+ }
822
+ }
823
+ }
824
+ validatePdf(content) {
825
+ if (!this.startsWithAscii(content, "%PDF-")) {
826
+ throw new ValidationError("Invalid PDF content");
827
+ }
828
+ }
829
+ validateZip(content) {
830
+ if (content.length <= 4) {
831
+ throw new ValidationError("Invalid ZIP content");
832
+ }
833
+ }
834
+ // Helpers
835
+ toHex(content) {
836
+ return Array.from(content).map((b) => b.toString(16).padStart(2, "0")).join("");
837
+ }
838
+ startsWithAscii(content, str) {
839
+ if (content.length < str.length) return false;
840
+ for (let i = 0; i < str.length; i++) {
841
+ if (content[i] !== str.charCodeAt(i)) return false;
842
+ }
843
+ return true;
844
+ }
845
+ };
846
+
847
+ // src/model/validators/ValidationRegistry.ts
848
+ var ValidationRegistry = class {
849
+ validators;
850
+ constructor() {
851
+ this.validators = [
852
+ new TextValidator(),
853
+ new BinaryValidator()
854
+ ];
855
+ }
856
+ /**
857
+ * Validate content using appropriate validator.
858
+ *
859
+ * @param content The content to validate
860
+ * @param mimeType The detected MIME type
861
+ * @throws ValidationError If content is invalid
862
+ */
863
+ validate(content, mimeType) {
864
+ if (!content || content instanceof Uint8Array && content.length === 0) {
865
+ throw new ValidationError("Empty content");
866
+ }
867
+ if (typeof content === "string" && !content) {
868
+ throw new ValidationError("Empty content");
869
+ }
870
+ for (const validator of this.validators) {
871
+ if (validator.canValidate(mimeType)) {
872
+ validator.validate(content, mimeType);
873
+ return;
874
+ }
875
+ }
876
+ this.basicValidation(content);
877
+ }
878
+ basicValidation(content) {
879
+ if (content instanceof Uint8Array) {
880
+ if (content.length === 0) {
881
+ throw new ValidationError("Invalid content: empty byte array");
882
+ }
883
+ }
884
+ }
885
+ };
886
+ var validationRegistry = new ValidationRegistry();
887
+
888
+ export {
889
+ computeHash,
890
+ Reader,
891
+ Writer,
892
+ State,
893
+ LensProtocol,
894
+ ErrorCodes,
895
+ VerificationStatus,
896
+ PreconditionViolation,
897
+ PostconditionViolation,
898
+ MCardStore,
899
+ ServiceWorkerPTR,
900
+ FaroSidecar,
901
+ ValidationRegistry,
902
+ validationRegistry
903
+ };