@promoboxx/use-filter 1.0.3 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### 1.0.6 (2021-07-16)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * dont deploy test files ([500151c](https://github.com/promoboxx/use-filter/commit/500151c04f75139c71baf29b2ad2dccefcd57db7))
11
+
12
+ ### 1.0.5 (2021-07-16)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * declaration files ([4ce29e4](https://github.com/promoboxx/use-filter/commit/4ce29e43469ad4ade2d222c3b09f38ad8f89ca4c))
18
+
19
+ ### 1.0.4 (2021-07-16)
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * more release prep ([daf06ac](https://github.com/promoboxx/use-filter/commit/daf06acc94668fdc7f0905c120f5541b4b2d16e9))
25
+
5
26
  ### 1.0.3 (2021-07-16)
6
27
 
7
28
  ### 1.0.2 (2021-07-16)
@@ -0,0 +1,3 @@
1
+ import { FilterInfo } from '../useFilter';
2
+ declare function buildDefaultFilterInfo<T>(filterInfo?: Partial<FilterInfo<T>>): FilterInfo<T>;
3
+ export default buildDefaultFilterInfo;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ var getOffsetFromPage_1 = __importDefault(require("./getOffsetFromPage"));
18
+ var getPageFromOffset_1 = __importDefault(require("./getPageFromOffset"));
19
+ function buildDefaultFilterInfo(filterInfo) {
20
+ if (filterInfo === void 0) { filterInfo = {}; }
21
+ var merged = __assign({
22
+ // Cast here to work around "'T' could be instantiated with an arbitrary
23
+ // type which could be unrelated to '{}'"
24
+ filter: {}, sort: undefined, pageSize: 20, lastRefreshAt: new Date().getTime(), totalResults: 1, totalPages: 1, offset: 0, page: 1 }, filterInfo);
25
+ // If there's a page but no offset, set the offset.
26
+ if (filterInfo.page != null && filterInfo.offset == null) {
27
+ merged.offset = getOffsetFromPage_1.default(filterInfo.page, merged.pageSize);
28
+ // If there's an offset but no page, set the page.
29
+ }
30
+ else if (filterInfo.page == null && filterInfo.offset != null) {
31
+ merged.page = getPageFromOffset_1.default(filterInfo.offset, merged.pageSize);
32
+ }
33
+ return merged;
34
+ }
35
+ exports.default = buildDefaultFilterInfo;
@@ -0,0 +1,2 @@
1
+ declare function getOffsetFromPage(page: number, pageSize: number): number;
2
+ export default getOffsetFromPage;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function getOffsetFromPage(page, pageSize) {
4
+ return pageSize * (page - 1);
5
+ }
6
+ exports.default = getOffsetFromPage;
@@ -0,0 +1,2 @@
1
+ declare function getPageFromOffset(offset: number, pageSize: number): number;
2
+ export default getPageFromOffset;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ function getPageFromOffset(offset, pageSize) {
4
+ return Math.floor(offset / pageSize) + 1;
5
+ }
6
+ exports.default = getPageFromOffset;
@@ -0,0 +1,2 @@
1
+ declare const shallowEqual: (objA: any, objB: any) => boolean;
2
+ export default shallowEqual;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var shallowEqual = function (objA, objB) {
4
+ if (Object.is(objA, objB)) {
5
+ return true;
6
+ }
7
+ if (typeof objA !== 'object' || !objA || typeof objB !== 'object' || !objB) {
8
+ return false;
9
+ }
10
+ var keysA = Object.keys(objA);
11
+ var keysB = Object.keys(objB);
12
+ if (keysA.length !== keysB.length) {
13
+ return false;
14
+ }
15
+ for (var _i = 0, keysA_1 = keysA; _i < keysA_1.length; _i++) {
16
+ var key = keysA_1[_i];
17
+ if (!Object.is(objA[key], objB[key])) {
18
+ return false;
19
+ }
20
+ }
21
+ return true;
22
+ };
23
+ exports.default = shallowEqual;
@@ -0,0 +1,8 @@
1
+ import { FilterInfo } from '../useFilter';
2
+ export interface FilterStore {
3
+ getFilter(namespace: string): FilterInfo<any> | null | undefined;
4
+ saveFilter(namespace: string, filter: FilterInfo<any>): void;
5
+ clear(): void;
6
+ }
7
+ export declare function setFilterStore(newStore: FilterStore): void;
8
+ export declare function getFilterStore(): FilterStore;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFilterStore = exports.setFilterStore = void 0;
4
+ var store;
5
+ function setFilterStore(newStore) {
6
+ store = newStore;
7
+ }
8
+ exports.setFilterStore = setFilterStore;
9
+ function getFilterStore() {
10
+ if (!store) {
11
+ throw new Error('A store must be set with setFilterStore');
12
+ }
13
+ return store;
14
+ }
15
+ exports.getFilterStore = getFilterStore;
@@ -0,0 +1,3 @@
1
+ import { FilterStore } from '.';
2
+ declare const memoryStore: FilterStore;
3
+ export default memoryStore;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var filters = {};
4
+ var memoryStore = {
5
+ getFilter: function (namespace) {
6
+ return filters[namespace];
7
+ },
8
+ saveFilter: function (namespace, filter) {
9
+ filters[namespace] = filter;
10
+ },
11
+ clear: function () {
12
+ filters = {};
13
+ },
14
+ };
15
+ exports.default = memoryStore;
@@ -0,0 +1,37 @@
1
+ declare type MaybePromise<T> = T | Promise<T>;
2
+ interface UseFilterOptions<TFilter, TResult> {
3
+ defaultFilterInfo?: Partial<FilterInfo<TFilter>>;
4
+ shouldForceRunOnMount?: boolean;
5
+ onChange: (filterInfo: FilterInfo<TFilter>) => MaybePromise<UseFilterOnChangeResult<TFilter, TResult>>;
6
+ debounceDuration?: number;
7
+ }
8
+ declare function useFilter<T>(namespace: string, options: UseFilterOptions<T, any>): {
9
+ isLoading: boolean;
10
+ doesFilterExist: boolean;
11
+ filterInfo: FilterInfo<T>;
12
+ updateFilter(filter: T): void;
13
+ resetFilter(): void;
14
+ setOffset(offset: number | string): void;
15
+ setPage(page: number | string): void;
16
+ setSort(sort: string | undefined): void;
17
+ forceRefresh(): void;
18
+ };
19
+ export default useFilter;
20
+ export interface FilterInfo<TFilter> {
21
+ filter: TFilter;
22
+ offset: number;
23
+ page: number;
24
+ sort?: string;
25
+ pageSize: number;
26
+ lastRefreshAt: number;
27
+ totalResults: number;
28
+ totalPages: number;
29
+ }
30
+ declare type UseFilterOnChangeResult<TFilter, TResult> = void | {
31
+ filterInfo?: Partial<Omit<FilterInfo<TFilter>, 'totalResults' | 'offset' | 'pageSize'> & {
32
+ totalResults: string | number;
33
+ offset: string | number;
34
+ pageSize: string | number;
35
+ }>;
36
+ data?: TResult;
37
+ };
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __rest = (this && this.__rest) || function (s, e) {
14
+ var t = {};
15
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16
+ t[p] = s[p];
17
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
18
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20
+ t[p[i]] = s[p[i]];
21
+ }
22
+ return t;
23
+ };
24
+ var __importDefault = (this && this.__importDefault) || function (mod) {
25
+ return (mod && mod.__esModule) ? mod : { "default": mod };
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ var react_1 = require("react");
29
+ var buildDefaultFilterInfo_1 = __importDefault(require("./lib/buildDefaultFilterInfo"));
30
+ var getOffsetFromPage_1 = __importDefault(require("./lib/getOffsetFromPage"));
31
+ var getPageFromOffset_1 = __importDefault(require("./lib/getPageFromOffset"));
32
+ var shallowEqual_1 = __importDefault(require("./lib/shallowEqual"));
33
+ var store_1 = require("./store");
34
+ function useFilter(namespace, options) {
35
+ var _a = react_1.useState(function () { return store_1.getFilterStore().getFilter(namespace); }), filterInfo = _a[0], setFilterInfoState = _a[1];
36
+ var setFilterInfo = react_1.useCallback(function (filterInfo, skipFetch) {
37
+ if (skipFetch === void 0) { skipFetch = false; }
38
+ setFilterInfoState(function (previousFilterInfo) {
39
+ var lastRefreshAt;
40
+ if (skipFetch) {
41
+ lastRefreshAt = previousFilterInfo === null || previousFilterInfo === void 0 ? void 0 : previousFilterInfo.lastRefreshAt;
42
+ }
43
+ else {
44
+ lastRefreshAt = new Date().getTime();
45
+ }
46
+ if (!lastRefreshAt) {
47
+ throw new Error();
48
+ }
49
+ return __assign(__assign({}, filterInfo), { lastRefreshAt: lastRefreshAt });
50
+ });
51
+ }, []);
52
+ var ctxRef = react_1.useRef({
53
+ namespace: namespace,
54
+ onChange: options.onChange,
55
+ debounceDuration: options.debounceDuration,
56
+ defaultFilterInfo: options.defaultFilterInfo,
57
+ });
58
+ var _b = react_1.useState(!filterInfo), isLoading = _b[0], setIsLoading = _b[1];
59
+ var doesFilterExist = react_1.useRef(!!filterInfo);
60
+ var lastRefreshAtRef = react_1.useRef(
61
+ // if shouldForceRunOnMount is set, always use -1
62
+ // otherwise, try grabbing lastRefreshAt
63
+ // then, just use -1 cause there's no other option
64
+ options.shouldForceRunOnMount
65
+ ? -1
66
+ : filterInfo
67
+ ? filterInfo.lastRefreshAt
68
+ : -1);
69
+ // Call onChange when data changes.
70
+ react_1.useEffect(function () {
71
+ setIsLoading(true);
72
+ // If there is no existing filter info, set it to the defaults and return.
73
+ // This same effect will trigger next go.
74
+ if (!filterInfo) {
75
+ setFilterInfo(buildDefaultFilterInfo_1.default(ctxRef.current.defaultFilterInfo));
76
+ return;
77
+ }
78
+ // If the lastRefreshAt hasn't changed, don't make a request.
79
+ if (lastRefreshAtRef.current === filterInfo.lastRefreshAt) {
80
+ setIsLoading(false);
81
+ return;
82
+ }
83
+ var timeout = setTimeout(function () {
84
+ lastRefreshAtRef.current = filterInfo.lastRefreshAt;
85
+ var response = ctxRef.current.onChange(filterInfo);
86
+ store_1.getFilterStore().saveFilter(namespace, filterInfo);
87
+ if (!response) {
88
+ setIsLoading(false);
89
+ return;
90
+ }
91
+ function handleResponse(response) {
92
+ if (!filterInfo) {
93
+ return;
94
+ }
95
+ if (!response) {
96
+ return;
97
+ }
98
+ if (response.filterInfo) {
99
+ var extra = {};
100
+ var _a = response.filterInfo, page = _a.page, offset = _a.offset, totalResults = _a.totalResults, pageSize = _a.pageSize, filterInfoFromResponse = __rest(_a, ["page", "offset", "totalResults", "pageSize"]);
101
+ var pageSizeNumber = Number(pageSize || filterInfo.pageSize);
102
+ if (page != null && offset == null) {
103
+ extra.offset = getOffsetFromPage_1.default(page, pageSizeNumber);
104
+ extra.page = page;
105
+ // If there's an offset but no page, set the page.
106
+ }
107
+ else if (page == null && offset != null) {
108
+ var offsetNumber = Number(offset);
109
+ extra.offset = offsetNumber;
110
+ extra.page = getPageFromOffset_1.default(offsetNumber, pageSizeNumber);
111
+ }
112
+ if (totalResults) {
113
+ extra.totalResults = Number(totalResults);
114
+ extra.totalPages = Math.ceil(extra.totalResults / pageSizeNumber);
115
+ }
116
+ // TODO Don't do anther request here????
117
+ setFilterInfo(__assign(__assign(__assign({}, filterInfo), filterInfoFromResponse), extra), true);
118
+ }
119
+ }
120
+ if (isPromise(response)) {
121
+ response.then(handleResponse).finally(function () { return setIsLoading(false); });
122
+ }
123
+ else {
124
+ handleResponse(response);
125
+ setIsLoading(false);
126
+ }
127
+ }, ctxRef.current.debounceDuration != null
128
+ ? ctxRef.current.debounceDuration
129
+ : 500);
130
+ return function () {
131
+ if (timeout) {
132
+ clearTimeout(timeout);
133
+ }
134
+ };
135
+ }, [filterInfo, setFilterInfo, namespace]);
136
+ return {
137
+ isLoading: isLoading,
138
+ doesFilterExist: doesFilterExist.current,
139
+ filterInfo: filterInfo || buildDefaultFilterInfo_1.default(options.defaultFilterInfo),
140
+ updateFilter: function (filter) {
141
+ if (!filterInfo) {
142
+ throw new Error();
143
+ }
144
+ var nextFilter = __assign(__assign({}, filterInfo.filter), filter);
145
+ if (shallowEqual_1.default(filterInfo.filter, nextFilter)) {
146
+ return;
147
+ }
148
+ setFilterInfo(__assign(__assign({}, filterInfo), { offset: 0, page: 1, totalResults: 1, totalPages: 1, filter: nextFilter }));
149
+ },
150
+ resetFilter: function () {
151
+ setFilterInfo(buildDefaultFilterInfo_1.default(options.defaultFilterInfo));
152
+ },
153
+ setOffset: function (offset) {
154
+ if (!filterInfo) {
155
+ throw new Error();
156
+ }
157
+ var offsetNumber = Number(offset);
158
+ setFilterInfo(__assign(__assign({}, filterInfo), { offset: offsetNumber, page: getPageFromOffset_1.default(offsetNumber, filterInfo.pageSize) }));
159
+ },
160
+ setPage: function (page) {
161
+ if (!filterInfo) {
162
+ throw new Error();
163
+ }
164
+ var pageNumber = Number(page);
165
+ setFilterInfo(__assign(__assign({}, filterInfo), { offset: getOffsetFromPage_1.default(pageNumber, filterInfo.pageSize), page: pageNumber }));
166
+ },
167
+ setSort: function (sort) {
168
+ if (!filterInfo) {
169
+ throw new Error();
170
+ }
171
+ setFilterInfo(__assign(__assign({}, filterInfo), { sort: sort }));
172
+ },
173
+ forceRefresh: function () {
174
+ if (!filterInfo) {
175
+ throw new Error();
176
+ }
177
+ setFilterInfo(__assign(__assign({}, filterInfo), { lastRefreshAt: new Date().getTime() }));
178
+ },
179
+ };
180
+ }
181
+ exports.default = useFilter;
182
+ function isPromise(t) {
183
+ return !!(t === null || t === void 0 ? void 0 : t.then);
184
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@promoboxx/use-filter",
3
- "version": "1.0.3",
3
+ "version": "1.0.6",
4
4
  "description": "",
5
- "main": "index.js",
5
+ "main": "dist/useFilter.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
8
8
  },
@@ -21,5 +21,21 @@
21
21
  "react-dom": "^17.0.2",
22
22
  "ts-jest": "^27.0.3",
23
23
  "typescript": "^4.3.5"
24
- }
24
+ },
25
+ "files": [
26
+ "dist/useFilter.d.ts",
27
+ "dist/store/index.d.ts",
28
+ "dist/store/index.js",
29
+ "dist/store/memoryStore.js",
30
+ "dist/store/memoryStore.d.ts",
31
+ "dist/useFilter.js",
32
+ "dist/lib/buildDefaultFilterInfo.js",
33
+ "dist/lib/shallowEqual.js",
34
+ "dist/lib/getOffsetFromPage.js",
35
+ "dist/lib/buildDefaultFilterInfo.d.ts",
36
+ "dist/lib/getOffsetFromPage.d.ts",
37
+ "dist/lib/getPageFromOffset.js",
38
+ "dist/lib/shallowEqual.d.ts",
39
+ "dist/lib/getPageFromOffset.d.ts"
40
+ ]
25
41
  }
