Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.vscode/*
!.vscode/settings.json

node_modules

build
electron

.local.env
.vscode/*
!.vscode/settings.json
node_modules
build
electron
.local.env
26 changes: 13 additions & 13 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"editor.detectIndentation": false,
"editor.insertSpaces": true,
"editor.tabSize": 2,
"editor.indentSize": "tabSize",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.autoSave": "afterDelay",
"files.autoSaveDelay": 1000,
"files.autoSaveWhenNoErrors": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true,
}
{
"editor.detectIndentation": false,
"editor.insertSpaces": true,
"editor.tabSize": 2,
"editor.indentSize": "tabSize",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"files.autoSave": "afterDelay",
"files.autoSaveDelay": 1000,
"files.autoSaveWhenNoErrors": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true,
}
266 changes: 133 additions & 133 deletions README.md

Large diffs are not rendered by default.

16 changes: 0 additions & 16 deletions backend/.local.env.template

This file was deleted.

20 changes: 20 additions & 0 deletions backend/04hw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
关于为什么使用yarn:

npm (Node Package Manager) 是 Node.js 的官方默认包管理器,它非常流行且拥有最大的生态系统。然而,Facebook 等公司在开发中遇到了 npm 的一些局限性,从而催生了 Yarn 的诞生。

1. 性能与速度 (Performance & Speed)
并行安装:Yarn 最开始的重大改进之一是并行执行操作。它会同时获取和安装多个包,极大地加快了安装速度。而早期的 npm 是顺序执行这些操作,速度较慢。
离线缓存:Yarn 拥有强大的离线模式。一旦安装过一个包,Yarn 会将其缓存下来。下次再安装时,即使没有网络,它也可以直接从本地缓存中读取,保证了安装的可靠性和速度。npm 后来也加入了缓存功能,但 Yarn 是先行者且实现得非常出色。

2. 稳定性与确定性 (Stability & Determinism)
yarn.lock 文件:这是最核心的原因之一。Yarn 会生成一个精确的 yarn.lock 文件,锁定每个依赖包及其所有子依赖的精确版本号。
好处:无论在什么机器上(开发环境、CI/CD 服务器、生产环境)执行 yarn install,安装的依赖树结构都是一模一样的。这避免了“在我的机器上是好的”这类问题,保证了依赖的确定性和项目稳定性。

npm:早期的 package-lock.json 文件存在一些不一致的问题,且行为在不同 npm 版本间有变化。虽然现在 npm 的 lockfile 已经很成熟,但 Yarn 是这一概念的推动者和标杆。

3. 安全性 (Security)
完整性校验:Yarn 在安装每个包时,会通过校验和(checksum) 来验证其完整性,确保在下载过程中没有被篡改。这为供应链安全增加了一层保障。npm 后来也采用了类似的行为。

4. 开发者体验 (Developer Experience)
简洁的输出:Yarn 的命令行输出通常更加简洁、友好且信息丰富。npm 的输出信息可能比较冗长和杂乱。
更好的命令:Yarn 的命令设计更直观(例如 yarn add, yarn remove),而早期的 npm 需要依赖 npm install --save 这样的 flags
1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"typescript": "5.5.4"
},
"scripts": {
"generate": "npx graphql-codegen",
"start": "nodemon src/index.ts",
"build": "tsc",
"serve": "node build/index.js",
Expand Down
89 changes: 82 additions & 7 deletions backend/src/graphql.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import exp from 'constants';
import { GraphQLClient, RequestOptions } from 'graphql-request';
import { gql } from 'graphql-request';
export type Maybe<T> = T | null;
Expand Down Expand Up @@ -79,6 +80,13 @@ export type Message = {
content: Scalars['String']['output'];
created_at: Scalars['timestamp']['output'];
/** An object relationship */
message?: Maybe<Message>;
/** An array relationship */
messages: Array<Message>;
/** An aggregate relationship */
messages_aggregate: Message_Aggregate;
reply_to_uuid?: Maybe<Scalars['uuid']['output']>;
/** An object relationship */
room: Room;
room_uuid: Scalars['uuid']['output'];
/** An object relationship */
Expand All @@ -87,6 +95,26 @@ export type Message = {
uuid: Scalars['uuid']['output'];
};


/** columns and relationships of "message" */
export type MessageMessagesArgs = {
distinct_on?: InputMaybe<Array<Message_Select_Column>>;
limit?: InputMaybe<Scalars['Int']['input']>;
offset?: InputMaybe<Scalars['Int']['input']>;
order_by?: InputMaybe<Array<Message_Order_By>>;
where?: InputMaybe<Message_Bool_Exp>;
};


/** columns and relationships of "message" */
export type MessageMessages_AggregateArgs = {
distinct_on?: InputMaybe<Array<Message_Select_Column>>;
limit?: InputMaybe<Scalars['Int']['input']>;
offset?: InputMaybe<Scalars['Int']['input']>;
order_by?: InputMaybe<Array<Message_Order_By>>;
where?: InputMaybe<Message_Bool_Exp>;
};

