fixxed color selector in the category settings and fixxed drag and drop
Build APK / build (push) Canceled after 2m0s
Build APK / build (push) Canceled after 2m0s
subtask
This commit is contained in:
Vendored
+513
-136
@@ -1,3 +1,5 @@
|
||||
export declare const ENTITIES: readonly ["categories", "tasks", "subtasks", "repeatProfiles", "friendships"];
|
||||
export type EntityName = (typeof ENTITIES)[number];
|
||||
export declare const users: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
name: "users";
|
||||
schema: undefined;
|
||||
@@ -50,6 +52,38 @@ export declare const users: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
resetToken: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "reset_token";
|
||||
tableName: "users";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: false;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
resetTokenExpiry: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "reset_token_expiry";
|
||||
tableName: "users";
|
||||
dataType: "number";
|
||||
columnType: "PgBigInt53";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: false;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "created_at";
|
||||
tableName: "users";
|
||||
@@ -334,7 +368,7 @@ export declare const tasks: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
notNull: false;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
@@ -455,6 +489,22 @@ export declare const tasks: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
allDay: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "all_day";
|
||||
tableName: "tasks";
|
||||
dataType: "boolean";
|
||||
columnType: "PgBoolean";
|
||||
data: boolean;
|
||||
driverParam: boolean;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
repeat: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "repeat";
|
||||
tableName: "tasks";
|
||||
@@ -551,6 +601,38 @@ export declare const tasks: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
reminders: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "reminders";
|
||||
tableName: "tasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
completedAt: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "completed_at";
|
||||
tableName: "tasks";
|
||||
dataType: "number";
|
||||
columnType: "PgBigInt53";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: false;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "created_at";
|
||||
tableName: "tasks";
|
||||
@@ -586,6 +668,436 @@ export declare const tasks: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
};
|
||||
dialect: "pg";
|
||||
}>;
|
||||
export declare const tombstones: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
name: "tombstones";
|
||||
schema: undefined;
|
||||
columns: {
|
||||
entity: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "entity";
|
||||
tableName: "tombstones";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: "categories" | "tasks" | "subtasks" | "repeatProfiles" | "friendships";
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: ["categories", "tasks", "subtasks", "repeatProfiles", "friendships"];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
entityId: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "entity_id";
|
||||
tableName: "tombstones";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
userId: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "user_id";
|
||||
tableName: "tombstones";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "updated_at";
|
||||
tableName: "tombstones";
|
||||
dataType: "number";
|
||||
columnType: "PgBigInt53";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
};
|
||||
dialect: "pg";
|
||||
}>;
|
||||
export declare const subtasks: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
name: "subtasks";
|
||||
schema: undefined;
|
||||
columns: {
|
||||
id: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "id";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: true;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
userId: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "user_id";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
taskId: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "task_id";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
parentSubtaskId: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "parent_subtask_id";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: false;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
title: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "title";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
description: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "description";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
priority: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "priority";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: "none" | "low" | "medium" | "high" | "critical";
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: ["none", "low", "medium", "high", "critical"];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
completed: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "completed";
|
||||
tableName: "subtasks";
|
||||
dataType: "boolean";
|
||||
columnType: "PgBoolean";
|
||||
data: boolean;
|
||||
driverParam: boolean;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
dueDate: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "due_date";
|
||||
tableName: "subtasks";
|
||||
dataType: "number";
|
||||
columnType: "PgBigInt53";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
dueTime: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "due_time";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
endTime: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "end_time";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
allDay: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "all_day";
|
||||
tableName: "subtasks";
|
||||
dataType: "boolean";
|
||||
columnType: "PgBoolean";
|
||||
data: boolean;
|
||||
driverParam: boolean;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
repeat: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "repeat";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: "custom" | "none" | "daily" | "weekly" | "monthly";
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: ["none", "daily", "weekly", "monthly", "custom"];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
repeatInterval: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "repeat_interval";
|
||||
tableName: "subtasks";
|
||||
dataType: "number";
|
||||
columnType: "PgInteger";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
repeatDays: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "repeat_days";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
seriesId: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "series_id";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
reminder: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "reminder";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440";
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: ["none", "at_time", "15", "30", "60", "120", "1440"];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
reminders: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "reminders";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
assigneeId: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "assignee_id";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: false;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
order: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "order";
|
||||
tableName: "subtasks";
|
||||
dataType: "number";
|
||||
columnType: "PgInteger";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "created_at";
|
||||
tableName: "subtasks";
|
||||
dataType: "number";
|
||||
columnType: "PgBigInt53";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "updated_at";
|
||||
tableName: "subtasks";
|
||||
dataType: "number";
|
||||
columnType: "PgBigInt53";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
};
|
||||
dialect: "pg";
|
||||
}>;
|
||||
export declare const repeatProfiles: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
name: "repeat_profiles";
|
||||
schema: undefined;
|
||||
@@ -721,141 +1233,6 @@ export declare const repeatProfiles: import("drizzle-orm/pg-core").PgTableWithCo
|
||||
};
|
||||
dialect: "pg";
|
||||
}>;
|
||||
export declare const subtasks: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
name: "subtasks";
|
||||
schema: undefined;
|
||||
columns: {
|
||||
id: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "id";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: true;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
userId: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "user_id";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
taskId: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "task_id";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
title: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "title";
|
||||
tableName: "subtasks";
|
||||
dataType: "string";
|
||||
columnType: "PgText";
|
||||
data: string;
|
||||
driverParam: string;
|
||||
notNull: true;
|
||||
hasDefault: false;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: [string, ...string[]];
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
completed: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "completed";
|
||||
tableName: "subtasks";
|
||||
dataType: "boolean";
|
||||
columnType: "PgBoolean";
|
||||
data: boolean;
|
||||
driverParam: boolean;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
order: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "order";
|
||||
tableName: "subtasks";
|
||||
dataType: "number";
|
||||
columnType: "PgInteger";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "created_at";
|
||||
tableName: "subtasks";
|
||||
dataType: "number";
|
||||
columnType: "PgBigInt53";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
updatedAt: import("drizzle-orm/pg-core").PgColumn<{
|
||||
name: "updated_at";
|
||||
tableName: "subtasks";
|
||||
dataType: "number";
|
||||
columnType: "PgBigInt53";
|
||||
data: number;
|
||||
driverParam: string | number;
|
||||
notNull: true;
|
||||
hasDefault: true;
|
||||
isPrimaryKey: false;
|
||||
isAutoincrement: false;
|
||||
hasRuntimeDefault: false;
|
||||
enumValues: undefined;
|
||||
baseColumn: never;
|
||||
generated: undefined;
|
||||
}, {}, {}>;
|
||||
};
|
||||
dialect: "pg";
|
||||
}>;
|
||||
export declare const userSettings: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
||||
name: "user_settings";
|
||||
schema: undefined;
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKhB,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAevB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQrB,CAAC;AAEH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmBhB,CAAC;AAEH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASzB,CAAC;AAEH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASnB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASvB,CAAC"}
|
||||
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,QAAQ,+EAAgF,CAAC;AACtG,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOhB,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAevB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQrB,CAAC;AAEH,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsBhB,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYtB,CAAC;AAGF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BlB,CAAC;AAEJ,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASzB,CAAC;AAEH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASvB,CAAC"}
|
||||
Vendored
+46
-12
@@ -1,12 +1,15 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.userSettings = exports.subtasks = exports.repeatProfiles = exports.tasks = exports.categories = exports.friendships = exports.users = void 0;
|
||||
exports.userSettings = exports.repeatProfiles = exports.subtasks = exports.tombstones = exports.tasks = exports.categories = exports.friendships = exports.users = exports.ENTITIES = void 0;
|
||||
const pg_core_1 = require("drizzle-orm/pg-core");
|
||||
const drizzle_orm_1 = require("drizzle-orm");
|
||||
exports.ENTITIES = ['categories', 'tasks', 'subtasks', 'repeatProfiles', 'friendships'];
|
||||
exports.users = (0, pg_core_1.pgTable)('users', {
|
||||
id: (0, pg_core_1.text)('id').primaryKey(),
|
||||
username: (0, pg_core_1.text)('username').notNull().unique(),
|
||||
passwordHash: (0, pg_core_1.text)('password_hash').notNull(),
|
||||
resetToken: (0, pg_core_1.text)('reset_token'),
|
||||
resetTokenExpiry: (0, pg_core_1.bigint)('reset_token_expiry', { mode: 'number' }),
|
||||
createdAt: (0, pg_core_1.bigint)('created_at', { mode: 'number' }).notNull().default((0, drizzle_orm_1.sql) `EXTRACT(EPOCH FROM NOW()) * 1000`),
|
||||
});
|
||||
exports.friendships = (0, pg_core_1.pgTable)('friendships', {
|
||||
@@ -33,7 +36,7 @@ exports.categories = (0, pg_core_1.pgTable)('categories', {
|
||||
exports.tasks = (0, pg_core_1.pgTable)('tasks', {
|
||||
id: (0, pg_core_1.text)('id').primaryKey(),
|
||||
userId: (0, pg_core_1.text)('user_id').notNull().references(() => exports.users.id, { onDelete: 'cascade' }),
|
||||
categoryId: (0, pg_core_1.text)('category_id').notNull().references(() => exports.categories.id, { onDelete: 'cascade' }),
|
||||
categoryId: (0, pg_core_1.text)('category_id').references(() => exports.categories.id, { onDelete: 'cascade' }),
|
||||
title: (0, pg_core_1.text)('title').notNull(),
|
||||
description: (0, pg_core_1.text)('description').notNull().default(''),
|
||||
priority: (0, pg_core_1.text)('priority', { enum: ['none', 'low', 'medium', 'high', 'critical'] }).notNull().default('none'),
|
||||
@@ -41,15 +44,56 @@ exports.tasks = (0, pg_core_1.pgTable)('tasks', {
|
||||
dueDate: (0, pg_core_1.bigint)('due_date', { mode: 'number' }).notNull().default(0),
|
||||
dueTime: (0, pg_core_1.text)('due_time').notNull().default(''),
|
||||
endTime: (0, pg_core_1.text)('end_time').notNull().default(''),
|
||||
allDay: (0, pg_core_1.boolean)('all_day').notNull().default(false),
|
||||
repeat: (0, pg_core_1.text)('repeat', { enum: ['none', 'daily', 'weekly', 'monthly', 'custom'] }).notNull().default('none'),
|
||||
repeatInterval: (0, pg_core_1.integer)('repeat_interval').notNull().default(1),
|
||||
repeatDays: (0, pg_core_1.text)('repeat_days').notNull().default(''),
|
||||
seriesId: (0, pg_core_1.text)('series_id').notNull().default(''),
|
||||
assigneeId: (0, pg_core_1.text)('assignee_id').references(() => exports.users.id, { onDelete: 'set null' }),
|
||||
reminder: (0, pg_core_1.text)('reminder', { enum: ['none', 'at_time', '15', '30', '60', '120', '1440'] }).notNull().default('none'),
|
||||
reminders: (0, pg_core_1.text)('reminders').notNull().default(''),
|
||||
completedAt: (0, pg_core_1.bigint)('completed_at', { mode: 'number' }),
|
||||
createdAt: (0, pg_core_1.bigint)('created_at', { mode: 'number' }).notNull().default((0, drizzle_orm_1.sql) `EXTRACT(EPOCH FROM NOW()) * 1000`),
|
||||
updatedAt: (0, pg_core_1.bigint)('updated_at', { mode: 'number' }).notNull().default((0, drizzle_orm_1.sql) `EXTRACT(EPOCH FROM NOW()) * 1000`),
|
||||
});
|
||||
exports.tombstones = (0, pg_core_1.pgTable)('tombstones', {
|
||||
entity: (0, pg_core_1.text)('entity', { enum: exports.ENTITIES }).notNull(),
|
||||
entityId: (0, pg_core_1.text)('entity_id').notNull(),
|
||||
userId: (0, pg_core_1.text)('user_id').notNull().references(() => exports.users.id, { onDelete: 'cascade' }),
|
||||
updatedAt: (0, pg_core_1.bigint)('updated_at', { mode: 'number' }).notNull(),
|
||||
}, (t) => ({
|
||||
pk: (0, pg_core_1.primaryKey)({ columns: [t.entity, t.entityId] }),
|
||||
userIdx: (0, pg_core_1.index)('tombstones_user_updated_idx').on(t.userId, t.updatedAt),
|
||||
}));
|
||||
// Define subtasks with explicit type to avoid circular reference
|
||||
exports.subtasks = (0, pg_core_1.pgTable)('subtasks', {
|
||||
id: (0, pg_core_1.text)('id').primaryKey(),
|
||||
userId: (0, pg_core_1.text)('user_id').notNull().references(() => exports.users.id, { onDelete: 'cascade' }),
|
||||
taskId: (0, pg_core_1.text)('task_id').notNull().references(() => exports.tasks.id, { onDelete: 'cascade' }),
|
||||
parentSubtaskId: (0, pg_core_1.text)('parent_subtask_id').references(() => exports.subtasks.id, { onDelete: 'cascade' }),
|
||||
title: (0, pg_core_1.text)('title').notNull(),
|
||||
description: (0, pg_core_1.text)('description').notNull().default(''),
|
||||
priority: (0, pg_core_1.text)('priority', { enum: ['none', 'low', 'medium', 'high', 'critical'] }).notNull().default('none'),
|
||||
completed: (0, pg_core_1.boolean)('completed').notNull().default(false),
|
||||
dueDate: (0, pg_core_1.bigint)('due_date', { mode: 'number' }).notNull().default(0),
|
||||
dueTime: (0, pg_core_1.text)('due_time').notNull().default(''),
|
||||
endTime: (0, pg_core_1.text)('end_time').notNull().default(''),
|
||||
allDay: (0, pg_core_1.boolean)('all_day').notNull().default(false),
|
||||
repeat: (0, pg_core_1.text)('repeat', { enum: ['none', 'daily', 'weekly', 'monthly', 'custom'] }).notNull().default('none'),
|
||||
repeatInterval: (0, pg_core_1.integer)('repeat_interval').notNull().default(1),
|
||||
repeatDays: (0, pg_core_1.text)('repeat_days').notNull().default(''),
|
||||
seriesId: (0, pg_core_1.text)('series_id').notNull().default(''),
|
||||
reminder: (0, pg_core_1.text)('reminder', { enum: ['none', 'at_time', '15', '30', '60', '120', '1440'] }).notNull().default('none'),
|
||||
reminders: (0, pg_core_1.text)('reminders').notNull().default(''),
|
||||
assigneeId: (0, pg_core_1.text)('assignee_id').references(() => exports.users.id, { onDelete: 'set null' }),
|
||||
order: (0, pg_core_1.integer)('order').notNull().default(0),
|
||||
createdAt: (0, pg_core_1.bigint)('created_at', { mode: 'number' }).notNull().default((0, drizzle_orm_1.sql) `EXTRACT(EPOCH FROM NOW()) * 1000`),
|
||||
updatedAt: (0, pg_core_1.bigint)('updated_at', { mode: 'number' }).notNull().default((0, drizzle_orm_1.sql) `EXTRACT(EPOCH FROM NOW()) * 1000`),
|
||||
}, (t) => ({
|
||||
parentIdx: (0, pg_core_1.index)('subtasks_parent_idx').on(t.parentSubtaskId),
|
||||
taskIdx: (0, pg_core_1.index)('subtasks_task_idx').on(t.taskId),
|
||||
userIdx: (0, pg_core_1.index)('subtasks_user_idx').on(t.userId),
|
||||
}));
|
||||
exports.repeatProfiles = (0, pg_core_1.pgTable)('repeat_profiles', {
|
||||
id: (0, pg_core_1.text)('id').primaryKey(),
|
||||
userId: (0, pg_core_1.text)('user_id').notNull().references(() => exports.users.id, { onDelete: 'cascade' }),
|
||||
@@ -60,16 +104,6 @@ exports.repeatProfiles = (0, pg_core_1.pgTable)('repeat_profiles', {
|
||||
createdAt: (0, pg_core_1.bigint)('created_at', { mode: 'number' }).notNull().default((0, drizzle_orm_1.sql) `EXTRACT(EPOCH FROM NOW()) * 1000`),
|
||||
updatedAt: (0, pg_core_1.bigint)('updated_at', { mode: 'number' }).notNull().default((0, drizzle_orm_1.sql) `EXTRACT(EPOCH FROM NOW()) * 1000`),
|
||||
});
|
||||
exports.subtasks = (0, pg_core_1.pgTable)('subtasks', {
|
||||
id: (0, pg_core_1.text)('id').primaryKey(),
|
||||
userId: (0, pg_core_1.text)('user_id').notNull().references(() => exports.users.id, { onDelete: 'cascade' }),
|
||||
taskId: (0, pg_core_1.text)('task_id').notNull().references(() => exports.tasks.id, { onDelete: 'cascade' }),
|
||||
title: (0, pg_core_1.text)('title').notNull(),
|
||||
completed: (0, pg_core_1.boolean)('completed').notNull().default(false),
|
||||
order: (0, pg_core_1.integer)('order').notNull().default(0),
|
||||
createdAt: (0, pg_core_1.bigint)('created_at', { mode: 'number' }).notNull().default((0, drizzle_orm_1.sql) `EXTRACT(EPOCH FROM NOW()) * 1000`),
|
||||
updatedAt: (0, pg_core_1.bigint)('updated_at', { mode: 'number' }).notNull().default((0, drizzle_orm_1.sql) `EXTRACT(EPOCH FROM NOW()) * 1000`),
|
||||
});
|
||||
exports.userSettings = (0, pg_core_1.pgTable)('user_settings', {
|
||||
userId: (0, pg_core_1.text)('user_id').primaryKey().references(() => exports.users.id, { onDelete: 'cascade' }),
|
||||
darkMode: (0, pg_core_1.boolean)('dark_mode').notNull().default(false),
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAYvB,QAAA,MAAM,GAAG,6CAAY,CAAC;AAkCtB,eAAe,GAAG,CAAC"}
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAavB,QAAA,MAAM,GAAG,6CAAY,CAAC;AAmCtB,eAAe,GAAG,CAAC"}
|
||||
Vendored
+2
@@ -12,6 +12,7 @@ const tasks_1 = __importDefault(require("./routes/tasks"));
|
||||
const subtasks_1 = __importDefault(require("./routes/subtasks"));
|
||||
const users_1 = __importDefault(require("./routes/users"));
|
||||
const friends_1 = __importDefault(require("./routes/friends"));
|
||||
const repeatProfiles_1 = __importDefault(require("./routes/repeatProfiles"));
|
||||
const sync_1 = __importDefault(require("./routes/sync"));
|
||||
const errorHandler_1 = require("./middleware/errorHandler");
|
||||
const app = (0, express_1.default)();
|
||||
@@ -31,6 +32,7 @@ app.use('/api/categories', categories_1.default);
|
||||
app.use('/api/tasks', tasks_1.default);
|
||||
app.use('/api/subtasks', subtasks_1.default);
|
||||
app.use('/api/users', users_1.default);
|
||||
app.use('/api/repeat-profiles', repeatProfiles_1.default);
|
||||
app.use('/api/sync', sync_1.default);
|
||||
app.use('/api/friends', friends_1.default);
|
||||
// 404 handler
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,yBAAuB;AACvB,sDAA8B;AAC9B,gDAAwB;AACxB,yDAAuC;AACvC,qEAAiD;AACjD,2DAAwC;AACxC,iEAA8C;AAC9C,2DAAwC;AACxC,+DAA4C;AAC5C,yDAAuC;AACvC,4DAA0E;AAE1E,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AAEtC,GAAG,CAAC,GAAG,CAAC,IAAA,cAAI,EAAC;IACX,MAAM,EAAE,IAAI;IACZ,WAAW,EAAE,IAAI;CAClB,CAAC,CAAC,CAAC;AACJ,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAExB,eAAe;AACf,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,aAAa;AACb,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,cAAU,CAAC,CAAC;AACjC,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,oBAAc,CAAC,CAAC;AAC3C,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,eAAU,CAAC,CAAC;AAClC,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,kBAAa,CAAC,CAAC;AACxC,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,eAAU,CAAC,CAAC;AAClC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,cAAU,CAAC,CAAC;AACjC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,iBAAY,CAAC,CAAC;AAEtC,cAAc;AACd,GAAG,CAAC,GAAG,CAAC,8BAAe,CAAC,CAAC;AAEzB,gBAAgB;AAChB,GAAG,CAAC,GAAG,CAAC,2BAAY,CAAC,CAAC;AAEtB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,yCAAyC,IAAI,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,wCAAwC,IAAI,MAAM,CAAC,CAAC;AAClE,CAAC,CAAC,CAAC;AAEH,kBAAe,GAAG,CAAC"}
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,yBAAuB;AACvB,sDAA8B;AAC9B,gDAAwB;AACxB,yDAAuC;AACvC,qEAAiD;AACjD,2DAAwC;AACxC,iEAA8C;AAC9C,2DAAwC;AACxC,+DAA4C;AAC5C,6EAA0D;AAC1D,yDAAuC;AACvC,4DAA0E;AAE1E,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC;AAEtC,GAAG,CAAC,GAAG,CAAC,IAAA,cAAI,EAAC;IACX,MAAM,EAAE,IAAI;IACZ,WAAW,EAAE,IAAI;CAClB,CAAC,CAAC,CAAC;AACJ,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAExB,eAAe;AACf,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,aAAa;AACb,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,cAAU,CAAC,CAAC;AACjC,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,oBAAc,CAAC,CAAC;AAC3C,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,eAAU,CAAC,CAAC;AAClC,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,kBAAa,CAAC,CAAC;AACxC,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,eAAU,CAAC,CAAC;AAClC,GAAG,CAAC,GAAG,CAAC,sBAAsB,EAAE,wBAAmB,CAAC,CAAC;AACrD,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,cAAU,CAAC,CAAC;AACjC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,iBAAY,CAAC,CAAC;AAEtC,cAAc;AACd,GAAG,CAAC,GAAG,CAAC,8BAAe,CAAC,CAAC;AAEzB,gBAAgB;AAChB,GAAG,CAAC,GAAG,CAAC,2BAAY,CAAC,CAAC;AAEtB,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,yCAAyC,IAAI,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,wCAAwC,IAAI,MAAM,CAAC,CAAC;AAClE,CAAC,CAAC,CAAC;AAEH,kBAAe,GAAG,CAAC"}
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAmFxB,eAAe,MAAM,CAAC"}
|
||||
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/routes/auth.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA0LxB,eAAe,MAAM,CAAC"}
|
||||
Vendored
+101
-9
@@ -1,4 +1,7 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const asyncHandler_1 = require("../utils/asyncHandler");
|
||||
@@ -8,7 +11,47 @@ const drizzle_orm_1 = require("drizzle-orm");
|
||||
const auth_1 = require("../utils/auth");
|
||||
const errorHandler_1 = require("../middleware/errorHandler");
|
||||
const zod_1 = require("zod");
|
||||
const bcryptjs_1 = __importDefault(require("bcryptjs"));
|
||||
const express_rate_limit_1 = __importDefault(require("express-rate-limit"));
|
||||
const crypto_1 = __importDefault(require("crypto"));
|
||||
const router = (0, express_1.Router)();
|
||||
// Rate limiting for auth endpoints
|
||||
const authLimiter = (0, express_rate_limit_1.default)({
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
max: 10, // limit each IP to 10 requests per windowMs
|
||||
message: {
|
||||
error: {
|
||||
code: 'RATE_LIMITED',
|
||||
message: 'Too many attempts. Please try again later.',
|
||||
},
|
||||
},
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
});
|
||||
const loginLimiter = (0, express_rate_limit_1.default)({
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
max: 5, // stricter limit for login
|
||||
message: {
|
||||
error: {
|
||||
code: 'RATE_LIMITED',
|
||||
message: 'Too many login attempts. Please try again later.',
|
||||
},
|
||||
},
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
});
|
||||
const passwordResetLimiter = (0, express_rate_limit_1.default)({
|
||||
windowMs: 60 * 60 * 1000, // 1 hour
|
||||
max: 3, // very strict for password reset
|
||||
message: {
|
||||
error: {
|
||||
code: 'RATE_LIMITED',
|
||||
message: 'Too many password reset requests. Please try again later.',
|
||||
},
|
||||
},
|
||||
standardHeaders: true,
|
||||
legacyHeaders: false,
|
||||
});
|
||||
const usernameSchema = zod_1.z
|
||||
.string()
|
||||
.min(3)
|
||||
@@ -22,15 +65,24 @@ const loginSchema = zod_1.z.object({
|
||||
username: zod_1.z.string(),
|
||||
password: zod_1.z.string(),
|
||||
});
|
||||
// In production, use bcrypt or argon2 for password hashing
|
||||
function hashPassword(password) {
|
||||
// Simple hash for demo - replace with bcrypt in production
|
||||
return Buffer.from(password).toString('base64');
|
||||
const forgotPasswordSchema = zod_1.z.object({
|
||||
username: zod_1.z.string().min(1),
|
||||
});
|
||||
const resetPasswordSchema = zod_1.z.object({
|
||||
token: zod_1.z.string().min(1),
|
||||
password: zod_1.z.string().min(8),
|
||||
});
|
||||
const BCRYPT_ROUNDS = 12;
|
||||
async function hashPassword(password) {
|
||||
return bcryptjs_1.default.hash(password, BCRYPT_ROUNDS);
|
||||
}
|
||||
function verifyPassword(password, hash) {
|
||||
return hashPassword(password) === hash;
|
||||
async function verifyPassword(password, hash) {
|
||||
return bcryptjs_1.default.compare(password, hash);
|
||||
}
|
||||
router.post('/register', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
function generateResetToken() {
|
||||
return crypto_1.default.randomBytes(32).toString('hex');
|
||||
}
|
||||
router.post('/register', authLimiter, (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const data = registerSchema.parse(req.body);
|
||||
const existing = await db_1.db.select().from(schema_1.users).where((0, drizzle_orm_1.eq)(schema_1.users.username, data.username)).limit(1);
|
||||
if (existing.length > 0) {
|
||||
@@ -41,7 +93,7 @@ router.post('/register', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
await db_1.db.insert(schema_1.users).values({
|
||||
id: userId,
|
||||
username: data.username,
|
||||
passwordHash: hashPassword(data.password),
|
||||
passwordHash: await hashPassword(data.password),
|
||||
createdAt: now,
|
||||
});
|
||||
const token = (0, auth_1.generateToken)({ userId, username: data.username });
|
||||
@@ -50,7 +102,7 @@ router.post('/register', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
token,
|
||||
});
|
||||
}));
|
||||
router.post('/login', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
router.post('/login', loginLimiter, (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const data = loginSchema.parse(req.body);
|
||||
const user = await db_1.db.select().from(schema_1.users).where((0, drizzle_orm_1.eq)(schema_1.users.username, data.username)).limit(1);
|
||||
if (user.length === 0 || !verifyPassword(data.password, user[0].passwordHash)) {
|
||||
@@ -72,5 +124,45 @@ router.get('/me', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
}
|
||||
res.json({ id: user[0].id, username: user[0].username });
|
||||
}));
|
||||
router.post('/forgot-password', passwordResetLimiter, (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const data = forgotPasswordSchema.parse(req.body);
|
||||
const user = await db_1.db.select().from(schema_1.users).where((0, drizzle_orm_1.eq)(schema_1.users.username, data.username)).limit(1);
|
||||
// Always return success to prevent username enumeration
|
||||
if (user.length === 0) {
|
||||
res.json({ success: true });
|
||||
return;
|
||||
}
|
||||
const resetToken = generateResetToken();
|
||||
const resetTokenExpiry = Date.now() + 3600000; // 1 hour
|
||||
await db_1.db
|
||||
.update(schema_1.users)
|
||||
.set({ resetToken, resetTokenExpiry })
|
||||
.where((0, drizzle_orm_1.eq)(schema_1.users.id, user[0].id));
|
||||
// In production, send email with reset link
|
||||
// For now, return token in response (dev only)
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
res.json({ success: true, resetToken });
|
||||
}
|
||||
else {
|
||||
res.json({ success: true });
|
||||
}
|
||||
}));
|
||||
router.post('/reset-password', passwordResetLimiter, (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const data = resetPasswordSchema.parse(req.body);
|
||||
const user = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.users)
|
||||
.where((0, drizzle_orm_1.eq)(schema_1.users.resetToken, data.token))
|
||||
.limit(1);
|
||||
if (user.length === 0 || !user[0].resetTokenExpiry || user[0].resetTokenExpiry < Date.now()) {
|
||||
throw new errorHandler_1.AppError('INVALID_TOKEN', 'Invalid or expired reset token', 400);
|
||||
}
|
||||
const newPasswordHash = await hashPassword(data.password);
|
||||
await db_1.db
|
||||
.update(schema_1.users)
|
||||
.set({ passwordHash: newPasswordHash, resetToken: null, resetTokenExpiry: null })
|
||||
.where((0, drizzle_orm_1.eq)(schema_1.users.id, user[0].id));
|
||||
res.json({ success: true });
|
||||
}));
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=auth.js.map
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"friends.d.ts","sourceRoot":"","sources":["../../src/routes/friends.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAsKxB,eAAe,MAAM,CAAC"}
|
||||
{"version":3,"file":"friends.d.ts","sourceRoot":"","sources":["../../src/routes/friends.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAuLxB,eAAe,MAAM,CAAC"}
|
||||
Vendored
+11
@@ -53,6 +53,17 @@ router.get('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
}));
|
||||
res.json({ friends, incoming, outgoing });
|
||||
}));
|
||||
router.get('/search', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const { q } = validation_1.searchQuerySchema.parse(req.query);
|
||||
const userId = req.user.userId;
|
||||
const results = await db_1.db
|
||||
.select({ id: schema_1.users.id, username: schema_1.users.username })
|
||||
.from(schema_1.users)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.ne)(schema_1.users.id, userId), (0, drizzle_orm_1.ilike)(schema_1.users.username, `%${q}%`)))
|
||||
.orderBy((0, drizzle_orm_1.asc)(schema_1.users.username))
|
||||
.limit(20);
|
||||
res.json(results);
|
||||
}));
|
||||
router.post('/requests', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const { username } = validation_1.friendRequestSchema.parse(req.body);
|
||||
const userId = req.user.userId;
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+3
@@ -0,0 +1,3 @@
|
||||
declare const router: import("express-serve-static-core").Router;
|
||||
export default router;
|
||||
//# sourceMappingURL=repeatProfiles.d.ts.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"repeatProfiles.d.ts","sourceRoot":"","sources":["../../src/routes/repeatProfiles.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA+ExB,eAAe,MAAM,CAAC"}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const asyncHandler_1 = require("../utils/asyncHandler");
|
||||
const db_1 = require("../db");
|
||||
const schema_1 = require("../db/schema");
|
||||
const drizzle_orm_1 = require("drizzle-orm");
|
||||
const auth_1 = require("../utils/auth");
|
||||
const auth_2 = require("../utils/auth");
|
||||
const errorHandler_1 = require("../middleware/errorHandler");
|
||||
const validation_1 = require("../utils/validation");
|
||||
const router = (0, express_1.Router)();
|
||||
router.use(auth_1.authMiddleware);
|
||||
router.get('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const profiles = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.repeatProfiles)
|
||||
.where((0, drizzle_orm_1.eq)(schema_1.repeatProfiles.userId, req.user.userId))
|
||||
.orderBy((0, drizzle_orm_1.asc)(schema_1.repeatProfiles.createdAt));
|
||||
res.json({ profiles });
|
||||
}));
|
||||
router.post('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const data = validation_1.repeatProfileSchema.parse(req.body);
|
||||
const userId = req.user.userId;
|
||||
const now = Date.now();
|
||||
const newProfile = {
|
||||
id: (0, auth_2.generateId)('rp'),
|
||||
userId,
|
||||
name: data.name,
|
||||
repeat: data.repeat,
|
||||
repeatInterval: data.repeatInterval,
|
||||
repeatDays: data.repeatDays,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
await db_1.db.insert(schema_1.repeatProfiles).values(newProfile);
|
||||
res.status(201).json(newProfile);
|
||||
}));
|
||||
router.patch('/:id', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const data = validation_1.repeatProfileUpdateSchema.parse(req.body);
|
||||
const userId = req.user.userId;
|
||||
const existing = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.repeatProfiles)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.repeatProfiles.id, req.params.id), (0, drizzle_orm_1.eq)(schema_1.repeatProfiles.userId, userId)))
|
||||
.limit(1);
|
||||
if (existing.length === 0) {
|
||||
throw new errorHandler_1.AppError('NOT_FOUND', 'Repeat profile not found', 404);
|
||||
}
|
||||
const now = Date.now();
|
||||
const updated = await db_1.db
|
||||
.update(schema_1.repeatProfiles)
|
||||
.set({ ...data, updatedAt: now })
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.repeatProfiles.id, req.params.id), (0, drizzle_orm_1.eq)(schema_1.repeatProfiles.userId, userId)))
|
||||
.returning();
|
||||
res.json(updated[0]);
|
||||
}));
|
||||
router.delete('/:id', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const userId = req.user.userId;
|
||||
const existing = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.repeatProfiles)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.repeatProfiles.id, req.params.id), (0, drizzle_orm_1.eq)(schema_1.repeatProfiles.userId, userId)))
|
||||
.limit(1);
|
||||
if (existing.length === 0) {
|
||||
throw new errorHandler_1.AppError('NOT_FOUND', 'Repeat profile not found', 404);
|
||||
}
|
||||
await db_1.db
|
||||
.delete(schema_1.repeatProfiles)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.repeatProfiles.id, req.params.id), (0, drizzle_orm_1.eq)(schema_1.repeatProfiles.userId, userId)));
|
||||
res.status(204).send();
|
||||
}));
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=repeatProfiles.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"repeatProfiles.js","sourceRoot":"","sources":["../../src/routes/repeatProfiles.ts"],"names":[],"mappings":"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"}
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"subtasks.d.ts","sourceRoot":"","sources":["../../src/routes/subtasks.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAmIxB,eAAe,MAAM,CAAC"}
|
||||
{"version":3,"file":"subtasks.d.ts","sourceRoot":"","sources":["../../src/routes/subtasks.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,MAAM,4CAAW,CAAC;AAoKxB,eAAe,MAAM,CAAC"}
|
||||
Vendored
+28
-2
@@ -10,6 +10,16 @@ const errorHandler_1 = require("../middleware/errorHandler");
|
||||
const validation_1 = require("../utils/validation");
|
||||
const router = (0, express_1.Router)();
|
||||
router.use(auth_1.authMiddleware);
|
||||
// Helper to build nested subtask tree
|
||||
const buildSubtaskTree = (allSubtasks, parentId = null) => {
|
||||
return allSubtasks
|
||||
.filter((s) => s.parentSubtaskId === parentId)
|
||||
.sort((a, b) => a.order - b.order)
|
||||
.map((s) => ({
|
||||
...s,
|
||||
subtasks: buildSubtaskTree(allSubtasks, s.id),
|
||||
}));
|
||||
};
|
||||
router.get('/task/:taskId', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const userId = req.user.userId;
|
||||
// Verify task exists and belongs to user
|
||||
@@ -26,7 +36,8 @@ router.get('/task/:taskId', (0, asyncHandler_1.asyncHandler)(async (req, res) =>
|
||||
.from(schema_1.subtasks)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.subtasks.taskId, req.params.taskId), (0, drizzle_orm_1.eq)(schema_1.subtasks.userId, userId)))
|
||||
.orderBy((0, drizzle_orm_1.asc)(schema_1.subtasks.order));
|
||||
res.json({ subtasks: taskSubtasks });
|
||||
const nestedSubtasks = buildSubtaskTree(taskSubtasks);
|
||||
res.json({ subtasks: nestedSubtasks });
|
||||
}));
|
||||
router.post('/task/:taskId', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const data = validation_1.subtaskCreateSchema.parse(req.body);
|
||||
@@ -40,10 +51,11 @@ router.post('/task/:taskId', (0, asyncHandler_1.asyncHandler)(async (req, res) =
|
||||
throw new errorHandler_1.AppError('NOT_FOUND', 'Task not found', 404);
|
||||
}
|
||||
const now = Date.now();
|
||||
const parentSubtaskId = data.parentSubtaskId || null;
|
||||
const maxOrder = await db_1.db
|
||||
.select({ order: schema_1.subtasks.order })
|
||||
.from(schema_1.subtasks)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.subtasks.taskId, req.params.taskId), (0, drizzle_orm_1.eq)(schema_1.subtasks.userId, userId)))
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.subtasks.taskId, req.params.taskId), (0, drizzle_orm_1.eq)(schema_1.subtasks.userId, userId), parentSubtaskId ? (0, drizzle_orm_1.eq)(schema_1.subtasks.parentSubtaskId, parentSubtaskId) : (0, drizzle_orm_1.isNull)(schema_1.subtasks.parentSubtaskId)))
|
||||
.orderBy((0, drizzle_orm_1.desc)(schema_1.subtasks.order))
|
||||
.limit(1);
|
||||
const subtaskId = `sub_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
|
||||
@@ -51,8 +63,22 @@ router.post('/task/:taskId', (0, asyncHandler_1.asyncHandler)(async (req, res) =
|
||||
id: subtaskId,
|
||||
userId,
|
||||
taskId: req.params.taskId,
|
||||
parentSubtaskId,
|
||||
title: data.title,
|
||||
description: data.description ?? '',
|
||||
priority: data.priority ?? 'none',
|
||||
completed: false,
|
||||
dueDate: data.dueDate ?? 0,
|
||||
dueTime: data.dueTime ?? '',
|
||||
endTime: data.endTime ?? '',
|
||||
allDay: data.allDay ?? false,
|
||||
repeat: data.repeat ?? 'none',
|
||||
repeatInterval: data.repeatInterval ?? 1,
|
||||
repeatDays: data.repeatDays ?? '',
|
||||
seriesId: data.seriesId ?? '',
|
||||
reminder: data.reminder ?? 'none',
|
||||
reminders: data.reminders ?? '',
|
||||
assigneeId: data.assigneeId ?? null,
|
||||
order: data.order ?? (maxOrder[0]?.order ?? -1) + 1,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA8SxB,eAAe,MAAM,CAAC"}
|
||||
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/routes/sync.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA2lBxB,eAAe,MAAM,CAAC"}
|
||||
Vendored
+281
-5
@@ -27,9 +27,8 @@ router.get('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.tasks.userId, userId), (0, drizzle_orm_1.gte)(schema_1.tasks.updatedAt, sinceDate)))
|
||||
.orderBy((0, drizzle_orm_1.asc)(schema_1.tasks.updatedAt));
|
||||
// Fetch subtasks changed since timestamp
|
||||
const taskIds = changedTasks.map(t => t.id);
|
||||
let changedSubtasks = [];
|
||||
if (taskIds.length > 0) {
|
||||
if (changedTasks.length > 0) {
|
||||
changedSubtasks = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.subtasks)
|
||||
@@ -37,7 +36,7 @@ router.get('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
.orderBy((0, drizzle_orm_1.asc)(schema_1.subtasks.updatedAt));
|
||||
}
|
||||
else {
|
||||
// Also fetch subtasks for tasks that might have been deleted (we track by updatedAt)
|
||||
// Also fetch subtasks for tasks that might have been deleted
|
||||
changedSubtasks = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.subtasks)
|
||||
@@ -56,6 +55,12 @@ router.get('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
.from(schema_1.friendships)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.or)((0, drizzle_orm_1.eq)(schema_1.friendships.userId, userId), (0, drizzle_orm_1.eq)(schema_1.friendships.friendId, userId)), (0, drizzle_orm_1.gte)(schema_1.friendships.updatedAt, sinceDate)))
|
||||
.orderBy((0, drizzle_orm_1.asc)(schema_1.friendships.updatedAt));
|
||||
// Fetch tombstones (deletions) changed since timestamp
|
||||
const changedTombstones = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.tombstones)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.tombstones.userId, userId), (0, drizzle_orm_1.gte)(schema_1.tombstones.updatedAt, sinceDate)))
|
||||
.orderBy((0, drizzle_orm_1.asc)(schema_1.tombstones.updatedAt));
|
||||
const timestamp = Date.now();
|
||||
res.json({
|
||||
categories: changedCategories,
|
||||
@@ -63,6 +68,7 @@ router.get('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
subtasks: changedSubtasks,
|
||||
repeatProfiles: changedRepeatProfiles,
|
||||
friendships: changedFriendships,
|
||||
deleted: changedTombstones.map((t) => ({ entity: t.entity, id: t.entityId, updatedAt: t.updatedAt })),
|
||||
timestamp,
|
||||
});
|
||||
}));
|
||||
@@ -73,6 +79,65 @@ router.post('/push', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const timestamp = Date.now();
|
||||
try {
|
||||
await db_1.db.transaction(async (tx) => {
|
||||
// Ensure every referenced category exists (FK integrity) so a stale or
|
||||
// never-synced category reference cannot fail the entire push. Missing
|
||||
// categories are recreated as a fallback and the client heals on pull.
|
||||
const referencedCategoryIds = new Set();
|
||||
for (const task of data.changes.tasks ?? []) {
|
||||
if (task.categoryId)
|
||||
referencedCategoryIds.add(task.categoryId);
|
||||
}
|
||||
for (const sub of data.changes.subtasks ?? []) {
|
||||
const task = (data.changes.tasks ?? []).find((t) => t.id === sub.taskId);
|
||||
if (task?.categoryId)
|
||||
referencedCategoryIds.add(task.categoryId);
|
||||
}
|
||||
if (referencedCategoryIds.size > 0) {
|
||||
const existing = await tx
|
||||
.select({ id: schema_1.categories.id })
|
||||
.from(schema_1.categories)
|
||||
.where((0, drizzle_orm_1.inArray)(schema_1.categories.id, [...referencedCategoryIds]));
|
||||
const existingIds = new Set(existing.map((c) => c.id));
|
||||
const missing = [...referencedCategoryIds].filter((id) => !existingIds.has(id));
|
||||
if (missing.length > 0) {
|
||||
const rows = await tx
|
||||
.select({ max: (0, drizzle_orm_1.sql) `max(${schema_1.categories.order})` })
|
||||
.from(schema_1.categories)
|
||||
.where((0, drizzle_orm_1.eq)(schema_1.categories.userId, userId));
|
||||
const startOrder = (rows[0]?.max ?? -1) + 1;
|
||||
await tx.insert(schema_1.categories).values(missing.map((id, i) => ({
|
||||
id,
|
||||
userId,
|
||||
name: 'Default',
|
||||
color: '#9E9E9E',
|
||||
order: startOrder + i,
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
})));
|
||||
}
|
||||
}
|
||||
// Sanitize assignee references: only real user ids may be stored (FK).
|
||||
// Stale/unknown assignee ids are silently dropped to null instead of
|
||||
// failing the whole push transaction.
|
||||
const assigneeIds = new Set();
|
||||
for (const task of data.changes.tasks ?? []) {
|
||||
if (task.assigneeId)
|
||||
assigneeIds.add(task.assigneeId);
|
||||
}
|
||||
for (const sub of data.changes.subtasks ?? []) {
|
||||
if (sub.assigneeId)
|
||||
assigneeIds.add(sub.assigneeId);
|
||||
}
|
||||
const validAssignees = new Set();
|
||||
if (assigneeIds.size > 0) {
|
||||
const rows = await tx
|
||||
.select({ id: schema_1.users.id })
|
||||
.from(schema_1.users)
|
||||
.where((0, drizzle_orm_1.inArray)(schema_1.users.id, [...assigneeIds]));
|
||||
for (const r of rows)
|
||||
validAssignees.add(r.id);
|
||||
}
|
||||
const sanitizeAssignee = (a) => a && validAssignees.has(a) ? a : null;
|
||||
// Process categories
|
||||
if (data.changes.categories && data.changes.categories.length > 0) {
|
||||
for (const cat of data.changes.categories) {
|
||||
@@ -131,6 +196,20 @@ router.post('/push', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
});
|
||||
continue; // Server wins
|
||||
}
|
||||
// Prevent completing tasks with future due dates
|
||||
if (task.completed === true) {
|
||||
const effectiveDueDate = task.dueDate ?? existing[0].dueDate;
|
||||
if (!(0, validation_1.canCompleteTask)(effectiveDueDate)) {
|
||||
conflicts.push({
|
||||
entity: 'tasks',
|
||||
id: task.id,
|
||||
serverVersion: existing[0],
|
||||
clientVersion: task,
|
||||
resolution: 'server_wins',
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
await tx
|
||||
.update(schema_1.tasks)
|
||||
.set({
|
||||
@@ -140,14 +219,17 @@ router.post('/push', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
priority: task.priority,
|
||||
completed: task.completed,
|
||||
dueDate: task.dueDate,
|
||||
dueTime: task.dueTime,
|
||||
dueTime: task.dueTime ?? '',
|
||||
endTime: task.endTime ?? '',
|
||||
allDay: task.allDay ?? false,
|
||||
repeat: task.repeat ?? 'none',
|
||||
repeatInterval: task.repeatInterval ?? 1,
|
||||
repeatDays: task.repeatDays ?? '',
|
||||
seriesId: task.seriesId ?? '',
|
||||
reminder: task.reminder ?? 'none',
|
||||
assigneeId: task.assigneeId ?? null,
|
||||
reminders: task.reminders ?? '',
|
||||
assigneeId: sanitizeAssignee(task.assigneeId),
|
||||
completedAt: task.completedAt ?? null,
|
||||
updatedAt: task.updatedAt,
|
||||
})
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.tasks.id, task.id), (0, drizzle_orm_1.eq)(schema_1.tasks.userId, userId)));
|
||||
@@ -155,6 +237,8 @@ router.post('/push', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
else {
|
||||
await tx.insert(schema_1.tasks).values({
|
||||
...task,
|
||||
assigneeId: sanitizeAssignee(task.assigneeId),
|
||||
allDay: task.allDay ?? false,
|
||||
userId,
|
||||
});
|
||||
}
|
||||
@@ -184,8 +268,22 @@ router.post('/push', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
.update(schema_1.subtasks)
|
||||
.set({
|
||||
taskId: sub.taskId,
|
||||
parentSubtaskId: sub.parentSubtaskId ?? null,
|
||||
title: sub.title,
|
||||
description: sub.description ?? '',
|
||||
priority: sub.priority ?? 'none',
|
||||
completed: sub.completed,
|
||||
dueDate: sub.dueDate ?? 0,
|
||||
dueTime: sub.dueTime ?? '',
|
||||
endTime: sub.endTime ?? '',
|
||||
allDay: sub.allDay ?? false,
|
||||
repeat: sub.repeat ?? 'none',
|
||||
repeatInterval: sub.repeatInterval ?? 1,
|
||||
repeatDays: sub.repeatDays ?? '',
|
||||
seriesId: sub.seriesId ?? '',
|
||||
reminder: sub.reminder ?? 'none',
|
||||
reminders: sub.reminders ?? '',
|
||||
assigneeId: sanitizeAssignee(sub.assigneeId),
|
||||
order: sub.order,
|
||||
updatedAt: sub.updatedAt,
|
||||
})
|
||||
@@ -194,6 +292,7 @@ router.post('/push', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
else {
|
||||
await tx.insert(schema_1.subtasks).values({
|
||||
...sub,
|
||||
assigneeId: sanitizeAssignee(sub.assigneeId),
|
||||
userId,
|
||||
});
|
||||
}
|
||||
@@ -273,6 +372,13 @@ router.post('/push', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Process deletions (tombstones) - last so they see the state produced
|
||||
// by the upserts above and resolve by last-writer-wins.
|
||||
if (data.deleted && data.deleted.length > 0) {
|
||||
for (const deleted of data.deleted) {
|
||||
await applyTombstone(tx, deleted.entity, deleted.id, deleted.updatedAt, userId, conflicts);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
@@ -285,5 +391,175 @@ router.post('/push', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
conflicts,
|
||||
});
|
||||
}));
|
||||
// Upsert a tombstone row, keeping the latest updatedAt.
|
||||
async function upsertTombstone(tx, entity, entityId, updatedAt, userId) {
|
||||
const existing = await tx
|
||||
.select({ updatedAt: schema_1.tombstones.updatedAt })
|
||||
.from(schema_1.tombstones)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.tombstones.entity, entity), (0, drizzle_orm_1.eq)(schema_1.tombstones.entityId, entityId)))
|
||||
.limit(1);
|
||||
const merged = Math.max(existing[0]?.updatedAt ?? 0, updatedAt);
|
||||
if (existing.length > 0) {
|
||||
await tx
|
||||
.update(schema_1.tombstones)
|
||||
.set({ updatedAt: merged })
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.tombstones.entity, entity), (0, drizzle_orm_1.eq)(schema_1.tombstones.entityId, entityId)));
|
||||
}
|
||||
else {
|
||||
await tx.insert(schema_1.tombstones).values({ entity, entityId, userId, updatedAt: merged });
|
||||
}
|
||||
}
|
||||
// Apply a client deletion. LWW: if the server row is newer than the deletion
|
||||
// timestamp, the deletion is rejected (server_wins conflict) so the client
|
||||
// re-pulls the row. Accepted deletions cascade tombstones to every FK-cascaded
|
||||
// child so all devices remove them too.
|
||||
async function applyTombstone(tx, entity, id, deletedAt, userId, conflicts) {
|
||||
const tombstoneOf = (e, ids) => ids.forEach((i) => upsertTombstone(tx, e, i, deletedAt, userId));
|
||||
if (entity === 'tasks') {
|
||||
const row = await tx
|
||||
.select()
|
||||
.from(schema_1.tasks)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.tasks.id, id), (0, drizzle_orm_1.eq)(schema_1.tasks.userId, userId)))
|
||||
.limit(1);
|
||||
if (row.length === 0) {
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
if (row[0].updatedAt > deletedAt) {
|
||||
conflicts.push({
|
||||
entity: 'tasks',
|
||||
id,
|
||||
serverVersion: row[0],
|
||||
clientVersion: { id, updatedAt: deletedAt },
|
||||
resolution: 'server_wins',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const children = await tx
|
||||
.select({ id: schema_1.subtasks.id })
|
||||
.from(schema_1.subtasks)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.subtasks.taskId, id), (0, drizzle_orm_1.eq)(schema_1.subtasks.userId, userId)));
|
||||
tombstoneOf('subtasks', children.map((c) => c.id));
|
||||
await tx.delete(schema_1.tasks).where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.tasks.id, id), (0, drizzle_orm_1.eq)(schema_1.tasks.userId, userId)));
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
if (entity === 'categories') {
|
||||
const row = await tx
|
||||
.select()
|
||||
.from(schema_1.categories)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.categories.id, id), (0, drizzle_orm_1.eq)(schema_1.categories.userId, userId)))
|
||||
.limit(1);
|
||||
if (row.length === 0) {
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
if (row[0].updatedAt > deletedAt) {
|
||||
conflicts.push({
|
||||
entity: 'categories',
|
||||
id,
|
||||
serverVersion: row[0],
|
||||
clientVersion: { id, updatedAt: deletedAt },
|
||||
resolution: 'server_wins',
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Deleting the category cascades its tasks (and their subtasks) -
|
||||
// tombstone all of them so every client removes them.
|
||||
const catTasks = await tx
|
||||
.select()
|
||||
.from(schema_1.tasks)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.tasks.categoryId, id), (0, drizzle_orm_1.eq)(schema_1.tasks.userId, userId)));
|
||||
for (const taskRow of catTasks) {
|
||||
const subIds = await tx
|
||||
.select({ id: schema_1.subtasks.id })
|
||||
.from(schema_1.subtasks)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.subtasks.taskId, taskRow.id), (0, drizzle_orm_1.eq)(schema_1.subtasks.userId, userId)));
|
||||
tombstoneOf('subtasks', subIds.map((s) => s.id));
|
||||
tombstoneOf('tasks', [taskRow.id]);
|
||||
}
|
||||
await tx.delete(schema_1.categories).where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.categories.id, id), (0, drizzle_orm_1.eq)(schema_1.categories.userId, userId)));
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
if (entity === 'subtasks') {
|
||||
const row = await tx
|
||||
.select()
|
||||
.from(schema_1.subtasks)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.subtasks.id, id), (0, drizzle_orm_1.eq)(schema_1.subtasks.userId, userId)))
|
||||
.limit(1);
|
||||
if (row.length === 0) {
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
if (row[0].updatedAt > deletedAt) {
|
||||
conflicts.push({
|
||||
entity: 'subtasks',
|
||||
id,
|
||||
serverVersion: row[0],
|
||||
clientVersion: { id, updatedAt: deletedAt },
|
||||
resolution: 'server_wins',
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Deleting a parent subtask cascades its children in PG - tombstone them.
|
||||
const children = await tx
|
||||
.select({ id: schema_1.subtasks.id })
|
||||
.from(schema_1.subtasks)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.subtasks.parentSubtaskId, id), (0, drizzle_orm_1.eq)(schema_1.subtasks.userId, userId)));
|
||||
tombstoneOf('subtasks', children.map((c) => c.id));
|
||||
await tx.delete(schema_1.subtasks).where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.subtasks.id, id), (0, drizzle_orm_1.eq)(schema_1.subtasks.userId, userId)));
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
if (entity === 'repeatProfiles') {
|
||||
const row = await tx
|
||||
.select()
|
||||
.from(schema_1.repeatProfiles)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.repeatProfiles.id, id), (0, drizzle_orm_1.eq)(schema_1.repeatProfiles.userId, userId)))
|
||||
.limit(1);
|
||||
if (row.length === 0) {
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
if (row[0].updatedAt > deletedAt) {
|
||||
conflicts.push({
|
||||
entity: 'repeatProfiles',
|
||||
id,
|
||||
serverVersion: row[0],
|
||||
clientVersion: { id, updatedAt: deletedAt },
|
||||
resolution: 'server_wins',
|
||||
});
|
||||
return;
|
||||
}
|
||||
await tx.delete(schema_1.repeatProfiles).where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.repeatProfiles.id, id), (0, drizzle_orm_1.eq)(schema_1.repeatProfiles.userId, userId)));
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
if (entity === 'friendships') {
|
||||
const row = await tx
|
||||
.select()
|
||||
.from(schema_1.friendships)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.friendships.id, id), (0, drizzle_orm_1.or)((0, drizzle_orm_1.eq)(schema_1.friendships.userId, userId), (0, drizzle_orm_1.eq)(schema_1.friendships.friendId, userId))))
|
||||
.limit(1);
|
||||
if (row.length === 0) {
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
if (row[0].updatedAt > deletedAt) {
|
||||
conflicts.push({
|
||||
entity: 'friendships',
|
||||
id,
|
||||
serverVersion: row[0],
|
||||
clientVersion: { id, updatedAt: deletedAt },
|
||||
resolution: 'server_wins',
|
||||
});
|
||||
return;
|
||||
}
|
||||
await tx.delete(schema_1.friendships).where((0, drizzle_orm_1.eq)(schema_1.friendships.id, id));
|
||||
await upsertTombstone(tx, entity, id, deletedAt, userId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=sync.js.map
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/routes/tasks.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA8RxB,eAAe,MAAM,CAAC"}
|
||||
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/routes/tasks.ts"],"names":[],"mappings":"AAUA,QAAA,MAAM,MAAM,4CAAW,CAAC;AA+TxB,eAAe,MAAM,CAAC"}
|
||||
Vendored
+48
-15
@@ -97,14 +97,16 @@ router.post('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
const data = validation_1.taskCreateSchema.parse(req.body);
|
||||
const userId = req.user.userId;
|
||||
const now = Date.now();
|
||||
// Verify category exists and belongs to user
|
||||
const cat = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.categories)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.categories.id, data.categoryId), (0, drizzle_orm_1.eq)(schema_1.categories.userId, userId)))
|
||||
.limit(1);
|
||||
if (cat.length === 0) {
|
||||
throw new errorHandler_1.AppError('NOT_FOUND', 'Category not found', 404);
|
||||
// Verify category exists and belongs to user (optional - tasks may be uncategorized)
|
||||
if (data.categoryId) {
|
||||
const cat = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.categories)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.categories.id, data.categoryId), (0, drizzle_orm_1.eq)(schema_1.categories.userId, userId)))
|
||||
.limit(1);
|
||||
if (cat.length === 0) {
|
||||
throw new errorHandler_1.AppError('NOT_FOUND', 'Category not found', 404);
|
||||
}
|
||||
}
|
||||
const taskId = `task_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
|
||||
const newTask = {
|
||||
@@ -118,7 +120,10 @@ router.post('/', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
dueDate: data.dueDate ?? 0,
|
||||
dueTime: data.dueTime ?? '',
|
||||
endTime: data.endTime ?? '',
|
||||
allDay: data.allDay ?? false,
|
||||
assigneeId: data.assigneeId ?? null,
|
||||
reminder: data.reminder ?? 'none',
|
||||
reminders: data.reminders ?? '',
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
@@ -166,6 +171,13 @@ router.patch('/:id', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
throw new errorHandler_1.AppError('NOT_FOUND', 'Category not found', 404);
|
||||
}
|
||||
}
|
||||
// Prevent completing tasks with future due dates
|
||||
if (data.completed === true) {
|
||||
const effectiveDueDate = data.dueDate ?? existing[0].dueDate;
|
||||
if (!(0, validation_1.canCompleteTask)(effectiveDueDate)) {
|
||||
throw new errorHandler_1.AppError('VALIDATION_ERROR', 'Cannot mark a task as completed if its due date is in the future', 400);
|
||||
}
|
||||
}
|
||||
const now = Date.now();
|
||||
const updated = await db_1.db
|
||||
.update(schema_1.tasks)
|
||||
@@ -207,13 +219,15 @@ router.post('/batch', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
for (const op of operations) {
|
||||
try {
|
||||
if (op.type === 'create') {
|
||||
const cat = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.categories)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.categories.id, op.data.categoryId), (0, drizzle_orm_1.eq)(schema_1.categories.userId, userId)))
|
||||
.limit(1);
|
||||
if (cat.length === 0)
|
||||
throw new errorHandler_1.AppError('NOT_FOUND', 'Category not found', 404);
|
||||
if (op.data.categoryId) {
|
||||
const cat = await db_1.db
|
||||
.select()
|
||||
.from(schema_1.categories)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.categories.id, op.data.categoryId), (0, drizzle_orm_1.eq)(schema_1.categories.userId, userId)))
|
||||
.limit(1);
|
||||
if (cat.length === 0)
|
||||
throw new errorHandler_1.AppError('NOT_FOUND', 'Category not found', 404);
|
||||
}
|
||||
const taskId = `task_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
|
||||
const now = Date.now();
|
||||
await db_1.db.insert(schema_1.tasks).values({
|
||||
@@ -227,6 +241,25 @@ router.post('/batch', (0, asyncHandler_1.asyncHandler)(async (req, res) => {
|
||||
results.push({ id: taskId, success: true });
|
||||
}
|
||||
else if (op.type === 'update') {
|
||||
if (op.data.completed === true) {
|
||||
let effectiveDueDate;
|
||||
if (op.data.dueDate !== undefined) {
|
||||
effectiveDueDate = op.data.dueDate;
|
||||
}
|
||||
else {
|
||||
const existingTask = await db_1.db
|
||||
.select({ dueDate: schema_1.tasks.dueDate })
|
||||
.from(schema_1.tasks)
|
||||
.where((0, drizzle_orm_1.and)((0, drizzle_orm_1.eq)(schema_1.tasks.id, op.id), (0, drizzle_orm_1.eq)(schema_1.tasks.userId, userId)))
|
||||
.limit(1);
|
||||
if (existingTask.length === 0)
|
||||
throw new errorHandler_1.AppError('NOT_FOUND', 'Task not found', 404);
|
||||
effectiveDueDate = existingTask[0].dueDate;
|
||||
}
|
||||
if (!(0, validation_1.canCompleteTask)(effectiveDueDate)) {
|
||||
throw new errorHandler_1.AppError('VALIDATION_ERROR', 'Cannot mark a task as completed if its due date is in the future', 400);
|
||||
}
|
||||
}
|
||||
await db_1.db
|
||||
.update(schema_1.tasks)
|
||||
.set({ ...op.data, updatedAt: Date.now() })
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from 'express';
|
||||
import { AuthPayload } from '../types';
|
||||
export declare function generateToken(payload: AuthPayload): string;
|
||||
export declare function verifyToken(token: string): AuthPayload | null;
|
||||
export declare function authMiddleware(req: Request, res: Response, next: NextFunction): void;
|
||||
export declare function authMiddleware(req: Request, res: Response, next: NextFunction): Promise<void>;
|
||||
export declare function optionalAuthMiddleware(req: Request, res: Response, next: NextFunction): void;
|
||||
export declare function generateId(prefix?: string): string;
|
||||
export declare function getCurrentTimestamp(): number;
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAKvC,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAE1D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAM7D;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CA4BpF;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAW5F;AAED,wBAAgB,UAAU,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAItD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
|
||||
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK1D,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAKvC,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAE1D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAM7D;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCnG;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAW5F;AAED,wBAAgB,UAAU,CAAC,MAAM,GAAE,MAAW,GAAG,MAAM,CAItD;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
|
||||
Vendored
+14
-1
@@ -10,6 +10,9 @@ exports.optionalAuthMiddleware = optionalAuthMiddleware;
|
||||
exports.generateId = generateId;
|
||||
exports.getCurrentTimestamp = getCurrentTimestamp;
|
||||
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
||||
const db_1 = require("../db");
|
||||
const schema_1 = require("../db/schema");
|
||||
const drizzle_orm_1 = require("drizzle-orm");
|
||||
const JWT_SECRET = process.env.JWT_SECRET || 'your-super-secret-jwt-key-change-in-production';
|
||||
const JWT_EXPIRES_IN = '7d';
|
||||
function generateToken(payload) {
|
||||
@@ -23,7 +26,7 @@ function verifyToken(token) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function authMiddleware(req, res, next) {
|
||||
async function authMiddleware(req, res, next) {
|
||||
const authHeader = req.headers.authorization;
|
||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||
res.status(401).json({
|
||||
@@ -45,6 +48,16 @@ function authMiddleware(req, res, next) {
|
||||
});
|
||||
return;
|
||||
}
|
||||
const user = await db_1.db.select({ id: schema_1.users.id }).from(schema_1.users).where((0, drizzle_orm_1.eq)(schema_1.users.id, payload.userId)).limit(1);
|
||||
if (user.length === 0) {
|
||||
res.status(401).json({
|
||||
error: {
|
||||
code: 'UNAUTHORIZED',
|
||||
message: 'User no longer exists, please log in again',
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
req.user = payload;
|
||||
next();
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":";;;;;AAOA,sCAEC;AAED,kCAMC;AAED,wCA4BC;AAED,wDAWC;AAED,gCAIC;AAED,kDAEC;AArED,gEAA+B;AAG/B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,gDAAgD,CAAC;AAC9F,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B,SAAgB,aAAa,CAAC,OAAoB;IAChD,OAAO,sBAAG,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,CAAC;AACtE,CAAC;AAED,SAAgB,WAAW,CAAC,KAAa;IACvC,IAAI,CAAC;QACH,OAAO,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAgB,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IAC5E,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IAE7C,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,KAAK,EAAE;gBACL,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,yCAAyC;aACnD;SACF,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAEnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,KAAK,EAAE;gBACL,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,0BAA0B;aACpC;SACF,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC;IACnB,IAAI,EAAE,CAAC;AACT,CAAC;AAED,SAAgB,sBAAsB,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IACpF,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IAE7C,IAAI,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACnD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC;QACrB,CAAC;IACH,CAAC;IACD,IAAI,EAAE,CAAC;AACT,CAAC;AAED,SAAgB,UAAU,CAAC,SAAiB,EAAE;IAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAAC;AAC9D,CAAC;AAED,SAAgB,mBAAmB;IACjC,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;AACpB,CAAC"}
|
||||
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/utils/auth.ts"],"names":[],"mappings":"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"}
|
||||
Vendored
+370
-90
@@ -1,4 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
export declare function canCompleteTask(dueDate: number): boolean;
|
||||
export declare const categoryCreateSchema: z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
color: z.ZodString;
|
||||
@@ -26,20 +27,25 @@ export declare const categoryUpdateSchema: z.ZodObject<{
|
||||
order?: number | undefined;
|
||||
}>;
|
||||
export declare const repeatSchema: z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>;
|
||||
export declare const repeatFieldSchema: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>, z.ZodLiteral<"">]>, "custom" | "none" | "daily" | "weekly" | "monthly", "" | "custom" | "none" | "daily" | "weekly" | "monthly">>;
|
||||
export declare const repeatIntervalFieldSchema: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, number>>;
|
||||
export declare const taskCreateSchema: z.ZodObject<{
|
||||
title: z.ZodString;
|
||||
description: z.ZodOptional<z.ZodString>;
|
||||
categoryId: z.ZodString;
|
||||
categoryId: z.ZodNullable<z.ZodEffects<z.ZodString, string | null, string>>;
|
||||
priority: z.ZodOptional<z.ZodEnum<["none", "low", "medium", "high", "critical"]>>;
|
||||
dueDate: z.ZodOptional<z.ZodNumber>;
|
||||
dueTime: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
||||
dueTime: z.ZodEffects<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>, string, string | undefined>;
|
||||
endTime: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
|
||||
repeat: z.ZodOptional<z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>>;
|
||||
repeatInterval: z.ZodOptional<z.ZodNumber>;
|
||||
allDay: z.ZodOptional<z.ZodBoolean>;
|
||||
repeat: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>, z.ZodLiteral<"">]>, "custom" | "none" | "daily" | "weekly" | "monthly", "" | "custom" | "none" | "daily" | "weekly" | "monthly">>;
|
||||
repeatInterval: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, number>>;
|
||||
repeatDays: z.ZodOptional<z.ZodString>;
|
||||
seriesId: z.ZodOptional<z.ZodString>;
|
||||
reminder: z.ZodOptional<z.ZodEnum<["none", "at_time", "15", "30", "60", "120", "1440"]>>;
|
||||
reminders: z.ZodOptional<z.ZodString>;
|
||||
assigneeId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
||||
completedAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
||||
subtasks: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
||||
title: z.ZodString;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
@@ -48,93 +54,189 @@ export declare const taskCreateSchema: z.ZodObject<{
|
||||
title: string;
|
||||
}>, "many">>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
categoryId: string;
|
||||
categoryId: string | null;
|
||||
title: string;
|
||||
dueTime: string;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}, {
|
||||
categoryId: string;
|
||||
categoryId: string | null;
|
||||
title: string;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "" | "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}>;
|
||||
export declare const taskUpdateSchema: z.ZodObject<{
|
||||
title: z.ZodOptional<z.ZodString>;
|
||||
description: z.ZodOptional<z.ZodString>;
|
||||
categoryId: z.ZodOptional<z.ZodString>;
|
||||
categoryId: z.ZodEffects<z.ZodOptional<z.ZodNullable<z.ZodString>>, string | null | undefined, string | null | undefined>;
|
||||
priority: z.ZodOptional<z.ZodEnum<["none", "low", "medium", "high", "critical"]>>;
|
||||
completed: z.ZodOptional<z.ZodBoolean>;
|
||||
dueDate: z.ZodOptional<z.ZodNumber>;
|
||||
dueTime: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
||||
dueTime: z.ZodEffects<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>, string | undefined, string | undefined>;
|
||||
endTime: z.ZodOptional<z.ZodString>;
|
||||
reminders: z.ZodOptional<z.ZodString>;
|
||||
assigneeId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
||||
completedAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
categoryId?: string | undefined;
|
||||
categoryId?: string | null | undefined;
|
||||
title?: string | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
completed?: boolean | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}, {
|
||||
categoryId?: string | undefined;
|
||||
categoryId?: string | null | undefined;
|
||||
title?: string | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
completed?: boolean | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}>;
|
||||
export declare const subtaskCreateSchema: z.ZodObject<{
|
||||
title: z.ZodString;
|
||||
description: z.ZodOptional<z.ZodString>;
|
||||
priority: z.ZodOptional<z.ZodEnum<["none", "low", "medium", "high", "critical"]>>;
|
||||
dueDate: z.ZodOptional<z.ZodNumber>;
|
||||
dueTime: z.ZodEffects<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>, string, string | undefined>;
|
||||
endTime: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
|
||||
allDay: z.ZodOptional<z.ZodBoolean>;
|
||||
repeat: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>, z.ZodLiteral<"">]>, "custom" | "none" | "daily" | "weekly" | "monthly", "" | "custom" | "none" | "daily" | "weekly" | "monthly">>;
|
||||
repeatInterval: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, number>>;
|
||||
repeatDays: z.ZodOptional<z.ZodString>;
|
||||
seriesId: z.ZodOptional<z.ZodString>;
|
||||
reminder: z.ZodOptional<z.ZodEnum<["none", "at_time", "15", "30", "60", "120", "1440"]>>;
|
||||
reminders: z.ZodOptional<z.ZodString>;
|
||||
assigneeId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
||||
order: z.ZodOptional<z.ZodNumber>;
|
||||
parentSubtaskId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
title: string;
|
||||
dueTime: string;
|
||||
order?: number | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}, {
|
||||
title: string;
|
||||
order?: number | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "" | "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}>;
|
||||
export declare const subtaskUpdateSchema: z.ZodObject<{
|
||||
title: z.ZodOptional<z.ZodString>;
|
||||
description: z.ZodOptional<z.ZodString>;
|
||||
priority: z.ZodOptional<z.ZodEnum<["none", "low", "medium", "high", "critical"]>>;
|
||||
completed: z.ZodOptional<z.ZodBoolean>;
|
||||
dueDate: z.ZodOptional<z.ZodNumber>;
|
||||
dueTime: z.ZodEffects<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>, string | undefined, string | undefined>;
|
||||
endTime: z.ZodOptional<z.ZodString>;
|
||||
allDay: z.ZodOptional<z.ZodBoolean>;
|
||||
repeat: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>, z.ZodLiteral<"">]>, "custom" | "none" | "daily" | "weekly" | "monthly", "" | "custom" | "none" | "daily" | "weekly" | "monthly">>;
|
||||
repeatInterval: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, number>>;
|
||||
repeatDays: z.ZodOptional<z.ZodString>;
|
||||
seriesId: z.ZodOptional<z.ZodString>;
|
||||
reminder: z.ZodOptional<z.ZodEnum<["none", "at_time", "15", "30", "60", "120", "1440"]>>;
|
||||
reminders: z.ZodOptional<z.ZodString>;
|
||||
assigneeId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
||||
order: z.ZodOptional<z.ZodNumber>;
|
||||
parentSubtaskId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
order?: number | undefined;
|
||||
title?: string | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
completed?: boolean | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}, {
|
||||
order?: number | undefined;
|
||||
title?: string | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
completed?: boolean | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "" | "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}>;
|
||||
export declare const userSettingsSchema: z.ZodObject<{
|
||||
darkMode: z.ZodOptional<z.ZodBoolean>;
|
||||
@@ -174,6 +276,29 @@ export declare const repeatProfileSchema: z.ZodObject<{
|
||||
repeatInterval: number;
|
||||
repeatDays: string;
|
||||
}>;
|
||||
export declare const repeatProfileUpdateSchema: z.ZodObject<{
|
||||
name: z.ZodOptional<z.ZodString>;
|
||||
repeat: z.ZodOptional<z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>>;
|
||||
repeatInterval: z.ZodOptional<z.ZodNumber>;
|
||||
repeatDays: z.ZodOptional<z.ZodString>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
name?: string | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
}, {
|
||||
name?: string | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
}>;
|
||||
export declare const searchQuerySchema: z.ZodObject<{
|
||||
q: z.ZodString;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
q: string;
|
||||
}, {
|
||||
q: string;
|
||||
}>;
|
||||
export declare const friendRequestSchema: z.ZodObject<{
|
||||
username: z.ZodString;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
@@ -203,6 +328,19 @@ export declare const friendshipSchema: z.ZodObject<{
|
||||
status: "pending" | "accepted";
|
||||
updatedAt: number;
|
||||
}>;
|
||||
export declare const tombstoneSchema: z.ZodObject<{
|
||||
entity: z.ZodEnum<["categories", "tasks", "subtasks", "repeatProfiles", "friendships"]>;
|
||||
id: z.ZodString;
|
||||
updatedAt: z.ZodNumber;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
id: string;
|
||||
updatedAt: number;
|
||||
entity: "categories" | "tasks" | "subtasks" | "repeatProfiles" | "friendships";
|
||||
}, {
|
||||
id: string;
|
||||
updatedAt: number;
|
||||
entity: "categories" | "tasks" | "subtasks" | "repeatProfiles" | "friendships";
|
||||
}>;
|
||||
export declare const pushChangesSchema: z.ZodObject<{
|
||||
changes: z.ZodObject<{
|
||||
categories: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
||||
@@ -231,16 +369,18 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
tasks: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
||||
title: z.ZodString;
|
||||
description: z.ZodOptional<z.ZodString>;
|
||||
categoryId: z.ZodString;
|
||||
categoryId: z.ZodNullable<z.ZodEffects<z.ZodString, string | null, string>>;
|
||||
priority: z.ZodOptional<z.ZodEnum<["none", "low", "medium", "high", "critical"]>>;
|
||||
dueDate: z.ZodOptional<z.ZodNumber>;
|
||||
dueTime: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
||||
dueTime: z.ZodEffects<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>, string, string | undefined>;
|
||||
endTime: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
|
||||
repeat: z.ZodOptional<z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>>;
|
||||
repeatInterval: z.ZodOptional<z.ZodNumber>;
|
||||
allDay: z.ZodOptional<z.ZodBoolean>;
|
||||
repeat: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>, z.ZodLiteral<"">]>, "custom" | "none" | "daily" | "weekly" | "monthly", "" | "custom" | "none" | "daily" | "weekly" | "monthly">>;
|
||||
repeatInterval: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, number>>;
|
||||
repeatDays: z.ZodOptional<z.ZodString>;
|
||||
seriesId: z.ZodOptional<z.ZodString>;
|
||||
reminder: z.ZodOptional<z.ZodEnum<["none", "at_time", "15", "30", "60", "120", "1440"]>>;
|
||||
reminders: z.ZodOptional<z.ZodString>;
|
||||
assigneeId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
||||
subtasks: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
||||
title: z.ZodString;
|
||||
@@ -254,52 +394,73 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
completed: z.ZodBoolean;
|
||||
createdAt: z.ZodNumber;
|
||||
updatedAt: z.ZodNumber;
|
||||
completedAt: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
categoryId: string;
|
||||
categoryId: string | null;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
dueTime: string;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}, {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
categoryId: string;
|
||||
categoryId: string | null;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "" | "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}>, "many">>;
|
||||
subtasks: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
||||
title: z.ZodString;
|
||||
description: z.ZodOptional<z.ZodString>;
|
||||
priority: z.ZodOptional<z.ZodEnum<["none", "low", "medium", "high", "critical"]>>;
|
||||
dueDate: z.ZodOptional<z.ZodNumber>;
|
||||
dueTime: z.ZodEffects<z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>, string, string | undefined>;
|
||||
endTime: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
|
||||
allDay: z.ZodOptional<z.ZodBoolean>;
|
||||
repeat: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodEnum<["none", "daily", "weekly", "monthly", "custom"]>, z.ZodLiteral<"">]>, "custom" | "none" | "daily" | "weekly" | "monthly", "" | "custom" | "none" | "daily" | "weekly" | "monthly">>;
|
||||
repeatInterval: z.ZodOptional<z.ZodEffects<z.ZodNumber, number, number>>;
|
||||
repeatDays: z.ZodOptional<z.ZodString>;
|
||||
seriesId: z.ZodOptional<z.ZodString>;
|
||||
reminder: z.ZodOptional<z.ZodEnum<["none", "at_time", "15", "30", "60", "120", "1440"]>>;
|
||||
reminders: z.ZodOptional<z.ZodString>;
|
||||
assigneeId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
||||
order: z.ZodOptional<z.ZodNumber>;
|
||||
parentSubtaskId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
||||
} & {
|
||||
id: z.ZodString;
|
||||
taskId: z.ZodString;
|
||||
@@ -312,8 +473,22 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
updatedAt: number;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
dueTime: string;
|
||||
taskId: string;
|
||||
order?: number | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}, {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
@@ -322,6 +497,20 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
completed: boolean;
|
||||
taskId: string;
|
||||
order?: number | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "" | "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}>, "many">>;
|
||||
repeatProfiles: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
@@ -372,14 +561,6 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
updatedAt: number;
|
||||
}>, "many">>;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
friendships?: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
userId: string;
|
||||
friendId: string;
|
||||
status: "pending" | "accepted";
|
||||
updatedAt: number;
|
||||
}[] | undefined;
|
||||
categories?: {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -392,23 +573,26 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
id: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
categoryId: string;
|
||||
categoryId: string | null;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
dueTime: string;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}[] | undefined;
|
||||
subtasks?: {
|
||||
id: string;
|
||||
@@ -416,8 +600,22 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
updatedAt: number;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
dueTime: string;
|
||||
taskId: string;
|
||||
order?: number | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}[] | undefined;
|
||||
repeatProfiles?: {
|
||||
id: string;
|
||||
@@ -428,15 +626,15 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
repeatInterval: number;
|
||||
repeatDays: string;
|
||||
}[] | undefined;
|
||||
friendships?: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
userId: string;
|
||||
friendId: string;
|
||||
status: "pending" | "accepted";
|
||||
updatedAt: number;
|
||||
}[] | undefined;
|
||||
}, {
|
||||
friendships?: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
userId: string;
|
||||
friendId: string;
|
||||
status: "pending" | "accepted";
|
||||
updatedAt: number;
|
||||
}[] | undefined;
|
||||
categories?: {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -449,23 +647,26 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
id: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
categoryId: string;
|
||||
categoryId: string | null;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "" | "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}[] | undefined;
|
||||
subtasks?: {
|
||||
id: string;
|
||||
@@ -475,6 +676,20 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
completed: boolean;
|
||||
taskId: string;
|
||||
order?: number | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "" | "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}[] | undefined;
|
||||
repeatProfiles?: {
|
||||
id: string;
|
||||
@@ -485,18 +700,31 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
repeatInterval: number;
|
||||
repeatDays: string;
|
||||
}[] | undefined;
|
||||
friendships?: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
userId: string;
|
||||
friendId: string;
|
||||
status: "pending" | "accepted";
|
||||
updatedAt: number;
|
||||
}[] | undefined;
|
||||
}>;
|
||||
deleted: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
||||
entity: z.ZodEnum<["categories", "tasks", "subtasks", "repeatProfiles", "friendships"]>;
|
||||
id: z.ZodString;
|
||||
updatedAt: z.ZodNumber;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
id: string;
|
||||
updatedAt: number;
|
||||
entity: "categories" | "tasks" | "subtasks" | "repeatProfiles" | "friendships";
|
||||
}, {
|
||||
id: string;
|
||||
updatedAt: number;
|
||||
entity: "categories" | "tasks" | "subtasks" | "repeatProfiles" | "friendships";
|
||||
}>, "many">>;
|
||||
lastPulledAt: z.ZodNumber;
|
||||
}, "strip", z.ZodTypeAny, {
|
||||
changes: {
|
||||
friendships?: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
userId: string;
|
||||
friendId: string;
|
||||
status: "pending" | "accepted";
|
||||
updatedAt: number;
|
||||
}[] | undefined;
|
||||
categories?: {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -509,23 +737,26 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
id: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
categoryId: string;
|
||||
categoryId: string | null;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
dueTime: string;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}[] | undefined;
|
||||
subtasks?: {
|
||||
id: string;
|
||||
@@ -533,8 +764,22 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
updatedAt: number;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
dueTime: string;
|
||||
taskId: string;
|
||||
order?: number | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}[] | undefined;
|
||||
repeatProfiles?: {
|
||||
id: string;
|
||||
@@ -545,18 +790,23 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
repeatInterval: number;
|
||||
repeatDays: string;
|
||||
}[] | undefined;
|
||||
friendships?: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
userId: string;
|
||||
friendId: string;
|
||||
status: "pending" | "accepted";
|
||||
updatedAt: number;
|
||||
}[] | undefined;
|
||||
};
|
||||
lastPulledAt: number;
|
||||
deleted?: {
|
||||
id: string;
|
||||
updatedAt: number;
|
||||
entity: "categories" | "tasks" | "subtasks" | "repeatProfiles" | "friendships";
|
||||
}[] | undefined;
|
||||
}, {
|
||||
changes: {
|
||||
friendships?: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
userId: string;
|
||||
friendId: string;
|
||||
status: "pending" | "accepted";
|
||||
updatedAt: number;
|
||||
}[] | undefined;
|
||||
categories?: {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -569,23 +819,26 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
id: string;
|
||||
createdAt: number;
|
||||
updatedAt: number;
|
||||
categoryId: string;
|
||||
categoryId: string | null;
|
||||
title: string;
|
||||
completed: boolean;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | null | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
repeat?: "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "" | "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
subtasks?: {
|
||||
title: string;
|
||||
}[] | undefined;
|
||||
reminders?: string | undefined;
|
||||
completedAt?: number | null | undefined;
|
||||
}[] | undefined;
|
||||
subtasks?: {
|
||||
id: string;
|
||||
@@ -595,6 +848,20 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
completed: boolean;
|
||||
taskId: string;
|
||||
order?: number | undefined;
|
||||
description?: string | undefined;
|
||||
priority?: "none" | "low" | "medium" | "high" | "critical" | undefined;
|
||||
dueDate?: number | undefined;
|
||||
dueTime?: string | undefined;
|
||||
endTime?: string | undefined;
|
||||
allDay?: boolean | undefined;
|
||||
repeat?: "" | "custom" | "none" | "daily" | "weekly" | "monthly" | undefined;
|
||||
repeatInterval?: number | undefined;
|
||||
repeatDays?: string | undefined;
|
||||
seriesId?: string | undefined;
|
||||
assigneeId?: string | null | undefined;
|
||||
reminder?: "none" | "at_time" | "15" | "30" | "60" | "120" | "1440" | undefined;
|
||||
reminders?: string | undefined;
|
||||
parentSubtaskId?: string | null | undefined;
|
||||
}[] | undefined;
|
||||
repeatProfiles?: {
|
||||
id: string;
|
||||
@@ -605,8 +872,21 @@ export declare const pushChangesSchema: z.ZodObject<{
|
||||
repeatInterval: number;
|
||||
repeatDays: string;
|
||||
}[] | undefined;
|
||||
friendships?: {
|
||||
id: string;
|
||||
createdAt: number;
|
||||
userId: string;
|
||||
friendId: string;
|
||||
status: "pending" | "accepted";
|
||||
updatedAt: number;
|
||||
}[] | undefined;
|
||||
};
|
||||
lastPulledAt: number;
|
||||
deleted?: {
|
||||
id: string;
|
||||
updatedAt: number;
|
||||
entity: "categories" | "tasks" | "subtasks" | "repeatProfiles" | "friendships";
|
||||
}[] | undefined;
|
||||
}>;
|
||||
export declare const syncQuerySchema: z.ZodObject<{
|
||||
since: z.ZodPipeline<z.ZodEffects<z.ZodString, number, string>, z.ZodNumber>;
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAI/B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAI/B,CAAC;AAEH,eAAO,MAAM,YAAY,6DAA2D,CAAC;AAErF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAe3B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU3B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;EAG9B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;EAI9B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;EAO7B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;EAK9B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;EAE9B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;EAO3B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS5B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;EAE1B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU1B,CAAC"}
|
||||
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAKxD;AAED,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAI/B,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;EAI/B,CAAC;AAEH,eAAO,MAAM,YAAY,6DAA2D,CAAC;AAIrF,eAAO,MAAM,iBAAiB,uOAGjB,CAAC;AACd,eAAO,MAAM,yBAAyB,0DAMzB,CAAC;AAEd,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkB3B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY3B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiB9B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkB9B,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;EAO7B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;EAK9B,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;EAKpC,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;EAE5B,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;EAE9B,CAAC;AAEH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;EAO3B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;EAI1B,CAAC;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU5B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;EAE1B,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU1B,CAAC"}
|
||||
Vendored
+77
-8
@@ -1,7 +1,15 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.taskQuerySchema = exports.syncQuerySchema = exports.pushChangesSchema = exports.friendshipSchema = exports.friendRequestSchema = exports.repeatProfileSchema = exports.userSettingsSchema = exports.subtaskUpdateSchema = exports.subtaskCreateSchema = exports.taskUpdateSchema = exports.taskCreateSchema = exports.repeatSchema = exports.categoryUpdateSchema = exports.categoryCreateSchema = void 0;
|
||||
exports.taskQuerySchema = exports.syncQuerySchema = exports.pushChangesSchema = exports.tombstoneSchema = exports.friendshipSchema = exports.friendRequestSchema = exports.searchQuerySchema = exports.repeatProfileUpdateSchema = exports.repeatProfileSchema = exports.userSettingsSchema = exports.subtaskUpdateSchema = exports.subtaskCreateSchema = exports.taskUpdateSchema = exports.taskCreateSchema = exports.repeatIntervalFieldSchema = exports.repeatFieldSchema = exports.repeatSchema = exports.categoryUpdateSchema = exports.categoryCreateSchema = void 0;
|
||||
exports.canCompleteTask = canCompleteTask;
|
||||
const zod_1 = require("zod");
|
||||
function canCompleteTask(dueDate) {
|
||||
if (dueDate === 0)
|
||||
return true;
|
||||
const now = new Date();
|
||||
const endOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999).getTime();
|
||||
return dueDate <= endOfToday;
|
||||
}
|
||||
exports.categoryCreateSchema = zod_1.z.object({
|
||||
name: zod_1.z.string().min(1).max(50),
|
||||
color: zod_1.z.string().regex(/^#[0-9A-Fa-f]{6}$/),
|
||||
@@ -13,41 +21,87 @@ exports.categoryUpdateSchema = zod_1.z.object({
|
||||
order: zod_1.z.number().int().min(0).optional(),
|
||||
});
|
||||
exports.repeatSchema = zod_1.z.enum(['none', 'daily', 'weekly', 'monthly', 'custom']);
|
||||
// The client stores '' / 0 for unset repeat values; normalize them so stale or
|
||||
// legacy rows never fail validation on push.
|
||||
exports.repeatFieldSchema = exports.repeatSchema
|
||||
.or(zod_1.z.literal(''))
|
||||
.transform((v) => (v === '' ? 'none' : v))
|
||||
.optional();
|
||||
exports.repeatIntervalFieldSchema = zod_1.z
|
||||
.number()
|
||||
.int()
|
||||
.min(0)
|
||||
.max(30)
|
||||
.transform((v) => Math.max(1, v))
|
||||
.optional();
|
||||
exports.taskCreateSchema = zod_1.z.object({
|
||||
title: zod_1.z.string().min(1).max(100),
|
||||
description: zod_1.z.string().max(1000).optional(),
|
||||
categoryId: zod_1.z.string().min(1),
|
||||
categoryId: zod_1.z.string().max(100).transform((v) => (v === '' ? null : v)).nullable(),
|
||||
priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
|
||||
dueDate: zod_1.z.number().int().min(0).optional(),
|
||||
dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().nullable(),
|
||||
dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v ?? ''),
|
||||
endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')),
|
||||
repeat: exports.repeatSchema.optional(),
|
||||
repeatInterval: zod_1.z.number().int().min(1).max(30).optional(),
|
||||
allDay: zod_1.z.boolean().optional(),
|
||||
repeat: exports.repeatFieldSchema,
|
||||
repeatInterval: exports.repeatIntervalFieldSchema,
|
||||
repeatDays: zod_1.z.string().max(20).optional(),
|
||||
seriesId: zod_1.z.string().max(50).optional(),
|
||||
reminder: zod_1.z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(),
|
||||
reminders: zod_1.z.string().max(100).optional(),
|
||||
assigneeId: zod_1.z.string().nullable().optional(),
|
||||
completedAt: zod_1.z.number().int().min(0).nullable().optional(),
|
||||
subtasks: zod_1.z.array(zod_1.z.object({ title: zod_1.z.string().min(1).max(100) })).optional(),
|
||||
});
|
||||
exports.taskUpdateSchema = zod_1.z.object({
|
||||
title: zod_1.z.string().min(1).max(100).optional(),
|
||||
description: zod_1.z.string().max(1000).optional(),
|
||||
categoryId: zod_1.z.string().min(1).optional(),
|
||||
categoryId: zod_1.z.string().max(100).nullable().optional().transform((v) => (v === '' ? null : v)),
|
||||
priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
|
||||
completed: zod_1.z.boolean().optional(),
|
||||
dueDate: zod_1.z.number().int().min(0).optional(),
|
||||
dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().nullable(),
|
||||
dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v === '' ? undefined : v),
|
||||
endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(),
|
||||
reminders: zod_1.z.string().max(100).optional(),
|
||||
assigneeId: zod_1.z.string().nullable().optional(),
|
||||
completedAt: zod_1.z.number().int().min(0).nullable().optional(),
|
||||
});
|
||||
exports.subtaskCreateSchema = zod_1.z.object({
|
||||
title: zod_1.z.string().min(1).max(100),
|
||||
description: zod_1.z.string().max(1000).optional(),
|
||||
priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
|
||||
dueDate: zod_1.z.number().int().min(0).optional(),
|
||||
dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v ?? ''),
|
||||
endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')),
|
||||
allDay: zod_1.z.boolean().optional(),
|
||||
repeat: exports.repeatFieldSchema,
|
||||
repeatInterval: exports.repeatIntervalFieldSchema,
|
||||
repeatDays: zod_1.z.string().max(20).optional(),
|
||||
seriesId: zod_1.z.string().max(50).optional(),
|
||||
reminder: zod_1.z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(),
|
||||
reminders: zod_1.z.string().max(100).optional(),
|
||||
assigneeId: zod_1.z.string().nullable().optional(),
|
||||
order: zod_1.z.number().int().min(0).optional(),
|
||||
parentSubtaskId: zod_1.z.string().nullable().optional(),
|
||||
});
|
||||
exports.subtaskUpdateSchema = zod_1.z.object({
|
||||
title: zod_1.z.string().min(1).max(100).optional(),
|
||||
description: zod_1.z.string().max(1000).optional(),
|
||||
priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(),
|
||||
completed: zod_1.z.boolean().optional(),
|
||||
dueDate: zod_1.z.number().int().min(0).optional(),
|
||||
dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v === '' ? undefined : v),
|
||||
endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(),
|
||||
allDay: zod_1.z.boolean().optional(),
|
||||
repeat: exports.repeatFieldSchema,
|
||||
repeatInterval: exports.repeatIntervalFieldSchema,
|
||||
repeatDays: zod_1.z.string().max(20).optional(),
|
||||
seriesId: zod_1.z.string().max(50).optional(),
|
||||
reminder: zod_1.z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(),
|
||||
reminders: zod_1.z.string().max(100).optional(),
|
||||
assigneeId: zod_1.z.string().nullable().optional(),
|
||||
order: zod_1.z.number().int().min(0).optional(),
|
||||
parentSubtaskId: zod_1.z.string().nullable().optional(),
|
||||
});
|
||||
exports.userSettingsSchema = zod_1.z.object({
|
||||
darkMode: zod_1.z.boolean().optional(),
|
||||
@@ -63,6 +117,15 @@ exports.repeatProfileSchema = zod_1.z.object({
|
||||
repeatInterval: zod_1.z.number().int().min(1).max(30),
|
||||
repeatDays: zod_1.z.string().max(20),
|
||||
});
|
||||
exports.repeatProfileUpdateSchema = zod_1.z.object({
|
||||
name: zod_1.z.string().min(1).max(50).optional(),
|
||||
repeat: exports.repeatSchema.optional(),
|
||||
repeatInterval: zod_1.z.number().int().min(1).max(30).optional(),
|
||||
repeatDays: zod_1.z.string().max(20).optional(),
|
||||
});
|
||||
exports.searchQuerySchema = zod_1.z.object({
|
||||
q: zod_1.z.string().min(1).max(50),
|
||||
});
|
||||
exports.friendRequestSchema = zod_1.z.object({
|
||||
username: zod_1.z.string().min(1).max(50),
|
||||
});
|
||||
@@ -74,14 +137,20 @@ exports.friendshipSchema = zod_1.z.object({
|
||||
createdAt: zod_1.z.number(),
|
||||
updatedAt: zod_1.z.number(),
|
||||
});
|
||||
exports.tombstoneSchema = zod_1.z.object({
|
||||
entity: zod_1.z.enum(['categories', 'tasks', 'subtasks', 'repeatProfiles', 'friendships']),
|
||||
id: zod_1.z.string(),
|
||||
updatedAt: zod_1.z.number().int().min(0),
|
||||
});
|
||||
exports.pushChangesSchema = zod_1.z.object({
|
||||
changes: zod_1.z.object({
|
||||
categories: zod_1.z.array(exports.categoryCreateSchema.extend({ id: zod_1.z.string(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(),
|
||||
tasks: zod_1.z.array(exports.taskCreateSchema.extend({ id: zod_1.z.string(), completed: zod_1.z.boolean(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(),
|
||||
tasks: zod_1.z.array(exports.taskCreateSchema.extend({ id: zod_1.z.string(), completed: zod_1.z.boolean(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number(), completedAt: zod_1.z.number().int().min(0).nullable().optional() })).optional(),
|
||||
subtasks: zod_1.z.array(exports.subtaskCreateSchema.extend({ id: zod_1.z.string(), taskId: zod_1.z.string(), completed: zod_1.z.boolean(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(),
|
||||
repeatProfiles: zod_1.z.array(exports.repeatProfileSchema.extend({ id: zod_1.z.string(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(),
|
||||
friendships: zod_1.z.array(exports.friendshipSchema).optional(),
|
||||
}),
|
||||
deleted: zod_1.z.array(exports.tombstoneSchema).optional(),
|
||||
lastPulledAt: zod_1.z.number().int().min(0),
|
||||
});
|
||||
exports.syncQuerySchema = zod_1.z.object({
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user