@liberfi.io/utils 0.2.71 → 0.2.73
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/realtime-cursor-collection/index.d.mts +46 -0
- package/dist/realtime-cursor-collection/index.d.ts +46 -0
- package/dist/realtime-cursor-collection/index.js +2 -0
- package/dist/realtime-cursor-collection/index.js.map +1 -0
- package/dist/realtime-cursor-collection/index.mjs +2 -0
- package/dist/realtime-cursor-collection/index.mjs.map +1 -0
- package/package.json +29 -4
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
type RealtimeCursorSource = "page" | "live";
|
|
2
|
+
interface RealtimeCursorPolicy<TItem> {
|
|
3
|
+
getKey(item: TItem): string;
|
|
4
|
+
compare(left: TItem, right: TItem): number;
|
|
5
|
+
include(item: TItem): boolean;
|
|
6
|
+
merge(previous: TItem, incoming: TItem, context: {
|
|
7
|
+
previousSource: RealtimeCursorSource;
|
|
8
|
+
incomingSource: RealtimeCursorSource;
|
|
9
|
+
}): {
|
|
10
|
+
item: TItem;
|
|
11
|
+
placement: "previous" | "incoming";
|
|
12
|
+
};
|
|
13
|
+
maxLiveItems?: number;
|
|
14
|
+
maxItems?: number;
|
|
15
|
+
}
|
|
16
|
+
interface RealtimeCursorSnapshot<TItem, TCursor> {
|
|
17
|
+
readonly items: readonly TItem[];
|
|
18
|
+
readonly pageItems: readonly TItem[];
|
|
19
|
+
readonly liveItems: readonly TItem[];
|
|
20
|
+
readonly nextCursor: TCursor | null;
|
|
21
|
+
readonly hasNextPage: boolean;
|
|
22
|
+
readonly generation: number;
|
|
23
|
+
}
|
|
24
|
+
type RealtimeCursorCommand<TItem, TCursor> = {
|
|
25
|
+
type: "page";
|
|
26
|
+
mode: "replace" | "append";
|
|
27
|
+
generation: number;
|
|
28
|
+
items: readonly TItem[];
|
|
29
|
+
nextCursor: TCursor | null;
|
|
30
|
+
hasNextPage: boolean;
|
|
31
|
+
} | {
|
|
32
|
+
type: "live";
|
|
33
|
+
items: readonly TItem[];
|
|
34
|
+
} | {
|
|
35
|
+
type: "clear-live";
|
|
36
|
+
} | {
|
|
37
|
+
type: "reset";
|
|
38
|
+
};
|
|
39
|
+
interface RealtimeCursorCollection<TItem, TCursor = unknown> {
|
|
40
|
+
readonly snapshot: RealtimeCursorSnapshot<TItem, TCursor>;
|
|
41
|
+
reduce(snapshot: RealtimeCursorSnapshot<TItem, TCursor>, command: RealtimeCursorCommand<TItem, TCursor>): RealtimeCursorSnapshot<TItem, TCursor>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
declare function createRealtimeCursorCollection<TItem, TCursor = unknown>(policy: RealtimeCursorPolicy<TItem>): RealtimeCursorCollection<TItem, TCursor>;
|
|
45
|
+
|
|
46
|
+
export { type RealtimeCursorCollection, type RealtimeCursorCommand, type RealtimeCursorPolicy, type RealtimeCursorSnapshot, type RealtimeCursorSource, createRealtimeCursorCollection };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
type RealtimeCursorSource = "page" | "live";
|
|
2
|
+
interface RealtimeCursorPolicy<TItem> {
|
|
3
|
+
getKey(item: TItem): string;
|
|
4
|
+
compare(left: TItem, right: TItem): number;
|
|
5
|
+
include(item: TItem): boolean;
|
|
6
|
+
merge(previous: TItem, incoming: TItem, context: {
|
|
7
|
+
previousSource: RealtimeCursorSource;
|
|
8
|
+
incomingSource: RealtimeCursorSource;
|
|
9
|
+
}): {
|
|
10
|
+
item: TItem;
|
|
11
|
+
placement: "previous" | "incoming";
|
|
12
|
+
};
|
|
13
|
+
maxLiveItems?: number;
|
|
14
|
+
maxItems?: number;
|
|
15
|
+
}
|
|
16
|
+
interface RealtimeCursorSnapshot<TItem, TCursor> {
|
|
17
|
+
readonly items: readonly TItem[];
|
|
18
|
+
readonly pageItems: readonly TItem[];
|
|
19
|
+
readonly liveItems: readonly TItem[];
|
|
20
|
+
readonly nextCursor: TCursor | null;
|
|
21
|
+
readonly hasNextPage: boolean;
|
|
22
|
+
readonly generation: number;
|
|
23
|
+
}
|
|
24
|
+
type RealtimeCursorCommand<TItem, TCursor> = {
|
|
25
|
+
type: "page";
|
|
26
|
+
mode: "replace" | "append";
|
|
27
|
+
generation: number;
|
|
28
|
+
items: readonly TItem[];
|
|
29
|
+
nextCursor: TCursor | null;
|
|
30
|
+
hasNextPage: boolean;
|
|
31
|
+
} | {
|
|
32
|
+
type: "live";
|
|
33
|
+
items: readonly TItem[];
|
|
34
|
+
} | {
|
|
35
|
+
type: "clear-live";
|
|
36
|
+
} | {
|
|
37
|
+
type: "reset";
|
|
38
|
+
};
|
|
39
|
+
interface RealtimeCursorCollection<TItem, TCursor = unknown> {
|
|
40
|
+
readonly snapshot: RealtimeCursorSnapshot<TItem, TCursor>;
|
|
41
|
+
reduce(snapshot: RealtimeCursorSnapshot<TItem, TCursor>, command: RealtimeCursorCommand<TItem, TCursor>): RealtimeCursorSnapshot<TItem, TCursor>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
declare function createRealtimeCursorCollection<TItem, TCursor = unknown>(policy: RealtimeCursorPolicy<TItem>): RealtimeCursorCollection<TItem, TCursor>;
|
|
45
|
+
|
|
46
|
+
export { type RealtimeCursorCollection, type RealtimeCursorCommand, type RealtimeCursorPolicy, type RealtimeCursorSnapshot, type RealtimeCursorSource, createRealtimeCursorCollection };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var g=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var b=(e,t)=>{for(var r in t)g(e,r,{get:t[r],enumerable:!0})},K=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of P(t))!h.call(e,n)&&n!==r&&g(e,n,{get:()=>t[n],enumerable:!(o=S(t,n))||o.enumerable});return e};var w=e=>K(g({},"__esModule",{value:!0}),e);var O={};b(O,{createRealtimeCursorCollection:()=>y});module.exports=w(O);var C=Object.freeze([]);function p(e,t){if(t!==void 0&&(typeof t!="number"||!Number.isSafeInteger(t)||t<0))throw new TypeError(`${e} must be a non-negative safe integer or undefined`)}function N(){return I({items:C,pageItems:C,liveItems:C,nextCursor:null,hasNextPage:!1,generation:0})}function I(e){return Object.freeze({items:Object.freeze(e.items),pageItems:Object.freeze(e.pageItems),liveItems:Object.freeze(e.liveItems),nextCursor:e.nextCursor,hasNextPage:e.hasNextPage,generation:e.generation})}function v(e,t){let r=[];for(let o of e)t.include(o)&&r.push(o);return r}function M(e,t,r,o){for(let n=r;n<e.length;n+=1)t.set(o.getKey(e[n]),n)}function x(e,t,r,o,n,i){let u=i.getKey(r),s=t.get(u);if(s===void 0){t.set(u,e.length),e.push(r);return}let c=e[s],m=i.merge(c,r,{previousSource:o,incomingSource:n});if(m.placement==="previous"){e[s]=m.item;return}e.splice(s,1),M(e,t,s,i),t.set(u,e.length),e.push(m.item)}function f(e,t,r){let o=[],n=new Map;for(let i of e)x(o,n,i,t,t,r);return o}function L(e,t,r){let o=new Map;for(let s of t)o.set(r.getKey(s),s);let n=new Map,i=[];for(let s of e){let c=r.getKey(s),m=o.get(c);if(m===void 0){i.push(s);continue}let a=r.merge(m,s,{previousSource:"live",incomingSource:"live"});n.set(c,a),a.placement==="incoming"&&i.push(a.item)}let u=[];for(let s of t){let c=r.getKey(s),m=n.get(c);if(m===void 0){u.push(s);continue}m.placement!=="incoming"&&u.push(m.item)}return[...i,...u]}function R(e,t){return t===void 0?e.slice():t===0?[]:e.length<=t?e.slice():e.slice(0,t)}function j(e,t){return e.map((r,o)=>({item:r,index:o})).sort((r,o)=>{let n=t(r.item,o.item);return n!==0?n:r.index-o.index}).map(r=>r.item)}function d(e,t,r){let o=new Map;for(let m of t)o.set(r.getKey(m),m);let n=new Set,i=[],u=new Map;for(let m of e){let a=r.getKey(m),l=o.get(a);if(l===void 0){i.push(m),n.add(a);continue}let T=r.merge(m,l,{previousSource:"live",incomingSource:"page"});T.placement==="previous"?(i.push(T.item),n.add(a)):u.set(a,T.item)}let s=[];for(let m of t){let a=r.getKey(m),l=u.get(a);if(l!==void 0){s.push(l);continue}n.has(a)||s.push(m)}let c=[...i,...s];return R(j(c,r.compare),r.maxItems)}function k(e,t,r){if(t.generation!==e.generation)return e;let o=v(t.items,r),n;if(t.mode==="replace")n=f(o,"page",r);else{n=e.pageItems.slice();let i=new Map;for(let s=0;s<n.length;s+=1)i.set(r.getKey(n[s]),s);let u=f(o,"page",r);for(let s of u)x(n,i,s,"page","page",r)}return I({items:d(e.liveItems,n,r),pageItems:n,liveItems:e.liveItems.slice(),nextCursor:t.nextCursor,hasNextPage:t.hasNextPage,generation:e.generation})}function z(e,t,r){let o=f(t.items,"live",r),n=v(o,r),i=L(n,e.liveItems,r),u=R(i,r.maxLiveItems);return I({items:d(u,e.pageItems,r),pageItems:e.pageItems.slice(),liveItems:u,nextCursor:e.nextCursor,hasNextPage:e.hasNextPage,generation:e.generation})}function E(e,t,r){switch(t.type){case"page":return k(e,t,r);case"live":return z(e,t,r);case"clear-live":return I({items:d([],e.pageItems,r),pageItems:e.pageItems.slice(),liveItems:[],nextCursor:e.nextCursor,hasNextPage:e.hasNextPage,generation:e.generation});case"reset":return I({items:[],pageItems:[],liveItems:[],nextCursor:null,hasNextPage:!1,generation:e.generation+1});default:return t}}function y(e){return p("maxLiveItems",e.maxLiveItems),p("maxItems",e.maxItems),{snapshot:N(),reduce(t,r){return E(t,r,e)}}}0&&(module.exports={createRealtimeCursorCollection});
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/realtime-cursor-collection/index.ts","../../src/realtime-cursor-collection/realtime-cursor-collection.ts"],"sourcesContent":["export { createRealtimeCursorCollection } from \"./realtime-cursor-collection\";\nexport type {\n RealtimeCursorCollection,\n RealtimeCursorCommand,\n RealtimeCursorPolicy,\n RealtimeCursorSnapshot,\n RealtimeCursorSource,\n} from \"./realtime-cursor-collection.types\";\n","import type {\n RealtimeCursorCollection,\n RealtimeCursorCommand,\n RealtimeCursorPolicy,\n RealtimeCursorSnapshot,\n RealtimeCursorSource,\n} from \"./realtime-cursor-collection.types\";\n\nconst EMPTY_ITEMS: readonly never[] = Object.freeze([]);\n\nfunction assertLimit(\n name: \"maxLiveItems\" | \"maxItems\",\n value: number | undefined,\n): void {\n if (value === undefined) return;\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) {\n throw new TypeError(\n `${name} must be a non-negative safe integer or undefined`,\n );\n }\n}\n\nfunction createEmptySnapshot<TItem, TCursor>(): RealtimeCursorSnapshot<\n TItem,\n TCursor\n> {\n const snapshot: RealtimeCursorSnapshot<TItem, TCursor> = {\n items: EMPTY_ITEMS as readonly TItem[],\n pageItems: EMPTY_ITEMS as readonly TItem[],\n liveItems: EMPTY_ITEMS as readonly TItem[],\n nextCursor: null,\n hasNextPage: false,\n generation: 0,\n };\n return freezeSnapshot(snapshot);\n}\n\nfunction freezeSnapshot<TItem, TCursor>(\n snapshot: RealtimeCursorSnapshot<TItem, TCursor>,\n): RealtimeCursorSnapshot<TItem, TCursor> {\n return Object.freeze({\n items: Object.freeze(snapshot.items),\n pageItems: Object.freeze(snapshot.pageItems),\n liveItems: Object.freeze(snapshot.liveItems),\n nextCursor: snapshot.nextCursor,\n hasNextPage: snapshot.hasNextPage,\n generation: snapshot.generation,\n });\n}\n\nfunction includedItems<TItem>(\n items: readonly TItem[],\n policy: RealtimeCursorPolicy<TItem>,\n): TItem[] {\n const result: TItem[] = [];\n for (const item of items) {\n if (policy.include(item)) result.push(item);\n }\n return result;\n}\n\nfunction reindexKeys<TItem>(\n items: readonly TItem[],\n keyToIndex: Map<string, number>,\n fromIndex: number,\n policy: RealtimeCursorPolicy<TItem>,\n): void {\n for (let index = fromIndex; index < items.length; index += 1) {\n keyToIndex.set(policy.getKey(items[index] as TItem), index);\n }\n}\n\nfunction upsertByKey<TItem>(\n items: TItem[],\n keyToIndex: Map<string, number>,\n incoming: TItem,\n previousSource: RealtimeCursorSource,\n incomingSource: RealtimeCursorSource,\n policy: RealtimeCursorPolicy<TItem>,\n): void {\n const key = policy.getKey(incoming);\n const existingIndex = keyToIndex.get(key);\n if (existingIndex === undefined) {\n keyToIndex.set(key, items.length);\n items.push(incoming);\n return;\n }\n\n const previous = items[existingIndex] as TItem;\n const merged = policy.merge(previous, incoming, {\n previousSource,\n incomingSource,\n });\n if (merged.placement === \"previous\") {\n items[existingIndex] = merged.item;\n return;\n }\n\n items.splice(existingIndex, 1);\n reindexKeys(items, keyToIndex, existingIndex, policy);\n keyToIndex.set(key, items.length);\n items.push(merged.item);\n}\n\nfunction foldSameSourceItems<TItem>(\n items: readonly TItem[],\n source: RealtimeCursorSource,\n policy: RealtimeCursorPolicy<TItem>,\n): TItem[] {\n const result: TItem[] = [];\n const keyToIndex = new Map<string, number>();\n for (const item of items) {\n upsertByKey(result, keyToIndex, item, source, source, policy);\n }\n return result;\n}\n\nfunction prependLive<TItem>(\n incoming: readonly TItem[],\n previousLive: readonly TItem[],\n policy: RealtimeCursorPolicy<TItem>,\n): TItem[] {\n const previousByKey = new Map<string, TItem>();\n for (const item of previousLive) {\n previousByKey.set(policy.getKey(item), item);\n }\n\n const decisions = new Map<\n string,\n { item: TItem; placement: \"previous\" | \"incoming\" }\n >();\n const front: TItem[] = [];\n\n for (const incomingItem of incoming) {\n const key = policy.getKey(incomingItem);\n const previous = previousByKey.get(key);\n if (previous === undefined) {\n front.push(incomingItem);\n continue;\n }\n const merged = policy.merge(previous, incomingItem, {\n previousSource: \"live\",\n incomingSource: \"live\",\n });\n decisions.set(key, merged);\n if (merged.placement === \"incoming\") {\n front.push(merged.item);\n }\n }\n\n const back: TItem[] = [];\n for (const previousItem of previousLive) {\n const key = policy.getKey(previousItem);\n const decision = decisions.get(key);\n if (decision === undefined) {\n back.push(previousItem);\n continue;\n }\n if (decision.placement === \"incoming\") continue;\n back.push(decision.item);\n }\n\n return [...front, ...back];\n}\n\nfunction truncateItems<TItem>(\n items: readonly TItem[],\n limit: number | undefined,\n): TItem[] {\n if (limit === undefined) return items.slice();\n if (limit === 0) return [];\n if (items.length <= limit) return items.slice();\n return items.slice(0, limit);\n}\n\nfunction stableSort<TItem>(\n items: readonly TItem[],\n compare: (left: TItem, right: TItem) => number,\n): TItem[] {\n return items\n .map((item, index) => ({ item, index }))\n .sort((left, right) => {\n const result = compare(left.item, right.item);\n if (result !== 0) return result;\n return left.index - right.index;\n })\n .map((entry) => entry.item);\n}\n\nfunction projectVisible<TItem>(\n liveItems: readonly TItem[],\n pageItems: readonly TItem[],\n policy: RealtimeCursorPolicy<TItem>,\n): TItem[] {\n const pageByKey = new Map<string, TItem>();\n for (const item of pageItems) {\n pageByKey.set(policy.getKey(item), item);\n }\n\n const liveKeysPlaced = new Set<string>();\n const livePart: TItem[] = [];\n const pageOverride = new Map<string, TItem>();\n\n for (const liveItem of liveItems) {\n const key = policy.getKey(liveItem);\n const pageItem = pageByKey.get(key);\n if (pageItem === undefined) {\n livePart.push(liveItem);\n liveKeysPlaced.add(key);\n continue;\n }\n const merged = policy.merge(liveItem, pageItem, {\n previousSource: \"live\",\n incomingSource: \"page\",\n });\n if (merged.placement === \"previous\") {\n livePart.push(merged.item);\n liveKeysPlaced.add(key);\n } else {\n pageOverride.set(key, merged.item);\n }\n }\n\n const pagePart: TItem[] = [];\n for (const pageItem of pageItems) {\n const key = policy.getKey(pageItem);\n const overridden = pageOverride.get(key);\n if (overridden !== undefined) {\n pagePart.push(overridden);\n continue;\n }\n if (liveKeysPlaced.has(key)) continue;\n pagePart.push(pageItem);\n }\n\n const candidates = [...livePart, ...pagePart];\n return truncateItems(stableSort(candidates, policy.compare), policy.maxItems);\n}\n\nfunction reducePage<TItem, TCursor>(\n snapshot: RealtimeCursorSnapshot<TItem, TCursor>,\n command: Extract<RealtimeCursorCommand<TItem, TCursor>, { type: \"page\" }>,\n policy: RealtimeCursorPolicy<TItem>,\n): RealtimeCursorSnapshot<TItem, TCursor> {\n if (command.generation !== snapshot.generation) return snapshot;\n\n const included = includedItems(command.items, policy);\n let pageItems: TItem[];\n if (command.mode === \"replace\") {\n pageItems = foldSameSourceItems(included, \"page\", policy);\n } else {\n pageItems = snapshot.pageItems.slice();\n const keyToIndex = new Map<string, number>();\n for (let index = 0; index < pageItems.length; index += 1) {\n keyToIndex.set(policy.getKey(pageItems[index] as TItem), index);\n }\n const incoming = foldSameSourceItems(included, \"page\", policy);\n for (const item of incoming) {\n upsertByKey(pageItems, keyToIndex, item, \"page\", \"page\", policy);\n }\n }\n\n return freezeSnapshot({\n items: projectVisible(snapshot.liveItems, pageItems, policy),\n pageItems,\n liveItems: snapshot.liveItems.slice(),\n nextCursor: command.nextCursor,\n hasNextPage: command.hasNextPage,\n generation: snapshot.generation,\n });\n}\n\nfunction reduceLive<TItem, TCursor>(\n snapshot: RealtimeCursorSnapshot<TItem, TCursor>,\n command: Extract<RealtimeCursorCommand<TItem, TCursor>, { type: \"live\" }>,\n policy: RealtimeCursorPolicy<TItem>,\n): RealtimeCursorSnapshot<TItem, TCursor> {\n const folded = foldSameSourceItems(command.items, \"live\", policy);\n const included = includedItems(folded, policy);\n const mergedLive = prependLive(included, snapshot.liveItems, policy);\n const liveItems = truncateItems(mergedLive, policy.maxLiveItems);\n\n return freezeSnapshot({\n items: projectVisible(liveItems, snapshot.pageItems, policy),\n pageItems: snapshot.pageItems.slice(),\n liveItems,\n nextCursor: snapshot.nextCursor,\n hasNextPage: snapshot.hasNextPage,\n generation: snapshot.generation,\n });\n}\n\nfunction reduceRealtimeCursorCollection<TItem, TCursor>(\n snapshot: RealtimeCursorSnapshot<TItem, TCursor>,\n command: RealtimeCursorCommand<TItem, TCursor>,\n policy: RealtimeCursorPolicy<TItem>,\n): RealtimeCursorSnapshot<TItem, TCursor> {\n switch (command.type) {\n case \"page\":\n return reducePage(snapshot, command, policy);\n case \"live\":\n return reduceLive(snapshot, command, policy);\n case \"clear-live\":\n return freezeSnapshot({\n items: projectVisible([], snapshot.pageItems, policy),\n pageItems: snapshot.pageItems.slice(),\n liveItems: [],\n nextCursor: snapshot.nextCursor,\n hasNextPage: snapshot.hasNextPage,\n generation: snapshot.generation,\n });\n case \"reset\":\n return freezeSnapshot<TItem, TCursor>({\n items: [],\n pageItems: [],\n liveItems: [],\n nextCursor: null,\n hasNextPage: false,\n generation: snapshot.generation + 1,\n });\n default: {\n const exhaustive: never = command;\n return exhaustive;\n }\n }\n}\n\nexport function createRealtimeCursorCollection<TItem, TCursor = unknown>(\n policy: RealtimeCursorPolicy<TItem>,\n): RealtimeCursorCollection<TItem, TCursor> {\n assertLimit(\"maxLiveItems\", policy.maxLiveItems);\n assertLimit(\"maxItems\", policy.maxItems);\n\n return {\n snapshot: createEmptySnapshot<TItem, TCursor>(),\n reduce(snapshot, command) {\n return reduceRealtimeCursorCollection(snapshot, command, policy);\n },\n };\n}\n"],"mappings":"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","names":["realtime_cursor_collection_exports","__export","createRealtimeCursorCollection","__toCommonJS","EMPTY_ITEMS","assertLimit","name","value","createEmptySnapshot","freezeSnapshot","snapshot","includedItems","items","policy","result","item","reindexKeys","keyToIndex","fromIndex","index","upsertByKey","incoming","previousSource","incomingSource","key","existingIndex","previous","merged","foldSameSourceItems","source","prependLive","previousLive","previousByKey","decisions","front","incomingItem","back","previousItem","decision","truncateItems","limit","stableSort","compare","left","right","entry","projectVisible","liveItems","pageItems","pageByKey","liveKeysPlaced","livePart","pageOverride","liveItem","pageItem","pagePart","overridden","candidates","reducePage","command","included","reduceLive","folded","mergedLive","reduceRealtimeCursorCollection","createRealtimeCursorCollection"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var g=Object.freeze([]);function d(e,r){if(r!==void 0&&(typeof r!="number"||!Number.isSafeInteger(r)||r<0))throw new TypeError(`${e} must be a non-negative safe integer or undefined`)}function R(){return I({items:g,pageItems:g,liveItems:g,nextCursor:null,hasNextPage:!1,generation:0})}function I(e){return Object.freeze({items:Object.freeze(e.items),pageItems:Object.freeze(e.pageItems),liveItems:Object.freeze(e.liveItems),nextCursor:e.nextCursor,hasNextPage:e.hasNextPage,generation:e.generation})}function p(e,r){let t=[];for(let o of e)r.include(o)&&t.push(o);return t}function y(e,r,t,o){for(let n=t;n<e.length;n+=1)r.set(o.getKey(e[n]),n)}function v(e,r,t,o,n,i){let u=i.getKey(t),s=r.get(u);if(s===void 0){r.set(u,e.length),e.push(t);return}let c=e[s],m=i.merge(c,t,{previousSource:o,incomingSource:n});if(m.placement==="previous"){e[s]=m.item;return}e.splice(s,1),y(e,r,s,i),r.set(u,e.length),e.push(m.item)}function C(e,r,t){let o=[],n=new Map;for(let i of e)v(o,n,i,r,r,t);return o}function S(e,r,t){let o=new Map;for(let s of r)o.set(t.getKey(s),s);let n=new Map,i=[];for(let s of e){let c=t.getKey(s),m=o.get(c);if(m===void 0){i.push(s);continue}let a=t.merge(m,s,{previousSource:"live",incomingSource:"live"});n.set(c,a),a.placement==="incoming"&&i.push(a.item)}let u=[];for(let s of r){let c=t.getKey(s),m=n.get(c);if(m===void 0){u.push(s);continue}m.placement!=="incoming"&&u.push(m.item)}return[...i,...u]}function x(e,r){return r===void 0?e.slice():r===0?[]:e.length<=r?e.slice():e.slice(0,r)}function P(e,r){return e.map((t,o)=>({item:t,index:o})).sort((t,o)=>{let n=r(t.item,o.item);return n!==0?n:t.index-o.index}).map(t=>t.item)}function f(e,r,t){let o=new Map;for(let m of r)o.set(t.getKey(m),m);let n=new Set,i=[],u=new Map;for(let m of e){let a=t.getKey(m),l=o.get(a);if(l===void 0){i.push(m),n.add(a);continue}let T=t.merge(m,l,{previousSource:"live",incomingSource:"page"});T.placement==="previous"?(i.push(T.item),n.add(a)):u.set(a,T.item)}let s=[];for(let m of r){let a=t.getKey(m),l=u.get(a);if(l!==void 0){s.push(l);continue}n.has(a)||s.push(m)}let c=[...i,...s];return x(P(c,t.compare),t.maxItems)}function h(e,r,t){if(r.generation!==e.generation)return e;let o=p(r.items,t),n;if(r.mode==="replace")n=C(o,"page",t);else{n=e.pageItems.slice();let i=new Map;for(let s=0;s<n.length;s+=1)i.set(t.getKey(n[s]),s);let u=C(o,"page",t);for(let s of u)v(n,i,s,"page","page",t)}return I({items:f(e.liveItems,n,t),pageItems:n,liveItems:e.liveItems.slice(),nextCursor:r.nextCursor,hasNextPage:r.hasNextPage,generation:e.generation})}function b(e,r,t){let o=C(r.items,"live",t),n=p(o,t),i=S(n,e.liveItems,t),u=x(i,t.maxLiveItems);return I({items:f(u,e.pageItems,t),pageItems:e.pageItems.slice(),liveItems:u,nextCursor:e.nextCursor,hasNextPage:e.hasNextPage,generation:e.generation})}function K(e,r,t){switch(r.type){case"page":return h(e,r,t);case"live":return b(e,r,t);case"clear-live":return I({items:f([],e.pageItems,t),pageItems:e.pageItems.slice(),liveItems:[],nextCursor:e.nextCursor,hasNextPage:e.hasNextPage,generation:e.generation});case"reset":return I({items:[],pageItems:[],liveItems:[],nextCursor:null,hasNextPage:!1,generation:e.generation+1});default:return r}}function w(e){return d("maxLiveItems",e.maxLiveItems),d("maxItems",e.maxItems),{snapshot:R(),reduce(r,t){return K(r,t,e)}}}export{w as createRealtimeCursorCollection};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/realtime-cursor-collection/realtime-cursor-collection.ts"],"sourcesContent":["import type {\n RealtimeCursorCollection,\n RealtimeCursorCommand,\n RealtimeCursorPolicy,\n RealtimeCursorSnapshot,\n RealtimeCursorSource,\n} from \"./realtime-cursor-collection.types\";\n\nconst EMPTY_ITEMS: readonly never[] = Object.freeze([]);\n\nfunction assertLimit(\n name: \"maxLiveItems\" | \"maxItems\",\n value: number | undefined,\n): void {\n if (value === undefined) return;\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) {\n throw new TypeError(\n `${name} must be a non-negative safe integer or undefined`,\n );\n }\n}\n\nfunction createEmptySnapshot<TItem, TCursor>(): RealtimeCursorSnapshot<\n TItem,\n TCursor\n> {\n const snapshot: RealtimeCursorSnapshot<TItem, TCursor> = {\n items: EMPTY_ITEMS as readonly TItem[],\n pageItems: EMPTY_ITEMS as readonly TItem[],\n liveItems: EMPTY_ITEMS as readonly TItem[],\n nextCursor: null,\n hasNextPage: false,\n generation: 0,\n };\n return freezeSnapshot(snapshot);\n}\n\nfunction freezeSnapshot<TItem, TCursor>(\n snapshot: RealtimeCursorSnapshot<TItem, TCursor>,\n): RealtimeCursorSnapshot<TItem, TCursor> {\n return Object.freeze({\n items: Object.freeze(snapshot.items),\n pageItems: Object.freeze(snapshot.pageItems),\n liveItems: Object.freeze(snapshot.liveItems),\n nextCursor: snapshot.nextCursor,\n hasNextPage: snapshot.hasNextPage,\n generation: snapshot.generation,\n });\n}\n\nfunction includedItems<TItem>(\n items: readonly TItem[],\n policy: RealtimeCursorPolicy<TItem>,\n): TItem[] {\n const result: TItem[] = [];\n for (const item of items) {\n if (policy.include(item)) result.push(item);\n }\n return result;\n}\n\nfunction reindexKeys<TItem>(\n items: readonly TItem[],\n keyToIndex: Map<string, number>,\n fromIndex: number,\n policy: RealtimeCursorPolicy<TItem>,\n): void {\n for (let index = fromIndex; index < items.length; index += 1) {\n keyToIndex.set(policy.getKey(items[index] as TItem), index);\n }\n}\n\nfunction upsertByKey<TItem>(\n items: TItem[],\n keyToIndex: Map<string, number>,\n incoming: TItem,\n previousSource: RealtimeCursorSource,\n incomingSource: RealtimeCursorSource,\n policy: RealtimeCursorPolicy<TItem>,\n): void {\n const key = policy.getKey(incoming);\n const existingIndex = keyToIndex.get(key);\n if (existingIndex === undefined) {\n keyToIndex.set(key, items.length);\n items.push(incoming);\n return;\n }\n\n const previous = items[existingIndex] as TItem;\n const merged = policy.merge(previous, incoming, {\n previousSource,\n incomingSource,\n });\n if (merged.placement === \"previous\") {\n items[existingIndex] = merged.item;\n return;\n }\n\n items.splice(existingIndex, 1);\n reindexKeys(items, keyToIndex, existingIndex, policy);\n keyToIndex.set(key, items.length);\n items.push(merged.item);\n}\n\nfunction foldSameSourceItems<TItem>(\n items: readonly TItem[],\n source: RealtimeCursorSource,\n policy: RealtimeCursorPolicy<TItem>,\n): TItem[] {\n const result: TItem[] = [];\n const keyToIndex = new Map<string, number>();\n for (const item of items) {\n upsertByKey(result, keyToIndex, item, source, source, policy);\n }\n return result;\n}\n\nfunction prependLive<TItem>(\n incoming: readonly TItem[],\n previousLive: readonly TItem[],\n policy: RealtimeCursorPolicy<TItem>,\n): TItem[] {\n const previousByKey = new Map<string, TItem>();\n for (const item of previousLive) {\n previousByKey.set(policy.getKey(item), item);\n }\n\n const decisions = new Map<\n string,\n { item: TItem; placement: \"previous\" | \"incoming\" }\n >();\n const front: TItem[] = [];\n\n for (const incomingItem of incoming) {\n const key = policy.getKey(incomingItem);\n const previous = previousByKey.get(key);\n if (previous === undefined) {\n front.push(incomingItem);\n continue;\n }\n const merged = policy.merge(previous, incomingItem, {\n previousSource: \"live\",\n incomingSource: \"live\",\n });\n decisions.set(key, merged);\n if (merged.placement === \"incoming\") {\n front.push(merged.item);\n }\n }\n\n const back: TItem[] = [];\n for (const previousItem of previousLive) {\n const key = policy.getKey(previousItem);\n const decision = decisions.get(key);\n if (decision === undefined) {\n back.push(previousItem);\n continue;\n }\n if (decision.placement === \"incoming\") continue;\n back.push(decision.item);\n }\n\n return [...front, ...back];\n}\n\nfunction truncateItems<TItem>(\n items: readonly TItem[],\n limit: number | undefined,\n): TItem[] {\n if (limit === undefined) return items.slice();\n if (limit === 0) return [];\n if (items.length <= limit) return items.slice();\n return items.slice(0, limit);\n}\n\nfunction stableSort<TItem>(\n items: readonly TItem[],\n compare: (left: TItem, right: TItem) => number,\n): TItem[] {\n return items\n .map((item, index) => ({ item, index }))\n .sort((left, right) => {\n const result = compare(left.item, right.item);\n if (result !== 0) return result;\n return left.index - right.index;\n })\n .map((entry) => entry.item);\n}\n\nfunction projectVisible<TItem>(\n liveItems: readonly TItem[],\n pageItems: readonly TItem[],\n policy: RealtimeCursorPolicy<TItem>,\n): TItem[] {\n const pageByKey = new Map<string, TItem>();\n for (const item of pageItems) {\n pageByKey.set(policy.getKey(item), item);\n }\n\n const liveKeysPlaced = new Set<string>();\n const livePart: TItem[] = [];\n const pageOverride = new Map<string, TItem>();\n\n for (const liveItem of liveItems) {\n const key = policy.getKey(liveItem);\n const pageItem = pageByKey.get(key);\n if (pageItem === undefined) {\n livePart.push(liveItem);\n liveKeysPlaced.add(key);\n continue;\n }\n const merged = policy.merge(liveItem, pageItem, {\n previousSource: \"live\",\n incomingSource: \"page\",\n });\n if (merged.placement === \"previous\") {\n livePart.push(merged.item);\n liveKeysPlaced.add(key);\n } else {\n pageOverride.set(key, merged.item);\n }\n }\n\n const pagePart: TItem[] = [];\n for (const pageItem of pageItems) {\n const key = policy.getKey(pageItem);\n const overridden = pageOverride.get(key);\n if (overridden !== undefined) {\n pagePart.push(overridden);\n continue;\n }\n if (liveKeysPlaced.has(key)) continue;\n pagePart.push(pageItem);\n }\n\n const candidates = [...livePart, ...pagePart];\n return truncateItems(stableSort(candidates, policy.compare), policy.maxItems);\n}\n\nfunction reducePage<TItem, TCursor>(\n snapshot: RealtimeCursorSnapshot<TItem, TCursor>,\n command: Extract<RealtimeCursorCommand<TItem, TCursor>, { type: \"page\" }>,\n policy: RealtimeCursorPolicy<TItem>,\n): RealtimeCursorSnapshot<TItem, TCursor> {\n if (command.generation !== snapshot.generation) return snapshot;\n\n const included = includedItems(command.items, policy);\n let pageItems: TItem[];\n if (command.mode === \"replace\") {\n pageItems = foldSameSourceItems(included, \"page\", policy);\n } else {\n pageItems = snapshot.pageItems.slice();\n const keyToIndex = new Map<string, number>();\n for (let index = 0; index < pageItems.length; index += 1) {\n keyToIndex.set(policy.getKey(pageItems[index] as TItem), index);\n }\n const incoming = foldSameSourceItems(included, \"page\", policy);\n for (const item of incoming) {\n upsertByKey(pageItems, keyToIndex, item, \"page\", \"page\", policy);\n }\n }\n\n return freezeSnapshot({\n items: projectVisible(snapshot.liveItems, pageItems, policy),\n pageItems,\n liveItems: snapshot.liveItems.slice(),\n nextCursor: command.nextCursor,\n hasNextPage: command.hasNextPage,\n generation: snapshot.generation,\n });\n}\n\nfunction reduceLive<TItem, TCursor>(\n snapshot: RealtimeCursorSnapshot<TItem, TCursor>,\n command: Extract<RealtimeCursorCommand<TItem, TCursor>, { type: \"live\" }>,\n policy: RealtimeCursorPolicy<TItem>,\n): RealtimeCursorSnapshot<TItem, TCursor> {\n const folded = foldSameSourceItems(command.items, \"live\", policy);\n const included = includedItems(folded, policy);\n const mergedLive = prependLive(included, snapshot.liveItems, policy);\n const liveItems = truncateItems(mergedLive, policy.maxLiveItems);\n\n return freezeSnapshot({\n items: projectVisible(liveItems, snapshot.pageItems, policy),\n pageItems: snapshot.pageItems.slice(),\n liveItems,\n nextCursor: snapshot.nextCursor,\n hasNextPage: snapshot.hasNextPage,\n generation: snapshot.generation,\n });\n}\n\nfunction reduceRealtimeCursorCollection<TItem, TCursor>(\n snapshot: RealtimeCursorSnapshot<TItem, TCursor>,\n command: RealtimeCursorCommand<TItem, TCursor>,\n policy: RealtimeCursorPolicy<TItem>,\n): RealtimeCursorSnapshot<TItem, TCursor> {\n switch (command.type) {\n case \"page\":\n return reducePage(snapshot, command, policy);\n case \"live\":\n return reduceLive(snapshot, command, policy);\n case \"clear-live\":\n return freezeSnapshot({\n items: projectVisible([], snapshot.pageItems, policy),\n pageItems: snapshot.pageItems.slice(),\n liveItems: [],\n nextCursor: snapshot.nextCursor,\n hasNextPage: snapshot.hasNextPage,\n generation: snapshot.generation,\n });\n case \"reset\":\n return freezeSnapshot<TItem, TCursor>({\n items: [],\n pageItems: [],\n liveItems: [],\n nextCursor: null,\n hasNextPage: false,\n generation: snapshot.generation + 1,\n });\n default: {\n const exhaustive: never = command;\n return exhaustive;\n }\n }\n}\n\nexport function createRealtimeCursorCollection<TItem, TCursor = unknown>(\n policy: RealtimeCursorPolicy<TItem>,\n): RealtimeCursorCollection<TItem, TCursor> {\n assertLimit(\"maxLiveItems\", policy.maxLiveItems);\n assertLimit(\"maxItems\", policy.maxItems);\n\n return {\n snapshot: createEmptySnapshot<TItem, TCursor>(),\n reduce(snapshot, command) {\n return reduceRealtimeCursorCollection(snapshot, command, policy);\n },\n };\n}\n"],"mappings":"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","names":["EMPTY_ITEMS","assertLimit","name","value","createEmptySnapshot","freezeSnapshot","snapshot","includedItems","items","policy","result","item","reindexKeys","keyToIndex","fromIndex","index","upsertByKey","incoming","previousSource","incomingSource","key","existingIndex","previous","merged","foldSameSourceItems","source","prependLive","previousLive","previousByKey","decisions","front","incomingItem","back","previousItem","decision","truncateItems","limit","stableSort","compare","left","right","entry","projectVisible","liveItems","pageItems","pageByKey","liveKeysPlaced","livePart","pageOverride","liveItem","pageItem","pagePart","overridden","candidates","reducePage","command","included","reduceLive","folded","mergedLive","reduceRealtimeCursorCollection","createRealtimeCursorCollection"]}
|
package/package.json
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liberfi.io/utils",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.73",
|
|
4
4
|
"description": "Liberfi React SDK utils",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": {
|
|
10
|
+
"types": "./dist/index.d.mts",
|
|
11
|
+
"default": "./dist/index.mjs"
|
|
12
|
+
},
|
|
13
|
+
"require": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"./realtime-cursor-collection": {
|
|
19
|
+
"import": {
|
|
20
|
+
"types": "./dist/realtime-cursor-collection/index.d.mts",
|
|
21
|
+
"default": "./dist/realtime-cursor-collection/index.mjs"
|
|
22
|
+
},
|
|
23
|
+
"require": {
|
|
24
|
+
"types": "./dist/realtime-cursor-collection/index.d.ts",
|
|
25
|
+
"default": "./dist/realtime-cursor-collection/index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
7
30
|
"keywords": [],
|
|
8
31
|
"files": [
|
|
9
32
|
"dist"
|
|
@@ -15,11 +38,11 @@
|
|
|
15
38
|
"ts-jest": "^29.4.0",
|
|
16
39
|
"tsup": "^8.5.0",
|
|
17
40
|
"typescript": "^5.9.2",
|
|
18
|
-
"tsconfig": "0.1.
|
|
41
|
+
"tsconfig": "0.1.257"
|
|
19
42
|
},
|
|
20
43
|
"dependencies": {
|
|
21
44
|
"bignumber.js": "^9.3.1",
|
|
22
|
-
"@liberfi.io/types": "0.4.
|
|
45
|
+
"@liberfi.io/types": "0.4.74"
|
|
23
46
|
},
|
|
24
47
|
"publishConfig": {
|
|
25
48
|
"access": "public"
|
|
@@ -27,6 +50,8 @@
|
|
|
27
50
|
"scripts": {
|
|
28
51
|
"dev": "tsup --watch",
|
|
29
52
|
"build": "tsup",
|
|
30
|
-
"
|
|
53
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
54
|
+
"lint": "eslint src",
|
|
55
|
+
"test": "jest --detectOpenHandles"
|
|
31
56
|
}
|
|
32
57
|
}
|