├── .env ├── .eslintignore ├── .eslintrc.js ├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── ci.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .prettierignore ├── .prettierrc.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── apps ├── faas-demo │ ├── CHANGELOG.md │ ├── README.md │ ├── local-invoke.js │ ├── mock │ │ ├── channelCreate.js │ │ ├── channelDelete.js │ │ └── example.js │ ├── package.json │ ├── project.json │ ├── src │ │ ├── config │ │ │ └── index.js │ │ ├── function │ │ │ ├── channel │ │ │ │ ├── channelCreate.ts │ │ │ │ └── channelDelete.ts │ │ │ ├── test │ │ │ │ ├── testOperationCount.ts │ │ │ │ ├── testOperationCreateMany.ts │ │ │ │ ├── testOperationDeleteMany.ts │ │ │ │ ├── testOperationFindList.ts │ │ │ │ ├── testOperationFirst.ts │ │ │ │ └── testOperationUpdateMany.ts │ │ │ └── user │ │ │ │ └── createUser.ts │ │ ├── io │ │ │ └── index.ts │ │ └── utils │ │ │ └── index.ts │ ├── tsconfig.json │ └── types │ │ └── schema.d.ts └── web-demo │ ├── .babelrc │ ├── CHANGELOG.md │ ├── README.md │ ├── index.html │ ├── package.json │ ├── postcss.config.js │ ├── project.json │ ├── src │ ├── index.js │ └── web-demo.js │ └── webpack.config.js ├── commitlint.config.js ├── docs ├── dev-and-deploy.md └── todo.md ├── integration ├── cjs │ ├── CHANGELOG.md │ ├── integration.test.cjs │ ├── package.json │ └── project.json └── esm │ ├── CHANGELOG.md │ ├── integration.test.mjs │ ├── package.json │ └── project.json ├── lerna.json ├── libs └── baas │ ├── CHANGELOG.md │ ├── index.d.ts │ ├── lib │ └── baas-sdk-v3.20.0.min.js │ ├── package.json │ └── project.json ├── nx.json ├── package.json ├── packages ├── cli │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── bin │ │ └── cli.js │ ├── global.d.ts │ ├── package.json │ ├── src │ │ ├── assist │ │ │ └── type.template.ts │ │ ├── commands │ │ │ ├── faas │ │ │ │ ├── build.ts │ │ │ │ ├── config.ts │ │ │ │ ├── debug.ts │ │ │ │ ├── deploy.ts │ │ │ │ ├── index.ts │ │ │ │ ├── mock.ts │ │ │ │ ├── upload.ts │ │ │ │ └── webpack.base.config.ts │ │ │ ├── index.ts │ │ │ ├── login │ │ │ │ └── index.ts │ │ │ └── type │ │ │ │ ├── generator.ts │ │ │ │ ├── index.ts │ │ │ │ ├── list.ts │ │ │ │ └── schema.d.ts │ │ ├── config │ │ │ ├── api.ts │ │ │ ├── constant.ts │ │ │ ├── index.ts │ │ │ └── type.d.ts │ │ ├── index.ts │ │ ├── request │ │ │ ├── api │ │ │ │ ├── function.ts │ │ │ │ ├── index.ts │ │ │ │ ├── login.ts │ │ │ │ └── schema.ts │ │ │ ├── index.ts │ │ │ └── utils.ts │ │ └── utils │ │ │ ├── cloud-function.ts │ │ │ ├── index.ts │ │ │ ├── logger.ts │ │ │ ├── path.ts │ │ │ └── token.ts │ ├── static │ │ └── network-save-response.png │ ├── tsconfig.json │ ├── typings │ │ └── schema.d.ts │ └── webpack.config.js ├── faas │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ └── faas.test.js │ ├── jest.config.ts │ ├── package.json │ ├── src │ │ ├── config.ts │ │ ├── createFaas.ts │ │ ├── formatters.ts │ │ ├── index.ts │ │ └── version.ts │ ├── tsconfig.cjs.json │ ├── tsconfig.json │ └── types │ │ └── index.d.ts ├── io │ ├── .env │ ├── .mincloudxrc │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── io.test.js │ │ └── operation.test.js │ ├── config │ │ └── index.ts │ ├── package.json │ ├── src │ │ ├── baas.ts │ │ ├── config │ │ │ └── index.ts │ │ ├── createIo.ts │ │ ├── index.ts │ │ ├── operations.ts │ │ └── type.ts │ ├── tool │ │ └── baas-init.js │ ├── tsconfig.json │ ├── types │ │ └── index.d.ts │ └── webpack.config.js └── types │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ └── types │ ├── baas │ ├── class │ │ ├── AlipayProfitSharingOrder.d.ts │ │ ├── BaseQuery.d.ts │ │ ├── BaseRecord.d.ts │ │ ├── Content.d.ts │ │ ├── ContentCategory.d.ts │ │ ├── ContentGroup.d.ts │ │ ├── ContentRecord.d.ts │ │ ├── File.d.ts │ │ ├── FileCategory.d.ts │ │ ├── GeoPoint.d.ts │ │ ├── GeoPolygon.d.ts │ │ ├── HError.d.ts │ │ ├── MobileTopup.d.ts │ │ ├── Order.d.ts │ │ ├── PeopleAlive.d.ts │ │ ├── Query.d.ts │ │ ├── RedPack.d.ts │ │ ├── TableObject.d.ts │ │ ├── TableRecord.d.ts │ │ ├── TableSchema.d.ts │ │ ├── UrlScheme.d.ts │ │ ├── User.d.ts │ │ ├── UserGroup.d.ts │ │ ├── UserRecord.d.ts │ │ ├── UserSuperGroup.d.ts │ │ ├── Validator.d.ts │ │ └── WechatProfitSharingOrder.d.ts │ ├── function.d.ts │ ├── index.d.ts │ ├── request.d.ts │ └── useVersion.d.ts │ ├── faas.d.ts │ └── index.d.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── tsconfig.json /.env: -------------------------------------------------------------------------------- 1 | # github release token 2 | GH_TOKEN= 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # 依赖 2 | node_modules 3 | 4 | # 构建出来的代码 5 | dist 6 | dist-ts 7 | libs/**/lib 8 | packages/**/lib 9 | 10 | # 测试相关文件 11 | coverage 12 | __snapshots__ 13 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint', 'prettier'], 5 | env: { 6 | es6: true, 7 | node: true, 8 | }, 9 | extends: [ 10 | 'eslint:recommended', 11 | 'plugin:@typescript-eslint/recommended', 12 | 'plugin:prettier/recommended', 13 | ], 14 | rules: { 15 | 'prettier/prettier': 'error', // 启用 prettier 的规则 16 | '@typescript-eslint/explicit-function-return-type': 'off', 17 | '@typescript-eslint/no-var-requires': 'off', 18 | // 关闭对禁止使用非空断言的检查 19 | '@typescript-eslint/no-non-null-assertion': 'off', 20 | '@typescript-eslint/no-explicit-any': 'off', 21 | }, 22 | globals: { 23 | BaaS: true, 24 | }, 25 | overrides: [ 26 | { 27 | files: ['**/__tests__/**', '**/__mocks__/**', '**/__helpers__/**'], 28 | env: { 29 | jest: true, 30 | }, 31 | rules: { 32 | 'import/no-extraneous-dependencies': 'off', 33 | 'import/order': 'off', 34 | 'max-classes-per-file': 'off', 35 | 'node/no-extraneous-require': 'off', 36 | 'node/no-unpublished-require': 'off', 37 | 'no-console': 'off', 38 | }, 39 | }, 40 | ], 41 | }; 42 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### ✨ Features 2 | 3 | ### ⚙️ Optimizations 4 | 5 | ### 🧪 Testing 6 | 7 | ### 🐛 Bug Fixes 8 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: ['master', 'develop'] 5 | pull_request: 6 | branches: [master] 7 | # workflow_dispatch: 8 | # inputs: 9 | # tag: 10 | # description: override release tag 11 | # required: false 12 | 13 | jobs: 14 | build-and-test: 15 | name: Build and Test 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | - run: corepack enable 21 | - uses: actions/setup-node@v4 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | cache: 'pnpm' 25 | - name: Install Dependencies 26 | run: pnpm install --frozen-lockfile 27 | - name: Lint 28 | run: pnpm run lint 29 | - name: Run Tests 30 | run: pnpm run test 31 | - name: Build 32 | run: pnpm run build 33 | 34 | Integration: 35 | name: TypeScript & Integration Tests 36 | runs-on: ubuntu-latest 37 | strategy: 38 | fail-fast: false 39 | matrix: 40 | node-version: [20, 18] 41 | 42 | steps: 43 | - uses: actions/checkout@v4 44 | - run: corepack enable 45 | - uses: actions/setup-node@v4 46 | with: 47 | node-version: ${{ matrix.node-version }} 48 | cache: 'pnpm' 49 | 50 | - name: Install Dependencies 51 | run: pnpm install --frozen-lockfile 52 | 53 | - name: Integration Tests 54 | run: pnpm test -- integration/ 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | yarn-error.log 3 | lerna-debug.log 4 | 5 | # 通过编译生成的文件 6 | /packages/*/lib 7 | dist/ 8 | dist-ts/ 9 | *.tsbuildinfo 10 | .nx 11 | 12 | # lock file 13 | package-lock.json 14 | 15 | # 知晓云云函数配置文件 16 | .mincloudrc 17 | 18 | # cli 19 | packages/cli/_schema.json 20 | packages/cli/types/schema.d.ts 21 | 22 | # log file 23 | apps/*/log 24 | 25 | # local env files 26 | .env*.local 27 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | pnpm exec commitlint --edit $1 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm run pre-commit -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | libs/**/lib -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "endOfLine": "lf", 5 | "bracketSameLine": false, 6 | "jsxSingleQuote": false, 7 | "printWidth": 80, 8 | "proseWrap": "preserve", 9 | "quoteProps": "as-needed", 10 | "semi": true, 11 | "singleQuote": true, 12 | "tabWidth": 2, 13 | "trailingComma": "all", 14 | "useTabs": false 15 | } 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## [0.4.2](https://github.com/anran758/mincloudx/compare/v4.0.2...v0.4.2) (2024-07-25) 7 | 8 | **Note:** Version bump only for package mincloudx 9 | 10 | ## [0.4.1](https://github.com/anran758/mincloudx/compare/v4.0.1...v0.4.1) (2024-07-18) 11 | 12 | **Note:** Version bump only for package mincloudx 13 | 14 | # [0.4.0](https://github.com/anran758/mincloudx/compare/v0.1.1...v0.4.0) (2024-04-19) 15 | 16 | ### Bug Fixes 17 | 18 | - **cli:** fix the issue where build fails in the absence of `ts-loader` dependency ([3e87715](https://github.com/anran758/mincloudx/commit/3e8771531d9a0f8cbaf8bd9fb2c11bcb393c9e11)) 19 | - **faas:** fixed the issue where createFaas could not be called properly ([00b0b19](https://github.com/anran758/mincloudx/commit/00b0b194ab165332fd3c9058649e89ce9e99e8f7)) 20 | - fix reading incorrect configuration for client_id ([df37a2c](https://github.com/anran758/mincloudx/commit/df37a2c8896a4b610a9c9afc48172da076b86f89)) 21 | - fixed the issue for `upload` command verbose log call error, add ([707993d](https://github.com/anran758/mincloudx/commit/707993d736753853e3d14fc8b1b617e5c59608be)) 22 | - fixed the issue where environment variables were not working correctly ([b57d924](https://github.com/anran758/mincloudx/commit/b57d924c9143ca84d4a7b653aed1daa6bf3f2918)) 23 | - **io:** io `find` operator should support offset and limit configuration ([2e068eb](https://github.com/anran758/mincloudx/commit/2e068eb81aa2fce1d0fdb150ab83d0467b9059a3)) 24 | - **io:** when the user sets plain, the find operator should return a data list, not object ([91a6c4b](https://github.com/anran758/mincloudx/commit/91a6c4b20a7024fd5f660ed0df6c953571d7be1a)) 25 | 26 | ### Features 27 | 28 | - `faas debug` support select cloud function ([c66d624](https://github.com/anran758/mincloudx/commit/c66d624b4fbd6ff31218a424694f9e08453955e6)) 29 | - 💥 add `faas upload` command, refactor `faas deploy` and other faas command params ([6ecff0b](https://github.com/anran758/mincloudx/commit/6ecff0bc52a3b5f3592d2f3a310c3626c1319847)) 30 | - add basic architecture to IO package ([3fd29c6](https://github.com/anran758/mincloudx/commit/3fd29c67a36da47ae831d31dbfc5c4379c03305d)) 31 | - add faas deploy command ([b6a5ab1](https://github.com/anran758/mincloudx/commit/b6a5ab18cd842941ae903871360ddc2f688376fb)) 32 | - added `faas mock` command to support invoking cloud function with mock data ([e066fc1](https://github.com/anran758/mincloudx/commit/e066fc107d63bb55e2f6f128429f93f7618ffba8)) 33 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 34 | - **cli:** cli faas debug command supports continuous debugging ([fc06472](https://github.com/anran758/mincloudx/commit/fc06472b46cb3ae3fffcddc0406fe44df94d4c3b)) 35 | - **cli:** support `faas debug` command ([0b6b3cf](https://github.com/anran758/mincloudx/commit/0b6b3cfbfc6594eb8ad1bc9d2e74ee4d057a3dd3)) 36 | - enhance faas deploy command to support deploying all cloud functions ([5fc0f8d](https://github.com/anran758/mincloudx/commit/5fc0f8d0e808ccc80a09ef4ab578de47b7c65a11)) 37 | - faas build supports single file ([a8a5cbd](https://github.com/anran758/mincloudx/commit/a8a5cbdc1a0db637fa8586c86f3adfbe28eb74d4)) 38 | - **faas:** add baas/faas type ([735b09d](https://github.com/anran758/mincloudx/commit/735b09d41de4f8659d765315a3dfb1d62f5b96f5)) 39 | - **faas:** add createFaas, complete basic implementation ([64a557a](https://github.com/anran758/mincloudx/commit/64a557a85aa64995e0a44a432d1f93b9f1a18306)) 40 | - **faas:** add new faas framework package, add jest framework, introduced jest for code testing ([12e48dd](https://github.com/anran758/mincloudx/commit/12e48dd7d07a8334f3f3ee52ce39bae807e93f6d)) 41 | - **io:** introduce `first` operator to efficiently retrieve the initial record ([56e9bbe](https://github.com/anran758/mincloudx/commit/56e9bbe1a1a22947380ee9289f6a19eae19b8f53)) 42 | - **io:** io support crud function, update faas-demo example ([d67f377](https://github.com/anran758/mincloudx/commit/d67f377c564d0935679c06d2c5c357d064321aae)) 43 | - **io:** support the `createMany` command to create many records ([e956c85](https://github.com/anran758/mincloudx/commit/e956c8541b403af50d5895c9c4c33161f246cfc3)) 44 | - **io:** support the `deleteMany` method for IO ([fcec4e3](https://github.com/anran758/mincloudx/commit/fcec4e3a292d88fb21695f767f8d64f641312655)) 45 | - **io:** support the `updateMany` method for IO, update document ([fe08bf6](https://github.com/anran758/mincloudx/commit/fe08bf6c75af054444a71197ecd815fb4b17f926)) 46 | - **io:** supports `count` function to fetch data count ([8e5273a](https://github.com/anran758/mincloudx/commit/8e5273ab80caa340fd6362481a2aa5d0b34c4d74)) 47 | - **io:** supports find to find lists of data ([ef4ceac](https://github.com/anran758/mincloudx/commit/ef4ceace80c70705c2462a62efd3dcdd9feb44e4)) 48 | - support faas build command ([13f705e](https://github.com/anran758/mincloudx/commit/13f705eb623b62d531ffc5825f0d60aed6e1c6ec)) 49 | - **types:** abstract the common TypeScript type files into the a separate package ([cc8fc2c](https://github.com/anran758/mincloudx/commit/cc8fc2cb64865a330043afc800150aca7abca6d1)) 50 | - **type:** support dynamic return via plain param ([8307f1c](https://github.com/anran758/mincloudx/commit/8307f1cfc864cc08f148e6cb184faa331c8445d8)) 51 | 52 | ### Performance Improvements 53 | 54 | - **cli:** abstract common configuration ([3ae22dc](https://github.com/anran758/mincloudx/commit/3ae22dc30c1086f3dd89a758a473c8dc1965b6b6)) 55 | - **cli:** introduce inquirer to enhance security when entering password during login ([7462292](https://github.com/anran758/mincloudx/commit/7462292dbf246df719d04c5089780bae085e91e3)) 56 | - **io:** unify the usage of BaaS.TableObject ([5b3132f](https://github.com/anran758/mincloudx/commit/5b3132f8d1e35ad038b3b222b0e9b52867f4868f)) 57 | - modify the usage of faas-demo ([c80e152](https://github.com/anran758/mincloudx/commit/c80e1523668e40887a115e0732d73055d9e9a490)) 58 | - use npmlog instead of default log ([b1294c3](https://github.com/anran758/mincloudx/commit/b1294c32ee4b808b4a779a888e029351dcaa6618)) 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 anran758 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mincloudx 2 | 3 | ![Github lerna version (branch)](https://img.shields.io/github/lerna-json/v/anran758/mincloudx) 4 | ![ts](https://badgen.net/badge/-/TypeScript?icon=typescript&label&labelColor=blue&color=555555) 5 | ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/anran758/mincloudx/ci.yml) 6 | [![GitHub](https://img.shields.io/github/license/anran758/mincloudx)](https://github.com/anran758/mincloudx/blob/master/LICENSE) 7 | 8 | [MinCloud](https://cloud.minapp.com/) is a cloud development platform that provides a variety of cloud services, including cloud databases, content storage, cloud functions, and WeChat Mini Program cloud development. 9 | 10 | Additionally, MinCloud offers features like visual website building, forms, message notifications, SMS verification, etc., providing developers with comprehensive cloud development services. 11 | 12 | 🔧 `mincloudx` is a library ecosystem built around MinCloud cloud development, aiming to expand the original functionalities to facilitate work. 13 | 14 | ## Development 15 | 16 | The development of mincloudx is based on the Monorepo project organization. We use [Lerna](https://lerna.js.org/) as the package manager, and all related packages are stored in a single Git repository. 17 | 18 | For development and release standards of Monorepo projects, please refer to [Development and Release Standards for Monorepo Projects](./docs/dev-and-deploy.md). 19 | 20 | ## Community 21 | 22 | - 💬 You can interact with other users on [GitHub Discussions](https://github.com/anran758/mincloudx/discussions). 23 | - 🚨 Report issues or request features on [GitHub Issues](https://github.com/anran758/mincloudx/issues). 24 | - 📒 Follow the [TODO](./docs/to) to know about the upcoming development plans for the project. 25 | -------------------------------------------------------------------------------- /apps/faas-demo/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [0.4.0](https://github.com/anran758/mincloudx/compare/v0.1.1...v0.4.0) (2024-04-19) 7 | 8 | ### Bug Fixes 9 | 10 | - **faas:** fixed the issue where createFaas could not be called properly ([00b0b19](https://github.com/anran758/mincloudx/commit/00b0b194ab165332fd3c9058649e89ce9e99e8f7)) 11 | 12 | ### Features 13 | 14 | - added `faas mock` command to support invoking cloud function with mock data ([e066fc1](https://github.com/anran758/mincloudx/commit/e066fc107d63bb55e2f6f128429f93f7618ffba8)) 15 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 16 | - **io:** introduce `first` operator to efficiently retrieve the initial record ([56e9bbe](https://github.com/anran758/mincloudx/commit/56e9bbe1a1a22947380ee9289f6a19eae19b8f53)) 17 | - **io:** io support crud function, update faas-demo example ([d67f377](https://github.com/anran758/mincloudx/commit/d67f377c564d0935679c06d2c5c357d064321aae)) 18 | - **io:** support the `createMany` command to create many records ([e956c85](https://github.com/anran758/mincloudx/commit/e956c8541b403af50d5895c9c4c33161f246cfc3)) 19 | - **io:** support the `deleteMany` method for IO ([fcec4e3](https://github.com/anran758/mincloudx/commit/fcec4e3a292d88fb21695f767f8d64f641312655)) 20 | - **io:** support the `updateMany` method for IO, update document ([fe08bf6](https://github.com/anran758/mincloudx/commit/fe08bf6c75af054444a71197ecd815fb4b17f926)) 21 | - **io:** supports `count` function to fetch data count ([8e5273a](https://github.com/anran758/mincloudx/commit/8e5273ab80caa340fd6362481a2aa5d0b34c4d74)) 22 | - **io:** supports find to find lists of data ([ef4ceac](https://github.com/anran758/mincloudx/commit/ef4ceace80c70705c2462a62efd3dcdd9feb44e4)) 23 | - **types:** abstract the common TypeScript type files into the a separate package ([cc8fc2c](https://github.com/anran758/mincloudx/commit/cc8fc2cb64865a330043afc800150aca7abca6d1)) 24 | 25 | ### Performance Improvements 26 | 27 | - modify the usage of faas-demo ([c80e152](https://github.com/anran758/mincloudx/commit/c80e1523668e40887a115e0732d73055d9e9a490)) 28 | - use npmlog instead of default log ([b1294c3](https://github.com/anran758/mincloudx/commit/b1294c32ee4b808b4a779a888e029351dcaa6618)) 29 | -------------------------------------------------------------------------------- /apps/faas-demo/README.md: -------------------------------------------------------------------------------- 1 | # @mincloudx/faas-demo 2 | 3 | **命令** 4 | 5 | ```bash 6 | # 编译源码 7 | pnpm build 8 | 9 | # 部署云函数 10 | pnpm deploy 11 | ``` 12 | 13 | **目录结构** 14 | 15 | ```bash 16 | . 17 | ├── _schema.json // [可选] 数据表结构,可从知晓云中下载到本地,也可以直接通过 mincloudx login 后获取 18 | ├── src // 项目源码 19 | │ ├── config // 配置信息 20 | │ │ └── index.js 21 | │ └── function // 云函数源码 22 | │ ├── createProduct.js // 云函数 A 23 | │ └── user // 分类文件夹 24 | │ └── createUser.js // 云函数 B 25 | ├── tsconfig.json 26 | └── typings // TypeScript 类型 27 | └── schema.d.ts // 通过 cli 生成的数据表类型 28 | ``` 29 | 30 | `src` 的源码应该直接使用 `ESModule` 语法,当 cli 构建源码时能对源码进行 `Tree Shaking`. 31 | -------------------------------------------------------------------------------- /apps/faas-demo/local-invoke.js: -------------------------------------------------------------------------------- 1 | const SKD_VERSION = 'v2.0'; 2 | global.BaaS = { 3 | VERSION: SKD_VERSION, 4 | useVersion(version) { 5 | BaaS.VERSION = version; 6 | }, 7 | }; 8 | 9 | const loadUserFunction = fileName => { 10 | const { main } = require(`./dist/${fileName}.js`); 11 | return main; 12 | }; 13 | 14 | const main = loadUserFunction(process.argv[process.argv.length - 1]); 15 | main(); 16 | -------------------------------------------------------------------------------- /apps/faas-demo/mock/channelCreate.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | data: { 3 | name: `旧书铺-${new Date()}`, 4 | cover: 5 | 'https://cloud-minapp-47549.cloud.ifanrusercontent.com/1rmlh9degSiaF4ua.jpg', 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /apps/faas-demo/mock/channelDelete.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | id: '65fa8a4ae37f7c453e7b7045', 3 | }; 4 | -------------------------------------------------------------------------------- /apps/faas-demo/mock/example.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | year: 2023, 3 | name: 'anran758', 4 | }; 5 | -------------------------------------------------------------------------------- /apps/faas-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/faas-demo", 3 | "version": "0.4.0", 4 | "private": true, 5 | "description": "Out-of-the-box Cloud Function Template", 6 | "author": "anran758 ", 7 | "homepage": "https://github.com/anran758/mincloudx/tree/main/packages/node-demo#readme", 8 | "license": "MIT", 9 | "sideEffects": false, 10 | "publishConfig": { 11 | "access": "restricted" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/anran758/mincloudx.git" 16 | }, 17 | "scripts": { 18 | "lint": "eslint .", 19 | "build": "mincloudx faas build", 20 | "upload": "mincloudx faas upload", 21 | "deploy": "mincloudx faas deploy", 22 | "debug": "mincloudx faas debug", 23 | "refresh": "mincloudx type --pull" 24 | }, 25 | "bugs": { 26 | "url": "https://github.com/anran758/mincloudx/issues" 27 | }, 28 | "dependencies": { 29 | "@mincloudx/cli": "workspace:*", 30 | "@mincloudx/faas": "workspace:*", 31 | "@mincloudx/io": "workspace:*", 32 | "ts-loader": "^9.5.1", 33 | "webpack-chain": "^6.5.1", 34 | "webpack-cli": "^5.1.4" 35 | }, 36 | "devDependencies": { 37 | "mincloud": "^1.2.3", 38 | "terser-webpack-plugin": "^5.3.9" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /apps/faas-demo/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/faas-demo", 3 | "projectType": "application" 4 | } 5 | -------------------------------------------------------------------------------- /apps/faas-demo/src/config/index.js: -------------------------------------------------------------------------------- 1 | export const NAME = 'test name 1'; 2 | 3 | export const NAME_MAP = { 4 | a: 'test name a', 5 | b: 'test name b', 6 | }; 7 | 8 | export const NEVER_USE_VAR = '从未被引用的变量,不应该被打包'; 9 | -------------------------------------------------------------------------------- /apps/faas-demo/src/function/channel/channelCreate.ts: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | import io from '@/io'; 3 | 4 | interface EventParams { 5 | data: { 6 | name: string; 7 | cover: string; 8 | }; 9 | } 10 | 11 | export default createFaas(async function main(event) { 12 | const { data } = event.data; 13 | 14 | const record = await io.channel.create(data); 15 | console.log('create result:', record); 16 | 17 | const updatedResult = await io.channel.update(record.id, { 18 | data: { 19 | description: 'This is description.', 20 | }, 21 | }); 22 | console.log('updated result:', updatedResult); 23 | 24 | const channel = await io.channel.get(record.id, { 25 | select: ['id', 'name', 'cover', 'description'], 26 | }); 27 | console.log('get result:', channel); 28 | 29 | return channel; 30 | }); 31 | -------------------------------------------------------------------------------- /apps/faas-demo/src/function/channel/channelDelete.ts: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | import io from '@/io'; 3 | 4 | interface EventParams { 5 | id: string; 6 | } 7 | 8 | export default createFaas(async function main(event) { 9 | const { id } = event.data; 10 | const result = await io.channel.delete(id); 11 | 12 | console.log('delete result:', result); 13 | 14 | return result; 15 | }); 16 | -------------------------------------------------------------------------------- /apps/faas-demo/src/function/test/testOperationCount.ts: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | import io from '@/io'; 3 | 4 | export default createFaas(async function main() { 5 | const query = io.getQuery({ 6 | description: 'This is description.', 7 | }); 8 | const count = await io.product.count(query); 9 | 10 | console.log('count: ', count); 11 | 12 | return { count }; 13 | }); 14 | -------------------------------------------------------------------------------- /apps/faas-demo/src/function/test/testOperationCreateMany.ts: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | import io from '@/io'; 3 | 4 | import { getCurrentDate } from '@/utils'; 5 | 6 | function generatorMockData() { 7 | const rawData = { 8 | name: `新书本-${getCurrentDate()}`, 9 | cover: 10 | 'https://cloud-minapp-47549.cloud.ifanrusercontent.com/1rmlh9degSiaF4ua.jpg', 11 | description: 'testOperationCreateMany create.', 12 | }; 13 | 14 | return Array(6) 15 | .fill(0) 16 | .map((_, i) => { 17 | return { 18 | ...rawData, 19 | name: `${rawData.name}_${i}`, 20 | }; 21 | }); 22 | } 23 | export default createFaas(async function main() { 24 | const list = generatorMockData(); 25 | 26 | const { 27 | operation_result: result, 28 | succeed, 29 | total_count, 30 | } = await io.product.createMany(list); 31 | 32 | console.log('result:', result); 33 | console.log('succeed: ', succeed); 34 | console.log('total: ', total_count); 35 | 36 | return result; 37 | }); 38 | -------------------------------------------------------------------------------- /apps/faas-demo/src/function/test/testOperationDeleteMany.ts: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | import io from '@/io'; 3 | 4 | export default createFaas(async function main() { 5 | const result = await io.product.deleteMany(io.query, { 6 | limit: 2, 7 | }); 8 | console.log( 9 | 'result: ', 10 | result.succeed, 11 | result.offset, 12 | result.limit, 13 | result.next, 14 | ); 15 | 16 | return result; 17 | }); 18 | -------------------------------------------------------------------------------- /apps/faas-demo/src/function/test/testOperationFindList.ts: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | import io from '@/io'; 3 | 4 | export default createFaas(async function main() { 5 | const query = io.getQuery({ 6 | description: 'This is description.', 7 | }); 8 | const result = await io.product.find(query, { 9 | select: ['id', 'name', 'description'], 10 | plain: true, 11 | }); 12 | 13 | return result; 14 | }); 15 | -------------------------------------------------------------------------------- /apps/faas-demo/src/function/test/testOperationFirst.ts: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | import io from '@/io'; 3 | 4 | export default createFaas(async function main() { 5 | const query = io.getQuery({ 6 | description: 'This is description.', 7 | }); 8 | const record = await io.product.first< 9 | { 10 | description: string; 11 | id: string; 12 | name: string; 13 | }, 14 | false 15 | >(query, { 16 | plain: false, 17 | select: ['description', 'id', 'name'], 18 | }); 19 | // const record = await io.product.first(query); 20 | 21 | console.log('record: ', record.data); 22 | 23 | return record; 24 | }); 25 | -------------------------------------------------------------------------------- /apps/faas-demo/src/function/test/testOperationUpdateMany.ts: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | import io from '@/io'; 3 | 4 | export default createFaas(async function main() { 5 | const list = await io.product.updateMany({ 6 | query: io.getQuery({ 7 | created_at: 1711691446, 8 | }), 9 | data: { 10 | description: `update date: ${new Date()}`, 11 | }, 12 | }); 13 | 14 | console.log('result:', list); 15 | 16 | return list; 17 | }); 18 | -------------------------------------------------------------------------------- /apps/faas-demo/src/function/user/createUser.ts: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | 3 | export default createFaas(async function main(event) { 4 | console.log(`event:`, event); 5 | 6 | return { status: 'ok' }; 7 | }); 8 | -------------------------------------------------------------------------------- /apps/faas-demo/src/io/index.ts: -------------------------------------------------------------------------------- 1 | import { createIo } from '@mincloudx/io'; 2 | 3 | export default createIo({ 4 | tables: ['channel', 'product'], 5 | }); 6 | -------------------------------------------------------------------------------- /apps/faas-demo/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export function getCurrentDate() { 2 | const now = new Date(); 3 | 4 | // 分别获取日期和时间字符串 5 | const dateString = now 6 | .toLocaleDateString('zh-CN', { 7 | year: 'numeric', 8 | month: '2-digit', 9 | day: '2-digit', 10 | }) 11 | .replace(/\//g, '-'); 12 | 13 | const timeString = now.toLocaleTimeString('zh-CN', { 14 | hour: '2-digit', 15 | minute: '2-digit', 16 | hour12: false, // 使用24小时制 17 | }); 18 | 19 | return `${dateString} ${timeString}`; 20 | } 21 | -------------------------------------------------------------------------------- /apps/faas-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "baseUrl": ".", 5 | "target": "ES2015", 6 | "module": "Node16", 7 | "moduleResolution": "node16", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "outDir": "./dist-ts", 11 | "paths": { 12 | "@/*": ["src/*"] 13 | } 14 | }, 15 | "exclude": ["node_modules", "**/*.spec.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /apps/faas-demo/types/schema.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * [tips]: This file is automatically generated by @mincloudx/cli, please do not modify the file directly. 3 | */ 4 | /* eslint-disable @typescript-eslint/no-unused-vars */ 5 | /* eslint-disable no-use-before-define */ 6 | 7 | export type SchemaId = string | number; 8 | 9 | /** 10 | * Fields ending in "_at" are conventionally designated as timestamp fields. 11 | **/ 12 | export type EpochSeconds = number & { seconds_since_the_unix_start: never }; 13 | export type JSONString = string & { json_parsable_string: never }; 14 | export type HTMLText = string & { html_content: never }; 15 | export type ValueOf = T[keyof T]; 16 | export type KeyOf = Array; 17 | export type Default = T; 18 | 19 | export interface BaseTable { 20 | _id: SchemaId; 21 | id: SchemaId; 22 | created_at: number; 23 | updated_at: number; 24 | created_by: CreatedBy; 25 | read_perm: string[]; 26 | write_perm: string[]; 27 | } 28 | 29 | interface UserProfile extends BaseTable {} 30 | 31 | export interface PointerWithoutData { 32 | id: SchemaId; 33 | _table: string; 34 | } 35 | 36 | export type SchemaPointer = T | PointerWithoutData; 37 | 38 | export type CreatedBy = UserProfile | PointerWithoutData | number; 39 | 40 | /** 41 | * MinCloud File operation result 42 | */ 43 | export interface FileOperationResult { 44 | /** 45 | * Record ID 46 | */ 47 | _id: string; 48 | /** 49 | * created time (in Unix timestamp format) 50 | */ 51 | created_at: number; 52 | /** 53 | * Path 54 | */ 55 | path: string; 56 | /** 57 | * created record user ID 58 | */ 59 | created_by: number; 60 | /** 61 | * Mime type 62 | */ 63 | mime_type: string; 64 | /** 65 | * Media type 66 | */ 67 | media_type: string; 68 | /** 69 | * File size 70 | */ 71 | size: number; 72 | /** 73 | * File name 74 | */ 75 | name: string; 76 | /** 77 | * File status 78 | */ 79 | status: string; 80 | /** 81 | * Reference 82 | */ 83 | reference: string; 84 | /** 85 | * CDN path 86 | */ 87 | cdn_path: string; 88 | /** 89 | * Integer. Updated time (in Unix timestamp format) 90 | */ 91 | updated_at: number; 92 | /** 93 | * File categories 94 | */ 95 | categories: string[]; 96 | } 97 | 98 | /** 99 | * 数据表: _userprofile 100 | * @description 101 | */ 102 | export interface UserProfile extends BaseTable { 103 | /** 104 | * 用户昵称 105 | **/ 106 | nickname: Default | string; 107 | /** 108 | * 用户的性别,值为 1 时是男性,值为 2 时是女性,值为 0 时是未知 109 | **/ 110 | gender: Default | number; 111 | /** 112 | * 用户所在国家 113 | **/ 114 | country: Default | string; 115 | /** 116 | * 用户所在省份 117 | **/ 118 | province: Default | string; 119 | /** 120 | * 用户所在城市 121 | **/ 122 | city: Default | string; 123 | /** 124 | * 用户的语言 125 | **/ 126 | language: Default | string; 127 | /** 128 | * openid 129 | **/ 130 | openid: Default | string; 131 | /** 132 | * unionid 133 | **/ 134 | unionid: Default | string; 135 | /** 136 | * 用户头像 137 | **/ 138 | avatar: Default | string; 139 | /** 140 | * 用户是否授权,True 为已授权,False 为未授权 141 | **/ 142 | is_authorized: Default | boolean; 143 | /** 144 | * 用户邮箱是否已经通过验证 145 | **/ 146 | _email_verified: Default | boolean; 147 | /** 148 | * 用户邮箱 149 | **/ 150 | _email: Default | string; 151 | /** 152 | * 用户名 153 | **/ 154 | _username: Default | string; 155 | /** 156 | * 用户在平台方的用户信息 157 | **/ 158 | _provider: Default | Record; 159 | /** 160 | * 用户手机 161 | **/ 162 | _phone: Default | string; 163 | /** 164 | * 用户手机是否已经通过验证 165 | **/ 166 | _phone_verified: Default | boolean; 167 | } 168 | 169 | /** 170 | * 数据表: _richtextcontent 171 | * @description 172 | */ 173 | export interface RichTextContent extends BaseTable { 174 | /** 175 | * 内容的标题 176 | **/ 177 | title: Default | string; 178 | /** 179 | * 内容的简介 180 | **/ 181 | description: Default | string; 182 | /** 183 | * 内容的封面图 184 | **/ 185 | cover: Default | FileOperationResult; 186 | /** 187 | * 内容详情 188 | **/ 189 | content: Default | string; 190 | /** 191 | * 内容库 ID 192 | **/ 193 | group_id: Default | number; 194 | /** 195 | * 内容分类的 ID 列表 196 | **/ 197 | categories: Default | number[]; 198 | /** 199 | * 内容阅读数 200 | **/ 201 | visit_count: Default | number; 202 | } 203 | 204 | /** 205 | * 数据表: product 206 | * @description 产品表 207 | */ 208 | export interface Product extends BaseTable { 209 | /** 210 | * 产品名 211 | **/ 212 | name: string; 213 | /** 214 | * 产品封面 215 | **/ 216 | cover: Default | string; 217 | /** 218 | * 描述 219 | **/ 220 | description: Default | string; 221 | } 222 | 223 | /** 224 | * 数据表: channel 225 | * @description 圈子表 226 | */ 227 | export interface Channel extends BaseTable { 228 | /** 229 | * 圈子名称 230 | **/ 231 | name: Default | string; 232 | /** 233 | * 圈子封面图 234 | **/ 235 | cover: Default | string; 236 | /** 237 | * 圈子描述 238 | **/ 239 | description: Default | string; 240 | /** 241 | * 圈子状态 242 | **/ 243 | status: Default<'approved'> | string | 'approved' | 'deleted'; 244 | } 245 | 246 | /** 247 | * 数据表: post 248 | * @description 帖子 249 | */ 250 | export interface Post extends BaseTable { 251 | /** 252 | * 内容 253 | **/ 254 | content: Default | string; 255 | /** 256 | * 封面 257 | **/ 258 | corver: Default | string; 259 | } 260 | -------------------------------------------------------------------------------- /apps/web-demo/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["@babel/syntax-dynamic-import"], 3 | "presets": [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | "modules": false 8 | } 9 | ] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /apps/web-demo/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [0.4.0](https://github.com/anran758/mincloudx/compare/v0.1.1...v0.4.0) (2024-04-19) 7 | 8 | ### Features 9 | 10 | - added `faas mock` command to support invoking cloud function with mock data ([e066fc1](https://github.com/anran758/mincloudx/commit/e066fc107d63bb55e2f6f128429f93f7618ffba8)) 11 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 12 | -------------------------------------------------------------------------------- /apps/web-demo/README.md: -------------------------------------------------------------------------------- 1 | # @mincloudx/web-demo 2 | 3 | > 知晓云 web 开发模板 4 | 5 | This project has been created using **webpack-cli**, you can now run 6 | 7 | ```bash 8 | npm run build 9 | ``` 10 | 11 | or 12 | 13 | ```bash 14 | pnpm build 15 | ``` 16 | 17 | to bundle your application 18 | -------------------------------------------------------------------------------- /apps/web-demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Webpack App 6 | 7 | 8 |

