feat: 기능 추가 과정중

This commit is contained in:
donghyeon-ka
2026-07-30 15:58:20 +09:00
parent d3ef801fe6
commit 6c52cdb916
648 changed files with 126325 additions and 6680 deletions
@@ -1,81 +1,115 @@
import { useApplication } from "../../../presentation/providers/application-provider.js";
import { useApplication } from "../../../presentation/providers/application-provider.tsx";
import {
useApplicationMutation,
useApplicationQuery,
} from "../../../presentation/adapters/query/application-query.js";
import { useRouteInput } from "../../../presentation/routes/app-router.js";
import type { ReferenceResourceView } from "../contracts/reference-mapper.js";
} from "../../../presentation/adapters/query/application-query.ts";
import { useRouteInput } from "../../../presentation/routes/route-input.tsx";
import {
REFERENCE_FEATURE_ID,
referenceQueryKeys,
} from "../contracts/reference-feature-contract.js";
REFERENCE_RESOURCE_INVALIDATION_TOPIC,
} from "../contracts/reference-feature-contract.ts";
import type {
ReferenceCreateCommand,
ReferenceFeatureInput,
ReferenceListFilters,
} from "../application/reference-feature-api.js";
} from "../application/reference-feature-api.ts";
import type { ReferenceResourceView } from "../contracts/reference-mapper.ts";
import {
bindQuery,
defineServerStateProfile,
type BoundMutation,
} from "../../../contracts/server-state.ts";
import { useServerStateScope } from "../../../presentation/adapters/query/server-state-scope-provider.tsx";
const REFERENCE_READ_PROFILE = defineServerStateProfile({
profileId: "reference-resource-read-v1",
staleTimeMs: 30_000,
gcTimeMs: 300_000,
refetchOnMount: true,
refetchOnFocus: true,
refetchOnReconnect: true,
retryOwner: "TRANSPORT",
maxResultItems: 100,
maxEstimatedResultBytes: 262_144,
});
export function useReferenceFeatureInput(): ReferenceFeatureInput {
const candidate = useApplication().features.get(REFERENCE_FEATURE_ID);
if (
!candidate ||
typeof candidate !== "object" ||
typeof (candidate as ReferenceFeatureInput).listResources !== "function" ||
typeof (candidate as ReferenceFeatureInput).createResource !== "function" ||
typeof (candidate as ReferenceFeatureInput).getResource !== "function"
) {
throw new Error("Reference feature application input is invalid");
}
return candidate as ReferenceFeatureInput;
return useApplication().features.get(REFERENCE_FEATURE_ID);
}
export function useReferenceDetail(resourceId: string) {
const input = useReferenceFeatureInput();
const query = useApplicationQuery({
queryKey: referenceQueryKeys.detail(resourceId),
execute: ({ signal }) => input.getResource(resourceId, { signal }),
});
const scope = useServerStateScope();
const query = useApplicationQuery(
bindQuery(
{
definitionId: "reference-resource-detail-v1",
definitionVersion: 1,
owner: REFERENCE_FEATURE_ID,
namespace: "reference-resource",
namespaceVersion: 1,
operationId: "GET_REFERENCE_RESOURCE",
profile: REFERENCE_READ_PROFILE,
execute: (selectedResourceId: string, { signal }) =>
input.getResource(selectedResourceId, { signal }),
},
resourceId,
scope,
),
);
return Object.freeze({ query });
}
export function useReferenceCreate() {
const input = useReferenceFeatureInput();
return useApplicationMutation({
const scope = useServerStateScope();
const mutation: BoundMutation<
ReferenceCreateCommand,
ReferenceResourceView
> = {
definitionId: "reference-resource-create-v1",
definitionVersion: 1,
operationId: "CREATE_REFERENCE_RESOURCE",
owner: REFERENCE_FEATURE_ID,
duplicatePolicy: "JOIN_IDENTICAL",
scope,
execute: input.createResource,
invalidate: [referenceQueryKeys.all()],
currentData: true,
});
invalidate: [REFERENCE_RESOURCE_INVALIDATION_TOPIC],
};
return useApplicationMutation(mutation);
}
export function useReferenceFeature() {
const input = useReferenceFeatureInput();
const scope = useServerStateScope();
const routeInput = useRouteInput();
const filters = routeInput.search as ReferenceListFilters;
const queryKey = referenceQueryKeys.list(filters);
const query = useApplicationQuery({
queryKey,
execute: ({ signal }) => input.listResources(filters, { signal }),
});
const mutation = useApplicationMutation({
execute: input.createResource,
invalidate: [referenceQueryKeys.all()],
currentData: true,
optimistic: {
queryKey,
update(previous, command: Readonly<{ name: string }>) {
const current = Array.isArray(previous)
? (previous as readonly ReferenceResourceView[])
: [];
return [
...current,
{
resourceId: `optimistic:${command.name}`,
title: command.name,
createdAt: null,
optimistic: true,
},
];
const query = useApplicationQuery(
bindQuery(
{
definitionId: "reference-resource-list-v1",
definitionVersion: 1,
owner: REFERENCE_FEATURE_ID,
namespace: "reference-resource",
namespaceVersion: 1,
operationId: "LIST_REFERENCE_RESOURCES",
profile: REFERENCE_READ_PROFILE,
execute: (selectedFilters: ReferenceListFilters, { signal }) =>
input.listResources(selectedFilters, { signal }),
},
},
filters,
scope,
),
);
const mutation = useApplicationMutation({
definitionId: "reference-resource-create-v1",
definitionVersion: 1,
operationId: "CREATE_REFERENCE_RESOURCE",
owner: REFERENCE_FEATURE_ID,
duplicatePolicy: "JOIN_IDENTICAL",
scope,
execute: input.createResource,
invalidate: [REFERENCE_RESOURCE_INVALIDATION_TOPIC],
});
return Object.freeze({ filters, query, mutation });
}