@xnetjs/core 0.2.0 → 0.3.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/dist/index.d.ts +56 -1
- package/dist/index.js +26 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -864,6 +864,61 @@ declare function validateExternalUrl(rawUrl: string): {
|
|
|
864
864
|
error?: string;
|
|
865
865
|
};
|
|
866
866
|
|
|
867
|
+
/**
|
|
868
|
+
* The ONE Last-Write-Wins ordering for xNet (docs/specs/protocol §L1.7,
|
|
869
|
+
* exploration 0276).
|
|
870
|
+
*
|
|
871
|
+
* Per-property conflict resolution and change-log application ordering were
|
|
872
|
+
* previously re-implemented in three places (`NodeStore.applyChange`, the
|
|
873
|
+
* SQLite adapter's ON CONFLICT guards, and the hub storages' change
|
|
874
|
+
* ordering) — a drift class on the protocol's core convergence invariant.
|
|
875
|
+
* Every implementation now derives from this module, and the golden-vector
|
|
876
|
+
* conformance suite (exploration 0200) pins them equal.
|
|
877
|
+
*
|
|
878
|
+
* Ordering: lamport time, then wall time, then author DID compared by UTF-16
|
|
879
|
+
* code units. NEVER `localeCompare` — locale collation is non-deterministic
|
|
880
|
+
* across ICU versions and would break CRDT convergence (see the
|
|
881
|
+
* `0004-tie-author-case-codeunit` golden vector).
|
|
882
|
+
*/
|
|
883
|
+
/** The timestamp triple every LWW comparison runs on. */
|
|
884
|
+
interface LwwStamp {
|
|
885
|
+
lamport: number;
|
|
886
|
+
wallTime: number;
|
|
887
|
+
author: string;
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Spec comparator (§L1.7): negative when `a` loses to `b`, positive when `a`
|
|
891
|
+
* beats `b`, zero only for identical stamps.
|
|
892
|
+
*/
|
|
893
|
+
declare function compareLwwStamps(a: LwwStamp, b: LwwStamp): number;
|
|
894
|
+
/** Whether an incoming write replaces the existing one under LWW. */
|
|
895
|
+
declare function lwwWins(incoming: LwwStamp, existing: LwwStamp): boolean;
|
|
896
|
+
/**
|
|
897
|
+
* Deterministic application order for change logs: lamport time, then author
|
|
898
|
+
* by code units. Used when replaying/relaying batches so every peer folds
|
|
899
|
+
* changes in the same sequence (matches the hub's
|
|
900
|
+
* `ORDER BY lamport_time ASC, lamport_author ASC`).
|
|
901
|
+
*/
|
|
902
|
+
declare function compareChangeApplicationOrder(a: {
|
|
903
|
+
lamport: number;
|
|
904
|
+
author: string;
|
|
905
|
+
}, b: {
|
|
906
|
+
lamport: number;
|
|
907
|
+
author: string;
|
|
908
|
+
}): number;
|
|
909
|
+
/**
|
|
910
|
+
* SQL `ON CONFLICT … DO UPDATE … WHERE` guard implementing {@link lwwWins}
|
|
911
|
+
* inside SQLite (the `excluded.` pseudo-table is the incoming row). Column
|
|
912
|
+
* text comparison (`>`) is byte order under SQLite's default BINARY
|
|
913
|
+
* collation, which matches the code-unit rule for our ASCII DID strings.
|
|
914
|
+
*/
|
|
915
|
+
declare function lwwUpdateGuardSql(input: {
|
|
916
|
+
table: string;
|
|
917
|
+
lamportColumn: string;
|
|
918
|
+
wallTimeColumn: string;
|
|
919
|
+
authorColumn: string;
|
|
920
|
+
}): string;
|
|
921
|
+
|
|
867
922
|
/**
|
|
868
923
|
* @xnetjs/core - Core types, schemas, and content addressing
|
|
869
924
|
*/
|
|
@@ -871,4 +926,4 @@ declare function validateExternalUrl(rawUrl: string): {
|
|
|
871
926
|
type DID = `did:key:${string}`;
|
|
872
927
|
type DocumentPath = `xnet://${DID}/workspace/${string}/doc/${string}`;
|
|
873
928
|
|
|
874
|
-
export { ALL_CAPABILITIES, AUTH_ACTIONS, type ActionKey, type AllowExpr, type AndExpr, type AuthAction, type AuthCheckInput, type AuthDecision, type AuthDenyReason, type AuthExpression, type AuthTrace, type AuthTraceStep, type AuthenticatedExpr, type AuthorizationDefinition, BOOTSTRAP_PEERS, type Capability, type ChainStatus, type Condition, type ContentChunk, type ContentId, type ContentResolver, type ContentTree, type CreatorRoleResolver, DEFAULT_SNAPSHOT_TRIGGERS, DEFAULT_STREAMING_OPTIONS, DHT_CONFIG, type DID, type DIDResolution, type DIDResolver, type DataSource, type DenyExpr, type DocumentLoad, type DocumentPath, type Fork, type Group, type IPCondition, type MembershipRoleResolver, type MerkleNode, type NotExpr, type OrExpr, type PeerLocation, type PermissionEvaluator, type PermissionGrant, type PolicyEvaluator, type PropertyRoleResolver, type PublicExpr, type Query, type QueryPlan, type QueryRequest, type QueryResponse, type QueryRouter, RESOLUTION_CACHE_CONFIG, type RelationRoleResolver, type ResolutionStrategy, type ResourceScope, type Role, type RoleKey, type RoleRefExpr, type RoleResolver, STANDARD_ROLES, type SchemaAction, type SerializedAuthExpression, type SerializedAuthorization, type SerializedRoleResolver, type SignedUpdate, type Snapshot, type SnapshotTriggers, SsrfError, type StreamingQueryOptions, type SubQuery, type TimeCondition, type UpdateVerifier, type VectorClock, assertPublicUrl, buildMerkleTree, clamp, clamp01, compareVectorClocks, createChunk, createContentId, deduplicatedUnion, detectFork, estimateQueryCost, evaluateCondition, formatBytes, getMostPermissiveCapability, hashContent, incrementVectorClock, isLocationFresh, isValidDID, isValidProgression, mergeStateVectors, mergeVectorClocks, parseContentId, parseDID, roleHasCapability, shouldCreateSnapshot, unionAggregate, validateExternalUrl, verifyContent, verifyUpdateChain };
|
|
929
|
+
export { ALL_CAPABILITIES, AUTH_ACTIONS, type ActionKey, type AllowExpr, type AndExpr, type AuthAction, type AuthCheckInput, type AuthDecision, type AuthDenyReason, type AuthExpression, type AuthTrace, type AuthTraceStep, type AuthenticatedExpr, type AuthorizationDefinition, BOOTSTRAP_PEERS, type Capability, type ChainStatus, type Condition, type ContentChunk, type ContentId, type ContentResolver, type ContentTree, type CreatorRoleResolver, DEFAULT_SNAPSHOT_TRIGGERS, DEFAULT_STREAMING_OPTIONS, DHT_CONFIG, type DID, type DIDResolution, type DIDResolver, type DataSource, type DenyExpr, type DocumentLoad, type DocumentPath, type Fork, type Group, type IPCondition, type LwwStamp, type MembershipRoleResolver, type MerkleNode, type NotExpr, type OrExpr, type PeerLocation, type PermissionEvaluator, type PermissionGrant, type PolicyEvaluator, type PropertyRoleResolver, type PublicExpr, type Query, type QueryPlan, type QueryRequest, type QueryResponse, type QueryRouter, RESOLUTION_CACHE_CONFIG, type RelationRoleResolver, type ResolutionStrategy, type ResourceScope, type Role, type RoleKey, type RoleRefExpr, type RoleResolver, STANDARD_ROLES, type SchemaAction, type SerializedAuthExpression, type SerializedAuthorization, type SerializedRoleResolver, type SignedUpdate, type Snapshot, type SnapshotTriggers, SsrfError, type StreamingQueryOptions, type SubQuery, type TimeCondition, type UpdateVerifier, type VectorClock, assertPublicUrl, buildMerkleTree, clamp, clamp01, compareChangeApplicationOrder, compareLwwStamps, compareVectorClocks, createChunk, createContentId, deduplicatedUnion, detectFork, estimateQueryCost, evaluateCondition, formatBytes, getMostPermissiveCapability, hashContent, incrementVectorClock, isLocationFresh, isValidDID, isValidProgression, lwwUpdateGuardSql, lwwWins, mergeStateVectors, mergeVectorClocks, parseContentId, parseDID, roleHasCapability, shouldCreateSnapshot, unionAggregate, validateExternalUrl, verifyContent, verifyUpdateChain };
|
package/dist/index.js
CHANGED
|
@@ -407,6 +407,28 @@ function validateExternalUrl(rawUrl) {
|
|
|
407
407
|
return { valid: false, error: error instanceof Error ? error.message : "Invalid URL" };
|
|
408
408
|
}
|
|
409
409
|
}
|
|
410
|
+
|
|
411
|
+
// src/lww.ts
|
|
412
|
+
function compareLwwStamps(a, b) {
|
|
413
|
+
if (a.lamport !== b.lamport) return a.lamport - b.lamport;
|
|
414
|
+
if (a.wallTime !== b.wallTime) return a.wallTime - b.wallTime;
|
|
415
|
+
return a.author < b.author ? -1 : a.author > b.author ? 1 : 0;
|
|
416
|
+
}
|
|
417
|
+
function lwwWins(incoming, existing) {
|
|
418
|
+
return compareLwwStamps(incoming, existing) > 0;
|
|
419
|
+
}
|
|
420
|
+
function compareChangeApplicationOrder(a, b) {
|
|
421
|
+
if (a.lamport !== b.lamport) return a.lamport - b.lamport;
|
|
422
|
+
return a.author < b.author ? -1 : a.author > b.author ? 1 : 0;
|
|
423
|
+
}
|
|
424
|
+
function lwwUpdateGuardSql(input) {
|
|
425
|
+
const { table, lamportColumn, wallTimeColumn, authorColumn } = input;
|
|
426
|
+
return `excluded.${lamportColumn} > ${table}.${lamportColumn}
|
|
427
|
+
OR (excluded.${lamportColumn} = ${table}.${lamportColumn}
|
|
428
|
+
AND (excluded.${wallTimeColumn} > ${table}.${wallTimeColumn}
|
|
429
|
+
OR (excluded.${wallTimeColumn} = ${table}.${wallTimeColumn}
|
|
430
|
+
AND excluded.${authorColumn} > ${table}.${authorColumn})))`;
|
|
431
|
+
}
|
|
410
432
|
export {
|
|
411
433
|
ALL_CAPABILITIES,
|
|
412
434
|
AUTH_ACTIONS,
|
|
@@ -421,6 +443,8 @@ export {
|
|
|
421
443
|
buildMerkleTree,
|
|
422
444
|
clamp,
|
|
423
445
|
clamp01,
|
|
446
|
+
compareChangeApplicationOrder,
|
|
447
|
+
compareLwwStamps,
|
|
424
448
|
compareVectorClocks,
|
|
425
449
|
createChunk,
|
|
426
450
|
createContentId,
|
|
@@ -435,6 +459,8 @@ export {
|
|
|
435
459
|
isLocationFresh,
|
|
436
460
|
isValidDID,
|
|
437
461
|
isValidProgression,
|
|
462
|
+
lwwUpdateGuardSql,
|
|
463
|
+
lwwWins,
|
|
438
464
|
mergeStateVectors,
|
|
439
465
|
mergeVectorClocks,
|
|
440
466
|
parseContentId,
|