Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@instantdb/core

Package Overview
Dependencies
Maintainers
4
Versions
207
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@instantdb/core - npm Package Compare versions

Comparing version 0.10.19 to 0.10.20

17

dist/instaml.js

@@ -66,4 +66,19 @@ "use strict";

}
function expandDeepMerge(attrs, [etype, eid, obj]) {
const attrTuples = Object.entries(obj).map(([identName, value]) => {
const attr = getAttrByFwdIdentName(attrs, etype, identName);
return ["deep-merge-triple", eid, attr.id, value];
});
const idTuple = [
"add-triple",
eid,
getAttrByFwdIdentName(attrs, etype, "id").id,
eid,
];
return attrTuples.concat([idTuple]);
}
function toTxSteps(attrs, [action, ...args]) {
switch (action) {
case "merge":
return expandDeepMerge(attrs, args);
case "update":

@@ -131,3 +146,3 @@ return expandUpdate(attrs, args);

function createMissingObjectAttrs(attrs, ops) {
const objectOps = ops.filter(([action]) => action === "update");
const objectOps = ops.filter(([action]) => action === "update" || action === "merge");
const objectIdents = uniqueIdents(objectOps.flatMap(extractIdents));

@@ -134,0 +149,0 @@ const missingIdents = objectIdents.filter(([etype, label]) => !getAttrByFwdIdentName(attrs, etype, label));

3

dist/instaql.d.ts

@@ -1,4 +0,5 @@

export default function query({ store, pageInfo }: {
export default function query({ store, pageInfo, aggregate }: {
store: any;
pageInfo: any;
aggregate: any;
}, q: any): {

@@ -5,0 +6,0 @@ data: {};

@@ -360,4 +360,9 @@ "use strict";

}
function query({ store, pageInfo }, q) {
function query({ store, pageInfo, aggregate }, q) {
const data = Object.keys(q).reduce((res, k) => {
if (aggregate === null || aggregate === void 0 ? void 0 : aggregate[k]) {
// Aggregate doesn't return any join rows and has no children,
// so don't bother querying further
return res;
}
res[k] = queryOne(store, {

@@ -375,2 +380,5 @@ etype: k,

}
if (aggregate) {
result.aggregate = aggregate;
}
return result;

@@ -377,0 +385,0 @@ }

@@ -1,2 +0,2 @@

declare type Action = "update" | "link" | "unlink" | "delete";
declare type Action = "update" | "link" | "unlink" | "delete" | "merge";
declare type EType = string;

@@ -55,2 +55,33 @@ declare type Id = string;

delete: () => TransactionChunk;
/**
*
* Similar to `update`, but instead of overwriting the current value, it will merge the provided values into the current value.
*
* This is useful for deeply nested, document-style values, or for updating a single attribute at an arbitrary depth without overwriting the rest of the object.
*
* For example, if you have a goal with a nested `metrics` object:
*
* ```js
* goal = { name: "Get fit", metrics: { progress: 0.3 } }
* ```
*
* You can update the `progress` attribute like so:
*
* ```js
* tx.goals[goalId].merge({ metrics: { progress: 0.5 }, category: "Fitness" })
* ```
*
* And the resulting object will be:
*
* ```js
* goal = { name: "Get fit", metrics: { progress: 0.5 }, category: "Fitness" }
* ```
*
* @example
* const goalId = id();
* tx.goals[goalId].merge({title: "Get fitter"})
*/
merge: (args: {
[attribute: string]: any;
}) => TransactionChunk;
}

@@ -57,0 +88,0 @@ export interface ETypeChunk {

@@ -58,4 +58,19 @@ import { getOps } from "./instatx";

}
function expandDeepMerge(attrs, [etype, eid, obj]) {
const attrTuples = Object.entries(obj).map(([identName, value]) => {
const attr = getAttrByFwdIdentName(attrs, etype, identName);
return ["deep-merge-triple", eid, attr.id, value];
});
const idTuple = [
"add-triple",
eid,
getAttrByFwdIdentName(attrs, etype, "id").id,
eid,
];
return attrTuples.concat([idTuple]);
}
function toTxSteps(attrs, [action, ...args]) {
switch (action) {
case "merge":
return expandDeepMerge(attrs, args);
case "update":

@@ -123,3 +138,3 @@ return expandUpdate(attrs, args);

function createMissingObjectAttrs(attrs, ops) {
const objectOps = ops.filter(([action]) => action === "update");
const objectOps = ops.filter(([action]) => action === "update" || action === "merge");
const objectIdents = uniqueIdents(objectOps.flatMap(extractIdents));

@@ -126,0 +141,0 @@ const missingIdents = objectIdents.filter(([etype, label]) => !getAttrByFwdIdentName(attrs, etype, label));

@@ -1,4 +0,5 @@

export default function query({ store, pageInfo }: {
export default function query({ store, pageInfo, aggregate }: {
store: any;
pageInfo: any;
aggregate: any;
}, q: any): {

@@ -5,0 +6,0 @@ data: {};

@@ -358,4 +358,9 @@ import { query as datalogQuery } from "./datalog";

}
export default function query({ store, pageInfo }, q) {
export default function query({ store, pageInfo, aggregate }, q) {
const data = Object.keys(q).reduce((res, k) => {
if (aggregate === null || aggregate === void 0 ? void 0 : aggregate[k]) {
// Aggregate doesn't return any join rows and has no children,
// so don't bother querying further
return res;
}
res[k] = queryOne(store, {

@@ -373,4 +378,7 @@ etype: k,

}
if (aggregate) {
result.aggregate = aggregate;
}
return result;
}
//# sourceMappingURL=instaql.js.map

@@ -1,2 +0,2 @@

declare type Action = "update" | "link" | "unlink" | "delete";
declare type Action = "update" | "link" | "unlink" | "delete" | "merge";
declare type EType = string;

@@ -55,2 +55,33 @@ declare type Id = string;

delete: () => TransactionChunk;
/**
*
* Similar to `update`, but instead of overwriting the current value, it will merge the provided values into the current value.
*
* This is useful for deeply nested, document-style values, or for updating a single attribute at an arbitrary depth without overwriting the rest of the object.
*
* For example, if you have a goal with a nested `metrics` object:
*
* ```js
* goal = { name: "Get fit", metrics: { progress: 0.3 } }
* ```
*
* You can update the `progress` attribute like so:
*
* ```js
* tx.goals[goalId].merge({ metrics: { progress: 0.5 }, category: "Fitness" })
* ```
*
* And the resulting object will be:
*
* ```js
* goal = { name: "Get fit", metrics: { progress: 0.5 }, category: "Fitness" }
* ```
*
* @example
* const goalId = id();
* tx.goals[goalId].merge({title: "Get fitter"})
*/
merge: (args: {
[attribute: string]: any;
}) => TransactionChunk;
}

@@ -57,0 +88,0 @@ export interface ETypeChunk {

@@ -71,5 +71,6 @@ /**

/** Runs instaql on a query and a store */
dataForResult(q: any, { store, pageInfo }: {
dataForResult(q: any, { store, pageInfo, aggregate }: {
store: any;
pageInfo: any;
aggregate: any;
}): {

@@ -76,0 +77,0 @@ data: {};

@@ -285,3 +285,3 @@ // @ts-check

_handleReceive(msg) {
var _a, _b, _c, _d;
var _a, _b, _c, _d, _e, _f;
switch (msg.op) {

@@ -302,6 +302,7 @@ case "init-ok":

const pageInfo = (_b = (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b["page-info"];
const aggregate = (_d = (_c = result === null || result === void 0 ? void 0 : result[0]) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d["aggregate"];
const triples = extractTriples(result);
const store = s.createStore(this.attrs, triples);
this.querySubs.set((prev) => {
prev[hash].result = { store, pageInfo };
prev[hash].result = { store, pageInfo, aggregate };
return prev;

@@ -316,3 +317,3 @@ });

const updates = computations.map((x) => {
var _a, _b;
var _a, _b, _c, _d;
const q = x["instaql-query"];

@@ -324,7 +325,8 @@ const result = x["instaql-result"];

const pageInfo = (_b = (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b["page-info"];
return { hash, store, pageInfo };
const aggregate = (_d = (_c = result === null || result === void 0 ? void 0 : result[0]) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d["aggregate"];
return { hash, store, pageInfo, aggregate };
});
updates.forEach(({ hash, store, pageInfo }) => {
updates.forEach(({ hash, store, pageInfo, aggregate }) => {
this.querySubs.set((prev) => {
prev[hash].result = { store, pageInfo };
prev[hash].result = { store, pageInfo, aggregate };
return prev;

@@ -385,3 +387,3 @@ });

// (XXX): Error handling is spaghetti right now.
const errorQ = msg.q || ((_c = msg["original-event"]) === null || _c === void 0 ? void 0 : _c.q);
const errorQ = msg.q || ((_e = msg["original-event"]) === null || _e === void 0 ? void 0 : _e.q);
const { "client-event-id": errorEventId } = msg;

@@ -421,3 +423,3 @@ const errorObj = Object.assign({}, msg);

}
const isInitError = ((_d = msg["original-event"]) === null || _d === void 0 ? void 0 : _d.op) === "init";
const isInitError = ((_f = msg["original-event"]) === null || _f === void 0 ? void 0 : _f.op) === "init";
if (isInitError) {

@@ -562,7 +564,7 @@ const errorMessage = {

/** Runs instaql on a query and a store */
dataForResult(q, { store, pageInfo }) {
dataForResult(q, { store, pageInfo, aggregate }) {
const muts = this._rewriteMutations(store.attrs, this.pendingMutations.currentValue);
const txSteps = [...muts.values()].flatMap((x) => x["tx-steps"]);
const newStore = s.transact(store, txSteps);
const resp = instaql({ store: newStore, pageInfo }, q);
const resp = instaql({ store: newStore, pageInfo, aggregate }, q);
return resp;

@@ -569,0 +571,0 @@ }

import { produce, enableMapSet } from "immer";
import { dMerge } from "./utils/object";
// Makes immer work with maps and sets

@@ -10,2 +11,5 @@ enableMapSet();

}
function isBlob(attr) {
return attr["value-type"] === "blob";
}
function getAttr(attrs, attrId) {

@@ -138,2 +142,31 @@ return attrs[attrId];

}
function mergeTriple(store, triple) {
var _a;
const [eid, aid, update] = triple;
const attr = getAttr(store.attrs, aid);
// (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.
if (!attr)
return;
// (XXX): We don't support merge for links
if (!isBlob(attr))
throw new Error("merge operation is not supported for links");
const eavValuesMap = getInMap(store.eav, [eid, aid]);
if (!eavValuesMap)
return;
const currentTriple = (_a = eavValuesMap.values().next()) === null || _a === void 0 ? void 0 : _a.value;
if (!currentTriple)
return;
const currentValue = currentTriple[2];
const updatedValue = dMerge(currentValue, update);
const enhancedTriple = [
eid,
aid,
updatedValue,
getCreatedAt(store, attr, currentTriple),
];
setInMap(store.eav, [eid, aid], new Map([[updatedValue, enhancedTriple]]));
}
function deleteEntity(store, [id]) {

@@ -203,2 +236,5 @@ // delete forward links

break;
case "deep-merge-triple":
mergeTriple(store, args);
break;
case "retract-triple":

@@ -205,0 +241,0 @@ retractTriple(store, args);

export function areObjectKeysEqual(a: any, b: any): boolean;
export function areObjectsShallowEqual(obj1: any, obj2: any): boolean;
export function areObjectsDeepEqual(obj1: any, obj2: any): any;
export function dMerge(target: any, source: any): any;
export function isObject(obj: any): boolean;
//# sourceMappingURL=object.d.ts.map

@@ -11,3 +11,6 @@ export function areObjectKeysEqual(a, b) {

export function areObjectsDeepEqual(obj1, obj2) {
if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
if (typeof obj1 !== "object" ||
typeof obj2 !== "object" ||
obj1 === null ||
obj2 === null) {
return obj1 === obj2;

@@ -18,4 +21,17 @@ }

}
return Object.keys(obj1).every(key => areObjectsDeepEqual(obj1[key], obj2[key]));
return Object.keys(obj1).every((key) => areObjectsDeepEqual(obj1[key], obj2[key]));
}
export function dMerge(target, source) {
if (!isObject(target) || !isObject(source)) {
return source;
}
for (const key of Object.keys(source)) {
const isMergeable = typeof target[key] === "object" && typeof source[key] === "object";
target[key] = isMergeable ? dMerge(target[key], source[key]) : source[key];
}
return target;
}
export function isObject(obj) {
return typeof obj === "object" && obj !== null;
}
//# sourceMappingURL=object.js.map

@@ -71,5 +71,6 @@ /**

/** Runs instaql on a query and a store */
dataForResult(q: any, { store, pageInfo }: {
dataForResult(q: any, { store, pageInfo, aggregate }: {
store: any;
pageInfo: any;
aggregate: any;
}): {

@@ -76,0 +77,0 @@ data: {};

@@ -313,3 +313,3 @@ "use strict";

_handleReceive(msg) {
var _a, _b, _c, _d;
var _a, _b, _c, _d, _e, _f;
switch (msg.op) {

@@ -330,6 +330,7 @@ case "init-ok":

const pageInfo = (_b = (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b["page-info"];
const aggregate = (_d = (_c = result === null || result === void 0 ? void 0 : result[0]) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d["aggregate"];
const triples = (0, triples_1.extractTriples)(result);
const store = s.createStore(this.attrs, triples);
this.querySubs.set((prev) => {
prev[hash].result = { store, pageInfo };
prev[hash].result = { store, pageInfo, aggregate };
return prev;

@@ -344,3 +345,3 @@ });

const updates = computations.map((x) => {
var _a, _b;
var _a, _b, _c, _d;
const q = x["instaql-query"];

@@ -352,7 +353,8 @@ const result = x["instaql-result"];

const pageInfo = (_b = (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b["page-info"];
return { hash, store, pageInfo };
const aggregate = (_d = (_c = result === null || result === void 0 ? void 0 : result[0]) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d["aggregate"];
return { hash, store, pageInfo, aggregate };
});
updates.forEach(({ hash, store, pageInfo }) => {
updates.forEach(({ hash, store, pageInfo, aggregate }) => {
this.querySubs.set((prev) => {
prev[hash].result = { store, pageInfo };
prev[hash].result = { store, pageInfo, aggregate };
return prev;

@@ -413,3 +415,3 @@ });

// (XXX): Error handling is spaghetti right now.
const errorQ = msg.q || ((_c = msg["original-event"]) === null || _c === void 0 ? void 0 : _c.q);
const errorQ = msg.q || ((_e = msg["original-event"]) === null || _e === void 0 ? void 0 : _e.q);
const { "client-event-id": errorEventId } = msg;

@@ -449,3 +451,3 @@ const errorObj = Object.assign({}, msg);

}
const isInitError = ((_d = msg["original-event"]) === null || _d === void 0 ? void 0 : _d.op) === "init";
const isInitError = ((_f = msg["original-event"]) === null || _f === void 0 ? void 0 : _f.op) === "init";
if (isInitError) {

@@ -590,7 +592,7 @@ const errorMessage = {

/** Runs instaql on a query and a store */
dataForResult(q, { store, pageInfo }) {
dataForResult(q, { store, pageInfo, aggregate }) {
const muts = this._rewriteMutations(store.attrs, this.pendingMutations.currentValue);
const txSteps = [...muts.values()].flatMap((x) => x["tx-steps"]);
const newStore = s.transact(store, txSteps);
const resp = (0, instaql_1.default)({ store: newStore, pageInfo }, q);
const resp = (0, instaql_1.default)({ store: newStore, pageInfo, aggregate }, q);
return resp;

@@ -597,0 +599,0 @@ }

@@ -5,2 +5,3 @@ "use strict";

const immer_1 = require("immer");
const object_1 = require("./utils/object");
// Makes immer work with maps and sets

@@ -14,2 +15,5 @@ (0, immer_1.enableMapSet)();

}
function isBlob(attr) {
return attr["value-type"] === "blob";
}
function getAttr(attrs, attrId) {

@@ -143,2 +147,31 @@ return attrs[attrId];

}
function mergeTriple(store, triple) {
var _a;
const [eid, aid, update] = triple;
const attr = getAttr(store.attrs, aid);
// (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.
if (!attr)
return;
// (XXX): We don't support merge for links
if (!isBlob(attr))
throw new Error("merge operation is not supported for links");
const eavValuesMap = getInMap(store.eav, [eid, aid]);
if (!eavValuesMap)
return;
const currentTriple = (_a = eavValuesMap.values().next()) === null || _a === void 0 ? void 0 : _a.value;
if (!currentTriple)
return;
const currentValue = currentTriple[2];
const updatedValue = (0, object_1.dMerge)(currentValue, update);
const enhancedTriple = [
eid,
aid,
updatedValue,
getCreatedAt(store, attr, currentTriple),
];
setInMap(store.eav, [eid, aid], new Map([[updatedValue, enhancedTriple]]));
}
function deleteEntity(store, [id]) {

@@ -208,2 +241,5 @@ // delete forward links

break;
case "deep-merge-triple":
mergeTriple(store, args);
break;
case "retract-triple":

@@ -210,0 +246,0 @@ retractTriple(store, args);

export function areObjectKeysEqual(a: any, b: any): boolean;
export function areObjectsShallowEqual(obj1: any, obj2: any): boolean;
export function areObjectsDeepEqual(obj1: any, obj2: any): any;
export function dMerge(target: any, source: any): any;
export function isObject(obj: any): boolean;
//# sourceMappingURL=object.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.areObjectsDeepEqual = exports.areObjectsShallowEqual = exports.areObjectKeysEqual = void 0;
exports.isObject = exports.dMerge = exports.areObjectsDeepEqual = exports.areObjectsShallowEqual = exports.areObjectKeysEqual = void 0;
function areObjectKeysEqual(a, b) {

@@ -16,3 +16,6 @@ const ak = Object.keys(a);

function areObjectsDeepEqual(obj1, obj2) {
if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
if (typeof obj1 !== "object" ||
typeof obj2 !== "object" ||
obj1 === null ||
obj2 === null) {
return obj1 === obj2;

@@ -23,5 +26,20 @@ }

}
return Object.keys(obj1).every(key => areObjectsDeepEqual(obj1[key], obj2[key]));
return Object.keys(obj1).every((key) => areObjectsDeepEqual(obj1[key], obj2[key]));
}
exports.areObjectsDeepEqual = areObjectsDeepEqual;
function dMerge(target, source) {
if (!isObject(target) || !isObject(source)) {
return source;
}
for (const key of Object.keys(source)) {
const isMergeable = typeof target[key] === "object" && typeof source[key] === "object";
target[key] = isMergeable ? dMerge(target[key], source[key]) : source[key];
}
return target;
}
exports.dMerge = dMerge;
function isObject(obj) {
return typeof obj === "object" && obj !== null;
}
exports.isObject = isObject;
//# sourceMappingURL=object.js.map
{
"name": "@instantdb/core",
"version": "0.10.19",
"version": "0.10.20",
"description": "Instant's core local abstraction",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -57,2 +57,3 @@ import { getOps } from "./instatx";

});
return attrTuples;

@@ -65,4 +66,22 @@ }

function expandDeepMerge(attrs, [etype, eid, obj]) {
const attrTuples = Object.entries(obj).map(([identName, value]) => {
const attr = getAttrByFwdIdentName(attrs, etype, identName);
return ["deep-merge-triple", eid, attr.id, value];
});
const idTuple = [
"add-triple",
eid,
getAttrByFwdIdentName(attrs, etype, "id").id,
eid,
];
return attrTuples.concat([idTuple]);
}
function toTxSteps(attrs, [action, ...args]) {
switch (action) {
case "merge":
return expandDeepMerge(attrs, args);
case "update":

@@ -136,3 +155,5 @@ return expandUpdate(attrs, args);

function createMissingObjectAttrs(attrs, ops) {
const objectOps = ops.filter(([action]) => action === "update");
const objectOps = ops.filter(
([action]) => action === "update" || action === "merge",
);
const objectIdents = uniqueIdents(objectOps.flatMap(extractIdents));

@@ -139,0 +160,0 @@ const missingIdents = objectIdents.filter(

@@ -459,4 +459,9 @@ import { query as datalogQuery } from "./datalog";

export default function query({ store, pageInfo }, q) {
export default function query({ store, pageInfo, aggregate }, q) {
const data = Object.keys(q).reduce((res, k) => {
if (aggregate?.[k]) {
// Aggregate doesn't return any join rows and has no children,
// so don't bother querying further
return res;
}
res[k] = queryOne(store, {

@@ -476,3 +481,7 @@ etype: k,

if (aggregate) {
result.aggregate = aggregate;
}
return result;
}

@@ -1,2 +0,2 @@

type Action = "update" | "link" | "unlink" | "delete";
type Action = "update" | "link" | "unlink" | "delete" | "merge";
type EType = string;

@@ -52,2 +52,32 @@ type Id = string;

delete: () => TransactionChunk;
/**
*
* Similar to `update`, but instead of overwriting the current value, it will merge the provided values into the current value.
*
* This is useful for deeply nested, document-style values, or for updating a single attribute at an arbitrary depth without overwriting the rest of the object.
*
* For example, if you have a goal with a nested `metrics` object:
*
* ```js
* goal = { name: "Get fit", metrics: { progress: 0.3 } }
* ```
*
* You can update the `progress` attribute like so:
*
* ```js
* tx.goals[goalId].merge({ metrics: { progress: 0.5 }, category: "Fitness" })
* ```
*
* And the resulting object will be:
*
* ```js
* goal = { name: "Get fit", metrics: { progress: 0.5 }, category: "Fitness" }
* ```
*
* @example
* const goalId = id();
* tx.goals[goalId].merge({title: "Get fitter"})
*/
merge: (args: { [attribute: string]: any }) => TransactionChunk;
}

@@ -54,0 +84,0 @@

@@ -261,6 +261,7 @@ // @ts-check

const pageInfo = result?.[0]?.data?.["page-info"];
const aggregate = result?.[0]?.data?.["aggregate"];
const triples = extractTriples(result);
const store = s.createStore(this.attrs, triples);
this.querySubs.set((prev) => {
prev[hash].result = { store, pageInfo };
prev[hash].result = { store, pageInfo, aggregate };
return prev;

@@ -281,7 +282,8 @@ });

const pageInfo = result?.[0]?.data?.["page-info"];
return { hash, store, pageInfo };
const aggregate = result?.[0]?.data?.["aggregate"];
return { hash, store, pageInfo, aggregate };
});
updates.forEach(({ hash, store, pageInfo }) => {
updates.forEach(({ hash, store, pageInfo, aggregate }) => {
this.querySubs.set((prev) => {
prev[hash].result = { store, pageInfo };
prev[hash].result = { store, pageInfo, aggregate };
return prev;

@@ -555,3 +557,3 @@ });

/** Runs instaql on a query and a store */
dataForResult(q, { store, pageInfo }) {
dataForResult(q, { store, pageInfo, aggregate }) {
const muts = this._rewriteMutations(

@@ -563,3 +565,3 @@ store.attrs,

const newStore = s.transact(store, txSteps);
const resp = instaql({ store: newStore, pageInfo }, q);
const resp = instaql({ store: newStore, pageInfo, aggregate }, q);
return resp;

@@ -566,0 +568,0 @@ }

import { produce, enableMapSet } from "immer";
import { dMerge } from "./utils/object";

@@ -14,2 +15,6 @@ // Makes immer work with maps and sets

function isBlob(attr) {
return attr["value-type"] === "blob";
}
function getAttr(attrs, attrId) {

@@ -152,2 +157,34 @@ return attrs[attrId];

function mergeTriple(store, triple) {
const [eid, aid, update] = triple;
const attr = getAttr(store.attrs, aid);
// (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.
if (!attr) return;
// (XXX): We don't support merge for links
if (!isBlob(attr))
throw new Error("merge operation is not supported for links");
const eavValuesMap = getInMap(store.eav, [eid, aid]);
if (!eavValuesMap) return;
const currentTriple = eavValuesMap.values().next()?.value;
if (!currentTriple) return;
const currentValue = currentTriple[2];
const updatedValue = dMerge(currentValue, update);
const enhancedTriple = [
eid,
aid,
updatedValue,
getCreatedAt(store, attr, currentTriple),
];
setInMap(store.eav, [eid, aid], new Map([[updatedValue, enhancedTriple]]));
}
function deleteEntity(store, [id]) {

@@ -223,2 +260,5 @@ // delete forward links

break;
case "deep-merge-triple":
mergeTriple(store, args);
break;
case "retract-triple":

@@ -225,0 +265,0 @@ retractTriple(store, args);

@@ -19,3 +19,8 @@ export function areObjectKeysEqual(a, b) {

export function areObjectsDeepEqual(obj1, obj2) {
if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
if (
typeof obj1 !== "object" ||
typeof obj2 !== "object" ||
obj1 === null ||
obj2 === null
) {
return obj1 === obj2;

@@ -28,3 +33,24 @@ }

return Object.keys(obj1).every(key => areObjectsDeepEqual(obj1[key], obj2[key]));
return Object.keys(obj1).every((key) =>
areObjectsDeepEqual(obj1[key], obj2[key]),
);
}
export function dMerge(target, source) {
if (!isObject(target) || !isObject(source)) {
return source;
}
for (const key of Object.keys(source)) {
const isMergeable =
typeof target[key] === "object" && typeof source[key] === "object";
target[key] = isMergeable ? dMerge(target[key], source[key]) : source[key];
}
return target;
}
export function isObject(obj) {
return typeof obj === "object" && obj !== null;
}

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

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

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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc