1
+ import type { FetchBaseQueryError } from "@reduxjs/toolkit/query" ;
2
+
1
3
// -----------------------------------------------------------------------------
2
4
// Model Types
3
5
// -----------------------------------------------------------------------------
4
6
5
7
// The fields of a model.
6
8
export type Fields = Record < string , unknown > ;
7
9
10
+ export type TagId = string | number ;
11
+
12
+ export type Tag < Type extends string > = {
13
+ type : Type ;
14
+ id : TagId ;
15
+ } ;
16
+
8
17
/**
9
18
* A data model.
10
- * ID: The type of ID.
11
- * ReadAndWrite: The fields that can both be read from and written to.
12
- * ReadOnly: The fields that can only be read from. 'id' is a mandatory
13
- * read-only field.
14
- * WriteOnly: The fields that can only be written to.
19
+ * Id: The type of Id.
20
+ * Data: The data fields.
15
21
*/
16
- export type Model <
17
- ID ,
18
- ReadAndWrite extends Fields = Fields ,
19
- ReadOnly extends Fields = Fields ,
20
- WriteOnly extends Fields = Fields
21
- > = ReadAndWrite & {
22
- _readOnly : ReadOnly & { id : ID ; } ;
23
- _writeOnly : WriteOnly ;
24
- } ;
22
+ export type Model < Id extends TagId , MFields extends Fields = Fields > = {
23
+ id : Id ;
24
+ } & Omit < MFields , "id" > ;
25
25
26
- // Gets the type of a model's ID.
27
- export type ID < M extends Model < any > > = M [ '_readOnly' ] [ 'id' ] ;
26
+ export type Result < M extends Model < any > , MFields extends keyof M = "id" > = Pick <
27
+ M ,
28
+ "id" | MFields
29
+ > ;
28
30
29
- // Gets the types of a model's readable fields.
30
- export type ReadFields < M extends Model < any > > =
31
- Omit < M , '_readOnly' | '_writeOnly' > & M [ '_readOnly' ] ;
32
-
33
- // Gets the types of a model's writeable fields.
34
- export type WriteFields < M extends Model < any > > =
35
- Omit < M , '_readOnly' | '_writeOnly' > & M [ '_writeOnly' ] ;
36
-
37
- // Gets the types of a model's readable and writeable fields.
38
- export type ReadAndWriteFields < M extends Model < any > > =
39
- Omit < M , '_readOnly' | '_writeOnly' > & M [ '_readOnly' ] & M [ '_writeOnly' ] ;
40
-
41
- // An array of tags with ID's.
42
- export type TagArray <
43
- Type extends string ,
44
- M extends Model < any > ,
45
- LookupField extends keyof ReadFields < M > = 'id'
46
- > = Array < {
47
- type : Type ;
48
- id : ReadFields < M > [ LookupField ] ;
49
- } > ;
31
+ export type Arg < M extends Model < any > , MFields extends keyof M > = Pick <
32
+ M ,
33
+ MFields
34
+ > ;
50
35
51
36
// -----------------------------------------------------------------------------
52
37
// CRUD Types
@@ -55,103 +40,199 @@ export type TagArray<
55
40
56
41
// Create
57
42
58
- export type CreateResult < M extends Model < any > > = ReadFields < M > ;
43
+ export type CreateResult <
44
+ M extends Model < any > ,
45
+ MFields extends keyof M = "id" ,
46
+ > = Result < M , MFields > ;
59
47
60
- export type CreateArg < M extends Model < any > > = WriteFields < M > ;
48
+ export type CreateArg <
49
+ M extends Model < any > ,
50
+ MFields extends keyof Omit < M , "id" > ,
51
+ > = Arg < M , MFields > ;
61
52
62
- export type BulkCreateResult < M extends Model < any > > = Array < CreateResult < M > > ;
53
+ export type BulkCreateResult <
54
+ M extends Model < any > ,
55
+ MFields extends keyof M = "id" ,
56
+ ExtraFields extends Fields = Fields ,
57
+ > = Array < Result < M , MFields > & ExtraFields > ;
63
58
64
- export interface BulkCreateArg < M extends Model < any > > {
65
- data : Array < CreateArg < M > > ;
66
- }
59
+ export type BulkCreateArg <
60
+ M extends Model < any > ,
61
+ MFields extends keyof Omit < M , "id" > ,
62
+ ExtraFields extends Fields = Fields ,
63
+ > = Array < Arg < M , MFields > & ExtraFields > ;
67
64
68
65
// Read
69
66
70
- export type RetrieveResult < M extends Model < any > > = ReadFields < M > ;
71
-
72
- export type RetrieveArg <
67
+ export type RetrieveResult <
73
68
M extends Model < any > ,
74
- LookupField extends keyof ReadAndWriteFields < M > = 'id'
75
- > = Pick < ReadAndWriteFields < M > , LookupField > ;
69
+ MFields extends keyof M = "id" ,
70
+ > = Result < M , MFields > ;
71
+
72
+ export type RetrieveArg < M extends Model < any > > = M [ "id" ] ;
76
73
77
- export interface ListResult < M extends Model < any > > {
74
+ export interface ListResult <
75
+ M extends Model < any > ,
76
+ MFields extends keyof M = "id" ,
77
+ ExtraFields extends Fields = Fields ,
78
+ > {
78
79
count : number ;
79
80
offset : number ;
80
81
limit : number ;
81
82
maxLimit : number ;
82
- data : Array < RetrieveResult < M > > ;
83
+ data : Array < Result < M , MFields > & ExtraFields > ;
83
84
}
84
85
85
- export type ListArg < Filters extends Fields = Fields > =
86
- null | Partial < Filters > ;
86
+ export type ListArg < Filters extends Fields = Fields > = {
87
+ limit : number ;
88
+ offset : number ;
89
+ } & Partial < Omit < Filters , "limit" | "offset" > > ;
87
90
88
91
// Update
89
92
90
- export type UpdateResult < M extends Model < any > > = ReadFields < M > ;
93
+ export type UpdateResult <
94
+ M extends Model < any > ,
95
+ MFields extends keyof M = "id" ,
96
+ > = Result < M , MFields > ;
91
97
92
98
export type UpdateArg <
93
99
M extends Model < any > ,
94
- LookupField extends keyof ReadAndWriteFields < M > = 'id'
95
- > = Pick < ReadAndWriteFields < M > , LookupField > & Partial < WriteFields < M > > ;
100
+ MFields extends keyof Omit < M , "id" > ,
101
+ ExtraFields extends Fields = Fields ,
102
+ > = [ M [ "id" ] , Arg < M , MFields > & ExtraFields ] ;
96
103
97
- export type BulkUpdateResult < M extends Model < any > > = Array < UpdateResult < M > > ;
104
+ export type BulkUpdateResult <
105
+ M extends Model < any > ,
106
+ MFields extends keyof M = "id" ,
107
+ ExtraFields extends Fields = Fields ,
108
+ > = Array < Result < M , MFields > & ExtraFields > ;
98
109
99
- export interface BulkUpdateArg <
110
+ export type BulkUpdateArg <
100
111
M extends Model < any > ,
101
- LookupField extends keyof ReadAndWriteFields < M > = 'id'
102
- > {
103
- data : Array < UpdateArg < M , LookupField > > ;
104
- }
112
+ MFields extends keyof Omit < M , "id" > ,
113
+ ExtraFields extends Fields = Fields ,
114
+ > = Record < M [ "id" ] , Arg < M , MFields > & ExtraFields > ;
115
+
116
+ export type PartialUpdateResult <
117
+ M extends Model < any > ,
118
+ MFields extends keyof M = "id" ,
119
+ > = Result < M , MFields > ;
120
+
121
+ export type PartialUpdateArg <
122
+ M extends Model < any > ,
123
+ MFields extends keyof Omit < M , "id" > ,
124
+ ExtraFields extends Fields = Fields ,
125
+ > = [ M [ "id" ] , Partial < Arg < M , MFields > & ExtraFields > ] ;
126
+
127
+ export type BulkPartialUpdateResult <
128
+ M extends Model < any > ,
129
+ MFields extends keyof M = "id" ,
130
+ ExtraFields extends Fields = Fields ,
131
+ > = Array < Result < M , MFields > & ExtraFields > ;
132
+
133
+ export type BulkPartialUpdateArg <
134
+ M extends Model < any > ,
135
+ MFields extends keyof Omit < M , "id" > ,
136
+ ExtraFields extends Fields = Fields ,
137
+ > = Record < M [ "id" ] , Partial < Arg < M , MFields > & ExtraFields > > ;
105
138
106
139
// Delete
107
140
108
141
export type DestroyResult = null ;
109
142
110
- export type DestroyArg <
111
- M extends Model < any > ,
112
- LookupField extends keyof ReadAndWriteFields < M > = 'id'
113
- > = Pick < ReadAndWriteFields < M > , LookupField > ;
143
+ export type DestroyArg < M extends Model < any > > = M [ "id" ] ;
114
144
115
145
export type BulkDestroyResult = null ;
116
146
117
- export interface BulkDestroyArg <
118
- M extends Model < any > ,
119
- LookupField extends keyof ReadAndWriteFields < M > = 'id'
120
- > {
121
- LookupField : Array < DestroyArg < M , LookupField > [ LookupField ] > ;
122
- }
147
+ export type BulkDestroyArg < M extends Model < any > > = Array < M [ "id" ] > ;
123
148
124
149
// -----------------------------------------------------------------------------
125
150
// Functions
126
151
// -----------------------------------------------------------------------------
127
152
128
- export function searchParamsToString ( arg : ListArg ) : string {
129
- if ( arg !== null ) {
130
- const searchParams = Object . entries ( arg )
153
+ export function buildUrl (
154
+ url : string ,
155
+ params : {
156
+ search ?: Fields ;
157
+ url ?: Fields ;
158
+ }
159
+ ) : string {
160
+ if ( params . url ) {
161
+ Object . entries ( params . url ) . forEach ( ( [ key , value ] ) => {
162
+ url = url . replace ( `<${ key } >` , String ( value ) ) ;
163
+ } ) ;
164
+ }
165
+
166
+ if ( params . search ) {
167
+ const searchParams = Object . entries ( params . search )
131
168
. filter ( ( [ _ , value ] ) => value !== undefined )
132
169
. map ( ( [ key , value ] ) => [ key , String ( value ) ] ) ;
133
170
134
171
if ( searchParams . length !== 0 ) {
135
- return `?${ new URLSearchParams ( searchParams ) . toString ( ) } ` ;
172
+ url += `?${ new URLSearchParams ( searchParams ) . toString ( ) } ` ;
136
173
}
137
174
}
138
175
139
- return '' ;
176
+ return url ;
140
177
}
141
178
142
- export function tagData <
143
- Type extends string ,
144
- M extends Model < any > ,
145
- LookupField extends keyof ReadFields < M > = 'id'
146
- > (
147
- result : ListResult < M > | BulkCreateResult < M > ,
148
- type : Type ,
149
- lookupField : LookupField = 'id' as LookupField
150
- ) : TagArray < Type , M , LookupField > {
151
- const data = 'data' in result ? result . data : result ;
152
-
153
- return data . map ( ( result ) => ( {
154
- type,
155
- id : result [ lookupField ]
156
- } ) ) as TagArray < Type , M , LookupField > ;
179
+ export function isTagId ( value : unknown ) : boolean {
180
+ return typeof value === "number" || typeof value === "string" ;
181
+ }
182
+
183
+ export function tagData < Type extends string , M extends Model < any > > (
184
+ type : Type
185
+ ) : (
186
+ result :
187
+ | Result < M , any >
188
+ | Array < Result < M , any > >
189
+ | ListResult < M , any >
190
+ | null
191
+ | undefined ,
192
+ error : FetchBaseQueryError | undefined ,
193
+ arg :
194
+ | Arg < M , any >
195
+ | Array < Arg < M , any > >
196
+ | [ M [ "id" ] , Arg < M , any > ]
197
+ | Record < M [ "id" ] , Arg < M , any > >
198
+ | ListArg < any >
199
+ | Array < M [ "id" ] >
200
+ | string
201
+ | number
202
+ | undefined
203
+ ) => Array < Tag < Type > > {
204
+ return ( result , error , arg ) => {
205
+ if ( ! error ) {
206
+ if ( arg ) {
207
+ if ( isTagId ( arg ) ) return [ { type, id : arg as TagId } ] ;
208
+
209
+ if ( Array . isArray ( arg ) && arg . length > 0 ) {
210
+ if ( isTagId ( arg [ 0 ] ) ) {
211
+ if ( arg . length === 2 && ! isTagId ( arg [ 1 ] ) ) {
212
+ return [ { type, id : ( arg as [ M [ "id" ] , Arg < M , any > ] ) [ 0 ] } ] ;
213
+ }
214
+
215
+ return ( arg as Array < M [ "id" ] > ) . map ( ( id ) => ( { type, id } ) ) ;
216
+ }
217
+ }
218
+ }
219
+
220
+ if ( result ) {
221
+ if ( "id" in result ) {
222
+ return [ { type, id : result [ "id" ] as TagId } ] ;
223
+ }
224
+
225
+ if ( Array . isArray ( result ) ) {
226
+ return result . map ( ( result ) => ( { type, id : result [ "id" ] as TagId } ) ) ;
227
+ }
228
+
229
+ return ( result as ListResult < M , any > ) . data . map ( ( result ) => ( {
230
+ type,
231
+ id : result [ "id" ] as TagId ,
232
+ } ) ) ;
233
+ }
234
+ }
235
+
236
+ return [ ] ;
237
+ } ;
157
238
}
0 commit comments