Repository navigation
Expand file tree
/
Copy pathmethods.ts
More file actions
190 lines (169 loc) · 6.63 KB
/
Copy pathmethods.ts
File metadata and controls
190 lines (169 loc) · 6.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import type { Product, ProductField } from './entities/catalog.js'
import type {
Activity,
BoolString,
Company,
Contact,
Currency,
CurrencyLocalization,
Deal,
Fields,
Id,
Input,
Lead,
ProductRow,
Status
} from './entities/crm.js'
import type { User } from './entities/user.js'
type Empty = Readonly<Record<string, never>>
export type FilterValue = string | number | boolean | null | ReadonlyArray<string | number>
export type Filter = Readonly<Record<string, FilterValue>>
export type Order = 'ASC' | 'DESC' | 'asc' | 'desc'
type MultiFields = 'PHONE' | 'EMAIL' | 'WEB' | 'IM' | 'LINK'
export type SelectField<E> = (keyof E & string) | '*' | 'UF_*' | MultiFields
export type ListParams<E, S extends readonly SelectField<E>[] = readonly SelectField<E>[]> = {
readonly select?: S
readonly filter?: Filter
readonly order?: { readonly [K in keyof E & string]?: Order }
readonly start?: number
}
type Standard<E> = Omit<E, `UF_${string}` | MultiFields>
type Nothing = Record<never, never>
type Flatten<T> = { [K in keyof T]: T[K] }
/**
* Row type of a CRM list for a given `select`: `*` and no select give the standard fields, `UF_*` adds
* user fields, named fields are picked as they are
*/
export type Selected<E, S extends readonly string[]> = Flatten<
S extends readonly []
? Standard<E>
: ('*' extends S[number] ? Standard<E> : Nothing) &
('UF_*' extends S[number] ? Pick<E, keyof E & `UF_${string}`> : Nothing) &
Pick<E, S[number] & keyof E>
>
type SonetParams = { readonly params?: { readonly REGISTER_SONET_EVENT?: BoolString } }
type CrmMethods<Name extends string, E> = Record<`crm.${Name}.fields`, { params: Empty; result: Fields }> &
Record<`crm.${Name}.get`, { params: { readonly id: Id }; result: E }> &
Record<`crm.${Name}.list`, { params: ListParams<E>; result: E[] }> &
Record<`crm.${Name}.add`, { params: { readonly fields: Input<E> } & SonetParams; result: number }> &
Record<
`crm.${Name}.update`,
{ params: { readonly id: Id; readonly fields: Input<E> } & SonetParams; result: boolean }
> &
Record<`crm.${Name}.delete`, { params: { readonly id: Id }; result: boolean }>
type ProductRowMethods<Name extends string> = Record<
`crm.${Name}.productrows.get`,
{ params: { readonly id: Id }; result: ProductRow[] }
> &
Record<
`crm.${Name}.productrows.set`,
{ params: { readonly id: Id; readonly rows: ReadonlyArray<Input<ProductRow>> }; result: boolean }
>
type CurrencyInput = Input<Omit<Currency, 'LANG'>> & {
readonly LANG?: Readonly<Record<string, Input<CurrencyLocalization>>>
}
type ProductFilter = Filter & { readonly iblockId: number }
type ProductInput = Input<Product> & { readonly iblockId: number; readonly name: string }
/**
* Registry of typed REST methods. Augment it to type methods the client does not cover:
* ```ts
* declare module '@2bad/bitrix' {
* interface Methods {
* 'tasks.task.get': { params: { taskId: number }; result: { task: Task } }
* }
* }
* ```
*/
export interface Methods
extends
CrmMethods<'deal', Deal>,
CrmMethods<'lead', Lead>,
CrmMethods<'contact', Contact>,
CrmMethods<'company', Company>,
CrmMethods<'activity', Activity>,
ProductRowMethods<'deal'>,
ProductRowMethods<'lead'> {
'crm.status.fields': { params: Empty; result: Fields }
'crm.status.get': { params: { readonly id: Id }; result: Status }
'crm.status.list': {
params: Pick<ListParams<Status>, 'filter' | 'order'>
result: Status[]
}
'crm.status.add': { params: { readonly fields: Input<Status> }; result: number }
'crm.status.update': { params: { readonly id: Id; readonly fields: Input<Status> }; result: boolean }
'crm.status.delete': {
params: { readonly id: Id; readonly params?: { readonly FORCED?: BoolString } }
result: boolean
}
'crm.currency.fields': { params: Empty; result: Fields }
'crm.currency.get': { params: { readonly id: string }; result: Currency }
'crm.currency.list': { params: Pick<ListParams<Currency>, 'order'>; result: Currency[] }
'crm.currency.add': { params: { readonly fields: CurrencyInput & { readonly CURRENCY: string } }; result: string }
'crm.currency.update': { params: { readonly id: string; readonly fields: CurrencyInput }; result: boolean }
'crm.currency.delete': { params: { readonly id: string }; result: boolean }
'crm.currency.base.get': { params: Empty; result: string }
'crm.currency.base.set': { params: { readonly id: string }; result: boolean }
'user.fields': { params: Empty; result: Record<string, string> }
'user.current': { params: Empty; result: User }
'user.get': {
params: {
readonly ID?: Id
readonly filter?: Filter
readonly sort?: keyof User & string
readonly order?: Order
readonly start?: number
readonly ADMIN_MODE?: boolean
}
result: User[]
}
'catalog.product.getFieldsByFilter': {
params: { readonly filter: ProductFilter }
result: { product: Record<string, ProductField> }
}
'catalog.product.get': { params: { readonly id: Id }; result: { product: Product } }
'catalog.product.list': {
params: {
readonly select?: ReadonlyArray<keyof Product & string>
readonly filter: ProductFilter
readonly order?: { readonly [K in keyof Product & string]?: Order }
readonly start?: number
}
result: { products: Product[] }
}
'catalog.product.add': { params: { readonly fields: ProductInput }; result: { element: Product } }
'catalog.product.update': {
params: { readonly id: Id; readonly fields: Input<Product> }
result: { element: Product }
}
'catalog.product.delete': { params: { readonly id: Id }; result: boolean }
}
/**
* Any method name. Known ones autocomplete and get typed params and results, the rest fall back to loose types
*/
export type Method = keyof Methods | (string & Record<never, never>)
export type Params<M extends string> = M extends keyof Methods
? Methods[M] extends { params: infer P }
? P
: never
: Readonly<Record<string, unknown>>
export type Result<M extends string> = M extends keyof Methods
? Methods[M] extends { result: infer R }
? R
: never
: unknown
/**
* Row type of a list method: the array itself, or the single array a catalog style result wraps it in
*/
export type Item<M extends string> =
Result<M> extends readonly (infer I)[]
? I
: Result<M> extends Readonly<Record<string, readonly (infer I)[]>>
? I
: unknown
/**
* Positional arguments after the method name: params are optional when the method requires none
*/
export type Args<M extends string, O> =
Readonly<Record<string, never>> extends Params<M>
? [params?: Params<M>, options?: O]
: [params: Params<M>, options?: O]