10. 帮我编写一个 aes 加密函数. 输入 key 和 data, 返回加密后的数据. 输入 data 和 key , 返回解密后的数据
基于 crypto-js 和 ts
9 。 开始编写服务器需要的一些工具函数
Q:
帮我用 crypto-js 编写函数。
输入账户,密码。 生成两个 key
第一个 key sha256(memo:sha256(username):sha256(password):talk);
第二 key 。sha256(memo:password:talk
用 ts 编写
第一个 key 名字为 userToken , 第二个 key 名字为 加密密钥(用英文)
8. 简单更新了一下首页的 UI , 然后把储存从 localstorage 换到了 IndexedDB
开始真正对接服务器了。
第一版做的简单一点,在页面加载的时候异步合并一下服务器的数据,合并后把数据上传到服务器。
4. 本来准备在 vite 里跑 mocha ,试了一下发现不太行,准备换一条路。 用假的 indexedDB 测试。 测试继续在 vitest 里跑。
3. 对 chatgpt 写的代码不太放心,准备写一个单元测试
Q: 帮我用 mocha 写单元测试
```ts
export interface ISettingService {
get<V extends SettingsValue>(key: string, defaultValue: V): Promise<V>;
set(key: string, value: SettingsValue): Promise<void>;
readConfig<T extends Record<string, SettingsValue>>(
defaultValue: T
): Promise<T>;
}
```
好的,我可以帮您实现一个基于 IndexedDB 的 ISettingService 。以下是实现代码示例:
typescript
Copy
export interface ConfigDatabase {
settings: Record<string, SettingsValue>;
}
export class IndexedDBSettingService implements ISettingService {
private readonly dbName: string = "my-settings-db";
private readonly dbVersion: number = 1;
private readonly storeName: string = "settings";
private db: IDBDatabase;
constructor() {
this.openDB();
}
private async openDB(): Promise<void> {
return new Promise<void>((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.dbVersion);
request.onerror = (event) => {
console.error("Error opening database", event);
reject(event);
};
request.onsuccess = (event) => {
this.db = request.result;
resolve();
};
request.onupgradeneeded = (event) => {
const db = request.result;
if (!db.objectStoreNames.contains(this.storeName)) {
db.createObjectStore(this.storeName);
}
};
});
}
public async get<V extends SettingsValue>(
key: string,
defaultValue: V
): Promise<V> {
return new Promise<V>((resolve, reject) => {
const transaction = this.db.transaction(this.storeName, "readonly");
const objectStore = transaction.objectStore(this.storeName);
const request = objectStore.get(key);
request.onerror = (event) => {
console.error(`Error getting value for key "${key}"`, event);
reject(event);
};
request.onsuccess = (event) => {
const value = request.result !== undefined ? request.result : defaultValue;
resolve(value);
};
});
}
public async set(key: string, value: SettingsValue): Promise<void> {
return new Promise<void>((resolve, reject) => {
const transaction = this.db.transaction(this.storeName, "readwrite");
const objectStore = transaction.objectStore(this.storeName);
const request = objectStore.put(value, key);
request.onerror = (event) => {
console.error(`Error setting value for key "${key}"`, event);
reject(event);
};
request.onsuccess = (event) => {
resolve();
};
});
}
public async readConfig<T extends Record<StorageKeys, SettingsValue>>(
defaultValue: T
): Promise<T> {
const config: T = {} as T;
// Read all values from the database and merge with default values
for (const key in defaultValue) {
if (defaultValue.hasOwnProperty(key)) {
const value = await this.get(key, defaultValue[key]);
config[key as keyof T] = value as T[keyof T];
}
}
return config;
}
public async clearAll(): Promise<void> {
return new Promise<void>((resolve, reject) => {
const transaction = this.db.transaction(this.storeName, "readwrite");
const objectStore = transaction.objectStore(this.storeName);
const request = objectStore.clear();
request.onerror = (event) => {
console.error("Error clearing settings", event);
reject(event);
};
request.onsuccess = (event) => {
resolve();
};
});
}
}
在这个实现中,我们创建了一个名为 my-settings-db 的 IndexedDB 数据库,并创建了一个名为 settings 的对象存储。在 get 和 set 方法中,我们分别使用事务来读取和写入数据。在 readConfig 方法中,我们遍历默认配置对象中的所有键,并使用 get 方法来获取每个键的值。最后,我们还为 IndexedDBSettingService 类添加了一个清除所有设置的 clearAll 方法。
请注意,由于 IndexedDB 是异步的,因此所有方法都返回一个 Promise 。此外,如果 IndexedDB 连接失败或出现错误,这些方法将会拒绝 Promise 并输出错误信息。
2. localstorage 存储量有限,准备基于 IndexedDB 实现本地存储
Q: 帮我基于 IndexedDB 实现一个 ISettingService 吧,我要把所有的配置都存在 IndexedDB 里面。
export type SettingsValue = string | boolean;
export enum StorageKeys {
backend = "backend",
"backend.hamsterbase.entrypoint" = "backend.hamsterbase.entrypoint",
"backend.hamsterbase.token" = "backend.hamsterbase.token",
"backend.notion.token" = "backend.notion.token",
"backend.notion.databaseId" = "backend.notion.databaseId",
"backend.notion.license" = "backend.notion.license",
autoOn = "autoOn",
autoOnBlockList = "autoOnBlockList",
}
export interface ISettingService {
_serviceBrand: undefined;
get<V extends SettingsValue>(key: string, defaultValue: V): Promise<V>;
set(key: string, value: SettingsValue): Promise<void>;
readConfig<T extends Record<StorageKeys, SettingsValue>>(
defaultValue: T
): Promise<T>;
}
1. 今天的目标: 发布 1.0 !!!
1. 接入 antd mobile ,重写 UI
2. 接入后端,实现登录功能.
1. 服务器不储存任何账户密码。只储存用户的 token ,token 由前端生成。
2. 把 token 作为文件夹名
3. token 的生成规则:sha256( `${sha256(user)} ${sha256(password)}`)
4. 文件储存之前使用 aes 加密。 加密 为 sha256(password)
3. 接入 PWA , 让软件可离线使用
太厉害了。 我也准备用类似方案跑我的项目,在 react native 里跑 nodejs 。实现一套代码支持全部平台
@
ShuaiYH 你们默认的权限要的太多了。 建议只授权 public 项目 + 邮箱。 等用户需要部署私有项目的时候,再请求进一步的授权。
之前我就是被这个方案劝退了。
@
findex 建议改一下默认授权。 上来就要求我私有库权限。 我选择拒绝。
21 Q: 帮我写一个 react 的页面,需要用 typescript 开发。
最顶上是一个提示框。 红色的字 “此项目还在开发中,请不要使用”
中间为一个消息窗口。 消息都靠右。
消息为圆角。消息的背景为蓝色。 参考 imessage
页面背景为白色。
最下面是一个 input 框。 里面有一个按钮。 按钮上面的字为 “发送”
颜色要好看一点。 圆角保存统一。
props 为 memotalks:MemoTalk, onCreateMemoTalk(content:string):void
export interface MemoTalk {
id: string;
content: string;
createTime: number;
}
20. 完善一下单元测试
Q: 帮我用 jest 编写测试。
如果重复删除,应该抛错
19. 在 chatgpt 的帮助下测出了一个 bug, 如果删除了,再次获取的时候应该返回 null 。 所有测试都通过啦