@tanstack/db
Version:
A reactive client store for building super fast apps on sync
172 lines (171 loc) • 6.57 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const typeGuards = require("../../utils/type-guards.cjs");
const equalityValueIdentity = require("../equality-value-identity.cjs");
const ROUTED_SCALAR_VALUE = /* @__PURE__ */ Symbol(`tanstack_db_routed_scalar_value`);
const CALLBACK_INPUT = /* @__PURE__ */ Symbol(`tanstack_db_callback_input`);
const CALLBACK_SELECTED = /* @__PURE__ */ Symbol(`tanstack_db_callback_selected`);
const ROUTE_METADATA = /* @__PURE__ */ Symbol(`tanstack_db_route_metadata`);
const INCLUDES_PUBLIC_KEY = /* @__PURE__ */ Symbol(`includesPublicKey`);
const INCLUDES_ROUTING = /* @__PURE__ */ Symbol(`includesRouting`);
const INTERNAL_ROUTE_KEYS = /* @__PURE__ */ new Set([
ROUTE_METADATA,
INCLUDES_PUBLIC_KEY,
CALLBACK_INPUT,
CALLBACK_SELECTED
]);
const INTERNAL_CALLBACK_KEYS = /* @__PURE__ */ new Set([
...INTERNAL_ROUTE_KEYS,
INCLUDES_ROUTING
]);
function attachRouteMetadata(value, correlationKey, parentContext) {
return Object.assign(value, {
[ROUTE_METADATA]: { correlationKey, parentContext }
});
}
function getRouteMetadata(value) {
if (value == null || typeof value !== `object` || !(ROUTE_METADATA in value)) {
return void 0;
}
return value[ROUTE_METADATA];
}
function getNamespacedRouteMetadata(row, source) {
return getRouteMetadata(row) ?? (row != null && typeof row === `object` ? getRouteMetadata(row[source]) : void 0);
}
function stripRouteMetadata(value) {
const result = { ...value };
delete result[ROUTE_METADATA];
return result;
}
function attachRouteMetadataToResult(value, correlationKey, parentContext, publicKey) {
if (correlationKey === void 0 && parentContext === void 0 && publicKey === void 0) {
return value;
}
return Object.assign(
typeGuards.isPlainObject(value) ? { ...value } : { [ROUTED_SCALAR_VALUE]: value },
{
[ROUTE_METADATA]: { correlationKey, parentContext },
[INCLUDES_PUBLIC_KEY]: publicKey
}
);
}
function getRoutedScalarMetadata(value) {
if (value == null || typeof value !== `object` || !(ROUTED_SCALAR_VALUE in value)) {
return void 0;
}
const routed = value;
return {
value: routed[ROUTED_SCALAR_VALUE],
...routed[ROUTE_METADATA],
publicKey: routed[INCLUDES_PUBLIC_KEY]
};
}
function wrapInputRow(alias, row, callbackValue) {
const scalar = getRoutedScalarMetadata(row);
const route = scalar ?? getRouteMetadata(row);
const namespaced = {
...equalityValueIdentity.getParentContextValue(route?.parentContext),
[alias]: scalar ? scalar.value : route ? stripRouteMetadata(row) : row
};
if (route)
attachRouteMetadata(namespaced, route.correlationKey, route.parentContext);
if (scalar)
Object.assign(namespaced, { [INCLUDES_PUBLIC_KEY]: scalar.publicKey });
if (callbackValue !== void 0 && callbackValue !== row)
Object.assign(namespaced, { [CALLBACK_INPUT]: { [alias]: callbackValue } });
return namespaced;
}
function getCallbackInput(row) {
const view = row[CALLBACK_INPUT];
if (Array.isArray(view)) {
const result = { ...view[0] };
if (`$selected` in row) result.$selected = row.$selected;
return result;
}
return view && typeof view === `object` ? { ...row, ...view } : row;
}
function stripInternalRouteMetadata(value) {
return transformPublicContainers(value, (leaf) => leaf, INTERNAL_ROUTE_KEYS);
}
function stripInternalCallbackMetadata(value) {
return transformPublicContainers(
value,
(leaf) => leaf,
INTERNAL_CALLBACK_KEYS
);
}
function transformPublicContainers(value, transformLeaf, omittedKeys) {
const rootReplacement = transformLeaf(value);
if (!Object.is(rootReplacement, value)) return rootReplacement;
if (!isPublicContainer(value)) return value;
const containers = /* @__PURE__ */ new Map();
const queue = [];
const markDirty = (container) => {
if (container.dirty) return;
container.dirty = true;
queue.push(container);
};
const visit = (current) => {
const existing = containers.get(current);
if (existing) return existing;
const container = {
value: current,
properties: Object.getOwnPropertyDescriptors(current),
parents: []
};
containers.set(current, container);
for (const key of Reflect.ownKeys(container.properties)) {
if (omittedKeys.has(key)) {
delete container.properties[key];
markDirty(container);
continue;
}
const descriptor = container.properties[key];
if (!descriptor.enumerable || !(`value` in descriptor)) continue;
const child = descriptor.value;
descriptor.value = transformLeaf(child);
if (!Object.is(descriptor.value, child)) markDirty(container);
else if (isPublicContainer(child)) {
descriptor.child = visit(child);
descriptor.child.parents.push(container);
}
}
return container;
};
const root = visit(value);
for (const container of queue) {
for (const parent of container.parents) markDirty(parent);
}
const copy = (container) => {
if (!container.dirty) return container.value;
if (container.copy) return container.copy;
const result = Array.isArray(container.value) ? [] : Object.create(Object.getPrototypeOf(container.value));
container.copy = result;
for (const key of Reflect.ownKeys(container.properties)) {
const descriptor = container.properties[key];
if (descriptor.child) descriptor.value = copy(descriptor.child);
}
return Object.defineProperties(result, container.properties);
};
return copy(root);
}
function isPublicContainer(value) {
return Array.isArray(value) || typeGuards.isPlainObject(value);
}
exports.CALLBACK_INPUT = CALLBACK_INPUT;
exports.CALLBACK_SELECTED = CALLBACK_SELECTED;
exports.INCLUDES_PUBLIC_KEY = INCLUDES_PUBLIC_KEY;
exports.INCLUDES_ROUTING = INCLUDES_ROUTING;
exports.attachRouteMetadata = attachRouteMetadata;
exports.attachRouteMetadataToResult = attachRouteMetadataToResult;
exports.getCallbackInput = getCallbackInput;
exports.getNamespacedRouteMetadata = getNamespacedRouteMetadata;
exports.getRouteMetadata = getRouteMetadata;
exports.getRoutedScalarMetadata = getRoutedScalarMetadata;
exports.isPublicContainer = isPublicContainer;
exports.stripInternalCallbackMetadata = stripInternalCallbackMetadata;
exports.stripInternalRouteMetadata = stripInternalRouteMetadata;
exports.stripRouteMetadata = stripRouteMetadata;
exports.transformPublicContainers = transformPublicContainers;
exports.wrapInputRow = wrapInputRow;
//# sourceMappingURL=route-metadata.cjs.map