Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(specs): partial update operation #3486

Merged
merged 31 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
68bc889
fix(specs): partial update operation
kai687 Aug 7, 2024
7752e3a
fix: add tests
kai687 Aug 7, 2024
3a22bff
Merge branch 'main' into fix/partial-update
kai687 Aug 14, 2024
2d4dc98
Merge branch 'main' into fix/partial-update
kai687 Aug 15, 2024
4c69392
Merge branch 'main' into fix/partial-update
shortcuts Aug 26, 2024
6bb5a52
fix: specs
shortcuts Aug 26, 2024
e52edd5
fix: maybe oneof primitive?
shortcuts Aug 26, 2024
26b0346
Merge branch 'main' into fix/partial-update
shortcuts Aug 26, 2024
eede2ab
fix: test expect
shortcuts Aug 26, 2024
61568c8
Merge branch 'main' into fix/partial-update
shortcuts Aug 27, 2024
993db53
chore: one more test
shortcuts Aug 27, 2024
56bbe69
Merge branch 'main' into fix/partial-update
shortcuts Aug 27, 2024
be66b76
any
millotp Aug 27, 2024
2c94a74
lint
millotp Aug 27, 2024
426bb9e
chore: lint common js
shortcuts Aug 27, 2024
22da99b
chore: chaining
shortcuts Aug 27, 2024
3fe6174
chore: no param reassign
shortcuts Aug 27, 2024
05b6a63
chore: oki
shortcuts Aug 27, 2024
f58ce64
chore: wiff not azert
shortcuts Aug 27, 2024
07d2583
chore: publish path
shortcuts Aug 27, 2024
5e0c296
fix java and csharp
millotp Aug 27, 2024
83d90f6
chore: maybe fix kotlin
shortcuts Aug 27, 2024
bd49650
chore: maybe fix scala
shortcuts Aug 27, 2024
1019930
Revert "chore: maybe fix kotlin"
shortcuts Aug 27, 2024
0e5ebe8
fix kotlin
millotp Aug 28, 2024
75f3fff
revert cts
millotp Aug 28, 2024
6afc5fa
always lint
millotp Aug 28, 2024
acb4b8a
revert js
millotp Aug 28, 2024
5beef66
revert js
millotp Aug 28, 2024
3016bef
better spec ?
millotp Aug 28, 2024
5461119
keep attributeToUpdate for backward compat
millotp Aug 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clients/algoliasearch-client-javascript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"build:many": "lerna run build --skip-nx-cache --include-dependencies --scope ${0:-'{@algolia/*,algoliasearch}'}",
"clean": "lerna run clean --include-dependencies",
"release:bump": "lerna version ${0:-patch} --no-changelog --no-git-tag-version --no-push --exact --force-publish --yes",
"release:publish": "tsc --project tsconfig.script.json && node dist/scripts/publish.js",
"release:publish": "tsc --project scripts/tsconfig.json && node scripts/dist/scripts/publish.js",
"test": "lerna run test $*",
"test:size": "bundlesize"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,12 @@ describe('browser local storage cache', () => {
const cache = createBrowserLocalStorageCache({ key: version });
const defaultValue = (): DefaultValue => Promise.resolve({ bar: 1 });

expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject(
{ bar: 1 }
);
expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject({ bar: 1 });
expect(missMock.mock.calls.length).toBe(1);

await cache.set({ key: 'foo' }, { foo: 2 });

expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject(
{ foo: 2 }
);
expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject({ foo: 2 });
expect(missMock.mock.calls.length).toBe(1);
});

Expand All @@ -51,7 +47,7 @@ describe('browser local storage cache', () => {
expect(
await cache.get({ key: 'foo' }, defaultValue, {
miss: () => Promise.resolve(missMock()),
})
}),
).toMatchObject({ bar: 1 });

expect(missMock.mock.calls.length).toBe(0);
Expand All @@ -65,9 +61,7 @@ describe('browser local storage cache', () => {

const defaultValue = (): DefaultValue => Promise.resolve({ bar: 2 });

expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject(
{ bar: 2 }
);
expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject({ bar: 2 });
expect(missMock.mock.calls.length).toBe(1);
});

Expand All @@ -83,7 +77,7 @@ describe('browser local storage cache', () => {
expect(
await cache.get({ key: 'foo' }, defaultValue, {
miss: () => Promise.resolve(missMock()),
})
}),
).toMatchObject({ bar: 2 });

expect(missMock.mock.calls.length).toBe(1);
Expand All @@ -102,7 +96,7 @@ describe('browser local storage cache', () => {
expect(
await cache.get({ key: 'foo' }, defaultValue, {
miss: () => Promise.resolve(missMock()),
})
}),
).toMatchObject({ bar: 2 });

expect(missMock.mock.calls.length).toBe(1);
Expand All @@ -111,8 +105,7 @@ describe('browser local storage cache', () => {
});

