@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,87 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+ import { OrgRoleWithOrgSchema } from "../orgs/schemas";
3
+
4
+ /**
5
+ * User schema
6
+ * Represents Supabase Auth user structure
7
+ */
8
+ export const UserSchema = Type.Object({
9
+ id: Type.String({ format: "uuid" }),
10
+ email: Type.Optional(Type.String({ format: "email" })),
11
+ app_metadata: Type.Record(Type.String(), Type.Unknown()),
12
+ user_metadata: Type.Record(Type.String(), Type.Unknown()),
13
+ created_at: Type.String(),
14
+
15
+ // id: string
16
+ // app_metadata: UserAppMetadata
17
+ // user_metadata: UserMetadata
18
+ // aud: string
19
+ // confirmation_sent_at?: string
20
+ // recovery_sent_at?: string
21
+ // email_change_sent_at?: string
22
+ // new_email?: string
23
+ // new_phone?: string
24
+ // invited_at?: string
25
+ // action_link?: string
26
+ // email?: string
27
+ // phone?: string
28
+ // created_at: string
29
+ // confirmed_at?: string
30
+ // email_confirmed_at?: string
31
+ // phone_confirmed_at?: string
32
+ // last_sign_in_at?: string
33
+ // role?: string
34
+ // updated_at?: string
35
+ // identities?: UserIdentity[]
36
+ // is_anonymous?: boolean
37
+ // is_sso_user?: boolean
38
+ // factors?: (Factor<FactorType, 'verified'> | Factor<FactorType, 'unverified'>)[]
39
+ // deleted_at?: string
40
+ });
41
+ export type User = Static<typeof UserSchema>;
42
+
43
+ /**
44
+ * Me response schema
45
+ */
46
+ export const MeResponseSchema = Type.Object({
47
+ user: UserSchema,
48
+ });
49
+ export type MeResponse = Static<typeof MeResponseSchema>;
50
+
51
+ /**
52
+ * Me orgs response schema
53
+ * Reuses OrgRoleWithOrgSchema from orgs module
54
+ */
55
+ export const MeOrgsResponseSchema = Type.Object({
56
+ orgs: Type.Array(OrgRoleWithOrgSchema),
57
+ });
58
+ export type MeOrgsResponse = Static<typeof MeOrgsResponseSchema>;
59
+
60
+ /**
61
+ * Me error response schema
62
+ * Discriminated union by error code
63
+ */
64
+ export const MeErrorSchema = Type.Union([
65
+ Type.Object({
66
+ code: Type.Literal("UNAUTHORIZED"),
67
+ message: Type.String(),
68
+ }),
69
+ Type.Object({
70
+ code: Type.Literal("USER_NOT_FOUND"),
71
+ message: Type.String(),
72
+ }),
73
+ Type.Object({
74
+ code: Type.Literal("FETCH_FAILED"),
75
+ message: Type.String(),
76
+ }),
77
+ ]);
78
+ export type MeError = Static<typeof MeErrorSchema>;
79
+
80
+ /**
81
+ * Me error response wrapper
82
+ */
83
+ export const MeErrorResponseSchema = Type.Object({
84
+ success: Type.Literal(false),
85
+ error: MeErrorSchema,
86
+ });
87
+ export type MeErrorResponse = Static<typeof MeErrorResponseSchema>;
@@ -0,0 +1,260 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+ import { OrgRoleTypeEnum, OrgTypeEnum } from "@teardown/types";
3
+ import {
4
+ type AssertSchemaCompatibleWithInsert,
5
+ type AssertSchemaCompatibleWithRow,
6
+ type AssertSchemaCompatibleWithUpdate,
7
+ type AssertTrue,
8
+ SlugSchema,
9
+ } from "../../common";
10
+
11
+ export const OrgHeadersSchema = Type.Object({
12
+ "td-org-id": Type.String(),
13
+ });
14
+ export type OrgHeaders = Static<typeof OrgHeadersSchema>;
15
+
16
+ /**
17
+ * Helper to check if role is admin or owner
18
+ */
19
+ export function isAdminRole(role: string): boolean {
20
+ return role === OrgRoleTypeEnum.OWNER || role === OrgRoleTypeEnum.ADMIN;
21
+ }
22
+
23
+ /**
24
+ * Helper to check if role is owner
25
+ */
26
+ export function isOwnerRole(role: string): boolean {
27
+ return role === OrgRoleTypeEnum.OWNER;
28
+ }
29
+
30
+ /**
31
+ * Parse and validate an OrgRoleTypeEnum value
32
+ * Uses a switch statement to ensure type safety and runtime validation
33
+ * @param value - The value to parse
34
+ * @returns The validated OrgRoleTypeEnum value
35
+ * @throws Error if the value is not a valid OrgRoleTypeEnum
36
+ */
37
+ export function parseOrgRoleTypeEnum(value: unknown): OrgRoleTypeEnum {
38
+ switch (value) {
39
+ case OrgRoleTypeEnum.OWNER:
40
+ return OrgRoleTypeEnum.OWNER;
41
+ case OrgRoleTypeEnum.ADMIN:
42
+ return OrgRoleTypeEnum.ADMIN;
43
+ case OrgRoleTypeEnum.ENGINEER:
44
+ return OrgRoleTypeEnum.ENGINEER;
45
+ default:
46
+ throw new Error(
47
+ `Invalid OrgRoleTypeEnum value: ${value}. Expected one of: ${Object.values(OrgRoleTypeEnum).join(", ")}`
48
+ );
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Parse and validate an OrgTypeEnum value
54
+ * Uses a switch statement to ensure type safety and runtime validation
55
+ * @param value - The value to parse
56
+ * @returns The validated OrgTypeEnum value
57
+ * @throws Error if the value is not a valid OrgTypeEnum
58
+ */
59
+ export function parseOrgTypeEnum(value: unknown): OrgTypeEnum {
60
+ switch (value) {
61
+ case OrgTypeEnum.PERSONAL:
62
+ return OrgTypeEnum.PERSONAL;
63
+ case OrgTypeEnum.START_UP:
64
+ return OrgTypeEnum.START_UP;
65
+ case OrgTypeEnum.SCALE_UP:
66
+ return OrgTypeEnum.SCALE_UP;
67
+ case OrgTypeEnum.AGENCY:
68
+ return OrgTypeEnum.AGENCY;
69
+ case OrgTypeEnum.ENTERPRISE:
70
+ return OrgTypeEnum.ENTERPRISE;
71
+ default:
72
+ throw new Error(`Invalid OrgTypeEnum value: ${value}. Expected one of: ${Object.values(OrgTypeEnum).join(", ")}`);
73
+ }
74
+ }
75
+
76
+ export const OrgSlugOrIdParamsSchema = Type.Object({
77
+ org_id_or_slug: Type.String(),
78
+ });
79
+ export type OrgSlugOrIdParams = Static<typeof OrgSlugOrIdParamsSchema>;
80
+
81
+ export const OrgIdParamsSchema = Type.Object({
82
+ org_id: Type.String(),
83
+ });
84
+ export type OrgIdParams = Static<typeof OrgIdParamsSchema>;
85
+
86
+ export const OrgSlugParamsSchema = Type.Object({
87
+ // org_slug: SlugSchema,
88
+ });
89
+ export type OrgSlugParams = Static<typeof OrgSlugParamsSchema>;
90
+
91
+ /**
92
+ * Base org schema
93
+ * Represents organisation table structure
94
+ */
95
+ export const OrgSchema = Type.Object({
96
+ id: Type.String({ format: "uuid" }),
97
+ name: Type.String({ minLength: 1 }),
98
+ slug: SlugSchema,
99
+ type: Type.Enum(OrgTypeEnum),
100
+ created_at: Type.String(),
101
+ updated_at: Type.String(),
102
+ });
103
+ export type Org = Static<typeof OrgSchema>;
104
+
105
+ /**
106
+ * Org role schema
107
+ * Represents organisation_role table structure
108
+ */
109
+ export const OrgRoleSchema = Type.Object({
110
+ id: Type.String({ format: "uuid" }),
111
+ org_id: Type.String({ format: "uuid" }),
112
+ user_id: Type.String({ format: "uuid" }),
113
+ role: Type.Enum(OrgRoleTypeEnum),
114
+ created_at: Type.String(),
115
+ updated_at: Type.String(),
116
+ });
117
+ export type OrgRole = Static<typeof OrgRoleSchema>;
118
+
119
+ /**
120
+ * Extended org role with org name
121
+ * Used for user's org list
122
+ */
123
+ export const OrgRoleWithOrgSchema = Type.Composite([
124
+ OrgRoleSchema,
125
+ Type.Object({
126
+ org_id: Type.String({ format: "uuid" }),
127
+ org_name: Type.String(),
128
+ org_slug: SlugSchema,
129
+ }),
130
+ ]);
131
+ export type OrgRoleWithOrg = Static<typeof OrgRoleWithOrgSchema>;
132
+
133
+ /**
134
+ * Create org request schema
135
+ */
136
+ export const CreateOrgSchema = Type.Object({
137
+ name: Type.String({ minLength: 1, maxLength: 255 }),
138
+ slug: SlugSchema,
139
+ type: Type.Enum(OrgTypeEnum),
140
+ });
141
+ export type CreateOrg = Static<typeof CreateOrgSchema>;
142
+
143
+ /**
144
+ * Update org request schema
145
+ */
146
+ export const UpdateOrgSchema = Type.Object({
147
+ name: Type.Optional(Type.String({ minLength: 1, maxLength: 255 })),
148
+ });
149
+ export type UpdateOrg = Static<typeof UpdateOrgSchema>;
150
+
151
+ /**
152
+ * Add org role request schema
153
+ */
154
+ export const AddOrgRoleSchema = Type.Object({
155
+ org_id: Type.String({ format: "uuid" }),
156
+ user_id: Type.String({ format: "uuid" }),
157
+ role: Type.Enum(OrgRoleTypeEnum),
158
+ });
159
+ export type AddOrgRole = Static<typeof AddOrgRoleSchema>;
160
+
161
+ /**
162
+ * Single org response schema
163
+ */
164
+ export const OrgResponseSchema = Type.Object({
165
+ success: Type.Literal(true),
166
+ data: Type.Object({
167
+ org: OrgRoleWithOrgSchema,
168
+ }),
169
+ });
170
+ export type OrgResponse = Static<typeof OrgResponseSchema>;
171
+
172
+ /**
173
+ * Org error response schema
174
+ * Discriminated union by error code
175
+ */
176
+ export const OrgErrorSchema = Type.Union([
177
+ Type.Object({
178
+ code: Type.Literal("UNKNOWN_ERROR"),
179
+ message: Type.String(),
180
+ }),
181
+ Type.Object({
182
+ code: Type.Literal("VALIDATION_ERROR"),
183
+ message: Type.String(),
184
+ }),
185
+ Type.Object({
186
+ code: Type.Literal("ORG_ID_MISMATCH"),
187
+ message: Type.String(),
188
+ }),
189
+ Type.Object({
190
+ code: Type.Literal("ORG_NOT_FOUND"),
191
+ message: Type.String(),
192
+ }),
193
+ Type.Object({
194
+ code: Type.Literal("ORG_ROLE_NOT_FOUND"),
195
+ message: Type.String(),
196
+ }),
197
+ Type.Object({
198
+ code: Type.Literal("USER_NOT_IN_ORG"),
199
+ message: Type.String(),
200
+ }),
201
+ Type.Object({
202
+ code: Type.Literal("FORBIDDEN"),
203
+ message: Type.String(),
204
+ }),
205
+ Type.Object({
206
+ code: Type.Literal("UNAUTHORIZED"),
207
+ message: Type.String(),
208
+ }),
209
+ Type.Object({
210
+ code: Type.Literal("INVALID_ROLE"),
211
+ message: Type.String(),
212
+ }),
213
+ Type.Object({
214
+ code: Type.Literal("ORG_ID_REQUIRED"),
215
+ message: Type.String(),
216
+ }),
217
+ Type.Object({
218
+ code: Type.Literal("SLUG_ALREADY_EXISTS"),
219
+ message: Type.String(),
220
+ }),
221
+ Type.Object({
222
+ code: Type.Literal("FETCH_FAILED"),
223
+ message: Type.String(),
224
+ }),
225
+ Type.Object({
226
+ code: Type.Literal("CREATE_FAILED"),
227
+ message: Type.String(),
228
+ }),
229
+ Type.Object({
230
+ code: Type.Literal("UPDATE_FAILED"),
231
+ message: Type.String(),
232
+ }),
233
+ Type.Object({
234
+ code: Type.Literal("DELETE_FAILED"),
235
+ message: Type.String(),
236
+ }),
237
+ Type.Object({
238
+ code: Type.Literal("ROLE_CREATION_FAILED"),
239
+ message: Type.String(),
240
+ }),
241
+ ]);
242
+ export type OrgError = Static<typeof OrgErrorSchema>;
243
+
244
+ /**
245
+ * Org error response wrapper
246
+ */
247
+ export const OrgErrorResponseSchema = Type.Object({
248
+ success: Type.Literal(false),
249
+ error: OrgErrorSchema,
250
+ });
251
+ export type OrgErrorResponse = Static<typeof OrgErrorResponseSchema>;
252
+
253
+ export const OrgRequestResponseSchema = Type.Union([OrgResponseSchema, OrgErrorResponseSchema]);
254
+ export type OrgRequestResponse = Static<typeof OrgRequestResponseSchema>;
255
+
256
+ export type _CheckOrgRow = AssertTrue<AssertSchemaCompatibleWithRow<Org, "orgs">>;
257
+ export type _CheckCreateOrg = AssertTrue<AssertSchemaCompatibleWithInsert<CreateOrg, "orgs">>;
258
+ export type _CheckUpdateOrg = AssertTrue<AssertSchemaCompatibleWithUpdate<UpdateOrg, "orgs">>;
259
+ export type _CheckOrgRoleRow = AssertTrue<AssertSchemaCompatibleWithRow<OrgRole, "org_roles">>;
260
+ export type _CheckAddOrgRole = AssertTrue<AssertSchemaCompatibleWithInsert<AddOrgRole, "org_roles">>;
@@ -0,0 +1,123 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+ import type { AssertSchemaCompatibleWithRow, AssertTrue } from "../../common";
3
+
4
+ /**
5
+ * Base persona schema
6
+ * Represents personas table structure
7
+ */
8
+ export const PersonaSchema = Type.Object({
9
+ id: Type.String({ format: "uuid" }),
10
+ environment_id: Type.String({ format: "uuid" }),
11
+ user_id: Type.Union([Type.String(), Type.Null()]),
12
+ name: Type.Union([Type.String(), Type.Null()]),
13
+ email: Type.Union([Type.String({ format: "email" }), Type.Null()]),
14
+ created_at: Type.String(),
15
+ updated_at: Type.String(),
16
+ });
17
+ export type Persona = Static<typeof PersonaSchema>;
18
+
19
+ /**
20
+ * Persona params schema
21
+ */
22
+ export const PersonaParamsSchema = Type.Object({
23
+ persona_id: Type.String({ format: "uuid" }),
24
+ });
25
+ export type PersonaParams = Static<typeof PersonaParamsSchema>;
26
+
27
+ /**
28
+ * Search personas query schema
29
+ * Supports pagination, search, and sorting
30
+ */
31
+ export const SearchPersonasQuerySchema = Type.Object({
32
+ project_id: Type.String({ format: "uuid" }),
33
+ page: Type.Number({ minimum: 1, default: 1 }),
34
+ limit: Type.Number({ minimum: 1, maximum: 100, default: 20 }),
35
+ search: Type.Optional(Type.String()),
36
+ sort_by: Type.Union([Type.Literal("created_at"), Type.Literal("updated_at"), Type.Literal("name"), Type.Literal("email")], {
37
+ default: "created_at",
38
+ }),
39
+ sort_order: Type.Union([Type.Literal("asc"), Type.Literal("desc")], { default: "desc" }),
40
+ });
41
+ export type SearchPersonasQuery = Static<typeof SearchPersonasQuerySchema>;
42
+
43
+ /**
44
+ * Search personas query schema without project_id (injected from headers)
45
+ */
46
+ export const SearchPersonasQueryParamsSchema = Type.Omit(SearchPersonasQuerySchema, ["project_id"]);
47
+ export type SearchPersonasQueryParams = Static<typeof SearchPersonasQueryParamsSchema>;
48
+
49
+ /**
50
+ * Personas by IDs request schema
51
+ */
52
+ export const PersonasByIdsSchema = Type.Object({
53
+ persona_ids: Type.Array(Type.String({ format: "uuid" }), { minItems: 1, maxItems: 100 }),
54
+ });
55
+ export type PersonasByIds = Static<typeof PersonasByIdsSchema>;
56
+
57
+ /**
58
+ * Paginated personas response schema
59
+ */
60
+ export const PersonasResponseSchema = Type.Object({
61
+ personas: Type.Array(PersonaSchema),
62
+ pagination: Type.Object({
63
+ page: Type.Integer({ minimum: 1 }),
64
+ limit: Type.Integer({ minimum: 1 }),
65
+ total: Type.Integer({ minimum: 0 }),
66
+ total_pages: Type.Integer({ minimum: 0 }),
67
+ }),
68
+ });
69
+ export type PersonasResponse = Static<typeof PersonasResponseSchema>;
70
+
71
+ /**
72
+ * Single persona response schema
73
+ */
74
+ export const PersonaResponseSchema = Type.Object({
75
+ success: Type.Literal(true),
76
+ data: PersonaSchema,
77
+ });
78
+ export type PersonaResponse = Static<typeof PersonaResponseSchema>;
79
+
80
+ /**
81
+ * Persona error response schema
82
+ * Discriminated union by error code
83
+ */
84
+ export const PersonaErrorSchema = Type.Union([
85
+ Type.Object({
86
+ code: Type.Literal("PERSONA_NOT_FOUND"),
87
+ message: Type.String(),
88
+ }),
89
+ Type.Object({
90
+ code: Type.Literal("PROJECT_NOT_FOUND"),
91
+ message: Type.String(),
92
+ }),
93
+ Type.Object({
94
+ code: Type.Literal("FORBIDDEN"),
95
+ message: Type.String(),
96
+ }),
97
+ Type.Object({
98
+ code: Type.Literal("FETCH_FAILED"),
99
+ message: Type.String(),
100
+ }),
101
+ Type.Object({
102
+ code: Type.Literal("INVALID_PARAMS"),
103
+ message: Type.String(),
104
+ }),
105
+ ]);
106
+ export type PersonaError = Static<typeof PersonaErrorSchema>;
107
+
108
+ /**
109
+ * Persona error response wrapper
110
+ */
111
+ export const PersonaErrorResponseSchema = Type.Object({
112
+ success: Type.Literal(false),
113
+ error: PersonaErrorSchema,
114
+ });
115
+ export type PersonaErrorResponse = Static<typeof PersonaErrorResponseSchema>;
116
+
117
+ /**
118
+ * Persona request response schema
119
+ */
120
+ export const PersonaRequestResponseSchema = Type.Union([PersonaResponseSchema, PersonaErrorResponseSchema]);
121
+ export type PersonaRequestResponse = Static<typeof PersonaRequestResponseSchema>;
122
+
123
+ export type _CheckPersonaRow = AssertTrue<AssertSchemaCompatibleWithRow<Persona, "personas">>;
@@ -0,0 +1,179 @@
1
+ import { type Static, Type } from "@sinclair/typebox";
2
+ import { ProjectStatusEnum, ProjectTypeEnum } from "@teardown/types";
3
+ import {
4
+ type AssertSchemaCompatibleWithInsert,
5
+ type AssertSchemaCompatibleWithRow,
6
+ type AssertSchemaCompatibleWithUpdate,
7
+ type AssertTrue,
8
+ SlugSchema,
9
+ } from "../../common";
10
+
11
+ /**
12
+ * Parse and validate a ProjectTypeEnum value
13
+ * Uses a switch statement to ensure type safety and runtime validation
14
+ * @param value - The value to parse
15
+ * @returns The validated ProjectTypeEnum value
16
+ * @throws Error if the value is not a valid ProjectTypeEnum
17
+ */
18
+ export function parseProjectTypeEnum(value: unknown): ProjectTypeEnum {
19
+ switch (value) {
20
+ case ProjectTypeEnum.REACT_NATIVE:
21
+ return ProjectTypeEnum.REACT_NATIVE;
22
+ case ProjectTypeEnum.EXPO:
23
+ return ProjectTypeEnum.EXPO;
24
+ default:
25
+ throw new Error(
26
+ `Invalid ProjectTypeEnum value: ${value}. Expected one of: ${Object.values(ProjectTypeEnum).join(", ")}`
27
+ );
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Parse and validate a ProjectStatusEnum value
33
+ * Uses a switch statement to ensure type safety and runtime validation
34
+ * @param value - The value to parse
35
+ * @returns The validated ProjectStatusEnum value
36
+ * @throws Error if the value is not a valid ProjectStatusEnum
37
+ */
38
+ export function parseProjectStatusEnum(value: unknown): ProjectStatusEnum {
39
+ switch (value) {
40
+ case ProjectStatusEnum.PENDING_SETUP:
41
+ return ProjectStatusEnum.PENDING_SETUP;
42
+ case ProjectStatusEnum.ACTIVE:
43
+ return ProjectStatusEnum.ACTIVE;
44
+ case ProjectStatusEnum.PAUSED:
45
+ return ProjectStatusEnum.PAUSED;
46
+ case ProjectStatusEnum.ARCHIVED:
47
+ return ProjectStatusEnum.ARCHIVED;
48
+ default:
49
+ throw new Error(
50
+ `Invalid ProjectStatusEnum value: ${value}. Expected one of: ${Object.values(ProjectStatusEnum).join(", ")}`
51
+ );
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Base project schema
57
+ * Represents projects table structure
58
+ */
59
+ export const ProjectSchema = Type.Object({
60
+ id: Type.String({ format: "uuid" }),
61
+ org_id: Type.String({ format: "uuid" }),
62
+ name: Type.String({ minLength: 1 }),
63
+ slug: SlugSchema,
64
+ type: Type.Enum(ProjectTypeEnum),
65
+ status: Type.Enum(ProjectStatusEnum),
66
+ created_at: Type.String(),
67
+ updated_at: Type.String(),
68
+ });
69
+ export type Project = Static<typeof ProjectSchema>;
70
+
71
+ export const ProjectParamsSchema = Type.Object({
72
+ project_id_or_slug: Type.String(),
73
+ });
74
+ export type ProjectParams = Static<typeof ProjectParamsSchema>;
75
+
76
+ /**
77
+ * Create project request schema
78
+ */
79
+ export const CreateProjectSchema = Type.Object({
80
+ name: Type.String({ minLength: 1, maxLength: 255 }),
81
+ slug: SlugSchema,
82
+ type: Type.Enum(ProjectTypeEnum),
83
+ org_id: Type.String(),
84
+ });
85
+ export type CreateProject = Static<typeof CreateProjectSchema>;
86
+
87
+ /**
88
+ * Update project request schema
89
+ */
90
+ export const UpdateProjectSchema = Type.Object({
91
+ name: Type.Optional(Type.String({ minLength: 1, maxLength: 255 })),
92
+ slug: Type.Optional(SlugSchema),
93
+ });
94
+ export type UpdateProject = Static<typeof UpdateProjectSchema>;
95
+
96
+ /**
97
+ * Single project response schema
98
+ */
99
+ export const ProjectResponseSchema = Type.Object({
100
+ success: Type.Literal(true),
101
+ data: ProjectSchema,
102
+ });
103
+ export type ProjectResponse = Static<typeof ProjectResponseSchema>;
104
+
105
+ /**
106
+ * Multiple projects response schema
107
+ */
108
+ export const ProjectsResponseSchema = Type.Object({
109
+ projects: Type.Array(ProjectSchema),
110
+ });
111
+ export type ProjectsResponse = Static<typeof ProjectsResponseSchema>;
112
+
113
+ /**
114
+ * Project error response schema
115
+ * Discriminated union by error code
116
+ */
117
+ export const ProjectErrorSchema = Type.Union([
118
+ Type.Object({
119
+ code: Type.Literal("PROJECT_NOT_FOUND"),
120
+ message: Type.String(),
121
+ }),
122
+ Type.Object({
123
+ code: Type.Literal("PROJECT_NOT_IN_ORG"),
124
+ message: Type.String(),
125
+ }),
126
+ Type.Object({
127
+ code: Type.Literal("INVALID_SLUG"),
128
+ message: Type.String(),
129
+ }),
130
+ Type.Object({
131
+ code: Type.Literal("SLUG_ALREADY_EXISTS"),
132
+ message: Type.String(),
133
+ }),
134
+ Type.Object({
135
+ code: Type.Literal("FORBIDDEN"),
136
+ message: Type.String(),
137
+ }),
138
+ Type.Object({
139
+ code: Type.Literal("CREATE_FAILED"),
140
+ message: Type.String(),
141
+ }),
142
+ Type.Object({
143
+ code: Type.Literal("UPDATE_FAILED"),
144
+ message: Type.String(),
145
+ }),
146
+ Type.Object({
147
+ code: Type.Literal("DELETE_FAILED"),
148
+ message: Type.String(),
149
+ }),
150
+ Type.Object({
151
+ code: Type.Literal("FETCH_FAILED"),
152
+ message: Type.String(),
153
+ }),
154
+ Type.Object({
155
+ code: Type.Literal("ARCHIVE_FAILED"),
156
+ message: Type.String(),
157
+ }),
158
+ Type.Object({
159
+ code: Type.Literal("INVALID_REQUEST"),
160
+ message: Type.String(),
161
+ }),
162
+ ]);
163
+ export type ProjectError = Static<typeof ProjectErrorSchema>;
164
+
165
+ /**
166
+ * Project error response wrapper
167
+ */
168
+ export const ProjectErrorResponseSchema = Type.Object({
169
+ success: Type.Literal(false),
170
+ error: ProjectErrorSchema,
171
+ });
172
+ export type ProjectErrorResponse = Static<typeof ProjectErrorResponseSchema>;
173
+
174
+ export const ProjectRequestResponseSchema = Type.Union([ProjectResponseSchema, ProjectErrorResponseSchema]);
175
+ export type ProjectRequestResponse = Static<typeof ProjectRequestResponseSchema>;
176
+
177
+ export type _CheckProjectRow = AssertTrue<AssertSchemaCompatibleWithRow<Project, "projects">>;
178
+ export type _CheckCreateProject = AssertTrue<AssertSchemaCompatibleWithInsert<CreateProject, "projects">>;
179
+ export type _CheckUpdateProject = AssertTrue<AssertSchemaCompatibleWithUpdate<UpdateProject, "projects">>;