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 @@ +# 快速开始 + +[![NPM version](https://img.shields.io/npm/v/fib-app.svg)](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` 方法, 可以在开发中获得更好的类型提示: + +![image](https://user-images.githubusercontent.com/6339390/208242575-8a398ed1-d015-45fd-a430-0dd1b3802bc9.png) + ## 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