├── .github ├── dependabot.yml └── workflows │ ├── ci.yaml │ ├── codeql.yml │ ├── deploy-docs.yml │ ├── releaser.yaml │ └── upload.yaml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yaml ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README-EN.md ├── README.md ├── SECURITY.md ├── cmd └── jzero │ ├── .template │ ├── client │ │ ├── client-go │ │ │ ├── clientset.go.tpl │ │ │ ├── go.mod.tpl │ │ │ └── typed │ │ │ │ ├── direct_client.go.tpl │ │ │ │ ├── resource.go.tpl │ │ │ │ ├── resource_expansion.go.tpl │ │ │ │ └── scope_client.go.tpl │ │ ├── client-ts │ │ │ ├── index.ts.tpl │ │ │ ├── package.json.tpl │ │ │ ├── rest │ │ │ │ └── request.ts.tpl │ │ │ └── typed │ │ │ │ ├── resource.ts.tpl │ │ │ │ └── scope_client.ts.tpl │ │ └── zrpcclient-go │ │ │ ├── clientset.go.tpl │ │ │ ├── go.mod.tpl │ │ │ ├── options.go.tpl │ │ │ └── typed │ │ │ └── scope_client.go.tpl │ ├── frame │ │ ├── api │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── app │ │ │ │ ├── .gitignore.tpl │ │ │ │ ├── .jzero.yaml.tpl │ │ │ │ ├── Dockerfile.tpl │ │ │ │ ├── README.md.tpl │ │ │ │ ├── cmd │ │ │ │ ├── root.go.tpl │ │ │ │ ├── server.go.tpl │ │ │ │ └── version.go.tpl │ │ │ │ ├── desc │ │ │ │ └── api │ │ │ │ │ └── v1 │ │ │ │ │ └── version.api.tpl │ │ │ │ ├── etc │ │ │ │ └── etc.yaml.tpl │ │ │ │ ├── go.mod.tpl │ │ │ │ ├── internal │ │ │ │ ├── config │ │ │ │ │ └── config.go.tpl │ │ │ │ ├── custom │ │ │ │ │ ├── custom.go.tpl │ │ │ │ │ └── routes.go.tpl │ │ │ │ ├── middleware │ │ │ │ │ ├── error.go.tpl │ │ │ │ │ ├── middleware.go.tpl │ │ │ │ │ ├── response.go.tpl │ │ │ │ │ └── validator.go.tpl │ │ │ │ └── svc │ │ │ │ │ ├── config.go.tpl │ │ │ │ │ └── service_context.go.tpl │ │ │ │ ├── main.go.tpl │ │ │ │ ├── plugins │ │ │ │ └── plugins.go.tpl │ │ │ │ └── serverless │ │ │ │ └── serverless.go.tpl │ │ ├── gateway │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── app │ │ │ │ ├── .gitignore.tpl │ │ │ │ ├── .jzero.yaml.tpl │ │ │ │ ├── Dockerfile.tpl │ │ │ │ ├── Makefile.tpl │ │ │ │ ├── README.md.tpl │ │ │ │ ├── cmd │ │ │ │ ├── root.go.tpl │ │ │ │ ├── server.go.tpl │ │ │ │ └── version.go.tpl │ │ │ │ ├── desc │ │ │ │ ├── pb │ │ │ │ │ └── embed.go.tpl │ │ │ │ └── proto │ │ │ │ │ ├── third_party │ │ │ │ │ ├── google │ │ │ │ │ │ ├── api │ │ │ │ │ │ │ ├── annotations.proto │ │ │ │ │ │ │ └── http.proto │ │ │ │ │ │ └── protobuf │ │ │ │ │ │ │ ├── descriptor.proto │ │ │ │ │ │ │ ├── duration.proto │ │ │ │ │ │ │ ├── struct.proto │ │ │ │ │ │ │ └── timestamp.proto │ │ │ │ │ ├── grpc-gateway │ │ │ │ │ │ └── protoc-gen-openapiv2 │ │ │ │ │ │ │ └── options │ │ │ │ │ │ │ ├── annotations.proto │ │ │ │ │ │ │ └── openapiv2.proto │ │ │ │ │ ├── jzero │ │ │ │ │ │ └── api │ │ │ │ │ │ │ ├── http.proto │ │ │ │ │ │ │ └── zrpc.proto │ │ │ │ │ └── validate │ │ │ │ │ │ └── validate.proto │ │ │ │ │ └── v1 │ │ │ │ │ └── version.proto │ │ │ │ ├── etc │ │ │ │ └── etc.yaml.tpl │ │ │ │ ├── go.mod.tpl │ │ │ │ ├── internal │ │ │ │ ├── config │ │ │ │ │ └── config.go.tpl │ │ │ │ ├── custom │ │ │ │ │ ├── custom.go.tpl │ │ │ │ │ └── routes.go.tpl │ │ │ │ ├── middleware │ │ │ │ │ ├── error.go.tpl │ │ │ │ │ ├── header_processor.go.tpl │ │ │ │ │ ├── middleware.go.tpl │ │ │ │ │ ├── response.go.tpl │ │ │ │ │ └── validator.go.tpl │ │ │ │ └── svc │ │ │ │ │ ├── config.go.tpl │ │ │ │ │ └── service_context.go.tpl │ │ │ │ └── main.go.tpl │ │ └── rpc │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── app │ │ │ ├── .gitignore.tpl │ │ │ ├── .jzero.yaml.tpl │ │ │ ├── Dockerfile.tpl │ │ │ ├── README.md.tpl │ │ │ ├── cmd │ │ │ ├── root.go.tpl │ │ │ ├── server.go.tpl │ │ │ └── version.go.tpl │ │ │ ├── desc │ │ │ └── proto │ │ │ │ ├── third_party │ │ │ │ ├── google │ │ │ │ │ ├── api │ │ │ │ │ │ ├── annotations.proto │ │ │ │ │ │ └── http.proto │ │ │ │ │ └── protobuf │ │ │ │ │ │ ├── descriptor.proto │ │ │ │ │ │ ├── duration.proto │ │ │ │ │ │ └── timestamp.proto │ │ │ │ ├── jzero │ │ │ │ │ └── api │ │ │ │ │ │ └── zrpc.proto │ │ │ │ └── validate │ │ │ │ │ └── validate.proto │ │ │ │ └── v1 │ │ │ │ └── version.proto │ │ │ ├── etc │ │ │ └── etc.yaml.tpl │ │ │ ├── go.mod.tpl │ │ │ ├── internal │ │ │ ├── config │ │ │ │ └── config.go.tpl │ │ │ ├── custom │ │ │ │ └── custom.go.tpl │ │ │ ├── middleware │ │ │ │ ├── middleware.go.tpl │ │ │ │ └── validator.go.tpl │ │ │ └── svc │ │ │ │ ├── config.go.tpl │ │ │ │ └── service_context.go.tpl │ │ │ └── main.go.tpl │ ├── go-zero │ │ ├── api │ │ │ ├── handler.tpl │ │ │ └── logic.tpl │ │ └── model │ │ │ ├── customized.tpl │ │ │ ├── delete.tpl │ │ │ ├── err.tpl │ │ │ ├── field.tpl │ │ │ ├── find-one-by-field-extra-method.tpl │ │ │ ├── find-one-by-field.tpl │ │ │ ├── find-one.tpl │ │ │ ├── import-no-cache.tpl │ │ │ ├── import.tpl │ │ │ ├── insert.tpl │ │ │ ├── interface-delete.tpl │ │ │ ├── interface-find-one-by-field.tpl │ │ │ ├── interface-find-one.tpl │ │ │ ├── interface-insert.tpl │ │ │ ├── interface-update.tpl │ │ │ ├── model-gen.tpl │ │ │ ├── model-new.tpl │ │ │ ├── model.tpl │ │ │ ├── table-name.tpl │ │ │ ├── tag.tpl │ │ │ ├── types.tpl │ │ │ ├── update.tpl │ │ │ └── var.tpl │ ├── ivm │ │ ├── add │ │ │ ├── template.api.tpl │ │ │ └── template.proto.tpl │ │ └── init │ │ │ ├── logic-body.tpl │ │ │ ├── logic-client-server-stream-adaptor.tpl │ │ │ ├── logic-client-server-stream-body.tpl │ │ │ ├── logic-client-stream-adaptor.tpl │ │ │ ├── logic-client-stream-body.tpl │ │ │ ├── logic-server-stream-adaptor.tpl │ │ │ └── logic-server-stream-body.tpl │ └── plugins │ │ ├── api │ │ ├── route2code.go.tpl │ │ ├── routes.go.tpl │ │ └── serverless_plugins.go.tpl │ │ ├── model │ │ └── model.go.tpl │ │ └── rpc │ │ ├── middleware_gen.go.tpl │ │ ├── middleware_http.go.tpl │ │ ├── middleware_zrpc.go.tpl │ │ └── server.go.tpl │ ├── go.mod │ ├── go.sum │ ├── internal │ ├── command │ │ ├── check │ │ │ └── check.go │ │ ├── completion │ │ │ └── completion.go │ │ ├── format │ │ │ ├── format.go │ │ │ └── formatgo │ │ │ │ └── run.go │ │ ├── gen │ │ │ ├── gen.go │ │ │ ├── gen │ │ │ │ └── run.go │ │ │ ├── genapi │ │ │ │ ├── gen.go │ │ │ │ ├── patch_handler.go │ │ │ │ ├── patch_logic.go │ │ │ │ ├── patch_svc.go │ │ │ │ ├── routes.go │ │ │ │ └── types.go │ │ │ ├── gendocs │ │ │ │ └── gen.go │ │ │ ├── genmodel │ │ │ │ ├── gen.go │ │ │ │ └── plugins.go │ │ │ ├── genrpc │ │ │ │ ├── gen.go │ │ │ │ ├── middleware.go │ │ │ │ ├── patch_logic.go │ │ │ │ ├── patch_svc.go │ │ │ │ ├── server.go │ │ │ │ ├── style.go │ │ │ │ └── suffix.go │ │ │ ├── gensdk │ │ │ │ ├── config │ │ │ │ │ └── config.go │ │ │ │ ├── gen.go │ │ │ │ ├── generator │ │ │ │ │ ├── common.go │ │ │ │ │ ├── golang.go │ │ │ │ │ ├── interface.go │ │ │ │ │ └── typescript.go │ │ │ │ ├── jparser │ │ │ │ │ ├── api │ │ │ │ │ │ └── parse.go │ │ │ │ │ ├── gateway │ │ │ │ │ │ ├── generator.go │ │ │ │ │ │ ├── parse.go │ │ │ │ │ │ └── types.go │ │ │ │ │ └── parser.go │ │ │ │ └── vars │ │ │ │ │ └── vars.go │ │ │ ├── genswagger │ │ │ │ └── gen.go │ │ │ └── genzrpcclient │ │ │ │ └── gen.go │ │ ├── ivm │ │ │ ├── ivm.go │ │ │ ├── ivmaddapi │ │ │ │ └── api.go │ │ │ ├── ivmaddproto │ │ │ │ └── proto.go │ │ │ └── ivminit │ │ │ │ ├── gen.go │ │ │ │ ├── init.go │ │ │ │ ├── logic.go │ │ │ │ └── proto.go │ │ ├── mcp │ │ │ ├── mcp.go │ │ │ └── run.go │ │ ├── migrate │ │ │ ├── migrate.go │ │ │ ├── migratedown │ │ │ │ └── run.go │ │ │ ├── migrategoto │ │ │ │ └── run.go │ │ │ ├── migrateup │ │ │ │ └── run.go │ │ │ └── migrateversion │ │ │ │ └── run.go │ │ ├── new │ │ │ ├── new.go │ │ │ ├── run.go │ │ │ └── template_data.go │ │ ├── serverless │ │ │ ├── serverless.go │ │ │ ├── serverlessbuild │ │ │ │ └── run.go │ │ │ └── serverlessdelete │ │ │ │ └── run.go │ │ ├── template │ │ │ ├── template.go │ │ │ ├── templatebuild │ │ │ │ ├── build.go │ │ │ │ └── filter.go │ │ │ └── templateinit │ │ │ │ └── init.go │ │ ├── upgrade │ │ │ └── upgrade.go │ │ └── version │ │ │ └── version.go │ ├── config │ │ └── config.go │ ├── desc │ │ └── desc.go │ ├── embeded │ │ └── template.go │ ├── hooks │ │ └── hooks.go │ ├── pkg │ │ ├── dsn │ │ │ ├── dsn.go │ │ │ ├── dsn_test.go │ │ │ ├── mysql.go │ │ │ └── postgres.go │ │ ├── execx │ │ │ └── exec.go │ │ ├── filex │ │ │ └── filex.go │ │ ├── gitstatus │ │ │ └── status.go │ │ ├── gogen │ │ │ ├── gogen.go │ │ │ ├── gogen_test.go │ │ │ ├── testdata │ │ │ │ └── example.api │ │ │ └── util.go │ │ ├── mcp │ │ │ └── mcp.go │ │ ├── mod │ │ │ └── mod.go │ │ ├── osx │ │ │ └── osx.go │ │ ├── stringx │ │ │ ├── stringx.go │ │ │ └── stringx_test.go │ │ └── templatex │ │ │ └── template.go │ └── plugin │ │ └── plugins.go │ └── main.go ├── core ├── configcenter │ └── subscriber │ │ ├── etcd.go │ │ └── fsnotify.go ├── embedx │ ├── embedx.go │ └── option.go ├── middleware │ └── fuzzy │ │ ├── decode.go │ │ ├── decode_extra.go │ │ ├── decode_extra_pointer.go │ │ ├── decode_test.go │ │ └── request.go ├── status │ ├── status.go │ └── status_test.go ├── stores │ ├── cache │ │ ├── cache.go │ │ ├── redis.go │ │ ├── redis_test.go │ │ ├── sync_map.go │ │ └── sync_map_test.go │ ├── condition │ │ ├── adapter.go │ │ ├── adapter_test.go │ │ ├── chain.go │ │ ├── chain_test.go │ │ ├── condition.go │ │ └── condition_test.go │ └── modelx │ │ ├── config.go │ │ └── model.go ├── swaggerv2 │ ├── option.go │ └── swaggerv2.go └── templatex │ └── templatex.go ├── docs ├── .gitignore ├── package.json ├── pnpm-lock.yaml ├── src │ ├── .vuepress │ │ ├── config.ts │ │ ├── navbar │ │ │ ├── en.ts │ │ │ ├── index.ts │ │ │ └── zh.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── sidebar.ts │ │ ├── styles │ │ │ ├── config.scss │ │ │ ├── index.scss │ │ │ └── palette.scss │ │ └── theme.ts │ ├── README.md │ ├── en │ │ └── README.md │ ├── faq │ │ ├── README.md │ │ ├── grpc.md │ │ ├── swagger.md │ │ └── upgrade.md │ ├── guide │ │ ├── check.md │ │ ├── config │ │ │ ├── README.md │ │ │ ├── dynamic_conf.md │ │ │ ├── etcd.md │ │ │ ├── introduction.md │ │ │ ├── limit.md │ │ │ ├── log.md │ │ │ ├── prometheus.md │ │ │ ├── telemetry.md │ │ │ └── timeout.md │ │ ├── contribute.md │ │ ├── deploy │ │ │ ├── README.md │ │ │ ├── build-binary.md │ │ │ └── image.md │ │ ├── develop │ │ │ ├── README.md │ │ │ ├── api.md │ │ │ ├── command.md │ │ │ ├── model.md │ │ │ └── proto.md │ │ ├── gen.md │ │ ├── gendoc.md │ │ ├── gensdk.md │ │ ├── genswagger.md │ │ ├── ivm.md │ │ ├── mcp.md │ │ ├── migrate.md │ │ ├── new.md │ │ ├── overview.md │ │ ├── serverless.md │ │ └── template.md │ └── project │ │ ├── README.md │ │ ├── api.md │ │ └── gateway.md └── tsconfig.json ├── go.mod └── go.sum /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "gomod" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | time: "10:00" 8 | labels: 9 | - "dependencies" 10 | - package-ecosystem: "github-actions" 11 | directory: "/" 12 | schedule: 13 | interval: "daily" 14 | time: "10:00" 15 | labels: 16 | - "dependencies" -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: jzero-ci 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - 'docs/**' 7 | - '**.md' 8 | pull_request: 9 | 10 | jobs: 11 | golangci: 12 | name: ci 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 19 | 20 | - uses: actions/setup-go@v5 21 | with: 22 | go-version: '1.24.3' 23 | 24 | - name: Install Tool 25 | run: | 26 | cd cmd/jzero 27 | go install 28 | jzero check 29 | 30 | - name: format go 31 | run: | 32 | jzero format -d --git-change=false 33 | 34 | - uses: actions/checkout@v4 35 | - name: golangci-lint 36 | uses: golangci/golangci-lint-action@v7 37 | with: 38 | version: latest 39 | working-directory: ${{ matrix.workdir }} 40 | skip-go-installation: true 41 | skip-pkg-cache: true 42 | -------------------------------------------------------------------------------- /.github/workflows/deploy-docs.yml: -------------------------------------------------------------------------------- 1 | name: deploy-docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - 'docs/**' 9 | - '.github/workflows/deploy-docs.yml' 10 | 11 | permissions: 12 | contents: write 13 | 14 | jobs: 15 | deploy-gh-pages: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | 23 | - name: Set node 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: 20 27 | cache: npm 28 | cache-dependency-path: docs/pnpm-lock.yaml 29 | 30 | - uses: actions/setup-go@v5 31 | with: 32 | go-version: '1.24.3' 33 | 34 | - name: Build Docs 35 | env: 36 | NODE_OPTIONS: --max_old_space_size=8192 37 | run: |- 38 | cd docs 39 | npm i 40 | npm run docs:build 41 | > src/.vuepress/dist/.nojekyll 42 | 43 | - name: Deploy 44 | uses: JamesIves/github-pages-deploy-action@v4.7.3 45 | with: 46 | branch: gh-pages 47 | folder: docs/src/.vuepress/dist 48 | 49 | - name: Upload to jaronnie/jzero-docs-deploy-pages 50 | run: | 51 | go install github.com/jaronnie/grum@latest 52 | GITHUB_TOKEN=${{ secrets.ACCESS_TOKEN }} grum clone https://github.com/jaronnie/jzero-docs-deploy-pages 53 | cd jzero-docs-deploy-pages 54 | git config user.name "dependabot[bot]" 55 | git config user.email "49699333+dependabot[bot]@users.noreply.github.com" 56 | find . -mindepth 1 ! -name "api" ! -name ".git" ! -name "vercel.json" ! -path "./api/*" ! -path "./.git/*" -exec rm -rf {} + 57 | mv ../docs/src/.vuepress/dist/* ./ 58 | git add . 59 | git diff-index --quiet HEAD || git commit -m "chore(docs): update docs" 60 | git push -f -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | dist 4 | node_modules 5 | docs/package-lock.json -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | run: 3 | modules-download-mode: readonly 4 | linters: 5 | default: none 6 | enable: 7 | - thelper 8 | - tparallel 9 | - unconvert 10 | - unused 11 | - wastedassign 12 | - whitespace 13 | formatters: 14 | enable: 15 | - gofmt 16 | - gofumpt 17 | - goimports 18 | settings: 19 | goimports: 20 | local-prefixes: 21 | - github.com/jzero-io/jzero -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | before: 4 | hooks: 5 | - go mod tidy 6 | 7 | builds: 8 | - env: 9 | - CGO_ENABLED=0 10 | goos: 11 | - linux 12 | - windows 13 | - darwin 14 | goarch: 15 | - amd64 16 | - arm64 17 | dir: ./cmd/jzero 18 | id: jzero 19 | binary: jzero 20 | 21 | archives: 22 | - format: tar.gz 23 | # this name template makes the OS and Arch compatible with the results of `uname`. 24 | name_template: >- 25 | {{ .ProjectName }}_ 26 | {{- title .Os }}_ 27 | {{- if eq .Arch "amd64" }}x86_64 28 | {{- else if eq .Arch "386" }}i386 29 | {{- else }}{{ .Arch }}{{ end }} 30 | {{- if .Arm }}v{{ .Arm }}{{ end }} 31 | # use zip for windows archives 32 | format_overrides: 33 | - goos: windows 34 | format: zip 35 | 36 | changelog: 37 | filters: 38 | exclude: 39 | - "^docs:" 40 | - "^test:" 41 | 42 | force_token: github 43 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Jzero 2 | 3 | ## steps 4 | 5 | ### 1. fork 6 | 7 | https://github.com/jzero-io/jzero/fork 8 | 9 | ### 2. clone 10 | 11 | ```shell 12 | git clone https://github.com/your_username/jzero 13 | ``` 14 | 15 | ### 3. checkout branch 16 | 17 | ```shell 18 | cd jzero 19 | 20 | git checkout -b feat/patch-1 21 | ``` 22 | 23 | ### 4. push 24 | 25 | ```shell 26 | git add . 27 | git commit -m "feat(xx): custom message" 28 | git push 29 | ``` 30 | 31 | ### 5. pull request 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:alpine 2 | 3 | ENV CGO_ENABLED=0 4 | 5 | LABEL \ 6 | org.opencontainers.image.title="jzero" \ 7 | org.opencontainers.image.description="jzero framework" \ 8 | org.opencontainers.image.url="https://github.com/jzero-io/jzero" \ 9 | org.opencontainers.image.documentation="https://github.com/jzero-io/jzero#readme" \ 10 | org.opencontainers.image.source="https://github.com/jzero-io/jzero" \ 11 | org.opencontainers.image.licenses="MIT" \ 12 | maintainer="jaronnie " 13 | 14 | WORKDIR /app 15 | 16 | COPY dist/jzero_linux_amd64_v1/jzero /dist/jzero_linux_amd64/jzero 17 | COPY dist/jzero_linux_arm64_v8.0/jzero /dist/jzero_linux_arm64/jzero 18 | 19 | RUN if [ `go env GOARCH` = "amd64" ]; then \ 20 | cp /dist/jzero_linux_amd64/jzero /usr/local/bin/jzero; \ 21 | elif [ `go env GOARCH` = "arm64" ]; then \ 22 | cp /dist/jzero_linux_arm64/jzero /usr/local/bin/jzero; \ 23 | fi 24 | 25 | RUN apk update --no-cache \ 26 | && apk add --no-cache tzdata ca-certificates protoc \ 27 | && jzero check \ 28 | && rm -rf /dist \ 29 | && rm -rf /go/pkg/mod \ 30 | && rm -rf /go/pkg/sumdb 31 | 32 | ENTRYPOINT ["jzero"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 jzero-io 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. -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Only the last stable version at any given point. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | Vulnerabilities can be disclosed in private using 10 | [GitHub advisories](https://github.com/jzero-io/jzero/security). 11 | 12 | Thanks! 13 | -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-go/clientset.go.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by jzero. DO NOT EDIT. 2 | // type: clientset 3 | 4 | package {{.Package}} 5 | 6 | import ( 7 | "github.com/jzero-io/restc" 8 | "{{.Module}}/typed" 9 | 10 | {{range $v := .Scopes}}"{{$.Module}}/typed/{{$v | lower}}"{{end}} 11 | ) 12 | 13 | type Interface interface { 14 | Direct() typed.DirectInterface 15 | 16 | {{range $v := .Scopes}}{{$v | FirstUpper | ToCamel}}() {{$v | lower}}.{{$v | FirstUpper | ToCamel}}Interface{{end}} 17 | } 18 | 19 | type Clientset struct { 20 | // direct client to request 21 | direct *typed.DirectClient 22 | 23 | {{range $v := .Scopes}}{{$v | ToCamel}} *{{$v | lower}}.{{$v | FirstUpper| ToCamel}}Client{{end}} 24 | } 25 | 26 | func (x *Clientset) Direct() typed.DirectInterface { 27 | return x.direct 28 | } 29 | 30 | {{range $v := .Scopes}}func (x *Clientset) {{$v | FirstUpper| ToCamel}}() {{$v | lower}}.{{$v | FirstUpper| ToCamel}}Interface { 31 | return x.{{$v | ToCamel}} 32 | } 33 | 34 | {{end}}func NewClientWithOptions(ops ...restc.Opt) ({{if eq (len .Scopes) 1}}{{index .Scopes 0 | lower}}.{{index .Scopes 0 | FirstUpper| ToCamel}}Interface{{else}}*Clientset{{end}}, error) { 35 | c := &restc.RESTClient{} 36 | for _, op := range ops { 37 | if err := op(c); err != nil { 38 | return nil, err 39 | } 40 | } 41 | configShallowCopy := *c 42 | var cs Clientset 43 | var err error 44 | cs.direct, err = typed.NewForConfig(&configShallowCopy) 45 | if err != nil { 46 | return nil, err 47 | } 48 | {{range $v := .Scopes}}cs.{{$v | ToCamel}}, err = {{$v | lower}}.NewForConfig(&configShallowCopy) 49 | if err != nil { 50 | return nil, err 51 | } 52 | {{end}} 53 | return {{if eq (len .Scopes) 1}}cs.{{index .Scopes 0 | FirstUpper| ToCamel}}(){{else}}&cs{{end}}, nil 54 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-go/go.mod.tpl: -------------------------------------------------------------------------------- 1 | module {{ .Module }} 2 | 3 | go {{ .GoVersion }} -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-go/typed/direct_client.go.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by jzero. DO NOT EDIT. 2 | // type: direct_client 3 | 4 | package typed 5 | 6 | import ( 7 | "github.com/jzero-io/restc" 8 | ) 9 | 10 | 11 | type DirectInterface interface { 12 | RESTClient() restc.Interface 13 | } 14 | 15 | type DirectClient struct { 16 | restClient restc.Interface 17 | } 18 | 19 | func (x *DirectClient) RESTClient() restc.Interface { 20 | if x == nil { 21 | return nil 22 | } 23 | return x.restClient 24 | } 25 | 26 | // NewForConfig creates a new DirectClient for the given config. 27 | func NewForConfig(x *restc.RESTClient) (*DirectClient, error) { 28 | return &DirectClient{x}, nil 29 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-go/typed/resource_expansion.go.tpl: -------------------------------------------------------------------------------- 1 | package {{.Scope | lower}} 2 | 3 | type {{.Resource | FirstUpper}}Expansion interface {} -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-go/typed/scope_client.go.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by jzero. DO NOT EDIT. 2 | // type: {{.Scope | lower}}_client 3 | 4 | package {{.Scope | lower}} 5 | 6 | import ( 7 | "github.com/jzero-io/restc" 8 | ) 9 | 10 | type {{.Scope | FirstUpper | ToCamel}}Interface interface { 11 | RESTClient() restc.Interface 12 | 13 | {{range $v := .Resources}}{{$v | FirstUpper| ToCamel}}Getter 14 | {{end}} 15 | } 16 | 17 | type {{.Scope | FirstUpper| ToCamel}}Client struct { 18 | restClient restc.Interface 19 | } 20 | 21 | func (x *{{.Scope | FirstUpper| ToCamel}}Client) RESTClient() restc.Interface { 22 | if x == nil { 23 | return nil 24 | } 25 | return x.restClient 26 | } 27 | 28 | {{range $v := .Resources}}func (x *{{$.Scope | FirstUpper| ToCamel}}Client) {{$v | FirstUpper| ToCamel}}() {{$v | FirstUpper| ToCamel}}Interface { 29 | return new{{$v | FirstUpper}}Client(x) 30 | } 31 | 32 | {{end}} 33 | // NewForConfig creates a new {{.Scope | FirstUpper| ToCamel}}Client for the given config. 34 | func NewForConfig(x *restc.RESTClient) (*{{.Scope | FirstUpper| ToCamel}}Client, error) { 35 | return &{{.Scope | FirstUpper| ToCamel}}Client{x}, nil 36 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-ts/index.ts.tpl: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import { RequestMethod } from "umi-request"; 3 | 4 | {{range $scope := .Scopes}}import { {{$scope | FirstUpper }}Client } from "./typed/{{$scope}}/{{$scope}}_client"; 5 | {{end}} 6 | 7 | export default class Clientset { 8 | constructor(private request: RequestMethod) { } 9 | {{range $scope := .Scopes}} 10 | get {{$scope | FirstUpper}}(): {{$scope | FirstUpper}}Client { 11 | return new {{$scope | FirstUpper}}Client(this.request); 12 | } 13 | {{end}} 14 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-ts/package.json.tpl: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@sdk/{{.APP}}", 3 | "description": "", 4 | "author": "", 5 | "dependencies": { 6 | "umi-request": "^1.4.0" 7 | }, 8 | "devDependencies": { 9 | "rxjs": "^7.8.0", 10 | "typescript": "^4.9.5" 11 | } 12 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-ts/rest/request.ts.tpl: -------------------------------------------------------------------------------- 1 | import { RequestMethod } from "umi-request" 2 | 3 | type PathParam = { 4 | name: string 5 | value: T 6 | } 7 | 8 | type QueryParam = { 9 | name: string 10 | value: string 11 | } 12 | 13 | export type Response = { 14 | code: number, 15 | message: string, 16 | data: T 17 | } 18 | 19 | 20 | type Verb = "POST" | "GET" 21 | 22 | export class Request { 23 | request: RequestMethod 24 | verb: Verb 25 | subPath: string 26 | params: string 27 | body: D 28 | headers: Record 29 | 30 | constructor(request: RequestMethod) { 31 | this.request = request; 32 | } 33 | 34 | setVerb(verb: Verb): this { 35 | this.verb = verb 36 | return this 37 | } 38 | 39 | setSubPath(subPath: string, ...args: PathParam[]): this { 40 | for (let v of args) { 41 | let placeHolder = "{"+v.name+"}"; 42 | subPath = subPath.replace(placeHolder, String(v.value)) 43 | } 44 | this.subPath = subPath 45 | return this 46 | } 47 | 48 | setHeaders(headers: Record): this { 49 | this.headers = headers 50 | return this 51 | } 52 | 53 | setParams(...args: QueryParam[]): this { 54 | if (args.length == 0) { 55 | return this 56 | } 57 | 58 | let queryParams: string[] = [] 59 | for (let arg of args) { 60 | let queryParam = arg.name + "=" + arg.value; 61 | queryParams.push(queryParam) 62 | } 63 | this.params = queryParams.join("&") 64 | return this 65 | } 66 | 67 | setBody(body: D): this { 68 | this.body = body 69 | return this 70 | } 71 | 72 | // @ts-ignore 73 | async send(): Promise> { 74 | if (this.verb == null) { 75 | throw new Error("verb is not set") 76 | } 77 | 78 | let url = this.subPath; 79 | 80 | return this.request>(url, { 81 | method: this.verb, 82 | data: this.body, 83 | headers: this.headers 84 | }).then(resp => { 85 | // @ts-ignore 86 | return Promise.resolve(resp) 87 | }) 88 | } 89 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-ts/typed/resource.ts.tpl: -------------------------------------------------------------------------------- 1 | {{- if not .EnableStylingCheck}} 2 | /* eslint-disable */ 3 | // @ts-nocheck 4 | {{- end}} 5 | /* 6 | * This file is a generated Typescript file for SDK Gateway, DO NOT MODIFY 7 | */ 8 | 9 | import { RequestMethod } from "umi-request"; 10 | import { Request, Response } from "../../rest/request"; 11 | 12 | /* 13 | TODO: add other import 14 | */ 15 | 16 | export class {{.Resource | FirstUpper}}Client { 17 | constructor(private request: RequestMethod) { } 18 | {{range $interface := .HTTPInterfaces}} 19 | {{end}} 20 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/client/client-ts/typed/scope_client.ts.tpl: -------------------------------------------------------------------------------- 1 | import { RequestMethod } from "umi-request"; 2 | {{range $resource := .Resources}}import { {{$resource | FirstUpper}}Client } from "./{{$resource}}"; 3 | {{end}} 4 | 5 | export class {{.Scope | FirstUpper}}Client { 6 | constructor(private request: RequestMethod) { } 7 | 8 | {{range $resource := .Resources}} 9 | get {{$resource | FirstUpper}}(): {{$resource | FirstUpper}}Client { 10 | return new {{$resource | FirstUpper}}Client(this.request); 11 | } 12 | {{end}} 13 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/client/zrpcclient-go/clientset.go.tpl: -------------------------------------------------------------------------------- 1 | package {{ .Package }} 2 | 3 | import ( 4 | {{range $v := .Scopes}}"{{$.Module}}/{{ $.ClientDir }}"{{end}} 5 | ) 6 | 7 | type Interface interface { 8 | {{range $v := .Scopes}}{{$v | FirstUpper | ToCamel}}() {{$v | lower}}.Interface{{end}} 9 | } 10 | 11 | type Clientset struct { 12 | {{range $v := .Scopes}}{{$v | ToCamel}} *{{$v}}.Client{{end}} 13 | } 14 | 15 | {{range $v := .Scopes}}func (x *Clientset) {{$v | FirstUpper | ToCamel}}() {{$v | lower}}.Interface { 16 | return x.{{$v | ToCamel}} 17 | } 18 | {{ end }} 19 | 20 | func NewClientWithOptions(ops ...Opt) *Clientset { 21 | cs := &Clientset{} 22 | 23 | for _, op := range ops { 24 | op(cs) 25 | } 26 | 27 | return cs 28 | } 29 | -------------------------------------------------------------------------------- /cmd/jzero/.template/client/zrpcclient-go/go.mod.tpl: -------------------------------------------------------------------------------- 1 | module {{ .Module }} 2 | 3 | go {{ .GoVersion }} -------------------------------------------------------------------------------- /cmd/jzero/.template/client/zrpcclient-go/options.go.tpl: -------------------------------------------------------------------------------- 1 | package {{ .Package }} 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/zrpc" 5 | 6 | {{range $v := .Scopes}}"{{$.Module}}/{{ $.ClientDir }}"{{end}} 7 | ) 8 | 9 | type Opt func(client *Clientset) 10 | 11 | {{ range $v := .Scopes}} 12 | func With{{ $v | FirstUpper | ToCamel }}Client(cli zrpc.Client) Opt { 13 | return func(client *Clientset) { 14 | client.{{ $v | ToCamel }} = {{ $v }}.New(cli) 15 | } 16 | } 17 | {{ end}} 18 | 19 | -------------------------------------------------------------------------------- /cmd/jzero/.template/client/zrpcclient-go/typed/scope_client.go.tpl: -------------------------------------------------------------------------------- 1 | package {{.Package}} 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/zrpc" 5 | {{ range $v := .Services}} 6 | "{{ $.Module }}/{{$.Scope}}/{{ $v | lower }}" 7 | {{ end }} 8 | ) 9 | 10 | type Interface interface { 11 | {{ range $v := .Services }} 12 | {{ $v | FirstUpper | ToCamel }}() {{ $v | lower }}.{{ $v | FirstUpper | ToCamel }} 13 | {{ end }} 14 | } 15 | 16 | type Client struct { 17 | client zrpc.Client 18 | } 19 | 20 | func New(c zrpc.Client) *Client { 21 | return &Client{client: c} 22 | } 23 | 24 | {{ range $v := .Services }} 25 | func (x *Client) {{ $v | FirstUpper | ToCamel }}() {{ $v | lower }}.{{ $v | FirstUpper | ToCamel }} { 26 | return {{ $v | lower }}.New{{ $v | FirstUpper | ToCamel }}(x.client) 27 | } 28 | {{ end }} -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 jzero 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 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/README.md: -------------------------------------------------------------------------------- 1 | # templates 2 | 3 | jzero template repo with only api project 4 | 5 | ```shell 6 | jzero new simpleapi --frame api 7 | ``` 8 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/.gitignore.tpl: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ 19 | 20 | # Go workspace file 21 | go.work 22 | go.work.sum 23 | 24 | # idea 25 | .idea 26 | 27 | # Vs Code 28 | .vscode 29 | 30 | # logs 31 | logs -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/.jzero.yaml.tpl: -------------------------------------------------------------------------------- 1 | syntax: v1 2 | 3 | gen: 4 | hooks: 5 | after: 6 | - jzero gen swagger 7 | - jzero format -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/Dockerfile.tpl: -------------------------------------------------------------------------------- 1 | FROM --platform=$BUILDPLATFORM ghcr.io/jzero-io/jzero:latest as builder 2 | 3 | ARG TARGETARCH 4 | ARG LDFLAGS 5 | 6 | ENV GOPROXY https://goproxy.cn,direct 7 | 8 | WORKDIR /usr/local/go/src/app 9 | 10 | COPY ./ ./ 11 | 12 | RUN --mount=type=cache,target=/go/pkg CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH go build -a -ldflags="$LDFLAGS" -o /dist/app main.go \ 13 | && jzero gen swagger \ 14 | && cp -r etc /dist/etc \ 15 | && mkdir -p /dist/desc && cp -r desc/swagger /dist/desc 16 | 17 | 18 | FROM --platform=$TARGETPLATFORM alpine:latest 19 | 20 | WORKDIR /dist 21 | 22 | COPY --from=builder /dist . 23 | 24 | EXPOSE 8001 25 | 26 | CMD ["./app", "server"] -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/README.md.tpl: -------------------------------------------------------------------------------- 1 | # {{ .APP }} 2 | 3 | ## Install Jzero Framework 4 | 5 | ```shell 6 | go install github.com/jzero-io/jzero/cmd/jzero@latest 7 | 8 | jzero check 9 | ``` 10 | 11 | ## Generate code 12 | 13 | ### Generate server code 14 | 15 | ```shell 16 | jzero gen 17 | ``` 18 | 19 | ### Generate swagger code 20 | 21 | ```shell 22 | jzero gen swagger 23 | ``` 24 | 25 | you can see generated swagger json in `desc/swagger` 26 | 27 | ## Build docker image 28 | 29 | ```shell 30 | # add a builder first 31 | docker buildx create --use --name=mybuilder --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master 32 | 33 | # build and load 34 | docker buildx build --platform linux/{{ .GoArch }} --progress=plain -t {{ .APP }}:latest . --load 35 | ``` 36 | 37 | ## Documents 38 | 39 | https://docs.jzero.io -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/cmd/root.go.tpl: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var cfgFile string 10 | 11 | // rootCmd represents the base command when called without any subcommands 12 | var rootCmd = &cobra.Command{ 13 | Use: "{{ .APP }}", 14 | Short: "{{ .APP }} root", 15 | Long: "{{ .APP }} root.", 16 | CompletionOptions: cobra.CompletionOptions{ 17 | DisableDefaultCmd: true, 18 | }, 19 | } 20 | 21 | // Execute adds all child commands to the root command and sets flags appropriately. 22 | // This is called by main.main(). It only needs to happen once to the rootCmd. 23 | func Execute() { 24 | err := rootCmd.Execute() 25 | if err != nil { 26 | os.Exit(1) 27 | } 28 | } 29 | 30 | func init() { 31 | rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "etc/etc.yaml", "config file (default is project root dir etc/etc.yaml") 32 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/cmd/server.go.tpl: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | configurator "github.com/zeromicro/go-zero/core/configcenter" 6 | "github.com/jzero-io/jzero/core/configcenter/subscriber" 7 | "github.com/zeromicro/go-zero/core/logx" 8 | "github.com/zeromicro/go-zero/core/service" 9 | "github.com/zeromicro/go-zero/rest" 10 | "github.com/common-nighthawk/go-figure" 11 | 12 | "{{ .Module }}/internal/config" 13 | "{{ .Module }}/internal/middleware" 14 | "{{ .Module }}/internal/handler" 15 | "{{ .Module }}/internal/svc" 16 | {{ if has "serverless_core" .Features }}"{{ .Module }}/plugins"{{end}} 17 | ) 18 | 19 | // serverCmd represents the server command 20 | var serverCmd = &cobra.Command{ 21 | Use: "server", 22 | Short: "{{ .APP }} server", 23 | Long: "{{ .APP }} server", 24 | Run: func(cmd *cobra.Command, args []string) { 25 | cc := configurator.MustNewConfigCenter[config.Config](configurator.Config{ 26 | Type: "yaml", 27 | }, subscriber.MustNewFsnotifySubscriber(cfgFile, subscriber.WithUseEnv(true))) 28 | c, err := cc.GetConfig() 29 | logx.Must(err) 30 | 31 | // set up logger 32 | logx.Must(logx.SetUp(c.Log.LogConf)) 33 | 34 | svcCtx := svc.NewServiceContext(cc) 35 | run(svcCtx) 36 | }, 37 | } 38 | 39 | func run(svcCtx *svc.ServiceContext) { 40 | c := svcCtx.MustGetConfig() 41 | 42 | server := rest.MustNewServer(c.Rest.RestConf) 43 | middleware.Register(server) 44 | 45 | // server add api handlers 46 | handler.RegisterHandlers(server, svcCtx) 47 | 48 | // server add custom routes 49 | svcCtx.Custom.AddRoutes(server) 50 | 51 | {{ if has "serverless_core" .Features }}// load plugins features 52 | plugins.LoadPlugins(server, *svcCtx){{end}} 53 | 54 | group := service.NewServiceGroup() 55 | group.Add(server) 56 | group.Add(svcCtx.Custom) 57 | 58 | printBanner(c) 59 | printVersion() 60 | 61 | logx.Infof("Starting rest server at %s:%d...", c.Rest.Host, c.Rest.Port) 62 | group.Start() 63 | } 64 | 65 | func printBanner(c config.Config) { 66 | figure.NewColorFigure(c.Banner.Text, c.Banner.FontName, c.Banner.Color, true).Print() 67 | } 68 | 69 | func init() { 70 | rootCmd.AddCommand(serverCmd) 71 | } 72 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/cmd/version.go.tpl: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "runtime" 8 | "time" 9 | 10 | "github.com/spf13/cast" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | var ( 15 | Version string 16 | Commit string 17 | Date string 18 | ) 19 | 20 | // versionCmd represents the version command 21 | var versionCmd = &cobra.Command{ 22 | Use: "version", 23 | Short: "{{ .APP }} version", 24 | Long: `{{ .APP }} version`, 25 | Run: func(cmd *cobra.Command, args []string) { 26 | printVersion() 27 | }, 28 | } 29 | 30 | func printVersion() { 31 | var versionBuffer bytes.Buffer 32 | 33 | if Version == "" { 34 | Version = "unknown" 35 | } 36 | versionBuffer.WriteString(fmt.Sprintf("{{ .APP }} version %s %s/%s\n", Version, runtime.GOOS, runtime.GOARCH)) 37 | 38 | versionBuffer.WriteString(fmt.Sprintf("Go version %s\n", runtime.Version())) 39 | 40 | if Commit == "" { 41 | Commit = "unknown" 42 | } 43 | versionBuffer.WriteString(fmt.Sprintf("Git commit %s\n", Commit)) 44 | 45 | if Date != "" { 46 | Date = cast.ToString(cast.ToTimeInDefaultLocation(Date, time.Local)) 47 | } else { 48 | Date = "unknown" 49 | } 50 | versionBuffer.WriteString(fmt.Sprintf("Build date: %s\n", Date)) 51 | 52 | fmt.Print(versionBuffer.String()) 53 | } 54 | 55 | func init() { 56 | _ = os.Setenv("VERSION", Version) 57 | _ = os.Setenv("COMMIT", Commit) 58 | _ = os.Setenv("DATE", Date) 59 | 60 | rootCmd.AddCommand(versionCmd) 61 | } 62 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/desc/api/v1/version.api.tpl: -------------------------------------------------------------------------------- 1 | syntax = "v1" 2 | 3 | info ( 4 | go_package: "version" 5 | version: "v1" 6 | ) 7 | 8 | type VersionRequest {} 9 | 10 | type VersionResponse { 11 | Version string `json:"version"` 12 | GoVersion string `json:"goVersion"` 13 | Commit string `json:"commit"` 14 | Date string `json:"date"` 15 | } 16 | 17 | @server( 18 | prefix: /api/v1{{ if has "serverless" .Features }}/{{ .APP }}{{end}} 19 | group: version 20 | ) 21 | service {{ .APP | ToCamel }} { 22 | @handler Version 23 | get /version (VersionRequest) returns (VersionResponse) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/etc/etc.yaml.tpl: -------------------------------------------------------------------------------- 1 | rest: 2 | name: {{ .APP }}-api 3 | host: 0.0.0.0 4 | port: 8001 5 | 6 | log: 7 | serviceName: {{ .APP }} 8 | encoding: plain 9 | level: info 10 | mode: console -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/go.mod.tpl: -------------------------------------------------------------------------------- 1 | module {{ .Module }} 2 | 3 | go {{ .GoVersion }} -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/internal/config/config.go.tpl: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/core/logx" 5 | "github.com/zeromicro/go-zero/rest" 6 | ) 7 | 8 | type Config struct { 9 | Rest RestConf 10 | Log LogConf 11 | 12 | Banner BannerConf 13 | } 14 | 15 | type RestConf struct { 16 | rest.RestConf 17 | } 18 | 19 | type LogConf struct { 20 | logx.LogConf 21 | } 22 | 23 | type BannerConf struct { 24 | Text string `json:",default=JZERO"` 25 | Color string `json:",default=green"` 26 | FontName string `json:",default=starwars,options=big|larry3d|starwars|standard"` 27 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/internal/custom/custom.go.tpl: -------------------------------------------------------------------------------- 1 | package custom 2 | 3 | type Custom struct{} 4 | 5 | func New() *Custom { 6 | return &Custom{} 7 | } 8 | 9 | // Start Please add custom logic here. 10 | func (c *Custom) Start() {} 11 | 12 | // Stop Please add shut down logic here. 13 | func (c *Custom) Stop() {} 14 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/internal/custom/routes.go.tpl: -------------------------------------------------------------------------------- 1 | package custom 2 | 3 | import ( 4 | "github.com/jzero-io/jzero/core/swaggerv2" 5 | "github.com/zeromicro/go-zero/rest" 6 | ) 7 | 8 | func (c *Custom) AddRoutes(server *rest.Server) { 9 | // server add swagger routes. If you do not want it, you can delete this line 10 | swaggerv2.RegisterRoutes(server) 11 | 12 | // add custom route 13 | // server.AddRoute(rest.Route{}) 14 | } 15 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/internal/middleware/error.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | func ErrorMiddleware(err error) (int, any) { 8 | return http.StatusOK, Body{ 9 | Data: nil, 10 | Code: http.StatusInternalServerError, 11 | Message: err.Error(), 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/internal/middleware/middleware.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/rest" 5 | "github.com/zeromicro/go-zero/rest/httpx" 6 | ) 7 | 8 | type Middleware struct {} 9 | 10 | func New() Middleware { 11 | return Middleware{} 12 | } 13 | 14 | func Register(server *rest.Server) { 15 | httpx.SetOkHandler(ResponseMiddleware) 16 | httpx.SetErrorHandler(ErrorMiddleware) 17 | httpx.SetValidator(NewValidator()) 18 | } 19 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/internal/middleware/response.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | ) 7 | 8 | type Body struct { 9 | Data interface{} `json:"data"` 10 | Code int `json:"code"` 11 | Message string `json:"message"` 12 | } 13 | 14 | func ResponseMiddleware(_ context.Context, data any) any { 15 | return Body{ 16 | Data: data, 17 | Code: http.StatusOK, 18 | Message: "success", 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/internal/svc/config.go.tpl: -------------------------------------------------------------------------------- 1 | package svc 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/core/logx" 5 | 6 | "{{ .Module }}/internal/config" 7 | ) 8 | 9 | func (sc *ServiceContext) GetConfig() (config.Config, error) { 10 | return sc.Config.GetConfig() 11 | } 12 | 13 | func (sc *ServiceContext) MustGetConfig() config.Config { 14 | c, err := sc.GetConfig() 15 | logx.Must(err) 16 | return c 17 | } 18 | 19 | func (sc *ServiceContext) SetConfigListener() { 20 | sc.Config.AddListener(func() { 21 | v, err := sc.GetConfig() 22 | if err != nil { 23 | logx.Errorf("reload config error: %v", err) 24 | return 25 | } 26 | 27 | logx.Infof("reload config successfully") 28 | switch v.Log.Level { 29 | case "debug": 30 | logx.SetLevel(logx.DebugLevel) 31 | case "info": 32 | logx.SetLevel(logx.InfoLevel) 33 | case "error": 34 | logx.SetLevel(logx.ErrorLevel) 35 | case "severe": 36 | logx.SetLevel(logx.SevereLevel) 37 | } 38 | 39 | // add custom logic here 40 | }) 41 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/internal/svc/service_context.go.tpl: -------------------------------------------------------------------------------- 1 | package svc 2 | 3 | import ( 4 | configurator "github.com/zeromicro/go-zero/core/configcenter" 5 | 6 | "{{ .Module }}/internal/config" 7 | "{{ .Module }}/internal/custom" 8 | "{{ .Module }}/internal/middleware" 9 | ) 10 | 11 | type ServiceContext struct { 12 | Config configurator.Configurator[config.Config] 13 | middleware.Middleware 14 | Custom *custom.Custom 15 | } 16 | 17 | func NewServiceContext(cc configurator.Configurator[config.Config]) *ServiceContext { 18 | sc := &ServiceContext{ 19 | Config: cc, 20 | Custom: custom.New(), 21 | Middleware: middleware.New(), 22 | } 23 | sc.SetConfigListener() 24 | return sc 25 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/main.go.tpl: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "{{ .Module }}/cmd" 5 | ) 6 | 7 | func main() { 8 | cmd.Execute() 9 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/plugins/plugins.go.tpl: -------------------------------------------------------------------------------- 1 | {{ if has "serverless_core" .Features }}// Code generated by jzero. DO NOT EDIT. 2 | package plugins 3 | 4 | import ( 5 | "{{ .Module }}/internal/svc" 6 | 7 | "github.com/zeromicro/go-zero/rest" 8 | ) 9 | 10 | type CoreSvcCtx = svc.ServiceContext 11 | 12 | func LoadPlugins(server *rest.Server, svcCtx CoreSvcCtx) {}{{ end }} -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/api/app/serverless/serverless.go.tpl: -------------------------------------------------------------------------------- 1 | {{ if has "serverless" .Features }}package serverless 2 | 3 | import ( 4 | "path/filepath" 5 | 6 | "github.com/jzero-io/jzero/core/configcenter/subscriber" 7 | configurator "github.com/zeromicro/go-zero/core/configcenter" 8 | "github.com/zeromicro/go-zero/core/logx" 9 | "github.com/zeromicro/go-zero/rest" 10 | 11 | "{{ .Module }}/internal/config" 12 | "{{ .Module }}/internal/handler" 13 | "{{ .Module }}/internal/svc" 14 | ) 15 | 16 | type Serverless struct { 17 | SvcCtx *svc.ServiceContext // 服务上下文 18 | HandlerFunc func(server *rest.Server, svcCtx *svc.ServiceContext) // 服务路由 19 | } 20 | 21 | // Serverless please replace coreSvcCtx any type to real CoreSvcCtx 22 | func New(coreSvcCtx any) *Serverless { 23 | cc := configurator.MustNewConfigCenter[config.Config](configurator.Config{ 24 | Type: "yaml", 25 | }, subscriber.MustNewFsnotifySubscriber(cfgFile, subscriber.WithUseEnv(true))) 26 | 27 | svcCtx := svc.NewServiceContext(cc) 28 | return &Serverless{ 29 | SvcCtx: svcCtx, 30 | HandlerFunc: handler.RegisterHandlers, 31 | } 32 | }{{end}} -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 jzero 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 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/README.md: -------------------------------------------------------------------------------- 1 | # templates 2 | 3 | jzero template repo with gateway project 4 | 5 | ```shell 6 | jzero new simplegateway --frame gateway 7 | ``` -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/.gitignore.tpl: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ 19 | 20 | # Go workspace file 21 | go.work 22 | go.work.sum 23 | 24 | # idea 25 | .idea 26 | 27 | # Vs Code 28 | .vscode 29 | 30 | # logs 31 | logs -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/.jzero.yaml.tpl: -------------------------------------------------------------------------------- 1 | syntax: v1 2 | 3 | gen: 4 | hooks: 5 | after: 6 | - jzero gen swagger -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/Dockerfile.tpl: -------------------------------------------------------------------------------- 1 | FROM --platform=$BUILDPLATFORM ghcr.io/jzero-io/jzero:latest as builder 2 | 3 | ARG TARGETARCH 4 | ARG LDFLAGS 5 | 6 | ENV GOPROXY https://goproxy.cn,direct 7 | 8 | WORKDIR /usr/local/go/src/app 9 | 10 | COPY ./ ./ 11 | 12 | RUN --mount=type=cache,target=/go/pkg CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH go build -a -ldflags="$LDFLAGS" -o /dist/app main.go \ 13 | && jzero gen swagger \ 14 | && cp -r etc /dist/etc \ 15 | && mkdir -p /dist/desc && cp -r desc/swagger /dist/desc 16 | 17 | 18 | FROM --platform=$TARGETPLATFORM alpine:latest 19 | 20 | WORKDIR /dist 21 | 22 | COPY --from=builder /dist . 23 | 24 | EXPOSE 8000 8001 25 | 26 | CMD ["./app", "server"] -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/Makefile.tpl: -------------------------------------------------------------------------------- 1 | ORGANIZATION = "organization" 2 | APP = "{{ .APP }}" 3 | 4 | VERSION := $(shell git describe --tags --always --match='v*' 2>/dev/null) 5 | ifeq ($(VERSION),) 6 | VERSION = "latest" 7 | endif 8 | 9 | COMMIT = $(shell git rev-parse --short HEAD 2>/dev/null) 10 | ifeq ($(COMMIT),) 11 | COMMIT = "" 12 | endif 13 | 14 | DATE = `date "+%Y-%m-%d %H:%M:%S"` 15 | ARCH = `go env GOARCH` 16 | 17 | .PHONY: build 18 | build: 19 | @go build -ldflags "-X '{{ .Module }}/cmd.Date=$(DATE)' -X '{{ .Module }}/cmd.Version=$(VERSION)' -X '{{ .Module }}/cmd.Commit=$(COMMIT)'" -o $(APP) main.go 20 | 21 | .PHONY: docker 22 | docker: 23 | @docker buildx build --platform linux/$(ARCH) --progress=plain -t $(ORGANIZATION)/$(APP):$(VERSION) . --load 24 | 25 | .PHONY: push 26 | push: 27 | @docker buildx create --use --name=mybuilder --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master 2> /dev/null || true 28 | @docker buildx build --platform linux/amd64,linux/arm64 --progress=plain -t $(ORGANIZATION)/$(APP):$(VERSION) . --push -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/README.md.tpl: -------------------------------------------------------------------------------- 1 | # {{ .APP }} 2 | 3 | ## Install Jzero Framework 4 | 5 | ```shell 6 | go install github.com/jzero-io/jzero/cmd/jzero@latest 7 | 8 | jzero check 9 | ``` 10 | 11 | ## Generate code 12 | 13 | ### Generate server code 14 | 15 | ```shell 16 | jzero gen 17 | ``` 18 | 19 | ### Generate client go code 20 | 21 | ```shell 22 | jzero gen sdk 23 | ``` 24 | 25 | ### Generate swagger code 26 | 27 | ```shell 28 | jzero gen swagger 29 | ``` 30 | 31 | ## Build docker image 32 | 33 | ```shell 34 | # add a builder first 35 | docker buildx create --use --name=mybuilder --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master 36 | 37 | # build and load 38 | docker buildx build --platform linux/{{ .GoArch }} --progress=plain -t {{ .APP }}:latest . --load 39 | ``` 40 | 41 | ## Documents 42 | 43 | https://docs.jzero.io -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/cmd/root.go.tpl: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var cfgFile string 10 | 11 | // rootCmd represents the base command when called without any subcommands 12 | var rootCmd = &cobra.Command{ 13 | Use: "{{ .APP }}", 14 | Short: "{{ .APP }} root", 15 | Long: "{{ .APP }} root.", 16 | CompletionOptions: cobra.CompletionOptions{ 17 | DisableDefaultCmd: true, 18 | }, 19 | } 20 | 21 | // Execute adds all child commands to the root command and sets flags appropriately. 22 | // This is called by main.main(). It only needs to happen once to the rootCmd. 23 | func Execute() { 24 | err := rootCmd.Execute() 25 | if err != nil { 26 | os.Exit(1) 27 | } 28 | } 29 | 30 | func init() { 31 | rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "etc/etc.yaml", "set config file") 32 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/cmd/version.go.tpl: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "runtime" 8 | "time" 9 | 10 | "github.com/spf13/cast" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | var ( 15 | Version string 16 | Commit string 17 | Date string 18 | ) 19 | 20 | // versionCmd represents the version command 21 | var versionCmd = &cobra.Command{ 22 | Use: "version", 23 | Short: "{{ .APP }} version", 24 | Long: `{{ .APP }} version`, 25 | Run: func(cmd *cobra.Command, args []string) { 26 | printVersion() 27 | }, 28 | } 29 | 30 | func printVersion() { 31 | var versionBuffer bytes.Buffer 32 | 33 | if Version == "" { 34 | Version = "unknown" 35 | } 36 | versionBuffer.WriteString(fmt.Sprintf("{{ .APP }} version %s %s/%s\n", Version, runtime.GOOS, runtime.GOARCH)) 37 | 38 | versionBuffer.WriteString(fmt.Sprintf("Go version %s\n", runtime.Version())) 39 | 40 | if Commit == "" { 41 | Commit = "unknown" 42 | } 43 | versionBuffer.WriteString(fmt.Sprintf("Git commit %s\n", Commit)) 44 | 45 | if Date != "" { 46 | Date = cast.ToString(cast.ToTimeInDefaultLocation(Date, time.Local)) 47 | } else { 48 | Date = "unknown" 49 | } 50 | versionBuffer.WriteString(fmt.Sprintf("Build date: %s\n", Date)) 51 | 52 | fmt.Print(versionBuffer.String()) 53 | } 54 | 55 | func init() { 56 | _ = os.Setenv("VERSION", Version) 57 | _ = os.Setenv("COMMIT", Commit) 58 | _ = os.Setenv("DATE", Date) 59 | 60 | rootCmd.AddCommand(versionCmd) 61 | } 62 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/desc/pb/embed.go.tpl: -------------------------------------------------------------------------------- 1 | package pb 2 | 3 | import ( 4 | "embed" 5 | ) 6 | 7 | var ( 8 | //go:embed * 9 | Embed embed.FS 10 | ) -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/desc/proto/third_party/google/api/annotations.proto: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/api/http.proto"; 20 | import "google/protobuf/descriptor.proto"; 21 | 22 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "AnnotationsProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | extend google.protobuf.MethodOptions { 29 | // See `HttpRule`. 30 | HttpRule http = 72295728; 31 | } 32 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/desc/proto/third_party/grpc-gateway/protoc-gen-openapiv2/options/annotations.proto: -------------------------------------------------------------------------------- 1 | 2 | syntax = "proto3"; 3 | 4 | package grpc.gateway.protoc_gen_openapiv2.options; 5 | 6 | import "google/protobuf/descriptor.proto"; 7 | import "grpc-gateway/protoc-gen-openapiv2/options/openapiv2.proto"; 8 | 9 | option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"; 10 | 11 | extend google.protobuf.FileOptions { 12 | // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. 13 | // 14 | // All IDs are the same, as assigned. It is okay that they are the same, as they extend 15 | // different descriptor messages. 16 | Swagger openapiv2_swagger = 1042; 17 | } 18 | extend google.protobuf.MethodOptions { 19 | // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. 20 | // 21 | // All IDs are the same, as assigned. It is okay that they are the same, as they extend 22 | // different descriptor messages. 23 | Operation openapiv2_operation = 1042; 24 | } 25 | extend google.protobuf.MessageOptions { 26 | // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. 27 | // 28 | // All IDs are the same, as assigned. It is okay that they are the same, as they extend 29 | // different descriptor messages. 30 | Schema openapiv2_schema = 1042; 31 | } 32 | extend google.protobuf.ServiceOptions { 33 | // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. 34 | // 35 | // All IDs are the same, as assigned. It is okay that they are the same, as they extend 36 | // different descriptor messages. 37 | Tag openapiv2_tag = 1042; 38 | } 39 | extend google.protobuf.FieldOptions { 40 | // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. 41 | // 42 | // All IDs are the same, as assigned. It is okay that they are the same, as they extend 43 | // different descriptor messages. 44 | JSONSchema openapiv2_field = 1042; 45 | } 46 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/desc/proto/third_party/jzero/api/http.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package jzero.api; 4 | 5 | option go_package = "github.com/jzero-io/desc/proto/third_party/jzero/api"; 6 | 7 | import "google/protobuf/descriptor.proto"; 8 | 9 | extend google.protobuf.MethodOptions { 10 | HttpRule http = 10000; 11 | } 12 | 13 | extend google.protobuf.ServiceOptions { 14 | HttpRule http_group = 10001; 15 | } 16 | 17 | message HttpRule { 18 | string middleware = 1; 19 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/desc/proto/third_party/jzero/api/zrpc.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package jzero.api; 4 | 5 | option go_package = "github.com/jzero-io/desc/proto/third_party/jzero/api"; 6 | 7 | import "google/protobuf/descriptor.proto"; 8 | 9 | extend google.protobuf.MethodOptions { 10 | ZrpcRule zrpc = 10002; 11 | } 12 | 13 | extend google.protobuf.ServiceOptions { 14 | ZrpcRule zrpc_group = 10003; 15 | } 16 | 17 | message ZrpcRule { 18 | string middleware = 1; 19 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/desc/proto/v1/version.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package versionpb; 4 | 5 | import "google/api/annotations.proto"; 6 | import "grpc-gateway/protoc-gen-openapiv2/options/annotations.proto"; 7 | 8 | option go_package = "./pb/versionpb"; 9 | 10 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { 11 | info: { 12 | version: "v1"; 13 | }; 14 | }; 15 | 16 | message VersionRequest {} 17 | 18 | message VersionResponse { 19 | string version = 1; 20 | string goVersion = 2; 21 | string commit = 3; 22 | string date = 4; 23 | } 24 | 25 | service Version { 26 | rpc Version(VersionRequest) returns(VersionResponse) { 27 | option (google.api.http) = { 28 | get: "/api/v1/version" 29 | }; 30 | }; 31 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/etc/etc.yaml.tpl: -------------------------------------------------------------------------------- 1 | zrpc: 2 | listenOn: 0.0.0.0:8000 3 | mode: dev 4 | name: {{ .APP }}.rpc 5 | gateway: 6 | name: {{ .APP }}.gw 7 | port: 8001 8 | upstreams: 9 | - grpc: 10 | endpoints: 11 | - 0.0.0.0:8000 12 | name: {{ .APP }}.gw 13 | 14 | log: 15 | serviceName: {{ .APP }} 16 | encoding: plain 17 | level: info 18 | mode: console -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/go.mod.tpl: -------------------------------------------------------------------------------- 1 | module {{ .Module }} 2 | 3 | go {{ .GoVersion }} -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/config/config.go.tpl: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/core/logx" 5 | "github.com/zeromicro/go-zero/gateway" 6 | "github.com/zeromicro/go-zero/zrpc" 7 | ) 8 | 9 | type Config struct { 10 | Zrpc ZrpcConf 11 | Gateway GatewayConf 12 | Log LogConf 13 | 14 | Banner BannerConf 15 | } 16 | 17 | type ZrpcConf struct { 18 | zrpc.RpcServerConf 19 | } 20 | 21 | type GatewayConf struct { 22 | gateway.GatewayConf 23 | } 24 | 25 | type LogConf struct { 26 | logx.LogConf 27 | } 28 | 29 | type BannerConf struct { 30 | Text string `json:",default=JZERO"` 31 | Color string `json:",default=green"` 32 | FontName string `json:",default=starwars,options=big|larry3d|starwars|standard"` 33 | } 34 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/custom/custom.go.tpl: -------------------------------------------------------------------------------- 1 | package custom 2 | 3 | import ( 4 | "os" 5 | 6 | configurator "github.com/zeromicro/go-zero/core/configcenter" 7 | 8 | "{{.Module}}/internal/config" 9 | ) 10 | 11 | type Custom struct { 12 | Config configurator.Configurator[config.Config] 13 | } 14 | 15 | func New(config configurator.Configurator[config.Config]) *Custom { 16 | return &Custom{Config: config} 17 | } 18 | 19 | // Start Please add custom logic here. 20 | func (c *Custom) Start() {} 21 | 22 | // Stop Please add shut down logic here. 23 | func (c *Custom) Stop() { 24 | conf, err := c.Config.GetConfig() 25 | if err == nil { 26 | // remove temp pb file 27 | if len(conf.Gateway.Upstreams) > 0 { 28 | for _, p := range conf.Gateway.Upstreams[0].ProtoSets { 29 | _ = os.Remove(p) 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/custom/routes.go.tpl: -------------------------------------------------------------------------------- 1 | package custom 2 | 3 | import ( 4 | "github.com/jzero-io/jzero/core/swaggerv2" 5 | "github.com/zeromicro/go-zero/gateway" 6 | ) 7 | 8 | func (c *Custom) AddRoutes(gw *gateway.Server) { 9 | // gw add swagger routes. If you do not want it, you can delete this line 10 | swaggerv2.RegisterRoutes(gw.Server) 11 | 12 | // add custom route 13 | // gw.AddRoute(rest.Route{}) 14 | } 15 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/middleware/error.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "net/http" 5 | 6 | "google.golang.org/grpc/status" 7 | ) 8 | 9 | func ErrorMiddleware(err error) (int, any) { 10 | code := http.StatusInternalServerError 11 | message := err.Error() 12 | 13 | // from grpc error 14 | if st, ok := status.FromError(err); ok { 15 | code = int(st.Code()) 16 | message = st.Message() 17 | } 18 | 19 | return http.StatusOK, Body{ 20 | Data: nil, 21 | Code: code, 22 | Message: message, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/middleware/header_processor.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | 7 | "github.com/zeromicro/go-zero/gateway" 8 | "google.golang.org/grpc" 9 | ) 10 | 11 | func WithHeaderProcessor() gateway.Option { 12 | return gateway.WithHeaderProcessor(func(header http.Header) []string { 13 | var headers []string 14 | //// You can add header from request header here 15 | //// for example 16 | //for k, v := range header { 17 | // if k == "Authorization" { 18 | // headers = append(headers, fmt.Sprintf("%s:%s", k, strings.Join(v, ";"))) 19 | // } 20 | //} 21 | return headers 22 | }) 23 | } 24 | 25 | func WithValueMiddleware(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { 26 | //md, b := metadata.FromIncomingContext(ctx) 27 | //if !b { 28 | // return handler(ctx, req) 29 | //} 30 | //// You can verify Authorization here and set user info in context value 31 | //// get Authorization 32 | //value := md.Get("Authorization") 33 | //if len(value) == 1 { 34 | // // set context value 35 | // ctx = context.WithValue(ctx, "Authorization", value[0]) 36 | //} 37 | return handler(ctx, req) 38 | } 39 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/middleware/middleware.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/gateway" 5 | "github.com/zeromicro/go-zero/zrpc" 6 | "github.com/zeromicro/go-zero/rest/httpx" 7 | ) 8 | 9 | func Register(z *zrpc.RpcServer, gw *gateway.Server) { 10 | z.AddUnaryInterceptors(ValidatorMiddleware) 11 | z.AddUnaryInterceptors(WithValueMiddleware) 12 | 13 | httpx.SetErrorHandler(ErrorMiddleware) 14 | gw.Use(ResponseMiddleware) 15 | } 16 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/middleware/response.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "net/http" 7 | "strings" 8 | 9 | "github.com/zeromicro/go-zero/core/logc" 10 | "github.com/zeromicro/go-zero/core/logx" 11 | "github.com/zeromicro/go-zero/rest/httpx" 12 | ) 13 | 14 | type Body struct { 15 | Data interface{} `json:"data"` 16 | Code int `json:"code"` 17 | Message string `json:"message"` 18 | } 19 | 20 | type responseWriter struct { 21 | http.ResponseWriter 22 | statusCode int 23 | body bytes.Buffer 24 | } 25 | 26 | func (rw *responseWriter) WriteHeader(statusCode int) { 27 | rw.statusCode = statusCode 28 | rw.ResponseWriter.WriteHeader(statusCode) 29 | } 30 | 31 | func (rw *responseWriter) Write(p []byte) (int, error) { 32 | return rw.body.Write(p) 33 | } 34 | 35 | func (rw *responseWriter) Body() []byte { 36 | return rw.body.Bytes() 37 | } 38 | 39 | func ResponseMiddleware(next http.HandlerFunc) http.HandlerFunc { 40 | return func(w http.ResponseWriter, r *http.Request) { 41 | logCtx := logx.ContextWithFields(r.Context(), logx.Field("path", r.URL.Path)) 42 | 43 | rw := &responseWriter{ 44 | ResponseWriter: w, 45 | statusCode: http.StatusOK, 46 | } 47 | 48 | next.ServeHTTP(rw, r) 49 | 50 | if strings.Contains(strings.ToLower(w.Header().Get("Content-Type")), "application/json") { 51 | var resp map[string]interface{} 52 | err := json.Unmarshal(rw.Body(), &resp) 53 | if err != nil { 54 | logc.Errorf(logCtx, "Unmarshal resp error: %s\n", err.Error()) 55 | return 56 | } 57 | 58 | if _, ok := resp["code"]; ok { 59 | httpx.OkJson(w, resp) 60 | return 61 | } 62 | 63 | wrappedResp := Body{ 64 | Data: resp, 65 | Code: http.StatusOK, 66 | Message: "success", 67 | } 68 | httpx.OkJson(w, wrappedResp) 69 | return 70 | } 71 | 72 | _, err := w.Write(rw.Body()) 73 | if err != nil { 74 | logc.Errorf(logCtx, "Write response error: %s\n", err.Error()) 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/middleware/validator.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc" 7 | "google.golang.org/grpc/codes" 8 | "google.golang.org/grpc/status" 9 | ) 10 | 11 | type Validator interface { 12 | ValidateAll() error 13 | } 14 | 15 | func ValidatorMiddleware(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { 16 | if r, ok := req.(Validator); ok { 17 | if err := r.ValidateAll(); err != nil { 18 | return nil, status.Error(codes.InvalidArgument, err.Error()) 19 | } 20 | } 21 | 22 | return handler(ctx, req) 23 | } 24 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/svc/config.go.tpl: -------------------------------------------------------------------------------- 1 | package svc 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/core/logx" 5 | 6 | "{{ .Module }}/internal/config" 7 | ) 8 | 9 | func (sc *ServiceContext) GetConfig() (config.Config, error) { 10 | return sc.Config.GetConfig() 11 | } 12 | 13 | func (sc *ServiceContext) MustGetConfig() config.Config { 14 | c, err := sc.GetConfig() 15 | logx.Must(err) 16 | return c 17 | } 18 | 19 | func (sc *ServiceContext) SetConfigListener() { 20 | sc.Config.AddListener(func() { 21 | v, err := sc.GetConfig() 22 | if err != nil { 23 | logx.Errorf("reload config error: %v", err) 24 | return 25 | } 26 | 27 | logx.Infof("reload config successfully") 28 | switch v.Log.Level { 29 | case "debug": 30 | logx.SetLevel(logx.DebugLevel) 31 | case "info": 32 | logx.SetLevel(logx.InfoLevel) 33 | case "error": 34 | logx.SetLevel(logx.ErrorLevel) 35 | case "severe": 36 | logx.SetLevel(logx.SevereLevel) 37 | } 38 | 39 | // add custom logic here 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/internal/svc/service_context.go.tpl: -------------------------------------------------------------------------------- 1 | package svc 2 | 3 | import ( 4 | "{{ .Module }}/internal/config" 5 | "{{ .Module }}/internal/custom" 6 | 7 | configurator "github.com/zeromicro/go-zero/core/configcenter" 8 | ) 9 | 10 | type ServiceContext struct { 11 | Config configurator.Configurator[config.Config] 12 | 13 | Custom *custom.Custom 14 | } 15 | 16 | func NewServiceContext(cc configurator.Configurator[config.Config]) *ServiceContext { 17 | sc := &ServiceContext{ 18 | Config: cc, 19 | Custom: custom.New(cc), 20 | } 21 | sc.SetConfigListener() 22 | return sc 23 | } 24 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/gateway/app/main.go.tpl: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "{{ .Module }}/cmd" 5 | ) 6 | 7 | func main() { 8 | cmd.Execute() 9 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 jzero 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 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/README.md: -------------------------------------------------------------------------------- 1 | # templates 2 | 3 | jzero template repo with only rpc project 4 | 5 | ```shell 6 | jzero new simplerpc --frame rpc 7 | ``` -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/.gitignore.tpl: -------------------------------------------------------------------------------- 1 | # If you prefer the allow list template instead of the deny list, see community template: 2 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 3 | # 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Dependency directories (remove the comment below to include it) 18 | # vendor/ 19 | 20 | # Go workspace file 21 | go.work 22 | go.work.sum 23 | 24 | # idea 25 | .idea 26 | 27 | # Vs Code 28 | .vscode 29 | 30 | # logs 31 | logs -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/.jzero.yaml.tpl: -------------------------------------------------------------------------------- 1 | syntax: v1 2 | 3 | gen: 4 | # add custom gen flags 5 | 6 | # add custom gen zrpcclient flags 7 | zrpcclient: -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/Dockerfile.tpl: -------------------------------------------------------------------------------- 1 | FROM --platform=$BUILDPLATFORM ghcr.io/jzero-io/jzero:latest as builder 2 | 3 | ARG TARGETARCH 4 | ARG LDFLAGS 5 | 6 | ENV GOPROXY https://goproxy.cn,direct 7 | 8 | WORKDIR /usr/local/go/src/app 9 | 10 | COPY ./ ./ 11 | 12 | RUN --mount=type=cache,target=/go/pkg CGO_ENABLED=0 GOOS=linux GOARCH=$TARGETARCH go build -a -ldflags="$LDFLAGS" -o /dist/app main.go \ 13 | && jzero gen swagger \ 14 | && cp -r etc /dist/etc \ 15 | && mkdir -p /dist/desc && cp -r desc/swagger /dist/desc 16 | 17 | 18 | FROM --platform=$TARGETPLATFORM alpine:latest 19 | 20 | WORKDIR /dist 21 | 22 | COPY --from=builder /dist . 23 | 24 | EXPOSE 8000 8001 25 | 26 | CMD ["./app", "server"] -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/README.md.tpl: -------------------------------------------------------------------------------- 1 | # {{ .APP }} 2 | 3 | ## Install Jzero Framework 4 | 5 | ```shell 6 | go install github.com/jzero-io/jzero/cmd/jzero@latest 7 | 8 | jzero check 9 | ``` 10 | 11 | ## Generate code 12 | 13 | ### Generate server code 14 | 15 | ```shell 16 | jzero gen 17 | ``` 18 | 19 | ### Generate swagger code 20 | 21 | ```shell 22 | jzero gen swagger 23 | ``` 24 | 25 | ## Build docker image 26 | 27 | ```shell 28 | # add a builder first 29 | docker buildx create --use --name=mybuilder --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master 30 | 31 | # build and load 32 | docker buildx build --platform linux/{{ .GoArch }} --progress=plain -t {{ .APP }}:latest . --load 33 | ``` 34 | 35 | ## Documents 36 | 37 | https://docs.jzero.io -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/cmd/root.go.tpl: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var cfgFile string 10 | 11 | // rootCmd represents the base command when called without any subcommands 12 | var rootCmd = &cobra.Command{ 13 | Use: "{{ .APP }}", 14 | Short: "{{ .APP }} root", 15 | Long: "{{ .APP }} root.", 16 | CompletionOptions: cobra.CompletionOptions{ 17 | DisableDefaultCmd: true, 18 | }, 19 | } 20 | 21 | // Execute adds all child commands to the root command and sets flags appropriately. 22 | // This is called by main.main(). It only needs to happen once to the rootCmd. 23 | func Execute() { 24 | err := rootCmd.Execute() 25 | if err != nil { 26 | os.Exit(1) 27 | } 28 | } 29 | 30 | func init() { 31 | rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "etc/etc.yaml", "config file (default is project root dir etc/etc.yaml)") 32 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/cmd/server.go.tpl: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | configurator "github.com/zeromicro/go-zero/core/configcenter" 5 | "github.com/jzero-io/jzero/core/configcenter/subscriber" 6 | "github.com/spf13/cobra" 7 | "github.com/zeromicro/go-zero/core/logx" 8 | "github.com/zeromicro/go-zero/core/service" 9 | "github.com/common-nighthawk/go-figure" 10 | 11 | "{{ .Module }}/internal/config" 12 | "{{ .Module }}/internal/middleware" 13 | "{{ .Module }}/internal/server" 14 | "{{ .Module }}/internal/svc" 15 | ) 16 | 17 | // serverCmd represents the server command 18 | var serverCmd = &cobra.Command{ 19 | Use: "server", 20 | Short: "{{ .APP }} server", 21 | Long: "{{ .APP }} server", 22 | Run: func(cmd *cobra.Command, args []string) { 23 | cc := configurator.MustNewConfigCenter[config.Config](configurator.Config{ 24 | Type: "yaml", 25 | }, subscriber.MustNewFsnotifySubscriber(cfgFile, subscriber.WithUseEnv(true))) 26 | c, err := cc.GetConfig() 27 | logx.Must(err) 28 | 29 | // set up logger 30 | logx.Must(logx.SetUp(c.Log.LogConf)) 31 | 32 | svcCtx := svc.NewServiceContext(cc) 33 | run(svcCtx) 34 | }, 35 | } 36 | 37 | func run(svcCtx *svc.ServiceContext) { 38 | c := svcCtx.MustGetConfig() 39 | 40 | zrpc := server.RegisterZrpc(c, svcCtx) 41 | middleware.Register(zrpc) 42 | 43 | group := service.NewServiceGroup() 44 | group.Add(zrpc) 45 | group.Add(svcCtx.Custom) 46 | 47 | printBanner(c) 48 | printVersion() 49 | 50 | logx.Infof("Starting rpc server at %s...", c.Zrpc.ListenOn) 51 | group.Start() 52 | } 53 | 54 | func printBanner(c config.Config) { 55 | figure.NewColorFigure(c.Banner.Text, c.Banner.FontName, c.Banner.Color, true).Print() 56 | } 57 | 58 | func init() { 59 | rootCmd.AddCommand(serverCmd) 60 | } 61 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/cmd/version.go.tpl: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os" 7 | "runtime" 8 | "time" 9 | 10 | "github.com/spf13/cast" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | var ( 15 | Version string 16 | Commit string 17 | Date string 18 | ) 19 | 20 | // versionCmd represents the version command 21 | var versionCmd = &cobra.Command{ 22 | Use: "version", 23 | Short: "{{ .APP }} version", 24 | Long: `{{ .APP }} version`, 25 | Run: func(cmd *cobra.Command, args []string) { 26 | printVersion() 27 | }, 28 | } 29 | 30 | func printVersion() { 31 | var versionBuffer bytes.Buffer 32 | 33 | if Version == "" { 34 | Version = "unknown" 35 | } 36 | versionBuffer.WriteString(fmt.Sprintf("{{ .APP }} version %s %s/%s\n", Version, runtime.GOOS, runtime.GOARCH)) 37 | 38 | versionBuffer.WriteString(fmt.Sprintf("Go version %s\n", runtime.Version())) 39 | 40 | if Commit == "" { 41 | Commit = "unknown" 42 | } 43 | versionBuffer.WriteString(fmt.Sprintf("Git commit %s\n", Commit)) 44 | 45 | if Date != "" { 46 | Date = cast.ToString(cast.ToTimeInDefaultLocation(Date, time.Local)) 47 | } else { 48 | Date = "unknown" 49 | } 50 | versionBuffer.WriteString(fmt.Sprintf("Build date: %s\n", Date)) 51 | 52 | fmt.Print(versionBuffer.String()) 53 | } 54 | 55 | func init() { 56 | _ = os.Setenv("VERSION", Version) 57 | _ = os.Setenv("COMMIT", Commit) 58 | _ = os.Setenv("DATE", Date) 59 | 60 | rootCmd.AddCommand(versionCmd) 61 | } 62 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/desc/proto/third_party/google/api/annotations.proto: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, Google Inc. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | package google.api; 18 | 19 | import "google/api/http.proto"; 20 | import "google/protobuf/descriptor.proto"; 21 | 22 | option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations"; 23 | option java_multiple_files = true; 24 | option java_outer_classname = "AnnotationsProto"; 25 | option java_package = "com.google.api"; 26 | option objc_class_prefix = "GAPI"; 27 | 28 | extend google.protobuf.MethodOptions { 29 | // See `HttpRule`. 30 | HttpRule http = 72295728; 31 | } 32 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/desc/proto/third_party/jzero/api/zrpc.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package jzero.api; 4 | 5 | option go_package = "github.com/jzero-io/desc/proto/third_party/jzero/api"; 6 | 7 | import "google/protobuf/descriptor.proto"; 8 | 9 | extend google.protobuf.MethodOptions { 10 | ZrpcRule zrpc = 10002; 11 | } 12 | 13 | extend google.protobuf.ServiceOptions { 14 | ZrpcRule zrpc_group = 10003; 15 | } 16 | 17 | message ZrpcRule { 18 | string middleware = 1; 19 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/desc/proto/v1/version.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package versionpb; 4 | 5 | option go_package = "./pb/versionpb"; 6 | 7 | message VersionRequest {} 8 | 9 | message VersionResponse { 10 | string version = 1; 11 | string goVersion = 2; 12 | string commit = 3; 13 | string date = 4; 14 | } 15 | 16 | service Version { 17 | rpc Version(VersionRequest) returns(VersionResponse) {}; 18 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/etc/etc.yaml.tpl: -------------------------------------------------------------------------------- 1 | zrpc: 2 | listenOn: 0.0.0.0:8000 3 | mode: dev 4 | name: {{ .APP }}.rpc 5 | 6 | log: 7 | serviceName: {{ .APP }} 8 | encoding: plain 9 | level: info 10 | mode: console -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/go.mod.tpl: -------------------------------------------------------------------------------- 1 | module {{ .Module }} 2 | 3 | go {{ .GoVersion }} -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/internal/config/config.go.tpl: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/core/logx" 5 | "github.com/zeromicro/go-zero/zrpc" 6 | ) 7 | 8 | type Config struct { 9 | Zrpc ZrpcConf 10 | Log LogConf 11 | 12 | Banner BannerConf 13 | } 14 | 15 | type ZrpcConf struct { 16 | zrpc.RpcServerConf 17 | } 18 | 19 | type LogConf struct { 20 | logx.LogConf 21 | } 22 | 23 | type BannerConf struct { 24 | Text string `json:",default=JZERO"` 25 | Color string `json:",default=green"` 26 | FontName string `json:",default=starwars,options=big|larry3d|starwars|standard"` 27 | } 28 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/internal/custom/custom.go.tpl: -------------------------------------------------------------------------------- 1 | package custom 2 | 3 | type Custom struct{} 4 | 5 | func New() *Custom { 6 | return &Custom{} 7 | } 8 | 9 | // Start Please add custom logic here. 10 | func (c *Custom) Start() {} 11 | 12 | // Stop Please add shut down logic here. 13 | func (c *Custom) Stop() {} 14 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/internal/middleware/middleware.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/zrpc" 5 | ) 6 | 7 | func Register(z *zrpc.RpcServer) { 8 | z.AddUnaryInterceptors(ValidatorMiddleware) 9 | } 10 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/internal/middleware/validator.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | 6 | "google.golang.org/grpc" 7 | "google.golang.org/grpc/codes" 8 | "google.golang.org/grpc/status" 9 | ) 10 | 11 | type Validator interface { 12 | ValidateAll() error 13 | } 14 | 15 | func ValidatorMiddleware(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { 16 | if r, ok := req.(Validator); ok { 17 | if err := r.ValidateAll(); err != nil { 18 | return nil, status.Error(codes.InvalidArgument, err.Error()) 19 | } 20 | } 21 | 22 | return handler(ctx, req) 23 | } 24 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/internal/svc/config.go.tpl: -------------------------------------------------------------------------------- 1 | package svc 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/core/logx" 5 | 6 | "{{ .Module }}/internal/config" 7 | ) 8 | 9 | func (sc *ServiceContext) GetConfig() (config.Config, error) { 10 | return sc.Config.GetConfig() 11 | } 12 | 13 | func (sc *ServiceContext) MustGetConfig() config.Config { 14 | c, err := sc.GetConfig() 15 | logx.Must(err) 16 | return c 17 | } 18 | 19 | func (sc *ServiceContext) SetConfigListener() { 20 | sc.Config.AddListener(func() { 21 | v, err := sc.GetConfig() 22 | if err != nil { 23 | logx.Errorf("reload config error: %v", err) 24 | return 25 | } 26 | 27 | logx.Infof("reload config successfully") 28 | switch v.Log.Level { 29 | case "debug": 30 | logx.SetLevel(logx.DebugLevel) 31 | case "info": 32 | logx.SetLevel(logx.InfoLevel) 33 | case "error": 34 | logx.SetLevel(logx.ErrorLevel) 35 | case "severe": 36 | logx.SetLevel(logx.SevereLevel) 37 | } 38 | 39 | // add custom logic here 40 | }) 41 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/internal/svc/service_context.go.tpl: -------------------------------------------------------------------------------- 1 | package svc 2 | 3 | import ( 4 | "{{ .Module }}/internal/config" 5 | "{{ .Module }}/internal/custom" 6 | 7 | configurator "github.com/zeromicro/go-zero/core/configcenter" 8 | ) 9 | 10 | type ServiceContext struct { 11 | Config configurator.Configurator[config.Config] 12 | 13 | Custom *custom.Custom 14 | } 15 | 16 | func NewServiceContext(cc configurator.Configurator[config.Config]) *ServiceContext { 17 | sc := &ServiceContext{ 18 | Config: cc, 19 | Custom: custom.New(), 20 | } 21 | sc.SetConfigListener() 22 | return sc 23 | } 24 | -------------------------------------------------------------------------------- /cmd/jzero/.template/frame/rpc/app/main.go.tpl: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "{{ .Module }}/cmd" 5 | ) 6 | 7 | func main() { 8 | cmd.Execute() 9 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/api/logic.tpl: -------------------------------------------------------------------------------- 1 | package {{.pkgName}} 2 | 3 | import ( 4 | "net/http" 5 | 6 | {{.imports}} 7 | ) 8 | 9 | type {{.logic}} struct { 10 | logx.Logger 11 | ctx context.Context 12 | svcCtx *svc.ServiceContext 13 | r *http.Request 14 | {{if eq .responseType "error"}}w http.ResponseWriter{{end}} 15 | } 16 | 17 | {{if .hasDoc}}{{.doc}}{{end}} 18 | func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext, r *http.Request, {{if eq .responseType "error"}}w http.ResponseWriter{{end}}) *{{.logic}} { 19 | return &{{.logic}}{ 20 | Logger: logx.WithContext(ctx), 21 | ctx: ctx, 22 | svcCtx: svcCtx, 23 | r: r, 24 | {{if eq .responseType "error"}}w: w,{{end}} 25 | } 26 | } 27 | 28 | func (l *{{.logic}}) {{.function}}({{.request}}) {{.responseType}} { 29 | // todo: add your logic here and delete this line 30 | 31 | {{.returnString}} 32 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/delete.tpl: -------------------------------------------------------------------------------- 1 | func (m *default{{.upperStartCamelObject}}Model) Delete(ctx context.Context, session sqlx.Session, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error { 2 | sb := sqlbuilder.DeleteFrom(m.table) 3 | sb.Where(sb.EQ(condition.Field("{{.originalPrimaryKey}}"), {{.lowerStartCamelPrimaryKey}})) 4 | statement, args := sb.Build() 5 | var err error 6 | if session != nil { 7 | _, err = session.ExecCtx(ctx, statement, args...) 8 | } else { 9 | _, err = m.conn.ExecCtx(ctx, statement, args...) 10 | } 11 | return err 12 | } 13 | 14 | func (m *default{{.upperStartCamelObject}}Model) DeleteWithCache(ctx context.Context, session sqlx.Session, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error { 15 | {{if .withCache}}{{if .containsIndexCache}}data, err := m.FindOne(ctx, session, {{.lowerStartCamelPrimaryKey}}) 16 | if err != nil{ 17 | return err 18 | } 19 | 20 | {{end}} {{.keys}} 21 | _, err {{if .containsIndexCache}}={{else}}:={{end}} m.cachedConn.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { 22 | sb := sqlbuilder.DeleteFrom(m.table) 23 | sb.Where(sb.EQ(condition.Field("{{.originalPrimaryKey}}"), {{.lowerStartCamelPrimaryKey}})) 24 | statement, args := sb.Build() 25 | if session != nil { 26 | return session.ExecCtx(ctx, statement, args...) 27 | } 28 | return conn.ExecCtx(ctx, statement, args...) 29 | }, {{.keyValues}}) 30 | return err{{else}}return m.Delete(ctx, session, {{.lowerStartCamelPrimaryKey}}){{end}} 31 | } 32 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/err.tpl: -------------------------------------------------------------------------------- 1 | package {{.pkg}} 2 | 3 | import "github.com/zeromicro/go-zero/core/stores/sqlx" 4 | 5 | var ErrNotFound = sqlx.ErrNotFound 6 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/field.tpl: -------------------------------------------------------------------------------- 1 | {{.name}} {{.type}} {{.tag}} {{if .hasComment}}// {{.comment}}{{end}} -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/find-one-by-field-extra-method.tpl: -------------------------------------------------------------------------------- 1 | func (m *default{{.upperStartCamelObject}}Model) formatPrimary(primary any) string { 2 | return fmt.Sprintf("%s%v", {{.primaryKeyLeft}}, primary) 3 | } 4 | 5 | func (m *default{{.upperStartCamelObject}}Model) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary any) error { 6 | sb := sqlbuilder.Select({{.lowerStartCamelObject}}Rows).From(m.table) 7 | sb.Where(sb.EQ(condition.Field("{{.originalPrimaryField}}"), primary)) 8 | sql, args := sb.Build() 9 | return conn.QueryRowCtx(ctx, v, sql, args...) 10 | } 11 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/find-one-by-field.tpl: -------------------------------------------------------------------------------- 1 | func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}(ctx context.Context, session sqlx.Session, {{.in}}) (*{{.upperStartCamelObject}}, error) { 2 | var resp {{.upperStartCamelObject}} 3 | var err error 4 | 5 | sb := sqlbuilder.Select({{.lowerStartCamelObject}}Rows).From(m.table) 6 | condition.SelectByWhereRawSql(sb, "{{.originalField}}", {{.lowerStartCamelField}}) 7 | sb.Limit(1) 8 | 9 | sql, args := sb.Build() 10 | 11 | if session != nil { 12 | err = session.QueryRowCtx(ctx, &resp, sql, args...) 13 | } else { 14 | err = m.conn.QueryRowCtx(ctx, &resp, sql, args...) 15 | } 16 | 17 | switch err { 18 | case nil: 19 | return &resp, nil 20 | case sqlx.ErrNotFound: 21 | return nil, ErrNotFound 22 | default: 23 | return nil, err 24 | } 25 | } 26 | 27 | func (m *default{{.upperStartCamelObject}}Model) FindOneBy{{.upperField}}WithCache(ctx context.Context, session sqlx.Session, {{.in}}) (*{{.upperStartCamelObject}}, error) { 28 | {{if .withCache}}{{.cacheKey}} 29 | var resp {{.upperStartCamelObject}} 30 | err := m.cachedConn.QueryRowIndexCtx(ctx, &resp, {{.cacheKeyVariable}}, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v any) (i any, e error) { 31 | sb := sqlbuilder.Select({{.lowerStartCamelObject}}Rows).From(m.table) 32 | condition.SelectByWhereRawSql(sb, "{{.originalField}}", {{.lowerStartCamelField}}) 33 | sb.Limit(1) 34 | sql, args := sb.Build() 35 | var err error 36 | 37 | if session != nil { 38 | err = session.QueryRowCtx(ctx, &resp, sql, args...) 39 | } else { 40 | err = conn.QueryRowCtx(ctx, &resp, sql, args...) 41 | } 42 | if err != nil { 43 | return nil, err 44 | } 45 | return resp.{{.upperStartCamelPrimaryKey}}, nil 46 | }, m.queryPrimary) 47 | switch err { 48 | case nil: 49 | return &resp, nil 50 | case sqlc.ErrNotFound: 51 | return nil, ErrNotFound 52 | default: 53 | return nil, err 54 | }{{else}}return m.FindOneBy{{.upperField}}(ctx, session, {{.lowerStartCamelField}}){{end}} 55 | } 56 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/find-one.tpl: -------------------------------------------------------------------------------- 1 | func (m *default{{.upperStartCamelObject}}Model) FindOne(ctx context.Context, session sqlx.Session, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) { 2 | sb := sqlbuilder.Select({{.lowerStartCamelObject}}Rows).From(m.table) 3 | sb.Where(sb.EQ(condition.Field("{{.originalPrimaryKey}}"), {{.lowerStartCamelPrimaryKey}})) 4 | sb.Limit(1) 5 | sql, args := sb.Build() 6 | var resp {{.upperStartCamelObject}} 7 | var err error 8 | if session != nil { 9 | err = session.QueryRowCtx(ctx, &resp, sql, args...) 10 | } else { 11 | err = m.conn.QueryRowCtx(ctx, &resp, sql, args...) 12 | } 13 | switch err { 14 | case nil: 15 | return &resp, nil 16 | case sqlx.ErrNotFound: 17 | return nil, ErrNotFound 18 | default: 19 | return nil, err 20 | } 21 | } 22 | 23 | func (m *default{{.upperStartCamelObject}}Model) FindOneWithCache(ctx context.Context, session sqlx.Session, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) { 24 | {{if .withCache}}{{.cacheKey}} 25 | var resp {{.upperStartCamelObject}} 26 | err := m.cachedConn.QueryRowCtx(ctx, &resp, {{.cacheKeyVariable}}, func(ctx context.Context, conn sqlx.SqlConn, v any) error { 27 | sb := sqlbuilder.Select({{.lowerStartCamelObject}}Rows).From(m.table) 28 | sb.Where(sb.EQ(condition.Field("{{.originalPrimaryKey}}"), {{.lowerStartCamelPrimaryKey}})) 29 | sql, args := sb.Build() 30 | if session != nil { 31 | return session.QueryRowCtx(ctx, v, sql, args...) 32 | } 33 | return conn.QueryRowCtx(ctx, v, sql, args...) 34 | }) 35 | switch err { 36 | case nil: 37 | return &resp, nil 38 | case sqlc.ErrNotFound: 39 | return nil, ErrNotFound 40 | default: 41 | return nil, err 42 | }{{else}}return m.FindOne(ctx, session, {{.lowerStartCamelPrimaryKey}}){{end}} 43 | } 44 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/import-no-cache.tpl: -------------------------------------------------------------------------------- 1 | import ( 2 | "context" 3 | "database/sql" 4 | "strings" 5 | {{if .time}}"time"{{end}} 6 | 7 | "github.com/zeromicro/go-zero/core/stores/sqlc" 8 | "github.com/zeromicro/go-zero/core/stores/sqlx" 9 | "github.com/huandu/go-sqlbuilder" 10 | "github.com/jzero-io/jzero/core/stores/condition" 11 | "github.com/jzero-io/jzero/core/stores/modelx" 12 | "github.com/eddieowens/opts" 13 | 14 | {{.third}} 15 | ) 16 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/import.tpl: -------------------------------------------------------------------------------- 1 | import ( 2 | "context" 3 | "database/sql" 4 | "fmt" 5 | "strings" 6 | {{if .time}}"time"{{end}} 7 | 8 | "github.com/zeromicro/go-zero/core/stores/sqlc" 9 | "github.com/zeromicro/go-zero/core/stores/sqlx" 10 | "github.com/huandu/go-sqlbuilder" 11 | "github.com/jzero-io/jzero/core/stores/condition" 12 | "github.com/jzero-io/jzero/core/stores/modelx" 13 | "github.com/eddieowens/opts" 14 | 15 | {{.third}} 16 | ) 17 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/insert.tpl: -------------------------------------------------------------------------------- 1 | func (m *default{{.upperStartCamelObject}}Model) Insert(ctx context.Context, session sqlx.Session, data *{{.upperStartCamelObject}}) (sql.Result,error) { 2 | statement, args := sqlbuilder.NewInsertBuilder(). 3 | InsertInto(m.table). 4 | Cols({{.lowerStartCamelObject}}RowsExpectAutoSet). 5 | Values({{.expressionValues}}).Build() 6 | if session != nil { 7 | return session.ExecCtx(ctx, statement, args...) 8 | } 9 | return m.conn.ExecCtx(ctx, statement, args...) 10 | } 11 | 12 | func (m *default{{.upperStartCamelObject}}Model) InsertWithCache(ctx context.Context, session sqlx.Session, data *{{.upperStartCamelObject}}) (sql.Result,error) { 13 | {{if .withCache}}{{.keys}} 14 | statement, args := sqlbuilder.NewInsertBuilder(). 15 | InsertInto(m.table). 16 | Cols({{.lowerStartCamelObject}}RowsExpectAutoSet). 17 | Values({{.expressionValues}}).Build() 18 | return m.cachedConn.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { 19 | if session != nil { 20 | return session.ExecCtx(ctx, statement, args...) 21 | } 22 | return conn.ExecCtx(ctx, statement, args...) 23 | }, {{.keyValues}}){{else}}return m.Insert(ctx, session, data){{end}} 24 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/interface-delete.tpl: -------------------------------------------------------------------------------- 1 | Delete(ctx context.Context, session sqlx.Session, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error 2 | DeleteWithCache(ctx context.Context, session sqlx.Session, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) error -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/interface-find-one-by-field.tpl: -------------------------------------------------------------------------------- 1 | FindOneBy{{.upperField}}(ctx context.Context, session sqlx.Session, {{.in}}) (*{{.upperStartCamelObject}}, error) 2 | FindOneBy{{.upperField}}WithCache(ctx context.Context, session sqlx.Session, {{.in}}) (*{{.upperStartCamelObject}}, error) -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/interface-find-one.tpl: -------------------------------------------------------------------------------- 1 | FindOne(ctx context.Context, session sqlx.Session, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) 2 | FindOneWithCache(ctx context.Context, session sqlx.Session, {{.lowerStartCamelPrimaryKey}} {{.dataType}}) (*{{.upperStartCamelObject}}, error) -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/interface-insert.tpl: -------------------------------------------------------------------------------- 1 | Insert(ctx context.Context, session sqlx.Session, data *{{.upperStartCamelObject}}) (sql.Result,error) 2 | InsertWithCache(ctx context.Context, session sqlx.Session, data *{{.upperStartCamelObject}}) (sql.Result,error) -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/interface-update.tpl: -------------------------------------------------------------------------------- 1 | Update(ctx context.Context, session sqlx.Session, {{if .containsIndexCache}}newData{{else}}data{{end}} *{{.upperStartCamelObject}}) error 2 | UpdateWithCache(ctx context.Context, session sqlx.Session, {{if .containsIndexCache}}newData{{else}}data{{end}} *{{.upperStartCamelObject}}) error -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/model-gen.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by goctl. Templates Edited by jzero. DO NOT EDIT. 2 | 3 | package {{.pkg}} 4 | {{.imports}} 5 | {{.vars}} 6 | {{.types}} 7 | {{.new}} 8 | {{.delete}} 9 | {{.find}} 10 | {{.insert}} 11 | {{.update}} 12 | {{.extraMethod}} 13 | {{.tableName}} 14 | {{.customized}} 15 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/model-new.tpl: -------------------------------------------------------------------------------- 1 | func new{{.upperStartCamelObject}}Model(conn sqlx.SqlConn, op ...opts.Opt[modelx.ModelOpts]) *default{{.upperStartCamelObject}}Model { 2 | o := opts.DefaultApply(op...) 3 | var cachedConn sqlc.CachedConn 4 | if len(o.CacheConf) > 0 { 5 | cachedConn = sqlc.NewConn(conn, o.CacheConf, o.CacheOpts...) 6 | } 7 | if o.CachedConn != nil { 8 | cachedConn = *o.CachedConn 9 | } 10 | 11 | initVars() 12 | 13 | return &default{{.upperStartCamelObject}}Model{ 14 | cachedConn: cachedConn, 15 | conn: conn, 16 | table: condition.Table({{.table}}), 17 | } 18 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/model.tpl: -------------------------------------------------------------------------------- 1 | package {{.pkg}} 2 | import ( 3 | "github.com/zeromicro/go-zero/core/stores/sqlx" 4 | "github.com/jzero-io/jzero/core/stores/modelx" 5 | "github.com/eddieowens/opts" 6 | ) 7 | 8 | var _ {{.upperStartCamelObject}}Model = (*custom{{.upperStartCamelObject}}Model)(nil) 9 | 10 | type ( 11 | // {{.upperStartCamelObject}}Model is an interface to be customized, add more methods here, 12 | // and implement the added methods in custom{{.upperStartCamelObject}}Model. 13 | {{.upperStartCamelObject}}Model interface { 14 | {{.lowerStartCamelObject}}Model 15 | } 16 | 17 | custom{{.upperStartCamelObject}}Model struct { 18 | *default{{.upperStartCamelObject}}Model 19 | } 20 | ) 21 | 22 | // New{{.upperStartCamelObject}}Model returns a model for the database table. 23 | func New{{.upperStartCamelObject}}Model(conn sqlx.SqlConn, op ...opts.Opt[modelx.ModelOpts]) {{.upperStartCamelObject}}Model { 24 | return &custom{{.upperStartCamelObject}}Model{ 25 | default{{.upperStartCamelObject}}Model: new{{.upperStartCamelObject}}Model(conn, op...), 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/table-name.tpl: -------------------------------------------------------------------------------- 1 | func (m *default{{.upperStartCamelObject}}Model) tableName() string { 2 | return m.table 3 | } 4 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/tag.tpl: -------------------------------------------------------------------------------- 1 | `db:"{{.field}}"` -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/types.tpl: -------------------------------------------------------------------------------- 1 | type ( 2 | {{.lowerStartCamelObject}}Model interface{ 3 | {{.method}} 4 | 5 | // custom interface generated by jzero 6 | BulkInsert(ctx context.Context, session sqlx.Session, datas []*{{.upperStartCamelObject}}) error 7 | FindByCondition(ctx context.Context, session sqlx.Session, conds ...condition.Condition) ([]*{{.upperStartCamelObject}}, error) 8 | FindSelectedColumnsByCondition(ctx context.Context, session sqlx.Session, columns []string, conds ...condition.Condition) ([]*{{.upperStartCamelObject}}, error) 9 | FindOneByCondition(ctx context.Context, session sqlx.Session, conds ...condition.Condition) (*{{.upperStartCamelObject}}, error) 10 | CountByCondition(ctx context.Context, session sqlx.Session, conds ...condition.Condition) (int64, error) 11 | PageByCondition(ctx context.Context, session sqlx.Session, conds ...condition.Condition) ([]*{{.upperStartCamelObject}}, int64 ,error) 12 | UpdateFieldsByCondition(ctx context.Context, session sqlx.Session, field map[string]any, conds ...condition.Condition) error 13 | DeleteByCondition(ctx context.Context, session sqlx.Session, conds ...condition.Condition) error 14 | } 15 | 16 | default{{.upperStartCamelObject}}Model struct { 17 | cachedConn sqlc.CachedConn 18 | conn sqlx.SqlConn 19 | table string 20 | } 21 | 22 | {{.upperStartCamelObject}} struct { 23 | {{.fields}} 24 | } 25 | ) 26 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/update.tpl: -------------------------------------------------------------------------------- 1 | func (m *default{{.upperStartCamelObject}}Model) Update(ctx context.Context, session sqlx.Session, {{if .containsIndexCache}}newData{{else}}data{{end}} *{{.upperStartCamelObject}}) error { 2 | sb := sqlbuilder.Update(m.table) 3 | split := strings.Split({{.lowerStartCamelObject}}RowsExpectAutoSet, ",") 4 | var assigns []string 5 | for _, s := range split { 6 | assigns = append(assigns, sb.Assign(s, nil)) 7 | } 8 | sb.Set(assigns...) 9 | sb.Where(sb.EQ(condition.Field("{{.originalPrimaryKey}}"), nil)) 10 | statement, _ := sb.Build() 11 | 12 | var err error 13 | if session != nil{ 14 | _, err = session.ExecCtx(ctx, statement, {{.expressionValues}}) 15 | }else{ 16 | _, err = m.conn.ExecCtx(ctx, statement, {{.expressionValues}}) 17 | } 18 | return err 19 | } 20 | 21 | func (m *default{{.upperStartCamelObject}}Model) UpdateWithCache(ctx context.Context, session sqlx.Session, {{if .containsIndexCache}}newData{{else}}data{{end}} *{{.upperStartCamelObject}}) error { 22 | {{if .withCache}}{{if .containsIndexCache}}data, err := m.FindOne(ctx, session, newData.{{.upperStartCamelPrimaryKey}}) 23 | if err != nil{ 24 | return err 25 | } 26 | {{end}}{{.keys}} 27 | _, {{if .containsIndexCache}}err{{else}}err :{{end}}= m.cachedConn.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { 28 | sb := sqlbuilder.Update(m.table) 29 | split := strings.Split({{.lowerStartCamelObject}}RowsExpectAutoSet, ",") 30 | var assigns []string 31 | for _, s := range split { 32 | assigns = append(assigns, sb.Assign(s, nil)) 33 | } 34 | sb.Set(assigns...) 35 | sb.Where(sb.EQ(condition.Field("{{.originalPrimaryKey}}"), nil)) 36 | statement, _ := sb.Build() 37 | if session != nil{ 38 | return session.ExecCtx(ctx, statement, {{.expressionValues}}) 39 | } 40 | return conn.ExecCtx(ctx, statement, {{.expressionValues}}) 41 | }, {{.keyValues}}) 42 | return err{{else}}return m.Update(ctx, session, {{if .containsIndexCache}}newData{{else}}data{{end}}){{end}} 43 | } 44 | -------------------------------------------------------------------------------- /cmd/jzero/.template/go-zero/model/var.tpl: -------------------------------------------------------------------------------- 1 | var ( 2 | {{.lowerStartCamelObject}}FieldNames []string 3 | {{.lowerStartCamelObject}}Rows string 4 | {{.lowerStartCamelObject}}RowsExpectAutoSet string 5 | 6 | {{if .withCache}}{{.cacheKeys}}{{end}} 7 | ) 8 | 9 | func initVars() { 10 | {{.lowerStartCamelObject}}FieldNames = condition.RawFieldNames(&{{.upperStartCamelObject}}{}) 11 | {{.lowerStartCamelObject}}Rows = strings.Join({{.lowerStartCamelObject}}FieldNames, ",") 12 | {{.lowerStartCamelObject}}RowsExpectAutoSet = strings.Join(condition.RemoveIgnoreColumns({{.lowerStartCamelObject}}FieldNames, {{if .autoIncrement}}"{{.originalPrimaryKey}}", {{end}} {{.ignoreColumns}}), ",") 13 | } 14 | -------------------------------------------------------------------------------- /cmd/jzero/.template/ivm/add/template.api.tpl: -------------------------------------------------------------------------------- 1 | syntax = "v1" 2 | 3 | info ( 4 | go_package: "{{ .Group }}" 5 | ) 6 | 7 | {{range $v := .Handlers | uniq}}type {{$v.Name | FirstUpper}}Request {} 8 | 9 | type {{$v.Name | FirstUpper}}Response {} 10 | 11 | {{end}} 12 | 13 | @server ( 14 | prefix: /api/v1 15 | group: {{ .Group }} 16 | ) 17 | service {{ .Service }} { 18 | {{range $v := .Handlers | uniq}}@handler {{$v.Name}}Handler 19 | {{$v.Verb}} /{{ $.Group }}/{{$v.Name | FirstLower}} ({{$v.Name | FirstUpper}}Request) returns ({{$v.Name | FirstUpper}}Response) 20 | 21 | {{end}} 22 | } 23 | 24 | -------------------------------------------------------------------------------- /cmd/jzero/.template/ivm/add/template.proto.tpl: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package {{ .Package }}{{ .Version }}pb; 4 | 5 | import "google/api/annotations.proto"; 6 | import "validate/validate.proto"; 7 | import "grpc-gateway/protoc-gen-openapiv2/options/annotations.proto"; 8 | 9 | option go_package = "./pb/{{ .Package }}{{ .Version }}pb"; 10 | 11 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { 12 | info: { 13 | version: "{{ .UrlVersion }}"; 14 | }; 15 | }; 16 | 17 | {{range $v := .Methods}}message {{$v.Name | FirstUpper}}Request {} 18 | message {{$v.Name | FirstUpper}}Response {} 19 | {{end}} 20 | 21 | {{range $service := .Services}} 22 | service {{ $service | FirstUpper }}{{ $.Version | FirstUpper }} { {{range $m := $.Methods}} 23 | rpc {{ $m.Name }}({{$m.Name | FirstUpper}}Request) returns({{$m.Name | FirstUpper}}Response) { 24 | option (google.api.http) = { 25 | {{ $m.Verb }}: "/api/{{ $.UrlVersion }}/{{ $service }}/{{ $m.Name | FirstLower}}" 26 | }; 27 | }; 28 | {{end}} 29 | } 30 | {{end}} 31 | -------------------------------------------------------------------------------- /cmd/jzero/.template/ivm/init/logic-body.tpl: -------------------------------------------------------------------------------- 1 | logic := {{ .OldService }}logic.New{{ .LogicTypeName | FirstUpper }}(l.ctx, l.svcCtx) 2 | marshal, err := proto.Marshal(in) 3 | if err != nil { 4 | return nil, err 5 | } 6 | var oldIn {{ .OldService }}pb.{{ .RequestTypeName }} 7 | err = proto.Unmarshal(marshal, &oldIn) 8 | if err != nil { 9 | return nil, err 10 | } 11 | result, err := logic.{{ .MethodName }}(&oldIn) 12 | if err != nil { 13 | return nil, err 14 | } 15 | marshal, err = proto.Marshal(result) 16 | if err != nil { 17 | return nil, err 18 | } 19 | var newResp {{ .Service }}pb.{{ .ResponseTypeName }} 20 | err = proto.Unmarshal(marshal, &newResp) 21 | if err != nil { 22 | return nil, err 23 | } 24 | return &newResp, nil -------------------------------------------------------------------------------- /cmd/jzero/.template/ivm/init/logic-client-server-stream-adaptor.tpl: -------------------------------------------------------------------------------- 1 | type {{ .MethodName | FirstUpper }}ServerAdapter struct { 2 | {{ .Service }}pb.{{ .Service | FirstUpper }}_{{ .MethodName | FirstUpper }}Server 3 | } 4 | 5 | func (s {{ .MethodName | FirstUpper }}ServerAdapter) Send(response *{{ .OldService }}pb.{{ .ResponseTypeName }}) error { 6 | marshal, err := proto.Marshal(response) 7 | if err != nil { 8 | return err 9 | } 10 | var newResp {{ .Service }}pb.{{ .ResponseTypeName }} 11 | err = proto.Unmarshal(marshal, &newResp) 12 | if err != nil { 13 | return err 14 | } 15 | 16 | err = s.SendMsg(&newResp) 17 | if err != nil { 18 | if err == io.EOF { 19 | return nil 20 | } 21 | return err 22 | } 23 | 24 | return nil 25 | } 26 | 27 | func (s {{ .MethodName | FirstUpper }}ServerAdapter) Recv() (*{{ .OldService }}pb.{{ .RequestTypeName }}, error) { 28 | for { 29 | newIn, err := s.{{ .Service | FirstUpper }}_{{ .MethodName | FirstUpper }}Server.Recv() 30 | if err == io.EOF { 31 | return nil, io.EOF 32 | } 33 | if err != nil { 34 | return nil, err 35 | } 36 | 37 | marshal, err := proto.Marshal(newIn) 38 | if err != nil { 39 | return nil, err 40 | } 41 | var oldIn {{ .OldService }}pb.{{ .RequestTypeName }} 42 | err = proto.Unmarshal(marshal, &oldIn) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | return &oldIn, nil 48 | } 49 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/ivm/init/logic-client-server-stream-body.tpl: -------------------------------------------------------------------------------- 1 | logic := {{ .OldService }}logic.New{{ .LogicTypeName }}(l.ctx, l.svcCtx) 2 | 3 | // Create the adapter 4 | adapter := &{{ .MethodName | FirstUpper }}ServerAdapter{ 5 | stream, 6 | } 7 | 8 | return logic.{{ .MethodName | FirstUpper }}(adapter) -------------------------------------------------------------------------------- /cmd/jzero/.template/ivm/init/logic-client-stream-adaptor.tpl: -------------------------------------------------------------------------------- 1 | type {{ .MethodName | FirstUpper }}ServerAdapter struct { 2 | {{ .Service }}pb.{{ .Service | FirstUpper }}_{{ .MethodName | FirstUpper }}Server 3 | } 4 | 5 | func (s *{{ .MethodName | FirstUpper }}ServerAdapter) SendAndClose(response *{{ .OldService }}pb.{{ .ResponseTypeName }}) error { 6 | marshal, err := proto.Marshal(response) 7 | if err != nil { 8 | return err 9 | } 10 | 11 | var newResp {{ .Service }}pb.{{ .ResponseTypeName }} 12 | err = proto.Unmarshal(marshal, &newResp) 13 | if err != nil { 14 | return err 15 | } 16 | return s.SendMsg(&newResp) 17 | } 18 | 19 | func (s *{{ .MethodName | FirstUpper }}ServerAdapter) Recv() (*{{ .OldService }}pb.{{ .RequestTypeName }}, error) { 20 | for { 21 | newIn, err := s.{{ .Service | FirstUpper }}_{{ .MethodName | FirstUpper }}Server.Recv() 22 | if err == io.EOF { 23 | return nil, io.EOF 24 | } 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | marshal, err := proto.Marshal(newIn) 30 | if err != nil { 31 | return nil, err 32 | } 33 | var oldIn {{ .OldService }}pb.{{ .RequestTypeName }} 34 | err = proto.Unmarshal(marshal, &oldIn) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | return &oldIn, nil 40 | } 41 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/ivm/init/logic-client-stream-body.tpl: -------------------------------------------------------------------------------- 1 | logic := {{ .OldService }}logic.New{{ .LogicTypeName }}(l.ctx, l.svcCtx) 2 | 3 | // Create the adapter 4 | adapter := &{{ .MethodName | FirstUpper }}ServerAdapter{ 5 | stream, 6 | } 7 | 8 | return logic.{{ .MethodName | FirstUpper }}(adapter) -------------------------------------------------------------------------------- /cmd/jzero/.template/ivm/init/logic-server-stream-adaptor.tpl: -------------------------------------------------------------------------------- 1 | type {{ .MethodName | FirstUpper }}ServerAdapter struct { 2 | {{ .Service }}pb.{{ .Service | FirstUpper }}_{{ .MethodName | FirstUpper }}Server 3 | } 4 | 5 | func (s *{{ .MethodName | FirstUpper }}ServerAdapter) Send(response *{{ .OldService }}pb.{{ .ResponseTypeName }}) error { 6 | marshal, err := proto.Marshal(response) 7 | if err != nil { 8 | return err 9 | } 10 | var newResp {{ .Service }}pb.{{ .ResponseTypeName }} 11 | err = proto.Unmarshal(marshal, &newResp) 12 | if err != nil { 13 | return err 14 | } 15 | 16 | err = s.SendMsg(&newResp) 17 | if err != nil { 18 | if err == io.EOF { 19 | return nil 20 | } 21 | return err 22 | } 23 | 24 | return nil 25 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/ivm/init/logic-server-stream-body.tpl: -------------------------------------------------------------------------------- 1 | logic := {{ .OldService }}logic.New{{ .LogicTypeName }}(l.ctx, l.svcCtx) 2 | 3 | // Create the adapter 4 | adapter := &{{ .MethodName | FirstUpper }}ServerAdapter{ 5 | stream, 6 | } 7 | 8 | marshal, err := proto.Marshal(in) 9 | if err != nil { 10 | return err 11 | } 12 | 13 | var oldIn {{ .OldService }}pb.{{ .RequestTypeName }} 14 | err = proto.Unmarshal(marshal, &oldIn) 15 | if err != nil { 16 | return err 17 | } 18 | 19 | return logic.{{ .MethodName | FirstUpper }}(&oldIn, adapter) -------------------------------------------------------------------------------- /cmd/jzero/.template/plugins/api/route2code.go.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by jzero. DO NOT EDIT. 2 | 3 | package handler 4 | 5 | import ( 6 | "net/http" 7 | "path" 8 | "strings" 9 | "sync" 10 | 11 | "github.com/zeromicro/go-zero/core/logx" 12 | "github.com/zeromicro/go-zero/core/search" 13 | ) 14 | 15 | var RoutesCodesMap = map[string]string{ 16 | {{ range $v := .Routes }}"{{ $v.Method | upper }}:{{ $v.Path }}":"{{ replace `/` `:` $v.Group | FirstLower }}:{{ $v.Handler | FirstLower}}", 17 | {{ end }} 18 | } 19 | 20 | var ( 21 | MST map[string]*search.Tree 22 | once sync.Once 23 | ) 24 | 25 | func Route2Code(r *http.Request) string { 26 | once.Do(func() { 27 | RegisterRoute2Code(RoutesCodesMap) 28 | }) 29 | if tree, ok := MST[strings.ToUpper(r.Method)]; ok { 30 | if result, ok := tree.Search(path.Clean(r.URL.Path)); ok { 31 | return result.Item.(string) 32 | } 33 | } 34 | 35 | return "unknown" 36 | } 37 | 38 | func RegisterRoute2Code(maps map[string]string) { 39 | if MST == nil { 40 | MST = make(map[string]*search.Tree) 41 | } 42 | for k, v := range maps { 43 | if splits := strings.Split(k, ":"); len(splits) >= 2 { 44 | if _, ok := MST[splits[0]]; ok { 45 | logx.Must(MST[splits[0]].Add(path.Clean(strings.Join(splits[1:], ":")), v)) 46 | } else { 47 | tree := search.NewTree() 48 | logx.Must(tree.Add(strings.Join(splits[1:], ":"), v)) 49 | MST[splits[0]] = tree 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /cmd/jzero/.template/plugins/api/routes.go.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by jzero. DO NOT EDIT. 2 | package handler 3 | 4 | import ( 5 | "net/http" 6 | "time" 7 | 8 | "github.com/zeromicro/go-zero/rest" 9 | "{{.Module}}/internal/svc"{{ if .HandlerImports }}{{ .HandlerImports }}{{ end }} 10 | ) 11 | 12 | var ( 13 | _ = http.StatusOK 14 | _ = time.Now() 15 | ) 16 | 17 | func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { 18 | {{if .Routes}}{{.Routes}}{{end}} 19 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/plugins/api/serverless_plugins.go.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by jzero. DO NOT EDIT. 2 | package plugins 3 | 4 | import ( 5 | "github.com/zeromicro/go-zero/rest" 6 | 7 | "{{ .Module }}/internal/svc" 8 | {{range $v := .Plugins}}{{ $v.Path | base }} "{{ $v.Module }}/serverless" 9 | {{end}} 10 | ) 11 | 12 | type CoreSvcCtx = svc.ServiceContext 13 | 14 | func LoadPlugins(server *rest.Server, svcCtx CoreSvcCtx) { 15 | {{ range $v := .Plugins }} 16 | { 17 | serverless := {{ $v.Path | base }}.New(svcCtx) 18 | serverless.HandlerFunc(server, serverless.SvcCtx) 19 | } 20 | {{end}} 21 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/plugins/model/model.go.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by jzero. DO NOT EDIT. 2 | 3 | package model 4 | 5 | import ( 6 | "github.com/zeromicro/go-zero/core/stores/sqlx" 7 | "github.com/jzero-io/jzero/core/stores/modelx" 8 | "github.com/eddieowens/opts" 9 | 10 | {{range $v := .Imports}}"{{$v}}" 11 | {{end}} 12 | ) 13 | 14 | type Model struct { 15 | {{range $v := .TablePackages}}{{$v | FirstUpper | ToCamel}} {{$v}}.{{$v | FirstUpper |ToCamel}}Model 16 | {{end}} 17 | } 18 | 19 | func NewModel(conn sqlx.SqlConn, op ...opts.Opt[modelx.ModelOpts]) Model { 20 | return Model{ 21 | {{range $v := .TablePackages}}{{$v | FirstUpper | ToCamel}}: {{$v}}.New{{ $v | FirstUpper | ToCamel }}Model(conn, op...), 22 | {{end}} 23 | } 24 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/plugins/rpc/middleware_gen.go.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by jzero. DO NOT EDIT. 2 | 3 | package middleware 4 | 5 | import ( 6 | "fmt" 7 | "context" 8 | "regexp" 9 | 10 | "github.com/zeromicro/go-zero/gateway" 11 | "github.com/zeromicro/go-zero/zrpc" 12 | "google.golang.org/grpc" 13 | ) 14 | 15 | var ( 16 | _ = fmt.Sprintf("middleware_gen.go") 17 | _ = context.Background() 18 | _ = grpc.SupportPackageIsVersion7 19 | ) 20 | 21 | func RegisterGen(zrpc *zrpc.RpcServer, gw *gateway.Server) { 22 | {{range $v := .HttpMiddlewares}}gw.Use({{$v.Name | FirstUpper}}Middleware) 23 | {{end}} 24 | {{range $v := .ZrpcMiddlewares}}zrpc.AddUnaryInterceptors({{$v.Name | FirstUpper}}Middleware) 25 | zrpc.AddStreamInterceptors({{$v.Name | FirstUpper}}StreamMiddleware){{end}} 26 | } 27 | 28 | // Define and compile routes 29 | var routesMap map[string][]*regexp.Regexp 30 | 31 | // loadRoute compiles and stores a route pattern. 32 | func loadRoutes(middleware string, patterns ...string) { 33 | if routesMap == nil { 34 | routesMap = make(map[string][]*regexp.Regexp) 35 | } 36 | 37 | re := regexp.MustCompile(`\{[^}]+\}`) 38 | var routes []*regexp.Regexp 39 | for _, pattern := range patterns { 40 | pattern = re.ReplaceAllString(pattern, "([^/]+)") 41 | compiledPattern := "^" + pattern + "$" 42 | routes = append(routes, regexp.MustCompile(compiledPattern)) 43 | } 44 | routesMap[middleware] = routes 45 | } 46 | 47 | // MatchRoute checks if a route matches any compiled route. 48 | func MatchRoute(middleware, route string) bool { 49 | if routesReg, ok := routesMap[middleware]; ok { 50 | for _, rr := range routesReg { 51 | if rr.MatchString(route) { 52 | return true 53 | } 54 | } 55 | } 56 | return false 57 | } 58 | 59 | func init() { 60 | {{range $v := .HttpMiddlewares}} 61 | loadRoutes("{{$v.Name}}", 62 | {{range $vv := $v.Routes}}"{{$vv}}", 63 | {{end}}) 64 | {{end}} 65 | 66 | {{range $v := .ZrpcMiddlewares}} 67 | loadRoutes("{{$v.Name}}", 68 | {{range $vv := $v.Routes}}"{{$vv}}", 69 | {{end}}) 70 | {{end}} 71 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/plugins/rpc/middleware_http.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/zeromicro/go-zero/core/logx" 8 | ) 9 | 10 | func {{.Name | FirstUpper}}Middleware(next http.HandlerFunc) http.HandlerFunc { 11 | return func(writer http.ResponseWriter, request *http.Request) { 12 | if MatchRoute("{{.Name}}", fmt.Sprintf("%s:%s",request.Method,request.URL.Path)) { 13 | // do something before middleware 14 | logx.WithContext(request.Context()).Info("enter {{.Name}} before middleware") 15 | } 16 | next.ServeHTTP(writer, request) 17 | if MatchRoute("{{.Name}}", fmt.Sprintf("%s:%s",request.Method,request.URL.Path)) { 18 | // do something after middleware 19 | logx.WithContext(request.Context()).Info("enter {{.Name}} after middleware") 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/plugins/rpc/middleware_zrpc.go.tpl: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | 4 | import ( 5 | "context" 6 | 7 | "google.golang.org/grpc" 8 | "github.com/zeromicro/go-zero/core/logx" 9 | ) 10 | 11 | func {{.Name | FirstUpper}}Middleware(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { 12 | if MatchRoute("{{.Name}}", info.FullMethod) { 13 | // do something before middleware 14 | logx.WithContext(ctx).Info("enter {{.Name}} before middleware") 15 | } 16 | hd, err := handler(ctx, req) 17 | if MatchRoute("{{.Name}}", info.FullMethod) { 18 | // do something after middleware 19 | logx.WithContext(ctx).Info("enter {{.Name}} after middleware") 20 | } 21 | return hd, err 22 | } 23 | 24 | func {{.Name | FirstUpper}}StreamMiddleware(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { 25 | if MatchRoute("{{.Name}}", info.FullMethod) { 26 | // do something before middleware 27 | logx.WithContext(ss.Context()).Info("enter stream {{.Name}} before middleware") 28 | } 29 | hd := handler(srv, ss) 30 | if MatchRoute("{{.Name}}", info.FullMethod) { 31 | // do something after middleware 32 | logx.WithContext(ss.Context()).Info("enter stream {{.Name}} after middleware") 33 | } 34 | return hd 35 | } -------------------------------------------------------------------------------- /cmd/jzero/.template/plugins/rpc/server.go.tpl: -------------------------------------------------------------------------------- 1 | // Code generated by jzero. DO NOT EDIT. 2 | 3 | package server 4 | 5 | import ( 6 | "github.com/zeromicro/go-zero/core/service" 7 | "github.com/zeromicro/go-zero/zrpc" 8 | "google.golang.org/grpc" 9 | "google.golang.org/grpc/reflection" 10 | 11 | "{{ .Module }}/internal/config" 12 | "{{ .Module }}/internal/svc"{{ if .ServerImports }}{{ .ServerImports }}{{ end }}{{ if .PbImports }}{{ .PbImports }}{{ end }} 13 | ) 14 | 15 | func RegisterZrpc(c config.Config, ctx *svc.ServiceContext) *zrpc.RpcServer { 16 | s := zrpc.MustNewServer(c.Zrpc.RpcServerConf, func(grpcServer *grpc.Server) { 17 | {{ if .RegisterServers }}{{ .RegisterServers }}{{ end }} 18 | 19 | if c.Zrpc.Mode == service.DevMode || c.Zrpc.Mode == service.TestMode { 20 | reflection.Register(grpcServer) 21 | } 22 | }) 23 | 24 | return s 25 | } -------------------------------------------------------------------------------- /cmd/jzero/internal/command/completion/completion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2024 jaronnie jaron@jaronnie.com 3 | 4 | */ 5 | 6 | package completion 7 | 8 | import ( 9 | "os" 10 | 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | var completionCmd = &cobra.Command{ 15 | Use: "completion [bash|zsh|fish|powershell]", 16 | Short: "Generate completion script", 17 | Long: `To load completions: 18 | 19 | Bash: 20 | 21 | $ source <(jzero completion bash) 22 | 23 | # To load completions for each session, execute once: 24 | Linux: 25 | $ jzero completion bash > /etc/bash_completion.d/jzero 26 | MacOS: 27 | $ jzero completion bash > /usr/local/etc/bash_completion.d/jzero 28 | 29 | Zsh: 30 | 31 | # If shell completion is not already enabled in your environment you will need 32 | # to enable it. You can execute the following once: 33 | 34 | $ echo "autoload -U compinit; compinit" >> ~/.zshrc 35 | 36 | # To load completions for each session, execute once: 37 | $ jzero completion zsh > "${fpath[1]}/_jzero" 38 | 39 | # You will need to start a new shell for this setup to take effect. 40 | 41 | Fish: 42 | 43 | $ jzero completion fish | source 44 | 45 | # To load completions for each session, execute once: 46 | $ jzero completion fish > ~/.config/fish/completions/jzero.fish 47 | 48 | PowerShell: 49 | $ jzero completion powershell | Out-String | Invoke-Expression 50 | `, 51 | DisableFlagsInUseLine: true, 52 | ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, 53 | Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), 54 | Run: func(cmd *cobra.Command, args []string) { 55 | switch args[0] { 56 | case "bash": 57 | _ = cmd.Root().GenBashCompletion(os.Stdout) 58 | case "zsh": 59 | _ = cmd.Root().GenZshCompletion(os.Stdout) 60 | case "fish": 61 | _ = cmd.Root().GenFishCompletion(os.Stdout, true) 62 | case "powershell": 63 | _ = cmd.Root().GenPowerShellCompletion(os.Stdout) 64 | } 65 | }, 66 | } 67 | 68 | func GetCommand() *cobra.Command { 69 | return completionCmd 70 | } 71 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/format/format.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2025 jaronnie 3 | */ 4 | 5 | package format 6 | 7 | import ( 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/format/formatgo" 11 | ) 12 | 13 | // formatCmd represents the format command 14 | var formatCmd = &cobra.Command{ 15 | Use: "format", 16 | Short: "jzero code format tool", 17 | Long: `used to format code. e.g. go/api/proto/sql`, 18 | RunE: func(cmd *cobra.Command, args []string) error { 19 | if err := formatgo.Run(); err != nil { 20 | return err 21 | } 22 | return nil 23 | }, 24 | SilenceUsage: true, 25 | } 26 | 27 | // formatGoCmd represents the format go code command 28 | var formatGoCmd = &cobra.Command{ 29 | Use: "go", 30 | Short: "used to format go code", 31 | RunE: func(cmd *cobra.Command, args []string) error { 32 | if err := formatgo.Run(); err != nil { 33 | return err 34 | } 35 | return nil 36 | }, 37 | SilenceUsage: true, 38 | } 39 | 40 | func GetCommand() *cobra.Command { 41 | formatCmd.PersistentFlags().BoolP("git-change", "", true, "just format git changed files") 42 | formatCmd.PersistentFlags().BoolP("display-diff", "d", false, "display diffs instead of rewriting files") 43 | 44 | formatCmd.AddCommand(formatGoCmd) 45 | return formatCmd 46 | } 47 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/format/formatgo/run.go: -------------------------------------------------------------------------------- 1 | package formatgo 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "regexp" 7 | 8 | "github.com/fsgo/go_fmt/gofmtapi" 9 | "github.com/zeromicro/go-zero/core/mr" 10 | 11 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 12 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/gitstatus" 13 | ) 14 | 15 | var rxCodeGenerated = regexp.MustCompile(`^// Code generated .* DO NOT EDIT\.$`) 16 | 17 | func Run() error { 18 | files := getFormatFiles() 19 | 20 | files = filterFiles(files) 21 | 22 | return FormatFiles(files) 23 | } 24 | 25 | func FormatFiles(files []string) error { 26 | gf := gofmtapi.NewFormatter() 27 | opt := gofmtapi.NewOptions() 28 | opt.BindFlags() 29 | 30 | opt.DisplayDiff = config.C.Format.DisplayDiff 31 | opt.Files = files 32 | 33 | if len(opt.Files) == 0 { 34 | return nil 35 | } 36 | return gf.Execute(opt) 37 | } 38 | 39 | func getFormatFiles() []string { 40 | if config.C.Format.GitChange { 41 | files, _, err := gitstatus.ChangedFiles(".", ".go") 42 | if err == nil { 43 | return files 44 | } 45 | return []string{"."} 46 | } 47 | return []string{"."} 48 | } 49 | 50 | func filterFiles(files []string) []string { 51 | var result []string 52 | 53 | mr.ForEach(func(source chan<- string) { 54 | for _, v := range files { 55 | source <- v 56 | } 57 | }, func(item string) { 58 | line, _ := readFirstLine(item) 59 | if !rxCodeGenerated.MatchString(line) { 60 | result = append(result, item) 61 | } 62 | }) 63 | 64 | return result 65 | } 66 | 67 | func readFirstLine(filePath string) (string, error) { 68 | file, err := os.Open(filePath) 69 | if err != nil { 70 | return "", err 71 | } 72 | defer file.Close() 73 | 74 | scanner := bufio.NewScanner(file) 75 | if scanner.Scan() { 76 | return scanner.Text(), nil 77 | } 78 | 79 | return "", scanner.Err() 80 | } 81 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/gen/genapi/patch_svc.go: -------------------------------------------------------------------------------- 1 | package genapi 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strings" 7 | 8 | "github.com/zeromicro/go-zero/tools/goctl/util/format" 9 | 10 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 11 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/filex" 12 | ) 13 | 14 | func (ja *JzeroApi) patchSvc() error { 15 | namingFormat, err := format.FileNamingFormat(config.C.Gen.Style, "service_context.go") 16 | if err != nil { 17 | return err 18 | } 19 | 20 | if !filex.DirExists(filepath.Join("internal", "svc")) || filex.FileExists(filepath.Join("internal", "svc", namingFormat)) { 21 | return nil 22 | } 23 | 24 | dir, err := os.ReadDir(filepath.Join("internal", "svc")) 25 | if err != nil { 26 | return err 27 | } 28 | for _, v := range dir { 29 | if !v.IsDir() { 30 | if strings.HasPrefix(v.Name(), "service") && strings.HasSuffix(v.Name(), "context.go") { 31 | if err = os.Rename(filepath.Join("internal", "svc", v.Name()), filepath.Join("internal", "svc", namingFormat)); err != nil { 32 | return err 33 | } 34 | } 35 | } 36 | } 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/gen/genrpc/patch_svc.go: -------------------------------------------------------------------------------- 1 | package genrpc 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strings" 7 | 8 | "github.com/zeromicro/go-zero/tools/goctl/util/format" 9 | 10 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 11 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/filex" 12 | ) 13 | 14 | func (jr *JzeroRpc) patchSvc() error { 15 | namingFormat, err := format.FileNamingFormat(config.C.Gen.Style, "service_context.go") 16 | if err != nil { 17 | return err 18 | } 19 | 20 | if !filex.DirExists(filepath.Join("internal", "svc")) || filex.FileExists(filepath.Join("internal", "svc", namingFormat)) { 21 | return nil 22 | } 23 | 24 | dir, err := os.ReadDir(filepath.Join("internal", "svc")) 25 | if err != nil { 26 | return err 27 | } 28 | for _, v := range dir { 29 | if !v.IsDir() { 30 | if strings.HasPrefix(v.Name(), "service") && strings.HasSuffix(v.Name(), "context.go") { 31 | if err = os.Rename(filepath.Join("internal", "svc", v.Name()), filepath.Join("internal", "svc", namingFormat)); err != nil { 32 | return err 33 | } 34 | } 35 | } 36 | } 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/gen/gensdk/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | type Config struct { 4 | GenModule bool 5 | } 6 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/gen/gensdk/gen.go: -------------------------------------------------------------------------------- 1 | package gensdk 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | 7 | "github.com/pkg/errors" 8 | "github.com/rinchsan/gosimports" 9 | "github.com/zeromicro/go-zero/tools/goctl/util/pathx" 10 | 11 | gensdkconfig "github.com/jzero-io/jzero/cmd/jzero/internal/command/gen/gensdk/config" 12 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/gen/gensdk/generator" 13 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 14 | ) 15 | 16 | func GenSdk(genModule bool) error { 17 | if !pathx.FileExists(config.C.Gen.Sdk.Output) { 18 | if err := os.MkdirAll(config.C.Gen.Sdk.Output, 0o755); err != nil { 19 | return err 20 | } 21 | } 22 | 23 | gc := gensdkconfig.Config{ 24 | GenModule: genModule, 25 | } 26 | 27 | gen, err := generator.New(gc) 28 | if err != nil { 29 | return err 30 | } 31 | 32 | files, err := gen.Gen() 33 | if err != nil { 34 | return err 35 | } 36 | 37 | for _, v := range files { 38 | if !pathx.FileExists(filepath.Dir(filepath.Join(config.C.Gen.Sdk.Output, v.Path))) { 39 | if err = os.MkdirAll(filepath.Dir(filepath.Join(config.C.Gen.Sdk.Output, v.Path)), 0o755); err != nil { 40 | return err 41 | } 42 | } 43 | if pathx.FileExists(filepath.Join(config.C.Gen.Sdk.Output, v.Path)) && v.Skip { 44 | continue 45 | } 46 | 47 | if filepath.Ext(v.Path) == ".go" { 48 | formated, err := gosimports.Process("", v.Content.Bytes(), nil) 49 | if err != nil { 50 | return errors.Errorf("format go file %s %s meet error: %v", v.Path, v.Content.Bytes(), err) 51 | } 52 | if err = os.WriteFile(filepath.Join(config.C.Gen.Sdk.Output, v.Path), formated, 0o644); err != nil { 53 | return err 54 | } 55 | } else { 56 | if err = os.WriteFile(filepath.Join(config.C.Gen.Sdk.Output, v.Path), v.Content.Bytes(), 0o644); err != nil { 57 | return err 58 | } 59 | } 60 | } 61 | 62 | return nil 63 | } 64 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/gen/gensdk/generator/common.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/gen/gensdk/vars" 5 | ) 6 | 7 | func getScopes(rhis vars.ScopeResourceHTTPInterfaceMap) []string { 8 | var scopes []string 9 | for k := range rhis { 10 | scopes = append(scopes, string(k)) 11 | } 12 | 13 | return scopes 14 | } 15 | 16 | func getScopeResources(resource vars.ResourceHTTPInterfaceMap) []string { 17 | var resources []string 18 | 19 | for k := range resource { 20 | resources = append(resources, string(k)) 21 | } 22 | 23 | return resources 24 | } 25 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/gen/gensdk/generator/interface.go: -------------------------------------------------------------------------------- 1 | package generator 2 | 3 | import ( 4 | "bytes" 5 | 6 | "github.com/pkg/errors" 7 | 8 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/gen/gensdk/config" 9 | gconfig "github.com/jzero-io/jzero/cmd/jzero/internal/config" 10 | ) 11 | 12 | type GeneratedFile struct { 13 | Path string 14 | Content bytes.Buffer 15 | Skip bool 16 | } 17 | 18 | type Generator interface { 19 | Gen() ([]*GeneratedFile, error) 20 | } 21 | 22 | var langGenerator = map[string]NewFunc{} 23 | 24 | type NewFunc func(target config.Config) (Generator, error) 25 | 26 | func New(config config.Config) (Generator, error) { 27 | f, ok := langGenerator[gconfig.C.Gen.Sdk.Language] 28 | if !ok { 29 | return nil, errors.Errorf("language %s not support", gconfig.C.Gen.Sdk.Language) 30 | } 31 | return f(config) 32 | } 33 | 34 | func Register(language string, f NewFunc) { 35 | langGenerator[language] = f 36 | } 37 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/gen/gensdk/jparser/api/parse.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/zeromicro/go-zero/tools/goctl/api/spec" 7 | 8 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/gen/gensdk/vars" 9 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/stringx" 10 | ) 11 | 12 | func CreatePathParam(pattern string, route *spec.Route) ([]*vars.PathParam, error) { 13 | pathSegments := strings.Split(pattern, "/") 14 | params := make([]*vars.PathParam, 0) 15 | 16 | for i, segment := range pathSegments { 17 | if strings.HasPrefix(segment, ":") { 18 | param := &vars.PathParam{ 19 | Index: i, 20 | Name: segment[1:], 21 | } 22 | // get GoName 23 | if _, ok := route.RequestType.(spec.DefineStruct); ok { 24 | members := route.RequestType.(spec.DefineStruct).GetTagMembers("path") 25 | for _, member := range members { 26 | name, _ := member.GetPropertyName() 27 | if name == segment[1:] { 28 | param.GoName = stringx.FirstUpper(member.Name) 29 | } 30 | } 31 | params = append(params, param) 32 | } 33 | } 34 | } 35 | return params, nil 36 | } 37 | 38 | func CreateQueryParams(route *spec.Route) []*vars.QueryParam { 39 | if route.ResponseType == nil { 40 | return nil 41 | } 42 | 43 | if _, ok := route.RequestType.(spec.DefineStruct); !ok { 44 | return nil 45 | } 46 | 47 | return extractQueryParams(route.RequestType.(spec.DefineStruct)) 48 | } 49 | 50 | func extractQueryParams(defineStruct spec.DefineStruct) []*vars.QueryParam { 51 | members := defineStruct.GetTagMembers("form") 52 | params := make([]*vars.QueryParam, 0) 53 | for _, member := range members { 54 | name, _ := member.GetPropertyName() 55 | if name != "" { 56 | param := &vars.QueryParam{ 57 | GoName: stringx.FirstUpper(member.Name), 58 | Name: name, 59 | } 60 | params = append(params, param) 61 | } 62 | 63 | // 递归处理嵌套的 DefineStruct 64 | if nestedStruct, ok := member.Type.(spec.DefineStruct); ok { 65 | params = append(params, extractQueryParams(nestedStruct)...) 66 | } 67 | } 68 | return params 69 | } 70 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/gen/gensdk/jparser/gateway/types.go: -------------------------------------------------------------------------------- 1 | // Refer: https://github.com/grpc-ecosystem/grpc-gateway 2 | 3 | package gateway 4 | 5 | import ( 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | type segment interface { 11 | fmt.Stringer 12 | } 13 | 14 | type wildcard struct{} 15 | 16 | type deepWildcard struct{} 17 | 18 | type literal string 19 | 20 | type variable struct { 21 | path string 22 | segments []segment 23 | } 24 | 25 | func (wildcard) String() string { 26 | return "*" 27 | } 28 | 29 | func (deepWildcard) String() string { 30 | return "**" 31 | } 32 | 33 | func (l literal) String() string { 34 | return string(l) 35 | } 36 | 37 | func (v variable) String() string { 38 | var segs []string 39 | for _, s := range v.segments { 40 | segs = append(segs, s.String()) 41 | } 42 | return fmt.Sprintf("{%s=%s}", v.path, strings.Join(segs, "/")) 43 | } 44 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/gen/gensdk/vars/vars.go: -------------------------------------------------------------------------------- 1 | package vars 2 | 3 | type ( 4 | Scope string 5 | 6 | Resource string 7 | 8 | ResourceHTTPInterfaceMap = map[Resource][]*HTTPInterface 9 | 10 | ScopeResourceHTTPInterfaceMap map[Scope]ResourceHTTPInterfaceMap 11 | ) 12 | 13 | // HTTPInterface parse grpc http options, go-zero api file 14 | type HTTPInterface struct { 15 | Scope Scope 16 | Resource Resource 17 | 18 | Method string 19 | URL string 20 | MethodName string 21 | 22 | // body 23 | Request *Request 24 | 25 | Response *Response 26 | 27 | // param 28 | PathParams []*PathParam 29 | 30 | QueryParams []*QueryParam 31 | 32 | // comments 33 | Comments string 34 | 35 | IsStreamClient bool 36 | IsStreamServer bool 37 | IsSpecified bool 38 | } 39 | 40 | type Request struct { 41 | Body string // if proto. it takes effect. * or others 42 | RealBodyName string // if proto and body is not *. use it 43 | Name string // request type name 44 | Type string // proto or api 45 | Package string // for example. types. *types.HelloParamRequest 46 | FullName string 47 | } 48 | 49 | type Response struct { 50 | FullName string 51 | Package string 52 | } 53 | 54 | type PathParam struct { 55 | Index int 56 | Name string 57 | GoName string 58 | } 59 | 60 | type QueryParam struct { 61 | GoName string 62 | Name string 63 | } 64 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/ivm/ivmaddapi/api.go: -------------------------------------------------------------------------------- 1 | package ivmaddapi 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strings" 7 | 8 | "github.com/zeromicro/go-zero/tools/goctl/api/format" 9 | 10 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 11 | "github.com/jzero-io/jzero/cmd/jzero/internal/desc" 12 | "github.com/jzero-io/jzero/cmd/jzero/internal/embeded" 13 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/stringx" 14 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/templatex" 15 | ) 16 | 17 | type Handler struct { 18 | Name string 19 | Verb string 20 | } 21 | 22 | func Run() error { 23 | baseApiDir := filepath.Join("desc", "api") 24 | 25 | service := desc.GetApiServiceName(filepath.Join("desc", "api")) 26 | 27 | var handlers []Handler 28 | for _, v := range config.C.Ivm.Add.Api.Handlers { 29 | split := strings.Split(v, ":") 30 | var method Handler 31 | if len(split) == 2 { 32 | method.Name = split[1] 33 | method.Verb = split[0] 34 | } else if len(split) == 1 { 35 | method.Name = split[0] 36 | method.Verb = "get" 37 | } else { 38 | continue 39 | } 40 | handlers = append(handlers, method) 41 | } 42 | 43 | template, err := templatex.ParseTemplate(map[string]any{ 44 | "Handlers": handlers, 45 | "Service": service, 46 | "Group": config.C.Ivm.Add.Api.Group, 47 | "GroupCamel": stringx.FirstUpper(stringx.ToCamel(config.C.Ivm.Add.Api.Group)), 48 | }, embeded.ReadTemplateFile(filepath.Join("ivm", "add", "template.api.tpl"))) 49 | if err != nil { 50 | return err 51 | } 52 | 53 | err = os.WriteFile(filepath.Join(baseApiDir, config.C.Ivm.Add.Api.Name+".api"), template, 0o644) 54 | if err != nil { 55 | return err 56 | } 57 | 58 | // format 59 | return format.ApiFormatByPath(filepath.Join(baseApiDir, config.C.Ivm.Add.Api.Name+".api"), false) 60 | } 61 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/ivm/ivmaddproto/proto.go: -------------------------------------------------------------------------------- 1 | package ivmaddproto 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "strings" 8 | 9 | "github.com/pkg/errors" 10 | "github.com/zeromicro/go-zero/tools/goctl/util/pathx" 11 | 12 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 13 | "github.com/jzero-io/jzero/cmd/jzero/internal/embeded" 14 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/templatex" 15 | ) 16 | 17 | type Method struct { 18 | Name string 19 | Verb string 20 | } 21 | 22 | func Run() error { 23 | var methods []Method 24 | for _, v := range config.C.Ivm.Add.Proto.Methods { 25 | split := strings.Split(v, ":") 26 | var method Method 27 | if len(split) == 2 { 28 | method.Name = split[1] 29 | method.Verb = split[0] 30 | } else if len(split) == 1 { 31 | method.Name = split[0] 32 | method.Verb = "get" 33 | } else { 34 | continue 35 | } 36 | methods = append(methods, method) 37 | } 38 | 39 | var version string 40 | var versionSuffix string 41 | 42 | if config.C.Ivm.Version == "v1" { 43 | version = "" 44 | versionSuffix = "" 45 | } else { 46 | version = config.C.Ivm.Version 47 | versionSuffix = "_" + config.C.Ivm.Version 48 | } 49 | 50 | template, err := templatex.ParseTemplate(map[string]any{ 51 | "Package": config.C.Ivm.Add.Proto.Name, 52 | "Methods": methods, 53 | "Services": config.C.Ivm.Add.Proto.Services, 54 | "Version": version, 55 | "UrlVersion": config.C.Ivm.Version, 56 | "ProtoPath": filepath.Join(config.C.Ivm.Version, fmt.Sprintf("%s%s.proto", config.C.Ivm.Add.Proto.Name, versionSuffix)), 57 | }, embeded.ReadTemplateFile(filepath.Join("ivm", "add", "template.proto.tpl"))) 58 | if err != nil { 59 | return err 60 | } 61 | 62 | // format proto 63 | // Create a new printer 64 | // printer := &protoprint.Printer{} 65 | 66 | output := filepath.Join("desc", "proto", config.C.Ivm.Version, fmt.Sprintf("%s%s.proto", config.C.Ivm.Add.Proto.Name, versionSuffix)) 67 | 68 | if pathx.FileExists(output) { 69 | return errors.New("proto file already exists") 70 | } 71 | 72 | return os.WriteFile(output, template, 0o644) 73 | } 74 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/ivm/ivminit/gen.go: -------------------------------------------------------------------------------- 1 | package ivminit 2 | 3 | import ( 4 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/gen/gen" 5 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 6 | ) 7 | 8 | func (ivm *IvmInit) gen() error { 9 | defer gen.RemoveExtraFiles(config.C.Wd(), config.C.Ivm.Init.Style) 10 | 11 | err := ivm.jzeroRpc.Gen() 12 | if err != nil { 13 | return err 14 | } 15 | 16 | return nil 17 | } 18 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/mcp/run.go: -------------------------------------------------------------------------------- 1 | package mcp 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/signal" 7 | "syscall" 8 | 9 | "github.com/spf13/cobra" 10 | 11 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/mcp" 12 | ) 13 | 14 | func Run(rootCmd *cobra.Command) error { 15 | quit := make(chan os.Signal, 1) 16 | signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) 17 | commands := rootCmd.Commands() 18 | for _, cmd := range commands { 19 | if cmd.Use == "mcp" { 20 | rootCmd.RemoveCommand(cmd) 21 | } 22 | } 23 | mcpServer := mcp.NewCobraMCPServer(rootCmd) 24 | go func() { 25 | if err := mcpServer.ServeStdio(); err != nil { 26 | fmt.Printf("MCP server error: %v\n", err) 27 | os.Exit(1) 28 | } 29 | }() 30 | <-quit 31 | return nil 32 | } 33 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/migrate/migrate.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2025 jaronnie 3 | */ 4 | 5 | package migrate 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/spf13/cobra" 11 | 12 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/migrate/migratedown" 13 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/migrate/migrategoto" 14 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/migrate/migrateup" 15 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/migrate/migrateversion" 16 | ) 17 | 18 | // migrateCmd represents the migrate command 19 | var migrateCmd = &cobra.Command{ 20 | Use: "migrate", 21 | Short: "jzero migrate", 22 | RunE: func(cmd *cobra.Command, args []string) error { 23 | fmt.Println(cmd.UsageString()) 24 | return nil 25 | }, 26 | } 27 | 28 | var migrateUpCmd = &cobra.Command{ 29 | Use: "up", 30 | Short: "migrate up", 31 | RunE: func(cmd *cobra.Command, args []string) error { 32 | return migrateup.Run(args) 33 | }, 34 | } 35 | 36 | var migrateDownCmd = &cobra.Command{ 37 | Use: "down", 38 | Short: "migrate down", 39 | RunE: func(cmd *cobra.Command, args []string) error { 40 | return migratedown.Run(args) 41 | }, 42 | } 43 | 44 | var migrateGotoCmd = &cobra.Command{ 45 | Use: "goto", 46 | Short: "migrate goto", 47 | RunE: func(cmd *cobra.Command, args []string) error { 48 | return migrategoto.Run(args) 49 | }, 50 | } 51 | 52 | var migrateVersionCmd = &cobra.Command{ 53 | Use: "version", 54 | Short: "migrate version", 55 | RunE: func(cmd *cobra.Command, args []string) error { 56 | return migrateversion.Run(args) 57 | }, 58 | } 59 | 60 | func GetCommand() *cobra.Command { 61 | migrateCmd.PersistentFlags().StringP("source", "", "file://desc/sql_migration", "migrate source") 62 | _ = migrateCmd.MarkFlagRequired("source") 63 | migrateCmd.PersistentFlags().StringP("database", "", "mysql", "migrate database") 64 | _ = migrateCmd.MarkFlagRequired("database") 65 | 66 | migrateCmd.AddCommand(migrateUpCmd) 67 | migrateCmd.AddCommand(migrateDownCmd) 68 | migrateCmd.AddCommand(migrateGotoCmd) 69 | migrateCmd.AddCommand(migrateVersionCmd) 70 | return migrateCmd 71 | } 72 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/migrate/migratedown/run.go: -------------------------------------------------------------------------------- 1 | package migratedown 2 | 3 | import ( 4 | "errors" 5 | 6 | migrate "github.com/golang-migrate/migrate/v4" 7 | _ "github.com/golang-migrate/migrate/v4/database/mysql" 8 | _ "github.com/golang-migrate/migrate/v4/source/file" 9 | "github.com/spf13/cast" 10 | 11 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 12 | ) 13 | 14 | func Run(args []string) error { 15 | m, err := migrate.New(config.C.Migrate.Source, config.C.Migrate.Database) 16 | if err != nil { 17 | return err 18 | } 19 | 20 | if len(args) > 0 { 21 | if cast.ToInt(args[0]) < 0 { 22 | return errors.New("step must be greater than 0") 23 | } 24 | return m.Steps(-cast.ToInt(args[0])) 25 | } 26 | return m.Steps(-1) 27 | } 28 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/migrate/migrategoto/run.go: -------------------------------------------------------------------------------- 1 | package migrategoto 2 | 3 | import ( 4 | "errors" 5 | 6 | migrate "github.com/golang-migrate/migrate/v4" 7 | _ "github.com/golang-migrate/migrate/v4/database/mysql" 8 | _ "github.com/golang-migrate/migrate/v4/source/file" 9 | "github.com/spf13/cast" 10 | 11 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 12 | ) 13 | 14 | func Run(args []string) error { 15 | m, err := migrate.New(config.C.Migrate.Source, config.C.Migrate.Database) 16 | if err != nil { 17 | return err 18 | } 19 | 20 | if len(args) <= 0 { 21 | return errors.New("step must be greater than 0") 22 | } 23 | 24 | if err = m.Migrate(cast.ToUint(args[0])); err != nil { 25 | if errors.Is(err, migrate.ErrNoChange) { 26 | return err 27 | } 28 | } 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/migrate/migrateup/run.go: -------------------------------------------------------------------------------- 1 | package migrateup 2 | 3 | import ( 4 | "errors" 5 | 6 | migrate "github.com/golang-migrate/migrate/v4" 7 | _ "github.com/golang-migrate/migrate/v4/database/mysql" 8 | _ "github.com/golang-migrate/migrate/v4/source/file" 9 | "github.com/spf13/cast" 10 | 11 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 12 | ) 13 | 14 | func Run(args []string) error { 15 | m, err := migrate.New(config.C.Migrate.Source, config.C.Migrate.Database) 16 | if err != nil { 17 | return err 18 | } 19 | 20 | if len(args) > 0 { 21 | if cast.ToInt(args[0]) < 0 { 22 | return errors.New("step must be greater than 0") 23 | } 24 | if err = m.Steps(cast.ToInt(args[0])); err != nil { 25 | if errors.Is(err, migrate.ErrNoChange) { 26 | return nil 27 | } 28 | } 29 | return err 30 | } 31 | 32 | if err = m.Up(); err != nil { 33 | if errors.Is(err, migrate.ErrNoChange) { 34 | return nil 35 | } 36 | } 37 | 38 | return err 39 | } 40 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/migrate/migrateversion/run.go: -------------------------------------------------------------------------------- 1 | package migrateversion 2 | 3 | import ( 4 | "fmt" 5 | 6 | migrate "github.com/golang-migrate/migrate/v4" 7 | _ "github.com/golang-migrate/migrate/v4/database/mysql" 8 | _ "github.com/golang-migrate/migrate/v4/source/file" 9 | 10 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 11 | ) 12 | 13 | func Run(args []string) error { 14 | m, err := migrate.New(config.C.Migrate.Source, config.C.Migrate.Database) 15 | if err != nil { 16 | return err 17 | } 18 | 19 | version, dirty, err := m.Version() 20 | if err != nil { 21 | return err 22 | } 23 | 24 | if dirty { 25 | fmt.Printf("%v (dirty)\n", version) 26 | } else { 27 | fmt.Printf("%v\n", version) 28 | } 29 | return nil 30 | } 31 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/new/template_data.go: -------------------------------------------------------------------------------- 1 | package new 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "strings" 7 | 8 | "github.com/hashicorp/go-version" 9 | 10 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/mod" 11 | ) 12 | 13 | const ( 14 | go1_21_0 = "1.21.0" 15 | ) 16 | 17 | func NewTemplateData() (map[string]any, error) { 18 | goVersion, err := mod.GetGoVersion() 19 | if err != nil { 20 | return nil, err 21 | } 22 | 23 | newVersion, err := version.NewVersion(goVersion) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | go1210version, err := version.NewVersion(go1_21_0) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | if newVersion.LessThan(go1210version) { 34 | split := strings.Split(goVersion, ".") 35 | goVersion = fmt.Sprintf("%s.%s", split[0], split[1]) 36 | } 37 | 38 | templateData := map[string]any{ 39 | "GoVersion": goVersion, 40 | "GoArch": runtime.GOARCH, 41 | } 42 | 43 | return templateData, nil 44 | } 45 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/serverless/serverless.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2024 jaronnie 3 | */ 4 | 5 | package serverless 6 | 7 | import ( 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/serverless/serverlessbuild" 11 | "github.com/jzero-io/jzero/cmd/jzero/internal/command/serverless/serverlessdelete" 12 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 13 | "github.com/jzero-io/jzero/cmd/jzero/internal/embeded" 14 | ) 15 | 16 | // serverlessCmd represents the serverless command 17 | var serverlessCmd = &cobra.Command{ 18 | Use: "serverless", 19 | Short: "jzero serverless", 20 | Long: `jzero serverless.`, 21 | } 22 | 23 | var serverlessBuildCmd = &cobra.Command{ 24 | Use: "build", 25 | Short: "jzero serverless build", 26 | Long: `jzero serverless build.`, 27 | RunE: func(cmd *cobra.Command, args []string) error { 28 | embeded.Home = config.C.Serverless.Home 29 | return serverlessbuild.Run() 30 | }, 31 | } 32 | 33 | var serverlessDeleteCmd = &cobra.Command{ 34 | Use: "delete", 35 | Short: "jzero serverless delete", 36 | Long: `jzero serverless delete.`, 37 | RunE: func(cmd *cobra.Command, args []string) error { 38 | embeded.Home = config.C.Serverless.Home 39 | return serverlessdelete.Run() 40 | }, 41 | } 42 | 43 | func GetCommand() *cobra.Command { 44 | serverlessCmd.AddCommand(serverlessBuildCmd) 45 | serverlessCmd.AddCommand(serverlessDeleteCmd) 46 | 47 | serverlessCmd.PersistentFlags().StringP("home", "", ".template", "set templates path") 48 | serverlessDeleteCmd.Flags().StringSliceP("plugin", "p", nil, "plugin name") 49 | 50 | return serverlessCmd 51 | } 52 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/template/templatebuild/filter.go: -------------------------------------------------------------------------------- 1 | package templatebuild 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | 7 | "github.com/moby/patternmatcher" 8 | ) 9 | 10 | var IgnoreDirs = []string{".git", ".idea", ".vscode", ".DS_Store", "node_modules"} 11 | 12 | func filter(dir, name string, matcher *patternmatcher.PatternMatcher) bool { 13 | pwd, err := os.Getwd() 14 | if err != nil { 15 | return true 16 | } 17 | target := filepath.Join(dir, name) 18 | relFilePath, err := filepath.Rel(pwd, target) 19 | if err != nil { 20 | return true 21 | } 22 | skip, err := filepathMatches(matcher, relFilePath) 23 | if err != nil || skip { 24 | return true 25 | } 26 | return false 27 | } 28 | 29 | func filepathMatches(matcher *patternmatcher.PatternMatcher, file string) (bool, error) { 30 | file = filepath.Clean(file) 31 | if file == "." { 32 | // Don't let them exclude everything, kind of silly. 33 | return false, nil 34 | } 35 | return matcher.MatchesOrParentMatches(file) 36 | } 37 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/template/templateinit/init.go: -------------------------------------------------------------------------------- 1 | package templateinit 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "path/filepath" 8 | "time" 9 | 10 | "github.com/go-git/go-git/v5" 11 | "github.com/go-git/go-git/v5/plumbing" 12 | "github.com/zeromicro/go-zero/core/color" 13 | 14 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 15 | "github.com/jzero-io/jzero/cmd/jzero/internal/embeded" 16 | ) 17 | 18 | func Run() error { 19 | if config.C.Template.Init.Remote != "" && config.C.Template.Init.Branch != "" { 20 | target := filepath.Join(config.C.Template.Init.Output, config.C.Template.Init.Branch) 21 | _ = os.MkdirAll(target, 0o755) 22 | fmt.Printf("%s templates into '%s', please wait...\n", color.WithColor("Cloning", color.FgGreen), target) 23 | 24 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) 25 | defer cancel() 26 | _, err := git.PlainCloneContext(ctx, target, false, &git.CloneOptions{ 27 | SingleBranch: true, 28 | URL: config.C.Template.Init.Remote, 29 | Depth: 0, 30 | ReferenceName: plumbing.ReferenceName("refs/heads/" + config.C.Template.Init.Branch), 31 | }) 32 | if err != nil { 33 | return err 34 | } 35 | _ = os.RemoveAll(filepath.Join(target, ".git")) 36 | fmt.Println(color.WithColor("Done", color.FgGreen)) 37 | return nil 38 | } 39 | fmt.Printf("%s templates into '%s', please wait...\n", color.WithColor("Initializing embedded", color.FgGreen), config.C.Template.Init.Output) 40 | err := embeded.WriteTemplateDir("", config.C.Template.Init.Output) 41 | if err != nil { 42 | return err 43 | } 44 | fmt.Println(color.WithColor("Done", color.FgGreen)) 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/upgrade/upgrade.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2024 jaronnie 3 | 4 | */ 5 | 6 | package upgrade 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/spf13/cobra" 12 | "github.com/zeromicro/go-zero/tools/goctl/pkg/golang" 13 | 14 | "github.com/jzero-io/jzero/cmd/jzero/internal/config" 15 | ) 16 | 17 | var upgradeCmd = &cobra.Command{ 18 | Use: "upgrade", 19 | Short: `Upgrade the version of jzero tool.`, 20 | RunE: func(cmd *cobra.Command, args []string) error { 21 | switch config.C.Upgrade.Channel { 22 | case "stable": 23 | return golang.Install("github.com/jzero-io/jzero/cmd/jzero@latest") 24 | default: 25 | return golang.Install(fmt.Sprintf("github.com/jzero-io/jzero/cmd/jzero@%s", config.C.Upgrade.Channel)) 26 | } 27 | }, 28 | } 29 | 30 | func GetCommand() *cobra.Command { 31 | upgradeCmd.Flags().StringP("channel", "c", "stable", "channel to upgrade jzero") 32 | return upgradeCmd 33 | } 34 | -------------------------------------------------------------------------------- /cmd/jzero/internal/command/version/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2024 jaronnie 3 | 4 | */ 5 | 6 | package version 7 | 8 | import ( 9 | "bytes" 10 | "fmt" 11 | "runtime" 12 | "time" 13 | 14 | "github.com/spf13/cast" 15 | "github.com/spf13/cobra" 16 | ) 17 | 18 | var ( 19 | Version string 20 | Commit string 21 | Date string 22 | ) 23 | 24 | // versionCmd represents the version command 25 | var versionCmd = &cobra.Command{ 26 | Use: "version", 27 | Short: `Print jzero version`, 28 | Run: func(cmd *cobra.Command, args []string) { 29 | GetVersion() 30 | }, 31 | } 32 | 33 | func GetVersion() { 34 | var versionBuffer bytes.Buffer 35 | 36 | if Version != "" { 37 | versionBuffer.WriteString(fmt.Sprintf("jzero version %s %s/%s\n", Version, runtime.GOOS, runtime.GOARCH)) 38 | } else { 39 | versionBuffer.WriteString(fmt.Sprintf("jzero version %s %s/%s\n", "unknown", runtime.GOOS, runtime.GOARCH)) 40 | } 41 | 42 | versionBuffer.WriteString(fmt.Sprintf("Go version %s\n", runtime.Version())) 43 | if Commit != "" { 44 | versionBuffer.WriteString(fmt.Sprintf("Git commit %s\n", Commit)) 45 | } else { 46 | versionBuffer.WriteString(fmt.Sprintf("Git commit %s\n", "unknown")) 47 | } 48 | 49 | if Date != "" { 50 | versionBuffer.WriteString(fmt.Sprintf("Build date %s\n", cast.ToTimeInDefaultLocation(Date, time.Local))) 51 | } else { 52 | versionBuffer.WriteString(fmt.Sprintf("Build date %s\n", "unknown")) 53 | } 54 | 55 | fmt.Print(versionBuffer.String()) 56 | } 57 | 58 | func GetCommand() *cobra.Command { 59 | return versionCmd 60 | } 61 | -------------------------------------------------------------------------------- /cmd/jzero/internal/embeded/template.go: -------------------------------------------------------------------------------- 1 | package embeded 2 | 3 | import ( 4 | "embed" 5 | "os" 6 | "path/filepath" 7 | ) 8 | 9 | var ( 10 | Template embed.FS 11 | 12 | // Home template home 13 | Home string 14 | ) 15 | 16 | func ReadTemplateFile(filename string) []byte { 17 | if Home != "" { 18 | file, err := os.ReadFile(filepath.Join(Home, filename)) 19 | if err == nil { 20 | return file 21 | } 22 | } 23 | path := filepath.ToSlash(filepath.Join(".template", filename)) 24 | data, err := Template.ReadFile(path) 25 | if err != nil { 26 | return nil 27 | } 28 | return data 29 | } 30 | 31 | func ReadTemplateDir(dirname string) []os.DirEntry { 32 | if Home != "" { 33 | file, err := os.ReadDir(filepath.Join(Home, dirname)) 34 | if err == nil { 35 | return file 36 | } 37 | } 38 | path := filepath.ToSlash(filepath.Join(".template", dirname)) 39 | data, err := Template.ReadDir(path) 40 | if err != nil { 41 | return nil 42 | } 43 | return data 44 | } 45 | 46 | func WriteTemplateDir(sourceDir, targetDir string) error { 47 | err := os.MkdirAll(targetDir, 0o755) 48 | if err != nil { 49 | return err 50 | } 51 | 52 | err = writeTemplateDirRecursive(sourceDir, targetDir) 53 | if err != nil { 54 | return err 55 | } 56 | 57 | return nil 58 | } 59 | 60 | func writeTemplateDirRecursive(sourceDir, targetDir string) error { 61 | entries, err := Template.ReadDir(filepath.ToSlash(filepath.Join(".template", sourceDir))) 62 | if err != nil { 63 | return err 64 | } 65 | 66 | for _, entry := range entries { 67 | sourcePath := filepath.Join(sourceDir, entry.Name()) 68 | targetPath := filepath.Join(targetDir, entry.Name()) 69 | 70 | if entry.IsDir() { 71 | err := os.MkdirAll(targetPath, 0o755) 72 | if err != nil { 73 | return err 74 | } 75 | 76 | err = writeTemplateDirRecursive(sourcePath, targetPath) 77 | if err != nil { 78 | return err 79 | } 80 | } else { 81 | data, err := Template.ReadFile(filepath.ToSlash(filepath.Join(".template", sourcePath))) 82 | if err != nil { 83 | return err 84 | } 85 | 86 | err = os.WriteFile(targetPath, data, 0o644) 87 | if err != nil { 88 | return err 89 | } 90 | } 91 | } 92 | 93 | return nil 94 | } 95 | -------------------------------------------------------------------------------- /cmd/jzero/internal/hooks/hooks.go: -------------------------------------------------------------------------------- 1 | package hooks 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | 8 | "github.com/pkg/errors" 9 | "github.com/spf13/cobra" 10 | "github.com/zeromicro/go-zero/core/color" 11 | "github.com/zeromicro/go-zero/core/logx" 12 | 13 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/execx" 14 | ) 15 | 16 | func Run(cmd *cobra.Command, hookAction, hooksName string, hooks []string) error { 17 | wd, _ := os.Getwd() 18 | 19 | if os.Getenv("JZERO_HOOK_TRIGGERED") == "true" { 20 | return nil 21 | } 22 | 23 | if os.Getenv("JZERO_FORKED") == "true" && hooksName == "global" && hookAction == "Before" { 24 | return nil 25 | } 26 | 27 | if len(hooks) > 0 { 28 | fmt.Printf("%s\n", color.WithColor(fmt.Sprintf("Start %s %s hooks", hookAction, hooksName), color.FgGreen)) 29 | } 30 | 31 | for _, v := range hooks { 32 | fmt.Printf("%s command %s\n", color.WithColor("Run", color.FgGreen), v) 33 | err := execx.Run(v, wd, "JZERO_HOOK_TRIGGERED=true") 34 | if err != nil { 35 | return err 36 | } 37 | } 38 | 39 | if len(hooks) > 0 { 40 | fmt.Printf("%s\n", color.WithColor("Done", color.FgGreen)) 41 | } 42 | 43 | // fork 一个子进程来运行后续的指令 44 | if len(hooks) > 0 && hookAction == "Before" && hooksName == "global" { 45 | logx.Debugf("Before hooks executed, forking a new process to continue") 46 | 47 | // 获取当前可执行文件路径 48 | executable, err := os.Executable() 49 | if err != nil { 50 | return fmt.Errorf("failed to get executable path: %v", err) 51 | } 52 | // 准备命令行参数 53 | args := os.Args[1:] 54 | 55 | // 设置环境变量,防止无限递归 56 | env := append(os.Environ(), "JZERO_FORKED=true") 57 | 58 | // 创建新进程 59 | fork := exec.Command(executable, args...) 60 | fork.Env = env 61 | fork.Stdin = os.Stdin 62 | fork.Stdout = os.Stdout 63 | fork.Stderr = os.Stderr 64 | 65 | // 启动新进程 66 | if err = fork.Start(); err != nil { 67 | return fmt.Errorf("failed to start forked process: %v", err) 68 | } 69 | // 等待新进程完成 70 | if err = fork.Wait(); err != nil { 71 | var exitErr *exec.ExitError 72 | if errors.As(err, &exitErr) { 73 | os.Exit(exitErr.ExitCode()) 74 | } 75 | return fmt.Errorf("forked process failed: %v", err) 76 | } 77 | // 子进程成功完成,退出当前进程 78 | os.Exit(0) 79 | } 80 | 81 | return nil 82 | } 83 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/dsn/dsn_test.go: -------------------------------------------------------------------------------- 1 | package dsn 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestParseDSN(t *testing.T) { 9 | // Add tests for ParseDSN function 10 | t.Run("Test ParseDSN", func(t *testing.T) { 11 | // Add test cases for ParseDSN function 12 | t.Run("Test ParseDSN with mysql", func(t *testing.T) { 13 | // Add test cases for ParseDSN function with mysql 14 | t.Run("Test ParseDSN with mysql and valid dsn", func(t *testing.T) { 15 | // Add test cases for ParseDSN function with mysql and valid dsn 16 | meta, err := ParseDSN("mysql", "user:password@tcp(localhost:3306)/dbname") 17 | if err != nil { 18 | t.Errorf("ParseDSN() error = %v", err) 19 | } 20 | if meta[User] != "user" { 21 | t.Errorf("ParseDSN() user = %v, want %v", meta[User], "user") 22 | } 23 | if meta[Host] != "localhost" { 24 | t.Errorf("ParseDSN() host = %v, want %v", meta[Host], "localhost") 25 | } 26 | if meta[Port] != "3306" { 27 | t.Errorf("ParseDSN() port = %v, want %v", meta[Port], "3306") 28 | } 29 | if meta[Database] != "dbname" { 30 | t.Errorf("ParseDSN() dbname = %v, want %v", meta[Database], "dbname") 31 | } 32 | }) 33 | }) 34 | }) 35 | 36 | t.Run("Test ParseDSN with postgres", func(t *testing.T) { 37 | // Add test cases for ParseDSN function with postgres 38 | t.Run("Test ParseDSN with postgres and valid dsn", func(t *testing.T) { 39 | // Add test cases for ParseDSN function with postgres and valid dsn 40 | meta, err := ParseDSN("postgres", "postgres://user:password@localhost:5432/dbname") 41 | if err != nil { 42 | t.Errorf("ParseDSN() error = %v", err) 43 | } 44 | fmt.Println(meta) 45 | if meta[User] != "user" { 46 | t.Errorf("ParseDSN() user = %v, want %v", meta[User], "user") 47 | } 48 | if meta[Host] != "localhost" { 49 | t.Errorf("ParseDSN() host = %v, want %v", meta[Host], "localhost") 50 | } 51 | if meta[Port] != "5432" { 52 | t.Errorf("ParseDSN() port = %v, want %v", meta[Port], "5432") 53 | } 54 | if meta[Database] != "dbname" { 55 | t.Errorf("ParseDSN() dbname = %v, want %v", meta[Database], "dbname") 56 | } 57 | }) 58 | }) 59 | } 60 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/execx/exec.go: -------------------------------------------------------------------------------- 1 | package execx 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "os/exec" 8 | "runtime" 9 | 10 | "github.com/zeromicro/go-zero/tools/goctl/vars" 11 | ) 12 | 13 | func Run(arg, dir string, env ...string) error { 14 | goos := runtime.GOOS 15 | var cmd *exec.Cmd 16 | switch goos { 17 | case vars.OsMac, vars.OsLinux: 18 | cmd = exec.Command("sh", "-c", arg) 19 | case vars.OsWindows: 20 | cmd = exec.Command("cmd.exe", "/c", arg) 21 | default: 22 | return fmt.Errorf("unexpected os: %v", goos) 23 | } 24 | 25 | if len(dir) > 0 { 26 | cmd.Dir = dir 27 | } 28 | 29 | if len(env) > 0 { 30 | cmd.Env = append(os.Environ(), env...) 31 | } 32 | 33 | stdout, err := cmd.StdoutPipe() 34 | if err != nil { 35 | return err 36 | } 37 | 38 | stderr, err := cmd.StderrPipe() 39 | if err != nil { 40 | return err 41 | } 42 | 43 | if err := cmd.Start(); err != nil { 44 | return err 45 | } 46 | 47 | go func() { 48 | _, _ = io.Copy(os.Stdout, stdout) 49 | }() 50 | 51 | go func() { 52 | _, _ = io.Copy(os.Stderr, stderr) 53 | }() 54 | 55 | if err := cmd.Wait(); err != nil { 56 | return err 57 | } 58 | 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/filex/filex.go: -------------------------------------------------------------------------------- 1 | package filex 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | "strings" 8 | ) 9 | 10 | // FileExists check file exist 11 | func FileExists(path string) bool { 12 | info, err := os.Stat(path) 13 | if os.IsNotExist(err) { 14 | return false 15 | } 16 | return !info.IsDir() 17 | } 18 | 19 | func DirExists(path string) bool { 20 | info, err := os.Stat(path) 21 | if os.IsNotExist(err) { 22 | return false 23 | } 24 | return info.IsDir() 25 | } 26 | 27 | // IsYamlFile check YAML file 28 | func IsYamlFile(path string) bool { 29 | ext := strings.ToLower(filepath.Ext(path)) 30 | return ext == ".yaml" || ext == ".yml" 31 | } 32 | 33 | // EnsureDirExists create dir with check 34 | func EnsureDirExists(dirPath string) error { 35 | info, err := os.Stat(dirPath) 36 | if os.IsNotExist(err) { 37 | err = os.MkdirAll(dirPath, 0o755) 38 | if err != nil { 39 | return fmt.Errorf("failed to create directory: %w", err) 40 | } 41 | } else if err != nil { 42 | return fmt.Errorf("failed to check directory: %w", err) 43 | } else if !info.IsDir() { 44 | return fmt.Errorf("path exists but is not a directory: %s", dirPath) 45 | } 46 | return nil 47 | } 48 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/gitstatus/status.go: -------------------------------------------------------------------------------- 1 | package gitstatus 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "os/exec" 7 | "path/filepath" 8 | "strings" 9 | ) 10 | 11 | func ChangedFiles(path, ext string) ([]string, []string, error) { 12 | var m []string 13 | var d []string 14 | 15 | cmd := exec.Command("git", "status", "-su") 16 | // set working dir 17 | cmd.Dir = path 18 | data, err := cmd.CombinedOutput() 19 | if err != nil { 20 | return nil, nil, fmt.Errorf("exec ( git status -su ) with error: %w\n%s", err, data) 21 | } 22 | data = bytes.TrimSpace(data) 23 | lines := bytes.Split(data, []byte("\n")) 24 | for _, line := range lines { 25 | if ext != "" { 26 | if !bytes.HasSuffix(line, []byte(ext)) { 27 | continue 28 | } 29 | } 30 | 31 | arr := bytes.Split(line, []byte(" ")) 32 | filename := string(arr[len(arr)-1]) 33 | 34 | if strings.HasPrefix(filename, "..") { 35 | continue 36 | } 37 | 38 | if filename != "" { 39 | if bytes.HasPrefix(line, []byte("D")) { 40 | d = append(d, filepath.Join(path, filepath.Join(strings.Split(filename, "/")...))) 41 | } else { 42 | m = append(m, filepath.Join(path, filepath.Join(strings.Split(filename, "/")...))) 43 | } 44 | } 45 | } 46 | return m, d, nil 47 | } 48 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/gogen/gogen_test.go: -------------------------------------------------------------------------------- 1 | package gogen 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/zeromicro/go-zero/tools/goctl/config" 10 | "github.com/zeromicro/go-zero/tools/goctl/pkg/parser/api/parser" 11 | ) 12 | 13 | func TestGenRoutesString(t *testing.T) { 14 | parse, err := parser.Parse(filepath.Join("testdata", "example.api"), nil) 15 | assert.Nil(t, err) 16 | 17 | routesString, err := GenRoutesString("example", &config.Config{ 18 | NamingFormat: "gozero", 19 | }, parse) 20 | assert.NotNil(t, routesString) 21 | assert.Nil(t, err) 22 | fmt.Println(routesString) 23 | } 24 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/gogen/testdata/example.api: -------------------------------------------------------------------------------- 1 | syntax = "v1" 2 | 3 | info( 4 | title: "demo title" 5 | desc: "demo desc" 6 | author: "keson.an" 7 | date: "2024-06-25" 8 | version: "v1" 9 | ) 10 | 11 | // empty structure 12 | type Foo { 13 | } 14 | 15 | // type lit 16 | type Bar { 17 | Foo int `json:"foo"` 18 | Bar bool `json:"bar"` 19 | Baz []string `json:"baz"` 20 | Qux map[string]string `json:"qux"` 21 | } 22 | 23 | type Baz { 24 | Foo `json:"foo"` 25 | // array type 26 | Arr [2]int `json:"arr"` 27 | // nested type 28 | Bar { 29 | Foo string `json:"foo"` 30 | Bar bool `json:"bar"` 31 | Baz { 32 | Foo string `json:"foo"` 33 | Bar bool `json:"bar"` 34 | } 35 | Qux { 36 | Foo string `json:"foo"` 37 | Bar bool `json:"bar"` 38 | } `json:"qux"` 39 | } `json:"bar"` 40 | } 41 | 42 | 43 | type UpdateReq { 44 | Arg1 string `json:"arg1"` 45 | } 46 | 47 | type ListItem { 48 | Value1 string `json:"value1"` 49 | } 50 | 51 | type LoginReq { 52 | Username string `json:"username"` 53 | Password string `json:"password"` 54 | } 55 | 56 | type LoginResp { 57 | Name string `json:"name"` 58 | } 59 | 60 | type FormExampleReq { 61 | Name string `form:"name"` 62 | } 63 | 64 | type PathExampleReq { 65 | ID string `path:"id"` 66 | } 67 | 68 | type PathExampleResp { 69 | Name string `json:"name"` 70 | } 71 | 72 | @server( 73 | jwt: Auth 74 | prefix: /v1 75 | group: g1 76 | timeout: 3s 77 | middleware: AuthInterceptor 78 | maxBytes: 1048576 79 | ) 80 | service Foo { 81 | @handler ping 82 | get /ping 83 | 84 | @handler update 85 | post /update (UpdateReq) 86 | 87 | @handler list 88 | get /list returns ([]ListItem) 89 | 90 | @handler login 91 | post /login (LoginReq) returns (LoginResp) 92 | 93 | @handler formExample 94 | post /form/example (FormExampleReq) 95 | 96 | @handler pathExample 97 | get /path/example/:id (PathExampleReq) returns (PathExampleResp) 98 | } 99 | 100 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/gogen/util.go: -------------------------------------------------------------------------------- 1 | package gogen 2 | 3 | import ( 4 | "bytes" 5 | "strings" 6 | "text/template" 7 | 8 | "github.com/zeromicro/go-zero/tools/goctl/api/spec" 9 | "github.com/zeromicro/go-zero/tools/goctl/pkg/golang" 10 | "github.com/zeromicro/go-zero/tools/goctl/util/pathx" 11 | ) 12 | 13 | type fileGenConfig struct { 14 | dir string 15 | subdir string 16 | filename string 17 | templateName string 18 | category string 19 | templateFile string 20 | builtinTemplate string 21 | data any 22 | } 23 | 24 | func genFileString(c fileGenConfig) (string, error) { 25 | var ( 26 | text string 27 | err error 28 | ) 29 | if len(c.category) == 0 || len(c.templateFile) == 0 { 30 | text = c.builtinTemplate 31 | } else { 32 | text, err = pathx.LoadTemplate(c.category, c.templateFile, c.builtinTemplate) 33 | if err != nil { 34 | return "", err 35 | } 36 | } 37 | 38 | t := template.Must(template.New(c.templateName).Parse(text)) 39 | buffer := new(bytes.Buffer) 40 | err = t.Execute(buffer, c.data) 41 | if err != nil { 42 | return "", err 43 | } 44 | 45 | code := golang.FormatCode(buffer.String()) 46 | return code, nil 47 | } 48 | 49 | func getDoc(doc string) string { 50 | if len(doc) == 0 { 51 | return "" 52 | } 53 | 54 | return "// " + strings.Trim(doc, "\"") 55 | } 56 | 57 | func getHandlerName(route spec.Route) string { 58 | handler, err := getHandlerBaseName(route) 59 | if err != nil { 60 | panic(err) 61 | } 62 | 63 | return handler + "Handler" 64 | } 65 | 66 | func getHandlerBaseName(route spec.Route) (string, error) { 67 | handler := route.Handler 68 | handler = strings.TrimSpace(handler) 69 | handler = strings.TrimSuffix(handler, "handler") 70 | handler = strings.TrimSuffix(handler, "Handler") 71 | 72 | return handler, nil 73 | } 74 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/osx/osx.go: -------------------------------------------------------------------------------- 1 | package osx 2 | 3 | import "os" 4 | 5 | func IsDir(path string) bool { 6 | if info, err := os.Stat(path); err == nil && info.IsDir() { 7 | return true 8 | } 9 | return false 10 | } 11 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/stringx/stringx.go: -------------------------------------------------------------------------------- 1 | package stringx 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | func FirstUpper(s string) string { 8 | if len(s) > 0 { 9 | return strings.ToUpper(string(s[0])) + s[1:] 10 | } 11 | return s 12 | } 13 | 14 | func FirstLower(s string) string { 15 | if len(s) > 0 { 16 | return strings.ToLower(string(s[0])) + s[1:] 17 | } 18 | return s 19 | } 20 | 21 | func ToCamel(s string) string { 22 | s = strings.ReplaceAll(s, "_", "-") 23 | s = strings.ReplaceAll(s, "/", "-") 24 | words := strings.Split(s, "-") 25 | 26 | for i := 1; i < len(words); i++ { 27 | words[i] = FirstUpper(words[i]) 28 | } 29 | 30 | result := strings.Join(words, "") 31 | 32 | return result 33 | } 34 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/stringx/stringx_test.go: -------------------------------------------------------------------------------- 1 | package stringx 2 | 3 | import "testing" 4 | 5 | func TestToCamel(t *testing.T) { 6 | type args struct { 7 | s string 8 | } 9 | tests := []struct { 10 | name string 11 | args args 12 | want string 13 | }{ 14 | { 15 | name: "test1", 16 | args: args{ 17 | s: "ping-pong", 18 | }, 19 | want: "pingPong", 20 | }, 21 | 22 | { 23 | name: "test2", 24 | args: args{ 25 | s: "ping/pong", 26 | }, 27 | want: "pingPong", 28 | }, 29 | } 30 | for _, tt := range tests { 31 | t.Run(tt.name, func(t *testing.T) { 32 | if got := ToCamel(tt.args.s); got != tt.want { 33 | t.Errorf("ToCamel() = %v, want %v", got, tt.want) 34 | } 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cmd/jzero/internal/pkg/templatex/template.go: -------------------------------------------------------------------------------- 1 | package templatex 2 | 3 | import ( 4 | "text/template" 5 | 6 | "github.com/jzero-io/jzero/core/templatex" 7 | 8 | "github.com/jzero-io/jzero/cmd/jzero/internal/pkg/stringx" 9 | ) 10 | 11 | var registerFuncMap = map[string]any{ 12 | "FirstUpper": stringx.FirstUpper, 13 | "FirstLower": stringx.FirstLower, 14 | "ToCamel": stringx.ToCamel, 15 | } 16 | 17 | func ParseTemplate(data any, tplT []byte) ([]byte, error) { 18 | return templatex.ParseTemplate(data, tplT, templatex.WithFuncMaps([]template.FuncMap{registerFuncMap})) 19 | } 20 | -------------------------------------------------------------------------------- /cmd/jzero/internal/plugin/plugins.go: -------------------------------------------------------------------------------- 1 | package plugin 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | ) 7 | 8 | type Plugin struct { 9 | Path string 10 | Module string 11 | } 12 | 13 | func GetPlugins() ([]Plugin, error) { 14 | var plugins []Plugin 15 | dir, err := os.ReadDir("plugins") 16 | if err != nil { 17 | return nil, err 18 | } 19 | for _, p := range dir { 20 | if p.IsDir() { 21 | plugins = append(plugins, Plugin{ 22 | Path: filepath.ToSlash(filepath.Join("plugins", p.Name())), 23 | }) 24 | } else if p.Type() == os.ModeSymlink { 25 | plugins = append(plugins, Plugin{ 26 | Path: filepath.ToSlash(filepath.Join("plugins", p.Name())), 27 | }) 28 | } 29 | } 30 | return plugins, nil 31 | } 32 | -------------------------------------------------------------------------------- /core/configcenter/subscriber/etcd.go: -------------------------------------------------------------------------------- 1 | package subscriber 2 | 3 | import ( 4 | "github.com/zeromicro/go-zero/core/configcenter/subscriber" 5 | "github.com/zeromicro/go-zero/core/logx" 6 | ) 7 | 8 | // MustNewEtcdSubscriber returns an etcd Subscriber, exits on errors. 9 | func MustNewEtcdSubscriber(conf subscriber.EtcdConf) subscriber.Subscriber { 10 | s, err := subscriber.NewEtcdSubscriber(conf) 11 | logx.Must(err) 12 | return s 13 | } 14 | -------------------------------------------------------------------------------- /core/embedx/embedx.go: -------------------------------------------------------------------------------- 1 | package embedx 2 | 3 | import ( 4 | "embed" 5 | "fmt" 6 | "io/fs" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | type Opts func(config *embedxConfig) 14 | 15 | type embedxConfig struct { 16 | Dir string 17 | FileMatchFunc func(path string) bool 18 | } 19 | 20 | func WriteToLocal(ef embed.FS, opts ...Opts) ([]string, error) { 21 | config := &embedxConfig{} 22 | 23 | for _, opt := range opts { 24 | opt(config) 25 | } 26 | 27 | var fileList []string 28 | 29 | err := fs.WalkDir(ef, ".", func(path string, d fs.DirEntry, err error) error { 30 | if err != nil { 31 | return err 32 | } 33 | if !d.IsDir() { 34 | data, err := ef.ReadFile(path) 35 | if err != nil { 36 | return err 37 | } 38 | if config.Dir != "" { 39 | if stat, err := os.Stat(config.Dir); err != nil { 40 | if !os.IsExist(err) { 41 | err = os.MkdirAll(config.Dir, 0o755) 42 | if err != nil { 43 | return err 44 | } 45 | } 46 | } else { 47 | if !stat.IsDir() { 48 | return errors.Errorf("%s: not a directory", config.Dir) 49 | } 50 | } 51 | } 52 | 53 | var tmpFile *os.File 54 | if config.FileMatchFunc != nil { 55 | if config.FileMatchFunc(path) { 56 | if tmpFile, err = createTemp(config.Dir, path, data); err != nil { 57 | return err 58 | } 59 | } 60 | } else { 61 | if tmpFile, err = createTemp(config.Dir, path, data); err != nil { 62 | return err 63 | } 64 | } 65 | if tmpFile != nil { 66 | fileList = append(fileList, tmpFile.Name()) 67 | } 68 | } 69 | return nil 70 | }) 71 | if err != nil { 72 | return nil, err 73 | } 74 | return fileList, nil 75 | } 76 | 77 | func createTemp(dir, path string, data []byte) (*os.File, error) { 78 | tmpFile, err := os.CreateTemp(dir, fmt.Sprintf("*%s", filepath.Ext(path))) 79 | if err != nil { 80 | return nil, err 81 | } 82 | defer tmpFile.Close() 83 | if _, err := tmpFile.Write(data); err != nil { 84 | return nil, err 85 | } 86 | 87 | return tmpFile, nil 88 | } 89 | -------------------------------------------------------------------------------- /core/embedx/option.go: -------------------------------------------------------------------------------- 1 | package embedx 2 | 3 | func WithDir(dir string) Opts { 4 | return func(config *embedxConfig) { 5 | config.Dir = dir 6 | } 7 | } 8 | 9 | func WithFileMatchFunc(fileFilter func(path string) bool) Opts { 10 | return func(config *embedxConfig) { 11 | config.FileMatchFunc = fileFilter 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /core/middleware/fuzzy/decode.go: -------------------------------------------------------------------------------- 1 | package fuzzy 2 | 3 | import ( 4 | "sync" 5 | 6 | jsoniter "github.com/json-iterator/go" 7 | "github.com/microcosm-cc/bluemonday" 8 | ) 9 | 10 | var ( 11 | once sync.Once 12 | EnableXssProtection bool 13 | BlueMondayPolicy = bluemonday.StrictPolicy() 14 | ) 15 | 16 | func Decode(bodyBytes []byte, req any) ([]byte, error) { 17 | once.Do(func() { 18 | RegisterFuzzyDecoders() 19 | RegisterPointerFuzzyDecoders() 20 | }) 21 | 22 | if err := jsoniter.Unmarshal(bodyBytes, &req); err != nil { 23 | return nil, err 24 | } 25 | 26 | fuzzyDecodeBytes, err := jsoniter.Marshal(req) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | return fuzzyDecodeBytes, nil 32 | } 33 | -------------------------------------------------------------------------------- /core/middleware/fuzzy/request.go: -------------------------------------------------------------------------------- 1 | package fuzzy 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "net/http" 7 | "strings" 8 | 9 | "github.com/zeromicro/go-zero/core/logx" 10 | ) 11 | 12 | func DecodeRequest(r *http.Request, req any) error { 13 | if r.Body == nil { 14 | return nil 15 | } 16 | 17 | if r.Method != http.MethodPost && r.Method != http.MethodPut { 18 | return nil 19 | } 20 | 21 | if !strings.Contains(r.Header.Get("Content-Type"), "application/json") { 22 | return nil 23 | } 24 | 25 | bodyBytes, err := io.ReadAll(r.Body) 26 | if err != nil { 27 | return err 28 | } 29 | 30 | if err = r.Body.Close(); err != nil { 31 | return err 32 | } 33 | 34 | bodyBytes, err = Decode(bodyBytes, req) 35 | if err != nil { 36 | return err 37 | } 38 | 39 | r.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) 40 | r.ContentLength = int64(len(bodyBytes)) 41 | 42 | logx.Debugf("new request body bytes: %s", bodyBytes) 43 | 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /core/status/status_test.go: -------------------------------------------------------------------------------- 1 | package status 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | 7 | "github.com/pkg/errors" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | const ( 12 | GetUserListError = Code(28001) 13 | ) 14 | 15 | func TestError(t *testing.T) { 16 | err := Error(GetUserListError) 17 | status := FromError(err) 18 | assert.Equal(t, GetUserListError, status.Code()) 19 | assert.Equal(t, "get user list error", status.Message()) 20 | } 21 | 22 | func TestUnknownError(t *testing.T) { 23 | err := Error(28000) 24 | 25 | status := FromError(err) 26 | assert.Equal(t, http.StatusInternalServerError, int(status.Code())) 27 | } 28 | 29 | func TestWrap(t *testing.T) { 30 | err := Wrap(GetUserListError, errors.New("connect to db error")) 31 | status := FromError(err) 32 | assert.Equal(t, GetUserListError, status.Code()) 33 | assert.Equal(t, "get user list error: connect to db error", status.Error()) 34 | assert.Equal(t, "connect to db error", status.Unwrap().Error()) 35 | } 36 | 37 | func init() { 38 | RegisterWithMessage(GetUserListError, "get user list error") 39 | } 40 | -------------------------------------------------------------------------------- /core/stores/cache/cache.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/zeromicro/go-zero/core/stores/cache" 8 | ) 9 | 10 | type Cache interface { 11 | cache.Cache 12 | 13 | // SetNoExpireCtx Because zero cache set ctx has default expire, so jzero add this method 14 | SetNoExpireCtx(ctx context.Context, key string, val any) error 15 | 16 | // GetPrefixKeysCtx get prefix key, give prefix key return all matched key 17 | GetPrefixKeysCtx(ctx context.Context, prefix string) ([]string, error) 18 | 19 | // ExpireCtx set key expire 20 | ExpireCtx(ctx context.Context, key string, expire time.Duration) error 21 | } 22 | -------------------------------------------------------------------------------- /core/stores/cache/redis_test.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/alicebob/miniredis/v2" 8 | "github.com/pkg/errors" 9 | "github.com/stretchr/testify/assert" 10 | "github.com/zeromicro/go-zero/core/stores/redis" 11 | ) 12 | 13 | func TestRedisNode(t *testing.T) { 14 | r, err := miniredis.Run() 15 | assert.NoError(t, err) 16 | defer r.Close() 17 | 18 | cache := NewRedisNode(redis.New(r.Addr()), errors.New("not found")) 19 | 20 | err = cache.SetCtx(context.Background(), "JWT_ADMIN_AUTH:1:abc", "abc") 21 | assert.NoError(t, err) 22 | 23 | err = cache.SetCtx(context.Background(), "JWT_ADMIN_AUTH:1:def", "def") 24 | assert.NoError(t, err) 25 | 26 | err = cache.SetCtx(context.Background(), "JWT_ADMIN_AUTH:1:ghi", "ghi") 27 | assert.NoError(t, err) 28 | 29 | keys, err := cache.GetPrefixKeysCtx(context.Background(), "JWT_ADMIN_AUTH:1:") 30 | assert.NoError(t, err) 31 | 32 | assert.Equal(t, []string{"JWT_ADMIN_AUTH:1:abc", "JWT_ADMIN_AUTH:1:def", "JWT_ADMIN_AUTH:1:ghi"}, keys) 33 | } 34 | -------------------------------------------------------------------------------- /core/stores/cache/sync_map_test.go: -------------------------------------------------------------------------------- 1 | package cache 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | "time" 7 | 8 | "github.com/alicebob/miniredis/v2" 9 | "github.com/pkg/errors" 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestSyncMap(t *testing.T) { 14 | t.Run("TestSyncMap", func(t *testing.T) { 15 | cache := NewSyncMap(errors.New("not found")) 16 | 17 | err := cache.SetCtx(context.Background(), "JWT_ADMIN_AUTH:1:abc", "abc") 18 | assert.NoError(t, err) 19 | err = cache.SetCtx(context.Background(), "JWT_ADMIN_AUTH:1:def", "def") 20 | assert.NoError(t, err) 21 | err = cache.SetCtx(context.Background(), "JWT_ADMIN_AUTH:1:ghi", "ghi") 22 | assert.NoError(t, err) 23 | 24 | keys, err := cache.GetPrefixKeysCtx(context.Background(), "JWT_ADMIN_AUTH:1:") 25 | assert.NoError(t, err) 26 | assert.Contains(t, keys, "JWT_ADMIN_AUTH:1:abc") 27 | assert.Contains(t, keys, "JWT_ADMIN_AUTH:1:def") 28 | assert.Contains(t, keys, "JWT_ADMIN_AUTH:1:ghi") 29 | }) 30 | } 31 | 32 | func TestSyncMapExpireCtx(t *testing.T) { 33 | r, err := miniredis.Run() 34 | assert.NoError(t, err) 35 | defer r.Close() 36 | 37 | cache := NewSyncMap(errors.New("not found")) 38 | 39 | err = cache.SetWithExpireCtx(context.Background(), "JWT_ADMIN_AUTH:1:abc", "abc", time.Duration(5)*time.Second) 40 | assert.NoError(t, err) 41 | 42 | var val any 43 | err = cache.Get("JWT_ADMIN_AUTH:1:abc", &val) 44 | assert.NoError(t, err) 45 | assert.Equal(t, "abc", val) 46 | 47 | time.Sleep(time.Second * 6) 48 | var newVal any 49 | err = cache.Get("JWT_ADMIN_AUTH:1:abc", &newVal) 50 | assert.Error(t, err) 51 | } 52 | -------------------------------------------------------------------------------- /core/stores/condition/adapter_test.go: -------------------------------------------------------------------------------- 1 | package condition 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/huandu/go-sqlbuilder" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestSelectByWhereRawSql(t *testing.T) { 11 | type args struct { 12 | sb *sqlbuilder.SelectBuilder 13 | originalField string 14 | args []any 15 | } 16 | tests := []struct { 17 | name string 18 | args args 19 | }{ 20 | { 21 | name: "test", 22 | args: args{ 23 | sb: sqlbuilder.NewSelectBuilder(), 24 | originalField: "`sys_user_id` = ? and `sys_authority_authority_id` = ?", 25 | args: []any{1, 1}, 26 | }, 27 | }, 28 | } 29 | for _, tt := range tests { 30 | t.Run(tt.name, func(t *testing.T) { 31 | sqlbuilder.DefaultFlavor = sqlbuilder.PostgreSQL 32 | SelectByWhereRawSql(tt.args.sb, tt.args.originalField, tt.args.args...) 33 | 34 | sql, arguments := tt.args.sb.Build() 35 | assert.Equal(t, `WHERE "sys_user_id" = ? AND "sys_authority_authority_id" = ?`, sql) 36 | assert.Equal(t, []any{1, 1}, arguments) 37 | }) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /core/stores/condition/chain_test.go: -------------------------------------------------------------------------------- 1 | package condition 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/huandu/go-sqlbuilder" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestChain(t *testing.T) { 11 | sb := sqlbuilder.NewSelectBuilder().Select("name", "age").From("user") 12 | 13 | chain := NewChain() 14 | conds := chain. 15 | Equal("field1", "value1", WithSkip(true)). 16 | Equal("field2", "value2"). 17 | OrderBy("create_time desc"). 18 | OrderBy("sort desc"). 19 | Build() 20 | builder := Select(*sb, conds...) 21 | 22 | sql, args := builder.Build() 23 | assert.Equal(t, `SELECT name, age FROM user WHERE field2 = ? ORDER BY create_time desc, sort desc`, sql) 24 | assert.Equal(t, []any{"value2"}, args) 25 | } 26 | 27 | func TestChainJoin(t *testing.T) { 28 | sb := sqlbuilder.NewSelectBuilder().Select("user.name", "user.age").From("user") 29 | chain := NewChain() 30 | conds := chain. 31 | Equal("user.field", "value2"). 32 | Join(sqlbuilder.InnerJoin, "user_info", "user.id = user_info.user_id"). 33 | Build() 34 | builder := Select(*sb, conds...) 35 | sql, args := builder.Build() 36 | assert.Equal(t, `SELECT user.name, user.age FROM user INNER JOIN user_info ON user.id = user_info.user_id WHERE user.field = ?`, sql) 37 | assert.Equal(t, []any{"value2"}, args) 38 | } 39 | -------------------------------------------------------------------------------- /core/stores/modelx/model.go: -------------------------------------------------------------------------------- 1 | package modelx 2 | 3 | import ( 4 | "github.com/eddieowens/opts" 5 | "github.com/zeromicro/go-zero/core/stores/cache" 6 | "github.com/zeromicro/go-zero/core/stores/sqlc" 7 | ) 8 | 9 | type ModelOpts struct { 10 | CachedConn *sqlc.CachedConn 11 | CacheConf cache.CacheConf 12 | CacheOpts []cache.Option 13 | } 14 | 15 | func (opts ModelOpts) DefaultOptions() ModelOpts { 16 | return ModelOpts{} 17 | } 18 | 19 | func WithCachedConn(cachedConn sqlc.CachedConn) opts.Opt[ModelOpts] { 20 | return func(o *ModelOpts) { 21 | o.CachedConn = &cachedConn 22 | } 23 | } 24 | 25 | func WithCacheConf(cacheConf cache.CacheConf) opts.Opt[ModelOpts] { 26 | return func(o *ModelOpts) { 27 | o.CacheConf = cacheConf 28 | } 29 | } 30 | 31 | func WithCacheOpts(cacheOpts ...cache.Option) opts.Opt[ModelOpts] { 32 | return func(o *ModelOpts) { 33 | o.CacheOpts = cacheOpts 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/swaggerv2/option.go: -------------------------------------------------------------------------------- 1 | package swaggerv2 2 | 3 | func WithSwaggerHost(swaggerHost string) Opts { 4 | return func(config *swaggerConfig) { 5 | config.SwaggerHost = swaggerHost 6 | } 7 | } 8 | 9 | func WithSwaggerPath(swaggerPath string) Opts { 10 | return func(config *swaggerConfig) { 11 | config.SwaggerPath = swaggerPath 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /core/templatex/templatex.go: -------------------------------------------------------------------------------- 1 | package templatex 2 | 3 | import ( 4 | "bytes" 5 | "text/template" 6 | 7 | "github.com/Masterminds/sprig/v3" 8 | "github.com/eddieowens/opts" 9 | ) 10 | 11 | type TemplateOpts struct { 12 | Options []string 13 | FuncMaps []template.FuncMap 14 | } 15 | 16 | func (opts TemplateOpts) DefaultOptions() TemplateOpts { 17 | return TemplateOpts{} 18 | } 19 | 20 | func WithFuncMaps(funcMaps []template.FuncMap) opts.Opt[TemplateOpts] { 21 | return func(o *TemplateOpts) { 22 | o.FuncMaps = funcMaps 23 | } 24 | } 25 | 26 | func WithOptions(options ...string) opts.Opt[TemplateOpts] { 27 | return func(o *TemplateOpts) { 28 | o.Options = options 29 | } 30 | } 31 | 32 | // ParseTemplate template 33 | func ParseTemplate(data any, tplT []byte, op ...opts.Opt[TemplateOpts]) ([]byte, error) { 34 | o := opts.DefaultApply(op...) 35 | 36 | var err error 37 | t := template.New("production").Funcs(sprig.TxtFuncMap()) 38 | for _, funcMap := range o.FuncMaps { 39 | t = t.Funcs(funcMap) 40 | } 41 | if len(o.Options) > 0 { 42 | t = t.Option(o.Options...) 43 | } 44 | 45 | t, err = t.Parse(string(tplT)) 46 | if err != nil { 47 | return nil, err 48 | } 49 | 50 | buf := new(bytes.Buffer) 51 | err = t.Execute(buf, data) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return buf.Bytes(), err 56 | } 57 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules/ 3 | src/.vuepress/.cache/ 4 | src/.vuepress/.temp/ 5 | src/.vuepress/dist/ 6 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jzero-docs", 3 | "version": "1.0.0", 4 | "description": "jzero framework", 5 | "license": "UnLicense", 6 | "type": "module", 7 | "scripts": { 8 | "docs:build": "vuepress-vite build src", 9 | "docs:clean-dev": "vuepress-vite dev src --clean-cache", 10 | "docs:dev": "vuepress-vite dev src", 11 | "docs:update-package": "pnpm dlx vp-update" 12 | }, 13 | "devDependencies": { 14 | "@vuepress/bundler-vite": "2.0.0-rc.13", 15 | "vue": "^3.4.21", 16 | "vuepress": "2.0.0-rc.13", 17 | "vuepress-theme-hope": "2.0.0-rc.49" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/src/.vuepress/config.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import { defineUserConfig } from "vuepress"; 3 | import theme from "./theme.js"; 4 | 5 | export default defineUserConfig({ 6 | base: "/", 7 | 8 | locales: { 9 | "/": { 10 | lang: "zh-CN", 11 | title: "Jzero Framework", 12 | description: "Jzero docs", 13 | }, 14 | "/en/": { 15 | lang: "en-US", 16 | title: "Jzero Framework", 17 | description: "Jzero docs", 18 | }, 19 | }, 20 | 21 | theme, 22 | 23 | // 和 PWA 一起启用 24 | // shouldPrefetch: false, 25 | }); 26 | -------------------------------------------------------------------------------- /docs/src/.vuepress/navbar/en.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import { navbar } from "vuepress-theme-hope"; 3 | 4 | // @ts-ignore 5 | export const enNavbar = navbar([ 6 | "/en/", 7 | { 8 | link: "https://github.com/jzero-io/templates", 9 | text: "template repo", 10 | icon: "octicon:repo-16" 11 | }, 12 | { 13 | link: "https://github.com/jzero-io/examples", 14 | text: "code example", 15 | icon: "vscode-icons:file-type-go" 16 | }, 17 | ]); 18 | -------------------------------------------------------------------------------- /docs/src/.vuepress/navbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./en.js"; 2 | export * from "./zh.js"; -------------------------------------------------------------------------------- /docs/src/.vuepress/navbar/zh.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import { navbar } from "vuepress-theme-hope"; 3 | 4 | // @ts-ignore 5 | export const zhNavbar = navbar([ 6 | "/", 7 | { 8 | link: "https://github.com/jzero-io/templates", 9 | text: "远程模板仓库", 10 | icon: "octicon:repo-16" 11 | }, 12 | { 13 | link: "https://github.com/jzero-io/examples", 14 | text: "代码示例", 15 | icon: "vscode-icons:file-type-go" 16 | }, 17 | { 18 | link: "https://github.com/jzero-io/jzero-admin", 19 | text: "jzero 后台管理系统", 20 | icon: "icon-park-outline:system" 21 | }, 22 | ]); 23 | -------------------------------------------------------------------------------- /docs/src/.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jzero-io/jzero/4074b555a76f8f312b451ae06c35154f1fde301c/docs/src/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /docs/src/.vuepress/sidebar.ts: -------------------------------------------------------------------------------- 1 | import { sidebar } from "vuepress-theme-hope"; 2 | 3 | export default sidebar({ 4 | "/": [ 5 | "", 6 | { 7 | text: "文档", 8 | icon: "vscode-icons:folder-type-docs", 9 | prefix: "guide/", 10 | children: "structure", 11 | collapsible: true, 12 | expanded: true, 13 | }, 14 | { 15 | text: "项目实战", 16 | icon: "mdi:arrow-projectile-multiple", 17 | prefix: "project/", 18 | children: "structure", 19 | collapsible: true, 20 | }, 21 | { 22 | text: "问题与解决", 23 | icon: "mdi:faq", 24 | prefix: "faq/", 25 | children: "structure", 26 | collapsible: true, 27 | }, 28 | { 29 | text: "路线图", 30 | icon: "mdi:roadmap", 31 | prefix: "roadmap/", 32 | children: "structure", 33 | collapsible: true, 34 | }, 35 | ], 36 | }); 37 | -------------------------------------------------------------------------------- /docs/src/.vuepress/styles/config.scss: -------------------------------------------------------------------------------- 1 | // you can change config here 2 | $colors: #c0392b, #d35400, #f39c12, #27ae60, #16a085, #2980b9, #8e44ad, #2c3e50, 3 | #7f8c8d !default; 4 | -------------------------------------------------------------------------------- /docs/src/.vuepress/styles/index.scss: -------------------------------------------------------------------------------- 1 | // place your custom styles here 2 | -------------------------------------------------------------------------------- /docs/src/.vuepress/styles/palette.scss: -------------------------------------------------------------------------------- 1 | // you can change colors here 2 | $theme-color: #096dd9; 3 | -------------------------------------------------------------------------------- /docs/src/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: false 3 | icon: fluent:home-heart-20-filled 4 | title: 首页 5 | --- 6 | 7 |
8 | 9 |
10 | 11 | ## 介绍 12 | 13 | 基于 [go-zero](https://go-zero.dev) 开发的低代码微服务开发框架 `jzero`, 通过可描述文件(**api/proto/sql**)自动生成**服务端代码/客户端代码/数据库**代码, 降低开发心智, 解放双手! 14 | 15 | jzero 具备以下特点: 16 | 17 | * 支持通过配置文件, 命令行参数以及环境变量的组合的方式控制命令的参数, 告别繁琐的命令配置 18 | * 支持基于 git 对改动文件部分生成代码, 极大提升大型项目代码生成效率 19 | * 优化 go-zero 已有的痛点并扩展新的特性 20 | * 内置常用开发模板并增强模板特性, 支持通过自定义模板内容, 构建企业内部代码模板 21 | * 所有配套工具链跨平台使用, 支持 windows/mac/linux 22 | 23 | ## 快速开始 24 | 25 | :::tip Windows 用户请在 powershell 下执行所有指令 26 | ::: 27 | 28 | ::: code-tabs#shell 29 | @tab jzero 30 | 31 | ```bash 32 | # 安装 jzero 33 | go install github.com/jzero-io/jzero/cmd/jzero@latest 34 | # 一键安装所需的工具 35 | jzero check 36 | # 一键创建项目 37 | jzero new your_project 38 | cd your_project 39 | # 下载依赖 40 | go mod tidy 41 | # 生成 swagger 42 | jzero gen swagger 43 | # 启动服务端程序 44 | go run main.go server 45 | # 访问 swagger ui 46 | http://localhost:8001/swagger 47 | ``` 48 | 49 | @tab Docker 50 | 51 | ```bash 52 | # 创建项目 53 | docker run --rm -v ${PWD}:/app ghcr.io/jzero-io/jzero:latest new your_project 54 | cd your_project 55 | # 下载依赖 56 | go mod tidy 57 | # 生成 swagger 58 | docker run --rm -v ${PWD}:/app ghcr.io/jzero-io/jzero:latest gen swagger 59 | # 启动项目 60 | go run main.go server 61 | # 访问 swagger ui 62 | http://localhost:8001/swagger 63 | ``` 64 | ::: 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /docs/src/en/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: false 3 | icon: fluent:home-heart-20-filled 4 | title: Home 5 | --- 6 | 7 |
8 | 9 |
10 | 11 | ## Introduction 12 | 13 | `jzero` is a low-code microservice development framework based on [go-zero](https://go-zero.dev). It automatically generates **server-side code/client-side code/database** code through descriptive files (**api/proto/sql**), reducing development complexity and freeing your hands! 14 | 15 | jzero has the following features: 16 | 17 | * Supports controlling command parameters through a combination of configuration files, command-line arguments, and environment variables, eliminating tedious command configurations 18 | * Supports generating code incrementally based on git-tracked file changes, significantly improving code generation efficiency for large projects 19 | * Optimizes existing pain points in go-zero and extends new features 20 | * Built-in commonly used development templates with enhanced template capabilities, supporting custom template content to build enterprise-level code templates 21 | * All supporting tools are cross-platform, compatible with Windows/Mac/Linux 22 | 23 | ## Quick Start 24 | 25 | :::tip Windows users, please execute all commands in PowerShell 26 | ::: 27 | 28 | ::: code-tabs#shell 29 | @tab jzero 30 | 31 | ```bash 32 | # Install jzero 33 | go install github.com/jzero-io/jzero/cmd/jzero@latest 34 | # One-click installation of required tools 35 | jzero check 36 | # Create a project 37 | jzero new your_project 38 | cd your_project 39 | # Download dependencies 40 | go mod tidy 41 | # Generate swagger 42 | jzero gen swagger 43 | # Start the server 44 | go run main.go server 45 | # Access swagger UI 46 | http://localhost:8001/swagger 47 | ``` 48 | 49 | @tab Docker 50 | 51 | ```bash 52 | # Create a project 53 | docker run --rm -v ${PWD}:/app ghcr.io/jzero-io/jzero:latest new your_project 54 | cd your_project 55 | # Download dependencies 56 | go mod tidy 57 | # Generate swagger 58 | docker run --rm -v ${PWD}:/app ghcr.io/jzero-io/jzero:latest gen swagger 59 | # Start the server 60 | go run main.go server 61 | # Access swagger UI 62 | http://localhost:8001/swagger 63 | ``` 64 | ::: -------------------------------------------------------------------------------- /docs/src/faq/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 问题与解决 3 | icon: mdi:faq 4 | index: false 5 | dir: 6 | order: 10 7 | --- 8 | 9 | -------------------------------------------------------------------------------- /docs/src/faq/grpc.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: gateway/rpc 框架问题记录 3 | icon: logos:grpc 4 | star: true 5 | order: 3 6 | category: faq 7 | tag: 8 | - faq 9 | --- 10 | 11 | ## 服务端 panic, 客户端会收到详细的错误信息暴露了服务端 12 | 13 | ![](http://oss.jaronnie.com/image-20241226200214351.png) 14 | 15 | ![](http://oss.jaronnie.com/image-20241226200236983.png) 16 | 17 | 解决方案: 18 | 19 | * 去掉 grpc 内置的 recover interceptor, 改为自定义的 recover interceptor 20 | 21 | ![](http://oss.jaronnie.com/image-20241227114544243.png) 22 | 23 | ![](http://oss.jaronnie.com/image-20241227114611375.png) 24 | 25 | 代码如下: 26 | 27 | ```go 28 | package middleware 29 | 30 | import ( 31 | "context" 32 | "runtime/debug" 33 | 34 | "github.com/zeromicro/go-zero/core/logx" 35 | "google.golang.org/grpc" 36 | "google.golang.org/grpc/codes" 37 | "google.golang.org/grpc/status" 38 | ) 39 | 40 | // StreamRecoverInterceptor catches panics in processing stream requests and recovers. 41 | func StreamRecoverInterceptor(svr any, stream grpc.ServerStream, _ *grpc.StreamServerInfo, 42 | handler grpc.StreamHandler) (err error) { 43 | defer handleCrash(func(r any) { 44 | err = toPanicError(r) 45 | }) 46 | 47 | return handler(svr, stream) 48 | } 49 | 50 | // UnaryRecoverInterceptor catches panics in processing unary requests and recovers. 51 | func UnaryRecoverInterceptor(ctx context.Context, req any, _ *grpc.UnaryServerInfo, 52 | handler grpc.UnaryHandler) (resp any, err error) { 53 | defer handleCrash(func(r any) { 54 | err = toPanicError(r) 55 | }) 56 | 57 | return handler(ctx, req) 58 | } 59 | 60 | func handleCrash(handler func(any)) { 61 | if r := recover(); r != nil { 62 | handler(r) 63 | } 64 | } 65 | 66 | func toPanicError(r any) error { 67 | logx.Errorf("%+v\n\n%s", r, debug.Stack()) 68 | return status.Errorf(codes.Internal, "Service temporarily unavailable") 69 | } 70 | ``` 71 | -------------------------------------------------------------------------------- /docs/src/faq/swagger.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: swagger 问题 3 | icon: vscode-icons:file-type-swagger 4 | star: true 5 | order: 1 6 | category: faq 7 | tag: 8 | - faq 9 | --- 10 | 11 | ## 1. 为什么我的 proto 字段是 order_id 但是生成的 swagger 是 orderId, 如何解决? 12 | 13 | ```protobuf 14 | syntax = "proto3"; 15 | 16 | message GetOrderRequest { 17 | int32 order_id = 2; 18 | } 19 | ``` 20 | 21 | 生成的 pb.go 文件: 22 | 23 | ```go 24 | type SayHelloRequest struct { 25 | state protoimpl.MessageState 26 | sizeCache protoimpl.SizeCache 27 | unknownFields protoimpl.UnknownFields 28 | 29 | Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` 30 | OrderId int32 `protobuf:"varint,2,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` 31 | } 32 | ``` 33 | 34 | swagger ui 如图所示: 35 | 36 | 37 | 38 | 解决方案: 39 | 40 | ```protobuf 41 | syntax = "proto3"; 42 | 43 | message GetOrderRequest { 44 | int32 order_id = 2 [json_name = "order_id"]; 45 | } 46 | ``` 47 | 48 | 49 | 50 | 如果需要自定义注释等信息, 可以使用 51 | 52 | ```protobuf 53 | syntax = "proto3"; 54 | import "google/api/annotations.proto"; 55 | import "grpc-gateway/protoc-gen-openapiv2/options/annotations.proto"; 56 | 57 | message GetOrderRequest { 58 | int32 order_id = 2 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { 59 | description: "订单 id" 60 | }, json_name = "order_id"]; 61 | } 62 | ``` 63 | 64 | 65 | -------------------------------------------------------------------------------- /docs/src/faq/upgrade.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 版本升级兼容 3 | icon: fluent-mdl2:upgrade-analysis 4 | star: true 5 | order: 2 6 | category: faq 7 | tag: 8 | - faq 9 | --- 10 | 11 | ## from old to v0.30.0+ 12 | 13 | add `MustGetConfig` method for `ServiceContext` return `config.Config` 14 | 15 | ```go 16 | func (sc *ServiceContext) MustGetConfig() config.Config { 17 | return sc.Config 18 | } 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /docs/src/guide/config/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 服务端配置 3 | icon: vscode-icons:file-type-gleamconfig 4 | index: false 5 | dir: 6 | order: 6 7 | --- 8 | 9 | -------------------------------------------------------------------------------- /docs/src/guide/config/etcd.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: etcd 配置 3 | icon: carbon:database-etcd 4 | star: true 5 | order: 7 6 | category: 配置 7 | tag: 8 | - Guide 9 | --- 10 | 11 | ## zrpc 12 | 13 | 修改 etc/etc.yaml, 增加以下配置, 设置 etcd endpoints 和该服务在 etcd 上的 key 14 | 15 | ```yaml 16 | zrpc: 17 | etcd: 18 | key: your_project.rpc 19 | hosts: 20 | - 127.0.0.1:2379 21 | listenOn: 0.0.0.0:8000 22 | mode: dev 23 | name: your_project.rpc 24 | ``` 25 | 26 | ## 快速部署测试使用的 etcd 环境 27 | 28 | ```shell 29 | docker pull bitnami/etcd:3.5.14 30 | # 如果无法 pull 31 | docker pull registry.cn-hangzhou.aliyuncs.com/jaronnie/etcd:3.5.14 32 | docker tag registry.cn-hangzhou.aliyuncs.com/jaronnie/etcd:3.5.14 bitnami/etcd:3.5.14 33 | ``` 34 | 35 | ```shell 36 | docker run -p 2379:2379 -e ALLOW_NONE_AUTHENTICATION=yes bitnami/etcd:3.5.14 37 | ``` 38 | 39 | 启动服务端后,查看 etcd 上的注册信息, 以下表示成功 40 | 41 | ![](https://oss.jaronnie.com/image-20240710222837633.png) 42 | 43 | -------------------------------------------------------------------------------- /docs/src/guide/config/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 配置说明 3 | icon: vscode-icons:file-type-gleamconfig 4 | order: 1 5 | star: true 6 | category: 配置 7 | tag: 8 | - Guide 9 | --- 10 | 11 | # 配置项 12 | 13 | jzero 支持以下几种场景: 14 | 15 | * api 项目: 基于 go-zero api 框架, 配置项为 **rest** 16 | * rpc 项目: 基于 go-zero zrpc 框架, 配置项为 **zrpc** 17 | * gateway 项目: 基于 go-zero gateway 框架以及 zrpc 框架, 配置项为 **gateway** 和 **zrpc** 18 | 19 | 其中对于基础服务配置项为 **rest**/**zrpc**/**gateway**, 日志配置项为 **log** 20 | 21 | :::tip 22 | 后续所有关于配置的地方, 标题表示在哪个配置项进行配置 23 | 请根据自己的场景选取在哪个配置项配置 24 | ::: -------------------------------------------------------------------------------- /docs/src/guide/config/limit.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 限流配置 3 | icon: mdi:car-speed-limiter 4 | star: true 5 | order: 6 6 | category: 配置 7 | tag: 8 | - Guide 9 | --- 10 | 11 | ## rest 12 | 13 | 修改 etc/etc.yaml, 增加以下配置, 设置最大 qps 100 14 | 15 | ```yaml 16 | rest: 17 | maxConns: 100 18 | ``` 19 | 20 | ## gateway 21 | 22 | 修改 etc/etc.yaml, 增加以下配置, 设置最大 qps 100 23 | 24 | ```yaml 25 | gateway: 26 | maxConns: 100 27 | ``` -------------------------------------------------------------------------------- /docs/src/guide/config/log.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 日志配置 3 | icon: mdi:math-log 4 | star: true 5 | order: 3 6 | category: 配置 7 | tag: 8 | - Guide 9 | --- 10 | 11 | 修改 etc/etc.yaml, 增加以下配置 12 | 13 | ```yaml 14 | log: 15 | keepDays: 30 16 | level: info 17 | maxBackups: 7 18 | maxSize: 50 19 | mode: file 20 | rotation: size 21 | serviceName: your_project 22 | encoding: plain 23 | ``` 24 | 25 | 默认配置下日志最大占用空间: 2G 26 | 27 | 计算规则如下: 28 | 29 | logs 文件夹一共 5 个文件. 每个文件最大占用 50MB, 最多备份 7 个. 即 50MB * 8 * 5 -------------------------------------------------------------------------------- /docs/src/guide/config/telemetry.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 链路追踪配置 3 | icon: tabler:http-trace 4 | star: true 5 | order: 5 6 | category: 配置 7 | tag: 8 | - Guide 9 | --- 10 | 11 | # 开发指南 12 | 13 | * 获取 trace 值 14 | 15 | ```go 16 | import "github.com/zeromicro/go-zero/core/trace" 17 | 18 | # 从 ctx 中获取 trace 值 19 | traceId := trace.TraceIDFromContext(l.ctx) 20 | ``` 21 | 22 | ## rest 23 | 24 | 修改 etc/etc.yaml 添加一下内容 25 | 26 | ```yaml 27 | rest: 28 | telemetry: 29 | name: "your_project-api" 30 | endpoint: "http://jaeger:14268/api/traces" 31 | sampler: 1.0 32 | batcher: "jaeger" 33 | ``` 34 | 35 | ## zrpc 36 | 37 | 修改 etc/etc.yaml, 增加以下配置 38 | 39 | ```yaml 40 | zrpc: 41 | telemetry: 42 | name: "your_project-rpc" 43 | endpoint: "http://jaeger:14268/api/traces" 44 | sampler: 1.0 45 | batcher: "jaeger" 46 | ``` 47 | 48 | ## gateway 49 | 50 | 修改 etc/etc.yaml 添加一下内容 51 | 52 | ```yaml 53 | zrpc: 54 | telemetry: 55 | name: "your_project-rpc" 56 | endpoint: "http://jaeger:14268/api/traces" 57 | sampler: 1.0 58 | batcher: "jaeger" 59 | 60 | gateway: 61 | telemetry: 62 | name: "your_project-gw" 63 | endpoint: "http://jaeger:14268/api/traces" 64 | sampler: 1.0 65 | batcher: "jaeger" 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/src/guide/config/timeout.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 超时配置 3 | icon: eos-icons:timeout 4 | order: 2 5 | star: true 6 | category: 配置 7 | tag: 8 | - Guide 9 | --- 10 | 11 | ## rest 12 | 13 | 修改 etc/etc.yaml, 增加以下配置 14 | 15 | ```yaml 16 | rest: 17 | timeout: 10000 # 10s 18 | ``` 19 | 20 | ## zrpc 21 | 22 | 修改 etc/etc.yaml, 增加以下配置 23 | 24 | ```yaml 25 | zrpc: 26 | timeout: 10000 # 10s 27 | ``` 28 | 29 | ## gateway 30 | 31 | 修改 etc/etc.yaml, 增加以下配置 32 | 33 | ```yaml 34 | gateway: 35 | timeout: 10000 # 10s 36 | upstreams: 37 | - grpc: 38 | timeout: 10000 # 10s 39 | zrpc: 40 | timeout: 10000 # 10s 41 | ``` -------------------------------------------------------------------------------- /docs/src/guide/contribute.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 贡献指南 3 | icon: ooui:user-contributions-ltr 4 | star: true 5 | order: 30 6 | category: contribute 7 | tag: 8 | - contribute 9 | --- 10 | 11 | 欢迎参与 jzero 的开发以及维护, 这是一件非常有意义的事情, 让我们一起让 jzero 变得更好. 12 | 13 | ## 步骤 14 | 15 | ### 1. fork jzero 16 | 17 | [点击这里 fork](https://github.com/jzero-io/jzero/fork) 18 | 19 | ### 2. clone 20 | 21 | ```shell 22 | git clone https://github.com/your_username/jzero 23 | ``` 24 | 25 | ### 3. checkout branch 26 | 27 | ```shell 28 | cd jzero 29 | 30 | git checkout -b feat/patch-1 31 | ``` 32 | 33 | ### 4. format the code what you changes 34 | 35 | ```shell 36 | jzero format 37 | ``` 38 | 39 | ### 5. lint codes 40 | 41 | ```shell 42 | go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest 43 | golangci-lint run --fix 44 | ``` 45 | 46 | ### 6. push 47 | 48 | ```shell 49 | git add . 50 | git commit -m "feat(xx): custom message" 51 | git push 52 | ``` 53 | 54 | ### 7. pull request 55 | 56 | Create your pull request!!! 57 | 58 | ## debug jzero 59 | 60 | 1. fork jzero 并 clone jzero 到本地后 61 | 62 | ```shell 63 | cd jzero 64 | go install 65 | ``` 66 | 67 | 2. new project with branch, e.g. `api` 68 | 69 | ```shell 70 | jzero new your_project --branch api 71 | ``` 72 | 73 | 3. run jzero gen with debug mode 74 | 75 | ```shell 76 | jzero gen --debug --debug-sleep-time 15 77 | ``` 78 | 79 | 4. attach jzero process 80 | 81 | 推荐采用 goland, 使用 attach 到 jzero 的进程中, 即可 debug, 如下所示: 82 | 83 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /docs/src/guide/deploy/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 部署 3 | icon: icon-park:rocket-one 4 | index: false 5 | dir: 6 | order: 8 7 | --- 8 | 9 | -------------------------------------------------------------------------------- /docs/src/guide/deploy/build-binary.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 编译二进制文件 3 | icon: fa6-solid:square-binary 4 | star: true 5 | order: 1 6 | category: 开发 7 | tag: 8 | - Guide 9 | --- 10 | 11 | ## 正常编译 12 | 13 | ```shell 14 | GOOS=linux GOARCH=amd64 go build 15 | ``` 16 | 17 | ## 优化二进制体积 18 | 19 | ```shell 20 | GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" 21 | ``` 22 | 23 | ## 继续优化 24 | 25 | > 如果未使用 Kubernetes 的服务发现,可以在编译的时候使用 -tags no_k8s 来排除 k8s 相关的依赖包。 26 | 27 | ```shell 28 | GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -tags no_k8s 29 | ``` 30 | 31 | ## 压缩二进制 32 | 33 | [下载 upx](https://github.com/upx/upx/releases) 34 | 35 | ```shell 36 | upx your_binary 37 | ``` 38 | 39 | 实测从 go build 90MB 到最终使用 upx 压缩后, 二进制大小为 12MB. -------------------------------------------------------------------------------- /docs/src/guide/deploy/image.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 镜像制作与推送 3 | icon: vscode-icons:file-type-docker2 4 | star: true 5 | order: 1 6 | category: 开发 7 | tag: 8 | - Guide 9 | --- 10 | 11 | ## 创建一个可以构建多平台的 buildx 12 | 13 | ```shell 14 | docker buildx create --use --name=mybuilder --driver docker-container --driver-opt image=dockerpracticesig/buildkit:master 15 | ``` 16 | 17 | ## 推送多平台镜像 18 | 19 | ```shell 20 | cd your_project 21 | docker buildx build --platform linux/amd64,linux/arm64 --progress=plain -t your_project:latest . --push 22 | ``` 23 | 24 | ## 编译单平台镜像 25 | 26 | ```shell 27 | cd your_project 28 | docker buildx build --platform linux/amd64 --progress=plain -t your_project:latest . --load 29 | ``` -------------------------------------------------------------------------------- /docs/src/guide/develop/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 开发 3 | icon: carbon:development 4 | index: false 5 | dir: 6 | order: 7 7 | --- 8 | 9 | -------------------------------------------------------------------------------- /docs/src/guide/develop/api.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: api 使用文档 3 | icon: eos-icons:api 4 | star: true 5 | order: 0.2 6 | category: 开发 7 | tag: 8 | - Guide 9 | --- 10 | 11 | ## 前言 12 | 13 | 通过 go-zero 自研的 api 文件定义, 称为 api 可描述语言, 可用于 14 | 15 | * 自动生成多语言服务端代码 16 | * 自动生成文档(json/html/swagger) 17 | * 自动生成多语言客户端代码 18 | 19 | 与 proto 文件有异曲同工之妙, 但是比 proto 更简单易用 20 | 21 | [go-zero api 教程](https://go-zero.dev/docs/tutorials) 22 | 23 | ![](http://oss.jaronnie.com/image-20250120232337438.png) 24 | 25 | ## api 字段校验 26 | 27 | > jzero 默认集成 [https://github.com/go-playground/validator](https://github.com/go-playground/validator) 进行字段校验 28 | 29 | ```shell {4} 30 | syntax = "v1" 31 | 32 | type CreateRequest { 33 | name string `json:"name" validate:"gte=2,lte=30"` // 名称 34 | } 35 | ``` 36 | 37 | ## 将 types 文件夹按照 go_package 进行分组 38 | 39 | :::important go_package 的选项, 参考自 proto 文件, 能将 message 生成的结构体分组 40 | 41 | 在 api 文件中同理, go_package 选项能将定义的 type 生成的结构体分组 42 | 43 | 两大优点: 44 | 1. 避免默认生成的 types/types.go 爆炸 45 | 46 | 2. 提升开发体验, 不同 group 下的 type 命名不会冲突 47 | ::: 48 | 49 | ```shell {3,4,5,6} 50 | syntax = "v1" 51 | 52 | info ( 53 | go_package: "version" 54 | ) 55 | ``` 56 | 57 | ## 合并同一个 group 的 handler/logic 为同一个文件 58 | 59 | ```shell {4,5} 60 | @server ( 61 | prefix: /api/v1 62 | group: system/user 63 | compact_handler: true 64 | compact_logic: true 65 | ) 66 | service simpleapi { 67 | @handler GetUserHandler 68 | get /system/user/getUser (GetUser2Request) returns (GetUserResponse) 69 | 70 | @handler DeleteUserHandler 71 | get /system/user/deleteUser (DeleteUserRequest) returns (DeleteUserResponse) 72 | } 73 | ``` 74 | 75 | ## 自动生成 api 文件: 76 | 77 | ```shell 78 | jzero ivm add api --name user 79 | ``` 80 | 81 | 完整命令如下: 82 | 83 | ```shell 84 | jzero ivm add api --name user --handlers get:List,get:Get,post:Edit,get:Delete 85 | ``` -------------------------------------------------------------------------------- /docs/src/guide/develop/command.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 命令行 cobra 使用文档 3 | icon: clarity:command-line 4 | star: true 5 | order: 0.1 6 | category: 开发 7 | tag: 8 | - Guide 9 | --- 10 | 11 | jzero 基于 [cobra](https://github.com/spf13/cobra) 库实现命令行管理. 可基于 [cobra-cli](https://github.com/spf13/cobra-cli) 工具新增 command. 12 | 13 | ```shell 14 | go install github.com/spf13/cobra-cli@latest 15 | 16 | cd your_project 17 | cobra-cli add init 18 | go run main.go -h 19 | ``` -------------------------------------------------------------------------------- /docs/src/guide/gen.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 生成服务端代码 3 | icon: vscode-icons:folder-type-api-opened 4 | order: 4 5 | --- 6 | 7 | jzero 根据可描述语言生成代码: 8 | * desc/api 9 | * desc/proto 10 | * desc/sql 11 | 12 | ## 生成代码 13 | 14 | ::: code-tabs#shell 15 | 16 | @tab jzero 17 | 18 | ```bash 19 | cd your_project 20 | jzero gen 21 | ``` 22 | 23 | @tab Docker 24 | 25 | ```bash 26 | cd your_project 27 | docker run --rm -v ${PWD}:/app ghcr.io/jzero-io/jzero:latest gen 28 | ``` 29 | ::: 30 | 31 | ## 下载依赖 32 | 33 | ```shell 34 | go mod tidy 35 | ``` 36 | 37 | ## 运行项目 38 | 39 | ```shell 40 | go run main.go server 41 | ``` 42 | 43 | ## 高级教程 44 | 45 | ### 基于 git 变动生成代码 46 | 47 | ```shell 48 | jzero gen --git-change 49 | ``` 50 | 51 | ### 指定 desc 生成代码 52 | 53 | ```shell 54 | jzero gen --desc desc/api/xx.api 55 | jzero gen --desc desc/proto/v1/xx.proto 56 | jzero gen --desc desc/sql/xx.sql 57 | ``` 58 | 59 | ### 生成代码忽略 desc 60 | 61 | > 支持传入数组, 支持指定文件夹或者文件 62 | 63 | ```shell 64 | jzero gen --desc-ignore desc/api/xx.api 65 | jzero gen --desc-ignore desc/proto/v1/xx.proto 66 | jzero gen --desc-ignore desc/sql/xx.sql 67 | ``` -------------------------------------------------------------------------------- /docs/src/guide/gendoc.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 生成 markdown 等文档 3 | icon: ph:markdown-logo-bold 4 | order: 5.2 5 | --- 6 | 7 | :::tip 目前仅支持 proto 可描述文件 8 | ::: 9 | 10 | ## markdown 11 | 12 | ```shell 13 | jzero gen doc 14 | ``` 15 | 16 | 默认输出路径 `desc/docs/markdown/index.md` 17 | 18 | ## json 19 | 20 | ```shell 21 | jzero gen doc --format json 22 | ``` 23 | 24 | 默认输出路径 `desc/docs/json/index.json` 25 | 26 | ## html 27 | 28 | ```shell 29 | jzero gen doc --format html 30 | ``` 31 | 32 | 默认输出路径 `desc/docs/html/index.html` 33 | -------------------------------------------------------------------------------- /docs/src/guide/genswagger.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 生成 swagger 文档 3 | icon: vscode-icons:file-type-swagger 4 | order: 5.1 5 | --- 6 | 7 | ::: code-tabs#shell 8 | 9 | @tab jzero 10 | 11 | ```bash 12 | cd your_project 13 | jzero gen swagger 14 | ``` 15 | 16 | @tab Docker 17 | ```bash 18 | cd your_project 19 | docker run --rm -v ${PWD}:/app ghcr.io/jzero-io/jzero:latest gen swagger 20 | ``` 21 | ::: 22 | 23 | ## 在线访问 swagger ui 24 | 25 | swagger ui 地址: **localhost:8001/swagger** 26 | 27 | ![](https://oss.jaronnie.com/image-20240731134511973.png) -------------------------------------------------------------------------------- /docs/src/guide/ivm.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 接口版本控制 3 | icon: hugeicons:api 4 | order: 6 5 | category: 开发 6 | tag: 7 | - Guide 8 | --- 9 | 10 | ## 说明 11 | 12 | 接口版本控制功能, 是用来管理服务端的接口版本, 目前仅支持 grpc 场景. 默认会创建 v1 版本, 对应 desc/proto/v1 文件夹中的 proto 13 | 14 | 可以通过 ivm 命令自动初始化 v2 版本的接口, 并默认调用 v1 接口逻辑, 这意味着你仅需一条命令, 就可以自动生成 v2 的接口, 后续对 v2 接口继续更改即可 15 | 16 | ```shell 17 | $ tree desc 18 | desc 19 | └── proto 20 | ├── v1 21 | │   └── hello.proto 22 | └── v2 23 | └── hello_v2.proto 24 | ``` 25 | 26 | ## 初始化新版本 27 | 28 | > 请依次进行变更, 如初始化 v3 版本时必须已有 v2 版本 29 | 30 | ```shell 31 | # 初始化 v2 版本 32 | jzero ivm init --version v2 33 | ``` 34 | 35 | ## 新增 proto 36 | 37 | 可基于该命令自动生成一个带版本的 proto example, 可以快速生成一个 proto 文件 38 | 39 | ```shell 40 | # 在 desc/proto/v2 文件夹新增一个 machine.proto, service 默认与 name 同名, 可以指定 services, 也可以指定 service methods 41 | jzero ivm add proto --name machine --version v2 42 | ``` 43 | 44 | ## 新增 api 45 | 46 | 可基于该命令自动生成 api example, 可以快速生成一个 api 文件 47 | 48 | ```shell 49 | # 在 desc/api 文件夹新增一个 machine.api 文件, 默认 group 为 machine, 可以使用 --group 进行指定 50 | jzero ivm add api --name machine 51 | ``` 52 | -------------------------------------------------------------------------------- /docs/src/guide/mcp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: mcp server 3 | icon: tabler:photo-ai 4 | order: 5.3 5 | category: 开发 6 | tag: 7 | - Guide 8 | --- 9 | 10 | ## 使用 mcp 11 | 12 | 使用 mcp client, 如 [deepchat](https://deepchat.thinkinai.xyz/) 13 | 14 | ![](http://oss.jaronnie.com/image-20250512113200546.png) 15 | 16 | ## 测试 jzero mcp 之底层协议 17 | 18 | ```shell 19 | $ jzero mcp test 20 | [INPUT] Enter your command (press Enter to send): 21 | {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{"roots":{"listChanged":true},"sampling":{}},"clientInfo":{"name":"ExampleClient","version":"1.0.0"}}} 22 | [SERVER OUTPUT] {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"logging":{},"resources":{"subscribe":true,"listChanged":true},"tools":{}},"serverInfo":{"name":"Used to create project by templates and generate server/client code by proto and api file.\n","version":"1.0.0"}}} 23 | [INPUT] Enter your command (press Enter to send): 24 | {"jsonrpc":"2.0","method":"notifications/initialized"} 25 | [INPUT] Enter your command (press Enter to send): 26 | {"jsonrpc":"2.0","id":2,"method":"tools/list"} 27 | ``` 28 | 29 | -------------------------------------------------------------------------------- /docs/src/guide/migrate.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 数据库迁移特性 3 | icon: carbon:migrate 4 | star: true 5 | order: 5.5 6 | category: 开发 7 | tag: 8 | - Guide 9 | --- 10 | 11 | * jzero 基于 [migrate](https://github.com/golang-migrate/migrate) 实现数据库迁移能力 12 | * jzero 默认检测 desc/sql_migration 目录下的文件, 执行迁移 13 | * 参考 [最佳实践](https://github.com/golang-migrate/migrate/blob/master/MIGRATIONS.md) 如何编写数据库迁移文件 14 | 15 | ## 配置 16 | 17 | ```yaml 18 | migrate: 19 | database: "mysql://root:123456@tcp(127.0.0.1:3306)/jzero" 20 | ``` 21 | 22 | ## 升级 23 | 24 | ```shell 25 | # 默认升级到最新 26 | jzero migrate up 27 | ``` 28 | 29 | ## 回滚 30 | 31 | ```shell 32 | # 默认仅回滚 1 个版本 33 | jzero migrate down 34 | ``` 35 | 36 | ## 获取版本 37 | 38 | ```shell 39 | jzero migrate version 40 | ``` 41 | 42 | ## 强制回滚到某个版本 43 | 44 | ```shell 45 | jzero migrate goto 46 | ``` -------------------------------------------------------------------------------- /docs/src/guide/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: jzero 概览 3 | icon: grommet-icons:overview 4 | order: 3 5 | --- 6 | 7 | ## 不同姿势使用 jzero 8 | 9 | :::important 涨知识的小技巧 10 | ::: 11 | 12 | * 支持通过配置文件 .jzero.yaml 控制各种参数(**强烈推荐在每个项目的根目录新建该文件**) 13 | * 支持通过 flag 控制各种参数 14 | * 支持通过环境变量控制各种参数 15 | * 支持通过以上组合的方式控制各种参数, 优先级从高到低为 环境变量 > flag > 配置文件 16 | 17 | 如: `jzero gen --style go_zero` 对应 .jzero.yaml 内容 18 | 19 | ```yaml 20 | gen: 21 | style: go_zero 22 | ``` 23 | 24 | 即 `jzero gen` + `.jzero.yaml` = `jzero gen --style go_zero` 25 | 26 | 对于环境变量的使用, 需要增加前缀 `JZERO_`, 如 `JZERO_GEN_STYLE` 27 | 28 | 即 `JZERO_GEN_STYLE=go_zero jzero gen` = `jzero gen --style go_zero` -------------------------------------------------------------------------------- /docs/src/guide/serverless.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: serverless 插件化特性 3 | icon: arcticons:game-plugins 4 | star: true 5 | order: 5.4 6 | category: 开发 7 | tag: 8 | - Guide 9 | --- 10 | 11 | jzero 支持插件化机制, 可以方便的进行插件的安装和卸载操作. 12 | 13 | ## 新增需要支持插件化机制的项目 14 | 15 | ```shell 16 | jzero new your_project --frame api --features serverless_core 17 | 18 | cd your_project 19 | jzero gen 20 | 21 | go mod tidy 22 | ``` 23 | 24 | ## 新增插件 25 | 26 | ```shell 27 | jzero new your_plugin --frame api --features serverless --output ./plugins/your_plugin 28 | cd ./plugins/your_plugin 29 | jzero gen 30 | 31 | go mod tidy 32 | 33 | # 回到根目录 34 | cd ... 35 | ``` 36 | 37 | ## 编译带有插件的项目 38 | 39 | ```shell 40 | jzero serverless build 41 | 42 | go build 43 | ``` 44 | 45 | ## 卸载插件 46 | 47 | ```shell 48 | # 卸载所有 49 | jzero serverless delete 50 | 51 | # 卸载指定插件 52 | jzero serverless delete --plugin 53 | 54 | # 重新编译 55 | go build 56 | ``` -------------------------------------------------------------------------------- /docs/src/guide/template.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 模版特性 3 | icon: vscode-icons:folder-type-template 4 | star: true 5 | order: 5.3 6 | category: 开发 7 | tag: 8 | - Guide 9 | --- 10 | 11 | ## 模版初始化 12 | 13 | 将jzero内嵌模版或者远程仓库的模版初始化到本地磁盘。 14 | 15 | ```shell 16 | # 初始化jzero内嵌模板到 $HOME/.jzero/templates/$Version 下, 可以修改模板后再进行新建项目 17 | jzero template init 18 | # 或者初始化模板到当前项目的 .template, jzero gen 默认会优先读取当前项目的 .template 作为模板 home 19 | jzero template init --output .template 20 | # 初始化远程仓库模板到 $HOME/.jzero/templates/remote 下, 如 gateway, 21 | jzero template init --branch gateway 22 | 23 | # 如果仍需要扩展 go-zero 的 template 24 | goctl template init --home .template/go-zero 25 | ``` 26 | 27 | ## 构建属于自己的模版 28 | 29 | ```shell 30 | # 将当前项目构建为模版,并保存到 $HOME/.jzero/templates/local 下 31 | jzero template build --name template_name 32 | ``` 33 | 34 | ## 使用模版创建项目 35 | 36 | 1. 使用远程模版 37 | 38 | :::tip 此指令将重新从远程拉去模版 39 | ::: 40 | 41 | - 使用默认仓库:`https://github.com/jzero-io/templates` 42 | 43 | ```shell 44 | jzero new project_name --branch template_branch 45 | ``` 46 | 47 | - 指定远程仓库 48 | 49 | ```shell 50 | jzero new project_name --remote repo_to_your_templates --branch template_branch 51 | ``` 52 | 53 | 2. 使用本地缓存的远程模版 54 | 55 | :::tip 本地缓存的模版在 `$HOME/.jzero/templates/remote` 下。 56 | ::: 57 | 58 | ```shell 59 | jzero new project_name --branch --cache template_branch 60 | ``` 61 | 62 | 3. 使用自构建模版 63 | 64 | ```shell 65 | jzero new project_name --local template_name 66 | ``` 67 | 68 | 4. 使用指定路径模版 69 | 70 | ```shell 71 | jzero new project_name --home path_to_template 72 | ``` 73 | -------------------------------------------------------------------------------- /docs/src/project/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 项目实战 3 | icon: mdi:arrow-projectile-multiple 4 | index: false 5 | dir: 6 | order: 9 7 | --- 8 | 9 | -------------------------------------------------------------------------------- /docs/src/project/api.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: api 项目实战 3 | icon: mdi:arrow-projectile-multiple 4 | star: true 5 | order: 1 6 | category: project 7 | tag: 8 | - Guide 9 | --- 10 | 11 | ## 1. 简介 12 | 13 | api 项目包含以下技术栈: 14 | * cobra: 提供命令行框架 15 | * api: 基于 go-zero api 框架提供 http 服务 16 | 17 | ## 2. 新建项目 18 | 19 | ```shell 20 | jzero new simpleapi --frame api 21 | cd simpleapi 22 | go mod tidy 23 | ``` 24 | 25 | ## 3. 生成 swagger 26 | 27 | ```shell 28 | jzero gen swagger 29 | ``` 30 | 31 | ## 4. 测试 32 | 33 | ```shell 34 | go run main.go server 35 | # 访问 localhost:8001/swagger 进行测试 36 | ``` 37 | 38 | 至此, 你已经拥有了一个可用的 api 服务. 39 | 40 | ## 5. 开发教程 41 | 42 | ### 5.1. 鉴权 43 | 44 | 在实际的项目中, 鉴权是必不可少的, 那么在 jzero 的 api 模板中, 如何进行鉴权呢? 45 | 46 | 例如增加了一个鉴权中间件 AuthMiddleware, 获取鉴权信息, 然后能在 logic 中使用 47 | 48 | ```go 49 | func(next http.HandlerFunc) http.HandlerFunc { 50 | return func(writer http.ResponseWriter, request *http.Request) { 51 | // 获取用户信息 52 | rctx := r.Context() 53 | rctx = context.WithValue(rctx, "auth", "xx") 54 | // 携带 auth 55 | next(w, r.WithContext(rctx)) 56 | } 57 | } 58 | ``` -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "NodeNext", 4 | "moduleResolution": "NodeNext", 5 | "target": "ES2022" 6 | }, 7 | "include": [ 8 | "src/.vuepress/**/*.ts", 9 | "src/.vuepress/**/*.vue" 10 | ], 11 | "exclude": [ 12 | "node_modules" 13 | ] 14 | } 15 | --------------------------------------------------------------------------------