@teardown/schemas 0.1.21 → 0.1.23

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 (76) hide show
  1. package/package.json +49 -52
  2. package/src/common/primitives.ts +21 -0
  3. package/src/common/responses.ts +25 -0
  4. package/{dist/common/type-checks.d.ts → src/common/type-checks.ts} +23 -4
  5. package/{dist/index.js → src/index.ts} +1 -0
  6. package/src/modules/analytics/schemas.ts +178 -0
  7. package/src/modules/builds/schemas.ts +171 -0
  8. package/src/modules/devices/schemas.ts +196 -0
  9. package/src/modules/environment/schemas.ts +81 -0
  10. package/src/modules/events/index.ts +2 -0
  11. package/src/modules/events/schemas.ts +129 -0
  12. package/src/modules/identify/schemas.ts +257 -0
  13. package/src/modules/me/schemas.ts +87 -0
  14. package/src/modules/orgs/schemas.ts +260 -0
  15. package/src/modules/personas/schemas.ts +123 -0
  16. package/src/modules/projects/schemas.ts +179 -0
  17. package/src/modules/sessions/schemas.ts +158 -0
  18. package/src/modules/versions/schemas.ts +192 -0
  19. package/dist/common/index.js +0 -3
  20. package/dist/common/primitives.d.ts +0 -11
  21. package/dist/common/primitives.js +0 -8
  22. package/dist/common/responses.d.ts +0 -27
  23. package/dist/common/responses.js +0 -13
  24. package/dist/common/type-checks.js +0 -1
  25. package/dist/index.d.ts +0 -13
  26. package/dist/modules/analytics/schemas.d.ts +0 -239
  27. package/dist/modules/analytics/schemas.js +0 -136
  28. package/dist/modules/builds/schemas.d.ts +0 -248
  29. package/dist/modules/builds/schemas.js +0 -137
  30. package/dist/modules/devices/schemas.d.ts +0 -207
  31. package/dist/modules/devices/schemas.js +0 -165
  32. package/dist/modules/environment/schemas.d.ts +0 -56
  33. package/dist/modules/environment/schemas.js +0 -57
  34. package/dist/modules/events/schemas.d.ts +0 -138
  35. package/dist/modules/events/schemas.js +0 -116
  36. package/dist/modules/identify/index.js +0 -1
  37. package/dist/modules/identify/schemas.d.ts +0 -377
  38. package/dist/modules/identify/schemas.js +0 -221
  39. package/dist/modules/index.js +0 -12
  40. package/dist/modules/me/index.d.ts +0 -1
  41. package/dist/modules/me/index.js +0 -1
  42. package/dist/modules/me/schemas.d.ts +0 -75
  43. package/dist/modules/me/schemas.js +0 -76
  44. package/dist/modules/orgs/index.d.ts +0 -1
  45. package/dist/modules/orgs/index.js +0 -1
  46. package/dist/modules/orgs/schemas.d.ts +0 -308
  47. package/dist/modules/orgs/schemas.js +0 -214
  48. package/dist/modules/personas/index.d.ts +0 -1
  49. package/dist/modules/personas/index.js +0 -1
  50. package/dist/modules/personas/schemas.d.ts +0 -170
  51. package/dist/modules/personas/schemas.js +0 -100
  52. package/dist/modules/projects/index.d.ts +0 -1
  53. package/dist/modules/projects/index.js +0 -1
  54. package/dist/modules/projects/schemas.d.ts +0 -222
  55. package/dist/modules/projects/schemas.js +0 -145
  56. package/dist/modules/sessions/index.d.ts +0 -1
  57. package/dist/modules/sessions/index.js +0 -1
  58. package/dist/modules/sessions/schemas.d.ts +0 -258
  59. package/dist/modules/sessions/schemas.js +0 -128
  60. package/dist/modules/versions/index.d.ts +0 -1
  61. package/dist/modules/versions/index.js +0 -1
  62. package/dist/modules/versions/schemas.d.ts +0 -248
  63. package/dist/modules/versions/schemas.js +0 -155
  64. /package/{dist/common/index.d.ts → src/common/index.ts} +0 -0
  65. /package/{dist/modules/analytics/index.d.ts → src/modules/analytics/index.ts} +0 -0
  66. /package/{dist/modules/analytics/index.js → src/modules/builds/index.ts} +0 -0
  67. /package/{dist/modules/builds/index.d.ts → src/modules/devices/index.ts} +0 -0
  68. /package/{dist/modules/builds/index.js → src/modules/environment/index.ts} +0 -0
  69. /package/{dist/modules/devices/index.d.ts → src/modules/identify/index.ts} +0 -0
  70. /package/{dist/modules/index.d.ts → src/modules/index.ts} +0 -0
  71. /package/{dist/modules/devices/index.js → src/modules/me/index.ts} +0 -0
  72. /package/{dist/modules/environment/index.d.ts → src/modules/orgs/index.ts} +0 -0
  73. /package/{dist/modules/environment/index.js → src/modules/personas/index.ts} +0 -0
  74. /package/{dist/modules/events/index.d.ts → src/modules/projects/index.ts} +0 -0
  75. /package/{dist/modules/events/index.js → src/modules/sessions/index.ts} +0 -0
  76. /package/{dist/modules/identify/index.d.ts → src/modules/versions/index.ts} +0 -0
