@allbluecn/web-app 0.22.4 → 0.23.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/package.json +4 -14
- package/src/__tests__/integration/login-email-acceptance.test.ts +16 -0
- package/src/__tests__/story-view.test.ts +33 -1
- package/src/components/agents/__tests__/agent-bindings-tab.test.tsx +221 -0
- package/src/components/agents/__tests__/agents-page.test.tsx +284 -0
- package/src/components/agents/agent-bindings-tab.tsx +59 -45
- package/src/components/agents/agent-form-dialog.tsx +3 -3
- package/src/components/agents/agent-selector.tsx +2 -3
- package/src/components/agents/agents-page.tsx +66 -31
- package/src/components/agents/slash-skill-menu.tsx +2 -3
- package/src/components/auth/__tests__/session-guard.test.tsx +74 -0
- package/src/components/auth/session-guard.tsx +8 -0
- package/src/components/billing/login-prompt-dialog.tsx +1 -1
- package/src/components/billing/subscription-provider.tsx +2 -16
- package/src/components/bug/__tests__/peek-modes.test.tsx +8 -0
- package/src/components/bug/__tests__/subgroup-header.test.tsx +202 -40
- package/src/components/bug/peek-panel.tsx +5 -3
- package/src/components/bug/views/bug-list/group.tsx +12 -2
- package/src/components/bug/views/bug-list/index.tsx +94 -67
- package/src/components/command/command-palette.tsx +10 -9
- package/src/components/design/canvas/document/frame-custom-presets.ts +9 -1
- package/src/components/design/canvas/panels/toolbar.tsx +21 -22
- package/src/components/design/canvas/react/__tests__/canvas-context-load-echo.test.tsx +199 -0
- package/src/components/design/canvas/react/__tests__/hooks.test.tsx +17 -3
- package/src/components/design/canvas/react/canvas-context.tsx +47 -26
- package/src/components/design/canvas/react/hooks.ts +39 -34
- package/src/components/design/editor/layout/__tests__/collab-param-wiring.test.tsx +17 -0
- package/src/components/design/editor/layout/__tests__/context-menu.test.tsx +17 -1
- package/src/components/design/editor/layout/__tests__/no-page-save-toast.test.tsx +17 -0
- package/src/components/design/editor/layout/__tests__/persistence-restore.test.tsx +17 -1
- package/src/components/design/editor/layout/__tests__/ssr-localstorage-smoke.test.tsx +17 -1
- package/src/components/design/editor/layout/design-editor-layout.tsx +13 -2
- package/src/components/design/editor/layout/hooks/use-design-auto-save.ts +3 -19
- package/src/components/devtools/devtools-panel.tsx +56 -0
- package/src/components/forms/__tests__/create-app-form.test.tsx +131 -0
- package/src/components/forms/app-field-error.tsx +21 -1
- package/src/components/forms/app-field.tsx +8 -8
- package/src/components/forms/app-submit.tsx +12 -9
- package/src/components/forms/create-app-form.tsx +124 -0
- package/src/components/forms/index.ts +2 -3
- package/src/components/harness/__tests__/gallery-behavior.test.tsx +37 -1
- package/src/components/harness/__tests__/harness-workbench-first-send.test.tsx +4 -1
- package/src/components/harness/__tests__/message-actions.test.tsx +7 -6
- package/src/components/harness/__tests__/use-video-generation.test.tsx +165 -0
- package/src/components/harness/ai-chat-history/index.tsx +5 -3
- package/src/components/harness/gallery/gallery-card.tsx +57 -35
- package/src/components/harness/gallery/gallery-grid.tsx +32 -15
- package/src/components/harness/gallery/gallery-types.ts +19 -0
- package/src/components/harness/gallery/gallery-video-card.tsx +54 -0
- package/src/components/harness/gallery/types.ts +2 -0
- package/src/components/harness/gallery/use-video-generation.ts +95 -0
- package/src/components/harness/harness-workbench-page.tsx +2 -3
- package/src/components/harness/message-actions.tsx +5 -3
- package/src/components/hotkeys/shortcuts-panel.tsx +28 -13
- package/src/components/iteration/__tests__/burndown-chart.test.tsx +118 -0
- package/src/components/iteration/burndown-chart.tsx +54 -23
- package/src/components/knowledge/editor/__tests__/knowledge-doc-editor-collab.test.tsx +96 -0
- package/src/components/knowledge/editor/knowledge-doc-editor.tsx +56 -1
- package/src/components/knowledge/editor/mindmap-doc-editor.tsx +12 -0
- package/src/components/knowledge/editor/use-auto-save-channels.ts +3 -1
- package/src/components/layout/sidebar-03/__tests__/nav-workspace.test.tsx +0 -4
- package/src/components/layout/sidebar-03/nav-knowledge.tsx +11 -11
- package/src/components/layout/sidebar-03/nav-main.tsx +12 -15
- package/src/components/layout/sidebar-03/nav-notifications.tsx +5 -8
- package/src/components/layout/sidebar-03/nav-workspace.tsx +11 -9
- package/src/components/notifications/__tests__/settings-notifications.test.tsx +158 -0
- package/src/components/notifications/settings-notifications.tsx +37 -13
- package/src/components/notifications/team-notifications.tsx +10 -14
- package/src/components/settings/personal-team/account/__tests__/account-client.test.tsx +170 -0
- package/src/components/settings/personal-team/account/account-client.tsx +44 -7
- package/src/components/settings/personal-team/team/team-client.tsx +17 -19
- package/src/components/shared-kit/list-kit/__tests__/frozen-header.test.ts +210 -41
- package/src/components/shared-kit/list-kit/frozen-header.ts +134 -21
- package/src/components/shared-kit/list-kit/kanban/frozen-header.ts +20 -27
- package/src/components/story/__tests__/peek-panel-patch-sync.test.tsx +8 -0
- package/src/components/story/__tests__/story-list-table.test.tsx +214 -0
- package/src/components/story/columns.tsx +11 -2
- package/src/components/story/peek-panel.tsx +4 -2
- package/src/components/story/story-list-table.tsx +16 -1
- package/src/components/story/views/story-list/__tests__/frozen-headers.test.tsx +186 -0
- package/src/components/story/views/story-list/group.tsx +12 -1
- package/src/components/story/views/story-list/index.tsx +101 -68
- package/src/components/testcase/__tests__/case-row.test.tsx +134 -2
- package/src/components/testcase/__tests__/peek-panel.test.tsx +8 -0
- package/src/components/testcase/__tests__/step-editor.test.tsx +106 -0
- package/src/components/testcase/list/grouped-list.tsx +50 -22
- package/src/components/testcase/peek-panel.tsx +7 -4
- package/src/components/testcase/step-editor.tsx +196 -150
- package/src/components/tiptap/notion-like/editor-extensions.ts +0 -3
- package/src/components/tiptap/notion-like/notion-like-editor-header.tsx +1 -31
- package/src/components/tiptap/notion-like/notion-like-editor.tsx +32 -1
- package/src/components/workspace/__tests__/dialogs/create-workspace-dialog.test.tsx +2 -28
- package/src/components/workspace/__tests__/dialogs/edit-workspace-dialog.test.tsx +2 -28
- package/src/components/workspace/dialogs/create-workspace-dialog.tsx +45 -43
- package/src/components/workspace/dialogs/edit-workspace-dialog.tsx +38 -36
- package/src/design-engine/engine/engine-decor.ts +2 -0
- package/src/design-engine/engine/engine-path.ts +2 -0
- package/src/hooks/__tests__/use-unsaved-guard.test.tsx +180 -0
- package/src/hooks/use-notifications.ts +9 -16
- package/src/hooks/use-unsaved-guard.tsx +87 -0
- package/src/lib/__tests__/pacer.test.ts +33 -96
- package/src/lib/__tests__/query-defaults.test.ts +169 -0
- package/src/lib/__tests__/query-global-error.test.ts +256 -0
- package/src/lib/anyhub/anyhub-store.ts +2 -2
- package/src/lib/changelog/sdk-versions.ts +2 -10
- package/src/lib/collab/presence-store.ts +5 -5
- package/src/lib/collab/use-presence-list-refresh.ts +2 -2
- package/src/lib/collab/use-share-presence.ts +2 -2
- package/src/lib/collections/query-keys.ts +7 -2
- package/src/lib/commands/__tests__/command-palette-state.test.ts +12 -14
- package/src/lib/commands/__tests__/registry.test.ts +6 -3
- package/src/lib/commands/command-palette-state.ts +8 -31
- package/src/lib/hotkeys/__tests__/registry.test.ts +71 -18
- package/src/lib/hotkeys/registry.ts +188 -85
- package/src/lib/hotkeys/types.ts +1 -13
- package/src/lib/pacer.ts +1 -79
- package/src/lib/queries/README.md +67 -0
- package/src/lib/queries/__tests__/agents-queries.test.ts +101 -0
- package/src/lib/queries/__tests__/compliance-queries.test.ts +136 -0
- package/src/lib/queries/__tests__/notifications-queries.test.ts +175 -0
- package/src/lib/queries/__tests__/team-queries.test.ts +87 -0
- package/src/lib/queries/agents.ts +40 -0
- package/src/lib/queries/compliance.ts +69 -0
- package/src/lib/queries/notifications.ts +63 -0
- package/src/lib/queries/team.ts +39 -0
- package/src/lib/query-defaults.ts +8 -0
- package/src/lib/query-global-error.ts +128 -0
- package/src/lib/remote-auth-client.ts +16 -0
- package/src/paraglide/README.md +1 -1
- package/src/paraglide/messages/_index.d.ts +11 -0
- package/src/paraglide/messages/_index.js +5659 -88285
- package/src/paraglide/messages/common_error_generic.d.ts +16 -0
- package/src/paraglide/messages/common_error_generic.js +29 -0
- package/src/paraglide/messages/common_unsaved_body.d.ts +16 -0
- package/src/paraglide/messages/common_unsaved_body.js +29 -0
- package/src/paraglide/messages/common_unsaved_leave.d.ts +16 -0
- package/src/paraglide/messages/common_unsaved_leave.js +29 -0
- package/src/paraglide/messages/common_unsaved_stay.d.ts +16 -0
- package/src/paraglide/messages/common_unsaved_stay.js +29 -0
- package/src/paraglide/messages/common_unsaved_title.d.ts +16 -0
- package/src/paraglide/messages/common_unsaved_title.js +29 -0
- package/src/paraglide/messages/gallery_videofailed1.d.ts +17 -0
- package/src/paraglide/messages/gallery_videofailed1.js +30 -0
- package/src/paraglide/messages/gallery_videogenerating1.d.ts +17 -0
- package/src/paraglide/messages/gallery_videogenerating1.js +30 -0
- package/src/paraglide/messages/gallery_videomissingprompt2.d.ts +17 -0
- package/src/paraglide/messages/gallery_videomissingprompt2.js +30 -0
- package/src/paraglide/messages/gallery_videoprogress1.d.ts +19 -0
- package/src/paraglide/messages/gallery_videoprogress1.js +30 -0
- package/src/paraglide/messages/gallery_videostop1.d.ts +17 -0
- package/src/paraglide/messages/gallery_videostop1.js +30 -0
- package/src/paraglide/messages/story_table_resizecolumn1.d.ts +17 -0
- package/src/paraglide/messages/story_table_resizecolumn1.js +30 -0
- package/src/providers/index.tsx +5 -50
- package/src/routeTree.gen.ts +21 -0
- package/src/router.tsx +21 -8
- package/src/routes/__root.tsx +2 -1
- package/src/routes/__tests__/-edition-routing.test.tsx +6 -1
- package/src/routes/_login/forgot-password/route.lazy.tsx +7 -6
- package/src/routes/_login/login/route.lazy.tsx +10 -9
- package/src/routes/_login/register/route.lazy.tsx +19 -18
- package/src/routes/_login/reset-password/route.lazy.tsx +10 -9
- package/src/routes/_nav/knowledge/compliance/$id.lazy.tsx +9 -12
- package/src/routes/_nav/knowledge/compliance/index.lazy.tsx +16 -13
- package/src/routes/_nav/knowledge/laws/$id.lazy.tsx +1 -1
- package/src/routes/_nav/notifications/route.tsx +6 -16
- package/src/routes/_nav/settings/-settings-tabs.tsx +9 -12
- package/src/routes/api/generate/__tests__/media.test.ts +378 -0
- package/src/routes/api/generate/media.ts +179 -0
- package/src/server/__tests__/agent-client-graph.test.ts +0 -1
- package/src/server/__tests__/agent-crud.test.ts +37 -4
- package/src/server/__tests__/bug-groups-two-level.test.ts +34 -1
- package/src/server/__tests__/chat-conversations.test.ts +37 -4
- package/src/server/__tests__/chat-list-messages.test.ts +40 -7
- package/src/server/__tests__/csv-export.test.ts +36 -3
- package/src/server/__tests__/desktop-bootstrap.test.ts +189 -0
- package/src/server/__tests__/remote-auth.test.ts +72 -0
- package/src/server/__tests__/skill-crud.test.ts +37 -4
- package/src/server/__tests__/sso-domain.test.ts +1 -1
- package/src/server/__tests__/sso-rate-limit-singleton.test.ts +123 -0
- package/src/server/__tests__/task-serverfn-crud.test.ts +35 -2
- package/src/server/__tests__/task-serverfn-queries.test.ts +35 -2
- package/src/server/__tests__/testcase-board.test.ts +38 -5
- package/src/server/__tests__/testcase-bulk.test.ts +38 -5
- package/src/server/__tests__/testcase-list-scope.test.ts +38 -5
- package/src/server/ai-gateway/__tests__/ai-output-guard.test.ts +126 -2
- package/src/server/ai-gateway/__tests__/chat-stream-builder-code-mode.test.ts +4 -0
- package/src/server/ai-gateway/__tests__/chat-stream-builder-memory.test.ts +4 -0
- package/src/server/ai-gateway/__tests__/chat-stream-builder-sandbox.test.ts +4 -0
- package/src/server/ai-gateway/__tests__/chat-stream-builder-skills.test.ts +4 -0
- package/src/server/ai-gateway/__tests__/pgvector-memory-adapter.test.ts +30 -0
- package/src/server/ai-gateway/__tests__/pgvector-memory-conformance.test.ts +92 -0
- package/src/server/ai-gateway/__tests__/source-mode.test.ts +49 -8
- package/src/server/ai-gateway/ai-output-guard.ts +50 -2
- package/src/server/ai-gateway/chat-stream-builder.ts +3 -0
- package/src/server/ai-gateway/media/index.ts +36 -29
- package/src/server/ai-gateway/media/trim-input.ts +52 -0
- package/src/server/ai-gateway/memory/pgvector-adapter.ts +27 -13
- package/src/server/ai-gateway/sandbox/__tests__/harness-sandbox.test.ts +252 -41
- package/src/server/ai-gateway/sandbox/harness-sandbox.ts +6 -67
- package/src/server/ai-gateway/source-mode.ts +24 -8
- package/src/server/desktop-bootstrap.ts +74 -0
- package/src/server/lib/__tests__/rate-limit.test.ts +0 -1
- package/src/server/lib/rate-limit.ts +0 -2
- package/src/server/middlewares/__tests__/auth-context.test.ts +156 -0
- package/src/server/middlewares/auth-context.ts +62 -0
- package/src/server/remote-auth.ts +58 -31
- package/src/server/serverFns/__tests__/ai-hosted-models.test.ts +47 -15
- package/src/server/serverFns/__tests__/ai-source-mode.test.ts +45 -15
- package/src/server/serverFns/__tests__/billing.test.ts +37 -2
- package/src/server/serverFns/__tests__/collab-snapshot.test.ts +41 -14
- package/src/server/serverFns/__tests__/collab.test.ts +41 -14
- package/src/server/serverFns/__tests__/compliance.test.ts +33 -1
- package/src/server/serverFns/__tests__/email-verification.test.ts +35 -1
- package/src/server/serverFns/__tests__/knowledge-breadcrumb.test.ts +46 -6
- package/src/server/serverFns/__tests__/knowledge-delete.test.ts +42 -14
- package/src/server/serverFns/__tests__/knowledge-kb-projects.test.ts +46 -6
- package/src/server/serverFns/__tests__/knowledge-public-compliance.test.ts +36 -2
- package/src/server/serverFns/__tests__/knowledge-readable-kb.test.ts +42 -10
- package/src/server/serverFns/__tests__/knowledge-search.test.ts +45 -9
- package/src/server/serverFns/__tests__/legal-code-canonical.test.ts +36 -2
- package/src/server/serverFns/__tests__/link-preview.test.ts +38 -4
- package/src/server/serverFns/__tests__/notifications-list.test.ts +36 -3
- package/src/server/serverFns/__tests__/ownership-merge.test.ts +38 -4
- package/src/server/serverFns/__tests__/project-delete-transaction.test.ts +39 -2
- package/src/server/serverFns/__tests__/project-kb.test.ts +34 -1
- package/src/server/serverFns/__tests__/project-member-idor.test.ts +34 -1
- package/src/server/serverFns/__tests__/project-team-assign.test.ts +34 -1
- package/src/server/serverFns/__tests__/read-write-merge.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-comments.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-crud-archive-detail.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-crud-labels-users.test.ts +37 -3
- package/src/server/serverFns/__tests__/story-crud.test.ts +36 -3
- package/src/server/serverFns/__tests__/story-links.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-reactions.test.ts +38 -4
- package/src/server/serverFns/__tests__/story-tree.test.ts +38 -4
- package/src/server/serverFns/__tests__/team-accept.test.ts +34 -1
- package/src/server/serverFns/__tests__/team-invitation.test.ts +34 -1
- package/src/server/serverFns/__tests__/team-join-request.test.ts +34 -1
- package/src/server/serverFns/__tests__/team-members.test.ts +34 -1
- package/src/server/serverFns/__tests__/team-ownership-merge.test.ts +34 -1
- package/src/server/serverFns/__tests__/update-bug-guard.test.ts +37 -3
- package/src/server/serverFns/__tests__/update-document-guard.test.ts +38 -4
- package/src/server/serverFns/__tests__/update-page-guard.test.ts +40 -4
- package/src/server/serverFns/__tests__/update-seats.test.ts +33 -1
- package/src/server/serverFns/__tests__/update-story-guard.test.ts +36 -3
- package/src/server/serverFns/__tests__/update-testcase-guard.test.ts +37 -3
- package/src/server/serverFns/__tests__/workspace-kb-idor.test.ts +36 -2
- package/src/server/serverFns/__tests__/workspace-kb.test.ts +36 -2
- package/src/server/serverFns/__tests__/workspace.test.ts +34 -1
- package/src/server/serverFns/activity.ts +10 -14
- package/src/server/serverFns/agents/agent-crud.ts +16 -15
- package/src/server/serverFns/agents/bindings.ts +12 -13
- package/src/server/serverFns/agents/skill-crud.ts +16 -15
- package/src/server/serverFns/ai/code-mode-readiness.ts +3 -4
- package/src/server/serverFns/ai/search-capability.ts +3 -4
- package/src/server/serverFns/anyhub/app.ts +10 -14
- package/src/server/serverFns/anyhub/index.ts +7 -10
- package/src/server/serverFns/anyhub/install.ts +4 -4
- package/src/server/serverFns/anyhub/permissions.ts +10 -14
- package/src/server/serverFns/anyhub/proxy.ts +4 -6
- package/src/server/serverFns/auth/email-verification.ts +4 -5
- package/src/server/serverFns/auth/session.ts +9 -0
- package/src/server/serverFns/billing.ts +18 -28
- package/src/server/serverFns/blob-upload.ts +6 -9
- package/src/server/serverFns/bug/__tests__/bug-access-tokens.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-activities.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-comments.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-crud.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-fix.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-groups.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-reactions.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-reorder.test.ts +39 -5
- package/src/server/serverFns/bug/__tests__/bug-repro.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-story.test.ts +34 -1
- package/src/server/serverFns/bug/__tests__/bug-webhooks.test.ts +34 -1
- package/src/server/serverFns/bug/bug-access-tokens.ts +16 -22
- package/src/server/serverFns/bug/bug-activities.ts +4 -6
- package/src/server/serverFns/bug/bug-collect-tokens.ts +13 -18
- package/src/server/serverFns/bug/bug-comments.ts +13 -18
- package/src/server/serverFns/bug/bug-crud/detail.ts +10 -14
- package/src/server/serverFns/bug/bug-crud.ts +28 -38
- package/src/server/serverFns/bug/bug-display-options.ts +8 -11
- package/src/server/serverFns/bug/bug-export.ts +5 -7
- package/src/server/serverFns/bug/bug-fix.ts +10 -14
- package/src/server/serverFns/bug/bug-groups.ts +10 -14
- package/src/server/serverFns/bug/bug-reactions.ts +10 -14
- package/src/server/serverFns/bug/bug-reorder.ts +4 -6
- package/src/server/serverFns/bug/bug-repro.ts +8 -11
- package/src/server/serverFns/bug/bug-story-bulk.ts +13 -18
- package/src/server/serverFns/bug/bug-story.ts +10 -14
- package/src/server/serverFns/bug/bug-views.ts +12 -18
- package/src/server/serverFns/bug/bug-webhooks.ts +13 -18
- package/src/server/serverFns/bug/test-bug-confirm.ts +7 -10
- package/src/server/serverFns/changelog/__tests__/fetch.test.ts +40 -1
- package/src/server/serverFns/changelog/fetch.ts +4 -6
- package/src/server/serverFns/chat/conversations.ts +17 -28
- package/src/server/serverFns/chat/list-messages.ts +4 -7
- package/src/server/serverFns/collab-presence.ts +11 -13
- package/src/server/serverFns/collab-snapshot.ts +6 -7
- package/src/server/serverFns/collab.ts +7 -7
- package/src/server/serverFns/compliance.ts +8 -8
- package/src/server/serverFns/design/__tests__/comments.test.ts +54 -10
- package/src/server/serverFns/design/__tests__/designs.test.ts +39 -16
- package/src/server/serverFns/design/__tests__/page-versions.test.ts +52 -14
- package/src/server/serverFns/design/__tests__/shares-password.test.ts +44 -14
- package/src/server/serverFns/design/__tests__/shares.test.ts +44 -14
- package/src/server/serverFns/design/__tests__/versions.test.ts +44 -14
- package/src/server/serverFns/design/ai/__tests__/agent-conversations.test.ts +50 -21
- package/src/server/serverFns/design/ai/__tests__/providers.test.ts +42 -8
- package/src/server/serverFns/design/ai/agent-conversations.ts +19 -26
- package/src/server/serverFns/design/ai/fill-annotation.ts +5 -7
- package/src/server/serverFns/design/ai/generate-prototype.ts +5 -7
- package/src/server/serverFns/design/ai/hosted-models.ts +4 -5
- package/src/server/serverFns/design/ai/providers.ts +30 -39
- package/src/server/serverFns/design/ai/source-mode.ts +10 -12
- package/src/server/serverFns/design/comments.ts +14 -13
- package/src/server/serverFns/design/designs.ts +13 -19
- package/src/server/serverFns/design/page-versions.ts +17 -18
- package/src/server/serverFns/design/pages.ts +17 -18
- package/src/server/serverFns/design/reviews.ts +8 -9
- package/src/server/serverFns/design/shares-password.ts +13 -19
- package/src/server/serverFns/design/shares.ts +22 -31
- package/src/server/serverFns/design/versions.ts +8 -9
- package/src/server/serverFns/harness/__tests__/attach-prototype.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/attach-to-kb.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/attach-to-story-ssrf.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/attach-to-story.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/cancel-run.test.ts +40 -15
- package/src/server/serverFns/harness/__tests__/extract-attachment.spec.ts +52 -2
- package/src/server/serverFns/harness/__tests__/gallery.spec.ts +76 -12
- package/src/server/serverFns/harness/__tests__/github-workspace.spec.ts +38 -6
- package/src/server/serverFns/harness/__tests__/media-prototype.spec.ts +50 -6
- package/src/server/serverFns/harness/__tests__/media.spec.ts +55 -11
- package/src/server/serverFns/harness/__tests__/sandbox-policy.test.ts +41 -16
- package/src/server/serverFns/harness/__tests__/workspace-files.test.ts +41 -16
- package/src/server/serverFns/harness/attach-prototype.ts +4 -4
- package/src/server/serverFns/harness/attach-to-kb.ts +4 -4
- package/src/server/serverFns/harness/attach-to-story.ts +4 -4
- package/src/server/serverFns/harness/cancel-run.ts +4 -6
- package/src/server/serverFns/harness/extract-attachment.ts +3 -4
- package/src/server/serverFns/harness/gallery.ts +19 -23
- package/src/server/serverFns/harness/github-workspace.ts +14 -21
- package/src/server/serverFns/harness/media.ts +18 -117
- package/src/server/serverFns/harness/sandbox-policy.ts +11 -10
- package/src/server/serverFns/harness/search-mention-candidates.ts +4 -6
- package/src/server/serverFns/harness/workspace-files.ts +19 -26
- package/src/server/serverFns/iteration/__tests__/iteration-auto-schedule.test.ts +35 -3
- package/src/server/serverFns/iteration/__tests__/iteration-crud.test.ts +35 -3
- package/src/server/serverFns/iteration/__tests__/iteration-stories.test.ts +35 -3
- package/src/server/serverFns/iteration/__tests__/iteration-transfer.test.ts +35 -3
- package/src/server/serverFns/iteration/iteration-auto-schedule.ts +7 -10
- package/src/server/serverFns/iteration/iteration-burndown.ts +4 -6
- package/src/server/serverFns/iteration/iteration-crud.ts +26 -35
- package/src/server/serverFns/iteration/iteration-stories.ts +10 -14
- package/src/server/serverFns/iteration/iteration-transfer.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/categories.ts +11 -15
- package/src/server/serverFns/knowledge/public/bookmarks/create.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/delete.ts +5 -7
- package/src/server/serverFns/knowledge/public/bookmarks/detail.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/favorite.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/list.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/refresh-favicon.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/share.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/sync-github.ts +5 -7
- package/src/server/serverFns/knowledge/public/bookmarks/unshare.ts +4 -6
- package/src/server/serverFns/knowledge/public/bookmarks/update.ts +6 -8
- package/src/server/serverFns/knowledge/public/compliance/create.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/delete.ts +5 -7
- package/src/server/serverFns/knowledge/public/compliance/detail.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/list.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/share.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/unshare.ts +4 -6
- package/src/server/serverFns/knowledge/public/compliance/update.ts +5 -7
- package/src/server/serverFns/knowledge/public/dictionary/create.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/delete.ts +5 -7
- package/src/server/serverFns/knowledge/public/dictionary/detail.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/list.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/share.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/unshare.ts +4 -6
- package/src/server/serverFns/knowledge/public/dictionary/update.ts +5 -7
- package/src/server/serverFns/knowledge/public/entity-tags.ts +4 -6
- package/src/server/serverFns/knowledge/public/favorite.ts +7 -10
- package/src/server/serverFns/knowledge/public/legal/create.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/delete.ts +5 -7
- package/src/server/serverFns/knowledge/public/legal/detail.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/list.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/share.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/unshare.ts +4 -6
- package/src/server/serverFns/knowledge/public/legal/update.ts +5 -7
- package/src/server/serverFns/knowledge-index.ts +12 -16
- package/src/server/serverFns/knowledge.ts +50 -67
- package/src/server/serverFns/notifications.ts +25 -34
- package/src/server/serverFns/plugins/harness-plugins.ts +16 -23
- package/src/server/serverFns/project/module-overview.ts +7 -10
- package/src/server/serverFns/project.ts +48 -68
- package/src/server/serverFns/references/create.ts +4 -6
- package/src/server/serverFns/references/resolve.ts +4 -6
- package/src/server/serverFns/references/search.ts +4 -6
- package/src/server/serverFns/share/design/[designId]/events.ts +4 -6
- package/src/server/serverFns/sso.ts +1 -1
- package/src/server/serverFns/story/__tests__/bulk.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-assoc.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-attachments.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-crud-date-key.test.ts +42 -17
- package/src/server/serverFns/story/__tests__/story-dependencies.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-gantt-deps.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-groups.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-read-path-authz.test.ts +40 -4
- package/src/server/serverFns/story/__tests__/story-search.test.ts +34 -1
- package/src/server/serverFns/story/__tests__/story-transfer.test.ts +34 -1
- package/src/server/serverFns/story/link-preview.ts +5 -7
- package/src/server/serverFns/story/story-assoc.ts +28 -38
- package/src/server/serverFns/story/story-attachments.ts +7 -10
- package/src/server/serverFns/story/story-children.ts +4 -6
- package/src/server/serverFns/story/story-comments.ts +13 -18
- package/src/server/serverFns/story/story-crud/activities.ts +4 -6
- package/src/server/serverFns/story/story-crud/archive.ts +7 -10
- package/src/server/serverFns/story/story-crud/bulk.ts +10 -14
- package/src/server/serverFns/story/story-crud/detail.ts +7 -10
- package/src/server/serverFns/story/story-crud/label-suggest.ts +4 -6
- package/src/server/serverFns/story/story-crud/labels.ts +6 -9
- package/src/server/serverFns/story/story-crud/user-brief.ts +4 -6
- package/src/server/serverFns/story/story-crud.ts +13 -18
- package/src/server/serverFns/story/story-dependencies.ts +16 -22
- package/src/server/serverFns/story/story-groups.ts +10 -14
- package/src/server/serverFns/story/story-links.ts +13 -18
- package/src/server/serverFns/story/story-reactions.ts +13 -18
- package/src/server/serverFns/story/story-search.ts +7 -10
- package/src/server/serverFns/story/story-transfer.ts +10 -14
- package/src/server/serverFns/story/story-tree.ts +7 -10
- package/src/server/serverFns/story-display-options.ts +7 -8
- package/src/server/serverFns/story-view.ts +12 -18
- package/src/server/serverFns/tasks/task-crud.ts +13 -17
- package/src/server/serverFns/tasks/task-queries.ts +12 -18
- package/src/server/serverFns/team.ts +46 -66
- package/src/server/serverFns/testcase/__tests__/automation.test.ts +38 -5
- package/src/server/serverFns/testcase/__tests__/evidence-upload.test.ts +37 -3
- package/src/server/serverFns/testcase/__tests__/generation.test.ts +38 -5
- package/src/server/serverFns/testcase/__tests__/plans.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/regression.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/run-cases.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/runs.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/stats.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/testcase-board.test.ts +39 -5
- package/src/server/serverFns/testcase/__tests__/testcase-crud.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/testcase-folders.test.ts +36 -3
- package/src/server/serverFns/testcase/__tests__/testcase-groups.test.ts +38 -5
- package/src/server/serverFns/testcase/automation.ts +13 -17
- package/src/server/serverFns/testcase/bulk.ts +10 -14
- package/src/server/serverFns/testcase/evidence-upload.ts +5 -7
- package/src/server/serverFns/testcase/generation.ts +10 -13
- package/src/server/serverFns/testcase/plans.ts +23 -31
- package/src/server/serverFns/testcase/regression.ts +7 -10
- package/src/server/serverFns/testcase/run-cases.ts +13 -18
- package/src/server/serverFns/testcase/runs.ts +13 -18
- package/src/server/serverFns/testcase/stats.ts +13 -18
- package/src/server/serverFns/testcase/testcase-activities.ts +4 -6
- package/src/server/serverFns/testcase/testcase-board.ts +4 -6
- package/src/server/serverFns/testcase/testcase-crud.ts +20 -27
- package/src/server/serverFns/testcase/testcase-display-options.ts +8 -11
- package/src/server/serverFns/testcase/testcase-export.ts +5 -7
- package/src/server/serverFns/testcase/testcase-filter-views.ts +12 -18
- package/src/server/serverFns/testcase/testcase-folders.ts +16 -22
- package/src/server/serverFns/testcase/testcase-groups.ts +4 -6
- package/src/server/serverFns/testcase/testcase-reorder.ts +4 -6
- package/src/server/serverFns/translation.ts +4 -6
- package/src/server/serverFns/user/avatar.ts +4 -6
- package/src/server/serverFns/user/settings.ts +4 -6
- package/src/server/serverFns/user/update-locale.ts +4 -6
- package/src/server/serverFns/workspace-kb.ts +26 -35
- package/src/server/serverFns/workspace.ts +43 -59
- package/src/server/serverFns/ws.ts +4 -6
- package/src/server/serverfn-public-allowlist.ts +117 -0
- package/src/server/story/types.ts +0 -1
- package/src/server/sync/__tests__/scopes.test.ts +64 -0
- package/src/server/sync/scopes.ts +7 -0
- package/src/server/testcase/__tests__/auto-bug.test.ts +44 -12
- package/src/__tests__/bench/baselines/format-timestamp.json +0 -44
- package/src/__typeprobe__.d.ts +0 -4
- package/src/components/forms/app-form-dialog.tsx +0 -126
- package/src/components/forms/hooks/use-form-submit.ts +0 -57
- package/src/components/forms/types.ts +0 -34
- package/src/components/harness/code/workspace-picker.tsx +0 -239
- package/src/components/tiptap/extensions/local-file/insert-local-file.ts +0 -35
- package/src/components/tiptap/extensions/local-file/local-file-node.ts +0 -71
- package/src/devframe-docks/ai-chat-iframe.tsx +0 -29
- package/src/devframe-docks/session-iframe.tsx +0 -90
- package/src/lib/__tests__/desktop-detect.test.ts +0 -19
- package/src/lib/collections/index.ts +0 -22
- package/src/lib/collections/knowledge/index.ts +0 -18
- package/src/lib/collections/knowledge/knowledge-bases-collection.ts +0 -34
- package/src/lib/collections/reference/bookmark-categories-collection.ts +0 -31
- package/src/lib/collections/reference/labels-collection.ts +0 -31
- package/src/lib/collections/reference/projects-collection.ts +0 -31
- package/src/lib/collections/reference/users-brief-collection.ts +0 -35
- package/src/lib/collections/reference/workspaces-collection.ts +0 -34
- package/src/lib/desktop-detect.ts +0 -29
- package/src/paraglide/messages/en.js +0 -28260
- package/src/paraglide/messages/zh.js +0 -28258
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
// (我的任务列表)/ getAiTaskFn(任务详情 + run 历史)。本文件只准导出 createServerFn
|
|
3
3
|
// 产物(纯净红线,CI 守护):serializeTask、probeSourceExists 等辅助逻辑一律文件内
|
|
4
4
|
// 非导出成员。
|
|
5
|
-
// 鉴权惯例(同 testcase-crud):serverFn 是独立 RPC 入口,路由层守卫拦不到,
|
|
6
|
-
//
|
|
5
|
+
// 鉴权惯例(同 testcase-crud):serverFn 是独立 RPC 入口,路由层守卫拦不到,
|
|
6
|
+
// 链上挂 authContextMiddleware 注入 context.user。
|
|
7
7
|
import { getPrisma } from "@allbluecn/database/get-prisma";
|
|
8
8
|
import type { Prisma } from "@allbluecn/database";
|
|
9
9
|
import { createServerFn } from "@tanstack/react-start";
|
|
10
|
-
import { getRequest } from "@tanstack/react-start/server";
|
|
11
10
|
import { z } from "zod";
|
|
12
|
-
import {
|
|
11
|
+
import { authContextMiddleware } from '@/server/middlewares/auth-context'
|
|
13
12
|
import { fetchAssignedToMe } from "@/server/ai-task/assigned-query";
|
|
14
13
|
import type { AssignedResult } from "@/server/ai-task/types";
|
|
15
14
|
|
|
@@ -58,11 +57,9 @@ async function probeSourceExists(
|
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
/** 「分配给我的」三表聚合(story → bug → testcase),直接透传任务 3 的查询结果 */
|
|
61
|
-
export const listAssignedToMeFn = createServerFn({ method: "GET" }).handler(
|
|
62
|
-
async (): Promise<AssignedResult> => {
|
|
63
|
-
const
|
|
64
|
-
const session = await requireAuth(request);
|
|
65
|
-
const userId = session.user.id;
|
|
60
|
+
export const listAssignedToMeFn = createServerFn({ method: "GET" }).middleware([authContextMiddleware]).handler(
|
|
61
|
+
async ({ context }): Promise<AssignedResult> => {
|
|
62
|
+
const userId = context.user.id;
|
|
66
63
|
|
|
67
64
|
return fetchAssignedToMe(userId);
|
|
68
65
|
},
|
|
@@ -70,11 +67,9 @@ export const listAssignedToMeFn = createServerFn({ method: "GET" }).handler(
|
|
|
70
67
|
|
|
71
68
|
/** 我的任务列表:归属圈定 + updatedAt 倒序投影(含 instruction 供前端指令搜索,
|
|
72
69
|
* useTaskFilter 纯函数按字段存在性自适应——任务 47 的过渡兼容即插即用) */
|
|
73
|
-
export const listAiTasksFn = createServerFn({ method: "GET" }).handler(
|
|
74
|
-
async () => {
|
|
75
|
-
const
|
|
76
|
-
const session = await requireAuth(request);
|
|
77
|
-
const userId = session.user.id;
|
|
70
|
+
export const listAiTasksFn = createServerFn({ method: "GET" }).middleware([authContextMiddleware]).handler(
|
|
71
|
+
async ({ context }) => {
|
|
72
|
+
const userId = context.user.id;
|
|
78
73
|
|
|
79
74
|
const prisma = await getPrisma();
|
|
80
75
|
const rows = await prisma.aiTask.findMany({
|
|
@@ -113,15 +108,14 @@ const getAiTaskSchema = z.object({ id: z.string().min(1) });
|
|
|
113
108
|
|
|
114
109
|
/** 任务详情:全字段 task(附关联项目名,信息区展示)+ run 历史(startedAt 倒序)+ 源条目存在性 */
|
|
115
110
|
export const getAiTaskFn = createServerFn({ method: "GET" })
|
|
111
|
+
.middleware([authContextMiddleware])
|
|
116
112
|
.validator(getAiTaskSchema)
|
|
117
|
-
.handler(async ({ data }): Promise<{
|
|
113
|
+
.handler(async ({ data, context }): Promise<{
|
|
118
114
|
task: ReturnType<typeof serializeTask> & { projectName: string | null };
|
|
119
115
|
runs: AiTaskRunRow[];
|
|
120
116
|
sourceExists: boolean | null;
|
|
121
117
|
}> => {
|
|
122
|
-
const
|
|
123
|
-
const session = await requireAuth(request);
|
|
124
|
-
const userId = session.user.id;
|
|
118
|
+
const userId = context.user.id;
|
|
125
119
|
|
|
126
120
|
const prisma = await getPrisma();
|
|
127
121
|
|
|
@@ -3,7 +3,7 @@ import { createServerFn } from '@tanstack/react-start'
|
|
|
3
3
|
import { getRequest } from '@tanstack/react-start/server'
|
|
4
4
|
import crypto from 'node:crypto'
|
|
5
5
|
import { z } from 'zod'
|
|
6
|
-
import {
|
|
6
|
+
import { authContextMiddleware } from '@/server/middlewares/auth-context'
|
|
7
7
|
import { assertOwned } from '@/server/lib/ownership'
|
|
8
8
|
import { requireTeamSeats } from '@/server/resources'
|
|
9
9
|
import { auditLog } from '@/server/audit'
|
|
@@ -31,12 +31,11 @@ const createInvitationSchema = z.object({
|
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
export const createTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
34
|
+
.middleware([authContextMiddleware])
|
|
34
35
|
.validator(createInvitationSchema)
|
|
35
|
-
.handler(async ({ data }) => {
|
|
36
|
+
.handler(async ({ data, context }) => {
|
|
36
37
|
const prisma = await getPrisma()
|
|
37
|
-
const
|
|
38
|
-
const session = await requireAuth(request)
|
|
39
|
-
const ownerId = session.user.id
|
|
38
|
+
const ownerId = context.user.id
|
|
40
39
|
|
|
41
40
|
const email = data.channel === 'email' ? data.email!.toLowerCase() : null
|
|
42
41
|
|
|
@@ -129,12 +128,10 @@ export const createTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
|
129
128
|
return { success: true, token, invitationId: invitation.id }
|
|
130
129
|
})
|
|
131
130
|
|
|
132
|
-
export const listTeamInvitationsFn = createServerFn({ method: 'GET' }).handler(async () => {
|
|
131
|
+
export const listTeamInvitationsFn = createServerFn({ method: 'GET' }).middleware([authContextMiddleware]).handler(async ({ context }) => {
|
|
133
132
|
const prisma = await getPrisma()
|
|
134
133
|
try {
|
|
135
|
-
const
|
|
136
|
-
const session = await requireAuth(request)
|
|
137
|
-
const ownerId = session.user.id
|
|
134
|
+
const ownerId = context.user.id
|
|
138
135
|
const now = new Date()
|
|
139
136
|
|
|
140
137
|
await prisma.teamInvitation.updateMany({
|
|
@@ -187,12 +184,11 @@ export const listTeamInvitationsFn = createServerFn({ method: 'GET' }).handler(a
|
|
|
187
184
|
const revokeSchema = z.object({ invitationId: z.string() })
|
|
188
185
|
|
|
189
186
|
export const clearExpiredInvitationsFn = createServerFn({ method: 'POST' })
|
|
187
|
+
.middleware([authContextMiddleware])
|
|
190
188
|
.validator(z.object({}))
|
|
191
|
-
.handler(async () => {
|
|
189
|
+
.handler(async ({ context }) => {
|
|
192
190
|
const prisma = await getPrisma()
|
|
193
|
-
const
|
|
194
|
-
const session = await requireAuth(request)
|
|
195
|
-
const ownerId = session.user.id
|
|
191
|
+
const ownerId = context.user.id
|
|
196
192
|
const res = await prisma.teamInvitation.deleteMany({
|
|
197
193
|
where: { ownerId, status: 'expired', channel: 'email' },
|
|
198
194
|
})
|
|
@@ -208,12 +204,11 @@ export const clearExpiredInvitationsFn = createServerFn({ method: 'POST' })
|
|
|
208
204
|
})
|
|
209
205
|
|
|
210
206
|
export const revokeTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
207
|
+
.middleware([authContextMiddleware])
|
|
211
208
|
.validator(revokeSchema)
|
|
212
|
-
.handler(async ({ data }) => {
|
|
209
|
+
.handler(async ({ data, context }) => {
|
|
213
210
|
const prisma = await getPrisma()
|
|
214
|
-
const
|
|
215
|
-
const session = await requireAuth(request)
|
|
216
|
-
const ownerId = session.user.id
|
|
211
|
+
const ownerId = context.user.id
|
|
217
212
|
// DB-03:属主校验并入单次 findFirst(消除查后比对二次往返与 TOCTOU),文案保持
|
|
218
213
|
const inv = await assertOwned(prisma.teamInvitation, { where: { id: data.invitationId, ownerId } }, '邀请不存在')
|
|
219
214
|
if (inv.status !== 'pending' && inv.status !== 'pending_approval') throw new Error('仅待处理/待批准邀请可撤销')
|
|
@@ -238,12 +233,11 @@ export const revokeTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
|
238
233
|
})
|
|
239
234
|
|
|
240
235
|
export const resendTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
236
|
+
.middleware([authContextMiddleware])
|
|
241
237
|
.validator(revokeSchema)
|
|
242
|
-
.handler(async ({ data }) => {
|
|
238
|
+
.handler(async ({ data, context }) => {
|
|
243
239
|
const prisma = await getPrisma()
|
|
244
|
-
const
|
|
245
|
-
const session = await requireAuth(request)
|
|
246
|
-
const ownerId = session.user.id
|
|
240
|
+
const ownerId = context.user.id
|
|
247
241
|
// DB-03:属主校验并入单次 findFirst(消除查后比对二次往返与 TOCTOU),文案保持
|
|
248
242
|
const inv = await assertOwned(prisma.teamInvitation, { where: { id: data.invitationId, ownerId } }, '邀请不存在')
|
|
249
243
|
if (inv.status !== 'pending' && inv.status !== 'expired') {
|
|
@@ -282,12 +276,11 @@ export const resendTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
|
282
276
|
})
|
|
283
277
|
|
|
284
278
|
export const refreshTeamInvitationLinkFn = createServerFn({ method: 'POST' })
|
|
279
|
+
.middleware([authContextMiddleware])
|
|
285
280
|
.validator(z.object({ expiresInDays: z.number().int().min(1).max(365).optional() }))
|
|
286
|
-
.handler(async ({ data }) => {
|
|
281
|
+
.handler(async ({ data, context }) => {
|
|
287
282
|
const prisma = await getPrisma()
|
|
288
|
-
const
|
|
289
|
-
const session = await requireAuth(request)
|
|
290
|
-
const ownerId = session.user.id
|
|
283
|
+
const ownerId = context.user.id
|
|
291
284
|
|
|
292
285
|
await requireTeamSeats(ownerId, 'member', 1)
|
|
293
286
|
|
|
@@ -333,11 +326,9 @@ export const refreshTeamInvitationLinkFn = createServerFn({ method: 'POST' })
|
|
|
333
326
|
|
|
334
327
|
// ---------- 成员管理 ----------
|
|
335
328
|
|
|
336
|
-
export const listTeamMembersFn = createServerFn({ method: 'GET' }).handler(async () => {
|
|
329
|
+
export const listTeamMembersFn = createServerFn({ method: 'GET' }).middleware([authContextMiddleware]).handler(async ({ context }) => {
|
|
337
330
|
const prisma = await getPrisma()
|
|
338
|
-
const
|
|
339
|
-
const session = await requireAuth(request)
|
|
340
|
-
const ownerId = session.user.id
|
|
331
|
+
const ownerId = context.user.id
|
|
341
332
|
|
|
342
333
|
// 以 memberId 判当前用户的归属:避免为已是别家成员的账号创建自引用 owner 记录(P2002)
|
|
343
334
|
const ownEntry = await prisma.teamMembership.findUnique({
|
|
@@ -378,12 +369,11 @@ export const listTeamMembersFn = createServerFn({ method: 'GET' }).handler(async
|
|
|
378
369
|
const removeMemberSchema = z.object({ membershipId: z.string() })
|
|
379
370
|
|
|
380
371
|
export const removeTeamMemberFn = createServerFn({ method: 'POST' })
|
|
372
|
+
.middleware([authContextMiddleware])
|
|
381
373
|
.validator(removeMemberSchema)
|
|
382
|
-
.handler(async ({ data }) => {
|
|
374
|
+
.handler(async ({ data, context }) => {
|
|
383
375
|
const prisma = await getPrisma()
|
|
384
|
-
const
|
|
385
|
-
const session = await requireAuth(request)
|
|
386
|
-
const ownerId = session.user.id
|
|
376
|
+
const ownerId = context.user.id
|
|
387
377
|
const m = await prisma.teamMembership.findUnique({ where: { id: data.membershipId } })
|
|
388
378
|
if (!m) throw new Error('成员不存在')
|
|
389
379
|
if (m.ownerId !== ownerId) throw new Error('权限不足:仅团队所有者可移除成员')
|
|
@@ -401,11 +391,9 @@ export const removeTeamMemberFn = createServerFn({ method: 'POST' })
|
|
|
401
391
|
return { success: true }
|
|
402
392
|
})
|
|
403
393
|
|
|
404
|
-
export const leaveTeamFn = createServerFn({ method: 'POST' }).validator(z.object({})).handler(async () => {
|
|
394
|
+
export const leaveTeamFn = createServerFn({ method: 'POST' }).middleware([authContextMiddleware]).validator(z.object({})).handler(async ({ context }) => {
|
|
405
395
|
const prisma = await getPrisma()
|
|
406
|
-
const
|
|
407
|
-
const session = await requireAuth(request)
|
|
408
|
-
const userId = session.user.id
|
|
396
|
+
const userId = context.user.id
|
|
409
397
|
const m = await prisma.teamMembership.findUnique({ where: { memberId: userId } })
|
|
410
398
|
if (!m) throw new Error('你未加入任何团队')
|
|
411
399
|
await prisma.$transaction(async (tx) => {
|
|
@@ -430,12 +418,11 @@ const approveJoinRequestSchema = z.object({
|
|
|
430
418
|
})
|
|
431
419
|
|
|
432
420
|
export const approveTeamJoinRequestFn = createServerFn({ method: 'POST' })
|
|
421
|
+
.middleware([authContextMiddleware])
|
|
433
422
|
.validator(approveJoinRequestSchema)
|
|
434
|
-
.handler(async ({ data }) => {
|
|
423
|
+
.handler(async ({ data, context }) => {
|
|
435
424
|
const prisma = await getPrisma()
|
|
436
|
-
const
|
|
437
|
-
const session = await requireAuth(request)
|
|
438
|
-
const ownerId = session.user.id
|
|
425
|
+
const ownerId = context.user.id
|
|
439
426
|
|
|
440
427
|
// DB-03:属主校验并入单次 findFirst(include 关系一并取回)。
|
|
441
428
|
// 此处内联 findFirst 而非 assertOwned:include 投影类型(reqRow.invitation)需走
|
|
@@ -499,12 +486,11 @@ export const approveTeamJoinRequestFn = createServerFn({ method: 'POST' })
|
|
|
499
486
|
})
|
|
500
487
|
|
|
501
488
|
export const rejectTeamJoinRequestFn = createServerFn({ method: 'POST' })
|
|
489
|
+
.middleware([authContextMiddleware])
|
|
502
490
|
.validator(joinRequestSchema)
|
|
503
|
-
.handler(async ({ data }) => {
|
|
491
|
+
.handler(async ({ data, context }) => {
|
|
504
492
|
const prisma = await getPrisma()
|
|
505
|
-
const
|
|
506
|
-
const session = await requireAuth(request)
|
|
507
|
-
const ownerId = session.user.id
|
|
493
|
+
const ownerId = context.user.id
|
|
508
494
|
|
|
509
495
|
// DB-03:属主校验并入单次 findFirst
|
|
510
496
|
const reqRow = await assertOwned(prisma.teamJoinRequest, { where: { id: data.requestId, ownerId } }, '申请不存在')
|
|
@@ -527,12 +513,11 @@ export const rejectTeamJoinRequestFn = createServerFn({ method: 'POST' })
|
|
|
527
513
|
})
|
|
528
514
|
|
|
529
515
|
export const deleteTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
516
|
+
.middleware([authContextMiddleware])
|
|
530
517
|
.validator(revokeSchema)
|
|
531
|
-
.handler(async ({ data }) => {
|
|
518
|
+
.handler(async ({ data, context }) => {
|
|
532
519
|
const prisma = await getPrisma()
|
|
533
|
-
const
|
|
534
|
-
const session = await requireAuth(request)
|
|
535
|
-
const ownerId = session.user.id
|
|
520
|
+
const ownerId = context.user.id
|
|
536
521
|
|
|
537
522
|
// DB-03:属主校验并入单次 findFirst
|
|
538
523
|
const invRow = await assertOwned(prisma.teamInvitation, { where: { id: data.invitationId, ownerId } }, '邀请不存在')
|
|
@@ -553,12 +538,11 @@ export const deleteTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
|
553
538
|
})
|
|
554
539
|
|
|
555
540
|
export const deleteTeamJoinRequestFn = createServerFn({ method: 'POST' })
|
|
541
|
+
.middleware([authContextMiddleware])
|
|
556
542
|
.validator(joinRequestSchema)
|
|
557
|
-
.handler(async ({ data }) => {
|
|
543
|
+
.handler(async ({ data, context }) => {
|
|
558
544
|
const prisma = await getPrisma()
|
|
559
|
-
const
|
|
560
|
-
const session = await requireAuth(request)
|
|
561
|
-
const ownerId = session.user.id
|
|
545
|
+
const ownerId = context.user.id
|
|
562
546
|
|
|
563
547
|
// DB-03:属主校验并入单次 findFirst
|
|
564
548
|
const reqRow = await assertOwned(prisma.teamJoinRequest, { where: { id: data.requestId, ownerId } }, '申请不存在')
|
|
@@ -576,11 +560,9 @@ export const deleteTeamJoinRequestFn = createServerFn({ method: 'POST' })
|
|
|
576
560
|
return { success: true }
|
|
577
561
|
})
|
|
578
562
|
|
|
579
|
-
export const listTeamUsersFn = createServerFn({ method: 'GET' }).handler(async () => {
|
|
563
|
+
export const listTeamUsersFn = createServerFn({ method: 'GET' }).middleware([authContextMiddleware]).handler(async ({ context }) => {
|
|
580
564
|
const prisma = await getPrisma()
|
|
581
|
-
const
|
|
582
|
-
const session = await requireAuth(request)
|
|
583
|
-
const userId = session.user.id
|
|
565
|
+
const userId = context.user.id
|
|
584
566
|
const joined = await prisma.teamMembership.findUnique({ where: { memberId: userId } })
|
|
585
567
|
const ownerId = joined ? joined.ownerId : userId
|
|
586
568
|
const [owner, members] = await Promise.all([
|
|
@@ -796,17 +778,16 @@ export const applyTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
|
796
778
|
})
|
|
797
779
|
|
|
798
780
|
export const acceptTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
781
|
+
.middleware([authContextMiddleware])
|
|
799
782
|
.validator(tokenSchema)
|
|
800
|
-
.handler(async ({ data }) => {
|
|
783
|
+
.handler(async ({ data, context }) => {
|
|
801
784
|
const prisma = await getPrisma()
|
|
802
|
-
const
|
|
803
|
-
const session = await requireAuth(request)
|
|
804
|
-
const userId = session.user.id
|
|
785
|
+
const userId = context.user.id
|
|
805
786
|
const currentUser = await prisma.user.findUnique({
|
|
806
787
|
where: { id: userId },
|
|
807
788
|
select: { email: true },
|
|
808
789
|
})
|
|
809
|
-
const email = (currentUser?.email ??
|
|
790
|
+
const email = (currentUser?.email ?? context.user.email ?? '').toLowerCase()
|
|
810
791
|
if (!email) throw new Error('当前账号缺少邮箱,无法申请')
|
|
811
792
|
|
|
812
793
|
const inv = await prisma.teamInvitation.findUnique({ where: { token: data.token } })
|
|
@@ -864,12 +845,11 @@ const approveSchema = z.object({
|
|
|
864
845
|
})
|
|
865
846
|
|
|
866
847
|
export const approveTeamInvitationFn = createServerFn({ method: 'POST' })
|
|
848
|
+
.middleware([authContextMiddleware])
|
|
867
849
|
.validator(approveSchema)
|
|
868
|
-
.handler(async ({ data }) => {
|
|
850
|
+
.handler(async ({ data, context }) => {
|
|
869
851
|
const prisma = await getPrisma()
|
|
870
|
-
const
|
|
871
|
-
const session = await requireAuth(request)
|
|
872
|
-
const ownerId = session.user.id
|
|
852
|
+
const ownerId = context.user.id
|
|
873
853
|
|
|
874
854
|
// DB-03:属主校验并入单次 findFirst
|
|
875
855
|
const inv = await assertOwned(prisma.teamInvitation, { where: { id: data.invitationId, ownerId } }, '邀请不存在')
|
|
@@ -72,24 +72,57 @@ const PRISMA = H.prisma;
|
|
|
72
72
|
vi.mock("@tanstack/react-start", () => {
|
|
73
73
|
// 每个 serverFn 实例独立持有自己的 capture,避免同模块多实例共用导致 validator 串号
|
|
74
74
|
const createServerFn = () => {
|
|
75
|
-
const capture: { validator?: unknown; handler?: unknown } = {};
|
|
75
|
+
const capture: { validator?: unknown; handler?: unknown; middlewares?: unknown[] } = {};
|
|
76
76
|
const api = {
|
|
77
77
|
validator: (v: unknown) => {
|
|
78
78
|
capture.validator = v;
|
|
79
79
|
return api;
|
|
80
80
|
},
|
|
81
|
+
middleware: (mws: unknown[]) => {
|
|
82
|
+
capture.middlewares = mws;
|
|
83
|
+
return api;
|
|
84
|
+
},
|
|
81
85
|
handler: (h: unknown) => {
|
|
82
86
|
capture.handler = h;
|
|
83
87
|
return async (args: { data: unknown }) => {
|
|
84
88
|
const v = capture.validator as { parse?: (d: unknown) => unknown } | undefined;
|
|
85
89
|
const data = v && v.parse ? v.parse(args.data) : args.data;
|
|
86
|
-
|
|
90
|
+
// 迁移后经 .middleware([authContextMiddleware]) 注入 context.user:
|
|
91
|
+
// 依序执行 middleware 的 server 段,真实鉴权链由被 mock 的 auth-helpers 承接
|
|
92
|
+
let context: Record<string, unknown> = {};
|
|
93
|
+
for (const mw of capture.middlewares ?? []) {
|
|
94
|
+
const serverFn = (mw as { options?: { server?: unknown } })?.options?.server;
|
|
95
|
+
if (typeof serverFn !== "function") continue;
|
|
96
|
+
const result = await (
|
|
97
|
+
serverFn as (p: unknown) => Promise<{ context?: unknown }>
|
|
98
|
+
)({
|
|
99
|
+
data,
|
|
100
|
+
context,
|
|
101
|
+
method: "POST",
|
|
102
|
+
serverFnMeta: {},
|
|
103
|
+
signal: new AbortController().signal,
|
|
104
|
+
next: async (inner: { context?: unknown }) => ({
|
|
105
|
+
context: { ...context, ...(inner?.context ?? {}) },
|
|
106
|
+
}),
|
|
107
|
+
});
|
|
108
|
+
context = (result?.context ?? context) as Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
return (h as (p: { data: unknown; context: unknown }) => Promise<unknown>)({ data, context });
|
|
87
111
|
};
|
|
88
112
|
},
|
|
89
113
|
};
|
|
90
114
|
return api;
|
|
91
115
|
};
|
|
92
|
-
|
|
116
|
+
// auth-context.ts 依赖 createMiddleware({ type: 'function' }).server(fn)
|
|
117
|
+
const createMiddleware = (opts?: { type?: string }) => {
|
|
118
|
+
const mw: { options: { type?: string; server?: unknown }; server?: unknown } = { options: { type: opts?.type } };
|
|
119
|
+
mw.server = (fn: unknown) => {
|
|
120
|
+
mw.options.server = fn;
|
|
121
|
+
return mw;
|
|
122
|
+
};
|
|
123
|
+
return mw;
|
|
124
|
+
};
|
|
125
|
+
return { createServerFn, createMiddleware };
|
|
93
126
|
});
|
|
94
127
|
|
|
95
128
|
vi.mock("@tanstack/react-start/server", () => ({ getRequest: () => REQ }));
|
|
@@ -223,7 +256,7 @@ describe("generateArtifactFn", () => {
|
|
|
223
256
|
).resolves.toMatchObject({ artifact: expect.anything() });
|
|
224
257
|
});
|
|
225
258
|
|
|
226
|
-
it("requireFeature
|
|
259
|
+
it("requireFeature 门控先于业务逻辑(认证经 authContextMiddleware 前置)+ AI 调用走 testgen bizKey + testcase.automation promptKey 覆盖", async () => {
|
|
227
260
|
M.runChatAsAgent.mockResolvedValue(aiOutput());
|
|
228
261
|
M.runVitestSpec.mockResolvedValue(runResult());
|
|
229
262
|
|
|
@@ -231,7 +264,7 @@ describe("generateArtifactFn", () => {
|
|
|
231
264
|
|
|
232
265
|
expect(M.requireFeature).toHaveBeenCalledWith(REQ, "testGeneration");
|
|
233
266
|
expect(M.requireFeature.mock.invocationCallOrder[0]).toBeLessThan(
|
|
234
|
-
M.
|
|
267
|
+
M.checkAiRateLimit.mock.invocationCallOrder[0],
|
|
235
268
|
);
|
|
236
269
|
expect(M.checkAiRateLimit).toHaveBeenCalledWith(U, "testGeneration");
|
|
237
270
|
expect(M.runChatAsAgent).toHaveBeenCalledTimes(1);
|
|
@@ -33,25 +33,59 @@ const M = H.fns;
|
|
|
33
33
|
const BLOB_PUT = H.blobPut;
|
|
34
34
|
|
|
35
35
|
vi.mock("@tanstack/react-start", () => {
|
|
36
|
+
// 每个 serverFn 实例独立持有自己的 capture,避免同模块多实例共用导致 validator 串号
|
|
36
37
|
const createServerFn = () => {
|
|
37
|
-
const capture: { validator?: unknown; handler?: unknown } = {};
|
|
38
|
+
const capture: { validator?: unknown; handler?: unknown; middlewares?: unknown[] } = {};
|
|
38
39
|
const api = {
|
|
39
40
|
validator: (v: unknown) => {
|
|
40
41
|
capture.validator = v;
|
|
41
42
|
return api;
|
|
42
43
|
},
|
|
44
|
+
middleware: (mws: unknown[]) => {
|
|
45
|
+
capture.middlewares = mws;
|
|
46
|
+
return api;
|
|
47
|
+
},
|
|
43
48
|
handler: (h: unknown) => {
|
|
44
49
|
capture.handler = h;
|
|
45
50
|
return async (args: { data: unknown }) => {
|
|
46
51
|
const v = capture.validator as { parse?: (d: unknown) => unknown } | undefined;
|
|
47
52
|
const data = v && v.parse ? v.parse(args.data) : args.data;
|
|
48
|
-
|
|
53
|
+
// 迁移后经 .middleware([authContextMiddleware]) 注入 context.user:
|
|
54
|
+
// 依序执行 middleware 的 server 段,真实鉴权链由被 mock 的 auth-helpers 承接
|
|
55
|
+
let context: Record<string, unknown> = {};
|
|
56
|
+
for (const mw of capture.middlewares ?? []) {
|
|
57
|
+
const serverFn = (mw as { options?: { server?: unknown } })?.options?.server;
|
|
58
|
+
if (typeof serverFn !== "function") continue;
|
|
59
|
+
const result = await (
|
|
60
|
+
serverFn as (p: unknown) => Promise<{ context?: unknown }>
|
|
61
|
+
)({
|
|
62
|
+
data,
|
|
63
|
+
context,
|
|
64
|
+
method: "POST",
|
|
65
|
+
serverFnMeta: {},
|
|
66
|
+
signal: new AbortController().signal,
|
|
67
|
+
next: async (inner: { context?: unknown }) => ({
|
|
68
|
+
context: { ...context, ...(inner?.context ?? {}) },
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
71
|
+
context = (result?.context ?? context) as Record<string, unknown>;
|
|
72
|
+
}
|
|
73
|
+
return (h as (p: { data: unknown; context: unknown }) => Promise<unknown>)({ data, context });
|
|
49
74
|
};
|
|
50
75
|
},
|
|
51
76
|
};
|
|
52
77
|
return api;
|
|
53
78
|
};
|
|
54
|
-
|
|
79
|
+
// auth-context.ts 依赖 createMiddleware({ type: 'function' }).server(fn)
|
|
80
|
+
const createMiddleware = (opts?: { type?: string }) => {
|
|
81
|
+
const mw: { options: { type?: string; server?: unknown }; server?: unknown } = { options: { type: opts?.type } };
|
|
82
|
+
mw.server = (fn: unknown) => {
|
|
83
|
+
mw.options.server = fn;
|
|
84
|
+
return mw;
|
|
85
|
+
};
|
|
86
|
+
return mw;
|
|
87
|
+
};
|
|
88
|
+
return { createServerFn, createMiddleware };
|
|
55
89
|
});
|
|
56
90
|
|
|
57
91
|
vi.mock("@tanstack/react-start/server", () => ({ getRequest: () => ({}) }));
|
|
@@ -82,24 +82,57 @@ const PRISMA = H.prisma;
|
|
|
82
82
|
vi.mock("@tanstack/react-start", () => {
|
|
83
83
|
// 每个 serverFn 实例独立持有自己的 capture,避免同模块多实例共用导致 validator 串号
|
|
84
84
|
const createServerFn = () => {
|
|
85
|
-
const capture: { validator?: unknown; handler?: unknown } = {};
|
|
85
|
+
const capture: { validator?: unknown; handler?: unknown; middlewares?: unknown[] } = {};
|
|
86
86
|
const api = {
|
|
87
87
|
validator: (v: unknown) => {
|
|
88
88
|
capture.validator = v;
|
|
89
89
|
return api;
|
|
90
90
|
},
|
|
91
|
+
middleware: (mws: unknown[]) => {
|
|
92
|
+
capture.middlewares = mws;
|
|
93
|
+
return api;
|
|
94
|
+
},
|
|
91
95
|
handler: (h: unknown) => {
|
|
92
96
|
capture.handler = h;
|
|
93
97
|
return async (args: { data: unknown }) => {
|
|
94
98
|
const v = capture.validator as { parse?: (d: unknown) => unknown } | undefined;
|
|
95
99
|
const data = v && v.parse ? v.parse(args.data) : args.data;
|
|
96
|
-
|
|
100
|
+
// 迁移后经 .middleware([authContextMiddleware]) 注入 context.user:
|
|
101
|
+
// 依序执行 middleware 的 server 段,真实鉴权链由被 mock 的 auth-helpers 承接
|
|
102
|
+
let context: Record<string, unknown> = {};
|
|
103
|
+
for (const mw of capture.middlewares ?? []) {
|
|
104
|
+
const serverFn = (mw as { options?: { server?: unknown } })?.options?.server;
|
|
105
|
+
if (typeof serverFn !== "function") continue;
|
|
106
|
+
const result = await (
|
|
107
|
+
serverFn as (p: unknown) => Promise<{ context?: unknown }>
|
|
108
|
+
)({
|
|
109
|
+
data,
|
|
110
|
+
context,
|
|
111
|
+
method: "POST",
|
|
112
|
+
serverFnMeta: {},
|
|
113
|
+
signal: new AbortController().signal,
|
|
114
|
+
next: async (inner: { context?: unknown }) => ({
|
|
115
|
+
context: { ...context, ...(inner?.context ?? {}) },
|
|
116
|
+
}),
|
|
117
|
+
});
|
|
118
|
+
context = (result?.context ?? context) as Record<string, unknown>;
|
|
119
|
+
}
|
|
120
|
+
return (h as (p: { data: unknown; context: unknown }) => Promise<unknown>)({ data, context });
|
|
97
121
|
};
|
|
98
122
|
},
|
|
99
123
|
};
|
|
100
124
|
return api;
|
|
101
125
|
};
|
|
102
|
-
|
|
126
|
+
// auth-context.ts 依赖 createMiddleware({ type: 'function' }).server(fn)
|
|
127
|
+
const createMiddleware = (opts?: { type?: string }) => {
|
|
128
|
+
const mw: { options: { type?: string; server?: unknown }; server?: unknown } = { options: { type: opts?.type } };
|
|
129
|
+
mw.server = (fn: unknown) => {
|
|
130
|
+
mw.options.server = fn;
|
|
131
|
+
return mw;
|
|
132
|
+
};
|
|
133
|
+
return mw;
|
|
134
|
+
};
|
|
135
|
+
return { createServerFn, createMiddleware };
|
|
103
136
|
});
|
|
104
137
|
|
|
105
138
|
vi.mock("@tanstack/react-start/server", () => ({ getRequest: () => REQ }));
|
|
@@ -227,7 +260,7 @@ beforeEach(() => {
|
|
|
227
260
|
});
|
|
228
261
|
|
|
229
262
|
describe("startGenerationFn", () => {
|
|
230
|
-
it("requireFeature('testGeneration')
|
|
263
|
+
it("requireFeature('testGeneration') 门控先于业务逻辑(认证经 authContextMiddleware 前置)", async () => {
|
|
231
264
|
DB.storyFindUnique.mockResolvedValue({
|
|
232
265
|
id: "s-1",
|
|
233
266
|
projectId: P,
|
|
@@ -243,7 +276,7 @@ describe("startGenerationFn", () => {
|
|
|
243
276
|
|
|
244
277
|
expect(M.requireFeature).toHaveBeenCalledWith(REQ, "testGeneration");
|
|
245
278
|
expect(M.requireFeature.mock.invocationCallOrder[0]).toBeLessThan(
|
|
246
|
-
|
|
279
|
+
DB.storyFindUnique.mock.invocationCallOrder[0]!,
|
|
247
280
|
);
|
|
248
281
|
});
|
|
249
282
|
|
|
@@ -72,24 +72,57 @@ const PRISMA = H.prisma;
|
|
|
72
72
|
vi.mock("@tanstack/react-start", () => {
|
|
73
73
|
// 每个 serverFn 实例独立持有自己的 capture,避免同模块多实例共用导致 validator 串号
|
|
74
74
|
const createServerFn = () => {
|
|
75
|
-
const capture: { validator?: unknown; handler?: unknown } = {};
|
|
75
|
+
const capture: { validator?: unknown; handler?: unknown; middlewares?: unknown[] } = {};
|
|
76
76
|
const api = {
|
|
77
77
|
validator: (v: unknown) => {
|
|
78
78
|
capture.validator = v;
|
|
79
79
|
return api;
|
|
80
80
|
},
|
|
81
|
+
middleware: (mws: unknown[]) => {
|
|
82
|
+
capture.middlewares = mws;
|
|
83
|
+
return api;
|
|
84
|
+
},
|
|
81
85
|
handler: (h: unknown) => {
|
|
82
86
|
capture.handler = h;
|
|
83
87
|
return async (args: { data: unknown }) => {
|
|
84
88
|
const v = capture.validator as { parse?: (d: unknown) => unknown } | undefined;
|
|
85
89
|
const data = v && v.parse ? v.parse(args.data) : args.data;
|
|
86
|
-
|
|
90
|
+
// 迁移后经 .middleware([authContextMiddleware]) 注入 context.user:
|
|
91
|
+
// 依序执行 middleware 的 server 段,真实鉴权链由被 mock 的 auth-helpers 承接
|
|
92
|
+
let context: Record<string, unknown> = {};
|
|
93
|
+
for (const mw of capture.middlewares ?? []) {
|
|
94
|
+
const serverFn = (mw as { options?: { server?: unknown } })?.options?.server;
|
|
95
|
+
if (typeof serverFn !== "function") continue;
|
|
96
|
+
const result = await (
|
|
97
|
+
serverFn as (p: unknown) => Promise<{ context?: unknown }>
|
|
98
|
+
)({
|
|
99
|
+
data,
|
|
100
|
+
context,
|
|
101
|
+
method: "POST",
|
|
102
|
+
serverFnMeta: {},
|
|
103
|
+
signal: new AbortController().signal,
|
|
104
|
+
next: async (inner: { context?: unknown }) => ({
|
|
105
|
+
context: { ...context, ...(inner?.context ?? {}) },
|
|
106
|
+
}),
|
|
107
|
+
});
|
|
108
|
+
context = (result?.context ?? context) as Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
return (h as (p: { data: unknown; context: unknown }) => Promise<unknown>)({ data, context });
|
|
87
111
|
};
|
|
88
112
|
},
|
|
89
113
|
};
|
|
90
114
|
return api;
|
|
91
115
|
};
|
|
92
|
-
|
|
116
|
+
// auth-context.ts 依赖 createMiddleware({ type: 'function' }).server(fn)
|
|
117
|
+
const createMiddleware = (opts?: { type?: string }) => {
|
|
118
|
+
const mw: { options: { type?: string; server?: unknown }; server?: unknown } = { options: { type: opts?.type } };
|
|
119
|
+
mw.server = (fn: unknown) => {
|
|
120
|
+
mw.options.server = fn;
|
|
121
|
+
return mw;
|
|
122
|
+
};
|
|
123
|
+
return mw;
|
|
124
|
+
};
|
|
125
|
+
return { createServerFn, createMiddleware };
|
|
93
126
|
});
|
|
94
127
|
|
|
95
128
|
vi.mock("@tanstack/react-start/server", () => ({ getRequest: () => ({}) }));
|