relation-matcher 1.0.13 → 1.1.1

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 (40) hide show
  1. package/.vscode/settings.json +4 -4
  2. package/.yarn/install-state.gz +0 -0
  3. package/.yarn/releases/yarn-4.13.0.cjs +940 -940
  4. package/.yarnrc.yml +3 -3
  5. package/README.md +185 -150
  6. package/dist/src/index.d.ts +10 -5
  7. package/dist/src/index.js +35 -46
  8. package/dist/src/types/generic-bases.d.ts +2 -1
  9. package/dist/src/types/generic-less.d.ts +8 -3
  10. package/dist/src/types/inputs.d.ts +14 -7
  11. package/dist/src/types/return.d.ts +5 -2
  12. package/dist/src/types/typetest.d.ts +1 -0
  13. package/dist/src/types/utils.d.ts +3 -0
  14. package/dist/src/utils/invertInput.d.ts +2 -1
  15. package/dist/src/utils/invertInput.js +4 -9
  16. package/dist/src/utils/isNullable.d.ts +2 -0
  17. package/dist/src/utils/isNullable.js +6 -0
  18. package/dist/src/utils/joins.d.ts +5 -0
  19. package/dist/src/utils/joins.js +9 -0
  20. package/dist/src/utils/keys.js +6 -1
  21. package/dist/src/utils/matcher.d.ts +3 -3
  22. package/dist/src/utils/matcher.js +2 -1
  23. package/dist/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +36 -36
  25. package/src/index.test.ts +105 -105
  26. package/src/index.ts +124 -151
  27. package/src/testing/file-output.ts +15 -15
  28. package/src/testing/test-data.ts +172 -172
  29. package/src/types/generic-bases.ts +10 -9
  30. package/src/types/generic-less.ts +20 -14
  31. package/src/types/index.ts +5 -5
  32. package/src/types/inputs.ts +36 -30
  33. package/src/types/return.ts +65 -67
  34. package/src/types/typetest.ts +87 -84
  35. package/src/types/utils.ts +33 -28
  36. package/src/utils/invertInput.ts +27 -28
  37. package/src/utils/isNullable.ts +11 -0
  38. package/src/utils/joins.ts +22 -0
  39. package/src/utils/keys.ts +7 -1
  40. package/src/utils/matcher.ts +16 -8
