{"id":20100870,"url":"https://github.com/yenche123/all-serverless","last_synced_at":"2025-10-24T04:51:25.184Z","repository":{"id":59442995,"uuid":"515256145","full_name":"yenche123/all-serverless","owner":"yenche123","description":"改三行代码，直接切换 Serverless 云厂商！","archived":false,"fork":false,"pushed_at":"2022-09-21T08:10:24.000Z","size":97,"stargazers_count":22,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-31T18:15:01.631Z","etag":null,"topics":["baas","cloudbase","faas","firebase","laf","serverless","supabase","tencent-scf"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yenche123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-18T16:14:05.000Z","updated_at":"2023-12-01T05:15:24.000Z","dependencies_parsed_at":"2023-01-18T17:46:36.757Z","dependency_job_id":null,"html_url":"https://github.com/yenche123/all-serverless","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yenche123%2Fall-serverless","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yenche123%2Fall-serverless/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yenche123%2Fall-serverless/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yenche123%2Fall-serverless/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yenche123","download_url":"https://codeload.github.com/yenche123/all-serverless/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224491892,"owners_count":17320217,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["baas","cloudbase","faas","firebase","laf","serverless","supabase","tencent-scf"],"created_at":"2024-11-13T17:21:53.851Z","updated_at":"2025-10-24T04:51:25.110Z","avatar_url":"https://github.com/yenche123.png","language":"TypeScript","readme":"# all-serverless\n\n改三行代码，直接切换 Serverless 云厂商！\n\n比如原先在服务端/云函数（Node.js）使用的微信云开发\n\n```js\nconst cloud = require(\"wx-server-sdk\")\ncloud.init()\n```\n\n使用原写法，切换到 Laf 云，只要这样做：\n\n```js\nconst asls = require(\"all-serverless\")\nconst { wxcb: cloud, SdkType } = asls\ncloud.init({\n  targetSdk: SdkType.LAF,\n  lafConfig: {\n    baseUrl: \"你的 laf 云环境地址\",\n    dbProxyUrl: \"你的 laf 云访问策略路径\",\n  }\n})\n\n// 之后的代码 几乎无需改动！\n```\n\n初始化后的剩余代码，都无需改变；从今以后使用 Serverless 拒绝厂商绑定！\n\n## 概览\n\nServerless 没有严格的定义，普遍上大家认为是 BaaS (后端即服务) + FaaS (函数即服务)。\n\nServerless 确实免去了业务开发人员关于服务器运维的工作量，却也带来了\"厂商绑定\"、\"围墙花园\"的问题。当开发者基于特定云厂商的 sdk 进行低成本开发，直到有一天云厂商说我要涨价，没有商量的余地，开发者才发现我所有的代码、配置、数据格式都是基于该云厂商的，想迁云？天方夜谈！\n\n`all-serverless` 是在这样的背景下诞生的。虽然做不到一键迁云这么简单，但还是非常期望让开发者在业务层只要修改少许的代码（主要是初始化的部分）就完成切换云平台的作用。\n\n撇开人和设备 (机器) 所扮演的角色，如果将一个完整的应用简化成 \"前端代码\" + \"后端代码\" + \"配置(环境)\" + \"数据\"，那么值得注意的是，`all-serverless` 提供的是 \"后端代码\" `运行时`的迁移 (兼容) 方案，并且聚焦于 `数据库 db 的操作` 上，所以其他因素的迁移————包括后端代码如何部署、CLI脚手架、配套插件等————都不在本项目的讨论范围。\n\n在研究各个云厂商关于 Serverless SDK 的实现时，有不少是大同小异的，比如触发云函数有的叫 `callFunction` 有的则叫 `invokeFunction`，有的返回参数用 `data` 有的则用 `list`，仔细一看明明做的是一样的事却有着不同的`写法`，直叫人抓狂！\n\n因此，`all-serverless` 的目标是弭平各个云厂商所实现的 SDK 差异，让开发者随意使用一种 sdk 之写法也可以快速兼容其他云平台的 Serverless 服务，远景是**让万物皆可 Serverless!**\n\n## 原理\n\n你可以把 `all-serverless` 当作一个**转换器**，它仅有的并且实际使用到的外部依赖目前为 `laf-client-sdk` / `@cloudbase/node-sdk` / `wx-server-sdk`。\n\n当你使用 `wx-server-sdk` 所定义的写法格式时，`all-serverless` 负责把你的请求转换成目标 SDK 的格式，最后使用目标 SDK 发起请求，得到结果后再把结果转回 `wx-server-sdk` 的写法格式再返回给你，如此实现兼容。\n\n未来也会兼容其他 SDK 的写法格式，见[TODO](#todo)。\n\n## 安装\n\n```sh\nnpm i all-serverless\n# or\npnpm i all-serverless\n```\n\n## 迁云\n\n如果你之前使用了 `laf-client-sdk` / `@cloudbase/node-sdk` / `wx-server-sdk` 以上任意 sdk 写了后端应用，现在想实现快速迁移至其他 Serverless 平台时，请留意以下注意事项:\n\n1. 本项目仅支持后端云函数上的代码迁移\n2. `all-serverless` 为后端 sdk，请不要在前端使用\n3. 本项目不提供数据的迁移，请在迁移云函数代码前，确保迁移后的数据库也包含原数据库的结构。\n4. 支持 `Laf` / `腾讯云开发` / `微信云开发` 之间的任意切换，然而目前仅支持微信云开发 `wx-server-sdk` 的写法格式，即初始化之后的 `cloud` 的使用方式完全与微信云开发一致。\n5. 原 `wx-server-sdk` 下关于 `openapi` / `cloudPay` / `callContainer` 属性或方法皆能在 `wxcb` 中使用，只不过 `all-serverless` 会直接调用 `wx-server-sdk` 而非你所指定的 `targetSdk`。\n6. 本项目聚焦于 `db` 数据库操作的代码迁移，也就是最常见的增删改查 CRUD 和聚合操作，故不支持文件存储 (uploadFile / getTempFileURL / deleteFile / downloadFile)、数据库事务 (startTransaction) 、用户系统（user，包含鉴权相关的 auth）和广告数据上报 (analytics) 等延申操作。\n7. 与其说\"迁移\"，不如说\"兼容\"。\n\n## 开新项目\n\n如果你不是迁移用户，没有任何历史包袱，依然非常推荐你使用 `all-serverless`。一起拒绝被任何云厂商绑定！\n\n当前支持的微信云开发写法，其初始化方式如下:\n\n```js\n// CommonJS\nconst asls = require(\"all-serverless\")\nconst { wxcb: cloud, SdkType } = asls\n\n// or ESModule or TypeScript\nimport { wxcb as cloud, SdkType } from \"all-serverless\"\n\n// 数据库连接到 laf\ncloud.init({\n  targetSdk: SdkType.LAF,\n  lafConfig: {\n    // 配置见 https://www.lafyun.com/guide/db/\n  },\n  // 或者，如果直接在 laf 云函数上，可以直接传 lafCloudSdk\n  lafCloudSdk: LafCloud,\n})\n\n// 数据库连接到 腾讯云开发\ncloud.init({\n  targetSdk: SdkType.TCB,\n  tcbConfig: {\n    // 配置见 https://docs.cloudbase.net/api-reference/server/node-sdk/initialization#init\n    // 结构同 tcb.init(opt) 的 opt\n    secretId: \"你的腾讯云 secretId\",\n    secretKey: \"你的腾讯云 secretKey\",\n    env: \"你的腾讯云开发环境标识\",\n  }\n})\n\n// 数据库连接到 微信云开发\ncloud.init({\n  targetSdk: SdkType.WXCB,\n  wxcbConfig: {\n    // 配置见 https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/init/server.init.html\n    // 结构同 cloud.init(options) 的 options\n  }\n})\n\n```\n\n其中，`wxcb`（weixin-cloudbase）表示使用微信云开发的写法，未来也会支持 `tcb` (腾讯云开发) 和 `laf` (laf云开发) 的写法。\n\n`all-serverless` 让你的后端代码与平台无关，不再被特定 sdk 绑架，快速兼容其他云平台的 sdk。\n\n你的后端云就应该像装在口袋里的巧克力，想吃哪一个就吃哪一个！\n\n\u003cbr\u003e\n\n## 初始化\n\n```js\nimport { wxcb as cloud, SdkType } from \"all-serverless\"\ncloud.init(initOptions)\n```\n\n其中 `initOptions` 配置如下\n\n### initOptions\n\n|     属性     |     类型     | 必有 |       说明        |\n| ------------ | ----------- | ---- | ----------------- |\n| targetSdk    |   SdkType   |  N   |  标识连的是哪个云厂商 |\n| lafConfig    | LafCloudOpt |  N   |  同 `laf-client-sdk` 的初始化配置项一致，当 `targetSdk` 为 `SdkType.LAF` 时与 `lafCloudSdk` 二选一 |\n| lafCloudSdk  | LafCloud    |  N   |  注1，当 `targetSdk` 为 `SdkType.LAF` 时与 `lafConfig` 二选一 |\n| tcbConfig    | TcbCloudOpt |  N   |  当 `targetSdk` 为 `SdkType.TCB` 时必有 |\n| wxcbConfig   | WxcbCloudOpt | N   |  当 `targetSdk` 为 `SdkType.WXCB` 时必有 |\n\n\u003e 注1: 当前云函数部署在 laf 云时，可传入 `import cloud from '@/cloud-sdk'` 的 `cloud` 作为属性 `lafCloudSdk` 的值，使后续调用执行的是免鉴权的 `cloud-sdk` 而非 `laf-client-sdk`，省略前端访问策略的配置。\n\n#### SdkType\n\n有以下枚举值\n\n|   枚举值   |    最终调用的 sdk        |           说明            |\n| --------- | ----------------------- | ------------------------- |\n|    LAF    |   laf-client-sdk (注2)  |  表示云环境连接到 Laf       |\n|    TCB    |   @cloudbase/node-sdk   |  表示云环境连接到 腾讯云开发 |\n|    WXCB   |   wx-server-sdk         |  表示云环境连接到 微信云开发 |\n\n\u003e 注2: 若 `lafCloudSdk` 有值，最终调用的 sdk 改为 laf 云上的 `cloud-sdk`\n\n#### LafCloudOpt\n\n|     属性     |   类型   | 必有 |       说明        |\n| ------------ | ------- | ---- | ----------------- |\n|    baseUrl   | String  |  Y   | laf 应用的服务地址  |\n|  dbProxyUrl  | String  |  Y   | laf 访问策略的入口地址 |\n\n该配置项同 laf-client-sdk 的使用示例:\n\n```js\nimport { Cloud } from 'laf-client-sdk'\nconst cloud = new Cloud(lafConfig)\n```\n\n具体请参考 [https://github.com/labring/laf/tree/main/packages/client-sdk](https://github.com/labring/laf/tree/main/packages/client-sdk#%E4%BD%BF%E7%94%A8%E7%A4%BA%E4%BE%8B)\n\n#### TcbCloudOpt\n\n结构与腾讯云开发 Node.js SDK 的 `init()` 入参保持一致，即\n\n```js\nconst tcb = require(\"@cloudbase/node-sdk\")\nconst app = tcb.init(tcbCloudOpt)\n```\n\n具体请参见 [https://docs.cloudbase.net/api-reference/server/node-sdk/initialization](https://docs.cloudbase.net/api-reference/server/node-sdk/initialization#2-%E8%BE%93%E5%85%A5%E5%8F%82%E6%95%B0)\n\n#### WxcbCloudOpt\n\n结构与微信云开发 Node.js SDK 的 `init()` 入参保持一致，即\n\n```js\nconst cloud = require(\"wx-server-sdk\")\ncloud.init(wxcbCloudOpt)\n```\n\n具体请参见 [https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/init/server.init.html](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/init/server.init.html)\n\n## 初始化之后\n\n假设已有下方初始化的代码\n\n```js\n// 当前支持的微信云开发写法\nimport { wxcb as cloud } from \"all-serverless\"\n\n// 后续将支持腾讯云开发的写法\n// import { tcb } from \"all-serverless\"\n// const app = tcb.init()\n\n// 后续将支持 laf 云开发的写法\n// import { LafCloud as Cloud } from \"all-serverless\"\n// const cloud = new Cloud()\n```\n\n我们已实现了各个 BaaS 在`数据库操作`层的大致兼容，那 FaaS 呢？\n\n各个云服务厂商的云函数之异同体现在`入口文件`、`部署方式`、`获取入参`以及`返回出参`等地方，其中`入口文件`和`部署方式`涉及各个云厂商工具链的差异，较难弭平各个 SDK 的差异，如前文所说不在本项目的讨论范围；而`返回出参`在异步的云函数上有些会直接用 `return`，有些则用 `response.send()` 来传递，这一块也较难完成统一。故 `all-serverless` 主要在 `获取入参` 之处来帮助开发者统一各端的差异。\n\n## faas \n\n```js\n// ES6 or TypeScript\nimport { faas } from \"all-serverless\"\n// CommonJS\nconst asls = require(\"all-serverless\")\nconst { faas } = asls\n```\n\n### getEntryData(param1[, param2])\n\n获取入参\n\n#### param1\n\n必填，云函数的入口函数之第一个参数\n\n#### param2\n\n选填，云函数的入口函数之第二个参数\n\n#### 返回\n\n开发者自定义的入参 body，如果 `all-serverless` 判别环境失败则返回一个空对象 `{}`\n\n#### 使用方式\n\n```js\n// 在腾讯云函数 scf 上（腾讯云开发、微信云开发的云函数都是复用 scf 的）\nexports.main = async (param1, param2) =\u003e {\n  const event = faas.getEntryData(param1, param2)\n}\n```\n\n```ts\n// 在 laf 云函数上\nexports.main = async (param1: FunctionContext) =\u003e {\n  const event = faas.getEntryData(param1)\n}\n```\n\n### getFaaSManufacturer(param1, param2): FaaSManufacturer\n\n获取当前云函数运行所在的厂商\n\n#### param1\n\n必填，云函数的入口函数之第一个参数\n\n#### param2\n\n选填，云函数的入口函数之第二个参数\n\n#### 返回值 FaaSManufacturer\n\n`FaaSManufacturer` 有以下字符串: \n\n- `lafyun`: 表示laf云 \n- `tencent-scf`: 表示腾讯云\n- `空字符串`: 表示未知\n\n\n\u003cbr\u003e\n\n## TODO\n\n- [ ] 支持 `腾讯云开发` 的写法\n- [ ] 支持 `Laf` 的写法\n- [ ] 支持 `Firebase` 的写法 + 覆盖其他端\n- [ ] 支持 `Supabase` 的写法 + 覆盖其他端 （需调研 MonogoDB 和 PostgreSQL 的转换）\n\n## 开源协议\n\nMIT","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyenche123%2Fall-serverless","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyenche123%2Fall-serverless","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyenche123%2Fall-serverless/lists"}