@@ -0,0 +1,196 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+ import { DevicePlatformEnum } from "@teardown/types";
3
+ import type { AssertSchemaCompatibleWithRow, AssertTrue } from "../../common";
4
+
5
+ /**
6
+ * Device platform enum matching database
7
+ */
8
+
9
+ /**
10
+ * Device platform
11
+ */
12
+ export const DevicePlatformSchema = Type.Enum(DevicePlatformEnum, { error: "platform is required" });
13
+ export type DevicePlatform = Static<typeof DevicePlatformSchema>;
14
+
15
+ /**
16
+ * Parse and validate a DevicePlatformEnum value
17
+ * Uses a switch statement to ensure type safety and runtime validation
18
+ * @param value - The value to parse
19
+ * @returns The validated DevicePlatformEnum value or null
20
+ * @throws Error if the value is not a valid DevicePlatformEnum and not null
21
+ */
22
+ export function parseDevicePlatformEnum(value: unknown): DevicePlatformEnum | null {
23
+ if (value === null || value === undefined) {
24
+ return null;
25
+ }
26
+ switch (value) {
27
+ case DevicePlatformEnum.IOS:
28
+ return DevicePlatformEnum.IOS;
29
+ case DevicePlatformEnum.ANDROID:
30
+ return DevicePlatformEnum.ANDROID;
31
+ case DevicePlatformEnum.WEB:
32
+ return DevicePlatformEnum.WEB;
33
+ case DevicePlatformEnum.WINDOWS:
34
+ return DevicePlatformEnum.WINDOWS;
35
+ case DevicePlatformEnum.MACOS:
36
+ return DevicePlatformEnum.MACOS;
37
+ case DevicePlatformEnum.LINUX:
38
+ return DevicePlatformEnum.LINUX;
39
+ case DevicePlatformEnum.PHONE:
40
+ return DevicePlatformEnum.PHONE;
41
+ case DevicePlatformEnum.TABLET:
42
+ return DevicePlatformEnum.TABLET;
43
+ case DevicePlatformEnum.DESKTOP:
44
+ return DevicePlatformEnum.DESKTOP;
45
+ case DevicePlatformEnum.CONSOLE:
46
+ return DevicePlatformEnum.CONSOLE;
47
+ case DevicePlatformEnum.TV:
48
+ return DevicePlatformEnum.TV;
49
+ case DevicePlatformEnum.WEARABLE:
50
+ return DevicePlatformEnum.WEARABLE;
51
+ case DevicePlatformEnum.GAME_CONSOLE:
52
+ return DevicePlatformEnum.GAME_CONSOLE;
53
+ case DevicePlatformEnum.VR:
54
+ return DevicePlatformEnum.VR;
55
+ case DevicePlatformEnum.UNKNOWN:
56
+ return DevicePlatformEnum.UNKNOWN;
57
+ case DevicePlatformEnum.OTHER:
58
+ return DevicePlatformEnum.OTHER;
59
+ default:
60
+ throw new Error(
61
+ `Invalid DevicePlatformEnum value: ${value}. Expected one of: ${Object.values(DevicePlatformEnum).join(", ")}`
62
+ );
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Base device schema
68
+ * Represents devices table structure
69
+ */
70
+ export const DeviceSchema = Type.Object({
71
+ id: Type.String({ format: "uuid" }),
72
+ persona_id: Type.String({ format: "uuid" }),
73
+ environment_id: Type.Union([Type.String({ format: "uuid" }), Type.Null()]),
74
+ device_id: Type.String(),
75
+ platform: Type.Union([DevicePlatformSchema, Type.Null()]),
76
+ os_type: Type.Union([Type.String(), Type.Null()]),
77
+ os_name: Type.Union([Type.String(), Type.Null()]),
78
+ device_name: Type.Union([Type.String(), Type.Null()]),
79
+ device_brand: Type.Union([Type.String(), Type.Null()]),
80
+ metadata: Type.Union([Type.Record(Type.String(), Type.Unknown()), Type.Null()]),
81
+ created_at: Type.String(),
82
+ updated_at: Type.String(),
83
+ });
84
+ export type Device = Static<typeof DeviceSchema>;
85
+
86
+ /**
87
+ * Device params schema
88
+ */
89
+ export const DeviceParamsSchema = Type.Object({
90
+ device_id: Type.String({ format: "uuid" }),
91
+ });
92
+ export type DeviceParams = Static<typeof DeviceParamsSchema>;
93
+
94
+ /**
95
+ * Search devices query schema
96
+ * Supports pagination, search, and sorting
97
+ */
98
+ export const SearchDevicesQuerySchema = Type.Object({
99
+ project_id: Type.String({ format: "uuid" }),
100
+ page: Type.Number({ minimum: 1, default: 1 }),
101
+ limit: Type.Number({ minimum: 1, maximum: 100, default: 20 }),
102
+ search: Type.Optional(Type.String()),
103
+ sort_by: Type.Union(
104
+ [
105
+ Type.Literal("created_at"),
106
+ Type.Literal("updated_at"),
107
+ Type.Literal("device_name"),
108
+ Type.Literal("platform"),
109
+ Type.Literal("os_name"),
110
+ ],
111
+ { default: "created_at" }
112
+ ),
113
+ sort_order: Type.Union([Type.Literal("asc"), Type.Literal("desc")], { default: "desc" }),
114
+ });
115
+ export type SearchDevicesQuery = Static<typeof SearchDevicesQuerySchema>;
116
+
117
+ /**
118
+ * Search devices query schema without project_id (injected from headers)
119
+ */
120
+ export const SearchDevicesQueryParamsSchema = Type.Omit(SearchDevicesQuerySchema, ["project_id"]);
121
+ export type SearchDevicesQueryParams = Static<typeof SearchDevicesQueryParamsSchema>;
122
+
123
+ /**
124
+ * Devices by IDs request schema
125
+ */
126
+ export const DevicesByIdsSchema = Type.Object({
127
+ device_ids: Type.Array(Type.String({ format: "uuid" }), { minItems: 1, maxItems: 100 }),
128
+ });
129
+ export type DevicesByIds = Static<typeof DevicesByIdsSchema>;
130
+
131
+ /**
132
+ * Paginated devices response schema
133
+ */
134
+ export const DevicesResponseSchema = Type.Object({
135
+ devices: Type.Array(DeviceSchema),
136
+ pagination: Type.Object({
137
+ page: Type.Integer({ minimum: 1 }),
138
+ limit: Type.Integer({ minimum: 1 }),
139
+ total: Type.Integer({ minimum: 0 }),
140
+ total_pages: Type.Integer({ minimum: 0 }),
141
+ }),
142
+ });
143
+ export type DevicesResponse = Static<typeof DevicesResponseSchema>;
144
+
145
+ /**
146
+ * Single device response schema
147
+ */
148
+ export const DeviceResponseSchema = Type.Object({
149
+ success: Type.Literal(true),
150
+ data: DeviceSchema,
151
+ });
152
+ export type DeviceResponse = Static<typeof DeviceResponseSchema>;
153
+
154
+ /**
155
+ * Device error response schema
156
+ * Discriminated union by error code
157
+ */
158
+ export const DeviceErrorSchema = Type.Union([
159
+ Type.Object({
160
+ code: Type.Literal("DEVICE_NOT_FOUND"),
161
+ message: Type.String(),
162
+ }),
163
+ Type.Object({
164
+ code: Type.Literal("PROJECT_NOT_FOUND"),
165
+ message: Type.String(),
166
+ }),
167
+ Type.Object({
168
+ code: Type.Literal("FORBIDDEN"),
169
+ message: Type.String(),
170
+ }),
171
+ Type.Object({
172
+ code: Type.Literal("FETCH_FAILED"),
173
+ message: Type.String(),
174
+ }),
175
+ Type.Object({
176
+ code: Type.Literal("INVALID_PARAMS"),
177
+ message: Type.String(),
178
+ }),
179
+ ]);
180
+ export type DeviceError = Static<typeof DeviceErrorSchema>;
181
+
182
+ /**
183
+ * Device error response wrapper
184
+ */
185
+ export const DeviceErrorResponseSchema = Type.Object({
186
+ success: Type.Literal(false),
187
+ error: DeviceErrorSchema,
188
+ });
189
+ export type DeviceErrorResponse = Static<typeof DeviceErrorResponseSchema>;
190
+
191
+ /**
192
+ * Device request response schema
193
+ */
194
+ export const DeviceRequestResponseSchema = Type.Union([DeviceResponseSchema, DeviceErrorResponseSchema]);
195
+ export type DeviceRequestResponse = Static<typeof DeviceRequestResponseSchema>;
196
+ export type _CheckDeviceRow = AssertTrue<AssertSchemaCompatibleWithRow<Device, "devices">>;
@@ -0,0 +1,81 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+ import { EnvironmentTypeEnum } from "@teardown/types";
3
+ import type {
4
+ AssertSchemaCompatibleWithInsert,
5
+ AssertSchemaCompatibleWithRow,
6
+ AssertSchemaCompatibleWithUpdate,
7
+ AssertTrue,
8
+ } from "../../common";
9
+
10
+ /**
11
+ * Environment type enum (re-exported for backward compatibility)
12
+ * @deprecated Use EnvironmentTypeEnum from @teardown/types instead
13
+ */
14
+ export { EnvironmentTypeEnum as EnvironmentType };
15
+
16
+ /**
17
+ * Environment schema
18
+ * Represents an environment within a project
19
+ */
20
+ export const EnvironmentSchema = Type.Object({
21
+ id: Type.String({ format: "uuid" }),
22
+ project_id: Type.String({ format: "uuid" }),
23
+ name: Type.String({ minLength: 1 }),
24
+ slug: Type.String({ minLength: 1 }),
25
+ type: Type.Enum(EnvironmentTypeEnum),
26
+ created_at: Type.String(),
27
+ updated_at: Type.String(),
28
+ });
29
+
30
+ /**
31
+ * Parse and validate an EnvironmentTypeEnum value
32
+ * Uses a switch statement to ensure type safety and runtime validation
33
+ * @param value - The value to parse
34
+ * @returns The validated EnvironmentTypeEnum value
35
+ * @throws Error if the value is not a valid EnvironmentTypeEnum
36
+ */
37
+ export function parseEnvironmentTypeEnum(value: unknown): EnvironmentTypeEnum {
38
+ switch (value) {
39
+ case EnvironmentTypeEnum.DEVELOPMENT:
40
+ return EnvironmentTypeEnum.DEVELOPMENT;
41
+ case EnvironmentTypeEnum.STAGING:
42
+ return EnvironmentTypeEnum.STAGING;
43
+ case EnvironmentTypeEnum.PRODUCTION:
44
+ return EnvironmentTypeEnum.PRODUCTION;
45
+ default:
46
+ throw new Error(
47
+ `Invalid EnvironmentTypeEnum value: ${value}. Expected one of: ${Object.values(EnvironmentTypeEnum).join(", ")}`
48
+ );
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Create environment schema
54
+ * Used for creating new environments
55
+ */
56
+ export const CreateEnvironmentSchema = Type.Object({
57
+ project_id: Type.String({ format: "uuid" }),
58
+ name: Type.String({ minLength: 1 }),
59
+ slug: Type.String({ minLength: 1 }),
60
+ type: Type.Enum(EnvironmentTypeEnum),
61
+ });
62
+
63
+ /**
64
+ * Update environment schema
65
+ * Used for updating existing environments
66
+ */
67
+ export const UpdateEnvironmentSchema = Type.Object({
68
+ name: Type.String({ minLength: 1 }),
69
+ type: Type.Enum(EnvironmentTypeEnum),
70
+ });
71
+
72
+ /**
73
+ * TypeScript types inferred from schemas
74
+ */
75
+ export type Environment = Static<typeof EnvironmentSchema>;
76
+ export type CreateEnvironment = Static<typeof CreateEnvironmentSchema>;
77
+ export type UpdateEnvironment = Static<typeof UpdateEnvironmentSchema>;
78
+
79
+ export type _CheckEnvironmentRow = AssertTrue<AssertSchemaCompatibleWithRow<Environment, "environments">>;
80
+ export type _CheckCreateEnvironment = AssertTrue<AssertSchemaCompatibleWithInsert<CreateEnvironment, "environments">>;
81
+ export type _CheckUpdateEnvironment = AssertTrue<AssertSchemaCompatibleWithUpdate<UpdateEnvironment, "environments">>;
@@ -0,0 +1,2 @@
1
+ export * from "./schemas";
2
+
@@ -0,0 +1,129 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+ import type { AssertSchemaCompatibleWithRow, AssertTrue } from "../../common";
3
+
4
+ /**
5
+ * Event type enum
6
+ */
7
+ export const EventTypeEnum = ["action", "screen_view", "custom"] as const;
8
+ export type EventType = (typeof EventTypeEnum)[number];
9
+
10
+ /**
11
+ * Single event schema
12
+ */
13
+ export const EventSchema = Type.Object({
14
+ /**
15
+ * Name of the event (required)
16
+ */
17
+ event_name: Type.String({ minLength: 1, error: "event_name is required" }),
18
+ /**
19
+ * Type of event
20
+ */
21
+ event_type: Type.Union([Type.Literal("action"), Type.Literal("screen_view"), Type.Literal("custom")], { default: "custom" }),
22
+ /**
23
+ * Custom properties for the event (optional)
24
+ */
25
+ properties: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
26
+ /**
27
+ * Client-side timestamp (optional, defaults to server time)
28
+ */
29
+ timestamp: Type.Optional(Type.String()),
30
+ /**
31
+ * Session ID (optional, can come from header)
32
+ */
33
+ session_id: Type.Optional(Type.String({ format: "uuid" })),
34
+ /**
35
+ * Device ID (optional, can come from header)
36
+ */
37
+ device_id: Type.Optional(Type.String()),
38
+ });
39
+ export type Event = Static<typeof EventSchema>;
40
+
41
+ /**
42
+ * Batch events request schema
43
+ * Accepts 1-100 events per request
44
+ */
45
+ export const EventsRequestSchema = Type.Object({
46
+ /**
47
+ * Array of events to ingest (1-100)
48
+ */
49
+ events: Type.Array(EventSchema, { minItems: 1, maxItems: 100, error: "At least one event is required, maximum 100" }),
50
+ /**
51
+ * Session ID (optional, applies to all events if not specified per-event)
52
+ */
53
+ session_id: Type.Optional(Type.String({ format: "uuid" })),
54
+ /**
55
+ * Device ID (optional, applies to all events if not specified per-event)
56
+ */
57
+ device_id: Type.Optional(Type.String()),
58
+ });
59
+ export type EventsRequest = Static<typeof EventsRequestSchema>;
60
+
61
+ /**
62
+ * Events response schema
63
+ */
64
+ export const EventsResponseSchema = Type.Object({
65
+ success: Type.Literal(true),
66
+ data: Type.Object({
67
+ /**
68
+ * IDs of created events
69
+ */
70
+ event_ids: Type.Array(Type.String()),
71
+ /**
72
+ * Number of successfully processed events
73
+ */
74
+ processed_count: Type.Number(),
75
+ /**
76
+ * Number of failed events
77
+ */
78
+ failed_count: Type.Number(),
79
+ }),
80
+ });
81
+ export type EventsResponse = Static<typeof EventsResponseSchema>;
82
+
83
+ /**
84
+ * Events error response schema
85
+ */
86
+ export const EventsErrorResponseSchema = Type.Object({
87
+ success: Type.Literal(false),
88
+ error: Type.Union([
89
+ Type.Object({
90
+ code: Type.Literal("MISSING_ORG_ID"),
91
+ message: Type.String(),
92
+ }),
93
+ Type.Object({
94
+ code: Type.Literal("MISSING_PROJECT_ID"),
95
+ message: Type.String(),
96
+ }),
97
+ Type.Object({
98
+ code: Type.Literal("MISSING_ENVIRONMENT_SLUG"),
99
+ message: Type.String(),
100
+ }),
101
+ Type.Object({
102
+ code: Type.Literal("MISSING_DEVICE_ID"),
103
+ message: Type.String(),
104
+ }),
105
+ Type.Object({
106
+ code: Type.Literal("EVENTS_PROCESSING_FAILED"),
107
+ message: Type.String(),
108
+ }),
109
+ Type.Object({
110
+ code: Type.Literal("INVALID_SESSION"),
111
+ message: Type.String(),
112
+ }),
113
+ Type.Object({
114
+ code: Type.Literal("INVALID_DEVICE"),
115
+ message: Type.String(),
116
+ }),
117
+ Type.Object({
118
+ code: Type.Literal("BATCH_SIZE_EXCEEDED"),
119
+ message: Type.String(),
120
+ }),
121
+ Type.Object({
122
+ code: Type.Literal("VALIDATION_ERROR"),
123
+ message: Type.String(),
124
+ }),
125
+ ]),
126
+ });
127
+ export type EventsErrorResponse = Static<typeof EventsErrorResponseSchema>;
128
+
129
+ export type _CheckEventRow = AssertTrue<AssertSchemaCompatibleWithRow<Event, "events">>;
@@ -0,0 +1,257 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+ import { DevicePlatformEnum } from "@teardown/types";
3
+ import { EmailSchema } from "../../common";
4
+
5
+ export { DevicePlatformEnum };
6
+
7
+ /**
8
+ * Application info schema
9
+ */
10
+ export const ApplicationInfoSchema = Type.Object({
11
+ version: Type.String({ error: "version is required" }),
12
+ build_number: Type.String({ error: "build_number is required" }),
13
+ });
14
+ export type ApplicationInfo = Static<typeof ApplicationInfoSchema>;
15
+
16
+ /**
17
+ * OS info schema
18
+ */
19
+ export const OSInfoSchema = Type.Object({
20
+ /**
21
+ * Device platform
22
+ */
23
+ platform: Type.Enum(DevicePlatformEnum, { error: "platform is required" }),
24
+ /**
25
+ * OS name
26
+ */
27
+ name: Type.String({ error: "name is required" }),
28
+ /**
29
+ * OS version
30
+ */
31
+ version: Type.String({ error: "version is required" }),
32
+ });
33
+ export type OSInfo = Static<typeof OSInfoSchema>;
34
+
35
+ /**
36
+ * Hardware info schema
37
+ */
38
+ export const HardwareInfoSchema = Type.Object({
39
+ device_name: Type.String({ error: "device_name is required" }),
40
+ device_type: Type.String({ error: "device_type is required" }),
41
+ device_brand: Type.String({ error: "device_brand is required" }),
42
+ });
43
+ export type HardwareInfo = Static<typeof HardwareInfoSchema>;
44
+
45
+ export const EmergencyLaunchSchema = Type.Union([
46
+ Type.Object({
47
+ is_emergency_launch: Type.Literal(true),
48
+ reason: Type.String({ error: "reason is required when is_emergency_launch is true" }),
49
+ }),
50
+ Type.Object({
51
+ is_emergency_launch: Type.Literal(false),
52
+ reason: Type.Optional(Type.Never()),
53
+ }),
54
+ ]);
55
+ export type EmergencyLaunch = Static<typeof EmergencyLaunchSchema>;
56
+
57
+ /**
58
+ * Update info schema
59
+ */
60
+ export const DeviceUpdateInfoSchema = Type.Object({
61
+ is_enabled: Type.Boolean(),
62
+ update_id: Type.String({ error: "update_id is required" }),
63
+ update_channel: Type.String({ error: "update_channel is required" }),
64
+ runtime_version: Type.String({ error: "runtime_version is required" }),
65
+ emergency_launch: EmergencyLaunchSchema,
66
+ is_embedded_launch: Type.Boolean({ error: "is_embedded_launch is required" }),
67
+ created_at: Type.String(),
68
+ });
69
+ export type DeviceUpdateInfo = Static<typeof DeviceUpdateInfoSchema>;
70
+
71
+ export enum NotificationPlatformEnum {
72
+ APNS = "APNS", // Apple Push Notification Service
73
+ FCM = "FCM", // Firebase Cloud Messaging
74
+ EXPO = "EXPO", // Expo Push Notifications
75
+ }
76
+
77
+ /**
78
+ * Push notification info schema
79
+ */
80
+ export const PushNotificationInfoSchema = Type.Object({
81
+ enabled: Type.Boolean({ error: "enabled is required" }),
82
+ granted: Type.Boolean({ error: "granted is required" }),
83
+ token: Type.Union([Type.String({ error: "token is required" }), Type.Null()]),
84
+ platform: Type.Enum(NotificationPlatformEnum, { error: "platform is required" }),
85
+ });
86
+ export type PushNotificationInfo = Static<typeof PushNotificationInfoSchema>;
87
+
88
+ export const NotificationsInfoSchema = Type.Object({
89
+ push: PushNotificationInfoSchema,
90
+ });
91
+ export type NotificationsInfo = Static<typeof NotificationsInfoSchema>;
92
+
93
+ /**
94
+ * Device info schema
95
+ */
96
+ export const DeviceInfoSchema = Type.Object({
97
+ /**
98
+ * Timestamp of collection on device (optional, generated server-side if not provided)
99
+ */
100
+ timestamp: Type.Optional(Type.Date({ error: "timestamp is required" })),
101
+ /**
102
+ * Application info, required
103
+ */
104
+ application: ApplicationInfoSchema,
105
+ /**
106
+ * Update info (optional) - not all builds will have an update
107
+ */
108
+ update: Type.Union([DeviceUpdateInfoSchema, Type.Null()]),
109
+ /**
110
+ * Hardware info, required
111
+ */
112
+ hardware: HardwareInfoSchema,
113
+ /**
114
+ * OS info, required
115
+ */
116
+ os: OSInfoSchema,
117
+ /**
118
+ * Notifications info, required
119
+ */
120
+ notifications: NotificationsInfoSchema,
121
+ });
122
+ export type DeviceInfo = Static<typeof DeviceInfoSchema>;
123
+
124
+ /**
125
+ * Persona info schema (optional fields)
126
+ * Matches personas table structure
127
+ */
128
+ export const PersonaInfoSchema = Type.Object({
129
+ user_id: Type.Optional(Type.String({ error: "user_id is required" })),
130
+ email: Type.Optional(EmailSchema),
131
+ name: Type.Optional(Type.String({ error: "name is required" })),
132
+ });
133
+ export type PersonaInfo = Static<typeof PersonaInfoSchema>;
134
+
135
+ /**
136
+ * Identify request schema
137
+ * Ties a device to a persona with optional persona data
138
+ */
139
+ export const IdentifyRequestSchema = Type.Object({
140
+ device: DeviceInfoSchema,
141
+ persona: Type.Optional(PersonaInfoSchema),
142
+ });
143
+ export type IdentifyRequest = Static<typeof IdentifyRequestSchema>;
144
+
145
+ export enum IdentifyVersionStatusEnum {
146
+ /**
147
+ * A new version is available
148
+ */
149
+ UPDATE_AVAILABLE = "UPDATE_AVAILABLE",
150
+ /**
151
+ * An update is required
152
+ */
153
+ UPDATE_REQUIRED = "UPDATE_REQUIRED",
154
+ /**
155
+ * The current version is valid & up to date
156
+ */
157
+ UP_TO_DATE = "UP_TO_DATE",
158
+ /**
159
+ * The version or build has been disabled
160
+ */
161
+ DISABLED = "DISABLED",
162
+ }
163
+
164
+ export const UpdateInfoSchema = Type.Object({
165
+ version: Type.String({ error: "version is required" }),
166
+ build: Type.String({ error: "build is required" }),
167
+ update_id: Type.String({ error: "update_id is required" }),
168
+ effective_date: Type.Date({ error: "effective_date is required" }),
169
+ });
170
+ export type UpdateInfo = Static<typeof UpdateInfoSchema>;
171
+
172
+ export const UpToDateInfoSchema = Type.Object({
173
+ status: Type.Literal(IdentifyVersionStatusEnum.UP_TO_DATE),
174
+ update: Type.Null(),
175
+ });
176
+ export type UpToDateInfo = Static<typeof UpToDateInfoSchema>;
177
+
178
+ export const UpdateRequiredInfoSchema = Type.Object({
179
+ status: Type.Literal(IdentifyVersionStatusEnum.UPDATE_REQUIRED),
180
+ update: UpdateInfoSchema,
181
+ });
182
+ export type UpdateRequiredInfo = Static<typeof UpdateRequiredInfoSchema>;
183
+
184
+ export const UpdateAvailableInfoSchema = Type.Object({
185
+ status: Type.Literal(IdentifyVersionStatusEnum.UPDATE_AVAILABLE),
186
+ update: UpdateInfoSchema,
187
+ });
188
+ export type UpdateAvailableInfo = Static<typeof UpdateAvailableInfoSchema>;
189
+
190
+ export const VersionInfoSchema = Type.Object({
191
+ /**
192
+ * The status of the version
193
+ */
194
+ status: Type.Enum(IdentifyVersionStatusEnum, { error: "status is required" }),
195
+ update: Type.Optional(Type.Union([UpdateAvailableInfoSchema, Type.Null()])),
196
+ });
197
+ export type VersionInfo = Static<typeof VersionInfoSchema>;
198
+
199
+ /**
200
+ * Identify response schema
201
+ */
202
+ export const IdentifyResponseSchema = Type.Object({
203
+ success: Type.Literal(true),
204
+ data: Type.Object({
205
+ session_id: Type.String({ error: "session_id is required" }),
206
+ device_id: Type.String({ error: "device_id is required" }),
207
+ persona_id: Type.String({ error: "persona_id is required" }),
208
+ token: Type.String({ error: "token is required" }), // JWT token for session authentication
209
+ version_info: VersionInfoSchema,
210
+ }),
211
+ });
212
+ export type IdentifyResponse = Static<typeof IdentifyResponseSchema>;
213
+
214
+ export const IdentifyErrorResponseSchema = Type.Object({
215
+ success: Type.Literal(false),
216
+ error: Type.Union([
217
+ Type.Object({
218
+ code: Type.Literal("MISSING_ORG_ID"),
219
+ message: Type.String(),
220
+ }),
221
+ Type.Object({
222
+ code: Type.Literal("MISSING_PROJECT_ID"),
223
+ message: Type.String(),
224
+ }),
225
+ Type.Object({
226
+ code: Type.Literal("MISSING_ENVIRONMENT_SLUG"),
227
+ message: Type.String(),
228
+ }),
229
+ Type.Object({
230
+ code: Type.Literal("MISSING_DEVICE_ID"),
231
+ message: Type.String(),
232
+ }),
233
+ Type.Object({
234
+ code: Type.Literal("IDENTIFY_FAILED"),
235
+ message: Type.String(),
236
+ }),
237
+ Type.Object({
238
+ code: Type.Literal("NO_SESSION_ID_GENERATED"),
239
+ message: Type.String(),
240
+ }),
241
+ Type.Object({
242
+ code: Type.Literal("NO_DEVICE_ID_GENERATED"),
243
+ message: Type.String(),
244
+ }),
245
+ Type.Object({
246
+ code: Type.Literal("NO_PERSONA_ID_GENERATED"),
247
+ message: Type.String(),
248
+ }),
249
+ ]),
250
+ });
251
+ export type IdentifyErrorResponse = Static<typeof IdentifyErrorResponseSchema>;
252
+
253
+ export const ValidationErrorSchema = Type.Object({
254
+ success: Type.Literal(false),
255
+ error: Type.Literal("VALIDATION"),
256
+ message: Type.String(),
257
+ });