it('do throws localstorage exceptions on access', async () => {
const message =
"Failed to read the 'localStorage' property from 'Window': Access is denied for this document.";
const message = "Failed to read the 'localStorage' property from 'Window': Access is denied for this document.";
const cache = createBrowserLocalStorageCache(
new Proxy(
{ key: 'foo' },
Expand All @@ -125,20 +118,16 @@ describe('browser local storage cache', () => {
// Simulates a window.localStorage access.
throw new DOMException(message);
},
}
)
},
),
);
const key = { foo: 'bar' };
const value = 'foo';
const fallback = 'bar';

await expect(cache.delete(key)).rejects.toEqual(new DOMException(message));
await expect(cache.set(key, value)).rejects.toEqual(
new DOMException(message)
);
await expect(
cache.get(key, () => Promise.resolve(fallback))
).rejects.toEqual(new DOMException(message));
await expect(cache.set(key, value)).rejects.toEqual(new DOMException(message));
await expect(cache.get(key, () => Promise.resolve(fallback))).rejects.toEqual(new DOMException(message));
});

it('do throws localstorage exceptions after access', async () => {
Expand All @@ -153,9 +142,7 @@ describe('browser local storage cache', () => {

await expect(cache.delete(key)).rejects.toEqual(new Error(message));
await expect(cache.set(key, value)).rejects.toEqual(new Error(message));
await expect(
cache.get(key, () => Promise.resolve(fallback))
).rejects.toEqual(new Error(message));
await expect(cache.get(key, () => Promise.resolve(fallback))).rejects.toEqual(new Error(message));
});

it('creates a namespace within local storage', async () => {
Expand All @@ -175,12 +162,8 @@ describe('browser local storage cache', () => {
},
});

const localStorageValue = localStorage.getItem(
`algolia-client-js-${version}`
);
const localStorageValue = localStorage.getItem(`algolia-client-js-${version}`);

expect(JSON.parse(localStorageValue ? localStorageValue : '{}')).toEqual(
expectedValue
);
expect(JSON.parse(localStorageValue ? localStorageValue : '{}')).toEqual(expectedValue);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,14 @@ describe('memory cache', () => {
const cache = createMemoryCache();
const defaultValue = (): DefaultValue => Promise.resolve({ bar: 1 });

expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject(
{
bar: 1,
}
);
expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject({
bar: 1,
});

await cache.set({ key: 'foo' }, { foo: 2 });

expect(missMock.mock.calls.length).toBe(1);
expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject(
{ foo: 2 }
);
expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject({ foo: 2 });
expect(missMock.mock.calls.length).toBe(1);
});

Expand All @@ -54,9 +50,7 @@ describe('memory cache', () => {

const defaultValue = (): DefaultValue => Promise.resolve({ bar: 2 });

expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject(
{ bar: 2 }
);
expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject({ bar: 2 });
expect(missMock.mock.calls.length).toBe(1);
});

Expand All @@ -68,9 +62,7 @@ describe('memory cache', () => {

const defaultValue = (): DefaultValue => Promise.resolve({ bar: 2 });

expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject(
{ bar: 2 }
);
expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject({ bar: 2 });
expect(missMock.mock.calls.length).toBe(1);
});

Expand All @@ -82,9 +74,7 @@ describe('memory cache', () => {

const defaultValue = (): DefaultValue => Promise.resolve({ bar: 2 });

expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject(
{ bar: 2 }
);
expect(await cache.get({ key: 'foo' }, defaultValue, events)).toMatchObject({ bar: 2 });
expect(missMock.mock.calls.length).toBe(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,19 @@ describe('null cache', () => {

await cache.set({ key: 'key' }, { foo: 10 });

expect(await cache.get({ key: 'key' }, defaultValue, events)).toMatchObject(
{
bar: 12,
}
);
expect(await cache.get({ key: 'key' }, defaultValue, events)).toMatchObject({
bar: 12,
});

expect(missMock.mock.calls.length).toBe(1);
});

it('returns default value', async () => {
const defaultValue = (): DefaultValue => Promise.resolve({ bar: 12 });

expect(await cache.get({ foo: 'foo' }, defaultValue, events)).toMatchObject(
{
bar: 12,
}
);
expect(await cache.get({ foo: 'foo' }, defaultValue, events)).toMatchObject({
bar: 12,
});

expect(missMock.mock.calls.length).toBe(1);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,7 @@ describe('createIterablePromise', () => {
validate: () => false,
});

await expect(promise).rejects.toEqual(
expect.objectContaining({ message: 'nope' })
);
await expect(promise).rejects.toEqual(expect.objectContaining({ message: 'nope' }));
});

it('gets the rejection of the given promise via throw', async () => {
Expand All @@ -178,9 +176,7 @@ describe('createIterablePromise', () => {
validate: () => false,
});

await expect(promise).rejects.toEqual(
expect.objectContaining({ message: 'nope' })
);
await expect(promise).rejects.toEqual(expect.objectContaining({ message: 'nope' }));
});

it('rejects with the given `message` when `validate` hits', async () => {
Expand All @@ -204,7 +200,7 @@ describe('createIterablePromise', () => {
await expect(promise).rejects.toEqual(
expect.objectContaining({
message: 'Error is thrown: 3/3',
})
}),
);
expect(calls).toBe(MAX_RETRIES);
});
Expand All @@ -230,7 +226,7 @@ describe('createIterablePromise', () => {
await expect(promise).rejects.toEqual(
expect.objectContaining({
message: 'Error is thrown: 3/3',
})
}),
);
expect(calls).toBe(MAX_RETRIES);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import type {
BrowserLocalStorageCacheItem,
BrowserLocalStorageOptions,
Cache,
CacheEvents,
} from '../types';

export function createBrowserLocalStorageCache(
options: BrowserLocalStorageOptions
): Cache {
import type { BrowserLocalStorageCacheItem, BrowserLocalStorageOptions, Cache, CacheEvents } from '../types';

export function createBrowserLocalStorageCache(options: BrowserLocalStorageOptions): Cache {
let storage: Storage;
// We've changed the namespace to avoid conflicts with v4, as this version is a huge breaking change
const namespaceKey = `algolia-client-js-${options.key}`;
Expand Down Expand Up @@ -35,7 +28,7 @@ export function createBrowserLocalStorageCache(
const filteredNamespaceWithoutOldFormattedCacheItems = Object.fromEntries(
Object.entries(namespace).filter(([, cacheItem]) => {
return cacheItem.timestamp !== undefined;
})
}),
);

setNamespace(filteredNamespaceWithoutOldFormattedCacheItems);
Expand All @@ -45,14 +38,12 @@ export function createBrowserLocalStorageCache(
}

const filteredNamespaceWithoutExpiredItems = Object.fromEntries(
Object.entries(filteredNamespaceWithoutOldFormattedCacheItems).filter(
([, cacheItem]) => {
const currentTimestamp = new Date().getTime();
const isExpired = cacheItem.timestamp + timeToLive < currentTimestamp;

return !isExpired;
}
)
Object.entries(filteredNamespaceWithoutOldFormattedCacheItems).filter(([, cacheItem]) => {
const currentTimestamp = new Date().getTime();
const isExpired = cacheItem.timestamp + timeToLive < currentTimestamp;

return !isExpired;
}),
);

setNamespace(filteredNamespaceWithoutExpiredItems);
Expand All @@ -64,32 +55,24 @@ export function createBrowserLocalStorageCache(
defaultValue: () => Promise<TValue>,
events: CacheEvents<TValue> = {
miss: () => Promise.resolve(),
}
},
): Promise<TValue> {
return Promise.resolve()
.then(() => {
removeOutdatedCacheItems();

return getNamespace<Promise<BrowserLocalStorageCacheItem>>()[
JSON.stringify(key)
];
return getNamespace<Promise<BrowserLocalStorageCacheItem>>()[JSON.stringify(key)];
})
.then((value) => {
return Promise.all([
value ? value.value : defaultValue(),
value !== undefined,
]);
return Promise.all([value ? value.value : defaultValue(), value !== undefined]);
})
.then(([value, exists]) => {
return Promise.all([value, exists || events.miss(value)]);
})
.then(([value]) => value);
},

set<TValue>(
key: Record<string, any> | string,
value: TValue
): Promise<TValue> {
set<TValue>(key: Record<string, any> | string, value: TValue): Promise<TValue> {
return Promise.resolve().then(() => {
const namespace = getNamespace();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import type { FallbackableCacheOptions, Cache, CacheEvents } from '../types';

import { createNullCache } from './createNullCache';

export function createFallbackableCache(
options: FallbackableCacheOptions
): Cache {
export function createFallbackableCache(options: FallbackableCacheOptions): Cache {
const caches = [...options.caches];
const current = caches.shift();

Expand All @@ -18,21 +16,14 @@ export function createFallbackableCache(
defaultValue: () => Promise<TValue>,
events: CacheEvents<TValue> = {
miss: (): Promise<void> => Promise.resolve(),
}
},
): Promise<TValue> {
return current.get(key, defaultValue, events).catch(() => {
return createFallbackableCache({ caches }).get(
key,
defaultValue,
events
);
return createFallbackableCache({ caches }).get(key, defaultValue, events);
});
},

set<TValue>(
key: Record<string, any> | string,
value: TValue
): Promise<TValue> {
set<TValue>(key: Record<string, any> | string, value: TValue): Promise<TValue> {
return current.set(key, value).catch(() => {
return createFallbackableCache({ caches }).set(key, value);
});
Expand Down
Loading
Loading