@lcas58/esmi-api-types 1.0.6 → 1.0.7
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/app.d.ts +1 -1
- package/dist/src/app.js +0 -1
- package/dist/src/routes/events/events.handlers.d.ts +20 -0
- package/dist/src/routes/events/events.handlers.js +177 -0
- package/dist/src/routes/events/events.index.d.ts +501 -0
- package/dist/src/routes/events/events.index.js +9 -0
- package/dist/src/routes/events/events.routes.d.ts +1375 -0
- package/dist/src/routes/events/events.routes.js +72 -0
- package/dist/src/routes/events/schemas/event.schemas.d.ts +896 -0
- package/dist/src/routes/events/schemas/event.schemas.js +49 -0
- package/dist/src/routes/events/schemas/index.d.ts +1 -0
- package/dist/src/routes/events/schemas/index.js +1 -0
- package/dist/src/routes/index.route.d.ts +13 -0
- package/dist/src/routes/index.route.js +19 -0
- package/dist/src/routes/leagues/leagues.handlers.d.ts +3 -0
- package/dist/src/routes/leagues/leagues.handlers.js +49 -0
- package/dist/src/routes/leagues/leagues.index.d.ts +53 -0
- package/dist/src/routes/leagues/leagues.index.js +6 -0
- package/dist/src/routes/leagues/leagues.routes.d.ts +137 -0
- package/dist/src/routes/leagues/leagues.routes.js +47 -0
- package/dist/src/routes/marketing/marketing.handlers.d.ts +4 -0
- package/dist/src/routes/marketing/marketing.handlers.js +20 -0
- package/dist/src/routes/marketing/marketing.index.d.ts +58 -0
- package/dist/src/routes/marketing/marketing.index.js +7 -0
- package/dist/src/routes/marketing/marketing.routes.d.ts +154 -0
- package/dist/src/routes/marketing/marketing.routes.js +27 -0
- package/dist/src/routes/organizations/organizations.handlers.d.ts +74 -0
- package/dist/src/routes/organizations/organizations.handlers.js +485 -0
- package/dist/src/routes/organizations/organizations.index.d.ts +517 -0
- package/dist/src/routes/organizations/organizations.index.js +12 -0
- package/dist/src/routes/organizations/organizations.routes.d.ts +1236 -0
- package/dist/src/routes/organizations/organizations.routes.js +137 -0
- package/dist/src/routes/organizations/tasks.test.d.ts +0 -0
- package/dist/src/routes/organizations/tasks.test.js +181 -0
- package/dist/src/routes/tags/tags.handlers.d.ts +3 -0
- package/dist/src/routes/tags/tags.handlers.js +15 -0
- package/dist/src/routes/tags/tags.index.d.ts +24 -0
- package/dist/src/routes/tags/tags.index.js +6 -0
- package/dist/src/routes/tags/tags.routes.d.ts +68 -0
- package/dist/src/routes/tags/tags.routes.js +25 -0
- package/dist/src/shared/client-types.d.ts +8 -3
- package/dist/src/shared/client-types.js +1 -1
- package/package.json +2 -2
package/dist/src/app.d.ts
CHANGED
package/dist/src/app.js
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AppRouteHandler } from "../../lib/types.js";
|
|
2
|
+
import type { CreateRoute, GetCountStatsRoute, ListRoute, PatchRoute } from "./events.routes.js";
|
|
3
|
+
/**
|
|
4
|
+
* GET /events
|
|
5
|
+
* - Returns a list of events
|
|
6
|
+
*/
|
|
7
|
+
export declare const list: AppRouteHandler<ListRoute>;
|
|
8
|
+
/**
|
|
9
|
+
* POST /events
|
|
10
|
+
* - Idempotently upserts the optional location
|
|
11
|
+
* - Inserts the event in a single transaction
|
|
12
|
+
* - Returns 201 + created entity
|
|
13
|
+
*/
|
|
14
|
+
export declare const create: AppRouteHandler<CreateRoute>;
|
|
15
|
+
/**
|
|
16
|
+
* PATCH /events/{id}
|
|
17
|
+
* - Updates the event
|
|
18
|
+
*/
|
|
19
|
+
export declare const patch: AppRouteHandler<PatchRoute>;
|
|
20
|
+
export declare const getCountStats: AppRouteHandler<GetCountStatsRoute>;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { and, eq, 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 from "../../db/schema/event.js";
|
|
6
|
+
import location from "../../db/schema/location.js";
|
|
7
|
+
import { ZOD_ERROR_CODES, ZOD_ERROR_MESSAGES } from "../../lib/constants.js";
|
|
8
|
+
/**
|
|
9
|
+
* GET /events
|
|
10
|
+
* - Returns a list of events
|
|
11
|
+
*/
|
|
12
|
+
export const list = async (c) => {
|
|
13
|
+
const { db } = createDb(c.env);
|
|
14
|
+
const { type, organizationId, status } = c.req.valid("query");
|
|
15
|
+
// Build where conditions
|
|
16
|
+
const whereConditions = [];
|
|
17
|
+
if (type) {
|
|
18
|
+
whereConditions.push(eq(event.type, type));
|
|
19
|
+
}
|
|
20
|
+
if (status) {
|
|
21
|
+
whereConditions.push(eq(event.status, status));
|
|
22
|
+
}
|
|
23
|
+
if (organizationId) {
|
|
24
|
+
whereConditions.push(eq(event.organizationId, organizationId));
|
|
25
|
+
}
|
|
26
|
+
const events = await db.query.event.findMany({
|
|
27
|
+
where: whereConditions.length > 0 ? and(...whereConditions) : undefined,
|
|
28
|
+
with: {
|
|
29
|
+
creator: true,
|
|
30
|
+
organization: true,
|
|
31
|
+
location: true,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
if (events.length === 0) {
|
|
35
|
+
return c.json({
|
|
36
|
+
message: HttpStatusPhrases.NOT_FOUND,
|
|
37
|
+
}, HttpStatusCodes.NOT_FOUND);
|
|
38
|
+
}
|
|
39
|
+
return c.json(events, HttpStatusCodes.OK);
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* POST /events
|
|
43
|
+
* - Idempotently upserts the optional location
|
|
44
|
+
* - Inserts the event in a single transaction
|
|
45
|
+
* - Returns 201 + created entity
|
|
46
|
+
*/
|
|
47
|
+
export const create = async (c) => {
|
|
48
|
+
const { db } = createDb(c.env);
|
|
49
|
+
const data = c.req.valid("json");
|
|
50
|
+
const user = c.get("user");
|
|
51
|
+
if (!user) {
|
|
52
|
+
return c.json({ message: HttpStatusPhrases.UNAUTHORIZED }, HttpStatusCodes.UNAUTHORIZED);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
// Insert location first (if provided)
|
|
56
|
+
if (data.location) {
|
|
57
|
+
const loc = data.location;
|
|
58
|
+
await db
|
|
59
|
+
.insert(location)
|
|
60
|
+
.values({
|
|
61
|
+
id: loc.id,
|
|
62
|
+
provider: loc.provider,
|
|
63
|
+
name: loc.name,
|
|
64
|
+
formattedAddress: loc.formattedAddress,
|
|
65
|
+
city: loc.city,
|
|
66
|
+
state: loc.state,
|
|
67
|
+
country: loc.country,
|
|
68
|
+
postalCode: loc.postalCode,
|
|
69
|
+
latitude: loc.latitude ? Number.parseFloat(loc.latitude) : null,
|
|
70
|
+
longitude: loc.longitude ? Number.parseFloat(loc.longitude) : null,
|
|
71
|
+
})
|
|
72
|
+
.onConflictDoNothing({ target: location.id });
|
|
73
|
+
}
|
|
74
|
+
// Insert event
|
|
75
|
+
const [createdEvent] = await db
|
|
76
|
+
.insert(event)
|
|
77
|
+
.values({
|
|
78
|
+
name: data.name.trim(),
|
|
79
|
+
description: data.description ?? null,
|
|
80
|
+
locationId: data.location?.id ?? null,
|
|
81
|
+
type: data.type,
|
|
82
|
+
organizationId: data.organizationId,
|
|
83
|
+
creatorId: user.id,
|
|
84
|
+
mode: "ADULT",
|
|
85
|
+
ageGroup: data.ageGroup,
|
|
86
|
+
gender: data.gender,
|
|
87
|
+
status: "WIP",
|
|
88
|
+
})
|
|
89
|
+
.returning();
|
|
90
|
+
const eventWithRelations = await db.query.event.findFirst({
|
|
91
|
+
where: eq(event.id, createdEvent.id),
|
|
92
|
+
with: {
|
|
93
|
+
creator: true,
|
|
94
|
+
organization: true,
|
|
95
|
+
location: true,
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
return c.json(eventWithRelations, HttpStatusCodes.CREATED);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
console.error("Error creating event:", err);
|
|
102
|
+
return c.json({
|
|
103
|
+
success: false,
|
|
104
|
+
error: {
|
|
105
|
+
issues: [
|
|
106
|
+
{
|
|
107
|
+
code: "CREATE_EVENT_FAILED",
|
|
108
|
+
path: [],
|
|
109
|
+
message: err instanceof Error ? err.message : "Failed to create event.",
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
name: "ValidationError",
|
|
113
|
+
},
|
|
114
|
+
}, HttpStatusCodes.UNPROCESSABLE_ENTITY);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* PATCH /events/{id}
|
|
119
|
+
* - Updates the event
|
|
120
|
+
*/
|
|
121
|
+
export const patch = async (c) => {
|
|
122
|
+
const { db } = createDb(c.env);
|
|
123
|
+
const { id } = c.req.valid("param");
|
|
124
|
+
const updates = c.req.valid("json");
|
|
125
|
+
if (Object.keys(updates).length === 0) {
|
|
126
|
+
return c.json({
|
|
127
|
+
success: false,
|
|
128
|
+
error: {
|
|
129
|
+
issues: [
|
|
130
|
+
{
|
|
131
|
+
code: ZOD_ERROR_CODES.INVALID_UPDATES,
|
|
132
|
+
path: [],
|
|
133
|
+
message: ZOD_ERROR_MESSAGES.NO_UPDATES,
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
name: "ZodError",
|
|
137
|
+
},
|
|
138
|
+
}, HttpStatusCodes.UNPROCESSABLE_ENTITY);
|
|
139
|
+
}
|
|
140
|
+
const [updatedEvent] = await db.update(event)
|
|
141
|
+
.set(updates)
|
|
142
|
+
.where(eq(event.id, id))
|
|
143
|
+
.returning();
|
|
144
|
+
if (!updatedEvent) {
|
|
145
|
+
return c.json({
|
|
146
|
+
message: HttpStatusPhrases.NOT_FOUND,
|
|
147
|
+
}, HttpStatusCodes.NOT_FOUND);
|
|
148
|
+
}
|
|
149
|
+
// Fetch the updated event with relations
|
|
150
|
+
const eventWithRelations = await db.query.event.findFirst({
|
|
151
|
+
where: eq(event.id, updatedEvent.id),
|
|
152
|
+
with: {
|
|
153
|
+
creator: true,
|
|
154
|
+
organization: true,
|
|
155
|
+
location: true,
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
return c.json(eventWithRelations, HttpStatusCodes.OK);
|
|
159
|
+
};
|
|
160
|
+
export const getCountStats = async (c) => {
|
|
161
|
+
const { db } = createDb(c.env);
|
|
162
|
+
const { organizationId } = c.req.valid("query");
|
|
163
|
+
// Single optimized query to get all counts at once
|
|
164
|
+
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
|
|
165
|
+
const oneYearAgo = new Date(Date.now() - 360 * 24 * 60 * 60 * 1000);
|
|
166
|
+
const [stats] = await db
|
|
167
|
+
.select({
|
|
168
|
+
total: sql `count(case when ${event.status} in ('IN_PROGRESS', 'PUBLISHED', 'COMPLETED') then 1 end)`,
|
|
169
|
+
thisMonth: sql `count(case when ${event.createdAt} >= ${thirtyDaysAgo} and ${event.status} in ('IN_PROGRESS', 'PUBLISHED', 'COMPLETED') then 1 end)`,
|
|
170
|
+
inProgress: sql `count(case when ${event.status} = 'IN_PROGRESS' then 1 end)`,
|
|
171
|
+
completed: sql `count(case when ${event.status} = 'COMPLETED' and ${event.createdAt} >= ${oneYearAgo} then 1 end)`,
|
|
172
|
+
upcoming: sql `count(case when ${event.status} = 'PUBLISHED' and ${event.createdAt} >= ${thirtyDaysAgo} then 1 end)`,
|
|
173
|
+
})
|
|
174
|
+
.from(event)
|
|
175
|
+
.where(eq(event.organizationId, organizationId));
|
|
176
|
+
return c.json(stats, HttpStatusCodes.OK);
|
|
177
|
+
};
|