@instantdb/core
Advanced tools
Comparing version 0.7.14 to 0.7.15
@@ -185,2 +185,3 @@ import { test, expect } from "vitest"; | ||
.flatMap((vec) => vec[0]); | ||
expect(retThree).toEqual([]); | ||
@@ -187,0 +188,0 @@ expect(retFour).toEqual([]); |
@@ -25,9 +25,12 @@ "use strict"; | ||
} | ||
// Namespaces | ||
// Parts | ||
// ----------------- | ||
function getNamespace(k) { | ||
return k; | ||
// (XXX) | ||
// We shouldn't need to generate wildcards like this. | ||
// Datalog could understand '?_' as a wildcard | ||
// Doing this to move fast. | ||
let _seed = 0; | ||
function wildcard(friendlyName) { | ||
return makeVar(`_${friendlyName}`, _seed++); | ||
} | ||
// Parts | ||
// ----------------- | ||
function makeVar(x, level) { | ||
@@ -40,10 +43,4 @@ return `?${x}-${level}`; | ||
} | ||
const ATTR_VAR = makeVar("attr"); | ||
const VAL_VAR = makeVar("val"); | ||
const TIME_VAR = makeVar("time"); | ||
// Where | ||
// ----------------- | ||
function defaultWhere(store, etype, level) { | ||
return [eidWhere(store, etype, level), attrWhere(etype, level)]; | ||
} | ||
function idAttr(store, ns) { | ||
@@ -56,2 +53,5 @@ const attr = getAttrByFwdIdentName(store.attrs, ns, "id"); | ||
} | ||
function defaultWhere(store, etype, level) { | ||
return [eidWhere(store, etype, level), attrWhere(etype, level)]; | ||
} | ||
function eidWhere(store, etype, level) { | ||
@@ -62,7 +62,12 @@ return [ | ||
makeVar(etype, level), | ||
TIME_VAR, | ||
wildcard("time"), | ||
]; | ||
} | ||
function attrWhere(etype, level) { | ||
return [makeVar(etype, level), ATTR_VAR, VAL_VAR, TIME_VAR]; | ||
return [ | ||
makeVar(etype, level), | ||
makeVar("attr", level), | ||
makeVar("val", level), | ||
makeVar("time", level), | ||
]; | ||
} | ||
@@ -86,4 +91,14 @@ function replaceInAttrPat(attrPat, needle, v) { | ||
const attrPat = fwdAttr | ||
? [makeVar(fwdEtype, level), attr.id, makeVar(revEtype, nextLevel), TIME_VAR] | ||
: [makeVar(fwdEtype, nextLevel), attr.id, makeVar(revEtype, level), TIME_VAR]; | ||
? [ | ||
makeVar(fwdEtype, level), | ||
attr.id, | ||
makeVar(revEtype, nextLevel), | ||
wildcard("time"), | ||
] | ||
: [ | ||
makeVar(fwdEtype, nextLevel), | ||
attr.id, | ||
makeVar(revEtype, level), | ||
wildcard("time"), | ||
]; | ||
const nextEtype = fwdAttr ? revEtype : fwdEtype; | ||
@@ -97,3 +112,3 @@ return [nextEtype, nextLevel, attrPat]; | ||
} | ||
return [makeVar(valueEtype, valueLevel), attr.id, v, TIME_VAR]; | ||
return [makeVar(valueEtype, valueLevel), attr.id, v, wildcard("time")]; | ||
} | ||
@@ -128,3 +143,8 @@ function refAttrPats(store, etype, level, refsPath) { | ||
function makeFind(etype, level) { | ||
return [makeVar(etype, level), ATTR_VAR, VAL_VAR, TIME_VAR]; | ||
return [ | ||
makeVar(etype, level), | ||
makeVar("attr", level), | ||
makeVar("val", level), | ||
makeVar("time", level), | ||
]; | ||
} | ||
@@ -144,7 +164,9 @@ // Relations | ||
function runDatalog(store, dq) { | ||
return (0, datalog_1.query)(store, dq).sort((tripleA, tripleB) => { | ||
return (0, datalog_1.query)(store, dq) | ||
.sort((tripleA, tripleB) => { | ||
const tsA = tripleA[3]; | ||
const tsB = tripleB[3]; | ||
return new Date(tsA) - new Date(tsB); | ||
}).reduce((res, [e, a, v]) => { | ||
}) | ||
.reduce((res, [e, a, v]) => { | ||
if (ignoredAttr(store.attrs, a)) { | ||
@@ -182,4 +204,3 @@ return res; | ||
} | ||
return (Object.entries(parents) | ||
.map(([eid, parent]) => { | ||
return Object.entries(parents).map(([eid, parent]) => { | ||
const childResults = children.map((label) => { | ||
@@ -206,3 +227,3 @@ try { | ||
}, parent); | ||
})); | ||
}); | ||
} | ||
@@ -209,0 +230,0 @@ function queryOne(store, opts) { |
@@ -23,9 +23,12 @@ import { query as datalogQuery } from "./datalog"; | ||
} | ||
// Namespaces | ||
// Parts | ||
// ----------------- | ||
function getNamespace(k) { | ||
return k; | ||
// (XXX) | ||
// We shouldn't need to generate wildcards like this. | ||
// Datalog could understand '?_' as a wildcard | ||
// Doing this to move fast. | ||
let _seed = 0; | ||
function wildcard(friendlyName) { | ||
return makeVar(`_${friendlyName}`, _seed++); | ||
} | ||
// Parts | ||
// ----------------- | ||
function makeVar(x, level) { | ||
@@ -38,10 +41,4 @@ return `?${x}-${level}`; | ||
} | ||
const ATTR_VAR = makeVar("attr"); | ||
const VAL_VAR = makeVar("val"); | ||
const TIME_VAR = makeVar("time"); | ||
// Where | ||
// ----------------- | ||
function defaultWhere(store, etype, level) { | ||
return [eidWhere(store, etype, level), attrWhere(etype, level)]; | ||
} | ||
function idAttr(store, ns) { | ||
@@ -54,2 +51,5 @@ const attr = getAttrByFwdIdentName(store.attrs, ns, "id"); | ||
} | ||
function defaultWhere(store, etype, level) { | ||
return [eidWhere(store, etype, level), attrWhere(etype, level)]; | ||
} | ||
function eidWhere(store, etype, level) { | ||
@@ -60,7 +60,12 @@ return [ | ||
makeVar(etype, level), | ||
TIME_VAR, | ||
wildcard("time"), | ||
]; | ||
} | ||
function attrWhere(etype, level) { | ||
return [makeVar(etype, level), ATTR_VAR, VAL_VAR, TIME_VAR]; | ||
return [ | ||
makeVar(etype, level), | ||
makeVar("attr", level), | ||
makeVar("val", level), | ||
makeVar("time", level), | ||
]; | ||
} | ||
@@ -84,4 +89,14 @@ function replaceInAttrPat(attrPat, needle, v) { | ||
const attrPat = fwdAttr | ||
? [makeVar(fwdEtype, level), attr.id, makeVar(revEtype, nextLevel), TIME_VAR] | ||
: [makeVar(fwdEtype, nextLevel), attr.id, makeVar(revEtype, level), TIME_VAR]; | ||
? [ | ||
makeVar(fwdEtype, level), | ||
attr.id, | ||
makeVar(revEtype, nextLevel), | ||
wildcard("time"), | ||
] | ||
: [ | ||
makeVar(fwdEtype, nextLevel), | ||
attr.id, | ||
makeVar(revEtype, level), | ||
wildcard("time"), | ||
]; | ||
const nextEtype = fwdAttr ? revEtype : fwdEtype; | ||
@@ -95,3 +110,3 @@ return [nextEtype, nextLevel, attrPat]; | ||
} | ||
return [makeVar(valueEtype, valueLevel), attr.id, v, TIME_VAR]; | ||
return [makeVar(valueEtype, valueLevel), attr.id, v, wildcard("time")]; | ||
} | ||
@@ -126,3 +141,8 @@ function refAttrPats(store, etype, level, refsPath) { | ||
function makeFind(etype, level) { | ||
return [makeVar(etype, level), ATTR_VAR, VAL_VAR, TIME_VAR]; | ||
return [ | ||
makeVar(etype, level), | ||
makeVar("attr", level), | ||
makeVar("val", level), | ||
makeVar("time", level), | ||
]; | ||
} | ||
@@ -142,7 +162,9 @@ // Relations | ||
function runDatalog(store, dq) { | ||
return datalogQuery(store, dq).sort((tripleA, tripleB) => { | ||
return datalogQuery(store, dq) | ||
.sort((tripleA, tripleB) => { | ||
const tsA = tripleA[3]; | ||
const tsB = tripleB[3]; | ||
return new Date(tsA) - new Date(tsB); | ||
}).reduce((res, [e, a, v]) => { | ||
}) | ||
.reduce((res, [e, a, v]) => { | ||
if (ignoredAttr(store.attrs, a)) { | ||
@@ -180,4 +202,3 @@ return res; | ||
} | ||
return (Object.entries(parents) | ||
.map(([eid, parent]) => { | ||
return Object.entries(parents).map(([eid, parent]) => { | ||
const childResults = children.map((label) => { | ||
@@ -204,3 +225,3 @@ try { | ||
}, parent); | ||
})); | ||
}); | ||
} | ||
@@ -207,0 +228,0 @@ function queryOne(store, opts) { |
@@ -75,3 +75,10 @@ import { produce } from "immer"; | ||
const [eid, aid, v] = triple; | ||
const attr = getAttrAsserting(store.attrs, aid); | ||
const attr = getAttr(store.attrs, aid); | ||
if (!attr) { | ||
// (XXX): Due to the way we're handling attrs, it's | ||
// possible to enter a state where we receive a triple without an attr. | ||
// See: https://github.com/jsventures/instant-local/pull/132 for details. | ||
// For now, if we receive a command without an attr, we no-op. | ||
return; | ||
} | ||
if (hasEA(attr)) { | ||
@@ -85,2 +92,3 @@ deleteIn(store.ea, [eid, aid]); | ||
} | ||
let _seed = 0; | ||
function getCreatedAt(store, attr, triple) { | ||
@@ -97,8 +105,16 @@ const [eid, aid, v] = triple; | ||
// anything committed to the server. | ||
// eventually we may need something different, if we wanted to 'expose' the createdAt and updatedAt to the client | ||
return createdAt || Date.now() * 10; | ||
// eventually we may need something different, | ||
// if we wanted to 'expose' the createdAt and updatedAt to the client | ||
return createdAt || Date.now() * 10 + _seed++; | ||
} | ||
function addTriple(store, triple) { | ||
const [eid, aid, v] = triple; | ||
const attr = getAttrAsserting(store.attrs, aid); | ||
const attr = getAttr(store.attrs, aid); | ||
if (!attr) { | ||
// (XXX): Due to the way we're handling attrs, it's | ||
// possible to enter a state where we receive a triple without an attr. | ||
// See: https://github.com/jsventures/instant-local/pull/132 for details. | ||
// For now, if we receive a command without an attr, we no-op. | ||
return; | ||
} | ||
const enhancedTriple = [...triple, getCreatedAt(store, attr, triple)]; | ||
@@ -123,3 +139,4 @@ if (hasEA(attr)) { | ||
vaeTriples.forEach((triple) => { | ||
deleteIn(store.eav, triple); | ||
const [e, a, v] = triple; | ||
deleteIn(store.eav, [e, a, v]); | ||
}); | ||
@@ -126,0 +143,0 @@ } |
@@ -79,3 +79,10 @@ "use strict"; | ||
const [eid, aid, v] = triple; | ||
const attr = getAttrAsserting(store.attrs, aid); | ||
const attr = getAttr(store.attrs, aid); | ||
if (!attr) { | ||
// (XXX): Due to the way we're handling attrs, it's | ||
// possible to enter a state where we receive a triple without an attr. | ||
// See: https://github.com/jsventures/instant-local/pull/132 for details. | ||
// For now, if we receive a command without an attr, we no-op. | ||
return; | ||
} | ||
if (hasEA(attr)) { | ||
@@ -89,2 +96,3 @@ deleteIn(store.ea, [eid, aid]); | ||
} | ||
let _seed = 0; | ||
function getCreatedAt(store, attr, triple) { | ||
@@ -101,8 +109,16 @@ const [eid, aid, v] = triple; | ||
// anything committed to the server. | ||
// eventually we may need something different, if we wanted to 'expose' the createdAt and updatedAt to the client | ||
return createdAt || Date.now() * 10; | ||
// eventually we may need something different, | ||
// if we wanted to 'expose' the createdAt and updatedAt to the client | ||
return createdAt || Date.now() * 10 + _seed++; | ||
} | ||
function addTriple(store, triple) { | ||
const [eid, aid, v] = triple; | ||
const attr = getAttrAsserting(store.attrs, aid); | ||
const attr = getAttr(store.attrs, aid); | ||
if (!attr) { | ||
// (XXX): Due to the way we're handling attrs, it's | ||
// possible to enter a state where we receive a triple without an attr. | ||
// See: https://github.com/jsventures/instant-local/pull/132 for details. | ||
// For now, if we receive a command without an attr, we no-op. | ||
return; | ||
} | ||
const enhancedTriple = [...triple, getCreatedAt(store, attr, triple)]; | ||
@@ -127,3 +143,4 @@ if (hasEA(attr)) { | ||
vaeTriples.forEach((triple) => { | ||
deleteIn(store.eav, triple); | ||
const [e, a, v] = triple; | ||
deleteIn(store.eav, [e, a, v]); | ||
}); | ||
@@ -130,0 +147,0 @@ } |
{ | ||
"name": "@instantdb/core", | ||
"version": "0.7.14", | ||
"version": "0.7.15", | ||
"description": "Instant's core local abstraction", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -26,12 +26,16 @@ import { query as datalogQuery } from "./datalog"; | ||
// Namespaces | ||
// Parts | ||
// ----------------- | ||
function getNamespace(k) { | ||
return k; | ||
// (XXX) | ||
// We shouldn't need to generate wildcards like this. | ||
// Datalog could understand '?_' as a wildcard | ||
// Doing this to move fast. | ||
let _seed = 0; | ||
function wildcard(friendlyName) { | ||
return makeVar(`_${friendlyName}`, _seed++); | ||
} | ||
// Parts | ||
// ----------------- | ||
function makeVar(x, level) { | ||
@@ -46,13 +50,5 @@ return `?${x}-${level}`; | ||
const ATTR_VAR = makeVar("attr"); | ||
const VAL_VAR = makeVar("val"); | ||
const TIME_VAR = makeVar("time"); | ||
// Where | ||
// ----------------- | ||
function defaultWhere(store, etype, level) { | ||
return [eidWhere(store, etype, level), attrWhere(etype, level)]; | ||
} | ||
function idAttr(store, ns) { | ||
@@ -66,2 +62,6 @@ const attr = getAttrByFwdIdentName(store.attrs, ns, "id"); | ||
function defaultWhere(store, etype, level) { | ||
return [eidWhere(store, etype, level), attrWhere(etype, level)]; | ||
} | ||
function eidWhere(store, etype, level) { | ||
@@ -72,3 +72,3 @@ return [ | ||
makeVar(etype, level), | ||
TIME_VAR, | ||
wildcard("time"), | ||
]; | ||
@@ -78,3 +78,8 @@ } | ||
function attrWhere(etype, level) { | ||
return [makeVar(etype, level), ATTR_VAR, VAL_VAR, TIME_VAR]; | ||
return [ | ||
makeVar(etype, level), | ||
makeVar("attr", level), | ||
makeVar("val", level), | ||
makeVar("time", level), | ||
]; | ||
} | ||
@@ -103,4 +108,14 @@ | ||
const attrPat = fwdAttr | ||
? [makeVar(fwdEtype, level), attr.id, makeVar(revEtype, nextLevel), TIME_VAR] | ||
: [makeVar(fwdEtype, nextLevel), attr.id, makeVar(revEtype, level), TIME_VAR]; | ||
? [ | ||
makeVar(fwdEtype, level), | ||
attr.id, | ||
makeVar(revEtype, nextLevel), | ||
wildcard("time"), | ||
] | ||
: [ | ||
makeVar(fwdEtype, nextLevel), | ||
attr.id, | ||
makeVar(revEtype, level), | ||
wildcard("time"), | ||
]; | ||
@@ -121,3 +136,3 @@ const nextEtype = fwdAttr ? revEtype : fwdEtype; | ||
return [makeVar(valueEtype, valueLevel), attr.id, v, TIME_VAR]; | ||
return [makeVar(valueEtype, valueLevel), attr.id, v, wildcard("time")]; | ||
} | ||
@@ -172,3 +187,8 @@ | ||
function makeFind(etype, level) { | ||
return [makeVar(etype, level), ATTR_VAR, VAL_VAR, TIME_VAR]; | ||
return [ | ||
makeVar(etype, level), | ||
makeVar("attr", level), | ||
makeVar("val", level), | ||
makeVar("time", level), | ||
]; | ||
} | ||
@@ -193,16 +213,18 @@ | ||
function runDatalog(store, dq) { | ||
return datalogQuery(store, dq).sort((tripleA, tripleB) => { | ||
const tsA = tripleA[3]; | ||
const tsB = tripleB[3]; | ||
return new Date(tsA) - new Date(tsB); | ||
}).reduce((res, [e, a, v]) => { | ||
if (ignoredAttr(store.attrs, a)) { | ||
return datalogQuery(store, dq) | ||
.sort((tripleA, tripleB) => { | ||
const tsA = tripleA[3]; | ||
const tsB = tripleB[3]; | ||
return new Date(tsA) - new Date(tsB); | ||
}) | ||
.reduce((res, [e, a, v]) => { | ||
if (ignoredAttr(store.attrs, a)) { | ||
return res; | ||
} | ||
res[e] = res[e] || {}; | ||
const attr = store.attrs[a]; | ||
const label = attr["forward-identity"][2]; | ||
res[e][label] = v; | ||
return res; | ||
} | ||
res[e] = res[e] || {}; | ||
const attr = store.attrs[a]; | ||
const label = attr["forward-identity"][2]; | ||
res[e][label] = v; | ||
return res; | ||
}, {}) | ||
}, {}); | ||
} | ||
@@ -232,33 +254,30 @@ | ||
} | ||
return ( | ||
Object.entries(parents) | ||
.map(([eid, parent]) => { | ||
const childResults = children.map((label) => { | ||
try { | ||
const [nextEtype, nextLevel, join] = makeJoin( | ||
store, | ||
etype, | ||
level, | ||
label, | ||
eid, | ||
); | ||
const child = queryOne(store, { | ||
etype: nextEtype, | ||
level: nextLevel, | ||
form: form[label], | ||
join, | ||
}); | ||
return { [label]: child }; | ||
} catch (e) { | ||
if (e instanceof AttrNotFoundError) { | ||
return { [label]: [] }; | ||
} | ||
throw e; | ||
} | ||
return Object.entries(parents).map(([eid, parent]) => { | ||
const childResults = children.map((label) => { | ||
try { | ||
const [nextEtype, nextLevel, join] = makeJoin( | ||
store, | ||
etype, | ||
level, | ||
label, | ||
eid, | ||
); | ||
const child = queryOne(store, { | ||
etype: nextEtype, | ||
level: nextLevel, | ||
form: form[label], | ||
join, | ||
}); | ||
return childResults.reduce((parent, child) => { | ||
return { ...parent, ...child }; | ||
}, parent); | ||
}) | ||
); | ||
return { [label]: child }; | ||
} catch (e) { | ||
if (e instanceof AttrNotFoundError) { | ||
return { [label]: [] }; | ||
} | ||
throw e; | ||
} | ||
}); | ||
return childResults.reduce((parent, child) => { | ||
return { ...parent, ...child }; | ||
}, parent); | ||
}); | ||
} | ||
@@ -265,0 +284,0 @@ |
@@ -85,3 +85,10 @@ import { produce } from "immer"; | ||
const [eid, aid, v] = triple; | ||
const attr = getAttrAsserting(store.attrs, aid); | ||
const attr = getAttr(store.attrs, aid); | ||
if (!attr) { | ||
// (XXX): Due to the way we're handling attrs, it's | ||
// possible to enter a state where we receive a triple without an attr. | ||
// See: https://github.com/jsventures/instant-local/pull/132 for details. | ||
// For now, if we receive a command without an attr, we no-op. | ||
return; | ||
} | ||
if (hasEA(attr)) { | ||
@@ -96,2 +103,3 @@ deleteIn(store.ea, [eid, aid]); | ||
let _seed = 0; | ||
function getCreatedAt(store, attr, triple) { | ||
@@ -108,4 +116,5 @@ const [eid, aid, v] = triple; | ||
// anything committed to the server. | ||
// eventually we may need something different, if we wanted to 'expose' the createdAt and updatedAt to the client | ||
return createdAt || Date.now() * 10; | ||
// eventually we may need something different, | ||
// if we wanted to 'expose' the createdAt and updatedAt to the client | ||
return createdAt || Date.now() * 10 + _seed++; | ||
} | ||
@@ -115,3 +124,10 @@ | ||
const [eid, aid, v] = triple; | ||
const attr = getAttrAsserting(store.attrs, aid); | ||
const attr = getAttr(store.attrs, aid); | ||
if (!attr) { | ||
// (XXX): Due to the way we're handling attrs, it's | ||
// possible to enter a state where we receive a triple without an attr. | ||
// See: https://github.com/jsventures/instant-local/pull/132 for details. | ||
// For now, if we receive a command without an attr, we no-op. | ||
return; | ||
} | ||
const enhancedTriple = [...triple, getCreatedAt(store, attr, triple)]; | ||
@@ -138,5 +154,7 @@ if (hasEA(attr)) { | ||
Object.values(store.vae[id]).flatMap((vMap) => Object.values(vMap)); | ||
if (vaeTriples) { | ||
vaeTriples.forEach((triple) => { | ||
deleteIn(store.eav, triple); | ||
const [e, a, v] = triple; | ||
deleteIn(store.eav, [e, a, v]); | ||
}); | ||
@@ -221,4 +239,4 @@ } | ||
: Object.values(store.eav).flatMap((aMap) => { | ||
return Object.values(aMap).flatMap((vMap) => Object.values(vMap)); | ||
}); | ||
return Object.values(aMap).flatMap((vMap) => Object.values(vMap)); | ||
}); | ||
} | ||
@@ -225,0 +243,0 @@ |
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
1430333
32624