diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
index 16a18c5..14958fa 100644
--- a/docs/.vuepress/config.js
+++ b/docs/.vuepress/config.js
@@ -27,6 +27,7 @@ module.exports = {
],
sidebar: [
// ['/', '首页'],
+ ['/zh/getting-started', '快速开始'],
['/zh/guide', '指南'],
'/zh/app-acl',
['/zh/app-model-extends', 'ORM 扩展选项'],
diff --git a/docs/index.md b/docs/index.md
index b4360b4..626f016 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -4,13 +4,13 @@ home: true
heroText: fib-app
tagline: 为个人网站和中小企业而生
actionText: 快速上手 →
-actionLink: /zh/guide
+actionLink: /zh/getting-started
features:
-- title: RESTful
- details: 内部基于 RESTful 标准实现,一键部署 http 服务
-- title: ORM
+- title: RESTful/GraphQL
+ details: 将你的数据库一键变为标准的 http rest 服务, 并带有 GraphQL 支持
+- title: RDB ORM
details: 基于 @fxjs/orm, 快速连接已有关系型数据库(MySQL/SQLite)
-- title: 高性能
- details: 享受 fibjs 的高性能
+- title: Fast!
+ details: 享受来自 FIBJS 生态的高性能
footer: MIT Licensed | Copyright © 2015-present fibjs
---
\ No newline at end of file
diff --git a/docs/zh/app-internal-api.md b/docs/zh/app-internal-api.md
index 8d769ef..d3ccafb 100644
--- a/docs/zh/app-internal-api.md
+++ b/docs/zh/app-internal-api.md
@@ -1,6 +1,6 @@
## `app.api.*`
-通过内部方法, 直接进行 rest 风格的操作, 详情可参考 [@types/app.d.ts] 中的 FibAppInternalApis.
+通过内部方法, 直接进行 rest 风格的操作, 详情可参考 [typings/app.d.ts] 中的 FibAppInternalApis.
- app.api.post: FibAppIneternalApiFunction__Post
- app.api.get: FibAppIneternalApiFunction__Get
@@ -20,7 +20,7 @@ FibAppInternalApis 中的所有所有 rest 操作函数, 内部都经过了 `app
* `app.filterRequest: FibAppSetupChainFn`
-注意该函数无返回值, 而是以最后一个参数作为回调函数. 更多详情可参考 [@types/app.d.ts](@types/app.d.ts)
+注意该函数无返回值, 而是以最后一个参数作为回调函数. 更多详情可参考 [typings/app.d.ts]
使用 `app.filterRequest` 为 app 定制个性化的路由
------------
@@ -74,11 +74,13 @@ app.get('/__null_cls', (request) => {
实际上, [Model Function](./app-model-function.md) 正是通过 `app.filterRequest` 实现的, 详情可参考 [src/classes/index.ts] 中关于 `app.post(':classname/:func', ...)` 的实现.
[mq.Routing]:http://fibjs.org/docs/manual/object/ifs/routing.md.html
-[src/classes]:src/classes
-[src/classes/index.ts]:src/classes/index.ts
-[src/classes/base.ts]:src/classes/base.ts
-[src/classes/extend.ts]:src/classes/extend.ts
+
+[src/http/index.ts]:https://github.com/fibjs/fib-app/blob/master/src/http/index.ts
+[src/http/base.ts]:https://github.com/fibjs/fib-app/blob/master/src/http/base.ts
+[src/http/extend.ts]:https://github.com/fibjs/fib-app/blob/master/src/http/extend.ts
### hasMany-extra read/epost/eput(beta)
-...
\ No newline at end of file
+...
+
+[typings/app.d.ts]:https://github.com/fibjs/fib-app/blob/master/typings/app.d.ts
diff --git a/docs/zh/app-model-extends.md b/docs/zh/app-model-extends.md
index 7c259ba..c1b31cb 100644
--- a/docs/zh/app-model-extends.md
+++ b/docs/zh/app-model-extends.md
@@ -4,7 +4,7 @@
你可以在 Model Function 中调用 app.api 上的 rest 风格函数, 来定制属于你的函数, 比如
-```JavaScript
+```js
module.exports = db => {
var Person = db.define('person', {
name: String,
@@ -202,9 +202,12 @@ viewFunctions: {
#### 共同点
`viewFunction` 与 `function` 很相似
-1. 都要返回符合 [`FibAppResponse` 格式](./@types/app.d.ts) 的对象
+1. 都要返回符合 [`FibAppResponse` 格式] 的对象
1. 都是 ORM Model 的定义选项
#### 区别
1. `function` 处理 fib-app 中的 `POST /:classname/:func` 请求; `viewFunctions` 处理 fib-app 中的 `GET /:classname/:func` 且 `Accept` 头包含 `text/html` 的请求
1. `function` 函数的返回值, fib-app 会尝试以 json 的方式写入 `HttpResponse`; `viewFunction` 函数的返回值, fib-app 会尝试以文本的方式写入 `HttpResponse`
+
+[typings/app.d.ts]:https://github.com/fibjs/fib-app/blob/master/typings/app.d.ts
+[`FibAppResponse` 格式]:typings/app.d.ts
diff --git a/docs/zh/getting-started.md b/docs/zh/getting-started.md
new file mode 100644
index 0000000..1260c6a
--- /dev/null
+++ b/docs/zh/getting-started.md
@@ -0,0 +1,174 @@
+# 快速开始
+
+[](https://www.npmjs.org/package/fib-app)
+[![Build Status][actions-image]][actions-url]
+
+[actions-image]:https://github.com/fibjs/fib-app/actions/workflows/run-ci.yml/badge.svg
+[actions-url]:https://github.com/fibjs/fib-app/actions/workflows/run-ci.yml
+
+基于 `fib-app`, 快速对业务建模, 并通过 http 对模型进行 restful 操作.
+
+```js
+// index.js
+const http = require('http');
+const App = require('fib-app');
+
+const person_def = App.defineAppModel(orm => {
+ orm.define('person', {
+ name: String,
+ age: Number,
+ gender: ['male', 'female']
+ })
+})
+
+const app = new App('sqlite:test.db');
+app.db.use(person_def);
+
+const svr = new http.Server(1234, [
+ {
+ '/1.0': app
+ }
+]);
+
+svr.start();
+```
+
+通过 `fibjs index.js`, 运行上述代码, 我们就完成了两项工作:
+
+1. 对数据库中的表(`person`)建模
+2. 将其映射到了 `http://127.0.0.1:1234/1.0` 这个 endpoint
+
+现在我们可以通过该 endpoint 对数据库进行操作
+
+## create
+
+**请求格式**: `POST http://{endpoint}/{model_name}`
+
+通过 POST 操作, 我们可以向数据库中添加一条 person 数据
+
+```bash
+curl -X POST 'http://127.0.0.1:1234/1.0/person' \
+ -H 'Content-Type: application/json' \
+ -d '{"name": "Jack", "age": 12, "gender": "male"}'
+```
+
+请求结果:
+
+```json
+{
+ "id": 1,
+ "createdAt": "2022-12-17T13:06:41.592Z"
+}
+```
+
+这表示, 该操作往数据库中添加了一条新数据, 且其 id 为 1
+
+## get
+
+**请求格式**: `GET http://{endpoint}/{model_name}/:id`
+
+已知一个 `person` 的 id, 可以通过 GET 请求查询其信息
+
+```bash
+curl -X GET 'http://127.0.0.1:1234/1.0/person/1'
+```
+
+请求结果:
+
+```json
+{
+ "name": "Jack",
+ "age": 12,
+ "gender": "male",
+ "createdAt": "2022-12-17T13:06:41.592Z",
+ "updatedAt": "2022-12-17T13:06:41.592Z",
+ "id":1
+}
+```
+
+如果查询一个不存在的 id, 则会返回错误:
+
+```bash
+curl -X GET 'http://127.0.0.1:1234/1.0/person/9999'
+```
+
+请求结果
+
+```json
+{
+ "code":4040102,
+ "message":"Object '9999' not found in class 'person'."
+}
+```
+
+## find
+
+**请求格式**: `GET http://{endpoint}/{model_name}`
+
+在不知道 id 情况下, 我们也可以直接尝试 list `person`,
+
+```bash
+curl -X GET 'http://127.0.0.1:1234/1.0/person'
+```
+
+请求结果:
+
+```json
+[
+ {
+ "name": "Jack",
+ "age": 12,
+ "gender": "male",
+ "createdAt": "2022-12-17T13:06:41.592Z",
+ "updatedAt": "2022-12-17T13:06:41.592Z",
+ "id":1
+ }
+]
+```
+
+## update
+
+**请求格式**: `PUT http://{endpoint}/{model_name}/:id`
+
+已知一个 `person` 的 id, 可以通过 PUT 请求更改其信息
+
+```bash
+curl -X PUT 'http://127.0.0.1:1234/1.0/person/1' \
+ -H 'Content-Type: application/json' \
+ -d '{"age": 13}'
+```
+
+请求结果:
+
+```json
+{
+ "id":1
+}
+```
+
+这表示, 该操作改变了数据库中 id 为 1 的 person 的数据
+
+
+## remove
+
+**请求格式**: `DELETE http://{endpoint}/{model_name}/:id`
+
+已知一个 `person` 的 id, 可以通过 DELETE 请求删除这条数据
+
+```bash
+curl -X DELETE 'http://127.0.0.1:1234/1.0/person/1'
+```
+
+请求结果:
+
+```json
+{
+ "id":1
+}
+```
+
+这表示, 该操作删除了数据库中 id 为 1 的 person 的数据.
+
+## 下一步呢?
+
+让我们跟随[指南](/zh/guide.html), 学习 fib-app 更多的定制方法.
diff --git a/docs/zh/guide.md b/docs/zh/guide.md
index 333edea..148430b 100644
--- a/docs/zh/guide.md
+++ b/docs/zh/guide.md
@@ -2,41 +2,54 @@
## 建立基础脚本
-```JavaScript
+```js
+// index.js
const http = require('http');
const util = require('util')
const Session = require('fib-session')
-const App = require('../');
+const App = require('fib-app');
-var app = new App('sqlite:test.db', {
+const app = new App('sqlite:test.db', {
uuid: true
});
app.db.use(require('./defs/person'));
-var session = new Session(new util.LruCache(20000), {
+const session = new Session(new util.LruCache(20000), {
timeout: 60 * 1000
});
-var svr = new http.Server(8080, [
+const svr = new http.Server(8080, [
session.cookie_filter,
{
'/1.0': app
}
]);
-svr.run();
+
+svr.start();
```
+
其中 `person` 是 Model 定义模块, 内容如下:
-```JavaScript
-module.exports = db => {
+
+```js
+// person.js
+const { defineAppModel } = require('fib-app')
+
+// defineAppModel is not requried, you can return the define function directly
+module.exports = defineAppModel(db => {
db.define('person', {
name: String,
sex: ["male", "female"],
age: Number
});
-};
+});
```
+
这是一个标准的 orm 定义, 同样可以使用 orm 的其它功能, 比如类型检查, 事件等。
+**注意**: 定义一个 orm model 时, `defineAppModel` 不是必需的, 你可以直接返回这个函数作为 orm 定义, 但是, 使用 `defineAppModel` 方法, 可以在开发中获得更好的类型提示:
+
+
+
## API 数据格式
对于 POST 和 PUT 请求, 请求的主体必须是 JSON 格式, 而且 HTTP header 的 Content-Type 需要设置为 application/json。
@@ -49,8 +62,8 @@ curl -X PUT \
```
对于所有的请求, 响应格式都是一个 JSON 对象。
-一个请求是否成功是由 HTTP 状态码标明的。一个 2XX 的状态码表示成功, 而一个 4XX 表示请求失败。当一个请求失败时响应的主体仍然是一个 JSON 对象, 但是总是会包含 code 和 message 这两个字段, 你可以用它们来进行调试。举个例子, 如果一个请求权限认证失败, 会返回以下信息:
-```JavaScript
+一个请求是否成功是由 HTTP 状态码标明的。一个 `2XX` 的状态码表示成功, 而一个 `4XX` 表示请求失败。当一个请求失败时响应的主体仍然是一个 JSON 对象, 但是总是会包含 code 和 message 这两个字段, 你可以用它们来进行调试。举个例子, 如果一个请求权限认证失败, 会返回以下信息:
+```js
{
"code": 4030501,
"message": "The operation isn’t allowed for clients due to class-level permissions."
@@ -59,7 +72,7 @@ curl -X PUT \
code 编码分为三个部分, 前三位 403 表示错误类型, 05 表示数据表编号, 01 表示详细错误编码。
对于 GET 请求, 通常会返回对象数据, 根据 GET 请求的地址不同, 可能会返回一个对象, 也可能会返回一个数组。比如:
-```JavaScript
+```js
{
"name": "tom",
"sex": "male",
@@ -67,7 +80,7 @@ code 编码分为三个部分, 前三位 403 表示错误类型, 05 表示数据
}
```
或者:
-```JavaScript
+```js
[
{
"name": "tom",
@@ -82,6 +95,7 @@ code 编码分为三个部分, 前三位 403 表示错误类型, 05 表示数据
]
```
## 特殊字段
+
对象数据中, 有四个特殊含义的字段, 是不允许通过 API 更改的。分别是 `id`, `updatedAt`, `createdAt`, `createdBy`.
其中 `id`, `updatedAt`, `createdAt` 单个字段会自动创建和修改。`createdBy` 则需要自行指定类型。
@@ -106,7 +120,7 @@ curl -X POST \
http://localhost/1.0/person
```
当创建成功时, HTTP 的返回是 201 Created, 响应的主体是一个 JSON 对象, 包含新的对象的 objectId 和 createdAt 时间戳:
-```JavaScript
+```js
{
"createdAt": "2017-11-25T01:39:35.931Z",
"id": "57fbbdb0a2400000"
@@ -118,7 +132,7 @@ curl -X POST \
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000
```
返回的主体是一个 JSON 对象包含所有用户提供的 field 加上 `createdAt`、`updatedAt` 和 `id` 字段:
-```JavaScript
+```js
{
"name": "tom",
"sex": "male",
@@ -133,7 +147,7 @@ curl -X GET http://localhost/1.0/person/57fbbdb0a2400000
curl -X GET http://localhost/1.0/person/57fbbdb0a2400000?keys=name%2Csex
```
将返回:
-```JavaScript
+```js
{
"name": "tom",
"sex": "male"
@@ -148,7 +162,7 @@ curl -X PUT \
http://localhost/1.0/person/57fbbdb0a2400000
```
返回的 JSON 对象会包含 `updatedAt` 和 `id` 字段, 表明更新发生的时间:
-```JavaScript
+```js
{
"updatedAt": "2017-11-25T01:39:35.931Z",
"id": "57fbbdb0a2400000"
@@ -165,7 +179,7 @@ curl -X DELETE http://localhost/1.0/person/57fbbdb0a2400000
curl -X GET http://localhost/1.0/person
```
返回的值就是一个 JSON 对象包含了 results 字段, 它的值就是对象的列表:
-```JavaScript
+```js
[
{
"name": "tom",
@@ -207,19 +221,19 @@ curl -X GET http://localhost/1.0/person?where=%7B%22name%22%3A%22tom%22%7D
| key | operation | sample |
|--------------|-----------|-----------------------|
-| eq | 等于 | {"name":{"eq":"tom"}} 或者 {"name":"tom"} |
-| ne | 不等于 | {"name":{"ne":"tom"}} |
-| gt | 大于 | {"age":{"gt":"24"}} |
-| gte | 大于等于 | {"age":{"gte":"24"}} |
-| lt | 小于 | {"age":{"lt":"24"}} |
-| lte | 小于等于 | {"age":{"lte":"24"}} |
-| like | 模糊查询 | {"name":{"like":"%m"}} |
-| not\_like | 模糊查询 | {"name":{"not_like":"%m"}} |
-| between | 区间比较 | {"age":{"between":[22,25]}} |
-| not\_between | 区间比较 | {"age":{"not_between":[22,25]}} |
-| in | 枚举 | {"name":{"in":["tom","lily"]}} |
-| not\_in | 枚举 | {"name":{"not_in":["tom","lily"]}} |
-| or | 或运算 | {"or":[{"name":"tom"},{"age":24}]} |
+| eq | 等于 | `{"name":{"eq":"tom"}}` 或者 `{"name":"tom"}` |
+| ne | 不等于 | `{"name":{"ne":"tom"}}` |
+| gt | 大于 | `{"age":{"gt":"24"}}` |
+| gte | 大于等于 | `{"age":{"gte":"24"}}` |
+| lt | 小于 | `{"age":{"lt":"24"}}` |
+| lte | 小于等于 | `{"age":{"lte":"24"}}` |
+| like | 模糊查询 | `{"name":{"like":"%m"}}` |
+| not\_like | 模糊查询 | `{"name":{"not_like":"%m"}}` |
+| between | 区间比较 | `{"age":{"between":[22,25]}}` |
+| not\_between | 区间比较 | `{"age":{"not_between":[22,25]}}` |
+| in | 枚举 | `{"name":{"in":["tom","lily"]}}` |
+| not\_in | 枚举 | `{"name":{"not_in":["tom","lily"]}}` |
+| or | 或运算 | `{"or":[{"name":"tom"},{"age":24}]}` |
#### skip 跳过记录
通过 `skip` 选项, 可以跳过指定的记录数, 达到翻页的效果。
@@ -242,7 +256,7 @@ curl -X GET http://localhost/1.0/person?order=-id
curl -X GET http://localhost/1.0/person?count=1&limit=1
```
此时返回结果将包含 `count` 和 `results` 两个字段, 分别包含总数和结果:
-```JavaScript
+```js
{
"count": 2,
"results": [
@@ -260,7 +274,7 @@ curl -X GET http://localhost/1.0/person?count=1&limit=1
## 建立扩展对象
通过 orm 定义 hasOne 和 hasMany, 可以定义对象之间的关联关系, 并在 API 上体现出来, 例如:
-```JavaScript
+```js
module.exports = db => {
var Person = db.models.person;
@@ -342,16 +356,13 @@ Person.hasMany('pets', Pet, {}, {reverse: 'owners'});
curl -X GET http://localhost/1.0/pet/57fbbdb0a2400007/owners
```
-#### findby 过滤条件
-
-**Started From 1.13.20, >= 1.13.25 Recommended**
+#### findby 过滤条件
通过 `findby` 参数的形式可以对查询对象做出约束。和 `where` 一样, `findby` 参数的值应该是被 JSON 编码又经过 url 编码的的。
参数包含的选项含义如下
- `findby.extend` 是由 orm 定义时的 `hasOne`, `hasMany`, `extendsTo` 关联关系. 如 extend 描述的**关联关系**对该**基础对象**而言不存在, 则该 `findby` 条件实际上不会生效.
-- `findby.where`: 只适用于 `hasOne` 关系 适用于所有的扩展关系. 与[基础的 where](#where-选项) 含义一致.
-- `findby.on`: 只适用于 `hasMany` 关系. 与[基础的 where](#where-选项) 含义一致, 但其 key 只能是关联关系中的字段, 而不能是被关联中的对象中的字段. 推荐使用功能更为完备的 `findby.where`
+- `findby.where`: 与[基础的 where](#where-选项) 含义一致.
例如, 存在以下关系
@@ -370,26 +381,27 @@ curl -X GET http://localhost/1.0/person?findby=%7B%22extend%22%3A%22father%22%2C
```sh
curl -X GET http://localhost/1.0/person?findby=%7B%22extend%22%3A%22pets%22%2C%22on%22%3A%7B%22pets_id%22%3A%2257fbbdb0a2400007%22%7D%7D
```
-`findby` 的内容为:`{"extend":"pets","on":{"pets_id":"57fbbdb0a2400007"}}`
+`findby` 的内容为:`{"extend":"pets","where":{"pets_id":"57fbbdb0a2400007"}}`
这看起来似乎等价于 [查询具有reverse关系的扩展对象列表](#查询具有reverse关系的扩展对象列表), 事实上, 当以**完全匹配id**作为查询条件的时候的确如此. 但 findby 比 [查询具有reverse关系的扩展对象列表](#查询具有reverse关系的扩展对象列表) 的优势在于, 可以使用复杂的 where 条件. 例如, 如果我们想搜索宠物 id **不为某些值**的的用户, 就可以这样写:
```sh
curl -X GET http://localhost/1.0/person?findby=%7B%22extend%22%3A%22pets%22%2C%22on%22%3A%7B%22pets_id%22%3A%7B%22not_in%22%3A%5B%2257fbbdb0a2400007%22%5D%7D%7D%7D
```
-`findby` 的内容为:`{"extend":"pets","on":{"pets_id":{"not_in":["57fbbdb0a2400007"]}}}`
-
-
-#### join_where 过滤条件
+`findby` 的内容为:`{"extend":"pets","where":{"pets_id":{"not_in":["57fbbdb0a2400007"]}}}`
-**Started From 1.13.25**
-通过 `join_where` 参数的形式可以在对具有 hasMany 关系的扩展对象查询时, 对关联表中的字段进行筛选做出约束。和 `where` 一样, `join_where` 参数的值应该是被 JSON 编码又经过 url 编码的的。
+#### 将 hasMany 扩展对象中的 extra 属性作为查询条件
例如, 存在以下关系
-- person hasMany pets, 且含有扩展字段:
- - nickname: { type: "text", size: 256 }
+```js
+person.hasMany('pets', pets, {
+ nickname: { type: "text", size: 256 }
+}, {
+ // ...options
+})
+```
现在我们希望查询级联的用户、宠物信息, 要求**按照"拥有年龄不低于 1 岁的的宠物" 对 person 进行 findby 查找**
@@ -437,7 +449,7 @@ curl -X GET http://localhost/1.0/person?findby=%7B%22extend%22%3A%22pets%22%2C%2
id
name
pets(
- join_where: {
+ where: {
nickname: { like: "%a%" }
}
){
@@ -470,11 +482,6 @@ curl -X GET http://localhost/1.0/person?findby=%7B%22extend%22%3A%22pets%22%2C%2
pets(
where: {
age: {gte: 1}
- }
- # where 和 join_where 可以一起使用, 二者含义不同
- # where 的筛选对象是 pet 本身的字段;
- # join_where 的筛选对象是 person-pet 关系中的扩展字段;
- join_where: {
nickname: { like: "%a%" }
}
){
@@ -490,7 +497,7 @@ curl -X GET http://localhost/1.0/person?findby=%7B%22extend%22%3A%22pets%22%2C%2
## ACL
可以通过定义 Model 的 ACL 控制数据权限。比如:
-```JavaScript
+```js
const orm = require('@fxjs/orm');
module.exports = db => {
@@ -518,7 +525,7 @@ module.exports = db => {
};
```
如果定义 Model 时未指定 ACL, 则等同于设定了缺省权限:
-```JavaScript
+```js
{
"*": {
"*": true
@@ -554,7 +561,7 @@ ACL 根据 API 行为将权限分类五种:
比如以上例子, 如果需要设定 `user` 只允许读取 `title` 和 `detail`, 其他人可以读取 `title`, 则可以这样设定:
-```JavaScript
+```js
{
"*": {
"*": false,
@@ -575,7 +582,7 @@ ACL 根据 API 行为将权限分类五种:
在 Model 上设定的是整个类的权限, 如果需要对具体的对象设定权限, 可以通过设置 OACL 来实现:
-```JavaScript
+```js
module.exports = db => {
db.define('person', {
name: String,
@@ -610,7 +617,7 @@ module.exports = db => {
### 扩展对象权限
扩展对象的访问权限控制和基础对象权限相似, 唯一不同的是在 ACL 需要单独指定:
-```JavaScript
+```js
module.exports = db => {
var Person = db.define('person', {
name: String,
@@ -669,7 +676,7 @@ curl -X GET http://localhost/1.0/person/57fbbdb0a2400000/pets/57fbbdb0a2400007
## 类型
-如果要使用 fib-app 的高级特性, 你需要了解至少以下类型. 更多的类型可参见 [@types/app.d.ts]
+如果要使用 fib-app 的高级特性, 你需要了解至少以下类型. 更多的类型可参见 [typings/app.d.ts]
```typescript
interface FibAppORMModelFunction {
@@ -754,4 +761,4 @@ doSomething(orm)
- [ORM 扩展选项](./app-model-extends.md)
[fib-pool]:https://github.com/fibjs/fib-pool
-[@types/app.d.ts]:https://github.com/fibjs/fib-app/blob/master/%40types/app.d.ts
+[typings/app.d.ts]:https://github.com/fibjs/fib-app/blob/master/typings/app.d.ts
diff --git a/examples/simple-person/.gitignore b/examples/simple-person/.gitignore
new file mode 100644
index 0000000..483a9c4
--- /dev/null
+++ b/examples/simple-person/.gitignore
@@ -0,0 +1 @@
+package-lock.json
\ No newline at end of file
diff --git a/examples/simple-person/index.js b/examples/simple-person/index.js
new file mode 100644
index 0000000..74b06fb
--- /dev/null
+++ b/examples/simple-person/index.js
@@ -0,0 +1,125 @@
+const http = require('http');
+const App = require('fib-app');
+
+const person_def = App.defineAppModel(orm => {
+ orm.define('person', {
+ name: String,
+ age: Number,
+ gender: ['male', 'female']
+ })
+})
+
+const app = new App('sqlite:test.db');
+app.db.use(person_def);
+
+const svr = new http.Server(1234, [
+ {
+ '/1.0': app
+ }
+]);
+
+svr.start();
+
+/**
+ * now we can get/find/put/delete person table via http rest, e.g. we can use curl:
+ *
+ *
+ * ```bash
+ * curl --location --request POST 'http://127.0.0.1:1234/1.0/person' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{"name": "Jack", "age": 12, "gender": "male"}'
+ ```
+
+ maybe you will get successful response like:
+
+ ```json
+ {
+ "id": 1,
+ "createdAt": "2022-12-17T13:06:41.592Z"
+ }
+ ```
+
+ then you can get the person info by:
+ ```bash
+ curl --location --request GET 'http://127.0.0.1:1234/1.0/person/1'
+ ```
+ result:
+
+ ```json
+ {
+ "name": "Jack",
+ "age": 12,
+ "gender": "male"
+ "createdAt": "2022-12-17T13:06:41.592Z",
+ "updatedAt": "2022-12-17T13:06:41.592Z",
+ "id":1
+ }
+ ```
+
+ but if you try to get person with non-exist id(such as 9999):
+ ```bash
+ curl --location --request GET 'http://127.0.0.1:1234/1.0/person/9999'
+ ```
+ result:
+
+ ```json
+ {
+ "code":4040102,
+ "message":"Object '9999' not found in class 'person'."
+ }
+ ```
+
+ you can also list person:
+
+ ```bash
+ curl --location --request GET 'http://127.0.0.1:1234/1.0/person/9999'
+ ```
+ result:
+
+ ```json
+ [
+ {"name":"Jack","age":12,"gender":"male","createdAt":"2022-12-17T13:06:41.592Z","updatedAt":"2022-12-17T13:06:41.592Z","id":1}
+ ]
+ ```
+
+ you can update the person's info:
+
+ ```bash
+ curl --location --request PUT 'http://127.0.0.1:1234/1.0/person/1' \
+ --header 'Content-Type: application/json' \
+ --data-raw '{"age": 13}'
+ ```
+
+ result:
+
+ ```json
+ {"id":1}
+ ```
+
+ re fetch the person's info, you will see the age of Jack has been updated:
+
+ ```json
+ {
+ "name": "Jack",
+ "age":13,
+ "gender": "male",
+ "createdAt": "2022-12-17T13:06:41.592Z",
+ "updatedAt": "2022-12-17T13:10:16.266Z",
+ "id": 1
+ }
+ ```
+
+ and the property `updatedAt` has been refreshed!
+
+ also, we can delete the information of Jack from database:
+
+ ```bash
+ curl --location --request DELETE 'http://127.0.0.1:1234/1.0/person/1'
+ ```
+
+ result:
+ ```json
+ {"id":1}
+ ```
+ */
+//
diff --git a/examples/simple-person/package.json b/examples/simple-person/package.json
new file mode 100644
index 0000000..3f14dbf
--- /dev/null
+++ b/examples/simple-person/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "simple-person",
+ "version": "1.0.0",
+ "description": "",
+ "repository": "",
+ "keywords": "",
+ "author": "",
+ "license": "ISC",
+ "scripts": {
+ "start": "rm -rf test.db* && fibjs ./index.js"
+ },
+ "dependencies": {
+ "fib-app": "file:../.."
+ }
+}
diff --git a/examples/simple-person/req.sh b/examples/simple-person/req.sh
new file mode 100644
index 0000000..85c64ca
--- /dev/null
+++ b/examples/simple-person/req.sh
@@ -0,0 +1,21 @@
+# create
+curl --location -X POST 'http://127.0.0.1:1234/1.0/person' \
+ -H 'Content-Type: application/json' \
+ -d '{"name": "Jack", "age": 12, "gender": "male"}'
+
+# get existed
+curl --location -X GET 'http://127.0.0.1:1234/1.0/person/1'
+
+# get non-existed
+curl --location -X GET 'http://127.0.0.1:1234/1.0/person/9999'
+
+# find
+curl --location -X GET 'http://127.0.0.1:1234/1.0/person'
+
+# update
+curl --location -X POST 'http://127.0.0.1:1234/1.0/person/1' \
+ -H 'Content-Type: application/json' \
+ -d '{"age": 13}'
+
+# del
+curl --location -X DELETE 'http://127.0.0.1:1234/1.0/person/1'
\ No newline at end of file