@@ -1,84 +1,87 @@
1
- import type { RelationMapperReturnRoot } from "./return";
2
- import type { DeepSimplify, ExtendsNull, Simplify } from "./utils";
3
-
4
- export type A = DeepSimplify<
5
- RelationMapperReturnRoot<
6
- {
7
- team: {
8
- created_at: Date;
9
- updated_at: Date | null;
10
- id: string;
11
- team_name: string;
12
- club_name: string;
13
- club_postcode: string;
14
- };
15
- team_to_user: {
16
- created_at: Date;
17
- updated_at: Date | null;
18
- user_clerk_id: string;
19
- team_id: string;
20
- } | null;
21
- },
22
- {
23
- base: "team";
24
- id: "id";
25
-
26
- _teamToUser: {
27
- base: "team_to_user";
28
- id: "user_clerk_id";
29
- joinsTo: "team_id";
30
- joinsFrom: "id";
31
- joinType: "single";
32
-
33
- _team: {
34
- base: "team";
35
- id: "id";
36
- joinsFrom: "team_id";
37
- joinsTo: "id";
38
- joinType: "array";
39
- };
40
- };
41
- }
42
- >,
43
- Date | null | number
44
- >;
45
-
46
- type B = RelationMapperReturnRoot<
47
- {
48
- user: {
49
- clerk_id: string;
50
- };
51
- team_to_user: {
52
- team_id: string;
53
- user_clerk_id: string;
54
- } | null;
55
- },
56
- {
57
- base: "user";
58
- id: "clerk_id";
59
-
60
- _teamToUser: {
61
- base: "team_to_user";
62
- id: "team_id";
63
- joinsFrom: "clerk_id";
64
- joinsTo: "user_clerk_id";
65
- joinType: "single";
66
-
67
- _user: {
68
- base: "user";
69
- id: "clerk_id";
70
- joinsFrom: "user_clerk_id";
71
- joinsTo: "clerk_id";
72
- joinType: "array";
73
- };
74
- };
75
- }
76
- >;
77
-
78
- type C = Simplify<B>;
79
- // ^?
80
-
81
- type D = ExtendsNull<{
82
- team_id: string;
83
- user_clerk_id: string;
84
- } | null>;
1
+ import type { RelationMapperReturnRoot } from "./return";
2
+ import type { DeepSimplify, ExtendsNull, Simplify } from "./utils";
3
+
4
+ type E = true extends undefined ? true : false;
5
+
6
+ export type A = DeepSimplify<
7
+ RelationMapperReturnRoot<
8
+ {
9
+ team: {
10
+ created_at: Date;
11
+ updated_at: Date | null;
12
+ id: string;
13
+ team_name: string;
14
+ club_name: string;
15
+ club_postcode: string;
16
+ };
17
+ team_to_user: {
18
+ created_at: Date;
19
+ updated_at: Date | null;
20
+ user_clerk_id: string;
21
+ team_id: string;
22
+ } | null;
23
+ },
24
+ {
25
+ base: "team";
26
+ id: "id";
27
+
28
+ _teamToUser: {
29
+ base: "team_to_user";
30
+ id: "user_clerk_id";
31
+ joinsTo: "team_id";
32
+ joinsFrom: "id";
33
+ joinType: "single";
34
+ isNullable: false;
35
+
36
+ _team: {
37
+ base: "team";
38
+ id: "id";
39
+ joinsFrom: "team_id";
40
+ joinsTo: "id";
41
+ joinType: "array";
42
+ };
43
+ };
44
+ }
45
+ >,
46
+ Date | null | number
47
+ >;
48
+
49
+ type B = RelationMapperReturnRoot<
50
+ {
51
+ user: {
52
+ clerk_id: string;
53
+ };
54
+ team_to_user: {
55
+ team_id: string;
56
+ user_clerk_id: string;
57
+ } | null;
58
+ },
59
+ {
60
+ base: "user";
61
+ id: "clerk_id";
62
+
63
+ _teamToUser: {
64
+ base: "team_to_user";
65
+ id: "team_id";
66
+ joinsFrom: "clerk_id";
67
+ joinsTo: "user_clerk_id";
68
+ joinType: "single";
69
+
70
+ _user: {
71
+ base: "user";
72
+ id: "clerk_id";
73
+ joinsFrom: "user_clerk_id";
74
+ joinsTo: "clerk_id";
75
+ joinType: "array";
76
+ };
77
+ };
78
+ }
79
+ >;
80
+
81
+ type C = Simplify<B>;
82
+ // ^?
83
+
84
+ type D = ExtendsNull<{
85
+ team_id: string;
86
+ user_clerk_id: string;
87
+ } | null>;
@@ -1,28 +1,33 @@
1
- export type Simplify<T> = {
2
- [k in keyof T]: T[k];
3
- } & {};
4
-
5
- export type DeepSimplify<TInput, TDontSimplify> = {
6
- [k in keyof TInput]: TInput[k] extends TDontSimplify
7
- ? TInput[k]
8
- : DeepSimplify<TInput[k], TDontSimplify>;
9
- } & {};
10
-
11
- export type NoUnderscore<T extends string | number | symbol> =
12
- T extends `_${infer Result}` ? Result : never;
13
-
14
- export type DeepNonNullable<T extends object> = {
15
- [k in keyof T]: T[k] extends infer NonNull | null ? NonNull : T[k];
16
- };
17
-
18
- export type ArrayOrSingle<
19
- T,
20
- TType extends "single" | "array",
21
- > = TType extends "array" ? Array<T> : T;
22
-
23
- export type IsNullIfNull<
24
- TIsNull extends object | null,
25
- TReturn extends object | never = never,
26
- > = TIsNull extends infer T ? (T & TReturn) | null : TIsNull & TReturn;
27
-
28
- export type ExtendsNull<T> = null extends T ? true : false;
1
+ export type Simplify<T> = {
2
+ [k in keyof T]: T[k];
3
+ } & {};
4
+
5
+ export type DeepSimplify<TInput, TDontSimplify> = {
6
+ [k in keyof TInput]: TInput[k] extends TDontSimplify
7
+ ? TInput[k]
8
+ : DeepSimplify<TInput[k], TDontSimplify>;
9
+ } & {};
10
+
11
+ export type NoUnderscore<T extends string | number | symbol> =
12
+ T extends `_${infer Result}` ? Result : never;
13
+
14
+ export type DeepNonNullable<T extends object> = {
15
+ [k in keyof T]: T[k] extends infer NonNull | null ? NonNull : T[k];
16
+ };
17
+
18
+ export type ArrayOrSingle<
19
+ T,
20
+ TType extends "single" | "array",
21
+ > = TType extends "array" ? Array<T> : T;
22
+
23
+ export type IsNullIfNull<
24
+ TIsNull extends object | null,
25
+ TReturn extends object | never = never,
26
+ > = TIsNull extends infer T ? (T & TReturn) | null : TIsNull & TReturn;
27
+
28
+ export type ExtendsNull<T> = null extends T ? true : false;
29
+
30
+ export type MaybeNull<T> = T | null;
31
+ export type MaybeArray<T> = T | T[];
32
+
33
+ export type SRecord<T> = Record<string, T>;
@@ -1,28 +1,27 @@
1
- import type { TInputBase } from "~/types/generic-bases";
2
-
3
- export type InvertedInput<TInput extends TInputBase = TInputBase> = Record<
4
- keyof TInput,
5
- TInput[keyof TInput][]
6
- >;
7
-
8
- const invertInput = <TInput extends TInputBase>(
9
- inputs: TInputBase[],
10
- ): InvertedInput<TInput> => {
11
- const invertedInput = inputs.reduce<InvertedInput<TInput>>((final, row) => {
12
- Object.entries(row).forEach(([header, value]) => {
13
- if (final[header]) {
14
- if (value) final[header].push(value as TInput[keyof TInput]);
15
- } else {
16
- final[header as keyof TInput] = value
17
- ? [value as TInput[keyof TInput]]
18
- : [];
19
- }
20
- });
21
-
22
- return final;
23
- }, {} as InvertedInput<TInput>);
24
-
25
- return invertedInput;
26
- };
27
-
28
- export default invertInput;
1
+ import type { TInputBase } from "~/types/generic-bases";
2
+
3
+ export type InvertedInputRow<TInput extends TInputBase = TInputBase> =
4
+ TInput[keyof TInput][];
5
+ export type InvertedInput<TInput extends TInputBase = TInputBase> = Record<
6
+ keyof TInput,
7
+ InvertedInputRow<TInput>
8
+ >;
9
+
10
+ const invertInput = <TInput extends TInputBase>(
11
+ inputs: TInputBase[],
12
+ ): InvertedInput<TInput> => {
13
+ const invertedInput = inputs.reduce<InvertedInput<TInput>>((final, row) => {
14
+ Object.entries(row).forEach(([header, value]) => {
15
+ final[header as keyof TInput] ??= [];
16
+
17
+ // Instantiated above.
18
+ if (value) final[header]!.push(value as TInput[keyof TInput]);
19
+ });
20
+
21
+ return final;
22
+ }, {} as InvertedInput<TInput>);
23
+
24
+ return invertedInput;
25
+ };
26
+
27
+ export default invertInput;
@@ -0,0 +1,11 @@
1
+ /** Asserts that if `isNullable` is false then item is not null. */
2
+ export const assertIsNullable = (
3
+ item: Record<string, unknown> | null,
4
+ isNullable: false | undefined,
5
+ ) => {
6
+ if (isNullable === false && item === null) {
7
+ throw new Error(
8
+ "Value should exist as output schema defines it as nullable. Instead found null in array",
9
+ );
10
+ }
11
+ };
@@ -0,0 +1,22 @@
1
+ import type { OutputBase, TInputBase } from "~/types";
2
+ import type { InvertedInput, InvertedInputRow } from "./invertInput";
3
+ import { type MatcherFunc } from "./matcher";
4
+
5
+ export const singleJoinBase = <TValue extends OutputBase<"single">>(
6
+ input: InvertedInputRow,
7
+ matcherFunc: MatcherFunc,
8
+ ): Record<string, unknown> | null => {
9
+ const item =
10
+ (input.find(matcherFunc) as TInputBase[string] | undefined) ?? null;
11
+
12
+ return item;
13
+ };
14
+
15
+ export const arrayJoinBase = <TValue extends OutputBase<"single">>(
16
+ input: InvertedInputRow,
17
+ matcherFunc: MatcherFunc,
18
+ ): Record<string, unknown>[] => {
19
+ const item = input.filter(matcherFunc);
20
+
21
+ return item;
22
+ };
package/src/utils/keys.ts CHANGED
@@ -1 +1,7 @@
1
- export const getJoinFinalKey = (key: string) => key.substring(1);
1
+ export const getJoinFinalKey = (key: string) => {
2
+ if (key[0] !== "_") {
3
+ throw new Error("Joining key must start with underscore.");
4
+ }
5
+
6
+ return key.substring(1);
7
+ };
@@ -1,8 +1,16 @@
1
- import type { TInputBase } from "~/types/generic-bases";
2
- import type { InvertedInput } from "./invertInput";
3
- import type { Output } from "~/types/generic-less";
4
-
5
- export const matcherFunc =
6
- <TInput extends TInputBase>(row: TInput[keyof TInput], value: Output) =>
7
- (item: InvertedInput[keyof InvertedInput][number]) =>
8
- row?.[value.joinsFrom as string] === item?.[value.joinsTo as string];
1
+ import type { TInputBase, TInputBaseJoin } from "~/types/generic-bases";
2
+ import type { InvertedInput } from "./invertInput";
3
+ import type { Output } from "~/types/generic-less";
4
+
5
+ export type MatcherFunc = (
6
+ item: TInputBaseJoin | null,
7
+ ) => item is TInputBaseJoin;
8
+
9
+ export const createMatcherFunc =
10
+ <TInput extends TInputBase>(
11
+ row: TInput[keyof TInput],
12
+ value: Output,
13
+ ): MatcherFunc =>
14
+ (item): item is TInputBaseJoin =>
15
+ !!item &&
16
+ row?.[value.joinsFrom as string] === item?.[value.joinsTo as string];