Skip to content

Commit fbe7620

Browse files
authored
Merge pull request #1 from Adaptavist/detect-missing-fn-invoke
Throw meaningful error if a missing or invalid function invocation is attempted
2 parents 43a1328 + 77db9dd commit fbe7620

7 files changed

Lines changed: 76 additions & 10 deletions

File tree

deno.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"name": "@adaptavist/forge-resolver",
3-
"version": "0.0.4",
3+
"version": "0.0.5",
44
"license": "MIT",
55
"tasks": {
66
"ok": "deno fmt && deno lint && deno check && deno test && deno publish --dry-run --allow-dirty"
77
},
88
"imports": {
99
"@standard-schema/spec": "jsr:@standard-schema/spec@^1.0.0",
1010
"@std/assert": "jsr:@std/assert@^1.0.13",
11-
"@std/testing": "jsr:@std/testing@^1.0.13"
11+
"@std/testing": "jsr:@std/testing@^1.0.14"
1212
},
1313
"exports": {
1414
".": "./lib/mod.ts",

deno.lock

Lines changed: 32 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/_fixtures/functions.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
import type { ResolverFunction } from "@adaptavist/forge-resolver/types";
2+
13
export * from "./resolver/hello.ts";
24
export * from "./resolver/helloValidated.ts";
35
export * from "./resolver/another.ts";
46
export * from "./resolver/nopayload.ts";
7+
8+
export const notReallyAFunction = 123 as unknown as ResolverFunction;

lib/mock-bridge.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export function mockBridge(
2222
context,
2323
});
2424
} catch (e: unknown) {
25+
console.error("Mock Bridge Error:", e);
2526
bridgeErrors.push(e);
2627
// TODO: what should we return on error?
2728
}

lib/resolver.test.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,28 @@ Deno.test("invalid payload validation", async () => {
171171
const error = bridgeErrors.pop();
172172

173173
assertIsError(error, SchemaError);
174+
});
175+
176+
Deno.test("non-existent resolver function", async () => {
177+
await invoke("nonExistentFunction", {});
178+
179+
const error = bridgeErrors.pop();
174180

175-
// console.log(error);
181+
assertIsError(
182+
error,
183+
TypeError,
184+
/^Resolver function not found: "nonExistentFunction"/,
185+
);
186+
});
187+
188+
Deno.test("invalid resolver function", async () => {
189+
await invoke("notReallyAFunction", {});
190+
191+
const error = bridgeErrors.pop();
192+
193+
assertIsError(
194+
error,
195+
TypeError,
196+
/^Resolver member is not a function: "notReallyAFunction"/,
197+
);
176198
});

lib/resolver.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ export function createResolver(fns: ResolverFunctionsModule): ResolverHandler {
2323
) => {
2424
const fn = fns[functionKey];
2525

26+
if (!fn) {
27+
throw new TypeError(
28+
`Resolver function not found: "${functionKey}"\n` +
29+
`Available functions: ${Object.keys(fns).join(", ")}`,
30+
);
31+
}
32+
33+
if (typeof fn !== "function") {
34+
throw new TypeError(
35+
`Resolver member is not a function: "${functionKey}"`,
36+
);
37+
}
38+
2639
const schemas = getSchemas(fn);
2740

2841
if (schemas) {

lib/schemas.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function setSchemas<I extends AnyPayload, O extends AnyResult>(
2828
export function getSchemas<F extends ResolverFunction>(
2929
fn: F,
3030
): Schemas | undefined {
31-
return (fn as unknown as WithSchemas)[schemasSymbol];
31+
return (fn as unknown as WithSchemas)?.[schemasSymbol];
3232
}
3333

3434
export interface Schemas<

0 commit comments

Comments
 (0)