@teardown/ingest-api 0.1.46 → 0.1.47-alpha-01
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/generated/app.d.ts +82 -33
- package/package.json +1 -1
- package/src/client/index.ts +1 -0
- package/src/client/ingest.client.ts +171 -0
package/generated/app.d.ts
CHANGED
|
@@ -8,6 +8,12 @@ export declare const baseApp: Elysia<"", {
|
|
|
8
8
|
}, {
|
|
9
9
|
typebox: {};
|
|
10
10
|
error: {};
|
|
11
|
+
} & {
|
|
12
|
+
typebox: {};
|
|
13
|
+
error: {};
|
|
14
|
+
} & {
|
|
15
|
+
typebox: {};
|
|
16
|
+
error: {};
|
|
11
17
|
} & {
|
|
12
18
|
typebox: {};
|
|
13
19
|
error: {
|
|
@@ -30,6 +36,20 @@ export declare const baseApp: Elysia<"", {
|
|
|
30
36
|
macroFn: {};
|
|
31
37
|
parser: {};
|
|
32
38
|
response: {};
|
|
39
|
+
} & {
|
|
40
|
+
schema: {};
|
|
41
|
+
standaloneSchema: {};
|
|
42
|
+
macro: {};
|
|
43
|
+
macroFn: {};
|
|
44
|
+
parser: {};
|
|
45
|
+
response: {};
|
|
46
|
+
} & {
|
|
47
|
+
schema: {};
|
|
48
|
+
standaloneSchema: {};
|
|
49
|
+
macro: {};
|
|
50
|
+
macroFn: {};
|
|
51
|
+
parser: {};
|
|
52
|
+
response: {};
|
|
33
53
|
} & {
|
|
34
54
|
schema: {};
|
|
35
55
|
standaloneSchema: {};
|
|
@@ -51,12 +71,23 @@ export declare const baseApp: Elysia<"", {
|
|
|
51
71
|
body: unknown;
|
|
52
72
|
params: {};
|
|
53
73
|
query: unknown;
|
|
54
|
-
headers:
|
|
74
|
+
headers: {
|
|
75
|
+
"td-api-version"?: string | undefined;
|
|
76
|
+
};
|
|
55
77
|
response: {
|
|
56
78
|
200: import("@teardown/errors").ErrorResponse | {
|
|
57
79
|
message: string;
|
|
58
80
|
version: string;
|
|
59
81
|
};
|
|
82
|
+
422: {
|
|
83
|
+
type: "validation";
|
|
84
|
+
on: string;
|
|
85
|
+
summary?: string;
|
|
86
|
+
message?: string;
|
|
87
|
+
found?: unknown;
|
|
88
|
+
property?: string;
|
|
89
|
+
expected?: string;
|
|
90
|
+
};
|
|
60
91
|
};
|
|
61
92
|
};
|
|
62
93
|
} & {
|
|
@@ -65,7 +96,9 @@ export declare const baseApp: Elysia<"", {
|
|
|
65
96
|
body: unknown;
|
|
66
97
|
params: {};
|
|
67
98
|
query: unknown;
|
|
68
|
-
headers:
|
|
99
|
+
headers: {
|
|
100
|
+
"td-api-version"?: string | undefined;
|
|
101
|
+
};
|
|
69
102
|
response: {
|
|
70
103
|
200: import("@teardown/errors").ErrorResponse | {
|
|
71
104
|
status: string;
|
|
@@ -73,6 +106,15 @@ export declare const baseApp: Elysia<"", {
|
|
|
73
106
|
build_id: string;
|
|
74
107
|
service_id: string | undefined;
|
|
75
108
|
};
|
|
109
|
+
422: {
|
|
110
|
+
type: "validation";
|
|
111
|
+
on: string;
|
|
112
|
+
summary?: string;
|
|
113
|
+
message?: string;
|
|
114
|
+
found?: unknown;
|
|
115
|
+
property?: string;
|
|
116
|
+
expected?: string;
|
|
117
|
+
};
|
|
76
118
|
};
|
|
77
119
|
};
|
|
78
120
|
};
|
|
@@ -85,8 +127,9 @@ export declare const baseApp: Elysia<"", {
|
|
|
85
127
|
body: {
|
|
86
128
|
user?: {
|
|
87
129
|
name?: string | undefined;
|
|
88
|
-
|
|
130
|
+
persona_id?: string | undefined;
|
|
89
131
|
user_id?: string | undefined;
|
|
132
|
+
email?: string | undefined;
|
|
90
133
|
} | undefined;
|
|
91
134
|
device: {
|
|
92
135
|
timestamp?: Date | undefined;
|
|
@@ -96,19 +139,17 @@ export declare const baseApp: Elysia<"", {
|
|
|
96
139
|
platform: import("@teardown/types").DevicePlatformEnum;
|
|
97
140
|
};
|
|
98
141
|
application: {
|
|
99
|
-
build_number: number;
|
|
100
142
|
version: string;
|
|
143
|
+
build_number: number;
|
|
101
144
|
};
|
|
102
145
|
hardware: {
|
|
103
|
-
device_brand: string;
|
|
104
146
|
device_name: string;
|
|
105
147
|
device_type: string;
|
|
148
|
+
device_brand: string;
|
|
106
149
|
};
|
|
107
150
|
update: {
|
|
108
|
-
created_at: string;
|
|
109
|
-
is_embedded_launch: boolean;
|
|
110
|
-
update_id: string;
|
|
111
151
|
is_enabled: boolean;
|
|
152
|
+
update_id: string;
|
|
112
153
|
update_channel: string;
|
|
113
154
|
runtime_version: string;
|
|
114
155
|
emergency_launch: {
|
|
@@ -118,6 +159,8 @@ export declare const baseApp: Elysia<"", {
|
|
|
118
159
|
reason?: undefined;
|
|
119
160
|
is_emergency_launch: false;
|
|
120
161
|
};
|
|
162
|
+
is_embedded_launch: boolean;
|
|
163
|
+
created_at: string;
|
|
121
164
|
} | null;
|
|
122
165
|
};
|
|
123
166
|
};
|
|
@@ -135,9 +178,9 @@ export declare const baseApp: Elysia<"", {
|
|
|
135
178
|
200: {
|
|
136
179
|
success: true;
|
|
137
180
|
data: {
|
|
138
|
-
device_id: string;
|
|
139
181
|
user_id: string;
|
|
140
182
|
session_id: string;
|
|
183
|
+
device_id: string;
|
|
141
184
|
token: string;
|
|
142
185
|
version_info: {
|
|
143
186
|
status: import("@teardown/schemas").IdentifyVersionStatusEnum;
|
|
@@ -162,32 +205,32 @@ export declare const baseApp: Elysia<"", {
|
|
|
162
205
|
};
|
|
163
206
|
};
|
|
164
207
|
400: {
|
|
165
|
-
success: false;
|
|
166
208
|
error: {
|
|
167
|
-
message: string;
|
|
168
209
|
code: "MISSING_ORG_ID";
|
|
169
|
-
} | {
|
|
170
210
|
message: string;
|
|
171
|
-
code: "MISSING_PROJECT_ID";
|
|
172
211
|
} | {
|
|
212
|
+
code: "MISSING_PROJECT_ID";
|
|
173
213
|
message: string;
|
|
174
|
-
code: "MISSING_ENVIRONMENT_SLUG";
|
|
175
214
|
} | {
|
|
215
|
+
code: "MISSING_ENVIRONMENT_SLUG";
|
|
176
216
|
message: string;
|
|
177
|
-
code: "MISSING_DEVICE_ID";
|
|
178
217
|
} | {
|
|
218
|
+
code: "MISSING_DEVICE_ID";
|
|
179
219
|
message: string;
|
|
180
|
-
code: "IDENTIFY_FAILED";
|
|
181
220
|
} | {
|
|
221
|
+
code: "IDENTIFY_FAILED";
|
|
182
222
|
message: string;
|
|
183
|
-
code: "NO_SESSION_ID_GENERATED";
|
|
184
223
|
} | {
|
|
224
|
+
code: "NO_SESSION_ID_GENERATED";
|
|
185
225
|
message: string;
|
|
186
|
-
code: "NO_DEVICE_ID_GENERATED";
|
|
187
226
|
} | {
|
|
227
|
+
code: "NO_DEVICE_ID_GENERATED";
|
|
188
228
|
message: string;
|
|
229
|
+
} | {
|
|
189
230
|
code: "NO_USER_ID_GENERATED";
|
|
231
|
+
message: string;
|
|
190
232
|
};
|
|
233
|
+
success: false;
|
|
191
234
|
};
|
|
192
235
|
422: {
|
|
193
236
|
type: "validation";
|
|
@@ -209,13 +252,13 @@ export declare const baseApp: Elysia<"", {
|
|
|
209
252
|
events: {
|
|
210
253
|
post: {
|
|
211
254
|
body: {
|
|
212
|
-
device_id?: string | undefined;
|
|
213
255
|
session_id?: string | undefined;
|
|
256
|
+
device_id?: string | undefined;
|
|
214
257
|
events: {
|
|
215
258
|
properties?: {} | undefined;
|
|
216
|
-
device_id?: string | undefined;
|
|
217
|
-
session_id?: string | undefined;
|
|
218
259
|
timestamp?: string | undefined;
|
|
260
|
+
session_id?: string | undefined;
|
|
261
|
+
device_id?: string | undefined;
|
|
219
262
|
event_name: string;
|
|
220
263
|
event_type: "action" | "screen_view" | "custom";
|
|
221
264
|
}[];
|
|
@@ -240,35 +283,35 @@ export declare const baseApp: Elysia<"", {
|
|
|
240
283
|
};
|
|
241
284
|
};
|
|
242
285
|
400: {
|
|
243
|
-
success: false;
|
|
244
286
|
error: {
|
|
245
|
-
message: string;
|
|
246
287
|
code: "MISSING_ORG_ID";
|
|
247
|
-
} | {
|
|
248
288
|
message: string;
|
|
249
|
-
code: "MISSING_PROJECT_ID";
|
|
250
289
|
} | {
|
|
290
|
+
code: "MISSING_PROJECT_ID";
|
|
251
291
|
message: string;
|
|
252
|
-
code: "MISSING_ENVIRONMENT_SLUG";
|
|
253
292
|
} | {
|
|
293
|
+
code: "MISSING_ENVIRONMENT_SLUG";
|
|
254
294
|
message: string;
|
|
255
|
-
code: "MISSING_DEVICE_ID";
|
|
256
295
|
} | {
|
|
296
|
+
code: "MISSING_DEVICE_ID";
|
|
257
297
|
message: string;
|
|
258
|
-
code: "EVENTS_PROCESSING_FAILED";
|
|
259
298
|
} | {
|
|
299
|
+
code: "EVENTS_PROCESSING_FAILED";
|
|
260
300
|
message: string;
|
|
261
|
-
code: "INVALID_SESSION";
|
|
262
301
|
} | {
|
|
302
|
+
code: "INVALID_SESSION";
|
|
263
303
|
message: string;
|
|
264
|
-
code: "INVALID_DEVICE";
|
|
265
304
|
} | {
|
|
305
|
+
code: "INVALID_DEVICE";
|
|
266
306
|
message: string;
|
|
267
|
-
code: "BATCH_SIZE_EXCEEDED";
|
|
268
307
|
} | {
|
|
308
|
+
code: "BATCH_SIZE_EXCEEDED";
|
|
269
309
|
message: string;
|
|
310
|
+
} | {
|
|
270
311
|
code: "VALIDATION_ERROR";
|
|
312
|
+
message: string;
|
|
271
313
|
};
|
|
314
|
+
success: false;
|
|
272
315
|
};
|
|
273
316
|
422: {
|
|
274
317
|
type: "validation";
|
|
@@ -291,7 +334,10 @@ export declare const baseApp: Elysia<"", {
|
|
|
291
334
|
response: {};
|
|
292
335
|
}, {
|
|
293
336
|
derive: {};
|
|
294
|
-
resolve: {
|
|
337
|
+
resolve: {
|
|
338
|
+
readonly apiVersion: "2024-12-12";
|
|
339
|
+
readonly requestedVersion: string | null;
|
|
340
|
+
};
|
|
295
341
|
schema: import("elysia").UnwrapRoute<{
|
|
296
342
|
headers: z.ZodObject<{
|
|
297
343
|
authorization: z.ZodOptional<z.ZodString>;
|
|
@@ -304,7 +350,10 @@ export declare const baseApp: Elysia<"", {
|
|
|
304
350
|
}, z.core.$strip>;
|
|
305
351
|
}, {}, "">;
|
|
306
352
|
standaloneSchema: {};
|
|
307
|
-
response: {
|
|
353
|
+
response: import("elysia").ExtractErrorFromHandle<{
|
|
354
|
+
readonly apiVersion: "2024-12-12";
|
|
355
|
+
readonly requestedVersion: string | null;
|
|
356
|
+
}>;
|
|
308
357
|
} & {
|
|
309
358
|
derive: {};
|
|
310
359
|
resolve: {};
|
package/package.json
CHANGED
package/src/client/index.ts
CHANGED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { edenFetch } from "@elysiajs/eden";
|
|
2
|
+
import { API_VERSION_HEADER } from "@teardown/schemas/contracts";
|
|
3
|
+
import type { IdentifyRequest, IdentifyResponse } from "@teardown/schemas/identify";
|
|
4
|
+
import type { IngestApp } from "../../generated/app";
|
|
5
|
+
import type { ClientConfig, RequestOptions } from "./client";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Ingest API Target Version
|
|
9
|
+
*
|
|
10
|
+
* This is the API contract version this client is built for.
|
|
11
|
+
* The client will send this version in the td-api-version header.
|
|
12
|
+
* Ingest API will validate and respond with the version used.
|
|
13
|
+
*/
|
|
14
|
+
export const INGEST_TARGET_API_VERSION = "2024-12-12";
|
|
15
|
+
|
|
16
|
+
export type IngestApiClientOptions = {
|
|
17
|
+
/**
|
|
18
|
+
* Base URL for the Ingest API
|
|
19
|
+
*/
|
|
20
|
+
url: string;
|
|
21
|
+
/**
|
|
22
|
+
* API key for authentication
|
|
23
|
+
*/
|
|
24
|
+
apiKey: string;
|
|
25
|
+
/**
|
|
26
|
+
* Organization ID
|
|
27
|
+
*/
|
|
28
|
+
orgId: string;
|
|
29
|
+
/**
|
|
30
|
+
* Project ID
|
|
31
|
+
*/
|
|
32
|
+
projectId: string;
|
|
33
|
+
/**
|
|
34
|
+
* Environment slug (e.g., "production", "staging")
|
|
35
|
+
*/
|
|
36
|
+
environmentSlug: string;
|
|
37
|
+
/**
|
|
38
|
+
* Device ID (unique identifier for this device)
|
|
39
|
+
*/
|
|
40
|
+
deviceId: string;
|
|
41
|
+
/**
|
|
42
|
+
* Session ID (optional, set after identify)
|
|
43
|
+
*/
|
|
44
|
+
sessionId?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Override the API version to use.
|
|
47
|
+
* Defaults to INGEST_TARGET_API_VERSION.
|
|
48
|
+
*/
|
|
49
|
+
apiVersion?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Optional Eden fetch config
|
|
52
|
+
*/
|
|
53
|
+
config?: ClientConfig;
|
|
54
|
+
/**
|
|
55
|
+
* Hook to modify request options before each request
|
|
56
|
+
*/
|
|
57
|
+
onRequest?: (endpoint: string, options: RequestOptions) => Promise<RequestOptions>;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
type IngestClient = ReturnType<typeof edenFetch<typeof IngestApp>>;
|
|
61
|
+
|
|
62
|
+
export class IngestApiClient {
|
|
63
|
+
private readonly client: IngestClient;
|
|
64
|
+
private readonly apiVersion: string;
|
|
65
|
+
private sessionId: string | undefined;
|
|
66
|
+
|
|
67
|
+
constructor(private readonly options: IngestApiClientOptions) {
|
|
68
|
+
this.client = edenFetch<typeof IngestApp>(this.options.url, this.options.config);
|
|
69
|
+
this.apiVersion = options.apiVersion ?? INGEST_TARGET_API_VERSION;
|
|
70
|
+
this.sessionId = options.sessionId;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get the API version this client is using
|
|
75
|
+
*/
|
|
76
|
+
getApiVersion(): string {
|
|
77
|
+
return this.apiVersion;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get the current session ID (if set)
|
|
82
|
+
*/
|
|
83
|
+
getSessionId(): string | undefined {
|
|
84
|
+
return this.sessionId;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Set the session ID (typically after identify)
|
|
89
|
+
*/
|
|
90
|
+
setSessionId(sessionId: string): void {
|
|
91
|
+
this.sessionId = sessionId;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Generate base headers for all requests
|
|
96
|
+
*/
|
|
97
|
+
generateBaseHeaders(): Record<string, string> {
|
|
98
|
+
const headers: Record<string, string> = {
|
|
99
|
+
// Always send API version header
|
|
100
|
+
[API_VERSION_HEADER]: this.apiVersion,
|
|
101
|
+
"td-api-key": this.options.apiKey,
|
|
102
|
+
"td-org-id": this.options.orgId,
|
|
103
|
+
"td-project-id": this.options.projectId,
|
|
104
|
+
"td-environment-slug": this.options.environmentSlug,
|
|
105
|
+
"td-device-id": this.options.deviceId,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
if (this.sessionId) {
|
|
109
|
+
headers["td-session-id"] = this.sessionId;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return headers;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Make a fetch request to the Ingest API
|
|
117
|
+
* @internal Use typed convenience methods like identify() instead
|
|
118
|
+
*/
|
|
119
|
+
// biome-ignore lint/suspicious/noExplicitAny: Eden types are complex, using any for flexibility
|
|
120
|
+
async fetch(endpoint: string, options?: Record<string, any>): Promise<any> {
|
|
121
|
+
const baseHeaders = this.generateBaseHeaders();
|
|
122
|
+
const baseOptions = {
|
|
123
|
+
...options,
|
|
124
|
+
headers: {
|
|
125
|
+
...baseHeaders,
|
|
126
|
+
...options?.headers,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const requestOptions = this.options.onRequest
|
|
131
|
+
? await this.options.onRequest(endpoint, baseOptions as RequestOptions)
|
|
132
|
+
: baseOptions;
|
|
133
|
+
|
|
134
|
+
// biome-ignore lint/suspicious/noExplicitAny: Eden types require any cast
|
|
135
|
+
const result = await this.client(endpoint as any, requestOptions as any);
|
|
136
|
+
|
|
137
|
+
if (result.error) {
|
|
138
|
+
throw result.error;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Identify the current device/user
|
|
146
|
+
* This should be called at app startup to establish a session
|
|
147
|
+
*/
|
|
148
|
+
async identify(request: IdentifyRequest): Promise<IdentifyResponse> {
|
|
149
|
+
const baseHeaders = this.generateBaseHeaders();
|
|
150
|
+
|
|
151
|
+
// biome-ignore lint/suspicious/noExplicitAny: Eden types are complex
|
|
152
|
+
const result = await this.client("/v1/identify" as any, {
|
|
153
|
+
method: "POST",
|
|
154
|
+
body: request,
|
|
155
|
+
headers: baseHeaders,
|
|
156
|
+
} as any);
|
|
157
|
+
|
|
158
|
+
if (result.error) {
|
|
159
|
+
throw result.error;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const data = result.data as IdentifyResponse;
|
|
163
|
+
|
|
164
|
+
// Automatically set session ID from response
|
|
165
|
+
if (data.success && data.data.session_id) {
|
|
166
|
+
this.setSessionId(data.data.session_id);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return data;
|
|
170
|
+
}
|
|
171
|
+
}
|