@lcas58/esmi-api-types 1.0.27 → 1.0.28

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.
@@ -44,6 +44,7 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
44
44
  source: "external" | "community";
45
45
  thumbnailUrl: string | null;
46
46
  createdByUserId: string | null;
47
+ groupId: string | null;
47
48
  creator: {
48
49
  image: string | null;
49
50
  id: string;
@@ -95,6 +96,7 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
95
96
  source: "external" | "community";
96
97
  thumbnailUrl: string | null;
97
98
  createdByUserId: string | null;
99
+ groupId: string | null;
98
100
  creator: {
99
101
  image: string | null;
100
102
  id: string;
@@ -162,6 +164,7 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
162
164
  source: "external" | "community";
163
165
  thumbnailUrl: string | null;
164
166
  createdByUserId: string | null;
167
+ groupId: string | null;
165
168
  creator: {
166
169
  image: string | null;
167
170
  id: string;
@@ -291,6 +294,7 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
291
294
  source: "external" | "community";
292
295
  thumbnailUrl: string | null;
293
296
  createdByUserId: string | null;
297
+ groupId: string | null;
294
298
  creator: {
295
299
  image: string | null;
296
300
  id: string;
@@ -106,6 +106,7 @@ export declare const list: {
106
106
  } | (string | number | boolean | {
107
107
  [key: string]: string | number | boolean | /*elided*/ any | /*elided*/ any | null;
108
108
  } | /*elided*/ any | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null>>;
109
+ groupId: z.ZodNullable<z.ZodString>;
109
110
  createdByUserId: z.ZodNullable<z.ZodString>;
110
111
  createdAt: z.ZodDate;
111
112
  }, {
@@ -225,6 +226,7 @@ export declare const list: {
225
226
  source: "external" | "community";
226
227
  thumbnailUrl: string | null;
227
228
  createdByUserId: string | null;
229
+ groupId: string | null;
228
230
  creator: {
229
231
  image: string | null;
230
232
  id: string;
@@ -287,6 +289,7 @@ export declare const list: {
287
289
  source: "external" | "community";
288
290
  thumbnailUrl: string | null;
289
291
  createdByUserId: string | null;
292
+ groupId: string | null;
290
293
  creator: {
291
294
  image: string | null;
292
295
  id: string;
@@ -383,6 +386,7 @@ export declare const getOne: {
383
386
  } | (string | number | boolean | {
384
387
  [key: string]: string | number | boolean | /*elided*/ any | /*elided*/ any | null;
385
388
  } | /*elided*/ any | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null>>;
389
+ groupId: z.ZodNullable<z.ZodString>;
386
390
  createdByUserId: z.ZodNullable<z.ZodString>;
387
391
  createdAt: z.ZodDate;
388
392
  }, {
@@ -502,6 +506,7 @@ export declare const getOne: {
502
506
  source: "external" | "community";
503
507
  thumbnailUrl: string | null;
504
508
  createdByUserId: string | null;
509
+ groupId: string | null;
505
510
  creator: {
506
511
  image: string | null;
507
512
  id: string;
@@ -564,6 +569,7 @@ export declare const getOne: {
564
569
  source: "external" | "community";
565
570
  thumbnailUrl: string | null;
566
571
  createdByUserId: string | null;
572
+ groupId: string | null;
567
573
  creator: {
568
574
  image: string | null;
569
575
  id: string;
@@ -720,6 +726,7 @@ export declare const discover: {
720
726
  } | (string | number | boolean | {
721
727
  [key: string]: string | number | boolean | /*elided*/ any | /*elided*/ any | null;
722
728
  } | /*elided*/ any | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null>>;
729
+ groupId: z.ZodNullable<z.ZodString>;
723
730
  createdByUserId: z.ZodNullable<z.ZodString>;
724
731
  createdAt: z.ZodDate;
725
732
  }, {
@@ -839,6 +846,7 @@ export declare const discover: {
839
846
  source: "external" | "community";
840
847
  thumbnailUrl: string | null;
841
848
  createdByUserId: string | null;
849
+ groupId: string | null;
842
850
  creator: {
843
851
  image: string | null;
844
852
  id: string;
@@ -901,6 +909,7 @@ export declare const discover: {
901
909
  source: "external" | "community";
902
910
  thumbnailUrl: string | null;
903
911
  createdByUserId: string | null;
912
+ groupId: string | null;
904
913
  creator: {
905
914
  image: string | null;
906
915
  id: string;
@@ -1194,6 +1203,7 @@ export declare const saveExternal: {
1194
1203
  } | (string | number | boolean | {
1195
1204
  [key: string]: string | number | boolean | /*elided*/ any | /*elided*/ any | null;
1196
1205
  } | /*elided*/ any | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null>>;
1206
+ groupId: z.ZodNullable<z.ZodString>;
1197
1207
  createdByUserId: z.ZodNullable<z.ZodString>;
1198
1208
  createdAt: z.ZodDate;
1199
1209
  }, {
@@ -1313,6 +1323,7 @@ export declare const saveExternal: {
1313
1323
  source: "external" | "community";
1314
1324
  thumbnailUrl: string | null;
1315
1325
  createdByUserId: string | null;
1326
+ groupId: string | null;
1316
1327
  creator: {
1317
1328
  image: string | null;
1318
1329
  id: string;
@@ -1375,6 +1386,7 @@ export declare const saveExternal: {
1375
1386
  source: "external" | "community";
1376
1387
  thumbnailUrl: string | null;
1377
1388
  createdByUserId: string | null;
1389
+ groupId: string | null;
1378
1390
  creator: {
1379
1391
  image: string | null;
1380
1392
  id: string;
@@ -59,6 +59,7 @@ export declare const eventWithRelationsSchema: z.ZodObject<z.objectUtil.extendSh
59
59
  } | (string | number | boolean | {
60
60
  [key: string]: string | number | boolean | /*elided*/ any | /*elided*/ any | null;
61
61
  } | /*elided*/ any | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null)[] | null>>;
62
+ groupId: z.ZodNullable<z.ZodString>;
62
63
  createdByUserId: z.ZodNullable<z.ZodString>;
63
64
  createdAt: z.ZodDate;
64
65
  }, {
@@ -178,6 +179,7 @@ export declare const eventWithRelationsSchema: z.ZodObject<z.objectUtil.extendSh
178
179
  source: "external" | "community";
179
180
  thumbnailUrl: string | null;
180
181
  createdByUserId: string | null;
182
+ groupId: string | null;
181
183
  creator: {
182
184
  image: string | null;
183
185
  id: string;
@@ -240,6 +242,7 @@ export declare const eventWithRelationsSchema: z.ZodObject<z.objectUtil.extendSh
240
242
  source: "external" | "community";
241
243
  thumbnailUrl: string | null;
242
244
  createdByUserId: string | null;
245
+ groupId: string | null;
243
246
  creator: {
244
247
  image: string | null;
245
248
  id: string;
@@ -0,0 +1,7 @@
1
+ import type { AppRouteHandler } from "../../lib/types.js";
2
+ import type { CreateRoute, GetEventsRoute, GetOneRoute, ListRoute, UpdateRoute } from "./groups.routes.js";
3
+ export declare const list: AppRouteHandler<ListRoute>;
4
+ export declare const getOne: AppRouteHandler<GetOneRoute>;
5
+ export declare const getEvents: AppRouteHandler<GetEventsRoute>;
6
+ export declare const create: AppRouteHandler<CreateRoute>;
7
+ export declare const update: AppRouteHandler<UpdateRoute>;
@@ -0,0 +1,205 @@
1
+ import { and, count, eq, gte, ilike, lte, or, sql } from "drizzle-orm";
2
+ import * as HttpStatusCodes from "stoker/http-status-codes";
3
+ import * as HttpStatusPhrases from "stoker/http-status-phrases";
4
+ import { createDb } from "../../db/index.js";
5
+ import { event, group } from "../../db/schema/index.js";
6
+ function slugify(name) {
7
+ return name
8
+ .toLowerCase()
9
+ .replace(/[^\w\s-]/g, "")
10
+ .replace(/[\s_]+/g, "-")
11
+ .replace(/^-+|-+$/g, "")
12
+ .slice(0, 255);
13
+ }
14
+ export const list = async (c) => {
15
+ const { db } = createDb(c.env);
16
+ const query = c.req.valid("query");
17
+ const { sportId, source, search } = query;
18
+ const limit = query.limit ?? 20;
19
+ const offset = query.offset ?? 0;
20
+ const city = query.city?.trim();
21
+ const state = query.state?.trim();
22
+ const whereConditions = [eq(group.isActive, true)];
23
+ if (sportId) {
24
+ whereConditions.push(eq(group.sportId, sportId));
25
+ }
26
+ if (source) {
27
+ whereConditions.push(eq(group.source, source));
28
+ }
29
+ if (city) {
30
+ whereConditions.push(ilike(group.city, city));
31
+ }
32
+ if (state) {
33
+ whereConditions.push(ilike(group.state, state));
34
+ }
35
+ if (search) {
36
+ whereConditions.push(or(ilike(group.name, `%${search}%`), ilike(group.description, `%${search}%`)));
37
+ }
38
+ const groups = await db.query.group.findMany({
39
+ where: and(...whereConditions),
40
+ with: {
41
+ sport: true,
42
+ creator: {
43
+ columns: {
44
+ id: true,
45
+ name: true,
46
+ image: true,
47
+ },
48
+ },
49
+ },
50
+ limit,
51
+ offset,
52
+ orderBy: (group, { asc }) => [asc(group.name)],
53
+ });
54
+ // Count events per group
55
+ const groupIds = groups.map(g => g.id);
56
+ let eventCounts = {};
57
+ if (groupIds.length > 0) {
58
+ const counts = await db
59
+ .select({
60
+ groupId: event.groupId,
61
+ count: count(),
62
+ })
63
+ .from(event)
64
+ .where(and(sql `${event.groupId} IN ${groupIds}`, gte(event.startsAt, new Date())))
65
+ .groupBy(event.groupId);
66
+ eventCounts = Object.fromEntries(counts.map(r => [r.groupId, r.count]));
67
+ }
68
+ const result = groups.map(g => ({
69
+ ...g,
70
+ _count: { events: eventCounts[g.id] ?? 0 },
71
+ }));
72
+ return c.json(result, HttpStatusCodes.OK);
73
+ };
74
+ export const getOne = async (c) => {
75
+ const { db } = createDb(c.env);
76
+ const { id } = c.req.valid("param");
77
+ const foundGroup = await db.query.group.findFirst({
78
+ where: eq(group.id, id),
79
+ with: {
80
+ sport: true,
81
+ creator: {
82
+ columns: {
83
+ id: true,
84
+ name: true,
85
+ image: true,
86
+ },
87
+ },
88
+ },
89
+ });
90
+ if (!foundGroup) {
91
+ return c.json({ message: HttpStatusPhrases.NOT_FOUND }, HttpStatusCodes.NOT_FOUND);
92
+ }
93
+ return c.json(foundGroup, HttpStatusCodes.OK);
94
+ };
95
+ export const getEvents = async (c) => {
96
+ const { db } = createDb(c.env);
97
+ const { id } = c.req.valid("param");
98
+ const query = c.req.valid("query");
99
+ const foundGroup = await db.query.group.findFirst({
100
+ where: eq(group.id, id),
101
+ columns: { id: true },
102
+ });
103
+ if (!foundGroup) {
104
+ return c.json({ message: HttpStatusPhrases.NOT_FOUND }, HttpStatusCodes.NOT_FOUND);
105
+ }
106
+ const limit = query.limit ?? 20;
107
+ const offset = query.offset ?? 0;
108
+ const whereConditions = [eq(event.groupId, id)];
109
+ if (query.from) {
110
+ whereConditions.push(gte(event.startsAt, query.from));
111
+ }
112
+ if (query.to) {
113
+ const to = new Date(query.to);
114
+ if (to.getUTCHours() === 0 && to.getUTCMinutes() === 0 && to.getUTCSeconds() === 0) {
115
+ to.setUTCHours(23, 59, 59, 999);
116
+ }
117
+ whereConditions.push(lte(event.startsAt, to));
118
+ }
119
+ const events = await db.query.event.findMany({
120
+ where: and(...whereConditions),
121
+ with: {
122
+ sport: true,
123
+ location: true,
124
+ externalLink: true,
125
+ creator: {
126
+ columns: {
127
+ id: true,
128
+ name: true,
129
+ image: true,
130
+ },
131
+ },
132
+ },
133
+ limit,
134
+ offset,
135
+ orderBy: (event, { asc }) => [asc(event.startsAt)],
136
+ });
137
+ return c.json(events, HttpStatusCodes.OK);
138
+ };
139
+ export const create = async (c) => {
140
+ const { db } = createDb(c.env);
141
+ const body = c.req.valid("json");
142
+ const user = c.get("user");
143
+ const slug = body.slug || slugify(body.name);
144
+ const [newGroup] = await db.insert(group).values({
145
+ name: body.name,
146
+ slug,
147
+ description: body.description,
148
+ source: "internal",
149
+ sportId: body.sportId,
150
+ city: body.city,
151
+ state: body.state,
152
+ imageUrl: body.imageUrl,
153
+ createdByUserId: user.id,
154
+ }).returning();
155
+ const result = await db.query.group.findFirst({
156
+ where: eq(group.id, newGroup.id),
157
+ with: {
158
+ sport: true,
159
+ creator: {
160
+ columns: {
161
+ id: true,
162
+ name: true,
163
+ image: true,
164
+ },
165
+ },
166
+ },
167
+ });
168
+ return c.json(result, HttpStatusCodes.OK);
169
+ };
170
+ export const update = async (c) => {
171
+ const { db } = createDb(c.env);
172
+ const { id } = c.req.valid("param");
173
+ const body = c.req.valid("json");
174
+ const user = c.get("user");
175
+ const existing = await db.query.group.findFirst({
176
+ where: eq(group.id, id),
177
+ });
178
+ if (!existing) {
179
+ return c.json({ message: HttpStatusPhrases.NOT_FOUND }, HttpStatusCodes.NOT_FOUND);
180
+ }
181
+ if (existing.source === "external") {
182
+ return c.json({ message: "Cannot update external groups" }, HttpStatusCodes.UNAUTHORIZED);
183
+ }
184
+ if (existing.createdByUserId !== user.id) {
185
+ return c.json({ message: HttpStatusPhrases.UNAUTHORIZED }, HttpStatusCodes.UNAUTHORIZED);
186
+ }
187
+ await db.update(group).set({
188
+ ...body,
189
+ updatedAt: new Date(),
190
+ }).where(eq(group.id, id));
191
+ const result = await db.query.group.findFirst({
192
+ where: eq(group.id, id),
193
+ with: {
194
+ sport: true,
195
+ creator: {
196
+ columns: {
197
+ id: true,
198
+ name: true,
199
+ image: true,
200
+ },
201
+ },
202
+ },
203
+ });
204
+ return c.json(result, HttpStatusCodes.OK);
205
+ };
@@ -0,0 +1,337 @@
1
+ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shared/index.js").AppBindings, {
2
+ "/groups": {
3
+ $get: {
4
+ input: {
5
+ query: {
6
+ search?: string | string[] | undefined;
7
+ city?: string | string[] | undefined;
8
+ state?: string | string[] | undefined;
9
+ sportId?: string | string[] | undefined;
10
+ source?: string | string[] | undefined;
11
+ limit?: string | string[] | undefined;
12
+ offset?: string | string[] | undefined;
13
+ };
14
+ };
15
+ output: {
16
+ id: string;
17
+ description: string | null;
18
+ name: string;
19
+ city: string | null;
20
+ state: string | null;
21
+ sportId: string;
22
+ createdAt: string;
23
+ sport: {
24
+ id: string;
25
+ name: string;
26
+ icon: string | null;
27
+ } | null;
28
+ country: string;
29
+ source: "external" | "internal";
30
+ slug: string;
31
+ isActive: boolean;
32
+ sourceOrgId: string | null;
33
+ externalUrl: string | null;
34
+ updatedAt: string;
35
+ createdByUserId: string | null;
36
+ imageUrl: string | null;
37
+ creator: {
38
+ image: string | null;
39
+ id: string;
40
+ name: string;
41
+ } | null;
42
+ _count?: {
43
+ events: number;
44
+ } | undefined;
45
+ }[];
46
+ outputFormat: "text" | "json";
47
+ status: 200;
48
+ };
49
+ };
50
+ } & {
51
+ "/groups/:id": {
52
+ $get: {
53
+ input: {
54
+ param: {
55
+ id: string;
56
+ };
57
+ };
58
+ output: {
59
+ message: string;
60
+ };
61
+ outputFormat: "text" | "json";
62
+ status: 404;
63
+ } | {
64
+ input: {
65
+ param: {
66
+ id: string;
67
+ };
68
+ };
69
+ output: {
70
+ id: string;
71
+ description: string | null;
72
+ name: string;
73
+ city: string | null;
74
+ state: string | null;
75
+ sportId: string;
76
+ createdAt: string;
77
+ sport: {
78
+ id: string;
79
+ name: string;
80
+ icon: string | null;
81
+ } | null;
82
+ country: string;
83
+ source: "external" | "internal";
84
+ slug: string;
85
+ isActive: boolean;
86
+ sourceOrgId: string | null;
87
+ externalUrl: string | null;
88
+ updatedAt: string;
89
+ createdByUserId: string | null;
90
+ imageUrl: string | null;
91
+ creator: {
92
+ image: string | null;
93
+ id: string;
94
+ name: string;
95
+ } | null;
96
+ _count?: {
97
+ events: number;
98
+ } | undefined;
99
+ };
100
+ outputFormat: "text" | "json";
101
+ status: 200;
102
+ };
103
+ };
104
+ } & {
105
+ "/groups/:id/events": {
106
+ $get: {
107
+ input: {
108
+ param: {
109
+ id: string;
110
+ };
111
+ } & {
112
+ query: {
113
+ from?: string | string[] | undefined;
114
+ to?: string | string[] | undefined;
115
+ limit?: string | string[] | undefined;
116
+ offset?: string | string[] | undefined;
117
+ };
118
+ };
119
+ output: {
120
+ metadata: any;
121
+ id: string;
122
+ title: string;
123
+ sportId: string;
124
+ createdAt: string;
125
+ sport: {
126
+ id: string;
127
+ name: string;
128
+ icon: string | null;
129
+ } | null;
130
+ startsAt: string;
131
+ endsAt: string | null;
132
+ timezone: string;
133
+ location: {
134
+ id: string;
135
+ name: string;
136
+ city: string | null;
137
+ state: string | null;
138
+ formattedAddress: string;
139
+ latitude: number | null;
140
+ longitude: number | null;
141
+ } | null;
142
+ locationId: string | null;
143
+ externalLinkId: string | null;
144
+ source: "external" | "community";
145
+ thumbnailUrl: string | null;
146
+ createdByUserId: string | null;
147
+ groupId: string | null;
148
+ creator: {
149
+ image: string | null;
150
+ id: string;
151
+ name: string;
152
+ } | null;
153
+ externalLink: {
154
+ url: string;
155
+ id: string;
156
+ domain: string;
157
+ } | null;
158
+ }[];
159
+ outputFormat: "text" | "json";
160
+ status: 200;
161
+ } | {
162
+ input: {
163
+ param: {
164
+ id: string;
165
+ };
166
+ } & {
167
+ query: {
168
+ from?: string | string[] | undefined;
169
+ to?: string | string[] | undefined;
170
+ limit?: string | string[] | undefined;
171
+ offset?: string | string[] | undefined;
172
+ };
173
+ };
174
+ output: {
175
+ message: string;
176
+ };
177
+ outputFormat: "text" | "json";
178
+ status: 404;
179
+ };
180
+ };
181
+ } & {
182
+ "/groups": {
183
+ $post: {
184
+ input: {
185
+ json: {
186
+ name: string;
187
+ sportId: string;
188
+ description?: string | undefined;
189
+ city?: string | undefined;
190
+ state?: string | undefined;
191
+ slug?: string | undefined;
192
+ imageUrl?: string | undefined;
193
+ };
194
+ };
195
+ output: {
196
+ message: string;
197
+ };
198
+ outputFormat: "text" | "json";
199
+ status: 401;
200
+ } | {
201
+ input: {
202
+ json: {
203
+ name: string;
204
+ sportId: string;
205
+ description?: string | undefined;
206
+ city?: string | undefined;
207
+ state?: string | undefined;
208
+ slug?: string | undefined;
209
+ imageUrl?: string | undefined;
210
+ };
211
+ };
212
+ output: {
213
+ id: string;
214
+ description: string | null;
215
+ name: string;
216
+ city: string | null;
217
+ state: string | null;
218
+ sportId: string;
219
+ createdAt: string;
220
+ sport: {
221
+ id: string;
222
+ name: string;
223
+ icon: string | null;
224
+ } | null;
225
+ country: string;
226
+ source: "external" | "internal";
227
+ slug: string;
228
+ isActive: boolean;
229
+ sourceOrgId: string | null;
230
+ externalUrl: string | null;
231
+ updatedAt: string;
232
+ createdByUserId: string | null;
233
+ imageUrl: string | null;
234
+ creator: {
235
+ image: string | null;
236
+ id: string;
237
+ name: string;
238
+ } | null;
239
+ _count?: {
240
+ events: number;
241
+ } | undefined;
242
+ };
243
+ outputFormat: "text" | "json";
244
+ status: 200;
245
+ };
246
+ };
247
+ } & {
248
+ "/groups/:id": {
249
+ $patch: {
250
+ input: {
251
+ param: {
252
+ id: string;
253
+ };
254
+ } & {
255
+ json: {
256
+ description?: string | undefined;
257
+ name?: string | undefined;
258
+ city?: string | undefined;
259
+ state?: string | undefined;
260
+ imageUrl?: string | null | undefined;
261
+ };
262
+ };
263
+ output: {
264
+ message: string;
265
+ };
266
+ outputFormat: "text" | "json";
267
+ status: 404;
268
+ } | {
269
+ input: {
270
+ param: {
271
+ id: string;
272
+ };
273
+ } & {
274
+ json: {
275
+ description?: string | undefined;
276
+ name?: string | undefined;
277
+ city?: string | undefined;
278
+ state?: string | undefined;
279
+ imageUrl?: string | null | undefined;
280
+ };
281
+ };
282
+ output: {
283
+ message: string;
284
+ };
285
+ outputFormat: "text" | "json";
286
+ status: 401;
287
+ } | {
288
+ input: {
289
+ param: {
290
+ id: string;
291
+ };
292
+ } & {
293
+ json: {
294
+ description?: string | undefined;
295
+ name?: string | undefined;
296
+ city?: string | undefined;
297
+ state?: string | undefined;
298
+ imageUrl?: string | null | undefined;
299
+ };
300
+ };
301
+ output: {
302
+ id: string;
303
+ description: string | null;
304
+ name: string;
305
+ city: string | null;
306
+ state: string | null;
307
+ sportId: string;
308
+ createdAt: string;
309
+ sport: {
310
+ id: string;
311
+ name: string;
312
+ icon: string | null;
313
+ } | null;
314
+ country: string;
315
+ source: "external" | "internal";
316
+ slug: string;
317
+ isActive: boolean;
318
+ sourceOrgId: string | null;
319
+ externalUrl: string | null;
320
+ updatedAt: string;
321
+ createdByUserId: string | null;
322
+ imageUrl: string | null;
323
+ creator: {
324
+ image: string | null;
325
+ id: string;
326
+ name: string;
327
+ } | null;
328
+ _count?: {
329
+ events: number;
330
+ } | undefined;
331
+ };
332
+ outputFormat: "text" | "json";
333
+ status: 200;
334
+ };
335
+ };
336
+ }, "/">;
337
+ export default router;