# V2.0更新说明

## 引言

Fireboom2.0是一个值得骄傲的作品！其中最亮眼的特性是：<mark style="color:purple;">多人协作支持</mark>和<mark style="color:purple;">极致性能提升</mark>！

有内测用户讲，2.0升级后好像没啥变化，我打趣道：<mark style="color:purple;">2.0样子没变，心变了</mark>！

**存储重构，支持协作**：

1.0版本存储层数据结构不合理，无法用github合并，只适用于单人开发，无法多人协作。而对团队而言，多人协作是不可或缺的功能。

在2.0版本中，我们对存储层数据结构进行了全面的重新设计和优化，不仅支持基于GitHub的**离线协作**，而且在架构上支持实时协作。

**引擎重构，性能提升：**

1.0版本存在性能问题，在表数量接近300时，常常内省失败，且构建的“超图”冗余过多，导致`fireboom.config.json`动辄十几个G，不仅编译较慢，而且运行时很消耗内存。

重构引擎，2.0的生成文件缩小 <mark style="color:purple;">10 倍</mark> ，运行内存缩小 <mark style="color:orange;">10 倍</mark>，静态编译速度提升 <mark style="color:green;">5 倍</mark>。

这还不够，进一步支持了OPERATION增量编译，实现了无感编译！

**体验优化，流畅开发：**

1.0版本也存在一些开发体验问题，其中最影响体验的是钩子服务与Fireboom服务的循环依赖。

2.0版本重构了钩子SDK，采用心跳上报的方式完美解决了该问题，钩子开发前所未有的流畅。

## 新功能和改进

接下来，我们详细介绍全部更新。

### 存储结构变更

#### 旧版`store` 目录

```
store
├── hooks
│   ├── auth
│   ├── customize
│   ├── global
│   ├── hooks
│   └── uploads
├── list
│   ├── FbAuthentication
│   ├── FbDataSource
│   ├── FbOperation
│   ├── FbRole
│   ├── FbSDK
│   └── FbStorageBucket
└── object
    ├── global_config.json
    ├── global_operation_config.json
    ├── global_system_config.json
    └── operations
```

旧版存储有两类问题：

1，list目录中以json数组的方式存储所有数据源、OPERATION，任意API的变更，都会影响整体文件，导致多人协作时，经常冲突

2，相同业务存储过于分散，操作一个对象，要同时操作N个文件

#### 新版`store`目录

```
store
├── authentication # 对应list/FbAuthentication
│   ├── auth0.json
├── config
│   ├── global.operation.json
│   └── global.setting.json
├── datasource # 对应list/FbDataSource
│   ├── main.json
│   ├── system.json
├── operation # 对应list/FbOperation
│   ├── xxx.graphql  # 对应exported/operations下的xxx.graphql
│   ├── xxx.json # 将hooks/hooks和list/FbOperation的文件合在一起
├── role # 对应list/FbRole
│   ├── admin.json
│   └── user.json
├── sdk
│   └── golang-server.json
└── storage # 对应list/FbStorageBucket
    └── aliyun.json
```

新版存储，重新设计了存储结构，完全解决了旧版的两大问题，且具备如下优势：

* **方便合并**：每个文件代表一个对象，例如OPERATION `operation`等
* **统一读取**：OPERATION相关的业务都存储在了同一个json中
* **方便管理**：将`exported/operations`目录下`.graphql`文件移到了operation目录，和`.json`同名

### 构建物优化

构建物位于`exported/generated`目录，v1.0版本中`fireboom.config.json`文件中有很多冗余，动辄十几个G。

新版本将其拆分为了2个文件：`fireboom.config.json`和`fireboom.operations.json`，且将冗余存储改为了引用存储，数十倍的减少了文件大小。小的构建物，成倍缩小了运行内存。

此外，文件的拆分也减少了GraphQL对象的转换次数，成倍提升了合成超图的速度。

### 增量编译

1.0版本任意一次OPERATION的编辑都会触发全量的OPERATION编译，造成巨大的性能浪费。新版本将全量编译改为了增量编译，极大提升了OPERATION的编译速度！

这取决于项目OPERATION的数量，OPEARTION越多，提升效果越显著！

### Prisma数据源

2.0版本增加了一种特殊数据源：**Prisma数据源**，适用于数据库表数量较多的场景。

