@lcas58/esmi-api-types 1.0.3 → 1.0.5

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License Copyright (c) 2024 w3cj
2
+
3
+ Permission is hereby granted, free of
4
+ charge, to any person obtaining a copy of this software and associated
5
+ documentation files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use, copy, modify, merge,
7
+ publish, distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice
12
+ (including the next paragraph) shall be included in all copies or substantial
13
+ portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
18
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md CHANGED
@@ -1,24 +1,136 @@
1
- # ESMI API Types
1
+ ## Esmi API
2
2
 
3
- Shared TypeScript types for ESMI frontend and backend applications.
3
+ Type-safe JSON API built with Hono, OpenAPI, Drizzle ORM, and Better Auth. Runs locally via Cloudflare Wrangler with Node.js compatibility.
4
4
 
5
- ## Installation
5
+ ### Features
6
+
7
+ - **OpenAPI docs**: `@hono/zod-openapi` + Scalar UI
8
+ - **Auth**: Better Auth routes proxied under `/api/auth/*`
9
+ - **Database**: PostgreSQL via Drizzle ORM
10
+ - **Logging**: Pino + `hono-pino`
11
+
12
+ ---
13
+
14
+ ## Quick start
15
+
16
+ ### Prerequisites
17
+
18
+ - Node.js 20+
19
+ - Bun (for `bunx` used by db scripts)
20
+ - Cloudflare Wrangler (`npm i -g wrangler`)
21
+ - A PostgreSQL database (e.g. Neon) and `DATABASE_URL`
22
+
23
+ ### Install
24
+
25
+ ```bash
26
+ npm install
27
+ ```
28
+
29
+ ### Environment
30
+
31
+ Create a `.env` file with:
32
+
33
+ ```bash
34
+ NODE_ENV=development
35
+ LOG_LEVEL=info
36
+ DATABASE_URL=postgres://user:pass@host/db
37
+ # Only required in production when using Neon auth token
38
+ DATABASE_AUTH_TOKEN=
39
+
40
+ BETTER_AUTH_SECRET=replace-me
41
+ BETTER_AUTH_URL=http://localhost:8787
42
+ BETTER_AUTH_TRUSTED_ORIGINS=http://localhost:3000
43
+
44
+ # OAuth (Google) for Better Auth
45
+ AUTH_GOOGLE_ID=
46
+ AUTH_GOOGLE_SECRET=
47
+ ```
48
+
49
+ ### Database
50
+
51
+ Generate and run migrations:
6
52
 
7
53
  ```bash
8
- bun add @lcas58/esmi-api-types
9
- # or
10
- npm install @lcas58/esmi-api-types
54
+ npm run db:generate
55
+ npm run db:migrate
11
56
  ```
12
57
 
13
- ## Usage
58
+ Optional seed:
14
59
 
