Skip to content

Frontend proxies

@cratis/showrunner.usher is the TypeScript side of Cratis.Showrunner.Usher: the proxies Arc generates for Usher’s commands and queries, and a few helpers for reporting errors. It has no components; @cratis/showrunner.usher.react builds the dialogs on top of it; see React components.

Terminal window
yarn add @cratis/showrunner.usher @cratis/arc @cratis/arc.react @cratis/fundamentals

@cratis/arc, @cratis/arc.react and @cratis/fundamentals are peer dependencies, so the application decides their versions. The proxies need @cratis/arc.react because Arc generates a React hook, such as ReportError.use(), on every command and query proxy. Use the package version that matches the Cratis.Showrunner.Usher NuGet package: both are released together with the same version.

Every command and query of the backend has a proxy, exported from the package root:

import { ReportIssue, MyIssues, AccessDuration } from '@cratis/showrunner.usher';
import { Guid } from '@cratis/fundamentals';
const report = new ReportIssue();
report.issueId = Guid.create();
report.summary = 'The invoice is not sent';
report.description = 'I pressed send and nothing happened.';
report.accessDuration = AccessDuration.oneHour;
const result = await report.execute();

The proxies are generated from the C# code; never edit them. They live in the folder of their slice, so Reporting/ReportError/ReportError.ts is the proxy for the ReportError command in the Reporting feature.

Each proxy carries the slice it belongs to as a static sliceLocation, the same location the backend resolves for the command or query:

import { SliceLocation } from '@cratis/arc/reflection';
import { ReportError } from '@cratis/showrunner.usher';
ReportError.sliceLocation.toString(); // 'Reporting/ReportError'
SliceLocation.of(new ReportError()); // the same location, from an instance

Usher’s slices sit directly under the Cratis.Showrunner.Usher namespace, so their module is empty: ReportError is feature Reporting, slice ReportError.

The ReportError command wants the error message and type, the correlation ids, the stack frames and where it happened. These helpers build that as ErrorDetails from whatever the application has at hand, and never return null or undefined parts: what is not known is empty.

FunctionFrom
errorDetailsFromError(error, location?)Anything thrown: a JavaScript Error, or any other value.
errorDetailsFromCommandResult(result, command?, location?)The result of a failed Arc command.
errorDetailsFromQueryResult(result, query?, location?, correlationId?)The result of a failed Arc query.
parseStackTrace(stackTrace?)A stack trace: a JavaScript stack from Chromium, Node.js, Firefox or Safari, or the .NET stack trace Arc returns.
import { errorDetailsFromCommandResult, ReportError } from '@cratis/showrunner.usher';
const result = await payInvoice.execute();
if (!result.isSuccess) {
const details = errorDetailsFromCommandResult(result, payInvoice, location);
const report = new ReportError();
report.location = details.location;
report.errorMessage = details.message;
report.errorType = details.type;
report.correlationIds = details.correlationIds;
report.stackFrames = details.stackFrames;
}
  • Where it happened. When the failing command or query is passed and its proxy declares a slice location, that is used. Otherwise the location passed is used, typically the one useSliceContext() from @cratis/arc.react/slices gives the component that shows the error. Without either, it is empty.
  • The type. A JavaScript error’s type is its name, or its class when a subclass keeps the name Error. Arc does not return the .NET type of a failing command or query, so for those the type is empty.
  • Correlation ids. A command result carries its correlation id, and it is included. A query result does not; pass it when you know it.

For a failing command, the client’s view is only a fallback. The backend captures the error of the failing command itself, and when the report carries the command’s correlation id, Usher records the error as the backend saw it, type and stack frames included; see error capture.

The Debug build of Cratis.Showrunner.Usher generates the proxies into Source/JavaScript/Usher, and they are committed. The npm build compiles the committed proxies with the helpers; it does not run the .NET build. Continuous integration rebuilds Debug and fails when the committed proxies differ from what the backend generates, so a backend change is never released with stale proxies.

Terminal window
dotnet build Showrunner.slnx -c Debug # regenerates Source/JavaScript/Usher
yarn build # builds the npm packages from the committed proxies

The package contains the compiled JavaScript, the type declarations and the TypeScript sources; specifications are left out.