@instantdb/core
Advanced tools
Comparing version 0.3.393 to 0.3.394
@@ -0,2 +1,4 @@ | ||
export function getAttrByFwdIdentName(attrs: any, inputEtype: any, inputIdentName: any): any; | ||
export function getAttrByReverseIdentName(attrs: any, inputEtype: any, inputIdentName: any): any; | ||
export function transform(attrs: any, inputChunks: any): any[]; | ||
//# sourceMappingURL=instaml.d.ts.map |
@@ -6,3 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.transform = void 0; | ||
exports.transform = exports.getAttrByReverseIdentName = exports.getAttrByFwdIdentName = void 0; | ||
const instatx_1 = require("./instatx"); | ||
@@ -16,2 +16,3 @@ const uuid_1 = __importDefault(require("./utils/uuid")); | ||
} | ||
exports.getAttrByFwdIdentName = getAttrByFwdIdentName; | ||
function getAttrByReverseIdentName(attrs, inputEtype, inputIdentName) { | ||
@@ -26,2 +27,3 @@ return Object.values(attrs).find((attr) => { | ||
} | ||
exports.getAttrByReverseIdentName = getAttrByReverseIdentName; | ||
function expandLink(attrs, [etype, eidA, obj]) { | ||
@@ -28,0 +30,0 @@ return Object.entries(obj).map(([label, eidB]) => { |
@@ -0,2 +1,4 @@ | ||
export function getAttrByFwdIdentName(attrs: any, inputEtype: any, inputIdentName: any): any; | ||
export function getAttrByReverseIdentName(attrs: any, inputEtype: any, inputIdentName: any): any; | ||
export function transform(attrs: any, inputChunks: any): any[]; | ||
//# sourceMappingURL=instaml.d.ts.map |
import { getOps } from "./instatx"; | ||
import uuid from "./utils/uuid"; | ||
function getAttrByFwdIdentName(attrs, inputEtype, inputIdentName) { | ||
export function getAttrByFwdIdentName(attrs, inputEtype, inputIdentName) { | ||
return Object.values(attrs).find((attr) => { | ||
@@ -9,3 +9,3 @@ const [_id, etype, label] = attr["forward-identity"]; | ||
} | ||
function getAttrByReverseIdentName(attrs, inputEtype, inputIdentName) { | ||
export function getAttrByReverseIdentName(attrs, inputEtype, inputIdentName) { | ||
return Object.values(attrs).find((attr) => { | ||
@@ -12,0 +12,0 @@ const revIdent = attr["reverse-identity"]; |
@@ -27,3 +27,3 @@ export default class ReactiveDB { | ||
/** | ||
* On refresh we clear out penidng mutations that we know have been applied | ||
* On refresh we clear out pending mutations that we know have been applied | ||
* by the server and thus those mutations are applied in the instaql result | ||
@@ -46,2 +46,3 @@ * returned by the server | ||
subscribeQuery(q: any, cb: any): () => void; | ||
_rewriteMutations(attrs: any, muts: any): any; | ||
optimisticAttrs(): any; | ||
@@ -78,3 +79,2 @@ /** Runs instaql on a query and a store */ | ||
_wsOnClose: () => void; | ||
_reconnectTimeoutMss: number; | ||
_startSocket(): void; | ||
@@ -81,0 +81,0 @@ } |
@@ -133,3 +133,4 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
this.pendingMutations.set((_) => ret); | ||
storageMuts.forEach((mut, k) => { | ||
const rewrittenStorageMuts = this._rewriteMutations(this.attrs, storageMuts); | ||
rewrittenStorageMuts.forEach((mut, k) => { | ||
if (!inMemoryMuts.has(k) && !mut["tx-id"]) { | ||
@@ -150,3 +151,2 @@ this._sendMutation(k, mut); | ||
this.status = STATUS.OPENED; | ||
this._reconnectTimeoutMs = 0; | ||
this._forceSend(uuid(), { | ||
@@ -165,3 +165,3 @@ op: "init", | ||
this.status = STATUS.CLOSED; | ||
this._reconnectTimeoutMss = Math.min(this._reconnectTimeoutMs + 1000, 10000); | ||
this._reconnectTimeoutMs = Math.min(this._reconnectTimeoutMs + 1000, 10000); | ||
log.info("[socket-close] scheduling reconnect", this._reconnectTimeoutMs); | ||
@@ -212,3 +212,3 @@ setTimeout(() => { | ||
/** | ||
* On refresh we clear out penidng mutations that we know have been applied | ||
* On refresh we clear out pending mutations that we know have been applied | ||
* by the server and thus those mutations are applied in the instaql result | ||
@@ -232,2 +232,3 @@ * returned by the server | ||
this.status = STATUS.AUTHENTICATED; | ||
this._reconnectTimeoutMs = 0; | ||
this._setAttrs(msg.attrs); | ||
@@ -267,7 +268,11 @@ this._flushPendingMessages(); | ||
const { "client-event-id": eventId, "tx-id": txId } = msg; | ||
const prevMutation = this.pendingMutations.currentValue.get(eventId); | ||
const muts = this._rewriteMutations(this.attrs, this.pendingMutations.currentValue); | ||
const prevMutation = muts.get(eventId); | ||
if (!prevMutation) { | ||
break; | ||
} | ||
prevMutation["tx-id"] = txId; | ||
this.pendingMutations.set((prev) => { | ||
prev.set(eventId, Object.assign(Object.assign({}, prevMutation), { "tx-id": txId })); | ||
return prev; | ||
}); | ||
const newAttrs = prevMutation["tx-steps"] | ||
@@ -335,2 +340,54 @@ .filter(([action, ..._args]) => action === "add-attr") | ||
} | ||
// (XXX) | ||
// There is a race condition: | ||
// When we `pushTx`, it's possible that we don't yet have `this.attrs` | ||
// This means that `tx-steps` in `pendingMutations` will include `add-attr` | ||
// commands for attrs that already exist. | ||
// | ||
// This will also affect `add-triple` and `retract-triple` which | ||
// reference attr-ids that do not match the server. | ||
// | ||
// We fix this by rewriting `tx-steps` in each `pendingMutation`. | ||
// We remove `add-attr` commands for attrs that already exist. | ||
// We update `add-triple` and `retract-triple` commands to use the | ||
// server attr-ids. | ||
_rewriteMutations(attrs, muts) { | ||
if (!attrs) | ||
return muts; | ||
const findExistingAttr = ([action, attr]) => { | ||
if (action !== "add-attr") { | ||
return; | ||
} | ||
const [_, etype, label] = attr["forward-identity"]; | ||
const existing = instaml.getAttrByFwdIdentName(attrs, etype, label); | ||
return existing; | ||
}; | ||
const rewriteTxSteps = (mapping, txSteps) => { | ||
return txSteps.reduce(([mapping, retTxSteps], txStep) => { | ||
// Handles add-attr | ||
// If existing, we drop it, and track it | ||
// to update add/retract triples | ||
const existing = findExistingAttr(txStep); | ||
if (existing) { | ||
const [_action, attr] = txStep; | ||
mapping[attr.id] = existing.id; | ||
return [mapping, retTxSteps]; | ||
} | ||
// Handles add-triple|retract-triple | ||
// If in mapping, we update the attr-id | ||
const [action, eid, attrId, ...rest] = txStep; | ||
const newTxStep = mapping[attrId] | ||
? [action, eid, mapping[attrId], ...rest] | ||
: txStep; | ||
retTxSteps.push(newTxStep); | ||
return [mapping, retTxSteps]; | ||
}, [mapping, []]); | ||
}; | ||
const [_, __, rewritten] = [...muts.entries()].reduce(([attrs, mapping, newMuts], [k, mut]) => { | ||
const [newMapping, newTxSteps] = rewriteTxSteps(mapping, mut["tx-steps"]); | ||
newMuts.set(k, Object.assign(Object.assign({}, mut), { "tx-steps": newTxSteps })); | ||
return [attrs, newMapping, newMuts]; | ||
}, [attrs, {}, new Map()]); | ||
return rewritten; | ||
} | ||
// --------------------------- | ||
@@ -352,3 +409,4 @@ // Transact | ||
dataForResult(q, { store }) { | ||
const txSteps = [...this.pendingMutations.currentValue.values()].flatMap((x) => x["tx-steps"]); | ||
const muts = this._rewriteMutations(store.attrs, this.pendingMutations.currentValue); | ||
const txSteps = [...muts.values()].flatMap((x) => x["tx-steps"]); | ||
const newStore = s.transact(store, txSteps); | ||
@@ -409,3 +467,4 @@ const data = instaql(newStore, q); | ||
}); | ||
this.pendingMutations.currentValue.forEach((mut, eventId) => { | ||
const muts = this._rewriteMutations(this.attrs, this.pendingMutations.currentValue); | ||
muts.forEach((mut, eventId) => { | ||
if (!mut["tx-id"]) { | ||
@@ -412,0 +471,0 @@ this._sendMutation(eventId, mut); |
@@ -27,3 +27,3 @@ export default class ReactiveDB { | ||
/** | ||
* On refresh we clear out penidng mutations that we know have been applied | ||
* On refresh we clear out pending mutations that we know have been applied | ||
* by the server and thus those mutations are applied in the instaql result | ||
@@ -46,2 +46,3 @@ * returned by the server | ||
subscribeQuery(q: any, cb: any): () => void; | ||
_rewriteMutations(attrs: any, muts: any): any; | ||
optimisticAttrs(): any; | ||
@@ -78,3 +79,2 @@ /** Runs instaql on a query and a store */ | ||
_wsOnClose: () => void; | ||
_reconnectTimeoutMss: number; | ||
_startSocket(): void; | ||
@@ -81,0 +81,0 @@ } |
@@ -161,3 +161,4 @@ "use strict"; | ||
this.pendingMutations.set((_) => ret); | ||
storageMuts.forEach((mut, k) => { | ||
const rewrittenStorageMuts = this._rewriteMutations(this.attrs, storageMuts); | ||
rewrittenStorageMuts.forEach((mut, k) => { | ||
if (!inMemoryMuts.has(k) && !mut["tx-id"]) { | ||
@@ -178,3 +179,2 @@ this._sendMutation(k, mut); | ||
this.status = STATUS.OPENED; | ||
this._reconnectTimeoutMs = 0; | ||
this._forceSend((0, uuid_1.default)(), { | ||
@@ -193,3 +193,3 @@ op: "init", | ||
this.status = STATUS.CLOSED; | ||
this._reconnectTimeoutMss = Math.min(this._reconnectTimeoutMs + 1000, 10000); | ||
this._reconnectTimeoutMs = Math.min(this._reconnectTimeoutMs + 1000, 10000); | ||
log_1.default.info("[socket-close] scheduling reconnect", this._reconnectTimeoutMs); | ||
@@ -240,3 +240,3 @@ setTimeout(() => { | ||
/** | ||
* On refresh we clear out penidng mutations that we know have been applied | ||
* On refresh we clear out pending mutations that we know have been applied | ||
* by the server and thus those mutations are applied in the instaql result | ||
@@ -260,2 +260,3 @@ * returned by the server | ||
this.status = STATUS.AUTHENTICATED; | ||
this._reconnectTimeoutMs = 0; | ||
this._setAttrs(msg.attrs); | ||
@@ -295,7 +296,11 @@ this._flushPendingMessages(); | ||
const { "client-event-id": eventId, "tx-id": txId } = msg; | ||
const prevMutation = this.pendingMutations.currentValue.get(eventId); | ||
const muts = this._rewriteMutations(this.attrs, this.pendingMutations.currentValue); | ||
const prevMutation = muts.get(eventId); | ||
if (!prevMutation) { | ||
break; | ||
} | ||
prevMutation["tx-id"] = txId; | ||
this.pendingMutations.set((prev) => { | ||
prev.set(eventId, Object.assign(Object.assign({}, prevMutation), { "tx-id": txId })); | ||
return prev; | ||
}); | ||
const newAttrs = prevMutation["tx-steps"] | ||
@@ -363,2 +368,54 @@ .filter(([action, ..._args]) => action === "add-attr") | ||
} | ||
// (XXX) | ||
// There is a race condition: | ||
// When we `pushTx`, it's possible that we don't yet have `this.attrs` | ||
// This means that `tx-steps` in `pendingMutations` will include `add-attr` | ||
// commands for attrs that already exist. | ||
// | ||
// This will also affect `add-triple` and `retract-triple` which | ||
// reference attr-ids that do not match the server. | ||
// | ||
// We fix this by rewriting `tx-steps` in each `pendingMutation`. | ||
// We remove `add-attr` commands for attrs that already exist. | ||
// We update `add-triple` and `retract-triple` commands to use the | ||
// server attr-ids. | ||
_rewriteMutations(attrs, muts) { | ||
if (!attrs) | ||
return muts; | ||
const findExistingAttr = ([action, attr]) => { | ||
if (action !== "add-attr") { | ||
return; | ||
} | ||
const [_, etype, label] = attr["forward-identity"]; | ||
const existing = instaml.getAttrByFwdIdentName(attrs, etype, label); | ||
return existing; | ||
}; | ||
const rewriteTxSteps = (mapping, txSteps) => { | ||
return txSteps.reduce(([mapping, retTxSteps], txStep) => { | ||
// Handles add-attr | ||
// If existing, we drop it, and track it | ||
// to update add/retract triples | ||
const existing = findExistingAttr(txStep); | ||
if (existing) { | ||
const [_action, attr] = txStep; | ||
mapping[attr.id] = existing.id; | ||
return [mapping, retTxSteps]; | ||
} | ||
// Handles add-triple|retract-triple | ||
// If in mapping, we update the attr-id | ||
const [action, eid, attrId, ...rest] = txStep; | ||
const newTxStep = mapping[attrId] | ||
? [action, eid, mapping[attrId], ...rest] | ||
: txStep; | ||
retTxSteps.push(newTxStep); | ||
return [mapping, retTxSteps]; | ||
}, [mapping, []]); | ||
}; | ||
const [_, __, rewritten] = [...muts.entries()].reduce(([attrs, mapping, newMuts], [k, mut]) => { | ||
const [newMapping, newTxSteps] = rewriteTxSteps(mapping, mut["tx-steps"]); | ||
newMuts.set(k, Object.assign(Object.assign({}, mut), { "tx-steps": newTxSteps })); | ||
return [attrs, newMapping, newMuts]; | ||
}, [attrs, {}, new Map()]); | ||
return rewritten; | ||
} | ||
// --------------------------- | ||
@@ -380,3 +437,4 @@ // Transact | ||
dataForResult(q, { store }) { | ||
const txSteps = [...this.pendingMutations.currentValue.values()].flatMap((x) => x["tx-steps"]); | ||
const muts = this._rewriteMutations(store.attrs, this.pendingMutations.currentValue); | ||
const txSteps = [...muts.values()].flatMap((x) => x["tx-steps"]); | ||
const newStore = s.transact(store, txSteps); | ||
@@ -437,3 +495,4 @@ const data = (0, instaql_1.default)(newStore, q); | ||
}); | ||
this.pendingMutations.currentValue.forEach((mut, eventId) => { | ||
const muts = this._rewriteMutations(this.attrs, this.pendingMutations.currentValue); | ||
muts.forEach((mut, eventId) => { | ||
if (!mut["tx-id"]) { | ||
@@ -440,0 +499,0 @@ this._sendMutation(eventId, mut); |
{ | ||
"name": "@instantdb/core", | ||
"version": "0.3.393", | ||
"version": "0.3.394", | ||
"description": "Instant's core local abstraction", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
import { getOps } from "./instatx"; | ||
import uuid from "./utils/uuid"; | ||
function getAttrByFwdIdentName(attrs, inputEtype, inputIdentName) { | ||
export function getAttrByFwdIdentName(attrs, inputEtype, inputIdentName) { | ||
return Object.values(attrs).find((attr) => { | ||
@@ -11,3 +11,3 @@ const [_id, etype, label] = attr["forward-identity"]; | ||
function getAttrByReverseIdentName(attrs, inputEtype, inputIdentName) { | ||
export function getAttrByReverseIdentName(attrs, inputEtype, inputIdentName) { | ||
return Object.values(attrs).find((attr) => { | ||
@@ -14,0 +14,0 @@ const revIdent = attr["reverse-identity"]; |
@@ -8,3 +8,3 @@ import log from "./utils/log"; | ||
import IndexedDBStorage from "./IndexedDBStorage"; | ||
import WindowNetworkListener from "./WindowNetworkListener"; | ||
import WindowNetworkListener from "./WindowNetworkListener"; | ||
@@ -110,3 +110,7 @@ const STATUS = { | ||
constructor(config, Storage = IndexedDBStorage, NetworkListener = WindowNetworkListener) { | ||
constructor( | ||
config, | ||
Storage = IndexedDBStorage, | ||
NetworkListener = WindowNetworkListener, | ||
) { | ||
this.config = config; | ||
@@ -195,3 +199,7 @@ // (XXX) This is to protect us against running | ||
this.pendingMutations.set((_) => ret); | ||
storageMuts.forEach((mut, k) => { | ||
const rewrittenStorageMuts = this._rewriteMutations( | ||
this.attrs, | ||
storageMuts, | ||
); | ||
rewrittenStorageMuts.forEach((mut, k) => { | ||
if (!inMemoryMuts.has(k) && !mut["tx-id"]) { | ||
@@ -204,3 +212,3 @@ this._sendMutation(k, mut); | ||
/** | ||
* On refresh we clear out penidng mutations that we know have been applied | ||
* On refresh we clear out pending mutations that we know have been applied | ||
* by the server and thus those mutations are applied in the instaql result | ||
@@ -225,2 +233,3 @@ * returned by the server | ||
this.status = STATUS.AUTHENTICATED; | ||
this._reconnectTimeoutMs = 0; | ||
this._setAttrs(msg.attrs); | ||
@@ -260,7 +269,14 @@ this._flushPendingMessages(); | ||
const { "client-event-id": eventId, "tx-id": txId } = msg; | ||
const prevMutation = this.pendingMutations.currentValue.get(eventId); | ||
const muts = this._rewriteMutations( | ||
this.attrs, | ||
this.pendingMutations.currentValue, | ||
); | ||
const prevMutation = muts.get(eventId); | ||
if (!prevMutation) { | ||
break; | ||
} | ||
prevMutation["tx-id"] = txId; | ||
this.pendingMutations.set((prev) => { | ||
prev.set(eventId, { ...prevMutation, "tx-id": txId }); | ||
return prev; | ||
}); | ||
const newAttrs = prevMutation["tx-steps"] | ||
@@ -332,2 +348,63 @@ .filter(([action, ..._args]) => action === "add-attr") | ||
// (XXX) | ||
// There is a race condition: | ||
// When we `pushTx`, it's possible that we don't yet have `this.attrs` | ||
// This means that `tx-steps` in `pendingMutations` will include `add-attr` | ||
// commands for attrs that already exist. | ||
// | ||
// This will also affect `add-triple` and `retract-triple` which | ||
// reference attr-ids that do not match the server. | ||
// | ||
// We fix this by rewriting `tx-steps` in each `pendingMutation`. | ||
// We remove `add-attr` commands for attrs that already exist. | ||
// We update `add-triple` and `retract-triple` commands to use the | ||
// server attr-ids. | ||
_rewriteMutations(attrs, muts) { | ||
if (!attrs) return muts; | ||
const findExistingAttr = ([action, attr]) => { | ||
if (action !== "add-attr") { | ||
return; | ||
} | ||
const [_, etype, label] = attr["forward-identity"]; | ||
const existing = instaml.getAttrByFwdIdentName(attrs, etype, label); | ||
return existing; | ||
}; | ||
const rewriteTxSteps = (mapping, txSteps) => { | ||
return txSteps.reduce( | ||
([mapping, retTxSteps], txStep) => { | ||
// Handles add-attr | ||
// If existing, we drop it, and track it | ||
// to update add/retract triples | ||
const existing = findExistingAttr(txStep); | ||
if (existing) { | ||
const [_action, attr] = txStep; | ||
mapping[attr.id] = existing.id; | ||
return [mapping, retTxSteps]; | ||
} | ||
// Handles add-triple|retract-triple | ||
// If in mapping, we update the attr-id | ||
const [action, eid, attrId, ...rest] = txStep; | ||
const newTxStep = mapping[attrId] | ||
? [action, eid, mapping[attrId], ...rest] | ||
: txStep; | ||
retTxSteps.push(newTxStep); | ||
return [mapping, retTxSteps]; | ||
}, | ||
[mapping, []], | ||
); | ||
}; | ||
const [_, __, rewritten] = [...muts.entries()].reduce( | ||
([attrs, mapping, newMuts], [k, mut]) => { | ||
const [newMapping, newTxSteps] = rewriteTxSteps( | ||
mapping, | ||
mut["tx-steps"], | ||
); | ||
newMuts.set(k, { ...mut, "tx-steps": newTxSteps }); | ||
return [attrs, newMapping, newMuts]; | ||
}, | ||
[attrs, {}, new Map()], | ||
); | ||
return rewritten; | ||
} | ||
// --------------------------- | ||
@@ -354,5 +431,7 @@ // Transact | ||
dataForResult(q, { store }) { | ||
const txSteps = [...this.pendingMutations.currentValue.values()].flatMap( | ||
(x) => x["tx-steps"], | ||
const muts = this._rewriteMutations( | ||
store.attrs, | ||
this.pendingMutations.currentValue, | ||
); | ||
const txSteps = [...muts.values()].flatMap((x) => x["tx-steps"]); | ||
const newStore = s.transact(store, txSteps); | ||
@@ -426,3 +505,7 @@ const data = instaql(newStore, q); | ||
}); | ||
this.pendingMutations.currentValue.forEach((mut, eventId) => { | ||
const muts = this._rewriteMutations( | ||
this.attrs, | ||
this.pendingMutations.currentValue, | ||
); | ||
muts.forEach((mut, eventId) => { | ||
if (!mut["tx-id"]) { | ||
@@ -448,3 +531,2 @@ this._sendMutation(eventId, mut); | ||
this.status = STATUS.OPENED; | ||
this._reconnectTimeoutMs = 0; | ||
this._forceSend(uuid(), { | ||
@@ -466,6 +548,3 @@ op: "init", | ||
this.status = STATUS.CLOSED; | ||
this._reconnectTimeoutMss = Math.min( | ||
this._reconnectTimeoutMs + 1000, | ||
10000, | ||
); | ||
this._reconnectTimeoutMs = Math.min(this._reconnectTimeoutMs + 1000, 10000); | ||
log.info("[socket-close] scheduling reconnect", this._reconnectTimeoutMs); | ||
@@ -472,0 +551,0 @@ setTimeout(() => { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
993618
19109