@unisian/start 0.0.0-placeholder → 0.0.0-stage
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/README.md +3 -0
- package/package.json +3 -50
- package/dist/browser-error-contract.d.mts +0 -15
- package/dist/browser-error-contract.mjs +0 -20
- package/dist/browser-error-report.d.mts +0 -8
- package/dist/browser-error-report.mjs +0 -29
- package/dist/client.d.mts +0 -31
- package/dist/client.mjs +0 -63
- package/dist/command-form.d.mts +0 -36
- package/dist/command-form.mjs +0 -61
- package/dist/failure.d.mts +0 -33
- package/dist/failure.mjs +0 -24
- package/dist/function-id.d.mts +0 -7
- package/dist/function-id.mjs +0 -18
- package/dist/index.d.mts +0 -5
- package/dist/index.mjs +0 -5
- package/dist/input.d.mts +0 -6
- package/dist/input.mjs +0 -5
- package/dist/middleware.d.mts +0 -14
- package/dist/middleware.mjs +0 -24
- package/dist/report-browser-error.d.mts +0 -10
- package/dist/report-browser-error.mjs +0 -15
- package/dist/report.d.mts +0 -15
- package/dist/report.mjs +0 -31
- package/dist/router.d.mts +0 -10
- package/dist/router.mjs +0 -27
- package/dist/serve.d.mts +0 -31
- package/dist/serve.mjs +0 -34
- package/dist/wire.mjs +0 -32
package/README.md
ADDED
package/package.json
CHANGED
|
@@ -1,53 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unisian/start",
|
|
3
|
-
"version": "0.0.0-
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/baoagency/unisian-next.git",
|
|
8
|
-
"directory": "packages/start"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"dist"
|
|
12
|
-
],
|
|
13
|
-
"type": "module",
|
|
14
|
-
"exports": {
|
|
15
|
-
".": "./dist/index.mjs",
|
|
16
|
-
"./react": "./dist/client.mjs",
|
|
17
|
-
"./serve": "./dist/serve.mjs",
|
|
18
|
-
"./middleware": "./dist/middleware.mjs",
|
|
19
|
-
"./function-id": "./dist/function-id.mjs"
|
|
20
|
-
},
|
|
21
|
-
"publishConfig": {
|
|
22
|
-
"access": "public"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"@tanstack/react-form": "1.33.5"
|
|
26
|
-
},
|
|
27
|
-
"devDependencies": {
|
|
28
|
-
"@tanstack/react-query": "5.104.1",
|
|
29
|
-
"@tanstack/react-router": "1.170.41",
|
|
30
|
-
"@tanstack/react-router-ssr-query": "1.167.3",
|
|
31
|
-
"@tanstack/react-start": "1.168.60",
|
|
32
|
-
"effect": "4.0.2",
|
|
33
|
-
"react": "19.3.0",
|
|
34
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
|
|
35
|
-
"@unisian/capability": "0.1.0",
|
|
36
|
-
"@unisian/effect-observability": "0.1.0",
|
|
37
|
-
"@unisian/shopify-auth": "0.1.0",
|
|
38
|
-
"@unisian/shopify-sessions": "0.1.0"
|
|
39
|
-
},
|
|
40
|
-
"peerDependencies": {
|
|
41
|
-
"@tanstack/react-query": "^5.104.1",
|
|
42
|
-
"@tanstack/react-router": "^1.170.41",
|
|
43
|
-
"@tanstack/react-router-ssr-query": "^1.167.3",
|
|
44
|
-
"@tanstack/react-start": "^1.168.60",
|
|
45
|
-
"effect": "^4.0.2",
|
|
46
|
-
"react": "^19.3.0",
|
|
47
|
-
"@unisian/capability": "0.1.0",
|
|
48
|
-
"@unisian/shopify-auth": "0.1.0",
|
|
49
|
-
"@unisian/effect-observability": "0.1.0",
|
|
50
|
-
"@unisian/shopify-sessions": "0.1.0"
|
|
51
|
-
},
|
|
52
|
-
"scripts": {}
|
|
3
|
+
"version": "0.0.0-stage",
|
|
4
|
+
"stub": true,
|
|
5
|
+
"description": "Temporary package placeholder for staged publishing"
|
|
53
6
|
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
|
-
//#region src/browser-error-contract.d.ts
|
|
3
|
-
export declare const browserErrorLimits: {
|
|
4
|
-
readonly message: 2000;
|
|
5
|
-
readonly path: 500;
|
|
6
|
-
readonly stack: 8000;
|
|
7
|
-
};
|
|
8
|
-
export declare const reportBrowserErrorContract: import("@unisian/capability").Contract<"reportBrowserError", Schema.Struct<{
|
|
9
|
-
readonly message: Schema.String;
|
|
10
|
-
readonly path: Schema.String;
|
|
11
|
-
readonly stack: Schema.optional<Schema.String>;
|
|
12
|
-
}>, Schema.Struct<{
|
|
13
|
-
readonly reference: Schema.String;
|
|
14
|
-
}>, Schema.Never>;
|
|
15
|
-
//#endregion
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
|
-
import { defineContract } from "@unisian/capability";
|
|
3
|
-
//#region src/browser-error-contract.ts
|
|
4
|
-
const browserErrorLimits = {
|
|
5
|
-
message: 2e3,
|
|
6
|
-
path: 500,
|
|
7
|
-
stack: 8e3
|
|
8
|
-
};
|
|
9
|
-
const reportBrowserErrorContract = defineContract("reportBrowserError", {
|
|
10
|
-
description: "Log an error that broke a page in the merchant's browser, under this request's reference, and return the reference for the error page to show",
|
|
11
|
-
failure: Schema.Never,
|
|
12
|
-
input: Schema.Struct({
|
|
13
|
-
message: Schema.String.check(Schema.isMaxLength(browserErrorLimits.message)),
|
|
14
|
-
path: Schema.String.check(Schema.isMaxLength(browserErrorLimits.path)),
|
|
15
|
-
stack: Schema.optional(Schema.String.check(Schema.isMaxLength(browserErrorLimits.stack)))
|
|
16
|
-
}),
|
|
17
|
-
output: Schema.Struct({ reference: Schema.String })
|
|
18
|
-
});
|
|
19
|
-
//#endregion
|
|
20
|
-
export { browserErrorLimits, reportBrowserErrorContract };
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { reportBrowserErrorContract } from "./browser-error-contract.mjs";
|
|
2
|
-
import { command } from "./client.mjs";
|
|
3
|
-
import { QueryClient } from "@tanstack/react-query";
|
|
4
|
-
//#region src/browser-error-report.d.ts
|
|
5
|
-
export type BrowserErrorReport = ReturnType<typeof command<typeof reportBrowserErrorContract>>;
|
|
6
|
-
export declare const reportBrowserErrors: (queryClient: QueryClient, report: BrowserErrorReport) => (cause: unknown) => void;
|
|
7
|
-
export declare const useBrowserErrorReference: (report: BrowserErrorReport, cause: unknown) => string | undefined;
|
|
8
|
-
//#endregion
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { caughtError, decodeReport } from "./report.mjs";
|
|
2
|
-
import { browserErrorLimits, reportBrowserErrorContract } from "./browser-error-contract.mjs";
|
|
3
|
-
import * as Schema from "effect/Schema";
|
|
4
|
-
import { MutationObserver, useMutationState } from "@tanstack/react-query";
|
|
5
|
-
//#region src/browser-error-report.ts
|
|
6
|
-
const reportedMessage = (cause) => caughtError(cause).message.slice(0, browserErrorLimits.message);
|
|
7
|
-
const reportBrowserErrors = (queryClient, report) => (cause) => {
|
|
8
|
-
if (decodeReport(cause).reference !== "none") return;
|
|
9
|
-
new MutationObserver(queryClient, report).mutate({
|
|
10
|
-
message: reportedMessage(cause),
|
|
11
|
-
path: globalThis.location.pathname.slice(0, browserErrorLimits.path),
|
|
12
|
-
stack: caughtError(cause).stack?.slice(0, browserErrorLimits.stack)
|
|
13
|
-
}).catch(() => null);
|
|
14
|
-
};
|
|
15
|
-
const isReportInput = Schema.is(reportBrowserErrorContract.input);
|
|
16
|
-
const isReportOutput = Schema.is(reportBrowserErrorContract.output);
|
|
17
|
-
const useBrowserErrorReference = (report, cause) => {
|
|
18
|
-
const message = reportedMessage(cause);
|
|
19
|
-
return useMutationState({
|
|
20
|
-
filters: {
|
|
21
|
-
mutationKey: report.mutationKey,
|
|
22
|
-
predicate: ({ state }) => isReportInput(state.variables) && state.variables.message === message,
|
|
23
|
-
status: "success"
|
|
24
|
-
},
|
|
25
|
-
select: ({ state }) => isReportOutput(state.data) ? state.data.reference : void 0
|
|
26
|
-
}).at(-1);
|
|
27
|
-
};
|
|
28
|
-
//#endregion
|
|
29
|
-
export { reportBrowserErrors, useBrowserErrorReference };
|
package/dist/client.d.mts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { CapabilityFailureError } from "./failure.mjs";
|
|
2
|
-
import { BrowserErrorReport, reportBrowserErrors, useBrowserErrorReference } from "./browser-error-report.mjs";
|
|
3
|
-
import { useCommandForm } from "./command-form.mjs";
|
|
4
|
-
import { AppRouterOptions, createAppRouter } from "./router.mjs";
|
|
5
|
-
import * as Schema from "effect/Schema";
|
|
6
|
-
import * as Option from "effect/Option";
|
|
7
|
-
import { AnyContract, FailureOf, InputOf, OutputOf } from "@unisian/capability";
|
|
8
|
-
import { QueryClient, QueryKey, UseSuspenseQueryOptions } from "@tanstack/react-query";
|
|
9
|
-
//#region src/client.d.ts
|
|
10
|
-
export type ServerFn<ContractType extends AnyContract> = (options: {
|
|
11
|
-
readonly data: InputOf<ContractType>["Encoded"];
|
|
12
|
-
readonly headers?: Record<string, string>;
|
|
13
|
-
}) => Promise<Schema.Json>;
|
|
14
|
-
export interface PerCall {
|
|
15
|
-
readonly headers?: Record<string, string> | undefined;
|
|
16
|
-
readonly key?: Schema.Json | undefined;
|
|
17
|
-
}
|
|
18
|
-
export declare const query: <ContractType extends AnyContract>(contract: ContractType, serverFn: ServerFn<ContractType>) => (input: InputOf<ContractType>["Type"], perCall?: PerCall) => import("@tanstack/react-query").OmitKeyof<import("@tanstack/react-query").UseQueryOptions<Schema.Json, CapabilityFailureError<FailureOf<ContractType>["Type"]>, OutputOf<ContractType>["Type"], readonly [ContractType["name"], InputOf<ContractType>["Encoded"], ...Schema.Json[]]>, "queryFn"> & {
|
|
19
|
-
queryFn?: import("@tanstack/react-query").QueryFunction<Schema.Json, readonly [ContractType["name"], InputOf<ContractType>["Encoded"], ...Schema.Json[]], never>;
|
|
20
|
-
} & import("@tanstack/react-query").QueryKeyWithDataTag<readonly [ContractType["name"], InputOf<ContractType>["Encoded"], ...Schema.Json[]], Schema.Json, CapabilityFailureError<FailureOf<ContractType>["Type"]>>;
|
|
21
|
-
export declare const cachedData: <Output>(client: QueryClient, options: {
|
|
22
|
-
readonly queryKey: QueryKey;
|
|
23
|
-
readonly select?: ((encoded: Schema.Json) => Output) | undefined;
|
|
24
|
-
}) => Output | undefined;
|
|
25
|
-
export declare const cachedQuery: <QueryFnData, QueryError, Data, Key extends QueryKey>(client: QueryClient, options: UseSuspenseQueryOptions<QueryFnData, QueryError, Data, Key>) => Promise<Option.Option<Data>>;
|
|
26
|
-
export interface CommandOptions extends PerCall {
|
|
27
|
-
readonly invalidates: readonly AnyContract[];
|
|
28
|
-
}
|
|
29
|
-
export declare const command: <ContractType extends AnyContract>(contract: ContractType, serverFn: ServerFn<ContractType>, options: CommandOptions) => import("@tanstack/react-query").WithRequired<import("@tanstack/react-query").UseMutationOptions<OutputOf<ContractType>["Type"], CapabilityFailureError<FailureOf<ContractType>["Type"]>, InputOf<ContractType>["Type"], unknown>, "mutationKey">;
|
|
30
|
-
//#endregion
|
|
31
|
-
export { type AppRouterOptions, type BrowserErrorReport, createAppRouter, reportBrowserErrors, useBrowserErrorReference, useCommandForm };
|
package/dist/client.mjs
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { CapabilityFailureError } from "./failure.mjs";
|
|
2
|
-
import { wireFor } from "./wire.mjs";
|
|
3
|
-
import { reportBrowserErrors, useBrowserErrorReference } from "./browser-error-report.mjs";
|
|
4
|
-
import { useCommandForm } from "./command-form.mjs";
|
|
5
|
-
import { createAppRouter } from "./router.mjs";
|
|
6
|
-
import * as Schema from "effect/Schema";
|
|
7
|
-
import * as Option from "effect/Option";
|
|
8
|
-
import { environmentManager, mutationOptions, queryOptions } from "@tanstack/react-query";
|
|
9
|
-
//#region src/client.ts
|
|
10
|
-
const transportRetries = 2;
|
|
11
|
-
const keyFor = (head, { key }) => key === void 0 ? head : [...head, key];
|
|
12
|
-
const callerFor = (contract, serverFn) => {
|
|
13
|
-
const encodeInput = Schema.encodeSync(contract.input);
|
|
14
|
-
const decodeOutput = Schema.decodeUnknownSync(Schema.toCodecJson(contract.output));
|
|
15
|
-
const { decode } = wireFor(contract.failure);
|
|
16
|
-
return {
|
|
17
|
-
call: (data, { headers }) => serverFn(headers === void 0 ? { data } : {
|
|
18
|
-
data,
|
|
19
|
-
headers
|
|
20
|
-
}).then(decode),
|
|
21
|
-
decodeOutput,
|
|
22
|
-
encodeInput
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
const query = (contract, serverFn) => {
|
|
26
|
-
const { encodeInput, decodeOutput, call } = callerFor(contract, serverFn);
|
|
27
|
-
return (input, perCall = {}) => {
|
|
28
|
-
const data = encodeInput(input);
|
|
29
|
-
return queryOptions({
|
|
30
|
-
queryFn: () => call(data, perCall),
|
|
31
|
-
queryKey: keyFor([contract.name, data], perCall),
|
|
32
|
-
retry: (failureCount, error) => !(error instanceof CapabilityFailureError) && failureCount < (environmentManager.isServer() ? 0 : transportRetries),
|
|
33
|
-
select: decodeOutput
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
const cachedData = (client, options) => {
|
|
38
|
-
const encoded = client.getQueryData(options.queryKey);
|
|
39
|
-
return encoded === void 0 ? void 0 : options.select?.(encoded);
|
|
40
|
-
};
|
|
41
|
-
const cachedQuery = (client, options) => {
|
|
42
|
-
const { queryFn } = options;
|
|
43
|
-
return queryFn === void 0 ? Promise.resolve(Option.none()) : client.query({
|
|
44
|
-
...options,
|
|
45
|
-
queryFn,
|
|
46
|
-
staleTime: "static"
|
|
47
|
-
}).then(Option.some);
|
|
48
|
-
};
|
|
49
|
-
const command = (contract, serverFn, options) => {
|
|
50
|
-
const { encodeInput, decodeOutput, call } = callerFor(contract, serverFn);
|
|
51
|
-
return mutationOptions({
|
|
52
|
-
mutationFn: async (input, { client }) => {
|
|
53
|
-
try {
|
|
54
|
-
return decodeOutput(await call(encodeInput(input), options));
|
|
55
|
-
} finally {
|
|
56
|
-
await Promise.all(options.invalidates.map(({ name }) => client.invalidateQueries({ queryKey: [name] })));
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
mutationKey: keyFor([contract.name], options)
|
|
60
|
-
});
|
|
61
|
-
};
|
|
62
|
-
//#endregion
|
|
63
|
-
export { cachedData, cachedQuery, command, createAppRouter, query, reportBrowserErrors, useBrowserErrorReference, useCommandForm };
|
package/dist/command-form.d.mts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { CapabilityFailureError } from "./failure.mjs";
|
|
2
|
-
import { InputSchema } from "@unisian/capability";
|
|
3
|
-
import { UseMutationOptions } from "@tanstack/react-query";
|
|
4
|
-
//#region src/command-form.d.ts
|
|
5
|
-
interface FormMessage {
|
|
6
|
-
readonly message: string;
|
|
7
|
-
}
|
|
8
|
-
interface SavingForm<Values> {
|
|
9
|
-
readonly fieldInfo: object;
|
|
10
|
-
readonly reset: (values: Values) => void;
|
|
11
|
-
setErrorMap(errorMap: {
|
|
12
|
-
readonly onSubmit: {
|
|
13
|
-
readonly fields: Record<string, FormMessage>;
|
|
14
|
-
readonly form: readonly FormMessage[] | undefined;
|
|
15
|
-
};
|
|
16
|
-
}): void;
|
|
17
|
-
}
|
|
18
|
-
export declare const useCommandForm: <Input extends InputSchema, Failure>({ command, contract, defaultValues, onSaved }: {
|
|
19
|
-
readonly command: UseMutationOptions<Input["Type"], CapabilityFailureError<Failure>, Input["Type"]>;
|
|
20
|
-
readonly contract: {
|
|
21
|
-
readonly input: Input;
|
|
22
|
-
};
|
|
23
|
-
readonly defaultValues: Input["Type"];
|
|
24
|
-
readonly onSaved?: (output: Input["Type"]) => void;
|
|
25
|
-
}) => {
|
|
26
|
-
defaultValues: Input["Encoded"];
|
|
27
|
-
onSubmit: ({ formApi, value }: {
|
|
28
|
-
readonly formApi: SavingForm<Input["Encoded"]>;
|
|
29
|
-
readonly value: Input["Encoded"];
|
|
30
|
-
}) => Promise<void>;
|
|
31
|
-
validationLogic: import("@tanstack/react-form").ValidationLogicFn;
|
|
32
|
-
validators: {
|
|
33
|
-
onDynamic: import("effect/StandardSchema").StandardSchemaV1<Input["Encoded"], Input["Type"]> & Input;
|
|
34
|
-
};
|
|
35
|
-
};
|
|
36
|
-
//#endregion
|
package/dist/command-form.mjs
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { CapabilityFailureError, isFieldIssues, isMerchantFacing } from "./failure.mjs";
|
|
2
|
-
import { input } from "./input.mjs";
|
|
3
|
-
import * as Schema from "effect/Schema";
|
|
4
|
-
import { useMutation } from "@tanstack/react-query";
|
|
5
|
-
import { revalidateLogic } from "@tanstack/react-form";
|
|
6
|
-
//#region src/command-form.ts
|
|
7
|
-
const issuesIn = (cause) => {
|
|
8
|
-
if (!(cause instanceof CapabilityFailureError)) return [];
|
|
9
|
-
const failure = cause.failure;
|
|
10
|
-
return [...isMerchantFacing(failure) ? [{
|
|
11
|
-
message: failure.merchantMessage,
|
|
12
|
-
path: []
|
|
13
|
-
}] : [], ...isFieldIssues(failure) ? failure.fieldIssues : []];
|
|
14
|
-
};
|
|
15
|
-
const fieldName = (path) => path.map((segment, index) => {
|
|
16
|
-
if (/^\d+$/u.test(segment)) return `[${segment}]`;
|
|
17
|
-
return index === 0 ? segment : `.${segment}`;
|
|
18
|
-
}).join("");
|
|
19
|
-
const showOnForm = (form, cause) => {
|
|
20
|
-
const issues = issuesIn(cause).map((issue) => ({
|
|
21
|
-
...issue,
|
|
22
|
-
name: fieldName(issue.path)
|
|
23
|
-
}));
|
|
24
|
-
if (issues.length === 0) return false;
|
|
25
|
-
const isField = (name) => Object.hasOwn(form.fieldInfo, name);
|
|
26
|
-
const fields = Object.fromEntries(issues.filter(({ name }) => isField(name)).toReversed().map(({ message, name }) => [name, { message }]));
|
|
27
|
-
const formIssues = issues.filter(({ name }) => !isField(name)).map(({ message }) => ({ message }));
|
|
28
|
-
form.setErrorMap({ onSubmit: {
|
|
29
|
-
fields,
|
|
30
|
-
form: formIssues.length === 0 ? void 0 : formIssues
|
|
31
|
-
} });
|
|
32
|
-
return true;
|
|
33
|
-
};
|
|
34
|
-
const commandFormOptions = (contract, save, defaultValues, onSaved) => {
|
|
35
|
-
const encodeSync = Schema.encodeSync(contract.input);
|
|
36
|
-
const encode = (values) => encodeSync(values, { disableChecks: true });
|
|
37
|
-
const decode = Schema.decodeUnknownSync(contract.input);
|
|
38
|
-
return {
|
|
39
|
-
defaultValues: encode(defaultValues),
|
|
40
|
-
onSubmit: ({ formApi, value }) => save(decode(value)).then((output) => {
|
|
41
|
-
formApi.reset(encode(output));
|
|
42
|
-
onSaved?.(output);
|
|
43
|
-
}, (error) => {
|
|
44
|
-
showOnForm(formApi, error);
|
|
45
|
-
}),
|
|
46
|
-
validationLogic: revalidateLogic({
|
|
47
|
-
mode: "submit",
|
|
48
|
-
modeAfterSubmission: "change"
|
|
49
|
-
}),
|
|
50
|
-
validators: { onDynamic: input(contract) }
|
|
51
|
-
};
|
|
52
|
-
};
|
|
53
|
-
const useCommandForm = ({ command, contract, defaultValues, onSaved }) => {
|
|
54
|
-
const { mutateAsync } = useMutation({
|
|
55
|
-
...command,
|
|
56
|
-
throwOnError: (error) => issuesIn(error).length === 0
|
|
57
|
-
});
|
|
58
|
-
return commandFormOptions(contract, mutateAsync, defaultValues, onSaved);
|
|
59
|
-
};
|
|
60
|
-
//#endregion
|
|
61
|
-
export { commandFormOptions, showOnForm, useCommandForm };
|
package/dist/failure.d.mts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { ErrorReport } from "./report.mjs";
|
|
2
|
-
import * as Schema from "effect/Schema";
|
|
3
|
-
//#region src/failure.d.ts
|
|
4
|
-
export declare class CapabilityFailureError<Failure = unknown> extends Error {
|
|
5
|
-
readonly name = "CapabilityFailureError";
|
|
6
|
-
readonly report: ErrorReport;
|
|
7
|
-
readonly failure: Failure | undefined;
|
|
8
|
-
constructor(report: ErrorReport, failure: Failure | undefined);
|
|
9
|
-
}
|
|
10
|
-
export declare const isFailure: <Failure extends {
|
|
11
|
-
readonly _tag: string;
|
|
12
|
-
}, const Tag extends Failure["_tag"]>(error: CapabilityFailureError<Failure> | Error | null | undefined, tag: Tag) => error is CapabilityFailureError<Extract<Failure, {
|
|
13
|
-
readonly _tag: Tag;
|
|
14
|
-
}>>;
|
|
15
|
-
export declare const MerchantFacing: Schema.Struct<{
|
|
16
|
-
readonly merchantMessage: Schema.String;
|
|
17
|
-
}>;
|
|
18
|
-
export declare const isMerchantFacing: <I>(input: I) => input is I & {
|
|
19
|
-
readonly merchantMessage: string;
|
|
20
|
-
};
|
|
21
|
-
export declare const FieldIssues: Schema.Struct<{
|
|
22
|
-
readonly fieldIssues: Schema.$Array<Schema.Struct<{
|
|
23
|
-
readonly message: Schema.String;
|
|
24
|
-
readonly path: Schema.$Array<Schema.String>;
|
|
25
|
-
}>>;
|
|
26
|
-
}>;
|
|
27
|
-
export declare const isFieldIssues: <I>(input: I) => input is I & {
|
|
28
|
-
readonly fieldIssues: readonly {
|
|
29
|
-
readonly message: string;
|
|
30
|
-
readonly path: readonly string[];
|
|
31
|
-
}[];
|
|
32
|
-
};
|
|
33
|
-
//#endregion
|
package/dist/failure.mjs
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { encodeReport } from "./report.mjs";
|
|
2
|
-
import * as Predicate from "effect/Predicate";
|
|
3
|
-
import * as Schema from "effect/Schema";
|
|
4
|
-
//#region src/failure.ts
|
|
5
|
-
var CapabilityFailureError = class extends Error {
|
|
6
|
-
name = "CapabilityFailureError";
|
|
7
|
-
report;
|
|
8
|
-
failure;
|
|
9
|
-
constructor(report, failure) {
|
|
10
|
-
super(encodeReport(report));
|
|
11
|
-
this.report = report;
|
|
12
|
-
this.failure = failure;
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
const isFailure = (error, tag) => error instanceof CapabilityFailureError && Predicate.isTagged(error.failure, tag);
|
|
16
|
-
const MerchantFacing = Schema.Struct({ merchantMessage: Schema.String });
|
|
17
|
-
const isMerchantFacing = Schema.is(MerchantFacing);
|
|
18
|
-
const FieldIssues = Schema.Struct({ fieldIssues: Schema.Array(Schema.Struct({
|
|
19
|
-
message: Schema.String,
|
|
20
|
-
path: Schema.Array(Schema.String)
|
|
21
|
-
})) });
|
|
22
|
-
const isFieldIssues = Schema.is(FieldIssues);
|
|
23
|
-
//#endregion
|
|
24
|
-
export { CapabilityFailureError, FieldIssues, MerchantFacing, isFailure, isFieldIssues, isMerchantFacing };
|
package/dist/function-id.d.mts
DELETED
package/dist/function-id.mjs
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
//#region src/function-id.ts
|
|
2
|
-
const SERVER_FN_SUFFIX = "Fn";
|
|
3
|
-
const HANDLER_SUFFIX = `${SERVER_FN_SUFFIX}_createServerFn_handler`;
|
|
4
|
-
const serverFnNameFor = (contractName) => `${contractName}${SERVER_FN_SUFFIX}`;
|
|
5
|
-
const functionIds = () => {
|
|
6
|
-
const sources = /* @__PURE__ */ new Map();
|
|
7
|
-
return ({ filename, functionName }) => {
|
|
8
|
-
const source = `${filename} ${functionName}`;
|
|
9
|
-
if (!functionName.endsWith(HANDLER_SUFFIX)) throw new Error(`${source}: name a server function <contract name>${SERVER_FN_SUFFIX}, so its URL names the contract`);
|
|
10
|
-
const id = functionName.slice(0, -HANDLER_SUFFIX.length);
|
|
11
|
-
const claimed = sources.get(id);
|
|
12
|
-
if (claimed !== void 0 && claimed !== source) throw new Error(`${source} and ${claimed} both serve ${id}; declare its server function once and import it`);
|
|
13
|
-
sources.set(id, source);
|
|
14
|
-
return id;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
//#endregion
|
|
18
|
-
export { functionIds, serverFnNameFor };
|
package/dist/index.d.mts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { ErrorReport, PUBLIC_ERROR_MESSAGE, decodeReport, encodeReport, errorPageHtml, errorReport } from "./report.mjs";
|
|
2
|
-
import { CapabilityFailureError, FieldIssues, MerchantFacing, isFailure, isFieldIssues, isMerchantFacing } from "./failure.mjs";
|
|
3
|
-
import { browserErrorLimits, reportBrowserErrorContract } from "./browser-error-contract.mjs";
|
|
4
|
-
import { input } from "./input.mjs";
|
|
5
|
-
export { CapabilityFailureError, ErrorReport, FieldIssues, MerchantFacing, PUBLIC_ERROR_MESSAGE, browserErrorLimits, decodeReport, encodeReport, errorPageHtml, errorReport, input, isFailure, isFieldIssues, isMerchantFacing, reportBrowserErrorContract };
|
package/dist/index.mjs
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { ErrorReport, PUBLIC_ERROR_MESSAGE, decodeReport, encodeReport, errorPageHtml, errorReport } from "./report.mjs";
|
|
2
|
-
import { CapabilityFailureError, FieldIssues, MerchantFacing, isFailure, isFieldIssues, isMerchantFacing } from "./failure.mjs";
|
|
3
|
-
import { input } from "./input.mjs";
|
|
4
|
-
import { browserErrorLimits, reportBrowserErrorContract } from "./browser-error-contract.mjs";
|
|
5
|
-
export { CapabilityFailureError, ErrorReport, FieldIssues, MerchantFacing, PUBLIC_ERROR_MESSAGE, browserErrorLimits, decodeReport, encodeReport, errorPageHtml, errorReport, input, isFailure, isFieldIssues, isMerchantFacing, reportBrowserErrorContract };
|
package/dist/input.d.mts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { InputSchema } from "@unisian/capability";
|
|
2
|
-
//#region src/input.d.ts
|
|
3
|
-
export declare const input: <Input extends InputSchema>(contract: {
|
|
4
|
-
readonly input: Input;
|
|
5
|
-
}) => import("effect/StandardSchema").StandardSchemaV1<Input["Encoded"], Input["Type"]> & Input;
|
|
6
|
-
//#endregion
|
package/dist/input.mjs
DELETED
package/dist/middleware.d.mts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import * as Cause from "effect/Cause";
|
|
2
|
-
import { RequestLogTags, RunTags } from "@unisian/effect-observability";
|
|
3
|
-
import * as Effect from "effect/Effect";
|
|
4
|
-
import { RequestServerFn } from "@tanstack/react-start";
|
|
5
|
-
//#region src/middleware.d.ts
|
|
6
|
-
export interface RequestMiddlewareAnswers<Added, E> {
|
|
7
|
-
readonly refuse: (request: Request, cause: Cause.Cause<E>, log: RequestLogTags) => Response;
|
|
8
|
-
readonly answer?: (response: Response, added: Added) => Response;
|
|
9
|
-
}
|
|
10
|
-
export declare const respond: <E>(name: string, tags: RunTags, refuse: (cause: Cause.Cause<E>) => Response) => (effect: Effect.Effect<Response, E>) => Promise<Response>;
|
|
11
|
-
export declare const requestMiddleware: <Added extends object, E>(name: string, run: (request: Request, pathname: string) => Effect.Effect<Added, E>, answers: RequestMiddlewareAnswers<Added, E>) => RequestServerFn<object, undefined, Added & {
|
|
12
|
-
readonly log: RequestLogTags;
|
|
13
|
-
}>;
|
|
14
|
-
//#endregion
|
package/dist/middleware.mjs
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import * as Exit from "effect/Exit";
|
|
2
|
-
import { requestLogTags, runPromiseExit } from "@unisian/effect-observability";
|
|
3
|
-
//#region src/middleware.ts
|
|
4
|
-
const isSettled = (effect) => Exit.isExit(effect);
|
|
5
|
-
const settle = (name, tags, effect) => isSettled(effect) ? Promise.resolve(effect) : effect.pipe(runPromiseExit(name, tags));
|
|
6
|
-
const respond = (name, tags, refuse) => async (effect) => {
|
|
7
|
-
const exit = await settle(name, tags, effect);
|
|
8
|
-
return Exit.isSuccess(exit) ? exit.value : refuse(exit.cause);
|
|
9
|
-
};
|
|
10
|
-
const requestMiddleware = (name, run, answers) => async ({ request, pathname, next: route }) => {
|
|
11
|
-
const log = requestLogTags(request);
|
|
12
|
-
const exit = await settle(name, log, run(request, pathname));
|
|
13
|
-
if (Exit.isFailure(exit)) return answers.refuse(request, exit.cause, log);
|
|
14
|
-
const result = await route({ context: {
|
|
15
|
-
...exit.value,
|
|
16
|
-
log
|
|
17
|
-
} });
|
|
18
|
-
return answers.answer === void 0 ? result : {
|
|
19
|
-
...result,
|
|
20
|
-
response: answers.answer(result.response, exit.value)
|
|
21
|
-
};
|
|
22
|
-
};
|
|
23
|
-
//#endregion
|
|
24
|
-
export { requestMiddleware, respond };
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { RequestReference } from "@unisian/effect-observability";
|
|
2
|
-
//#region src/report-browser-error.d.ts
|
|
3
|
-
export declare const reportBrowserError: import("@unisian/capability").Capability<import("@unisian/capability").Contract<"reportBrowserError", import("effect/Schema").Struct<{
|
|
4
|
-
readonly message: import("effect/Schema").String;
|
|
5
|
-
readonly path: import("effect/Schema").String;
|
|
6
|
-
readonly stack: import("effect/Schema").optional<import("effect/Schema").String>;
|
|
7
|
-
}>, import("effect/Schema").Struct<{
|
|
8
|
-
readonly reference: import("effect/Schema").String;
|
|
9
|
-
}>, import("effect/Schema").Never>, RequestReference>;
|
|
10
|
-
//#endregion
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { reportBrowserErrorContract } from "./browser-error-contract.mjs";
|
|
2
|
-
import { implement } from "@unisian/capability";
|
|
3
|
-
import { RequestReference } from "@unisian/effect-observability";
|
|
4
|
-
import * as Effect from "effect/Effect";
|
|
5
|
-
//#region src/report-browser-error.ts
|
|
6
|
-
const reportBrowserError = implement(reportBrowserErrorContract, ({ message, path, stack }) => Effect.gen(function* logBrowserError() {
|
|
7
|
-
yield* Effect.logError("browser error", {
|
|
8
|
-
browserMessage: message,
|
|
9
|
-
browserPath: path,
|
|
10
|
-
browserStack: stack ?? null
|
|
11
|
-
});
|
|
12
|
-
return yield* RequestReference;
|
|
13
|
-
}));
|
|
14
|
-
//#endregion
|
|
15
|
-
export { reportBrowserError };
|
package/dist/report.d.mts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
|
-
import * as Cause from "effect/Cause";
|
|
3
|
-
//#region src/report.d.ts
|
|
4
|
-
export declare const PUBLIC_ERROR_MESSAGE = "Something went wrong loading this app. Try again, and if it keeps happening, quote this reference.";
|
|
5
|
-
export declare const ErrorReport: Schema.Struct<{
|
|
6
|
-
readonly diagnostic: Schema.optional<Schema.String>;
|
|
7
|
-
readonly merchantMessage: Schema.optional<Schema.String>;
|
|
8
|
-
readonly reference: Schema.String;
|
|
9
|
-
}>;
|
|
10
|
-
export type ErrorReport = typeof ErrorReport.Type;
|
|
11
|
-
export declare const errorReport: (reference: string, cause: Cause.Cause<unknown>, merchantMessage?: string) => ErrorReport;
|
|
12
|
-
export declare const encodeReport: (report: ErrorReport) => string;
|
|
13
|
-
export declare const decodeReport: (cause: unknown) => ErrorReport;
|
|
14
|
-
export declare const errorPageHtml: (report: ErrorReport) => string;
|
|
15
|
-
//#endregion
|
package/dist/report.mjs
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import * as Schema from "effect/Schema";
|
|
2
|
-
import * as Cause from "effect/Cause";
|
|
3
|
-
import * as Option from "effect/Option";
|
|
4
|
-
//#region src/report.ts
|
|
5
|
-
const PUBLIC_ERROR_MESSAGE = "Something went wrong loading this app. Try again, and if it keeps happening, quote this reference.";
|
|
6
|
-
const ErrorReport = Schema.Struct({
|
|
7
|
-
diagnostic: Schema.optional(Schema.String),
|
|
8
|
-
merchantMessage: Schema.optional(Schema.String),
|
|
9
|
-
reference: Schema.String
|
|
10
|
-
});
|
|
11
|
-
const REPORT_PREFIX = "error-report:";
|
|
12
|
-
const decodeReportJson = Schema.decodeUnknownOption(Schema.fromJsonString(ErrorReport));
|
|
13
|
-
const errorReport = (reference, cause, merchantMessage) => ({
|
|
14
|
-
diagnostic: import.meta.env.DEV ? Cause.pretty(cause) : void 0,
|
|
15
|
-
merchantMessage,
|
|
16
|
-
reference
|
|
17
|
-
});
|
|
18
|
-
const encodeReport = (report) => `${REPORT_PREFIX}${JSON.stringify(report)}`;
|
|
19
|
-
const caughtError = (cause) => cause instanceof Error ? cause : new Error(String(cause));
|
|
20
|
-
const decodeReport = (cause) => {
|
|
21
|
-
const { message } = caughtError(cause);
|
|
22
|
-
if (!message.startsWith(REPORT_PREFIX)) return import.meta.env.DEV ? {
|
|
23
|
-
diagnostic: message,
|
|
24
|
-
reference: "none"
|
|
25
|
-
} : { reference: "none" };
|
|
26
|
-
return Option.getOrElse(decodeReportJson(message.slice(13)), () => ({ reference: "none" }));
|
|
27
|
-
};
|
|
28
|
-
const escapeHtml = (text) => text.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """);
|
|
29
|
-
const errorPageHtml = (report) => `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Something went wrong</title></head><body><main><h1>Something went wrong</h1><p>${escapeHtml(PUBLIC_ERROR_MESSAGE)}</p><p>Reference: <code>${escapeHtml(report.reference)}</code></p>${report.diagnostic === void 0 ? "" : `<pre>${escapeHtml(report.diagnostic)}</pre>`}</main></body></html>`;
|
|
30
|
-
//#endregion
|
|
31
|
-
export { ErrorReport, PUBLIC_ERROR_MESSAGE, caughtError, decodeReport, encodeReport, errorPageHtml, errorReport };
|
package/dist/router.d.mts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { BrowserErrorReport } from "./browser-error-report.mjs";
|
|
2
|
-
import { AnyRoute, Router, RouterOptions } from "@tanstack/react-router";
|
|
3
|
-
//#region src/router.d.ts
|
|
4
|
-
type PageComponents = Required<Pick<RouterOptions<AnyRoute, "never">, "defaultErrorComponent">> & Pick<RouterOptions<AnyRoute, "never">, "defaultNotFoundComponent" | "defaultPendingComponent">;
|
|
5
|
-
export type AppRouterOptions<RouteTree extends AnyRoute> = PageComponents & {
|
|
6
|
-
readonly routeTree: RouteTree;
|
|
7
|
-
readonly browserErrorReport: BrowserErrorReport;
|
|
8
|
-
};
|
|
9
|
-
export declare const createAppRouter: <RouteTree extends AnyRoute>({ routeTree, browserErrorReport, ...components }: AppRouterOptions<RouteTree>) => Router<RouteTree>;
|
|
10
|
-
//#endregion
|
package/dist/router.mjs
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { reportBrowserErrors } from "./browser-error-report.mjs";
|
|
2
|
-
import { QueryClient } from "@tanstack/react-query";
|
|
3
|
-
import { createRouter } from "@tanstack/react-router";
|
|
4
|
-
import { setupRouterSsrQueryIntegration } from "@tanstack/react-router-ssr-query";
|
|
5
|
-
//#region src/router.ts
|
|
6
|
-
const createAppRouter = ({ routeTree, browserErrorReport, ...components }) => {
|
|
7
|
-
const queryClient = new QueryClient({ defaultOptions: { queries: {
|
|
8
|
-
gcTime: 6e5,
|
|
9
|
-
refetchOnWindowFocus: false,
|
|
10
|
-
staleTime: 3e5
|
|
11
|
-
} } });
|
|
12
|
-
const router = createRouter({
|
|
13
|
-
...components,
|
|
14
|
-
context: { queryClient },
|
|
15
|
-
defaultOnCatch: reportBrowserErrors(queryClient, browserErrorReport),
|
|
16
|
-
defaultPreload: "viewport",
|
|
17
|
-
routeTree,
|
|
18
|
-
scrollRestoration: true
|
|
19
|
-
});
|
|
20
|
-
setupRouterSsrQueryIntegration({
|
|
21
|
-
queryClient,
|
|
22
|
-
router
|
|
23
|
-
});
|
|
24
|
-
return router;
|
|
25
|
-
};
|
|
26
|
-
//#endregion
|
|
27
|
-
export { createAppRouter };
|
package/dist/serve.d.mts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { reportBrowserError } from "./report-browser-error.mjs";
|
|
2
|
-
import * as Schema from "effect/Schema";
|
|
3
|
-
import { AnyContract, Capability, InputOf } from "@unisian/capability";
|
|
4
|
-
import { RequestLogTags, RequestReference } from "@unisian/effect-observability";
|
|
5
|
-
import { AuthenticatedShop, CurrentShop, ShopifyAdmin, ShopifyApp, ShopifyLayerConfig } from "@unisian/shopify-auth";
|
|
6
|
-
import * as Layer from "effect/Layer";
|
|
7
|
-
import { ShopDomain } from "@unisian/shopify-sessions";
|
|
8
|
-
import { HttpClient } from "effect/http";
|
|
9
|
-
//#region src/serve.d.ts
|
|
10
|
-
export interface ServeContext {
|
|
11
|
-
readonly shopify: AuthenticatedShop;
|
|
12
|
-
readonly log: RequestLogTags;
|
|
13
|
-
}
|
|
14
|
-
export interface ServeConfig<Services, ServicesError> extends ShopifyLayerConfig {
|
|
15
|
-
readonly services?: Layer.Layer<Services, ServicesError> | undefined;
|
|
16
|
-
}
|
|
17
|
-
export type Provided<Services> = CurrentShop | ShopifyAdmin | ShopifyApp | HttpClient.HttpClient | RequestReference | Services;
|
|
18
|
-
export interface ServerFnCall<ContractType extends AnyContract, Context> {
|
|
19
|
-
readonly data: InputOf<ContractType>["Type"];
|
|
20
|
-
readonly context: Context;
|
|
21
|
-
readonly serverFnMeta: {
|
|
22
|
-
readonly name: string;
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export declare const serveWith: <Context, Services, ServicesError>(callerOf: (context: Context) => {
|
|
26
|
-
readonly shop: ShopDomain;
|
|
27
|
-
readonly log: RequestLogTags;
|
|
28
|
-
}, layerFor: (context: Context) => Layer.Layer<Services, ServicesError>) => <ContractType extends AnyContract, Requirements extends Services | CurrentShop | RequestReference>(capability: Capability<ContractType, Requirements>) => ({ data, context, serverFnMeta }: ServerFnCall<ContractType, Context>) => Promise<Schema.Json>;
|
|
29
|
-
export declare const makeServe: <Services = never, ServicesError = never>(config: () => ServeConfig<Services, ServicesError>) => <ContractType extends AnyContract, Requirements extends (HttpClient.HttpClient | ShopifyAdmin | ShopifyApp | Exclude<Services, CurrentShop | RequestReference>) | CurrentShop | RequestReference>(capability: Capability<ContractType, Requirements>) => ({ data, context, serverFnMeta }: ServerFnCall<ContractType, ServeContext>) => Promise<Schema.Json>;
|
|
30
|
-
//#endregion
|
|
31
|
-
export { reportBrowserError };
|
package/dist/serve.mjs
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { wireFor } from "./wire.mjs";
|
|
2
|
-
import { serverFnNameFor } from "./function-id.mjs";
|
|
3
|
-
import { reportBrowserError } from "./report-browser-error.mjs";
|
|
4
|
-
import * as Schema from "effect/Schema";
|
|
5
|
-
import { RequestReference, logFailure, runPromiseExit } from "@unisian/effect-observability";
|
|
6
|
-
import { CurrentShop, ShopifyAdmin, shopifyLayer } from "@unisian/shopify-auth";
|
|
7
|
-
import * as Effect from "effect/Effect";
|
|
8
|
-
import * as Layer from "effect/Layer";
|
|
9
|
-
//#region src/serve.ts
|
|
10
|
-
const serveWith = (callerOf, layerFor) => (capability) => {
|
|
11
|
-
const { contract } = capability;
|
|
12
|
-
const encodeOutput = Schema.encodeEffect(Schema.toCodecJson(contract.output));
|
|
13
|
-
const wire = wireFor(contract.failure);
|
|
14
|
-
const serverFnName = serverFnNameFor(contract.name);
|
|
15
|
-
return async ({ data, context, serverFnMeta }) => {
|
|
16
|
-
if (serverFnMeta.name !== serverFnName) throw new Error(`${serverFnMeta.name} serves ${contract.name}; name it ${serverFnName} so its URL names the contract`);
|
|
17
|
-
const { shop, log } = callerOf(context);
|
|
18
|
-
const layer = Layer.mergeAll(layerFor(context), Layer.succeed(CurrentShop, { shop }), Layer.succeed(RequestReference, { reference: log.reference })).pipe(Layer.orDie);
|
|
19
|
-
const exit = await capability.handler(data).pipe(Effect.flatMap((output) => Effect.orDie(encodeOutput(output))), Effect.provide(layer), Effect.tapCause((cause) => logFailure("server function", cause)), runPromiseExit(contract.name, {
|
|
20
|
-
...log,
|
|
21
|
-
shop
|
|
22
|
-
}));
|
|
23
|
-
return wire.encode(exit, log.reference);
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
const makeServe = (config) => serveWith((context) => ({
|
|
27
|
-
log: context.log,
|
|
28
|
-
shop: context.shopify.shop
|
|
29
|
-
}), (context) => {
|
|
30
|
-
const { services, ...shopify } = config();
|
|
31
|
-
return Layer.mergeAll(ShopifyAdmin.layer(context.shopify).pipe(Layer.provideMerge(shopifyLayer(shopify))), services ?? Layer.empty);
|
|
32
|
-
});
|
|
33
|
-
//#endregion
|
|
34
|
-
export { makeServe, reportBrowserError, serveWith };
|
package/dist/wire.mjs
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { ErrorReport, errorReport } from "./report.mjs";
|
|
2
|
-
import { CapabilityFailureError, isMerchantFacing } from "./failure.mjs";
|
|
3
|
-
import * as Schema from "effect/Schema";
|
|
4
|
-
import * as Cause from "effect/Cause";
|
|
5
|
-
import * as Exit from "effect/Exit";
|
|
6
|
-
//#region src/wire.ts
|
|
7
|
-
const isErrorReport = Schema.is(ErrorReport);
|
|
8
|
-
const reportIn = (cause) => cause.reasons.filter(Cause.isDieReason).map((reason) => reason.defect).find(isErrorReport) ?? { reference: "none" };
|
|
9
|
-
const wireFor = (failure) => {
|
|
10
|
-
const codec = Schema.toCodecJson(Schema.Exit(Schema.Json, failure, Schema.Defect()));
|
|
11
|
-
const encodeExit = Schema.encodeSync(codec);
|
|
12
|
-
const decodeExit = Schema.decodeSync(codec);
|
|
13
|
-
const isContractFailure = Schema.is(failure);
|
|
14
|
-
const encode = (exit, reference) => {
|
|
15
|
-
if (Exit.isSuccess(exit)) return encodeExit(exit);
|
|
16
|
-
const failures = exit.cause.reasons.filter(Cause.isFailReason).filter((reason) => isContractFailure(reason.error));
|
|
17
|
-
const merchantMessage = failures.map((reason) => reason.error).find(isMerchantFacing)?.merchantMessage;
|
|
18
|
-
return encodeExit(Exit.failCause(Cause.fromReasons([...failures, Cause.makeDieReason(errorReport(reference, exit.cause, merchantMessage))])));
|
|
19
|
-
};
|
|
20
|
-
const decode = (wire) => {
|
|
21
|
-
const exit = decodeExit(wire);
|
|
22
|
-
if (Exit.isSuccess(exit)) return exit.value;
|
|
23
|
-
const contractFailure = exit.cause.reasons.find(Cause.isFailReason)?.error;
|
|
24
|
-
throw new CapabilityFailureError(reportIn(exit.cause), contractFailure);
|
|
25
|
-
};
|
|
26
|
-
return {
|
|
27
|
-
decode,
|
|
28
|
-
encode
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
//#endregion
|
|
32
|
-
export { wireFor };
|