Skip to content

Commit

Permalink
feat(mapOptionToKey): provide first helper
Browse files Browse the repository at this point in the history
  • Loading branch information
code-forger committed Oct 23, 2023
1 parent cd4c175 commit 9202e22
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 7 deletions.
59 changes: 52 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -597,20 +597,17 @@ To overcome this, you can specify a function instead of a `headers` object in th
This function will be called, to re-make the headers just before an API call is made, even when you call `run`.
Note: If you don't want the dynamic headers to result in a cache miss, you must remove the keys of the dynamic headers from the options using `mapOptionsToKey` (see example below).
Note: If you don't want the dynamic headers to result in a cache miss, you must remove the keys of the dynamic headers from the options using `mapOptionsToKey` (see example below that uses the `ignoreHeadersByKey` helper).
```jsx
import React from 'react';
import { useFetchye } from 'fetchye';
import { useFetchye, ignoreHeadersByKey } from 'fetchye';
import uuid from 'uuid';

const BookList = () => {
const { isLoading, data } = useFetchye('http://example.com/api/books/', {
// remove the 'correlationId' header from the headers, as its the only dynamic header
mapOptionsToKey: ({ headers: { correlationId, ...headers }, ...options }) => ({
...options,
headers,
}),
mapOptionsToKey: ignoreHeadersByKey(['correlationId']),
headers: () => ({
// static headers are still fine, and can be specified here like normal
staticHeader: 'staticValue',
Expand Down Expand Up @@ -810,6 +807,8 @@ const ParentComponent = ({ children }) => (
* [`DELETE_DATA`](#delete_data)
* [`ERROR`](#error)
* [`CLEAR_ERROR`](#clear_error)
* [`mapOptionToKey Helpers`](#mapoptiontokey-helpers)
* [`ignoreHeadersByKey`](#ignoreheadersbykey)
### `useFetchye`
Expand All @@ -833,7 +832,7 @@ const { isLoading, data, error, run } = useFetchye(key, { defer: Boolean, mapOpt
| name | type | required | description |
|--------------------|-------------------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `mapOptionsToKey` | `(options: Options) => transformedOptions` | `false` | A function that maps options to the key that will become part of the cache key |
| `mapOptionsToKey` | `(options: Options) => transformedOptions` | `false` | A function that maps options to the key that will become part of the cache key. See below for a list of mapOptionsToKey helpers. |
| `mapKeyToCacheKey` | `(key: String, options: Options) => cacheKey: String` | `false` | A function that maps the key for use as the cacheKey allowing direct control of the cacheKey |
| `defer` | `Boolean` | `false` | Prevents execution of `useFetchye` on each render in favor of using the returned `run` function. *Defaults to `false`* |
| `initialData` | `Object` | `false` | Seeds the initial data on first render of `useFetchye` to accomodate server side rendering *Defaults to `undefined`* |
Expand Down Expand Up @@ -1221,6 +1220,52 @@ import { CLEAR_ERROR } from 'fetchye-core';
|---|---|---|
| `hash` | `String` | The hash value generated by [`object-hash`](https://github.com/puleos/object-hash) package for the query |
### mapOptionToKey Helpers
These helpers provide a more compact and simple way of common transforms.
There is currently one helper.
#### ignoreHeadersByKey
**Shape**
`(String[]) => mapOptionsToKeyFunction`
**Arguments**
| name | type | required | description |
|--------|-----------------|----------|--------------------------------------------------------------------------------------------------|
| `keys` | `Array<String>` | `true` | creates a mapOptionsToKey function that removes headers whose keys match the specified keys |
**Returns**
| name | type | description |
|----------------------------|---------------------------|-----------------------------------------------------------------------------------------------------------------------------|
| `mapOptionsToKey Function` | `mapOptionsToKeyFunction` | A function to be passed to the mapOptionsToKey option in useFetchye, or the `fetchye` function made by `makeServerFetchye`. |
**Example**
```jsx
import React from 'react';
import { useFetchye, ignoreHeadersByKey } from 'fetchye';

