@lcas58/esmi-api-types 1.0.28 → 1.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/routes/events/events.handlers.d.ts +1 -1
- package/dist/src/routes/events/events.handlers.js +5 -5
- package/dist/src/routes/events/events.index.d.ts +23 -19
- package/dist/src/routes/events/events.routes.d.ts +51 -39
- package/dist/src/routes/events/schemas/event.schemas.d.ts +11 -8
- package/dist/src/routes/groups/groups.handlers.js +53 -12
- package/dist/src/routes/groups/groups.index.d.ts +73 -28
- package/dist/src/routes/groups/groups.routes.d.ts +210 -67
- package/dist/src/routes/groups/schemas/group.schemas.d.ts +82 -19
- package/dist/src/routes/groups/schemas/group.schemas.js +20 -1
- package/dist/src/routes/groups/schemas/index.d.ts +1 -1
- package/dist/src/routes/groups/schemas/index.js +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,28 @@
|
|
|
1
|
-
import { and, count, eq, gte, ilike, lte, or, sql } from "drizzle-orm";
|
|
1
|
+
import { and, count, eq, gte, ilike, inArray, lte, or, sql } from "drizzle-orm";
|
|
2
2
|
import * as HttpStatusCodes from "stoker/http-status-codes";
|
|
3
3
|
import * as HttpStatusPhrases from "stoker/http-status-phrases";
|
|
4
4
|
import { createDb } from "../../db/index.js";
|
|
5
|
-
import { event, group } from "../../db/schema/index.js";
|
|
5
|
+
import { event, group, groupTag, tag } from "../../db/schema/index.js";
|
|
6
|
+
function withTags(g) {
|
|
7
|
+
const { groupTags, ...rest } = g;
|
|
8
|
+
return { ...rest, tags: groupTags.map(gt => ({ id: gt.tag.id, name: gt.tag.name })) };
|
|
9
|
+
}
|
|
10
|
+
async function upsertTags(db, groupId, tagNames) {
|
|
11
|
+
if (tagNames.length === 0) {
|
|
12
|
+
await db.delete(groupTag).where(eq(groupTag.groupId, groupId));
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const slugs = tagNames.map(n => slugify(n));
|
|
16
|
+
await db.insert(tag)
|
|
17
|
+
.values(tagNames.map((name, i) => ({ name, slug: slugs[i] })))
|
|
18
|
+
.onConflictDoNothing({ target: tag.slug });
|
|
19
|
+
const tagRecords = await db.select({ id: tag.id, slug: tag.slug })
|
|
20
|
+
.from(tag)
|
|
21
|
+
.where(inArray(tag.slug, slugs));
|
|
22
|
+
await db.delete(groupTag).where(eq(groupTag.groupId, groupId));
|
|
23
|
+
await db.insert(groupTag)
|
|
24
|
+
.values(tagRecords.map(t => ({ groupId, tagId: t.id })));
|
|
25
|
+
}
|
|
6
26
|
function slugify(name) {
|
|
7
27
|
return name
|
|
8
28
|
.toLowerCase()
|
|
@@ -14,7 +34,7 @@ function slugify(name) {
|
|
|
14
34
|
export const list = async (c) => {
|
|
15
35
|
const { db } = createDb(c.env);
|
|
16
36
|
const query = c.req.valid("query");
|
|
17
|
-
const { sportId,
|
|
37
|
+
const { sportId, platform, search } = query;
|
|
18
38
|
const limit = query.limit ?? 20;
|
|
19
39
|
const offset = query.offset ?? 0;
|
|
20
40
|
const city = query.city?.trim();
|
|
@@ -23,8 +43,8 @@ export const list = async (c) => {
|
|
|
23
43
|
if (sportId) {
|
|
24
44
|
whereConditions.push(eq(group.sportId, sportId));
|
|
25
45
|
}
|
|
26
|
-
if (
|
|
27
|
-
whereConditions.push(eq(group.
|
|
46
|
+
if (platform) {
|
|
47
|
+
whereConditions.push(eq(group.platform, platform));
|
|
28
48
|
}
|
|
29
49
|
if (city) {
|
|
30
50
|
whereConditions.push(ilike(group.city, city));
|
|
@@ -46,6 +66,9 @@ export const list = async (c) => {
|
|
|
46
66
|
image: true,
|
|
47
67
|
},
|
|
48
68
|
},
|
|
69
|
+
groupTags: {
|
|
70
|
+
with: { tag: true },
|
|
71
|
+
},
|
|
49
72
|
},
|
|
50
73
|
limit,
|
|
51
74
|
offset,
|
|
@@ -66,7 +89,7 @@ export const list = async (c) => {
|
|
|
66
89
|
eventCounts = Object.fromEntries(counts.map(r => [r.groupId, r.count]));
|
|
67
90
|
}
|
|
68
91
|
const result = groups.map(g => ({
|
|
69
|
-
...g,
|
|
92
|
+
...withTags(g),
|
|
70
93
|
_count: { events: eventCounts[g.id] ?? 0 },
|
|
71
94
|
}));
|
|
72
95
|
return c.json(result, HttpStatusCodes.OK);
|
|
@@ -85,12 +108,15 @@ export const getOne = async (c) => {
|
|
|
85
108
|
image: true,
|
|
86
109
|
},
|
|
87
110
|
},
|
|
111
|
+
groupTags: {
|
|
112
|
+
with: { tag: true },
|
|
113
|
+
},
|
|
88
114
|
},
|
|
89
115
|
});
|
|
90
116
|
if (!foundGroup) {
|
|
91
117
|
return c.json({ message: HttpStatusPhrases.NOT_FOUND }, HttpStatusCodes.NOT_FOUND);
|
|
92
118
|
}
|
|
93
|
-
return c.json(foundGroup, HttpStatusCodes.OK);
|
|
119
|
+
return c.json(withTags(foundGroup), HttpStatusCodes.OK);
|
|
94
120
|
};
|
|
95
121
|
export const getEvents = async (c) => {
|
|
96
122
|
const { db } = createDb(c.env);
|
|
@@ -145,13 +171,18 @@ export const create = async (c) => {
|
|
|
145
171
|
name: body.name,
|
|
146
172
|
slug,
|
|
147
173
|
description: body.description,
|
|
148
|
-
source: "internal",
|
|
149
174
|
sportId: body.sportId,
|
|
150
175
|
city: body.city,
|
|
151
176
|
state: body.state,
|
|
152
177
|
imageUrl: body.imageUrl,
|
|
178
|
+
skillLevel: body.skillLevel,
|
|
179
|
+
vibe: body.vibe,
|
|
180
|
+
activityFrequency: body.activityFrequency,
|
|
153
181
|
createdByUserId: user.id,
|
|
154
182
|
}).returning();
|
|
183
|
+
if (body.tags?.length) {
|
|
184
|
+
await upsertTags(db, newGroup.id, body.tags);
|
|
185
|
+
}
|
|
155
186
|
const result = await db.query.group.findFirst({
|
|
156
187
|
where: eq(group.id, newGroup.id),
|
|
157
188
|
with: {
|
|
@@ -163,9 +194,12 @@ export const create = async (c) => {
|
|
|
163
194
|
image: true,
|
|
164
195
|
},
|
|
165
196
|
},
|
|
197
|
+
groupTags: {
|
|
198
|
+
with: { tag: true },
|
|
199
|
+
},
|
|
166
200
|
},
|
|
167
201
|
});
|
|
168
|
-
return c.json(result, HttpStatusCodes.OK);
|
|
202
|
+
return c.json(withTags(result), HttpStatusCodes.OK);
|
|
169
203
|
};
|
|
170
204
|
export const update = async (c) => {
|
|
171
205
|
const { db } = createDb(c.env);
|
|
@@ -178,16 +212,20 @@ export const update = async (c) => {
|
|
|
178
212
|
if (!existing) {
|
|
179
213
|
return c.json({ message: HttpStatusPhrases.NOT_FOUND }, HttpStatusCodes.NOT_FOUND);
|
|
180
214
|
}
|
|
181
|
-
if (existing.
|
|
215
|
+
if (existing.platform) {
|
|
182
216
|
return c.json({ message: "Cannot update external groups" }, HttpStatusCodes.UNAUTHORIZED);
|
|
183
217
|
}
|
|
184
218
|
if (existing.createdByUserId !== user.id) {
|
|
185
219
|
return c.json({ message: HttpStatusPhrases.UNAUTHORIZED }, HttpStatusCodes.UNAUTHORIZED);
|
|
186
220
|
}
|
|
221
|
+
const { tags: tagNames, ...groupFields } = body;
|
|
187
222
|
await db.update(group).set({
|
|
188
|
-
...
|
|
223
|
+
...groupFields,
|
|
189
224
|
updatedAt: new Date(),
|
|
190
225
|
}).where(eq(group.id, id));
|
|
226
|
+
if (tagNames !== undefined) {
|
|
227
|
+
await upsertTags(db, id, tagNames ?? []);
|
|
228
|
+
}
|
|
191
229
|
const result = await db.query.group.findFirst({
|
|
192
230
|
where: eq(group.id, id),
|
|
193
231
|
with: {
|
|
@@ -199,7 +237,10 @@ export const update = async (c) => {
|
|
|
199
237
|
image: true,
|
|
200
238
|
},
|
|
201
239
|
},
|
|
240
|
+
groupTags: {
|
|
241
|
+
with: { tag: true },
|
|
242
|
+
},
|
|
202
243
|
},
|
|
203
244
|
});
|
|
204
|
-
return c.json(result, HttpStatusCodes.OK);
|
|
245
|
+
return c.json(withTags(result), HttpStatusCodes.OK);
|
|
205
246
|
};
|
|
@@ -4,10 +4,10 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
|
|
|
4
4
|
input: {
|
|
5
5
|
query: {
|
|
6
6
|
search?: string | string[] | undefined;
|
|
7
|
+
sportId?: string | string[] | undefined;
|
|
7
8
|
city?: string | string[] | undefined;
|
|
8
9
|
state?: string | string[] | undefined;
|
|
9
|
-
|
|
10
|
-
source?: string | string[] | undefined;
|
|
10
|
+
platform?: string | string[] | undefined;
|
|
11
11
|
limit?: string | string[] | undefined;
|
|
12
12
|
offset?: string | string[] | undefined;
|
|
13
13
|
};
|
|
@@ -16,29 +16,35 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
|
|
|
16
16
|
id: string;
|
|
17
17
|
description: string | null;
|
|
18
18
|
name: string;
|
|
19
|
-
city: string | null;
|
|
20
|
-
state: string | null;
|
|
21
|
-
sportId: string;
|
|
22
19
|
createdAt: string;
|
|
23
20
|
sport: {
|
|
24
21
|
id: string;
|
|
25
22
|
name: string;
|
|
26
23
|
icon: string | null;
|
|
27
24
|
} | null;
|
|
25
|
+
sportId: string;
|
|
26
|
+
city: string | null;
|
|
27
|
+
state: string | null;
|
|
28
28
|
country: string;
|
|
29
|
-
source: "external" | "internal";
|
|
30
29
|
slug: string;
|
|
31
|
-
|
|
32
|
-
sourceOrgId: string | null;
|
|
30
|
+
platform: string | null;
|
|
33
31
|
externalUrl: string | null;
|
|
34
32
|
updatedAt: string;
|
|
35
33
|
createdByUserId: string | null;
|
|
36
34
|
imageUrl: string | null;
|
|
35
|
+
skillLevel: "advanced" | "beginner" | "intermediate" | "all-levels" | null;
|
|
36
|
+
vibe: "social" | "casual" | "competitive" | "fitness" | null;
|
|
37
|
+
activityFrequency: "weekly" | "biweekly" | "monthly" | "sporadic" | null;
|
|
38
|
+
isActive: boolean;
|
|
37
39
|
creator: {
|
|
38
40
|
image: string | null;
|
|
39
41
|
id: string;
|
|
40
42
|
name: string;
|
|
41
43
|
} | null;
|
|
44
|
+
tags: {
|
|
45
|
+
id: string;
|
|
46
|
+
name: string;
|
|
47
|
+
}[];
|
|
42
48
|
_count?: {
|
|
43
49
|
events: number;
|
|
44
50
|
} | undefined;
|
|
@@ -70,29 +76,35 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
|
|
|
70
76
|
id: string;
|
|
71
77
|
description: string | null;
|
|
72
78
|
name: string;
|
|
73
|
-
city: string | null;
|
|
74
|
-
state: string | null;
|
|
75
|
-
sportId: string;
|
|
76
79
|
createdAt: string;
|
|
77
80
|
sport: {
|
|
78
81
|
id: string;
|
|
79
82
|
name: string;
|
|
80
83
|
icon: string | null;
|
|
81
84
|
} | null;
|
|
85
|
+
sportId: string;
|
|
86
|
+
city: string | null;
|
|
87
|
+
state: string | null;
|
|
82
88
|
country: string;
|
|
83
|
-
source: "external" | "internal";
|
|
84
89
|
slug: string;
|
|
85
|
-
|
|
86
|
-
sourceOrgId: string | null;
|
|
90
|
+
platform: string | null;
|
|
87
91
|
externalUrl: string | null;
|
|
88
92
|
updatedAt: string;
|
|
89
93
|
createdByUserId: string | null;
|
|
90
94
|
imageUrl: string | null;
|
|
95
|
+
skillLevel: "advanced" | "beginner" | "intermediate" | "all-levels" | null;
|
|
96
|
+
vibe: "social" | "casual" | "competitive" | "fitness" | null;
|
|
97
|
+
activityFrequency: "weekly" | "biweekly" | "monthly" | "sporadic" | null;
|
|
98
|
+
isActive: boolean;
|
|
91
99
|
creator: {
|
|
92
100
|
image: string | null;
|
|
93
101
|
id: string;
|
|
94
102
|
name: string;
|
|
95
103
|
} | null;
|
|
104
|
+
tags: {
|
|
105
|
+
id: string;
|
|
106
|
+
name: string;
|
|
107
|
+
}[];
|
|
96
108
|
_count?: {
|
|
97
109
|
events: number;
|
|
98
110
|
} | undefined;
|
|
@@ -119,23 +131,24 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
|
|
|
119
131
|
output: {
|
|
120
132
|
metadata: any;
|
|
121
133
|
id: string;
|
|
134
|
+
description: string | null;
|
|
122
135
|
title: string;
|
|
123
|
-
sportId: string;
|
|
124
136
|
createdAt: string;
|
|
125
137
|
sport: {
|
|
126
138
|
id: string;
|
|
127
139
|
name: string;
|
|
128
140
|
icon: string | null;
|
|
129
141
|
} | null;
|
|
142
|
+
sportId: string;
|
|
130
143
|
startsAt: string;
|
|
131
144
|
endsAt: string | null;
|
|
132
145
|
timezone: string;
|
|
133
146
|
location: {
|
|
134
147
|
id: string;
|
|
135
148
|
name: string;
|
|
149
|
+
formattedAddress: string;
|
|
136
150
|
city: string | null;
|
|
137
151
|
state: string | null;
|
|
138
|
-
formattedAddress: string;
|
|
139
152
|
latitude: number | null;
|
|
140
153
|
longitude: number | null;
|
|
141
154
|
} | null;
|
|
@@ -190,6 +203,10 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
|
|
|
190
203
|
state?: string | undefined;
|
|
191
204
|
slug?: string | undefined;
|
|
192
205
|
imageUrl?: string | undefined;
|
|
206
|
+
skillLevel?: "advanced" | "beginner" | "intermediate" | "all-levels" | undefined;
|
|
207
|
+
vibe?: "social" | "casual" | "competitive" | "fitness" | undefined;
|
|
208
|
+
activityFrequency?: "weekly" | "biweekly" | "monthly" | "sporadic" | undefined;
|
|
209
|
+
tags?: string[] | undefined;
|
|
193
210
|
};
|
|
194
211
|
};
|
|
195
212
|
output: {
|
|
@@ -207,35 +224,45 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
|
|
|
207
224
|
state?: string | undefined;
|
|
208
225
|
slug?: string | undefined;
|
|
209
226
|
imageUrl?: string | undefined;
|
|
227
|
+
skillLevel?: "advanced" | "beginner" | "intermediate" | "all-levels" | undefined;
|
|
228
|
+
vibe?: "social" | "casual" | "competitive" | "fitness" | undefined;
|
|
229
|
+
activityFrequency?: "weekly" | "biweekly" | "monthly" | "sporadic" | undefined;
|
|
230
|
+
tags?: string[] | undefined;
|
|
210
231
|
};
|
|
211
232
|
};
|
|
212
233
|
output: {
|
|
213
234
|
id: string;
|
|
214
235
|
description: string | null;
|
|
215
236
|
name: string;
|
|
216
|
-
city: string | null;
|
|
217
|
-
state: string | null;
|
|
218
|
-
sportId: string;
|
|
219
237
|
createdAt: string;
|
|
220
238
|
sport: {
|
|
221
239
|
id: string;
|
|
222
240
|
name: string;
|
|
223
241
|
icon: string | null;
|
|
224
242
|
} | null;
|
|
243
|
+
sportId: string;
|
|
244
|
+
city: string | null;
|
|
245
|
+
state: string | null;
|
|
225
246
|
country: string;
|
|
226
|
-
source: "external" | "internal";
|
|
227
247
|
slug: string;
|
|
228
|
-
|
|
229
|
-
sourceOrgId: string | null;
|
|
248
|
+
platform: string | null;
|
|
230
249
|
externalUrl: string | null;
|
|
231
250
|
updatedAt: string;
|
|
232
251
|
createdByUserId: string | null;
|
|
233
252
|
imageUrl: string | null;
|
|
253
|
+
skillLevel: "advanced" | "beginner" | "intermediate" | "all-levels" | null;
|
|
254
|
+
vibe: "social" | "casual" | "competitive" | "fitness" | null;
|
|
255
|
+
activityFrequency: "weekly" | "biweekly" | "monthly" | "sporadic" | null;
|
|
256
|
+
isActive: boolean;
|
|
234
257
|
creator: {
|
|
235
258
|
image: string | null;
|
|
236
259
|
id: string;
|
|
237
260
|
name: string;
|
|
238
261
|
} | null;
|
|
262
|
+
tags: {
|
|
263
|
+
id: string;
|
|
264
|
+
name: string;
|
|
265
|
+
}[];
|
|
239
266
|
_count?: {
|
|
240
267
|
events: number;
|
|
241
268
|
} | undefined;
|
|
@@ -258,6 +285,10 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
|
|
|
258
285
|
city?: string | undefined;
|
|
259
286
|
state?: string | undefined;
|
|
260
287
|
imageUrl?: string | null | undefined;
|
|
288
|
+
skillLevel?: "advanced" | "beginner" | "intermediate" | "all-levels" | null | undefined;
|
|
289
|
+
vibe?: "social" | "casual" | "competitive" | "fitness" | null | undefined;
|
|
290
|
+
activityFrequency?: "weekly" | "biweekly" | "monthly" | "sporadic" | null | undefined;
|
|
291
|
+
tags?: string[] | null | undefined;
|
|
261
292
|
};
|
|
262
293
|
};
|
|
263
294
|
output: {
|
|
@@ -277,6 +308,10 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
|
|
|
277
308
|
city?: string | undefined;
|
|
278
309
|
state?: string | undefined;
|
|
279
310
|
imageUrl?: string | null | undefined;
|
|
311
|
+
skillLevel?: "advanced" | "beginner" | "intermediate" | "all-levels" | null | undefined;
|
|
312
|
+
vibe?: "social" | "casual" | "competitive" | "fitness" | null | undefined;
|
|
313
|
+
activityFrequency?: "weekly" | "biweekly" | "monthly" | "sporadic" | null | undefined;
|
|
314
|
+
tags?: string[] | null | undefined;
|
|
280
315
|
};
|
|
281
316
|
};
|
|
282
317
|
output: {
|
|
@@ -296,35 +331,45 @@ declare const router: import("@hono/zod-openapi").OpenAPIHono<import("../../shar
|
|
|
296
331
|
city?: string | undefined;
|
|
297
332
|
state?: string | undefined;
|
|
298
333
|
imageUrl?: string | null | undefined;
|
|
334
|
+
skillLevel?: "advanced" | "beginner" | "intermediate" | "all-levels" | null | undefined;
|
|
335
|
+
vibe?: "social" | "casual" | "competitive" | "fitness" | null | undefined;
|
|
336
|
+
activityFrequency?: "weekly" | "biweekly" | "monthly" | "sporadic" | null | undefined;
|
|
337
|
+
tags?: string[] | null | undefined;
|
|
299
338
|
};
|
|
300
339
|
};
|
|
301
340
|
output: {
|
|
302
341
|
id: string;
|
|
303
342
|
description: string | null;
|
|
304
343
|
name: string;
|
|
305
|
-
city: string | null;
|
|
306
|
-
state: string | null;
|
|
307
|
-
sportId: string;
|
|
308
344
|
createdAt: string;
|
|
309
345
|
sport: {
|
|
310
346
|
id: string;
|
|
311
347
|
name: string;
|
|
312
348
|
icon: string | null;
|
|
313
349
|
} | null;
|
|
350
|
+
sportId: string;
|
|
351
|
+
city: string | null;
|
|
352
|
+
state: string | null;
|
|
314
353
|
country: string;
|
|
315
|
-
source: "external" | "internal";
|
|
316
354
|
slug: string;
|
|
317
|
-
|
|
318
|
-
sourceOrgId: string | null;
|
|
355
|
+
platform: string | null;
|
|
319
356
|
externalUrl: string | null;
|
|
320
357
|
updatedAt: string;
|
|
321
358
|
createdByUserId: string | null;
|
|
322
359
|
imageUrl: string | null;
|
|
360
|
+
skillLevel: "advanced" | "beginner" | "intermediate" | "all-levels" | null;
|
|
361
|
+
vibe: "social" | "casual" | "competitive" | "fitness" | null;
|
|
362
|
+
activityFrequency: "weekly" | "biweekly" | "monthly" | "sporadic" | null;
|
|
363
|
+
isActive: boolean;
|
|
323
364
|
creator: {
|
|
324
365
|
image: string | null;
|
|
325
366
|
id: string;
|
|
326
367
|
name: string;
|
|
327
368
|
} | null;
|
|
369
|
+
tags: {
|
|
370
|
+
id: string;
|
|
371
|
+
name: string;
|
|
372
|
+
}[];
|
|
328
373
|
_count?: {
|
|
329
374
|
events: number;
|
|
330
375
|
} | undefined;
|