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

@data-eden/athena

Package Overview
Dependencies
Maintainers
4
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@data-eden/athena - npm Package Compare versions

Comparing version 0.14.0 to 0.15.0

94

__tests__/client.test.ts

@@ -65,4 +65,4 @@ import {

adapter: adapter,
getCacheKey: (v: Entity, parent: Entity) => {
if (v.id) {
getCacheKey: (v: Entity) => {
if (v?.id) {
return `${v.__typename}:${v?.id}`;

@@ -370,5 +370,7 @@ }

type: 'APPRECIATION',
__typename: 'Reaction',
},
commentSummary: {
count: 0,
__typename: 'CommentSummary',
},

@@ -441,3 +443,3 @@ __typename: 'SocialMetadata',

commentSummary: {
count: 0,
count: 1,
__typename: 'CommentSummary',

@@ -460,3 +462,89 @@ },

).toEqual('INTEREST');
await client.processEntities({
toggleSocialReaction: {
socialMetadata: {
reactionSummaries: [],
id: 'urn:li:comment:(activity:7070125034782027776,7071631601935249410)',
commentSummary: {
count: 1,
__typename: 'CommentSummary',
},
__typename: 'SocialMetadata',
},
__typename: 'ToggleSocialReactionResult',
responseCode: 'OK_200',
},
});
expect(
result.paginatedCommentsPage.comments[0].socialMetadata
.reactionSummaries
).toEqual([]);
});
test('should be able to handle nested entites that are managed on entites that are not managed', async () => {
const result = await client.processEntities({
reactionsPage: {
id: 'urn:li:reactions:12345678954',
reactions: [
{
actor: {
firstName: 'Bob',
lastName: 'Bobberson',
profilePicture: {
url: 'https://media.licdn.com/dms/image/C5603AQGjVp-oZT1bnw/profile-displayphoto-shrink_400_400/0/1561741260600?e=1693440000&v=beta&t=YAiJc0lInvPXvlUuohhyC0oZJ9trFc3hfE8F21CIMkI',
__typename: 'Asset',
},
id: 'urn:li:member:655184127',
profileCanonicalUrl: {
url: 'https://www.linkedin.com/in/bob-bobberson',
__typename: 'ProfileCanonicalUrl',
},
__typename: 'Profile',
},
type: 'EMPATHY',
__typename: 'Reaction',
},
{
actor: {
firstName: 'Chris',
lastName: 'Freeman',
profilePicture: {
url: 'https://media.licdn.com/dms/image/D5603AQE1vYzjTXjiRA/profile-displayphoto-shrink_400_400/0/1664897400696?e=1693440000&v=beta&t=Lj5VkKd3h-6AQQSNeIPtPDfELpEMUE8QEdxT4D0ll8c',
__typename: 'Asset',
},
id: 'urn:li:member:96146350',
profileCanonicalUrl: {
url: 'https://www.linkedin.com/in/chris-freeman-2ba24828',
__typename: 'ProfileCanonicalUrl',
},
__typename: 'Profile',
},
type: 'LIKE',
__typename: 'Reaction',
},
],
socialMetadata: {
reactionSummaries: [
{
count: 1,
type: 'LIKE',
__typename: 'ReactionSummary',
},
{
count: 1,
type: 'EMPATHY',
__typename: 'ReactionSummary',
},
],
},
__typename: 'ReactionsPage',
},
});
expect(result.reactionsPage.reactions[0].actor).not.toEqual({
__link: 'Profile:urn:li:member:655184127',
});
});
});

@@ -463,0 +551,0 @@

@@ -129,2 +129,3 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */

undefined,
undefined,
250

@@ -131,0 +132,0 @@ );

4

