Some checks failed
CI / typecheck + lint + boundaries + test + build (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Coverage snapshot / snapshot (push) Has been cancelled
Release Please / release-please (push) Has been cancelled
Sentry PII guard (R31) / pii-guard (push) Has been cancelled
CI / Playwright e2e (push) Has been cancelled
CI / Storybook smoke tests + visual regression (push) Has been cancelled
Mutation testing (nightly) / mutate (push) Has been cancelled
Library trace revalidation (weekly) / revalidate (push) Has been cancelled
Replace NotImplementedError stubs in AuthenticationService with working implementations: createSession signs a HS256 JWT using Payload's instance secret, validateSession verifies and decodes the token then looks up the user, invalidateSession returns a blank cookie with maxAge 0. No external JWT dependency — uses Node crypto HMAC directly. Also clarify withAudit/withAnalytics comments: the wrappers intentionally delegate recording to the use case body (only it knows which fields to extract), so the TODO was misleading.
36 lines
1.7 KiB
TypeScript
36 lines
1.7 KiB
TypeScript
import type { IAnalytics } from "./analytics.interface";
|
|
import { attachBrand } from "@repo/core-shared/conformance";
|
|
|
|
/**
|
|
* Phantom-type brand attached at wrap time by `withAnalytics`. The conformance
|
|
* system uses this as the type-level seam for use cases that declare
|
|
* `analyticsEvents: [...]` in their manifest — without `__analyzed`, the
|
|
* binding is not assignable to `ProductionUseCase<I, O, M>` when M demands it.
|
|
* At runtime the brand is a non-enumerable property attached by `attachBrand`
|
|
* from `@repo/core-shared/conformance`, so the boot-time assertion can verify
|
|
* the binding went through the analytics-aware path.
|
|
*/
|
|
export type Analyzed<F> = F & { readonly __analyzed: true };
|
|
|
|
/**
|
|
* Use-case wrapper applied at DI bind time. The wrapper is a thin closure
|
|
* that forwards to `fn` unchanged and carries the `__analyzed` brand. The
|
|
* forward closure (instead of returning `fn` directly) keeps the brand on
|
|
* a fresh function so the caller's original `fn` is not mutated — important
|
|
* when the same factory output is used elsewhere unwrapped (dev-seed paths,
|
|
* tests).
|
|
*/
|
|
export function withAnalytics<Args extends unknown[], R>(
|
|
// The wrapper attaches the brand and ensures the analytics dependency is
|
|
// available at bind time. Actual `analytics.track()` calls live in the
|
|
// use case body — only the use case knows which properties to extract
|
|
// from its input/output for the analytics event.
|
|
analytics: IAnalytics,
|
|
fn: (...args: Args) => Promise<R>,
|
|
): Analyzed<(...args: Args) => Promise<R>> {
|
|
void analytics;
|
|
const wrapped: (...args: Args) => Promise<R> = (...args) => fn(...args);
|
|
attachBrand(wrapped, "__analyzed");
|
|
return wrapped as Analyzed<(...args: Args) => Promise<R>>;
|
|
}
|