@nocobase/plugin-ai 3.0.0-alpha.1 → 3.0.0-alpha.11
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/dist/ai/docs/nocobase/ai/ai-quick-start.md +1 -1
- package/dist/ai/docs/nocobase/ai/claude-code/index.md +1 -1
- package/dist/ai/docs/nocobase/ai/codex/index.md +1 -1
- package/dist/ai/docs/nocobase/ai/hermes-agent/index.md +1 -1
- package/dist/ai/docs/nocobase/ai/index.md +6 -25
- package/dist/ai/docs/nocobase/ai/install-nocobase-app.md +1 -1
- package/dist/ai/docs/nocobase/ai/openclaw/index.md +1 -1
- package/dist/ai/docs/nocobase/ai/opencode/index.md +1 -1
- package/dist/ai/docs/nocobase/ai/quick-start.mdx +9 -7
- package/dist/ai/docs/nocobase/ai/workbuddy/index.md +1 -1
- package/dist/ai/docs/nocobase/ai-builder/ai-portal/agent-workflow.md +153 -0
- package/dist/ai/docs/nocobase/ai-builder/ai-portal/components.md +134 -0
- package/dist/ai/docs/nocobase/ai-builder/ai-portal/deploy.md +164 -0
- package/dist/ai/docs/nocobase/ai-builder/ai-portal/index.md +144 -0
- package/dist/ai/docs/nocobase/ai-builder/ai-portal/model-selection.md +120 -0
- package/dist/ai/docs/nocobase/ai-builder/ai-portal/project-structure.md +128 -0
- package/dist/ai/docs/nocobase/ai-builder/index.md +73 -32
- package/dist/ai/docs/nocobase/ai-builder/ui-builder.md +2 -0
- package/dist/ai/docs/nocobase/ai-dev/index.md +2 -1
- package/dist/ai/docs/nocobase/ai-dev/watermark-plugin.md +2 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/complete-example.md +206 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/define-ai-employee.md +149 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/define-skill.md +138 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/define-tool.md +189 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/frontend-tool-ui.md +296 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/index.md +126 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/internationalization.md +88 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/troubleshooting.md +86 -0
- package/dist/ai/docs/nocobase/ai-employees/{knowledge-base/dev → dev/knowledge-base}/external-knowledge-base.md +2 -2
- package/dist/ai/docs/nocobase/ai-employees/knowledge-base/knowledge-base/index.md +1 -1
- package/dist/ai/docs/nocobase/ai-employees/knowledge-base/rag.md +43 -13
- package/dist/ai/docs/nocobase/api/cli/api/resource/create.md +4 -3
- package/dist/ai/docs/nocobase/api/cli/index.md +1 -1
- package/dist/ai/docs/nocobase/api/cli/portal/config.md +5 -3
- package/dist/ai/docs/nocobase/api/cli/portal/create.md +3 -6
- package/dist/ai/docs/nocobase/api/cli/portal/deploy.md +1 -1
- package/dist/ai/docs/nocobase/api/cli/portal/destroy.md +6 -4
- package/dist/ai/docs/nocobase/api/cli/portal/dev.md +21 -9
- package/dist/ai/docs/nocobase/api/cli/portal/index.md +19 -13
- package/dist/ai/docs/nocobase/api/cli/portal/info.md +3 -3
- package/dist/ai/docs/nocobase/api/cli/portal/list.md +5 -5
- package/dist/ai/docs/nocobase/api/cli/portal/pull.md +11 -1
- package/dist/ai/docs/nocobase/api/cli/portal/push.md +1 -1
- package/dist/ai/docs/nocobase/development/index.md +1 -1
- package/dist/ai/docs/nocobase/file-manager/file-preview/index.md +44 -3
- package/dist/ai/docs/nocobase/file-manager/storage/aliyun-oss.md +100 -3
- package/dist/ai/docs/nocobase/nocobase-cli/installation/cli.md +1 -1
- package/dist/ai/docs/nocobase/plugin-development/build.md +10 -4
- package/dist/ai/docs/nocobase/plugin-development/client/appendix/faq.md +1 -1
- package/dist/ai/docs/nocobase/plugin-development/client/examples/custom-action.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/client/examples/custom-block.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/client/examples/custom-field.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/client/examples/fullstack-plugin.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/client/examples/settings-page.md +2 -0
- package/dist/ai/docs/nocobase/plugin-development/common/i18n.md +3 -3
- package/dist/ai/docs/nocobase/plugin-development/server/cache.md +1 -1
- package/dist/ai/docs/nocobase/plugin-development/server/collections.md +0 -6
- package/dist/ai/docs/nocobase/plugin-development/server/command.md +2 -2
- package/dist/ai/docs/nocobase/plugin-development/server/context.md +2 -2
- package/dist/ai/docs/nocobase/plugin-development/server/i18n.md +4 -4
- package/dist/ai/docs/nocobase/plugin-development/write-your-first-plugin.md +91 -43
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-action-bulk-edit/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-action-bulk-update/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-action-custom-request/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-action-duplicate/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-action-export/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-action-import/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-action-print/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-ai/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-ai-gigachat/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-api-doc/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-api-keys/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-async-task-manager/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-audit-logs/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-auth/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-auth-sms/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-backup-restore/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-backups/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-block-comment/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-block-grid-card/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-block-iframe/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-block-list/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-block-markdown/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-block-multi-step-form/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-block-template/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-block-tree/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-block-workbench/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-calendar/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-charts/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-client/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-collection-fdw/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-collection-sql/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-collection-tree/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-comments/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-custom-variables/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-data-source-main/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-data-source-manager/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-data-visualization/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-data-visualization-echarts/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-departments/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-embed/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-environment-variables/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-error-handler/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-field-attachment-url/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-field-china-region/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-field-code/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-field-formula/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-field-m2m-array/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-field-markdown-vditor/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-field-sequence/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-field-sort/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-file-manager/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-file-previewer-office/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-flow-engine/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-form-drafts/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-gantt/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-graph-collection-manager/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-idp-oauth/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-kanban/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-license/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-locale-tester/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-localization/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-logger/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-map/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-mcp-server/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-mobile/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-mobile-client/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-multi-app-manager/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-multi-app-share-collection/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-multi-keyword-filter/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-notification-email/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-notification-in-app-message/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-notification-manager/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-public-forms/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-snapshot-field/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-system-settings/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-text-copy/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-theme-editor/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-ui-layout/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-ui-schema-storage/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-ui-templates/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-user-data-sync/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-users/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-verification/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-action-trigger/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-aggregate/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-cc/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-custom-action-trigger/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-date-calculation/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-delay/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-dynamic-calculation/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-javascript/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-json-variable-mapping/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-loop/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-mailer/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-manual/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-notification/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-parallel/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-request/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-request-interceptor/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-response-message/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-sql/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-test/index.md +1 -1
- package/dist/ai/docs/nocobase/plugins/@nocobase/plugin-workflow-variable/index.md +1 -1
- package/dist/ai/docs/nocobase/users-permissions/sync/index.md +8 -1
- package/dist/ai/docs/nocobase/users-permissions/sync/sources/dingtalk.md +138 -0
- package/dist/ai/docs/nocobase/users-permissions/sync/sources/ldap.md +87 -0
- package/dist/ai/docs/nocobase/workflow/nodes/javascript.md +21 -1
- package/dist/ai/tools/knowledge-base-retrieve.js +3 -1
- package/dist/client/244.276308c9b2090ec2.js +10 -0
- package/dist/client/{264.cc98933ef65608b6.js → 264.6ca5f2eeb4173d86.js} +1 -1
- package/dist/client/{705.19b642db34de438a.js → 705.a4fe26945d175e8a.js} +1 -1
- package/dist/client/index.js +3 -3
- package/dist/client-v2/244.e85b8d4659ca66c0.js +10 -0
- package/dist/client-v2/{264.be92ff6a4d2612f1.js → 264.3c7d8e90aa7f46ee.js} +1 -1
- package/dist/client-v2/420.a5b929a5e7f330be.js +10 -0
- package/dist/client-v2/{705.8dc34d43f02f322c.js → 705.f2e1b26a3f000075.js} +1 -1
- package/dist/client-v2/ai-employees/chatbox/hooks/reasoning-stream.d.ts +10 -0
- package/dist/client-v2/ai-employees/chatbox/stores/chat-box.d.ts +0 -2
- package/dist/client-v2/index.js +3 -3
- package/dist/client-v2/llm-providers/forms.d.ts +2 -0
- package/dist/client-v2/llm-providers/index.d.ts +1 -0
- package/dist/client-v2/models/ai-employees/AIEmployeeShortcutModel.d.ts +3 -0
- package/dist/client-v2/pages/EmployeesPage.d.ts +10 -0
- package/dist/client-v2/pages/LLMServicesPage.d.ts +9 -4
- package/dist/client-v2/repositories/AIConfigRepository.d.ts +2 -0
- package/dist/collections/ai-employees.d.ts +1 -0
- package/dist/collections/ai-employees.js +1 -0
- package/dist/externalVersion.js +18 -16
- package/dist/locale/de-DE.json +2 -1
- package/dist/locale/en-US.json +18 -5
- package/dist/locale/es-ES.json +2 -1
- package/dist/locale/fr-FR.json +2 -1
- package/dist/locale/hu-HU.json +2 -1
- package/dist/locale/id-ID.json +2 -1
- package/dist/locale/it-IT.json +2 -1
- package/dist/locale/ja-JP.json +2 -1
- package/dist/locale/ko-KR.json +2 -1
- package/dist/locale/nl-NL.json +2 -1
- package/dist/locale/pt-BR.json +2 -1
- package/dist/locale/ru-RU.json +2 -1
- package/dist/locale/tr-TR.json +2 -1
- package/dist/locale/uk-UA.json +2 -1
- package/dist/locale/vi-VN.json +2 -1
- package/dist/locale/zh-CN.json +18 -5
- package/dist/locale/zh-TW.json +2 -1
- package/dist/node_modules/@langchain/mistralai/package.json +1 -1
- package/dist/node_modules/@langchain/xai/package.json +1 -1
- package/dist/node_modules/fs-extra/package.json +1 -1
- package/dist/node_modules/jsonrepair/package.json +1 -1
- package/dist/node_modules/just-bash/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/node_modules/openai/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/ai-employees/ai-conversations.d.ts +2 -1
- package/dist/server/ai-employees/ai-conversations.js +2 -0
- package/dist/server/ai-employees/ai-employee.d.ts +2 -0
- package/dist/server/ai-employees/ai-employee.js +86 -40
- package/dist/server/ai-employees/ai-knowledge-base.d.ts +21 -1
- package/dist/server/ai-employees/ai-knowledge-base.js +76 -8
- package/dist/server/ai-employees/reasoning-stream-state.d.ts +23 -0
- package/dist/server/ai-employees/reasoning-stream-state.js +63 -0
- package/dist/server/collections/ai-conversations.js +5 -0
- package/dist/server/features/knowledge-base.d.ts +2 -0
- package/dist/server/llm-providers/common/reasoning.js +18 -10
- package/dist/{client-v2/ai-employees/chatbox/components/DebugPanel.d.ts → server/llm-providers/deepseek/index.d.ts} +2 -2
- package/dist/server/llm-providers/deepseek/index.js +32 -0
- package/dist/server/llm-providers/deepseek/provider.d.ts +57 -0
- package/dist/server/llm-providers/deepseek/provider.js +320 -0
- package/dist/server/llm-providers/deepseek/reasoning.d.ts +83 -0
- package/dist/server/llm-providers/deepseek/reasoning.js +285 -0
- package/dist/server/llm-providers/mistral.d.ts +1 -1
- package/dist/server/llm-providers/provider.d.ts +1 -0
- package/dist/server/llm-providers/provider.js +3 -0
- package/dist/server/llm-providers/shengsuanyun.d.ts +29 -0
- package/dist/server/llm-providers/shengsuanyun.js +114 -0
- package/dist/server/manager/ai-feature-manager.js +1 -1
- package/dist/server/manager/ai-manager.d.ts +3 -0
- package/dist/server/manager/ai-manager.js +7 -2
- package/dist/server/migrations/20260501000000-ai-employee-knowledge-base-retrieval-strategy.d.ts +14 -0
- package/dist/server/migrations/20260501000000-ai-employee-knowledge-base-retrieval-strategy.js +49 -0
- package/dist/server/migrations/20260803185305-migrate-ai-conversations-portal-name.d.ts +14 -0
- package/dist/server/migrations/20260803185305-migrate-ai-conversations-portal-name.js +52 -0
- package/dist/server/plugin.js +6 -0
- package/dist/server/resource/aiConversations.js +14 -2
- package/dist/server/resource/aiEmployees.js +8 -0
- package/dist/server/types/ai-message.type.d.ts +4 -0
- package/dist/server/types/knowledge-base.type.d.ts +2 -1
- package/dist/swagger/index.d.ts +29 -0
- package/dist/swagger/llm.d.ts +8 -0
- package/dist/swagger/llm.js +8 -0
- package/dist/swagger/schemas.d.ts +21 -0
- package/dist/swagger/schemas.js +11 -0
- package/package.json +2 -2
- package/dist/client/244.8631eb5cf3f05e21.js +0 -10
- package/dist/client-v2/244.c428e645ecb94414.js +0 -10
- package/dist/client-v2/420.b2aedb1ff71fca0e.js +0 -10
- package/dist/client-v2/debug-logger.d.ts +0 -52
- package/dist/server/llm-providers/deepseek.d.ts +0 -40
- package/dist/server/llm-providers/deepseek.js +0 -174
|
@@ -7,7 +7,7 @@ A storage engine based on Aliyun OSS. Before use, you need to prepare the releva
|
|
|
7
7
|
|
|
8
8
|
This engine does not support private access. After a file is uploaded, NocoBase generates a directly accessible URL, and anyone who has that URL can access the file.
|
|
9
9
|
|
|
10
|
-
Even if the OSS bucket itself is private, the built-in Aliyun OSS engine does not generate temporary signed URLs for file access. If you need private access, use [S3 Pro](./s3-pro). If historical files already exist, see [Migrate to S3 Pro](./migrate-to-s3-pro.md).
|
|
10
|
+
Even if the OSS bucket itself is private, the built-in Aliyun OSS engine does not generate temporary signed URLs for file access. If you need private access, use [S3 Pro](./s3-pro.md). If historical files already exist, see [Migrate to S3 Pro](./migrate-to-s3-pro.md).
|
|
11
11
|
|
|
12
12
|
:::
|
|
13
13
|
|
|
@@ -18,9 +18,13 @@ Even if the OSS bucket itself is private, the built-in Aliyun OSS engine does no
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
:::info{title=Note}
|
|
21
|
-
This section only introduces the specific parameters for the Aliyun OSS storage engine. For general parameters,
|
|
21
|
+
This section only introduces the specific parameters for the Aliyun OSS storage engine. For general parameters, see [General Engine Parameters](./index.md#common-parameters).
|
|
22
22
|
:::
|
|
23
23
|
|
|
24
|
+
### Base URL
|
|
25
|
+
|
|
26
|
+
Enter the file access URL prefix, such as a custom domain bound to the current bucket: `https://oss.example.com`. Accessing PDFs through the default Aliyun OSS domain may cause the browser to download them. We recommend binding a custom domain first. See [Common issues](#common-issues) below for details.
|
|
27
|
+
|
|
24
28
|
### Region
|
|
25
29
|
|
|
26
30
|
Enter the region of the OSS storage, for example: `oss-cn-hangzhou`.
|
|
@@ -43,4 +47,97 @@ Enter the name of the OSS bucket.
|
|
|
43
47
|
|
|
44
48
|
### Timeout
|
|
45
49
|
|
|
46
|
-
Enter the timeout for uploading to Aliyun OSS, in milliseconds. The default is `60000` milliseconds (i.e., 60 seconds).
|
|
50
|
+
Enter the timeout for uploading to Aliyun OSS, in milliseconds. The default is `60000` milliseconds (i.e., 60 seconds).
|
|
51
|
+
|
|
52
|
+
## Common issues
|
|
53
|
+
|
|
54
|
+
### A PDF is downloaded instead of previewed
|
|
55
|
+
|
|
56
|
+
NocoBase previews cross-origin PDFs in an iframe. The browser accesses the OSS file URL directly, so the OSS response headers determine whether the file is displayed or downloaded.
|
|
57
|
+
|
|
58
|
+
If a PDF is downloaded from the iframe, inspect the file request in the browser developer tools. A typical problematic response looks like this:
|
|
59
|
+
|
|
60
|
+
```http
|
|
61
|
+
Content-Type: application/pdf
|
|
62
|
+
Content-Disposition: attachment
|
|
63
|
+
x-oss-force-download: true
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`Content-Type: application/pdf` identifies the file correctly, but `Content-Disposition: attachment` instructs the browser to download it. The default Aliyun OSS domain forces downloads in some cases. See the official Aliyun documentation: [How do I configure a PDF file to be previewed instead of downloaded?](https://help.aliyun.com/zh/oss/user-guide/how-do-i-configure-an-object-to-be-previewed-instead-of-downloaded).
|
|
67
|
+
|
|
68
|
+
We recommend the following configuration:
|
|
69
|
+
|
|
70
|
+
1. Follow [Access OSS resources through a custom domain](https://help.aliyun.com/zh/oss/user-guide/access-buckets-via-custom-domain-names) to bind a custom domain to the bucket
|
|
71
|
+
2. Configure DNS and the HTTPS certificate, then verify that the custom domain can access the file directly
|
|
72
|
+
3. Configure the access URL for the NocoBase storage engine in use
|
|
73
|
+
|
|
74
|
+
For step 3:
|
|
75
|
+
|
|
76
|
+
- With the built-in **Aliyun OSS** engine, set **Base URL** to the bound custom domain, such as `https://oss.example.com`
|
|
77
|
+
- With [S3 Pro](./s3-pro.md) connected to Aliyun OSS, the upload endpoint can continue to use the regional OSS endpoint; set the access endpoint to the custom domain and set `Full access URL style` to `Ignore`
|
|
78
|
+
|
|
79
|
+
Upload a new PDF to verify the configuration. If an existing file record stores a complete URL, also make sure that the URL returned to the frontend now uses the custom domain.
|
|
80
|
+
|
|
81
|
+
:::tip Check the response headers
|
|
82
|
+
|
|
83
|
+
Previewing a cross-origin PDF in an iframe does not itself require CORS. Whether the PDF can be displayed inline primarily depends on `Content-Type` and `Content-Disposition`. This is separate from the CORS requirement for the download button described below.
|
|
84
|
+
|
|
85
|
+
:::
|
|
86
|
+
|
|
87
|
+
### An image previews correctly, but the download button reports a CORS error
|
|
88
|
+
|
|
89
|
+
Images are usually previewed with `<img>`, and cross-origin PDFs are previewed with an iframe. Both can display resources without CORS response headers. The download button, however, reads the file with `fetch` and creates a Blob for the browser to download. This request is subject to the browser's same-origin policy.
|
|
90
|
+
|
|
91
|
+
The following console error means that OSS did not return `Access-Control-Allow-Origin` for the current NocoBase site:
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
Access to fetch at 'https://oss.example.com/path/to/file.jpg' from origin
|
|
95
|
+
'https://example.com' has been blocked by CORS policy:
|
|
96
|
+
No 'Access-Control-Allow-Origin' header is present on the requested resource.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Follow the official Aliyun guide [Configure cross-origin resource sharing](https://help.aliyun.com/zh/oss/user-guide/configure-cross-origin-resource-sharing) and create a CORS rule for the bucket. For downloads from the preview component, use values like these:
|
|
100
|
+
|
|
101
|
+
| Setting | Recommended value |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| Allowed Origins | The complete NocoBase origin, such as `https://example.com` |
|
|
104
|
+
| Allowed Methods | `GET`, `HEAD` |
|
|
105
|
+
| Allowed Headers | `*` |
|
|
106
|
+
| Expose Headers | `ETag`, `Content-Disposition` |
|
|
107
|
+
| MaxAgeSeconds | `600` |
|
|
108
|
+
|
|
109
|
+
If S3 Pro also uploads files directly from the browser, add methods such as `PUT` and `POST` according to the actual upload requests shown in the browser Network panel, or create a separate upload rule.
|
|
110
|
+
|
|
111
|
+
After saving the rule, request the file again with the NocoBase site origin. The response should include at least:
|
|
112
|
+
|
|
113
|
+
```http
|
|
114
|
+
Access-Control-Allow-Origin: https://example.com
|
|
115
|
+
Access-Control-Allow-Methods: GET, HEAD
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The browser may already have cached the response used for the image preview. That request did not include an `Origin` header, and the cached response may not contain `Access-Control-Allow-Origin`. If downloading still fails after you configure CORS, clear the browser cache for the file or select **Disable cache** in the developer tools and try again.
|
|
119
|
+
|
|
120
|
+
### Verify the response headers
|
|
121
|
+
|
|
122
|
+
Use `curl` to simulate a cross-origin request from the NocoBase site. Replace the example origin, file URL, and signature parameters with the actual values:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
curl -sS -D - -o /dev/null \
|
|
126
|
+
-H 'Origin: https://example.com' \
|
|
127
|
+
'https://oss.example.com/path/to/file.pdf?<signed-query>'
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Check the following results:
|
|
131
|
+
|
|
132
|
+
- PDF preview returns `Content-Type: application/pdf` without `Content-Disposition: attachment`
|
|
133
|
+
- Cross-origin download returns an `Access-Control-Allow-Origin` matching the NocoBase site
|
|
134
|
+
- The actual file URL uses the custom domain instead of the default `*.oss-cn-*.aliyuncs.com` domain
|
|
135
|
+
|
|
136
|
+
It is normal for a request without an `Origin` header to omit CORS response headers. Keep the `Origin` header in the example when verifying CORS.
|
|
137
|
+
|
|
138
|
+
## Related links
|
|
139
|
+
|
|
140
|
+
- [File Preview](../file-preview/index.md)
|
|
141
|
+
- [S3 Pro](./s3-pro.md)
|
|
142
|
+
- [Migrate to S3 Pro](./migrate-to-s3-pro.md)
|
|
143
|
+
- [Storage Engines](./index.md)
|
|
@@ -6,7 +6,7 @@ keywords: "plugin build,plugin package,yarn build,tar,build.config.ts,Rsbuild,ts
|
|
|
6
6
|
|
|
7
7
|
# Build and Package
|
|
8
8
|
|
|
9
|
-
After plugin development is complete, you need to go through two steps — build (compile source code) and package (generate `.
|
|
9
|
+
After plugin development is complete, you need to go through two steps — build (compile source code) and package (generate `.tgz`) — before distributing it to other NocoBase applications.
|
|
10
10
|
|
|
11
11
|
## Build Plugin
|
|
12
12
|
|
|
@@ -26,13 +26,13 @@ If the plugin is created in a source code repository, the first build will trigg
|
|
|
26
26
|
|
|
27
27
|
## Package Plugin
|
|
28
28
|
|
|
29
|
-
Packaging compresses the build artifacts into a `.
|
|
29
|
+
Packaging compresses the build artifacts into a `.tgz` file for easy upload to other environments:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
32
|
yarn nocobase tar @my-project/plugin-hello
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
The package file is output to `storage/tar/@my-project/plugin-hello.
|
|
35
|
+
The package file is output to `storage/tar/` by default, named `<package-name>-<version>.tgz` — for example, `storage/tar/@my-project/plugin-hello-0.1.0.tgz`.
|
|
36
36
|
|
|
37
37
|
You can also combine build and package into one step using the `--tar` flag:
|
|
38
38
|
|
|
@@ -42,7 +42,13 @@ yarn build @my-project/plugin-hello --tar
|
|
|
42
42
|
|
|
43
43
|
## Upload to Other NocoBase Applications
|
|
44
44
|
|
|
45
|
-
Upload and extract the `.
|
|
45
|
+
Upload and extract the `.tgz` file to the target application's `./storage/plugins` directory. For detailed steps, see [Install and Upgrade Plugins](../get-started/install-upgrade-plugins.mdx).
|
|
46
|
+
|
|
47
|
+
If the target application was created with the NocoBase CLI (`nb init`), you can also import it directly with `nb plugin import` instead of extracting it manually:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
nb plugin import /your/path/plugin-hello-0.1.0.tgz
|
|
51
|
+
```
|
|
46
52
|
|
|
47
53
|
### Enable a Plugin by Default
|
|
48
54
|
|
|
@@ -12,7 +12,7 @@ This page collects common pitfalls when developing client plugins. If you run in
|
|
|
12
12
|
|
|
13
13
|
### Plugin not visible in the Plugin Manager after creation
|
|
14
14
|
|
|
15
|
-
Make sure you ran `yarn pm create` instead of manually creating the directory. `yarn pm create`
|
|
15
|
+
Make sure you ran `yarn pm create` instead of manually creating the directory. Besides generating files, `yarn pm create` updates `tsconfig.paths.json` and runs `yarn postinstall`, which links the plugin into `node_modules` and regenerates the client plugin index so the application can discover it. A manually created directory skips that step — run `yarn nocobase upgrade` to rescan and register it in the `applicationPlugins` table.
|
|
16
16
|
|
|
17
17
|
### No changes on the page after enabling a plugin
|
|
18
18
|
|
|
@@ -49,6 +49,8 @@ yarn pm create @my-project/plugin-simple-action
|
|
|
49
49
|
|
|
50
50
|
For detailed instructions, see [Writing Your First Plugin](../../write-your-first-plugin).
|
|
51
51
|
|
|
52
|
+
Next, start development mode so your code changes hot-reload: for a project created by `nb init`, run `nb source dev` from the project root (`<app-path>`); for a NocoBase source repository you cloned yourself, run `yarn dev` from the source root.
|
|
53
|
+
|
|
52
54
|
## Step 2: Create Action Models
|
|
53
55
|
|
|
54
56
|
Each action needs to declare the scenario it appears in via the `static scene` property:
|
|
@@ -51,6 +51,8 @@ yarn pm create @my-project/plugin-simple-block
|
|
|
51
51
|
|
|
52
52
|
This will generate a basic file structure under `packages/plugins/@my-project/plugin-simple-block`. For detailed instructions, see [Writing Your First Plugin](../../write-your-first-plugin).
|
|
53
53
|
|
|
54
|
+
Next, start development mode so your code changes hot-reload: for a project created by `nb init`, run `nb source dev` from the project root (`<app-path>`); for a NocoBase source repository you cloned yourself, run `yarn dev` from the source root.
|
|
55
|
+
|
|
54
56
|
## Step 2: Create the Block Model
|
|
55
57
|
|
|
56
58
|
Create `src/client-v2/models/SimpleBlockModel.tsx`. This is the core of the entire plugin -- defining how the block renders and how it's configured.
|
|
@@ -52,6 +52,8 @@ yarn pm create @my-project/plugin-field-simple
|
|
|
52
52
|
|
|
53
53
|
For detailed instructions, see [Writing Your First Plugin](../../write-your-first-plugin).
|
|
54
54
|
|
|
55
|
+
Next, start development mode so your code changes hot-reload: for a project created by `nb init`, run `nb source dev` from the project root (`<app-path>`); for a NocoBase source repository you cloned yourself, run `yarn dev` from the source root.
|
|
56
|
+
|
|
55
57
|
## Step 2: Create the Field Model
|
|
56
58
|
|
|
57
59
|
Create `src/client-v2/models/DisplaySimpleFieldModel.tsx`. This is the core of the plugin -- defining how the field renders and which field interface it binds to.
|
|
@@ -55,6 +55,8 @@ yarn pm create @my-project/plugin-custom-table-block-resource
|
|
|
55
55
|
|
|
56
56
|
For detailed instructions, see [Writing Your First Plugin](../../write-your-first-plugin).
|
|
57
57
|
|
|
58
|
+
Next, start development mode so your code changes hot-reload: for a project created by `nb init`, run `nb source dev` from the project root (`<app-path>`); for a NocoBase source repository you cloned yourself, run `yarn dev` from the source root.
|
|
59
|
+
|
|
58
60
|
## Step 2: Define the Data Table (Server-Side)
|
|
59
61
|
|
|
60
62
|
Create `src/server/collections/todoItems.ts`. NocoBase will automatically load collection definitions from this directory:
|
|
@@ -52,6 +52,8 @@ yarn pm create @my-project/plugin-settings-page
|
|
|
52
52
|
|
|
53
53
|
This will generate a basic file structure under `packages/plugins/@my-project/plugin-settings-page`, including `src/client-v2/`, `src/server/`, `src/locale/`, and other directories. For detailed instructions, see [Writing Your First Plugin](../../write-your-first-plugin).
|
|
54
54
|
|
|
55
|
+
Next, start development mode so your code changes hot-reload: for a project created by `nb init`, run `nb source dev` from the project root (`<app-path>`); for a NocoBase source repository you cloned yourself, run `yarn dev` from the source root.
|
|
56
|
+
|
|
55
57
|
## Step 2: Register the Settings Page
|
|
56
58
|
|
|
57
59
|
Edit `src/client-v2/plugin.tsx`. In `load()`, use `this.pluginSettingsManager` to register the settings page. This is done in two steps -- first register the menu entry with `addMenuItem()`, then register the actual page with `addPageTabItem()`:
|
|
@@ -61,11 +61,11 @@ export class PluginSampleI18nServer extends Plugin {
|
|
|
61
61
|
},
|
|
62
62
|
],
|
|
63
63
|
});
|
|
64
|
-
await this.app.changeLanguage(answer1);
|
|
64
|
+
await this.app.i18n.changeLanguage(answer1);
|
|
65
65
|
const answer2 = await input({
|
|
66
|
-
message: app.i18n.t('Enter your name'),
|
|
66
|
+
message: this.app.i18n.t('Enter your name'),
|
|
67
67
|
});
|
|
68
|
-
console.log(app.i18n.t(`Your name is {{name}}`, { name: answer2 }));
|
|
68
|
+
console.log(this.app.i18n.t(`Your name is {{name}}`, { name: answer2 }));
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -212,7 +212,7 @@ export default class PluginCacheDemo extends Plugin {
|
|
|
212
212
|
});
|
|
213
213
|
|
|
214
214
|
// Create cache using newly registered store
|
|
215
|
-
const redisCache = await this.app.createCache({
|
|
215
|
+
const redisCache = await this.app.cacheManager.createCache({
|
|
216
216
|
name: 'redisCache',
|
|
217
217
|
store: 'redis',
|
|
218
218
|
prefix: 'app:',
|
|
@@ -197,12 +197,6 @@ When a plugin is first activated, the system will automatically synchronize Coll
|
|
|
197
197
|
yarn nocobase upgrade
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
If exceptions or dirty data occur during synchronization, you can rebuild the table structure by reinstalling the application:
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
yarn nocobase install -f
|
|
204
|
-
```
|
|
205
|
-
|
|
206
200
|
If you need to migrate existing data during plugin upgrades -- such as renaming fields, splitting tables, backfilling default values, etc. -- you should handle it through [Migration](./migration.md) scripts rather than manually modifying the database.
|
|
207
201
|
|
|
208
202
|
## Making a Collection Appear in the UI Data Table List
|
|
@@ -30,7 +30,7 @@ export default function (app: Application) {
|
|
|
30
30
|
app
|
|
31
31
|
.command('echo')
|
|
32
32
|
.option('-v, --version')
|
|
33
|
-
.action(async (
|
|
33
|
+
.action(async (options) => {
|
|
34
34
|
console.log('Hello World!');
|
|
35
35
|
if (options.version) {
|
|
36
36
|
console.log('Current version:', await app.version.get());
|
|
@@ -68,7 +68,7 @@ export default class PluginHelloServer extends Plugin {
|
|
|
68
68
|
app
|
|
69
69
|
.command('echo')
|
|
70
70
|
.option('-v, --version')
|
|
71
|
-
.action(async (
|
|
71
|
+
.action(async (options) => {
|
|
72
72
|
console.log('Hello World!');
|
|
73
73
|
if (options.version) {
|
|
74
74
|
console.log('Current version:', await app.version.get());
|
|
@@ -56,7 +56,7 @@ resourceManager.use(async (ctx) => {
|
|
|
56
56
|
|
|
57
57
|
```ts
|
|
58
58
|
resourceManager.use(async (ctx) => {
|
|
59
|
-
await ctx.cache.set('key', 'value',
|
|
59
|
+
await ctx.cache.set('key', 'value', 60 * 1000); // Cache for 60 seconds (TTL is in milliseconds)
|
|
60
60
|
const val = await ctx.cache.get('key');
|
|
61
61
|
ctx.body = val;
|
|
62
62
|
});
|
|
@@ -113,7 +113,7 @@ resourceManager.use(async (ctx) => {
|
|
|
113
113
|
|
|
114
114
|
```ts
|
|
115
115
|
resourceManager.use(async (ctx) => {
|
|
116
|
-
const canEdit =
|
|
116
|
+
const canEdit = ctx.can({ resource: 'posts', action: 'edit' });
|
|
117
117
|
if (!canEdit) {
|
|
118
118
|
ctx.throw(403, 'Forbidden');
|
|
119
119
|
}
|
|
@@ -68,13 +68,13 @@ export class PluginSampleI18nServer extends Plugin {
|
|
|
68
68
|
]
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
await this.app.changeLanguage(answer1);
|
|
71
|
+
await this.app.i18n.changeLanguage(answer1);
|
|
72
72
|
|
|
73
73
|
const answer2 = await input({
|
|
74
|
-
message: app.i18n.t('Enter your name')
|
|
74
|
+
message: this.app.i18n.t('Enter your name')
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
console.log(app.i18n.t('Your name is {{name}}', { name: answer2 }));
|
|
77
|
+
console.log(this.app.i18n.t('Your name is {{name}}', { name: answer2 }));
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -129,7 +129,7 @@ export class PluginSampleI18nServer extends Plugin {
|
|
|
129
129
|
load() {
|
|
130
130
|
this.app.use(async (ctx, next) => {
|
|
131
131
|
if (ctx.path === '/api/plugin-i18n') {
|
|
132
|
-
ctx.body = this.
|
|
132
|
+
ctx.body = this.t('Hello');
|
|
133
133
|
}
|
|
134
134
|
await next();
|
|
135
135
|
});
|
|
@@ -28,50 +28,83 @@ yarn pm create @my-project/plugin-hello
|
|
|
28
28
|
After the command runs successfully, it will generate basic files in the `packages/plugins/@my-project/plugin-hello` directory. The default structure is as follows:
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
31
|
+
packages/plugins/@my-project/plugin-hello/
|
|
32
|
+
├─ package.json
|
|
33
|
+
├─ README.md
|
|
34
|
+
├─ .npmignore
|
|
35
|
+
├─ client-v2.d.ts # v2 client entry type declaration
|
|
36
|
+
├─ client-v2.js # v2 client entry
|
|
37
|
+
├─ client.d.ts # v1 client entry type declaration
|
|
38
|
+
├─ client.js # v1 client entry
|
|
39
|
+
├─ server.d.ts # Server entry type declaration
|
|
40
|
+
├─ server.js # Server entry
|
|
41
|
+
└─ src
|
|
42
|
+
├─ index.ts # Default export server-side plugin
|
|
43
|
+
├─ client-v2 # v2 client-side code location
|
|
44
|
+
│ ├─ index.tsx # Default exported client-side plugin class
|
|
45
|
+
│ ├─ plugin.tsx # Plugin entry (extends @nocobase/client-v2 Plugin)
|
|
46
|
+
│ └─ client.d.ts
|
|
47
|
+
├─ client # v1 client-side code location
|
|
48
|
+
│ ├─ index.tsx
|
|
49
|
+
│ ├─ plugin.tsx
|
|
50
|
+
│ ├─ locale.ts
|
|
51
|
+
│ ├─ models
|
|
52
|
+
│ │ └─ index.ts
|
|
53
|
+
│ └─ client.d.ts
|
|
54
|
+
├─ server # Server-side code location
|
|
55
|
+
│ ├─ index.ts # Default exported server-side plugin class
|
|
56
|
+
│ ├─ plugin.ts # Plugin entry (extends @nocobase/server Plugin)
|
|
57
|
+
│ └─ collections # Server-side collections (empty directory initially)
|
|
58
|
+
└─ locale # Locale resources
|
|
59
|
+
├─ en-US.json
|
|
60
|
+
└─ zh-CN.json
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
The scaffold generates a minimal skeleton — `src/client-v2/` contains only entry files. The `models/` directory and `locale.ts` used in the following steps are ones you create yourself.
|
|
64
|
+
|
|
65
|
+
Next, start development mode so your code changes hot-reload:
|
|
66
|
+
|
|
67
|
+
- If the project was created with the NocoBase CLI (`nb init`), run this from the project root (`<app-path>`):
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
nb source dev
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
- If you cloned the NocoBase source repository yourself, run this from the source root:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
yarn dev
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Once it is running, access the plugin manager page in your browser (default URL: http://localhost:13000/admin/settings/plugin-manager) to confirm whether the plugin appears in the list.
|
|
64
80
|
|
|
65
81
|
## Step 2: Implement a Simple Client Block
|
|
66
82
|
|
|
67
83
|
Next, we'll add a custom block model to the plugin to display a welcome message.
|
|
68
84
|
|
|
69
|
-
1. **Create
|
|
85
|
+
1. **Create the translation helper file** `src/client-v2/locale.ts`. `tExpr` declares a namespaced translation expression, and `useT` provides the translation function inside components:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { tExpr as _tExpr, useFlowEngine } from '@nocobase/flow-engine';
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
import pkg from '../../package.json';
|
|
91
|
+
|
|
92
|
+
export function useT() {
|
|
93
|
+
const engine = useFlowEngine();
|
|
94
|
+
return (str: string) => engine.context.t(str, { ns: [pkg.name, 'client'] });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function tExpr(key: string) {
|
|
98
|
+
return _tExpr(key, { ns: [pkg.name, 'client'] });
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
2. **Create a new block model file** `src/client-v2/models/HelloBlockModel.tsx`:
|
|
70
103
|
|
|
71
104
|
```tsx pure
|
|
72
|
-
import { BlockModel } from '@nocobase/client-v2';
|
|
73
105
|
import React from 'react';
|
|
74
|
-
import {
|
|
106
|
+
import { BlockModel } from '@nocobase/client-v2';
|
|
107
|
+
import { tExpr } from '../locale';
|
|
75
108
|
|
|
76
109
|
export class HelloBlockModel extends BlockModel {
|
|
77
110
|
renderComponent() {
|
|
@@ -89,18 +122,27 @@ HelloBlockModel.define({
|
|
|
89
122
|
});
|
|
90
123
|
```
|
|
91
124
|
|
|
92
|
-
|
|
125
|
+
3. **Register the block model**. Creating the model file is not enough on its own — the frontend runtime does not scan the `models/` directory automatically, so you have to register it explicitly in the plugin entry. Edit `src/client-v2/plugin.tsx` and declare how the model is loaded via `registerModelLoaders` inside `load()`:
|
|
93
126
|
|
|
94
|
-
```
|
|
95
|
-
import {
|
|
96
|
-
|
|
127
|
+
```tsx pure
|
|
128
|
+
import { Plugin } from '@nocobase/client-v2';
|
|
129
|
+
|
|
130
|
+
export class PluginHelloClientV2 extends Plugin {
|
|
131
|
+
async load() {
|
|
132
|
+
this.flowEngine.registerModelLoaders({
|
|
133
|
+
HelloBlockModel: {
|
|
134
|
+
loader: () => import('./models/HelloBlockModel'),
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
97
139
|
|
|
98
|
-
export default
|
|
99
|
-
HelloBlockModel,
|
|
100
|
-
} as Record<string, ModelConstructor>;
|
|
140
|
+
export default PluginHelloClientV2;
|
|
101
141
|
```
|
|
102
142
|
|
|
103
|
-
|
|
143
|
+
`registerModelLoaders` takes lazy-loading functions, so a model is only loaded once it is actually used. The key (`HelloBlockModel`) must match the model class name — the runtime uses it to pick the model class out of the module's named exports.
|
|
144
|
+
|
|
145
|
+
After saving the code, if you're running development mode, you should see hot-reload logs in the terminal output.
|
|
104
146
|
|
|
105
147
|
## Step 3: Activate and Test the Plugin
|
|
106
148
|
|
|
@@ -162,7 +204,7 @@ If the plugin is created in a source code repository, the first build will trigg
|
|
|
162
204
|
|
|
163
205
|
:::
|
|
164
206
|
|
|
165
|
-
After the build completes, the package file is located
|
|
207
|
+
After the build completes, the package file is located under `storage/tar/` by default, named `<package-name>-<version>.tgz` — for example, `storage/tar/@my-project/plugin-hello-0.1.0.tgz`.
|
|
166
208
|
|
|
167
209
|
:::tip
|
|
168
210
|
|
|
@@ -174,6 +216,12 @@ It's recommended to write test cases to verify core logic before publishing a pl
|
|
|
174
216
|
|
|
175
217
|
Upload and extract the package file to the target application's `./storage/plugins` directory. For detailed steps, see [Install and Upgrade Plugins](../get-started/install-upgrade-plugins.mdx).
|
|
176
218
|
|
|
219
|
+
If the target application was created with the NocoBase CLI (`nb init`), you can also import it directly with `nb plugin import` instead of extracting it manually:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
nb plugin import /your/path/plugin-hello-0.1.0.tgz
|
|
223
|
+
```
|
|
224
|
+
|
|
177
225
|
## Related Links
|
|
178
226
|
|
|
179
227
|
- [Plugin Development Overview](./index.md) — Understand NocoBase microkernel architecture and plugin lifecycle
|
|
@@ -10,7 +10,7 @@ description: |
|
|
|
10
10
|
Duplicate a record, you can either duplicate it into a form and edit it before saving it, or you can duplicate it directly to generate a new record.
|
|
11
11
|
isFree: true
|
|
12
12
|
builtIn: true
|
|
13
|
-
defaultEnabled:
|
|
13
|
+
defaultEnabled: true
|
|
14
14
|
editionLevel: 0
|
|
15
15
|
---
|
|
16
16
|
|