dist/client.d.ts
import { type MergeResolvers } from './signal-cache.js';
import type { DefaultVariables, DocumentInput, GraphQLOperation, IdFetcher, OperationResult, ReactiveAdapter } from './types.js';
import type { DefaultVariables, DocumentInput, GraphQLOperation, IdFetcher, SyntheticIdFetcher, OperationResult, ReactiveAdapter } from './types.js';
export interface ClientArgs {
url: string;
getCacheKey: IdFetcher;
getSyntheticKey?: SyntheticIdFetcher;
fetch?: typeof fetch;

@@ -25,2 +26,3 @@ buildRequest?: BuildRequest;

private getCacheKey;
private getSyntheticKey;
private signalCache;

@@ -27,0 +29,0 @@ private buildRequest;

import type { CacheKey, PropertyPath } from './client.js';
import type { DefaultVariables, Entity, GraphQLOperation, IdFetcher, ReactiveAdapter, Scalar, WithSignal } from './types.js';
import type { DefaultVariables, Entity, GraphQLOperation, IdFetcher, ReactiveAdapter, Scalar, SyntheticIdFetcher, WithSignal } from './types.js';
export type Link = Record<string, string | Array<string>>;

@@ -16,2 +16,3 @@ interface LinkNode {

getCacheKey: IdFetcher;
getSyntheticKey: SyntheticIdFetcher;
mergeResolvers?: MergeResolvers;

@@ -22,6 +23,6 @@ queryLifetimes: Map<string, number>;

links: Map<string, Link>;
records: Map<string, Record<string, Scalar> | WithSignal<Entity>>;
records: Map<string, Record<string, Scalar>>;
signals: Map<string, WeakRef<WithSignal<Entity>>>;
private registry;
constructor(signalAdapter: ReactiveAdapter, getCacheKey?: IdFetcher, mergeResolvers?: MergeResolvers, queryTTL?: number);
constructor(signalAdapter: ReactiveAdapter, getCacheKey?: IdFetcher, getSyntheticKey?: SyntheticIdFetcher, mergeResolvers?: MergeResolvers, queryTTL?: number);
storeOperation(operation: GraphQLOperation, links?: Map<PropertyPath, CacheKey>): void;

@@ -28,0 +29,0 @@ readOperation<Data extends object = object, Variables extends DefaultVariables = DefaultVariables>(operation: GraphQLOperation<Data, Variables>): WithSignal<Entity> | undefined;

@@ -50,3 +50,4 @@ import type { buildCache } from '@data-eden/cache';

}
export type IdFetcher<T = any> = (v: T, parent: T) => string | undefined;
export type IdFetcher<T = any> = (v: T) => string | undefined;
export type SyntheticIdFetcher = (parsedEntity: ParsedEntity, getCacheKey: IdFetcher) => string;
//# sourceMappingURL=types.d.ts.map
import type { DocumentNode } from 'graphql';
import type { DefaultVariables, DocumentInput, GraphQLOperation } from './types.js';
import type { DefaultVariables, DocumentInput, GraphQLOperation, IdFetcher, ParsedEntity } from './types.js';
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
export declare function addTypenameToDocument<Data extends object = object, Variables extends DefaultVariables = DefaultVariables>(query: DocumentNode | TypedDocumentNode<Data, Variables>): TypedDocumentNode<Data, Variables>;
export declare function prepareOperation<Data extends object = object, Variables extends DefaultVariables = DefaultVariables>(operation: DocumentInput<Data, Variables>, variables?: Variables, fetchMore?: boolean): GraphQLOperation<Data, Variables>;
export declare function defaultSyntheticKey(parsedEntity: ParsedEntity, getCacheKey: IdFetcher): string;
//# sourceMappingURL=utils.d.ts.map
{
"name": "@data-eden/athena",
"version": "0.14.0",
"version": "0.15.0",
"repository": {

@@ -27,3 +27,3 @@ "type": "git",

"dependencies": {
"@data-eden/cache": "^0.14.0",
"@data-eden/cache": "^0.15.0",
"date-fns": "^2.30.0",

@@ -33,5 +33,5 @@ "lodash-es": "^4.17.21"

"devDependencies": {
"@data-eden/codegen": "0.14.0",
"@data-eden/mocker": "0.14.0",
"@data-eden/shared-test-utilities": "0.14.0",
"@data-eden/codegen": "0.15.0",
"@data-eden/mocker": "0.15.0",
"@data-eden/shared-test-utilities": "0.15.0",
"@graphql-typed-document-node/core": "^3.2.0",

@@ -38,0 +38,0 @@ "@signalis/core": "^0.1.0",

@@ -16,6 +16,7 @@ import type { Cache } from '@data-eden/cache';

IdFetcher,
SyntheticIdFetcher,
OperationResult,
ReactiveAdapter,
} from './types.js';
import { prepareOperation } from './utils.js';
import { defaultSyntheticKey, prepareOperation } from './utils.js';

@@ -25,2 +26,3 @@ export interface ClientArgs {

getCacheKey: IdFetcher;
getSyntheticKey?: SyntheticIdFetcher;
fetch?: typeof fetch;

@@ -62,2 +64,3 @@ buildRequest?: BuildRequest;

private getCacheKey: IdFetcher;
private getSyntheticKey: SyntheticIdFetcher;
private signalCache: SignalCache;

@@ -69,2 +72,3 @@ private buildRequest: BuildRequest;

this.getCacheKey = options.getCacheKey;
this.getSyntheticKey = options.getSyntheticKey || defaultSyntheticKey;
this.fetch = options.fetch || globalThis.fetch.bind(globalThis);

@@ -75,2 +79,3 @@ this.buildRequest = options.buildRequest || defaultBuildRequest;

options.getCacheKey,
this.getSyntheticKey,
options.mergeResolvers,

@@ -205,7 +210,10 @@ options.queryTTL

for (const { parent, prop, entity } of parsedEntities) {
const key = this.getCacheKey(entity, parent);
let key = this.getCacheKey(entity);
if (!key) {
// if we don't have a key it is not cacheable and must be cached based on the parent
continue;
// set a synthetic shallow cache key
key = this.getSyntheticKey(
{ parent, prop, entity },
this.getCacheKey
);
}

@@ -212,0 +220,0 @@

@@ -13,4 +13,6 @@ import { addMilliseconds, getTime } from 'date-fns';

Scalar,
SyntheticIdFetcher,
WithSignal,
} from './types.js';
import { defaultSyntheticKey } from './utils.js';

@@ -48,2 +50,3 @@ export type Link = Record<string, string | Array<string>>;

getCacheKey: IdFetcher;
getSyntheticKey: SyntheticIdFetcher;
mergeResolvers?: MergeResolvers;

@@ -55,3 +58,3 @@ queryLifetimes = new Map<string, number>();

links = new Map<string, Link>();
records = new Map<string, Record<string, Scalar> | WithSignal<Entity>>();
records = new Map<string, Record<string, Scalar>>();
signals = new Map<string, WeakRef<WithSignal<Entity>>>();

@@ -63,2 +66,3 @@ private registry: FinalizationRegistry<string>;

getCacheKey: IdFetcher = defaultIdGetter,
getSyntheticKey: SyntheticIdFetcher = defaultSyntheticKey,
mergeResolvers?: MergeResolvers,

@@ -69,2 +73,3 @@ queryTTL = 60_000

this.getCacheKey = getCacheKey;
this.getSyntheticKey = getSyntheticKey;
this.mergeResolvers = mergeResolvers;

@@ -158,10 +163,2 @@ this.queryTTL = queryTTL;

});
// We only want to update the array value on the entity if the record has an array value or if the record has a length
// This is to ensure we update the record with an empty array if had an original value
if (
recordArray.length > 0 ||
(record[entityKey] && Array.isArray(record[entityKey]))
) {
record[entityKey] = recordArray;
}
links[entityKey] = arrayLink;

@@ -214,3 +211,10 @@ } else if (isLinkNode(value)) {

exploring.delete(entityKey);
root = createSignalProxy(this.signalAdapter({ id: '', __typename: '' }));
root = createSignalProxy(
// the id is the source of the truth for the signal's cache key
// it is import that this is set so that given a signal we know the cache key
this.signalAdapter({
id: entityKey,
__typename: '',
})
);
this.signals.set(entityKey, new WeakRef(root));

@@ -252,8 +256,20 @@ this.registry.register(root, entityKey);

// as well
const toRemove = parentArray.filter((v) => {
const key = this.getCacheKey(v, parent);
const toRemove = parentArray.filter((v, i) => {
let key = this.getCacheKey(v);
// if there is no key we can't consistency manage it.
// it will get overriden when new values are returned on the parent object
return key && !value.includes(key);
if (!key) {
key = this.getSyntheticKey(
// we know the prop is the key and value in the array as the second value
// i is a number and needs to be a string to match the same value as provided in the first getSyntheticKey in process entities
// TODO: props should be a function we can normalize to avoid this
{
entity: v,
parent: root,
prop: [parentKey as string, i.toString()],
},
this.getCacheKey
);
}
return !value.includes(key);
});

@@ -282,2 +298,3 @@

parentKey = null;
parentArray = null;
}

@@ -321,6 +338,2 @@

// in order to get consistency updates on non managed field updates we set the signal if we have it
// so we can update it in storeEntity
this.records.set(entityKey, root);
return root;

@@ -327,0 +340,0 @@ }

@@ -69,2 +69,6 @@ import type { buildCache } from '@data-eden/cache';

export type IdFetcher<T = any> = (v: T, parent: T) => string | undefined;
export type IdFetcher<T = any> = (v: T) => string | undefined;
export type SyntheticIdFetcher = (
parsedEntity: ParsedEntity,
getCacheKey: IdFetcher
) => string;

@@ -13,2 +13,4 @@ import type {

GraphQLOperation,
IdFetcher,
ParsedEntity,
} from './types.js';

@@ -129,1 +131,29 @@ import type { TypedDocumentNode } from '@graphql-typed-document-node/core';

}
function hashCode(str: string) {
let hash = 0;
for (let i = 0, len = str.length; i < len; i++) {
let chr = str.charCodeAt(i);
// eslint-disable-next-line no-bitwise
hash = (hash << 5) - hash + chr;
// eslint-disable-next-line no-bitwise
hash |= 0; // Convert to 32bit integer
}
return hash.toString();
}
// The purpose of this function is to generate a shallow key that you know only the fields that will not change if data is updated
export function defaultSyntheticKey(
parsedEntity: ParsedEntity,
getCacheKey: IdFetcher
): string {
const { entity, parent, prop } = parsedEntity;
return `${entity.__typename}:${hashCode(
JSON.stringify({
prop,
parentId: getCacheKey(parent),
entityType: entity.__typename,
})
)}`;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

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