persian-data-grid 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/OFL.txt +93 -0
- package/README.md +179 -22
- package/dist/ERPTableGroupRow-E5Q6FYDS.js +125 -0
- package/dist/ERPTableGroupRow-E5Q6FYDS.js.map +1 -0
- package/dist/ERPTableGroupRow-F2IPDYL5.cjs +131 -0
- package/dist/ERPTableGroupRow-F2IPDYL5.cjs.map +1 -0
- package/dist/GridPlugin-Bewn0X51.d.ts +57 -0
- package/dist/GridPlugin-DewWufGZ.d.cts +57 -0
- package/dist/GridPresenceService-GEH6535Q.js +3 -0
- package/dist/GridPresenceService-GEH6535Q.js.map +1 -0
- package/dist/GridPresenceService-RDN5FXHQ.cjs +12 -0
- package/dist/GridPresenceService-RDN5FXHQ.cjs.map +1 -0
- package/dist/GridSession-CeIfVFck.d.ts +2625 -0
- package/dist/GridSession-CmQn2RnL.d.cts +2625 -0
- package/dist/GridSyncService-3JQLEY65.cjs +12 -0
- package/dist/GridSyncService-3JQLEY65.cjs.map +1 -0
- package/dist/GridSyncService-GECXGEKL.js +3 -0
- package/dist/GridSyncService-GECXGEKL.js.map +1 -0
- package/dist/PdfRenderer-B9FJaCo_.d.cts +22 -0
- package/dist/PdfRenderer-bN7ca_Aj.d.ts +22 -0
- package/dist/RemoteApi-CCQxiSf1.d.cts +28 -0
- package/dist/RemoteApi-CCQxiSf1.d.ts +28 -0
- package/dist/SelectImpl-NM4O4IGW.js +447 -0
- package/dist/SelectImpl-NM4O4IGW.js.map +1 -0
- package/dist/SelectImpl-W2EI4T7O.cjs +453 -0
- package/dist/SelectImpl-W2EI4T7O.cjs.map +1 -0
- package/dist/UITableController-C71LXBiX.d.ts +678 -0
- package/dist/UITableController-CIwnHIw8.d.cts +678 -0
- package/dist/VazirmatnPdfRenderer-CpCqA-Wh.d.cts +96 -0
- package/dist/VazirmatnPdfRenderer-D46smncn.d.ts +96 -0
- package/dist/adapters/arian-erp.cjs +89 -0
- package/dist/adapters/arian-erp.cjs.map +1 -0
- package/dist/adapters/arian-erp.d.cts +62 -0
- package/dist/adapters/arian-erp.d.ts +62 -0
- package/dist/adapters/arian-erp.js +79 -0
- package/dist/adapters/arian-erp.js.map +1 -0
- package/dist/appendAtEnd-RHIQRG2W.cjs +35 -0
- package/dist/appendAtEnd-RHIQRG2W.cjs.map +1 -0
- package/dist/appendAtEnd-TJEABLGD.js +33 -0
- package/dist/appendAtEnd-TJEABLGD.js.map +1 -0
- package/dist/applyImportedRows-C2fWYoPy.d.cts +135 -0
- package/dist/applyImportedRows-Cqh_N_0k.d.ts +135 -0
- package/dist/applyRowVisibilityHandler-Q64ZFC7A.cjs +86 -0
- package/dist/applyRowVisibilityHandler-Q64ZFC7A.cjs.map +1 -0
- package/dist/applyRowVisibilityHandler-ZLZXQEGY.js +84 -0
- package/dist/applyRowVisibilityHandler-ZLZXQEGY.js.map +1 -0
- package/dist/broadcastChannelTransport-FHUMV76O.cjs +12 -0
- package/dist/broadcastChannelTransport-FHUMV76O.cjs.map +1 -0
- package/dist/broadcastChannelTransport-MIH53VNZ.js +3 -0
- package/dist/broadcastChannelTransport-MIH53VNZ.js.map +1 -0
- package/dist/callbackRemoteApi-BYLjmSI6.d.ts +51 -0
- package/dist/callbackRemoteApi-Cv26MmSD.d.cts +51 -0
- package/dist/cellRenderContext-BaNh4qn_.d.ts +42 -0
- package/dist/cellRenderContext-DvngkptV.d.cts +42 -0
- package/dist/chunk-27ALJSZP.js +12187 -0
- package/dist/chunk-27ALJSZP.js.map +1 -0
- package/dist/chunk-3HP3HQCW.cjs +688 -0
- package/dist/chunk-3HP3HQCW.cjs.map +1 -0
- package/dist/chunk-3Y3KKGEC.js +3 -0
- package/dist/chunk-3Y3KKGEC.js.map +1 -0
- package/dist/chunk-52LFOPXD.cjs +588 -0
- package/dist/chunk-52LFOPXD.cjs.map +1 -0
- package/dist/chunk-5ALMNLUR.cjs +1408 -0
- package/dist/chunk-5ALMNLUR.cjs.map +1 -0
- package/dist/chunk-5HKVMPBD.js +937 -0
- package/dist/chunk-5HKVMPBD.js.map +1 -0
- package/dist/chunk-72IVAOTK.cjs +38 -0
- package/dist/chunk-72IVAOTK.cjs.map +1 -0
- package/dist/chunk-77UXAJII.js +112 -0
- package/dist/chunk-77UXAJII.js.map +1 -0
- package/dist/chunk-7GWV5HGO.js +36 -0
- package/dist/chunk-7GWV5HGO.js.map +1 -0
- package/dist/chunk-7T6AWRPU.js +581 -0
- package/dist/chunk-7T6AWRPU.js.map +1 -0
- package/dist/chunk-AU3RDJYQ.js +243 -0
- package/dist/chunk-AU3RDJYQ.js.map +1 -0
- package/dist/chunk-CILNIWYW.cjs +100 -0
- package/dist/chunk-CILNIWYW.cjs.map +1 -0
- package/dist/chunk-CMQ4VLCW.cjs +840 -0
- package/dist/chunk-CMQ4VLCW.cjs.map +1 -0
- package/dist/chunk-DFFP7SJ6.cjs +257 -0
- package/dist/chunk-DFFP7SJ6.cjs.map +1 -0
- package/dist/chunk-E2J533UH.cjs +53 -0
- package/dist/chunk-E2J533UH.cjs.map +1 -0
- package/dist/chunk-EBV6HGZB.cjs +33 -0
- package/dist/chunk-EBV6HGZB.cjs.map +1 -0
- package/dist/chunk-F4PYOYHR.js +112 -0
- package/dist/chunk-F4PYOYHR.js.map +1 -0
- package/dist/chunk-F6EMC75A.cjs +34 -0
- package/dist/chunk-F6EMC75A.cjs.map +1 -0
- package/dist/chunk-GKE33FOJ.js +32 -0
- package/dist/chunk-GKE33FOJ.js.map +1 -0
- package/dist/chunk-GQEDLUMB.js +168 -0
- package/dist/chunk-GQEDLUMB.js.map +1 -0
- package/dist/chunk-HLOHWFOA.js +645 -0
- package/dist/chunk-HLOHWFOA.js.map +1 -0
- package/dist/chunk-IMPCRWYP.cjs +251 -0
- package/dist/chunk-IMPCRWYP.cjs.map +1 -0
- package/dist/chunk-IPPIXOVQ.js +317 -0
- package/dist/chunk-IPPIXOVQ.js.map +1 -0
- package/dist/chunk-J4XJ4UBC.js +1404 -0
- package/dist/chunk-J4XJ4UBC.js.map +1 -0
- package/dist/chunk-J7CPPFXT.cjs +89 -0
- package/dist/chunk-J7CPPFXT.cjs.map +1 -0
- package/dist/chunk-JOICD47Q.cjs +41 -0
- package/dist/chunk-JOICD47Q.cjs.map +1 -0
- package/dist/chunk-KCNTKYUY.js +206 -0
- package/dist/chunk-KCNTKYUY.js.map +1 -0
- package/dist/chunk-KHMG6EI2.js +13 -0
- package/dist/chunk-KHMG6EI2.js.map +1 -0
- package/dist/chunk-KMRURD5J.cjs +15 -0
- package/dist/chunk-KMRURD5J.cjs.map +1 -0
- package/dist/chunk-KRJG3KMP.cjs +174 -0
- package/dist/chunk-KRJG3KMP.cjs.map +1 -0
- package/dist/chunk-LY27YAXE.cjs +208 -0
- package/dist/chunk-LY27YAXE.cjs.map +1 -0
- package/dist/chunk-MT3KLB2Q.cjs +944 -0
- package/dist/chunk-MT3KLB2Q.cjs.map +1 -0
- package/dist/chunk-MUQQKPWR.js +84 -0
- package/dist/chunk-MUQQKPWR.js.map +1 -0
- package/dist/chunk-N7SJTINL.cjs +4 -0
- package/dist/chunk-N7SJTINL.cjs.map +1 -0
- package/dist/chunk-NB5GCGHL.js +833 -0
- package/dist/chunk-NB5GCGHL.js.map +1 -0
- package/dist/chunk-NQUVAJQA.js +298 -0
- package/dist/chunk-NQUVAJQA.js.map +1 -0
- package/dist/chunk-NTV2UUAJ.cjs +149 -0
- package/dist/chunk-NTV2UUAJ.cjs.map +1 -0
- package/dist/chunk-PJQWHF6T.js +31 -0
- package/dist/chunk-PJQWHF6T.js.map +1 -0
- package/dist/chunk-PQY54EL5.js +248 -0
- package/dist/chunk-PQY54EL5.js.map +1 -0
- package/dist/chunk-Q7TBBUTX.cjs +110 -0
- package/dist/chunk-Q7TBBUTX.cjs.map +1 -0
- package/dist/chunk-QZN7R2WP.cjs +114 -0
- package/dist/chunk-QZN7R2WP.cjs.map +1 -0
- package/dist/chunk-RKVSJU46.js +35 -0
- package/dist/chunk-RKVSJU46.js.map +1 -0
- package/dist/chunk-SVO62ZV2.js +50 -0
- package/dist/chunk-SVO62ZV2.js.map +1 -0
- package/dist/chunk-SX4VQXAA.cjs +114 -0
- package/dist/chunk-SX4VQXAA.cjs.map +1 -0
- package/dist/chunk-SZ7BLAY3.js +92 -0
- package/dist/chunk-SZ7BLAY3.js.map +1 -0
- package/dist/chunk-TN4MG6FY.js +112 -0
- package/dist/chunk-TN4MG6FY.js.map +1 -0
- package/dist/chunk-UC7PHDM6.cjs +331 -0
- package/dist/chunk-UC7PHDM6.cjs.map +1 -0
- package/dist/chunk-UXVLYUUW.js +108 -0
- package/dist/chunk-UXVLYUUW.js.map +1 -0
- package/dist/chunk-VBAZ77Q4.js +932 -0
- package/dist/chunk-VBAZ77Q4.js.map +1 -0
- package/dist/chunk-VSAFQTW5.cjs +319 -0
- package/dist/chunk-VSAFQTW5.cjs.map +1 -0
- package/dist/chunk-VYJQ2HTA.cjs +936 -0
- package/dist/chunk-VYJQ2HTA.cjs.map +1 -0
- package/dist/chunk-W5256BJ4.js +56 -0
- package/dist/chunk-W5256BJ4.js.map +1 -0
- package/dist/chunk-WTHTVKVI.cjs +12299 -0
- package/dist/chunk-WTHTVKVI.cjs.map +1 -0
- package/dist/chunk-WUMOSOEK.cjs +62 -0
- package/dist/chunk-WUMOSOEK.cjs.map +1 -0
- package/dist/chunk-XLRE2J25.js +140 -0
- package/dist/chunk-XLRE2J25.js.map +1 -0
- package/dist/chunk-Z4QPZ3Z3.cjs +114 -0
- package/dist/chunk-Z4QPZ3Z3.cjs.map +1 -0
- package/dist/createEngineGridQuery-BBkud5oE.d.ts +939 -0
- package/dist/createEngineGridQuery-D-fgO_jg.d.cts +939 -0
- package/dist/date-picker-jalali.cjs +263 -0
- package/dist/date-picker-jalali.cjs.map +1 -0
- package/dist/date-picker-jalali.d.cts +62 -0
- package/dist/date-picker-jalali.d.ts +62 -0
- package/dist/date-picker-jalali.js +256 -0
- package/dist/date-picker-jalali.js.map +1 -0
- package/dist/finance.cjs +205 -0
- package/dist/finance.cjs.map +1 -0
- package/dist/finance.d.cts +90 -0
- package/dist/finance.d.ts +90 -0
- package/dist/finance.js +157 -0
- package/dist/finance.js.map +1 -0
- package/dist/foldedColumn-IHDT4ARZ.cjs +66 -0
- package/dist/foldedColumn-IHDT4ARZ.cjs.map +1 -0
- package/dist/foldedColumn-TFURUKFG.js +64 -0
- package/dist/foldedColumn-TFURUKFG.js.map +1 -0
- package/dist/headless.cjs +729 -0
- package/dist/headless.cjs.map +1 -0
- package/dist/headless.d.cts +508 -0
- package/dist/headless.d.ts +508 -0
- package/dist/headless.js +226 -0
- package/dist/headless.js.map +1 -0
- package/dist/index-DN8M8Jkq.d.cts +14 -0
- package/dist/index-DmzL-F_o.d.ts +14 -0
- package/dist/index.cjs +8060 -11409
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +457 -2305
- package/dist/index.d.ts +457 -2305
- package/dist/index.js +7302 -11084
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.cjs +12 -0
- package/dist/locales/ar.cjs.map +1 -0
- package/dist/locales/ar.d.cts +6 -0
- package/dist/locales/ar.d.ts +6 -0
- package/dist/locales/ar.js +3 -0
- package/dist/locales/ar.js.map +1 -0
- package/dist/locales/en.cjs +12 -0
- package/dist/locales/en.cjs.map +1 -0
- package/dist/locales/en.d.cts +6 -0
- package/dist/locales/en.d.ts +6 -0
- package/dist/locales/en.js +3 -0
- package/dist/locales/en.js.map +1 -0
- package/dist/locales/fa.cjs +12 -0
- package/dist/locales/fa.cjs.map +1 -0
- package/dist/locales/fa.d.cts +6 -0
- package/dist/locales/fa.d.ts +6 -0
- package/dist/locales/fa.js +3 -0
- package/dist/locales/fa.js.map +1 -0
- package/dist/locales/index.cjs +51 -0
- package/dist/locales/index.cjs.map +1 -0
- package/dist/locales/index.d.cts +5 -0
- package/dist/locales/index.d.ts +5 -0
- package/dist/locales/index.js +6 -0
- package/dist/locales/index.js.map +1 -0
- package/dist/memoryRecords-AWDKUJ2F.cjs +50 -0
- package/dist/memoryRecords-AWDKUJ2F.cjs.map +1 -0
- package/dist/memoryRecords-OJTGXLRH.js +47 -0
- package/dist/memoryRecords-OJTGXLRH.js.map +1 -0
- package/dist/pagedFooterTotals-DXCGDO6F.cjs +27 -0
- package/dist/pagedFooterTotals-DXCGDO6F.cjs.map +1 -0
- package/dist/pagedFooterTotals-ORWKUNE7.js +25 -0
- package/dist/pagedFooterTotals-ORWKUNE7.js.map +1 -0
- package/dist/pagedKit-MFGAJFSK.cjs +134 -0
- package/dist/pagedKit-MFGAJFSK.cjs.map +1 -0
- package/dist/pagedKit-WYWY4LRV.js +127 -0
- package/dist/pagedKit-WYWY4LRV.js.map +1 -0
- package/dist/pagedSearch-HCPJW7VM.js +38 -0
- package/dist/pagedSearch-HCPJW7VM.js.map +1 -0
- package/dist/pagedSearch-U3WCG4GN.cjs +42 -0
- package/dist/pagedSearch-U3WCG4GN.cjs.map +1 -0
- package/dist/plugins/csv.cjs +124 -0
- package/dist/plugins/csv.cjs.map +1 -0
- package/dist/plugins/csv.d.cts +44 -0
- package/dist/plugins/csv.d.ts +44 -0
- package/dist/plugins/csv.js +120 -0
- package/dist/plugins/csv.js.map +1 -0
- package/dist/plugins/excel.cjs +52 -0
- package/dist/plugins/excel.cjs.map +1 -0
- package/dist/plugins/excel.d.cts +14 -0
- package/dist/plugins/excel.d.ts +14 -0
- package/dist/plugins/excel.js +7 -0
- package/dist/plugins/excel.js.map +1 -0
- package/dist/plugins/pdf/fonts/vazirmatn.cjs +50 -0
- package/dist/plugins/pdf/fonts/vazirmatn.cjs.map +1 -0
- package/dist/plugins/pdf/fonts/vazirmatn.d.cts +24 -0
- package/dist/plugins/pdf/fonts/vazirmatn.d.ts +24 -0
- package/dist/plugins/pdf/fonts/vazirmatn.js +39 -0
- package/dist/plugins/pdf/fonts/vazirmatn.js.map +1 -0
- package/dist/plugins/pdf.cjs +24 -0
- package/dist/plugins/pdf.cjs.map +1 -0
- package/dist/plugins/pdf.d.cts +21 -0
- package/dist/plugins/pdf.d.ts +21 -0
- package/dist/plugins/pdf.js +7 -0
- package/dist/plugins/pdf.js.map +1 -0
- package/dist/presence.cjs +56 -0
- package/dist/presence.cjs.map +1 -0
- package/dist/presence.d.cts +17 -0
- package/dist/presence.d.ts +17 -0
- package/dist/presence.js +54 -0
- package/dist/presence.js.map +1 -0
- package/dist/rebuildRowVisibility-66EAZ356.cjs +21 -0
- package/dist/rebuildRowVisibility-66EAZ356.cjs.map +1 -0
- package/dist/rebuildRowVisibility-6TYM5BP2.js +19 -0
- package/dist/rebuildRowVisibility-6TYM5BP2.js.map +1 -0
- package/dist/styles.css +1440 -0
- package/dist/sync.cjs +148 -0
- package/dist/sync.cjs.map +1 -0
- package/dist/sync.d.cts +17 -0
- package/dist/sync.d.ts +17 -0
- package/dist/sync.js +146 -0
- package/dist/sync.js.map +1 -0
- package/dist/types-D__47BKv.d.cts +23 -0
- package/dist/types-D__47BKv.d.ts +23 -0
- package/package.json +185 -29
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// application/sync/resolveCellConflicts.ts
|
|
2
|
+
function resolveConflictChoice(conflict, policy) {
|
|
3
|
+
if (policy === "manual") return "unresolved";
|
|
4
|
+
if (policy === "serverWins") return "remote";
|
|
5
|
+
if (conflict.remote.version !== conflict.local.version) {
|
|
6
|
+
return conflict.remote.version > conflict.local.version ? "remote" : "local";
|
|
7
|
+
}
|
|
8
|
+
if (conflict.remote.occurredAt !== conflict.local.occurredAt) {
|
|
9
|
+
return conflict.remote.occurredAt > conflict.local.occurredAt ? "remote" : "local";
|
|
10
|
+
}
|
|
11
|
+
return "remote";
|
|
12
|
+
}
|
|
13
|
+
function cellKeyFromPayload(payload) {
|
|
14
|
+
if (!payload || typeof payload !== "object") return null;
|
|
15
|
+
const p = payload;
|
|
16
|
+
const columnId = p.columnId;
|
|
17
|
+
if (typeof columnId !== "string" || !columnId) return null;
|
|
18
|
+
const rowRaw = p.rowId;
|
|
19
|
+
const rowId = typeof rowRaw === "number" ? rowRaw : typeof rowRaw === "string" ? Number(rowRaw) : NaN;
|
|
20
|
+
if (!Number.isFinite(rowId)) return null;
|
|
21
|
+
return { rowId, columnId };
|
|
22
|
+
}
|
|
23
|
+
function cellKeyId(rowId, columnId) {
|
|
24
|
+
return `${rowId}:${columnId}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// application/sync/GridSyncService.ts
|
|
28
|
+
function isCellChanged(event) {
|
|
29
|
+
return event.type === "CELL_CHANGED";
|
|
30
|
+
}
|
|
31
|
+
function toSide(event) {
|
|
32
|
+
const payload = event.payload;
|
|
33
|
+
return {
|
|
34
|
+
eventId: event.eventId,
|
|
35
|
+
value: payload?.newValue,
|
|
36
|
+
occurredAt: event.occurredAt,
|
|
37
|
+
version: event.version
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
var GridSyncService = class {
|
|
41
|
+
constructor(options) {
|
|
42
|
+
this.options = options;
|
|
43
|
+
this.openConflicts = [];
|
|
44
|
+
this.conflictListeners = /* @__PURE__ */ new Set();
|
|
45
|
+
/** Remote events waiting on manual resolution (by conflict id). */
|
|
46
|
+
this.deferredRemote = /* @__PURE__ */ new Map();
|
|
47
|
+
this.disposed = false;
|
|
48
|
+
this.policy = options.policy ?? "lastWriteWins";
|
|
49
|
+
this.cursor = options.initialCursor ?? 0;
|
|
50
|
+
}
|
|
51
|
+
getPolicy() {
|
|
52
|
+
return this.policy;
|
|
53
|
+
}
|
|
54
|
+
setPolicy(policy) {
|
|
55
|
+
this.policy = policy;
|
|
56
|
+
}
|
|
57
|
+
getOpenConflicts() {
|
|
58
|
+
return this.openConflicts;
|
|
59
|
+
}
|
|
60
|
+
subscribeConflicts(listener) {
|
|
61
|
+
if (this.disposed) return () => void 0;
|
|
62
|
+
this.conflictListeners.add(listener);
|
|
63
|
+
listener(this.openConflicts);
|
|
64
|
+
return () => this.conflictListeners.delete(listener);
|
|
65
|
+
}
|
|
66
|
+
/** Drop listeners and deferred conflicts; later sync() calls are no-ops. */
|
|
67
|
+
dispose() {
|
|
68
|
+
this.disposed = true;
|
|
69
|
+
this.conflictListeners.clear();
|
|
70
|
+
this.deferredRemote.clear();
|
|
71
|
+
this.openConflicts = [];
|
|
72
|
+
}
|
|
73
|
+
emptyResult() {
|
|
74
|
+
return { pushed: 0, pulled: 0, applied: 0, conflicts: [] };
|
|
75
|
+
}
|
|
76
|
+
async sync() {
|
|
77
|
+
if (this.disposed) return this.emptyResult();
|
|
78
|
+
const pending = this.options.offlineStatus.getPendingChanges();
|
|
79
|
+
const pushable = pending.map((p) => p.event).filter(
|
|
80
|
+
(e) => Boolean(e) && e.tableId === this.options.tableId
|
|
81
|
+
);
|
|
82
|
+
const { acceptedIds } = await this.options.transport.push(pushable);
|
|
83
|
+
if (this.disposed) return this.emptyResult();
|
|
84
|
+
if (acceptedIds.length > 0) {
|
|
85
|
+
this.options.offlineStatus.markSynced([...acceptedIds]);
|
|
86
|
+
}
|
|
87
|
+
const localByCell = /* @__PURE__ */ new Map();
|
|
88
|
+
for (const event of pushable) {
|
|
89
|
+
if (!isCellChanged(event)) continue;
|
|
90
|
+
const key = cellKeyFromPayload(event.payload);
|
|
91
|
+
if (!key) continue;
|
|
92
|
+
localByCell.set(cellKeyId(key.rowId, key.columnId), event);
|
|
93
|
+
}
|
|
94
|
+
for (const event of this.options.offlineStatus.getPendingChanges().map((p) => p.event).filter((e) => Boolean(e))) {
|
|
95
|
+
if (!isCellChanged(event) || event.tableId !== this.options.tableId) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const key = cellKeyFromPayload(event.payload);
|
|
99
|
+
if (!key) continue;
|
|
100
|
+
localByCell.set(cellKeyId(key.rowId, key.columnId), event);
|
|
101
|
+
}
|
|
102
|
+
const pulled = await this.options.transport.pull(this.cursor);
|
|
103
|
+
if (this.disposed) return this.emptyResult();
|
|
104
|
+
this.cursor = pulled.cursor;
|
|
105
|
+
let applied = 0;
|
|
106
|
+
const conflicts = [];
|
|
107
|
+
for (const remote of pulled.events) {
|
|
108
|
+
if (this.disposed) return this.emptyResult();
|
|
109
|
+
if (remote.tableId !== this.options.tableId) continue;
|
|
110
|
+
if (!isCellChanged(remote)) {
|
|
111
|
+
await this.ingestRemote(remote);
|
|
112
|
+
applied += 1;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const key = cellKeyFromPayload(remote.payload);
|
|
116
|
+
if (!key) continue;
|
|
117
|
+
const id = cellKeyId(key.rowId, key.columnId);
|
|
118
|
+
const local = localByCell.get(id);
|
|
119
|
+
if (local && toSide(local).value !== toSide(remote).value) {
|
|
120
|
+
const conflict = {
|
|
121
|
+
id: `conflict:${id}:${remote.eventId}`,
|
|
122
|
+
key,
|
|
123
|
+
local: toSide(local),
|
|
124
|
+
remote: toSide(remote)
|
|
125
|
+
};
|
|
126
|
+
const choice = resolveConflictChoice(conflict, this.policy);
|
|
127
|
+
if (choice === "unresolved") {
|
|
128
|
+
conflicts.push(conflict);
|
|
129
|
+
this.deferredRemote.set(conflict.id, remote);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (choice === "remote") {
|
|
133
|
+
await this.applyRemoteCell(remote, key.rowId, key.columnId);
|
|
134
|
+
this.options.offlineStatus.markSynced([local.eventId]);
|
|
135
|
+
applied += 1;
|
|
136
|
+
} else {
|
|
137
|
+
await this.ingestRemote(remote);
|
|
138
|
+
}
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
await this.applyRemoteCell(remote, key.rowId, key.columnId);
|
|
142
|
+
applied += 1;
|
|
143
|
+
}
|
|
144
|
+
this.openConflicts = [
|
|
145
|
+
...this.openConflicts.filter((c) => this.deferredRemote.has(c.id)),
|
|
146
|
+
...conflicts
|
|
147
|
+
];
|
|
148
|
+
this.emitConflicts();
|
|
149
|
+
return {
|
|
150
|
+
pushed: acceptedIds.length,
|
|
151
|
+
pulled: pulled.events.length,
|
|
152
|
+
applied,
|
|
153
|
+
conflicts: this.openConflicts
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
async resolveConflict(conflictId, choice) {
|
|
157
|
+
if (this.disposed) return;
|
|
158
|
+
const conflict = this.openConflicts.find((c) => c.id === conflictId);
|
|
159
|
+
const remote = this.deferredRemote.get(conflictId);
|
|
160
|
+
if (!conflict || !remote) return;
|
|
161
|
+
if (choice === "remote") {
|
|
162
|
+
await this.applyRemoteCell(
|
|
163
|
+
remote,
|
|
164
|
+
conflict.key.rowId,
|
|
165
|
+
conflict.key.columnId
|
|
166
|
+
);
|
|
167
|
+
this.options.offlineStatus.markSynced([conflict.local.eventId]);
|
|
168
|
+
} else {
|
|
169
|
+
await this.ingestRemote(remote);
|
|
170
|
+
}
|
|
171
|
+
this.deferredRemote.delete(conflictId);
|
|
172
|
+
this.openConflicts = this.openConflicts.filter((c) => c.id !== conflictId);
|
|
173
|
+
this.emitConflicts();
|
|
174
|
+
}
|
|
175
|
+
async applyRemoteCell(remote, rowId, columnId) {
|
|
176
|
+
await this.ingestRemote(remote);
|
|
177
|
+
const before = new Set(
|
|
178
|
+
this.options.offlineStatus.getPendingChanges().map((p) => p.eventId)
|
|
179
|
+
);
|
|
180
|
+
const value = remote.payload?.newValue;
|
|
181
|
+
await this.options.applyCellValue(rowId, columnId, value);
|
|
182
|
+
const created = this.options.offlineStatus.getPendingChanges().filter((p) => !before.has(p.eventId)).map((p) => p.eventId);
|
|
183
|
+
if (created.length > 0) {
|
|
184
|
+
this.options.offlineStatus.markSynced(created);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async ingestRemote(remote) {
|
|
188
|
+
const streamId = remote.streamId || `table:${remote.tableId}`;
|
|
189
|
+
const existing = await this.options.eventStore.read(streamId);
|
|
190
|
+
if (existing.some((e) => e.eventId === remote.eventId)) {
|
|
191
|
+
this.options.offlineStatus.markSynced([remote.eventId]);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
await this.options.eventStore.append(streamId, [remote], -1);
|
|
195
|
+
this.options.offlineStatus.markSynced([remote.eventId]);
|
|
196
|
+
}
|
|
197
|
+
emitConflicts() {
|
|
198
|
+
for (const listener of this.conflictListeners) {
|
|
199
|
+
listener(this.openConflicts);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export { GridSyncService };
|
|
205
|
+
//# sourceMappingURL=chunk-KCNTKYUY.js.map
|
|
206
|
+
//# sourceMappingURL=chunk-KCNTKYUY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../application/sync/resolveCellConflicts.ts","../application/sync/GridSyncService.ts"],"names":[],"mappings":"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","file":"chunk-KCNTKYUY.js","sourcesContent":["import type {\r\n SyncConflict,\r\n SyncConflictPolicy,\r\n ManualResolution,\r\n} from '../ports/SyncPort';\r\n\r\n/**\r\n * Pure conflict resolution (PR-138).\r\n * `manual` always returns unresolved so the UI can choose.\r\n */\r\nexport function resolveConflictChoice(\r\n conflict: SyncConflict,\r\n policy: SyncConflictPolicy,\r\n): ManualResolution | 'unresolved' {\r\n if (policy === 'manual') return 'unresolved';\r\n if (policy === 'serverWins') return 'remote';\r\n // lastWriteWins — tie-break on version then occurredAt\r\n if (conflict.remote.version !== conflict.local.version) {\r\n return conflict.remote.version > conflict.local.version\r\n ? 'remote'\r\n : 'local';\r\n }\r\n if (conflict.remote.occurredAt !== conflict.local.occurredAt) {\r\n return conflict.remote.occurredAt > conflict.local.occurredAt\r\n ? 'remote'\r\n : 'local';\r\n }\r\n return 'remote';\r\n}\r\n\r\nexport function cellKeyFromPayload(\r\n payload: unknown,\r\n): { rowId: number; columnId: string } | null {\r\n if (!payload || typeof payload !== 'object') return null;\r\n const p = payload as Record<string, unknown>;\r\n const columnId = p.columnId;\r\n if (typeof columnId !== 'string' || !columnId) return null;\r\n const rowRaw = p.rowId;\r\n const rowId =\r\n typeof rowRaw === 'number'\r\n ? rowRaw\r\n : typeof rowRaw === 'string'\r\n ? Number(rowRaw)\r\n : NaN;\r\n if (!Number.isFinite(rowId)) return null;\r\n return { rowId, columnId };\r\n}\r\n\r\nexport function cellKeyId(rowId: number, columnId: string): string {\r\n return `${rowId}:${columnId}`;\r\n}\r\n","import type { EventStore } from '../ports/EventStore';\r\nimport type { GridEvent } from '../../domain/types/GridEvent';\r\nimport type { OfflineStatus } from '../offline/OfflineStatus';\r\nimport type {\r\n ManualResolution,\r\n SyncConflict,\r\n SyncConflictPolicy,\r\n SyncPort,\r\n SyncResult,\r\n SyncTransport,\r\n} from '../ports/SyncPort';\r\nimport {\r\n cellKeyFromPayload,\r\n cellKeyId,\r\n resolveConflictChoice,\r\n} from './resolveCellConflicts';\r\n\r\nexport type GridSyncServiceOptions = {\r\n readonly tableId: string;\r\n readonly eventStore: EventStore;\r\n readonly offlineStatus: OfflineStatus;\r\n readonly transport: SyncTransport;\r\n /** Apply a winning remote CELL_CHANGED into the local domain. */\r\n readonly applyCellValue: (\r\n rowId: number,\r\n columnId: string,\r\n value: unknown,\r\n ) => Promise<void>;\r\n /** Initial pull cursor (default 0). */\r\n readonly initialCursor?: number;\r\n readonly policy?: SyncConflictPolicy;\r\n};\r\n\r\nfunction isCellChanged(event: GridEvent): boolean {\r\n return event.type === 'CELL_CHANGED';\r\n}\r\n\r\nfunction toSide(event: GridEvent): SyncConflict['local'] {\r\n const payload = event.payload as { newValue?: unknown };\r\n return {\r\n eventId: event.eventId,\r\n value: payload?.newValue,\r\n occurredAt: event.occurredAt,\r\n version: event.version,\r\n };\r\n}\r\n\r\n/**\r\n * SyncPort implementation over EventStore + OfflineStatus + SyncTransport (PR-138).\r\n */\r\nexport class GridSyncService implements SyncPort {\r\n private policy: SyncConflictPolicy;\r\n private cursor: number;\r\n private openConflicts: SyncConflict[] = [];\r\n private readonly conflictListeners = new Set<\r\n (conflicts: readonly SyncConflict[]) => void\r\n >();\r\n /** Remote events waiting on manual resolution (by conflict id). */\r\n private readonly deferredRemote = new Map<string, GridEvent>();\r\n private disposed = false;\r\n\r\n constructor(private readonly options: GridSyncServiceOptions) {\r\n this.policy = options.policy ?? 'lastWriteWins';\r\n this.cursor = options.initialCursor ?? 0;\r\n }\r\n\r\n getPolicy(): SyncConflictPolicy {\r\n return this.policy;\r\n }\r\n\r\n setPolicy(policy: SyncConflictPolicy): void {\r\n this.policy = policy;\r\n }\r\n\r\n getOpenConflicts(): readonly SyncConflict[] {\r\n return this.openConflicts;\r\n }\r\n\r\n subscribeConflicts(\r\n listener: (conflicts: readonly SyncConflict[]) => void,\r\n ): () => void {\r\n if (this.disposed) return () => undefined;\r\n this.conflictListeners.add(listener);\r\n listener(this.openConflicts);\r\n return () => this.conflictListeners.delete(listener);\r\n }\r\n\r\n /** Drop listeners and deferred conflicts; later sync() calls are no-ops. */\r\n dispose(): void {\r\n this.disposed = true;\r\n this.conflictListeners.clear();\r\n this.deferredRemote.clear();\r\n this.openConflicts = [];\r\n }\r\n\r\n private emptyResult(): SyncResult {\r\n return { pushed: 0, pulled: 0, applied: 0, conflicts: [] };\r\n }\r\n\r\n async sync(): Promise<SyncResult> {\r\n if (this.disposed) return this.emptyResult();\r\n const pending = this.options.offlineStatus.getPendingChanges();\r\n const pushable = pending\r\n .map((p) => p.event)\r\n .filter(\r\n (e): e is GridEvent =>\r\n Boolean(e) && e.tableId === this.options.tableId,\r\n );\r\n\r\n const { acceptedIds } = await this.options.transport.push(pushable);\r\n if (this.disposed) return this.emptyResult();\r\n if (acceptedIds.length > 0) {\r\n this.options.offlineStatus.markSynced([...acceptedIds]);\r\n }\r\n\r\n // Locals just pushed (or still pending) — used to detect cell conflicts on pull.\r\n const localByCell = new Map<string, GridEvent>();\r\n for (const event of pushable) {\r\n if (!isCellChanged(event)) continue;\r\n const key = cellKeyFromPayload(event.payload);\r\n if (!key) continue;\r\n localByCell.set(cellKeyId(key.rowId, key.columnId), event);\r\n }\r\n for (const event of this.options.offlineStatus\r\n .getPendingChanges()\r\n .map((p) => p.event)\r\n .filter((e): e is GridEvent => Boolean(e))) {\r\n if (!isCellChanged(event) || event.tableId !== this.options.tableId) {\r\n continue;\r\n }\r\n const key = cellKeyFromPayload(event.payload);\r\n if (!key) continue;\r\n localByCell.set(cellKeyId(key.rowId, key.columnId), event);\r\n }\r\n\r\n const pulled = await this.options.transport.pull(this.cursor);\r\n if (this.disposed) return this.emptyResult();\r\n this.cursor = pulled.cursor;\r\n\r\n let applied = 0;\r\n const conflicts: SyncConflict[] = [];\r\n\r\n for (const remote of pulled.events) {\r\n // Torn down mid-apply: stop writing into a released event store.\r\n if (this.disposed) return this.emptyResult();\r\n if (remote.tableId !== this.options.tableId) continue;\r\n if (!isCellChanged(remote)) {\r\n await this.ingestRemote(remote);\r\n applied += 1;\r\n continue;\r\n }\r\n const key = cellKeyFromPayload(remote.payload);\r\n if (!key) continue;\r\n const id = cellKeyId(key.rowId, key.columnId);\r\n const local = localByCell.get(id);\r\n if (local && toSide(local).value !== toSide(remote).value) {\r\n const conflict: SyncConflict = {\r\n id: `conflict:${id}:${remote.eventId}`,\r\n key,\r\n local: toSide(local),\r\n remote: toSide(remote),\r\n };\r\n const choice = resolveConflictChoice(conflict, this.policy);\r\n if (choice === 'unresolved') {\r\n conflicts.push(conflict);\r\n this.deferredRemote.set(conflict.id, remote);\r\n continue;\r\n }\r\n if (choice === 'remote') {\r\n await this.applyRemoteCell(remote, key.rowId, key.columnId);\r\n this.options.offlineStatus.markSynced([local.eventId]);\r\n applied += 1;\r\n } else {\r\n // Keep local — acknowledge remote without applying its value\r\n await this.ingestRemote(remote);\r\n }\r\n continue;\r\n }\r\n await this.applyRemoteCell(remote, key.rowId, key.columnId);\r\n applied += 1;\r\n }\r\n\r\n this.openConflicts = [\r\n ...this.openConflicts.filter((c) => this.deferredRemote.has(c.id)),\r\n ...conflicts,\r\n ];\r\n this.emitConflicts();\r\n\r\n return {\r\n pushed: acceptedIds.length,\r\n pulled: pulled.events.length,\r\n applied,\r\n conflicts: this.openConflicts,\r\n };\r\n }\r\n\r\n async resolveConflict(\r\n conflictId: string,\r\n choice: ManualResolution,\r\n ): Promise<void> {\r\n if (this.disposed) return;\r\n const conflict = this.openConflicts.find((c) => c.id === conflictId);\r\n const remote = this.deferredRemote.get(conflictId);\r\n if (!conflict || !remote) return;\r\n\r\n if (choice === 'remote') {\r\n await this.applyRemoteCell(\r\n remote,\r\n conflict.key.rowId,\r\n conflict.key.columnId,\r\n );\r\n this.options.offlineStatus.markSynced([conflict.local.eventId]);\r\n } else {\r\n await this.ingestRemote(remote);\r\n }\r\n\r\n this.deferredRemote.delete(conflictId);\r\n this.openConflicts = this.openConflicts.filter((c) => c.id !== conflictId);\r\n this.emitConflicts();\r\n }\r\n\r\n private async applyRemoteCell(\r\n remote: GridEvent,\r\n rowId: number,\r\n columnId: string,\r\n ): Promise<void> {\r\n await this.ingestRemote(remote);\r\n const before = new Set(\r\n this.options.offlineStatus.getPendingChanges().map((p) => p.eventId),\r\n );\r\n const value = (remote.payload as { newValue?: unknown })?.newValue;\r\n await this.options.applyCellValue(rowId, columnId, value);\r\n // CHANGE_CELL_VALUE may dual-write a new local event — treat as synced.\r\n const created = this.options.offlineStatus\r\n .getPendingChanges()\r\n .filter((p) => !before.has(p.eventId))\r\n .map((p) => p.eventId);\r\n if (created.length > 0) {\r\n this.options.offlineStatus.markSynced(created);\r\n }\r\n }\r\n\r\n private async ingestRemote(remote: GridEvent): Promise<void> {\r\n const streamId = remote.streamId || `table:${remote.tableId}`;\r\n const existing = await this.options.eventStore.read(streamId);\r\n if (existing.some((e) => e.eventId === remote.eventId)) {\r\n this.options.offlineStatus.markSynced([remote.eventId]);\r\n return;\r\n }\r\n await this.options.eventStore.append(streamId, [remote], -1);\r\n // Remote ingest must not look like a local pending mutation.\r\n this.options.offlineStatus.markSynced([remote.eventId]);\r\n }\r\n\r\n private emitConflicts(): void {\r\n for (const listener of this.conflictListeners) {\r\n listener(this.openConflicts);\r\n }\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// domain/errors/DomainError.ts
|
|
2
|
+
var DomainError = class extends Error {
|
|
3
|
+
constructor(code, message, details) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.details = details;
|
|
7
|
+
this.name = "DomainError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export { DomainError };
|
|
12
|
+
//# sourceMappingURL=chunk-KHMG6EI2.js.map
|
|
13
|
+
//# sourceMappingURL=chunk-KHMG6EI2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../domain/errors/DomainError.ts"],"names":[],"mappings":";AAcO,IAAM,WAAA,GAAN,cAA0B,KAAA,CAAM;AAAA,EACrC,WAAA,CACkB,IAAA,EAChB,OAAA,EACgB,OAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAJG,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAEA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AAAA,EACd;AACF","file":"chunk-KHMG6EI2.js","sourcesContent":["//domain/errors\r\nexport type DomainErrorCode =\r\n | 'ROW_NOT_FOUND'\r\n | 'PAGE_NOT_CHANGED'\r\n | 'COLUMN_NOT_FOUND'\r\n | 'CELL_NOT_FOUND'\r\n | 'NOT_EDITABLE'\r\n | 'FORBIDDEN'\r\n | 'INVALID_VALUE'\r\n | 'DUPLICATE_ROW'\r\n | 'INVARIANT_VIOLATION'\r\n | 'ROW_NOT_EXPANDED'\r\n | 'DRAG_OR_DROP_ROW_NOT_FOUND';\r\n\r\nexport class DomainError extends Error {\r\n constructor(\r\n public readonly code: DomainErrorCode,\r\n message: string,\r\n public readonly details?: unknown\r\n ) {\r\n super(message);\r\n this.name = 'DomainError';\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// domain/errors/DomainError.ts
|
|
4
|
+
var DomainError = class extends Error {
|
|
5
|
+
constructor(code, message, details) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.details = details;
|
|
9
|
+
this.name = "DomainError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
exports.DomainError = DomainError;
|
|
14
|
+
//# sourceMappingURL=chunk-KMRURD5J.cjs.map
|
|
15
|
+
//# sourceMappingURL=chunk-KMRURD5J.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../domain/errors/DomainError.ts"],"names":[],"mappings":";;;AAcO,IAAM,WAAA,GAAN,cAA0B,KAAA,CAAM;AAAA,EACrC,WAAA,CACkB,IAAA,EAChB,OAAA,EACgB,OAAA,EAChB;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAJG,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAEA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AAAA,EACd;AACF","file":"chunk-KMRURD5J.cjs","sourcesContent":["//domain/errors\r\nexport type DomainErrorCode =\r\n | 'ROW_NOT_FOUND'\r\n | 'PAGE_NOT_CHANGED'\r\n | 'COLUMN_NOT_FOUND'\r\n | 'CELL_NOT_FOUND'\r\n | 'NOT_EDITABLE'\r\n | 'FORBIDDEN'\r\n | 'INVALID_VALUE'\r\n | 'DUPLICATE_ROW'\r\n | 'INVARIANT_VIOLATION'\r\n | 'ROW_NOT_EXPANDED'\r\n | 'DRAG_OR_DROP_ROW_NOT_FOUND';\r\n\r\nexport class DomainError extends Error {\r\n constructor(\r\n public readonly code: DomainErrorCode,\r\n message: string,\r\n public readonly details?: unknown\r\n ) {\r\n super(message);\r\n this.name = 'DomainError';\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkDFFP7SJ6_cjs = require('./chunk-DFFP7SJ6.cjs');
|
|
4
|
+
|
|
5
|
+
// infrastructure/date/jalaliMath.ts
|
|
6
|
+
function isJalaliLeap(jy) {
|
|
7
|
+
return jalaliLeapOffset(jy) === 0;
|
|
8
|
+
}
|
|
9
|
+
function jalaliLeapOffset(jy) {
|
|
10
|
+
const breaks = [
|
|
11
|
+
-61,
|
|
12
|
+
9,
|
|
13
|
+
38,
|
|
14
|
+
199,
|
|
15
|
+
426,
|
|
16
|
+
686,
|
|
17
|
+
756,
|
|
18
|
+
818,
|
|
19
|
+
1111,
|
|
20
|
+
1181,
|
|
21
|
+
1210,
|
|
22
|
+
1635,
|
|
23
|
+
2060,
|
|
24
|
+
2097,
|
|
25
|
+
2192,
|
|
26
|
+
2262,
|
|
27
|
+
2324,
|
|
28
|
+
2394,
|
|
29
|
+
2456,
|
|
30
|
+
3178
|
|
31
|
+
];
|
|
32
|
+
const bl = breaks.length;
|
|
33
|
+
let jp = breaks[0];
|
|
34
|
+
let jump = 0;
|
|
35
|
+
for (let i = 1; i < bl; i += 1) {
|
|
36
|
+
const jm = breaks[i];
|
|
37
|
+
jump = jm - jp;
|
|
38
|
+
if (jy < jm) break;
|
|
39
|
+
jp = jm;
|
|
40
|
+
}
|
|
41
|
+
let n = jy - jp;
|
|
42
|
+
if (jump - n < 6) n = n - jump + Math.floor((jump + 4) / 33) * 33;
|
|
43
|
+
let leap = ((n + 1) % 33 - 1) % 4;
|
|
44
|
+
if (leap === -1) leap = 4;
|
|
45
|
+
return leap;
|
|
46
|
+
}
|
|
47
|
+
function jalaliMonthLength(jy, jm) {
|
|
48
|
+
if (jm <= 6) return 31;
|
|
49
|
+
if (jm <= 11) return 30;
|
|
50
|
+
return isJalaliLeap(jy) ? 30 : 29;
|
|
51
|
+
}
|
|
52
|
+
function jalaliToGregorian(jy, jm, jd) {
|
|
53
|
+
const r = jalaliToJdn(jy, jm, jd);
|
|
54
|
+
return jdnToGregorian(r);
|
|
55
|
+
}
|
|
56
|
+
function gregorianToJalali(gy, gm, gd) {
|
|
57
|
+
return jdnToJalali(gregorianToJdn(gy, gm, gd));
|
|
58
|
+
}
|
|
59
|
+
function jalaliToGregorianDate(jy, jm, jd) {
|
|
60
|
+
const g = jalaliToGregorian(jy, jm, jd);
|
|
61
|
+
return new Date(Date.UTC(g.gy, g.gm - 1, g.gd, 12, 0, 0));
|
|
62
|
+
}
|
|
63
|
+
function gregorianDateToJalali(date) {
|
|
64
|
+
return gregorianToJalali(
|
|
65
|
+
date.getUTCFullYear(),
|
|
66
|
+
date.getUTCMonth() + 1,
|
|
67
|
+
date.getUTCDate()
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
function pad2(n) {
|
|
71
|
+
return String(n).padStart(2, "0");
|
|
72
|
+
}
|
|
73
|
+
function div(a, b) {
|
|
74
|
+
return Math.floor(a / b);
|
|
75
|
+
}
|
|
76
|
+
function gregorianToJdn(gy, gm, gd) {
|
|
77
|
+
const a = div(14 - gm, 12);
|
|
78
|
+
const y = gy + 4800 - a;
|
|
79
|
+
const m = gm + 12 * a - 3;
|
|
80
|
+
return gd + div(153 * m + 2, 5) + 365 * y + div(y, 4) - div(y, 100) + div(y, 400) - 32045;
|
|
81
|
+
}
|
|
82
|
+
function jdnToGregorian(jdn) {
|
|
83
|
+
let a = jdn + 32044;
|
|
84
|
+
const b = div(4 * a + 3, 146097);
|
|
85
|
+
a -= div(146097 * b, 4);
|
|
86
|
+
const c = div(4 * a + 3, 1461);
|
|
87
|
+
a -= div(1461 * c, 4);
|
|
88
|
+
const d = div(5 * a + 2, 153);
|
|
89
|
+
const gd = a - div(153 * d + 2, 5) + 1;
|
|
90
|
+
const gm = d + 3 - 12 * div(d, 10);
|
|
91
|
+
const gy = 100 * b + c - 4800 + div(d, 10);
|
|
92
|
+
return { gy, gm, gd };
|
|
93
|
+
}
|
|
94
|
+
function jalaliToJdn(jy, jm, jd) {
|
|
95
|
+
const epbase = jy - (jy >= 0 ? 474 : 473);
|
|
96
|
+
const epyear = 474 + epbase % 2820;
|
|
97
|
+
return jd + (jm <= 7 ? (jm - 1) * 31 : (jm - 1) * 30 + 6) + div(epyear * 682 - 110, 2816) + (epyear - 1) * 365 + div(epbase, 2820) * 1029983 + (1948320 - 1);
|
|
98
|
+
}
|
|
99
|
+
function jdnToJalali(jdn) {
|
|
100
|
+
const depoch = jdn - jalaliToJdn(475, 1, 1);
|
|
101
|
+
const cycle = div(depoch, 1029983);
|
|
102
|
+
const cyear = depoch % 1029983;
|
|
103
|
+
let ycycle;
|
|
104
|
+
if (cyear === 1029982) {
|
|
105
|
+
ycycle = 2820;
|
|
106
|
+
} else {
|
|
107
|
+
const aux1 = div(cyear, 366);
|
|
108
|
+
const aux2 = cyear % 366;
|
|
109
|
+
ycycle = div(2134 * aux1 + 2816 * aux2 + 2815, 1028522) + aux1 + 1;
|
|
110
|
+
}
|
|
111
|
+
const jy = ycycle + 2820 * cycle + 474;
|
|
112
|
+
const yday = jdn - jalaliToJdn(jy, 1, 1) + 1;
|
|
113
|
+
const jm = yday <= 186 ? Math.ceil(yday / 31) : Math.ceil((yday - 6) / 30);
|
|
114
|
+
const jd = jdn - jalaliToJdn(jy, jm, 1) + 1;
|
|
115
|
+
return { jy, jm, jd };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// infrastructure/date/jalaliAdapter.ts
|
|
119
|
+
var JALALI_RE = /^(\d{4})[/\-.](\d{1,2})[/\-.](\d{1,2})$/;
|
|
120
|
+
function utcDay(date) {
|
|
121
|
+
return new Date(
|
|
122
|
+
Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 12)
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
function parseTimestamp(input) {
|
|
126
|
+
if (input instanceof Date && !Number.isNaN(input.getTime())) {
|
|
127
|
+
return utcDay(input);
|
|
128
|
+
}
|
|
129
|
+
if (typeof input === "number" && Number.isFinite(input)) {
|
|
130
|
+
const d = new Date(input);
|
|
131
|
+
return Number.isNaN(d.getTime()) ? null : utcDay(d);
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
var jalaliAdapter = {
|
|
136
|
+
id: "jalali",
|
|
137
|
+
parse(input) {
|
|
138
|
+
if (input == null || input === "") return null;
|
|
139
|
+
const fromTs = parseTimestamp(input);
|
|
140
|
+
if (fromTs) return fromTs;
|
|
141
|
+
const text = chunkDFFP7SJ6_cjs.normalizeDigits(String(input).trim());
|
|
142
|
+
const m = JALALI_RE.exec(text);
|
|
143
|
+
if (!m) return null;
|
|
144
|
+
const jy = Number(m[1]);
|
|
145
|
+
const jm = Number(m[2]);
|
|
146
|
+
const jd = Number(m[3]);
|
|
147
|
+
if (jm < 1 || jm > 12 || jd < 1 || jd > 31) return null;
|
|
148
|
+
return jalaliToGregorianDate(jy, jm, jd);
|
|
149
|
+
},
|
|
150
|
+
format(date) {
|
|
151
|
+
const { jy, jm, jd } = gregorianDateToJalali(utcDay(date));
|
|
152
|
+
return `${jy}/${pad2(jm)}/${pad2(jd)}`;
|
|
153
|
+
},
|
|
154
|
+
addDays(date, days) {
|
|
155
|
+
const next = utcDay(date);
|
|
156
|
+
next.setUTCDate(next.getUTCDate() + days);
|
|
157
|
+
return next;
|
|
158
|
+
},
|
|
159
|
+
startOfMonth(date) {
|
|
160
|
+
const { jy, jm } = gregorianDateToJalali(utcDay(date));
|
|
161
|
+
return jalaliToGregorianDate(jy, jm, 1);
|
|
162
|
+
},
|
|
163
|
+
compare(a, b) {
|
|
164
|
+
return utcDay(a).getTime() - utcDay(b).getTime();
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
exports.gregorianDateToJalali = gregorianDateToJalali;
|
|
169
|
+
exports.jalaliAdapter = jalaliAdapter;
|
|
170
|
+
exports.jalaliMonthLength = jalaliMonthLength;
|
|
171
|
+
exports.jalaliToGregorianDate = jalaliToGregorianDate;
|
|
172
|
+
exports.pad2 = pad2;
|
|
173
|
+
//# sourceMappingURL=chunk-KRJG3KMP.cjs.map
|
|
174
|
+
//# sourceMappingURL=chunk-KRJG3KMP.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../infrastructure/date/jalaliMath.ts","../infrastructure/date/jalaliAdapter.ts"],"names":["normalizeDigits"],"mappings":"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","file":"chunk-KRJG3KMP.cjs","sourcesContent":["/**\r\n * Jalali ↔ Gregorian conversion (PR-128).\r\n * Algorithm adapted from the public-domain jalaali-js approach.\r\n */\r\n\r\nexport function isJalaliLeap(jy: number): boolean {\r\n return jalaliLeapOffset(jy) === 0;\r\n}\r\n\r\nfunction jalaliLeapOffset(jy: number): number {\r\n const breaks = [\r\n -61, 9, 38, 199, 426, 686, 756, 818, 1111, 1181, 1210, 1635, 2060, 2097,\r\n 2192, 2262, 2324, 2394, 2456, 3178,\r\n ];\r\n const bl = breaks.length;\r\n let jp = breaks[0]!;\r\n let jump = 0;\r\n for (let i = 1; i < bl; i += 1) {\r\n const jm = breaks[i]!;\r\n jump = jm - jp;\r\n if (jy < jm) break;\r\n jp = jm;\r\n }\r\n let n = jy - jp;\r\n if (jump - n < 6) n = n - jump + Math.floor((jump + 4) / 33) * 33;\r\n let leap = ((((n + 1) % 33) - 1) % 4);\r\n if (leap === -1) leap = 4;\r\n return leap;\r\n}\r\n\r\nexport function jalaliMonthLength(jy: number, jm: number): number {\r\n if (jm <= 6) return 31;\r\n if (jm <= 11) return 30;\r\n return isJalaliLeap(jy) ? 30 : 29;\r\n}\r\n\r\nexport function jalaliToGregorian(\r\n jy: number,\r\n jm: number,\r\n jd: number,\r\n): { gy: number; gm: number; gd: number } {\r\n const r = jalaliToJdn(jy, jm, jd);\r\n return jdnToGregorian(r);\r\n}\r\n\r\nexport function gregorianToJalali(\r\n gy: number,\r\n gm: number,\r\n gd: number,\r\n): { jy: number; jm: number; jd: number } {\r\n return jdnToJalali(gregorianToJdn(gy, gm, gd));\r\n}\r\n\r\nexport function jalaliToGregorianDate(jy: number, jm: number, jd: number): Date {\r\n const g = jalaliToGregorian(jy, jm, jd);\r\n return new Date(Date.UTC(g.gy, g.gm - 1, g.gd, 12, 0, 0));\r\n}\r\n\r\nexport function gregorianDateToJalali(date: Date): {\r\n jy: number;\r\n jm: number;\r\n jd: number;\r\n} {\r\n return gregorianToJalali(\r\n date.getUTCFullYear(),\r\n date.getUTCMonth() + 1,\r\n date.getUTCDate(),\r\n );\r\n}\r\n\r\nexport function pad2(n: number): string {\r\n return String(n).padStart(2, '0');\r\n}\r\n\r\nfunction div(a: number, b: number): number {\r\n return Math.floor(a / b);\r\n}\r\n\r\nfunction gregorianToJdn(gy: number, gm: number, gd: number): number {\r\n const a = div(14 - gm, 12);\r\n const y = gy + 4800 - a;\r\n const m = gm + 12 * a - 3;\r\n return (\r\n gd +\r\n div(153 * m + 2, 5) +\r\n 365 * y +\r\n div(y, 4) -\r\n div(y, 100) +\r\n div(y, 400) -\r\n 32045\r\n );\r\n}\r\n\r\nfunction jdnToGregorian(jdn: number): { gy: number; gm: number; gd: number } {\r\n let a = jdn + 32044;\r\n const b = div(4 * a + 3, 146097);\r\n a -= div(146097 * b, 4);\r\n const c = div(4 * a + 3, 1461);\r\n a -= div(1461 * c, 4);\r\n const d = div(5 * a + 2, 153);\r\n const gd = a - div(153 * d + 2, 5) + 1;\r\n const gm = d + 3 - 12 * div(d, 10);\r\n const gy = 100 * b + c - 4800 + div(d, 10);\r\n return { gy, gm, gd };\r\n}\r\n\r\nfunction jalaliToJdn(jy: number, jm: number, jd: number): number {\r\n const epbase = jy - (jy >= 0 ? 474 : 473);\r\n const epyear = 474 + (epbase % 2820);\r\n return (\r\n jd +\r\n (jm <= 7 ? (jm - 1) * 31 : (jm - 1) * 30 + 6) +\r\n div(epyear * 682 - 110, 2816) +\r\n (epyear - 1) * 365 +\r\n div(epbase, 2820) * 1029983 +\r\n (1948320 - 1)\r\n );\r\n}\r\n\r\nfunction jdnToJalali(jdn: number): { jy: number; jm: number; jd: number } {\r\n const depoch = jdn - jalaliToJdn(475, 1, 1);\r\n const cycle = div(depoch, 1029983);\r\n const cyear = depoch % 1029983;\r\n let ycycle: number;\r\n if (cyear === 1029982) {\r\n ycycle = 2820;\r\n } else {\r\n const aux1 = div(cyear, 366);\r\n const aux2 = cyear % 366;\r\n ycycle = div(2134 * aux1 + 2816 * aux2 + 2815, 1028522) + aux1 + 1;\r\n }\r\n const jy = ycycle + 2820 * cycle + 474;\r\n const yday = jdn - jalaliToJdn(jy, 1, 1) + 1;\r\n const jm = yday <= 186 ? Math.ceil(yday / 31) : Math.ceil((yday - 6) / 30);\r\n const jd = jdn - jalaliToJdn(jy, jm, 1) + 1;\r\n return { jy, jm, jd };\r\n}\r\n","import type { DateAdapter } from '../../application/ports/DateAdapter';\r\nimport { normalizeDigits } from '../../engine/dataOps/sortModel';\r\nimport {\r\n gregorianDateToJalali,\r\n jalaliToGregorianDate,\r\n pad2,\r\n} from './jalaliMath';\r\n\r\nconst JALALI_RE = /^(\\d{4})[/\\-.](\\d{1,2})[/\\-.](\\d{1,2})$/;\r\n\r\nfunction utcDay(date: Date): Date {\r\n return new Date(\r\n Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 12),\r\n );\r\n}\r\n\r\nfunction parseTimestamp(input: unknown): Date | null {\r\n if (input instanceof Date && !Number.isNaN(input.getTime())) {\r\n return utcDay(input);\r\n }\r\n if (typeof input === 'number' && Number.isFinite(input)) {\r\n const d = new Date(input);\r\n return Number.isNaN(d.getTime()) ? null : utcDay(d);\r\n }\r\n return null;\r\n}\r\n\r\n/** Default calendar for Persian hosts (PR-128 / D21). */\r\nexport const jalaliAdapter: DateAdapter = {\r\n id: 'jalali',\r\n\r\n parse(input: unknown): Date | null {\r\n if (input == null || input === '') return null;\r\n const fromTs = parseTimestamp(input);\r\n if (fromTs) return fromTs;\r\n const text = normalizeDigits(String(input).trim());\r\n const m = JALALI_RE.exec(text);\r\n if (!m) return null;\r\n const jy = Number(m[1]);\r\n const jm = Number(m[2]);\r\n const jd = Number(m[3]);\r\n if (jm < 1 || jm > 12 || jd < 1 || jd > 31) return null;\r\n return jalaliToGregorianDate(jy, jm, jd);\r\n },\r\n\r\n format(date: Date): string {\r\n const { jy, jm, jd } = gregorianDateToJalali(utcDay(date));\r\n return `${jy}/${pad2(jm)}/${pad2(jd)}`;\r\n },\r\n\r\n addDays(date: Date, days: number): Date {\r\n const next = utcDay(date);\r\n next.setUTCDate(next.getUTCDate() + days);\r\n return next;\r\n },\r\n\r\n startOfMonth(date: Date): Date {\r\n const { jy, jm } = gregorianDateToJalali(utcDay(date));\r\n return jalaliToGregorianDate(jy, jm, 1);\r\n },\r\n\r\n compare(a: Date, b: Date): number {\r\n return utcDay(a).getTime() - utcDay(b).getTime();\r\n },\r\n};\r\n"]}
|