@alanszp/business-days-date-fns 4.0.10

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.
Files changed (74) hide show
  1. package/.eslintrc.js +93 -0
  2. package/.gitignore +3 -0
  3. package/.npmignore +3 -0
  4. package/LICENSE +21 -0
  5. package/README.MD +51 -0
  6. package/babel.config.js +7 -0
  7. package/dist/cache/index.d.ts +1 -0
  8. package/dist/cache/index.js +17 -0
  9. package/dist/cache/index.js.map +1 -0
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js +6 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/utils/addBusinessDays.d.ts +1 -0
  14. package/dist/utils/addBusinessDays.js +42 -0
  15. package/dist/utils/addBusinessDays.js.map +1 -0
  16. package/dist/utils/addBusinessDays.test.d.ts +1 -0
  17. package/dist/utils/addBusinessDays.test.js +94 -0
  18. package/dist/utils/addBusinessDays.test.js.map +1 -0
  19. package/dist/utils/differenceInBusinessDay.test.d.ts +1 -0
  20. package/dist/utils/differenceInBusinessDay.test.js +96 -0
  21. package/dist/utils/differenceInBusinessDay.test.js.map +1 -0
  22. package/dist/utils/differenceInBusinessDays.d.ts +1 -0
  23. package/dist/utils/differenceInBusinessDays.js +34 -0
  24. package/dist/utils/differenceInBusinessDays.js.map +1 -0
  25. package/dist/utils/isBusinessDay.d.ts +1 -0
  26. package/dist/utils/isBusinessDay.js +16 -0
  27. package/dist/utils/isBusinessDay.js.map +1 -0
  28. package/dist/utils/isBusinessDay.test.d.ts +1 -0
  29. package/dist/utils/isBusinessDay.test.js +34 -0
  30. package/dist/utils/isBusinessDay.test.js.map +1 -0
  31. package/dist/utils/isNonBusinessDay.d.ts +1 -0
  32. package/dist/utils/isNonBusinessDay.js +17 -0
  33. package/dist/utils/isNonBusinessDay.js.map +1 -0
  34. package/dist/utils/isNonBusinessDay.test.d.ts +1 -0
  35. package/dist/utils/isNonBusinessDay.test.js +52 -0
  36. package/dist/utils/isNonBusinessDay.test.js.map +1 -0
  37. package/dist/utils/requiredArgs.d.ts +1 -0
  38. package/dist/utils/requiredArgs.js +10 -0
  39. package/dist/utils/requiredArgs.js.map +1 -0
  40. package/dist/utils/subBusinessDays.d.ts +1 -0
  41. package/dist/utils/subBusinessDays.js +14 -0
  42. package/dist/utils/subBusinessDays.js.map +1 -0
  43. package/dist/utils/subBusinessDays.test.d.ts +1 -0
  44. package/dist/utils/subBusinessDays.test.js +69 -0
  45. package/dist/utils/subBusinessDays.test.js.map +1 -0
  46. package/dist/utils/withNonBusinessDays.d.ts +11 -0
  47. package/dist/utils/withNonBusinessDays.js +45 -0
  48. package/dist/utils/withNonBusinessDays.js.map +1 -0
  49. package/dist/utils/withNonBusinessDays.test.d.ts +1 -0
  50. package/dist/utils/withNonBusinessDays.test.js +73 -0
  51. package/dist/utils/withNonBusinessDays.test.js.map +1 -0
  52. package/dist/utils/wrapperNonBusinessDays.d.ts +3 -0
  53. package/dist/utils/wrapperNonBusinessDays.js +70 -0
  54. package/dist/utils/wrapperNonBusinessDays.js.map +1 -0
  55. package/header.png +0 -0
  56. package/jest.config.js +10 -0
  57. package/package.json +39 -0
  58. package/src/cache/index.ts +13 -0
  59. package/src/index.ts +1 -0
  60. package/src/utils/addBusinessDays.test.ts +131 -0
  61. package/src/utils/addBusinessDays.ts +46 -0
  62. package/src/utils/differenceInBusinessDay.test.ts +176 -0
  63. package/src/utils/differenceInBusinessDays.ts +37 -0
  64. package/src/utils/isBusinessDay.test.ts +47 -0
  65. package/src/utils/isBusinessDay.ts +18 -0
  66. package/src/utils/isNonBusinessDay.test.ts +69 -0
  67. package/src/utils/isNonBusinessDay.ts +17 -0
  68. package/src/utils/requiredArgs.ts +5 -0
  69. package/src/utils/subBusinessDays.test.ts +99 -0
  70. package/src/utils/subBusinessDays.ts +10 -0
  71. package/src/utils/withNonBusinessDays.test.ts +82 -0
  72. package/src/utils/withNonBusinessDays.ts +87 -0
  73. package/src/utils/wrapperNonBusinessDays.ts +78 -0
  74. package/tsconfig.json +15 -0
