@dabble/patches 0.5.1 → 0.5.2
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/dist/algorithms/server/commitChanges.js +2 -2
- package/dist/algorithms/server/createVersion.js +3 -2
- package/dist/algorithms/server/handleOfflineSessionsAndBatches.js +3 -3
- package/dist/data/change.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/server/PatchesBranchManager.js +2 -2
- package/dist/utils/dates.d.ts +13 -22
- package/dist/utils/dates.js +16 -28
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../../chunk-IZ2YBCUP.js";
|
|
2
|
-
import { clampTimestamp,
|
|
2
|
+
import { clampTimestamp, getISO, timestampDiff } from "../../utils/dates.js";
|
|
3
3
|
import { applyChanges } from "../shared/applyChanges.js";
|
|
4
4
|
import { createVersion } from "./createVersion.js";
|
|
5
5
|
import { getSnapshotAtRevision } from "./getSnapshotAtRevision.js";
|
|
@@ -15,7 +15,7 @@ async function commitChanges(store, docId, changes, sessionTimeoutMillis) {
|
|
|
15
15
|
const currentState = applyChanges(initialState, currentChanges);
|
|
16
16
|
const currentRev = currentChanges.at(-1)?.rev ?? initialRev;
|
|
17
17
|
const baseRev = changes[0].baseRev ?? currentRev;
|
|
18
|
-
const serverNow =
|
|
18
|
+
const serverNow = getISO();
|
|
19
19
|
let rev = baseRev + 1;
|
|
20
20
|
changes.forEach((c) => {
|
|
21
21
|
if (c.baseRev == null) c.baseRev = baseRev;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import "../../chunk-IZ2YBCUP.js";
|
|
2
2
|
import { createVersionMetadata } from "../../data/version.js";
|
|
3
|
+
import { getISO } from "../../utils/dates.js";
|
|
3
4
|
async function createVersion(store, docId, state, changes, metadata) {
|
|
4
5
|
if (changes.length === 0) return;
|
|
5
6
|
const baseRev = changes[0].baseRev;
|
|
@@ -9,8 +10,8 @@ async function createVersion(store, docId, state, changes, metadata) {
|
|
|
9
10
|
const sessionMetadata = createVersionMetadata({
|
|
10
11
|
origin: "main",
|
|
11
12
|
// Convert client timestamps to UTC for version metadata (enables lexicographic sorting)
|
|
12
|
-
startedAt:
|
|
13
|
-
endedAt:
|
|
13
|
+
startedAt: getISO(changes[0].createdAt),
|
|
14
|
+
endedAt: getISO(changes[changes.length - 1].createdAt),
|
|
14
15
|
rev: changes[changes.length - 1].rev,
|
|
15
16
|
baseRev,
|
|
16
17
|
...metadata
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "../../chunk-IZ2YBCUP.js";
|
|
2
2
|
import { createSortableId } from "crypto-id";
|
|
3
3
|
import { createVersionMetadata } from "../../data/version.js";
|
|
4
|
-
import { timestampDiff } from "../../utils/dates.js";
|
|
4
|
+
import { getISO, timestampDiff } from "../../utils/dates.js";
|
|
5
5
|
import { applyChanges } from "../shared/applyChanges.js";
|
|
6
6
|
import { getStateAtRevision } from "./getStateAtRevision.js";
|
|
7
7
|
async function handleOfflineSessionsAndBatches(store, sessionTimeoutMillis, docId, changes, baseRev, batchId) {
|
|
@@ -41,8 +41,8 @@ async function handleOfflineSessionsAndBatches(store, sessionTimeoutMillis, docI
|
|
|
41
41
|
groupId,
|
|
42
42
|
origin: "offline",
|
|
43
43
|
// Convert client timestamps to UTC for version metadata (enables lexicographic sorting)
|
|
44
|
-
startedAt:
|
|
45
|
-
endedAt:
|
|
44
|
+
startedAt: getISO(sessionChanges[0].createdAt),
|
|
45
|
+
endedAt: getISO(sessionChanges[sessionChanges.length - 1].createdAt),
|
|
46
46
|
rev: sessionChanges[sessionChanges.length - 1].rev,
|
|
47
47
|
baseRev
|
|
48
48
|
});
|
package/dist/data/change.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "../chunk-IZ2YBCUP.js";
|
|
2
2
|
import { inc } from "alphacounter";
|
|
3
3
|
import { createId } from "crypto-id";
|
|
4
|
-
import {
|
|
4
|
+
import { getLocalISO } from "../utils/dates.js";
|
|
5
5
|
function createChangeId(rev) {
|
|
6
6
|
return inc.from(rev) + createId(4);
|
|
7
7
|
}
|
|
@@ -10,7 +10,7 @@ function createChange(baseRev, rev, ops, metadata) {
|
|
|
10
10
|
return {
|
|
11
11
|
id: createId(8),
|
|
12
12
|
ops: baseRev,
|
|
13
|
-
createdAt:
|
|
13
|
+
createdAt: getLocalISO(),
|
|
14
14
|
...rev
|
|
15
15
|
};
|
|
16
16
|
} else {
|
|
@@ -19,7 +19,7 @@ function createChange(baseRev, rev, ops, metadata) {
|
|
|
19
19
|
baseRev,
|
|
20
20
|
rev,
|
|
21
21
|
ops,
|
|
22
|
-
createdAt:
|
|
22
|
+
createdAt: getLocalISO(),
|
|
23
23
|
...metadata
|
|
24
24
|
};
|
|
25
25
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export { transformPatch } from './json-patch/transformPatch.js';
|
|
|
18
18
|
export { JSONPatch, PathLike, WriteOptions } from './json-patch/JSONPatch.js';
|
|
19
19
|
export { ApplyJSONPatchOptions, JSONPatchOpHandlerMap as JSONPatchCustomTypes, JSONPatchOp } from './json-patch/types.js';
|
|
20
20
|
export { Branch, BranchStatus, Change, ChangeInput, ChangeMutator, EditableBranchMetadata, EditableVersionMetadata, ListChangesOptions, ListVersionsOptions, PatchesSnapshot, PatchesState, PathProxy, SyncingState, VersionMetadata } from './types.js';
|
|
21
|
-
export { clampTimestamp,
|
|
21
|
+
export { clampTimestamp, extractTimezoneOffset, getISO, getLocalISO, getLocalTimezoneOffset, timestampDiff } from './utils/dates.js';
|
|
22
22
|
export { add } from './json-patch/ops/add.js';
|
|
23
23
|
export { copy } from './json-patch/ops/copy.js';
|
|
24
24
|
export { increment } from './json-patch/ops/increment.js';
|
|
@@ -2,7 +2,7 @@ import "../chunk-IZ2YBCUP.js";
|
|
|
2
2
|
import { createId } from "crypto-id";
|
|
3
3
|
import { createChange } from "../data/change.js";
|
|
4
4
|
import { createVersionMetadata } from "../data/version.js";
|
|
5
|
-
import {
|
|
5
|
+
import { getISO } from "../utils/dates.js";
|
|
6
6
|
class PatchesBranchManager {
|
|
7
7
|
constructor(store, patchesServer) {
|
|
8
8
|
this.store = store;
|
|
@@ -31,7 +31,7 @@ class PatchesBranchManager {
|
|
|
31
31
|
}
|
|
32
32
|
const stateAtRev = (await this.patchesServer.getStateAtRevision(docId, rev)).state;
|
|
33
33
|
const branchDocId = createId();
|
|
34
|
-
const now =
|
|
34
|
+
const now = getISO();
|
|
35
35
|
const initialVersionMetadata = createVersionMetadata({
|
|
36
36
|
origin: "main",
|
|
37
37
|
// Branch doc versions are 'main' until merged
|
package/dist/utils/dates.d.ts
CHANGED
|
@@ -5,48 +5,39 @@
|
|
|
5
5
|
* Server-side timestamps use UTC with Z suffix.
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* Example: "2025-12-
|
|
8
|
+
* Converts a Date or ISO string to UTC format without milliseconds.
|
|
9
|
+
* Example: "2025-12-26T10:00:00Z"
|
|
10
10
|
*/
|
|
11
|
-
declare function
|
|
11
|
+
declare function getISO(date?: Date | string): string;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*/
|
|
16
|
-
declare function createServerTimestamp(): string;
|
|
17
|
-
/**
|
|
18
|
-
* Parses an ISO string to a Date for comparisons.
|
|
13
|
+
* Formats a Date with a specific timezone offset string.
|
|
14
|
+
* The date is adjusted to display the correct local time for that offset.
|
|
19
15
|
*/
|
|
20
|
-
declare function
|
|
16
|
+
declare function getLocalISO(date?: Date | string, offset?: string): string;
|
|
21
17
|
/**
|
|
22
18
|
* Calculates milliseconds between two ISO timestamps.
|
|
23
19
|
* Returns (a - b) in milliseconds.
|
|
24
20
|
*/
|
|
25
21
|
declare function timestampDiff(a: string, b: string): number;
|
|
26
|
-
/**
|
|
27
|
-
* Extracts the timezone offset string from an ISO timestamp.
|
|
28
|
-
* Returns "+04:00", "-05:00", or "Z".
|
|
29
|
-
*/
|
|
30
|
-
declare function extractTimezoneOffset(iso: string): string;
|
|
31
22
|
/**
|
|
32
23
|
* Clamps a timestamp to not exceed a limit, preserving the original timezone offset.
|
|
33
24
|
* Returns the original if it's <= limit, otherwise returns limit in original's timezone.
|
|
34
25
|
*
|
|
35
26
|
* Example:
|
|
36
|
-
* timestamp: "2025-12-26T18:00:00
|
|
37
|
-
* limit: "2025-12-26T10:00:
|
|
38
|
-
* result: "2025-12-26T14:00:00
|
|
27
|
+
* timestamp: "2025-12-26T18:00:00+04:00" (future)
|
|
28
|
+
* limit: "2025-12-26T10:00:00Z" (server time)
|
|
29
|
+
* result: "2025-12-26T14:00:00+04:00" (clamped, same instant as limit)
|
|
39
30
|
*/
|
|
40
31
|
declare function clampTimestamp(timestamp: string, limit: string): string;
|
|
41
32
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
33
|
+
* Extracts the timezone offset string from an ISO timestamp.
|
|
34
|
+
* Returns "+04:00", "-05:00", or "Z".
|
|
44
35
|
*/
|
|
45
|
-
declare function
|
|
36
|
+
declare function extractTimezoneOffset(iso: string): string;
|
|
46
37
|
/**
|
|
47
38
|
* Gets the local timezone offset string for the current environment.
|
|
48
39
|
* Returns "+04:00", "-05:00", or "Z" for UTC.
|
|
49
40
|
*/
|
|
50
41
|
declare function getLocalTimezoneOffset(): string;
|
|
51
42
|
|
|
52
|
-
export { clampTimestamp,
|
|
43
|
+
export { clampTimestamp, extractTimezoneOffset, getISO, getLocalISO, getLocalTimezoneOffset, timestampDiff };
|
package/dist/utils/dates.js
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import "../chunk-IZ2YBCUP.js";
|
|
2
|
-
function
|
|
3
|
-
const
|
|
4
|
-
return
|
|
2
|
+
function getISO(date = /* @__PURE__ */ new Date()) {
|
|
3
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
4
|
+
return d.toISOString().replace(/\.\d{3}/, "");
|
|
5
5
|
}
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
function getLocalISO(date = /* @__PURE__ */ new Date(), offset = getLocalTimezoneOffset()) {
|
|
7
|
+
const match = offset.match(/([+-])(\d{2}):(\d{2})/);
|
|
8
|
+
if (offset === "Z" || !match) return getISO(date);
|
|
9
|
+
const sign = match[1] === "+" ? 1 : -1;
|
|
10
|
+
const offsetMinutes = sign * (parseInt(match[2]) * 60 + parseInt(match[3]));
|
|
11
|
+
const localDate = new Date((typeof date === "string" ? new Date(date) : date).getTime() + offsetMinutes * 60 * 1e3);
|
|
12
|
+
return getISO(localDate).slice(0, -1) + offset;
|
|
11
13
|
}
|
|
12
14
|
function timestampDiff(a, b) {
|
|
13
15
|
return new Date(a).getTime() - new Date(b).getTime();
|
|
14
16
|
}
|
|
15
|
-
function extractTimezoneOffset(iso) {
|
|
16
|
-
const match = iso.match(/([+-]\d{2}:\d{2}|Z)$/);
|
|
17
|
-
return match ? match[1] : "Z";
|
|
18
|
-
}
|
|
19
17
|
function clampTimestamp(timestamp, limit) {
|
|
20
18
|
const timestampDate = new Date(timestamp);
|
|
21
19
|
const limitDate = new Date(limit);
|
|
@@ -23,19 +21,11 @@ function clampTimestamp(timestamp, limit) {
|
|
|
23
21
|
return timestamp;
|
|
24
22
|
}
|
|
25
23
|
const offset = extractTimezoneOffset(timestamp);
|
|
26
|
-
return
|
|
24
|
+
return getLocalISO(limitDate, offset);
|
|
27
25
|
}
|
|
28
|
-
function
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
const match = offset.match(/([+-])(\d{2}):(\d{2})/);
|
|
33
|
-
if (!match) return date.toISOString();
|
|
34
|
-
const sign = match[1] === "+" ? 1 : -1;
|
|
35
|
-
const offsetMinutes = sign * (parseInt(match[2]) * 60 + parseInt(match[3]));
|
|
36
|
-
const localDate = new Date(date.getTime() + offsetMinutes * 60 * 1e3);
|
|
37
|
-
const iso = localDate.toISOString();
|
|
38
|
-
return iso.slice(0, -1) + offset;
|
|
26
|
+
function extractTimezoneOffset(iso) {
|
|
27
|
+
const match = iso.match(/([+-]\d{2}:\d{2}|Z)$/);
|
|
28
|
+
return match ? match[1] : "Z";
|
|
39
29
|
}
|
|
40
30
|
function getLocalTimezoneOffset() {
|
|
41
31
|
const offset = -(/* @__PURE__ */ new Date()).getTimezoneOffset();
|
|
@@ -47,11 +37,9 @@ function getLocalTimezoneOffset() {
|
|
|
47
37
|
}
|
|
48
38
|
export {
|
|
49
39
|
clampTimestamp,
|
|
50
|
-
createClientTimestamp,
|
|
51
|
-
createServerTimestamp,
|
|
52
40
|
extractTimezoneOffset,
|
|
53
|
-
|
|
41
|
+
getISO,
|
|
42
|
+
getLocalISO,
|
|
54
43
|
getLocalTimezoneOffset,
|
|
55
|
-
parseTimestamp,
|
|
56
44
|
timestampDiff
|
|
57
45
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dabble/patches",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Immutable JSON Patch implementation based on RFC 6902 supporting operational transformation and last-writer-wins",
|
|
5
5
|
"author": "Jacob Wright <jacwright@gmail.com>",
|
|
6
6
|
"bugs": {
|