15
- ```typescript
16
- import type { AppType } from "@lcas58/esmi-api-types";
60
+ ```bash
61
+ npm run db:seed
62
+ ```
63
+
64
+ ### Run locally
17
65
 
18
- // Use AppType in your Hono client
19
- const client = hc<AppType>("/api");
66
+ ```bash
67
+ npm run dev
68
+ # Wrangler serves on http://localhost:8787 by default
20
69
  ```
21
70
 
22
- ## Development
71
+ ### Build & deploy
72
+
73
+ ```bash
74
+ npm run build
75
+ npm run deploy
76
+ ```
77
+
78
+ ---
79
+
80
+ ## API
81
+
82
+ ### Docs
83
+
84
+ - `GET /doc` OpenAPI spec (JSON)
85
+ - `GET /reference` Scalar API UI
86
+
87
+ ### Auth
88
+
89
+ - `GET|POST /api/auth/*` handled by Better Auth
90
+
91
+ ### Index
92
+
93
+ - `GET /` health/info
94
+
95
+ ### Organizations (requires auth)
96
+
97
+ - `GET /organizations/{ownerId}` list organizations for a user
98
+ - `POST /organizations` create organization
99
+ - `PATCH /organizations/{id}` update by id
100
+ - `DELETE /organizations/{id}` delete by id
101
+
102
+ ### Leagues
103
+
104
+ - `GET /leagues/{locationId}` list leagues for a location
105
+
106
+ ### Marketing
107
+
108
+ - `GET /marketing/email` list email signups
109
+ - `POST /marketing/email` create email signup
110
+
111
+ ### Tags
112
+
113
+ - `GET /tags?type={type}` list tags (optional filter by `type`)
114
+
115
+ ---
116
+
117
+ ## Project structure
118
+
119
+ - App bootstrap: `src/app.ts`
120
+ - OpenAPI config & UI: `src/lib/configure-open-api.ts`
121
+ - Routes: `src/routes/**`
122
+ - DB schema: `src/db/schema/**`
123
+ - Drizzle config: `drizzle.config.ts`
124
+
125
+ For the current database model overview, see `DB_SCHEMA.md`.
126
+
127
+ ---
128
+
129
+ ## Scripts
23
130
 
24
- This package is automatically updated when the backend API types change.
131
+ - `dev`: Wrangler dev server
132
+ - `build`: TypeScript build + path aliasing
133
+ - `deploy`: Wrangler deploy
134
+ - `test`: Vitest
135
+ - `lint` / `lint:fix`
136
+ - `db:generate` / `db:migrate` / `db:studio` / `db:seed`
@@ -0,0 +1,264 @@
1
+ declare const event: import("drizzle-orm/pg-core").PgTableWithColumns<{
2
+ name: "event";
3
+ schema: undefined;
4
+ columns: {
5
+ id: import("drizzle-orm/pg-core").PgColumn<{
6
+ name: "id";
7
+ tableName: "event";
8
+ dataType: "string";
9
+ columnType: "PgText";
10
+ data: string;
11
+ driverParam: string;
12
+ notNull: true;
13
+ hasDefault: true;
14
+ isPrimaryKey: true;
15
+ isAutoincrement: false;
16
+ hasRuntimeDefault: true;
17
+ enumValues: [string, ...string[]];
18
+ baseColumn: never;
19
+ generated: undefined;
20
+ }, {}, {}>;
21
+ name: import("drizzle-orm/pg-core").PgColumn<{
22
+ name: "name";
23
+ tableName: "event";
24
+ dataType: "string";
25
+ columnType: "PgVarchar";
26
+ data: string;
27
+ driverParam: string;
28
+ notNull: true;
29
+ hasDefault: false;
30
+ isPrimaryKey: false;
31
+ isAutoincrement: false;
32
+ hasRuntimeDefault: false;
33
+ enumValues: [string, ...string[]];
34
+ baseColumn: never;
35
+ generated: undefined;
36
+ }, {}, {}>;
37
+ description: import("drizzle-orm/pg-core").PgColumn<{
38
+ name: "description";
39
+ tableName: "event";
40
+ dataType: "string";
41
+ columnType: "PgText";
42
+ data: string;
43
+ driverParam: string;
44
+ notNull: false;
45
+ hasDefault: false;
46
+ isPrimaryKey: false;
47
+ isAutoincrement: false;
48
+ hasRuntimeDefault: false;
49
+ enumValues: [string, ...string[]];
50
+ baseColumn: never;
51
+ generated: undefined;
52
+ }, {}, {}>;
53
+ locationId: import("drizzle-orm/pg-core").PgColumn<{
54
+ name: "location_id";
55
+ tableName: "event";
56
+ dataType: "string";
57
+ columnType: "PgVarchar";
58
+ data: string;
59
+ driverParam: string;
60
+ notNull: false;
61
+ hasDefault: false;
62
+ isPrimaryKey: false;
63
+ isAutoincrement: false;
64
+ hasRuntimeDefault: false;
65
+ enumValues: [string, ...string[]];
66
+ baseColumn: never;
67
+ generated: undefined;
68
+ }, {}, {}>;
69
+ type: import("drizzle-orm/pg-core").PgColumn<{
70
+ name: "type";
71
+ tableName: "event";
72
+ dataType: "string";
73
+ columnType: "PgVarchar";
74
+ data: string;
75
+ driverParam: string;
76
+ notNull: true;
77
+ hasDefault: false;
78
+ isPrimaryKey: false;
79
+ isAutoincrement: false;
80
+ hasRuntimeDefault: false;
81
+ enumValues: [string, ...string[]];
82
+ baseColumn: never;
83
+ generated: undefined;
84
+ }, {}, {}>;
85
+ organizationId: import("drizzle-orm/pg-core").PgColumn<{
86
+ name: "organizationId";
87
+ tableName: "event";
88
+ dataType: "string";
89
+ columnType: "PgText";
90
+ data: string;
91
+ driverParam: string;
92
+ notNull: true;
93
+ hasDefault: false;
94
+ isPrimaryKey: false;
95
+ isAutoincrement: false;
96
+ hasRuntimeDefault: false;
97
+ enumValues: [string, ...string[]];
98
+ baseColumn: never;
99
+ generated: undefined;
100
+ }, {}, {}>;
101
+ creatorId: import("drizzle-orm/pg-core").PgColumn<{
102
+ name: "creatorId";
103
+ tableName: "event";
104
+ dataType: "string";
105
+ columnType: "PgText";
106
+ data: string;
107
+ driverParam: string;
108
+ notNull: false;
109
+ hasDefault: false;
110
+ isPrimaryKey: false;
111
+ isAutoincrement: false;
112
+ hasRuntimeDefault: false;
113
+ enumValues: [string, ...string[]];
114
+ baseColumn: never;
115
+ generated: undefined;
116
+ }, {}, {}>;
117
+ mode: import("drizzle-orm/pg-core").PgColumn<{
118
+ name: "mode";
119
+ tableName: "event";
120
+ dataType: "string";
121
+ columnType: "PgVarchar";
122
+ data: string;
123
+ driverParam: string;
124
+ notNull: true;
125
+ hasDefault: false;
126
+ isPrimaryKey: false;
127
+ isAutoincrement: false;
128
+ hasRuntimeDefault: false;
129
+ enumValues: [string, ...string[]];
130
+ baseColumn: never;
131
+ generated: undefined;
132
+ }, {}, {}>;
133
+ ageGroup: import("drizzle-orm/pg-core").PgColumn<{
134
+ name: "age_group";
135
+ tableName: "event";
136
+ dataType: "string";
137
+ columnType: "PgVarchar";
138
+ data: string;
139
+ driverParam: string;
140
+ notNull: true;
141
+ hasDefault: false;
142
+ isPrimaryKey: false;
143
+ isAutoincrement: false;
144
+ hasRuntimeDefault: false;
145
+ enumValues: [string, ...string[]];
146
+ baseColumn: never;
147
+ generated: undefined;
148
+ }, {}, {}>;
149
+ gender: import("drizzle-orm/pg-core").PgColumn<{
150
+ name: "gender";
151
+ tableName: "event";
152
+ dataType: "string";
153
+ columnType: "PgVarchar";
154
+ data: string;
155
+ driverParam: string;
156
+ notNull: true;
157
+ hasDefault: false;
158
+ isPrimaryKey: false;
159
+ isAutoincrement: false;
160
+ hasRuntimeDefault: false;
161
+ enumValues: [string, ...string[]];
162
+ baseColumn: never;
163
+ generated: undefined;
164
+ }, {}, {}>;
165
+ status: import("drizzle-orm/pg-core").PgColumn<{
166
+ name: "status";
167
+ tableName: "event";
168
+ dataType: "string";
169
+ columnType: "PgVarchar";
170
+ data: string;
171
+ driverParam: string;
172
+ notNull: true;
173
+ hasDefault: false;
174
+ isPrimaryKey: false;
175
+ isAutoincrement: false;
176
+ hasRuntimeDefault: false;
177
+ enumValues: [string, ...string[]];
178
+ baseColumn: never;
179
+ generated: undefined;
180
+ }, {}, {}>;
181
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
182
+ name: "created_at";
183
+ tableName: "event";
184
+ dataType: "date";
185
+ columnType: "PgTimestamp";
186
+ data: Date;
187
+ driverParam: string;
188
+ notNull: true;
189
+ hasDefault: true;
190
+ isPrimaryKey: false;
191
+ isAutoincrement: false;
192
+ hasRuntimeDefault: false;
193
+ enumValues: undefined;
194
+ baseColumn: never;
195
+ generated: undefined;
196
+ }, {}, {}>;
197
+ updatedAt: import("drizzle-orm/pg-core").PgColumn<{
198
+ name: "updated_at";
199
+ tableName: "event";
200
+ dataType: "date";
201
+ columnType: "PgTimestamp";
202
+ data: Date;
203
+ driverParam: string;
204
+ notNull: true;
205
+ hasDefault: true;
206
+ isPrimaryKey: false;
207
+ isAutoincrement: false;
208
+ hasRuntimeDefault: false;
209
+ enumValues: undefined;
210
+ baseColumn: never;
211
+ generated: undefined;
212
+ }, {}, {}>;
213
+ };
214
+ dialect: "pg";
215
+ }>;
216
+ export declare const eventRelations: import("drizzle-orm").Relations<"event", {
217
+ creator: import("drizzle-orm").One<"user", false>;
218
+ organization: import("drizzle-orm").One<"organization", true>;
219
+ location: import("drizzle-orm").One<"location", false>;
220
+ }>;
221
+ export declare const selectEventSchema: import("zod").ZodObject<{
222
+ id: import("zod").ZodString;
223
+ name: import("zod").ZodString;
224
+ description: import("zod").ZodNullable<import("zod").ZodString>;
225
+ locationId: import("zod").ZodNullable<import("zod").ZodString>;
226
+ type: import("zod").ZodString;
227
+ organizationId: import("zod").ZodString;
228
+ creatorId: import("zod").ZodNullable<import("zod").ZodString>;
229
+ mode: import("zod").ZodString;
230
+ ageGroup: import("zod").ZodString;
231
+ gender: import("zod").ZodString;
232
+ status: import("zod").ZodString;
233
+ createdAt: import("zod").ZodDate;
234
+ updatedAt: import("zod").ZodDate;
235
+ }, import("zod").UnknownKeysParam, import("zod").ZodTypeAny, {
236
+ id: string;
237
+ status: string;
238
+ type: string;
239
+ description: string | null;
240
+ name: string;
241
+ locationId: string | null;
242
+ organizationId: string;
243
+ mode: string;
244
+ createdAt: Date;
245
+ updatedAt: Date;
246
+ creatorId: string | null;
247
+ ageGroup: string;
248
+ gender: string;
249
+ }, {
250
+ id: string;
251
+ status: string;
252
+ type: string;
253
+ description: string | null;
254
+ name: string;
255
+ locationId: string | null;
256
+ organizationId: string;
257
+ mode: string;
258
+ createdAt: Date;
259
+ updatedAt: Date;
260
+ creatorId: string | null;
261
+ ageGroup: string;
262
+ gender: string;
263
+ }>;
264
+ export default event;
@@ -0,0 +1,38 @@
1
+ import { relations } from "drizzle-orm";
2
+ import { pgTable, text, timestamp, varchar } from "drizzle-orm/pg-core";
3
+ import { createSelectSchema } from "drizzle-zod";
4
+ import { randomUUID } from "node:crypto";
5
+ import location from "./location.js";
6
+ import organization from "./organization.js";
7
+ import { user } from "./user.js";
8
+ const event = pgTable("event", {
9
+ id: text("id").primaryKey().$defaultFn(() => randomUUID()),
10
+ name: varchar("name", { length: 255 }).notNull(),
11
+ description: text("description"),
12
+ locationId: varchar("location_id").references(() => location.id),
13
+ type: varchar("type").notNull(),
14
+ organizationId: text("organizationId").references(() => organization.id, { onDelete: "cascade" }).notNull(),
15
+ creatorId: text("creatorId").references(() => user.id, { onDelete: "set null" }),
16
+ mode: varchar("mode").notNull(), // Adult, Youth
17
+ ageGroup: varchar("age_group").notNull(),
18
+ gender: varchar("gender").notNull(),
19
+ status: varchar("status").notNull(), // IN_PROGRESS, COMPLETED, CANCELLED
20
+ createdAt: timestamp("created_at").defaultNow().notNull(),
21
+ updatedAt: timestamp("updated_at").defaultNow().notNull(),
22
+ });
23
+ export const eventRelations = relations(event, ({ one }) => ({
24
+ creator: one(user, {
25
+ fields: [event.creatorId],
26
+ references: [user.id],
27
+ }),
28
+ organization: one(organization, {
29
+ fields: [event.organizationId],
30
+ references: [organization.id],
31
+ }),
32
+ location: one(location, {
33
+ fields: [event.locationId],
34
+ references: [location.id],
35
+ }),
36
+ }));
37
+ export const selectEventSchema = createSelectSchema(event);
38
+ export default event;
@@ -0,0 +1,8 @@
1
+ export { default as event, eventRelations, selectEventSchema } from "./event.js";
2
+ export { default as leagues, insertLeaguesSchema, leagueRelations, selectLeaguesSchema } from "./league.js";
3
+ export { default as location, insertLocationSchema, locationRelations, selectLocationSchema } from "./location.js";
4
+ export { emailCampaign, insertEmailCampaignSchema, selectEmailCampaignSchema } from "./marketing.js";
5
+ export { createOrganizationWithDetailsSchema, default as organization, generateSocialMediaUrl, getOrganizationWithDetailsSchema, insertOrganizationSchema, insertOrganizationSocialMediaSchema, insertOrganizationTagSchema, insertOrganizationWebsiteSchema, organizationRelations, organizationSocialMedia, organizationSocialMediaRelations, organizationTagsRelations, organizationWebsites, organizationWebsitesRelations, patchOrganizationSchema, selectOrganizationSchema, SOCIAL_MEDIA_PLATFORMS, type SocialMediaPlatform } from "./organization.js";
6
+ export { default as pickup, eventPickupRelations, pickupRelations, selectPickupSchema } from "./pickup.js";
7
+ export { default as tags, eventTags, organizationTags, selectTagsSchema } from "./tag.js";
8
+ export { account, selectUserSchema, session, user, verification } from "./user.js";
@@ -0,0 +1,8 @@
1
+ export { default as event, eventRelations, selectEventSchema } from "./event.js";
2
+ export { default as leagues, insertLeaguesSchema, leagueRelations, selectLeaguesSchema } from "./league.js";
3
+ export { default as location, insertLocationSchema, locationRelations, selectLocationSchema } from "./location.js";
4
+ export { emailCampaign, insertEmailCampaignSchema, selectEmailCampaignSchema } from "./marketing.js";
5
+ export { createOrganizationWithDetailsSchema, default as organization, generateSocialMediaUrl, getOrganizationWithDetailsSchema, insertOrganizationSchema, insertOrganizationSocialMediaSchema, insertOrganizationTagSchema, insertOrganizationWebsiteSchema, organizationRelations, organizationSocialMedia, organizationSocialMediaRelations, organizationTagsRelations, organizationWebsites, organizationWebsitesRelations, patchOrganizationSchema, selectOrganizationSchema, SOCIAL_MEDIA_PLATFORMS } from "./organization.js";
6
+ export { default as pickup, eventPickupRelations, pickupRelations, selectPickupSchema } from "./pickup.js";
7
+ export { default as tags, eventTags, organizationTags, selectTagsSchema } from "./tag.js";
8
+ export { account, selectUserSchema, session, user, verification } from "./user.js";