<figure><img src="https://2707494476-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNx22Cp3wzkuW1siRbMwW%2Fuploads%2Fqc2pc6F8TB0B29Azwz7u%2Fimage.png?alt=media&#x26;token=2b85e13c-067e-4ad6-821f-443bffcc6072" alt=""><figcaption><p>prisma 数据源</p></figcaption></figure>

其主要用途如下：

* 虚拟外键：数据库无需建立外键，只在Pirsma model中建立，支持同数据库的关联查询
* 支持视图：在prisma model建立视图表，实现视图的查询
* 精简数据表：简化prisma model表或字段，只声明业务需要的表或字段，缩减超图大小，提高性能

详情见 [#prisma-shu-ju-yuan](#prisma-shu-ju-yuan "mention") !

### 钩子扩展逻辑

OPERATION结合钩子能实现大部分接口，但仍有些接口无法实现，需要自行编写代码支持。

1.0版本只支持GraphQL钩子和[proxy钩子](#proxy-gou-zi)，2.0版本新增了[function钩子](#function-gou-zi)，且还解决了钩子的循环依赖问题。

修改钩子代码后，只需重启钩子，对应的数据将自动注册到Fireboom服务中。

<figure><img src="https://2707494476-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNx22Cp3wzkuW1siRbMwW%2Fuploads%2FtTuHmN1tECA0Nwi3jBU9%2Fimage.png?alt=media&#x26;token=3fc7647d-2fb9-4476-a743-ec1c7a58e55c" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
该特性，当前只有golang钩子支持，nodejs钩子正在进行中。
{% endhint %}

#### GraphQL钩子

GraphQL钩子注册到Fireboom中为一种特殊的GraphQL数据源。

见上图，数据源->statistic

<details>

<summary>GraphQL示例代码</summary>

{% code title="custom-go/customize/statistic.go" %}

```go
package customize

import (
	"custom-go/pkg/plugins"
	"fmt"

	"log"
	"time"

	"github.com/graphql-go/graphql"
)

type Feed struct {
	ID string `graphql:"id"`
}

var FeedType = graphql.NewObject(graphql.ObjectConfig{
	Name: "FeedType",
	Fields: graphql.Fields{
		"id": &graphql.Field{
			Type: graphql.ID,
		},
	},
})
var RootSubscription = graphql.NewObject(graphql.ObjectConfig{
	Name: "subscription",
	Fields: graphql.Fields{
		"feed": &graphql.Field{
			Type: FeedType,
			Resolve: func(p graphql.ResolveParams) (interface{}, error) {
				return p.Source, nil
			},
			Subscribe: func(p graphql.ResolveParams) (interface{}, error) {
				c := make(chan interface{})

				go func() {
					var i int

					for {
						i++

						feed := Feed{ID: fmt.Sprintf("%d", i)}

						select {
						case <-p.Context.Done():
							log.Println("[RootSubscription] [Subscribe] subscription canceled")
							close(c)
							return
						default:
							c <- feed
						}

						time.Sleep(250 * time.Millisecond)

						if i == 21 {
							close(c)
							return
						}
					}
				}()

				return c, nil
			},
		},
	},
})
var StatisticsSchema, _ = graphql.NewSchema(graphql.SchemaConfig{
	Query: graphql.NewObject(graphql.ObjectConfig{
		Name: "query",
		Fields: graphql.Fields{
			"GetMonthlySales": &graphql.Field{
				Type: graphql.String,
				Resolve: func(p graphql.ResolveParams) (res interface{}, err error) {
					_, _, err = plugins.ResolveArgs[any](p)
					if err != nil {
						return
					}
					return "ok", nil
				},
			},
		},
	}),
	Subscription: RootSubscription,
})

func init() {
	plugins.RegisterGraphql(&StatisticsSchema)
}

```

{% endcode %}

</details>

#### function钩子

function钩子注册到Fireboom中为一个API，且有出入参定义（json类型），此外还支持实时查询和权限控制。

见上图，API管理->function->login

<details>

<summary>function示例代码</summary>

{% code title="custom-go/function/login.go" %}

```go
package function

import (
	"custom-go/pkg/base"
	"custom-go/pkg/plugins"
)

func init() {
	plugins.RegisterFunction[loginReq, loginRes](login)
}

type loginReq struct {
	Username string `json:"username"`
	Password string `json:"password"`
	Res      loginRes
}

type loginRes struct {
	Msg  string `json:"msg"`
	Data string `json:"data"`
}

func login(hook *base.HookRequest, body *base.OperationBody[loginReq, loginRes]) (*base.OperationBody[loginReq, loginRes], error) {
	body.Response = &base.OperationBodyResponse[loginRes]{Data: loginRes{Msg: "123"}}
	return body, nil
}

```

{% endcode %}

</details>

#### proxy钩子

proxy钩子注册到Fireboom中也为一个API，和funciton的区别是，它没有出入参定义，可以为任意类型，如非结构化数据或xml数据，同时不支持实时查询。

见上图，API管理->proxy->test

<details>

<summary>proxy示例代码</summary>

{% code title="custom-go/proxy/test.go" %}

```go
package proxy

import (
	"custom-go/pkg/base"
	"custom-go/pkg/plugins"
	"custom-go/pkg/wgpb"
	"net/http"
)

func init() {
	plugins.RegisterProxyHook(ping)
}

var conf = &plugins.HookConfig{
	AuthRequired: true,
	AuthorizationConfig: &wgpb.OperationAuthorizationConfig{
		RoleConfig: &wgpb.OperationRoleConfig{
			RequireMatchAny: []string{"admin", "user"},
		},
	},
	EnableLiveQuery: false,
}

func ping(hook *base.HttpTransportHookRequest, body *plugins.HttpTransportBody) (*base.ClientResponse, error) {
	// do something here ...
	body.Response = &base.ClientResponse{
		StatusCode: http.StatusOK,
	}
	body.Response.OriginBody = []byte("ok")
	return body.Response, nil
}

```

{% endcode %}

</details>

推荐优先使用function，funciton满足不了的，再用proxy钩子。

若想使上述3个钩子生效，还需要在`main.go`文件中开启5-7行注释，匿名导入钩子。

{% code title="custom-go/main.go" lineNumbers="true" %}

```go
package main

import (
	// 根据需求，开启注释
	_ "custom-go/customize"
	_ "custom-go/function"
	_ "custom-go/proxy"
	"custom-go/server"
)

func main() {
	server.Execute()
}
```

{% endcode %}

### fromclaim指令升级

1.0版本`@fromClaim`指令只支持枚举值，无法注入自定义的数据。

新版本新增了`custom`参数，从User.CustomClaims中获取数据，实现了任意数据的注入，包括 标量和数组。其入参为`jsonPathComponents`，填写参数路径即可。

{% code title="custom-go/authentication/mutatingPostAuthentication.go" %}

```go
package authentication

import (
	"custom-go/pkg/base"
	"custom-go/pkg/plugins"
)

func MutatingPostAuthentication(hook *base.AuthenticationHookRequest) (*plugins.AuthenticationResponse, error) {
	// 定义自定义参数，其中key1为字符串，key2为对象
	hook.User.CustomClaims = map[string]any{
		"key1": "sss",
		"key2": map[string]string{
			"key3": "sss",
		},
	}
	return &plugins.AuthenticationResponse{User: hook.User, Status: "ok"}, nil
}
```

{% endcode %}

```graphql
# 将User.CustomClaims的key2.key3注入到$name中
mutation MyQuery($name: String! @fromClaim(name:CUSTOM,custom: {jsonPathComponents: ["key2", "key3"]})) {
  rb_createOneT(data: {name: $name}) {
    id
    name
  }
}
```

### 事务支持

新增`@transaction`指令，修饰mutation OPERATION，适用于如下场景：

* 至少有两个及以上的选择集（根字段）
* 且必须是同一个数据库

```graphql
mutation MyQuery @transaction {
  rb_createOneT(data: { name: "22211122"}) {
    id
    name
  }
  rb_createOneRole(data: {code: "a111111", name: "1111"}) {
    code
    name
  }
} 
```

### SDK升级策略优化

#### 稳定更新，避免过度升级

1.0版本的每次被删除后，都会从github拉取最新模板，导致过度升级。遇到破坏性更新时，钩子会报错。

因此，在sdk的json文件中增加了 `gitCommitHash`字段，记录模板的github hash值，保证每次都能拉取指定版本。

```json
  "gitCommitHash": "e7fa762965b03d47057643dda8784ada625b0cee",
```

此外，还增加了新版本检测功能，展示是否有新版本，并基于github的对比功能，实现了新旧版本对比。

<figure><img src="https://2707494476-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNx22Cp3wzkuW1siRbMwW%2Fuploads%2FLfV4SjJ7yDEbNGwQ8KZv%2Fimage.png?alt=media&#x26;token=3af33026-fb2c-41d7-8839-fc73fcef12fa" alt=""><figcaption></figcaption></figure>

例如：<https://github.com/fireboomio/sdk-template_go-server/compare/ab1427e..e7fa762>

#### 强制忽略，允许定制模板

1.0版本会对比`template/[sdk-name]`和`custom-[x]`中的文件更新时间，确定是否覆盖模板文件。若用户在custom-\[x]中修改模板，则每次编译都会被重新覆盖。

为了支持该特性，我们在`custom-[x]`中增加了`.fbignore`文件，语法类似`.gitignore`。模板生成时将忽略该文件声明的文件或目录，保证开发者修改不会被覆盖。

例如：如若修改`main.go`，则：

<pre class="language-gitignore" data-title="custom-go/.fbignore"><code class="lang-gitignore"><strong># 略
</strong><strong>main.go
</strong></code></pre>

### 环境变量优化

1.0版本的系统配置未支持环境变量，如设置->系统，不同环境迁移时，需要手动处理。

2.0版本优化了环境变量，通过环境变量可无缝迁移开发环境到生产环境。

<figure><img src="https://2707494476-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNx22Cp3wzkuW1siRbMwW%2Fuploads%2FzIAE4QKC0d3jFBVeHlti%2Fimage.png?alt=media&#x26;token=d34050af-8fd5-46c0-bdc3-979b22cf43e3" alt=""><figcaption></figcaption></figure>

## 迁移到V2.0

### 兼容性

1.0到2.0是一个破坏性更新，未来1.0不继续维护，但仍可以使用。

但我实在想不出，继续使用它的理由，不是吗？

### 迁移脚本

如果你已经有基于1.0版本项目，不用担心，我们提供了迁移脚本及教程。

您可以遵循下述仓库的教程操作，<mark style="color:red;">建议在开发环境下进行</mark>！

仓库：<https://github.com/fireboomio/fb-migration>

<mark style="color:blue;">如果有任何问题，我们将为您提供1对1指导，且免费！</mark>

## 文档及支持资源

当前您看到的就是2.0的文档。

2.0的文档暂未完全更新，但无需担心，只要您认真阅读 [#xin-gong-neng-he-gai-jin](#xin-gong-neng-he-gai-jin "mention")，基于1.0文档就可以上手2.0。

接下来，我们将逐渐更新2.0文档。

如有任何问题，可前往内测群咨询，[前往->](https://github.com/fireboomio/product-manual/discussions/1)

我们非常欢迎您提出2.0的反馈意见，这将是我们持续进步的动力！

这里有两个2.0的示例项目供您参考：

* 最全的2.0示例：<https://github.com/AnsonCode/fb-demo>
* 2.0 admin示例：<https://github.com/fireboomio/fb-admin>

## RoadMap

除了 [#xin-gong-neng-he-gai-jin](#xin-gong-neng-he-gai-jin "mention")外，还有一些我们计划支持的新特性。也希望您 [联系我们](https://github.com/fireboomio/product-manual/discussions/1) 提供更多建议。

### 实时协作

当前只支持离线协作，2.0计划支持实时协作，满足团队协作的需求。

* 多人协作功能，允许团队成员同时使用和编辑同一个项目
* 用户可以实时查看其他成员的更改，并进行实时协作和沟通，提高团队的协作效率

### 钩子新语言支持

当前钩子已完全支持golang，进一步优化nodejs，随后支持JAVA、Python语言！

### API市场

上线API市场，集成2大类API。

* 通用API：例如支付能力、短信验证码、邮箱发送、敏感词等通用API
* 模型API：集成各种AI模型，如GPT、辅助编码、图片生成等

### IDE优化

优化内置IDE，支持各种钩子语言的开发，包括语法提醒和在线调试。

当前可基于github codespace作为替代品，详情见 [文档](https://docs.github.com/zh/codespaces/getting-started/quickstart)！

### AI辅助

#### 辅助编程

基于IDE提供AI辅助编程能力，其相对于市面上同类工具最大的优势是对Fireboom钩子的特殊支持

#### API生成

用自然语言代替手工勾选生成OPERATION，实现API的自动生成

<figure><img src="https://2707494476-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNx22Cp3wzkuW1siRbMwW%2Fuploads%2F1pTgc3IuvkLlG7sJJhQD%2Fimage.png?alt=media&#x26;token=327d188f-95d1-46e9-9b7c-394a01a05a9a" alt=""><figcaption><p>基于声明式语法的API生成</p></figcaption></figure>

#### AI Agent

优化API文档，集成AI Agent，用自然语言实现API的编排

<figure><img src="https://2707494476-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNx22Cp3wzkuW1siRbMwW%2Fuploads%2F8pjUuRC57hEU1iR6iqg7%2Fimage.png?alt=media&#x26;token=2fd73084-8c03-4513-87c9-1b12146f1423" alt=""><figcaption><p>AI Agent Gateway：通过自然语言使用工具</p></figcaption></figure>

## 商业化

近日CEC-IDE事件在开发者中引起了广泛讨论，内测群也对此展开了更深入的讨论。

最终落脚点是：

> 从大众到企业付费意识极弱，软件繁荣不起来。表面看到的很多国外优秀开源作品，背后是人家的高GDP能保证牛奶面包可以让你去用爱发电，国外付费软件也是非常多的，开源只是一种营销手段。
>
> ——来自群友：7.

对此，我深表认同！

Fireboom作为一个还在萌芽中的技术型初创团队，一方面追求心中的月亮——**以开发者为中心**，另一方面又不可能离开六便士——**产品商业化**。

从2.0开始，Fireboom将开始探索商业化。但不用担心，我们将为您提供最慷慨的免费特性，在不影响您正常项目的情况下，提供增值服务。

当前Fireboom2.0有三种版本：社区版、专业版、企业版。

### 社区版

其中社区版适用个人开发者，除了拥有1.0所有功能外，有如下不同：

* API数量：100
* 数据源数量：5

<figure><img src="https://2707494476-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNx22Cp3wzkuW1siRbMwW%2Fuploads%2FQ7S2jOhgSX1k2bhGY7FH%2Fimage.png?alt=media&#x26;token=c8a97766-c364-454b-acbc-c61efcd6aac8" alt=""><figcaption></figcaption></figure>

但，别担心！当项目需求超出默认限制后，可随时**免费**申请扩容。**申请后，无限期生效！**

详情填写 [申请表单](https://bar9vnf09af.feishu.cn/share/base/form/shrcnZnKpk9Oi7qfcSXaFE7nM8g)\~

### 专业版

专业版适用于创业团队，拥有社区版的全部功能，且API、数据源默认无限，此外还具有如下特性：

* [#zeng-liang-bian-yi](#zeng-liang-bian-yi "mention")
* [#prisma-shu-ju-yuan](#prisma-shu-ju-yuan "mention")
* 实时协作：多人编辑时，实时联动
* 导入/导出：为项目导出API及其数据源依赖，导出插件

### 企业版

企业版适用于企业，拥有专业版的全部功能，此外还具有如下特性：

* 虚拟外键：Prisma数据源，支持虚拟外键和模型精简
* 日志监控
* 限流熔断
* 定时备份
* 集群部署
* ...

详情请前往官网 [查看](https://www.fireboom.io/)！

<mark style="color:red;">如果您觉得某些政策不合理，请随时联系我们。我们将会慎重考虑您的建议！</mark>

## 结语

结束之际，最想感谢的是Fireboom内测群所有种子用户。是你们的使用、反馈、建议让我们走到今天！

**为此，群内所有用户都将**<mark style="color:red;">**免费**</mark>**获得：**

1. **无**理由扩容 API和数据源数量&#x81F3;**∞** ，且永久有效  前往[申请](https://bar9vnf09af.feishu.cn/share/base/form/shrcnZnKpk9Oi7qfcSXaFE7nM8g)[->](https://bar9vnf09af.feishu.cn/share/base/form/shrcnZnKpk9Oi7qfcSXaFE7nM8g)
2. **有**理由<mark style="color:purple;">增量编译</mark>特权<mark style="color:red;">1年</mark><mark style="color:purple;">，</mark>前往[申请->](https://bar9vnf09af.feishu.cn/share/base/form/shrcnNDXxJKs7BUTIY4gEFCOvt6)

**1和2只需申请1个，申请2的话，自动拥有1的权限！**

希望接下来的日子，仍有您的陪伴！

Fireboom团队将始终坚持“**以开发者为中心**”的信念，不断推陈出新，改进和提升Fireboom的功能和性能。

未来，邀您一起见证！