package/.eslintrc.js DELETED
@@ -1,19 +0,0 @@
1
- module.exports = {
2
- extends: [
3
- // Base config applies to all projects.
4
- '@promoboxx/eslint-config',
5
- // If the project uses prettier:
6
- '@promoboxx/eslint-config/prettier',
7
- // If the project uses jest:
8
- '@promoboxx/eslint-config/jest',
9
- // If the project uses react:
10
- '@promoboxx/eslint-config/react',
11
- // If the project uses graphql:
12
- // '@promoboxx/eslint-config/graphql',
13
- ],
14
- parserOptions: {
15
- // If the project uses graphql, set the path/url to your schema below.
16
- // skipGraphQLConfig: true,
17
- // schema: 'node_modules/@promoboxx/graphql-server-types/graphql.schema.json',
18
- },
19
- }
@@ -1,32 +0,0 @@
1
- name: CI
2
- on: push
3
-
4
- jobs:
5
- ci:
6
- runs-on: ubuntu-latest
7
-
8
- steps:
9
- - uses: actions/checkout@v2
10
-
11
- - name: Cache node modules
12
- uses: actions/cache@v2
13
- with:
14
- path: |
15
- ~/.npm
16
- **/node_modules
17
- key: ${{ runner.os }}-node-modules-${{ hashFiles('**/package-lock.json') }}
18
-
19
- # https://github.community/t/github-actions-bot-email-address/17204/5
20
- - name: Prep for git push
21
- run: |
22
- git config --local user.name "${{secrets.GH_BOT_NAME}}"
23
- git config --local user.email "41898282+${{secrets.GH_BOT_NAME}}@users.noreply.github.com"
24
- git remote set-url origin "https://${{secrets.GH_BOT_NAME}}:${{secrets.GH_TOKEN}}@github.com/${GITHUB_REPOSITORY}.git"
25
-
26
- - name: Prep NPM
27
- run: npm config set '//registry.npmjs.org/:_authToken' "${{secrets.NPM_TOKEN}}"
28
-
29
- - run: make prepare-env
30
- - run: make test
31
- - run: make build
32
- - run: make deploy
@@ -1,3 +0,0 @@
1
- {
2
- "typescript.tsdk": "node_modules/typescript/lib"
3
- }
package/Makefile DELETED
@@ -1,31 +0,0 @@
1
- all: test
2
-
3
- prepare-env:
4
- ifeq ($(CI),true)
5
- npm ci --ignore-scripts
6
- else
7
- npm install
8
- endif
9
-
10
- prepare-when-local:
11
- ifneq ($(CI),true)
12
- $(MAKE) prepare-env
13
- endif
14
-
15
- build: prepare-when-local
16
- rm -rf dist/
17
- npx tsc
18
-
19
- test: prepare-when-local
20
- ifeq ($(CI),true)
21
- npx jest --ci
22
- else
23
- npx jest --watch
24
- endif
25
-
26
- deploy:
27
- ifeq ($(GITHUB_REF),refs/heads/main)
28
- npx standard-version
29
- git push origin --tags HEAD
30
- npm publish
31
- endif