/** aggregated selection of "message" */
export type Message_Aggregate = {
__typename?: 'message_aggregate';
Expand Down Expand Up @@ -141,6 +169,10 @@ export type Message_Bool_Exp = {
_or?: InputMaybe<Array<Message_Bool_Exp>>;
content?: InputMaybe<String_Comparison_Exp>;
created_at?: InputMaybe<Timestamp_Comparison_Exp>;
message?: InputMaybe<Message_Bool_Exp>;
messages?: InputMaybe<Message_Bool_Exp>;
messages_aggregate?: InputMaybe<Message_Aggregate_Bool_Exp>;
reply_to_uuid?: InputMaybe<Uuid_Comparison_Exp>;
room?: InputMaybe<Room_Bool_Exp>;
room_uuid?: InputMaybe<Uuid_Comparison_Exp>;
user?: InputMaybe<User_Bool_Exp>;
Expand All @@ -158,6 +190,9 @@ export enum Message_Constraint {
export type Message_Insert_Input = {
content?: InputMaybe<Scalars['String']['input']>;
created_at?: InputMaybe<Scalars['timestamp']['input']>;
message?: InputMaybe<Message_Obj_Rel_Insert_Input>;
messages?: InputMaybe<Message_Arr_Rel_Insert_Input>;
reply_to_uuid?: InputMaybe<Scalars['uuid']['input']>;
room?: InputMaybe<Room_Obj_Rel_Insert_Input>;
room_uuid?: InputMaybe<Scalars['uuid']['input']>;
user?: InputMaybe<User_Obj_Rel_Insert_Input>;
Expand All @@ -170,6 +205,7 @@ export type Message_Max_Fields = {
__typename?: 'message_max_fields';
content?: Maybe<Scalars['String']['output']>;
created_at?: Maybe<Scalars['timestamp']['output']>;
reply_to_uuid?: Maybe<Scalars['uuid']['output']>;
room_uuid?: Maybe<Scalars['uuid']['output']>;
user_uuid?: Maybe<Scalars['uuid']['output']>;
uuid?: Maybe<Scalars['uuid']['output']>;
Expand All @@ -179,6 +215,7 @@ export type Message_Max_Fields = {
export type Message_Max_Order_By = {
content?: InputMaybe<Order_By>;
created_at?: InputMaybe<Order_By>;
reply_to_uuid?: InputMaybe<Order_By>;
room_uuid?: InputMaybe<Order_By>;
user_uuid?: InputMaybe<Order_By>;
uuid?: InputMaybe<Order_By>;
Expand All @@ -189,6 +226,7 @@ export type Message_Min_Fields = {
__typename?: 'message_min_fields';
content?: Maybe<Scalars['String']['output']>;
created_at?: Maybe<Scalars['timestamp']['output']>;
reply_to_uuid?: Maybe<Scalars['uuid']['output']>;
room_uuid?: Maybe<Scalars['uuid']['output']>;
user_uuid?: Maybe<Scalars['uuid']['output']>;
uuid?: Maybe<Scalars['uuid']['output']>;
Expand All @@ -198,6 +236,7 @@ export type Message_Min_Fields = {
export type Message_Min_Order_By = {
content?: InputMaybe<Order_By>;
created_at?: InputMaybe<Order_By>;
reply_to_uuid?: InputMaybe<Order_By>;
room_uuid?: InputMaybe<Order_By>;
user_uuid?: InputMaybe<Order_By>;
uuid?: InputMaybe<Order_By>;
Expand All @@ -212,6 +251,13 @@ export type Message_Mutation_Response = {
returning: Array<Message>;
};

/** input type for inserting object relation for remote table "message" */
export type Message_Obj_Rel_Insert_Input = {
data: Message_Insert_Input;
/** upsert condition */
on_conflict?: InputMaybe<Message_On_Conflict>;
};

/** on_conflict condition type for table "message" */
export type Message_On_Conflict = {
constraint: Message_Constraint;
Expand All @@ -223,6 +269,9 @@ export type Message_On_Conflict = {
export type Message_Order_By = {
content?: InputMaybe<Order_By>;
created_at?: InputMaybe<Order_By>;
message?: InputMaybe<Message_Order_By>;
messages_aggregate?: InputMaybe<Message_Aggregate_Order_By>;
reply_to_uuid?: InputMaybe<Order_By>;
room?: InputMaybe<Room_Order_By>;
room_uuid?: InputMaybe<Order_By>;
user?: InputMaybe<User_Order_By>;
Expand All @@ -242,6 +291,8 @@ export enum Message_Select_Column {
/** column name */
CreatedAt = 'created_at',
/** column name */
ReplyToUuid = 'reply_to_uuid',
/** column name */
RoomUuid = 'room_uuid',
/** column name */
UserUuid = 'user_uuid',
Expand All @@ -253,6 +304,7 @@ export enum Message_Select_Column {
export type Message_Set_Input = {
content?: InputMaybe<Scalars['String']['input']>;
created_at?: InputMaybe<Scalars['timestamp']['input']>;
reply_to_uuid?: InputMaybe<Scalars['uuid']['input']>;
room_uuid?: InputMaybe<Scalars['uuid']['input']>;
user_uuid?: InputMaybe<Scalars['uuid']['input']>;
uuid?: InputMaybe<Scalars['uuid']['input']>;
Expand All @@ -270,6 +322,7 @@ export type Message_Stream_Cursor_Input = {
export type Message_Stream_Cursor_Value_Input = {
content?: InputMaybe<Scalars['String']['input']>;
created_at?: InputMaybe<Scalars['timestamp']['input']>;
reply_to_uuid?: InputMaybe<Scalars['uuid']['input']>;
room_uuid?: InputMaybe<Scalars['uuid']['input']>;
user_uuid?: InputMaybe<Scalars['uuid']['input']>;
uuid?: InputMaybe<Scalars['uuid']['input']>;
Expand All @@ -282,6 +335,8 @@ export enum Message_Update_Column {
/** column name */
CreatedAt = 'created_at',
/** column name */
ReplyToUuid = 'reply_to_uuid',
/** column name */
RoomUuid = 'room_uuid',
/** column name */
UserUuid = 'user_uuid',
Expand Down Expand Up @@ -1319,7 +1374,7 @@ export type User_Room_Bool_Exp = {

/** unique or primary key constraints on table "user_room" */
export enum User_Room_Constraint {
/** unique or primary key constraint on columns "user_uuid", "room_uuid" */
/** unique or primary key constraint on columns "room_uuid", "user_uuid" */
UserRoomPkey = 'user_room_pkey'
}

Expand Down Expand Up @@ -1542,6 +1597,7 @@ export type JoinRoomMutation = { __typename?: 'mutation_root', insert_user_room_
export type AddUserMutationVariables = Exact<{
username: Scalars['String']['input'];
password: Scalars['String']['input'];
email: InputMaybe<Scalars['String']['input']>;
}>;


Expand All @@ -1552,8 +1608,16 @@ export type GetUsersByUsernameQueryVariables = Exact<{
}>;


export type GetUsersByUsernameQuery = { __typename?: 'query_root', user: Array<{ __typename?: 'user', uuid: any, password: string }> };
export type GetUsersByUsernameQuery = { __typename?: 'query_root', user: Array<{
[x: string]: any; __typename?: 'user', uuid: any, password: string
}> };

export type UpdateUserPasswordMutationVariables = Exact<{
username: Scalars['String']['input'];
password: Scalars['String']['input'];
}>;

export type UpdateUserPasswordMutation = { __typename?: 'mutation_root', update_user?: { __typename?: 'user_mutation_response', affected_rows: number } | null };

export const AddMessageDocument = gql`
mutation addMessage($user_uuid: uuid!, $room_uuid: uuid!, $content: String!) {
Expand Down Expand Up @@ -1613,17 +1677,25 @@ export const JoinRoomDocument = gql`
}
`;
export const AddUserDocument = gql`
mutation addUser($username: String!, $password: String!) {
insert_user_one(object: {username: $username, password: $password}) {
uuid
mutation addUser($username: String!, $password: String!, $email: String) {
insert_user_one(object: {username: $username, password: $password, email: $email}) {
uuid
}
}
`;
`;
export const GetUsersByUsernameDocument = gql`
query getUsersByUsername($username: String!) {
user(where: {username: {_eq: $username}}) {
uuid
password
email
}
}
`;
export const UpdateUserPasswordDocument = gql`
mutation updateUserPassword($username: String!, $password: String!) {
update_user(where: {username: {_eq: $username}}, _set: {password: $password}) {
affected_rows
}
}
`;
Expand Down Expand Up @@ -1658,7 +1730,10 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper =
},
getUsersByUsername(variables: GetUsersByUsernameQueryVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise<GetUsersByUsernameQuery> {
return withWrapper((wrappedRequestHeaders) => client.request<GetUsersByUsernameQuery>(GetUsersByUsernameDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getUsersByUsername', 'query', variables);
},
updateUserPassword(variables: UpdateUserPasswordMutationVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise<UpdateUserPasswordMutation> {
return withWrapper((wrappedRequestHeaders) => client.request<UpdateUserPasswordMutation>(UpdateUserPasswordDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'updateUserPassword', 'mutation', variables);
}
};
}
export type Sdk = ReturnType<typeof getSdk>;
export type Sdk = ReturnType<typeof getSdk>;
2 changes: 2 additions & 0 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ dotenv.config({
path: path.resolve(process.cwd(), ".local.env"),
});

console.log("JWT_SECRET: ", process.env.JWT_SECRET);

const client = new GraphQLClient(
process.env.HASURA_GRAPHQL_ENDPOINT!,
{
Expand Down
Loading