@@ -0,0 +1,82 @@
1
+ import assert from "assert";
2
+ import { withNonBusinessDays } from "./withNonBusinessDays";
3
+
4
+ const mockNBD = [new Date("2022-01-19"), new Date("2022-01-20")];
5
+ const mockSerializer = jest.fn();
6
+
7
+ describe("withNonBusinessDays", () => {
8
+ it("bootstraping sync should return fns", () => {
9
+ const {
10
+ addBusinessDays,
11
+ subBusinessDays,
12
+ isBusinessDay,
13
+ isNonBusinessDay,
14
+ differenceInBusinessDays,
15
+ } = withNonBusinessDays([new Date("2022-01-01"), new Date("2022-01-10")]);
16
+
17
+ expect(typeof addBusinessDays).toBe("function");
18
+ expect(typeof subBusinessDays).toBe("function");
19
+ expect(typeof isBusinessDay).toBe("function");
20
+ expect(typeof isNonBusinessDay).toBe("function");
21
+ expect(typeof differenceInBusinessDays).toBe("function");
22
+ });
23
+
24
+ it("bootstraping async should return fns and call serializer", async () => {
25
+ const mockFetchStrategy = jest.fn();
26
+ mockFetchStrategy.mockImplementation(() => Promise.resolve(mockNBD));
27
+
28
+ const {
29
+ addBusinessDays,
30
+ subBusinessDays,
31
+ isBusinessDay,
32
+ isNonBusinessDay,
33
+ differenceInBusinessDays,
34
+ } = withNonBusinessDays(mockFetchStrategy, {
35
+ serializeOptions: mockSerializer,
36
+ });
37
+
38
+ expect(typeof addBusinessDays).toBe("function");
39
+ expect(typeof subBusinessDays).toBe("function");
40
+ expect(typeof isBusinessDay).toBe("function");
41
+ expect(typeof isNonBusinessDay).toBe("function");
42
+ expect(typeof differenceInBusinessDays).toBe("function");
43
+
44
+ await addBusinessDays(new Date(), 1, { month: 1 });
45
+
46
+ expect(mockSerializer).toHaveBeenCalledWith({ month: 1 });
47
+ expect(mockFetchStrategy).toHaveBeenCalled();
48
+ });
49
+
50
+ it("bootstraping async addBusinessDays", async () => {
51
+ const mockFetchStrategy = jest.fn();
52
+ mockFetchStrategy.mockImplementation(() => Promise.resolve(mockNBD));
53
+ const { addBusinessDays } = withNonBusinessDays(mockFetchStrategy, {
54
+ serializeOptions: (obj) => JSON.stringify(obj),
55
+ });
56
+
57
+ const result = await addBusinessDays(new Date("2022-01-18"), 1);
58
+ expect(result).toEqual(new Date("2022-01-21"));
59
+ });
60
+
61
+ it("bootstraping async throw error", async () => {
62
+ const mockFetchStrategy = jest.fn();
63
+ mockFetchStrategy.mockImplementation(() => Promise.reject());
64
+ try {
65
+ assert.throws(withNonBusinessDays.bind(mockFetchStrategy), TypeError);
66
+ } catch {}
67
+ });
68
+
69
+ it("bootstraping sync addBusinessDays", () => {
70
+ const { addBusinessDays } = withNonBusinessDays(mockNBD);
71
+
72
+ const result = addBusinessDays(new Date("2022-01-18"), 1);
73
+ expect(result).toEqual(new Date("2022-01-21"));
74
+ });
75
+
76
+ it("bootstraping should throw error for bad input", () => {
77
+ try {
78
+ assert.throws(withNonBusinessDays.bind(null), TypeError);
79
+ assert.throws(withNonBusinessDays.bind(null), TypeError);
80
+ } catch {}
81
+ });
82
+ });
@@ -0,0 +1,87 @@
1
+ import isFunction, { isArray } from "lodash/";
2
+ import { Options as CacheOptions } from "lru-cache";
3
+ import { addBusinessDays } from "./addBusinessDays";
4
+ import { subBusinessDays } from "./subBusinessDays";
5
+ import { differenceInBusinessDays } from "./differenceInBusinessDays";
6
+ import {
7
+ wrapperDateAndNumberNonBusinessDays,
8
+ wrapperDateNonBusinessDays,
9
+ } from "./wrapperNonBusinessDays";
10
+ import { isNonBusinessDay } from "./isNonBusinessDay";
11
+ import { isBusinessDay } from "./isBusinessDay";
12
+ import { buildNonBusinessDaysCache } from "../cache";
13
+
14
+ export type WithNonBusinessDaysOutput<IdentifyObject> = {
15
+ addBusinessDays: (
16
+ dirtyDate: Date | number,
17
+ dirtyAmount: number,
18
+ identify?: IdentifyObject
19
+ ) => Promise<Date> | Date;
20
+ subBusinessDays: (
21
+ dirtyDate: Date | number,
22
+ dirtyAmount: number,
23
+ identify?: IdentifyObject
24
+ ) => Promise<Date> | Date;
25
+ differenceInBusinessDays: (
26
+ dirtyDate: Date | number,
27
+ dirtyAmount: number,
28
+ identify: IdentifyObject
29
+ ) => Promise<number> | number;
30
+ isNonBusinessDay: (
31
+ date: Date,
32
+ identify: IdentifyObject
33
+ ) => Promise<boolean> | boolean;
34
+ isBusinessDay: (
35
+ date: Date,
36
+ identify: IdentifyObject
37
+ ) => Promise<boolean> | boolean;
38
+ };
39
+
40
+ export function withNonBusinessDays<Options>(
41
+ fetchStrategy: ((opts?: Options) => Promise<Date[]>) | Date[],
42
+ cacheOpts?: CacheOptions<string, Date[]> & {
43
+ serializeOptions?: (opts?: Options) => string;
44
+ }
45
+ ): WithNonBusinessDaysOutput<Options> {
46
+ if (!isFunction(fetchStrategy) && !isArray(fetchStrategy)) {
47
+ throw new Error(
48
+ "You must send a function for fetchStrategy or a list of dates"
49
+ );
50
+ }
51
+
52
+ const cache = buildNonBusinessDaysCache(cacheOpts);
53
+
54
+ return {
55
+ addBusinessDays: wrapperDateAndNumberNonBusinessDays(
56
+ cache,
57
+ fetchStrategy,
58
+ addBusinessDays,
59
+ cacheOpts?.serializeOptions
60
+ ),
61
+ differenceInBusinessDays: wrapperDateAndNumberNonBusinessDays(
62
+ cache,
63
+
64
+ fetchStrategy,
65
+ differenceInBusinessDays,
66
+ cacheOpts?.serializeOptions
67
+ ),
68
+ subBusinessDays: wrapperDateAndNumberNonBusinessDays(
69
+ cache,
70
+ fetchStrategy,
71
+ subBusinessDays,
72
+ cacheOpts?.serializeOptions
73
+ ),
74
+ isNonBusinessDay: wrapperDateNonBusinessDays(
75
+ cache,
76
+ fetchStrategy,
77
+ isNonBusinessDay,
78
+ cacheOpts?.serializeOptions
79
+ ),
80
+ isBusinessDay: wrapperDateNonBusinessDays(
81
+ cache,
82
+ fetchStrategy,
83
+ isBusinessDay,
84
+ cacheOpts?.serializeOptions
85
+ ),
86
+ };
87
+ }
@@ -0,0 +1,78 @@
1
+ import { InternalServerError } from "@alanszp/errors";
2
+ import isArray from "lodash/isArray";
3
+ import LRUCache from "lru-cache";
4
+
5
+ export function wrapperDateAndNumberNonBusinessDays<IdentifyObject, R>(
6
+ cacheNBD: LRUCache<string, Date[]>,
7
+ fetchStrategy: ((opts?: IdentifyObject) => Promise<Date[]>) | Date[],
8
+ fn: (
9
+ nonBusinessDays: Date[],
10
+ dirtyDate: Date | number,
11
+ dirtyAmount: number
12
+ ) => R,
13
+ serializeOptions?: (opts?: IdentifyObject) => string
14
+ ) {
15
+ if (isArray(fetchStrategy)) {
16
+ return (dirtyDate: Date | number, dirtyAmount: number) =>
17
+ fn(fetchStrategy, dirtyDate, dirtyAmount);
18
+ }
19
+
20
+ return async (
21
+ dirtyDate: Date | number,
22
+ dirtyAmount: number,
23
+ identify?: IdentifyObject
24
+ ): Promise<R> => {
25
+ const cacheIdentify = serializeOptions
26
+ ? serializeOptions(identify)
27
+ : JSON.stringify(identify);
28
+ const cache = cacheNBD.get(cacheIdentify);
29
+
30
+ let nonBusinessDays: Date[] = [];
31
+
32
+ if (!cache) {
33
+ try {
34
+ nonBusinessDays = await fetchStrategy(identify);
35
+ cacheNBD.set(cacheIdentify, nonBusinessDays);
36
+ } catch (error: unknown) {
37
+ throw new InternalServerError(error);
38
+ }
39
+ } else {
40
+ nonBusinessDays = cache;
41
+ }
42
+
43
+ return fn(nonBusinessDays, dirtyDate, dirtyAmount);
44
+ };
45
+ }
46
+
47
+ export function wrapperDateNonBusinessDays<IdentifyObject, R>(
48
+ cacheNBD: LRUCache<string, Date[]>,
49
+ fetchStrategy: ((opts?: IdentifyObject) => Promise<Date[]>) | Date[],
50
+ fn: (nonBusinessDays: Date[], date: Date) => R,
51
+ serializeOptions?: (opts?: IdentifyObject) => string
52
+ ) {
53
+ if (isArray(fetchStrategy)) {
54
+ return (date: Date) => fn(fetchStrategy, date);
55
+ }
56
+
57
+ return async (date: Date, identify?: IdentifyObject): Promise<R> => {
58
+ const cacheIdentify = serializeOptions
59
+ ? serializeOptions(identify)
60
+ : JSON.stringify(identify);
61
+ const cache = cacheNBD.get(cacheIdentify);
62
+
63
+ let nonBusinessDays: Date[] = [];
64
+
65
+ if (!cache) {
66
+ try {
67
+ nonBusinessDays = await fetchStrategy(identify);
68
+ cacheNBD.set(cacheIdentify, nonBusinessDays);
69
+ } catch (error: unknown) {
70
+ throw new InternalServerError(error);
71
+ }
72
+ } else {
73
+ nonBusinessDays = cache;
74
+ }
75
+
76
+ return fn(nonBusinessDays, date);
77
+ };
78
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "rootDir": "src",
4
+ "outDir": "dist",
5
+ "module": "commonjs",
6
+ "target": "es6",
7
+ "types": ["jest", "node"],
8
+ "esModuleInterop": true,
9
+ "sourceMap": true,
10
+
11
+ "alwaysStrict": true,
12
+ "strictNullChecks": true
13
+ },
14
+ "exclude": ["node_modules"]
15
+ }