Hello world!

9 |

Tip: Check your console

10 | 11 | 12 | 29 | 30 | -------------------------------------------------------------------------------- /apps/web-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/web-demo", 3 | "version": "0.4.0", 4 | "private": true, 5 | "description": "web test demo", 6 | "author": "anran758 ", 7 | "homepage": "https://github.com/anran758/mincloudx#readme", 8 | "license": "MIT", 9 | "main": "index.js", 10 | "directories": { 11 | "lib": "dist", 12 | "test": "__tests__" 13 | }, 14 | "files": [ 15 | "dist" 16 | ], 17 | "publishConfig": { 18 | "access": "restricted" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/anran758/mincloudx.git" 23 | }, 24 | "scripts": { 25 | "lint": "eslint .", 26 | "test": "node ./__tests__/@mincloudx/web-demo.test.js", 27 | "build": "webpack --mode=production --node-env=production", 28 | "build:dev": "webpack --mode=development", 29 | "build:prod": "webpack --mode=production --node-env=production", 30 | "watch": "webpack --watch", 31 | "serve": "webpack serve" 32 | }, 33 | "bugs": { 34 | "url": "https://github.com/anran758/mincloudx/issues" 35 | }, 36 | "devDependencies": { 37 | "@babel/core": "^7.19.1", 38 | "@babel/preset-env": "^7.19.1", 39 | "autoprefixer": "^10.4.11", 40 | "babel-loader": "^8.2.5", 41 | "css-loader": "^6.7.1", 42 | "html-webpack-plugin": "^5.5.0", 43 | "less": "^4.1.3", 44 | "less-loader": "^11.0.0", 45 | "mini-css-extract-plugin": "^2.6.1", 46 | "postcss": "^8.4.16", 47 | "postcss-loader": "^7.0.1", 48 | "style-loader": "^3.3.1", 49 | "ts-loader": "^9.3.1", 50 | "webpack": "^5.74.0", 51 | "webpack-cli": "^5.1.4", 52 | "webpack-dev-server": "^4.11.0", 53 | "workbox-webpack-plugin": "^6.5.4" 54 | }, 55 | "dependencies": { 56 | "@mincloudx/io": "workspace:*" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /apps/web-demo/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Add you postcss configuration here 3 | // Learn more about it at https://github.com/webpack-contrib/postcss-loader#config-files 4 | plugins: [['autoprefixer']], 5 | }; 6 | -------------------------------------------------------------------------------- /apps/web-demo/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/web-demo", 3 | "projectType": "application" 4 | } 5 | -------------------------------------------------------------------------------- /apps/web-demo/src/index.js: -------------------------------------------------------------------------------- 1 | import { sayHi } from '@mincloudx/io'; 2 | 3 | sayHi(); 4 | 5 | console.log('Hello World, This is web demo!'); 6 | -------------------------------------------------------------------------------- /apps/web-demo/src/web-demo.js: -------------------------------------------------------------------------------- 1 | export default function webDemo() { 2 | return 'Hello from webDemo'; 3 | } 4 | -------------------------------------------------------------------------------- /apps/web-demo/webpack.config.js: -------------------------------------------------------------------------------- 1 | // Generated using webpack-cli https://github.com/webpack/webpack-cli 2 | 3 | const path = require('path'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 6 | const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); 7 | 8 | const isProduction = process.env.NODE_ENV == 'production'; 9 | 10 | const stylesHandler = MiniCssExtractPlugin.loader; 11 | 12 | const config = { 13 | entry: './src/index.ts', 14 | output: { 15 | path: path.resolve(__dirname, 'dist'), 16 | }, 17 | devServer: { 18 | open: true, 19 | host: 'localhost', 20 | }, 21 | plugins: [ 22 | new HtmlWebpackPlugin({ 23 | template: 'index.html', 24 | }), 25 | 26 | new MiniCssExtractPlugin(), 27 | 28 | // Add your plugins here 29 | // Learn more about plugins from https://webpack.js.org/configuration/plugins/ 30 | ], 31 | module: { 32 | rules: [ 33 | { 34 | test: /\.(ts|tsx)$/i, 35 | loader: 'ts-loader', 36 | exclude: ['/node_modules/'], 37 | }, 38 | { 39 | test: /\.less$/i, 40 | use: [stylesHandler, 'css-loader', 'postcss-loader', 'less-loader'], 41 | }, 42 | { 43 | test: /\.css$/i, 44 | use: [stylesHandler, 'css-loader', 'postcss-loader'], 45 | }, 46 | { 47 | test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i, 48 | type: 'asset', 49 | }, 50 | 51 | // Add your rules for custom modules here 52 | // Learn more about loaders from https://webpack.js.org/loaders/ 53 | ], 54 | }, 55 | resolve: { 56 | extensions: ['.tsx', '.ts', '.jsx', '.js', '...'], 57 | }, 58 | }; 59 | 60 | module.exports = () => { 61 | if (isProduction) { 62 | config.mode = 'production'; 63 | 64 | config.plugins.push(new WorkboxWebpackPlugin.GenerateSW()); 65 | } else { 66 | config.mode = 'development'; 67 | } 68 | return config; 69 | }; 70 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/dev-and-deploy.md: -------------------------------------------------------------------------------- 1 | # Monorepo 项目的开发与发布规范 2 | 3 | > 下述将对开发与部署做对应的约束 4 | 5 | 本项目采用 monorepo 的组织结构,使用 lerna 作为包管理器。 6 | 7 | ## 新增功能或新增 package 8 | 9 | 当需要新增功能或新增 package 时,需要切换到对应的 feature 分支。例如需要在 cli 中扩展新的功能,则需要切换至 feature/cli 中进行开发。 10 | 在项目中优先通过 `git flow` 来处理版本控制。 11 | 12 | ```bash 13 | # 创建新分支 14 | git flow feature start cli 15 | 16 | # or 17 | git checkout develop # 切换至开发分支 18 | git checkout -b feature/cli # 新分支的代码将基于 develop 19 | ``` 20 | 21 | ## 完成功能开发并测试通过 22 | 23 | 当在 `feature` 分支中完成功能开发并测试通过后,将开发分支的代码合并至 develop 分支中: 24 | 25 | ```bash 26 | git flow feature finish cli 27 | 28 | # or 29 | git checkout develop 30 | git merge --no-ff feature/cli 31 | git branch -d feature/cli 32 | ``` 33 | 34 | ## 发布 35 | 36 | `master` 分支是受保护的,不允许直接操作 `master` 分支。经过测试确认无误后,需要通过 Github 提出 Pull Request ,并且经过审核后再合并至 master 分支中。 37 | 38 | 在 `master` 分支执行 `npx nx run release` 39 | -------------------------------------------------------------------------------- /docs/todo.md: -------------------------------------------------------------------------------- 1 | # TODO 2 | 3 | Here is an overview of the upcoming development plans and strategies for `mincloudx`: 4 | 5 | ### Packages 6 | 7 | - **@mincloudx/cli**: Core development of the command-line interface tools. 8 | - [x] `login` command 9 | - [x] `type` command 10 | - [x] Cloud Functions (`faas`) related commands: 11 | - [x] `build` 12 | - [x] `upload` 13 | - [x] `deploy` 14 | - [x] `mock` 15 | - [x] `debug` 16 | - [x] **@mincloudx/faas**: Cloud functions development framework, completed. 17 | - [x] **@mincloudx/types**: Common TypeScript type definitions, completed. 18 | - [ ] **@mincloudx/io**: Input/output handling utilities, pending development. 19 | 20 | ### Others 21 | 22 | - [ ] **Monorepo Template Project**: will provide a template for quickly starting projects. 23 | - [ ] **Test Cases and Code Coverage**: aimed at ensuring code quality and stability. 24 | - [x] integration 25 | - [ ] e2e 26 | - [ ] **Documentation Auto Generation**: to simplify documentation maintenance. 27 | - **CI** 28 | - [x] lint/build/test 29 | - [ ] release: to implement an automated version control and release process. 30 | 31 | As packages are iteratively updated, we will also continuously improve and update the demo project. 32 | 33 | This description is more structured, making the status and plans of each project clear at a glance, facilitating team members and followers of the project to quickly grasp the development trajectory of the project. 34 | -------------------------------------------------------------------------------- /integration/cjs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [0.4.0](https://github.com/anran758/mincloudx/compare/v0.1.1...v0.4.0) (2024-04-19) 7 | 8 | ### Features 9 | 10 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 11 | -------------------------------------------------------------------------------- /integration/cjs/integration.test.cjs: -------------------------------------------------------------------------------- 1 | const test = require('node:test'); 2 | const assert = require('node:assert'); 3 | const { createFaas } = require('@mincloudx/faas'); 4 | 5 | test('@mincloudx/faas should export modules', () => { 6 | assert(createFaas instanceof Function); 7 | }); 8 | -------------------------------------------------------------------------------- /integration/cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@mincloudx/cjs-integration-tests", 4 | "version": "0.4.0", 5 | "devDependencies": { 6 | "@mincloudx/faas": "workspace:*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /integration/cjs/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/cjs-integration-tests", 3 | "projectType": "application", 4 | "tags": ["type:e2e"] 5 | } 6 | -------------------------------------------------------------------------------- /integration/esm/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [0.4.0](https://github.com/anran758/mincloudx/compare/v0.1.1...v0.4.0) (2024-04-19) 7 | 8 | ### Features 9 | 10 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 11 | -------------------------------------------------------------------------------- /integration/esm/integration.test.mjs: -------------------------------------------------------------------------------- 1 | import { createFaas } from '@mincloudx/faas'; 2 | import test from 'node:test'; 3 | import assert from 'node:assert'; 4 | 5 | test('@mincloudx/faas should export modules', () => { 6 | assert(createFaas instanceof Function); 7 | }); 8 | -------------------------------------------------------------------------------- /integration/esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "type": "module", 4 | "name": "@mincloudx/esm-integration-tests", 5 | "version": "0.4.0", 6 | "devDependencies": { 7 | "@mincloudx/faas": "workspace:*" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /integration/esm/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/esm-integration-tests", 3 | "projectType": "application", 4 | "tags": ["type:e2e"] 5 | } 6 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/lerna/schemas/lerna-schema.json", 3 | "useWorkspaces": true, 4 | "npmClient": "pnpm", 5 | "version": "0.4.2", 6 | "command": { 7 | "version": { 8 | "createRelease": "github", 9 | "conventionalCommits": true, 10 | "forcePublish": true, 11 | "message": "chore(release): publish" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /libs/baas/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | # [0.4.0](https://github.com/anran758/mincloudx/compare/v0.1.1...v0.4.0) (2024-04-19) 7 | 8 | ### Features 9 | 10 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 11 | -------------------------------------------------------------------------------- /libs/baas/index.d.ts: -------------------------------------------------------------------------------- 1 | import { BaaS } from '@mincloudx/types'; 2 | 3 | export default BaaS; 4 | -------------------------------------------------------------------------------- /libs/baas/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/baas", 3 | "version": "0.4.0", 4 | "private": true, 5 | "description": "MinCloud baas sdk", 6 | "author": "anran758 ", 7 | "main": "lib/baas-sdk-v3.20.0.min.js", 8 | "scripts": { 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@mincloudx/types": "workspace:^" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /libs/baas/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/baas", 3 | "projectType": "library" 4 | } 5 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 3 | "workspaceLayout": { 4 | "appsDir": "apps", 5 | "libsDir": "libs" 6 | }, 7 | "tasksRunnerOptions": { 8 | "default": { 9 | "runner": "nx/tasks-runners/default", 10 | "options": { 11 | "cacheableOperations": ["build", "lint", "test", "e2e"] 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mincloudx", 3 | "private": true, 4 | "description": "MinCloud Ecosystem Library Tools", 5 | "homepage": "https://github.com/anran758/mincloudx#readme", 6 | "author": "anran758 ", 7 | "license": "MIT", 8 | "nx": {}, 9 | "engines": { 10 | "node": ">=18" 11 | }, 12 | "scripts": { 13 | "pre-commit": "pnpm lint-staged", 14 | "postinstall": "husky install", 15 | "release": "lerna publish --no-private", 16 | "build": "pnpm -r --filter \"./packages/*\" run build", 17 | "lint-fix": "eslint . --fix", 18 | "lint": "eslint .", 19 | "check-format": "prettier --list-different .", 20 | "format": "prettier --write .", 21 | "test": "node --test integration/**/*.test.*" 22 | }, 23 | "lint-staged": { 24 | "*.{ts,tsx,js,mjs,cjs,jsx,json,css}": [ 25 | "pnpm format", 26 | "pnpm lint" 27 | ], 28 | "*.md": [ 29 | "pnpm format" 30 | ] 31 | }, 32 | "cspell": { 33 | "ignoreWords": [ 34 | "mincloud", 35 | "mincloudx", 36 | "faas", 37 | "baas" 38 | ] 39 | }, 40 | "devDependencies": { 41 | "@commitlint/cli": "^17.6.1", 42 | "@commitlint/config-conventional": "^17.6.1", 43 | "@types/node": "^20.11.24", 44 | "@typescript-eslint/eslint-plugin": "^7.0.2", 45 | "@typescript-eslint/parser": "^7.0.2", 46 | "chalk": "^5.3.0", 47 | "commitizen": "^4.3.0", 48 | "eslint": "^8.38.0", 49 | "eslint-config-prettier": "^8.8.0", 50 | "eslint-plugin-prettier": "^4.2.1", 51 | "husky": "^8.0.3", 52 | "lerna": "^6.4.1", 53 | "lint-staged": "^13.2.1", 54 | "nx": "^15.9.4", 55 | "prettier": "^2.2.1", 56 | "ts-node": "^10.9.2", 57 | "typescript": "^5.4.2" 58 | }, 59 | "dependencies": { 60 | "jest": "^29.7.0" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/cli/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 anran758 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/cli/README.md: -------------------------------------------------------------------------------- 1 | # @mincloudx/cli 2 | 3 | [![npm version](https://badge.fury.io/js/@mincloudx%2Fcli.svg)](https://www.npmjs.com/package/@mincloudx/cli) 4 | [![GitHub](https://img.shields.io/github/license/anran758/mincloudx)](https://github.com/anran758/mincloudx/blob/master/LICENSE) 5 | 6 | 基于知晓云生态的命令行工具,旨在提供一种简单、快捷的方式,帮助开发者快速处理知晓云相关的业务。 7 | 8 | **Table of Contents** 9 | 10 | - [Installation](#installation) 11 | - [Usage](#usage) 12 | - [Commands](#commands) 13 | - [login](#login) 14 | - [type](#type) 15 | - [faas](#faas) 16 | - [build](#build) 17 | - [upload](#upload) 18 | - [deploy](#deploy) 19 | - [mock](#mock) 20 | - [debug](#debug) 21 | - [help](#help) 22 | - [Development](#development) 23 | 24 | ## Installation 25 | 26 | 可以通过 pnpm 或 npm 安装: 27 | 28 | ```bash 29 | # 通过 pnpm 安装 30 | pnpm install @mincloudx/cli -D 31 | 32 | # 通过 npm 安装 33 | npm install @mincloudx/cli -D 34 | ``` 35 | 36 | ## Usage 37 | 38 | ```bash 39 | mincloudx [command] [options] 40 | ``` 41 | 42 | | Commands | Description | 43 | | --------------- | ----------------------------- | 44 | | [login](#login) | 登录知晓云 | 45 | | [type](#type) | 将知晓云数据表转换 TypeScript | 46 | | [help](#help) | 输出命令的帮助信息。 | 47 | 48 | **Global Options:** 49 | 50 | - `-V, --version`:输出版本号 51 | - `--env-id `:设置环境 ID 52 | - `-h, --help`:输出帮助信息 53 | 54 | ## Commands 55 | 56 | ### login 57 | 58 | 登录知晓云 59 | 60 | ```bash 61 | mincloudx login [options] [clientId] 62 | ``` 63 | 64 | **Parameter:** 65 | 66 | - `clientSecret`: 知晓云应用的密钥。 67 | - `clientId`: 知晓云应用的 clint_id,默认从 rc 文件中读取。 68 | 69 | **Example:** 70 | 71 | ```bash 72 | mincloudx login clientSecret clientId 73 | ``` 74 | 75 | 当 `mincloudx` 的命令中需要与知晓云应用交互时将优先读取 `.mincloudxrc` 配置文件中的 `client_id`。若项目目录或本地缓存中没有读取到,将会从知晓云官方提供的 `.mincloudrc` 中的 `client_id` 环境变量。 76 | 77 | 因此,若你不希望在项目中创建太多 `rc` 配置文件,也可以直接使用 `.mincloudrc` 配置,`mincloudx` 不会污染 `.mincloudrc` 的配置信息。 78 | 79 | ### type 80 | 81 | `type` 命令用于将知晓云数据表转换为 TypeScript 的 `.d.ts` 类型文件。 82 | 83 | ```bash 84 | mincloudx type [options] 85 | ``` 86 | 87 | **选项**: 88 | 89 | | 选项 | 描述 | 默认值 | 90 | | ----------------- | ------------------------------------------- | ------------------ | 91 | | `--pull` | 读取线上的知晓云数据表信息来转换类型文件 | `false` | 92 | | `-f, --transform` | 解析本地的 JSON 数据表文件来转换 TypeScript | `"./_schema.json"` | 93 | | `--output-path` | 类型文件的输出目录 | `"./typings"` | 94 | | `--output-file` | 类型文件的文件名 | `"schema"` | 95 | 96 | --- 97 | 98 | **转换方式**: 99 | 100 | **在线转换**: 101 | 102 | 登录知晓云账号后,直接读取线上最新的数据表记录来转换。 103 | 104 | ```bash 105 | mincloudx type --pull 106 | ``` 107 | 108 | **本地转换**: 109 | 110 | 若顾虑应用密匙泄露的安全性等因素也可以直接读取本地的 schema JSON 文件来转换。 111 | 112 | 方法:进入知晓云控制面板,打开浏览器开发者工具,在网络面板找到 `dserve/v1.8/schema/?offset=0& 113 | limit=200` 请求,并将 `JSON` 保存为 `_schema.json` 文件,放在与 `package.json` 同级目录中。 114 | 115 | ```bash 116 | mincloudx type --transform ./_schema.json 117 | ``` 118 | 119 | **注意**: 120 | 121 | 生成的类型文件可能会引用知晓云官方的全局命名空间。在使用前,请确保将 `minapp-sdk-typings` 添加到 `tsconfig.json` 的 `compilerOptions.types` 中。 122 | 123 | ### faas 124 | 125 | `faas` 命令为云函数环境下提供相应的帮助。 126 | 127 | 目前常规的云函数的项目结构如下: 128 | 129 | ```bash 130 | . 131 | ├── package.json 132 | ├── src 133 | │ ├── config // 项目常量或配置项 134 | │ │ └── index.js 135 | │ └── function // 云函数源码文件 136 | │ ├── updateProduct.ts // 云函数 A 137 | │ └── user // 云函数分类 138 | │ └── createUser.js // 云函数 B 139 | └── ... 140 | ``` 141 | 142 | `faas` 命令将按照项目结构的约束对项目中常见的操作做封装。 143 | 144 | #### build 145 | 146 | 构建云函数源码。`faas build` 将通过 webpack 对源码进行打包压缩。 147 | 148 | 构建全部云函数源码: 149 | 150 | ```bash 151 | # 默认打包 ./src/function 目录下云函数文件,默认输出到 ./dist 目录下 152 | mincloudx faas build 153 | ``` 154 | 155 | 单独构建云函数: 156 | 157 | ```bash 158 | # 只构建一个云函数,它会从云函数目录中递归查找是否存在对应的云函数 159 | mincloudx faas build createUser 160 | ``` 161 | 162 | 修改源码或构建目录的默认值: 163 | 164 | ```bash 165 | mincloudx faas build --entry-path ./src -o ./dist 166 | ``` 167 | 168 | #### upload 169 | 170 | 上传与云函数,默认从 `./dist` 目录读取文件。 171 | 172 | 上传已构建的全部云函数: 173 | 174 | ```bash 175 | mincloudx faas upload 176 | ``` 177 | 178 | 上传指定云函数: 179 | 180 | ```bash 181 | mincloudx faas upload createUser 182 | ``` 183 | 184 | 指定目录: 185 | 186 | ```bash 187 | mincloudx faas upload createUser --built-dir ./dist-ts 188 | ``` 189 | 190 | #### deploy 191 | 192 | 构建并上传云函数,相当于先后执行 `faas build` 和 `faas upload` 193 | 194 | `faas deploy` 默认从 `./dist` 目录中部署全部云函数文件: 195 | 196 | ```bash 197 | mincloudx faas deploy 198 | ``` 199 | 200 | 单独部署云函数: 201 | 202 | ```bash 203 | mincloudx faas deploy createUser 204 | ``` 205 | 206 | 默认情况下,云函数编译后的代码都会放在 `./dist` 目录下,若需要修改部署目录: 207 | 208 | ```bash 209 | mincloudx faas deploy --deploy-dir ./dist-test 210 | ``` 211 | 212 | #### mock 213 | 214 | 通过本地 mock 文件调用云函数。 215 | 216 | 项目默认的从根目录中的 `mock/` 文件夹中读取与云函数同名的 Mock 文件。Mock 文件可以导出一个对象或可执行函数,导出时通过 `module.exports` 导出。 217 | 218 | 当调用 `faas mock` 命令时,将会读取导出的数据或执行函数的结果传递给云函数执行,若本地不存在 Mock 文件则默认传入 `{}` 调用。 219 | 220 | ```bash 221 | mincloudx faas mock createUser 222 | ``` 223 | 224 | 修改默认 Mock 目录: 225 | 226 | ```bash 227 | mincloudx faas mock createUser --dir ./mocks 228 | ``` 229 | 230 | 修改默认日志目录: 231 | 232 | ```bash 233 | mincloudx faas mock createUser --out ./logs 234 | ``` 235 | 236 | #### debug 237 | 238 | 调试云函数,会将源码中的指定云函数进行构建上传并使用 mock 本地 mock 数据进行调试。 239 | 240 | 选择一个云函数: 241 | 242 | ```bash 243 | mincloudx faas debug 244 | ``` 245 | 246 | 指定云函数: 247 | 248 | ```bash 249 | mincloudx faas debug createUser 250 | ``` 251 | 252 | 修改默认目录: 253 | 254 | ```bash 255 | mincloudx faas debug createUser --entry-dir ./src --built-dir ./build --mock-dir ./mocks 256 | ``` 257 | 258 | ### help 259 | 260 | 输出命令的帮助信息。 261 | 262 | **Parameter:** 263 | 264 | - `command`: 要输出帮助信息的命令名称 265 | 266 | **Example:** 267 | 268 | ```bash 269 | # 查看 type 命令的使用方式 270 | mincloudx help type 271 | ``` 272 | 273 | ## Development 274 | 275 | 运行以下命令进行开发: 276 | 277 | ```shell 278 | # 监听项目中的文件变化 279 | pnpm watch 280 | 281 | # 执行本地编译后的 cli 文件 282 | pnpm test 283 | ``` 284 | 285 | 项目初始化使用 `pnpm install` 或 `pnpm` 安装依赖时会自动将 bin 安装到 node_modules 中。 286 | 287 | 若在开发过程中修改了 bin 名称,可在对应 package 中先通过 `pnpm unlink` 取消关联,再通过 `pnpm link` 重新关联。 288 | -------------------------------------------------------------------------------- /packages/cli/bin/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../lib'); 4 | -------------------------------------------------------------------------------- /packages/cli/global.d.ts: -------------------------------------------------------------------------------- 1 | import type { CookieJar } from 'tough-cookie'; 2 | 3 | declare module 'axios' { 4 | interface AxiosRequestConfig { 5 | jar?: CookieJar; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/cli", 3 | "version": "0.4.2", 4 | "description": "A command-line tool based on the MinCloud ecosystem, designed to offer a simple and quick way to help developers efficiently manage MinCloud-related tasks.", 5 | "author": "anran758 ", 6 | "homepage": "https://github.com/anran758/mincloudx/tree/main/packages/cli#readme", 7 | "license": "MIT", 8 | "main": "lib/index.js", 9 | "type": "commonjs", 10 | "publishConfig": { 11 | "access": "public" 12 | }, 13 | "keywords": [ 14 | "mincloudx", 15 | "mincloud", 16 | "typescript", 17 | "faas", 18 | "cli" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/anran758/mincloudx.git", 23 | "directory": "packages/cli" 24 | }, 25 | "scripts": { 26 | "prepublishOnly": "pnpm run build", 27 | "build": "webpack --node-env=production", 28 | "watch": "webpack --watch", 29 | "test": "mincloudx" 30 | }, 31 | "bin": { 32 | "mincloudx": "./bin/cli.js" 33 | }, 34 | "files": [ 35 | "bin", 36 | "lib" 37 | ], 38 | "bugs": { 39 | "url": "https://github.com/anran758/mincloudx/issues" 40 | }, 41 | "peerDependencies": { 42 | "minapp-sdk-typings": "^3.1.0" 43 | }, 44 | "devDependencies": { 45 | "@types/ini": "^1.3.31", 46 | "@types/lodash": "^4.14.202", 47 | "@types/mkdirp": "^1.0.2", 48 | "@types/osenv": "^0.1.1", 49 | "@types/rc": "^1.2.1", 50 | "@types/tough-cookie": "^4.0.2", 51 | "@types/webpack-env": "^1.18.4", 52 | "minapp-sdk-typings": "^3.1.0", 53 | "terser-webpack-plugin": "^5.3.10", 54 | "ts-loader": "^9.5.1", 55 | "webpack-cli": "^5.1.4", 56 | "webpack-node-externals": "^3.0.0" 57 | }, 58 | "dependencies": { 59 | "@inquirer/prompts": "^4.1.0", 60 | "axios": "^1.3.4", 61 | "axios-cookiejar-support": "^4.0.6", 62 | "chalk": "^4.1.2", 63 | "commander": "^9.4.1", 64 | "copy-webpack-plugin": "^12.0.2", 65 | "form-data": "^4.0.0", 66 | "import-fresh": "^3.3.0", 67 | "ini": "^3.0.1", 68 | "inquirer-autocomplete-standalone": "^0.8.1", 69 | "lodash": "^4.17.21", 70 | "mkdirp": "^1.0.4", 71 | "npmlog": "^7.0.1", 72 | "osenv": "^0.1.5", 73 | "rc": "^1.2.8", 74 | "tough-cookie": "^4.1.2", 75 | "webpack": "^5.90.3", 76 | "webpack-merge": "^5.10.0" 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /packages/cli/src/assist/type.template.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | /* eslint-disable no-use-before-define */ 3 | 4 | export type SchemaId = string | number; 5 | 6 | /** 7 | * Fields ending in "_at" are conventionally designated as timestamp fields. 8 | **/ 9 | export type EpochSeconds = number & { seconds_since_the_unix_start: never }; 10 | export type JSONString = string & { json_parsable_string: never }; 11 | export type HTMLText = string & { html_content: never }; 12 | export type ValueOf = T[keyof T]; 13 | export type KeyOf = Array; 14 | export type Default = T; 15 | 16 | export interface BaseTable { 17 | _id: SchemaId; 18 | id: SchemaId; 19 | created_at: number; 20 | updated_at: number; 21 | created_by: CreatedBy; 22 | read_perm: string[]; 23 | write_perm: string[]; 24 | } 25 | 26 | interface UserProfile extends BaseTable {} 27 | 28 | export interface PointerWithoutData { 29 | id: SchemaId; 30 | _table: string; 31 | } 32 | 33 | export type SchemaPointer = T | PointerWithoutData; 34 | 35 | export type CreatedBy = UserProfile | PointerWithoutData | number; 36 | 37 | /** 38 | * MinCloud File operation result 39 | */ 40 | export interface FileOperationResult { 41 | /** 42 | * Record ID 43 | */ 44 | _id: string; 45 | /** 46 | * created time (in Unix timestamp format) 47 | */ 48 | created_at: number; 49 | /** 50 | * Path 51 | */ 52 | path: string; 53 | /** 54 | * created record user ID 55 | */ 56 | created_by: number; 57 | /** 58 | * Mime type 59 | */ 60 | mime_type: string; 61 | /** 62 | * Media type 63 | */ 64 | media_type: string; 65 | /** 66 | * File size 67 | */ 68 | size: number; 69 | /** 70 | * File name 71 | */ 72 | name: string; 73 | /** 74 | * File status 75 | */ 76 | status: string; 77 | /** 78 | * Reference 79 | */ 80 | reference: string; 81 | /** 82 | * CDN path 83 | */ 84 | cdn_path: string; 85 | /** 86 | * Integer. Updated time (in Unix timestamp format) 87 | */ 88 | updated_at: number; 89 | /** 90 | * File categories 91 | */ 92 | categories: string[]; 93 | } 94 | -------------------------------------------------------------------------------- /packages/cli/src/commands/faas/build.ts: -------------------------------------------------------------------------------- 1 | import webpack from 'webpack'; 2 | import { merge } from 'webpack-merge'; 3 | import chalk from 'chalk'; 4 | 5 | import type { Command } from 'commander'; 6 | 7 | import { 8 | createLogger, 9 | resolveCwdAbsolutePath, 10 | scanForFunctionEntries, 11 | } from '@/utils'; 12 | import { DEFAULT_FUNCTION_DIR, DEFAULT_BUILT_DIR } from './config'; 13 | 14 | import baseConf from './webpack.base.config'; 15 | 16 | const COMMAND_NAME = 'build'; 17 | const logger = createLogger(COMMAND_NAME); 18 | 19 | const defaultConfig = { 20 | entryDir: DEFAULT_FUNCTION_DIR, 21 | outputDir: DEFAULT_BUILT_DIR, 22 | }; 23 | 24 | type BuildFaasParams = typeof defaultConfig & { 25 | functionName?: string; 26 | }; 27 | 28 | export function buildFunction({ 29 | entryDir, 30 | outputDir, 31 | functionName, 32 | }: BuildFaasParams = defaultConfig) { 33 | return new Promise((resolve, reject) => { 34 | const folderPath = resolveCwdAbsolutePath(entryDir); 35 | 36 | logger.log( 37 | COMMAND_NAME, 38 | `Preparing to collect cloud function source code from ${folderPath} ...`, 39 | ); 40 | 41 | const pickFiles = functionName ? [functionName] : []; 42 | const entry = scanForFunctionEntries(folderPath, { pick: pickFiles }); 43 | 44 | if (!Object.keys(entry).length && functionName) { 45 | logger.error( 46 | COMMAND_NAME, 47 | `Failed to build cloud function. Please ensure the ${chalk.bold( 48 | functionName, 49 | )} are in the entry directory.`, 50 | ); 51 | return; 52 | } 53 | 54 | const currentConf = { 55 | entry, 56 | output: { 57 | path: resolveCwdAbsolutePath(outputDir), 58 | }, 59 | }; 60 | 61 | // 后续可以考虑 merge 用户提供的 config 62 | const conf = merge(baseConf, currentConf); 63 | const compiler = webpack(conf); 64 | 65 | compiler.run((err, stats) => { 66 | // 处理构建过程中的错误 67 | if (err) { 68 | logger.error(COMMAND_NAME, '构建时发生错误:', err); 69 | reject(err); 70 | return; 71 | } 72 | 73 | // 处理编译过程中的错误 74 | if (stats?.hasErrors?.()) { 75 | logger.error(COMMAND_NAME, '构建时遇到错误:'); 76 | logger.error(COMMAND_NAME, stats.toString({ colors: true })); 77 | reject(stats); 78 | return; 79 | } 80 | 81 | // 构建成功 82 | logger.info(COMMAND_NAME, stats?.toString?.({ colors: true })); 83 | console.log(''); 84 | 85 | logger.success( 86 | COMMAND_NAME, 87 | 'CloudFunction build completed:', 88 | conf.output?.path, 89 | ); 90 | resolve('ok'); 91 | }); 92 | }); 93 | } 94 | 95 | /** 96 | * Build cloud function from source code. 97 | * 98 | * @example 99 | * Build all cloud functions using default directories: 100 | * ``` 101 | * mincloudx faas build 102 | * ``` 103 | * 104 | * @example 105 | * Build a specific cloud function named "createUser": 106 | * ``` 107 | * mincloudx faas build createUser 108 | * ``` 109 | * 110 | * @example 111 | * Build cloud functions specifying custom source and output directories: 112 | * ``` 113 | * mincloudx faas build --entry-dir ./src/functions --output-dir ./built 114 | * ``` 115 | */ 116 | export function registerCommand(program: Command) { 117 | return program 118 | .command('build') 119 | .description('Build cloud function from source code.') 120 | .argument('[functionName]', 'Cloud function name.') 121 | .option( 122 | '--entry-dir ', 123 | 'Cloud function source code directory', 124 | defaultConfig.entryDir, 125 | ) 126 | .option( 127 | '-o, --output-dir ', 128 | 'Cloud function built file output directory', 129 | defaultConfig.outputDir, 130 | ) 131 | .action((functionName, options: BuildFaasParams) => { 132 | if (functionName) { 133 | logger.log(COMMAND_NAME, `Cloud function name: ${functionName}`); 134 | } 135 | 136 | buildFunction({ ...options, functionName }); 137 | }); 138 | } 139 | -------------------------------------------------------------------------------- /packages/cli/src/commands/faas/config.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_MOCK_DIR = './mock'; 2 | 3 | export const DEFAULT_LOG_DIR = './log'; 4 | 5 | export const DEFAULT_BUILT_DIR = './dist'; 6 | 7 | /** 8 | * cloud function dir 9 | */ 10 | export const DEFAULT_FUNCTION_DIR = './src/function'; 11 | -------------------------------------------------------------------------------- /packages/cli/src/commands/faas/debug.ts: -------------------------------------------------------------------------------- 1 | import type { Command } from 'commander'; 2 | 3 | import { createLogger, selectCloudFunction } from '@/utils'; 4 | import { deployFunction } from './deploy'; 5 | import { invokeMockData } from './mock'; 6 | import { 7 | DEFAULT_FUNCTION_DIR, 8 | DEFAULT_BUILT_DIR, 9 | DEFAULT_LOG_DIR, 10 | DEFAULT_MOCK_DIR, 11 | } from './config'; 12 | 13 | const COMMAND_NAME = 'debug'; 14 | const logger = createLogger(COMMAND_NAME); 15 | 16 | const defaultConfig = { 17 | entryDir: DEFAULT_FUNCTION_DIR, 18 | builtDir: DEFAULT_BUILT_DIR, 19 | outputDir: DEFAULT_LOG_DIR, 20 | mockDir: DEFAULT_MOCK_DIR, 21 | }; 22 | 23 | type BuildFaasParams = typeof defaultConfig & { 24 | /** 25 | * 云函数名 26 | */ 27 | functionName?: string; 28 | }; 29 | 30 | async function debugFunction({ 31 | functionName, 32 | entryDir, 33 | builtDir, 34 | mockDir, 35 | outputDir, 36 | }: Required) { 37 | // Deploy the selected or provided cloud function with specified directories for entry and build. 38 | await deployFunction({ 39 | functionName, 40 | entryDir, 41 | builtDir, 42 | }); 43 | 44 | // Invoke the cloud function with mock data, specifying the mock data directory and the output directory for logs. 45 | await invokeMockData({ 46 | functionName, 47 | dir: mockDir, 48 | output: outputDir, 49 | }); 50 | } 51 | 52 | /** 53 | * Debug a specify cloud function with options for custom directories. 54 | * 55 | * @example 56 | * select a cloud function to debug 57 | * ``` 58 | * mincloudx faas debug 59 | * ``` 60 | * 61 | * @example 62 | * Debug a cloud function by name: 63 | * ``` 64 | * mincloudx faas debug createUser 65 | * ``` 66 | * 67 | * @example 68 | * Debug with custom source and build directories: 69 | * ``` 70 | * mincloudx faas debug exampl e --entry-dir ./src --built-dir ./build 71 | * ``` 72 | * 73 | * @example 74 | * Debug with custom mock data directory: 75 | * ``` 76 | * mincloudx faas debug createUser --mock-dir ./mocks 77 | * ``` 78 | */ 79 | export function registerCommand(program: Command) { 80 | return program 81 | .command(COMMAND_NAME) 82 | .description('Debug a specify cloud function.') 83 | .argument('[functionName]', 'Cloud function name.') 84 | .option( 85 | '--entry-dir ', 86 | 'Cloud function source code directory', 87 | defaultConfig.entryDir, 88 | ) 89 | .option( 90 | '--built-dir ', 91 | 'Cloud function built file output directory', 92 | defaultConfig.builtDir, 93 | ) 94 | .option( 95 | '--output-dir ', 96 | 'log output directory', 97 | defaultConfig.outputDir, 98 | ) 99 | .option('--mock-dir ', 'mock data directory', defaultConfig.mockDir) 100 | .action(async (functionName, options: BuildFaasParams) => { 101 | logger.verbose('verbose', 'function name:', functionName); 102 | 103 | const { entryDir, builtDir, outputDir, mockDir } = options; 104 | let name = functionName || ''; 105 | 106 | // If the cloud function name is not provided, prompt the user to select one from the available functions. 107 | // This step utilizes a search feature for ease of use. 108 | if (name) { 109 | await debugFunction({ 110 | functionName, 111 | entryDir, 112 | builtDir, 113 | mockDir, 114 | outputDir, 115 | }); 116 | 117 | return; 118 | } 119 | 120 | // eslint-disable-next-line no-constant-condition 121 | while (true) { 122 | const answer = await selectCloudFunction(entryDir, { 123 | message: 'Select a cloud function to debug (supports search)', 124 | defaultValue: name, 125 | }); 126 | name = answer; 127 | 128 | await debugFunction({ 129 | functionName: name, 130 | entryDir, 131 | builtDir, 132 | mockDir, 133 | outputDir, 134 | }); 135 | } 136 | }); 137 | } 138 | -------------------------------------------------------------------------------- /packages/cli/src/commands/faas/deploy.ts: -------------------------------------------------------------------------------- 1 | import type { Command } from 'commander'; 2 | 3 | import { createLogger } from '@/utils'; 4 | 5 | import { buildFunction } from './build'; 6 | import { uploadFunction } from './upload'; 7 | import { DEFAULT_FUNCTION_DIR, DEFAULT_BUILT_DIR } from './config'; 8 | 9 | const COMMAND_NAME = 'deploy'; 10 | const logger = createLogger(COMMAND_NAME); 11 | const defaultConfig = { 12 | entryDir: DEFAULT_FUNCTION_DIR, 13 | builtDir: DEFAULT_BUILT_DIR, 14 | }; 15 | 16 | type BuildFaasParams = typeof defaultConfig & { 17 | /** 18 | * 云函数名 19 | */ 20 | functionName?: string; 21 | }; 22 | 23 | /** 24 | * Deploys cloud functions 25 | 26 | * 27 | * @example 28 | * Deploy all cloud functions using default directories for source and output: 29 | * ``` 30 | * mincloudx faas deploy 31 | * ``` 32 | * 33 | * @example 34 | * Deploy a specific cloud function named "createUser": 35 | * ``` 36 | * mincloudx faas deploy createUser 37 | * ``` 38 | * 39 | * @example 40 | * Deploy cloud functions specifying custom source and output directories: 41 | * ``` 42 | * mincloudx faas deploy --entry-dir ./src/functions --built-dir ./built 43 | * ``` 44 | **/ 45 | export async function deployFunction({ 46 | entryDir, 47 | builtDir, 48 | functionName, 49 | }: BuildFaasParams) { 50 | // It first builds the cloud function by compiling the source code 51 | // located in `entryDir` and outputs the built files to `builtDir`. 52 | await buildFunction({ 53 | functionName, 54 | entryDir, 55 | outputDir: builtDir, 56 | }); 57 | 58 | // After the build process is successfully completed, 59 | // it uploads the built cloud function to the cloud, 60 | // making it available for execution. 61 | await uploadFunction({ builtDir, functionName }); 62 | 63 | logger.success(COMMAND_NAME, 'cloud function deploy completed.'); 64 | } 65 | 66 | export function registerCommand(program: Command) { 67 | return program 68 | .command(COMMAND_NAME) 69 | .description('Deploy the built package of the cloud functions.') 70 | .argument('[functionName]', 'Cloud function name.') 71 | .option( 72 | '--entry-dir ', 73 | 'Cloud function source code directory', 74 | defaultConfig.entryDir, 75 | ) 76 | .option( 77 | '--built-dir ', 78 | 'Built directory (usually the directory after source code compilation).', 79 | defaultConfig.builtDir, 80 | ) 81 | .action(async (functionName, options: BuildFaasParams) => { 82 | const { entryDir, builtDir } = options; 83 | 84 | try { 85 | await deployFunction({ functionName, entryDir, builtDir }); 86 | } catch (error) { 87 | logger.error( 88 | COMMAND_NAME, 89 | error instanceof Error ? error.message : error, 90 | ); 91 | } 92 | }); 93 | } 94 | -------------------------------------------------------------------------------- /packages/cli/src/commands/faas/index.ts: -------------------------------------------------------------------------------- 1 | import type { Command } from 'commander'; 2 | 3 | import { registerCommand as registerBuildCommand } from './build'; 4 | import { registerCommand as registerUploadCommand } from './upload'; 5 | import { registerCommand as registerDeployCommand } from './deploy'; 6 | import { registerCommand as registerMockCommand } from './mock'; 7 | import { registerCommand as registerDebugCommand } from './debug'; 8 | 9 | export const DEFAULT_COMMAND_CONFIG = { 10 | build: false, 11 | }; 12 | 13 | export function registerCommand(program: Command) { 14 | const faasCommand = program.command('faas').description('云函数常用工具'); 15 | 16 | // 注册子命令 (或许可以尝试从自动化导入的方式来简化代码) 17 | const tasks = [ 18 | registerBuildCommand, 19 | registerUploadCommand, 20 | registerDeployCommand, 21 | registerMockCommand, 22 | registerDebugCommand, 23 | ]; 24 | tasks.forEach(task => task(faasCommand)); 25 | 26 | return faasCommand; 27 | } 28 | 29 | export default registerCommand; 30 | -------------------------------------------------------------------------------- /packages/cli/src/commands/faas/mock.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import chalk from 'chalk'; 4 | import importFresh from 'import-fresh'; 5 | import { isFunction, isPlainObject } from 'lodash'; 6 | import os from 'os'; 7 | 8 | import type { Command } from 'commander'; 9 | 10 | import { 11 | getBaseType, 12 | createLogger, 13 | resolveCwdAbsolutePath, 14 | writeFile, 15 | formatBytes, 16 | generatorLog, 17 | } from '@/utils'; 18 | import { invokeCloudFunction } from '@/request/api'; 19 | 20 | import { DEFAULT_MOCK_DIR, DEFAULT_LOG_DIR } from './config'; 21 | 22 | const COMMAND_NAME = 'mock'; 23 | const logger = createLogger(COMMAND_NAME); 24 | const defaultConfig = { 25 | dir: DEFAULT_MOCK_DIR, 26 | output: DEFAULT_LOG_DIR, 27 | }; 28 | 29 | type BuildFaasParams = typeof defaultConfig & { 30 | /** 31 | * 云函数名 32 | */ 33 | functionName: string; 34 | }; 35 | 36 | function formatResult(data) { 37 | const content: (string | string[])[] = [ 38 | `测试结果:${data.code ? '失败' : '成功'}`, 39 | ]; 40 | 41 | const result = [`返回结果:`]; 42 | if (data.code) { 43 | result.push( 44 | `错误类型:${data.error.type}`, 45 | `错误信息:${data.error.message}`, 46 | `错误堆栈:${data.error.stack}`, 47 | ); 48 | } else { 49 | if (isPlainObject(data.data)) { 50 | result.push(...JSON.stringify(data.data, null, 2).split('\n')); 51 | } else { 52 | result.push(data.data); 53 | } 54 | } 55 | content.push(result, ''); 56 | content.push( 57 | '摘要:', 58 | [ 59 | `任务 ID:${data.job_id}`, 60 | `运行时间:${data.execution_time} ms`, 61 | `计费时间:${data.billing_time} ms`, 62 | `占用内存:${formatBytes(data.mem_usage)}`, 63 | ], 64 | '', 65 | ); 66 | 67 | content.push('日志:', data.log.split('\n')); 68 | 69 | return generatorLog(content); 70 | } 71 | 72 | export async function invokeMockData({ 73 | functionName, 74 | ...options 75 | }: BuildFaasParams) { 76 | if (!functionName) { 77 | const message = 'Please input cloud function name!'; 78 | logger.error(COMMAND_NAME, message); 79 | 80 | return Promise.reject(new Error(message)); 81 | } 82 | 83 | const folderPath = resolveCwdAbsolutePath(options.dir); 84 | const mockPath = path.resolve(folderPath, `${functionName}.js`); 85 | 86 | logger.verbose(COMMAND_NAME, 'mockPath:', mockPath); 87 | 88 | let data = {}; 89 | 90 | // check mock file exists 91 | if (!fs.existsSync(mockPath)) { 92 | logger.notice(COMMAND_NAME, `${mockPath} mock file not found.`); 93 | logger.notice( 94 | COMMAND_NAME, 95 | 'This call will use default value `{}` to invoke cloud function.', 96 | ); 97 | } else { 98 | // Due to the current inability of import() to handle cases with dynamic variables, we are temporarily compromising by using require to import. 99 | logger.notice(COMMAND_NAME, `prepare invoke ${mockPath} mock file.`); 100 | const content: Record | typeof Function = 101 | importFresh(mockPath); 102 | 103 | if (isFunction(content)) { 104 | data = content(); 105 | } else if (isPlainObject(content)) { 106 | data = content; 107 | } else { 108 | logger.error( 109 | COMMAND_NAME, 110 | `${chalk.bold(functionName)} mock file module exports type warning!`, 111 | `Expected export an object or function, but got ${getBaseType(data)}.`, 112 | ); 113 | 114 | return; 115 | } 116 | } 117 | 118 | try { 119 | const response = await invokeCloudFunction({ name: functionName, data }); 120 | 121 | const content = formatResult(response.data); 122 | const dir = resolveCwdAbsolutePath(options.output); 123 | const fileName = `${functionName}.log`; 124 | const result = await writeFile({ 125 | fileName, 126 | dirPath: dir, 127 | content, 128 | }); 129 | logger.success( 130 | COMMAND_NAME, 131 | 'Invoke result log saved to:', 132 | path.join(dir, fileName), 133 | ); 134 | 135 | return result; 136 | } catch (error) { 137 | let errorStr = error; 138 | if (error instanceof Error) { 139 | errorStr = error.message; 140 | } else if (typeof error !== 'string') { 141 | errorStr = JSON.stringify(error); 142 | } 143 | 144 | const errorPath = path.join( 145 | resolveCwdAbsolutePath(options.output), 146 | 'error.log', 147 | ); 148 | const errorLog = `[${new Date()}] ${errorStr} ${os.EOL}`; 149 | fs.appendFile(errorPath, errorLog, function (err) { 150 | if (err) throw err; 151 | logger.error( 152 | COMMAND_NAME, 153 | 'Invoke cloud function error.', 154 | `Log saved to: ${errorPath}`, 155 | ); 156 | }); 157 | } 158 | } 159 | 160 | /** 161 | * Invoke cloud function with mock data 162 | * 163 | * @example 164 | * Invoke the "createUser" cloud function without specifying a mock directory: 165 | * ``` 166 | * mincloudx faas mock createUser 167 | * ``` 168 | * 169 | * @example 170 | * Invoke the "createUser" cloud function with mock data from a specific directory: 171 | * ``` 172 | * mincloudx faas mock createUser --dir ./mocks 173 | * ``` 174 | * 175 | * @example 176 | * Invoke the "createUser" cloud function and specify a directory for the output logs: 177 | * ``` 178 | * mincloudx faas mock createUser --out ./logs 179 | * ``` 180 | */ 181 | export function registerCommand(program: Command) { 182 | return program 183 | .command(COMMAND_NAME) 184 | .description('Invoke cloud function with mock data') 185 | .argument('', 'Cloud function name.') 186 | .option('-d, --dir ', 'mock data directory', defaultConfig.dir) 187 | .option( 188 | '-o, --output ', 189 | 'specify the log directory for output', 190 | defaultConfig.output, 191 | ) 192 | .action((functionName: string, options: BuildFaasParams) => { 193 | return invokeMockData({ ...options, functionName }); 194 | }); 195 | } 196 | -------------------------------------------------------------------------------- /packages/cli/src/commands/faas/upload.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import chalk from 'chalk'; 4 | import { AxiosError } from 'axios'; 5 | import { readFile } from 'fs/promises'; 6 | 7 | import type { Command } from 'commander'; 8 | 9 | import { createLogger, resolveCwdAbsolutePath } from '@/utils'; 10 | import { createCloudFunction, updateCloudFunction } from '@/request/api'; 11 | import { DEFAULT_BUILT_DIR } from './config'; 12 | 13 | const COMMAND_NAME = 'upload'; 14 | const logger = createLogger(COMMAND_NAME); 15 | const defaultConfig = { 16 | builtDir: DEFAULT_BUILT_DIR, 17 | }; 18 | 19 | type BuildFaasParams = typeof defaultConfig & { 20 | /** 21 | * 云函数名 22 | */ 23 | functionName?: string; 24 | }; 25 | 26 | async function uploadFile({ 27 | dir, 28 | functionName, 29 | }: { 30 | dir: string; 31 | functionName: string; 32 | }) { 33 | const filePath = path.resolve(dir, `${functionName}.js`); 34 | if (!fs.existsSync(filePath)) { 35 | throw new Error( 36 | `"${functionName}" does not exist, please check if the corresponding file exists in the deployment directory.\n` + 37 | filePath, 38 | ); 39 | } 40 | 41 | const content = await readFile(filePath); 42 | 43 | try { 44 | await updateCloudFunction({ 45 | name: functionName, 46 | content: content.toString(), 47 | }); 48 | 49 | logger.success( 50 | COMMAND_NAME, 51 | `"${chalk.bold.blue(functionName)}" uploaded successfully.`, 52 | ); 53 | } catch (error) { 54 | if (error instanceof AxiosError) { 55 | const { status, statusText } = error.response || {}; 56 | logger.verbose( 57 | COMMAND_NAME, 58 | `Update of cloud function failed. HTTP status: ${status}, statusText: ${statusText}.`, 59 | ); 60 | 61 | if (status === 404) { 62 | logger.info( 63 | COMMAND_NAME, 64 | `Trying to create new cloud function "${functionName}".`, 65 | ); 66 | 67 | await createCloudFunction({ 68 | name: functionName, 69 | content: content.toString(), 70 | }).catch((err: AxiosError) => { 71 | const message = `"${chalk.bold.blue( 72 | functionName, 73 | )}" create failed, see details: ${err.message}`; 74 | logger.HTTP( 75 | COMMAND_NAME, 76 | `Create of cloud function failed. HTTP status: ${err.response?.status}, statusText: ${err.response?.statusText}.`, 77 | ); 78 | 79 | throw new Error(message); 80 | }); 81 | 82 | logger.info( 83 | COMMAND_NAME, 84 | `"${chalk.bold.blue(functionName)}" created successfully.`, 85 | ); 86 | } 87 | } else { 88 | logger.verbose( 89 | COMMAND_NAME, 90 | `update cloud function error, see details:`, 91 | error, 92 | ); 93 | } 94 | } 95 | } 96 | 97 | export async function uploadFunction({ 98 | builtDir, 99 | functionName, 100 | }: BuildFaasParams = defaultConfig) { 101 | const folderPath = resolveCwdAbsolutePath(builtDir); 102 | logger.log(COMMAND_NAME, `Deployment directory: ${folderPath}`); 103 | 104 | if (functionName) { 105 | logger.log(COMMAND_NAME, `Cloud Function:`, chalk.bold.blue(functionName)); 106 | const result = await uploadFile({ dir: folderPath, functionName }); 107 | 108 | return result; 109 | } else { 110 | logger.log( 111 | COMMAND_NAME, 112 | `Preparing to deploy`, 113 | chalk.bold('all cloud functions'), 114 | `from the directory...\n`, 115 | ); 116 | 117 | const extension = '.js'; 118 | const files = fs 119 | .readdirSync(folderPath) 120 | .filter(file => path.extname(file) === extension); 121 | 122 | return Promise.all( 123 | files.map(file => { 124 | const functionName = path.basename(file, extension); 125 | 126 | return uploadFile({ dir: folderPath, functionName }); 127 | }), 128 | ); 129 | } 130 | } 131 | 132 | /** 133 | * Uploads the built cloud function to the cloud environment. 134 | * 135 | * @example 136 | * Upload all cloud functions from the default build directory (`./dist`): 137 | * 138 | * ```bash 139 | * mincloudx faas upload 140 | * ``` 141 | * 142 | * @example 143 | * Upload a specific cloud function named "example" from the default build directory: 144 | * 145 | * ```bash 146 | * mincloudx faas upload createUser 147 | * ``` 148 | * 149 | * @example 150 | * Upload a specific cloud function named "example" from a custom build directory (`./dist-ts`): 151 | * 152 | * ```bash 153 | * mincloudx faas upload createUser --built-dir ./dist-ts 154 | * ``` 155 | */ 156 | export function registerCommand(program: Command) { 157 | return program 158 | .command(COMMAND_NAME) 159 | .description('Upload the built package of the cloud functions.') 160 | .argument('[functionName]', 'Cloud function name.') 161 | .option( 162 | '--built-dir ', 163 | 'Built directory (usually the directory after source code compilation).', 164 | defaultConfig.builtDir, 165 | ) 166 | .action(async (functionName, options: BuildFaasParams) => { 167 | try { 168 | await uploadFunction({ 169 | builtDir: options.builtDir, 170 | functionName, 171 | }); 172 | } catch (error) { 173 | logger.error( 174 | COMMAND_NAME, 175 | error instanceof Error ? error.message : error, 176 | ); 177 | } 178 | }); 179 | } 180 | -------------------------------------------------------------------------------- /packages/cli/src/commands/faas/webpack.base.config.ts: -------------------------------------------------------------------------------- 1 | import TerserPlugin from 'terser-webpack-plugin'; 2 | import { optimize } from 'webpack'; 3 | import type { Configuration } from 'webpack'; 4 | 5 | import { resolveCwdAbsolutePath } from '@/utils'; 6 | 7 | /** 8 | * @desc 针对云函数环境的基础构建配置 9 | */ 10 | const webpackConf: Configuration = { 11 | mode: 'production', 12 | output: { 13 | filename: '[name].js', 14 | clean: true, 15 | library: { 16 | name: 'exports.main', 17 | export: 'default', 18 | type: 'assign', 19 | }, 20 | }, 21 | target: 'node', 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.((j|t)s)$/, 26 | // using `resolve` to ensure the correct resolution path for 'ts-loader' 27 | // There are differences between Node.js `require` and webpack's `require`. 28 | // https://webpack.js.org/api/module-variables/#__non_webpack_require__-webpack-specific 29 | use: () => { 30 | /** 31 | * To avoid affecting the entire package usage due to `ts-loader not being installed in the user's environment, 32 | * the use property needs to be modified to execute through a function. 33 | */ 34 | try { 35 | return __non_webpack_require__.resolve('ts-loader'); 36 | } catch (e) { 37 | console.error( 38 | 'ts-loader is required but not installed. Please run "npm install ts-loader" to install it.', 39 | ); 40 | throw e; 41 | } 42 | }, 43 | 44 | exclude: /node_modules/, 45 | }, 46 | ], 47 | }, 48 | externalsPresets: { 49 | node: true, 50 | }, 51 | resolve: { 52 | alias: { 53 | '@': resolveCwdAbsolutePath('src'), 54 | }, 55 | extensions: ['.ts', '.js'], 56 | fallback: { path: false }, 57 | }, 58 | optimization: { 59 | minimizer: [ 60 | new optimize.ModuleConcatenationPlugin(), 61 | new TerserPlugin({ 62 | extractComments: false, 63 | }), 64 | ], 65 | }, 66 | }; 67 | 68 | export default webpackConf; 69 | -------------------------------------------------------------------------------- /packages/cli/src/commands/index.ts: -------------------------------------------------------------------------------- 1 | import { program } from 'commander'; 2 | import log from 'npmlog'; 3 | 4 | import { getConfig, getToken } from '@/config'; 5 | import { packageInfo, APP_NAME } from '@/config/constant'; 6 | import { registerMinCloudHeaders } from '@/request'; 7 | import { initLogger } from '@/utils'; 8 | 9 | import registerCommandType from './type'; 10 | import registerCommandLogin from './login'; 11 | import registerCommandFaas from './faas'; 12 | 13 | // 设置基本信息 14 | 15 | export function registerCommand(argv = process.argv) { 16 | program 17 | .name(APP_NAME) 18 | .description(packageInfo.description) 19 | .version(packageInfo.version) 20 | .option('--env-id ', 'BaaS environment ID') 21 | .option('-v, --verbose', 'output extra debugging') 22 | .option('--log-level', 'output log level') 23 | .hook('preAction', (_, actionCommand) => { 24 | const globalOptions = program.opts(); 25 | const opts = actionCommand.opts(); 26 | const config = getConfig({ ...globalOptions, ...opts }); 27 | const { envId, verbose, logLevel } = globalOptions; 28 | 29 | // output MinCloud info 30 | log.info('app', `Client ID: ${config.client_id}`); 31 | if (envId) log.info('app', `Environment ID: ${envId}`); 32 | console.log(''); 33 | 34 | initLogger(logLevel || verbose ? 'verbose' : ''); 35 | 36 | // 知晓云请求需要附带对应的请求头 37 | registerMinCloudHeaders({ 38 | token: getToken(), 39 | envId, 40 | }); 41 | }); 42 | 43 | // 注册对应的 command 44 | registerCommandType(program); 45 | registerCommandLogin(program); 46 | registerCommandFaas(program); 47 | 48 | program.parse(argv); 49 | } 50 | -------------------------------------------------------------------------------- /packages/cli/src/commands/login/index.ts: -------------------------------------------------------------------------------- 1 | import log from 'npmlog'; 2 | import type { Command } from 'commander'; 3 | import { password } from '@inquirer/prompts'; 4 | 5 | import config from '@/config'; 6 | import { login } from '@/request'; 7 | import { output } from '@/utils'; 8 | 9 | const COMMAND_NAME = 'login'; 10 | 11 | /** 12 | * 注册 `login` 命令 13 | */ 14 | export function registerCommand(program: Command) { 15 | return program 16 | .command(COMMAND_NAME) 17 | .description('Log in to MinCloud for data access') 18 | .argument('[clientId]', 'Log in to MinCloud for data access') 19 | .action(async clientId => { 20 | try { 21 | const clientSecret = await password({ 22 | message: 'Please enter your app client secret:', 23 | }); 24 | 25 | const id = clientId || config.client_id; 26 | if (!id) { 27 | log.error( 28 | 'login', 29 | 'Client ID not found! please configure or pass the client ID!', 30 | ); 31 | } 32 | 33 | await login({ 34 | clientId: id, 35 | clientSecret: clientSecret, 36 | }); 37 | 38 | output('Login successful!'); 39 | } catch (error) { 40 | log.error( 41 | 'login', 42 | 'Login failed:', 43 | error instanceof Error ? error.message : error, 44 | ); 45 | } 46 | }); 47 | } 48 | 49 | export default registerCommand; 50 | -------------------------------------------------------------------------------- /packages/cli/src/commands/type/generator.ts: -------------------------------------------------------------------------------- 1 | import { readFile } from 'fs/promises'; 2 | import path from 'path'; 3 | 4 | import { 5 | FIELD_TYPE_MAP, 6 | TABLE_NAME_MAPPING, 7 | packageInfo, 8 | } from '@/config/constant'; 9 | import { 10 | getBaseType, 11 | pascalCase, 12 | parseCollectionName, 13 | writeFile, 14 | } from '@/utils'; 15 | 16 | import type { SchemaRootObject, SchemeObject, SchemaField } from './schema'; 17 | 18 | /** 19 | * Read the content of TypeScript template file in assist directory 20 | */ 21 | export async function getBaseContent() { 22 | const filePath = path.join(__dirname, './assist/type.template.ts'); 23 | const data = await readFile(filePath, 'utf8'); 24 | 25 | return data; 26 | } 27 | 28 | /** 29 | * get interface name 30 | * @description special internal data tables need to be read from mapping first 31 | */ 32 | export function getInterfaceName(name: string) { 33 | return TABLE_NAME_MAPPING[name] || pascalCase(name); 34 | } 35 | 36 | export function getFieldChoices(field: SchemaField): string[] { 37 | const rule = field.constraints?.rules?.find?.( 38 | rule => rule.type === 'choices', 39 | ); 40 | 41 | return rule?.value || []; 42 | } 43 | 44 | export function getFieldType(field: SchemaField): string { 45 | // 初始化类型字符串 46 | const defaultType = getFieldDefaultType(field); 47 | let fieldType = defaultType ? `${defaultType} | ` : ''; 48 | 49 | // 处理时间戳字段 50 | if (field.name.endsWith('_at')) { 51 | fieldType += 'EpochSeconds'; 52 | return fieldType; 53 | } 54 | 55 | // 根据字段类型处理 56 | switch (field.type) { 57 | case 'array': 58 | fieldType += getArrayFieldType(field); 59 | break; 60 | case 'reference': 61 | fieldType += getReferenceFieldType(field); 62 | break; 63 | case 'string': 64 | fieldType += getStringFieldType(field); 65 | break; 66 | default: 67 | fieldType += FIELD_TYPE_MAP[field.type] || field.type; 68 | } 69 | 70 | // 添加默认值修饰符 71 | return fieldType; 72 | } 73 | 74 | /** 75 | * 处理数组类型 76 | * @param {SchemaField} field 字段 77 | * @return {string} 78 | */ 79 | function getArrayFieldType(field: SchemaField): string { 80 | const itemType = field.items?.type || ''; 81 | return `${FIELD_TYPE_MAP[itemType] || itemType}[]`; 82 | } 83 | 84 | /** 85 | * 处理引用类型 86 | * @param {SchemaField} field 字段 87 | * @return {string} 88 | */ 89 | function getReferenceFieldType(field: SchemaField): string { 90 | const { schemaName } = parseCollectionName(field.collection_name); 91 | const name = getInterfaceName(schemaName); 92 | 93 | return `SchemaPointer<${name}>`; 94 | } 95 | 96 | /** 97 | * 处理字符串类型,考虑字段选择 98 | */ 99 | function getStringFieldType(field: SchemaField): string { 100 | const fieldChoices = getFieldChoices(field).map(val => `'${val}'`); 101 | fieldChoices.unshift('string'); 102 | 103 | return fieldChoices.join(' | '); 104 | } 105 | 106 | /** 107 | * get field default type 108 | */ 109 | function getFieldDefaultType(field: SchemaField): string { 110 | if (field.default) { 111 | const defaultValue = JSON.stringify(field.default).replace(/"/g, `'`); 112 | const formattedDefault = 113 | // eslint: use an empty object instead of `{}` 114 | defaultValue === '{}' ? 'Record' : defaultValue; 115 | return `Default<${formattedDefault}>`; 116 | } 117 | 118 | if (field?.constraints?.required) return ''; 119 | 120 | return `Default`; 121 | } 122 | 123 | /** 124 | * 根据 schema 信息生成对应的类型代码 125 | * @returns {Number} 126 | */ 127 | export function generateDeclaration(schema: SchemeObject) { 128 | if (!schema) return ''; 129 | 130 | const { name = '' } = schema; 131 | const schemaName = getInterfaceName(name); 132 | const content = schema.schema.fields 133 | .filter(field => { 134 | return !['id', 'created_at', 'updated_at', 'created_by'].includes( 135 | field.name, 136 | ); 137 | }) 138 | .map((field: SchemaField) => { 139 | return [ 140 | ` /**`, 141 | ` * ${field.description}`, 142 | ` **/`, 143 | ` ${field.name}: ${getFieldType(field)};`, 144 | ].join('\n'); 145 | }) 146 | .join('\n'); 147 | 148 | const tableDescription = schema.options?.description; 149 | return [ 150 | ``, 151 | `/**`, 152 | ` * 数据表: ${name}`, 153 | ` * @description${tableDescription ? ` ${tableDescription}` : ''}`, 154 | ` */`, 155 | `export interface ${schemaName} extends BaseTable {`, 156 | `${content}`, 157 | `}`, 158 | ].join('\n'); 159 | } 160 | 161 | /** 162 | * 写入 schema 至 .d.ts 类型文件中 163 | */ 164 | export async function writeSchemaFile( 165 | list: SchemeObject[], 166 | { outputDir, outputFile }: { outputDir: string; outputFile: string }, 167 | ) { 168 | // 转为文本 169 | const schemasText = list 170 | .sort((a, b) => { 171 | const aIsBuiltInSchema = a.name.startsWith('_'); 172 | const bIsBuiltInSchema = b.name.startsWith('_'); 173 | 174 | if (aIsBuiltInSchema && !bIsBuiltInSchema) { 175 | return -1; 176 | } else if (!aIsBuiltInSchema && bIsBuiltInSchema) { 177 | return 1; 178 | } else { 179 | return 0; 180 | } 181 | }) 182 | .map(schema => generateDeclaration(schema)) 183 | .join('\n'); 184 | 185 | // 基础类型文件 186 | const baseTypeStr = await getBaseContent(); 187 | const content = [ 188 | `/*`, 189 | ` * [tips]: This file is automatically generated by ${packageInfo.name}, please do not modify the file directly.`, 190 | ` */`, 191 | baseTypeStr + schemasText, 192 | ].join('\n'); 193 | 194 | return writeFile({ 195 | fileName: `${outputFile}.d.ts`, 196 | dirPath: outputDir, 197 | content: `${content}\n`, 198 | }); 199 | } 200 | 201 | export async function generatorSchemaFile({ 202 | input, 203 | outputDir, 204 | outputFile = `schema`, 205 | }: { 206 | input: string; 207 | outputDir: string; 208 | outputFile?: string; 209 | }) { 210 | let schemaData: SchemaRootObject | null = null; 211 | 212 | // 解析 JSON 213 | try { 214 | const data = await readFile(input); 215 | schemaData = JSON.parse(data.toString()); 216 | 217 | // 检查格式是否正确 218 | if (getBaseType(schemaData) !== 'object') { 219 | throw new Error('schema 文件 JSON 格式有误'); 220 | } 221 | } catch (error) { 222 | const err = '读取文件失败!请确认 JSON 格式是否正确'; 223 | console.error(err, error); 224 | throw new Error(err); 225 | } 226 | 227 | const schemas = schemaData!.objects; 228 | if (!schemas?.length) { 229 | console.log('schemas 文件中没有找到 objects 数组或数组为空,结束生成'); 230 | return; 231 | } 232 | 233 | return writeSchemaFile(schemas, { outputDir, outputFile }); 234 | } 235 | -------------------------------------------------------------------------------- /packages/cli/src/commands/type/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import type { Command } from 'commander'; 3 | 4 | import { createLogger } from '@/utils'; 5 | 6 | import { generatorSchemaFile } from './generator'; 7 | import { generatorSchemaFileFromRemote } from './list'; 8 | 9 | const COMMAND_NAME = 'type'; 10 | const logger = createLogger(COMMAND_NAME); 11 | 12 | export const DEFAULT_COMMAND_CONFIG = { 13 | transform: './_schema.json', 14 | outputDir: './types', 15 | outputFile: 'schema', 16 | pull: true, 17 | }; 18 | 19 | /** 20 | * register `type` command 21 | * 22 | * @example 23 | * 24 | * ``` 25 | * mincloudx type 26 | * ``` 27 | * 28 | * @example 29 | * 30 | * ``` 31 | * mincloudx type --pull 32 | * ``` 33 | * 34 | * @example 35 | * 36 | * ``` 37 | * mincloudx type --transform ./_schema.json 38 | * ``` 39 | * 40 | * @example 41 | * 42 | * ``` 43 | * mincloudx type --pull --output-dir ./dist --output-file index 44 | * ``` 45 | */ 46 | export function registerCommand(program: Command) { 47 | return program 48 | .command(COMMAND_NAME) 49 | .description('generate .d.ts type files for LeanCloud data tables') 50 | .option( 51 | '-p, --pull', 52 | 'pull MinCloud data tables from remote and generate type definitions.', 53 | DEFAULT_COMMAND_CONFIG.pull, 54 | ) 55 | .option( 56 | '-t, --transform ', 57 | 'transform local JSON data tables to TypeScript type definitions.', 58 | ) 59 | .option( 60 | '-o, --output-dir ', 61 | 'TypeScript type file output directory.', 62 | DEFAULT_COMMAND_CONFIG.outputDir, 63 | ) 64 | .option( 65 | '--output-file ', 66 | 'name of the type file.', 67 | DEFAULT_COMMAND_CONFIG.outputFile, 68 | ) 69 | 70 | .action(async (options: typeof DEFAULT_COMMAND_CONFIG) => { 71 | const cwd = process.cwd(); 72 | const outputConf = { 73 | outputDir: path.resolve(cwd, options.outputDir), 74 | outputFile: options.outputFile, 75 | }; 76 | 77 | try { 78 | if (options.pull) { 79 | logger.notice( 80 | COMMAND_NAME, 81 | 'preparing to fetch data table structure information from remote.', 82 | ); 83 | await generatorSchemaFileFromRemote(outputConf); 84 | } else { 85 | await generatorSchemaFile({ 86 | ...outputConf, 87 | input: path.resolve(cwd, options.transform), 88 | }); 89 | } 90 | } catch (error) { 91 | logger.error( 92 | COMMAND_NAME, 93 | error instanceof Error 94 | ? error.message 95 | : 'The generation of data table type files failed.', 96 | ); 97 | 98 | return; 99 | } 100 | 101 | logger.success( 102 | COMMAND_NAME, 103 | 'Generation of type file was successful. Saved at:', 104 | 105 | path.join(outputConf.outputDir, `${outputConf.outputFile}.d.ts`), 106 | ); 107 | }); 108 | } 109 | 110 | export default registerCommand; 111 | -------------------------------------------------------------------------------- /packages/cli/src/commands/type/list.ts: -------------------------------------------------------------------------------- 1 | import { getSchemaList } from '@/request/api/schema'; 2 | 3 | import { writeSchemaFile } from './generator'; 4 | 5 | export async function generatorSchemaFileFromRemote({ 6 | outputDir, 7 | outputFile = `schema`, 8 | }: { 9 | outputDir: string; 10 | outputFile?: string; 11 | }) { 12 | // 从知晓云中读取列表数据 13 | const response = await getSchemaList(); 14 | 15 | return writeSchemaFile(response.data.objects, { 16 | outputDir, 17 | outputFile, 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /packages/cli/src/commands/type/schema.d.ts: -------------------------------------------------------------------------------- 1 | // 知晓云数据表列表请求的返回值 2 | 3 | export interface Meta { 4 | limit: number; 5 | next?: any; 6 | offset: number; 7 | previous?: any; 8 | total_count: number; 9 | } 10 | 11 | export interface DefaultRowPerm { 12 | _read_perm: string[]; 13 | _write_perm: string[]; 14 | } 15 | 16 | export interface Option { 17 | description: string; 18 | reference_schemas: any[]; 19 | } 20 | 21 | export interface SchemaField { 22 | acl: { 23 | clientReadOnly: boolean; 24 | clientVisible: boolean; 25 | creatorVisible: boolean; 26 | }; 27 | constraints?: { 28 | required: boolean; 29 | rules: any[]; 30 | }; 31 | collection_name: string; 32 | items?: { type: string }; 33 | default: any; 34 | description: string; 35 | name: string; 36 | type: string; 37 | } 38 | 39 | export interface Schema { 40 | fields: SchemaField[]; 41 | } 42 | 43 | export interface SchemeObject { 44 | acl_gid?: any; 45 | acl_permission: number; 46 | created_at: number; 47 | default_row_perm: DefaultRowPerm; 48 | dserve_hidden_columns: any[]; 49 | id: number; 50 | is_protected: boolean; 51 | name: string; 52 | options: Option; 53 | protected_fields?: any; 54 | row_acl_gid?: any; 55 | row_acl_permission?: any; 56 | row_read_perm: string; 57 | row_write_perm: string; 58 | schema: Schema; 59 | status: string; 60 | updated_at: number; 61 | write_perm: string[]; 62 | } 63 | 64 | export interface SchemaRootObject { 65 | meta: Meta; 66 | objects: SchemeObject[]; 67 | } 68 | -------------------------------------------------------------------------------- /packages/cli/src/config/api.ts: -------------------------------------------------------------------------------- 1 | export const ERROR_MESSAGE = { 2 | '401': '登录凭证已过期,请重新登录。', 3 | '403': '权限不足。', 4 | '404': '请求的资源不存在。', 5 | }; 6 | 7 | export const API_URL_MAPPING = { 8 | AUTHORIZE: '/api/oauth2/hydrogen/openapi/authorize/', 9 | ACCESS_TOKEN: '/api/oauth2/access_token/', 10 | TABLE: '/oserve/v1.8/table/', 11 | CLOUD_FUNCTION: '/oserve/v1.3/cloud-function/', 12 | CLOUD_FUNCTION_DEBUG: '/oserve/v1.3/cloud-function/{name}/debug/', 13 | }; 14 | -------------------------------------------------------------------------------- /packages/cli/src/config/constant.ts: -------------------------------------------------------------------------------- 1 | import * as packageInfo from '../../package.json'; 2 | 3 | export const APP_NAME = 'mincloudx'; 4 | export const MIN_CLOUD_KEY = 'mincloud'; 5 | 6 | /** 7 | * 默认表映射 8 | */ 9 | export const TABLE_NAME_MAPPING = { 10 | _userprofile: 'UserProfile', 11 | _richtextcontent: 'RichTextContent', 12 | }; 13 | 14 | export const FIELD_TYPE_MAP = { 15 | integer: 'number', 16 | file: 'FileOperationResult', 17 | object: 'Record', 18 | }; 19 | 20 | export { packageInfo }; 21 | -------------------------------------------------------------------------------- /packages/cli/src/config/index.ts: -------------------------------------------------------------------------------- 1 | import rc from 'rc'; 2 | import osenv from 'osenv'; 3 | import fs from 'fs'; 4 | import { writeFile } from 'fs/promises'; 5 | import path from 'path'; 6 | import ini from 'ini'; 7 | 8 | import { APP_NAME, MIN_CLOUD_KEY } from './constant'; 9 | import type { Config } from './type.d'; 10 | import { decodeTokens } from '../utils/token'; 11 | import { checkPathExists } from '@/utils'; 12 | 13 | type Mapping = Record; 14 | 15 | const IGNORE_CONFIG_KEYS = ['_', 'configs', 'config']; 16 | 17 | /** 18 | * 默认配置 19 | * 20 | * @description 项目全局配置,键名采用下划线命名法。可通过 .${APP_NAME}rc 文件中进行覆盖默认配置 21 | */ 22 | export const DEFAULT_CONFIG = { 23 | base_url: 'https://cloud.minapp.com/', 24 | os_home: osenv.home(), 25 | }; 26 | 27 | export function getConfig(args?: Mapping): Config { 28 | const config = { 29 | ...rc(APP_NAME, DEFAULT_CONFIG, args), 30 | }; 31 | if ( 32 | !checkPathExists(`.${APP_NAME}rc`) && 33 | checkPathExists(`.${MIN_CLOUD_KEY}rc`) 34 | ) { 35 | // 没有使用默认 rc 配置,但使用了知晓云官方的 rc 配置 36 | const minCloudConfig = rc(MIN_CLOUD_KEY, DEFAULT_CONFIG, args); 37 | 38 | // 仅读取 client_id 兼容 39 | config.client_id = minCloudConfig.client_id; 40 | } 41 | 42 | return config; 43 | } 44 | 45 | /** 46 | * 更新全局 rc 配置 47 | * 48 | * @description 本地临时配置都储存在 user 目录下的 rc 文件中 49 | */ 50 | export function updateConfig(data: Mapping) { 51 | // 默认配置不应污染 rc 文件的值 52 | const conf = rc(APP_NAME); 53 | const rootRcFilePath = path.join(DEFAULT_CONFIG.os_home, `.${APP_NAME}rc`); 54 | 55 | // 检测 user 路径下是否存在配置表,不存在则创建一个 56 | if (!fs.existsSync(rootRcFilePath)) { 57 | fs.writeFileSync(rootRcFilePath, ''); 58 | } 59 | 60 | const newConf = { ...data }; 61 | Object.keys(conf).forEach(key => { 62 | // 采用最新的数据 63 | if (newConf[key]) return; 64 | 65 | // rc 属性不储存 66 | if (IGNORE_CONFIG_KEYS.includes(key)) return; 67 | 68 | newConf[key] = conf[key]; 69 | }); 70 | 71 | // 写入 ini 格式 72 | return writeFile(rootRcFilePath, ini.stringify(newConf), 'utf8'); 73 | } 74 | 75 | /** 76 | * 从缓存中读取知晓云的 token 77 | */ 78 | export function getToken(clientId?: string, args?: Mapping) { 79 | const conf = getConfig(args); 80 | const id = clientId || conf.client_id; 81 | 82 | return id && conf.tokens ? decodeTokens(conf.tokens)[id] : ''; 83 | } 84 | 85 | export default getConfig(); 86 | -------------------------------------------------------------------------------- /packages/cli/src/config/type.d.ts: -------------------------------------------------------------------------------- 1 | import { DEFAULT_CONFIG } from './index'; 2 | 3 | export interface LocalRcConfig { 4 | tokens?: string; 5 | client_id?: string; 6 | } 7 | 8 | export type Config = typeof DEFAULT_CONFIG & LocalRcConfig; 9 | -------------------------------------------------------------------------------- /packages/cli/src/index.ts: -------------------------------------------------------------------------------- 1 | import { registerCommand } from './commands'; 2 | 3 | registerCommand(process.argv); 4 | -------------------------------------------------------------------------------- /packages/cli/src/request/api/function.ts: -------------------------------------------------------------------------------- 1 | import { API_URL_MAPPING } from '../../config/api'; 2 | import request from '../index'; 3 | 4 | /** 5 | * 更新云函数代码 6 | */ 7 | export async function updateCloudFunction({ 8 | name, 9 | content, 10 | remark, 11 | }: { 12 | name: string; 13 | content: string; 14 | remark?: string; 15 | }) { 16 | return request({ 17 | url: `${API_URL_MAPPING.CLOUD_FUNCTION}${name}`, 18 | method: 'PATCH', 19 | data: { 20 | name, 21 | function_code: content, 22 | remark, 23 | }, 24 | }); 25 | } 26 | 27 | /** 28 | * 更新云函数代码 29 | */ 30 | export async function createCloudFunction({ 31 | name, 32 | content, 33 | remark, 34 | }: { 35 | name: string; 36 | content: string; 37 | remark?: string; 38 | }) { 39 | return request({ 40 | url: `${API_URL_MAPPING.CLOUD_FUNCTION}`, 41 | method: 'POST', 42 | data: { 43 | name, 44 | function_code: content, 45 | remark, 46 | }, 47 | }); 48 | } 49 | 50 | /** 51 | * 更新云函数代码 52 | */ 53 | export async function invokeCloudFunction({ 54 | name, 55 | data, 56 | sync = true, 57 | }: { 58 | name: string; 59 | data: Record; 60 | sync?: boolean; 61 | }) { 62 | return request({ 63 | url: `${API_URL_MAPPING.CLOUD_FUNCTION_DEBUG.replace('{name}', name)}`, 64 | method: 'POST', 65 | data: { 66 | function_name: name, 67 | data, 68 | sync, 69 | }, 70 | }); 71 | } 72 | -------------------------------------------------------------------------------- /packages/cli/src/request/api/index.ts: -------------------------------------------------------------------------------- 1 | export * from './function'; 2 | export * from './login'; 3 | export * from './schema'; 4 | -------------------------------------------------------------------------------- /packages/cli/src/request/api/login.ts: -------------------------------------------------------------------------------- 1 | import FormData from 'form-data'; 2 | 3 | import request from '../index'; 4 | import { decodeTokens, encodeTokens } from '../../utils/token'; 5 | import { getConfig, updateConfig } from '../../config'; 6 | import { API_URL_MAPPING } from '../../config/api'; 7 | 8 | function saveToken(clientId: string, token: string) { 9 | const config = getConfig(); 10 | const tokens = decodeTokens(config.tokens); 11 | tokens[clientId] = token; 12 | 13 | return updateConfig({ 14 | tokens: encodeTokens(tokens), 15 | client_id: clientId, 16 | }); 17 | } 18 | 19 | /** 20 | * 登录 21 | * 22 | * @description 获取知晓云的登录授权 token 23 | */ 24 | export async function login({ 25 | clientId, 26 | clientSecret, 27 | }: { 28 | clientId: string; 29 | clientSecret: string; 30 | }) { 31 | // 获取 code 信息 32 | const authResponse = await request({ 33 | url: API_URL_MAPPING.AUTHORIZE, 34 | method: 'post', 35 | data: { 36 | client_id: clientId, 37 | client_secret: clientSecret, 38 | }, 39 | withCredentials: true, 40 | }); 41 | 42 | if (typeof authResponse.data === 'string') { 43 | console.error('登录授权失败:', authResponse); 44 | return; 45 | } 46 | 47 | const code = authResponse.data.code; 48 | const formData = new FormData(); 49 | formData.append('client_id', clientId); 50 | formData.append('client_secret', clientSecret); 51 | formData.append('grant_type', 'authorization_code'); 52 | formData.append('code', code); 53 | 54 | const response = await request.post<{ 55 | access_token: string; 56 | token_type: string; 57 | expires_in: number; 58 | scope: string; 59 | refresh_token: string; 60 | }>(API_URL_MAPPING.ACCESS_TOKEN, formData); 61 | 62 | // 缓存 token 63 | await saveToken(clientId, response.data.access_token); 64 | 65 | return response; 66 | } 67 | -------------------------------------------------------------------------------- /packages/cli/src/request/api/schema.ts: -------------------------------------------------------------------------------- 1 | import { API_URL_MAPPING } from '../../config/api'; 2 | import request from '../index'; 3 | 4 | /** 5 | * 获取数据表列表 6 | * @param {*} engine 7 | */ 8 | export async function getSchemaList() { 9 | return request.get(`${API_URL_MAPPING.TABLE}?limit=1000`); 10 | } 11 | -------------------------------------------------------------------------------- /packages/cli/src/request/index.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | import { wrapper } from 'axios-cookiejar-support'; 4 | import { CookieJar } from 'tough-cookie'; 5 | 6 | import { createLogger } from '@/utils'; 7 | 8 | import config from '../config'; 9 | import { transformErrorMessage, handleUnauthorizedError } from './utils'; 10 | 11 | const NAME = 'api'; 12 | const logger = createLogger(NAME); 13 | 14 | const jar = new CookieJar(); 15 | 16 | const instance = wrapper( 17 | axios.create({ 18 | baseURL: config.base_url, 19 | jar, 20 | }), 21 | ); 22 | 23 | instance.interceptors.response.use( 24 | function (response) { 25 | // console.log('axios.interceptors.response --> ', response); 26 | // Any status code that lie within the range of 2xx cause this function to trigger 27 | // Do something with response data 28 | 29 | return response; 30 | }, 31 | function (error) { 32 | // Any status codes that falls outside the range of 2xx cause this function to trigger 33 | // Do something with response error 34 | 35 | // transform response status to error message 36 | transformErrorMessage(error); 37 | handleUnauthorizedError(error); 38 | 39 | return Promise.reject(error); 40 | }, 41 | ); 42 | 43 | export function registerMinCloudHeaders({ 44 | token, 45 | envId, 46 | }: { 47 | token: string; 48 | envId: string; 49 | }) { 50 | instance.defaults.headers.common['Authorization'] = `Bearer ${token}`; 51 | logger.verbose(NAME, `request env id: ${envId}`); 52 | 53 | if (envId) { 54 | instance.defaults.headers.common['X-Hydrogen-Env-ID'] = envId; 55 | } 56 | } 57 | 58 | export default instance; 59 | 60 | export * from './api'; 61 | -------------------------------------------------------------------------------- /packages/cli/src/request/utils.ts: -------------------------------------------------------------------------------- 1 | import type { AxiosError } from 'axios'; 2 | import { isPlainObject } from 'lodash'; 3 | 4 | import { ERROR_MESSAGE } from '../config/api'; 5 | 6 | export function transformErrorMessage( 7 | error: AxiosError<{ status: string; error_msg: string }>, 8 | ) { 9 | const { status, data } = error.response || {}; 10 | 11 | // 设置错误信息 12 | if (status) { 13 | let message = ERROR_MESSAGE[status]; 14 | 15 | if (typeof data === 'string') { 16 | message = data; 17 | } else if (isPlainObject(data) && data?.error_msg) { 18 | message = data.error_msg; 19 | } 20 | 21 | if (message) { 22 | error.message = message; 23 | } 24 | } 25 | 26 | return error; 27 | } 28 | 29 | export function handleUnauthorizedError(error: AxiosError) { 30 | const status = error.response?.status; 31 | 32 | // 设置错误信息 33 | if (status === 401) { 34 | console.error('权限不足,请重新登录.'); 35 | } 36 | 37 | return error; 38 | } 39 | -------------------------------------------------------------------------------- /packages/cli/src/utils/cloud-function.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import autocomplete, { Separator } from 'inquirer-autocomplete-standalone'; 4 | 5 | import { resolveCwdAbsolutePath } from '@/utils'; 6 | 7 | /** 8 | * 递归地搜索云函数入口文件。 9 | * @param {string} dir - 要搜索的目录。 10 | * @param {string} baseDir - 基础目录,用于计算相对路径。 11 | * @returns {Object} - 入口点对象。 12 | */ 13 | 14 | export function scanForFunctionEntries( 15 | dir, 16 | { pick = [] }: { pick?: string[] } = {}, 17 | ) { 18 | const entries = {}; 19 | 20 | function findEntries(currentPath) { 21 | fs.readdirSync(currentPath).forEach(file => { 22 | const filePath = path.resolve(currentPath, file); 23 | const stat = fs.statSync(filePath); 24 | 25 | if (stat && stat.isDirectory()) { 26 | findEntries(filePath); 27 | } else if (file.endsWith('.js') || file.endsWith('.ts')) { 28 | const entryKey = path.basename(filePath, path.extname(filePath)); 29 | 30 | if (!pick.length || pick.includes(entryKey)) { 31 | entries[entryKey] = filePath; 32 | } 33 | } 34 | }); 35 | } 36 | 37 | findEntries(dir); 38 | 39 | return entries; 40 | } 41 | 42 | export async function selectCloudFunction( 43 | entryDir: string, 44 | { message = 'Select a cloud function', defaultValue = '' } = {}, 45 | ) { 46 | const folderPath = resolveCwdAbsolutePath(entryDir); 47 | const entry = scanForFunctionEntries(folderPath); 48 | const functionNames = Object.keys(entry); 49 | 50 | return autocomplete({ 51 | message, 52 | source: (input = '') => { 53 | return new Promise(resolve => { 54 | const results = functionNames.filter(s => 55 | s.toLowerCase().includes(input.toLowerCase()), 56 | ); 57 | const all: any = results.map(r => ({ 58 | value: r, 59 | name: r, 60 | // description: r, 61 | disabled: false, 62 | })); 63 | all.unshift(new Separator()); 64 | resolve(all); 65 | }); 66 | }, 67 | transformer: input => { 68 | return `Cloud function: ${input}`; 69 | }, 70 | default: defaultValue, 71 | pageSize: 10, 72 | validate(value) { 73 | if (!value) { 74 | return 'Please select a cloud function'; 75 | } 76 | return true; 77 | }, 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /packages/cli/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import mkdirp from 'mkdirp'; 3 | import fs from 'fs/promises'; 4 | 5 | export * from './path'; 6 | export * from './logger'; 7 | export * from './cloud-function'; 8 | 9 | /** 10 | * 获取类型的字段 11 | */ 12 | export function getBaseType(target: any) { 13 | const typeStr = Object.prototype.toString.call(target).toLocaleLowerCase(); 14 | 15 | return typeStr.slice(8, -1); 16 | } 17 | 18 | export function formatBytes(byte) { 19 | const divisor = 1024; 20 | const unit = ['Byte', 'KB', 'MB', 'GB', 'TB']; 21 | let i = 0; 22 | while (Math.floor(byte / divisor) > 1) { 23 | i++; 24 | byte = byte / divisor; 25 | } 26 | return byte.toFixed(2) + unit[i]; 27 | } 28 | 29 | export function pascalCase(str: string) { 30 | return str.replace(/(^|_)(\w)/g, (match, head, letter) => 31 | letter.toUpperCase(), 32 | ); 33 | } 34 | 35 | /** 36 | * 解析字段所引用的数据表 37 | */ 38 | export function parseCollectionName(collectionName = '') { 39 | const [appId, schemaId, ...others] = collectionName.split('_'); 40 | const schemaName = others.join('_'); 41 | 42 | return { 43 | appId, 44 | schemaId, 45 | schemaName, 46 | }; 47 | } 48 | 49 | export async function writeFile({ 50 | fileName, 51 | dirPath, 52 | content, 53 | }: { 54 | fileName: string; 55 | dirPath: string; 56 | content: string; 57 | }) { 58 | // 确保目录被创建 59 | await mkdirp(dirPath); 60 | 61 | return fs.writeFile(path.resolve(dirPath, fileName), content); 62 | } 63 | -------------------------------------------------------------------------------- /packages/cli/src/utils/logger.ts: -------------------------------------------------------------------------------- 1 | import log from 'npmlog'; 2 | import os from 'os'; 3 | 4 | import { APP_NAME } from '@/config/constant'; 5 | 6 | export function initLogger(logLevel?: string) { 7 | log.heading = APP_NAME; 8 | if (logLevel) { 9 | log.level = logLevel; 10 | } 11 | } 12 | 13 | /** 14 | * 简易版日志输出系统 15 | */ 16 | export function createLogger(name: string) { 17 | // handle log.success() 18 | log.addLevel('success', 3001, { fg: 'green', bold: true }); 19 | 20 | // emit all buffered logs at configured level and higher 21 | log.resume(); 22 | return log['newGroup'](name); 23 | } 24 | 25 | export function output(...args: any[]) { 26 | log.clearProgress(); 27 | console.log(...args); 28 | log.showProgress(); 29 | } 30 | 31 | /** 32 | * 生成日志格式,后续考虑用第三方库来处理 33 | */ 34 | export function generatorLog(list: (string | string[])[] = []) { 35 | const logs: string[] = []; 36 | list.forEach(item => { 37 | if (Array.isArray(item)) { 38 | item.forEach(str => { 39 | logs.push(str.length ? ` ${str}` : ''); 40 | }); 41 | } else { 42 | logs.push(item); 43 | } 44 | }); 45 | 46 | return logs.join(os.EOL); 47 | } 48 | -------------------------------------------------------------------------------- /packages/cli/src/utils/path.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | 4 | /** 5 | * 解析给定的文件路径为绝对路径。 6 | * @desc 如果路径已经是绝对路径,则返回该路径的真实(解析符号链接后的)路径。 7 | * 如果路径是相对路径,基于当前工作目录解析为绝对路径。 8 | * 9 | * @param {string} filePath - 待解析的文件路径。 10 | * @returns {string} 解析后的绝对文件路径。 11 | */ 12 | export function resolveCwdAbsolutePath(filePath) { 13 | if (path.isAbsolute(filePath)) { 14 | return fs.realpathSync(filePath); 15 | } 16 | 17 | return path.resolve(process.cwd(), filePath); 18 | } 19 | 20 | /** 21 | * 检查给定的文件或目录路径是否存在。 22 | * @param {string} filePath - 要检查的文件或目录的路径。 23 | * @returns {boolean} 如果路径存在,则返回 true;否则返回 false。 24 | */ 25 | export function checkPathExists(filePath) { 26 | const resolvedPath = resolveCwdAbsolutePath(filePath); 27 | return fs.existsSync(resolvedPath); 28 | } 29 | -------------------------------------------------------------------------------- /packages/cli/src/utils/token.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * tokens 解码为对象 3 | */ 4 | export function decodeTokens(str = '') { 5 | if (!str?.length) return {}; 6 | return str 7 | .trim() 8 | .split(',') 9 | .reduce((acc, pair) => { 10 | const [key, value] = pair.split(':'); 11 | acc[key] = value; 12 | return acc; 13 | }, {}); 14 | } 15 | 16 | /** 17 | * 将 tokens 对象编码为字符串 18 | */ 19 | export function encodeTokens(obj = {}) { 20 | return Object.keys(obj) 21 | .map(key => `${key}:${obj[key]}`) 22 | .join(','); 23 | } 24 | -------------------------------------------------------------------------------- /packages/cli/static/network-save-response.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anran758/mincloudx/7f4b501352e441c98f48b1f0d1c2aab8541436a3/packages/cli/static/network-save-response.png -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | 5 | // Code generation settings 6 | "target": "es2015", 7 | 8 | // Module resolution and path settings 9 | "rootDir": ".", 10 | "baseUrl": ".", 11 | "paths": { 12 | "@/*": ["src/*"] 13 | }, 14 | "resolveJsonModule": true, 15 | "module": "ESNext", 16 | "moduleResolution": "node", 17 | 18 | // Strictness and type checking 19 | "strict": true, 20 | "noImplicitAny": false, 21 | "skipLibCheck": true, 22 | "types": ["minapp-sdk-typings", "webpack-env"], 23 | 24 | // Interoperability with the ES6 module system 25 | "esModuleInterop": true, 26 | "allowSyntheticDefaultImports": true 27 | }, 28 | "include": ["src", "typings", "./package.json"], 29 | "exclude": ["node_modules", "lib", "__tests__"] 30 | } 31 | -------------------------------------------------------------------------------- /packages/cli/typings/schema.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | */ 3 | /* eslint-disable no-use-before-define */ 4 | 5 | type Int = number; 6 | type SchemaId = string | number; 7 | /** _at 结尾的字段默认约定为时间戳字段 **/ 8 | type EpochSeconds = number & { seconds_since_the_unix_start: never }; 9 | type JSONString = string & { json_parsable_string: never }; 10 | type HTMLText = string & { html_content: never }; 11 | type ValueOf = T[keyof T]; 12 | type KeyOf = Array; 13 | 14 | /** 15 | * 数据的默认值 16 | */ 17 | type Default = T; 18 | interface PointerWithoutData { 19 | id: SchemaId; 20 | _table: string; 21 | } 22 | 23 | type SchemaPointer = T | PointerWithoutData; 24 | 25 | type CreatedBy = UserProfile | PointerWithoutData | number; 26 | 27 | export interface BaseTable { 28 | _id: number; 29 | id: SchemaId; 30 | created_at: number; 31 | updated_at: number; 32 | created_by?: CreatedBy; 33 | read_perm: string[]; 34 | write_perm: string[]; 35 | } 36 | 37 | /** 38 | * 数据表: _userprofile 39 | * @description 40 | */ 41 | export interface UserProfile extends BaseTable { 42 | /** 43 | * 用户昵称 44 | **/ 45 | nickname: string | Default; 46 | /** 47 | * 用户的性别,值为 1 时是男性,值为 2 时是女性,值为 0 时是未知 48 | **/ 49 | gender: Int | Default; 50 | /** 51 | * 用户所在国家 52 | **/ 53 | country: string | Default; 54 | /** 55 | * 用户所在省份 56 | **/ 57 | province: string | Default; 58 | /** 59 | * 用户所在城市 60 | **/ 61 | city: string | Default; 62 | /** 63 | * 用户的语言 64 | **/ 65 | language: string | Default; 66 | /** 67 | * openid 68 | **/ 69 | openid: string | Default; 70 | /** 71 | * unionid 72 | **/ 73 | unionid: string | Default; 74 | /** 75 | * 用户头像 76 | **/ 77 | avatar: string | Default; 78 | /** 79 | * 用户是否授权,True 为已授权,False 为未授权 80 | **/ 81 | is_authorized: boolean | Default; 82 | /** 83 | * 用户邮箱是否已经通过验证 84 | **/ 85 | _email_verified: boolean | Default; 86 | /** 87 | * 用户邮箱 88 | **/ 89 | _email: string | Default; 90 | /** 91 | * 用户名 92 | **/ 93 | _username: string | Default; 94 | /** 95 | * 用户在平台方的用户信息 96 | **/ 97 | _provider: object | Default; 98 | /** 99 | * 用户手机 100 | **/ 101 | _phone: string | Default; 102 | /** 103 | * 用户手机是否已经通过验证 104 | **/ 105 | _phone_verified: boolean | Default; 106 | } 107 | 108 | /** 109 | * 数据表: _richtextcontent 110 | * @description 111 | */ 112 | export interface RichTextContent extends BaseTable { 113 | /** 114 | * 内容的标题 115 | **/ 116 | title: string | Default; 117 | /** 118 | * 内容的简介 119 | **/ 120 | description: string | Default; 121 | /** 122 | * 内容的封面图 123 | **/ 124 | cover: WechatBaaS.FileOperationResult | Default; 125 | /** 126 | * 内容详情 127 | **/ 128 | content: string | Default; 129 | /** 130 | * 内容库 ID 131 | **/ 132 | group_id: Int | Default; 133 | /** 134 | * 内容分类的 ID 列表 135 | **/ 136 | categories: Int[] | Default; 137 | /** 138 | * 内容阅读数 139 | **/ 140 | visit_count: Int | Default; 141 | } 142 | 143 | /** 144 | * 数据表: channel_follow 145 | * @description channel_follow 146 | */ 147 | export interface ChannelFollow extends BaseTable { 148 | /** 149 | * 圈子信息 150 | **/ 151 | channel: SchemaPointer | Default; 152 | } 153 | 154 | /** 155 | * 数据表: pins_vote_log 156 | * @description 想法点赞记录表 157 | */ 158 | export interface PinsVoteLog extends BaseTable { 159 | /** 160 | * 主体类型,用于区分 subject_id 的用途。可选类型为: 1. pins 161 | **/ 162 | subject_type: string | 'pins' | Default<'pins'>; 163 | /** 164 | * 主体的 id 165 | **/ 166 | subject_id: string | Default; 167 | } 168 | 169 | /** 170 | * 数据表: channel_activity_log 171 | * @description 圈子活动参与记录表 172 | */ 173 | export interface ChannelActivityLog extends BaseTable { 174 | /** 175 | * 圈子id 176 | **/ 177 | channel_id: string; 178 | /** 179 | * 关联的活动 id 180 | **/ 181 | activity_id: string; 182 | /** 183 | * applied_at 184 | **/ 185 | applied_at: EpochSeconds; 186 | } 187 | 188 | /** 189 | * 数据表: channel_feed 190 | * @description 圈子动态表 191 | */ 192 | export interface ChannelFeed extends BaseTable { 193 | /** 194 | * 关联的圈子 id 195 | **/ 196 | channel_id: string; 197 | /** 198 | * 主体类型,用于区分 subject_id 的用途。可选类型为: 1. activity 2. pins 199 | **/ 200 | subject_type: string | 'activity' | 'pins'; 201 | /** 202 | * 主体的 id 203 | **/ 204 | subject_id: string; 205 | } 206 | 207 | /** 208 | * 数据表: pins 209 | * @description 想法表 210 | */ 211 | export interface Pins extends BaseTable { 212 | /** 213 | * 内容点赞数 214 | **/ 215 | upvote: Int | Default<0>; 216 | /** 217 | * "想法" 附带的图片 218 | **/ 219 | images: string[] | Default; 220 | /** 221 | * 主体 id 222 | **/ 223 | subject_id: string | Default; 224 | /** 225 | * 主体类型,用于区分 subject_id 的用途。可选类型为: 1. channel 226 | **/ 227 | subject_type: string | Default; 228 | /** 229 | * "想法" 内容 230 | **/ 231 | content: string; 232 | /** 233 | * 是否将想法推送到广场中 234 | **/ 235 | is_public: boolean | Default; 236 | /** 237 | * 想法状态 238 | **/ 239 | status: string | 'approved' | 'deleted' | Default<'approved'>; 240 | } 241 | 242 | /** 243 | * 数据表: channel_activity 244 | * @description 圈子活动表 245 | */ 246 | export interface ChannelActivity extends BaseTable { 247 | /** 248 | * 关联的圈子 249 | **/ 250 | channel: SchemaPointer; 251 | /** 252 | * 活动名称 253 | **/ 254 | name: string; 255 | /** 256 | * 活动封面图 257 | **/ 258 | cover_image: string; 259 | /** 260 | * 活动的详细说明 261 | **/ 262 | detail: string | Default; 263 | /** 264 | * 报名结束时间 (unix 时间戳) 265 | **/ 266 | apply_ends_at: EpochSeconds; 267 | /** 268 | * 开放的参与名额,-1 表示不限数量 269 | **/ 270 | quota: Int | Default<-1>; 271 | /** 272 | * 已申请名额 273 | **/ 274 | applied_quota: Int | Default<0>; 275 | /** 276 | * 活动发起人的联系信息 277 | **/ 278 | contact_info: string | Default; 279 | } 280 | 281 | /** 282 | * 数据表: channel 283 | * @description 圈子表 284 | */ 285 | export interface Channel extends BaseTable { 286 | /** 287 | * 圈子名称 288 | **/ 289 | name: string | Default; 290 | /** 291 | * 圈子封面图 292 | **/ 293 | cover_image: string | Default; 294 | /** 295 | * 圈子描述 296 | **/ 297 | description: string | Default; 298 | /** 299 | * 圈子状态 300 | **/ 301 | status: string | 'approved' | 'deleted' | Default<'approved'>; 302 | } 303 | 304 | /** 305 | * 数据表: channel_admin 306 | * @description 用于保存圈子的管理员信息 307 | */ 308 | export interface ChannelAdmin extends BaseTable { 309 | /** 310 | * 圈子 id 311 | **/ 312 | channel_id: string | Default; 313 | } 314 | -------------------------------------------------------------------------------- /packages/cli/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | const TerserPlugin = require('terser-webpack-plugin'); 4 | const nodeExternals = require('webpack-node-externals'); 5 | const CopyPlugin = require('copy-webpack-plugin'); 6 | 7 | const webpackConf = { 8 | mode: 'production', 9 | entry: { 10 | index: path.resolve(__dirname, 'src/index.ts'), 11 | }, 12 | output: { 13 | path: path.resolve(__dirname, 'lib'), 14 | filename: 'index.js', 15 | clean: true, 16 | }, 17 | target: 'node', 18 | cache: { type: 'filesystem' }, 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.(js|ts)$/, 23 | loader: require.resolve('ts-loader'), 24 | exclude: /node_modules/, 25 | }, 26 | ], 27 | }, 28 | externalsPresets: { 29 | node: true, 30 | }, 31 | externals: [ 32 | nodeExternals({ 33 | allowlist: ['inquirer-autocomplete-standalone'], 34 | }), 35 | nodeExternals({ 36 | modulesDir: path.resolve(__dirname, '../../node_modules'), 37 | }), 38 | { deasync: 'commonjs deasync' }, 39 | ], 40 | resolve: { 41 | alias: { 42 | '@': path.resolve(__dirname, 'src'), 43 | }, 44 | extensions: ['.ts', '.js'], 45 | fallback: { path: false }, 46 | }, 47 | optimization: { 48 | minimizer: [ 49 | new webpack.optimize.ModuleConcatenationPlugin(), 50 | new TerserPlugin({ 51 | extractComments: false, 52 | }), 53 | new CopyPlugin({ 54 | patterns: [ 55 | { 56 | from: path.resolve(__dirname, 'src/assist'), // 源目录的绝对路径 57 | to: path.resolve(__dirname, 'lib/assist'), // 目标目录的绝对路径 58 | }, 59 | ], 60 | }), 61 | ], 62 | }, 63 | }; 64 | 65 | module.exports = webpackConf; 66 | -------------------------------------------------------------------------------- /packages/faas/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## [0.4.2](https://github.com/anran758/mincloudx/compare/v4.0.2...v0.4.2) (2024-07-25) 7 | 8 | **Note:** Version bump only for package @mincloudx/faas 9 | 10 | ## [0.4.1](https://github.com/anran758/mincloudx/compare/v4.0.1...v0.4.1) (2024-07-18) 11 | 12 | **Note:** Version bump only for package @mincloudx/faas 13 | 14 | # [0.4.0](https://github.com/anran758/mincloudx/compare/v0.1.1...v0.4.0) (2024-04-19) 15 | 16 | ### Bug Fixes 17 | 18 | - **faas:** fixed the issue where createFaas could not be called properly ([00b0b19](https://github.com/anran758/mincloudx/commit/00b0b194ab165332fd3c9058649e89ce9e99e8f7)) 19 | 20 | ### Features 21 | 22 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 23 | - **faas:** add baas/faas type ([735b09d](https://github.com/anran758/mincloudx/commit/735b09d41de4f8659d765315a3dfb1d62f5b96f5)) 24 | - **faas:** add createFaas, complete basic implementation ([64a557a](https://github.com/anran758/mincloudx/commit/64a557a85aa64995e0a44a432d1f93b9f1a18306)) 25 | - **faas:** add new faas framework package, add jest framework, introduced jest for code testing ([12e48dd](https://github.com/anran758/mincloudx/commit/12e48dd7d07a8334f3f3ee52ce39bae807e93f6d)) 26 | - **io:** io support crud function, update faas-demo example ([d67f377](https://github.com/anran758/mincloudx/commit/d67f377c564d0935679c06d2c5c357d064321aae)) 27 | - **types:** abstract the common TypeScript type files into the a separate package ([cc8fc2c](https://github.com/anran758/mincloudx/commit/cc8fc2cb64865a330043afc800150aca7abca6d1)) 28 | 29 | ## [0.1.1](https://github.com/anran758/mincloudx/compare/@mincloudx/faas@0.1.0...@mincloudx/faas@0.1.1) (2024-03-30) 30 | 31 | **Note:** Version bump only for package @mincloudx/faas 32 | 33 | # [0.1.0](https://github.com/anran758/mincloudx/compare/@mincloudx/faas@0.0.1...@mincloudx/faas@0.1.0) (2024-03-21) 34 | 35 | ### Features 36 | 37 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 38 | - **io:** io support crud function, update faas-demo example ([d67f377](https://github.com/anran758/mincloudx/commit/d67f377c564d0935679c06d2c5c357d064321aae)) 39 | 40 | ## 0.0.1 (2024-03-11) 41 | 42 | ### Bug Fixes 43 | 44 | - **faas:** fixed the issue where createFaas could not be called properly ([00b0b19](https://github.com/anran758/mincloudx/commit/00b0b194ab165332fd3c9058649e89ce9e99e8f7)) 45 | 46 | ### Features 47 | 48 | - **faas:** add baas/faas type ([735b09d](https://github.com/anran758/mincloudx/commit/735b09d41de4f8659d765315a3dfb1d62f5b96f5)) 49 | - **faas:** add createFaas, complete basic implementation ([64a557a](https://github.com/anran758/mincloudx/commit/64a557a85aa64995e0a44a432d1f93b9f1a18306)) 50 | - **faas:** add new faas framework package, add jest framework, introduced jest for code testing ([12e48dd](https://github.com/anran758/mincloudx/commit/12e48dd7d07a8334f3f3ee52ce39bae807e93f6d)) 51 | - **types:** abstract the common TypeScript type files into the a separate package ([cc8fc2c](https://github.com/anran758/mincloudx/commit/cc8fc2cb64865a330043afc800150aca7abca6d1)) 52 | -------------------------------------------------------------------------------- /packages/faas/README.md: -------------------------------------------------------------------------------- 1 | # @mincloudx/faas 2 | 3 | ![Version](https://badgen.net/npm/v/@mincloudx/faas) 4 | ![TypeScript](https://badgen.net/badge/-/TypeScript?icon=typescript&label&labelColor=blue&color=555555) 5 | 6 | > A more user-friendly Node.js cloud function development framework, designed to simplify interactions with Backend-as-a-Service (BaaS) and ensure consistent response structures. 7 | 8 | ## Features 9 | 10 | - **Default Parameter Handling**: Automatically transforms `null` or missing `event.data` into an empty object, ensuring your function always receives a valid event object. 11 | - **Unified Return Format**: Standardizes the return format of cloud functions. Non-object returns are wrapped as `{data: value}`, while object returns are passed through as-is. 12 | - **BaaS SDK Version Management**: By default, uses the latest SDK version available but allows for explicit version setting or opting out of version updates. 13 | 14 | ## Usage 15 | 16 | ### Installation 17 | 18 | ```bash 19 | pnpm install @mincloudx/faas 20 | ``` 21 | 22 | ### Creating a Cloud Function 23 | 24 | In your cloud function file, import and use `createFaas` to wrap your main function. This not only standardizes the behavior of your cloud function but also handles BaaS SDK version management and event data preprocessing. 25 | 26 | ```ts 27 | import { createFaas, FAAS_LATEST_SDK_VERSION } from '@mincloudx/faas'; 28 | 29 | async function main(event) { 30 | // Your function logic here 31 | console.log(`event:`, event); 32 | 33 | return { status: 'ok' }; 34 | } 35 | 36 | export default createFaas(main, { 37 | updateVersion: true, // Optional: Ensures the BaaS SDK is always up-to-date. Default is true. 38 | version: 'specific-version', // Optional: Set a specific BaaS SDK version if required. 39 | }); 40 | ``` 41 | 42 | ### Test 43 | 44 | Ensure the reliability and correctness of your functions by testing with Jest. The framework provides a streamlined way to test various scenarios, such as default parameter handling, unified return format, and BaaS SDK version management. 45 | 46 | ```bash 47 | pnpm run test 48 | ``` 49 | 50 | ## Development 51 | 52 | ### Compiling TypeScript 53 | 54 | Prepare your package for use by compiling TypeScript files. 55 | 56 | ```bash 57 | pnpm run tsc 58 | ``` 59 | 60 | ### Watch Mode 61 | 62 | Automatically recompile TypeScript files upon changes for efficient development. 63 | 64 | ```bash 65 | pnpm run watch 66 | ``` 67 | 68 | --- 69 | 70 | This improved README incorporates details from the test cases, emphasizing the utility and flexibility of `createFaas`. It clarifies how users can manage BaaS SDK versions and the behavior of cloud functions with respect to input and return values, providing a comprehensive guide for both usage and development. 71 | -------------------------------------------------------------------------------- /packages/faas/__tests__/faas.test.js: -------------------------------------------------------------------------------- 1 | const { createFaas, FAAS_LATEST_SDK_VERSION } = require('..'); 2 | 3 | // Mock global BaaS 4 | const SKD_VERSION = 'v2.0'; 5 | global.BaaS = { 6 | VERSION: SKD_VERSION, 7 | useVersion(version) { 8 | BaaS.VERSION = version; 9 | }, 10 | }; 11 | 12 | function defaultUserDefinedFunction() { 13 | return { status: 'ok' }; 14 | } 15 | 16 | describe('createFaas Functionality', () => { 17 | describe('Default Parameters Handling', () => { 18 | it('transforms event.data from null to an empty object if no event data is passed', async () => { 19 | const userDefinedFunction = createFaas(event => { 20 | expect(event.data).toEqual({}); 21 | }); 22 | 23 | await userDefinedFunction({}); // Passing an empty event object 24 | }); 25 | }); 26 | 27 | describe('Unified Return Format', () => { 28 | it('wraps non-object return values from the user-defined function in {data: value}', async () => { 29 | const returnValue = 'Test String'; 30 | const exceptResponse = { data: returnValue }; 31 | const userDefinedFunction = createFaas(() => returnValue); 32 | 33 | const response = await userDefinedFunction({}); 34 | expect(response).toEqual(exceptResponse); 35 | }); 36 | 37 | it('returns the object as-is if the return value from the user-defined function is an object', async () => { 38 | const returnValue = { key: 'value' }; 39 | const userDefinedFunction = createFaas(() => returnValue); 40 | 41 | const response = await userDefinedFunction({}); 42 | expect(response).toEqual(returnValue); 43 | }); 44 | }); 45 | 46 | describe('BaaS SDK version', () => { 47 | // reset to original version before each test to prevent tests from affecting each other 48 | beforeEach(() => { 49 | BaaS.VERSION = SKD_VERSION; 50 | }); 51 | 52 | it('default to using latest SDK version', async () => { 53 | const userDefinedFunction = createFaas(defaultUserDefinedFunction); 54 | await userDefinedFunction({}); 55 | expect(BaaS.VERSION).toEqual(FAAS_LATEST_SDK_VERSION); 56 | }); 57 | 58 | // Ensure the version is updated to the latest by default 59 | it('updates to the latest SDK version by default', async () => { 60 | const userDefinedFunction = createFaas(defaultUserDefinedFunction, { 61 | updateVersion: true, 62 | }); 63 | await userDefinedFunction({}); 64 | expect(BaaS.VERSION).toEqual(FAAS_LATEST_SDK_VERSION); 65 | }); 66 | 67 | // Keep the default version when updateVersion is explicitly set to false 68 | it('remains at the default SDK version when updateVersion is explicitly set to false', async () => { 69 | const userDefinedFunction = createFaas(defaultUserDefinedFunction, { 70 | updateVersion: false, 71 | }); 72 | await userDefinedFunction({}); 73 | expect(BaaS.VERSION).toEqual(SKD_VERSION); // Assuming originalVersion is the default version 74 | }); 75 | 76 | // Allow setting BaaS.VERSION to a specified version 77 | it('sets SDK to the specified version', async () => { 78 | const specifiedVersion = 'v3.0'; 79 | const userDefinedFunction = createFaas(defaultUserDefinedFunction, { 80 | version: specifiedVersion, 81 | }); 82 | await userDefinedFunction({}); 83 | expect(BaaS.VERSION).toEqual(specifiedVersion); 84 | }); 85 | }); 86 | }); 87 | -------------------------------------------------------------------------------- /packages/faas/jest.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * For a detailed explanation regarding each configuration property, visit: 3 | * https://jestjs.io/docs/configuration 4 | */ 5 | 6 | import type { Config } from 'jest'; 7 | 8 | const config: Config = { 9 | // ensure `npm cit` uses clean cache 10 | cacheDirectory: './node_modules/.cache/jest', 11 | clearMocks: true, 12 | testEnvironment: 'node', 13 | transform: {}, 14 | }; 15 | 16 | export default config; 17 | -------------------------------------------------------------------------------- /packages/faas/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/faas", 3 | "sideEffects": false, 4 | "version": "0.4.2", 5 | "description": "A more user-friendly Node.js cloud function development framework.", 6 | "keywords": [ 7 | "mincloudx", 8 | "mincloud", 9 | "Node.js", 10 | "faas", 11 | "baas", 12 | "serverless" 13 | ], 14 | "author": "anran758 ", 15 | "homepage": "https://github.com/anran758/mincloudx/tree/main/packages/faas#readme", 16 | "license": "MIT", 17 | "main": "./lib/cjs/index.js", 18 | "typings": "./lib/cjs/types/index.d.ts", 19 | "publishConfig": { 20 | "access": "public" 21 | }, 22 | "files": [ 23 | "lib" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/anran758/mincloudx.git" 28 | }, 29 | "scripts": { 30 | "prepare": "pnpm run build", 31 | "prepublishOnly": "pnpm run build", 32 | "test": "jest --verbose", 33 | "build": "pnpm run '/build:.*/'", 34 | "build:esm": "rm -rf lib/esm && tsc -p ./tsconfig.json", 35 | "build:cjs": "rm -rf lib/cjs && tsc -p ./tsconfig.cjs.json", 36 | "watch": "pnpm run '/^watch:.*/'", 37 | "watch:esm": "tsc -p ./tsconfig.json --watch", 38 | "watch:cjs": "tsc -p ./tsconfig.cjs.json --watch" 39 | }, 40 | "exports": { 41 | ".": { 42 | "import": { 43 | "types": "./lib/esm/types/index.d.mts", 44 | "default": "./lib/esm/index.js" 45 | }, 46 | "require": { 47 | "types": "./lib/cjs/types/index.d.ts", 48 | "default": "./lib/cjs/index.js" 49 | } 50 | } 51 | }, 52 | "bugs": { 53 | "url": "https://github.com/anran758/mincloudx/issues" 54 | }, 55 | "devDependencies": { 56 | "@mincloudx/types": "workspace:*", 57 | "@types/lodash": "^4.14.202" 58 | }, 59 | "dependencies": { 60 | "lodash": "^4.17.21" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/faas/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The latest SDK version of the cloud function, used to set the default value for the upgradeFaaSSdk function. 3 | */ 4 | export const FAAS_LATEST_SDK_VERSION = 'v3.20'; 5 | -------------------------------------------------------------------------------- /packages/faas/src/createFaas.ts: -------------------------------------------------------------------------------- 1 | import type { FaaS } from '@mincloudx/types'; 2 | 3 | import { upgradeFaaSSdk } from './version'; 4 | import { formatEvent, formatResponse } from './formatters'; 5 | 6 | export interface CreateFaasOptions { 7 | version?: string; 8 | updateVersion?: boolean; 9 | } 10 | 11 | export function createFaas( 12 | fn: FaaS.UserDefinedFunction, 13 | { version, updateVersion = true }: CreateFaasOptions = {}, 14 | ) { 15 | // specify the version 16 | if (version) { 17 | upgradeFaaSSdk(version); 18 | } else if (updateVersion) { 19 | // use least version 20 | upgradeFaaSSdk(); 21 | } 22 | 23 | /** 24 | * format user-defined function data structure 25 | */ 26 | return async function userDefinedFunctionProxy( 27 | evt: FaaS.Event, 28 | callback?: FaaS.MainCallback, 29 | ) { 30 | const event = formatEvent(evt); 31 | const response = await fn(event, callback); 32 | 33 | return formatResponse(response); 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /packages/faas/src/formatters.ts: -------------------------------------------------------------------------------- 1 | import { isPlainObject } from 'lodash'; 2 | import type { FaaS } from '@mincloudx/types'; 3 | 4 | /** 5 | * formatEvent 6 | * 7 | * @description`event.data` is the parameter passed by the user when invoking cloud function, 8 | * thus this handler ensures that ensure user-defined function can safely access. 9 | */ 10 | export function formatEvent(event: FaaS.Event): FaaS.Event { 11 | const evt = { ...event }; 12 | if (!isPlainObject(evt.data)) { 13 | evt.data = {} as T; 14 | } 15 | 16 | return evt; 17 | } 18 | 19 | /** 20 | * Ensure the returned object structure from the user-defined function 21 | */ 22 | export function formatResponse( 23 | response: any, 24 | ): Record | { data: any } { 25 | return isPlainObject(response) ? response : { data: response || 'success' }; 26 | } 27 | -------------------------------------------------------------------------------- /packages/faas/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config'; 2 | export * from './version'; 3 | export * from './formatters'; 4 | export * from './createFaas'; 5 | -------------------------------------------------------------------------------- /packages/faas/src/version.ts: -------------------------------------------------------------------------------- 1 | import { FAAS_LATEST_SDK_VERSION } from './config'; 2 | 3 | /** 4 | * Upgrade cloud function SDK 5 | * @desc Currently, if not set version, the default SDK version for cloud functions is 2.x, but some features are only available with higher versions of the SDK, thus it needs to be upgraded to a higher version. 6 | * However, since 2.x and 3.x are not fully compatible, old cloud functions need to be tested after upgrading, so the upgrade should be done gradually. 7 | * @param {string} version The version number, e.g., v3.10 8 | */ 9 | export function upgradeFaaSSdk(version = FAAS_LATEST_SDK_VERSION) { 10 | console.log('[upgradeFaaSSdk] current faas version: ', version); 11 | BaaS.useVersion(version); 12 | } 13 | -------------------------------------------------------------------------------- /packages/faas/tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["ES6"], 5 | "target": "es6", 6 | "module": "commonjs", 7 | "moduleResolution": "node10", 8 | "outDir": "lib/cjs", 9 | "declarationDir": "lib/cjs/types" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/faas/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["./src", "./types"], 4 | "exclude": ["**/*.test.ts"], 5 | "compilerOptions": { 6 | "typeRoots": ["../../node_modules/@types", "./types"], 7 | "noImplicitAny": false, 8 | "lib": ["ESNext"], 9 | "target": "es2022", 10 | "module": "NodeNext", 11 | "moduleResolution": "nodenext", 12 | "outDir": "lib/esm", 13 | "declarationDir": "lib/esm/types", 14 | "rootDir": "./src", 15 | "baseUrl": "./" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/faas/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { BaaS as BaaSModule } from '@mincloudx/types'; 2 | 3 | declare global { 4 | // eslint-disable-next-line no-var 5 | var BaaS: typeof BaaSModule; 6 | } 7 | -------------------------------------------------------------------------------- /packages/io/.env: -------------------------------------------------------------------------------- 1 | # test MinCloud baas 2 | TEST_MINI_APP_ID= 3 | TEST_MINI_APP_TOKEN= 4 | -------------------------------------------------------------------------------- /packages/io/.mincloudxrc: -------------------------------------------------------------------------------- 1 | client_id=bf59fcfcf09f23158fca -------------------------------------------------------------------------------- /packages/io/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## [0.4.2](https://github.com/anran758/mincloudx/compare/v4.0.2...v0.4.2) (2024-07-25) 7 | 8 | **Note:** Version bump only for package @mincloudx/io 9 | 10 | ## [0.4.1](https://github.com/anran758/mincloudx/compare/v4.0.1...v0.4.1) (2024-07-18) 11 | 12 | **Note:** Version bump only for package @mincloudx/io 13 | 14 | # [0.4.0](https://github.com/anran758/mincloudx/compare/v0.1.1...v0.4.0) (2024-04-19) 15 | 16 | ### Bug Fixes 17 | 18 | - **io:** io `find` operator should support offset and limit configuration ([2e068eb](https://github.com/anran758/mincloudx/commit/2e068eb81aa2fce1d0fdb150ab83d0467b9059a3)) 19 | - **io:** when the user sets plain, the find operator should return a data list, not object ([91a6c4b](https://github.com/anran758/mincloudx/commit/91a6c4b20a7024fd5f660ed0df6c953571d7be1a)) 20 | 21 | ### Features 22 | 23 | - add basic architecture to IO package ([3fd29c6](https://github.com/anran758/mincloudx/commit/3fd29c67a36da47ae831d31dbfc5c4379c03305d)) 24 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 25 | - **io:** introduce `first` operator to efficiently retrieve the initial record ([56e9bbe](https://github.com/anran758/mincloudx/commit/56e9bbe1a1a22947380ee9289f6a19eae19b8f53)) 26 | - **io:** io support crud function, update faas-demo example ([d67f377](https://github.com/anran758/mincloudx/commit/d67f377c564d0935679c06d2c5c357d064321aae)) 27 | - **io:** support the `createMany` command to create many records ([e956c85](https://github.com/anran758/mincloudx/commit/e956c8541b403af50d5895c9c4c33161f246cfc3)) 28 | - **io:** support the `deleteMany` method for IO ([fcec4e3](https://github.com/anran758/mincloudx/commit/fcec4e3a292d88fb21695f767f8d64f641312655)) 29 | - **io:** support the `updateMany` method for IO, update document ([fe08bf6](https://github.com/anran758/mincloudx/commit/fe08bf6c75af054444a71197ecd815fb4b17f926)) 30 | - **io:** supports `count` function to fetch data count ([8e5273a](https://github.com/anran758/mincloudx/commit/8e5273ab80caa340fd6362481a2aa5d0b34c4d74)) 31 | - **io:** supports find to find lists of data ([ef4ceac](https://github.com/anran758/mincloudx/commit/ef4ceace80c70705c2462a62efd3dcdd9feb44e4)) 32 | - **type:** support dynamic return via plain param ([8307f1c](https://github.com/anran758/mincloudx/commit/8307f1cfc864cc08f148e6cb184faa331c8445d8)) 33 | 34 | ### Performance Improvements 35 | 36 | - **io:** unify the usage of BaaS.TableObject ([5b3132f](https://github.com/anran758/mincloudx/commit/5b3132f8d1e35ad038b3b222b0e9b52867f4868f)) 37 | 38 | # [0.2.0](https://github.com/anran758/mincloudx/compare/@mincloudx/io@0.1.0...@mincloudx/io@0.2.0) (2024-03-30) 39 | 40 | ### Features 41 | 42 | - **io:** support the `createMany` command to create many records ([e956c85](https://github.com/anran758/mincloudx/commit/e956c8541b403af50d5895c9c4c33161f246cfc3)) 43 | - **io:** support the `deleteMany` method for IO ([fcec4e3](https://github.com/anran758/mincloudx/commit/fcec4e3a292d88fb21695f767f8d64f641312655)) 44 | - **io:** support the `updateMany` method for IO, update document ([fe08bf6](https://github.com/anran758/mincloudx/commit/fe08bf6c75af054444a71197ecd815fb4b17f926)) 45 | - **io:** supports `count` function to fetch data count ([8e5273a](https://github.com/anran758/mincloudx/commit/8e5273ab80caa340fd6362481a2aa5d0b34c4d74)) 46 | - **io:** supports find to find lists of data ([ef4ceac](https://github.com/anran758/mincloudx/commit/ef4ceace80c70705c2462a62efd3dcdd9feb44e4)) 47 | - **type:** support dynamic return via plain param ([8307f1c](https://github.com/anran758/mincloudx/commit/8307f1cfc864cc08f148e6cb184faa331c8445d8)) 48 | 49 | # 0.1.0 (2024-03-21) 50 | 51 | ### Features 52 | 53 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 54 | - **io:** io support crud function, update faas-demo example ([d67f377](https://github.com/anran758/mincloudx/commit/d67f377c564d0935679c06d2c5c357d064321aae)) 55 | 56 | # 0.1.0 (2024-01-18) 57 | 58 | ### Features 59 | 60 | - add basic architecture to IO package ([3fd29c6](https://github.com/anran758/mincloudx/commit/3fd29c67a36da47ae831d31dbfc5c4379c03305d)) 61 | 62 | ## 0.0.2 (2023-04-23) 63 | 64 | ### Features 65 | 66 | - 🔧 add eslint, lint-staged for project constraint ([12bc412](https://github.com/anran758/mincloudx/commit/12bc412e6f90d5229279e3c78f1eb8b3b0eac9a6)) 67 | 68 | ## 0.0.1-alpha.0 (2023-01-05) 69 | 70 | ### Features 71 | 72 | - 🎉 add faas-demo ([a2ca8c8](https://github.com/anran758/mincloudx/commit/a2ca8c83a54d0fd2a6f3d48b516aa6704e22ef30)) 73 | -------------------------------------------------------------------------------- /packages/io/README.md: -------------------------------------------------------------------------------- 1 | # @mincloudx/io 2 | 3 | The `@mincloudx/io` package simplifies CRUD (Create, Read, Update, Delete) operations on database tables, offering a streamlined interface for table management with minimal setup. 4 | 5 | ## Installation 6 | 7 | Install `@mincloudx/io` in your project using npm or pnpm: 8 | 9 | ```bash 10 | npm install @mincloudx/io 11 | # or 12 | pnpm add @mincloudx/io 13 | ``` 14 | 15 | ## Usage 16 | 17 | Begin by importing `createIo` and specifying your tables in the `tables` option to register them. This setup enables CRUD operations on the registered tables. 18 | 19 | ```javascript 20 | const { createIo } = require('@mincloudx/io'); 21 | 22 | // Registering tables 23 | const tables = ['channel', 'product']; 24 | const io = createIo({ tables }); 25 | ``` 26 | 27 | Access a registered table by appending its name to `io`, such as `io.channel` or `io.product`. 28 | 29 | ### query 30 | 31 | In batch lookup, update, delete, and other operations, the Query object is needed. It is used to describe the characteristics of the data rows that need to be matched. 32 | 33 | We can generate and obtain an instance of a `Query` object by reading `io.query`. 34 | 35 | ```ts 36 | const query = io.product.query; 37 | query.compare('name', '=', 'book'); 38 | ``` 39 | 40 | In most cases of query requests, many scenarios involve comparing values to see if they match. `io.getQuery` supports a more convenient way to generate a Query instance. The example code below is equivalent to the one above: 41 | 42 | ```ts 43 | const query = io.getQuery({ name: 'book' }); 44 | ``` 45 | 46 | ### create record 47 | 48 | create a record: 49 | 50 | ```ts 51 | const product = await io.product.create({ name: 'New product' }); 52 | ``` 53 | 54 | create many record: 55 | 56 | ```ts 57 | const dataList = [ 58 | { name: 'Product 1', value: 100 }, 59 | { name: 'Product 2', value: 200 }, 60 | { name: 'Product 3', value: 300 }, 61 | ]; 62 | 63 | const { operation_result } = await io.product.createMany(dataList); 64 | console.log('result: ', operation_result); 65 | 66 | // or 67 | const result = await io.product.createMany(dataList, { plain: false }); 68 | console.log('result: ', result.data.operation_result); 69 | ``` 70 | 71 | ### update record 72 | 73 | ```ts 74 | const product = await io.product.update('productId', { name: 'product 2' }); 75 | ``` 76 | 77 | ### read record 78 | 79 | fetch record: 80 | 81 | ```ts 82 | const product = await io.product.get('recordId'); 83 | ``` 84 | 85 | fetch list: 86 | 87 | ```ts 88 | const query = io.query.compare('deleted', '=', false); 89 | const list = await io.channel.find(query, { offset: 0, limit: 20 }); 90 | ``` 91 | 92 | ### delete record 93 | 94 | delete a record: 95 | 96 | ```ts 97 | const result = await io.channel.delete('recordId', { offset: 0, limit: 20 }); 98 | ``` 99 | 100 | delete many record 101 | 102 | ```ts 103 | const query = io.query.compare('deleted', '=', true); 104 | const result = await io.channel.deleteMany(query, { offset: 0, limit: 20 }); 105 | ``` 106 | 107 | ### count 108 | 109 | fetch record count: 110 | 111 | ```ts 112 | const query = io.getQuery({ deleted: false }); 113 | const count = await io.channel.deleteMany(query); 114 | ``` 115 | 116 | ## Development 117 | 118 | ```bash 119 | # local develop 120 | pnpm watch 121 | 122 | # build package 123 | pnpm build 124 | 125 | # run test case 126 | pnpm test 127 | ``` 128 | -------------------------------------------------------------------------------- /packages/io/__tests__/io.test.js: -------------------------------------------------------------------------------- 1 | // 引入所需模块和初始化代码 2 | require('../tool/baas-init'); 3 | const { createIo } = require('..'); 4 | const TABLE_OPERATION_KEYS = ['create', 'get', 'update', 'delete']; 5 | 6 | describe('createIo functionality', () => { 7 | it('register table to io', async () => { 8 | const tables = ['product', 'channel']; 9 | const io = createIo({ tables }); 10 | 11 | tables.forEach(key => expect(io).toHaveProperty(key)); 12 | TABLE_OPERATION_KEYS.forEach(key => { 13 | expect(io.product).toHaveProperty(key); 14 | }); 15 | }); 16 | }); 17 | 18 | describe('IO operations defined correctly after table registration', () => { 19 | const tables = ['product']; 20 | let io; 21 | 22 | beforeEach(() => { 23 | io = createIo({ tables }); 24 | }); 25 | 26 | it('read table property should return an instance of BaaS.TableObject', () => { 27 | expect(io.product).toBeDefined(); 28 | expect(io.product.table).toBeDefined(); 29 | expect(io.product.table._tableID).toEqual('product'); 30 | }); 31 | 32 | it('`create` method should be defined and be a function', () => { 33 | expect(io.product.create).toBeDefined(); 34 | expect(typeof io.product.create).toBe('function'); 35 | }); 36 | 37 | it('`get` method should be defined and be a function', () => { 38 | expect(io.product.get).toBeDefined(); 39 | expect(typeof io.product.get).toBe('function'); 40 | }); 41 | 42 | it('`update` method should be defined and be a function', () => { 43 | expect(io.product.update).toBeDefined(); 44 | expect(typeof io.product.update).toBe('function'); 45 | }); 46 | 47 | it('`delete` method should be defined and be a function', () => { 48 | expect(io.product.delete).toBeDefined(); 49 | expect(typeof io.product.delete).toBe('function'); 50 | }); 51 | 52 | it('`find` method should be defined and be a function', () => { 53 | expect(io.product.find).toBeDefined(); 54 | expect(typeof io.product.find).toBe('function'); 55 | }); 56 | 57 | it('`count` method should be defined and be a function', () => { 58 | expect(io.product.count).toBeDefined(); 59 | expect(typeof io.product.count).toBe('function'); 60 | }); 61 | 62 | it('`createMany` method should be defined and be a function', () => { 63 | expect(io.product.createMany).toBeDefined(); 64 | expect(typeof io.product.createMany).toBe('function'); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /packages/io/__tests__/operation.test.js: -------------------------------------------------------------------------------- 1 | // 引入所需模块和初始化代码 2 | require('../tool/baas-init'); 3 | const { createIo } = require('..'); 4 | 5 | describe('Mocking CRUD Operations in TableObject', () => { 6 | const tables = ['product']; 7 | let io; 8 | 9 | beforeEach(() => { 10 | io = createIo({ tables }); 11 | 12 | io.product.create = jest 13 | .fn() 14 | .mockResolvedValue({ id: '1', name: 'Test product' }); 15 | io.product.get = jest.fn().mockResolvedValue({ 16 | id: '1', 17 | name: 'Test product', 18 | description: 'A product for testing', 19 | }); 20 | io.product.update = jest.fn().mockResolvedValue({ 21 | id: '1', 22 | name: 'Test product Updated', 23 | description: 'Updated description', 24 | }); 25 | io.product.delete = jest.fn().mockResolvedValue(true); 26 | io.product.find = jest.fn().mockResolvedValue({ 27 | meta: { limit: 20, next: null, offset: 0, previous: null }, 28 | objects: [ 29 | { id: 1, description: 'This is description.' }, 30 | { id: 2, description: 'This is description.' }, 31 | ], 32 | }); 33 | 34 | io.product.count = jest.fn().mockResolvedValue(5); 35 | }); 36 | 37 | it('should correctly call and mock `create` method', async () => { 38 | const productData = { name: 'Test Product' }; 39 | const result = await io.product.create(productData); 40 | 41 | expect(io.product.create).toHaveBeenCalledWith(productData); 42 | expect(result).toHaveProperty('id'); 43 | expect(result).toHaveProperty('name', 'Test Product'); 44 | }); 45 | 46 | it('should correctly call and mock `get` method', async () => { 47 | const productId = '1'; 48 | const result = await io.product.get(productId); 49 | 50 | expect(io.product.get).toHaveBeenCalledWith(productId); 51 | expect(result).toHaveProperty('id', productId); 52 | expect(result).toHaveProperty('name', 'Test Product'); 53 | expect(result).toHaveProperty('description'); 54 | }); 55 | 56 | it('should correctly call and mock `find` method', async () => { 57 | const query = io.getQuery({ 58 | description: 'This is description.', 59 | }); 60 | const result = await io.product.find(query, { 61 | select: ['id', 'description'], 62 | }); 63 | 64 | // 验证返回的结果是否符合预期 65 | expect(result).toEqual({ 66 | meta: { limit: 20, next: null, offset: 0, previous: null }, 67 | objects: [ 68 | { id: 1, description: 'This is description.' }, 69 | { id: 2, description: 'This is description.' }, 70 | ], 71 | }); 72 | }); 73 | 74 | it('should correctly call and mock `update` method', async () => { 75 | const productId = '1'; 76 | const updateData = { description: 'Updated description' }; 77 | const result = await io.product.update(productId, updateData); 78 | 79 | expect(io.product.update).toHaveBeenCalledWith(productId, updateData); 80 | expect(result).toHaveProperty('description', 'Updated description'); 81 | }); 82 | 83 | it('should correctly call and mock `delete` method', async () => { 84 | const productId = '1'; 85 | const result = await io.product.delete(productId); 86 | 87 | expect(io.product.delete).toHaveBeenCalledWith(productId); 88 | expect(result).toBe(true); 89 | }); 90 | 91 | it('should correctly call and mock `count` method', async () => { 92 | const query = { description: 'This is description.' }; 93 | 94 | // 调用 count 方法 95 | const countResult = await io.product.count(query); 96 | 97 | // 验证 count 方法是否被以正确的参数调用 98 | expect(io.product.count).toHaveBeenCalledWith(query); 99 | 100 | // 验证返回的计数值是否符合预期 101 | expect(countResult).toBe(5); 102 | }); 103 | }); 104 | 105 | describe('Mocking `createMany` method in TableObject', () => { 106 | const tables = ['product']; 107 | const dataList = [ 108 | { name: 'Product 1', value: 100 }, 109 | { name: 'Product 2', value: 200 }, 110 | { name: 'Product 3', value: 300 }, 111 | ]; 112 | const expectData = { 113 | operation_result: [ 114 | { success: { id: 1, name: 'Product 1', value: 100 } }, 115 | { success: { id: 2, name: 'Product 2', value: 200 } }, 116 | { success: { id: 3, name: 'Product 3', value: 300 } }, 117 | ], 118 | succeed: dataList.length, 119 | total_count: dataList.length, 120 | }; 121 | let io; 122 | 123 | beforeEach(() => { 124 | io = createIo({ tables }); 125 | 126 | io.product.createMany = jest 127 | .fn() 128 | .mockImplementation((dataList, { plain = true } = {}) => { 129 | const createdList = dataList.map((item, index) => { 130 | return { success: { ...item, id: index + 1 } }; 131 | }); 132 | const result = { 133 | operation_result: createdList, 134 | succeed: createdList.length, 135 | total_count: createdList.length, 136 | }; 137 | 138 | return Promise.resolve( 139 | plain 140 | ? result 141 | : { 142 | status: 200, 143 | statusText: 'OK', 144 | headers: {}, 145 | data: result, 146 | }, 147 | ); 148 | }); 149 | }); 150 | 151 | it('should correctly call and mock `createMany` method, when plain is default', async () => { 152 | const result = await io.product.createMany(dataList); 153 | 154 | // 验证 createMany 方法是否以默认参数调用 155 | expect(io.product.createMany).toHaveBeenCalledWith(dataList); 156 | expect(result).toEqual(expectData); 157 | }); 158 | 159 | it('should correctly call and mock `createMany` method, when plain is true', async () => { 160 | const result = await io.product.createMany(dataList, { plain: true }); 161 | 162 | expect(io.product.createMany).toHaveBeenCalledWith(dataList, { 163 | plain: true, 164 | }); 165 | expect(result).toEqual(expectData); 166 | }); 167 | 168 | it('should correctly call and mock `createMany` method, when plain is false', async () => { 169 | // 调用方法 170 | const result = await io.product.createMany(dataList, { plain: false }); 171 | 172 | expect(io.product.createMany).toHaveBeenCalledWith(dataList, { 173 | plain: false, 174 | }); 175 | expect(result).toEqual({ 176 | status: 200, 177 | statusText: 'OK', 178 | headers: {}, 179 | data: expectData, 180 | }); 181 | }); 182 | }); 183 | -------------------------------------------------------------------------------- /packages/io/config/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 知晓云内置表名数组 3 | */ 4 | export const DEFAULT_TABLE_NAMES = ['_userprofile']; 5 | -------------------------------------------------------------------------------- /packages/io/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/io", 3 | "version": "0.4.2", 4 | "description": "A more convenient tool for MinCloud IO requests, optimized for ease of use and efficiency.", 5 | "author": "anran758 ", 6 | "homepage": "https://github.com/anran758/mincloudx/tree/main/packages/io#readme", 7 | "license": "MIT", 8 | "main": "dist/main.js", 9 | "typings": "./lib/types/index.d.ts", 10 | "publishConfig": { 11 | "access": "public" 12 | }, 13 | "files": [ 14 | "dist" 15 | ], 16 | "keywords": [ 17 | "mincloudx", 18 | "mincloud", 19 | "typescript", 20 | "faas", 21 | "baas", 22 | "io" 23 | ], 24 | "scripts": { 25 | "prepublishOnly": "pnpm run build", 26 | "lint": "eslint .", 27 | "test": "jest --verbose", 28 | "build": "webpack --mode=production --node-env=production", 29 | "build:dev": "webpack --mode=development --node-env=development", 30 | "watch": "webpack --watch" 31 | }, 32 | "devDependencies": { 33 | "@mincloudx/baas": "workspace:*", 34 | "@mincloudx/types": "workspace:*", 35 | "@webpack-cli/generators": "^2.5.0", 36 | "terser-webpack-plugin": "^5.3.10", 37 | "ts-loader": "^9.3.1", 38 | "webpack": "^5.74.0", 39 | "webpack-cli": "^5.1.4" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/io/src/baas.ts: -------------------------------------------------------------------------------- 1 | export function getBaaS() { 2 | if (global?.BaaS) { 3 | return global?.BaaS; 4 | } 5 | 6 | throw new Error('BaaS is not initialized.'); 7 | } 8 | 9 | export function getBaseIo(BaaS = getBaaS()) { 10 | return { 11 | get query() { 12 | return new BaaS.Query(); 13 | }, 14 | 15 | get user() { 16 | return new BaaS.User(); 17 | }, 18 | 19 | get file() { 20 | return new BaaS.File(); 21 | }, 22 | 23 | table(tableName: string) { 24 | return new BaaS.TableObject(tableName); 25 | }, 26 | 27 | getQuery(data?: Record) { 28 | const query = new BaaS.Query(); 29 | if (!data) return query; 30 | 31 | // Provides a completely equivalent way to generate `Query` from passed object letters 32 | Object.entries(data).forEach(([key, value]) => { 33 | query.compare(key, '=', value); 34 | }); 35 | 36 | return query; 37 | }, 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /packages/io/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_ENABLE_TRIGGER = true; 2 | -------------------------------------------------------------------------------- /packages/io/src/createIo.ts: -------------------------------------------------------------------------------- 1 | import { getBaaS, getBaseIo } from './baas'; 2 | import { createTableOperation } from './operations'; 3 | import type { Operation } from './type'; 4 | 5 | export function createIo(options: { tables?: T[] } = {}) { 6 | const BaaS = getBaaS(); 7 | const io = getBaseIo(BaaS); 8 | 9 | const dynamicIo = {} as { [K in T]: Operation }; 10 | options.tables?.forEach(tableName => { 11 | dynamicIo[tableName] = createTableOperation(tableName); 12 | }); 13 | 14 | return Object.assign(dynamicIo, io); 15 | } 16 | -------------------------------------------------------------------------------- /packages/io/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './createIo'; 2 | export * from './baas'; 3 | -------------------------------------------------------------------------------- /packages/io/src/operations.ts: -------------------------------------------------------------------------------- 1 | import { getBaseIo } from './baas'; 2 | 3 | import type { 4 | Operation, 5 | DeleteOperation, 6 | UpdateOperation, 7 | OperatorData, 8 | QueryOperationOptions, 9 | MinCloudResponse, 10 | FindListResponseData, 11 | } from './type'; 12 | import { DEFAULT_ENABLE_TRIGGER } from './config'; 13 | 14 | const io = getBaseIo(); 15 | export function createTableOperation(tableName: string): Operation { 16 | return { 17 | get table() { 18 | return io.table(tableName); 19 | }, 20 | 21 | /** 22 | * Create new a row for the table 23 | */ 24 | async create(data, { plain = true } = {}) { 25 | const record = this.table.create(); 26 | 27 | return record 28 | .set(data) 29 | .save() 30 | .then(res => (plain ? res.data : res)); 31 | }, 32 | 33 | /** 34 | * Create new a row for the table 35 | */ 36 | async createMany( 37 | dataList, 38 | { plain = true, enableTrigger = DEFAULT_ENABLE_TRIGGER } = {}, 39 | ) { 40 | return this.table 41 | .createMany(dataList, { enableTrigger }) 42 | .then(res => (plain ? res.data : res)); 43 | }, 44 | 45 | async update(id, options = {}) { 46 | if (!id) { 47 | throw new Error('Missing required id parameter'); 48 | } 49 | 50 | return updateRecord(this.table, { 51 | ...options, 52 | id, 53 | }); 54 | }, 55 | 56 | async updateMany(options = {}) { 57 | return updateRecord(this.table, options); 58 | }, 59 | 60 | async get(id, { expand, select, plain = true } = {}) { 61 | const { table } = this; 62 | if (expand) table.expand(expand); 63 | if (select) table.select(select); 64 | 65 | return table.get(id).then(res => (plain ? res.data : res)); 66 | }, 67 | 68 | async find( 69 | query = io.query, 70 | { 71 | expand, 72 | select, 73 | offset = 0, 74 | limit = 20, 75 | orderBy = '-created_at', 76 | withCount = false, 77 | plain = true, 78 | } = {}, 79 | ) { 80 | return this.table 81 | .setQuery(query) 82 | .offset(offset) 83 | .limit(limit) 84 | .orderBy(orderBy) 85 | .expand(expand) 86 | .select(select) 87 | .find({ withCount }) 88 | .then(res => (plain ? res.data.objects : res)); 89 | }, 90 | 91 | /** 92 | * Find the first record that matches `Query` 93 | */ 94 | async first< 95 | Data extends object = OperatorData, 96 | Plain extends boolean = true, 97 | >( 98 | query = io.query, 99 | { 100 | expand, 101 | select, 102 | offset = 0, 103 | orderBy = '-created_at', 104 | plain = true, 105 | }: QueryOperationOptions = {}, 106 | ) { 107 | const result = await this.find(query, { 108 | expand, 109 | select, 110 | offset, 111 | orderBy, 112 | plain, 113 | limit: 1, 114 | }); 115 | 116 | if (plain) return result[0]; 117 | 118 | const response = result as MinCloudResponse>; 119 | return { 120 | ...result, 121 | data: response.data.objects[0], 122 | }; 123 | }, 124 | 125 | async delete(id, options = {}) { 126 | if (!id) { 127 | return Promise.reject(new Error('Missing required id parameter')); 128 | } 129 | 130 | return deleteRecord(this.table, { 131 | id, 132 | ...options, 133 | }); 134 | }, 135 | 136 | async deleteMany(query, options = {}) { 137 | if (!query) { 138 | return Promise.reject(new Error('Missing required query parameter')); 139 | } 140 | 141 | return deleteRecord(this.table, { 142 | query, 143 | ...options, 144 | }); 145 | }, 146 | 147 | async count(query) { 148 | return this.table.setQuery(query).count(); 149 | }, 150 | }; 151 | } 152 | 153 | const updateRecord = (table, options: UpdateOperation) => { 154 | const { 155 | id, 156 | query = io.query, 157 | data, 158 | unset, 159 | incrementBy, 160 | append, 161 | uAppend, 162 | remove, 163 | patchObject, 164 | offset = 0, 165 | limit, 166 | enableTrigger = DEFAULT_ENABLE_TRIGGER, 167 | withCount = false, 168 | plain = true, 169 | } = options || {}; 170 | 171 | if (query) { 172 | table.offset(offset); 173 | if (limit) table.limit(limit); 174 | } 175 | 176 | const record = table.getWithoutData(id || query); 177 | const each = (method, data) => 178 | Object.entries(data).forEach(([key, val]) => record[method](key, val)); 179 | 180 | if (data) each('set', data); 181 | if (unset) each('unset', unset); 182 | if (incrementBy) each('incrementBy', incrementBy); 183 | if (append) each('append', append); 184 | if (uAppend) each('uAppend', uAppend); 185 | if (remove) each('remove', remove); 186 | if (patchObject) each('patchObject', patchObject); 187 | 188 | return record 189 | .update({ enableTrigger, withCount }) 190 | .then(res => (plain ? res.data : res)); 191 | }; 192 | 193 | /** 194 | * delete data record 195 | */ 196 | function deleteRecord( 197 | table, 198 | { 199 | id, 200 | query = io.query, 201 | offset = 0, 202 | limit, 203 | plain = true, 204 | enableTrigger = DEFAULT_ENABLE_TRIGGER, 205 | withCount = false, 206 | }: DeleteOperation = {}, 207 | ) { 208 | if (query) { 209 | table.offset(offset); 210 | if (limit) table.limit(limit); 211 | } 212 | 213 | return table 214 | .delete(id || query, { enableTrigger, withCount }) 215 | .then(res => (plain ? res.data : res)); 216 | } 217 | -------------------------------------------------------------------------------- /packages/io/src/type.ts: -------------------------------------------------------------------------------- 1 | import type { IncomingHttpHeaders } from 'http'; 2 | import type { BaaS } from '@mincloudx/types'; 3 | 4 | export interface Meta { 5 | limit: number; 6 | next: string | null; 7 | offset: number; 8 | previous: string | null; 9 | total_count?: number; 10 | } 11 | 12 | export type OperatorData = { 13 | [key: string | number]: any; 14 | }; 15 | 16 | export type FindListResponseData = { 17 | meta: Meta; 18 | objects: Data[]; 19 | }; 20 | 21 | export type RecordId = string | number; 22 | 23 | export interface MinCloudResponse { 24 | status: number; 25 | statusText: string; 26 | headers: IncomingHttpHeaders; 27 | data: Data; 28 | } 29 | 30 | export interface BasicOperationOptions { 31 | plain?: boolean; 32 | } 33 | 34 | export interface QueryParam { 35 | offset: number; 36 | limit: number; 37 | } 38 | 39 | export interface TableRecord { 40 | id: RecordId; 41 | [key: string | number]: any; 42 | } 43 | 44 | export interface BatchActionParams { 45 | enableTrigger?: boolean; 46 | withCount?: boolean; 47 | expand?: string | string[]; 48 | } 49 | 50 | export type OperationResult = ( 51 | | { success: Data } 52 | | { 53 | error: { 54 | code: number; 55 | err_msg: string; 56 | }; 57 | } 58 | )[]; 59 | 60 | /** 61 | * The data format returned by batch operations 62 | */ 63 | export interface BatchActionResult 64 | extends QueryParam { 65 | operation_result: OperationResult; 66 | succeed: number; 67 | total_count: number; 68 | next: string | null; 69 | } 70 | 71 | export type CreateManyResult = Pick< 72 | BatchActionResult<{ id: string; created_at: number }>, 73 | 'operation_result' | 'succeed' | 'total_count' 74 | >; 75 | 76 | export type QueryOperationOptions = BasicOperationOptions & 77 | Omit & 78 | Partial & { 79 | select?: string[]; 80 | orderBy?: string | string[]; 81 | }; 82 | 83 | export type UpdateOperation = BasicOperationOptions & 84 | Omit & 85 | Partial & { 86 | id?: RecordId; 87 | query?: BaaS.Query; 88 | data?: Record; 89 | unset?: Record; 90 | incrementBy?: Record; 91 | append?: Record; 92 | uAppend?: Record; 93 | remove?: Record; 94 | patchObject?: Record; 95 | }; 96 | 97 | export interface DeleteOperation 98 | extends Omit, 99 | BasicOperationOptions, 100 | Partial { 101 | id?: RecordId; 102 | query?: BaaS.Query; 103 | } 104 | 105 | export type OperationResponse< 106 | Data = any, 107 | Plain extends boolean = true, 108 | > = Plain extends true ? Promise : Promise>; 109 | 110 | export interface Operation { 111 | readonly table: BaaS.TableObject; 112 | create: ( 113 | data: Data, 114 | options?: BasicOperationOptions, 115 | ) => OperationResponse; 116 | createMany: < 117 | Data extends object = OperatorData, 118 | Plain extends boolean = true, 119 | >( 120 | dataList: Array, 121 | options?: BasicOperationOptions & Pick, 122 | ) => OperationResponse; 123 | get: ( 124 | id: RecordId, 125 | options?: Omit, 126 | ) => OperationResponse; 127 | find: ( 128 | query: BaaS.Query, 129 | options?: QueryOperationOptions, 130 | ) => OperationResponse>, Plain>; 131 | first: ( 132 | query: BaaS.Query, 133 | options?: QueryOperationOptions, 134 | ) => OperationResponse; 135 | update: ( 136 | id: UpdateOperation['id'], 137 | options: Omit, 138 | ) => OperationResponse; 139 | updateMany: ( 140 | options: Omit, 141 | ) => OperationResponse< 142 | BatchActionResult<{ id: string; updated_at: number }>, 143 | Plain 144 | >; 145 | delete: ( 146 | id: DeleteOperation['id'], 147 | options?: Omit, 148 | ) => OperationResponse<'', false>; 149 | deleteMany: ( 150 | query: DeleteOperation['query'], 151 | options?: Omit, 152 | ) => OperationResponse< 153 | Pick, 154 | Plain 155 | >; 156 | count: (query: BaaS.Query) => Promise; 157 | } 158 | -------------------------------------------------------------------------------- /packages/io/tool/baas-init.js: -------------------------------------------------------------------------------- 1 | global.BaaS = require('@mincloudx/baas'); 2 | global.__FAAS_EVENT = { 3 | ...global.__FAAS_EVENT, 4 | miniappId: process.env.TEST_MINI_APP_ID, 5 | token: process.env.TEST_MINI_APP_TOKEN, 6 | }; 7 | -------------------------------------------------------------------------------- /packages/io/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src", "test", "types", "tool/baas-init.ts"], 4 | "exclude": ["**/*.test.ts"], 5 | "compilerOptions": { 6 | "typeRoots": [ 7 | "../../node_modules/@types", 8 | "./node_modules/@types", 9 | "./types" 10 | ], 11 | "noImplicitAny": false, 12 | "target": "es2015", 13 | "module": "Node16", 14 | "moduleResolution": "Node16", 15 | "lib": ["es2015"], 16 | "declarationDir": "lib/types", 17 | "outDir": "lib", 18 | "rootDir": "./src", 19 | "baseUrl": "." 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/io/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { BaaS as BaaSModule } from '@mincloudx/types'; 2 | 3 | declare global { 4 | // eslint-disable-next-line no-var 5 | var BaaS: typeof BaaSModule; 6 | // var BaaS: any; 7 | } 8 | 9 | // eslint-disable-next-line no-var 10 | declare var BaaS: any; 11 | 12 | export {}; 13 | -------------------------------------------------------------------------------- /packages/io/webpack.config.js: -------------------------------------------------------------------------------- 1 | const TerserPlugin = require('terser-webpack-plugin'); 2 | const path = require('path'); 3 | 4 | const isProduction = process.env.NODE_ENV == 'production'; 5 | 6 | module.exports = () => { 7 | return { 8 | mode: isProduction ? 'production' : 'development', 9 | entry: './src/index.ts', 10 | output: { 11 | path: path.resolve(__dirname, 'dist'), 12 | libraryTarget: 'umd', 13 | globalObject: 'this', 14 | }, 15 | plugins: [ 16 | // Add your plugins here 17 | // Learn more about plugins from https://webpack.js.org/configuration/plugins/ 18 | ], 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.(ts|tsx)$/i, 23 | loader: 'ts-loader', 24 | exclude: ['/node_modules/'], 25 | }, 26 | ], 27 | }, 28 | resolve: { 29 | alias: { 30 | '@': path.resolve(__dirname, './src'), 31 | }, 32 | extensions: ['.ts', '.js'], 33 | fallback: { path: false }, 34 | }, 35 | optimization: { 36 | minimize: true, 37 | minimizer: [ 38 | new TerserPlugin({ 39 | terserOptions: { 40 | format: { 41 | comments: /@license/i, 42 | }, 43 | }, 44 | extractComments: false, 45 | }), 46 | ], 47 | }, 48 | }; 49 | }; 50 | -------------------------------------------------------------------------------- /packages/types/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## [0.4.2](https://github.com/anran758/mincloudx/compare/v4.0.2...v0.4.2) (2024-07-25) 7 | 8 | **Note:** Version bump only for package @mincloudx/types 9 | 10 | ## [0.4.1](https://github.com/anran758/mincloudx/compare/v4.0.1...v0.4.1) (2024-07-18) 11 | 12 | **Note:** Version bump only for package @mincloudx/types 13 | 14 | # [0.4.0](https://github.com/anran758/mincloudx/compare/v0.1.1...v0.4.0) (2024-04-19) 15 | 16 | ### Bug Fixes 17 | 18 | - **faas:** fixed the issue where createFaas could not be called properly ([00b0b19](https://github.com/anran758/mincloudx/commit/00b0b194ab165332fd3c9058649e89ce9e99e8f7)) 19 | 20 | ### Features 21 | 22 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 23 | - **io:** io support crud function, update faas-demo example ([d67f377](https://github.com/anran758/mincloudx/commit/d67f377c564d0935679c06d2c5c357d064321aae)) 24 | - **types:** abstract the common TypeScript type files into the a separate package ([cc8fc2c](https://github.com/anran758/mincloudx/commit/cc8fc2cb64865a330043afc800150aca7abca6d1)) 25 | 26 | ## [0.1.1](https://github.com/anran758/mincloudx/compare/@mincloudx/types@0.1.0...@mincloudx/types@0.1.1) (2024-03-30) 27 | 28 | **Note:** Version bump only for package @mincloudx/types 29 | 30 | # [0.1.0](https://github.com/anran758/mincloudx/compare/@mincloudx/types@0.0.1...@mincloudx/types@0.1.0) (2024-03-21) 31 | 32 | ### Features 33 | 34 | - added baas sdk lib as a local project test, supplement type ([01f3cc6](https://github.com/anran758/mincloudx/commit/01f3cc6ab6a993a0f27f2c14deb1ec525e7c3c52)) 35 | - **io:** io support crud function, update faas-demo example ([d67f377](https://github.com/anran758/mincloudx/commit/d67f377c564d0935679c06d2c5c357d064321aae)) 36 | 37 | ## 0.0.1 (2024-03-11) 38 | 39 | ### Bug Fixes 40 | 41 | - **faas:** fixed the issue where createFaas could not be called properly ([00b0b19](https://github.com/anran758/mincloudx/commit/00b0b194ab165332fd3c9058649e89ce9e99e8f7)) 42 | 43 | ### Features 44 | 45 | - **types:** abstract the common TypeScript type files into the a separate package ([cc8fc2c](https://github.com/anran758/mincloudx/commit/cc8fc2cb64865a330043afc800150aca7abca6d1)) 46 | -------------------------------------------------------------------------------- /packages/types/README.md: -------------------------------------------------------------------------------- 1 | # @mincloudx/types 2 | 3 | ![Version](https://badgen.net/npm/v/@mincloudx/types) 4 | ![TypeScript](https://badgen.net/badge/-/TypeScript?icon=typescript&label&labelColor=blue&color=555555) 5 | 6 | Common TypeScript types in MinCloud. 7 | 8 | ## Usage 9 | 10 | ```bash 11 | pnpm install @mincloudx/types 12 | 13 | # or use npm 14 | npm install @mincloudx/types 15 | ``` 16 | 17 | When we need to import the corresponding types, we can do so through the import statement: 18 | 19 | ```ts 20 | import type { FaaS } from '@mincloudx/types'; 21 | 22 | interface EventData { 23 | productId: string; 24 | name?: string; 25 | } 26 | 27 | export default async function userDefinedFunctionProxy( 28 | evt: FaaS.Event, 29 | ) { 30 | const { productId, name = 'mincloudx' } = evt.data; 31 | 32 | return `${name}_${productId}`; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /packages/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@mincloudx/types", 3 | "version": "0.4.2", 4 | "description": "Common TypeScript types in MinCloud.", 5 | "author": "anran758 ", 6 | "license": "MIT", 7 | "main": "./types/index.d.ts", 8 | "types": "./types/index.d.ts", 9 | "keywords": [ 10 | "mincloudx", 11 | "mincloud", 12 | "faas", 13 | "baas", 14 | "typescript" 15 | ], 16 | "publishConfig": { 17 | "access": "public" 18 | }, 19 | "files": [ 20 | "types" 21 | ], 22 | "scripts": { 23 | "test": "echo \"Error: no test specified\" && exit 1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/AlipayProfitSharingOrder.d.ts: -------------------------------------------------------------------------------- 1 | export = AlipayProfitSharingOrder; 2 | declare class AlipayProfitSharingOrder extends BaseQuery { 3 | getOrderList(params?: Record): any; 4 | } 5 | import BaseQuery = require('./BaseQuery'); 6 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/BaseQuery.d.ts: -------------------------------------------------------------------------------- 1 | export = BaseQuery; 2 | declare class BaseQuery { 3 | _initQueryParams(): void; 4 | _queryObject: any; 5 | _limit: any; 6 | _offset: any; 7 | _orderBy: any; 8 | _keys: any; 9 | _expand: any; 10 | setQuery(queryObject: any): this; 11 | select(args: any): this; 12 | expand(args: any): this; 13 | limit(value: any): this; 14 | offset(value: any): this; 15 | orderBy(args: any): this; 16 | _handleAllQueryConditions(): { 17 | limit: any; 18 | offset: any; 19 | order_by: any; 20 | keys: any; 21 | expand: any; 22 | where: string; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/BaseRecord.d.ts: -------------------------------------------------------------------------------- 1 | export = BaseRecord; 2 | declare class BaseRecord { 3 | constructor(recordID: any); 4 | _recordID: any; 5 | _recordValueInit(): void; 6 | _record: { 7 | $set: Record; 8 | $unset: Record; 9 | }; 10 | set(...args: any[]): this; 11 | unset(...args: any[]): this; 12 | incrementBy(key: any, value: any): this; 13 | append(key: any, value: any): this; 14 | uAppend(key: any, value: any): this; 15 | remove(key: any, value: any): this; 16 | patchObject(key: any, value: any): this; 17 | pop(key: any): this; 18 | shift(key: any): this; 19 | } 20 | declare namespace BaseRecord { 21 | export { _serializeValueFuncFactory }; 22 | } 23 | declare function _serializeValueFuncFactory( 24 | config?: string[], 25 | ): (value: any) => any; 26 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/Content.d.ts: -------------------------------------------------------------------------------- 1 | export = Content; 2 | declare class Content extends BaseQuery { 3 | constructor(groupID: any); 4 | _groupID: any; 5 | _defaultQuery: Query; 6 | get(contentID: any): any; 7 | create(): ContentRecord; 8 | getWithoutData(contentID: any): ContentRecord; 9 | /** 10 | * 设置 withCount 默认值为 true,以兼容旧的用法 11 | */ 12 | find({ withCount }?: { withCount?: any }): any; 13 | count(): any; 14 | delete(contentID: any): any; 15 | } 16 | import BaseQuery = require('./BaseQuery'); 17 | import Query = require('./Query'); 18 | import ContentRecord = require('./ContentRecord'); 19 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/ContentCategory.d.ts: -------------------------------------------------------------------------------- 1 | export = ContentCategory; 2 | declare class ContentCategory extends BaseQuery { 3 | constructor(groupID: any); 4 | _groupID: any; 5 | get(categoryID: any): any; 6 | /** 7 | * 设置 withCount 默认值为 true,以兼容旧的用法 8 | */ 9 | find({ withCount }?: { withCount?: any }): any; 10 | count(): any; 11 | create(data: any): any; 12 | update(categoryID: any, data: any): any; 13 | delete(categoryID: any): any; 14 | } 15 | import BaseQuery = require('./BaseQuery'); 16 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/ContentGroup.d.ts: -------------------------------------------------------------------------------- 1 | export = ContentGroup; 2 | declare class ContentGroup extends BaseQuery { 3 | static get(id: any): any; 4 | static find({ 5 | offset, 6 | limit, 7 | withCount, 8 | }?: { 9 | offset?: number; 10 | limit?: number; 11 | withCount?: boolean; 12 | }): any; 13 | constructor(contentGroupID: any); 14 | _contentGroupID: any; 15 | getContent(richTextID: any): any; 16 | /** 17 | * 设置 withCount 默认值为 true,以兼容旧的用法 18 | */ 19 | find({ withCount }?: { withCount?: any }): any; 20 | count(): any; 21 | getCategory(categoryID: any): any; 22 | /** 23 | * 设置 withCount 默认值为 true,以兼容旧的用法 24 | */ 25 | getCategoryList({ withCount }?: { withCount?: any }): any; 26 | } 27 | import BaseQuery = require('./BaseQuery'); 28 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/ContentRecord.d.ts: -------------------------------------------------------------------------------- 1 | export = ContentRecord; 2 | declare class ContentRecord extends BaseRecord { 3 | constructor(groupID: any, recordID: any); 4 | _groupID: any; 5 | save(): any; 6 | update(): any; 7 | } 8 | import BaseRecord = require('./BaseRecord'); 9 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/File.d.ts: -------------------------------------------------------------------------------- 1 | export = File; 2 | declare class File extends BaseQuery { 3 | delete(id: any): any; 4 | get(fileID: any): any; 5 | /** 6 | * 设置 withCount 默认值为 true,以兼容旧的用法 7 | */ 8 | find({ withCount }?: { withCount?: any }): any; 9 | createDownloadTask(...args: any[]): any; 10 | getDownloadTaskResult(...args: any[]): any; 11 | count(): any; 12 | upload(uploadFile: any, fileMeta: any): Promise; 13 | purgeCache(operation_type: any, content: any): any; 14 | getPurgeCacheHistory(params: any): any; 15 | } 16 | import BaseQuery = require('./BaseQuery'); 17 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/FileCategory.d.ts: -------------------------------------------------------------------------------- 1 | export = FileCategory; 2 | declare class FileCategory extends BaseQuery { 3 | get(categoryID: any): any; 4 | /** 5 | * 设置 withCount 默认值为 true,以兼容旧的用法 6 | */ 7 | find({ withCount }?: { withCount?: any }): any; 8 | count(): any; 9 | create(data: any): any; 10 | update(categoryID: any, data: any): any; 11 | delete(categoryID: any): any; 12 | } 13 | import BaseQuery = require('./BaseQuery'); 14 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/GeoPoint.d.ts: -------------------------------------------------------------------------------- 1 | export = GeoPoint; 2 | declare class GeoPoint { 3 | constructor(latitude: any, longitude: any); 4 | longitude: any; 5 | latitude: any; 6 | geoJSON: { 7 | type: string; 8 | coordinates: any[]; 9 | }; 10 | toGeoJSON(): any; 11 | } 12 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/GeoPolygon.d.ts: -------------------------------------------------------------------------------- 1 | export = GeoPolygon; 2 | declare class GeoPolygon { 3 | constructor(args: any); 4 | points: any[]; 5 | geoJSON: { 6 | type: string; 7 | coordinates: any[]; 8 | }; 9 | toGeoJSON(): any; 10 | } 11 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/HError.d.ts: -------------------------------------------------------------------------------- 1 | export = HError; 2 | declare class HError { 3 | constructor(code: any, msg: any); 4 | mapErrorMessage( 5 | code: any, 6 | ): 7 | | 'uninitialized' 8 | | 'network disconnected' 9 | | 'request timeout' 10 | | 'unauthorized' 11 | | 'session missing' 12 | | 'incorrect parameter type' 13 | | 'payment cancelled' 14 | | 'payment failed' 15 | | 'save failed' 16 | | 'unknown error'; 17 | } 18 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/MobileTopup.d.ts: -------------------------------------------------------------------------------- 1 | export = MobileTopup; 2 | declare class MobileTopup extends BaseQuery { 3 | getMobileTopUpList(params: any): any; 4 | topUpMobile(data: any): any; 5 | } 6 | import BaseQuery = require('./BaseQuery'); 7 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/Order.d.ts: -------------------------------------------------------------------------------- 1 | export = Order; 2 | declare class Order extends BaseQuery { 3 | get wechatPay(): { 4 | profitSharing: (data: any) => any; 5 | multiProfitSharing: (data: any) => any; 6 | }; 7 | get alipay(): { 8 | profitSharing: (data: any) => any; 9 | }; 10 | getOrderList(params?: Record): any; 11 | } 12 | import BaseQuery = require('./BaseQuery'); 13 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/PeopleAlive.d.ts: -------------------------------------------------------------------------------- 1 | export = PeopleAlive; 2 | declare class PeopleAlive extends BaseQuery { 3 | checkPeopleAlive(data: any): any; 4 | } 5 | import BaseQuery = require('./BaseQuery'); 6 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/Query.d.ts: -------------------------------------------------------------------------------- 1 | export = Query; 2 | declare class Query { 3 | static and(...queryObjects: any[]): Query; 4 | static or(...queryObjects: any[]): Query; 5 | queryObject: Record; 6 | compare(key: any, operator: any, value: any): Query; 7 | contains(key: any, str: any): Query; 8 | matches(key: any, regExp: any): Query; 9 | in(key: any, arr: any): Query; 10 | notIn(key: any, arr: any): Query; 11 | arrayContains(key: any, arr: any): Query; 12 | isNull(key: any): Query; 13 | isNotNull(key: any): Query; 14 | exists(key: any): Query; 15 | notExists(key: any): Query; 16 | include(key: any, point: any): Query; 17 | within(key: any, polygon: any): Query; 18 | withinCircle(key: any, point: any, radius: any): Query; 19 | withinRegion( 20 | key: any, 21 | point: any, 22 | maxDistance: any, 23 | minDistance?: number, 24 | ): Query; 25 | hasKey(key: any, fieldName: any): Query; 26 | _setQueryObject(queryObject: any): void; 27 | _addQueryObject(key: any, obj: any): void; 28 | _parseRegExp(regExp: any): any[]; 29 | } 30 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/RedPack.d.ts: -------------------------------------------------------------------------------- 1 | export = RedPack; 2 | declare class RedPack { 3 | sendRedPack(params: any): any; 4 | getSentRedPackList(params: any): any; 5 | getSentRedPack(params: any): any; 6 | getRedPackStatus(params: any): any; 7 | } 8 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/TableObject.d.ts: -------------------------------------------------------------------------------- 1 | export = TableObject; 2 | declare class TableObject extends BaseQuery { 3 | constructor(tableID: any); 4 | _tableID: any; 5 | create(): TableRecord; 6 | createMany( 7 | args: any, 8 | { 9 | enableTrigger, 10 | }?: { 11 | enableTrigger?: boolean; 12 | }, 13 | ): Promise; 14 | /** 15 | * 设置 withCount 默认值为 true,以兼容旧的用法 16 | */ 17 | delete( 18 | args: any, 19 | { 20 | enableTrigger, 21 | withCount, 22 | }?: { 23 | enableTrigger?: boolean; 24 | withCount?: any; 25 | }, 26 | ): Promise; 27 | getWithoutData(args: any): TableRecord; 28 | get(recordID: any): Promise; 29 | /** 30 | * 设置 withCount 默认值为 true,以兼容旧的用法 31 | */ 32 | find({ withCount }?: { withCount?: any }): Promise; 33 | count(): Promise; 34 | importData( 35 | { 36 | dataFileUrl, 37 | dataFile, 38 | }: { 39 | dataFileUrl: any; 40 | dataFile: any; 41 | }, 42 | fileType: any, 43 | ): Promise; 44 | exportData(fileType: any, mode: any, start: any, end: any): Promise; 45 | } 46 | import BaseQuery = require('./BaseQuery'); 47 | import TableRecord = require('./TableRecord'); 48 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/TableRecord.d.ts: -------------------------------------------------------------------------------- 1 | export = TableRecord; 2 | declare class TableRecord extends BaseRecord { 3 | constructor(tableID: any, recordID: any, queryObject?: Record); 4 | _tableID: any; 5 | _queryObject: Record; 6 | save(): any; 7 | /** 8 | * 设置 withCount 默认值为 true,以兼容旧的用法 9 | */ 10 | update({ 11 | enableTrigger, 12 | withCount, 13 | }?: { 14 | enableTrigger?: boolean; 15 | withCount?: any; 16 | }): any; 17 | } 18 | import BaseRecord = require('./BaseRecord'); 19 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/TableSchema.d.ts: -------------------------------------------------------------------------------- 1 | export = TableSchema; 2 | declare class TableSchema { 3 | getSchema(...args: any[]): any; 4 | getSchemaList(...args: any[]): any; 5 | updateSchema(...args: any[]): any; 6 | createSchema(...args: any[]): any; 7 | deleteSchema(...args: any[]): any; 8 | } 9 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/UrlScheme.d.ts: -------------------------------------------------------------------------------- 1 | export = UrlScheme; 2 | declare class UrlScheme extends BaseQuery { 3 | /** 4 | * 获取微信小程序 URL Scheme 码列表 5 | * @return {*} 6 | */ 7 | getUrlSchemeList(): any; 8 | /** 9 | * 获取单个微信小程序 URL Scheme 码 10 | * @param id 11 | * @return {*} 12 | */ 13 | get(id: any): any; 14 | /** 15 | * 创建单个微信小程序 URL Scheme 码 16 | * @param options 17 | */ 18 | generate(options?: Record): any; 19 | /** 20 | * 删除单个微信小程序 URL Scheme 码 21 | * @param id 22 | */ 23 | delete(id: any): any; 24 | } 25 | import BaseQuery = require('./BaseQuery'); 26 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/User.d.ts: -------------------------------------------------------------------------------- 1 | export = User; 2 | declare class User extends BaseQuery { 3 | create(): UserRecord; 4 | get(userID: any): any; 5 | getWithoutData(args: any): UserRecord; 6 | /** 7 | * 设置 withCount 默认值为 true,以兼容旧的用法 8 | */ 9 | find({ withCount }?: { withCount?: any }): any; 10 | count(): any; 11 | delete(userID: any): any; 12 | } 13 | declare namespace User { 14 | export { stripGroupQuery as _stripGroupQuery }; 15 | } 16 | import BaseQuery = require('./BaseQuery'); 17 | import UserRecord = require('./UserRecord'); 18 | /** 19 | * 剥离 _group 查询 20 | * @param queryObj 21 | */ 22 | declare function stripGroupQuery(queryObj: any): any; 23 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/UserGroup.d.ts: -------------------------------------------------------------------------------- 1 | export = UserGroup; 2 | declare class UserGroup extends BaseQuery { 3 | /** 4 | * 获取用户组信息 5 | * @param groupID 6 | * @return {*} 7 | */ 8 | get(groupID: any): any; 9 | /** 10 | * 创建用户组 11 | * @param name 12 | * @param parent 13 | */ 14 | create({ name, parent }: { name: any; parent: any }): any; 15 | /** 16 | * 修改用户组 17 | * @param groupID 18 | * @param data 19 | */ 20 | update(groupID: any, data: any): any; 21 | /** 22 | * 批量删除用户组 23 | * @param {Array} ids 24 | */ 25 | delete(ids: any[]): any; 26 | /** 27 | * 将用户加入组 28 | * @param users 29 | * @param groups 30 | */ 31 | addUserIntoGroup(users: any, groups: any): any; 32 | /** 33 | * 将用户移除用户组 34 | * @param users 35 | * @param groups 36 | */ 37 | removeUserFromGroup(users: any, groups: any): any; 38 | /** 39 | * 查询用户组 40 | * @param parentID 用户组的组集 ID 41 | * @return {*} 42 | */ 43 | getUserGroupList({ parentID }: { parentID: any }): any; 44 | } 45 | import BaseQuery = require('./BaseQuery'); 46 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/UserRecord.d.ts: -------------------------------------------------------------------------------- 1 | export = UserRecord; 2 | declare class UserRecord extends BaseRecord { 3 | constructor(userID: any, queryObject?: Record); 4 | _queryObject: Record; 5 | save(): any; 6 | /** 7 | * 设置 withCount 默认值为 true,以兼容旧的用法 8 | */ 9 | update({ 10 | enableTrigger, 11 | withCount, 12 | }?: { 13 | enableTrigger?: boolean; 14 | withCount?: any; 15 | }): any; 16 | setAccount(data: any): any; 17 | } 18 | import BaseRecord = require('./BaseRecord'); 19 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/UserSuperGroup.d.ts: -------------------------------------------------------------------------------- 1 | export = UserSuperGroup; 2 | declare class UserSuperGroup extends BaseQuery { 3 | /** 4 | * 获取特定的组集信息 5 | * @param superGroupID 6 | * @return {*} 7 | */ 8 | get(superGroupID: any): any; 9 | /** 10 | * 创建组集 11 | * @param name 组集的名称 12 | * @param children 用户组 ID 列表 13 | */ 14 | create({ name, children }: { name: any; children: any }): any; 15 | /** 16 | * 修改组集 17 | * @param id 18 | * @param data 19 | * @param data.name 组集名称 20 | * @param data.children 用户组 ID 列表 21 | */ 22 | update(id: any, data: any): any; 23 | /** 24 | * 批量删除组集 25 | * @param ids 26 | */ 27 | delete(ids: any): any; 28 | /** 29 | * 获取组集列表 30 | * @return {*} 31 | */ 32 | getUserSuperGroupList(): any; 33 | } 34 | import BaseQuery = require('./BaseQuery'); 35 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/Validator.d.ts: -------------------------------------------------------------------------------- 1 | export = Validator; 2 | declare class Validator { 3 | constructor(handlers: any); 4 | _handlers: any; 5 | _defaultHandler(): boolean; 6 | _getHandler(eventType: any): any; 7 | validate(event: any): any; 8 | } 9 | -------------------------------------------------------------------------------- /packages/types/types/baas/class/WechatProfitSharingOrder.d.ts: -------------------------------------------------------------------------------- 1 | export = WechatProfitSharingOrder; 2 | declare class WechatProfitSharingOrder extends BaseQuery { 3 | get finish(): (data: any) => any; 4 | get refund(): (data: any) => any; 5 | get getRefundmentOrder(): (data: any) => any; 6 | getOrderList(params?: Record): any; 7 | } 8 | import BaseQuery = require('./BaseQuery'); 9 | -------------------------------------------------------------------------------- /packages/types/types/baas/function.d.ts: -------------------------------------------------------------------------------- 1 | export function invokeFunction( 2 | functionName: any, 3 | params: any, 4 | sync?: boolean, 5 | ): any; 6 | export function invoke(functionName: any, params: any, sync?: boolean): any; 7 | export function sendEmail(data: any): any; 8 | export function sendTemplateMessage(data: any): any; 9 | export function sendAlipayTemplateMessage(data: any): any; 10 | export function sendQQTemplateMessage(data: any): any; 11 | export function sendBaiduTemplateMessage(data: any): any; 12 | export function sendBytedanceTemplateMessage(data: any): any; 13 | export function getOrderList(params: any): any; 14 | export function refund(data: any): any; 15 | export function wxAccessToken(signKey: any): any; 16 | export function wxAccessToken(signKey: any): any; 17 | export function wxCensorImage(fileID: any): any; 18 | export function wxCensorImage(fileID: any): any; 19 | export function wxCensorText(text: any): any; 20 | export function wxCensorText(text: any): any; 21 | export function wxDecryptData(data: any): any; 22 | export function wxDecryptData(data: any): any; 23 | export function qqCensorImage(fileID: any): any; 24 | export function qqCensorImage(fileID: any): any; 25 | export function qqCensorText(text: any): any; 26 | export function qqCensorText(text: any): any; 27 | export function alipayCensorText(text: any): any; 28 | export function alipayCensorText(text: any): any; 29 | export function wxPromotionTransfer(data: any): any; 30 | export function wxPromotionTransfer(data: any): any; 31 | export function sendSmsCode(params: any): any; 32 | export function sendSmsCode(params: any): any; 33 | export function sendSmsMessage(params: any): any; 34 | export function sendSmsMessage(params: any): any; 35 | export function verifySmsCode({ 36 | phone, 37 | code, 38 | userID, 39 | }: { 40 | phone: any; 41 | code: any; 42 | userID: any; 43 | }): any; 44 | export function verifySmsCode({ 45 | phone, 46 | code, 47 | userID, 48 | }: { 49 | phone: any; 50 | code: any; 51 | userID: any; 52 | }): any; 53 | export function updateWeChatUserInfo( 54 | userID: any, 55 | authData: any, 56 | { 57 | syncUserProfile, 58 | }?: { 59 | syncUserProfile?: string; 60 | }, 61 | ): any; 62 | export function updateWeChatUserInfo( 63 | userID: any, 64 | authData: any, 65 | { 66 | syncUserProfile, 67 | }?: { 68 | syncUserProfile?: string; 69 | }, 70 | ): any; 71 | export function getWXACode( 72 | type: any, 73 | params: any, 74 | cdn: any, 75 | categoryName: any, 76 | ): any; 77 | export function getWXACode( 78 | type: any, 79 | params: any, 80 | cdn: any, 81 | categoryName: any, 82 | ): any; 83 | export function getTemplateMsgTicketCount(options?: Record): any; 84 | export function getTemplateMsgTicketCount(options?: Record): any; 85 | export function getAlipayTemplateMsgTicketCount( 86 | options?: Record, 87 | ): any; 88 | export function getAlipayTemplateMsgTicketCount( 89 | options?: Record, 90 | ): any; 91 | export function getQQTemplateMsgTicketCount(options?: Record): any; 92 | export function getQQTemplateMsgTicketCount(options?: Record): any; 93 | export function getBaiduTemplateMsgTicketCount(options?: Record): any; 94 | export function getBaiduTemplateMsgTicketCount(options?: Record): any; 95 | export function getBytedanceTemplateMsgTicketCount( 96 | options?: Record, 97 | ): any; 98 | export function getBytedanceTemplateMsgTicketCount( 99 | options?: Record, 100 | ): any; 101 | export function getWxSubscribeMsgTicketCount(options?: Record): any; 102 | export function getWxSubscribeMsgTicketCount(options?: Record): any; 103 | export function getQQSubscribeMsgTicketCount(options?: Record): any; 104 | export function getQQSubscribeMsgTicketCount(options?: Record): any; 105 | export function sendWechatSubscribeMessage(options?: Record): any; 106 | export function sendWechatSubscribeMessage(options?: Record): any; 107 | export function sendQQSubscribeMessage(options?: Record): any; 108 | export function sendQQSubscribeMessage(options?: Record): any; 109 | export function getAlipayQRCode(data: any): any; 110 | export function getAlipayQRCode(data: any): any; 111 | export function getAsyncJobResult(id: any): any; 112 | export function getAsyncJobResult(id: any): any; 113 | export function getWxUserRiskRank(options?: Record): any; 114 | export function getWxUserRiskRank(options?: Record): any; 115 | export function createWxActivityID(options?: Record): any; 116 | export function createWxActivityID(options?: Record): any; 117 | -------------------------------------------------------------------------------- /packages/types/types/baas/index.d.ts: -------------------------------------------------------------------------------- 1 | import Content = require('./class/Content'); 2 | import ContentGroup = require('./class/ContentGroup'); 3 | import ContentCategory = require('./class/ContentCategory'); 4 | import File = require('./class/File'); 5 | import FileCategory = require('./class/FileCategory'); 6 | import GeoPoint = require('./class/GeoPoint'); 7 | import GeoPolygon = require('./class/GeoPolygon'); 8 | import Query = require('./class/Query'); 9 | import TableObject = require('./class/TableObject'); 10 | import TableRecord = require('./class/TableRecord.d'); 11 | import TableSchema = require('./class/TableSchema'); 12 | import User = require('./class/User'); 13 | import UserGroup = require('./class/UserGroup'); 14 | import UserSuperGroup = require('./class/UserSuperGroup'); 15 | import Order = require('./class/Order'); 16 | import RedPack = require('./class/RedPack'); 17 | import MobileTopUp = require('./class/MobileTopup'); 18 | import PeopleAlive = require('./class/PeopleAlive'); 19 | import request = require('./request'); 20 | import AlipayProfitSharingOrder = require('./class/AlipayProfitSharingOrder'); 21 | import WechatProfitSharingOrder = require('./class/WechatProfitSharingOrder'); 22 | import UrlScheme = require('./class/UrlScheme'); 23 | import useVersion = require('./useVersion'); 24 | import Validator = require('./class/Validator'); 25 | export declare const invokeFunction: ( 26 | functionName: any, 27 | params: any, 28 | sync?: boolean, 29 | ) => any; 30 | export declare const invoke: ( 31 | functionName: any, 32 | params: any, 33 | sync?: boolean, 34 | ) => any; 35 | export declare const sendEmail: (data: any) => any; 36 | export declare const sendTemplateMessage: (data: any) => any; 37 | export declare const getOrderList: (params: any) => any; 38 | export declare const refund: (data: any) => any; 39 | export declare const wxAccessToken: (signKey: any) => any; 40 | export declare const wxCensorImage: (fileID: any) => any; 41 | export declare const wxCensorText: (text: any) => any; 42 | export declare const wxPromotionTransfer: (data: any) => any; 43 | export declare const sendSmsCode: (params: any) => any; 44 | export declare const sendSmsMessage: (params: any) => any; 45 | export declare const verifySmsCode: ({ 46 | phone, 47 | code, 48 | userID, 49 | }: { 50 | phone: any; 51 | code: any; 52 | userID: any; 53 | }) => any; 54 | export declare const getWXACode: ( 55 | type: any, 56 | params: any, 57 | cdn: any, 58 | categoryName: any, 59 | ) => any; 60 | export declare const getTemplateMsgTicketCount: ( 61 | options?: Record, 62 | ) => any; 63 | export declare const getInnerRequest: typeof request.getInnerRequest; 64 | export declare const getOuterRequest: typeof request.getOuterRequest; 65 | export declare const getAsyncJobResult: (id: any) => any; 66 | export declare const getServerDate: () => any; 67 | export declare namespace alipay { 68 | const sendTemplateMessage_1: (data: any) => any; 69 | export { sendTemplateMessage_1 as sendTemplateMessage }; 70 | const getTemplateMsgTicketCount_1: (options?: Record) => any; 71 | export { getTemplateMsgTicketCount_1 as getTemplateMsgTicketCount }; 72 | export const getAlipayQRCode: (data: any) => any; 73 | export namespace profitSharing { 74 | export const addReceiver: (data: any) => any; 75 | export const removeReceiver: (data: any) => any; 76 | export const receiverQuery: (data: any) => any; 77 | export { AlipayProfitSharingOrder as Order }; 78 | } 79 | export const censorText: (text: any) => any; 80 | } 81 | export declare namespace qq { 82 | const sendTemplateMessage_2: (data: any) => any; 83 | export { sendTemplateMessage_2 as sendTemplateMessage }; 84 | const getTemplateMsgTicketCount_2: (options?: Record) => any; 85 | export { getTemplateMsgTicketCount_2 as getTemplateMsgTicketCount }; 86 | export const censorImage: (fileID: any) => any; 87 | const censorText_1: (text: any) => any; 88 | export { censorText_1 as censorText }; 89 | export const sendSubscribeMessage: (options?: Record) => any; 90 | export const getSubscribeMsgTicketCount: (options?: Record) => any; 91 | } 92 | export declare namespace baidu { 93 | const sendTemplateMessage_3: (data: any) => any; 94 | export { sendTemplateMessage_3 as sendTemplateMessage }; 95 | const getTemplateMsgTicketCount_3: (options?: Record) => any; 96 | export { getTemplateMsgTicketCount_3 as getTemplateMsgTicketCount }; 97 | } 98 | export declare namespace wechat { 99 | export namespace profitSharing_1 { 100 | const addReceiver_1: (data: any) => any; 101 | export { addReceiver_1 as addReceiver }; 102 | const removeReceiver_1: (data: any) => any; 103 | export { removeReceiver_1 as removeReceiver }; 104 | export { WechatProfitSharingOrder as Order }; 105 | } 106 | export { profitSharing_1 as profitSharing }; 107 | export namespace livestreaming { 108 | const getRoomList: (offset: any, limit: any) => any; 109 | const getPlaybackList: (room_id: any, offset: any, limit: any) => any; 110 | } 111 | export const decryptData: (data: any) => any; 112 | const sendSubscribeMessage_1: (options?: Record) => any; 113 | export { sendSubscribeMessage_1 as sendSubscribeMessage }; 114 | const getSubscribeMsgTicketCount_1: (options?: Record) => any; 115 | export { getSubscribeMsgTicketCount_1 as getSubscribeMsgTicketCount }; 116 | export const getUserRiskRank: (options?: Record) => any; 117 | export const createActivityID: (options?: Record) => any; 118 | export { UrlScheme }; 119 | } 120 | export declare namespace bytedance { 121 | const sendTemplateMessage_4: (data: any) => any; 122 | export { sendTemplateMessage_4 as sendTemplateMessage }; 123 | const getTemplateMsgTicketCount_4: (options?: Record) => any; 124 | export { getTemplateMsgTicketCount_4 as getTemplateMsgTicketCount }; 125 | export const getQRCode: ({ 126 | appName, 127 | path, 128 | platform, 129 | width, 130 | lineColor, 131 | background, 132 | setIcon, 133 | categoryName, 134 | categoryId, 135 | }: { 136 | appName: any; 137 | path: any; 138 | platform: any; 139 | width: any; 140 | lineColor: any; 141 | background: any; 142 | setIcon: any; 143 | categoryName: any; 144 | categoryId: any; 145 | }) => any; 146 | } 147 | export declare const VERSION: any; 148 | export { 149 | Content, 150 | ContentGroup, 151 | ContentCategory, 152 | File, 153 | FileCategory, 154 | GeoPoint, 155 | GeoPolygon, 156 | Query, 157 | TableObject, 158 | TableRecord, 159 | User, 160 | UserGroup, 161 | UserSuperGroup, 162 | Order, 163 | TableSchema, 164 | RedPack, 165 | MobileTopUp, 166 | PeopleAlive, 167 | useVersion, 168 | Validator, 169 | }; 170 | -------------------------------------------------------------------------------- /packages/types/types/baas/request.d.ts: -------------------------------------------------------------------------------- 1 | export function getInnerRequest(): any; 2 | export function getOuterRequest(): any; 3 | -------------------------------------------------------------------------------- /packages/types/types/baas/useVersion.d.ts: -------------------------------------------------------------------------------- 1 | declare function _exports(version: string): void; 2 | export = _exports; 3 | -------------------------------------------------------------------------------- /packages/types/types/faas.d.ts: -------------------------------------------------------------------------------- 1 | export declare namespace FaaS { 2 | /** 3 | * MinCloud function event 4 | * @see {@link https://doc.minapp.com/cloud-function/node-sdk/start/code-format.html} 5 | */ 6 | interface Event> { 7 | timeLimitInMS: number; 8 | eventType: 9 | | /** CLI invocation */ null 10 | | /** Called by MinCloud backend, mini program */ 'sdk' 11 | | 'open_api' 12 | | 'cloud_function' 13 | | 'flex_schema' 14 | | 'wechat_pay_success' 15 | | 'alipay_pay_success' 16 | | 'qpay_success' 17 | | 'timer' 18 | | 'debugger' 19 | | 'file_operation' 20 | | 'incoming_webhook' 21 | | 'wechat_message' 22 | | /** User backend */ 'user_dash'; 23 | request: { 24 | meta: { 25 | ip_address: string; 26 | user_agent: string; 27 | }; 28 | user?: { 29 | avatar_url: string; 30 | nickname: string; 31 | id: number; 32 | }; 33 | }; 34 | signKey: string; 35 | miniappId: number; 36 | /** true when invoked by CLI, MinCloud backend */ 37 | debug: boolean; 38 | timezone: string; 39 | jobId: string; 40 | /** 41 | * @description Parameters passed when the cloud function is called by the user 42 | */ 43 | data: Data; 44 | } 45 | 46 | /** 47 | * Structure of Trigger v2 48 | * @see {@link https://doc.minapp.com/support/guide/trigger-v2-guideline.html#%E8%A7%A6%E5%8F%91%E5%99%A8%E6%89%A7%E8%A1%8C%E4%BA%91%E5%87%BD%E6%95%B0%E6%97%B6-eventdata-%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E} 49 | */ 50 | interface TriggerSchemaV2< 51 | AfterData extends object, 52 | BeforeData extends object, 53 | > { 54 | after: AfterData; 55 | before: BeforeData; 56 | event: string; 57 | id: string; 58 | schema_id: number; 59 | schema_name: string; 60 | subject: string; 61 | } 62 | 63 | type MainCallback = (err: any, data: any) => any; 64 | 65 | type UserDefinedFunctionResponse = Record; 66 | 67 | type UserDefinedFunction = ( 68 | event: Event, 69 | callback?: MainCallback, 70 | ) => // TODO: need supports normal function 71 | Promise; 72 | } 73 | -------------------------------------------------------------------------------- /packages/types/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export * as BaaS from './baas'; 2 | export * from './faas'; 3 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*"' 3 | - 'libs/*"' 4 | - 'apps/*"' 5 | - 'integration/*"' 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": ["node_modules", "lib", "__tests__"], 3 | "include": ["package.json"], 4 | "ts-node": { 5 | "esm": true 6 | }, 7 | "compilerOptions": { 8 | "skipLibCheck": true, 9 | "strict": true, 10 | "rootDir": ".", 11 | "outDir": "lib", 12 | "moduleResolution": "node16", 13 | "resolveJsonModule": true, 14 | "allowSyntheticDefaultImports": true, 15 | "esModuleInterop": true, 16 | "declaration": true 17 | } 18 | } 19 | --------------------------------------------------------------------------------