@lovrabet/rabetbase-cli 2.3.16-beta.7 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -10
- package/lib/api/api-doc.js +1 -1
- package/lib/api/fetch-model-list.js +1 -1
- package/lib/api/generate-api-file.js +1 -1
- package/lib/auth/auth-server-ui.js +1 -1
- package/lib/auth/auth-server.js +1 -1
- package/lib/auth/constant.js +1 -1
- package/lib/auth/get-cookie.js +1 -1
- package/lib/auth/get-session-user.js +1 -1
- package/lib/auth/is-session-valid.js +1 -1
- package/lib/auth/login-success-html.js +1 -1
- package/lib/auth/logout.js +1 -1
- package/lib/cli-flags.js +1 -1
- package/lib/cli.js +1 -1
- package/lib/commands/api/generate.js +1 -1
- package/lib/commands/api/index.js +1 -1
- package/lib/commands/api/list.js +1 -1
- package/lib/commands/api/pull.js +1 -1
- package/lib/commands/api/shared.js +1 -1
- package/lib/commands/app/index.js +1 -1
- package/lib/commands/app/list.js +1 -1
- package/lib/commands/app/members-list.js +1 -1
- package/lib/commands/app/remote-directory.js +1 -1
- package/lib/commands/app/shared.js +1 -1
- package/lib/commands/app-config/delete.js +1 -1
- package/lib/commands/app-config/get.js +1 -1
- package/lib/commands/app-config/index.js +1 -1
- package/lib/commands/app-config/list.js +1 -1
- package/lib/commands/app-config/set.js +1 -1
- package/lib/commands/app-config/shared.js +1 -1
- package/lib/commands/auth/index.js +1 -1
- package/lib/commands/bff/create.js +1 -1
- package/lib/commands/bff/delete.js +1 -1
- package/lib/commands/bff/detail.js +1 -1
- package/lib/commands/bff/index.js +1 -1
- package/lib/commands/bff/list.js +1 -1
- package/lib/commands/bff/pull.js +1 -1
- package/lib/commands/bff/push.js +1 -1
- package/lib/commands/bff/status.js +1 -1
- package/lib/commands/cli-skill/index.js +1 -1
- package/lib/commands/cli-update.js +1 -1
- package/lib/commands/codegen/index.js +1 -1
- package/lib/commands/codegen/sdk.js +1 -1
- package/lib/commands/codegen/sql.js +1 -1
- package/lib/commands/common/app-registry.js +1 -1
- package/lib/commands/common/app-selector.js +1 -1
- package/lib/commands/common/async-task.js +1 -1
- package/lib/commands/common/dry-run.js +1 -1
- package/lib/commands/common/flags.js +1 -1
- package/lib/commands/common/local-file.js +1 -1
- package/lib/commands/common/validate.js +1 -1
- package/lib/commands/config/get.js +1 -1
- package/lib/commands/config/index.js +1 -1
- package/lib/commands/config/list.js +1 -1
- package/lib/commands/config/set.js +1 -1
- package/lib/commands/config/shared.js +1 -1
- package/lib/commands/data/filter.js +1 -1
- package/lib/commands/data/getOne.js +1 -1
- package/lib/commands/data/index.js +1 -1
- package/lib/commands/data/shared.js +1 -1
- package/lib/commands/dataset/business-group-update.js +1 -1
- package/lib/commands/dataset/capability.js +1 -1
- package/lib/commands/dataset/delete.js +1 -1
- package/lib/commands/dataset/detail.js +1 -1
- package/lib/commands/dataset/extend-update.js +1 -1
- package/lib/commands/dataset/field-update.js +1 -1
- package/lib/commands/dataset/generate.js +1 -1
- package/lib/commands/dataset/index.js +1 -1
- package/lib/commands/dataset/list.js +1 -1
- package/lib/commands/dataset/operations.js +1 -1
- package/lib/commands/dataset/relation-audit.js +1 -1
- package/lib/commands/dataset/relation-create.js +1 -1
- package/lib/commands/dataset/relation-delete.js +1 -1
- package/lib/commands/dataset/relation-shared.js +1 -1
- package/lib/commands/dataset/relation-update.js +1 -1
- package/lib/commands/dataset/relations.js +1 -1
- package/lib/commands/dataset/rename.js +1 -1
- package/lib/commands/dataset/restore.js +1 -1
- package/lib/commands/db/analysis-batching.js +1 -1
- package/lib/commands/db/analyze-batch-plan.js +1 -1
- package/lib/commands/db/analyze-cancel.js +1 -1
- package/lib/commands/db/analyze-start.js +1 -1
- package/lib/commands/db/analyze-status.js +1 -1
- package/lib/commands/db/create.js +1 -1
- package/lib/commands/db/delete.js +1 -1
- package/lib/commands/db/detail.js +1 -1
- package/lib/commands/db/diff.js +1 -1
- package/lib/commands/db/index.js +1 -1
- package/lib/commands/db/list.js +1 -1
- package/lib/commands/db/shared.js +1 -1
- package/lib/commands/db/tables.js +1 -1
- package/lib/commands/db/test.js +1 -1
- package/lib/commands/db/update.js +1 -1
- package/lib/commands/doctor.js +1 -1
- package/lib/commands/file/index.js +1 -1
- package/lib/commands/init/index.js +1 -1
- package/lib/commands/issue/index.js +1 -1
- package/lib/commands/issue/nudge.js +1 -1
- package/lib/commands/issue/report.js +1 -1
- package/lib/commands/issue/shared.js +1 -1
- package/lib/commands/kb/create.js +1 -1
- package/lib/commands/kb/delete.js +1 -1
- package/lib/commands/kb/detail.js +1 -1
- package/lib/commands/kb/index.js +1 -1
- package/lib/commands/kb/list.js +1 -1
- package/lib/commands/kb/shared.js +1 -1
- package/lib/commands/kb/update.js +1 -1
- package/lib/commands/logs/index.js +1 -1
- package/lib/commands/menu/asset-update.js +1 -1
- package/lib/commands/menu/delete.js +1 -1
- package/lib/commands/menu/external-link-create.js +1 -1
- package/lib/commands/menu/external-link-update.js +1 -1
- package/lib/commands/menu/group-create.js +1 -1
- package/lib/commands/menu/group-update.js +1 -1
- package/lib/commands/menu/index.js +1 -1
- package/lib/commands/menu/list.js +1 -1
- package/lib/commands/menu/move.js +1 -1
- package/lib/commands/menu/regroup-start.js +1 -1
- package/lib/commands/menu/rename.js +1 -1
- package/lib/commands/menu/shared/compare-table.js +1 -1
- package/lib/commands/menu/shared/delete-plan.js +1 -1
- package/lib/commands/menu/shared/facts.js +1 -1
- package/lib/commands/menu/shared/index.js +1 -1
- package/lib/commands/menu/shared/inquirer.js +1 -1
- package/lib/commands/menu/shared/local-pages.js +1 -1
- package/lib/commands/menu/shared/logic.js +1 -1
- package/lib/commands/menu/shared/mutations.js +1 -1
- package/lib/commands/menu/shared/service.js +1 -1
- package/lib/commands/menu/shared/sync-core.js +1 -1
- package/lib/commands/menu/shared/update-core.js +1 -1
- package/lib/commands/menu/shared/valid-url.js +1 -1
- package/lib/commands/menu/sync.js +1 -1
- package/lib/commands/notification/config-list.js +1 -1
- package/lib/commands/notification/index.js +1 -1
- package/lib/commands/ocr/index.js +1 -1
- package/lib/commands/page/generate-start.js +1 -1
- package/lib/commands/page/generate-status.js +1 -1
- package/lib/commands/page/index.js +1 -1
- package/lib/commands/page/pull.js +1 -1
- package/lib/commands/page/push.js +1 -1
- package/lib/commands/page/react/create.d.ts +2 -0
- package/lib/commands/page/react/create.js +1 -0
- package/lib/commands/page/react/detail.d.ts +2 -0
- package/lib/commands/page/react/detail.js +1 -0
- package/lib/commands/page/react/list.d.ts +2 -0
- package/lib/commands/page/react/list.js +1 -0
- package/lib/commands/page/react/publish.d.ts +2 -0
- package/lib/commands/page/react/publish.js +1 -0
- package/lib/commands/page/react/shared.d.ts +78 -0
- package/lib/commands/page/react/shared.js +1 -0
- package/lib/commands/page/react/syntax.d.ts +18 -0
- package/lib/commands/page/react/syntax.js +1 -0
- package/lib/commands/page/react/template.d.ts +8 -0
- package/lib/commands/page/react/template.js +1 -0
- package/lib/commands/page/react/update.d.ts +2 -0
- package/lib/commands/page/react/update.js +1 -0
- package/lib/commands/page/relation-audit.js +1 -1
- package/lib/commands/page/restore.js +1 -1
- package/lib/commands/page/shared.d.ts +1 -0
- package/lib/commands/page/shared.js +1 -1
- package/lib/commands/page/standard-page-status.js +1 -1
- package/lib/commands/page/sync.js +1 -1
- package/lib/commands/permit/index.js +1 -1
- package/lib/commands/permit/page-get.js +1 -1
- package/lib/commands/permit/page-set.js +1 -1
- package/lib/commands/permit/role-apis-set.js +1 -1
- package/lib/commands/permit/role-menus-set.js +1 -1
- package/lib/commands/permit/role-menus.js +1 -1
- package/lib/commands/permit/shared.js +1 -1
- package/lib/commands/project/create/enhanced-guided-create.js +1 -1
- package/lib/commands/project/create/format-elapsed.js +1 -1
- package/lib/commands/project/create/main.js +1 -1
- package/lib/commands/project/create/non-interactive.js +1 -1
- package/lib/commands/project/create/project-template-path.js +1 -1
- package/lib/commands/project/create/use-copy-project-template.js +1 -1
- package/lib/commands/project/create/use-format-code.js +1 -1
- package/lib/commands/project/create/use-install-dependencies.js +1 -1
- package/lib/commands/project/index.js +1 -1
- package/lib/commands/project/upgrade.js +1 -1
- package/lib/commands/registry.js +1 -1
- package/lib/commands/role/create.js +1 -1
- package/lib/commands/role/delete.js +1 -1
- package/lib/commands/role/detail.js +1 -1
- package/lib/commands/role/index.js +1 -1
- package/lib/commands/role/list.js +1 -1
- package/lib/commands/role/shared.js +1 -1
- package/lib/commands/role/update.js +1 -1
- package/lib/commands/role/user-add.js +1 -1
- package/lib/commands/role/user-remove.js +1 -1
- package/lib/commands/role/user-resolve.js +1 -1
- package/lib/commands/run/index.js +1 -1
- package/lib/commands/schema.js +1 -1
- package/lib/commands/sql/create.js +1 -1
- package/lib/commands/sql/delete.js +1 -1
- package/lib/commands/sql/detail.js +1 -1
- package/lib/commands/sql/exec.js +1 -1
- package/lib/commands/sql/index.js +1 -1
- package/lib/commands/sql/list.js +1 -1
- package/lib/commands/sql/pull.js +1 -1
- package/lib/commands/sql/push.js +1 -1
- package/lib/commands/sql/shared.js +1 -1
- package/lib/commands/sql/status.js +1 -1
- package/lib/commands/sql/validate.js +1 -1
- package/lib/commands/task/index.js +1 -1
- package/lib/commands/task/status.js +1 -1
- package/lib/commands/tenant/index.js +1 -1
- package/lib/commands/tenant/members-list.js +1 -1
- package/lib/commands/tenant/shared.js +1 -1
- package/lib/commands/user-account/dingding-sandbox-bind.d.ts +2 -0
- package/lib/commands/user-account/dingding-sandbox-bind.js +1 -0
- package/lib/commands/user-account/index.d.ts +2 -0
- package/lib/commands/user-account/index.js +1 -0
- package/lib/commands/workspace/add.js +1 -1
- package/lib/commands/workspace/index.js +1 -1
- package/lib/commands/workspace/remove.js +1 -1
- package/lib/config/schema.js +1 -1
- package/lib/constant/cdn.js +1 -1
- package/lib/constant/cli.js +1 -1
- package/lib/constant/defaults.js +1 -1
- package/lib/constant/domain.js +1 -1
- package/lib/constant/env.js +1 -1
- package/lib/constant/output.js +1 -1
- package/lib/constant/paths.js +1 -1
- package/lib/constant/risk.js +1 -1
- package/lib/context/app-resolver.js +1 -1
- package/lib/context/auth-resolver.js +1 -1
- package/lib/context/config-loader.js +1 -1
- package/lib/context.js +1 -1
- package/lib/core/alias-resolver.js +1 -1
- package/lib/core/api-client.d.ts +117 -0
- package/lib/core/api-client.js +1 -1
- package/lib/core/bff/config.js +1 -1
- package/lib/core/bff/file-system.js +1 -1
- package/lib/core/bff/hash.js +1 -1
- package/lib/core/bff/lock.js +1 -1
- package/lib/core/bff/utils.js +1 -1
- package/lib/core/db-resolver.js +1 -1
- package/lib/core/page/file-system.js +1 -1
- package/lib/core/page/hash.js +1 -1
- package/lib/core/page/lock.js +1 -1
- package/lib/core/sql-index-auditor.js +1 -1
- package/lib/core/sql-sync/config.js +1 -1
- package/lib/core/sql-sync/file-system.js +1 -1
- package/lib/core/sql-sync/hash.js +1 -1
- package/lib/core/sql-sync/lock.js +1 -1
- package/lib/core/sql-sync/utils.js +1 -1
- package/lib/core/sql-validator.js +1 -1
- package/lib/errors.js +1 -1
- package/lib/framework/build-all-flags.js +1 -1
- package/lib/framework/error-output.js +1 -1
- package/lib/framework/explicit-yes.js +1 -1
- package/lib/framework/flags.js +1 -1
- package/lib/framework/help.js +1 -1
- package/lib/framework/index.js +1 -1
- package/lib/framework/output.js +1 -1
- package/lib/framework/response.js +1 -1
- package/lib/framework/runner-alias.js +1 -1
- package/lib/framework/runner.js +1 -1
- package/lib/framework/schema-export.js +1 -1
- package/lib/framework/types.js +1 -1
- package/lib/generated/build-info.d.ts +4 -4
- package/lib/generated/build-info.js +1 -1
- package/lib/help.js +1 -1
- package/lib/postinstall.d.ts +3 -0
- package/lib/postinstall.js +1 -0
- package/lib/runtime/confirmation.js +1 -1
- package/lib/runtime/event.js +1 -1
- package/lib/runtime/index.js +1 -1
- package/lib/runtime/queue.js +1 -1
- package/lib/runtime/resolve.js +1 -1
- package/lib/skills/builtin-skill.d.ts +37 -0
- package/lib/skills/builtin-skill.js +1 -0
- package/lib/skills/main.js +1 -1
- package/lib/skills/npx-skills-add.d.ts +4 -2
- package/lib/skills/npx-skills-add.js +1 -1
- package/lib/skills/skill-presence.js +1 -1
- package/lib/telemetry/cli-command-trace.js +1 -1
- package/lib/telemetry/cli-help-trace.js +1 -1
- package/lib/telemetry/ensure-cli-otel-config.js +1 -1
- package/lib/telemetry/register-otel-exit-shutdown.js +1 -1
- package/lib/telemetry/send-cli-trace-log.js +1 -1
- package/lib/telemetry/send-platform-issue-collect-log.js +1 -1
- package/lib/utils/ai_config.js +1 -1
- package/lib/utils/apply-jq-filter.js +1 -1
- package/lib/utils/cdn-config.js +1 -1
- package/lib/utils/check-sdk-version.js +1 -1
- package/lib/utils/cli-version-check.js +1 -1
- package/lib/utils/cli-version-policy.js +1 -1
- package/lib/utils/config.js +1 -1
- package/lib/utils/copy-directory.js +1 -1
- package/lib/utils/entity-with-id.js +1 -1
- package/lib/utils/file-utils.js +1 -1
- package/lib/utils/guides-cdn.js +1 -1
- package/lib/utils/http-client.js +1 -1
- package/lib/utils/is-non-interactive.js +1 -1
- package/lib/utils/logger.js +1 -1
- package/lib/utils/params.js +1 -1
- package/lib/utils/platform.js +1 -1
- package/lib/utils/rules-cdn.js +1 -1
- package/lib/utils/sleep.js +1 -1
- package/lib/utils/template-replacer.js +1 -1
- package/lib/utils/update-notice.js +1 -1
- package/lib/utils/version.js +1 -1
- package/lib/utils/with-active-cookie.js +1 -1
- package/lib/utils/write-cli-side-channel.js +1 -1
- package/package.json +9 -3
- package/scripts/postinstall.mjs +24 -0
- package/skills/rabetbase/SKILL.md +493 -0
- package/skills/rabetbase/guides/backend-function.md +835 -0
- package/skills/rabetbase/guides/best-practices.md +137 -0
- package/skills/rabetbase/guides/bff-creation-workflow.md +148 -0
- package/skills/rabetbase/guides/conflict-detection.md +119 -0
- package/skills/rabetbase/guides/data-api-guidelines.md +414 -0
- package/skills/rabetbase/guides/database-connection-workflow.md +169 -0
- package/skills/rabetbase/guides/frontend-development.md +179 -0
- package/skills/rabetbase/guides/legacy-application-blueprint-workflow.md +495 -0
- package/skills/rabetbase/guides/menu-anomaly-manual-cleanup.md +137 -0
- package/skills/rabetbase/guides/page-development-workflow.md +187 -0
- package/skills/rabetbase/guides/react-custom-page-workflow.md +184 -0
- package/skills/rabetbase/guides/role-permit-workflow.md +127 -0
- package/skills/rabetbase/guides/sql-creation-workflow.md +173 -0
- package/skills/rabetbase/guides/sql-mybatis.md +126 -0
- package/skills/rabetbase/guides/troubleshooting.md +67 -0
- package/skills/rabetbase/guides/typescript-sdk.md +227 -0
- package/skills/rabetbase/knowledge/page-schema/LrSmartCreate.md +367 -0
- package/skills/rabetbase/knowledge/page-schema/LrSmartDetail.md +153 -0
- package/skills/rabetbase/knowledge/page-schema/LrSmartEcharts.md +291 -0
- package/skills/rabetbase/knowledge/page-schema/LrSmartFilter.md +478 -0
- package/skills/rabetbase/knowledge/page-schema/LrSmartJsx.md +119 -0
- package/skills/rabetbase/knowledge/page-schema/LrSmartStatistic.md +223 -0
- package/skills/rabetbase/knowledge/page-schema/LrSmartTable.md +632 -0
- package/skills/rabetbase/knowledge/page-schema/YtPage.md +172 -0
- package/skills/rabetbase/knowledge/page-schema/dataset-relations.md +126 -0
- package/skills/rabetbase/knowledge/page-schema/external-resources-usage.md +232 -0
- package/skills/rabetbase/knowledge/page-schema/field-components.md +312 -0
- package/skills/rabetbase/knowledge/page-schema/syntax-reference.md +278 -0
- package/skills/rabetbase/knowledge/react-page/components.md +225 -0
- package/skills/rabetbase/knowledge/react-page/generation-standards.md +385 -0
- package/skills/rabetbase/references/rabetbase-api-list.md +58 -0
- package/skills/rabetbase/references/rabetbase-api-pull.md +82 -0
- package/skills/rabetbase/references/rabetbase-app-config.md +95 -0
- package/skills/rabetbase/references/rabetbase-app-list.md +79 -0
- package/skills/rabetbase/references/rabetbase-app-members-list.md +64 -0
- package/skills/rabetbase/references/rabetbase-auth-login.md +53 -0
- package/skills/rabetbase/references/rabetbase-auth-logout.md +29 -0
- package/skills/rabetbase/references/rabetbase-bff-create.md +59 -0
- package/skills/rabetbase/references/rabetbase-bff-delete.md +42 -0
- package/skills/rabetbase/references/rabetbase-bff-detail.md +38 -0
- package/skills/rabetbase/references/rabetbase-bff-list.md +61 -0
- package/skills/rabetbase/references/rabetbase-bff-pull.md +42 -0
- package/skills/rabetbase/references/rabetbase-bff-push.md +65 -0
- package/skills/rabetbase/references/rabetbase-bff-save.md +63 -0
- package/skills/rabetbase/references/rabetbase-bff-status.md +37 -0
- package/skills/rabetbase/references/rabetbase-cli-skill-install.md +42 -0
- package/skills/rabetbase/references/rabetbase-codegen-sdk.md +35 -0
- package/skills/rabetbase/references/rabetbase-codegen-sql.md +33 -0
- package/skills/rabetbase/references/rabetbase-config.md +296 -0
- package/skills/rabetbase/references/rabetbase-dataset-business-group-update.md +84 -0
- package/skills/rabetbase/references/rabetbase-dataset-delete.md +54 -0
- package/skills/rabetbase/references/rabetbase-dataset-detail.md +106 -0
- package/skills/rabetbase/references/rabetbase-dataset-extend-update.md +70 -0
- package/skills/rabetbase/references/rabetbase-dataset-field-update.md +117 -0
- package/skills/rabetbase/references/rabetbase-dataset-generate.md +206 -0
- package/skills/rabetbase/references/rabetbase-dataset-list.md +42 -0
- package/skills/rabetbase/references/rabetbase-dataset-operations.md +34 -0
- package/skills/rabetbase/references/rabetbase-dataset-relation-audit.md +63 -0
- package/skills/rabetbase/references/rabetbase-dataset-relation-mutations.md +141 -0
- package/skills/rabetbase/references/rabetbase-dataset-relations.md +71 -0
- package/skills/rabetbase/references/rabetbase-dataset-rename.md +107 -0
- package/skills/rabetbase/references/rabetbase-dataset-restore.md +54 -0
- package/skills/rabetbase/references/rabetbase-db-analyze.md +135 -0
- package/skills/rabetbase/references/rabetbase-db-create.md +54 -0
- package/skills/rabetbase/references/rabetbase-db-delete.md +26 -0
- package/skills/rabetbase/references/rabetbase-db-detail.md +27 -0
- package/skills/rabetbase/references/rabetbase-db-diff.md +57 -0
- package/skills/rabetbase/references/rabetbase-db-list.md +37 -0
- package/skills/rabetbase/references/rabetbase-db-tables.md +25 -0
- package/skills/rabetbase/references/rabetbase-db-test.md +29 -0
- package/skills/rabetbase/references/rabetbase-db-update.md +29 -0
- package/skills/rabetbase/references/rabetbase-doctor.md +62 -0
- package/skills/rabetbase/references/rabetbase-file.md +35 -0
- package/skills/rabetbase/references/rabetbase-init.md +70 -0
- package/skills/rabetbase/references/rabetbase-issue-report.md +132 -0
- package/skills/rabetbase/references/rabetbase-kb.md +62 -0
- package/skills/rabetbase/references/rabetbase-menu-asset-update.md +135 -0
- package/skills/rabetbase/references/rabetbase-menu-delete.md +54 -0
- package/skills/rabetbase/references/rabetbase-menu-external-link-create.md +63 -0
- package/skills/rabetbase/references/rabetbase-menu-external-link-update.md +74 -0
- package/skills/rabetbase/references/rabetbase-menu-group-create.md +33 -0
- package/skills/rabetbase/references/rabetbase-menu-group-update.md +38 -0
- package/skills/rabetbase/references/rabetbase-menu-list.md +144 -0
- package/skills/rabetbase/references/rabetbase-menu-move.md +54 -0
- package/skills/rabetbase/references/rabetbase-menu-regroup-start.md +45 -0
- package/skills/rabetbase/references/rabetbase-menu-rename.md +48 -0
- package/skills/rabetbase/references/rabetbase-menu-sync.md +60 -0
- package/skills/rabetbase/references/rabetbase-notification-config-list.md +80 -0
- package/skills/rabetbase/references/rabetbase-ocr.md +86 -0
- package/skills/rabetbase/references/rabetbase-page-generate-start.md +32 -0
- package/skills/rabetbase/references/rabetbase-page-generate-status.md +32 -0
- package/skills/rabetbase/references/rabetbase-page-pull.md +47 -0
- package/skills/rabetbase/references/rabetbase-page-push.md +45 -0
- package/skills/rabetbase/references/rabetbase-page-react-create.md +29 -0
- package/skills/rabetbase/references/rabetbase-page-react-detail.md +26 -0
- package/skills/rabetbase/references/rabetbase-page-react-list.md +23 -0
- package/skills/rabetbase/references/rabetbase-page-react-publish.md +23 -0
- package/skills/rabetbase/references/rabetbase-page-react-update.md +24 -0
- package/skills/rabetbase/references/rabetbase-page-relation-binding.md +72 -0
- package/skills/rabetbase/references/rabetbase-page-restore.md +45 -0
- package/skills/rabetbase/references/rabetbase-page-sync.md +36 -0
- package/skills/rabetbase/references/rabetbase-permit-page-set.md +69 -0
- package/skills/rabetbase/references/rabetbase-permit-role-apis-set.md +53 -0
- package/skills/rabetbase/references/rabetbase-permit-role-menus-set.md +57 -0
- package/skills/rabetbase/references/rabetbase-project-create.md +46 -0
- package/skills/rabetbase/references/rabetbase-project-upgrade.md +57 -0
- package/skills/rabetbase/references/rabetbase-role-list.md +68 -0
- package/skills/rabetbase/references/rabetbase-role-user-add.md +54 -0
- package/skills/rabetbase/references/rabetbase-role-user-resolve.md +27 -0
- package/skills/rabetbase/references/rabetbase-run.md +53 -0
- package/skills/rabetbase/references/rabetbase-schema.md +22 -0
- package/skills/rabetbase/references/rabetbase-sql-create.md +41 -0
- package/skills/rabetbase/references/rabetbase-sql-delete.md +37 -0
- package/skills/rabetbase/references/rabetbase-sql-detail.md +32 -0
- package/skills/rabetbase/references/rabetbase-sql-exec.md +34 -0
- package/skills/rabetbase/references/rabetbase-sql-list.md +54 -0
- package/skills/rabetbase/references/rabetbase-sql-pull.md +54 -0
- package/skills/rabetbase/references/rabetbase-sql-push.md +46 -0
- package/skills/rabetbase/references/rabetbase-sql-status.md +39 -0
- package/skills/rabetbase/references/rabetbase-sql-validate.md +73 -0
- package/skills/rabetbase/references/rabetbase-standard-page-status.md +31 -0
- package/skills/rabetbase/references/rabetbase-task-status.md +40 -0
- package/skills/rabetbase/references/rabetbase-tenant-members-list.md +69 -0
- package/skills/rabetbase/references/rabetbase-update.md +56 -0
- package/skills/rabetbase/references/rabetbase-user-account.md +45 -0
- package/skills/rabetbase/references/rabetbase-workspace.md +60 -0
- package/skills/rabetbase.manifest.json +137 -0
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
# Backend Function 脚本编写规范
|
|
2
|
+
|
|
3
|
+
> 目标:约束 AI 在 Lovrabet 项目中编写 Backend Function 时的行为,避免凭空编造字段、误用 SDK 返回值、写出不可维护或高风险的脚本。
|
|
4
|
+
>
|
|
5
|
+
> 前置阅读:`data-api-guidelines.md`
|
|
6
|
+
|
|
7
|
+
## 阅读指南(按需跳转)
|
|
8
|
+
|
|
9
|
+
| 需求 | 位置 |
|
|
10
|
+
|------|------|
|
|
11
|
+
| CLI 信封、`datasetId`、`dbtableConfig` ↔ `data.dbtable`、OpenAPI 对照 | [`references/rabetbase-dataset-detail.md`](../references/rabetbase-dataset-detail.md) |
|
|
12
|
+
| 前后端数据访问、外键、性能 | [`data-api-guidelines.md`](data-api-guidelines.md) |
|
|
13
|
+
| 在 BFF 中发送应用级消息通知 | 下文“消息通知扩展” |
|
|
14
|
+
| HOOK/ENDPOINT 目录、注释模板、`context.client`、事务 | 下文 |
|
|
15
|
+
|
|
16
|
+
## 何时使用
|
|
17
|
+
|
|
18
|
+
当任务满足任一条件时,必须阅读并遵守本指南:
|
|
19
|
+
|
|
20
|
+
* 编写 HOOK 脚本
|
|
21
|
+
* 编写 ENDPOINT 脚本
|
|
22
|
+
* 在 BFF 中调用数据集 API
|
|
23
|
+
* 在 BFF 中调用自定义 SQL
|
|
24
|
+
* 在 BFF 中调用应用级消息通知
|
|
25
|
+
* 在 BFF 中处理事务、权限、脱敏、聚合或多表逻辑
|
|
26
|
+
|
|
27
|
+
## 核心原则
|
|
28
|
+
|
|
29
|
+
* 先校验数据集和字段,再写脚本
|
|
30
|
+
* 所有脚本统一使用 `export default async function`
|
|
31
|
+
* 前后端单条查询统一使用 `getOne({ id })`
|
|
32
|
+
* BFF 中的 SQL 返回值与前端 SDK 不同,不能混用
|
|
33
|
+
* 消息通知只引用当前应用中存在且未删除的 `configCode`,不接收 `appCode`、渠道地址或密钥
|
|
34
|
+
* 平台自动维护字段不得手动设置
|
|
35
|
+
* 发现明显性能问题时,必须先改写再继续
|
|
36
|
+
* 新建与长期维护的 BFF 源文件**仅**在 **`.rabetbase/bff/<appCode>/...`**(`bff create` / `bff pull` 与 `bff status` 扫描范围);不要写在 `src/` 等目录,详见 [`bff-creation-workflow.md`](bff-creation-workflow.md)
|
|
37
|
+
* BFF 脚本只写**纯 JavaScript(ESM)**,支持到 **ES2023** 特性,不支持 TypeScript
|
|
38
|
+
|
|
39
|
+
## 脚本类型
|
|
40
|
+
|
|
41
|
+
| 类型 | 作用 | 路径 / 触发方式 | 查询方式 |
|
|
42
|
+
|------|------|----------------|----------|
|
|
43
|
+
| HOOK | 挂在标准数据接口前后执行 | Before / After | 通过数据集详情 |
|
|
44
|
+
| ENDPOINT | 独立业务端点 | `POST /api/endpoint/{appCode}/{scriptName}` | `rabetbase bff list --format json`(默认) |
|
|
45
|
+
| COMMON | 公共函数,供其他脚本 import 复用 | 被其他 BFF 引用 | `rabetbase bff list --format json`(type=COMMON) |
|
|
46
|
+
|
|
47
|
+
写 BFF 前,先查一下公共函数列表(`rabetbase bff list --format json`),看是否有可复用的工具函数。
|
|
48
|
+
|
|
49
|
+
## 平台配置地址
|
|
50
|
+
|
|
51
|
+
| 类型 | 地址 |
|
|
52
|
+
|------|------|
|
|
53
|
+
| HOOK | `https://app.lovrabet.com/app/{appCode}/data/dataset/{datasetId}#api-list` |
|
|
54
|
+
| ENDPOINT | `https://app.lovrabet.com/app/{appCode}/data/backend-function` |
|
|
55
|
+
|
|
56
|
+
其中 `datasetId` 需要通过 `rabetbase dataset detail --code xxx --format json` 获取。
|
|
57
|
+
|
|
58
|
+
**平台 URL / OpenAPI `get-driven-data` 与 CLI `data` 的字段对应**(含 `datasetId`、`dbtable`):见 [`references/rabetbase-dataset-detail.md`](../references/rabetbase-dataset-detail.md)。
|
|
59
|
+
|
|
60
|
+
## 本地目录约定
|
|
61
|
+
|
|
62
|
+
BFF 脚本统一存放在 `.rabetbase/bff/<appCode>/` 目录下,由 CLI 同步体系管理:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
.rabetbase/bff/<appCode>/
|
|
66
|
+
├── HOOK/
|
|
67
|
+
│ └── <alias>/
|
|
68
|
+
│ └── <operationType>/
|
|
69
|
+
│ └── <functionNode>/
|
|
70
|
+
│ └── <name>.js
|
|
71
|
+
├── ENDPOINT/
|
|
72
|
+
│ └── <scriptName>.js
|
|
73
|
+
└── COMMON/
|
|
74
|
+
└── <scriptName>.js
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
规则:
|
|
78
|
+
|
|
79
|
+
* HOOK 放在 `.rabetbase/bff/<appCode>/HOOK/<alias>/<operationType>/<functionNode>/`
|
|
80
|
+
* ENDPOINT 放在 `.rabetbase/bff/<appCode>/ENDPOINT/`
|
|
81
|
+
* COMMON 放在 `.rabetbase/bff/<appCode>/COMMON/`
|
|
82
|
+
* 本地文件是可选的人类辅助物,平台是唯一 source of truth
|
|
83
|
+
|
|
84
|
+
### HOOK 目录名优先级
|
|
85
|
+
|
|
86
|
+
HOOK 的第一层子目录名(标识数据集)按以下优先级确定:
|
|
87
|
+
|
|
88
|
+
1. **alias**(优先):来自 `api.ts`(由 `rabetbase api pull` 生成)
|
|
89
|
+
2. **datasetCode**(兜底):当 `api.ts` 不可用时,直接使用 32 位数据集编码
|
|
90
|
+
|
|
91
|
+
推荐始终先执行 `rabetbase api pull` 以获得可读性更好的 alias 命名。
|
|
92
|
+
|
|
93
|
+
## 文件命名与函数命名
|
|
94
|
+
|
|
95
|
+
| 类型 | 文件名 | 导出函数 |
|
|
96
|
+
|------|--------|---------|
|
|
97
|
+
| HOOK Before | `<name>.js`(位于 `HOOK/<alias>/<operationType>/before/`) | `<name>` |
|
|
98
|
+
| HOOK After | `<name>.js`(位于 `HOOK/<alias>/<operationType>/after/`) | `<name>` |
|
|
99
|
+
| ENDPOINT | `<scriptName>.js`(位于 `ENDPOINT/`) | `<scriptName>` |
|
|
100
|
+
| COMMON | `<scriptName>.js`(位于 `COMMON/`) | `<scriptName>` |
|
|
101
|
+
|
|
102
|
+
常见 `Operation`:
|
|
103
|
+
|
|
104
|
+
* `filter`
|
|
105
|
+
* `getOne`
|
|
106
|
+
* `create`
|
|
107
|
+
* `update`
|
|
108
|
+
* `delete`
|
|
109
|
+
* `aggregate`(仅在数据集 operation 实际返回时使用;METADATA 默认不会提供)
|
|
110
|
+
|
|
111
|
+
使用 `aggregate` 时,聚合列名写在 `aggregate[].column`;`field` 只是历史兼容别名,新脚本不要使用。
|
|
112
|
+
|
|
113
|
+
BFF HOOK 可以挂在 `DB_TABLE` 或 `METADATA` 数据集上;是否可挂某个 operation,以平台返回的 operation types 为准。
|
|
114
|
+
|
|
115
|
+
### METADATA HOOK 脚本内部限制
|
|
116
|
+
|
|
117
|
+
METADATA 数据集没有 DB_TABLE 数据源上下文,脚本中优先使用标准 SDK 操作,例如 `filter`、`getOne`、`create`、`batchCreate`、`update`、`delete`。
|
|
118
|
+
|
|
119
|
+
不要在这类脚本中使用:
|
|
120
|
+
|
|
121
|
+
* `context.client.customSql()` 或其他自定义 SQL 路径
|
|
122
|
+
* aggregate 聚合接口
|
|
123
|
+
* 直接拼接和执行 SQL
|
|
124
|
+
|
|
125
|
+
如果需要复杂查询,优先组合 `filter` 的查询能力;无法满足时,考虑把数据源建模为 `DB_TABLE`,或在脚本中调用其他 `DB_TABLE` 数据集。
|
|
126
|
+
|
|
127
|
+
## 强制工作流
|
|
128
|
+
|
|
129
|
+
```text
|
|
130
|
+
理解需求 -> 校验数据集与字段 -> 选择脚本类型 -> 生成本地脚本 -> 自检 -> status -> dry-run -> push/pull
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Step 1:理解需求
|
|
134
|
+
|
|
135
|
+
开始写脚本前,AI 必须确认:
|
|
136
|
+
|
|
137
|
+
* 这是 HOOK 还是 ENDPOINT
|
|
138
|
+
* 作用于哪个数据集或接口
|
|
139
|
+
* 输入参数是什么
|
|
140
|
+
* 返回结构是什么
|
|
141
|
+
* 是否涉及权限、脱敏、事务、外部依赖或消息通知副作用
|
|
142
|
+
|
|
143
|
+
### Step 2:校验数据集、字段与关系
|
|
144
|
+
|
|
145
|
+
BFF 涉及数据集读写时,必须执行 `rabetbase dataset detail --code xxx --format json`(或 `--format compress`),必要时先用 `rabetbase dataset list --format json` 定位数据集。纯消息通知 ENDPOINT 不需要为满足流程而虚构 `datasetCode`,但必须先确认当前应用、通知 `configCode`、接收对象和消息内容契约。
|
|
146
|
+
|
|
147
|
+
必须确认:
|
|
148
|
+
|
|
149
|
+
* 字段真实存在
|
|
150
|
+
* 字段类型正确
|
|
151
|
+
* 必填字段已识别:以 `data.fields[].required === true` 为准,排除平台自动维护字段
|
|
152
|
+
* 枚举/选择字段已识别:写入时使用 `data.fields[].options[].value`,不要写展示用的 `label`
|
|
153
|
+
* 外键或关联关系真实存在
|
|
154
|
+
|
|
155
|
+
快速查看必填与枚举字段:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
rabetbase dataset detail --code <datasetCode> --format compress \
|
|
159
|
+
--jq '.data.fields[] | select(.required == true or (.options | type == "array")) | {name, displayName, type, required, options}'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
禁止行为:
|
|
163
|
+
|
|
164
|
+
* 未读取数据集详情就直接写字段名
|
|
165
|
+
* 凭经验猜 `user_id`、`status`、`deleted` 等通用字段
|
|
166
|
+
* 把前端代码里的字段名照搬到当前 BFF
|
|
167
|
+
* 把某个 Demo 或历史案例中的字段、枚举、表名当作当前任务的通用规则
|
|
168
|
+
|
|
169
|
+
### Step 3:选择脚本类型
|
|
170
|
+
|
|
171
|
+
使用规则:
|
|
172
|
+
|
|
173
|
+
* Before:修改请求参数、补默认值、做前置校验
|
|
174
|
+
* After:修改返回结果、做脱敏、补充展示字段
|
|
175
|
+
* ENDPOINT:独立业务流程、事务、多表写入、复杂业务端点
|
|
176
|
+
|
|
177
|
+
### Step 4:生成脚本
|
|
178
|
+
|
|
179
|
+
在本地 `.rabetbase/bff/<appCode>/...` 下生成或修改完整脚本。
|
|
180
|
+
|
|
181
|
+
脚本必须包含:
|
|
182
|
+
|
|
183
|
+
* 顶部注释
|
|
184
|
+
* `export default async function`
|
|
185
|
+
* 明确的输入输出
|
|
186
|
+
* 数据集映射
|
|
187
|
+
* 必要的错误处理
|
|
188
|
+
|
|
189
|
+
本地文件是主工作副本:
|
|
190
|
+
|
|
191
|
+
* 新建时用 `rabetbase bff create`
|
|
192
|
+
* 修改时直接编辑 `.rabetbase/bff/<appCode>/...`
|
|
193
|
+
* 需要远端最新内容时先 `rabetbase bff pull`
|
|
194
|
+
|
|
195
|
+
如果 BFF 行为与预期不符,或 `push` 显示 `unchanged` 但效果没变,先确认远端实际运行的是哪份代码:
|
|
196
|
+
|
|
197
|
+
* `rabetbase bff detail --id <id> --format json`
|
|
198
|
+
* 必要时再 `rabetbase bff pull --format json` 同步远端到本地
|
|
199
|
+
|
|
200
|
+
先确认“远端现在是什么”,再决定是否继续改本地、查页面或查锁状态。
|
|
201
|
+
|
|
202
|
+
### Step 5:自检
|
|
203
|
+
|
|
204
|
+
至少检查:
|
|
205
|
+
|
|
206
|
+
* 函数名匹配(用于 `scriptName` 参数)
|
|
207
|
+
* 顶部注释占位符已替换
|
|
208
|
+
* 单条查询是否统一使用 `getOne({ id })`
|
|
209
|
+
* SQL 返回值是否按 BFF 语义处理
|
|
210
|
+
* 是否误设置系统字段
|
|
211
|
+
* 是否存在明显性能问题
|
|
212
|
+
|
|
213
|
+
### Step 6:检查状态并预览
|
|
214
|
+
|
|
215
|
+
至少执行:
|
|
216
|
+
|
|
217
|
+
* `rabetbase bff status --format json`
|
|
218
|
+
* `rabetbase bff push --type <type> --name <name> --dry-run --format json`
|
|
219
|
+
|
|
220
|
+
确认:
|
|
221
|
+
|
|
222
|
+
* 脚本进入 `added` / `modified`
|
|
223
|
+
* 预览返回的 `lockKey`、`mode`、`status` 符合预期
|
|
224
|
+
|
|
225
|
+
### Step 7:推送到平台
|
|
226
|
+
|
|
227
|
+
确认无误后执行:
|
|
228
|
+
|
|
229
|
+
* `rabetbase bff push --yes --type <type> --name <name> --format json`
|
|
230
|
+
|
|
231
|
+
如果目标是同步远端到本地,则执行:
|
|
232
|
+
|
|
233
|
+
* `rabetbase bff pull --format json`
|
|
234
|
+
|
|
235
|
+
## 顶部注释规范
|
|
236
|
+
|
|
237
|
+
顶部注释必须写清楚:
|
|
238
|
+
|
|
239
|
+
* 脚本功能描述
|
|
240
|
+
* 接口路径
|
|
241
|
+
* 平台配置地址
|
|
242
|
+
* HTTP 请求参数
|
|
243
|
+
* 返回数据结构
|
|
244
|
+
|
|
245
|
+
占位符必须替换为真实值,不能保留:
|
|
246
|
+
|
|
247
|
+
* `{appCode}`
|
|
248
|
+
* `{datasetCode}`
|
|
249
|
+
* `{datasetId}`
|
|
250
|
+
* `{operation}`
|
|
251
|
+
* `{scriptName}`
|
|
252
|
+
|
|
253
|
+
### HOOK 注释模板
|
|
254
|
+
|
|
255
|
+
```javascript
|
|
256
|
+
/**
|
|
257
|
+
* 脚本功能描述
|
|
258
|
+
*
|
|
259
|
+
* [接口路径] POST /api/{appCode}/{datasetCode}/{operation}
|
|
260
|
+
* [平台配置] https://app.lovrabet.com/app/{appCode}/data/dataset/{datasetId}#api-list
|
|
261
|
+
*
|
|
262
|
+
* [HTTP 请求体参数]
|
|
263
|
+
* { "field1": "字段说明" }
|
|
264
|
+
*
|
|
265
|
+
* [返回数据结构]
|
|
266
|
+
* HOOK: 返回修改后的 params
|
|
267
|
+
*/
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### ENDPOINT 注释模板
|
|
271
|
+
|
|
272
|
+
```javascript
|
|
273
|
+
/**
|
|
274
|
+
* 脚本功能描述
|
|
275
|
+
*
|
|
276
|
+
* [接口路径] POST /api/endpoint/{appCode}/{scriptName}
|
|
277
|
+
* [平台配置] https://app.lovrabet.com/app/{appCode}/data/backend-function
|
|
278
|
+
*
|
|
279
|
+
* [HTTP 请求体参数]
|
|
280
|
+
* { "field1": "字段说明" }
|
|
281
|
+
*
|
|
282
|
+
* [返回数据结构]
|
|
283
|
+
* ENDPOINT: 返回业务数据对象
|
|
284
|
+
*/
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## 参数与返回值
|
|
288
|
+
|
|
289
|
+
| 类型 | `params` 含义 | 返回要求 |
|
|
290
|
+
|------|---------------|---------|
|
|
291
|
+
| Before | 请求参数 | 返回修改后的 `params` |
|
|
292
|
+
| After | 响应结果,如 `tableData`、`tableColumns` | 返回修改后的 `params` |
|
|
293
|
+
| ENDPOINT | HTTP 请求体 JSON | 返回业务数据对象 |
|
|
294
|
+
|
|
295
|
+
`context` 常用字段:
|
|
296
|
+
|
|
297
|
+
* `context.userInfo`
|
|
298
|
+
* `context.appCode`
|
|
299
|
+
* `context.tenantCode`
|
|
300
|
+
* `context.client`
|
|
301
|
+
|
|
302
|
+
## 数据集调用规范
|
|
303
|
+
|
|
304
|
+
通过 `context.client.models` 调用数据集。模型键格式为固定前缀 `"dataset_"` 拼接 32 位数据集编码,编码来自 `rabetbase dataset list/detail` 返回的 `code` 字段。
|
|
305
|
+
|
|
306
|
+
```javascript
|
|
307
|
+
const TABLES = {
|
|
308
|
+
primary: "dataset_0123456789abcdef0123456789abcdef", // 数据集: <displayName> | 数据表: <tableName>
|
|
309
|
+
detail: "dataset_fedcba9876543210fedcba9876543210", // 数据集: <displayName> | 数据表: <tableName>
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const models = context.client.models;
|
|
313
|
+
const record = await models[TABLES.primary].getOne({ id: params.id });
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
规则:
|
|
317
|
+
|
|
318
|
+
* 必须使用 `"dataset_" + 32 位数据集编码`,不要只写裸 `code`
|
|
319
|
+
* 每个映射后写 `// 数据集: ... | 数据表: ...`
|
|
320
|
+
* 查询单条统一使用 `getOne({ id })`
|
|
321
|
+
* 列表查询优先使用 `filter()`
|
|
322
|
+
* `context.client.models` 是 Proxy 对象,`Object.keys()` / `Object.entries()` 可能返回空数组;通过 `models[TABLES.xxx]` 访问即可
|
|
323
|
+
|
|
324
|
+
常用方法与返回值:
|
|
325
|
+
|
|
326
|
+
| 方法 | 返回值 | 说明 |
|
|
327
|
+
|------|--------|------|
|
|
328
|
+
| `getOne({ id })` | `object \| null` | 按主键查询单条 |
|
|
329
|
+
| `filter(params)` | `{ tableData, paging, tableColumns? }` | 高级过滤查询,数据在 `tableData`,不是 `list` |
|
|
330
|
+
| `aggregate(params)` | `{ tableData, paging, tableColumns? }` | DB_TABLE 单表聚合,数据在 `tableData` |
|
|
331
|
+
| `create(data)` | `number` | 创建记录,返回新记录 ID,不返回完整对象 |
|
|
332
|
+
| `batchCreate(rows)` | `Array<number | string>` | 批量创建同一数据集记录;ID 元素类型取决于数据集主键,顺序与输入一致 |
|
|
333
|
+
| `update({ id, ...fields })` | 无业务对象 | 更新记录(id 支持数组批量,最多 1000 条) |
|
|
334
|
+
| `delete({ id })` | 无业务对象 | 删除记录(id 支持数组批量,最多 1000 条) |
|
|
335
|
+
|
|
336
|
+
### 批量新增与批量更新
|
|
337
|
+
|
|
338
|
+
`batchCreate(rows)` 的 `rows` 必须是非空对象数组,直接传数组,不使用 `{"items":[...]}` 包装。批量数量不得超过运行时上限(默认 1000 条)。返回值是与输入顺序一致的新记录 ID 数组,元素类型取决于数据集主键:
|
|
339
|
+
|
|
340
|
+
```javascript
|
|
341
|
+
const createdIds = await models[TABLES.detail].batchCreate([
|
|
342
|
+
{ primary_id: params.primaryId, item_code: "A" },
|
|
343
|
+
{ primary_id: params.primaryId, item_code: "B" },
|
|
344
|
+
]);
|
|
345
|
+
|
|
346
|
+
await models[TABLES.primary].update({
|
|
347
|
+
id: [1, 2, 3],
|
|
348
|
+
status: "DONE",
|
|
349
|
+
});
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
批量更新仍使用 `update({ id: [...], ...fields })`。不存在 `batchUpdate()`,也不要写成 `update([{ id: 1, ... }, { id: 2, ... }])`。示例中的字段名、ID 和枚举值都必须替换为 `dataset detail` 已确认的真实值。
|
|
353
|
+
|
|
354
|
+
### aggregate 调用与选型
|
|
355
|
+
|
|
356
|
+
`` context.client.models[`dataset_${datasetCode}`].aggregate(params) `` 是 BFF 的数据集 Instant API。实际脚本仍按上文的数据集映射,通过 `models[TABLES.xxx]` 访问;示例字段只用于展示参数契约,编写业务脚本前必须用 `dataset detail` 替换为真实字段:
|
|
357
|
+
|
|
358
|
+
```javascript
|
|
359
|
+
const aggregateResult = await models[TABLES.primary].aggregate({
|
|
360
|
+
where: { status: { $eq: "ACTIVE" } },
|
|
361
|
+
aggregate: [
|
|
362
|
+
{ type: "SUM", column: "amount", alias: "totalAmount" },
|
|
363
|
+
{ type: "COUNT", column: "id", alias: "recordCount", distinct: true },
|
|
364
|
+
],
|
|
365
|
+
groupBy: ["company_id"],
|
|
366
|
+
having: { company_id: { $notNull: true } },
|
|
367
|
+
orderBy: [{ totalAmount: "desc" }],
|
|
368
|
+
currentPage: 1,
|
|
369
|
+
pageSize: 20,
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
const rows = aggregateResult.tableData;
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
聚合类型支持 `SUM`、`AVG`、`COUNT`、`MAX`、`MIN`。聚合项使用 `column` 指定真实数据集字段,可按需提供 `alias` 和 `distinct`;需要四舍五入时设置 `round: true`,`round: true` 时必须同时提供整数 `precision`。分组字段写入 `groupBy`。`having` 使用与 `where` 相同的对象结构,其中字段必须是真实数据集字段;示例使用真实分组字段 `company_id`,不要使用聚合输出别名。
|
|
376
|
+
|
|
377
|
+
### 聚合别名使用边界
|
|
378
|
+
|
|
379
|
+
`aggregate[].alias` 只定义聚合结果的输出字段名,不会成为新的数据集字段。当前服务端契约如下:
|
|
380
|
+
|
|
381
|
+
| 位置 | 聚合别名 | 约束 |
|
|
382
|
+
|------|----------|------|
|
|
383
|
+
| `aggregate[].alias` | 支持 | 仅定义返回结果字段名 |
|
|
384
|
+
| `select` | 不支持 | 使用真实数据集字段 |
|
|
385
|
+
| `where` | 不支持 | 使用真实数据集字段 |
|
|
386
|
+
| `having` | 不支持 | 使用真实数据集字段 |
|
|
387
|
+
| `groupBy` | 不支持 | 使用真实数据集字段 |
|
|
388
|
+
| `orderBy` | 支持 | 可以引用聚合输出别名 |
|
|
389
|
+
|
|
390
|
+
需要按聚合结果过滤且 `aggregate()` 无法用真实字段表达时,使用已配置的 Custom SQL。不要在运行时静默切换到 Custom SQL,也不要动态拼接 SQL。
|
|
391
|
+
|
|
392
|
+
选型规则:
|
|
393
|
+
|
|
394
|
+
* 单个 `DB_TABLE` 数据集的简单聚合优先使用 `aggregate()`,不要先写 Custom SQL
|
|
395
|
+
* 只有 JOIN、跨表统计、数据库特有函数或 `aggregate()` 无法表达的查询才使用已配置的 Custom SQL
|
|
396
|
+
* `aggregate()` 返回值与 `filter()` 一样,从 `.tableData` 读取数据,不要按 SQL 数组返回值处理
|
|
397
|
+
* `METADATA` 数据集不支持 `aggregate()` 或 Custom SQL;不要在失败后静默降级为动态 SQL
|
|
398
|
+
|
|
399
|
+
正确处理 `create()` 返回值:
|
|
400
|
+
|
|
401
|
+
```javascript
|
|
402
|
+
const primaryId = await models[TABLES.primary].create({
|
|
403
|
+
required_field_a: params.requiredFieldA,
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
await models[TABLES.detail].create({
|
|
407
|
+
primary_id: primaryId,
|
|
408
|
+
required_field_b: params.requiredFieldB,
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
不要写成:
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
const primary = await models[TABLES.primary].create({ required_field_a: params.requiredFieldA });
|
|
416
|
+
await models[TABLES.detail].create({ primary_id: primary.id }); // primary.id 是 undefined
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
不要再写:
|
|
420
|
+
|
|
421
|
+
```javascript
|
|
422
|
+
const record = await models[TABLES.primary].findOne({ id });
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
## 系统自动维护字段
|
|
426
|
+
|
|
427
|
+
以下字段由平台自动维护,代码中不要手动设置:
|
|
428
|
+
|
|
429
|
+
* `id`
|
|
430
|
+
* `create_time`
|
|
431
|
+
* `modify_time`
|
|
432
|
+
* `create_by`
|
|
433
|
+
* `modify_by`
|
|
434
|
+
|
|
435
|
+
正确做法是只设置业务字段。
|
|
436
|
+
|
|
437
|
+
## Before / After / Endpoint 规则
|
|
438
|
+
|
|
439
|
+
### Before
|
|
440
|
+
|
|
441
|
+
适合:
|
|
442
|
+
|
|
443
|
+
* 参数校验
|
|
444
|
+
* 默认值填充
|
|
445
|
+
* 权限过滤
|
|
446
|
+
|
|
447
|
+
规则:
|
|
448
|
+
|
|
449
|
+
* 普通接口可直接修改 `params.field`
|
|
450
|
+
* `filter` / `aggregate` 接口必须修改 `params.where`
|
|
451
|
+
* 追加过滤条件时要保留原条件,通常用 `$and`
|
|
452
|
+
|
|
453
|
+
```javascript
|
|
454
|
+
export default async function beforeFilter(params, context) {
|
|
455
|
+
if (context.userInfo.role !== "admin") {
|
|
456
|
+
params.where = params.where || {};
|
|
457
|
+
const originalWhere = { ...params.where };
|
|
458
|
+
params.where = {
|
|
459
|
+
$and: [originalWhere, { created_by: { $eq: context.userInfo.id } }],
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
return params;
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### After
|
|
467
|
+
|
|
468
|
+
适合:
|
|
469
|
+
|
|
470
|
+
* 数据脱敏
|
|
471
|
+
* 字段补充
|
|
472
|
+
* 展示增强
|
|
473
|
+
|
|
474
|
+
规则:
|
|
475
|
+
|
|
476
|
+
* 主要操作 `params.tableData`
|
|
477
|
+
* 不要破坏既有返回结构
|
|
478
|
+
|
|
479
|
+
```javascript
|
|
480
|
+
export default async function afterFilter(params) {
|
|
481
|
+
params.tableData?.forEach((record) => {
|
|
482
|
+
if (record.phone) {
|
|
483
|
+
record.phone = record.phone.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
return params;
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### ENDPOINT
|
|
491
|
+
|
|
492
|
+
适合:
|
|
493
|
+
|
|
494
|
+
* 独立业务流程
|
|
495
|
+
* 多表读写
|
|
496
|
+
* 事务处理
|
|
497
|
+
* 需要前端通过 `client.bff.execute()` 调用的业务接口
|
|
498
|
+
|
|
499
|
+
返回规则:
|
|
500
|
+
|
|
501
|
+
* ENDPOINT 返回业务对象本身
|
|
502
|
+
* 平台最终会包装成 `{ success, data }`
|
|
503
|
+
* 前端 SDK 调用 `client.bff.execute()` 时,拿到的是业务数据,不是 `{ success, data }`
|
|
504
|
+
|
|
505
|
+
## 公共函数(COMMON)
|
|
506
|
+
|
|
507
|
+
### 命名建议
|
|
508
|
+
|
|
509
|
+
公共函数建议统一加 `common` 前缀(如 `commonGetUserInfo`),便于与普通 ENDPOINT 区分,也方便人和 AI 识别。
|
|
510
|
+
|
|
511
|
+
### 在其他 BFF 中调用公共函数
|
|
512
|
+
|
|
513
|
+
通过 `context.client.bff.execute` 调用:
|
|
514
|
+
|
|
515
|
+
```javascript
|
|
516
|
+
const userInfo = await context.client.bff.execute({
|
|
517
|
+
scriptName: 'commonGetUserInfo',
|
|
518
|
+
params: { userId: params.userId }
|
|
519
|
+
});
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
参数说明:
|
|
523
|
+
|
|
524
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
525
|
+
|------|------|------|------|
|
|
526
|
+
| `scriptName` | string | 是 | 公共函数名称(与 COMMON 脚本的 scriptName 一致) |
|
|
527
|
+
| `params` | object | 否 | 传递的参数,默认 `{}` |
|
|
528
|
+
|
|
529
|
+
### 注意事项
|
|
530
|
+
|
|
531
|
+
* `scriptName` 必须与公共函数名称精确匹配(大小写敏感)
|
|
532
|
+
* 调用必须使用 `await`
|
|
533
|
+
* `params` 会被深拷贝,调用方的原始对象不会被修改
|
|
534
|
+
* 公共函数不可循环调用(A 调 B,B 又调 A)
|
|
535
|
+
* 公共函数抛出的异常会向上传播到调用方,需在调用方做 try-catch
|
|
536
|
+
* 修改公共函数的出入参会影响所有引用方;如需改动,建议新建 V2 版本逐步切换
|
|
537
|
+
|
|
538
|
+
### 组合调用示例
|
|
539
|
+
|
|
540
|
+
```javascript
|
|
541
|
+
export default async function runBusinessFlow(params, context) {
|
|
542
|
+
const sequence = await context.client.bff.execute({
|
|
543
|
+
scriptName: 'commonGenerateSequence',
|
|
544
|
+
params: {}
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
const result = await context.client.bff.execute({
|
|
548
|
+
scriptName: 'commonCreateRecordsWithTransaction',
|
|
549
|
+
params: { ...params, sequence }
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
return result;
|
|
553
|
+
}
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
## SQL 调用规则
|
|
557
|
+
|
|
558
|
+
在 BFF 中使用:
|
|
559
|
+
|
|
560
|
+
```javascript
|
|
561
|
+
const rows = await context.client.sql.execute({
|
|
562
|
+
sqlCode: "example-read-list",
|
|
563
|
+
params,
|
|
564
|
+
});
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
关键差异:
|
|
568
|
+
|
|
569
|
+
* 前端 SDK:返回 `{ execSuccess, execResult }`
|
|
570
|
+
* Backend Function:直接返回数组 `T[]`
|
|
571
|
+
|
|
572
|
+
不要写成:
|
|
573
|
+
|
|
574
|
+
```javascript
|
|
575
|
+
const result = await context.client.sql.execute({ sqlCode: "xxx" });
|
|
576
|
+
const rows = result.execResult;
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
## 消息通知扩展
|
|
580
|
+
|
|
581
|
+
### 类型选择
|
|
582
|
+
|
|
583
|
+
消息通知可以出现在以下三类脚本中:
|
|
584
|
+
|
|
585
|
+
* **Before HOOK**:用于在数据集操作执行前发送明确的预通知或告警,例如高风险变更开始提醒。仅当业务接受“通知已发送但后续操作仍可能失败”,并且希望通知失败时阻止本次操作,才使用该方式。消息必须使用“即将执行”或“准备执行”语义,不得宣称操作已经成功。
|
|
586
|
+
* **After HOOK**:用于数据集操作成功后的通知副作用。After HOOK 的 `params` 是业务接口响应结果,不是原始请求参数或操作前记录;仅当响应结果或固定可信规则已包含通知所需事实时才使用。`create` / `update` / `delete` 的响应若不含这些字段,不得把 `params` 当作“当前记录”,应改用能在写入前读取并暂存必要字段、在成功后发送通知的受控 ENDPOINT。
|
|
587
|
+
* **ENDPOINT**:用于页面、CLI 或其他服务显式调用的独立通知流程。调用方只传经过校验的最小业务字段,不能控制渠道配置、任意收件人或完整消息。
|
|
588
|
+
|
|
589
|
+
三者都使用 `context.client.extension.execute("notification", "send", params)`;`appCode` 和当前用户由 runtime 的可信脚本上下文注入,不能从 `params` 伪造。
|
|
590
|
+
|
|
591
|
+
下面是 ENDPOINT 使用运行时通知扩展的完整示例:
|
|
592
|
+
|
|
593
|
+
```javascript
|
|
594
|
+
const CONFIG_CODE = "<confirmed-config-code>";
|
|
595
|
+
const ALLOWED_AUDIENCES = [
|
|
596
|
+
{ type: "ROLE", codes: ["<confirmed-role-code>"] },
|
|
597
|
+
];
|
|
598
|
+
|
|
599
|
+
export default async function sendOrderNotification(params, context) {
|
|
600
|
+
const orderNo =
|
|
601
|
+
typeof params?.orderNo === "string" ? params.orderNo.trim() : "";
|
|
602
|
+
if (!/^[A-Za-z0-9_-]{1,64}$/.test(orderNo)) {
|
|
603
|
+
throw new Error(
|
|
604
|
+
"orderNo must be 1-64 letters, numbers, underscores, or hyphens",
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return await context.client.extension.execute("notification", "send", {
|
|
609
|
+
configCode: CONFIG_CODE,
|
|
610
|
+
audiences: ALLOWED_AUDIENCES,
|
|
611
|
+
message: {
|
|
612
|
+
title: "订单状态通知",
|
|
613
|
+
summary: "订单 " + orderNo + " 已进入待处理状态",
|
|
614
|
+
theme: "blue",
|
|
615
|
+
},
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
这是 ENDPOINT 的安全调用起点:部署前必须把两个占位值替换为当前应用已确认的配置编码和角色编码;调用方只能提供经过校验的最小业务字段,不能控制 `configCode`、任意 `audiences` 或完整 `message`。Before HOOK 从已确认的请求和可信上下文派生消息,After HOOK 只能使用响应结果或固定可信规则。三者都不要改写成 `context.client.notification.send(...)`、旧 MANUAL 通知参数或脚本内 `fetch(...)`。
|
|
621
|
+
|
|
622
|
+
### Before HOOK 调用方式
|
|
623
|
+
|
|
624
|
+
Before HOOK 在业务接口执行前运行。通知调用必须使用 `await`;发送完成后返回原始 `params`,让后续接口继续使用原请求参数:
|
|
625
|
+
|
|
626
|
+
```javascript
|
|
627
|
+
const CONFIG_CODE = "<confirmed-config-code>";
|
|
628
|
+
const ALLOWED_AUDIENCES = [
|
|
629
|
+
{ type: "ROLE", codes: ["<confirmed-role-code>"] },
|
|
630
|
+
];
|
|
631
|
+
|
|
632
|
+
export default async function beforeNotifyOrderUpdate(params, context) {
|
|
633
|
+
const orderNo =
|
|
634
|
+
typeof params?.orderNo === "string" ? params.orderNo.trim() : "";
|
|
635
|
+
if (!/^[A-Za-z0-9_-]{1,64}$/.test(orderNo)) {
|
|
636
|
+
throw new Error(
|
|
637
|
+
"orderNo must be 1-64 letters, numbers, underscores, or hyphens",
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
await context.client.extension.execute("notification", "send", {
|
|
642
|
+
configCode: CONFIG_CODE,
|
|
643
|
+
audiences: ALLOWED_AUDIENCES,
|
|
644
|
+
message: {
|
|
645
|
+
title: "订单变更即将执行",
|
|
646
|
+
summary: "订单 " + orderNo + " 即将执行变更,请关注后续结果",
|
|
647
|
+
theme: "orange",
|
|
648
|
+
},
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
return params;
|
|
652
|
+
}
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
Before HOOK 不得写成 `return await context.client.extension.execute(...)`。通知扩展返回的是 `{ sent, configCode, channelType, message }`;如果把它作为 Hook 返回值,runtime 会将其当作新的接口请求参数,覆盖原始 `params`。
|
|
656
|
+
|
|
657
|
+
Before HOOK 的执行边界:
|
|
658
|
+
|
|
659
|
+
* 通知失败会直接抛错,后续业务接口不会执行
|
|
660
|
+
* 通知发送成功只表示预通知已发出;后续业务操作仍可能校验失败、执行失败或回滚
|
|
661
|
+
* 消息标题和摘要必须表达“即将执行”或“准备执行”,不能表达“已完成”或“执行成功”
|
|
662
|
+
* `configCode` 和允许的接收范围应固定在受控脚本中,不能由接口调用方覆盖
|
|
663
|
+
|
|
664
|
+
After HOOK 通知失败或超时时,原业务操作可能已经完成,通知发送状态也可能未知;不得因此自动重试原业务请求。
|
|
665
|
+
|
|
666
|
+
### 获取 configCode
|
|
667
|
+
|
|
668
|
+
创建或修改通知型 BFF 前,先查询当前应用的应用级通知配置:
|
|
669
|
+
|
|
670
|
+
```bash
|
|
671
|
+
rabetbase notification config-list --type EMAIL --format compress
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
从 `data.configs[]` 中根据 `configName` 和 `description` 选择配置,把该项 `configCode` 固定到受控业务脚本中。查询命令只返回安全身份与描述字段,不返回 `channelConfig`、`endpointUrl` 或凭据。
|
|
675
|
+
|
|
676
|
+
`configCode` 与 `channelCode` 不是同一概念:
|
|
677
|
+
|
|
678
|
+
* `configCode`:应用级通知渠道配置编码,供 BFF `notification.send` 使用
|
|
679
|
+
* `channelCode`:dataset 级通知通道编码,不是本扩展的入参
|
|
680
|
+
|
|
681
|
+
查询为空时说明当前应用没有该类型的可用配置;查询出多个候选且无法从名称和描述判断业务目标时,向用户确认,不得自动取第一条。
|
|
682
|
+
|
|
683
|
+
### 调用对象
|
|
684
|
+
|
|
685
|
+
扩展调用对象只允许以下字段,多余字段会直接失败:
|
|
686
|
+
|
|
687
|
+
| 字段 | 必填 | 约束 |
|
|
688
|
+
|------|------|------|
|
|
689
|
+
| `configCode` | 是 | 当前应用中已存在且未删除的应用级通知渠道配置编码;先用 `rabetbase notification config-list` 查询,不要猜测 |
|
|
690
|
+
| `audiences` | 按渠道 | 对象数组;EMAIL 和飞书应用机器人必须至少解析出一个接收人,Webhook 机器人可以不传或传空数组 |
|
|
691
|
+
| `message` | 是 | 消息对象,字段严格按下表传递 |
|
|
692
|
+
|
|
693
|
+
`appCode` 和当前用户由可信脚本上下文注入。调用对象中禁止传 `appCode`、`datasetCode`、`sceneCode`、`endpointUrl`、`channelConfig`、token、secret 或其他旧通知字段。`configCode` 只能解析当前应用的配置,不能借此跨应用发送。
|
|
694
|
+
|
|
695
|
+
### audiences
|
|
696
|
+
|
|
697
|
+
每一项只能使用一种结构:
|
|
698
|
+
|
|
699
|
+
```javascript
|
|
700
|
+
[
|
|
701
|
+
{ type: "USER", ids: ["user@example.com"] },
|
|
702
|
+
{ type: "ROLE", codes: ["ADMIN"] },
|
|
703
|
+
]
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
| `type` | 值字段 | 说明 |
|
|
707
|
+
|--------|--------|------|
|
|
708
|
+
| `USER` | `ids` | 非空字符串数组;具体标识必须与目标渠道的接收人类型一致,EMAIL 可使用邮箱或可解析的应用用户标识 |
|
|
709
|
+
| `ROLE` | `codes` | 非空字符串数组;使用当前应用已确认的角色编码或角色标识,不要猜测 |
|
|
710
|
+
|
|
711
|
+
`type` 只支持 `USER` / `ROLE`,且对象不能混入其他字段。EMAIL 和飞书应用机器人若最终没有解析出有效接收人,会在发送前失败;不要把“传了 audiences”当作“接收人已解析”。
|
|
712
|
+
|
|
713
|
+
### message
|
|
714
|
+
|
|
715
|
+
| 字段 | 必填 | 约束 |
|
|
716
|
+
|------|------|------|
|
|
717
|
+
| `title` | 是 | 非空字符串 |
|
|
718
|
+
| `summary` | 是 | 非空字符串 |
|
|
719
|
+
| `theme` | 否 | `blue` / `green` / `orange` / `red` / `grey` |
|
|
720
|
+
| `detailMarkdown` | 否 | 字符串 |
|
|
721
|
+
| `facts` | 否 | 最多 8 项,每项严格为 `{ label, value }`,两个字段都是非空字符串 |
|
|
722
|
+
| `actions` | 否 | 最多 2 项,每项严格为 `{ text, url }`,两个字段都是非空字符串 |
|
|
723
|
+
|
|
724
|
+
消息对象不允许额外字段,也不支持 `${...}` 模板表达式。运行时值应由 BFF 根据已校验的 `params` 直接组装,不要把模板语法交给通知扩展解析。
|
|
725
|
+
|
|
726
|
+
### 返回值与副作用
|
|
727
|
+
|
|
728
|
+
成功时返回:
|
|
729
|
+
|
|
730
|
+
```json
|
|
731
|
+
{
|
|
732
|
+
"sent": true,
|
|
733
|
+
"configCode": "<confirmed-config-code>",
|
|
734
|
+
"channelType": "EMAIL",
|
|
735
|
+
"message": "通知发送成功"
|
|
736
|
+
}
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
`sent: true` 表示本次运行时通知分发成功,不表示接收人已经阅读,也不提供 exactly-once 保证。配置不存在、接收人解析为空、参数不合法或渠道调用失败会直接抛错,并保留通知错误码和消息。
|
|
740
|
+
|
|
741
|
+
通知发送是外部可见副作用:
|
|
742
|
+
|
|
743
|
+
* 创建/推送脚本的 dry-run 不会发送通知;只有执行 BFF 才会发送
|
|
744
|
+
* 运行 smoke 前必须向用户展示当前应用、函数名、`configCode`、接收对象和消息摘要并取得确认
|
|
745
|
+
* 面向多人调用的正式 ENDPOINT 必须在调用扩展前校验 `params` 的字段、类型和接收对象范围;固定业务通知优先在脚本内固定 `configCode` 和允许的接收范围,不要把任意渠道或任意收件人转发能力暴露给调用者
|
|
746
|
+
* 超时或客户端未拿到结果时,发送状态可能未知;不得自动重试,避免重复通知
|
|
747
|
+
* 不要在数据库事务中发送通知;先完成并提交业务写入,再执行通知调用
|
|
748
|
+
* 若运行环境报告没有 `notification` 扩展,停止并确认目标 runtime 已包含该能力;不要回退到旧 MANUAL 参数或自行发 HTTP 请求
|
|
749
|
+
|
|
750
|
+
## 事务规则
|
|
751
|
+
|
|
752
|
+
事务使用方式:
|
|
753
|
+
|
|
754
|
+
```javascript
|
|
755
|
+
await context.client.db.transaction(async (tx) => {
|
|
756
|
+
const primaryId = await tx.models[TABLES.primary].create({
|
|
757
|
+
required_field_a: params.requiredFieldA,
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
await tx.models[TABLES.detail].create({
|
|
761
|
+
primary_id: primaryId,
|
|
762
|
+
required_field_b: params.requiredFieldB,
|
|
763
|
+
});
|
|
764
|
+
|
|
765
|
+
// tx.models 与 context.client.models 用法一致
|
|
766
|
+
// tx.sql.execute 可在同一事务中执行自定义 SQL
|
|
767
|
+
// 成功自动提交,抛错自动回滚
|
|
768
|
+
});
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
必须遵守:
|
|
772
|
+
|
|
773
|
+
* 外层必须 `await`
|
|
774
|
+
* 回调函数必须是 `async`
|
|
775
|
+
* 不要在事务中调用外部慢接口
|
|
776
|
+
* 异常要向上抛出,不能吞掉
|
|
777
|
+
|
|
778
|
+
## 性能约束
|
|
779
|
+
|
|
780
|
+
编写 BFF 前,必须阅读 `data-api-guidelines.md` 中的性能优化部分。
|
|
781
|
+
|
|
782
|
+
重点避免:
|
|
783
|
+
|
|
784
|
+
* 循环查询单条
|
|
785
|
+
* 循环写入
|
|
786
|
+
* 嵌套循环查询
|
|
787
|
+
|
|
788
|
+
性能要求:
|
|
789
|
+
|
|
790
|
+
* 单次脚本数据库调用尽量控制在 `50` 次以内
|
|
791
|
+
* 可批量查询时,用 `filter + $in`
|
|
792
|
+
* 同一数据集批量新增优先使用 `batchCreate()`;相同字段值的批量更新优先使用 `update({ id: [...] })`
|
|
793
|
+
* 只有 Instant API 无法表达的复杂写入才考虑已有且契约可信的 Custom SQL
|
|
794
|
+
|
|
795
|
+
## 禁止事项
|
|
796
|
+
|
|
797
|
+
* 不要使用 `findOne`
|
|
798
|
+
* 不要使用 `getList()` 代替 `filter()`
|
|
799
|
+
* 不要手动设置系统字段
|
|
800
|
+
* 不要保留顶部注释占位符
|
|
801
|
+
* 不要把前端 SQL 返回值语义套到 BFF
|
|
802
|
+
* 不要在 BFF 中使用前端 SDK 独有的方法,如 `createClient`、`registerModels`
|
|
803
|
+
* 不要把示例里的字段名、表名、枚举值复制到真实脚本;字段事实必须来自当前数据集详情
|
|
804
|
+
* 不要忽略权限、脱敏和错误处理
|
|
805
|
+
* 不要在事务里做高延迟外部调用
|
|
806
|
+
* 不要在未确认 `configCode`、接收对象和消息内容时执行通知型 BFF
|
|
807
|
+
* 不要把通知执行超时当作“肯定未发送”并自动重试
|
|
808
|
+
|
|
809
|
+
## 自检清单
|
|
810
|
+
|
|
811
|
+
* [ ] 已确认脚本类型是 Before / After / Endpoint / Common
|
|
812
|
+
* [ ] 若脚本涉及数据集,已执行 `rabetbase dataset detail` 获取数据集信息
|
|
813
|
+
* [ ] 若涉及数据集,字段名、类型、必填、枚举、关系已核对
|
|
814
|
+
* [ ] 函数名正确(将作为 `scriptName` 参数传入)
|
|
815
|
+
* [ ] 顶部注释完整且占位符已替换
|
|
816
|
+
* [ ] 数据集映射使用 `"dataset_" + 32 位编码`
|
|
817
|
+
* [ ] 单条查询统一使用 `getOne`
|
|
818
|
+
* [ ] 列表查询使用 `filter`,并从 `.tableData` 读取结果
|
|
819
|
+
* [ ] DB_TABLE 简单单表聚合优先使用 `aggregate()`,并从 `.tableData` 读取结果
|
|
820
|
+
* [ ] `create()` 返回值按新记录 ID 处理,没有访问 `.id`
|
|
821
|
+
* [ ] `batchCreate()` 直接接收非空对象数组,并按新记录 ID 数组处理返回值
|
|
822
|
+
* [ ] 批量更新使用 `update({ id: [...] })`,没有使用不存在的 `batchUpdate()` 或记录数组参数
|
|
823
|
+
* [ ] 枚举/选择字段写入 `options[].value`,不是展示 `label`
|
|
824
|
+
* [ ] SQL 返回值按 BFF 语义处理
|
|
825
|
+
* [ ] 未设置系统自动维护字段
|
|
826
|
+
* [ ] 无明显 N+1 或循环写入问题
|
|
827
|
+
* [ ] HOOK 返回 `params`,ENDPOINT 返回业务对象
|
|
828
|
+
* [ ] 若脚本发送通知,只使用 `configCode` / `audiences` / `message`,且已确认接收对象和外部副作用
|
|
829
|
+
|
|
830
|
+
## 相关指南
|
|
831
|
+
|
|
832
|
+
* `data-api-guidelines.md`
|
|
833
|
+
* `sql-creation-workflow.md`
|
|
834
|
+
* `bff-creation-workflow.md`
|
|
835
|
+
* `conflict-detection.md`
|