Init
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/.devcontainer
|
||||||
|
/.vscode
|
||||||
|
/maintenance/test/data
|
||||||
|
.clang-format
|
||||||
|
/frontend/node_modules
|
0
CMakeLists.txt
Normal file
0
CMakeLists.txt
Normal file
0
docs/develop/开发文档.md
Normal file
0
docs/develop/开发文档.md
Normal file
0
docs/develop/总体设计文档.md
Normal file
0
docs/develop/总体设计文档.md
Normal file
0
docs/develop/需求分析文档.md
Normal file
0
docs/develop/需求分析文档.md
Normal file
162
docs/homework_requirement/README.md
Normal file
162
docs/homework_requirement/README.md
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
# 书店管理系统
|
||||||
|
|
||||||
|
SJTU ACM 班 2023 级程序设计课程大作业
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
* [简介](#简介)
|
||||||
|
* [作业说明](#作业说明)
|
||||||
|
* [评测方式](#评测方式)
|
||||||
|
* [分数组成](#分数组成)
|
||||||
|
* [时间表](#时间表)
|
||||||
|
* [项目说明](#项目说明)
|
||||||
|
* [开发要求](#开发要求)
|
||||||
|
* [需求分析文档](#需求分析文档)
|
||||||
|
* [总体设计文档](#总体设计文档)
|
||||||
|
* [开发文档](#开发文档)
|
||||||
|
* [Git 版本管理](#git-版本管理)
|
||||||
|
* [代码风格](#代码风格)
|
||||||
|
* [Bonus](#bonus)
|
||||||
|
* [扣分](#扣分)
|
||||||
|
|
||||||
|
## 简介
|
||||||
|
|
||||||
|
实现一个用 C++ 语言编写的书店管理系统,用于向店家和顾客提供图书检索与购买相关服务。
|
||||||
|
|
||||||
|
本项目目标如下:
|
||||||
|
|
||||||
|
- 培养学生工程开发的能力(全套的开发过程与程序的封装等);
|
||||||
|
- 培养学生编写文档的能力(需求文档/设计文档/开发文档的编写);
|
||||||
|
- 培养学生的代码管理能力(git 的使用),拥有良好的代码规范意识;
|
||||||
|
- 提升学生的编程学习与实践能力(块状链表的学习实现);
|
||||||
|
- 培养学生对编写软件的兴趣(见 [bonus](#bonus))。
|
||||||
|
|
||||||
|
### 关于本仓库
|
||||||
|
|
||||||
|
关于本仓库有任何问题欢迎联系助教,也可以直接 pull request;本仓库内容将维护至本作业结束,请保持关注题面更改,助教也会及时发布相关通知。
|
||||||
|
|
||||||
|
## 作业说明
|
||||||
|
|
||||||
|
### 评测方式
|
||||||
|
|
||||||
|
公开的评测数据可以从 [SJTU jBox](https://jbox.sjtu.edu.cn/l/b1x5MN) 下载。
|
||||||
|
|
||||||
|
注意,每个 testcase 为最小评测数据单元;在测试同一 testcase 的多个输入(.in)过程中,对于每个输入,都会运行学生程序,完成后关闭程序,再以下一个输入运行学生程序,但过程中不会清除学生程序运行生成的数据文件。而每个 testcase 测试结束后会清除所有学生程序生成的文件,再运行下一个 testcase。
|
||||||
|
|
||||||
|
Online Judge(以下简称 OJ)提交方式为提交 git repo 链接,提交内容应为形如 `https://github.com/username/repo` 的链接。编译评测方式详见 OJ 首页说明。OJ 使用沙盒评测文件读写。编译生成的可执行文件名应为 `code`,否则 OJ 无法运行。
|
||||||
|
|
||||||
|
由于网络原因可能会导致评测机 clone 仓库失败。
|
||||||
|
|
||||||
|
<!-- 仓库内容过大(如将解压后的数据文件或 build 内容一并放入仓库)导致的问题后果自负。(Tip:可以使用 Github 仓库加速通道链接提交作业,例如 Chrome 插件 [GitHub 加速](https://chrome.google.com/webstore/detail/github%E5%8A%A0%E9%80%9F/mfnkflidjnladnkldfonnaicljppahpg))-->
|
||||||
|
|
||||||
|
本地评测可用脚本评测,评测脚本已包含于数据包中,在含有 `./code` 的目录下运行脚本即可。例如你的 `code` 在 `./cmake-build-debug`,数据在 `./data`,则运行 `cd cmake-build-debug; ../data/judge` 即可。如运行评测脚本出现问题,请联系助教。
|
||||||
|
|
||||||
|
评测数据量(帐户和图书数量)不会超过 $1\times10^5$ 数量级。
|
||||||
|
|
||||||
|
### 分数组成
|
||||||
|
|
||||||
|
本作业满分为 100%,最终将以本作业占本课程成绩总分分数折算入课程成绩。
|
||||||
|
|
||||||
|
| 得分项 | 分值 | 说明 |
|
||||||
|
| ----------- | -------: | --------------------------------- |
|
||||||
|
| 正确性 | 55% | 通过所有公开数据点 |
|
||||||
|
| 鲁棒性 | 10% | 通过所有非公开数据点 |
|
||||||
|
| 文档编写 | 15% | 助教评分 |
|
||||||
|
| Code Review | 20% | Git 仓库管理、代码规范等 |
|
||||||
|
| Bonus | 最高 10% | 具体各项得分见 [bonus](#bonus) |
|
||||||
|
| 总计 | 110% | 未通过正确性测试者 bonus 不能得分 |
|
||||||
|
|
||||||
|
### 时间表
|
||||||
|
|
||||||
|
助教将在固定时间节点检查学生的完成进度。如遇困难请**提前**联系助教。
|
||||||
|
|
||||||
|
- **Week 0** *(对应校历 2023-2024 学年第一学期第 12 周)*
|
||||||
|
- 周一(11 月 27 日):发布项目和 [业务要求文档](业务要求.md),开始完成**需求分析文档**和**总体设计文档**;
|
||||||
|
- **Week 1** *(对应校历 2023-2024学年第一学期第 13 周)*
|
||||||
|
- 周二(12 月 5 日):检查需求分析文档和总体设计文档(分数占比 5pt);发布**标准要求**文档;
|
||||||
|
|
||||||
|
- **Week 2**
|
||||||
|
- 周一(12 月 11 日 18:30 前):**通过**前置作业评测;
|
||||||
|
- 周二(12 月 12 日):**中期检查**,检查开发文档编写情况以及主体部分构思(分数占比 5pt);
|
||||||
|
- **Week 4** *(对应校历第 16 周)*
|
||||||
|
- 周一(12 月 25 日 18:30 前):**通过**测试点评测;
|
||||||
|
- 非公开测试点和 Bonus 部分截止日期同主体逻辑,超时完成的部分不计分;
|
||||||
|
- 周二(12 月 26 日晚):进行代码检查(Code Review);
|
||||||
|
|
||||||
|
**友情提醒:临近期末,请尽早开工。**
|
||||||
|
|
||||||
|
## 项目说明
|
||||||
|
|
||||||
|
### 开发要求
|
||||||
|
|
||||||
|
每位学生均需完成一份需求分析文档、总体设计文档和开发文档。文档 **请使用 Markdown** 书写。
|
||||||
|
|
||||||
|
#### 需求分析文档
|
||||||
|
|
||||||
|
根据给出的要求文档,你需要用图或文字描述**书店系统**各个子系统的业务流程和数据流图。
|
||||||
|
|
||||||
|
#### 总体设计文档
|
||||||
|
|
||||||
|
你的总体设计文档应当包括如下部分:
|
||||||
|
|
||||||
|
- 功能设计
|
||||||
|
- 请概述各模块的功能和功能结构图;
|
||||||
|
|
||||||
|
- 用户交互设计
|
||||||
|
- 请设计所有的命令格式和对应的输出;
|
||||||
|
- 数据库设计
|
||||||
|
- 请指出你需要存储的数据以及存储方式;
|
||||||
|
- 类、结构体设计
|
||||||
|
|
||||||
|
#### 开发文档
|
||||||
|
|
||||||
|
开发文档内容**无硬性要求**,内容可以参考以下条目:
|
||||||
|
|
||||||
|
- 项目名称 / 文档作者
|
||||||
|
- 程序功能概述
|
||||||
|
- 主体逻辑说明
|
||||||
|
- 代码文件结构,即 `main` 函数与各个类的关系
|
||||||
|
- 各个类的接口及成员说明
|
||||||
|
- 文件存储说明
|
||||||
|
- 其他补充说明
|
||||||
|
|
||||||
|
如果最后提交代码不符合开发文档则会酌情扣分。合理的文档修订是允许的,但请写明修订记录。
|
||||||
|
|
||||||
|
#### Git 版本管理
|
||||||
|
|
||||||
|
你需要了解版本库、工作区、暂存区等 git 基础概念,并掌握 git 的常用指令。
|
||||||
|
|
||||||
|
你需要合理使用 commit 功能维护代码版本。具体来说:
|
||||||
|
|
||||||
|
- Commit 频率不可以太低(**例如,不可以整个项目只有三四个 commit**);
|
||||||
|
- 频繁的 commit 有助于细致地保存代码变更的历史。
|
||||||
|
- Commit message 内容可以清晰简要但不能缺失、不能是无意义内容。
|
||||||
|
- 对于比较大的 commit,鼓励用多行的 commit message 具体描述干了什么;
|
||||||
|
- 合理的 message 示例:
|
||||||
|
- docs: clarify design reasoning and details
|
||||||
|
- partial implementation of unrolled linked list
|
||||||
|
- fix: 切换帐户之前检查权限
|
||||||
|
- 不合理的 message 示例:
|
||||||
|
- update
|
||||||
|
- Add files via upload
|
||||||
|
- Update README.md
|
||||||
|
- bugfix *(具体修了什么?)*
|
||||||
|
- 20231122 *(git 会自动存储 commit 时间,不用在 commit message 里说明。)*
|
||||||
|
|
||||||
|
你的 git 仓库需要整体文件结构清晰,了解并自主设置 `.gitignore` 等文件,保证编译产物(`./code`、`cmake-build-debug` 等)和下发的测试数据点不进入 git 仓库。Git repository 总大小(包括 `.git` 文件夹在内的 worktree)不得超过 5 MiB。
|
||||||
|
|
||||||
|
**违反者会在 code review 中被扣分。**
|
||||||
|
|
||||||
|
#### 代码风格
|
||||||
|
|
||||||
|
选择合适的代码风格,严格遵守选定风格的代码规范。
|
||||||
|
|
||||||
|
### Bonus
|
||||||
|
|
||||||
|
见 [bonus 文档](bonus.md)。
|
||||||
|
|
||||||
|
### 扣分
|
||||||
|
|
||||||
|
请保证自己项目结构的可读性,可以包括优化项目结构、适当的文件树指南等,晦涩难懂的项目可能会加大助教的工作量,也可能会影响你的成绩。
|
||||||
|
|
||||||
|
**如有出现任何抄袭现象按 0 分计。**
|
214
docs/homework_requirement/bonus.md
Normal file
214
docs/homework_requirement/bonus.md
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
# Bonus
|
||||||
|
|
||||||
|
括号里的分值为最高得分,最终得分由 code review 确定。另请注意,总分值不能超过 10 分。
|
||||||
|
|
||||||
|
## 缓存 *(1.5 pts)*
|
||||||
|
|
||||||
|
如果将一些常用数据存在内存中,可以省去大量从外存上读取的时间,这就是缓存的意义。
|
||||||
|
|
||||||
|
此 bonus 根据实现难度和工作量给分。
|
||||||
|
|
||||||
|
**注:** 若选择实现并发功能,则此 bonus 分不再计入总分。
|
||||||
|
|
||||||
|
## 中文输入验证 *(1.5 pts)*
|
||||||
|
|
||||||
|
在实际使用中,书名、作者名等只支持 ASCII 显然是不够的;我们有很多中文的书名。但是,为了贯彻落实文化自信,我们也不允许书名中出现不是汉字的文字。
|
||||||
|
|
||||||
|
我们把图书相关信息做扩展定义如下:(其他定义不变)
|
||||||
|
|
||||||
|
- `[BookName]`, `[Author]`:图书名字,图书作者名字;
|
||||||
|
- 合法字符集:除不可见字符和英文双引号以外 ASCII 字符,以及汉字和允许的特殊符号;
|
||||||
|
- 最大长度:60,一个汉字或特殊符号算作一个字符。
|
||||||
|
- `[Keyword]`:图书关键词;
|
||||||
|
- 合法字符集:除不可见字符和英文双引号以外 ASCII 字符,以及汉字和允许的特殊符号;
|
||||||
|
- 最大长度:60,一个汉字或特殊符号算作一个字符。
|
||||||
|
|
||||||
|
其中,汉字的定义是:最新 Unicode 标准(Unicode 15.0.0)中指定的 Han Ideographs(汉字)区块内的字。网上能查到的大部分匹配方式都不符合这个要求。例如,它们都不能匹配「𰻝」字(音 biáng,U+30EDD,位于 CJK 扩展 G 区)。所以你需要自行查阅相关文档来找出具体的字汇。
|
||||||
|
|
||||||
|
允许的特殊符号有:
|
||||||
|
|
||||||
|
- 间隔号「·」,U+00B7
|
||||||
|
- Em Dash「—」,U+2014
|
||||||
|
- 括号「(」「)」,U+FF08 U+FF09
|
||||||
|
- 冒号「:」,U+FF1A
|
||||||
|
|
||||||
|
你需要自己了解并手写解析 UTF-8 编码的代码。使用 C++ 标准库解析 UTF-8 不能得分。
|
||||||
|
|
||||||
|
## Validator *(1.5 pts)*
|
||||||
|
|
||||||
|
本任务的主要目的是练习一些 C++ 语法的使用。
|
||||||
|
|
||||||
|
在写 Bookstore 的时候,你一定会写到很多参数的验证:指令需要验证,帐户信息需要验证,图书信息也需要验证。这个任务提供了一个参数验证方法。例如,如果想验证 `quantity` 在 1 到 10 之间且不是 4,就可以写:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
expect(quantity).ge(1).And.le(10).And.Not().toBe(4);
|
||||||
|
```
|
||||||
|
|
||||||
|
就相当于写:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if (!(quantity >= 1 && quantity <= 10 && quantity != 4)) {
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
本任务要求你实现一个这样的 `expect` 函数(写 bookstore 主体的时候这个函数也能用上),若验证不通过则 `throw` 任意值。它只有一个输入参数,其他参数以*链式调用 (method chaining)* 的方式传入。`expect` 函数是多态的。你需要实现以下接口:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct T {};
|
||||||
|
struct U : T {};
|
||||||
|
T x, y, z;
|
||||||
|
U u;
|
||||||
|
T &ref = u;
|
||||||
|
|
||||||
|
// T 的 == 需要有定义,验证是否有 x == y
|
||||||
|
expect(x).toBe(y);
|
||||||
|
|
||||||
|
// 验证 ref 是否为 U 的实例。
|
||||||
|
// **注意,此处如果 U 根本不是 T 的子类,则需要编译报错。**
|
||||||
|
expect(ref).toBe<U>();
|
||||||
|
|
||||||
|
// T 的 == 需要有定义,接收任意多个(至少一个)参数,验证 x 是否与参数列表中的至少一个值相等
|
||||||
|
expect(x).toBeOneOf(x, y, z, ...);
|
||||||
|
|
||||||
|
// T 的 <= 或 >= 需要有定义,验证是否有 x <= y 或 x >= y
|
||||||
|
expect(x).le(y);
|
||||||
|
expect(x).ge(y);
|
||||||
|
|
||||||
|
// Not() 将后面跟的所有条件取反
|
||||||
|
// 意为 x 不能为 1 或 2
|
||||||
|
expect(x).Not().toBe(1).Or.toBe(2);
|
||||||
|
```
|
||||||
|
|
||||||
|
如果传入的 x 是 [`std::basic_string<CharT>`](https://en.cppreference.com/w/cpp/string/basic_string)(注意不一定是 `std::string`,点击链接跳转到 C++ Reference),则还需实现以下函数:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::basic_string<CharT> str1, str2;
|
||||||
|
|
||||||
|
// 验证 str1 中的所有字符都包含于 str2 中
|
||||||
|
// 例如 expect(std::string("1024.00")).toBeConsistedOf("42.01")
|
||||||
|
// 提示:std::basic_string<CharT>::find()
|
||||||
|
expect(str1).consistedOf(str2);
|
||||||
|
|
||||||
|
// 验证 str1 符合 str2 这个正则表达式
|
||||||
|
// 提示:可以使用 std::basic_regex<CharT> 实现
|
||||||
|
expect(str1).toMatch(str2);
|
||||||
|
```
|
||||||
|
|
||||||
|
这些方法需要能够任意连接:(中间的 `And`, `Or` 和 `but` 为无意义连词,直接令其为 `*this` 即可):
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 意为 x 需要在 10 到 100 之间,且不是 2 3 5 7 11 中的任意一个
|
||||||
|
expect(x)
|
||||||
|
.ge(10)
|
||||||
|
.And.le(100)
|
||||||
|
.but.Not().toBeOneOf(2, 3, 5, 7)
|
||||||
|
.Or.toBe(11);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 并发 *(10 pts)*
|
||||||
|
|
||||||
|
对于一个强大的数据库系统来说,并发功能是非常重要的。在本任务中,你需要实现块链的并发功能。
|
||||||
|
|
||||||
|
从 Wikipedia 上可以找到对于并发的定义:
|
||||||
|
|
||||||
|
> In computer science, concurrency is the ability of different parts or units of a program, algorithm, or problem to be executed out-of-order or in partial order, without affecting the final outcome.
|
||||||
|
|
||||||
|
如果想要进一步了解 C++ 中如何实现一个并发的块状链表,你需要:
|
||||||
|
|
||||||
|
- 学习 C++ 中如何对线程进行操作,可参看 [C++多线程并发基础入门教程](https://zhuanlan.zhihu.com/p/194198073)
|
||||||
|
- 参考链表的线程安全实现,可参看 [使用线程安全型双向链表实现简单 LRU Cache 模拟](https://cloud.tencent.com/developer/article/1902797)
|
||||||
|
|
||||||
|
以上提供的资料仅用于初步了解并发,如果想要实现一个并发的块状链表,你可能还需要搜索、参看更多资料。
|
||||||
|
|
||||||
|
**Hint:** 简单来说,块状链表应该能够同时处理多个块,主要需要考虑如何分块、并块。如果不同线程同时处理的块恰为同一个块,如何让其中一个线程知道这个块正在被占用?将块正在被占用的信息写回外存显然在时间上是不可接受的。
|
||||||
|
|
||||||
|
此 bonus 仅是对于块状链表的要求,如果感兴趣,你也可以让你的主体支持高并发操作。
|
||||||
|
|
||||||
|
**注意:** 准备尝试此任务的同学请务必与助教联系并讨论自己的实现思路。
|
||||||
|
|
||||||
|
## 快照 *(10 pts)*
|
||||||
|
|
||||||
|
对于一个强大的数据库系统来说,支持快照与恢复功能是非常重要的。在本任务中,你需要实现一个快照系统,实现任意快照间的切换。
|
||||||
|
|
||||||
|
一个快照几乎不会占用额外存储空间:
|
||||||
|
|
||||||
|
- 在一个状态上创建一个快照,应该只会占用很小的额外存储来记录这个快照本身的信息,不会将快照的内容完全复制一遍;
|
||||||
|
- 在同样的内容上创建 100 个快照,应该只会占用很小的额外存储,不会使磁盘占用增加 100 倍;
|
||||||
|
- 在创建快照之后改动一小部分内容,再创建一个快照,也应该只会占用很小的额外存储,不会使磁盘占用增加一倍。
|
||||||
|
|
||||||
|
要做到这点,可以利用 [Copy-on-write](https://en.wikipedia.org/wiki/Copy-on-write) 的做法。简单来说,就是令所有块都是不可变的,在试图修改一个块的时候,对这个块做复制,然后在复制出的新块上做修改。但是如果在不快照的时候也对这些块做 copy-on-write 的话,每修改一次数据,就会增加一个新块,这是不可接受的。因此,你需要只在快照的时候做 copy-on-write。
|
||||||
|
|
||||||
|
本任务引入了一条新的指令 `snapshot`,需要权限等级为 7:
|
||||||
|
|
||||||
|
- `[SnapshotID]`
|
||||||
|
- 合法字符集:大小写英文字母和数字;
|
||||||
|
- 最大长度:16;
|
||||||
|
- 保证所有 `SnapshotID` 均合法。
|
||||||
|
- **创建快照**
|
||||||
|
- {7} `snapshot create [SnapshotID]`
|
||||||
|
- 在当前状态上创建一个快照,名称为 `SnapshotID`。
|
||||||
|
- 保证 `SnapshotID` 不会重复。
|
||||||
|
- **还原快照**
|
||||||
|
- {7} `snapshot restore [SnapshotID]`
|
||||||
|
- 还原到名称为 `SnapshotID` 的快照状态,并清空登录栈。
|
||||||
|
- 清空登录栈是为了避免书籍信息被修改所带来的不必要的麻烦;
|
||||||
|
- 保证 `SnapshotID` 是存在的。
|
||||||
|
- **删除快照**
|
||||||
|
- {7} `snapshot delete [SnapshotID]`
|
||||||
|
- 删除名称为 `SnapshotID` 的快照状态,不改变当前状态。
|
||||||
|
- 其占用的存储空间也需一并释放(下文中说明的情况除外);
|
||||||
|
- 保证 `SnapshotID` 是存在的。
|
||||||
|
- **合并快照(仅 A 班需要实现)**
|
||||||
|
- {7} `snapshot merge [SnapshotID]`
|
||||||
|
- 将名称为 `SnapshotID` 的快照状态合并到当前状态(不一定是一个快照)中,并清空登录栈;
|
||||||
|
- 只改变当前状态,快照状态不变;
|
||||||
|
- 清空登录栈是为了避免书籍信息被修改所带来的不必要的麻烦;
|
||||||
|
- 测试数据保证 `SnapshotID` 是存在的。
|
||||||
|
- 「合并」的定义是:
|
||||||
|
- 日志系统不做合并,保留当前日志;
|
||||||
|
- 首先,每个快照都需要记录一个「父节点」的信息,表示这个快照之前的快照;
|
||||||
|
- 对于第一个快照来说,其父节点是空状态。
|
||||||
|
- 找出当前状态与需要合并的快照状态的最小公共祖先;
|
||||||
|
- 即使 LCA 状态所对应的快照被删除了,它的状态也需要被保留。
|
||||||
|
- 将当前状态和需要合并的快照中,每个对象(一本书、一个帐户)的状态分别与 LCA 中的状态作合并。
|
||||||
|
- 如果存在两侧都修改(不包括删除)了同一个对象的情况,则输出 `Invalid\n` 并不做任何合并;
|
||||||
|
- 如果存在两侧都新增了同一个对象的情况(用户以 UserID 为准,书籍以 ISBN 为准),则输出 `Invalid\n` 并不做任何合并;
|
||||||
|
- 如果其中至少一侧删除了一个对象(包括两侧删除了同一个对象),则删除这个对象;
|
||||||
|
- 如果其中恰有一侧修改了一个对象,则保留修改过的对象;
|
||||||
|
- 如果其中恰有一侧新增了一个对象,则保留新增的对象;
|
||||||
|
- 数据保证 ISBN 不会被修改。
|
||||||
|
- 你可以暂时把所有数据加载到内存,但是合并结束之后需要将这些数据写回文件,并从内存中删除;
|
||||||
|
- 实现中不需要考虑时间复杂度。
|
||||||
|
|
||||||
|
**注意:** 准备尝试此任务的同学请务必与助教联系并讨论自己的实现思路。
|
||||||
|
|
||||||
|
## 容错 *(10 pts)*
|
||||||
|
|
||||||
|
程序执行时,我们可能会遇到突然断电等意外情况,导致操作中断。如果此时恰好在对磁盘进行读写操作,那么原本的文件系统就会被破坏,从而造成数据损坏的情况。
|
||||||
|
|
||||||
|
在 Unix 中常用的文件系统中,删除一个文件可以分为 3 步:
|
||||||
|
|
||||||
|
1. 删除访问的 entry 指针
|
||||||
|
2. 释放对应的 index node
|
||||||
|
3. 归还对应的磁盘空间
|
||||||
|
|
||||||
|
如果操作发生中断,一个常见的恢复方式是从第一条输入指令开始,重新执行一整轮操作,但是时间成本显然难以接受。
|
||||||
|
|
||||||
|
因此,我们可以实现一个 journaling file system,利用日志来恢复文件,保证文件的数据不被损坏。
|
||||||
|
|
||||||
|
我们可以考虑把一个指令分为多个 **原子操作** (atomic operation),在 journal 中保存每个原子操作。当程序中断时,我们就可以知道保存了哪些原子操作,进而进行文件恢复。
|
||||||
|
|
||||||
|
**Hint**:请思考一下在不同步骤发生中断时,应该如何选取合适的原子操作,并通过原子操作来恢复文件。 [reference link](https://en.wikipedia.org/wiki/Journaling_file_system)
|
||||||
|
|
||||||
|
**注意:** 准备尝试此任务的同学请务必与助教联系并讨论自己的实现思路。
|
||||||
|
|
||||||
|
## GUI 前端 *(8.5 pts)*
|
||||||
|
|
||||||
|
提供一个用户友好的图形化前端(Qt、Gtk、Web、Tcl/Tk 等均可)。基本要求为:
|
||||||
|
|
||||||
|
- 前后端分离,即前端代码不过度侵入主体逻辑;
|
||||||
|
- 用户能通过用户友好的图形化界面完成**所有**操作;
|
||||||
|
- 提供完整的《系统安装手册》《用户手册》。
|
||||||
|
|
||||||
|
**注意:** 准备尝试此任务的同学请务必与助教联系并讨论自己的实现思路。
|
40
docs/homework_requirement/业务要求.md
Normal file
40
docs/homework_requirement/业务要求.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# 业务要求
|
||||||
|
|
||||||
|
## 基本要求
|
||||||
|
|
||||||
|
设计并实现一个书店管理系统。该书店管理系统应当面向三类人员:顾客、销售人员和店长。最终交接物为需求分析文档、总体设计文档(13 周周二前)和源代码(16 周周一前)。关于程序有以下要求:
|
||||||
|
|
||||||
|
- 编程语言限制:软件主体(除 bonus 部分外)完全使用 C++ 编写;
|
||||||
|
- 系统数据需要存储在外存中;
|
||||||
|
- 系统首次运行时应当创建店主账户,其具有最高权限;
|
||||||
|
- 管理系统应当使用命令行进行交互;
|
||||||
|
|
||||||
|
- 系统支持嵌套登录,即允许多个帐户同时处于登录状态;允许同一帐户同时多次登录。输入的指令视为最后登录的帐户操作;
|
||||||
|
|
||||||
|
## 游客
|
||||||
|
|
||||||
|
游客只能注册/登录用户。
|
||||||
|
|
||||||
|
## 顾客
|
||||||
|
|
||||||
|
顾客可以查询和购买图书。
|
||||||
|
|
||||||
|
- 每种图书包含的信息有:ISBN 号(20 个数字,每本正版书都有惟一的标识)、书名(60 个字符、作者(60 个字符)、关键字(可以有多个,总共不超过 60 个字符)、库存量(整型)、单价(非负实数);
|
||||||
|
|
||||||
|
- 查询图书时可以根据 ISBN 号、作者名字、关键字、书名中的任意组合进行查询;
|
||||||
|
- 购买图书时,我们通过给定的 ISBN 号和购买数量来进行操作;
|
||||||
|
|
||||||
|
## 销售人员
|
||||||
|
|
||||||
|
销售人员可以执行所有顾客执行的操作,同时也可以进行进货、图书信息录入、图书信息修改、用户创建。
|
||||||
|
|
||||||
|
- 进货时需指定 ISBN 号、数量、进货价格;
|
||||||
|
- 第一次录入图书时,应当输入其完整信息;
|
||||||
|
|
||||||
|
## 店长
|
||||||
|
|
||||||
|
店长可以执行所有销售人员和顾客可以执行的功能,同时也可以查询某段时间的采购信息(即按照采购顺序输出采购图书的 ISBN 号、数量、单价等)、销售情况(即按照销售顺序输出售出图书的 ISBN 号、数量、单价等)、盈利信息(即输出该段时间的收入,支出以及利润)。除此之外,店长也可以查看各员工的工作情况报告(即按操作顺序输出每次操作类型及其对象,如创建用户操作以及对应的用户信息)和系统的整体工作日志。
|
||||||
|
|
||||||
|
## 性能需求
|
||||||
|
|
||||||
|
考虑到应用场景下帐户和图书数量较大,故**禁止将主体数据存储于内存**,应实时读写文件数据。运行过程中程序创建的文件数量不得超过 20 个。
|
0
docs/user/用户手册.md
Normal file
0
docs/user/用户手册.md
Normal file
0
docs/user/系统安装手册.md
Normal file
0
docs/user/系统安装手册.md
Normal file
7024
external/clipp/clipp.h
vendored
Normal file
7024
external/clipp/clipp.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
24596
external/json/json.hpp
vendored
Normal file
24596
external/json/json.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
0
frontend/index.js
Normal file
0
frontend/index.js
Normal file
657
frontend/package-lock.json
generated
Normal file
657
frontend/package-lock.json
generated
Normal file
@ -0,0 +1,657 @@
|
|||||||
|
{
|
||||||
|
"name": "BookStoreWebUI",
|
||||||
|
"version": "0.0.0.1",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "BookStoreWebUI",
|
||||||
|
"version": "0.0.0.1",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.18.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/accepts": {
|
||||||
|
"version": "1.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
|
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-types": "~2.1.34",
|
||||||
|
"negotiator": "0.6.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/array-flatten": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
||||||
|
},
|
||||||
|
"node_modules/body-parser": {
|
||||||
|
"version": "1.20.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
|
||||||
|
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
|
||||||
|
"dependencies": {
|
||||||
|
"bytes": "3.1.2",
|
||||||
|
"content-type": "~1.0.4",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"destroy": "1.2.0",
|
||||||
|
"http-errors": "2.0.0",
|
||||||
|
"iconv-lite": "0.4.24",
|
||||||
|
"on-finished": "2.4.1",
|
||||||
|
"qs": "6.11.0",
|
||||||
|
"raw-body": "2.5.1",
|
||||||
|
"type-is": "~1.6.18",
|
||||||
|
"unpipe": "1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8",
|
||||||
|
"npm": "1.2.8000 || >= 1.4.16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/bytes": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/call-bind": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-intrinsic": "^1.2.1",
|
||||||
|
"set-function-length": "^1.1.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/content-disposition": {
|
||||||
|
"version": "0.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||||
|
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "5.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/content-type": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cookie": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cookie-signature": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/define-data-property": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"get-intrinsic": "^1.2.1",
|
||||||
|
"gopd": "^1.0.1",
|
||||||
|
"has-property-descriptors": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/depd": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/destroy": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8",
|
||||||
|
"npm": "1.2.8000 || >= 1.4.16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ee-first": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||||
|
},
|
||||||
|
"node_modules/encodeurl": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/escape-html": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
|
||||||
|
},
|
||||||
|
"node_modules/etag": {
|
||||||
|
"version": "1.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||||
|
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/express": {
|
||||||
|
"version": "4.18.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
||||||
|
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"accepts": "~1.3.8",
|
||||||
|
"array-flatten": "1.1.1",
|
||||||
|
"body-parser": "1.20.1",
|
||||||
|
"content-disposition": "0.5.4",
|
||||||
|
"content-type": "~1.0.4",
|
||||||
|
"cookie": "0.5.0",
|
||||||
|
"cookie-signature": "1.0.6",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"encodeurl": "~1.0.2",
|
||||||
|
"escape-html": "~1.0.3",
|
||||||
|
"etag": "~1.8.1",
|
||||||
|
"finalhandler": "1.2.0",
|
||||||
|
"fresh": "0.5.2",
|
||||||
|
"http-errors": "2.0.0",
|
||||||
|
"merge-descriptors": "1.0.1",
|
||||||
|
"methods": "~1.1.2",
|
||||||
|
"on-finished": "2.4.1",
|
||||||
|
"parseurl": "~1.3.3",
|
||||||
|
"path-to-regexp": "0.1.7",
|
||||||
|
"proxy-addr": "~2.0.7",
|
||||||
|
"qs": "6.11.0",
|
||||||
|
"range-parser": "~1.2.1",
|
||||||
|
"safe-buffer": "5.2.1",
|
||||||
|
"send": "0.18.0",
|
||||||
|
"serve-static": "1.15.0",
|
||||||
|
"setprototypeof": "1.2.0",
|
||||||
|
"statuses": "2.0.1",
|
||||||
|
"type-is": "~1.6.18",
|
||||||
|
"utils-merge": "1.0.1",
|
||||||
|
"vary": "~1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/finalhandler": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"encodeurl": "~1.0.2",
|
||||||
|
"escape-html": "~1.0.3",
|
||||||
|
"on-finished": "2.4.1",
|
||||||
|
"parseurl": "~1.3.3",
|
||||||
|
"statuses": "2.0.1",
|
||||||
|
"unpipe": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/forwarded": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fresh": {
|
||||||
|
"version": "0.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
|
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/function-bind": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-intrinsic": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"has-proto": "^1.0.1",
|
||||||
|
"has-symbols": "^1.0.3",
|
||||||
|
"hasown": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gopd": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||||
|
"dependencies": {
|
||||||
|
"get-intrinsic": "^1.1.3"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-property-descriptors": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
|
||||||
|
"dependencies": {
|
||||||
|
"get-intrinsic": "^1.2.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-symbols": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hasown": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-errors": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"inherits": "2.0.4",
|
||||||
|
"setprototypeof": "1.2.0",
|
||||||
|
"statuses": "2.0.1",
|
||||||
|
"toidentifier": "1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/iconv-lite": {
|
||||||
|
"version": "0.4.24",
|
||||||
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
|
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||||
|
"dependencies": {
|
||||||
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
|
},
|
||||||
|
"node_modules/ipaddr.js": {
|
||||||
|
"version": "1.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||||
|
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/media-typer": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/merge-descriptors": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
|
||||||
|
},
|
||||||
|
"node_modules/methods": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||||
|
"bin": {
|
||||||
|
"mime": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
|
},
|
||||||
|
"node_modules/negotiator": {
|
||||||
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/object-inspect": {
|
||||||
|
"version": "1.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
||||||
|
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/on-finished": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
|
||||||
|
"dependencies": {
|
||||||
|
"ee-first": "1.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/parseurl": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/path-to-regexp": {
|
||||||
|
"version": "0.1.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||||
|
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
|
||||||
|
},
|
||||||
|
"node_modules/proxy-addr": {
|
||||||
|
"version": "2.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
|
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
|
||||||
|
"dependencies": {
|
||||||
|
"forwarded": "0.2.0",
|
||||||
|
"ipaddr.js": "1.9.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/qs": {
|
||||||
|
"version": "6.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||||
|
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"side-channel": "^1.0.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/range-parser": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/raw-body": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
|
||||||
|
"dependencies": {
|
||||||
|
"bytes": "3.1.2",
|
||||||
|
"http-errors": "2.0.0",
|
||||||
|
"iconv-lite": "0.4.24",
|
||||||
|
"unpipe": "1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"node_modules/safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
|
},
|
||||||
|
"node_modules/send": {
|
||||||
|
"version": "0.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||||
|
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"destroy": "1.2.0",
|
||||||
|
"encodeurl": "~1.0.2",
|
||||||
|
"escape-html": "~1.0.3",
|
||||||
|
"etag": "~1.8.1",
|
||||||
|
"fresh": "0.5.2",
|
||||||
|
"http-errors": "2.0.0",
|
||||||
|
"mime": "1.6.0",
|
||||||
|
"ms": "2.1.3",
|
||||||
|
"on-finished": "2.4.1",
|
||||||
|
"range-parser": "~1.2.1",
|
||||||
|
"statuses": "2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/send/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
|
},
|
||||||
|
"node_modules/serve-static": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
|
||||||
|
"dependencies": {
|
||||||
|
"encodeurl": "~1.0.2",
|
||||||
|
"escape-html": "~1.0.3",
|
||||||
|
"parseurl": "~1.3.3",
|
||||||
|
"send": "0.18.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/set-function-length": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"define-data-property": "^1.1.1",
|
||||||
|
"get-intrinsic": "^1.2.1",
|
||||||
|
"gopd": "^1.0.1",
|
||||||
|
"has-property-descriptors": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/setprototypeof": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
||||||
|
},
|
||||||
|
"node_modules/side-channel": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind": "^1.0.0",
|
||||||
|
"get-intrinsic": "^1.0.2",
|
||||||
|
"object-inspect": "^1.9.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/statuses": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/toidentifier": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/type-is": {
|
||||||
|
"version": "1.6.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||||
|
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||||
|
"dependencies": {
|
||||||
|
"media-typer": "0.3.0",
|
||||||
|
"mime-types": "~2.1.24"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/unpipe": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/utils-merge": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vary": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
frontend/package.json
Normal file
16
frontend/package.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "BookStoreWebUI",
|
||||||
|
"version": "0.0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "ZhuangYumin",
|
||||||
|
"license": "ISC",
|
||||||
|
"type": "commonjs",
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.18.2"
|
||||||
|
}
|
||||||
|
}
|
0
maintenance/install.sh
Executable file
0
maintenance/install.sh
Executable file
Reference in New Issue
Block a user