@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
package/package.json CHANGED
@@ -1,101 +1,98 @@
1
1
  {
2
2
  "name": "@teardown/schemas",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "type": "module",
9
9
  "files": [
10
- "dist/**/*"
10
+ "src/**/*"
11
11
  ],
12
- "main": "./dist/index.js",
13
- "module": "./dist/index.js",
14
- "types": "./dist/index.d.ts",
12
+ "main": "./src/index.ts",
13
+ "module": "./src/index.ts",
14
+ "types": "./src/index.ts",
15
15
  "exports": {
16
16
  ".": {
17
- "types": "./dist/index.d.ts",
18
- "import": "./dist/index.js",
19
- "default": "./dist/index.js"
17
+ "types": "./src/index.ts",
18
+ "import": "./src/index.ts",
19
+ "default": "./src/index.ts"
20
20
  },
21
21
  "./common": {
22
- "types": "./dist/common/index.d.ts",
23
- "import": "./dist/common/index.js",
24
- "default": "./dist/common/index.js"
22
+ "types": "./src/common/index.ts",
23
+ "import": "./src/common/index.ts",
24
+ "default": "./src/common/index.ts"
25
25
  },
26
26
  "./devices": {
27
- "types": "./dist/modules/devices/index.d.ts",
28
- "import": "./dist/modules/devices/index.js",
29
- "default": "./dist/modules/devices/index.js"
27
+ "types": "./src/modules/devices/index.ts",
28
+ "import": "./src/modules/devices/index.ts",
29
+ "default": "./src/modules/devices/index.ts"
30
30
  },
31
31
  "./environment": {
32
- "types": "./dist/modules/environment/index.d.ts",
33
- "import": "./dist/modules/environment/index.js",
34
- "default": "./dist/modules/environment/index.js"
32
+ "types": "./src/modules/environment/index.ts",
33
+ "import": "./src/modules/environment/index.ts",
34
+ "default": "./src/modules/environment/index.ts"
35
35
  },
36
36
  "./identify": {
37
- "types": "./dist/modules/identify/index.d.ts",
38
- "import": "./dist/modules/identify/index.js",
39
- "default": "./dist/modules/identify/index.js"
37
+ "types": "./src/modules/identify/index.ts",
38
+ "import": "./src/modules/identify/index.ts",
39
+ "default": "./src/modules/identify/index.ts"
40
40
  },
41
41
  "./me": {
42
- "types": "./dist/modules/me/index.d.ts",
43
- "import": "./dist/modules/me/index.js",
44
- "default": "./dist/modules/me/index.js"
42
+ "types": "./src/modules/me/index.ts",
43
+ "import": "./src/modules/me/index.ts",
44
+ "default": "./src/modules/me/index.ts"
45
45
  },
46
46
  "./orgs": {
47
- "types": "./dist/modules/orgs/index.d.ts",
48
- "import": "./dist/modules/orgs/index.js",
49
- "default": "./dist/modules/orgs/index.js"
47
+ "types": "./src/modules/orgs/index.ts",
48
+ "import": "./src/modules/orgs/index.ts",
49
+ "default": "./src/modules/orgs/index.ts"
50
50
  },
51
51
  "./personas": {
52
- "types": "./dist/modules/personas/index.d.ts",
53
- "import": "./dist/modules/personas/index.js",
54
- "default": "./dist/modules/personas/index.js"
52
+ "types": "./src/modules/personas/index.ts",
53
+ "import": "./src/modules/personas/index.ts",
54
+ "default": "./src/modules/personas/index.ts"
55
55
  },
56
56
  "./projects": {
57
- "types": "./dist/modules/projects/index.d.ts",
58
- "import": "./dist/modules/projects/index.js",
59
- "default": "./dist/modules/projects/index.js"
57
+ "types": "./src/modules/projects/index.ts",
58
+ "import": "./src/modules/projects/index.ts",
59
+ "default": "./src/modules/projects/index.ts"
60
60
  },
61
61
  "./sessions": {
62
- "types": "./dist/modules/sessions/index.d.ts",
63
- "import": "./dist/modules/sessions/index.js",
64
- "default": "./dist/modules/sessions/index.js"
62
+ "types": "./src/modules/sessions/index.ts",
63
+ "import": "./src/modules/sessions/index.ts",
64
+ "default": "./src/modules/sessions/index.ts"
65
65
  },
66
66
  "./versions": {
67
- "types": "./dist/modules/versions/index.d.ts",
68
- "import": "./dist/modules/versions/index.js",
69
- "default": "./dist/modules/versions/index.js"
67
+ "types": "./src/modules/versions/index.ts",
68
+ "import": "./src/modules/versions/index.ts",
69
+ "default": "./src/modules/versions/index.ts"
70
70
  },
71
71
  "./builds": {
72
- "types": "./dist/modules/builds/index.d.ts",
73
- "import": "./dist/modules/builds/index.js",
74
- "default": "./dist/modules/builds/index.js"
72
+ "types": "./src/modules/builds/index.ts",
73
+ "import": "./src/modules/builds/index.ts",
74
+ "default": "./src/modules/builds/index.ts"
75
75
  },
76
76
  "./analytics": {
77
- "types": "./dist/modules/analytics/index.d.ts",
78
- "import": "./dist/modules/analytics/index.js",
79
- "default": "./dist/modules/analytics/index.js"
77
+ "types": "./src/modules/analytics/index.ts",
78
+ "import": "./src/modules/analytics/index.ts",
79
+ "default": "./src/modules/analytics/index.ts"
80
80
  },
81
81
  "./events": {
82
- "types": "./dist/modules/events/index.d.ts",
83
- "import": "./dist/modules/events/index.js",
84
- "default": "./dist/modules/events/index.js"
82
+ "types": "./src/modules/events/index.ts",
83
+ "import": "./src/modules/events/index.ts",
84
+ "default": "./src/modules/events/index.ts"
85
85
  }
86
86
  },
87
87
  "scripts": {
88
- "dev": "tsc --project ./tsconfig.json --watch",
89
- "build": "tsc --project ./tsconfig.json",
90
88
  "typecheck": "tsc --noEmit --project ./tsconfig.json",
91
89
  "lint": "bun x biome lint .",
92
90
  "fmt": "bun x biome format --write .",
93
- "check": "bun x biome check .",
94
- "prepublishOnly": "bun x turbo run build"
91
+ "check": "bun x biome check ."
95
92
  },
96
93
  "dependencies": {
97
94
  "@sinclair/typebox": "^0.34.41",
98
- "@teardown/types": "0.1.21"
95
+ "@teardown/types": "0.1.23"
99
96
  },
100
97
  "devDependencies": {
101
98
  "@biomejs/biome": "2.3.7",
@@ -0,0 +1,21 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+
3
+ export const UUIDSchema = Type.String({ format: "uuid", error: "Invalid UUID" });
4
+ export const SlugSchema = Type.String({ pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$", error: "Invalid slug" });
5
+
6
+ export const URLSchema = Type.String({ format: "uri", error: "Invalid URL" });
7
+ export const TimestampSchema = Type.String({ format: "date-time", error: "Invalid timestamp" });
8
+
9
+ export type UUID = Static<typeof UUIDSchema>;
10
+ export type Slug = Static<typeof SlugSchema>;
11
+ export type URL = Static<typeof URLSchema>;
12
+ export type Timestamp = Static<typeof TimestampSchema>;
13
+
14
+ export const EmailSchema = Type.Transform(
15
+ Type.Optional(
16
+ Type.Union([Type.String({ format: "email", error: "Invalid email address" }), Type.Literal(""), Type.Undefined()])
17
+ )
18
+ )
19
+ .Decode((value) => (value === "" ? undefined : value))
20
+ .Encode((value) => value ?? "");
21
+ export type Email = Static<typeof EmailSchema>;
@@ -0,0 +1,25 @@
1
+ import { type Static, type TSchema, Type } from "@sinclair/typebox";
2
+
3
+ export const SuccessResponseSchema = <T extends TSchema>(dataSchema: T) =>
4
+ Type.Object({
5
+ success: Type.Literal(true),
6
+ data: dataSchema,
7
+ });
8
+
9
+ export const ErrorResponseSchema = Type.Object({
10
+ success: Type.Literal(false),
11
+ error: Type.Object({
12
+ message: Type.String(),
13
+ code: Type.Optional(Type.String()),
14
+ }),
15
+ });
16
+
17
+ export type SuccessResponse<T> = {
18
+ success: true;
19
+ data: T;
20
+ };
21
+
22
+ export type ErrorResponse = Static<typeof ErrorResponseSchema>;
23
+
24
+ export const RequestResponseSchema = <Success extends TSchema>(successSchema: Success) =>
25
+ Type.Union([SuccessResponseSchema(successSchema), ErrorResponseSchema]);
@@ -1,4 +1,5 @@
1
1
  import type { Insert, Tables, Update } from "@teardown/types";
2
+
2
3
  /**
3
4
  * Forces TypeScript to error if T is not `true`.
4
5
  * Wrap assertion types with this to ensure compile-time validation.
@@ -9,6 +10,7 @@ import type { Insert, Tables, Update } from "@teardown/types";
9
10
  * ```
10
11
  */
11
12
  export type AssertTrue<T extends true> = T;
13
+
12
14
  /**
13
15
  * Type-level assertion that ensures SchemaType is compatible with DbType.
14
16
  * This will cause a TypeScript error if SchemaType cannot be assigned to DbType.
@@ -18,7 +20,12 @@ export type AssertTrue<T extends true> = T;
18
20
  * type _Check = AssertTrue<AssertCompatible<Project, Tables<"projects">["Row"]>>;
19
21
  * ```
20
22
  */
21
- export type AssertCompatible<SchemaType, DbType> = SchemaType extends DbType ? DbType extends SchemaType ? true : never : never;
23
+ export type AssertCompatible<SchemaType, DbType> = SchemaType extends DbType
24
+ ? DbType extends SchemaType
25
+ ? true
26
+ : never
27
+ : never;
28
+
22
29
  /**
23
30
  * Type-level assertion that ensures SchemaType can be assigned to DbType.
24
31
  * This is less strict than AssertCompatible - it only checks one-way assignment.
@@ -29,6 +36,7 @@ export type AssertCompatible<SchemaType, DbType> = SchemaType extends DbType ? D
29
36
  * ```
30
37
  */
31
38
  export type AssertAssignable<SchemaType, DbType> = SchemaType extends DbType ? true : never;
39
+
32
40
  /**
33
41
  * Helper to check if a schema type is compatible with a database Row type
34
42
  *
@@ -37,7 +45,11 @@ export type AssertAssignable<SchemaType, DbType> = SchemaType extends DbType ? t
37
45
  * export type _CheckProjectRow = AssertSchemaCompatibleWithRow<Project, "projects">;
38
46
  * ```
39
47
  */
40
- export type AssertSchemaCompatibleWithRow<SchemaType, TableName extends keyof Tables> = AssertCompatible<SchemaType, Tables[TableName]["Row"]>;
48
+ export type AssertSchemaCompatibleWithRow<SchemaType, TableName extends keyof Tables> = AssertCompatible<
49
+ SchemaType,
50
+ Tables[TableName]["Row"]
51
+ >;
52
+
41
53
  /**
42
54
  * Helper to check if a create schema type is compatible with a database Insert type
43
55
  *
@@ -46,7 +58,11 @@ export type AssertSchemaCompatibleWithRow<SchemaType, TableName extends keyof Ta
46
58
  * type _CheckCreateProject = AssertSchemaCompatibleWithInsert<CreateProject, "projects">;
47
59
  * ```
48
60
  */
49
- export type AssertSchemaCompatibleWithInsert<SchemaType, TableName extends keyof Tables> = AssertAssignable<SchemaType, Insert<TableName>>;
61
+ export type AssertSchemaCompatibleWithInsert<SchemaType, TableName extends keyof Tables> = AssertAssignable<
62
+ SchemaType,
63
+ Insert<TableName>
64
+ >;
65
+
50
66
  /**
51
67
  * Helper to check if an update schema type is compatible with a database Update type
52
68
  *
@@ -55,4 +71,7 @@ export type AssertSchemaCompatibleWithInsert<SchemaType, TableName extends keyof
55
71
  * type _CheckUpdateProject = AssertSchemaCompatibleWithUpdate<UpdateProject, "projects">;
56
72
  * ```
57
73
  */
58
- export type AssertSchemaCompatibleWithUpdate<SchemaType, TableName extends keyof Tables> = AssertAssignable<SchemaType, Update<TableName>>;
74
+ export type AssertSchemaCompatibleWithUpdate<SchemaType, TableName extends keyof Tables> = AssertAssignable<
75
+ SchemaType,
76
+ Update<TableName>
77
+ >;
@@ -1,4 +1,5 @@
1
1
  // Module schemas
2
+
2
3
  export * from "./common";
3
4
  export * from "./modules/analytics";
4
5
  export * from "./modules/builds";
@@ -0,0 +1,178 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+
3
+ /**
4
+ * Version adoption schema
5
+ */
6
+ export const VersionAdoptionPointSchema = Type.Object({
7
+ date: Type.String(), // YYYY-MM-DD
8
+ versions: Type.Record(Type.String(), Type.Number()), // version -> count
9
+ });
10
+ export type VersionAdoptionPoint = Static<typeof VersionAdoptionPointSchema>;
11
+
12
+ export const VersionAdoptionResponseSchema = Type.Object({
13
+ success: Type.Literal(true),
14
+ data: Type.Array(VersionAdoptionPointSchema),
15
+ });
16
+ export type VersionAdoptionResponse = Static<typeof VersionAdoptionResponseSchema>;
17
+
18
+ /**
19
+ * Active sessions trend schema
20
+ */
21
+ export const ActiveSessionsPointSchema = Type.Object({
22
+ date: Type.String(), // YYYY-MM-DD
23
+ count: Type.Integer({ minimum: 0 }),
24
+ });
25
+ export type ActiveSessionsPoint = Static<typeof ActiveSessionsPointSchema>;
26
+
27
+ export const ActiveSessionsTrendResponseSchema = Type.Object({
28
+ success: Type.Literal(true),
29
+ data: Type.Array(ActiveSessionsPointSchema),
30
+ });
31
+ export type ActiveSessionsTrendResponse = Static<typeof ActiveSessionsTrendResponseSchema>;
32
+
33
+ /**
34
+ * Active users schema (with platform breakdown)
35
+ */
36
+ export const ActiveUsersSchema = Type.Object({
37
+ total: Type.Integer({ minimum: 0 }),
38
+ ios: Type.Integer({ minimum: 0 }),
39
+ android: Type.Integer({ minimum: 0 }),
40
+ trend: Type.Number(), // percentage change vs previous period
41
+ });
42
+ export type ActiveUsers = Static<typeof ActiveUsersSchema>;
43
+
44
+ export const ActiveUsersResponseSchema = Type.Object({
45
+ success: Type.Literal(true),
46
+ data: ActiveUsersSchema,
47
+ });
48
+ export type ActiveUsersResponse = Static<typeof ActiveUsersResponseSchema>;
49
+
50
+ /**
51
+ * Active users query params schema
52
+ */
53
+ export const ActiveUsersQuerySchema = Type.Object({
54
+ start_date: Type.String({ format: "date-time" }),
55
+ end_date: Type.String({ format: "date-time" }),
56
+ });
57
+ export type ActiveUsersQuery = Static<typeof ActiveUsersQuerySchema>;
58
+
59
+ /**
60
+ * Build adoption schema (with platform breakdown)
61
+ */
62
+ export const BuildStatsSchema = Type.Object({
63
+ total: Type.Integer({ minimum: 0 }),
64
+ ios: Type.Integer({ minimum: 0 }),
65
+ android: Type.Integer({ minimum: 0 }),
66
+ });
67
+ export type BuildStats = Static<typeof BuildStatsSchema>;
68
+
69
+ export const BuildAdoptionPointSchema = Type.Object({
70
+ date: Type.String(), // YYYY-MM-DD
71
+ builds: Type.Record(Type.String(), BuildStatsSchema), // build_number -> stats
72
+ });
73
+ export type BuildAdoptionPoint = Static<typeof BuildAdoptionPointSchema>;
74
+
75
+ export const BuildAdoptionResponseSchema = Type.Object({
76
+ success: Type.Literal(true),
77
+ data: Type.Array(BuildAdoptionPointSchema),
78
+ });
79
+ export type BuildAdoptionResponse = Static<typeof BuildAdoptionResponseSchema>;
80
+
81
+ /**
82
+ * Date range query params schema (shared)
83
+ */
84
+ export const DateRangeQuerySchema = Type.Object({
85
+ start_date: Type.String({ format: "date-time" }),
86
+ end_date: Type.String({ format: "date-time" }),
87
+ });
88
+ export type DateRangeQuery = Static<typeof DateRangeQuerySchema>;
89
+
90
+ /**
91
+ * Active versions/builds query params schema (with optional search)
92
+ */
93
+ export const ActiveVersionsQuerySchema = Type.Object({
94
+ start_date: Type.String({ format: "date-time" }),
95
+ end_date: Type.String({ format: "date-time" }),
96
+ search: Type.Optional(Type.String()),
97
+ });
98
+ export type ActiveVersionsQuery = Static<typeof ActiveVersionsQuerySchema>;
99
+
100
+ /**
101
+ * Active versions & builds analytics schema
102
+ * Aggregated session counts by version and build for a date range
103
+ */
104
+ export const ActiveBuildStatsSchema = Type.Object({
105
+ build_id: Type.String(),
106
+ build_number: Type.Integer({ minimum: 0 }),
107
+ platform: Type.Union([Type.Literal("IOS"), Type.Literal("ANDROID")]),
108
+ session_count: Type.Integer({ minimum: 0 }),
109
+ device_count: Type.Integer({ minimum: 0 }),
110
+ });
111
+ export type ActiveBuildStats = Static<typeof ActiveBuildStatsSchema>;
112
+
113
+ export const ActiveVersionStatsSchema = Type.Object({
114
+ version_id: Type.String(),
115
+ version_name: Type.String(),
116
+ session_count: Type.Integer({ minimum: 0 }),
117
+ device_count: Type.Integer({ minimum: 0 }),
118
+ ios_count: Type.Integer({ minimum: 0 }),
119
+ android_count: Type.Integer({ minimum: 0 }),
120
+ builds: Type.Array(ActiveBuildStatsSchema),
121
+ });
122
+ export type ActiveVersionStats = Static<typeof ActiveVersionStatsSchema>;
123
+
124
+ export const ActiveVersionsBuildsSchema = Type.Object({
125
+ versions: Type.Array(ActiveVersionStatsSchema),
126
+ });
127
+ export type ActiveVersionsBuilds = Static<typeof ActiveVersionsBuildsSchema>;
128
+
129
+ export const ActiveVersionsBuildsResponseSchema = Type.Object({
130
+ success: Type.Literal(true),
131
+ data: ActiveVersionsBuildsSchema,
132
+ });
133
+ export type ActiveVersionsBuildsResponse = Static<typeof ActiveVersionsBuildsResponseSchema>;
134
+
135
+ /**
136
+ * Session with user/device data for build sessions endpoint
137
+ */
138
+ export const SessionDeviceSchema = Type.Object({
139
+ id: Type.String(),
140
+ device_name: Type.Union([Type.String(), Type.Null()]),
141
+ device_brand: Type.Union([Type.String(), Type.Null()]),
142
+ });
143
+ export type SessionDevice = Static<typeof SessionDeviceSchema>;
144
+
145
+ export const SessionUserSchema = Type.Object({
146
+ id: Type.String(),
147
+ user_id: Type.Union([Type.String(), Type.Null()]),
148
+ email: Type.Union([Type.String(), Type.Null()]),
149
+ name: Type.Union([Type.String(), Type.Null()]),
150
+ });
151
+ export type SessionUser = Static<typeof SessionUserSchema>;
152
+
153
+ export const SessionWithUserSchema = Type.Object({
154
+ id: Type.String(),
155
+ started_at: Type.String(),
156
+ os_version: Type.Union([Type.String(), Type.Null()]),
157
+ device: SessionDeviceSchema,
158
+ user: Type.Union([SessionUserSchema, Type.Null()]),
159
+ });
160
+ export type SessionWithUser = Static<typeof SessionWithUserSchema>;
161
+
162
+ export const BuildSessionsQuerySchema = Type.Object({
163
+ start_date: Type.String({ format: "date-time" }),
164
+ end_date: Type.String({ format: "date-time" }),
165
+ cursor: Type.Optional(Type.String()),
166
+ limit: Type.Optional(Type.String({ default: "20" })),
167
+ search: Type.Optional(Type.String()),
168
+ });
169
+ export type BuildSessionsQuery = Static<typeof BuildSessionsQuerySchema>;
170
+
171
+ export const BuildSessionsResponseSchema = Type.Object({
172
+ success: Type.Literal(true),
173
+ data: Type.Object({
174
+ sessions: Type.Array(SessionWithUserSchema),
175
+ next_cursor: Type.Union([Type.String(), Type.Null()]),
176
+ }),
177
+ });
178
+ export type BuildSessionsResponse = Static<typeof BuildSessionsResponseSchema>;
@@ -0,0 +1,171 @@
1
+ import { VersionBuildStatusEnum } from "@teardown/types";
2
+ import { type Static, Type } from "@sinclair/typebox";
3
+ import type { AssertSchemaCompatibleWithRow, AssertTrue } from "../../common";
4
+ import { DevicePlatformSchema } from "../devices/schemas";
5
+
6
+ /**
7
+ * Build status enum matching database (reuses VersionBuildStatusEnum)
8
+ */
9
+ export const BuildStatusSchema = Type.Enum(VersionBuildStatusEnum);
10
+ export type BuildStatus = Static<typeof BuildStatusSchema>;
11
+
12
+ /**
13
+ * Base build schema
14
+ * Represents version_builds table structure
15
+ */
16
+ export const BuildSchema = Type.Object({
17
+ id: Type.String({ format: "uuid" }),
18
+ version_id: Type.String({ format: "uuid" }),
19
+ build_number: Type.Integer({ minimum: 0 }),
20
+ name: Type.Union([Type.String(), Type.Null()]),
21
+ summary: Type.Union([Type.String(), Type.Null()]),
22
+ commit_sha: Type.Union([Type.String(), Type.Null()]),
23
+ platform: DevicePlatformSchema,
24
+ status: BuildStatusSchema,
25
+ fingerprint: Type.Union([Type.String(), Type.Null()]),
26
+ created_at: Type.String(),
27
+ updated_at: Type.String(),
28
+ });
29
+ export type Build = Static<typeof BuildSchema>;
30
+
31
+ /**
32
+ * Build params schema
33
+ */
34
+ export const BuildParamsSchema = Type.Object({
35
+ build_id: Type.String({ format: "uuid" }),
36
+ });
37
+ export type BuildParams = Static<typeof BuildParamsSchema>;
38
+
39
+ /**
40
+ * Search builds query schema
41
+ * Supports pagination, search, and sorting
42
+ */
43
+ export const SearchBuildsQuerySchema = Type.Object({
44
+ project_id: Type.String({ format: "uuid" }),
45
+ page: Type.Number({ minimum: 1, default: 1 }),
46
+ limit: Type.Number({ minimum: 1, maximum: 100, default: 20 }),
47
+ search: Type.Optional(Type.String()),
48
+ sort_by: Type.Union(
49
+ [
50
+ Type.Literal("created_at"),
51
+ Type.Literal("updated_at"),
52
+ Type.Literal("build_number"),
53
+ Type.Literal("platform"),
54
+ Type.Literal("name"),
55
+ ],
56
+ { default: "created_at" }
57
+ ),
58
+ sort_order: Type.Union([Type.Literal("asc"), Type.Literal("desc")], { default: "desc" }),
59
+ });
60
+ export type SearchBuildsQuery = Static<typeof SearchBuildsQuerySchema>;
61
+
62
+ /**
63
+ * Search builds query schema without project_id (injected from headers)
64
+ */
65
+ export const SearchBuildsQueryParamsSchema = Type.Omit(SearchBuildsQuerySchema, ["project_id"]);
66
+ export type SearchBuildsQueryParams = Static<typeof SearchBuildsQueryParamsSchema>;
67
+
68
+ /**
69
+ * Builds by IDs request schema
70
+ */
71
+ export const BuildsByIdsSchema = Type.Object({
72
+ build_ids: Type.Array(Type.String({ format: "uuid" }), { minItems: 1, maxItems: 100 }),
73
+ });
74
+ export type BuildsByIds = Static<typeof BuildsByIdsSchema>;
75
+
76
+ /**
77
+ * Paginated builds response schema
78
+ */
79
+ export const BuildsResponseSchema = Type.Object({
80
+ builds: Type.Array(BuildSchema),
81
+ pagination: Type.Object({
82
+ page: Type.Integer({ minimum: 1 }),
83
+ limit: Type.Integer({ minimum: 1 }),
84
+ total: Type.Integer({ minimum: 0 }),
85
+ total_pages: Type.Integer({ minimum: 0 }),
86
+ }),
87
+ });
88
+ export type BuildsResponse = Static<typeof BuildsResponseSchema>;
89
+
90
+ /**
91
+ * Single build response schema
92
+ */
93
+ export const BuildResponseSchema = Type.Object({
94
+ success: Type.Literal(true),
95
+ data: BuildSchema,
96
+ });
97
+ export type BuildResponse = Static<typeof BuildResponseSchema>;
98
+
99
+ /**
100
+ * Build error response schema
101
+ * Discriminated union by error code
102
+ */
103
+ export const BuildErrorSchema = Type.Union([
104
+ Type.Object({
105
+ code: Type.Literal("BUILD_NOT_FOUND"),
106
+ message: Type.String(),
107
+ }),
108
+ Type.Object({
109
+ code: Type.Literal("PROJECT_NOT_FOUND"),
110
+ message: Type.String(),
111
+ }),
112
+ Type.Object({
113
+ code: Type.Literal("FORBIDDEN"),
114
+ message: Type.String(),
115
+ }),
116
+ Type.Object({
117
+ code: Type.Literal("FETCH_FAILED"),
118
+ message: Type.String(),
119
+ }),
120
+ Type.Object({
121
+ code: Type.Literal("INVALID_PARAMS"),
122
+ message: Type.String(),
123
+ }),
124
+ ]);
125
+ export type BuildError = Static<typeof BuildErrorSchema>;
126
+
127
+ /**
128
+ * Build error response wrapper
129
+ */
130
+ export const BuildErrorResponseSchema = Type.Object({
131
+ success: Type.Literal(false),
132
+ error: BuildErrorSchema,
133
+ });
134
+ export type BuildErrorResponse = Static<typeof BuildErrorResponseSchema>;
135
+
136
+ /**
137
+ * Build request response schema
138
+ */
139
+ export const BuildRequestResponseSchema = Type.Union([BuildResponseSchema, BuildErrorResponseSchema]);
140
+ export type BuildRequestResponse = Static<typeof BuildRequestResponseSchema>;
141
+
142
+ export type _CheckBuildRow = AssertTrue<AssertSchemaCompatibleWithRow<Build, "version_builds">>;
143
+
144
+ /**
145
+ * Update build status request body schema
146
+ */
147
+ export const UpdateBuildStatusBodySchema = Type.Object({
148
+ status: BuildStatusSchema,
149
+ });
150
+ export type UpdateBuildStatusBody = Static<typeof UpdateBuildStatusBodySchema>;
151
+
152
+ /**
153
+ * Add UPDATE_FAILED error code for update operations
154
+ */
155
+ export const BuildErrorSchemaWithUpdate = Type.Union([
156
+ BuildErrorSchema,
157
+ Type.Object({
158
+ code: Type.Literal("UPDATE_FAILED"),
159
+ message: Type.String(),
160
+ }),
161
+ ]);
162
+ export type BuildErrorWithUpdate = Static<typeof BuildErrorSchemaWithUpdate>;
163
+
164
+ /**
165
+ * Build error response wrapper with update error
166
+ */
167
+ export const BuildErrorResponseWithUpdateSchema = Type.Object({
168
+ success: Type.Literal(false),
169
+ error: BuildErrorSchemaWithUpdate,
170
+ });
171
+ export type BuildErrorResponseWithUpdate = Static<typeof BuildErrorResponseWithUpdateSchema>;