@vrplatform/api 1.3.0-stage.1301 → 1.3.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.
package/src/index.ts CHANGED
@@ -1,8 +1,11 @@
1
+ import type { useIngest } from './ingest';
1
2
  import type { ApiClient } from './types';
2
3
 
3
4
  export * from './client';
4
5
  export * from './error';
5
6
  export * from './generated/v1';
7
+ export * from './ingest';
6
8
  export * from './types';
7
9
 
10
+ export type ApiIngest = ReturnType<typeof useIngest>;
8
11
  export type VRPlatformApi = ApiClient;
@@ -0,0 +1,227 @@
1
+ import { throwIfError } from '../error';
2
+ import type { ApiClient, RequestBody } from '../types';
3
+ import type * as t from './types';
4
+
5
+ export * from './types';
6
+
7
+ function mergeConfig(
8
+ body: any,
9
+ config: t.IngestArg,
10
+ configOverwrites?: t.IngestFnArg
11
+ ) {
12
+ const headers: Record<string, string> = {};
13
+ if (configOverwrites) {
14
+ const { correlationId, ...restOverwrites } = configOverwrites;
15
+ for (const [key, value] of Object.entries(restOverwrites))
16
+ if (value) body[key] = value;
17
+ if (correlationId) headers['X-Correlation-Id'] = correlationId;
18
+ }
19
+ if (config.sessionId) headers['X-Session-Id'] = config.sessionId;
20
+
21
+ return headers;
22
+ }
23
+
24
+ export function usePostSources(api: ApiClient, config: t.IngestArg) {
25
+ const { sessionId: _, ...restConfig } = config;
26
+ async function post<T = undefined>(
27
+ data: RequestBody<'post:/sources/batch'>['data'],
28
+ configOverwrites?: t.IngestFnArg
29
+ ): Promise<t.TypedResponseData<T>[]> {
30
+ const body: RequestBody<'post:/sources/batch'> = {
31
+ ...restConfig,
32
+ data,
33
+ };
34
+ const headers = mergeConfig(body, config, configOverwrites);
35
+ const response = throwIfError(
36
+ await api.POST('/sources/batch', { body, headers })
37
+ );
38
+ return response.data as any;
39
+ }
40
+ return post;
41
+ }
42
+
43
+ export function useIngest(api: ApiClient, config: t.IngestArg) {
44
+ const post = usePostSources(api, config);
45
+ return {
46
+ api,
47
+ get sessionId() {
48
+ return api.sessionId;
49
+ },
50
+ async sources(
51
+ changes: t.IngestSourceInput[],
52
+ configOverwrites?: t.IngestFnArg
53
+ ) {
54
+ if (!changes.length) return undefined;
55
+ return await post(changes, configOverwrites);
56
+ },
57
+ async updateSources(
58
+ data: RequestBody<'put:/sources/batch'>['data'],
59
+ configOverwrites?: t.IngestFnArg
60
+ ) {
61
+ const { sessionId: _, ...restConfig } = config;
62
+ const body: RequestBody<'put:/sources/batch'> = {
63
+ ...restConfig,
64
+ data,
65
+ };
66
+ const headers = mergeConfig(body, config, configOverwrites);
67
+ const response = throwIfError(
68
+ await api.PUT('/sources/batch', { body, headers })
69
+ );
70
+ return response.data;
71
+ },
72
+ async reservations(
73
+ changes: t.IngestReservationInput[],
74
+ configOverwrites?: t.IngestFnArg
75
+ ) {
76
+ if (!changes.length) return [];
77
+ return await post<t.ReservationParam>(
78
+ changes.map(({ source, ...transform }) => {
79
+ return {
80
+ ...source,
81
+ type: source.type || 'reservation',
82
+ description: source.description || transform.confirmationCode,
83
+ uniqueRef: source.uniqueRef || transform.uniqueRef!,
84
+ date: source.date || transform.bookedAt,
85
+ status: source.status || 'active',
86
+ transform: {
87
+ data: transform,
88
+ type: 'reservation',
89
+ },
90
+ };
91
+ }),
92
+ configOverwrites
93
+ );
94
+ },
95
+ async payments(
96
+ changes: t.IngestPaymentInput[],
97
+ configOverwrites?: t.IngestFnArg
98
+ ) {
99
+ if (!changes.length) return undefined;
100
+ return await post<t.PaymentParam>(
101
+ changes.map(({ source, ...transform }) => {
102
+ return {
103
+ ...source,
104
+ type: source.type || 'payment',
105
+ description: source.description || transform.description,
106
+ uniqueRef: source.uniqueRef || transform.uniqueRef!,
107
+ date: source.date || transform.paidAt,
108
+ status: source.status || 'active',
109
+ transform: {
110
+ data: transform,
111
+ type: 'payment',
112
+ },
113
+ };
114
+ }),
115
+ configOverwrites
116
+ );
117
+ },
118
+ async listings(
119
+ changes: t.IngestListingInput[],
120
+ configOverwrites?: t.IngestFnArg
121
+ ) {
122
+ if (!changes.length) return undefined;
123
+ return await post<t.ListingParam>(
124
+ changes.map(({ source, ...transform }) => {
125
+ return {
126
+ ...source,
127
+ type: source.type || 'listing',
128
+ description: source.description || transform.name,
129
+ uniqueRef: source.uniqueRef || transform.uniqueRef!,
130
+ status: source.status || 'active',
131
+ transform: {
132
+ data: transform,
133
+ type: 'listing',
134
+ },
135
+ };
136
+ }),
137
+ configOverwrites
138
+ );
139
+ },
140
+ async cleanup(
141
+ type: string | 'listing',
142
+ configOverwrites?: t.IngestFnArg & {
143
+ whereRange?: RequestBody<'put:/sources/cleanup'>['whereRange'];
144
+ }
145
+ ) {
146
+ const body: RequestBody<'put:/sources/cleanup'> = {
147
+ syncId: configOverwrites?.syncId || config.syncId,
148
+ connectionId: configOverwrites?.connectionId || config.connectionId,
149
+ type,
150
+ };
151
+ if (configOverwrites?.whereRange) {
152
+ body.whereRange = configOverwrites.whereRange;
153
+ }
154
+ const headers = mergeConfig(body, config, configOverwrites);
155
+ const response = throwIfError(
156
+ await api.PUT('/sources/cleanup', { body, headers })
157
+ );
158
+ return response.ok as any;
159
+ },
160
+ async bankRecords(
161
+ changes: t.IngestBankRecordInput[],
162
+ configOverwrites?: t.IngestFnArg
163
+ ) {
164
+ if (!changes.length) return undefined;
165
+ return await post<t.BankRecordParam>(
166
+ changes.map(({ source, ...transform }) => {
167
+ return {
168
+ ...source,
169
+ type: source.type || 'bankRecord',
170
+ description: source.description || transform.description,
171
+ uniqueRef: source.uniqueRef || transform.uniqueRef!,
172
+ status: source.status || 'active',
173
+ transform: {
174
+ data: transform,
175
+ type: 'bankRecord',
176
+ },
177
+ };
178
+ }),
179
+ configOverwrites
180
+ );
181
+ },
182
+ async transactions(
183
+ changes: t.IngestTransactionInput[],
184
+ configOverwrites?: t.IngestFnArg
185
+ ) {
186
+ if (!changes.length) return undefined;
187
+ return await post<t.TransactionParam>(
188
+ changes.map(({ source, ...transform }) => {
189
+ return {
190
+ ...source,
191
+ type: source.type || 'transaction',
192
+ description: source.description || transform.description,
193
+ uniqueRef: source.uniqueRef || transform.uniqueRef!,
194
+ status: source.status || 'active',
195
+ transform: {
196
+ data: transform,
197
+ type: 'transaction',
198
+ },
199
+ };
200
+ }),
201
+ configOverwrites
202
+ );
203
+ },
204
+ async contacts(
205
+ changes: t.IngestContactInput[],
206
+ configOverwrites?: t.IngestFnArg
207
+ ) {
208
+ if (!changes.length) return undefined;
209
+ return await post<t.ContactParam>(
210
+ changes.map(({ source, ...transform }) => {
211
+ return {
212
+ ...source,
213
+ type: source.type || 'contact',
214
+ description: source.description || transform.name,
215
+ uniqueRef: source.uniqueRef || transform.email!,
216
+ status: source.status || 'active',
217
+ transform: {
218
+ data: transform,
219
+ type: 'contact',
220
+ },
221
+ };
222
+ }),
223
+ configOverwrites
224
+ );
225
+ },
226
+ };
227
+ }
@@ -0,0 +1,91 @@
1
+ import type { PartialBy } from '@vrplatform/utils';
2
+ import type { RequestBody, ResponseData } from '../types';
3
+
4
+ export type ReservationParam = Omit<
5
+ RequestBody<'post:/reservations/batch'>['data'][0],
6
+ 'sourceId'
7
+ >;
8
+ export type PaymentParam = Omit<
9
+ RequestBody<'post:/payments/batch'>['data'][0],
10
+ 'sourceId'
11
+ >;
12
+ export type ListingParam = Omit<
13
+ RequestBody<'post:/listings/batch'>['data'][0],
14
+ 'sourceId'
15
+ >;
16
+ export type BankRecordParam = Omit<
17
+ RequestBody<'post:/bank-records/batch'>['data'][0],
18
+ 'sourceId'
19
+ >;
20
+ export type TransactionParam = Omit<
21
+ RequestBody<'post:/transactions/batch'>['data'][0],
22
+ 'sourceId'
23
+ >;
24
+ export type ContactParam = Omit<
25
+ RequestBody<'post:/contacts/batch'>['data'][0],
26
+ 'sourceId'
27
+ >;
28
+ type _SourceWithoutTransform = Omit<
29
+ RequestBody<'post:/sources/batch'>['data'][number],
30
+ 'transform'
31
+ > & {
32
+ // this is ONLY for ecosystem ingestion, can be removed once ecosystem does not rely on ingest, but calls batch endpoints
33
+ fileStorageId?: string;
34
+ };
35
+ type _SourceWithTransform<T> = _SourceWithoutTransform & {
36
+ transform: { type: string; data: T };
37
+ };
38
+ export type Source<T = undefined> = T extends undefined
39
+ ? _SourceWithoutTransform
40
+ : _SourceWithTransform<T>;
41
+
42
+ export type IngestArg = Omit<RequestBody<'post:/sources/batch'>, 'data'> & {
43
+ sessionId?: string;
44
+ tenantId: string;
45
+ };
46
+ export type IngestFnArg = Omit<Partial<IngestArg>, 'sessionId'> & {
47
+ correlationId?: string;
48
+ };
49
+
50
+ export type BatchResponseData = ResponseData<'post:/sources/batch'>['data'][0];
51
+ export type TypedResponseData<T = undefined> = Omit<
52
+ BatchResponseData,
53
+ 'transform'
54
+ > &
55
+ (T extends undefined
56
+ ? { transform?: never }
57
+ : {
58
+ transform: Omit<BatchResponseData['transform'], 'data'> & {
59
+ data: T;
60
+ };
61
+ });
62
+
63
+ export type Impossible<K extends keyof any> = {
64
+ [P in K]: never;
65
+ };
66
+ export type NoExtraProperties<T, U extends T = T> = U &
67
+ Impossible<Exclude<keyof U, keyof T>>;
68
+
69
+ export type ObjectWithSource<T = undefined> = T & {
70
+ source: PartialBy<_SourceWithoutTransform, 'type'>;
71
+ };
72
+
73
+ export type IngestReservationInput = NoExtraProperties<
74
+ ObjectWithSource<ReservationParam>
75
+ >;
76
+ export type IngestPaymentInput = NoExtraProperties<
77
+ ObjectWithSource<PaymentParam>
78
+ >;
79
+ export type IngestListingInput = NoExtraProperties<
80
+ ObjectWithSource<ListingParam>
81
+ >;
82
+ export type IngestBankRecordInput = NoExtraProperties<
83
+ ObjectWithSource<BankRecordParam>
84
+ >;
85
+ export type IngestTransactionInput = NoExtraProperties<
86
+ ObjectWithSource<TransactionParam>
87
+ >;
88
+ export type IngestContactInput = NoExtraProperties<
89
+ ObjectWithSource<ContactParam>
90
+ >;
91
+ export type IngestSourceInput = NoExtraProperties<Source>;