@wfgraph/plugins 0.0.1
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/LICENSE +14 -0
- package/dist/client-BEcFnbOB.js +34 -0
- package/dist/client-C2NIQxhb.js +64 -0
- package/dist/client-DDDCNLId.js +58 -0
- package/dist/client-DJGI9f53.js +73 -0
- package/dist/client-DkPUX0ps.js +50 -0
- package/dist/errors-C4i6-DQE.js +77 -0
- package/dist/index.d.ts +886 -0
- package/dist/index.js +2236 -0
- package/dist/test-8wDSAiFQ.js +45 -0
- package/dist/test-B8I6nxMN.js +38 -0
- package/dist/test-DWVpiQNl.js +36 -0
- package/dist/test-Dsrib2EJ.js +32 -0
- package/dist/test-DzstoPiR.js +35 -0
- package/dist/test-S28s7Z3a.js +35 -0
- package/dist/ui.d.ts +73 -0
- package/dist/ui.js +1631 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Copyright 2025 Vercel, Inc.
|
|
2
|
+
Copyright 2026 Alan Cohen
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getErrorMessage } from "@wfgraph/core/plugin";
|
|
2
|
+
import { createClerkClient } from "@clerk/backend";
|
|
3
|
+
//#region src/clerk/client.ts
|
|
4
|
+
function createClerkBackendClient(secretKey) {
|
|
5
|
+
return createClerkClient({ secretKey });
|
|
6
|
+
}
|
|
7
|
+
function toClerkApiUser(user) {
|
|
8
|
+
return {
|
|
9
|
+
id: user.id,
|
|
10
|
+
first_name: user.firstName,
|
|
11
|
+
last_name: user.lastName,
|
|
12
|
+
email_addresses: user.emailAddresses.map((email) => ({
|
|
13
|
+
id: email.id,
|
|
14
|
+
email_address: email.emailAddress
|
|
15
|
+
})),
|
|
16
|
+
primary_email_address_id: user.primaryEmailAddressId,
|
|
17
|
+
public_metadata: user.publicMetadata,
|
|
18
|
+
private_metadata: user.privateMetadata,
|
|
19
|
+
created_at: user.createdAt,
|
|
20
|
+
updated_at: user.updatedAt
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function getClerkApiErrorMessage(error) {
|
|
24
|
+
if (error && typeof error === "object") {
|
|
25
|
+
const clerkError = error;
|
|
26
|
+
const firstError = Array.isArray(clerkError.errors) ? clerkError.errors[0] : void 0;
|
|
27
|
+
if (firstError && typeof firstError.message === "string" && firstError.message.length > 0) return firstError.message;
|
|
28
|
+
if (typeof clerkError.status === "number") return String(clerkError.status);
|
|
29
|
+
if (typeof clerkError.message === "string" && clerkError.message.length > 0) return clerkError.message;
|
|
30
|
+
}
|
|
31
|
+
return getErrorMessage(error);
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
export { getClerkApiErrorMessage as n, toClerkApiUser as r, createClerkBackendClient as t };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { callExternal, parsePayload } from "@wfgraph/core/plugin";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
//#region src/resend/client.ts
|
|
4
|
+
const RESEND_API_BASE = "https://api.resend.com";
|
|
5
|
+
/** Resend's error body. `name` is the machine-readable slug. */
|
|
6
|
+
const resendErrorSchema = Schema.Struct({
|
|
7
|
+
statusCode: Schema.optionalKey(Schema.Finite),
|
|
8
|
+
name: Schema.optionalKey(Schema.String),
|
|
9
|
+
message: Schema.optionalKey(Schema.String)
|
|
10
|
+
});
|
|
11
|
+
const sentEmailSchema = Schema.Struct({ id: Schema.String });
|
|
12
|
+
/**
|
|
13
|
+
* Resend's error body, for a caller that reports more than the message.
|
|
14
|
+
*
|
|
15
|
+
* The connection test is that caller: a send-only key answers
|
|
16
|
+
* `restricted_api_key` on the domains endpoint, which confirms the key works,
|
|
17
|
+
* and only the slug says so.
|
|
18
|
+
*/
|
|
19
|
+
function readResendError(payload) {
|
|
20
|
+
return parsePayload(payload, resendErrorSchema);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* What Resend said, in one sentence a person reads.
|
|
24
|
+
*
|
|
25
|
+
* A refusal carries Resend's own message when its error body is the documented
|
|
26
|
+
* shape and the bare status when it is not. A 2xx whose body is not the
|
|
27
|
+
* documented resource says so, because reporting success there would tell the
|
|
28
|
+
* run an email went out and leave nothing to look it up by.
|
|
29
|
+
*/
|
|
30
|
+
function describeResendFailure(error) {
|
|
31
|
+
if (error._tag === "ExternalUnreachable") return error.message;
|
|
32
|
+
if (error._tag === "ExternalUnreadable") return `Resend answered ${error.status} with an unrecognized body`;
|
|
33
|
+
return readResendError(error.payload)?.message ?? `HTTP ${error.status}`;
|
|
34
|
+
}
|
|
35
|
+
function requestResend(apiKey, path, schema, init) {
|
|
36
|
+
return callExternal({
|
|
37
|
+
system: "Resend",
|
|
38
|
+
url: `${RESEND_API_BASE}${path}`,
|
|
39
|
+
method: init.method,
|
|
40
|
+
headers: { authorization: `Bearer ${apiKey}` },
|
|
41
|
+
body: init.jsonBody === void 0 ? void 0 : {
|
|
42
|
+
kind: "json",
|
|
43
|
+
value: init.jsonBody
|
|
44
|
+
},
|
|
45
|
+
idempotencyKey: init.idempotencyKey,
|
|
46
|
+
schema
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function sendResendEmail(apiKey, payload, idempotencyKey) {
|
|
50
|
+
return requestResend(apiKey, "/emails", sentEmailSchema, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
jsonBody: payload,
|
|
53
|
+
idempotencyKey
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Listing domains is a read-only call any valid key can make, which makes it the
|
|
58
|
+
* check that says whether a key works without sending anything.
|
|
59
|
+
*/
|
|
60
|
+
function listResendDomains(apiKey) {
|
|
61
|
+
return requestResend(apiKey, "/domains", Schema.Unknown, { method: "GET" });
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { sendResendEmail as i, listResendDomains as n, readResendError as r, describeResendFailure as t };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { callExternal, parsePayload } from "@wfgraph/core/plugin";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
//#region src/slack/client.ts
|
|
4
|
+
const SLACK_API_BASE = "https://slack.com/api";
|
|
5
|
+
/**
|
|
6
|
+
* Slack answers every call with this envelope, on success and failure alike.
|
|
7
|
+
* The fields a caller actually wants sit beside these two, which is why the
|
|
8
|
+
* caller's own schema reads the same payload again below.
|
|
9
|
+
*/
|
|
10
|
+
const slackEnvelopeSchema = Schema.Struct({
|
|
11
|
+
ok: Schema.Boolean,
|
|
12
|
+
error: Schema.optionalKey(Schema.String)
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Slack's own error slug out of a refusal, or undefined when the refusal did
|
|
16
|
+
* not come from Slack.
|
|
17
|
+
*
|
|
18
|
+
* A refusal that does not read as a Slack envelope, or reads as one that says
|
|
19
|
+
* `ok: true`, came from something standing in front of the API, so its status
|
|
20
|
+
* is all there is to report. A caller that distinguishes the two -- the
|
|
21
|
+
* connection test does, because it words them differently -- asks here.
|
|
22
|
+
*/
|
|
23
|
+
function readSlackError(payload) {
|
|
24
|
+
const envelope = parsePayload(payload, slackEnvelopeSchema);
|
|
25
|
+
if (envelope === void 0 || envelope.ok) return;
|
|
26
|
+
return envelope.error ?? "unknown_error";
|
|
27
|
+
}
|
|
28
|
+
/** What Slack said, in one sentence a person reads. */
|
|
29
|
+
function describeSlackFailure(error) {
|
|
30
|
+
if (error._tag === "ExternalUnreachable") return error.message;
|
|
31
|
+
if (error._tag === "ExternalUnreadable") return `HTTP ${error.status}`;
|
|
32
|
+
return readSlackError(error.payload) ?? `HTTP ${error.status}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* `options` carries the arguments Slack's method takes and whether repeating the
|
|
36
|
+
* call is safe, in one bag so that a caller wanting the second does not have to
|
|
37
|
+
* name the first.
|
|
38
|
+
*/
|
|
39
|
+
function callSlack(token, method, schema, options = {}) {
|
|
40
|
+
return callExternal({
|
|
41
|
+
system: "Slack",
|
|
42
|
+
url: `${SLACK_API_BASE}/${method}`,
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: {
|
|
45
|
+
authorization: `Bearer ${token}`,
|
|
46
|
+
"content-type": "application/json; charset=utf-8"
|
|
47
|
+
},
|
|
48
|
+
body: {
|
|
49
|
+
kind: "json",
|
|
50
|
+
value: options.body ?? {}
|
|
51
|
+
},
|
|
52
|
+
schema,
|
|
53
|
+
refusedInBody: (payload) => parsePayload(payload, slackEnvelopeSchema)?.ok !== true,
|
|
54
|
+
safeToRepeat: options.safeToRepeat
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { describeSlackFailure as n, readSlackError as r, callSlack as t };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { callExternal, parsePayload } from "@wfgraph/core/plugin";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
import { omitBy } from "es-toolkit/object";
|
|
4
|
+
import { isNil } from "es-toolkit/predicate";
|
|
5
|
+
//#region src/twilio/client.ts
|
|
6
|
+
const TWILIO_API_BASE = "https://api.twilio.com/2010-04-01";
|
|
7
|
+
/** Twilio's error body, the same shape on every endpoint. */
|
|
8
|
+
const twilioErrorSchema = Schema.Struct({
|
|
9
|
+
code: Schema.optionalKey(Schema.Finite),
|
|
10
|
+
message: Schema.optionalKey(Schema.String),
|
|
11
|
+
more_info: Schema.optionalKey(Schema.String)
|
|
12
|
+
});
|
|
13
|
+
/** The Message resource, as much of it as this plugin reads. */
|
|
14
|
+
const twilioMessageSchema = Schema.Struct({
|
|
15
|
+
sid: Schema.String,
|
|
16
|
+
status: Schema.String,
|
|
17
|
+
to: Schema.String,
|
|
18
|
+
from: Schema.optionalKey(Schema.NullishOr(Schema.String)),
|
|
19
|
+
messaging_service_sid: Schema.optionalKey(Schema.NullishOr(Schema.String))
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* What Twilio said, in one sentence a person reads.
|
|
23
|
+
*
|
|
24
|
+
* A refusal carries Twilio's own message when its error body is the documented
|
|
25
|
+
* shape and the bare status when it is not, which is what something standing in
|
|
26
|
+
* front of the API answers with. A 2xx whose body is not the resource says so,
|
|
27
|
+
* because reporting success there would hand the run an empty message SID.
|
|
28
|
+
*/
|
|
29
|
+
function describeTwilioFailure(error) {
|
|
30
|
+
if (error._tag === "ExternalUnreachable") return error.message;
|
|
31
|
+
if (error._tag === "ExternalUnreadable") return `Twilio answered ${error.status} with an unrecognized body`;
|
|
32
|
+
return readTwilioError(error.payload)?.message ?? `HTTP ${error.status}`;
|
|
33
|
+
}
|
|
34
|
+
/** Twilio's error body, for a caller that reports more than the message. */
|
|
35
|
+
function readTwilioError(payload) {
|
|
36
|
+
return parsePayload(payload, twilioErrorSchema);
|
|
37
|
+
}
|
|
38
|
+
function toBasicAuth(accountSid, authToken) {
|
|
39
|
+
return `Basic ${Buffer.from(`${accountSid}:${authToken}`).toString("base64")}`;
|
|
40
|
+
}
|
|
41
|
+
function requestTwilio(credentials, path, schema, init) {
|
|
42
|
+
return callExternal({
|
|
43
|
+
system: "Twilio",
|
|
44
|
+
url: `${TWILIO_API_BASE}${path}`,
|
|
45
|
+
method: init.method,
|
|
46
|
+
headers: { authorization: toBasicAuth(credentials.accountSid, credentials.authToken) },
|
|
47
|
+
body: init.body === void 0 ? void 0 : {
|
|
48
|
+
kind: "form",
|
|
49
|
+
value: init.body
|
|
50
|
+
},
|
|
51
|
+
schema
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Sending is the one call here that a repeat could do twice, and Twilio's
|
|
56
|
+
* Message resource takes no idempotency key, so it is not retried: a send that
|
|
57
|
+
* timed out on the way back stays sent once.
|
|
58
|
+
*/
|
|
59
|
+
function createTwilioMessage(credentials, parameters) {
|
|
60
|
+
const { MediaUrl, ...scalars } = parameters;
|
|
61
|
+
const body = new URLSearchParams(omitBy(scalars, isNil));
|
|
62
|
+
for (const mediaUrl of MediaUrl ?? []) body.append("MediaUrl", mediaUrl);
|
|
63
|
+
return requestTwilio(credentials, `/Accounts/${encodeURIComponent(credentials.accountSid)}/Messages.json`, twilioMessageSchema, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
body
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/** Reading the account back is Twilio's cheapest credential check. */
|
|
69
|
+
function fetchTwilioAccount(credentials) {
|
|
70
|
+
return requestTwilio(credentials, `/Accounts/${encodeURIComponent(credentials.accountSid)}.json`, Schema.Struct({ sid: Schema.String }), { method: "GET" });
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { readTwilioError as i, describeTwilioFailure as n, fetchTwilioAccount as r, createTwilioMessage as t };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { StepFailure, getErrorMessage } from "@wfgraph/core/plugin";
|
|
2
|
+
import { Effect } from "effect";
|
|
3
|
+
import { Acuity, AcuityError } from "@fountain-bio/acuity";
|
|
4
|
+
//#region src/acuity/client.ts
|
|
5
|
+
/** Production SDK construction from stored credentials. */
|
|
6
|
+
function createAcuitySdk(userId, apiKey) {
|
|
7
|
+
return new Acuity({
|
|
8
|
+
userId,
|
|
9
|
+
apiKey
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The Acuity SDK, built from the step's own credentials, or the failure that
|
|
14
|
+
* says which of them is missing.
|
|
15
|
+
*
|
|
16
|
+
* It takes the handler's whole bag rather than the credentials, so fetching them
|
|
17
|
+
* is part of the one line every handler opens with. Every step starts here, which
|
|
18
|
+
* is what makes the check on them written once and reported the same way.
|
|
19
|
+
*
|
|
20
|
+
* A store that could not be read is passed on rather than turned into a
|
|
21
|
+
* `StepFailure`: that failure is the one a step is retried for.
|
|
22
|
+
*/
|
|
23
|
+
function createAcuityClient(bag, createSdk) {
|
|
24
|
+
return Effect.flatMap(bag.credentials, (credentials) => {
|
|
25
|
+
const userId = credentials.ACUITY_USER_ID?.trim();
|
|
26
|
+
const apiKey = credentials.ACUITY_API_KEY?.trim();
|
|
27
|
+
return userId && apiKey ? Effect.succeed(createSdk(userId, apiKey)) : Effect.fail(new StepFailure({ message: "ACUITY_USER_ID and ACUITY_API_KEY are required. Add them in Project Integrations." }));
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* One call to Acuity, with the sentence that says what went wrong if it did.
|
|
32
|
+
*
|
|
33
|
+
* The SDK throws, and what it throws is an `AcuityError` carrying the API's own
|
|
34
|
+
* message when Acuity answered and something more general when it did not, so
|
|
35
|
+
* the fallback each step passes names the thing that step was doing.
|
|
36
|
+
*/
|
|
37
|
+
function callAcuity(fallback, call) {
|
|
38
|
+
return Effect.tryPromise({
|
|
39
|
+
try: call,
|
|
40
|
+
catch: (error) => new StepFailure({ message: getAcuityErrorMessage(error, fallback) })
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function getAcuityErrorMessage(error, fallback) {
|
|
44
|
+
if (error instanceof AcuityError) return error.message;
|
|
45
|
+
const message = getErrorMessage(error);
|
|
46
|
+
if (message && message !== "Unknown error") return message;
|
|
47
|
+
return fallback;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { getAcuityErrorMessage as i, createAcuityClient as n, createAcuitySdk as r, callAcuity as t };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { getErrorMessage } from "@wfgraph/core/plugin";
|
|
2
|
+
import { Option, Schema } from "effect";
|
|
3
|
+
import { LinearError, parseLinearError } from "@linear/sdk";
|
|
4
|
+
//#region src/linear/errors.ts
|
|
5
|
+
/**
|
|
6
|
+
* The error payload Linear's `parseLinearError` reads: the GraphQL request that
|
|
7
|
+
* failed, the response that came back with its status and GraphQL errors, and a
|
|
8
|
+
* top-level message. Anything caught while talking to Linear arrives as `unknown`,
|
|
9
|
+
* so this schema is the boundary that decides whether Linear can classify it.
|
|
10
|
+
*
|
|
11
|
+
* Every level stays open, because Linear reads fields this schema does not name
|
|
12
|
+
* (`response.data`, `response.headers`) and the validated value is handed on to
|
|
13
|
+
* Linear whole. The named fields are the ones Linear reads unguarded: a `message`
|
|
14
|
+
* that is not a string, or a `response.errors` that is not a list of objects,
|
|
15
|
+
* makes Linear's own parsing throw. `onExcessProperty: "preserve"` in the decode
|
|
16
|
+
* below is what keeps the unnamed fields, at every level, on the value that comes
|
|
17
|
+
* back; the default strips them.
|
|
18
|
+
*
|
|
19
|
+
* Fields are described as the API sends them. Linear's LinearErrorRaw types both
|
|
20
|
+
* the per-error `message` and `extensions.type` as its LinearErrorType enum, while
|
|
21
|
+
* the wire carries readable text ("Authentication required") and a lowercase
|
|
22
|
+
* phrase ("authentication error") that Linear maps back to the enum itself.
|
|
23
|
+
*/
|
|
24
|
+
const linearGraphqlErrorSchema = Schema.Struct({
|
|
25
|
+
message: Schema.optionalKey(Schema.String),
|
|
26
|
+
path: Schema.optionalKey(Schema.Array(Schema.String)),
|
|
27
|
+
extensions: Schema.optionalKey(Schema.Struct({
|
|
28
|
+
type: Schema.optionalKey(Schema.String),
|
|
29
|
+
userError: Schema.optionalKey(Schema.Boolean),
|
|
30
|
+
userPresentableMessage: Schema.optionalKey(Schema.String)
|
|
31
|
+
}))
|
|
32
|
+
});
|
|
33
|
+
const linearErrorRawSchema = Schema.Struct({
|
|
34
|
+
name: Schema.optionalKey(Schema.String),
|
|
35
|
+
message: Schema.optionalKey(Schema.String),
|
|
36
|
+
request: Schema.optionalKey(Schema.Struct({
|
|
37
|
+
query: Schema.optionalKey(Schema.String),
|
|
38
|
+
variables: Schema.optionalKey(Schema.Record(Schema.String, Schema.Unknown))
|
|
39
|
+
})),
|
|
40
|
+
response: Schema.optionalKey(Schema.Struct({
|
|
41
|
+
status: Schema.optionalKey(Schema.Finite),
|
|
42
|
+
error: Schema.optionalKey(Schema.String),
|
|
43
|
+
errors: Schema.optionalKey(Schema.Array(linearGraphqlErrorSchema))
|
|
44
|
+
}))
|
|
45
|
+
});
|
|
46
|
+
const readLinearErrorRaw = Schema.decodeUnknownOption(linearErrorRawSchema, { onExcessProperty: "preserve" });
|
|
47
|
+
/**
|
|
48
|
+
* Normalizes anything thrown while talking to Linear into a LinearError, which is
|
|
49
|
+
* what the steps read an error type and a message from. The SDK wraps its own
|
|
50
|
+
* failures, so the remaining cases are a raw error payload from a GraphQL client,
|
|
51
|
+
* a plain Error, and a bare string.
|
|
52
|
+
*/
|
|
53
|
+
function toLinearError(error) {
|
|
54
|
+
if (error instanceof LinearError) return error;
|
|
55
|
+
const raw = Option.getOrUndefined(readLinearErrorRaw(error));
|
|
56
|
+
if (raw) return parseLinearError(raw);
|
|
57
|
+
if (error instanceof Error) return parseLinearError({
|
|
58
|
+
name: error.name,
|
|
59
|
+
message: error.message
|
|
60
|
+
});
|
|
61
|
+
if (typeof error === "string") return parseLinearError({ message: error });
|
|
62
|
+
return parseLinearError();
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* What Linear said, in the one sentence a step's failure carries.
|
|
66
|
+
*
|
|
67
|
+
* The GraphQL error is the specific one -- "Entity not found: Issue" -- and the
|
|
68
|
+
* wrapper's message is the general one, so the first that says anything wins.
|
|
69
|
+
* A throw Linear cannot classify at all falls through to whatever the thrown
|
|
70
|
+
* value had to say for itself.
|
|
71
|
+
*/
|
|
72
|
+
function describeLinearFailure(error) {
|
|
73
|
+
const linearError = toLinearError(error);
|
|
74
|
+
return linearError.errors?.[0]?.message || linearError.message || getErrorMessage(error);
|
|
75
|
+
}
|
|
76
|
+
//#endregion
|
|
77
|
+
export { toLinearError as n, describeLinearFailure as t };
|