const BookList = ({ locale }) => {
const { isLoading, data } = useFetchye('http://example.com/api/books/', {
// remove the 'locale' header from the headers when building the cache key
mapOptionsToKey: ignoreHeadersByKey(['locale']),
headers: { locale },
});

// ... rest of component
};

export default BookList;
```
## 📢 Mission
The Fetchye project wishes to bring a more flexible central caching experience
Expand Down
1 change: 1 addition & 0 deletions packages/fetchye/__tests__/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe('index', () => {
Array [
"FetchyeProvider",
"SimpleCache",
"ignoreHeadersByKey",
"makeServerFetchye",
"useFetchye",
]
Expand Down
54 changes: 54 additions & 0 deletions packages/fetchye/__tests__/mapOptionsToKeyHelpers.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2023 American Express Travel Related Services Company, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

import { ignoreHeadersByKey } from '../src/mapOptionsToKeyHelpers';

describe('mapOptionsToKeyHelpers', () => {
describe('ignoreHeadersByKey', () => {
it('should do nothing if the header key is not present', () => {
expect(ignoreHeadersByKey([])({})).toEqual({});
expect(ignoreHeadersByKey([])(
{ otherKey: 'otherKeyValue' }
)).toEqual(
{ otherKey: 'otherKeyValue' }
);
});
it('should do nothing if the header key is present, but the mentioned keys to remove are not present', () => {
expect(ignoreHeadersByKey(['removeHeaderKey'])(
{ headers: { preserveHeaderKey: 'preserveHeaderKeyValue' } }
)).toEqual(
{ headers: { preserveHeaderKey: 'preserveHeaderKeyValue' } }
);
expect(ignoreHeadersByKey(['removeHeaderKey'])(
{ otherKey: 'otherKeyValue', headers: { preserveHeaderKey: 'preserveHeaderKeyValue' } }
)).toEqual(
{ otherKey: 'otherKeyValue', headers: { preserveHeaderKey: 'preserveHeaderKeyValue' } }
);
});
it('should remove the mentioned key if its present in the headers', () => {
expect(ignoreHeadersByKey(['removeHeaderKey'])(
{ headers: { preserveHeaderKey: 'preserveHeaderKeyValue', removeHeaderKey: 'removeHeaderKeyValue' } }
)).toEqual(
{ headers: { preserveHeaderKey: 'preserveHeaderKeyValue' } }
);
expect(ignoreHeadersByKey(['removeHeaderKey'])(
{ otherKey: 'otherKeyValue', headers: { preserveHeaderKey: 'preserveHeaderKeyValue', removeHeaderKey: 'removeHeaderKeyValue' } }
)).toEqual(
{ otherKey: 'otherKeyValue', headers: { preserveHeaderKey: 'preserveHeaderKeyValue' } }
);
});
});
});
2 changes: 2 additions & 0 deletions packages/fetchye/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import useFetchye from './useFetchye';
import makeServerFetchye from './makeServerFetchye';
import FetchyeProvider from './FetchyeProvider';
import SimpleCache from './SimpleCache';
import { ignoreHeadersByKey } from './mapOptionsToKeyHelpers';

export {
useFetchye,
makeServerFetchye,
FetchyeProvider,
SimpleCache,
ignoreHeadersByKey,
};
32 changes: 32 additions & 0 deletions packages/fetchye/src/mapOptionsToKeyHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2023 American Express Travel Related Services Company, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

const filterObjectByKeys = (object, keys) => Object.keys(object)
.filter((key) => !keys.includes(key))
.reduce((acc, key) => {
// mutating accumulator to prevent many, many object allocations
acc[key] = object[key];
return acc;
}, {});

export const ignoreHeadersByKey = (keys) => ({ headers, ...options }) => (
headers
? {
...options,
headers: filterObjectByKeys(headers, keys),
}
: { ...options }
);

0 comments on commit 9202e22

Please sign in to comment.