Skip to content

Commit 028e157

Browse files
committed
✨ feat(sub-calendars): create calendar collection and schema
1 parent d227d8d commit 028e157

File tree

15 files changed

+730
-59
lines changed

15 files changed

+730
-59
lines changed

packages/backend/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
"saslprep": "^1.0.3",
2424
"socket.io": "^4.7.5",
2525
"supertokens-node": "^20.0.5",
26-
"tslib": "^2.4.0",
27-
"zod": "^3.24.1"
26+
"tslib": "^2.4.0"
2827
},
2928
"devDependencies": {
3029
"@faker-js/faker": "^9.6.0",

packages/backend/src/calendar/services/calendar.service.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class CalendarService {
99
) => {
1010
const payload = calendarList.google.items;
1111

12-
const response = await mongoService.calendar.updateOne(
12+
const response = await mongoService.calendarList.updateOne(
1313
{ user: userId },
1414
{ $push: { [`${integration}.items`]: payload } },
1515
{ upsert: true },
@@ -19,18 +19,18 @@ class CalendarService {
1919
};
2020

2121
create = async (calendarList: Schema_CalendarList) => {
22-
return await mongoService.calendar.insertOne(calendarList);
22+
return await mongoService.calendarList.insertOne(calendarList);
2323
};
2424

2525
async deleteAllByUser(userId: string) {
2626
const filter = { user: userId };
27-
const response = await mongoService.calendar.deleteMany(filter);
27+
const response = await mongoService.calendarList.deleteMany(filter);
2828

2929
return response;
3030
}
3131

3232
deleteByIntegrateion = async (integration: "google", userId: string) => {
33-
const response = await mongoService.calendar.updateOne(
33+
const response = await mongoService.calendarList.updateOne(
3434
{ user: userId },
3535
{ $unset: { [`${integration}.items`]: "" } },
3636
);

packages/backend/src/common/constants/collections.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { IS_DEV } from "./env.constants";
1+
import { IS_DEV } from "@backend/common/constants/env.constants";
22

33
export const Collections = {
4+
CALENDAR: IS_DEV ? "_dev.calendar" : "calendar",
45
CALENDARLIST: IS_DEV ? "_dev.calendarlist" : "calendarlist",
56
EVENT: IS_DEV ? "_dev.event" : "event",
67
OAUTH: IS_DEV ? "_dev.oauth" : "oauth",

packages/backend/src/common/services/mongo.service.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,25 @@ import {
1010
ObjectId,
1111
} from "mongodb";
1212
import { Logger } from "@core/logger/winston.logger";
13-
import { Schema_CalendarList as Schema_Calendar } from "@core/types/calendar.types";
13+
import {
14+
CompassCalendar,
15+
Schema_CalendarList as Schema_Calendar,
16+
} from "@core/types/calendar.types";
1417
import { Schema_Event } from "@core/types/event.types";
1518
import { Schema_Sync } from "@core/types/sync.types";
1619
import { Schema_User } from "@core/types/user.types";
1720
import { Schema_Waitlist } from "@core/types/waitlist/waitlist.types";
21+
import { Collections } from "@backend/common/constants/collections";
22+
import { ENV } from "@backend/common/constants/env.constants";
1823
import { waitUntilEvent } from "@backend/common/helpers/common.util";
19-
import { Collections } from "../constants/collections";
20-
import { ENV } from "../constants/env.constants";
2124

2225
const logger = Logger("app:mongo.service");
2326

2427
interface InternalClient {
2528
db: Db;
2629
client: MongoClient;
27-
calendar: Collection<Schema_Calendar>;
30+
calendar: Collection<CompassCalendar>;
31+
calendarList: Collection<Schema_Calendar>;
2832
event: Collection<Omit<Schema_Event, "_id">>;
2933
sync: Collection<Schema_Sync>;
3034
user: Collection<Schema_User>;
@@ -47,6 +51,15 @@ class MongoService {
4751
return this.#accessInternalCollectionProps("calendar");
4852
}
4953

54+
/**
55+
* calendarList
56+
*
57+
* mongo collection
58+
*/
59+
get calendarList(): InternalClient["calendarList"] {
60+
return this.#accessInternalCollectionProps("calendarList");
61+
}
62+
5063
/**
5164
* event
5265
*
@@ -114,7 +127,8 @@ class MongoService {
114127
return {
115128
db,
116129
client,
117-
calendar: db.collection<Schema_Calendar>(Collections.CALENDARLIST),
130+
calendar: db.collection<CompassCalendar>(Collections.CALENDAR),
131+
calendarList: db.collection<Schema_Calendar>(Collections.CALENDARLIST),
118132
event: db.collection<Omit<Schema_Event, "_id">>(Collections.EVENT),
119133
sync: db.collection<Schema_Sync>(Collections.SYNC),
120134
user: db.collection<Schema_User>(Collections.USER),

packages/core/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"dependencies": {
1414
"bson": "^6.10.4",
1515
"tinycolor2": "^1.6.0",
16-
"winston": "^3.8.1"
16+
"winston": "^3.8.1",
17+
"zod": "^3.25.76"
1718
}
1819
}

packages/core/src/types/calendar.types.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import { z } from "zod";
1+
import { z } from "zod/v4";
2+
import { CalendarProvider } from "@core/types/event.types";
23
import { gSchema$CalendarListEntry } from "@core/types/gcal";
3-
import { IDSchema, RGBHexSchema, TimezoneSchema } from "@core/types/type.utils";
4-
import { CalendarProvider } from "./event.types";
4+
import {
5+
IDSchemaV4,
6+
RGBHexSchema,
7+
TimezoneSchema,
8+
} from "@core/types/type.utils";
59

610
// @deprecated - will be replaced by Schema_Calendar
711
export interface Schema_CalendarList {
@@ -51,15 +55,15 @@ export const GoogleCalendarMetadataSchema = z.object({
5155
});
5256

5357
export const CompassCalendarSchema = z.object({
54-
_id: IDSchema,
55-
user: IDSchema,
58+
_id: IDSchemaV4,
59+
user: IDSchemaV4,
5660
backgroundColor: RGBHexSchema,
5761
color: RGBHexSchema,
5862
selected: z.boolean().default(true),
5963
primary: z.boolean().default(false),
60-
timezone: TimezoneSchema.optional(),
64+
timezone: TimezoneSchema.nullable().optional(),
6165
createdAt: z.date().default(() => new Date()),
62-
updatedAt: z.date().optional(),
66+
updatedAt: z.date().nullable().optional(),
6367
metadata: GoogleCalendarMetadataSchema, // use union when other providers present
6468
});
6569

packages/core/src/types/type.utils.test.ts

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ZodError } from "zod";
1+
import { ZodError, z } from "zod/v4";
22
import { faker } from "@faker-js/faker";
33
import { IDSchema, RGBHexSchema, TimezoneSchema } from "@core/types/type.utils";
44

@@ -15,9 +15,7 @@ describe("IDSchema", () => {
1515

1616
expect(result.success).toBe(false);
1717
expect(result.error).toBeInstanceOf(ZodError);
18-
expect(result.error?.errors).toEqual([
19-
{ message: "Invalid id", path: [], code: "custom" },
20-
]);
18+
expect(z.treeifyError(result.error!).errors).toEqual(["Invalid id"]);
2119
});
2220
});
2321

@@ -34,9 +32,7 @@ describe("TimezoneSchema", () => {
3432

3533
expect(result.success).toBe(false);
3634
expect(result.error).toBeInstanceOf(ZodError);
37-
expect(result.error?.errors).toEqual([
38-
{ message: "Invalid timezone", path: [], code: "custom" },
39-
]);
35+
expect(z.treeifyError(result.error!).errors).toEqual(["Invalid timezone"]);
4036
});
4137

4238
describe("RGBHexSchema", () => {
@@ -58,13 +54,8 @@ describe("TimezoneSchema", () => {
5854

5955
expect(result.success).toBe(false);
6056
expect(result.error).toBeInstanceOf(ZodError);
61-
expect(result.error?.errors).toEqual([
62-
{
63-
message: "Invalid color. Must be a 7-character hex color code.",
64-
path: [],
65-
code: "invalid_string",
66-
validation: "regex",
67-
},
57+
expect(z.treeifyError(result.error!).errors).toEqual([
58+
"Invalid color. Must be a 7-character hex color code.",
6859
]);
6960
});
7061

@@ -74,13 +65,8 @@ describe("TimezoneSchema", () => {
7465

7566
expect(result.success).toBe(false);
7667
expect(result.error).toBeInstanceOf(ZodError);
77-
expect(result.error?.errors).toEqual([
78-
{
79-
message: "Invalid color. Must be a 7-character hex color code.",
80-
path: [],
81-
code: "invalid_string",
82-
validation: "regex",
83-
},
68+
expect(z.treeifyError(result.error!).errors).toEqual([
69+
"Invalid color. Must be a 7-character hex color code.",
8470
]);
8571
});
8672

@@ -90,13 +76,8 @@ describe("TimezoneSchema", () => {
9076

9177
expect(result.success).toBe(false);
9278
expect(result.error).toBeInstanceOf(ZodError);
93-
expect(result.error?.errors).toEqual([
94-
{
95-
message: "Invalid color. Must be a 7-character hex color code.",
96-
path: [],
97-
code: "invalid_string",
98-
validation: "regex",
99-
},
79+
expect(z.treeifyError(result.error!).errors).toEqual([
80+
"Invalid color. Must be a 7-character hex color code.",
10081
]);
10182
});
10283
});

packages/core/src/types/type.utils.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ObjectId } from "bson";
22
import { z } from "zod";
3+
import { z as zod4 } from "zod/v4";
34

45
export type KeyOfType<T, V> = keyof {
56
[P in keyof T as T[P] extends V ? P : never]: unknown;
@@ -14,7 +15,11 @@ export const IDSchema = z.string().refine(ObjectId.isValid, {
1415
message: "Invalid id",
1516
});
1617

17-
export const TimezoneSchema = z.string().refine(
18+
export const IDSchemaV4 = zod4.string().refine(ObjectId.isValid, {
19+
message: "Invalid id",
20+
});
21+
22+
export const TimezoneSchema = zod4.string().refine(
1823
(timeZone) => {
1924
try {
2025
new Intl.DateTimeFormat("en-US", { timeZone });
@@ -28,6 +33,6 @@ export const TimezoneSchema = z.string().refine(
2833
{ message: "Invalid timezone" },
2934
);
3035

31-
export const RGBHexSchema = z.string().regex(/^#[0-9a-f]{6}$/i, {
36+
export const RGBHexSchema = zod4.string().regex(/^#[0-9a-f]{6}$/i, {
3237
message: "Invalid color. Must be a 7-character hex color code.",
3338
});

packages/scripts/src/commands/migrate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ async function template({
8686
contents
8787
.toString()
8888
.replace("class Template", `class ${migratorType}`)
89-
.replace("{{name}}", name.split(".").pop()!)
89+
.replace("{{name}}", name)
9090
.replace("{{path}}", path.replace(`${migrationsRoot}${sep}`, "")),
9191
],
9292
]);

0 commit comments

Comments
 (0)