@instantdb/core
Advanced tools
Comparing version 0.14.13 to 0.14.14
@@ -118,2 +118,282 @@ import { test, expect } from "vitest"; | ||
test("lookup creates unique attrs for lookups in link values", () => { | ||
const uid = uuid(); | ||
const ops = instatx.tx.users[uid] | ||
.update({}) | ||
.link({ posts: instatx.lookup("slug", "life-is-good") }); | ||
const result = instaml.transform({}, ops); | ||
expect(result).toEqual([ | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "users", "posts"], | ||
"reverse-identity": [expect.any(String), "posts", "users"], | ||
"value-type": "ref", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
isUnsynced: true, | ||
}, | ||
], | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "posts", "slug"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
isUnsynced: true, | ||
}, | ||
], | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "users", "id"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": false, | ||
isUnsynced: true, | ||
}, | ||
], | ||
["add-triple", uid, expect.any(String), uid], | ||
[ | ||
"add-triple", | ||
uid, | ||
expect.any(String), | ||
[expect.any(String), "life-is-good"], | ||
], | ||
]); | ||
}); | ||
test("lookup creates unique attrs for lookups in link values with arrays", () => { | ||
const uid = uuid(); | ||
const ops = instatx.tx.users[uid].update({}).link({ | ||
posts: [ | ||
instatx.lookup("slug", "life-is-good"), | ||
instatx.lookup("slug", "check-this-out"), | ||
], | ||
}); | ||
const result = instaml.transform({}, ops); | ||
const expected = [ | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "users", "posts"], | ||
"reverse-identity": [expect.any(String), "posts", "users"], | ||
"value-type": "ref", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
isUnsynced: true, | ||
}, | ||
], | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "posts", "slug"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
isUnsynced: true, | ||
}, | ||
], | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "users", "id"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": false, | ||
isUnsynced: true, | ||
}, | ||
], | ||
["add-triple", uid, expect.any(String), uid], | ||
[ | ||
"add-triple", | ||
uid, | ||
expect.any(String), | ||
[expect.any(String), "life-is-good"], | ||
], | ||
[ | ||
"add-triple", | ||
uid, | ||
expect.any(String), | ||
[expect.any(String), "check-this-out"], | ||
], | ||
]; | ||
expect(result).toHaveLength(expected.length); | ||
for (const item of expected) { | ||
expect(result).toContainEqual(item); | ||
} | ||
}); | ||
test("lookup creates unique attrs for lookups in link values when fwd-ident exists", () => { | ||
const uid = uuid(); | ||
const ops = instatx.tx.users[uid] | ||
.update({}) | ||
.link({ posts: instatx.lookup("slug", "life-is-good") }); | ||
const attrId = uuid(); | ||
const existingRefAttr = { | ||
id: attrId, | ||
"forward-identity": [uuid(), "users", "posts"], | ||
"reverse-identity": [uuid(), "posts", "users"], | ||
"value-type": "ref", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
}; | ||
const result = instaml.transform({ attrId: existingRefAttr }, ops); | ||
expect(result).toEqual([ | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "posts", "slug"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
isUnsynced: true, | ||
}, | ||
], | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "users", "id"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": false, | ||
isUnsynced: true, | ||
}, | ||
], | ||
["add-triple", uid, expect.any(String), uid], | ||
[ | ||
"add-triple", | ||
uid, | ||
expect.any(String), | ||
[expect.any(String), "life-is-good"], | ||
], | ||
]); | ||
}); | ||
test("lookup creates unique attrs for lookups in link values when rev-ident exists", () => { | ||
const uid = uuid(); | ||
const ops = instatx.tx.users[uid] | ||
.update({}) | ||
.link({ posts: instatx.lookup("slug", "life-is-good") }); | ||
const attrId = uuid(); | ||
const existingRefAttr = { | ||
id: attrId, | ||
"forward-identity": [uuid(), "posts", "users"], | ||
"reverse-identity": [uuid(), "users", "posts"], | ||
"value-type": "ref", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
}; | ||
const result = instaml.transform({ attrId: existingRefAttr }, ops); | ||
expect(result).toEqual([ | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "posts", "slug"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
isUnsynced: true, | ||
}, | ||
], | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "users", "id"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": false, | ||
isUnsynced: true, | ||
}, | ||
], | ||
["add-triple", uid, expect.any(String), uid], | ||
[ | ||
"add-triple", | ||
[expect.any(String), "life-is-good"], | ||
expect.any(String), | ||
uid, | ||
], | ||
]); | ||
}); | ||
test("lookup doesn't override attrs for lookups in link values", () => { | ||
const uid = uuid(); | ||
const ops = instatx.tx.users[uid] | ||
.update({}) | ||
.link({ posts: instatx.lookup("slug", "life-is-good") }); | ||
const refAttrId = uuid(); | ||
const userIdAttrId = uuid(); | ||
const postsSlugAttrId = uuid(); | ||
const attrs = { | ||
[refAttrId]: { | ||
id: refAttrId, | ||
"forward-identity": [uuid(), "users", "posts"], | ||
"reverse-identity": [uuid(), "posts", "users"], | ||
"value-type": "ref", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
}, | ||
[userIdAttrId]: { | ||
id: userIdAttrId, | ||
"forward-identity": [uuid(), "users", "id"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": false, | ||
}, | ||
[postsSlugAttrId]: { | ||
id: postsSlugAttrId, | ||
"forward-identity": [uuid(), "posts", "slug"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
}, | ||
}; | ||
const result = instaml.transform(attrs, ops); | ||
expect(result).toEqual([ | ||
["add-triple", uid, userIdAttrId, uid], | ||
["add-triple", uid, refAttrId, [postsSlugAttrId, "life-is-good"]], | ||
]); | ||
}); | ||
test("lookup creates unique ref attrs for ref lookup", () => { | ||
@@ -141,3 +421,3 @@ const uid = uuid(); | ||
cardinality: "one", | ||
"unique?": false, | ||
"unique?": true, | ||
"index?": false, | ||
@@ -154,3 +434,3 @@ isUnsynced: true, | ||
cardinality: "one", | ||
"unique?": false, | ||
"unique?": true, | ||
"index?": false, | ||
@@ -183,2 +463,54 @@ isUnsynced: true, | ||
test("lookup creates unique ref attrs for ref lookup in link value", () => { | ||
const uid = uuid(); | ||
const ops = [ | ||
instatx.tx.users[uid] | ||
.update({}) | ||
.link({ user_prefs: instatx.lookup("users.id", uid) }), | ||
]; | ||
const lookup = [ | ||
// The attr is going to be created, so we don't know its value yet | ||
expect.any(String), | ||
uid, | ||
]; | ||
const result = instaml.transform({}, ops); | ||
const expected = [ | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "users", "user_prefs"], | ||
"reverse-identity": [expect.any(String), "user_prefs", "users"], | ||
"value-type": "ref", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": true, | ||
isUnsynced: true, | ||
}, | ||
], | ||
[ | ||
"add-attr", | ||
{ | ||
id: expect.any(String), | ||
"forward-identity": [expect.any(String), "users", "id"], | ||
"value-type": "blob", | ||
cardinality: "one", | ||
"unique?": true, | ||
"index?": false, | ||
isUnsynced: true, | ||
}, | ||
], | ||
["add-triple", uid, expect.any(String), uid], | ||
["add-triple", uid, expect.any(String), lookup], | ||
]; | ||
expect(result).toHaveLength(expected.length); | ||
for (const item of expected) { | ||
expect(result).toContainEqual(item); | ||
} | ||
}); | ||
test("it throws if you use an invalid link attr", () => { | ||
@@ -214,3 +546,3 @@ expect(() => | ||
"forward-identity": [uuid(), "users", "id"], | ||
"index?": false, | ||
"index?": true, | ||
"unique?": false, | ||
@@ -261,3 +593,3 @@ "value-type": "blob", | ||
isUnsynced: true, | ||
"unique?": false, | ||
"unique?": true, | ||
"value-type": "blob", | ||
@@ -274,3 +606,3 @@ }, | ||
isUnsynced: true, | ||
"unique?": false, | ||
"unique?": true, | ||
"value-type": "blob", | ||
@@ -277,0 +609,0 @@ }, |
@@ -85,3 +85,4 @@ "use strict"; | ||
const fwdName = extractRefLookupFwdName(identName); | ||
const refAttr = getAttrByFwdIdentName(attrs, etype, fwdName); | ||
const refAttr = getAttrByFwdIdentName(attrs, etype, fwdName) || | ||
getAttrByReverseIdentName(attrs, etype, fwdName); | ||
if (refAttr && refAttr["value-type"] !== "ref") { | ||
@@ -238,3 +239,31 @@ throw new Error(`${identName} does not reference a valid link attribute.`); | ||
const refLookupProps = Object.assign(Object.assign({}, lookupProps), { cardinality: "one" }); | ||
function lookupPairsOfOp(op) { | ||
const res = []; | ||
const [action, etype, eid, obj] = op; | ||
if (!SUPPORTS_LOOKUP_ACTIONS.has(action)) { | ||
return res; | ||
} | ||
const eidLookupPair = lookupPairOfEid(eid); | ||
if (eidLookupPair) { | ||
res.push({ etype: etype, lookupPair: eidLookupPair }); | ||
} | ||
if (action === "link") { | ||
for (const [label, eidOrEids] of Object.entries(obj)) { | ||
const eids = Array.isArray(eidOrEids) ? eidOrEids : [eidOrEids]; | ||
for (const linkEid of eids) { | ||
const linkEidLookupPair = lookupPairOfEid(linkEid); | ||
if (linkEidLookupPair) { | ||
res.push({ | ||
etype: etype, | ||
lookupPair: linkEidLookupPair, | ||
linkLabel: label, | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
return res; | ||
} | ||
function createMissingAttrs(existingAttrs, ops) { | ||
var _a, _b; | ||
const [addedIds, attrs, addOps] = [new Set(), Object.assign({}, existingAttrs), []]; | ||
@@ -252,2 +281,12 @@ function addAttr(attr) { | ||
} | ||
// Adds attrs needed for a ref lookup | ||
function addForRef(etype, label) { | ||
const fwdAttr = getAttrByFwdIdentName(attrs, etype, label); | ||
const revAttr = getAttrByReverseIdentName(attrs, etype, label); | ||
addUnsynced(fwdAttr); | ||
addUnsynced(revAttr); | ||
if (!fwdAttr && !revAttr) { | ||
addAttr(createRefAttr(etype, label, refLookupProps)); | ||
} | ||
} | ||
// Create attrs for lookups if we need to | ||
@@ -257,21 +296,25 @@ // Do these first because otherwise we might add a non-unique attr | ||
for (const op of ops) { | ||
const [action, etype, eid, obj] = op; | ||
if (SUPPORTS_LOOKUP_ACTIONS.has(action)) { | ||
const lookupPair = lookupPairOfEid(eid); | ||
if (lookupPair) { | ||
const identName = lookupPair[0]; | ||
if (isRefLookupIdent(attrs, etype, identName)) { | ||
const label = extractRefLookupFwdName(identName); | ||
const fwdAttr = getAttrByFwdIdentName(attrs, etype, label); | ||
const revAttr = getAttrByReverseIdentName(attrs, etype, label); | ||
if (!fwdAttr && !revAttr) { | ||
addAttr(createRefAttr(etype, label, refLookupProps)); | ||
} | ||
addUnsynced(fwdAttr); | ||
addUnsynced(revAttr); | ||
for (const { etype, lookupPair, linkLabel } of lookupPairsOfOp(op)) { | ||
const identName = lookupPair[0]; | ||
// We got a link eid that's a lookup, linkLabel is the label of the ident, | ||
// e.g. `posts` in `link({posts: postIds})` | ||
if (linkLabel) { | ||
// Add our ref attr, e.g. users.posts | ||
addForRef(etype, linkLabel); | ||
// Figure out the link etype so we can make sure we have the attrs | ||
// for the link lookup | ||
const fwdAttr = getAttrByFwdIdentName(attrs, etype, linkLabel); | ||
const revAttr = getAttrByReverseIdentName(attrs, etype, linkLabel); | ||
addUnsynced(fwdAttr); | ||
addUnsynced(revAttr); | ||
const linkEtype = ((_a = fwdAttr === null || fwdAttr === void 0 ? void 0 : fwdAttr["reverse-identity"]) === null || _a === void 0 ? void 0 : _a[1]) || | ||
((_b = revAttr === null || revAttr === void 0 ? void 0 : revAttr["forward-identity"]) === null || _b === void 0 ? void 0 : _b[1]) || | ||
linkLabel; | ||
if (isRefLookupIdent(attrs, linkEtype, identName)) { | ||
addForRef(linkEtype, extractRefLookupFwdName(identName)); | ||
} | ||
else { | ||
const attr = getAttrByFwdIdentName(attrs, etype, identName); | ||
const attr = getAttrByFwdIdentName(attrs, linkEtype, identName); | ||
if (!attr) { | ||
addAttr(createObjectAttr(etype, identName, lookupProps)); | ||
addAttr(createObjectAttr(linkEtype, identName, lookupProps)); | ||
} | ||
@@ -281,2 +324,12 @@ addUnsynced(attr); | ||
} | ||
else if (isRefLookupIdent(attrs, etype, identName)) { | ||
addForRef(etype, extractRefLookupFwdName(identName)); | ||
} | ||
else { | ||
const attr = getAttrByFwdIdentName(attrs, etype, identName); | ||
if (!attr) { | ||
addAttr(createObjectAttr(etype, identName, lookupProps)); | ||
} | ||
addUnsynced(attr); | ||
} | ||
} | ||
@@ -295,3 +348,3 @@ } | ||
if (!fwdAttr) { | ||
addAttr(createObjectAttr(etype, label)); | ||
addAttr(createObjectAttr(etype, label, label === "id" ? { "unique?": true } : null)); | ||
} | ||
@@ -298,0 +351,0 @@ } |
@@ -76,3 +76,4 @@ import { getOps, isLookup, parseLookup } from "./instatx"; | ||
const fwdName = extractRefLookupFwdName(identName); | ||
const refAttr = getAttrByFwdIdentName(attrs, etype, fwdName); | ||
const refAttr = getAttrByFwdIdentName(attrs, etype, fwdName) || | ||
getAttrByReverseIdentName(attrs, etype, fwdName); | ||
if (refAttr && refAttr["value-type"] !== "ref") { | ||
@@ -229,3 +230,31 @@ throw new Error(`${identName} does not reference a valid link attribute.`); | ||
const refLookupProps = Object.assign(Object.assign({}, lookupProps), { cardinality: "one" }); | ||
function lookupPairsOfOp(op) { | ||
const res = []; | ||
const [action, etype, eid, obj] = op; | ||
if (!SUPPORTS_LOOKUP_ACTIONS.has(action)) { | ||
return res; | ||
} | ||
const eidLookupPair = lookupPairOfEid(eid); | ||
if (eidLookupPair) { | ||
res.push({ etype: etype, lookupPair: eidLookupPair }); | ||
} | ||
if (action === "link") { | ||
for (const [label, eidOrEids] of Object.entries(obj)) { | ||
const eids = Array.isArray(eidOrEids) ? eidOrEids : [eidOrEids]; | ||
for (const linkEid of eids) { | ||
const linkEidLookupPair = lookupPairOfEid(linkEid); | ||
if (linkEidLookupPair) { | ||
res.push({ | ||
etype: etype, | ||
lookupPair: linkEidLookupPair, | ||
linkLabel: label, | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
return res; | ||
} | ||
function createMissingAttrs(existingAttrs, ops) { | ||
var _a, _b; | ||
const [addedIds, attrs, addOps] = [new Set(), Object.assign({}, existingAttrs), []]; | ||
@@ -243,2 +272,12 @@ function addAttr(attr) { | ||
} | ||
// Adds attrs needed for a ref lookup | ||
function addForRef(etype, label) { | ||
const fwdAttr = getAttrByFwdIdentName(attrs, etype, label); | ||
const revAttr = getAttrByReverseIdentName(attrs, etype, label); | ||
addUnsynced(fwdAttr); | ||
addUnsynced(revAttr); | ||
if (!fwdAttr && !revAttr) { | ||
addAttr(createRefAttr(etype, label, refLookupProps)); | ||
} | ||
} | ||
// Create attrs for lookups if we need to | ||
@@ -248,21 +287,25 @@ // Do these first because otherwise we might add a non-unique attr | ||
for (const op of ops) { | ||
const [action, etype, eid, obj] = op; | ||
if (SUPPORTS_LOOKUP_ACTIONS.has(action)) { | ||
const lookupPair = lookupPairOfEid(eid); | ||
if (lookupPair) { | ||
const identName = lookupPair[0]; | ||
if (isRefLookupIdent(attrs, etype, identName)) { | ||
const label = extractRefLookupFwdName(identName); | ||
const fwdAttr = getAttrByFwdIdentName(attrs, etype, label); | ||
const revAttr = getAttrByReverseIdentName(attrs, etype, label); | ||
if (!fwdAttr && !revAttr) { | ||
addAttr(createRefAttr(etype, label, refLookupProps)); | ||
} | ||
addUnsynced(fwdAttr); | ||
addUnsynced(revAttr); | ||
for (const { etype, lookupPair, linkLabel } of lookupPairsOfOp(op)) { | ||
const identName = lookupPair[0]; | ||
// We got a link eid that's a lookup, linkLabel is the label of the ident, | ||
// e.g. `posts` in `link({posts: postIds})` | ||
if (linkLabel) { | ||
// Add our ref attr, e.g. users.posts | ||
addForRef(etype, linkLabel); | ||
// Figure out the link etype so we can make sure we have the attrs | ||
// for the link lookup | ||
const fwdAttr = getAttrByFwdIdentName(attrs, etype, linkLabel); | ||
const revAttr = getAttrByReverseIdentName(attrs, etype, linkLabel); | ||
addUnsynced(fwdAttr); | ||
addUnsynced(revAttr); | ||
const linkEtype = ((_a = fwdAttr === null || fwdAttr === void 0 ? void 0 : fwdAttr["reverse-identity"]) === null || _a === void 0 ? void 0 : _a[1]) || | ||
((_b = revAttr === null || revAttr === void 0 ? void 0 : revAttr["forward-identity"]) === null || _b === void 0 ? void 0 : _b[1]) || | ||
linkLabel; | ||
if (isRefLookupIdent(attrs, linkEtype, identName)) { | ||
addForRef(linkEtype, extractRefLookupFwdName(identName)); | ||
} | ||
else { | ||
const attr = getAttrByFwdIdentName(attrs, etype, identName); | ||
const attr = getAttrByFwdIdentName(attrs, linkEtype, identName); | ||
if (!attr) { | ||
addAttr(createObjectAttr(etype, identName, lookupProps)); | ||
addAttr(createObjectAttr(linkEtype, identName, lookupProps)); | ||
} | ||
@@ -272,2 +315,12 @@ addUnsynced(attr); | ||
} | ||
else if (isRefLookupIdent(attrs, etype, identName)) { | ||
addForRef(etype, extractRefLookupFwdName(identName)); | ||
} | ||
else { | ||
const attr = getAttrByFwdIdentName(attrs, etype, identName); | ||
if (!attr) { | ||
addAttr(createObjectAttr(etype, identName, lookupProps)); | ||
} | ||
addUnsynced(attr); | ||
} | ||
} | ||
@@ -286,3 +339,3 @@ } | ||
if (!fwdAttr) { | ||
addAttr(createObjectAttr(etype, label)); | ||
addAttr(createObjectAttr(etype, label, label === "id" ? { "unique?": true } : null)); | ||
} | ||
@@ -289,0 +342,0 @@ } |
@@ -488,5 +488,5 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
if (!joinedRoom) { | ||
if (this._roomsPendingLeave[roomId]) { | ||
if (this._roomsPendingLeave[loadingRoomId]) { | ||
this._tryLeaveRoom(loadingRoomId); | ||
delete this._roomsPendingLeave[roomId]; | ||
delete this._roomsPendingLeave[loadingRoomId]; | ||
} | ||
@@ -493,0 +493,0 @@ break; |
@@ -516,5 +516,5 @@ "use strict"; | ||
if (!joinedRoom) { | ||
if (this._roomsPendingLeave[roomId]) { | ||
if (this._roomsPendingLeave[loadingRoomId]) { | ||
this._tryLeaveRoom(loadingRoomId); | ||
delete this._roomsPendingLeave[roomId]; | ||
delete this._roomsPendingLeave[loadingRoomId]; | ||
} | ||
@@ -521,0 +521,0 @@ break; |
{ | ||
"name": "@instantdb/core", | ||
"version": "v0.14.13", | ||
"version": "v0.14.14", | ||
"description": "Instant's core local abstraction", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -90,3 +90,5 @@ import { getOps, isLookup, parseLookup } from "./instatx"; | ||
const refAttr = getAttrByFwdIdentName(attrs, etype, fwdName); | ||
const refAttr = | ||
getAttrByFwdIdentName(attrs, etype, fwdName) || | ||
getAttrByReverseIdentName(attrs, etype, fwdName); | ||
if (refAttr && refAttr["value-type"] !== "ref") { | ||
@@ -280,2 +282,31 @@ throw new Error(`${identName} does not reference a valid link attribute.`); | ||
function lookupPairsOfOp(op) { | ||
const res = []; | ||
const [action, etype, eid, obj] = op; | ||
if (!SUPPORTS_LOOKUP_ACTIONS.has(action)) { | ||
return res; | ||
} | ||
const eidLookupPair = lookupPairOfEid(eid); | ||
if (eidLookupPair) { | ||
res.push({ etype: etype, lookupPair: eidLookupPair }); | ||
} | ||
if (action === "link") { | ||
for (const [label, eidOrEids] of Object.entries(obj)) { | ||
const eids = Array.isArray(eidOrEids) ? eidOrEids : [eidOrEids]; | ||
for (const linkEid of eids) { | ||
const linkEidLookupPair = lookupPairOfEid(linkEid); | ||
if (linkEidLookupPair) { | ||
res.push({ | ||
etype: etype, | ||
lookupPair: linkEidLookupPair, | ||
linkLabel: label, | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
return res; | ||
} | ||
function createMissingAttrs(existingAttrs, ops) { | ||
@@ -295,2 +326,13 @@ const [addedIds, attrs, addOps] = [new Set(), { ...existingAttrs }, []]; | ||
// Adds attrs needed for a ref lookup | ||
function addForRef(etype, label) { | ||
const fwdAttr = getAttrByFwdIdentName(attrs, etype, label); | ||
const revAttr = getAttrByReverseIdentName(attrs, etype, label); | ||
addUnsynced(fwdAttr); | ||
addUnsynced(revAttr); | ||
if (!fwdAttr && !revAttr) { | ||
addAttr(createRefAttr(etype, label, refLookupProps)); | ||
} | ||
} | ||
// Create attrs for lookups if we need to | ||
@@ -300,23 +342,37 @@ // Do these first because otherwise we might add a non-unique attr | ||
for (const op of ops) { | ||
const [action, etype, eid, obj] = op; | ||
if (SUPPORTS_LOOKUP_ACTIONS.has(action)) { | ||
const lookupPair = lookupPairOfEid(eid); | ||
if (lookupPair) { | ||
const identName = lookupPair[0]; | ||
if (isRefLookupIdent(attrs, etype, identName)) { | ||
const label = extractRefLookupFwdName(identName); | ||
const fwdAttr = getAttrByFwdIdentName(attrs, etype, label); | ||
const revAttr = getAttrByReverseIdentName(attrs, etype, label); | ||
if (!fwdAttr && !revAttr) { | ||
addAttr(createRefAttr(etype, label, refLookupProps)); | ||
} | ||
addUnsynced(fwdAttr); | ||
addUnsynced(revAttr); | ||
for (const { etype, lookupPair, linkLabel } of lookupPairsOfOp(op)) { | ||
const identName = lookupPair[0]; | ||
// We got a link eid that's a lookup, linkLabel is the label of the ident, | ||
// e.g. `posts` in `link({posts: postIds})` | ||
if (linkLabel) { | ||
// Add our ref attr, e.g. users.posts | ||
addForRef(etype, linkLabel); | ||
// Figure out the link etype so we can make sure we have the attrs | ||
// for the link lookup | ||
const fwdAttr = getAttrByFwdIdentName(attrs, etype, linkLabel); | ||
const revAttr = getAttrByReverseIdentName(attrs, etype, linkLabel); | ||
addUnsynced(fwdAttr); | ||
addUnsynced(revAttr); | ||
const linkEtype = | ||
fwdAttr?.["reverse-identity"]?.[1] || | ||
revAttr?.["forward-identity"]?.[1] || | ||
linkLabel; | ||
if (isRefLookupIdent(attrs, linkEtype, identName)) { | ||
addForRef(linkEtype, extractRefLookupFwdName(identName)); | ||
} else { | ||
const attr = getAttrByFwdIdentName(attrs, etype, identName); | ||
const attr = getAttrByFwdIdentName(attrs, linkEtype, identName); | ||
if (!attr) { | ||
addAttr(createObjectAttr(etype, identName, lookupProps)); | ||
addAttr(createObjectAttr(linkEtype, identName, lookupProps)); | ||
} | ||
addUnsynced(attr); | ||
} | ||
} else if (isRefLookupIdent(attrs, etype, identName)) { | ||
addForRef(etype, extractRefLookupFwdName(identName)); | ||
} else { | ||
const attr = getAttrByFwdIdentName(attrs, etype, identName); | ||
if (!attr) { | ||
addAttr(createObjectAttr(etype, identName, lookupProps)); | ||
} | ||
addUnsynced(attr); | ||
} | ||
@@ -337,3 +393,9 @@ } | ||
if (!fwdAttr) { | ||
addAttr(createObjectAttr(etype, label)); | ||
addAttr( | ||
createObjectAttr( | ||
etype, | ||
label, | ||
label === "id" ? { "unique?": true } : null, | ||
), | ||
); | ||
} | ||
@@ -340,0 +402,0 @@ } |
@@ -457,5 +457,5 @@ // @ts-check | ||
if (!joinedRoom) { | ||
if (this._roomsPendingLeave[roomId]) { | ||
if (this._roomsPendingLeave[loadingRoomId]) { | ||
this._tryLeaveRoom(loadingRoomId); | ||
delete this._roomsPendingLeave[roomId]; | ||
delete this._roomsPendingLeave[loadingRoomId]; | ||
} | ||
@@ -462,0 +462,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 too big to display
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
2405529
42394