feat: add the TechLog asset multipart upload transport
Wires the whole Asset capability into the running application: the multipart upload transport (the contract runtime can only express JSON bodies), a single composition-root-owned CSRF provider shared between the platform's credential collaborator (18 JSON operations) and the upload transport (1 multipart operation), and Studio/StudioShell exposure of the Asset gateway alongside the existing document gateway. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
d9c2d8bc5e
commit
c9c832c365
@@ -7,6 +7,7 @@ import {
|
||||
} from "react";
|
||||
|
||||
import { isStudioGatewayError } from "../../application/ports/studio-gateway-error.ts";
|
||||
import type { StudioAssetGateway } from "../../application/ports/studio-asset-gateway.ts";
|
||||
import type { StudioGateway } from "../../application/ports/studio-gateway.ts";
|
||||
import type { ResolvePublishedLabel } from "../../domain/public-render-content.ts";
|
||||
import type {
|
||||
@@ -25,6 +26,9 @@ import { useBeforeUnload } from "./components/use-before-unload.ts";
|
||||
type StudioProviderProps = Readonly<{
|
||||
children: ReactNode;
|
||||
createGateway: () => StudioGateway;
|
||||
// Optional so test harnesses that only exercise the document gateway keep
|
||||
// working unchanged. `StudioShell` always supplies one in the running app.
|
||||
createAssetGateway?: () => StudioAssetGateway;
|
||||
resolvePublishedLabel?: ResolvePublishedLabel;
|
||||
now?: () => Date;
|
||||
navigate?: (href: string) => void;
|
||||
@@ -48,11 +52,18 @@ const missingPublishedLabel: ResolvePublishedLabel = () => undefined;
|
||||
export function StudioProvider({
|
||||
children,
|
||||
createGateway,
|
||||
createAssetGateway,
|
||||
resolvePublishedLabel = missingPublishedLabel,
|
||||
now = () => new Date("2026-08-14T01:00:00.000Z"),
|
||||
navigate = defaultNavigate,
|
||||
}: StudioProviderProps) {
|
||||
const [gateway] = useState<StudioGateway>(() => createGateway());
|
||||
// Same lazy, called-once-per-mount pattern as `gateway`. Both are keyed to
|
||||
// the same provider generation in `StudioShell`, so a persisted `pageshow`
|
||||
// remount recreates them together — never one without the other.
|
||||
const [assetGateway] = useState<StudioAssetGateway | null>(
|
||||
() => createAssetGateway?.() ?? null,
|
||||
);
|
||||
const [editor, setEditor] = useState<StudioEditorState | null>(null);
|
||||
const [pendingHref, setPendingHref] = useState<string | null>(null);
|
||||
const [requestAnnouncement, setRequestAnnouncement] = useState("");
|
||||
@@ -148,6 +159,7 @@ export function StudioProvider({
|
||||
const value = useMemo<StudioContextValue>(
|
||||
() => ({
|
||||
gateway,
|
||||
assetGateway,
|
||||
resolvePublishedLabel,
|
||||
now,
|
||||
editor,
|
||||
@@ -160,6 +172,7 @@ export function StudioProvider({
|
||||
clearEditor,
|
||||
}),
|
||||
[
|
||||
assetGateway,
|
||||
beginEditor,
|
||||
clearEditor,
|
||||
editor,
|
||||
|
||||
Reference in New Issue
Block a user